cnat: flag to disable rsession 08/34108/10
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Thu, 14 Oct 2021 15:41:57 +0000 (18:41 +0300)
committerBeno�t Ganne <bganne@cisco.com>
Tue, 8 Aug 2023 14:06:08 +0000 (14:06 +0000)
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 <nathan.skrzypczak@gmail.com>
src/plugins/cnat/cnat.api
src/plugins/cnat/cnat.rst
src/plugins/cnat/cnat_node.h
src/plugins/cnat/cnat_node_feature.c
src/plugins/cnat/cnat_node_snat.c
src/plugins/cnat/cnat_node_vip.c
src/plugins/cnat/cnat_src_policy.c
src/plugins/cnat/cnat_translation.c
src/plugins/cnat/cnat_translation.h
src/plugins/cnat/cnat_types.h

index e253084..846917e 100644 (file)
@@ -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
index a177bc1..b0426f3 100644 (file)
@@ -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.
 
 
index 75c1b4a..d81f674 100644 (file)
@@ -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],
index 2ab5cb2..9b2c0c2 100644 (file)
@@ -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)
index f5c8a20..57530eb 100644 (file)
@@ -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)
index 5db19d2..d320746 100644 (file)
@@ -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;
index cac24b7..8f3f337 100644 (file)
@@ -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;
index ee3dc78..4645c50 100644 (file)
@@ -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
index 97b0c90..d5923f0 100644 (file)
@@ -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
index bf2726f..84fb7d0 100644 (file)
  * 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)