[ovs-dev] [PATCH 2/4] Native tunnel: Add tnl/neigh/ageing command.

Paolo Valerio pvalerio at redhat.com
Tue Nov 2 17:12:22 UTC 2021


with the command is now possible to change the ageing time of the
cache entries.

For the existing entries the ageing time is updated only if the
current expiration is greater than the new one. In any case, the next
refresh will set it to the new value.

This is intended mostly for debugging purpose.

Signed-off-by: Paolo Valerio <pvalerio at redhat.com>
---
 NEWS                            |    3 ++
 lib/tnl-neigh-cache.c           |   77 ++++++++++++++++++++++++++++++++++-----
 ofproto/ofproto-tnl-unixctl.man |    9 +++++
 tests/tunnel-push-pop-ipv6.at   |   30 +++++++++++++++
 tests/tunnel-push-pop.at        |   30 +++++++++++++++
 5 files changed, 140 insertions(+), 9 deletions(-)

diff --git a/NEWS b/NEWS
index 90f4b1590..148dd5d61 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ Post-v2.16.0
        limiting behavior.
      * Add hardware offload support for matching IPv4/IPv6 frag types
        (experimental).
+   - Native tunnel:
+     * Added new ovs-appctl tnl/neigh/ageing to read/write the neigh ageing
+       time.
 
 
 v2.16.0 - 16 Aug 2021
diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
index 2769e5c3d..8eacaccd8 100644
--- a/lib/tnl-neigh-cache.c
+++ b/lib/tnl-neigh-cache.c
@@ -47,6 +47,7 @@
 
 /* In milliseconds */
 #define NEIGH_ENTRY_DEFAULT_IDLE_TIME  (15 * 60 * 1000)
+#define NEIGH_ENTRY_MAX_AGEING_TIME    (3600 * 1000)
 
 struct tnl_neigh_entry {
     struct cmap_node cmap_node;
@@ -58,6 +59,7 @@ struct tnl_neigh_entry {
 
 static struct cmap table = CMAP_INITIALIZER;
 static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
+static atomic_uint32_t neigh_ageing;
 
 static uint32_t
 tnl_neigh_hash(const struct in6_addr *ip)
@@ -75,6 +77,15 @@ tnl_neigh_expired(struct tnl_neigh_entry *neigh)
     return expired <= time_msec();
 }
 
+static uint32_t
+tnl_neigh_get_ageing(void)
+{
+    unsigned int ageing;
+
+    atomic_read_relaxed(&neigh_ageing, &ageing);
+    return ageing;
+}
+
 static struct tnl_neigh_entry *
 tnl_neigh_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
 {
@@ -89,7 +100,7 @@ tnl_neigh_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
             }
 
             atomic_store_relaxed(&neigh->expires, time_msec() +
-                                 NEIGH_ENTRY_DEFAULT_IDLE_TIME);
+                                 tnl_neigh_get_ageing());
             return neigh;
         }
     }
@@ -134,7 +145,7 @@ tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
     if (neigh) {
         if (eth_addr_equals(neigh->mac, mac)) {
             atomic_store_relaxed(&neigh->expires, time_msec() +
-                                 NEIGH_ENTRY_DEFAULT_IDLE_TIME);
+                                 tnl_neigh_get_ageing());
             ovs_mutex_unlock(&mutex);
             return;
         }
@@ -147,7 +158,7 @@ tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
     neigh->ip = *dst;
     neigh->mac = mac;
     atomic_store_relaxed(&neigh->expires, time_msec() +
-                         NEIGH_ENTRY_DEFAULT_IDLE_TIME);
+                         tnl_neigh_get_ageing());
     ovs_strlcpy(neigh->br_name, name, sizeof neigh->br_name);
     cmap_insert(&table, &neigh->cmap_node, tnl_neigh_hash(&neigh->ip));
     ovs_mutex_unlock(&mutex);
@@ -273,6 +284,43 @@ tnl_neigh_cache_flush(struct unixctl_conn *conn, int argc OVS_UNUSED,
     unixctl_command_reply(conn, "OK");
 }
 
+static void
+tnl_neigh_cache_ageing(struct unixctl_conn *conn, int argc,
+                        const char *argv[], void *aux OVS_UNUSED)
+{
+    long long int new_exp, curr_exp;
+    struct tnl_neigh_entry *neigh;
+    uint32_t ageing;
+
+    if (argc == 1) {
+        struct ds ds = DS_EMPTY_INITIALIZER;
+        ds_put_format(&ds, "%"PRIu32, tnl_neigh_get_ageing() / 1000);
+        unixctl_command_reply(conn, ds_cstr(&ds));
+        ds_destroy(&ds);
+
+        return;
+    }
+
+    if (!ovs_scan(argv[1], "%"SCNu32, &ageing) ||
+        !ageing || ageing > NEIGH_ENTRY_MAX_AGEING_TIME) {
+        unixctl_command_reply_error(conn, "bad ageing value");
+        return;
+    }
+
+    ageing *= 1000;
+    atomic_store_relaxed(&neigh_ageing, ageing);
+    new_exp = time_msec() + ageing;
+
+    CMAP_FOR_EACH (neigh, cmap_node, &table) {
+        atomic_read_relaxed(&neigh->expires, &curr_exp);
+        if (new_exp < curr_exp) {
+            atomic_store_relaxed(&neigh->expires, new_exp);
+        }
+    }
+
+    unixctl_command_reply(conn, "OK");
+}
+
 static int
 lookup_any(const char *host_name, struct in6_addr *address)
 {
@@ -347,10 +395,21 @@ tnl_neigh_cache_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
 void
 tnl_neigh_cache_init(void)
 {
-    unixctl_command_register("tnl/arp/show", "", 0, 0, tnl_neigh_cache_show, NULL);
-    unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3, tnl_neigh_cache_add, NULL);
-    unixctl_command_register("tnl/arp/flush", "", 0, 0, tnl_neigh_cache_flush, NULL);
-    unixctl_command_register("tnl/neigh/show", "", 0, 0, tnl_neigh_cache_show, NULL);
-    unixctl_command_register("tnl/neigh/set", "BRIDGE IP MAC", 3, 3, tnl_neigh_cache_add, NULL);
-    unixctl_command_register("tnl/neigh/flush", "", 0, 0, tnl_neigh_cache_flush, NULL);
+    atomic_init(&neigh_ageing, NEIGH_ENTRY_DEFAULT_IDLE_TIME);
+    unixctl_command_register("tnl/arp/show", "", 0, 0,
+                             tnl_neigh_cache_show, NULL);
+    unixctl_command_register("tnl/arp/set", "BRIDGE IP MAC", 3, 3,
+                             tnl_neigh_cache_add, NULL);
+    unixctl_command_register("tnl/arp/flush", "", 0, 0,
+                             tnl_neigh_cache_flush, NULL);
+    unixctl_command_register("tnl/arp/ageing", "[SECS]", 0, 1,
+                             tnl_neigh_cache_ageing, NULL);
+    unixctl_command_register("tnl/neigh/show", "", 0, 0,
+                             tnl_neigh_cache_show, NULL);
+    unixctl_command_register("tnl/neigh/set", "BRIDGE IP MAC", 3, 3,
+                             tnl_neigh_cache_add, NULL);
+    unixctl_command_register("tnl/neigh/flush", "", 0, 0,
+                             tnl_neigh_cache_flush, NULL);
+    unixctl_command_register("tnl/neigh/ageing", "[SECS]", 0, 1,
+                             tnl_neigh_cache_ageing, NULL);
 }
diff --git a/ofproto/ofproto-tnl-unixctl.man b/ofproto/ofproto-tnl-unixctl.man
index c70cca539..5c2ad4843 100644
--- a/ofproto/ofproto-tnl-unixctl.man
+++ b/ofproto/ofproto-tnl-unixctl.man
@@ -27,6 +27,15 @@ to \fImac\fR.
 .IP "\fBtnl/arp/flush\fR"
 Flush ARP table.
 .
+.IP "\fBtnl/neigh/ageing [\fIseconds\fB]\fR"
+.IP "\fBtnl/arp/ageing [\fIseconds\fB]\fR"
+Changes the ageing time. The accepted values of \fIseconds\fR are
+between 1 and 3600. The new entries will get the value as specified in
+\fIseconds\fR. For the existing entries, the ageing time is updated
+only if the current expiration is greater than \fIseconds\fR.
+.IP
+If used without arguments, it prints the current ageing value.
+.
 .IP "\fBtnl/egress_port_range [num1] [num2]\fR"
 Set range for UDP source port used for UDP based Tunnels. For
 example VxLAN. If case of zero arguments this command prints
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index 59723e63b..766a4bcf8 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -255,6 +255,36 @@ AT_CHECK([cat p0.pcap.txt | grep 93aa55aa55000086dd6000000000203aff2001cafe | un
 3333ff000093aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009387004d46000000002001cafe0000000000000000000000930101aa55aa550000
 ])
 
+dnl Set the ageing time to 5 seconds
+AT_CHECK([ovs-appctl tnl/neigh/ageing 5], [0], [OK
+])
+
+dnl Read the current ageing time
+AT_CHECK([ovs-appctl tnl/neigh/ageing], [0], [5
+])
+
+dnl Add an entry
+AT_CHECK([ovs-appctl tnl/neigh/set br0 2001:cafe::92 aa:bb:cc:00:00:01], [0], [OK
+])
+
+AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl
+2001:cafe::92                                 aa:bb:cc:00:00:01   br0
+])
+
+ovs-appctl time/warp 5000
+
+dnl Check the entry has been removed
+AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl
+])
+
+dnl Restore the ageing time to 900s (default)
+AT_CHECK([ovs-appctl tnl/neigh/ageing 900], [0], [OK
+])
+
+dnl Read the current ageing time
+AT_CHECK([ovs-appctl tnl/neigh/ageing], [0], [900
+])
+
 dnl Check ARP Snoop
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:c8,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:c8)'])
 
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index 12fc1ef91..385d14ab3 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -270,6 +270,36 @@ AT_CHECK([cat p0.pcap.txt | grep 101025d | uniq], [0], [dnl
 ffffffffffffaa55aa55000008060001080006040001aa55aa550000010102580000000000000101025d
 ])
 
+dnl Set the ageing time to 5 seconds
+AT_CHECK([ovs-appctl tnl/neigh/ageing 5], [0], [OK
+])
+
+dnl Read the current ageing time
+AT_CHECK([ovs-appctl tnl/neigh/ageing], [0], [5
+])
+
+dnl Add an entry
+AT_CHECK([ovs-appctl tnl/neigh/set br0 1.1.2.92 aa:bb:cc:00:00:01], [0], [OK
+])
+
+AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl
+1.1.2.92                                      aa:bb:cc:00:00:01   br0
+])
+
+ovs-appctl time/warp 5000
+
+dnl Check the entry has been removed
+AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl
+])
+
+dnl Restore the ageing time to 900s (default)
+AT_CHECK([ovs-appctl tnl/neigh/ageing 900], [0], [OK
+])
+
+dnl Read the current ageing time
+AT_CHECK([ovs-appctl tnl/neigh/ageing], [0], [900
+])
+
 dnl Check ARP Snoop
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:c8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:c8,tha=00:00:00:00:00:00)'])
 



More information about the dev mailing list