[ovs-dev,v2] tnl-neigh-cache: Purge learnt neighbors when port/bridge is deleted
diff mbox series

Message ID 20190620151123.23127-1-vdasari@gmail.com
State New
Headers show
Series
  • [ovs-dev,v2] tnl-neigh-cache: Purge learnt neighbors when port/bridge is deleted
Related show

Commit Message

Vasu Dasari June 20, 2019, 3:11 p.m. UTC
Say an ARP entry is learnt on a OVS port and when such a port is deleted,
learnt entry should be removed from the port. It would have be aged out after
ARP ageout time. This code will clean up immediately.

Added test case(tunnel - neighbor entry add and deletion) in tunnel.at, to
verify neighbors are added and removed on deletion of a ports and bridges.

Discussion for this addition is at:
https://mail.openvswitch.org/pipermail/ovs-discuss/2019-June/048754.html

Signed-off-by: Vasu Dasari <vdasari@gmail.com>
---
v1 -> v2:
  Incorporate robot comments. Verified the commit with utilities/checkpatch.py -1
---
 lib/tnl-neigh-cache.c        | 20 +++++++++++++++++
 lib/tnl-neigh-cache.h        |  1 +
 ofproto/ofproto-dpif-xlate.c |  3 +++
 tests/tunnel.at              | 43 ++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+)

Comments

Ben Pfaff July 5, 2019, 9:23 p.m. UTC | #1
On Thu, Jun 20, 2019 at 11:11:23AM -0400, Vasu Dasari wrote:
> Say an ARP entry is learnt on a OVS port and when such a port is deleted,
> learnt entry should be removed from the port. It would have be aged out after
> ARP ageout time. This code will clean up immediately.
> 
> Added test case(tunnel - neighbor entry add and deletion) in tunnel.at, to
> verify neighbors are added and removed on deletion of a ports and bridges.
> 
> Discussion for this addition is at:
> https://mail.openvswitch.org/pipermail/ovs-discuss/2019-June/048754.html
> 
> Signed-off-by: Vasu Dasari <vdasari@gmail.com>

The following use of nullable_string_is_equal in tnl_neigh_flush() seems
odd to me.  I don't see a caller to tnl_neigh_flush() that could pass
NULL, so the 'br_name' argument in nonnull.  neigh->br_name is an array,
not a pointer, so it is also always nonnull.  Why not use strcmp()?

Otherwise, this looks good, thank you.  I'll look forward to v3.

Patch
diff mbox series

diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
index b28f9f1bb..daa54432a 100644
--- a/lib/tnl-neigh-cache.c
+++ b/lib/tnl-neigh-cache.c
@@ -220,6 +220,26 @@  tnl_neigh_cache_run(void)
     }
 }
 
+void
+tnl_neigh_flush(const char br_name[])
+{
+    struct tnl_neigh_entry *neigh;
+    bool changed = false;
+
+    ovs_mutex_lock(&mutex);
+    CMAP_FOR_EACH (neigh, cmap_node, &table) {
+        if (nullable_string_is_equal(neigh->br_name, br_name)) {
+            tnl_neigh_delete(neigh);
+            changed = true;
+        }
+    }
+    ovs_mutex_unlock(&mutex);
+
+    if (changed) {
+        seq_change(tnl_conf_seq);
+    }
+}
+
 static void
 tnl_neigh_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
                     const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
diff --git a/lib/tnl-neigh-cache.h b/lib/tnl-neigh-cache.h
index fee8e6a6f..ded9c2f86 100644
--- a/lib/tnl-neigh-cache.h
+++ b/lib/tnl-neigh-cache.h
@@ -37,5 +37,6 @@  int tnl_neigh_lookup(const char dev_name[], const struct in6_addr *dst,
                      struct eth_addr *mac);
 void tnl_neigh_cache_init(void);
 void tnl_neigh_cache_run(void);
+void tnl_neigh_flush(const char dev_name[]);
 
 #endif
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 73966a4e8..28a7fdd84 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1481,6 +1481,9 @@  xlate_ofport_remove(struct ofport_dpif *ofport)
     ovs_assert(new_xcfg);
 
     xport = xport_lookup(new_xcfg, ofport);
+    if (xport) {
+        tnl_neigh_flush(netdev_get_name(xport->netdev));
+    }
     xlate_xport_remove(new_xcfg, xport);
 }
 
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 035c54f67..6d7550724 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -920,3 +920,46 @@  dnl which is not correct
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([tunnel - neighbor entry add and deletion])
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
+                    options:remote_ip=1.1.1.1 options:local_ip=2.2.2.2 \
+                    options:key=5 ofport_request=1 \
+                    -- add-port br0 p2 -- set Interface p2 type=gre \
+                    options:local_ip=3.3.3.3 options:remote_ip=4.4.4.4 \
+                    ofport_request=2])
+AT_CHECK([ovs-vsctl add-br br1 -- set bridge br1 datapath_type=dummy], [0])
+
+dnl Populate tunnel neighbor cache table
+AT_CHECK([
+    ovs-appctl tnl/arp/set p1 10.0.0.1 00:00:10:00:00:01
+    ovs-appctl tnl/arp/set p2 10.0.1.1 00:00:10:00:01:01
+    ovs-appctl tnl/arp/set br0 10.0.2.1 00:00:10:00:02:01
+    ovs-appctl tnl/arp/set br1 20.0.0.1 00:00:20:00:00:01
+], [0], [stdout])
+
+AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
+10.0.0.1                                      00:00:10:00:00:01   p1
+10.0.1.1                                      00:00:10:00:01:01   p2
+10.0.2.1                                      00:00:10:00:02:01   br0
+20.0.0.1                                      00:00:20:00:00:01   br1
+])
+
+dnl neighbor table after deleting port p1
+AT_CHECK([ovs-vsctl del-port br0 p1],[0], [stdout])
+AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | grep -w p1 | sort], [0], [dnl
+])
+
+dnl neighbor table after deleting bridge br0
+AT_CHECK([ovs-vsctl del-br br0],[0], [stdout])
+AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
+20.0.0.1                                      00:00:20:00:00:01   br1
+])
+
+dnl neighbor table after deleting bridge br1
+AT_CHECK([ovs-vsctl del-br br1],[0], [stdout])
+AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP