diff options
author | Klement Sekera <ksekera@cisco.com> | 2021-12-17 12:47:51 +0000 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-12-20 10:05:20 +0000 |
commit | 4ab6ad136b62add35598f3c354231701b7c14c65 (patch) | |
tree | 5cff25e84550e4b7855774e7213efd61bfe7a5cc /src/vnet | |
parent | e3241f04410fa45099f958f77636b80293904fc3 (diff) |
ip: SVR fix race condition
There could be a race condition where two fragments of one chain end up
at the same time on different workers, one overwriting others hash
entry. Add a check for that and restart processing on the unlucky worker
who ends up being second from hash table POV. This will then result in a
proper handover to worker now owning this reassembly.
Type: fix
Fixes: de34c35fc73226943538149fae9dbc5cfbdc6e75
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Change-Id: I9eb29c5cb1ffe3b5eb1d5a638e17ab7ba2628d28
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/ip/reass/ip4_sv_reass.c | 8 | ||||
-rw-r--r-- | src/vnet/ip/reass/ip6_sv_reass.c | 8 |
2 files changed, 14 insertions, 2 deletions
diff --git a/src/vnet/ip/reass/ip4_sv_reass.c b/src/vnet/ip/reass/ip4_sv_reass.c index f5fa575e64d..9971dafd9fd 100644 --- a/src/vnet/ip/reass/ip4_sv_reass.c +++ b/src/vnet/ip/reass/ip4_sv_reass.c @@ -321,6 +321,8 @@ ip4_sv_reass_find_or_create (vlib_main_t * vm, ip4_sv_reass_main_t * rm, ip4_sv_reass_t *reass = NULL; f64 now = vlib_time_now (vm); +again: + if (!clib_bihash_search_16_8 (&rm->hash, &kv->kv, &kv->kv)) { if (vm->thread_index != kv->v.thread_index) @@ -375,10 +377,14 @@ ip4_sv_reass_find_or_create (vlib_main_t * vm, ip4_sv_reass_main_t * rm, kv->v.thread_index = vm->thread_index; reass->last_heard = now; - if (clib_bihash_add_del_16_8 (&rm->hash, &kv->kv, 1)) + int rv = clib_bihash_add_del_16_8 (&rm->hash, &kv->kv, 2); + if (rv) { ip4_sv_reass_free (vm, rm, rt, reass); reass = NULL; + // if other worker created a context already work with the other copy + if (-2 == rv) + goto again; } return reass; diff --git a/src/vnet/ip/reass/ip6_sv_reass.c b/src/vnet/ip/reass/ip6_sv_reass.c index 58c7d8d8433..23ae6784127 100644 --- a/src/vnet/ip/reass/ip6_sv_reass.c +++ b/src/vnet/ip/reass/ip6_sv_reass.c @@ -311,6 +311,8 @@ ip6_sv_reass_find_or_create (vlib_main_t *vm, ip6_sv_reass_main_t *rm, ip6_sv_reass_t *reass = NULL; f64 now = vlib_time_now (vm); +again: + if (!clib_bihash_search_48_8 (&rm->hash, &kv->kv, &kv->kv)) { if (vm->thread_index != kv->v.thread_index) @@ -370,10 +372,14 @@ ip6_sv_reass_find_or_create (vlib_main_t *vm, ip6_sv_reass_main_t *rm, kv->v.thread_index = vm->thread_index; reass->last_heard = now; - if (clib_bihash_add_del_48_8 (&rm->hash, &kv->kv, 1)) + int rv = clib_bihash_add_del_48_8 (&rm->hash, &kv->kv, 2); + if (rv) { ip6_sv_reass_free (vm, rm, rt, reass); reass = NULL; + // if other worker created a context already work with the other copy + if (-2 == rv) + goto again; } return reass; |