cnat: flag to disable rsession
[vpp.git] / src / plugins / cnat / cnat_node_feature.c
index c99160c..9b2c0c2 100644 (file)
@@ -18,7 +18,7 @@
 #include <cnat/cnat_translation.h>
 #include <cnat/cnat_inline.h>
 #include <cnat/cnat_src_policy.h>
-#include <cnat/cnat_snat.h>
+#include <cnat/cnat_snat_policy.h>
 
 #include <vnet/dpo/load_balance.h>
 #include <vnet/dpo/load_balance_map.h>
@@ -125,37 +125,43 @@ cnat_input_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
       session->value.cs_port[VLIB_TX] =
        clib_host_to_net_u16 (trk0->ct_ep[VLIB_TX].ce_port);
       session->value.cs_port[VLIB_RX] = udp0->src_port;
+      session->value.flags = 0;
 
-      const dpo_id_t *dpo0;
-      const load_balance_t *lb1;
-      fib_entry_t *fib_entry;
-      fib_entry = fib_entry_get (trk0->ct_fei);
-
-      lb1 = load_balance_get (fib_entry->fe_lb /*[fct] */.dpoi_index);
-      dpo0 = load_balance_get_bucket_i (lb1, 0);
+      if (trk0->ct_flags & CNAT_TRK_FLAG_NO_NAT)
+       {
+         const dpo_id_t *dpo0;
+         const load_balance_t *lb1;
 
-      session->value.dpoi_next_node = dpo0->dpoi_next_node;
-      session->value.cs_lbi = dpo0->dpoi_index;
+         lb1 = load_balance_get (trk0->ct_dpo.dpoi_index);
+         /* Assume backend has exactly one item in LB */
+         dpo0 = load_balance_get_bucket_i (lb1, 0);
 
-      if (trk0->ct_flags & CNAT_TRK_FLAG_NO_NAT)
-       session->value.flags |= CNAT_SESSION_FLAG_NO_NAT;
+         session->value.dpoi_next_node = dpo0->dpoi_next_node;
+         session->value.cs_lbi = dpo0->dpoi_index;
+         session->value.flags = CNAT_SESSION_FLAG_NO_NAT;
+       }
 
       /* 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;
     }
 
-  next0 = session->value.dpoi_next_node;
-  vnet_buffer (b)->ip.adj_index[VLIB_TX] = session->value.cs_lbi;
-
   if (session->value.flags & CNAT_SESSION_FLAG_NO_NAT)
-    goto trace;
+    {
+      /* If we don't translate, directly do the lookup & bypass arc */
+      next0 = session->value.dpoi_next_node;
+      vnet_buffer (b)->ip.adj_index[VLIB_TX] = session->value.cs_lbi;
+      goto trace;
+    }
 
   if (AF_IP4 == ctx->af)
-    cnat_translation_ip4 (session, ip4, udp0);
+    cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags);
   else
-    cnat_translation_ip6 (session, ip6, udp0);
+    cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags);
 
   if (NULL != ct)
     {
@@ -190,8 +196,7 @@ VLIB_REGISTER_NODE (cnat_input_feature_ip4_node) = {
   .type = VLIB_NODE_TYPE_INTERNAL,
   .n_errors = CNAT_N_ERROR,
   .error_strings = cnat_error_strings,
-  .n_next_nodes = IP_LOOKUP_N_NEXT,
-  .next_nodes = IP4_LOOKUP_NEXT_NODES,
+  .sibling_of = "ip4-lookup",
 };
 
 VNET_FEATURE_INIT (cnat_in_ip4_feature, static) = {
@@ -217,10 +222,7 @@ VLIB_REGISTER_NODE (cnat_input_feature_ip6_node) = {
   .type = VLIB_NODE_TYPE_INTERNAL,
   .n_errors = CNAT_N_ERROR,
   .error_strings = cnat_error_strings,
-  .n_next_nodes = CNAT_FEATURE_N_NEXT,
-  .next_nodes = {
-      [CNAT_FEATURE_NEXT_DROP] = "error-drop",
-  },
+  .sibling_of = "ip6-lookup",
 };
 
 VNET_FEATURE_INIT (cnat_in_ip6_feature, static) = {
@@ -236,8 +238,7 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
                        vlib_buffer_t *b, cnat_node_ctx_t *ctx,
                        int session_not_found, cnat_session_t *session)
 {
-  cnat_main_t *cm = &cnat_main;
-  cnat_snat_policy_main_t *cms = &cnat_snat_policy_main;
+  cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
   ip4_header_t *ip4 = NULL;
   ip_protocol_t iproto;
   ip6_header_t *ip6 = NULL;
@@ -275,32 +276,31 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
       /* session table hit */
       cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
     }
-  else if (!cms->snat_policy)
+  else if (!cpm->snat_policy)
     goto trace;
   else
     {
-      /* TODO: handle errors? */
-      cms->snat_policy (vm, b, session, ctx, &do_snat);
+      do_snat = cpm->snat_policy (b, session);
       if (do_snat != 1)
        goto trace;
 
       if (AF_IP4 == ctx->af)
        {
-         if (ip_address_is_zero (&cm->snat_ip4.ce_ip))
+         if (ip_address_is_zero (&cpm->snat_ip4.ce_ip))
            goto trace;
 
          ip46_address_set_ip4 (&session->value.cs_ip[VLIB_RX],
-                               &ip_addr_v4 (&cm->snat_ip4.ce_ip));
+                               &ip_addr_v4 (&cpm->snat_ip4.ce_ip));
          ip46_address_set_ip4 (&session->value.cs_ip[VLIB_TX],
                                &ip4->dst_address);
        }
       else
        {
-         if (ip_address_is_zero (&cm->snat_ip6.ce_ip))
+         if (ip_address_is_zero (&cpm->snat_ip6.ce_ip))
            goto trace;
 
          ip46_address_set_ip6 (&session->value.cs_ip[VLIB_RX],
-                               &ip_addr_v6 (&cm->snat_ip6.ce_ip));
+                               &ip_addr_v6 (&cpm->snat_ip6.ce_ip));
          ip46_address_set_ip6 (&session->value.cs_ip[VLIB_TX],
                                &ip6->dst_address);
        }
@@ -323,14 +323,17 @@ 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_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)
-    cnat_translation_ip4 (session, ip4, udp0);
+    cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags);
   else
-    cnat_translation_ip6 (session, ip6, udp0);
+    cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags);
 
 trace:
   if (PREDICT_FALSE (ctx->do_trace))