diff mbox

[ovs-dev,IPv6,v2,09/10] ovn: Add support for link-local addresses.

Message ID 1469773580-33112-9-git-send-email-jpettit@ovn.org
State Accepted
Headers show

Commit Message

Justin Pettit July 29, 2016, 6:26 a.m. UTC
Every IPv6-enabled interface is supposed to have a link-local address
available to it.  This commit adds a link local interface to each router
port and scopes link-local routes to the ingress port that received the
packet.

Signed-off-by: Justin Pettit <jpettit@ovn.org>
---
 ovn/lib/ovn-util.c          | 11 +++++++++--
 ovn/northd/ovn-northd.8.xml |  5 +++++
 ovn/northd/ovn-northd.c     | 15 ++++++++++-----
 ovn/ovn-nb.xml              |  6 ++++++
 4 files changed, 30 insertions(+), 7 deletions(-)

Comments

Ben Pfaff July 29, 2016, 5:46 p.m. UTC | #1
On Thu, Jul 28, 2016 at 11:26:19PM -0700, Justin Pettit wrote:
> Every IPv6-enabled interface is supposed to have a link-local address
> available to it.  This commit adds a link local interface to each router
> port and scopes link-local routes to the ingress port that received the
> packet.
> 
> Signed-off-by: Justin Pettit <jpettit@ovn.org>

In add_route() in ovn-northd.c, I don't think that it's ideal to use a
string comparison to compare an IPv6 address:
+    struct ds match = DS_EMPTY_INITIALIZER;
+    if (!strcmp("fe80::", network_s) && plen == 64) {

Acked-by: Ben Pfaff <blp@ovn.org>
diff mbox

Patch

diff --git a/ovn/lib/ovn-util.c b/ovn/lib/ovn-util.c
index 51e3026..f90670e 100644
--- a/ovn/lib/ovn-util.c
+++ b/ovn/lib/ovn-util.c
@@ -122,9 +122,11 @@  extract_lsp_addresses(char *address, struct lport_addresses *laddrs)
 /* Extracts the mac, IPv4 and IPv6 addresses from the
  * "nbrec_logical_router_port" parameter 'lrp'.  Stores the IPv4 and
  * IPv6 addresses in the 'ipv4_addrs' and 'ipv6_addrs' fields of
- * 'laddrs', respectively.
+ * 'laddrs', respectively.  In addition, a link local IPv6 address
+ * based on the 'mac' member of 'lrp' is added to the 'ipv6_addrs'
+ * field.
  *
- * Return true if at least 'MAC' is found in 'lrp', false otherwise.
+ * Return true if a valid 'mac' address is found in 'lrp', false otherwise.
  *
  * The caller must call destroy_lport_addresses(). */
 bool
@@ -175,6 +177,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.8.xml b/ovn/northd/ovn-northd.8.xml
index 790ca7e..bfcaeb5 100644
--- a/ovn/northd/ovn-northd.8.xml
+++ b/ovn/northd/ovn-northd.8.xml
@@ -1131,6 +1131,11 @@  next;
           Instead, if the route is from a configured static route, <var>G</var>
           is the next hop IP address.  Else it is <code>ip6.dst</code>.
         </p>
+
+        <p>
+          If the address <var>A</var> is in the link-local scope, the
+          route will be limited to sending on the ingress port.
+        </p>
       </li>
 
 <!-- ICMP errors are not yet supported.
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 4e0e072..f0f72f0 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -2778,8 +2778,13 @@  add_route(struct hmap *lflows, const struct ovn_port *op,
 {
     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 (!strcmp("fe80::", network_s) && plen == 64) {
+        /* Scope IPv6 link-local addresses to the local router port. */
+        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");
@@ -2802,10 +2807,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(&match);
     ds_destroy(&actions);
-    free(match);
 }
 
 static void
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 85aa2d3..4ce295a 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -885,6 +885,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">