diff options
author | Nathan Skrzypczak <nathan.skrzypczak@gmail.com> | 2022-02-02 19:31:43 +0100 |
---|---|---|
committer | Beno�t Ganne <bganne@cisco.com> | 2022-03-18 11:33:51 +0000 |
commit | 762cfd408b16b6ab43ade3ab491292b93bdeb9b3 (patch) | |
tree | 3b303cb9db68a8003aca57820174b03902f3c714 /src/plugins/cnat/cnat_session.c | |
parent | 6798e9ec34a49df008ecb7f84559e531f6c0d651 (diff) |
cnat: Fix conflicting rsession
When dNAT-ing to a VIP, it can happen
that the return session conflicts with
another forward session than the one
we own.
This patchs adds a rsession_flags
CNAT_SESSION_RETRY_SNAT that makes cnat_session_create
search for a free src port to use for the
resulting return session.
It also makes forward & return session
share their fate in the session scanner.
Type: fix
Change-Id: Id0edf59abf8e5bc0c0d8941ba289c4563c77dee0
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
Diffstat (limited to 'src/plugins/cnat/cnat_session.c')
-rw-r--r-- | src/plugins/cnat/cnat_session.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/plugins/cnat/cnat_session.c b/src/plugins/cnat/cnat_session.c index 216d2575c37..fa04de602b4 100644 --- a/src/plugins/cnat/cnat_session.c +++ b/src/plugins/cnat/cnat_session.c @@ -172,15 +172,43 @@ cnat_session_purge (void) return (0); } +void +cnat_reverse_session_free (cnat_session_t *session) +{ + cnat_bihash_kv_t bkey, bvalue; + cnat_session_t *rsession = (cnat_session_t *) &bkey; + int rv; + + ip46_address_copy (&rsession->key.cs_ip[VLIB_RX], + &session->value.cs_ip[VLIB_TX]); + ip46_address_copy (&rsession->key.cs_ip[VLIB_TX], + &session->value.cs_ip[VLIB_RX]); + rsession->key.cs_proto = session->key.cs_proto; + rsession->key.cs_loc = session->key.cs_loc == CNAT_LOCATION_OUTPUT ? + CNAT_LOCATION_INPUT : + CNAT_LOCATION_OUTPUT; + rsession->key.__cs_pad = 0; + rsession->key.cs_af = session->key.cs_af; + rsession->key.cs_port[VLIB_RX] = session->value.cs_port[VLIB_TX]; + rsession->key.cs_port[VLIB_TX] = session->value.cs_port[VLIB_RX]; + + rv = cnat_bihash_search_i2 (&cnat_session_db, &bkey, &bvalue); + if (!rv) + { + /* other session is in bihash */ + cnat_session_t *rsession = (cnat_session_t *) &bvalue; + cnat_session_free (rsession); + } +} + u64 cnat_session_scan (vlib_main_t * vm, f64 start_time, int i) { BVT (clib_bihash) * h = &cnat_session_db; int j, k; - /* Don't scan the l2 fib if it hasn't been instantiated yet */ if (alloc_arena (h) == 0) - return 0.0; + return 0; for ( /* caller saves starting point */ ; i < h->nbuckets; i++) { @@ -219,6 +247,9 @@ cnat_session_scan (vlib_main_t * vm, f64 start_time, int i) cnat_timestamp_exp (session->value.cs_ts_index)) { /* age it */ + cnat_reverse_session_free (session); + /* this should be last as deleting the session memset it to + * 0xff */ cnat_session_free (session); /* |