bbaaef
From d7b024a24ee249c3ce6bf593499fdb6a79d78706 Mon Sep 17 00:00:00 2001
bbaaef
Message-Id: <d7b024a24ee249c3ce6bf593499fdb6a79d78706.1575382494.git.lorenzo.bianconi@redhat.com>
bbaaef
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
bbaaef
Date: Thu, 28 Nov 2019 14:48:35 +0200
bbaaef
Subject: [PATCH 1/2] Add support to Default Router Preference (PRF) - RFC 4191
bbaaef
bbaaef
Introduce support for Default Router Preference (PRF) in IPv6 Router
bbaaef
Advertisement according to RFC 4191
bbaaef
bbaaef
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
bbaaef
Signed-off-by: Numan Siddique <numans@ovn.org>
bbaaef
---
bbaaef
 ovn/controller/pinctrl.c | 20 +++++++++++++++++---
bbaaef
 ovn/lib/ovn-l7.h         |  4 ++++
bbaaef
 ovn/northd/ovn-northd.c  |  8 ++++++++
bbaaef
 ovn/ovn-nb.xml           | 12 ++++++++++++
bbaaef
 tests/ovn.at             | 13 +++++++++----
bbaaef
 5 files changed, 50 insertions(+), 7 deletions(-)
bbaaef
bbaaef
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
bbaaef
index fa9c827c1..ea0551c21 100644
bbaaef
--- a/ovn/controller/pinctrl.c
bbaaef
+++ b/ovn/controller/pinctrl.c
bbaaef
@@ -2267,10 +2267,10 @@ ipv6_ra_update_config(const struct sbrec_port_binding *pb)
bbaaef
         goto fail;
bbaaef
     }
bbaaef
     if (!strcmp(address_mode, "dhcpv6_stateless")) {
bbaaef
-        config->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
bbaaef
+        config->mo_flags |= IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
bbaaef
         config->la_flags |= IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS;
bbaaef
     } else if (!strcmp(address_mode, "dhcpv6_stateful")) {
bbaaef
-        config->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
bbaaef
+        config->mo_flags |= IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
bbaaef
     } else if (!strcmp(address_mode, "slaac")) {
bbaaef
         config->la_flags |= IPV6_ND_RA_OPT_PREFIX_AUTONOMOUS;
bbaaef
     } else {
bbaaef
@@ -2278,6 +2278,13 @@ ipv6_ra_update_config(const struct sbrec_port_binding *pb)
bbaaef
         goto fail;
bbaaef
     }
bbaaef
 
bbaaef
+    const char *prf = smap_get(&pb->options, "ipv6_ra_prf");
bbaaef
+    if (!strcmp(prf, "HIGH")) {
bbaaef
+        config->mo_flags |= IPV6_ND_RA_OPT_PRF_HIGH;
bbaaef
+    } else if (!strcmp(prf, "LOW")) {
bbaaef
+        config->mo_flags |= IPV6_ND_RA_OPT_PRF_LOW;
bbaaef
+    }
bbaaef
+
bbaaef
     const char *prefixes = smap_get(&pb->options, "ipv6_ra_prefixes");
bbaaef
     if (prefixes && !extract_ip_addresses(prefixes, &config->prefixes)) {
bbaaef
         VLOG_WARN("Invalid IPv6 prefixes: %s", prefixes);
bbaaef
@@ -2427,10 +2434,17 @@ ipv6_ra_send(struct rconn *swconn, struct ipv6_ra_state *ra)
bbaaef
 
bbaaef
     uint64_t packet_stub[128 / 8];
bbaaef
     struct dp_packet packet;
bbaaef
+    uint16_t router_lt = IPV6_ND_RA_LIFETIME;
bbaaef
+
bbaaef
+    if (!router_lt) {
bbaaef
+        /* Reset PRF to MEDIUM if router lifetime is not set */
bbaaef
+        ra->config->mo_flags &= ~IPV6_ND_RA_OPT_PRF_LOW;
bbaaef
+    }
bbaaef
+
bbaaef
     dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
bbaaef
     compose_nd_ra(&packet, ra->config->eth_src, ra->config->eth_dst,
bbaaef
             &ra->config->ipv6_src, &ra->config->ipv6_dst,
bbaaef
-            255, ra->config->mo_flags, htons(IPV6_ND_RA_LIFETIME), 0, 0,
bbaaef
+            255, ra->config->mo_flags, htons(router_lt), 0, 0,
bbaaef
             ra->config->mtu);
bbaaef
 
bbaaef
     for (int i = 0; i < ra->config->prefixes.n_ipv6_addrs; i++) {
bbaaef
diff --git a/ovn/lib/ovn-l7.h b/ovn/lib/ovn-l7.h
bbaaef
index 5fc370bf5..fd898b0dc 100644
bbaaef
--- a/ovn/lib/ovn-l7.h
bbaaef
+++ b/ovn/lib/ovn-l7.h
bbaaef
@@ -287,6 +287,10 @@ nd_ra_opts_destroy(struct hmap *nd_ra_opts)
bbaaef
 #define IPV6_ND_RA_OPT_PREFIX_VALID_LIFETIME        0xffffffff
bbaaef
 #define IPV6_ND_RA_OPT_PREFIX_PREFERRED_LIFETIME    0xffffffff
bbaaef
 
bbaaef
+#define IPV6_ND_RA_OPT_PRF_NORMAL                   0x00
bbaaef
+#define IPV6_ND_RA_OPT_PRF_HIGH                     0x08
bbaaef
+#define IPV6_ND_RA_OPT_PRF_LOW                      0x18
bbaaef
+
bbaaef
 static inline void
bbaaef
 nd_ra_opts_init(struct hmap *nd_ra_opts)
bbaaef
 {
bbaaef
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
bbaaef
index 0e6f8f621..1bcf34369 100644
bbaaef
--- a/ovn/northd/ovn-northd.c
bbaaef
+++ b/ovn/northd/ovn-northd.c
bbaaef
@@ -6755,6 +6755,14 @@ copy_ra_to_sb(struct ovn_port *op, const char *address_mode)
bbaaef
 
bbaaef
     smap_add(&options, "ipv6_ra_src_eth", op->lrp_networks.ea_s);
bbaaef
 
bbaaef
+    const char *prf = smap_get(&op->nbrp->ipv6_ra_configs,
bbaaef
+                               "router_preference");
bbaaef
+    if (!prf || (strcmp(prf, "HIGH") && strcmp(prf, "LOW"))) {
bbaaef
+        smap_add(&options, "ipv6_ra_prf", "MEDIUM");
bbaaef
+    } else {
bbaaef
+        smap_add(&options, "ipv6_ra_prf", prf);
bbaaef
+    }
bbaaef
+
bbaaef
     sbrec_port_binding_set_options(op->sb, &options);
bbaaef
     smap_destroy(&options);
bbaaef
 }
bbaaef
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
bbaaef
index 6f6e06777..16851dba1 100644
bbaaef
--- a/ovn/ovn-nb.xml
bbaaef
+++ b/ovn/ovn-nb.xml
bbaaef
@@ -1859,6 +1859,18 @@
bbaaef
         
bbaaef
       </column>
bbaaef
 
bbaaef
+      <column name="ipv6_ra_configs" key="router_preference">
bbaaef
+        Default Router Preference (PRF) indicates whether to prefer this
bbaaef
+        router over other default routers (RFC 4191).
bbaaef
+        Possible values are:
bbaaef
+
bbaaef
+        
    bbaaef
    +          
  • HIGH: mapped to 0x01 in RA PRF field
  • bbaaef
    +          
  • MEDIUM: mapped to 0x00 in RA PRF field
  • bbaaef
    +          
  • LOW: mapped to 0x11 in RA PRF field
  • bbaaef
    +        
    bbaaef
    +      </column>
    bbaaef
    +
    bbaaef
           <column name="ipv6_ra_configs" key="mtu">
    bbaaef
             The recommended MTU for the link. Default is 0, which means no MTU
    bbaaef
             Option will be included in RA packet replied by ovn-controller.
    bbaaef
    diff --git a/tests/ovn.at b/tests/ovn.at
    bbaaef
    index 33989e697..78524256f 100644
    bbaaef
    --- a/tests/ovn.at
    bbaaef
    +++ b/tests/ovn.at
    bbaaef
    @@ -11488,23 +11488,28 @@ ra_test 000005dc 00 0 0 c0 40 aef00000000000000000000000000000
    bbaaef
     ovn-nbctl --wait=hv set Logical_Router_port ro-sw networks='aef0\:\:1/64 fd0f\:\:1/48'
    bbaaef
     ra_test 000005dc 00 0 0 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
     
    bbaaef
    +# Test PRF for default gw
    bbaaef
    +ovn-nbctl --wait=hv set Logical_Router_port ro-sw ipv6_ra_configs:router_preference="LOW"
    bbaaef
    +ra_test 000005dc 18 0 0 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
    +
    bbaaef
     # Now test for RDNSS
    bbaaef
     ovn-nbctl --wait=hv set Logical_Router_port ro-sw ipv6_ra_configs:rdnss='aef0::11'
    bbaaef
     dns_addr=aef00000000000000000000000000011
    bbaaef
    -ra_test 000005dc 00 $dns_addr 0 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
    +ra_test 000005dc 18 $dns_addr 0 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
     
    bbaaef
     # Now test for DNSSL
    bbaaef
     ovn-nbctl --wait=hv set Logical_Router_port ro-sw ipv6_ra_configs:dnssl="aa.bb.cc"
    bbaaef
    +ovn-nbctl --wait=hv set Logical_Router_port ro-sw ipv6_ra_configs:router_preference="HIGH"
    bbaaef
     dnssl=02616102626202636300000000000000
    bbaaef
    -ra_test 000005dc 00 $dns_addr $dnssl c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
    +ra_test 000005dc 08 $dns_addr $dnssl c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
     
    bbaaef
     ## Test a different address mode now
    bbaaef
     ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateful
    bbaaef
    -ra_test 000005dc 80 $dns_addr $dnssl 80 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
    +ra_test 000005dc 88 $dns_addr $dnssl 80 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
     
    bbaaef
     # And the other address mode
    bbaaef
     ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateless
    bbaaef
    -ra_test 000005dc 40 $dns_addr $dnssl c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
    +ra_test 000005dc 48 $dns_addr $dnssl c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
    bbaaef
     
    bbaaef
     OVN_CLEANUP([hv1],[hv2])
    bbaaef
     AT_CLEANUP
    bbaaef
    -- 
    bbaaef
    2.21.0
    bbaaef