[ovs-dev] [PATCH 2/4] Native tunnel: Add tnl/neigh/ageing command.
Paolo Valerio
pvalerio at redhat.com
Mon Nov 8 19:30:48 UTC 2021
Gaëtan Rivet <grive at u256.net> writes:
> On Tue, Nov 2, 2021, at 18:12, Paolo Valerio wrote:
>> 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)
>
> Same remark, using _MS suffix would be nice.
>
>>
>> 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) {
>
> ageing is provided in seconds, while NEIGH_ENTRY_MAX_AGEING_TIME is
> in milliseconds right?
>
that's a leftover of a move around/revert back. It should really be in
seconds as it was.
Thanks for spotting this. While at it I will add a range check in the
test.
>> + unixctl_command_reply_error(conn, "bad ageing value");
>> + return;
>> + }
>> +
>> + ageing *= 1000;
>> + atomic_store_relaxed(&neigh_ageing, ageing);
>
> Release here with acquire in tnl_neigh_get_ageing() might be needed.
>
ACK
>> + 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);
>> + }
>
> Potential re-ordering issue between read and write seems more acute here.
> The explicit acquire / release ordering should probably be used.
>
Same remark as in patch 1.
A store after a conditional based on the outcome of the load.
If control dependency is not enough, guess we could use:
atomic_read_explicit(&neigh->expires, &curr_exp, memory_order_acquire)
atomic_store_explicit(&neigh->expires, new_exp, memory_order_release)
>> + }
>> +
>> + 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)'])
>>
>>
>> _______________________________________________
>> dev mailing list
>> dev at openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
> --
> Gaetan Rivet
More information about the dev
mailing list