[ovs-dev,ovn-ipv6,25/26,RFC] ovn: Add support for link-local addresses.
diff mbox

Message ID 1468306616-125783-26-git-send-email-jpettit@ovn.org
State RFC
Headers show

Commit Message

Justin Pettit July 12, 2016, 6:56 a.m. UTC
TODO:
    - Needs to update ovn-northd man page.
    - Code should be cleaned up.
---
 ovn/lib/ovn-util.c      |  5 +++++
 ovn/northd/ovn-northd.c | 39 ++++++++++++++++++++++++++++++---------
 ovn/ovn-nb.xml          |  6 ++++++
 3 files changed, 41 insertions(+), 9 deletions(-)

Patch
diff mbox

diff --git a/ovn/lib/ovn-util.c b/ovn/lib/ovn-util.c
index 7ad69ad..3e15c6b 100644
--- a/ovn/lib/ovn-util.c
+++ b/ovn/lib/ovn-util.c
@@ -175,6 +175,11 @@  extract_lrp_networks(const struct nbrec_logical_router_port *lrp,
         }
     }
 
+    /* Always add the IPv6 link local address. */
+    struct in6_addr lla;
+    in6_generate_lla(laddrs->ea, &lla);
+    add_ipv6_netaddr(laddrs, lla, 64);
+
     return true;
 }
 
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index e0e40d0..991018d 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -2086,12 +2086,17 @@  find_lrp_member_ip(const struct ovn_port *op, const char *ip_s)
 static void
 add_route(struct hmap *lflows, const struct ovn_port *op,
           const char *lrp_addr_s, const char *network_s, int plen,
-          const char *gateway)
+          const char *gateway, bool is_lla)
 {
     bool is_ipv4 = strchr(network_s, '.') ? true : false;
 
-    char *match = xasprintf("ip%s.dst == %s/%d", is_ipv4 ? "4" : "6",
-                            network_s, plen);
+    struct ds match = DS_EMPTY_INITIALIZER;
+    if (is_lla) {
+        /* xxx This is pretty hacky. */
+        ds_put_format(&match, "inport == %s && ", op->json_key);
+    }
+    ds_put_format(&match, "ip%s.dst == %s/%d", is_ipv4 ? "4" : "6",
+                  network_s, plen);
 
     struct ds actions = DS_EMPTY_INITIALIZER;
     ds_put_format(&actions, "ip.ttl--; %sreg0 = ", is_ipv4 ? "" : "xx");
@@ -2114,10 +2119,10 @@  add_route(struct hmap *lflows, const struct ovn_port *op,
 
     /* The priority here is calculated to implement longest-prefix-match
      * routing. */
-    ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_ROUTING, plen, match,
-                  ds_cstr(&actions));
+    ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_ROUTING, plen,
+                  ds_cstr(&match), ds_cstr(&actions));
     ds_destroy(&actions);
-    free(match);
+    ds_destroy(&match);
 }
 
 static void
@@ -2227,7 +2232,8 @@  build_static_route_flow(struct hmap *lflows, struct ovn_datapath *od,
         goto free_prefix_s;
     }
 
-    add_route(lflows, out_port, lrp_addr_s, prefix_s, plen, route->nexthop);
+    add_route(lflows, out_port, lrp_addr_s, prefix_s, plen,
+              route->nexthop, false);
 
 free_prefix_s:
     free(prefix_s);
@@ -2526,6 +2532,9 @@  build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         }
 
         if (op->lrp_networks.n_ipv6_addrs) {
+            /* xxx Fix this comment about broadcast */
+            /* xxx We should only drop a specific lla for the interface,
+             * xxx since theoretically, it could conflict on a diff iface. */
             /* L3 admission control: drop packets that originate from an
              * IPv6 address owned by the router or a broadcast address
              * known to the router (priority 100). */
@@ -2547,7 +2556,12 @@  build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                         "ip6.dst <-> ip6.src; "
                         "ip.ttl = 255; "
                         "icmp6.type = 129; "
+#if 0
+                        /* xxx Disable this to allow pinging the lla,
+                         * xxx since this clears the inport, and our lla
+                         * xxx route needs to scope it. */
                         "inport = \"\"; /* Allow sending out inport. */ "
+#endif
                         "next; ");
             ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
                           ds_cstr(&match), ds_cstr(&actions));
@@ -2733,13 +2747,20 @@  build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
             add_route(lflows, op, op->lrp_networks.ipv4_addrs[i].addr_s,
                       op->lrp_networks.ipv4_addrs[i].network_s,
-                      op->lrp_networks.ipv4_addrs[i].plen, NULL);
+                      op->lrp_networks.ipv4_addrs[i].plen, NULL, false);
         }
 
         for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
+            /* Do not route link local addresses. */
+            if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].addr)) {
+                add_route(lflows, op, op->lrp_networks.ipv6_addrs[i].addr_s,
+                          "fe80::", 64, NULL, true);
+                continue;
+            }
+
             add_route(lflows, op, op->lrp_networks.ipv6_addrs[i].addr_s,
                       op->lrp_networks.ipv6_addrs[i].network_s,
-                      op->lrp_networks.ipv6_addrs[i].plen, NULL);
+                      op->lrp_networks.ipv6_addrs[i].plen, NULL, false);
         }
     }
 
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index e571eeb..22a3fdf 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -801,6 +801,12 @@ 
         address is 192.168.0.1 and that packets destined to
         192.168.0.<var>x</var> should be routed to this port.
       </p>
+
+      <p>
+        A logical router port always adds a link-local IPv6 address
+        (fe80::/64) automatically generated from the interface's MAC
+        address using the modified EUI-64 format.
+      </p>
     </column>
 
     <column name="mac">