[ovs-dev] [PATCH ovn v2 1/3] ovn-northd: Support optionally avoid static neighbor flows in routers.

Han Zhou hzhou at ovn.org
Wed Aug 5 07:05:12 UTC 2020


Support option:dynamic_neigh_routers for logical routers, so that in
particular use cases static neighbor flows are not prepopulated IP
addresses belonging to neighbor router ports, to avoid flow exploding
problem reported for ovn-kubernetes large scale setup.

Reported-by: Girish Moodalbail <gmoodalbail at gmail.com>
Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2020-May/049995.html
Signed-off-by: Han Zhou <hzhou at ovn.org>
---
 northd/ovn-northd.8.xml |   5 ++-
 northd/ovn-northd.c     |   6 +++
 ovn-nb.xml              |  13 ++++++
 tests/ovn.at            | 112 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index ed1cd58..508123e 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -2727,7 +2727,10 @@ outport = <var>P</var>;
           <code>Logical_Switch_Port</code> table.  For router ports
           connected to other logical routers, MAC bindings can be known
           statically from the <code>mac</code> and <code>networks</code>
-          column in the <code>Logical_Router_Port</code> table.
+          column in the <code>Logical_Router_Port</code> table.  (Note: the
+          flow is NOT installed for the IP addresses that belong to a neighbor
+          logical router port if the current router has the
+          <code>options:dynamic_neigh_routers</code> set to <code>true</code>)
         </p>
 
         <p>
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 03c62ba..5dd49f9 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -10401,6 +10401,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                 continue;
             }
 
+            if (peer->od->nbr &&
+                smap_get_bool(&peer->od->nbr->options,
+                              "dynamic_neigh_routers", false)) {
+                continue;
+            }
+
             for (size_t i = 0; i < op->od->n_router_ports; i++) {
                 const char *router_port_name = smap_get(
                                     &op->od->router_ports[i]->nbsp->options,
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 5e434d2..4c59338 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1846,6 +1846,19 @@
           connected to the logical router. Default: False.
         </p>
       </column>
+      <column name="options" key="dynamic_neigh_routers" type='{"type": "boolean"}'>
+        <p>
+          If set to <code>true</code>, the router will resolve neighbor
+          routers' MAC addresses only by dynamic ARP/ND, instead of
+          prepopulating static mappings for all neighbor routers in the ARP/ND
+          Resolution stage.  This reduces number of flows, but requires ARP/ND
+          messages to resolve the IP-MAC bindings when needed.  It is
+          <code>false</code> by default.  It is recommended to set to
+          <code>true</code> when a large number of logical routers are
+          connected to the same logical switch but most of them never need to
+          send traffic between each other.
+        </p>
+      </column>
     </group>
 
     <group title="Common Columns">
diff --git a/tests/ovn.at b/tests/ovn.at
index b0179a8..654c343 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -21122,3 +21122,115 @@ AT_CHECK([
 
 OVN_CLEANUP([hv1], [hv2])
 AT_CLEANUP
+
+# Test option:dynamic_neigh_routers. No static neighbor flows when enabled, and
+# traffic should still work, with the help of dynamic mac_bindings.
+AT_SETUP([ovn -- Dynamic neighbor between LRs])
+ovn_start
+
+# Logical network:
+# 2 LRs - R1 and R2 that are connected to each other via LS "join"
+# in 10.0.0.0/24 network.
+# R1 is connected to S1 (10.0.1.0/24), R2 is connected to S2 (10.0.2.0/24)
+
+ovn-nbctl lr-add r1 -- set logical_router r1 option:dynamic_neigh_routers=true
+ovn-nbctl lr-add r2 -- set logical_router r2 option:dynamic_neigh_routers=true
+
+ovn-nbctl ls-add s1
+ovn-nbctl ls-add s2
+ovn-nbctl ls-add join
+
+# Connnect r1 to s1.
+ovn-nbctl lrp-add r1 lrp-r1-s1 00:00:00:00:01:01 10.0.1.1/24
+ovn-nbctl lsp-add s1 lsp-s1-r1 -- set Logical_Switch_Port lsp-s1-r1 type=router \
+    options:router-port=lrp-r1-s1 addresses=router
+
+# Connnect r2 to s2.
+ovn-nbctl lrp-add r2 lrp-r2-s2 00:00:00:00:02:01 10.0.2.1/24
+ovn-nbctl lsp-add s2 lsp-s2-r2 -- set Logical_Switch_Port lsp-s2-r2 type=router \
+    options:router-port=lrp-r2-s2 addresses=router
+
+# Connect r1 to join
+ovn-nbctl lrp-add r1 lrp-r1-join 00:00:00:00:03:01 10.0.0.1/24
+ovn-nbctl lsp-add join lsp-join-r1 -- set Logical_Switch_Port lsp-join-r1 \
+    type=router options:router-port=lrp-r1-join addresses=router
+
+# Connect r2 to join
+ovn-nbctl lrp-add r2 lrp-r2-join 00:00:00:00:03:02 10.0.0.2/24
+ovn-nbctl lsp-add join lsp-join-r2 -- set Logical_Switch_Port lsp-join-r2 \
+    type=router options:router-port=lrp-r2-join addresses=router
+
+#install static routes
+ovn-nbctl lr-route-add r1 10.0.2.0/24 10.0.0.2
+ovn-nbctl lr-route-add r2 10.0.1.0/24 10.0.0.1
+
+# Create logical port p1 in s1
+ovn-nbctl lsp-add s1 p1 \
+-- lsp-set-addresses p1 "f0:00:00:00:01:02 10.0.1.2"
+
+# Create logical port p2 in s2
+ovn-nbctl lsp-add s2 p2 \
+-- lsp-set-addresses p2 "f0:00:00:00:02:02 10.0.2.2"
+
+# Create two hypervisor and create OVS ports corresponding to logical ports.
+net_add n1
+
+sim_add hv1
+as hv1
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.1
+ovs-vsctl -- add-port br-int hv1-vif1 -- \
+    set interface hv1-vif1 external-ids:iface-id=p1 \
+    options:tx_pcap=hv1/vif1-tx.pcap \
+    options:rxq_pcap=hv1/vif1-rx.pcap \
+    ofport-request=1
+
+sim_add hv2
+as hv2
+ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.2
+ovs-vsctl -- add-port br-int hv2-vif1 -- \
+    set interface hv2-vif1 external-ids:iface-id=p2 \
+    options:tx_pcap=hv2/vif1-tx.pcap \
+    options:rxq_pcap=hv2/vif1-rx.pcap \
+    ofport-request=1
+
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+OVN_POPULATE_ARP
+
+ovn-nbctl --wait=hv sync
+
+AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.1], [1], [])
+AT_CHECK([ovn-sbctl lflow-list | grep lr_in_arp_resolve | grep 10.0.0.2], [1], [])
+
+ip_to_hex() {
+    printf "%02x%02x%02x%02x" "$@"
+}
+
+# Send ip packets from p1 to p2
+src_mac="f00000000102"
+dst_mac="000000000101"
+src_ip=`ip_to_hex 10 0 1 2`
+dst_ip=`ip_to_hex 10 0 2 2`
+packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
+as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
+as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
+
+# Packet to Expect at p2
+src_mac="000000000201"
+dst_mac="f00000000202"
+src_ip=`ip_to_hex 10 0 1 2`
+dst_ip=`ip_to_hex 10 0 2 2`
+echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
+
+OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
+
+# MAC binding entry should have generated
+AT_CHECK([ovn-sbctl find mac ip=10.0.0.2 mac='"00:00:00:00:03:02"' logical_port=lrp-r1-join | grep 10\.0\.0\.2], [0], [ignore], [])
+
+OVN_CLEANUP([hv1],[hv2])
+
+AT_CLEANUP
-- 
2.1.0



More information about the dev mailing list