diff options
author | Klement Sekera <ksekera@cisco.com> | 2020-12-15 18:47:05 +0100 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-01-18 08:36:26 +0000 |
commit | 4881cb4c6f0d9c6276eb7a45ed355f9fc3d729b3 (patch) | |
tree | 07959eb6fc99b88b30e6f81f4620d8d6c70110e2 /src/plugins/nat/nat44/ed_inlines.h | |
parent | 4a58e49cfe03150034a65e147a2ffe8d24391b86 (diff) |
nat: deal with flows instead of sessions
This change introduces flow concept to endpoint-dependent NAT. Instead
of having a session and a plethora of special cases in code for e.g.
hairpinning, twice-nat and others, figure all this out and store it in
flow logic. Every flow has a match and a rewrite part. This unifies all
the NAT packet processing cases into one - match a flow and rewrite the
packet based on that flow. It also provides a cure for hairpinning
dilemma where one part of the flow is on one worker and another on
a different one. These cases are also sped up by not requiring
destination adress lookup every single time to be able to rewrite source
nat as this is now part of flow rewrite logic.
Type: improvement
Change-Id: Ib60c992e16792ea4d4129bc10202ebb99a73b5be
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Diffstat (limited to 'src/plugins/nat/nat44/ed_inlines.h')
-rw-r--r-- | src/plugins/nat/nat44/ed_inlines.h | 116 |
1 files changed, 111 insertions, 5 deletions
diff --git a/src/plugins/nat/nat44/ed_inlines.h b/src/plugins/nat/nat44/ed_inlines.h index 1b4df4d02fd..87de25e990b 100644 --- a/src/plugins/nat/nat44/ed_inlines.h +++ b/src/plugins/nat/nat44/ed_inlines.h @@ -51,6 +51,60 @@ nat_ed_lru_insert (snat_main_per_thread_data_t * tsm, return 1; } +static_always_inline void +nat_6t_flow_to_ed_k (clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f) +{ + init_ed_k (kv, f->match.saddr, f->match.sport, f->match.daddr, + f->match.dport, f->match.fib_index, f->match.proto); +} + +static_always_inline void +nat_6t_flow_to_ed_kv (clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f, + u32 thread_idx, u32 session_idx) +{ + init_ed_kv (kv, f->match.saddr, f->match.sport, f->match.daddr, + f->match.dport, f->match.fib_index, f->match.proto, thread_idx, + session_idx); +} + +static_always_inline int +nat_ed_ses_i2o_flow_hash_add_del (snat_main_t *sm, u32 thread_idx, + snat_session_t *s, int is_add) +{ + snat_main_per_thread_data_t *tsm = + vec_elt_at_index (sm->per_thread_data, thread_idx); + clib_bihash_kv_16_8_t kv; + if (0 == is_add) + { + nat_6t_flow_to_ed_k (&kv, &s->i2o); + } + else + { + nat_6t_flow_to_ed_kv (&kv, &s->i2o, thread_idx, s - tsm->sessions); + nat_6t_l3_l4_csum_calc (&s->i2o); + } + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, is_add); +} + +static_always_inline int +nat_ed_ses_o2i_flow_hash_add_del (snat_main_t *sm, u32 thread_idx, + snat_session_t *s, int is_add) +{ + snat_main_per_thread_data_t *tsm = + vec_elt_at_index (sm->per_thread_data, thread_idx); + clib_bihash_kv_16_8_t kv; + if (0 == is_add) + { + nat_6t_flow_to_ed_k (&kv, &s->o2i); + } + else + { + nat_6t_flow_to_ed_kv (&kv, &s->o2i, thread_idx, s - tsm->sessions); + nat_6t_l3_l4_csum_calc (&s->o2i); + } + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, is_add); +} + always_inline void nat_ed_session_delete (snat_main_t * sm, snat_session_t * ses, u32 thread_index, int lru_delete @@ -64,6 +118,10 @@ nat_ed_session_delete (snat_main_t * sm, snat_session_t * ses, clib_dlist_remove (tsm->lru_pool, ses->lru_index); } pool_put_index (tsm->lru_pool, ses->lru_index); + if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, ses, 0)) + nat_elog_warn ("flow hash del failed"); + if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, ses, 0)) + nat_elog_warn ("flow hash del failed"); pool_put (tsm->sessions, ses); vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, pool_elts (tsm->sessions)); @@ -225,10 +283,10 @@ per_vrf_sessions_unregister_session (snat_session_t * s, u32 thread_index) per_vrf_sessions_t *per_vrf_sessions; ASSERT (s->per_vrf_sessions_index != ~0); - + tsm = vec_elt_at_index (sm->per_thread_data, thread_index); - per_vrf_sessions = vec_elt_at_index (tsm->per_vrf_sessions_vec, - s->per_vrf_sessions_index); + per_vrf_sessions = + vec_elt_at_index (tsm->per_vrf_sessions_vec, s->per_vrf_sessions_index); ASSERT (per_vrf_sessions->ses_count != 0); @@ -247,9 +305,57 @@ per_vrf_sessions_is_expired (snat_session_t * s, u32 thread_index) ASSERT (s->per_vrf_sessions_index != ~0); tsm = vec_elt_at_index (sm->per_thread_data, thread_index); - per_vrf_sessions = vec_elt_at_index (tsm->per_vrf_sessions_vec, - s->per_vrf_sessions_index); + per_vrf_sessions = + vec_elt_at_index (tsm->per_vrf_sessions_vec, s->per_vrf_sessions_index); return per_vrf_sessions->expired; } +static_always_inline void +nat_6t_flow_init (nat_6t_flow_t *f, u32 thread_idx, ip4_address_t saddr, + u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, + u8 proto, u32 session_idx) +{ + clib_memset (f, 0, sizeof (*f)); + f->match.saddr = saddr; + f->match.sport = sport; + f->match.daddr = daddr; + f->match.dport = dport; + f->match.proto = proto; + f->match.fib_index = fib_index; +} + +static_always_inline void +nat_6t_i2o_flow_init (snat_main_t *sm, u32 thread_idx, snat_session_t *s, + ip4_address_t saddr, u16 sport, ip4_address_t daddr, + u16 dport, u32 fib_index, u8 proto) +{ + snat_main_per_thread_data_t *tsm = + vec_elt_at_index (sm->per_thread_data, thread_idx); + nat_6t_flow_init (&s->i2o, thread_idx, saddr, sport, daddr, dport, fib_index, + proto, s - tsm->sessions); +} + +static_always_inline void +nat_6t_o2i_flow_init (snat_main_t *sm, u32 thread_idx, snat_session_t *s, + ip4_address_t saddr, u16 sport, ip4_address_t daddr, + u16 dport, u32 fib_index, u8 proto) +{ + snat_main_per_thread_data_t *tsm = + vec_elt_at_index (sm->per_thread_data, thread_idx); + nat_6t_flow_init (&s->o2i, thread_idx, saddr, sport, daddr, dport, fib_index, + proto, s - tsm->sessions); +} + +static_always_inline int +nat_6t_flow_match (nat_6t_flow_t *f, vlib_buffer_t *b, ip4_address_t saddr, + u16 sport, ip4_address_t daddr, u16 dport, u8 protocol, + u32 fib_index) +{ + return f->match.daddr.as_u32 == daddr.as_u32 && + f->match.dport == vnet_buffer (b)->ip.reass.l4_dst_port && + f->match.proto == protocol && f->match.fib_index == fib_index && + f->match.saddr.as_u32 == saddr.as_u32 && + f->match.sport == vnet_buffer (b)->ip.reass.l4_src_port; +} + #endif |