nat: Final NAT44 EI/ED split patch
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_in2out.c
similarity index 92%
rename from src/plugins/nat/in2out_ed.c
rename to src/plugins/nat/nat44-ed/nat44_ed_in2out.c
index 9dc6857..784dea0 100644 (file)
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/udp/udp_local.h>
 #include <vppinfra/error.h>
-#include <nat/nat.h>
-#include <nat/lib/ipfix_logging.h>
-#include <nat/nat_inlines.h>
-#include <nat/nat44/inlines.h>
+
 #include <nat/lib/nat_syslog.h>
-#include <nat/nat44/ed_inlines.h>
 #include <nat/lib/nat_inlines.h>
+#include <nat/lib/ipfix_logging.h>
+
+#include <nat/nat44-ed/nat44_ed.h>
+#include <nat/nat44-ed/nat44_ed_inlines.h>
 
 /* number of attempts to get a port for ED overloading algorithm, if rolling
  * a dice this many times doesn't produce a free port, it's treated
@@ -95,6 +95,75 @@ format_nat_in2out_ed_trace (u8 * s, va_list * args)
   return s;
 }
 
+/**
+ * @brief Check if packet should be translated
+ *
+ * Packets aimed at outside interface and external address with active session
+ * should be translated.
+ *
+ * @param sm            NAT main
+ * @param rt            NAT runtime data
+ * @param sw_if_index0  index of the inside interface
+ * @param ip0           IPv4 header
+ * @param proto0        NAT protocol
+ * @param rx_fib_index0 RX FIB index
+ *
+ * @returns 0 if packet should be translated otherwise 1
+ */
+static inline int
+snat_not_translate_fast (snat_main_t *sm, vlib_node_runtime_t *node,
+                        u32 sw_if_index0, ip4_header_t *ip0, u32 proto0,
+                        u32 rx_fib_index0)
+{
+  fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
+  nat_outside_fib_t *outside_fib;
+  fib_prefix_t pfx = {
+    .fp_proto = FIB_PROTOCOL_IP4,
+    .fp_len = 32,
+    .fp_addr = {
+               .ip4.as_u32 = ip0->dst_address.as_u32,
+               }
+    ,
+  };
+
+  /* Don't NAT packet aimed at the intfc address */
+  if (PREDICT_FALSE (
+       is_interface_addr (sm, node, sw_if_index0, ip0->dst_address.as_u32)))
+    return 1;
+
+  fei = fib_table_lookup (rx_fib_index0, &pfx);
+  if (FIB_NODE_INDEX_INVALID != fei)
+    {
+      u32 sw_if_index = fib_entry_get_resolving_interface (fei);
+      if (sw_if_index == ~0)
+       {
+         vec_foreach (outside_fib, sm->outside_fibs)
+           {
+             fei = fib_table_lookup (outside_fib->fib_index, &pfx);
+             if (FIB_NODE_INDEX_INVALID != fei)
+               {
+                 sw_if_index = fib_entry_get_resolving_interface (fei);
+                 if (sw_if_index != ~0)
+                   break;
+               }
+           }
+       }
+      if (sw_if_index == ~0)
+       return 1;
+
+      snat_interface_t *i;
+      pool_foreach (i, sm->interfaces)
+       {
+         /* NAT packet aimed at outside interface */
+         if ((nat_interface_is_outside (i)) &&
+             (sw_if_index == i->sw_if_index))
+           return 0;
+       }
+    }
+
+  return 1;
+}
+
 static int
 nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto,
                            u32 thread_index, ip4_address_t r_addr, u16 r_port,
@@ -160,7 +229,7 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto,
 
          foreach_nat_protocol;
        default:
-         nat_elog_info ("unknown protocol");
+         nat_elog_info (sm, "unknown protocol");
          return 1;
        }
     }
@@ -174,7 +243,7 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto,
        {
          foreach_nat_protocol;
        default:
-         nat_elog_info ("unknown protocol");
+         nat_elog_info (sm, "unknown protocol");
          return 1;
        }
     }
@@ -198,7 +267,6 @@ nat_outside_fib_index_lookup (snat_main_t * sm, ip4_address_t addr)
     ,
   };
   // TODO: multiple vrfs none can resolve addr
-  /* *INDENT-OFF* */
   vec_foreach (outside_fib, sm->outside_fibs)
     {
       fei = fib_table_lookup (outside_fib->fib_index, &pfx);
@@ -210,7 +278,6 @@ nat_outside_fib_index_lookup (snat_main_t * sm, ip4_address_t addr)
             }
         }
     }
-  /* *INDENT-ON* */
   return ~0;
 }
 
@@ -279,7 +346,7 @@ slow_path_ed (snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr,
          b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
          nat_ipfix_logging_max_sessions (thread_index,
                                          sm->max_translations_per_thread);
-         nat_elog_notice ("maximum sessions exceeded");
+         nat_elog_notice (sm, "maximum sessions exceeded");
          return NAT_NEXT_DROP;
        }
     }
@@ -360,7 +427,7 @@ slow_path_ed (snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr,
            sm->port_per_thread, tsm->snat_thread_index, s, &outside_addr,
            &outside_port))
        {
-         nat_elog_notice ("addresses exhausted");
+         nat_elog_notice (sm, "addresses exhausted");
          b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
          nat_ed_session_delete (sm, s, thread_index, 1);
          return NAT_NEXT_DROP;
@@ -401,7 +468,7 @@ slow_path_ed (snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr,
       nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
       if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 2))
        {
-         nat_elog_notice ("out2in key add failed");
+         nat_elog_notice (sm, "out2in key add failed");
          goto error;
        }
     }
@@ -429,7 +496,7 @@ slow_path_ed (snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr,
 
   if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
     {
-      nat_elog_notice ("in2out key add failed");
+      nat_elog_notice (sm, "in2out key add failed");
       goto error;
     }
 
@@ -441,12 +508,10 @@ slow_path_ed (snat_main_t *sm, vlib_buffer_t *b, ip4_address_t l_addr,
                                      s->in2out.port,
                                      s->out2in.port, s->in2out.fib_index);
 
-  nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
-                        &s->in2out.addr, s->in2out.port,
-                        &s->ext_host_nat_addr, s->ext_host_nat_port,
-                        &s->out2in.addr, s->out2in.port,
-                        &s->ext_host_addr, s->ext_host_port, s->nat_proto,
-                        0);
+  nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr,
+                        s->in2out.port, &s->ext_host_nat_addr,
+                        s->ext_host_nat_port, &s->out2in.addr, s->out2in.port,
+                        &s->ext_host_addr, s->ext_host_port, s->nat_proto, 0);
 
   per_vrf_sessions_register_session (s, thread_index);
 
@@ -610,13 +675,11 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
        return 0;
 
       /* hairpinning */
-      /* *INDENT-OFF* */
       pool_foreach (i, sm->output_feature_interfaces)
        {
         if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
            return 0;
       }
-      /* *INDENT-ON* */
       return 1;
     }
 
@@ -729,7 +792,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
       b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
       nat_ipfix_logging_max_sessions (thread_index,
                                      sm->max_translations_per_thread);
-      nat_elog_notice ("maximum sessions exceeded");
+      nat_elog_notice (sm, "maximum sessions exceeded");
       return 0;
     }
 
@@ -794,7 +857,7 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
   if (!s)
     {
       b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
-      nat_elog_warn ("create NAT session failed");
+      nat_elog_warn (sm, "create NAT session failed");
       return 0;
     }
 
@@ -831,14 +894,14 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
 
   if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
     {
-      nat_elog_notice ("in2out flow hash add failed");
+      nat_elog_notice (sm, "in2out flow hash add failed");
       nat_ed_session_delete (sm, s, thread_index, 1);
       return NULL;
     }
 
   if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
     {
-      nat_elog_notice ("out2in flow hash add failed");
+      nat_elog_notice (sm, "out2in flow hash add failed");
       nat_ed_session_delete (sm, s, thread_index, 1);
       return NULL;
     }
@@ -1089,22 +1152,21 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
       switch (proto0)
        {
        case NAT_PROTOCOL_TCP:
-         vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.tcp,
+         vlib_increment_simple_counter (&sm->counters.fastpath.in2out.tcp,
                                         thread_index, sw_if_index0, 1);
          nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
          break;
        case NAT_PROTOCOL_UDP:
-         vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.udp,
+         vlib_increment_simple_counter (&sm->counters.fastpath.in2out.udp,
                                         thread_index, sw_if_index0, 1);
          break;
        case NAT_PROTOCOL_ICMP:
-         vlib_increment_simple_counter (&sm->counters.fastpath.in2out_ed.icmp,
+         vlib_increment_simple_counter (&sm->counters.fastpath.in2out.icmp,
                                         thread_index, sw_if_index0, 1);
          break;
        case NAT_PROTOCOL_OTHER:
-         vlib_increment_simple_counter (
-           &sm->counters.fastpath.in2out_ed.other, thread_index, sw_if_index0,
-           1);
+         vlib_increment_simple_counter (&sm->counters.fastpath.in2out.other,
+                                        thread_index, sw_if_index0, 1);
          break;
        }
 
@@ -1144,9 +1206,8 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
 
       if (next[0] == NAT_NEXT_DROP)
        {
-         vlib_increment_simple_counter (&sm->counters.fastpath.
-                                        in2out_ed.drops, thread_index,
-                                        sw_if_index0, 1);
+         vlib_increment_simple_counter (&sm->counters.fastpath.in2out.drops,
+                                        thread_index, sw_if_index0, 1);
        }
 
       n_left_from--;
@@ -1231,9 +1292,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
              goto trace0;
            }
 
-         vlib_increment_simple_counter (&sm->counters.slowpath.
-                                        in2out_ed.other, thread_index,
-                                        sw_if_index0, 1);
+         vlib_increment_simple_counter (&sm->counters.slowpath.in2out.other,
+                                        thread_index, sw_if_index0, 1);
          goto trace0;
        }
 
@@ -1250,9 +1310,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
              goto trace0;
            }
 
-         vlib_increment_simple_counter (&sm->counters.slowpath.
-                                        in2out_ed.icmp, thread_index,
-                                        sw_if_index0, 1);
+         vlib_increment_simple_counter (&sm->counters.slowpath.in2out.icmp,
+                                        thread_index, sw_if_index0, 1);
          goto trace0;
        }
 
@@ -1336,13 +1395,13 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
 
       if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
        {
-         vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.tcp,
+         vlib_increment_simple_counter (&sm->counters.slowpath.in2out.tcp,
                                         thread_index, sw_if_index0, 1);
          nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index);
        }
       else
        {
-         vlib_increment_simple_counter (&sm->counters.slowpath.in2out_ed.udp,
+         vlib_increment_simple_counter (&sm->counters.slowpath.in2out.udp,
                                         thread_index, sw_if_index0, 1);
        }
 
@@ -1381,9 +1440,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
 
       if (next[0] == NAT_NEXT_DROP)
        {
-         vlib_increment_simple_counter (&sm->counters.slowpath.
-                                        in2out_ed.drops, thread_index,
-                                        sw_if_index0, 1);
+         vlib_increment_simple_counter (&sm->counters.slowpath.in2out.drops,
+                                        thread_index, sw_if_index0, 1);
        }
 
       n_left_from--;
@@ -1404,7 +1462,6 @@ VLIB_NODE_FN (nat44_ed_in2out_node) (vlib_main_t * vm,
   return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
   .name = "nat44-ed-in2out",
   .vector_size = sizeof (u32),
@@ -1415,7 +1472,6 @@ VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
   .error_strings = nat_in2out_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 VLIB_NODE_FN (nat44_ed_in2out_output_node) (vlib_main_t * vm,
                                            vlib_node_runtime_t * node,
@@ -1424,7 +1480,6 @@ VLIB_NODE_FN (nat44_ed_in2out_output_node) (vlib_main_t * vm,
   return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
   .name = "nat44-ed-in2out-output",
   .vector_size = sizeof (u32),
@@ -1435,7 +1490,6 @@ VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
   .error_strings = nat_in2out_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 VLIB_NODE_FN (nat44_ed_in2out_slowpath_node) (vlib_main_t * vm,
                                              vlib_node_runtime_t *
@@ -1444,7 +1498,6 @@ VLIB_NODE_FN (nat44_ed_in2out_slowpath_node) (vlib_main_t * vm,
   return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 0);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node) = {
   .name = "nat44-ed-in2out-slowpath",
   .vector_size = sizeof (u32),
@@ -1455,7 +1508,6 @@ VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node) = {
   .error_strings = nat_in2out_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 VLIB_NODE_FN (nat44_ed_in2out_output_slowpath_node) (vlib_main_t * vm,
                                                     vlib_node_runtime_t
@@ -1465,7 +1517,6 @@ VLIB_NODE_FN (nat44_ed_in2out_output_slowpath_node) (vlib_main_t * vm,
   return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 1);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node) = {
   .name = "nat44-ed-in2out-output-slowpath",
   .vector_size = sizeof (u32),
@@ -1476,7 +1527,6 @@ VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node) = {
   .error_strings = nat_in2out_ed_error_strings,
   .runtime_data_bytes = sizeof (snat_runtime_t),
 };
-/* *INDENT-ON* */
 
 static u8 *
 format_nat_pre_trace (u8 * s, va_list * args)
@@ -1502,7 +1552,6 @@ VLIB_NODE_FN (nat_pre_in2out_output_node)
                                 NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH);
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (nat_pre_in2out_node) = {
   .name = "nat-pre-in2out",
   .vector_size = sizeof (u32),
@@ -1520,7 +1569,6 @@ VLIB_REGISTER_NODE (nat_pre_in2out_output_node) = {
   .type = VLIB_NODE_TYPE_INTERNAL,
   .n_errors = 0,
 };
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON