nat: nat44-ed configuration refactor & cleanup
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_out2in.c
index f46433c..186d1d6 100644 (file)
@@ -37,6 +37,15 @@ static char *nat_out2in_ed_error_strings[] = {
 #undef _
 };
 
+typedef enum
+{
+  NAT_ED_SP_REASON_NO_REASON,
+  NAT_ED_SP_REASON_LOOKUP_FAILED,
+  NAT_ED_SP_REASON_VRF_EXPIRED,
+  NAT_ED_SP_TCP_CLOSED,
+  NAT_ED_SP_SESS_EXPIRED,
+} nat_slow_path_reason_e;
+
 typedef struct
 {
   u32 sw_if_index;
@@ -49,8 +58,29 @@ typedef struct
   u8 is_slow_path;
   u8 translation_via_i2of;
   u8 lookup_skipped;
+  nat_slow_path_reason_e slow_path_reason;
 } nat44_ed_out2in_trace_t;
 
+static u8 *
+format_slow_path_reason (u8 *s, va_list *args)
+{
+  nat_slow_path_reason_e reason = va_arg (*args, nat_slow_path_reason_e);
+  switch (reason)
+    {
+    case NAT_ED_SP_REASON_NO_REASON:
+      return format (s, "no reason for slow path");
+    case NAT_ED_SP_REASON_LOOKUP_FAILED:
+      return format (s, "slow path because lookup failed");
+    case NAT_ED_SP_REASON_VRF_EXPIRED:
+      return format (s, "slow path because vrf expired");
+    case NAT_ED_SP_TCP_CLOSED:
+      return format (s, "slow path because tcp closed");
+    case NAT_ED_SP_SESS_EXPIRED:
+      return format (s, "slow path because session expired");
+    }
+  return format (s, "invalid reason value");
+}
+
 static u8 *
 format_nat44_ed_out2in_trace (u8 * s, va_list * args)
 {
@@ -85,6 +115,7 @@ format_nat44_ed_out2in_trace (u8 * s, va_list * args)
          s = format (s, "\n  search key %U", format_ed_session_kvp,
                      &t->search_key);
        }
+      s = format (s, "\n %U", format_slow_path_reason, t->slow_path_reason);
     }
 
   return s;
@@ -441,7 +472,7 @@ create_session_for_static_mapping_ed (
       snat_address_t *filter = 0;
 
       // if exact address is specified use this address
-      if (is_exact_address (mapping))
+      if (is_sm_exact_address (mapping->flags))
        {
          snat_address_t *ap;
          vec_foreach (ap, sm->twice_nat_addresses)
@@ -583,8 +614,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s,
 
   if (ip->protocol == IP_PROTOCOL_ICMP)
     {
-      if (nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr,
-                                             &lookup_sport, &lookup_daddr,
+      if (nat_get_icmp_session_lookup_values (b, ip, &lookup_daddr,
+                                             &lookup_sport, &lookup_saddr,
                                              &lookup_dport, &lookup_protocol))
        return;
     }
@@ -790,6 +821,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
       snat_session_t *s0 = 0;
       clib_bihash_kv_16_8_t kv0, value0;
       nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
+      nat_slow_path_reason_e slow_path_reason = NAT_ED_SP_REASON_NO_REASON;
       nat_6t_flow_t *f = 0;
       nat_6t_t lookup;
       int lookup_skipped = 0;
@@ -806,7 +838,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
 
          vlib_prefetch_buffer_header (p2, LOAD);
 
-         CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, LOAD);
+         clib_prefetch_load (p2->data);
        }
 
       next[0] = vnet_buffer2 (b0)->nat.arc_next;
@@ -891,6 +923,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
       if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
        {
          // flow does not exist go slow path
+         slow_path_reason = NAT_ED_SP_REASON_LOOKUP_FAILED;
          next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
          goto trace0;
        }
@@ -900,11 +933,14 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
                           ed_value_get_session_index (&value0));
     skip_lookup:
 
+      ASSERT (thread_index == s0->thread_index);
+
       if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
        {
          // session is closed, go slow path
          nat_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         slow_path_reason = NAT_ED_SP_REASON_VRF_EXPIRED;
          next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
          goto trace0;
        }
@@ -914,6 +950,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
          if (now >= s0->tcp_closed_timestamp)
            {
              // session is closed, go slow path, freed in slow path
+             slow_path_reason = NAT_ED_SP_TCP_CLOSED;
              next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
            }
          else
@@ -934,6 +971,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
          // session is closed, go slow path
          nat_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         slow_path_reason = NAT_ED_SP_SESS_EXPIRED;
          next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
          goto trace0;
        }
@@ -982,16 +1020,18 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
                  nat_free_session_data (sm, s0, thread_index, 0);
                  nat_ed_session_delete (sm, s0, thread_index, 1);
                  next[0] = NAT_NEXT_DROP;
+                 b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
                  goto trace0;
                }
            }
        }
 
       if (NAT_ED_TRNSL_ERR_SUCCESS !=
-         (translation_error = nat_6t_flow_buf_translate (
-            sm, b0, ip0, f, proto0, 0 /* is_output_feature */)))
+         (translation_error = nat_6t_flow_buf_translate_o2i (
+            vm, sm, b0, ip0, f, proto0, 0 /* is_output_feature */)))
        {
          next[0] = NAT_NEXT_DROP;
+         b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
          goto trace0;
        }
 
@@ -1042,6 +1082,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
          t->translation_error = translation_error;
          clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
          t->lookup_skipped = lookup_skipped;
+         t->slow_path_reason = slow_path_reason;
 
          if (s0)
            {
@@ -1141,11 +1182,14 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
              if (!s0)
                next[0] = NAT_NEXT_DROP;
            }
-         if (NAT_NEXT_DROP != next[0] &&
+         if (NAT_NEXT_DROP != next[0] && s0 &&
              NAT_ED_TRNSL_ERR_SUCCESS !=
-               (translation_error = nat_6t_flow_buf_translate (
-                  sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
+               (translation_error = nat_6t_flow_buf_translate_o2i (
+                  vm, sm, b0, ip0, &s0->o2i, proto0,
+                  0 /* is_output_feature */)))
            {
+             next[0] = NAT_NEXT_DROP;
+             b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
              goto trace0;
            }
 
@@ -1162,9 +1206,12 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
 
          if (NAT_NEXT_DROP != next[0] && s0 &&
              NAT_ED_TRNSL_ERR_SUCCESS !=
-               (translation_error = nat_6t_flow_buf_translate (
-                  sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
+               (translation_error = nat_6t_flow_buf_translate_o2i (
+                  vm, sm, b0, ip0, &s0->o2i, proto0,
+                  0 /* is_output_feature */)))
            {
+             next[0] = NAT_NEXT_DROP;
+             b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED];
              goto trace0;
            }
 
@@ -1272,8 +1319,8 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
        }
 
       if (NAT_ED_TRNSL_ERR_SUCCESS !=
-         (translation_error = nat_6t_flow_buf_translate (
-            sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
+         (translation_error = nat_6t_flow_buf_translate_o2i (
+            vm, sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */)))
        {
          next[0] = NAT_NEXT_DROP;
          goto trace0;
@@ -1360,7 +1407,6 @@ VLIB_NODE_FN (nat44_ed_out2in_node) (vlib_main_t * vm,
     }
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_out2in_node) = {
   .name = "nat44-ed-out2in",
   .vector_size = sizeof (u32),
@@ -1371,7 +1417,6 @@ VLIB_REGISTER_NODE (nat44_ed_out2in_node) = {
   .error_strings = nat_out2in_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm,
                                              vlib_node_runtime_t * node,
@@ -1380,7 +1425,6 @@ VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm,
   return nat44_ed_out2in_slow_path_node_fn_inline (vm, node, frame);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = {
   .name = "nat44-ed-out2in-slowpath",
   .vector_size = sizeof (u32),
@@ -1391,7 +1435,6 @@ VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = {
   .error_strings = nat_out2in_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 static u8 *
 format_nat_pre_trace (u8 * s, va_list * args)
@@ -1411,7 +1454,6 @@ VLIB_NODE_FN (nat_pre_out2in_node) (vlib_main_t * vm,
                                 NAT_NEXT_OUT2IN_ED_FAST_PATH);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat_pre_out2in_node) = {
   .name = "nat-pre-out2in",
   .vector_size = sizeof (u32),
@@ -1420,7 +1462,6 @@ VLIB_REGISTER_NODE (nat_pre_out2in_node) = {
   .type = VLIB_NODE_TYPE_INTERNAL,
   .n_errors = 0,
  };
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON