nat: fix per-vrf session bookkeeping 70/36670/6
authorJing Peng <jing@meter.com>
Fri, 15 Jul 2022 19:12:29 +0000 (15:12 -0400)
committerOle Tr�an <otroan@employees.org>
Mon, 7 Nov 2022 08:00:23 +0000 (08:00 +0000)
commit61fdfd51d1dd5bd4f3bc02b332b265c28e879221
tree414b4893346d8dccddf44723fdccd802dee7db2b
parent9ff833d8f4ccccc475f9a302b8f70eed49963472
nat: fix per-vrf session bookkeeping

Each NAT44 ED session has a per_vrf_sessions_index referencing
an element in the thread-local vector per_vrf_sessions_vec.
However this index can be possibly invalidated by vec_del1() in
per_vrf_sessions_cleanup(), before a session is registered.
Such a stale index can cause an assertion failure in function
per_vrf_sessions_is_expired() when we use it to locate the
per_vrf_sessions object.

A possible sequence to reproduce is:

1. Create two NAT44 ED sessions s1, s2 so that two per_vrf_sessions are created:
     index 0: between VRF pair 10 and 11 (expired=0, ses_count=1)
     index 1: between VRF pair 20 and 21 (expired=0, ses_count=1)
   For the sessions we have:
     s1->per_vrf_sessions_index == 0
     s2->per_vrf_sessions_index == 1

2. Delete the first session via CLI, now the two per_vrf_sessions become:
     index 0: between VRF pair 10 and 11 (expired=0, ses_count=0)
     index 1: between VRF pair 20 and 21 (expired=0, ses_count=1)
   For the sessions we have:
     s2->per_vrf_sessions_index == 1

3. Delete the VRF 11:
     index 0: between VRF pair 10 and 11 (expired=1, ses_count=0)
     index 1: between VRF pair 20 and 21 (expired=0, ses_count=1)
   For the sessions we have:
     s2->per_vrf_sessions_index == 1

4. Create a new session s3 between VRF pair 20 and 21 so that the first
   per_vrf_sessions will be deleted:
     index 0: between VRF pair 20 and 21 (expired=0, ses_count=2)
   For the sessions we have:
     s2->per_vrf_sessions_index == 1
     s3->per_vrf_sessions_index == 0
   Here, note that the actual index of per_vrf_session is changed due
   to vec_del1(). The new session is added after the cleanup so it gets
   the correct index. But the index held by the existing session is not
   updated.

5. Trigger the fast path of the session s2. To achieve this, session
   s2 could be created in step 1 by
     ping -i20 -Iiface_in_vrf_10 1.1.1.1
   and steps 2-4 should then be performed within the 20-second interval.

This patch fixes this by changing per_vrf_sessions_vec to a pool so
that indicies are kept intact.

Type: fix
Signed-off-by: Jing Peng <jing@meter.com>
Change-Id: I4c08f9bfd50134bcb5f08e50ad61af2bddbcb645
src/plugins/nat/nat44-ed/nat44_ed.c
src/plugins/nat/nat44-ed/nat44_ed.h
src/plugins/nat/nat44-ed/nat44_ed_inlines.h