From 6631032791f842017c20ddf217e915c465ff809d Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Thu, 14 Oct 2021 18:41:57 +0300 Subject: [PATCH] cnat: flag to disable rsession This adds a flag on the translation asking the VIP & input-feature nodes not to create the return session when translating / load-balancing an incoming flow. This is needed with maglev & DSR Type: feature Change-Id: I699012310ddc59f6ceeeb4878638eac6da5128dc Signed-off-by: Nathan Skrzypczak --- src/plugins/cnat/cnat.api | 1 + src/plugins/cnat/cnat.rst | 10 +++++----- src/plugins/cnat/cnat_node.h | 18 ++++++++++++++---- src/plugins/cnat/cnat_node_feature.c | 13 +++++++++---- src/plugins/cnat/cnat_node_snat.c | 5 +++-- src/plugins/cnat/cnat_node_vip.c | 4 +++- src/plugins/cnat/cnat_src_policy.c | 4 ++-- src/plugins/cnat/cnat_translation.c | 10 +++++----- src/plugins/cnat/cnat_translation.h | 14 ++++++++------ src/plugins/cnat/cnat_types.h | 6 ++++-- 10 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/plugins/cnat/cnat.api b/src/plugins/cnat/cnat.api index e253084e74e..846917eb2e7 100644 --- a/src/plugins/cnat/cnat.api +++ b/src/plugins/cnat/cnat.api @@ -27,6 +27,7 @@ import "vnet/interface_types.api"; enum cnat_translation_flags:u8 { CNAT_TRANSLATION_ALLOC_PORT = 1, + CNAT_TRANSLATION_NO_RETURN_SESSION = 4, }; enum cnat_endpoint_tuple_flags:u8 diff --git a/src/plugins/cnat/cnat.rst b/src/plugins/cnat/cnat.rst index a177bc10aa2..b0426f35373 100644 --- a/src/plugins/cnat/cnat.rst +++ b/src/plugins/cnat/cnat.rst @@ -134,19 +134,19 @@ This plugin is built to be extensible. For now two NAT types are defined, ``cnat * Session lookup : ``rv`` will be set to ``0`` if a session was found * Translation primitives ``cnat_translation_ip4`` based on sessions * A session creation primitive ``cnat_session_create`` +* A reverse session creation primitive ``cnat_rsession_create`` -Creating a session will also create a reverse session (for matching return traffic), -and call a NAT node back that will perform the translation. +Creating a session will also create reverse session matching return traffic unless told otherwise by setting ``CNAT_TR_FLAG_NO_RETURN_SESSION`` on the translation. This will call the NAT nodes on the return flow and perform the inverse translation. Known limitations _________________ This plugin is still under development, it lacks the following features : * Load balancing doesn't support parametric probabilities -* VRFs aren't supported. All rules apply to fib table 0 only +* VRFs are not supported, all rules apply regardless of the FIB table. * Programmatic session handling (deletion, lifetime updates) aren't supported -* ICMP is not yet supported -* Traffic matching is only done based on ``(proto, dst_addr, dst_port)`` source matching isn't supported +* translations (i.e. rewriting the destination address) only match on the three +tuple ``(proto, dst_addr, dst_port)`` other matches are not supported * Statistics & session tracking are still rudimentary. diff --git a/src/plugins/cnat/cnat_node.h b/src/plugins/cnat/cnat_node.h index 75c1b4ac3ab..d81f6745bc4 100644 --- a/src/plugins/cnat/cnat_node.h +++ b/src/plugins/cnat/cnat_node.h @@ -819,10 +819,20 @@ cnat_load_balance (const cnat_translation_t *ct, ip_address_family_t af, * rsession_location is the location the (return) session will be * matched at */ + static_always_inline void -cnat_session_create (cnat_session_t *session, cnat_node_ctx_t *ctx, - cnat_session_location_t rsession_location, - u8 rsession_flags) +cnat_session_create (cnat_session_t *session, cnat_node_ctx_t *ctx) +{ + cnat_bihash_kv_t *bkey = (cnat_bihash_kv_t *) session; + + session->value.cs_ts_index = cnat_timestamp_new (ctx->now); + cnat_bihash_add_del (&cnat_session_db, bkey, 1); +} + +static_always_inline void +cnat_rsession_create (cnat_session_t *session, cnat_node_ctx_t *ctx, + cnat_session_location_t rsession_location, + cnat_session_flag_t rsession_flags) { cnat_client_t *cc; cnat_bihash_kv_t rkey; @@ -831,7 +841,7 @@ cnat_session_create (cnat_session_t *session, cnat_node_ctx_t *ctx, int rv, n_retries = 0; static u32 sport_seed = 0; - session->value.cs_ts_index = cnat_timestamp_new (ctx->now); + cnat_timestamp_inc_refcnt (session->value.cs_ts_index); /* First create the return session */ ip46_address_copy (&rsession->key.cs_ip[VLIB_RX], diff --git a/src/plugins/cnat/cnat_node_feature.c b/src/plugins/cnat/cnat_node_feature.c index 2ab5cb232b4..9b2c0c2fe06 100644 --- a/src/plugins/cnat/cnat_node_feature.c +++ b/src/plugins/cnat/cnat_node_feature.c @@ -143,7 +143,10 @@ cnat_input_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node, /* refcnt session in current client */ cnat_client_cnt_session (cc); - cnat_session_create (session, ctx, CNAT_LOCATION_OUTPUT, rsession_flags); + cnat_session_create (session, ctx); + if (!(ct->flags & CNAT_TR_FLAG_NO_RETURN_SESSION)) + cnat_rsession_create (session, ctx, CNAT_LOCATION_OUTPUT, + rsession_flags); trace_flags |= CNAT_TRACE_SESSION_CREATED; } @@ -320,9 +323,11 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node, CNAT_SESSION_FLAG_NO_CLIENT | CNAT_SESSION_FLAG_ALLOC_PORT; trace_flags |= CNAT_TRACE_SESSION_CREATED; - cnat_session_create (session, ctx, CNAT_LOCATION_INPUT, - CNAT_SESSION_FLAG_NO_CLIENT | - CNAT_SESSION_RETRY_SNAT); + + cnat_session_create (session, ctx); + cnat_rsession_create (session, ctx, CNAT_LOCATION_INPUT, + CNAT_SESSION_FLAG_NO_CLIENT | + CNAT_SESSION_RETRY_SNAT); } if (AF_IP4 == ctx->af) diff --git a/src/plugins/cnat/cnat_node_snat.c b/src/plugins/cnat/cnat_node_snat.c index f5c8a20121c..57530eb397d 100644 --- a/src/plugins/cnat/cnat_node_snat.c +++ b/src/plugins/cnat/cnat_node_snat.c @@ -129,8 +129,9 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, CNAT_SESSION_FLAG_NO_CLIENT | CNAT_SESSION_FLAG_ALLOC_PORT; trace_flags |= CNAT_TRACE_SESSION_CREATED; - cnat_session_create (session, ctx, CNAT_LOCATION_FIB, - CNAT_SESSION_FLAG_HAS_SNAT); + cnat_session_create (session, ctx); + cnat_rsession_create (session, ctx, CNAT_LOCATION_FIB, + CNAT_SESSION_FLAG_HAS_SNAT); } if (AF_IP4 == ctx->af) diff --git a/src/plugins/cnat/cnat_node_vip.c b/src/plugins/cnat/cnat_node_vip.c index 5db19d2c61e..d320746c5fa 100644 --- a/src/plugins/cnat/cnat_node_vip.c +++ b/src/plugins/cnat/cnat_node_vip.c @@ -168,7 +168,9 @@ cnat_vip_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, /* refcnt session in current client */ cnat_client_cnt_session (cc); - cnat_session_create (session, ctx, CNAT_LOCATION_FIB, rsession_flags); + cnat_session_create (session, ctx); + if (!(ct->flags & CNAT_TR_FLAG_NO_RETURN_SESSION)) + cnat_rsession_create (session, ctx, CNAT_LOCATION_FIB, rsession_flags); trace_flags |= CNAT_TRACE_SESSION_CREATED; next0 = ct->ct_lb.dpoi_next_node; diff --git a/src/plugins/cnat/cnat_src_policy.c b/src/plugins/cnat/cnat_src_policy.c index cac24b7742c..8f3f3375148 100644 --- a/src/plugins/cnat/cnat_src_policy.c +++ b/src/plugins/cnat/cnat_src_policy.c @@ -59,8 +59,8 @@ cnat_vip_default_source_policy (vlib_main_t * vm, u16 sport; sport = udp0->src_port; /* Allocate a port only if asked and if we actually sNATed */ - if ((ct->flags & CNAT_TRANSLATION_FLAG_ALLOCATE_PORT) - && (*rsession_flags & CNAT_SESSION_FLAG_HAS_SNAT)) + if ((ct->flags & CNAT_TR_FLAG_ALLOCATE_PORT) && + (*rsession_flags & CNAT_SESSION_FLAG_HAS_SNAT)) { sport = 0; /* force allocation */ session->value.flags |= CNAT_SESSION_FLAG_ALLOC_PORT; diff --git a/src/plugins/cnat/cnat_translation.c b/src/plugins/cnat/cnat_translation.c index ee3dc780fea..4645c50c3c2 100644 --- a/src/plugins/cnat/cnat_translation.c +++ b/src/plugins/cnat/cnat_translation.c @@ -233,7 +233,7 @@ cnat_translation_stack (cnat_translation_t * ct) dpo_set (&ct->ct_lb, DPO_LOAD_BALANCE, dproto, lbi); dpo_stack (cnat_client_dpo, dproto, &ct->ct_lb, &ct->ct_lb); - ct->flags |= CNAT_TRANSLATION_STACKED; + ct->flags |= CNAT_TR_FLAG_STACKED; } int @@ -315,7 +315,7 @@ cnat_translation_update (cnat_endpoint_t *vip, ip_protocol_t proto, } vec_reset_length (ct->ct_paths); - ct->flags &= ~CNAT_TRANSLATION_STACKED; + ct->flags &= ~CNAT_TR_FLAG_STACKED; u64 path_idx = 0; vec_foreach (path, paths) @@ -513,7 +513,7 @@ cnat_translation_back_walk_notify (fib_node_t * node, /* If we have more than FIB_PATH_LIST_POPULAR paths * we might get called during path tracking * (cnat_tracker_track) */ - if (!(ct->flags & CNAT_TRANSLATION_STACKED)) + if (!(ct->flags & CNAT_TR_FLAG_STACKED)) return (FIB_NODE_BACK_WALK_CONTINUE); cnat_translation_stack (ct); @@ -662,11 +662,11 @@ cnat_if_addr_add_del_backend_cb (addr_resolution_t * ar, ep->ce_flags |= CNAT_EP_FLAG_RESOLVED; } - ct->flags &= ~CNAT_TRANSLATION_STACKED; + ct->flags &= ~CNAT_TR_FLAG_STACKED; cnat_tracker_track (ar->cti, trk); cnat_translation_stack (ct); - ct->flags |= CNAT_TRANSLATION_STACKED; + ct->flags |= CNAT_TR_FLAG_STACKED; } static void diff --git a/src/plugins/cnat/cnat_translation.h b/src/plugins/cnat/cnat_translation.h index 97b0c908b42..d5923f04397 100644 --- a/src/plugins/cnat/cnat_translation.h +++ b/src/plugins/cnat/cnat_translation.h @@ -60,12 +60,14 @@ typedef struct cnat_ep_trk_t_ typedef enum cnat_translation_flag_t_ { /* Do allocate a source port */ - CNAT_TRANSLATION_FLAG_ALLOCATE_PORT = (1 << 0), + CNAT_TR_FLAG_ALLOCATE_PORT = (1 << 0), /* Has this translation been satcked ? * this allow not being called twice when * with more then FIB_PATH_LIST_POPULAR backends */ - CNAT_TRANSLATION_STACKED = (1 << 1), -} cnat_translation_flag_t; + CNAT_TR_FLAG_STACKED = (1 << 1), + /* Do not create a return session */ + CNAT_TR_FLAG_NO_RETURN_SESSION = (1 << 2), +} __clib_packed cnat_translation_flag_t; typedef enum { @@ -76,11 +78,11 @@ typedef enum CNAT_ADDR_N_RESOLUTIONS, } cnat_addr_resol_type_t; -typedef enum __attribute__ ((__packed__)) +typedef enum { CNAT_LB_DEFAULT, CNAT_LB_MAGLEV, -} cnat_lb_type_t; +} __clib_packed cnat_lb_type_t; /** * Entry used to account for a translation's backend @@ -160,7 +162,7 @@ typedef struct cnat_translation_t_ /** * Translation flags */ - u8 flags; + cnat_translation_flag_t flags; /** * Type of load balancing diff --git a/src/plugins/cnat/cnat_types.h b/src/plugins/cnat/cnat_types.h index bf2726fa63a..84fb7d0b3c3 100644 --- a/src/plugins/cnat/cnat_types.h +++ b/src/plugins/cnat/cnat_types.h @@ -50,8 +50,10 @@ * from fib_source.h */ #define CNAT_FIB_SOURCE_PRIORITY 0x02 -/* Initial refcnt for timestamps (2 : session & rsession) */ -#define CNAT_TIMESTAMP_INIT_REFCNT 2 +/* Initial number of timestamps for a session + * this will be incremented when adding the reverse + * session in cnat_rsession_create */ +#define CNAT_TIMESTAMP_INIT_REFCNT 1 #define MIN_SRC_PORT ((u16) 0xC000) -- 2.16.6