[ovs-dev] [PATCH] ovn: Fix the invalid eth.dst and ip6.dst set by nd_ns action for certain cases.

nusiddiq at redhat.com nusiddiq at redhat.com
Mon Dec 17 16:19:44 UTC 2018


From: Numan Siddique <nusiddiq at redhat.com>

When an IPv6 packet enters a router pipeline and it needs to be routed via
the nexthop IP address set in the static route, OVN generates an IPv6
Neigh Solicitation request if the nexthop IP is not resolved yet. But
right now, the generated IPv6 Neigh Solicitation packet doesn't set
the eth.dst to the mutlicast address derived from the nexthop and
ip6.dst to the solicited-node multicast address corresponding to the
nexthop address. Instead it generates these values from the actual
ip6.dst of the original packet.

This patch fixes this issue.

Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
---
 ovn/northd/ovn-northd.8.xml | 24 +++++++++++++
 ovn/northd/ovn-northd.c     | 36 ++++++++++++++++++++
 tests/ovn.at                | 68 ++++++++++++++++++++++++++++++++-----
 3 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
index f52699bd3..392a5efc9 100644
--- a/ovn/northd/ovn-northd.8.xml
+++ b/ovn/northd/ovn-northd.8.xml
@@ -2084,6 +2084,30 @@ arp {
 };
         </pre>
 
+        <p>
+          Unknown MAC address.  For each IPv6 static route associated with the
+          router with the nexthop IP: <var>G</var>, a priority-200 flow
+          for IPv6 packets with match
+          <code>eth.dst == 00:00:00:00:00:00 &amp;&amp;
+          xxreg0 == <var>G</var></code>
+          with the following actions is added:
+        </p>
+
+        <pre>
+nd_ns {
+    eth.dst = <var>E</var>;
+    ip6.dst = <var>I</var>
+    nd.target = <var>G</var>;
+    output;
+};
+        </pre>
+
+        <p>
+          Where <var>E</var> is the multicast mac derived from the Gateway IP,
+          <var>I</var> is the solicited-node multicast address corresponding
+          to the target address <var>G</var>.
+        </p>
+
         <p>
           Unknown MAC address.  A priority-100 flow for IPv6 packets with match
           <code>eth.dst == 00:00:00:00:00:00</code> has the following actions:
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index e1fbf60f3..6850d4f72 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -6624,6 +6624,42 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
             continue;
         }
 
+        for (int i = 0; i < od->nbr->n_static_routes; i++) {
+            const struct nbrec_logical_router_static_route *route;
+
+            route = od->nbr->static_routes[i];
+            struct in6_addr gw_ip6;
+            unsigned int plen;
+            char *error = ipv6_parse_cidr(route->nexthop, &gw_ip6, &plen);
+            if (error || plen != 128) {
+                free(error);
+                continue;
+            }
+
+            ds_clear(&match);
+            ds_put_format(&match, "eth.dst == 00:00:00:00:00:00 && "
+                          "ip6 && xxreg0 == %s", route->nexthop);
+            struct in6_addr sn_addr;
+            struct eth_addr eth_dst;
+            in6_addr_solicited_node(&sn_addr, &gw_ip6);
+            ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);
+
+            char sn_addr_s[INET6_ADDRSTRLEN + 1];
+            ipv6_string_mapped(sn_addr_s, &sn_addr);
+
+            ds_clear(&actions);
+            ds_put_format(&actions,
+                          "nd_ns { "
+                          "eth.dst = "ETH_ADDR_FMT"; "
+                          "ip6.dst = %s; "
+                          "nd.target = %s; "
+                          "output; "
+                          "};", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
+                          route->nexthop);
+            ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
+                          ds_cstr(&match), ds_cstr(&actions));
+        }
+
         ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
                       "eth.dst == 00:00:00:00:00:00",
                       "arp { "
diff --git a/tests/ovn.at b/tests/ovn.at
index afefb8ad6..a370738dc 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -9984,6 +9984,10 @@ ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
 2001:db8:1:0:200:02ff:fe01:0204/64 \
 -- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
 
+#install static route
+ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
+ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
+-- add Logical_Router lr0_ip6 static_routes @lrt
 
 ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
 rp-ip6_public  type=router options:router-port=ip6_public \
@@ -10026,36 +10030,82 @@ trim_zeros() {
     sed 's/\(00\)\{1,\}$//'
 }
 
+reset_pcap_file() {
+    local iface=$1
+    local pcap_file=$2
+    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
+options:rxq_pcap=dummy-rx.pcap
+    rm -f ${pcap_file}*.pcap
+    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
+options:rxq_pcap=${pcap_file}-rx.pcap
+}
+
 # Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for unknown MAC
 # addresses. ovn-controller should generate an IPv6 NS request for IPv6
 # packets whose MAC is unknown (in the ARP_REQUEST router pipeline stage.
 # test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
 # This function sends ipv6 packet
 test_ipv6() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4
-    dst_ip=20010db800010000020002fffe010205
+    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
+    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
 
     local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
     packet=${packet}8000000000000000
-    shift; shift; shift; shift
 
-    dst_mac=3333ff010205
     src_mac=000002010204
-    mcast_node_ip=ff0200000000000000000001ff010205
-    expected_packet=${dst_mac}${src_mac}86dd6000000000203aff${src_ip}
-    expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000${dst_ip}
-    expected_packet=${expected_packet}0101${src_mac}
+    expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
+    expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
+    expected_packet=${expected_packet}${nd_target}0101${src_mac}
 
     as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
+    rm -f ipv6_ns.expected
     echo $expected_packet >> ipv6_ns.expected
 }
 
 src_mac=506400000002
 dst_mac=00000000af01
 src_ip=aef0000000000000526400fffe000002
+dst_ip=20010db800010000020002fffe010205
+dst_mcast_mac=3333ff010205
+mcast_node_ip=ff0200000000000000000001ff010205
+nd_target=20010db800010000020002fffe010205
 # Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
 # should be received by the ports attached to br-phys.
-test_ipv6 1 $src_mac $dst_mac $src_ip 2
+test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
+$mcast_node_ip $nd_target
+
+OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
+OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
+
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
+trim_zeros > 1.packets
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
+trim_zeros > 2.packets
+
+cat ipv6_ns.expected | cut -c -112 > expout
+AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
+AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
+
+# Skipping the ICMPv6 checksum
+cat ipv6_ns.expected | cut -c 117- > expout
+AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
+AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
+
+# Now send a packet with destination ip other than
+# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
+reset_pcap_file br-phys_n1 hv1/br-phys_n1
+reset_pcap_file br-phys hv1/br-phys
+
+src_mac=506400000002
+dst_mac=00000000af01
+src_ip=aef0000000000000526400fffe000002
+dst_ip=20020ab8000100000200020000020306
+# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
+dst_mcast_mac=3333ff011305
+mcast_node_ip=ff0200000000000000000001ff011305
+nd_target=20010db800010000020002fffe011305
+test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
+$mcast_node_ip $nd_target
 
 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
 OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
-- 
2.19.2



More information about the dev mailing list