On Tue, Jul 25, 2017 at 6:14 PM, Miguel Angel Ajo Pelayo <
majop...@redhat.com> wrote:

> Looks good, just a tiny comment, but not actually very important.
>
>
> On Fri, Jul 14, 2017 at 2:26 PM, <nusid...@redhat.com> wrote:
>
>> From: Zongkai LI <zealo...@gmail.com>
>>
>> This patch adds logical flows which sends IPv6 Router Advertisement
>> packet in response to the IPv6 Router Solicitation request. It uses
>> the actions "put_nd_ra_opts" to transform the RS packet to RA packet
>> in the newly added ingress stage "lr_in_nd_ra_options" in router
>> pipeline. If the action "put_nd_ra_opts" is successful, it sends the
>> RA packet back to the originating port in the next ingress stage
>> "lr_in_nd_ra_response".
>>
>> A new column "ipv6_ra_configs" is added in the Logical_Router_Port
>> table, which the CMS is expected to configure IPv6 RA
>> configurations - "address_mode" and "mtu" for adding these flows.
>>
>> Co-authored-by: Numan Siddique <nusid...@redhat.com>
>> Signed-off-by: Zongkai LI <zealo...@gmail.com>
>> Signed-off-by: Numan Siddique <nusid...@redhat.com>
>> ---
>>  ovn/lib/logical-fields.c    |   4 +
>>  ovn/northd/ovn-northd.8.xml |  81 ++++++++++++++-
>>  ovn/northd/ovn-northd.c     | 129 ++++++++++++++++++++----
>>  ovn/ovn-nb.ovsschema        |   7 +-
>>  ovn/ovn-nb.xml              |  39 ++++++++
>>  ovn/ovn-sb.xml              |   4 +
>>  tests/ovn.at                | 237 ++++++++++++++++++++++++++++++
>> ++++++++++++++
>>  7 files changed, 478 insertions(+), 23 deletions(-)
>>
>> diff --git a/ovn/lib/logical-fields.c b/ovn/lib/logical-fields.c
>> index 26e336f5a..a8b5e3c51 100644
>> --- a/ovn/lib/logical-fields.c
>> +++ b/ovn/lib/logical-fields.c
>> @@ -183,6 +183,10 @@ ovn_init_symtab(struct shash *symtab)
>>                "icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255");
>>      expr_symtab_add_predicate(symtab, "nd_na",
>>                "icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255");
>> +    expr_symtab_add_predicate(symtab, "nd_rs",
>> +              "icmp6.type == 133 && icmp6.code == 0 && ip.ttl == 255");
>> +    expr_symtab_add_predicate(symtab, "nd_ra",
>> +              "icmp6.type == 134 && icmp6.code == 0 && ip.ttl == 255");
>>      expr_symtab_add_field(symtab, "nd.target", MFF_ND_TARGET, "nd",
>> false);
>>      expr_symtab_add_field(symtab, "nd.sll", MFF_ND_SLL, "nd_ns", false);
>>      expr_symtab_add_field(symtab, "nd.tll", MFF_ND_TLL, "nd_na", false);
>> diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
>> index 7ff524508..911f67b21 100644
>> --- a/ovn/northd/ovn-northd.8.xml
>> +++ b/ovn/northd/ovn-northd.8.xml
>> @@ -1573,7 +1573,80 @@ icmp4 {
>>        </li>
>>      </ul>
>>
>> -    <h3>Ingress Table 5: IP Routing</h3>
>> +    <h3>Ingress Table 5: IPv6 ND RA option processing</h3>
>> +
>> +    <ul>
>> +      <li>
>> +        <p>
>> +          A priority-50 logical flow is added for each logical router
>> port
>> +          configured with IPv6 ND RA options which matches IPv6 ND Router
>> +          Solicitation packet and applies the action
>> +          <code>put_nd_ra_opts</code> and advances the packet to the next
>> +          table.
>> +        </p>
>> +
>> +        <pre>
>> +reg0[5] = put_nd_ra_opts(<var>options</var>);next;
>> +        </pre>
>> +
>> +        <p>
>> +          For a valid IPv6 ND RS packet, this transforms the packet into
>> an
>> +          IPv6 ND RA reply and sets the RA options to the packet and
>> stores 1
>> +          into reg0[5]. For other kinds of packets, it just stores 0 into
>> +          reg0[5]. Either way, it continues to the next table.
>> +        </p>
>> +      </li>
>> +
>> +      <li>
>> +        A priority-0 logical flow with match <code>1</code> has actions
>> +        <code>next;</code>.
>> +      </li>
>> +    </ul>
>> +
>> +    <h3>Ingress Table 6: IPv6 ND RA responder</h3>
>> +
>> +    <p>
>> +      This table implements IPv6 ND RA responder for the IPv6 ND RA
>> replies
>> +      generated by the previous table.
>> +    </p>
>> +
>> +    <ul>
>> +      <li>
>> +        <p>
>> +          A priority-50 logical flow is added for each logical router
>> port
>> +          configured with IPv6 ND RA options which matches IPv6 ND RA
>> +          packets and <code>reg0[5] == 1</code> and responds back to the
>> +          <code>inport</code> after applying these actions.
>> +          If <code>reg0[5]</code> is set to 1, it means that the action
>> +          <code>put_nd_ra_opts</code> was successful.
>> +        </p>
>> +
>> +        <pre>
>> +eth.src = <var>E</var>;
>> +ip6.src = <var>I</var>;
>> +outport = <var>P</var>;
>> +flags.loopback = 1;
>> +output;
>> +        </pre>
>> +
>> +        <p>
>> +          where <var>E</var> is the MAC address and <var>I</var> is the
>> IPv6
>> +          link local address of the logical router port.
>> +        </p>
>> +
>> +        <p>
>> +          (This terminates packet processing in ingress pipeline; the
>> packet
>> +          does not go to the next ingress table.)
>> +        </p>
>> +      </li>
>> +
>> +      <li>
>> +        A priority-0 logical flow with match <code>1</code> has actions
>> +        <code>next;</code>.
>> +      </li>
>> +    </ul>
>> +
>> +    <h3>Ingress Table 7: IP Routing</h3>
>>
>>      <p>
>>        A packet that arrives at this table is an IP packet that should be
>> @@ -1675,7 +1748,7 @@ next;
>>        </li>
>>      </ul>
>>
>> -    <h3>Ingress Table 6: ARP/ND Resolution</h3>
>> +    <h3>Ingress Table 8: ARP/ND Resolution</h3>
>>
>>      <p>
>>        Any packet that reaches this table is an IP packet whose next-hop
>> @@ -1768,7 +1841,7 @@ next;
>>        </li>
>>      </ul>
>>
>> -    <h3>Ingress Table 7: Gateway Redirect</h3>
>> +    <h3>Ingress Table 9: Gateway Redirect</h3>
>>
>>      <p>
>>        For distributed logical routers where one of the logical router
>> @@ -1825,7 +1898,7 @@ next;
>>        </li>
>>      </ul>
>>
>> -    <h3>Ingress Table 8: ARP Request</h3>
>> +    <h3>Ingress Table 10: ARP Request</h3>
>>
>>      <p>
>>        In the common case where the Ethernet destination has been
>> resolved, this
>> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
>> index 2d7c2d86e..5e36eb9b1 100644
>> --- a/ovn/northd/ovn-northd.c
>> +++ b/ovn/northd/ovn-northd.c
>> @@ -128,15 +128,17 @@ enum ovn_stage {
>>      PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2,  8, "ls_out_port_sec_l2")
>>   \
>>                                                                        \
>>      /* Logical router ingress stages. */                              \
>> -    PIPELINE_STAGE(ROUTER, IN,  ADMISSION,   0, "lr_in_admission")    \
>> -    PIPELINE_STAGE(ROUTER, IN,  IP_INPUT,    1, "lr_in_ip_input")     \
>> -    PIPELINE_STAGE(ROUTER, IN,  DEFRAG,      2, "lr_in_defrag")       \
>> -    PIPELINE_STAGE(ROUTER, IN,  UNSNAT,      3, "lr_in_unsnat")       \
>> -    PIPELINE_STAGE(ROUTER, IN,  DNAT,        4, "lr_in_dnat")         \
>> -    PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING,  5, "lr_in_ip_routing")   \
>> -    PIPELINE_STAGE(ROUTER, IN,  ARP_RESOLVE, 6, "lr_in_arp_resolve")  \
>> -    PIPELINE_STAGE(ROUTER, IN,  GW_REDIRECT, 7, "lr_in_gw_redirect")  \
>> -    PIPELINE_STAGE(ROUTER, IN,  ARP_REQUEST, 8, "lr_in_arp_request")  \
>> +    PIPELINE_STAGE(ROUTER, IN,  ADMISSION,      0, "lr_in_admission")
>> \
>> +    PIPELINE_STAGE(ROUTER, IN,  IP_INPUT,       1, "lr_in_ip_input")
>>  \
>> +    PIPELINE_STAGE(ROUTER, IN,  DEFRAG,         2, "lr_in_defrag")
>>  \
>> +    PIPELINE_STAGE(ROUTER, IN,  UNSNAT,         3, "lr_in_unsnat")
>>  \
>> +    PIPELINE_STAGE(ROUTER, IN,  DNAT,           4, "lr_in_dnat")
>>  \
>> +    PIPELINE_STAGE(ROUTER, IN,  ND_RA_OPTIONS,  5,
>> "lr_in_nd_ra_options") \
>> +    PIPELINE_STAGE(ROUTER, IN,  ND_RA_RESPONSE, 6,
>> "lr_in_nd_ra_response") \
>> +    PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING,     7, "lr_in_ip_routing")
>>  \
>> +    PIPELINE_STAGE(ROUTER, IN,  ARP_RESOLVE,    8, "lr_in_arp_resolve")
>> \
>> +    PIPELINE_STAGE(ROUTER, IN,  GW_REDIRECT,    9, "lr_in_gw_redirect")
>> \
>> +    PIPELINE_STAGE(ROUTER, IN,  ARP_REQUEST,    10,
>> "lr_in_arp_request")  \
>>                                                                        \
>>      /* Logical router egress stages. */                               \
>>      PIPELINE_STAGE(ROUTER, OUT, UNDNAT,    0, "lr_out_undnat")        \
>> @@ -158,11 +160,12 @@ enum ovn_stage {
>>  #define OVN_ACL_PRI_OFFSET 1000
>>
>>  /* Register definitions specific to switches. */
>> -#define REGBIT_CONNTRACK_DEFRAG "reg0[0]"
>> -#define REGBIT_CONNTRACK_COMMIT "reg0[1]"
>> -#define REGBIT_CONNTRACK_NAT    "reg0[2]"
>> -#define REGBIT_DHCP_OPTS_RESULT "reg0[3]"
>> +#define REGBIT_CONNTRACK_DEFRAG  "reg0[0]"
>> +#define REGBIT_CONNTRACK_COMMIT  "reg0[1]"
>> +#define REGBIT_CONNTRACK_NAT     "reg0[2]"
>> +#define REGBIT_DHCP_OPTS_RESULT  "reg0[3]"
>>  #define REGBIT_DNS_LOOKUP_RESULT "reg0[4]"
>> +#define REGBIT_ND_RA_OPTS_RESULT "reg0[5]"
>>
>>  /* Register definitions for switches and routers. */
>>  #define REGBIT_NAT_REDIRECT     "reg9[0]"
>> @@ -2634,7 +2637,11 @@ build_pre_acls(struct ovn_datapath *od, struct
>> hmap *lflows)
>>           *
>>           * Not to do conntrack on ND packets. */
>>          ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110, "nd",
>> "next;");
>> +        ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110, "(nd_rs ||
>> nd_ra)",
>> +                      "next;");
>>          ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110, "nd",
>> "next;");
>> +        ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
>> +                      "(nd_rs || nd_ra)", "next;");
>>
>>          /* Ingress and Egress Pre-ACL Table (Priority 100).
>>           *
>> @@ -5030,7 +5037,95 @@ build_lrouter_flows(struct hmap *datapaths, struct
>> hmap *ports,
>>          sset_destroy(&all_ips);
>>      }
>>
>> -    /* Logical router ingress table 5: IP Routing.
>> +    /* Logical router ingress table 5 and 6: IPv6 Router Adv (RA)
>> options and
>> +     * response. */
>> +    HMAP_FOR_EACH (op, key_node, ports) {
>> +        if (!op->nbrp || op->nbrp->peer || !op->peer) {
>> +            continue;
>> +        }
>> +
>> +        if (!op->lrp_networks.n_ipv6_addrs) {
>> +            continue;
>> +        }
>> +
>> +        const char *address_mode = smap_get(
>> +            &op->nbrp->ipv6_ra_configs, "address_mode");
>> +
>> +        if (!address_mode || (strcmp(address_mode, "slaac") &&
>> +                              strcmp(address_mode, "dhcpv6_stateful") &&
>> +                              strcmp(address_mode, "dhcpv6_stateless")))
>> {
>> +            continue;
>>
> Would it be worth to log a rate limited warning?
>

Thanks for the review Miguel. I have addressed this comment, rebased the
patch series to resolve the merge conflicts and submitted the v4.

Numan


>
>
>
>> +        }
>> +
>> +        ds_clear(&match);
>> +        ds_put_format(&match, "inport == %s && ip6.dst == ff02::2 &&
>> nd_rs",
>> +                              op->json_key);
>> +        ds_clear(&actions);
>> +
>> +        const char *mtu_s = smap_get(
>> +            &op->nbrp->ipv6_ra_configs, "mtu");
>> +
>> +        uint32_t mtu = (mtu_s && atoi(mtu_s) >= 1280) ? atoi(mtu_s) : 0;
>> +
>> +        ds_put_format(&actions, REGBIT_ND_RA_OPTS_RESULT" =
>> put_nd_ra_opts("
>> +                      "addr_mode = \"%s\", slla = %s",
>> +                      address_mode, op->lrp_networks.ea_s);
>> +        if (mtu > 0) {
>> +            ds_put_format(&actions, ", mtu = %u", mtu);
>> +        }
>> +
>> +        bool add_rs_response_flow = false;
>> +
>> +        for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
>> +            if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].network)) {
>> +                continue;
>> +            }
>> +
>> +            /* Add the prefix option if the address mode is slaac or
>> +             * dhcpv6_stateless. */
>> +            if (strcmp(address_mode, "dhcpv6_stateful")) {
>> +                ds_put_format(&actions, ", prefix = %s/%u",
>> +                              op->lrp_networks.ipv6_addrs[i].network_s,
>> +                              op->lrp_networks.ipv6_addrs[i].plen);
>> +            }
>> +            add_rs_response_flow = true;
>> +        }
>> +
>> +        if (add_rs_response_flow) {
>> +            ds_put_cstr(&actions, "); next;");
>> +            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS, 50,
>> +                          ds_cstr(&match), ds_cstr(&actions));
>> +            ds_clear(&actions);
>> +            ds_clear(&match);
>> +            ds_put_format(&match, "inport == %s && ip6.src == ff02::2 &&
>> "
>> +                          "nd_ra && "REGBIT_ND_RA_OPTS_RESULT,
>> op->json_key);
>> +
>> +            char ip6_str[INET6_ADDRSTRLEN + 1];
>> +            struct in6_addr lla;
>> +            in6_generate_lla(op->lrp_networks.ea, &lla);
>> +            memset(ip6_str, 0, sizeof(ip6_str));
>> +            ipv6_string_mapped(ip6_str, &lla);
>> +            ds_put_format(&actions, "eth.src = %s; ip6.src = %s; "
>> +                          "outport = inport; flags.loopback = 1; "
>> +                          "output;",
>> +                          op->lrp_networks.ea_s, ip6_str);
>> +            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_RESPONSE, 50,
>> +                          ds_cstr(&match), ds_cstr(&actions));
>> +        }
>> +    }
>> +
>> +    /* Logical router ingress table 5, 6: RS responder, by default goto
>> next.
>> +     * (priority 0)*/
>> +    HMAP_FOR_EACH (od, key_node, datapaths) {
>> +        if (!od->nbr) {
>> +            continue;
>> +        }
>> +
>> +        ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, "1",
>> "next;");
>> +        ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, "1",
>> "next;");
>> +    }
>> +
>> +    /* Logical router ingress table 7: IP Routing.
>>       *
>>       * A packet that arrives at this table is an IP packet that should be
>>       * routed to the address in 'ip[46].dst'. This table sets outport to
>> @@ -5072,7 +5167,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
>> hmap *ports,
>>
>>      /* XXX destination unreachable */
>>
>> -    /* Local router ingress table 6: ARP Resolution.
>> +    /* Local router ingress table 8: ARP Resolution.
>>       *
>>       * Any packet that reaches this table is an IP packet whose next-hop
>> IP
>>       * address is in reg0. (ip4.dst is the final destination.) This table
>> @@ -5267,7 +5362,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
>> hmap *ports,
>>                        "get_nd(outport, xxreg0); next;");
>>      }
>>
>> -    /* Logical router ingress table 7: Gateway redirect.
>> +    /* Logical router ingress table 9: Gateway redirect.
>>       *
>>       * For traffic with outport equal to the l3dgw_port
>>       * on a distributed router, this table redirects a subset
>> @@ -5307,7 +5402,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
>> hmap *ports,
>>          ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 0, "1",
>> "next;");
>>      }
>>
>> -    /* Local router ingress table 8: ARP request.
>> +    /* Local router ingress table 10: ARP request.
>>       *
>>       * In the common case where the Ethernet destination has been
>> resolved,
>>       * this table outputs the packet (priority 0).  Otherwise, it
>> composes
>> diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
>> index c6a1417ff..a15a24c27 100644
>> --- a/ovn/ovn-nb.ovsschema
>> +++ b/ovn/ovn-nb.ovsschema
>> @@ -1,7 +1,7 @@
>>  {
>>      "name": "OVN_Northbound",
>> -    "version": "5.6.0",
>> -    "cksum": "2552205612 15123",
>> +    "version": "5.6.1",
>> +    "cksum": "3970773262 15286",
>>      "tables": {
>>          "NB_Global": {
>>              "columns": {
>> @@ -207,6 +207,9 @@
>>                  "mac": {"type": "string"},
>>                  "peer": {"type": {"key": "string", "min": 0, "max": 1}},
>>                  "enabled": {"type": {"key": "boolean", "min": 0, "max":
>> 1}},
>> +                "ipv6_ra_configs": {
>> +                    "type": {"key": "string", "value": "string",
>> +                             "min": 0, "max": "unlimited"}},
>>                  "external_ids": {
>>                      "type": {"key": "string", "value": "string",
>>                               "min": 0, "max": "unlimited"}}},
>> diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
>> index 32c10c147..c9ed80cce 100644
>> --- a/ovn/ovn-nb.xml
>> +++ b/ovn/ovn-nb.xml
>> @@ -1276,6 +1276,45 @@
>>        port has all ingress and egress traffic dropped.
>>      </column>
>>
>> +    <group title="ipv6_ra_configs">
>> +      <p>
>> +        This column defines the IPv6 ND RA address mode and ND MTU
>> Option to be
>> +        included by <code>ovn-controller</code> when it replies to the
>> IPv6
>> +        Router solicitation requests.
>> +      </p>
>> +
>> +      <column name="ipv6_ra_configs" key="address_mode">
>> +        The address mode to be used for IPv6 address configuration.
>> +        The supported values are:
>> +        <ul>
>> +          <li>
>> +            <code>slaac</code>: Address configuration using Router
>> +            Advertisement (RA) packet. The IPv6 prefixes defined in the
>> +            <ref table="Logical_Router_Port"/> table's
>> +            <ref table="Logical_Router_Port" column="networks"/> column
>> will
>> +            be included in the RA's ICMPv6 option - Prefix information.
>> +          </li>
>> +
>> +          <li>
>> +            <code>dhcpv6_stateful</code>: Address configuration using
>> DHCPv6.
>> +          </li>
>> +
>> +          <li>
>> +            <code>dhcpv6_stateless</code>: Address configuration using
>> Router
>> +            Advertisement (RA) packet. Other IPv6 options are provided by
>> +            DHCPv6.
>> +          </li>
>> +        </ul>
>> +      </column>
>> +
>> +      <column name="ipv6_ra_configs" key="mtu">
>> +        The recommended MTU for the link. Default is 0, which means no
>> MTU
>> +        Option will be included in RA packet replied by ovn-controller.
>> +        Per RFC 2460, the mtu value is recommended no less than 1280, so
>> +        any mtu value less than 1280 will be considered as no MTU Option.
>> +      </column>
>> +    </group>
>> +
>>      <group title="Options">
>>        <p>
>>          Additional options for the logical router port.
>> diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
>> index 824ff123a..43bcf380e 100644
>> --- a/ovn/ovn-sb.xml
>> +++ b/ovn/ovn-sb.xml
>> @@ -908,6 +908,10 @@
>>          <li><code>nd</code> expands to <code>icmp6.type == {135, 136}
>> &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
>>          <li><code>nd_ns</code> expands to <code>icmp6.type == 135
>> &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
>>          <li><code>nd_na</code> expands to <code>icmp6.type == 136
>> &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
>> +        <li><code>nd_rs</code> expands to <code>icmp6.type == 133
>> &amp;&amp;
>> +        icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
>> +        <li><code>nd_ra</code> expands to <code>icmp6.type == 134
>> &amp;&amp;
>> +        icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
>>          <li><code>tcp</code> expands to <code>ip.proto == 6</code></li>
>>          <li><code>udp</code> expands to <code>ip.proto == 17</code></li>
>>          <li><code>sctp</code> expands to <code>ip.proto ==
>> 132</code></li>
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index 8add532d7..f39481d5a 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -7306,6 +7306,243 @@ OVN_CLEANUP([hv1],[hv2],[hv3])
>>
>>  AT_CLEANUP
>>
>> +AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
>> +AT_KEYWORDS([ovn-nd_ra])
>> +AT_SKIP_IF([test $HAVE_PYTHON = no])
>> +ovn_start
>> +
>> +# In this test case we create 1 lswitch with 3 VIF ports attached,
>> +# and a lrouter connected to the lswitch.
>> +# We generate the Router solicitation packet and verify the Router
>> Advertisement
>> +# reply packet from the ovn-controller.
>> +
>> +# Create hypervisor and logical switch lsw0, logical router lr0, attach
>> lsw0
>> +# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode column
>> to
>> +# 'slaac' to allow lrp0 send RA for SLAAC mode.
>> +ovn-nbctl ls-add lsw0
>> +ovn-nbctl lr-add lr0
>> +ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
>> +ovn-nbctl set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode="
>> slaac"
>> +ovn-nbctl \
>> +    -- lsp-add lsw0 lsp0 \
>> +    -- set Logical_Switch_Port lsp0 type=router \
>> +                     options:router-port=lrp0 \
>> +                     addresses='"fa:16:3e:00:00:01 fdad:1234:5678::1"'
>> +net_add n1
>> +sim_add hv1
>> +as hv1
>> +ovs-vsctl add-br br-phys
>> +ovn_attach n1 br-phys 192.168.0.2
>> +
>> +ovn-nbctl lsp-add lsw0 lp1
>> +ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
>> fdad:1234:5678:0:f816:3eff:fe:2"
>> +ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
>> fdad:1234:5678:0:f816:3eff:fe:2"
>> +
>> +ovn-nbctl lsp-add lsw0 lp2
>> +ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
>> fdad:1234:5678:0:f816:3eff:fe:3"
>> +ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
>> fdad:1234:5678:0:f816:3eff:fe:3"
>> +
>> +ovn-nbctl lsp-add lsw0 lp3
>> +ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
>> fdad:1234:5678:0:f816:3eff:fe:4"
>> +ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
>> fdad:1234:5678:0:f816:3eff:fe:4"
>> +
>> +# Add ACL rule for ICMPv6 on lsw0
>> +ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
>> +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'
>> allow-related
>> +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'
>> allow-related
>> +ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 && icmp6'
>> allow-related
>> +
>> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
>> +    set interface hv1-vif1 external-ids:iface-id=lp1 \
>> +    options:tx_pcap=hv1/vif1-tx.pcap \
>> +    options:rxq_pcap=hv1/vif1-rx.pcap \
>> +    ofport-request=1
>> +
>> +ovs-vsctl -- add-port br-int hv1-vif2 -- \
>> +    set interface hv1-vif2 external-ids:iface-id=lp2 \
>> +    options:tx_pcap=hv1/vif2-tx.pcap \
>> +    options:rxq_pcap=hv1/vif2-rx.pcap \
>> +    ofport-request=2
>> +
>> +ovs-vsctl -- add-port br-int hv1-vif3 -- \
>> +    set interface hv1-vif3 external-ids:iface-id=lp3 \
>> +    options:tx_pcap=hv1/vif3-tx.pcap \
>> +    options:rxq_pcap=hv1/vif3-rx.pcap \
>> +    ofport-request=3
>> +
>> +# Allow some time for ovn-northd and ovn-controller to catch up.
>> +# XXX This should be more systematic.
>> +sleep 1
>> +
>> +reset_pcap_file() {
>> +    local iface=$1
>> +    local pcap_file=$2
>> +    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>> +options:rxq_pcap=dummy-rx.pcap
>> +    rm -f ${pcap_file}*.pcap
>> +    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap
>> \
>> +options:rxq_pcap=${pcap_file}-rx.pcap
>> +}
>> +
>> +# This shell function sends a Router Solicitation packet.
>> +# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
>> +test_ipv6_ra() {
>> +    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
>> prefix_opt=$6
>> +    local request=333300000002${src_mac}86dd6000000000103aff${src_lla}
>> ff02000000000000000000000000000285000efc000000000101${src_mac}
>> +
>> +    local len=24
>> +    local mtu_opt=""
>> +    if test $mtu != 0; then
>> +        len=`expr $len + 8`
>> +        mtu_opt=05010000${mtu}
>> +    fi
>> +
>> +    if test ${#prefix_opt} != 0; then
>> +        prefix_opt=${prefix_opt}fdad1234567800000000000000000000
>> +        len=`expr $len + ${#prefix_opt} / 2`
>> +    fi
>> +
>> +    len=$(printf "%x" $len)
>> +    local lrp_mac=fa163e000001
>> +    local lrp_lla=fe80000000000000f8163efffe000001
>> +    local reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}
>> ${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101$
>> {lrp_mac}${mtu_opt}${prefix_opt}
>> +    echo $reply >> $inport.expected
>> +
>> +    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
>> +}
>> +
>> +AT_CAPTURE_FILE([ofctl_monitor0.log])
>> +as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>> +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>> +
>> +# MTU is not set and the address mode is set to slaac
>> +addr_mode=00
>> +default_prefix_option_config=030440c0ffffffffffffffff00000000
>> +src_mac=fa163e000002
>> +src_lla=fe80000000000000f8163efffe000002
>> +test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
>> $default_prefix_option_config
>> +
>> +# NXT_RESUME should be 1.
>> +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
>> +
>> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  >
>> 1.packets
>> +
>> +cat 1.expected | cut -c -112 > expout
>> +AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>> +
>> +# Skipping the ICMPv6 checksum.
>> +cat 1.expected | cut -c 117- > expout
>> +AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>> +
>> +rm -f *.expected
>> +reset_pcap_file hv1-vif1 hv1/vif1
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +reset_pcap_file hv1-vif3 hv1/vif3
>> +
>> +# Set the MTU to 1500
>> +ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500
>> +
>> +addr_mode=00
>> +default_prefix_option_config=030440c0ffffffffffffffff00000000
>> +src_mac=fa163e000003
>> +src_lla=fe80000000000000f8163efffe000003
>> +mtu=000005dc
>> +
>> +test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
>> $default_prefix_option_config
>> +
>> +# NXT_RESUME should be 2.
>> +OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
>> +
>> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap  >
>> 2.packets
>> +
>> +cat 2.expected | cut -c -112 > expout
>> +AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>> +
>> +# Skipping the ICMPv6 checksum.
>> +cat 2.expected | cut -c 117- > expout
>> +AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>> +
>> +rm -f *.expected
>> +reset_pcap_file hv1-vif1 hv1/vif1
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +reset_pcap_file hv1-vif3 hv1/vif3
>> +
>> +# Set the address mode to dhcpv6_stateful
>> +ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>> ipv6_ra_configs:address_mode=dhcpv6_stateful
>> +
>> +addr_mode=80
>> +default_prefix_option_config=""
>> +src_mac=fa163e000004
>> +src_lla=fe80000000000000f8163efffe000004
>> +mtu=000005dc
>> +
>> +test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
>> $default_prefix_option_config
>> +
>> +# NXT_RESUME should be 3.
>> +OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
>> +
>> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap  >
>> 3.packets
>> +
>> +cat 3.expected | cut -c -112 > expout
>> +AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
>> +
>> +# Skipping the ICMPv6 checksum.
>> +cat 3.expected | cut -c 117- > expout
>> +AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
>> +
>> +rm -f *.expected
>> +reset_pcap_file hv1-vif1 hv1/vif1
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +reset_pcap_file hv1-vif3 hv1/vif3
>> +
>> +# Set the address mode to dhcpv6_stateless
>> +ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>> ipv6_ra_configs:address_mode=dhcpv6_stateless
>> +
>> +addr_mode=40
>> +default_prefix_option_config=030440c0ffffffffffffffff00000000
>> +src_mac=fa163e000002
>> +src_lla=fe80000000000000f8163efffe000002
>> +mtu=000005dc
>> +
>> +test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>> $default_prefix_option_config
>> +
>> +# NXT_RESUME should be 4.
>> +OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
>> +
>> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  >
>> 1.packets
>> +
>> +cat 1.expected | cut -c -112 > expout
>> +AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>> +
>> +# Skipping the ICMPv6 checksum.
>> +cat 1.expected | cut -c 117- > expout
>> +AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>> +
>> +rm -f *.expected
>> +reset_pcap_file hv1-vif1 hv1/vif1
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +reset_pcap_file hv1-vif3 hv1/vif3
>> +
>> +# Set the address mode to invalid.
>> +ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>> ipv6_ra_configs:address_mode=invalid
>> +
>> +addr_mode=40
>> +default_prefix_option_config=""
>> +src_mac=fa163e000002
>> +src_lla=fe80000000000000f8163efffe000002
>> +mtu=000005dc
>> +
>> +test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>> $default_prefix_option_config
>> +
>> +# NXT_RESUME should be 4 only.
>> +OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
>> +
>> +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  >
>> 1.packets
>> +AT_CHECK([cat 1.packets], [0], [])
>> +
>> +OVN_CLEANUP([hv1])
>> +AT_CLEANUP
>> +
>>  AT_SETUP([ovn -- /32 router IP address])
>>  AT_SKIP_IF([test $HAVE_PYTHON = no])
>>  ovn_start
>> --
>> 2.13.0
>>
>> _______________________________________________
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to