[ovs-dev,RFC,ovn,2/2] northd: add logical flows for dhcpv6 pfd parsing
diff mbox series

Message ID 080653d905ecc79ec8b941332453fa82995f07bb.1572024147.git.lorenzo.bianconi@redhat.com
State New
Headers show
Series
  • Add IPv6 Prefix delegation (RFC3633)
Related show

Commit Message

Lorenzo Bianconi Oct. 25, 2019, 5:36 p.m. UTC
Introduce logical flows in ovn router pipeline in order to parse dhcpv6
advertise/reply from IPv6 prefix delegation router.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 northd/ovn-northd.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index ea8ad7c2d..d2a545b2b 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -2570,6 +2570,8 @@  ovn_port_update_sbrec(struct northd_context *ctx,
                       struct sset *active_ha_chassis_grps)
 {
     sbrec_port_binding_set_datapath(op->sb, op->od->sb);
+    const char *ipv6_pd_list = NULL;
+
     if (op->nbrp) {
         /* If the router is for l3 gateway, it resides on a chassis
          * and its port type is "l3gateway". */
@@ -2692,6 +2694,12 @@  ovn_port_update_sbrec(struct northd_context *ctx,
                 smap_add(&new, "l3gateway-chassis", chassis_name);
             }
         }
+
+        ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list");
+        if (ipv6_pd_list) {
+            smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list);
+        }
+
         sbrec_port_binding_set_options(op->sb, &new);
         smap_destroy(&new);
 
@@ -2741,6 +2749,12 @@  ovn_port_update_sbrec(struct northd_context *ctx,
                 smap_add_format(&options,
                                 "qdisc_queue_id", "%d", queue_id);
             }
+
+            ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list");
+            if (ipv6_pd_list) {
+                smap_add(&options, "ipv6_ra_pd_list", ipv6_pd_list);
+            }
+
             sbrec_port_binding_set_options(op->sb, &options);
             smap_destroy(&options);
             if (ovn_is_known_nb_lsp_type(op->nbsp->type)) {
@@ -2790,6 +2804,12 @@  ovn_port_update_sbrec(struct northd_context *ctx,
                 if (chassis) {
                     smap_add(&new, "l3gateway-chassis", chassis);
                 }
+
+                ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list");
+                if (ipv6_pd_list) {
+                    smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list);
+                }
+
                 sbrec_port_binding_set_options(op->sb, &new);
                 smap_destroy(&new);
             } else {
@@ -5385,7 +5405,8 @@  build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
         }
 
         if (!op->nbsp->dhcpv4_options && !op->nbsp->dhcpv6_options) {
-            /* CMS has disabled both native DHCPv4 and DHCPv6 for this lport.
+            /* CMS has disabled native DHCPv4, DHCPv6 and prefix
+             * delegation for this lport.
              */
             continue;
         }
@@ -7055,6 +7076,31 @@  build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         free(snat_ips);
     }
 
+    /* DHCPv6 reply handling */
+    HMAP_FOR_EACH (op, key_node, ports) {
+        if (!op->nbrp) {
+            continue;
+        }
+
+        struct lport_addresses lrp_networks;
+        if (!extract_lrp_networks(op->nbrp, &lrp_networks)) {
+            continue;
+        }
+
+        for (size_t i = 0; i < lrp_networks.n_ipv6_addrs; i++) {
+            ds_clear(&actions);
+            ds_clear(&match);
+            ds_put_format(&match, "inport == %s && ip6.dst == %s"
+                          " && udp.src == 547 && udp.dst == 546",
+                          op->json_key, lrp_networks.ipv6_addrs[i].addr_s);
+            ds_put_format(&actions, "reg0 = 0; dhcp6_server_pkt { "
+                          "eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
+                          "outport <-> inport; output; };");
+            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100,
+                          ds_cstr(&match), ds_cstr(&actions));
+        }
+    }
+
     /* Logical router ingress table 1: IP Input for IPv6. */
     HMAP_FOR_EACH (op, key_node, ports) {
         if (!op->nbrp) {
@@ -7774,6 +7820,19 @@  build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
             continue;
         }
 
+        /* enable IPv6 prefix delegation */
+        bool prefix_delegation = smap_get_bool(&op->nbrp->options,
+                                               "prefix_delegation", false);
+        if (prefix_delegation) {
+            struct smap options;
+
+            smap_clone(&options, &op->sb->options);
+            smap_add(&options, "ipv6_prefix_delegation", "true");
+
+            sbrec_port_binding_set_options(op->sb, &options);
+            smap_destroy(&options);
+        }
+
         const char *address_mode = smap_get(
             &op->nbrp->ipv6_ra_configs, "address_mode");