Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/817002/?format=api
{ "id": 817002, "url": "http://patchwork.ozlabs.org/api/patches/817002/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20170921160949.24901-1-nusiddiq@redhat.com/", "project": { "id": 47, "url": "http://patchwork.ozlabs.org/api/projects/47/?format=api", "name": "Open vSwitch", "link_name": "openvswitch", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "git@github.com:openvswitch/ovs.git", "webscm_url": "https://github.com/openvswitch/ovs", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170921160949.24901-1-nusiddiq@redhat.com>", "list_archive_url": null, "date": "2017-09-21T16:09:49", "name": "[ovs-dev,v8,3/4] ovn-northd: Add logical flows to support native IPv6 RA", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "04182983eaead65a630451ceb32dc2ff2540a56d", "submitter": { "id": 67480, "url": "http://patchwork.ozlabs.org/api/people/67480/?format=api", "name": "Numan Siddique", "email": "nusiddiq@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20170921160949.24901-1-nusiddiq@redhat.com/mbox/", "series": [ { "id": 4431, "url": "http://patchwork.ozlabs.org/api/series/4431/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=4431", "date": "2017-09-21T16:07:47", "name": "ovn IPv6: Add Router Solicitation responder support and generate Neighbor Solicitation request for unknown MACs", "version": 8, "mbox": "http://patchwork.ozlabs.org/series/4431/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/817002/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/817002/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "ovs-dev@mail.linuxfoundation.org" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=openvswitch.org\n\t(client-ip=140.211.169.12; helo=mail.linuxfoundation.org;\n\tenvelope-from=ovs-dev-bounces@openvswitch.org;\n\treceiver=<UNKNOWN>)", "ext-mx02.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com", "ext-mx02.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=nusiddiq@redhat.com" ], "Received": [ "from mail.linuxfoundation.org (mail.linuxfoundation.org\n\t[140.211.169.12])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xyhRd75K9z9t42\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 02:10:53 +1000 (AEST)", "from mail.linux-foundation.org (localhost [127.0.0.1])\n\tby mail.linuxfoundation.org (Postfix) with ESMTP id B130BB7F;\n\tThu, 21 Sep 2017 16:10:10 +0000 (UTC)", "from smtp1.linuxfoundation.org (smtp1.linux-foundation.org\n\t[172.17.192.35])\n\tby mail.linuxfoundation.org (Postfix) with ESMTPS id B8162B4B\n\tfor <dev@openvswitch.org>; Thu, 21 Sep 2017 16:10:09 +0000 (UTC)", "from mx1.redhat.com (mx1.redhat.com [209.132.183.28])\n\tby smtp1.linuxfoundation.org (Postfix) with ESMTPS id 4565941D\n\tfor <dev@openvswitch.org>; Thu, 21 Sep 2017 16:10:08 +0000 (UTC)", "from smtp.corp.redhat.com\n\t(int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 840308765C;\n\tThu, 21 Sep 2017 16:10:07 +0000 (UTC)", "from numans.blr.redhat.com (ovpn-116-55.sin2.redhat.com\n\t[10.67.116.55])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id BF83D61F21;\n\tThu, 21 Sep 2017 16:10:03 +0000 (UTC)" ], "X-Greylist": [ "domain auto-whitelisted by SQLgrey-1.7.6", "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.26]);\n\tThu, 21 Sep 2017 16:10:07 +0000 (UTC)" ], "DMARC-Filter": "OpenDMARC Filter v1.3.2 mx1.redhat.com 840308765C", "From": "nusiddiq@redhat.com", "To": "dev@openvswitch.org", "Date": "Thu, 21 Sep 2017 21:39:49 +0530", "Message-Id": "<20170921160949.24901-1-nusiddiq@redhat.com>", "In-Reply-To": "<20170921160747.24602-1-nusiddiq@redhat.com>", "References": "<20170921160747.24602-1-nusiddiq@redhat.com>", "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.15", "X-Spam-Status": "No, score=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI,\n\tRP_MATCHES_RCVD autolearn=disabled version=3.3.1", "X-Spam-Checker-Version": "SpamAssassin 3.3.1 (2010-03-16) on\n\tsmtp1.linux-foundation.org", "Subject": "[ovs-dev] [PATCH v8 3/4] ovn-northd: Add logical flows to support\n\tnative IPv6 RA", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.12", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "ovs-dev-bounces@openvswitch.org", "Errors-To": "ovs-dev-bounces@openvswitch.org" }, "content": "From: Zongkai LI <zealokii@gmail.com>\n\nThis patch adds logical flows which sends IPv6 Router Advertisement\npacket in response to the IPv6 Router Solicitation request. It uses\nthe actions \"put_nd_ra_opts\" to transform the RS packet to RA packet\nin the newly added ingress stage \"lr_in_nd_ra_options\" in router\npipeline. If the action \"put_nd_ra_opts\" is successful, it sends the\nRA packet back to the originating port in the next ingress stage\n\"lr_in_nd_ra_response\".\n\nA new column \"ipv6_ra_configs\" is added in the Logical_Router_Port\ntable, which the CMS is expected to configure IPv6 RA\nconfigurations - \"address_mode\" and \"mtu\" for adding these flows.\n\nCo-authored-by: Numan Siddique <nusiddiq@redhat.com>\nSigned-off-by: Zongkai LI <zealokii@gmail.com>\nSigned-off-by: Numan Siddique <nusiddiq@redhat.com>\nAcked-by: Miguel Angel Ajo <majopela@redhat.com>\n---\n ovn/lib/logical-fields.c | 4 +\n ovn/northd/ovn-northd.8.xml | 83 ++++++++++++++-\n ovn/northd/ovn-northd.c | 137 +++++++++++++++++++++---\n ovn/ovn-nb.ovsschema | 7 +-\n ovn/ovn-nb.xml | 39 +++++++\n ovn/ovn-sb.xml | 4 +\n tests/ovn.at | 249 ++++++++++++++++++++++++++++++++++++++++++++\n 7 files changed, 500 insertions(+), 23 deletions(-)", "diff": "diff --git a/ovn/lib/logical-fields.c b/ovn/lib/logical-fields.c\nindex 26e336f5a..a8b5e3c51 100644\n--- a/ovn/lib/logical-fields.c\n+++ b/ovn/lib/logical-fields.c\n@@ -183,6 +183,10 @@ ovn_init_symtab(struct shash *symtab)\n \"icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255\");\n expr_symtab_add_predicate(symtab, \"nd_na\",\n \"icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255\");\n+ expr_symtab_add_predicate(symtab, \"nd_rs\",\n+ \"icmp6.type == 133 && icmp6.code == 0 && ip.ttl == 255\");\n+ expr_symtab_add_predicate(symtab, \"nd_ra\",\n+ \"icmp6.type == 134 && icmp6.code == 0 && ip.ttl == 255\");\n expr_symtab_add_field(symtab, \"nd.target\", MFF_ND_TARGET, \"nd\", false);\n expr_symtab_add_field(symtab, \"nd.sll\", MFF_ND_SLL, \"nd_ns\", false);\n expr_symtab_add_field(symtab, \"nd.tll\", MFF_ND_TLL, \"nd_na\", false);\ndiff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml\nindex 0d85ec0d2..a994abf78 100644\n--- a/ovn/northd/ovn-northd.8.xml\n+++ b/ovn/northd/ovn-northd.8.xml\n@@ -1584,7 +1584,82 @@ icmp4 {\n </li>\n </ul>\n \n- <h3>Ingress Table 5: IP Routing</h3>\n+ <h3>Ingress Table 5: IPv6 ND RA option processing</h3>\n+\n+ <ul>\n+ <li>\n+ <p>\n+ A priority-50 logical flow is added for each logical router port\n+ configured with IPv6 ND RA options which matches IPv6 ND Router\n+ Solicitation packet and applies the action\n+ <code>put_nd_ra_opts</code> and advances the packet to the next\n+ table.\n+ </p>\n+\n+ <pre>\n+reg0[5] = put_nd_ra_opts(<var>options</var>);next;\n+ </pre>\n+\n+ <p>\n+ For a valid IPv6 ND RS packet, this transforms the packet into an\n+ IPv6 ND RA reply and sets the RA options to the packet and stores 1\n+ into reg0[5]. For other kinds of packets, it just stores 0 into\n+ reg0[5]. Either way, it continues to the next table.\n+ </p>\n+ </li>\n+\n+ <li>\n+ A priority-0 logical flow with match <code>1</code> has actions\n+ <code>next;</code>.\n+ </li>\n+ </ul>\n+\n+ <h3>Ingress Table 6: IPv6 ND RA responder</h3>\n+\n+ <p>\n+ This table implements IPv6 ND RA responder for the IPv6 ND RA replies\n+ generated by the previous table.\n+ </p>\n+\n+ <ul>\n+ <li>\n+ <p>\n+ A priority-50 logical flow is added for each logical router port\n+ configured with IPv6 ND RA options which matches IPv6 ND RA\n+ packets and <code>reg0[5] == 1</code> and responds back to the\n+ <code>inport</code> after applying these actions.\n+ If <code>reg0[5]</code> is set to 1, it means that the action\n+ <code>put_nd_ra_opts</code> was successful.\n+ </p>\n+\n+ <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+ip6.dst = ip6.src;\n+ip6.src = <var>I</var>;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+output;\n+ </pre>\n+\n+ <p>\n+ where <var>E</var> is the MAC address and <var>I</var> is the IPv6\n+ link local address of the logical router port.\n+ </p>\n+\n+ <p>\n+ (This terminates packet processing in ingress pipeline; the packet\n+ does not go to the next ingress table.)\n+ </p>\n+ </li>\n+\n+ <li>\n+ A priority-0 logical flow with match <code>1</code> has actions\n+ <code>next;</code>.\n+ </li>\n+ </ul>\n+\n+ <h3>Ingress Table 7: IP Routing</h3>\n \n <p>\n A packet that arrives at this table is an IP packet that should be\n@@ -1686,7 +1761,7 @@ next;\n </li>\n </ul>\n \n- <h3>Ingress Table 6: ARP/ND Resolution</h3>\n+ <h3>Ingress Table 8: ARP/ND Resolution</h3>\n \n <p>\n Any packet that reaches this table is an IP packet whose next-hop\n@@ -1779,7 +1854,7 @@ next;\n </li>\n </ul>\n \n- <h3>Ingress Table 7: Gateway Redirect</h3>\n+ <h3>Ingress Table 9: Gateway Redirect</h3>\n \n <p>\n For distributed logical routers where one of the logical router\n@@ -1836,7 +1911,7 @@ next;\n </li>\n </ul>\n \n- <h3>Ingress Table 8: ARP Request</h3>\n+ <h3>Ingress Table 10: ARP Request</h3>\n \n <p>\n In the common case where the Ethernet destination has been resolved, this\ndiff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c\nindex 75f2c6607..3da20d25b 100644\n--- a/ovn/northd/ovn-northd.c\n+++ b/ovn/northd/ovn-northd.c\n@@ -129,15 +129,17 @@ enum ovn_stage {\n PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 8, \"ls_out_port_sec_l2\") \\\n \\\n /* Logical router ingress stages. */ \\\n- PIPELINE_STAGE(ROUTER, IN, ADMISSION, 0, \"lr_in_admission\") \\\n- PIPELINE_STAGE(ROUTER, IN, IP_INPUT, 1, \"lr_in_ip_input\") \\\n- PIPELINE_STAGE(ROUTER, IN, DEFRAG, 2, \"lr_in_defrag\") \\\n- PIPELINE_STAGE(ROUTER, IN, UNSNAT, 3, \"lr_in_unsnat\") \\\n- PIPELINE_STAGE(ROUTER, IN, DNAT, 4, \"lr_in_dnat\") \\\n- PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 5, \"lr_in_ip_routing\") \\\n- PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 6, \"lr_in_arp_resolve\") \\\n- PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 7, \"lr_in_gw_redirect\") \\\n- PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 8, \"lr_in_arp_request\") \\\n+ PIPELINE_STAGE(ROUTER, IN, ADMISSION, 0, \"lr_in_admission\") \\\n+ PIPELINE_STAGE(ROUTER, IN, IP_INPUT, 1, \"lr_in_ip_input\") \\\n+ PIPELINE_STAGE(ROUTER, IN, DEFRAG, 2, \"lr_in_defrag\") \\\n+ PIPELINE_STAGE(ROUTER, IN, UNSNAT, 3, \"lr_in_unsnat\") \\\n+ PIPELINE_STAGE(ROUTER, IN, DNAT, 4, \"lr_in_dnat\") \\\n+ PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 5, \"lr_in_nd_ra_options\") \\\n+ PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 6, \"lr_in_nd_ra_response\") \\\n+ PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 7, \"lr_in_ip_routing\") \\\n+ PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 8, \"lr_in_arp_resolve\") \\\n+ PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 9, \"lr_in_gw_redirect\") \\\n+ PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 10, \"lr_in_arp_request\") \\\n \\\n /* Logical router egress stages. */ \\\n PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, \"lr_out_undnat\") \\\n@@ -159,11 +161,12 @@ enum ovn_stage {\n #define OVN_ACL_PRI_OFFSET 1000\n \n /* Register definitions specific to switches. */\n-#define REGBIT_CONNTRACK_DEFRAG \"reg0[0]\"\n-#define REGBIT_CONNTRACK_COMMIT \"reg0[1]\"\n-#define REGBIT_CONNTRACK_NAT \"reg0[2]\"\n-#define REGBIT_DHCP_OPTS_RESULT \"reg0[3]\"\n+#define REGBIT_CONNTRACK_DEFRAG \"reg0[0]\"\n+#define REGBIT_CONNTRACK_COMMIT \"reg0[1]\"\n+#define REGBIT_CONNTRACK_NAT \"reg0[2]\"\n+#define REGBIT_DHCP_OPTS_RESULT \"reg0[3]\"\n #define REGBIT_DNS_LOOKUP_RESULT \"reg0[4]\"\n+#define REGBIT_ND_RA_OPTS_RESULT \"reg0[5]\"\n \n /* Register definitions for switches and routers. */\n #define REGBIT_NAT_REDIRECT \"reg9[0]\"\n@@ -2868,7 +2871,11 @@ build_pre_acls(struct ovn_datapath *od, struct hmap *lflows)\n *\n * Not to do conntrack on ND packets. */\n ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110, \"nd\", \"next;\");\n+ ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110, \"(nd_rs || nd_ra)\",\n+ \"next;\");\n ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110, \"nd\", \"next;\");\n+ ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,\n+ \"(nd_rs || nd_ra)\", \"next;\");\n \n /* Ingress and Egress Pre-ACL Table (Priority 100).\n *\n@@ -5319,7 +5326,103 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,\n sset_destroy(&all_ips);\n }\n \n- /* Logical router ingress table 5: IP Routing.\n+ /* Logical router ingress table 5 and 6: IPv6 Router Adv (RA) options and\n+ * response. */\n+ HMAP_FOR_EACH (op, key_node, ports) {\n+ if (!op->nbrp || op->nbrp->peer || !op->peer) {\n+ continue;\n+ }\n+\n+ if (!op->lrp_networks.n_ipv6_addrs) {\n+ continue;\n+ }\n+\n+ const char *address_mode = smap_get(\n+ &op->nbrp->ipv6_ra_configs, \"address_mode\");\n+\n+ if (!address_mode) {\n+ continue;\n+ }\n+ if (strcmp(address_mode, \"slaac\") &&\n+ strcmp(address_mode, \"dhcpv6_stateful\") &&\n+ strcmp(address_mode, \"dhcpv6_stateless\")) {\n+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);\n+ VLOG_WARN_RL(&rl, \"Invalid address mode [%s] defined\",\n+ address_mode);\n+ continue;\n+ }\n+\n+ ds_clear(&match);\n+ ds_put_format(&match, \"inport == %s && ip6.dst == ff02::2 && nd_rs\",\n+ op->json_key);\n+ ds_clear(&actions);\n+\n+ const char *mtu_s = smap_get(\n+ &op->nbrp->ipv6_ra_configs, \"mtu\");\n+\n+ /* As per RFC 2460, 1280 is minimum IPv6 MTU. */\n+ uint32_t mtu = (mtu_s && atoi(mtu_s) >= 1280) ? atoi(mtu_s) : 0;\n+\n+ ds_put_format(&actions, REGBIT_ND_RA_OPTS_RESULT\" = put_nd_ra_opts(\"\n+ \"addr_mode = \\\"%s\\\", slla = %s\",\n+ address_mode, op->lrp_networks.ea_s);\n+ if (mtu > 0) {\n+ ds_put_format(&actions, \", mtu = %u\", mtu);\n+ }\n+\n+ bool add_rs_response_flow = false;\n+\n+ for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {\n+ if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].network)) {\n+ continue;\n+ }\n+\n+ /* Add the prefix option if the address mode is slaac or\n+ * dhcpv6_stateless. */\n+ if (strcmp(address_mode, \"dhcpv6_stateful\")) {\n+ ds_put_format(&actions, \", prefix = %s/%u\",\n+ op->lrp_networks.ipv6_addrs[i].network_s,\n+ op->lrp_networks.ipv6_addrs[i].plen);\n+ }\n+ add_rs_response_flow = true;\n+ }\n+\n+ if (add_rs_response_flow) {\n+ ds_put_cstr(&actions, \"); next;\");\n+ ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS, 50,\n+ ds_cstr(&match), ds_cstr(&actions));\n+ ds_clear(&actions);\n+ ds_clear(&match);\n+ ds_put_format(&match, \"inport == %s && ip6.dst == ff02::2 && \"\n+ \"nd_ra && \"REGBIT_ND_RA_OPTS_RESULT, op->json_key);\n+\n+ char ip6_str[INET6_ADDRSTRLEN + 1];\n+ struct in6_addr lla;\n+ in6_generate_lla(op->lrp_networks.ea, &lla);\n+ memset(ip6_str, 0, sizeof(ip6_str));\n+ ipv6_string_mapped(ip6_str, &lla);\n+ ds_put_format(&actions, \"eth.dst = eth.src; eth.src = %s; \"\n+ \"ip6.dst = ip6.src; ip6.src = %s; \"\n+ \"outport = inport; flags.loopback = 1; \"\n+ \"output;\",\n+ op->lrp_networks.ea_s, ip6_str);\n+ ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_RESPONSE, 50,\n+ ds_cstr(&match), ds_cstr(&actions));\n+ }\n+ }\n+\n+ /* Logical router ingress table 5, 6: RS responder, by default goto next.\n+ * (priority 0)*/\n+ HMAP_FOR_EACH (od, key_node, datapaths) {\n+ if (!od->nbr) {\n+ continue;\n+ }\n+\n+ ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, \"1\", \"next;\");\n+ ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, \"1\", \"next;\");\n+ }\n+\n+ /* Logical router ingress table 7: IP Routing.\n *\n * A packet that arrives at this table is an IP packet that should be\n * routed to the address in 'ip[46].dst'. This table sets outport to\n@@ -5361,7 +5464,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,\n \n /* XXX destination unreachable */\n \n- /* Local router ingress table 6: ARP Resolution.\n+ /* Local router ingress table 8: ARP Resolution.\n *\n * Any packet that reaches this table is an IP packet whose next-hop IP\n * address is in reg0. (ip4.dst is the final destination.) This table\n@@ -5556,7 +5659,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,\n \"get_nd(outport, xxreg0); next;\");\n }\n \n- /* Logical router ingress table 7: Gateway redirect.\n+ /* Logical router ingress table 9: Gateway redirect.\n *\n * For traffic with outport equal to the l3dgw_port\n * on a distributed router, this table redirects a subset\n@@ -5596,7 +5699,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,\n ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 0, \"1\", \"next;\");\n }\n \n- /* Local router ingress table 8: ARP request.\n+ /* Local router ingress table 10: ARP request.\n *\n * In the common case where the Ethernet destination has been resolved,\n * this table outputs the packet (priority 0). Otherwise, it composes\ndiff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema\nindex a077bfb81..fcd878cf2 100644\n--- a/ovn/ovn-nb.ovsschema\n+++ b/ovn/ovn-nb.ovsschema\n@@ -1,7 +1,7 @@\n {\n \"name\": \"OVN_Northbound\",\n- \"version\": \"5.8.0\",\n- \"cksum\": \"2812300190 16766\",\n+ \"version\": \"5.8.1\",\n+ \"cksum\": \"607160660 16929\",\n \"tables\": {\n \"NB_Global\": {\n \"columns\": {\n@@ -222,6 +222,9 @@\n \"mac\": {\"type\": \"string\"},\n \"peer\": {\"type\": {\"key\": \"string\", \"min\": 0, \"max\": 1}},\n \"enabled\": {\"type\": {\"key\": \"boolean\", \"min\": 0, \"max\": 1}},\n+ \"ipv6_ra_configs\": {\n+ \"type\": {\"key\": \"string\", \"value\": \"string\",\n+ \"min\": 0, \"max\": \"unlimited\"}},\n \"external_ids\": {\n \"type\": {\"key\": \"string\", \"value\": \"string\",\n \"min\": 0, \"max\": \"unlimited\"}}},\ndiff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml\nindex 9869d7ed7..8ad53cd7d 100644\n--- a/ovn/ovn-nb.xml\n+++ b/ovn/ovn-nb.xml\n@@ -1332,6 +1332,45 @@\n port has all ingress and egress traffic dropped.\n </column>\n \n+ <group title=\"ipv6_ra_configs\">\n+ <p>\n+ This column defines the IPv6 ND RA address mode and ND MTU Option to be\n+ included by <code>ovn-controller</code> when it replies to the IPv6\n+ Router solicitation requests.\n+ </p>\n+\n+ <column name=\"ipv6_ra_configs\" key=\"address_mode\">\n+ The address mode to be used for IPv6 address configuration.\n+ The supported values are:\n+ <ul>\n+ <li>\n+ <code>slaac</code>: Address configuration using Router\n+ Advertisement (RA) packet. The IPv6 prefixes defined in the\n+ <ref table=\"Logical_Router_Port\"/> table's\n+ <ref table=\"Logical_Router_Port\" column=\"networks\"/> column will\n+ be included in the RA's ICMPv6 option - Prefix information.\n+ </li>\n+\n+ <li>\n+ <code>dhcpv6_stateful</code>: Address configuration using DHCPv6.\n+ </li>\n+\n+ <li>\n+ <code>dhcpv6_stateless</code>: Address configuration using Router\n+ Advertisement (RA) packet. Other IPv6 options are provided by\n+ DHCPv6.\n+ </li>\n+ </ul>\n+ </column>\n+\n+ <column name=\"ipv6_ra_configs\" key=\"mtu\">\n+ The recommended MTU for the link. Default is 0, which means no MTU\n+ Option will be included in RA packet replied by ovn-controller.\n+ Per RFC 2460, the mtu value is recommended no less than 1280, so\n+ any mtu value less than 1280 will be considered as no MTU Option.\n+ </column>\n+ </group>\n+\n <group title=\"Options\">\n <p>\n Additional options for the logical router port.\ndiff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml\nindex fab3f9de6..2e4f28b96 100644\n--- a/ovn/ovn-sb.xml\n+++ b/ovn/ovn-sb.xml\n@@ -911,6 +911,10 @@\n <li><code>nd</code> expands to <code>icmp6.type == {135, 136} && icmp6.code == 0 && ip.ttl == 255</code></li>\n <li><code>nd_ns</code> expands to <code>icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255</code></li>\n <li><code>nd_na</code> expands to <code>icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255</code></li>\n+ <li><code>nd_rs</code> expands to <code>icmp6.type == 133 &&\n+ icmp6.code == 0 && ip.ttl == 255</code></li>\n+ <li><code>nd_ra</code> expands to <code>icmp6.type == 134 &&\n+ icmp6.code == 0 && ip.ttl == 255</code></li>\n <li><code>tcp</code> expands to <code>ip.proto == 6</code></li>\n <li><code>udp</code> expands to <code>ip.proto == 17</code></li>\n <li><code>sctp</code> expands to <code>ip.proto == 132</code></li>\ndiff --git a/tests/ovn.at b/tests/ovn.at\nindex e56dc6232..3aa4e5e22 100644\n--- a/tests/ovn.at\n+++ b/tests/ovn.at\n@@ -7847,6 +7847,255 @@ OVN_CLEANUP([hv1],[hv2],[hv3])\n \n AT_CLEANUP\n \n+AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])\n+AT_KEYWORDS([ovn-nd_ra])\n+AT_SKIP_IF([test $HAVE_PYTHON = no])\n+ovn_start\n+\n+# In this test case we create 1 lswitch with 3 VIF ports attached,\n+# and a lrouter connected to the lswitch.\n+# We generate the Router solicitation packet and verify the Router Advertisement\n+# reply packet from the ovn-controller.\n+\n+# Create hypervisor and logical switch lsw0, logical router lr0, attach lsw0\n+# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode column to\n+# 'slaac' to allow lrp0 send RA for SLAAC mode.\n+ovn-nbctl ls-add lsw0\n+ovn-nbctl lr-add lr0\n+ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64\n+ovn-nbctl set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=\"slaac\"\n+ovn-nbctl \\\n+ -- lsp-add lsw0 lsp0 \\\n+ -- set Logical_Switch_Port lsp0 type=router \\\n+ options:router-port=lrp0 \\\n+ addresses='\"fa:16:3e:00:00:01 fdad:1234:5678::1\"'\n+net_add n1\n+sim_add hv1\n+as hv1\n+ovs-vsctl add-br br-phys\n+ovn_attach n1 br-phys 192.168.0.2\n+\n+ovn-nbctl lsp-add lsw0 lp1\n+ovn-nbctl lsp-set-addresses lp1 \"fa:16:3e:00:00:02 10.0.0.12 fdad:1234:5678:0:f816:3eff:fe:2\"\n+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\"\n+\n+ovn-nbctl lsp-add lsw0 lp2\n+ovn-nbctl lsp-set-addresses lp2 \"fa:16:3e:00:00:03 10.0.0.13 fdad:1234:5678:0:f816:3eff:fe:3\"\n+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\"\n+\n+ovn-nbctl lsp-add lsw0 lp3\n+ovn-nbctl lsp-set-addresses lp3 \"fa:16:3e:00:00:04 10.0.0.14 fdad:1234:5678:0:f816:3eff:fe:4\"\n+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\"\n+\n+# Add ACL rule for ICMPv6 on lsw0\n+ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6' allow-related\n+ovn-nbctl acl-add lsw0 to-lport 1002 'outport == \"lp1\" && ip6 && icmp6' allow-related\n+ovn-nbctl acl-add lsw0 to-lport 1002 'outport == \"lp2\" && ip6 && icmp6' allow-related\n+ovn-nbctl acl-add lsw0 to-lport 1002 'outport == \"lp3\" && ip6 && icmp6' allow-related\n+\n+ovs-vsctl -- add-port br-int hv1-vif1 -- \\\n+ set interface hv1-vif1 external-ids:iface-id=lp1 \\\n+ options:tx_pcap=hv1/vif1-tx.pcap \\\n+ options:rxq_pcap=hv1/vif1-rx.pcap \\\n+ ofport-request=1\n+\n+ovs-vsctl -- add-port br-int hv1-vif2 -- \\\n+ set interface hv1-vif2 external-ids:iface-id=lp2 \\\n+ options:tx_pcap=hv1/vif2-tx.pcap \\\n+ options:rxq_pcap=hv1/vif2-rx.pcap \\\n+ ofport-request=2\n+\n+ovs-vsctl -- add-port br-int hv1-vif3 -- \\\n+ set interface hv1-vif3 external-ids:iface-id=lp3 \\\n+ options:tx_pcap=hv1/vif3-tx.pcap \\\n+ options:rxq_pcap=hv1/vif3-rx.pcap \\\n+ ofport-request=3\n+\n+# Allow some time for ovn-northd and ovn-controller to catch up.\n+# XXX This should be more systematic.\n+sleep 1\n+\n+reset_pcap_file() {\n+ local iface=$1\n+ local pcap_file=$2\n+ ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \\\n+options:rxq_pcap=dummy-rx.pcap\n+ rm -f ${pcap_file}*.pcap\n+ ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \\\n+options:rxq_pcap=${pcap_file}-rx.pcap\n+}\n+\n+# Make sure that ovn-controller has installed the corresponding OF Flow.\n+OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c \"ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0\"`])\n+\n+# This shell function sends a Router Solicitation packet.\n+# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT\n+test_ipv6_ra() {\n+ local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5 prefix_opt=$6\n+ local request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac}\n+\n+ local len=24\n+ local mtu_opt=\"\"\n+ if test $mtu != 0; then\n+ len=`expr $len + 8`\n+ mtu_opt=05010000${mtu}\n+ fi\n+\n+ if test ${#prefix_opt} != 0; then\n+ prefix_opt=${prefix_opt}fdad1234567800000000000000000000\n+ len=`expr $len + ${#prefix_opt} / 2`\n+ fi\n+\n+ len=$(printf \"%x\" $len)\n+ local lrp_mac=fa163e000001\n+ local lrp_lla=fe80000000000000f8163efffe000001\n+ local reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt}\n+ echo $reply >> $inport.expected\n+\n+ as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request\n+}\n+\n+AT_CAPTURE_FILE([ofctl_monitor0.log])\n+as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \\\n+--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log\n+\n+# MTU is not set and the address mode is set to slaac\n+addr_mode=00\n+default_prefix_option_config=030440c0ffffffffffffffff00000000\n+src_mac=fa163e000002\n+src_lla=fe80000000000000f8163efffe000002\n+test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0 $default_prefix_option_config\n+\n+# NXT_RESUME should be 1.\n+OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])\n+\n+$PYTHON \"$top_srcdir/utilities/ovs-pcap.in\" hv1/vif1-tx.pcap > 1.packets\n+\n+cat 1.expected | cut -c -112 > expout\n+AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])\n+\n+# Skipping the ICMPv6 checksum.\n+cat 1.expected | cut -c 117- > expout\n+AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])\n+\n+rm -f *.expected\n+reset_pcap_file hv1-vif1 hv1/vif1\n+reset_pcap_file hv1-vif2 hv1/vif2\n+reset_pcap_file hv1-vif3 hv1/vif3\n+\n+# Set the MTU to 1500\n+ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500\n+\n+# Make sure that ovn-controller has installed the corresponding OF Flow.\n+OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c \"ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0\"`])\n+\n+addr_mode=00\n+default_prefix_option_config=030440c0ffffffffffffffff00000000\n+src_mac=fa163e000003\n+src_lla=fe80000000000000f8163efffe000003\n+mtu=000005dc\n+\n+test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config\n+\n+# NXT_RESUME should be 2.\n+OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])\n+\n+$PYTHON \"$top_srcdir/utilities/ovs-pcap.in\" hv1/vif2-tx.pcap > 2.packets\n+\n+cat 2.expected | cut -c -112 > expout\n+AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])\n+\n+# Skipping the ICMPv6 checksum.\n+cat 2.expected | cut -c 117- > expout\n+AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])\n+\n+rm -f *.expected\n+reset_pcap_file hv1-vif1 hv1/vif1\n+reset_pcap_file hv1-vif2 hv1/vif2\n+reset_pcap_file hv1-vif3 hv1/vif3\n+\n+# Set the address mode to dhcpv6_stateful\n+ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateful\n+# Make sure that ovn-controller has installed the corresponding OF Flow.\n+OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c \"ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0\"`])\n+\n+addr_mode=80\n+default_prefix_option_config=\"\"\n+src_mac=fa163e000004\n+src_lla=fe80000000000000f8163efffe000004\n+mtu=000005dc\n+\n+test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config\n+\n+# NXT_RESUME should be 3.\n+OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])\n+\n+$PYTHON \"$top_srcdir/utilities/ovs-pcap.in\" hv1/vif3-tx.pcap > 3.packets\n+\n+cat 3.expected | cut -c -112 > expout\n+AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])\n+\n+# Skipping the ICMPv6 checksum.\n+cat 3.expected | cut -c 117- > expout\n+AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])\n+\n+rm -f *.expected\n+reset_pcap_file hv1-vif1 hv1/vif1\n+reset_pcap_file hv1-vif2 hv1/vif2\n+reset_pcap_file hv1-vif3 hv1/vif3\n+\n+# Set the address mode to dhcpv6_stateless\n+ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateless\n+# Make sure that ovn-controller has installed the corresponding OF Flow.\n+OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c \"ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0\"`])\n+\n+addr_mode=40\n+default_prefix_option_config=030440c0ffffffffffffffff00000000\n+src_mac=fa163e000002\n+src_lla=fe80000000000000f8163efffe000002\n+mtu=000005dc\n+\n+test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config\n+\n+# NXT_RESUME should be 4.\n+OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])\n+\n+$PYTHON \"$top_srcdir/utilities/ovs-pcap.in\" hv1/vif1-tx.pcap > 1.packets\n+\n+cat 1.expected | cut -c -112 > expout\n+AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])\n+\n+# Skipping the ICMPv6 checksum.\n+cat 1.expected | cut -c 117- > expout\n+AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])\n+\n+rm -f *.expected\n+reset_pcap_file hv1-vif1 hv1/vif1\n+reset_pcap_file hv1-vif2 hv1/vif2\n+reset_pcap_file hv1-vif3 hv1/vif3\n+\n+# Set the address mode to invalid.\n+ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=invalid\n+# Make sure that ovn-controller has not installed any OF Flow for IPv6 ND RA.\n+OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | grep -c \"ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0\"`])\n+\n+addr_mode=40\n+default_prefix_option_config=\"\"\n+src_mac=fa163e000002\n+src_lla=fe80000000000000f8163efffe000002\n+mtu=000005dc\n+\n+test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config\n+\n+# NXT_RESUME should be 4 only.\n+OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])\n+\n+$PYTHON \"$top_srcdir/utilities/ovs-pcap.in\" hv1/vif1-tx.pcap > 1.packets\n+AT_CHECK([cat 1.packets], [0], [])\n+\n+OVN_CLEANUP([hv1])\n+AT_CLEANUP\n+\n AT_SETUP([ovn -- /32 router IP address])\n AT_SKIP_IF([test $HAVE_PYTHON = no])\n ovn_start\n", "prefixes": [ "ovs-dev", "v8", "3/4" ] }