nat: add saddr info to nat44-ed o2i flow's rewrite
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_in2out.c
index b0e0784..9b4dac3 100644 (file)
@@ -102,14 +102,18 @@ nat_ed_alloc_addr_and_port_with_snat_address (
   u16 port_per_thread, u32 snat_thread_index, snat_session_t *s,
   ip4_address_t *outside_addr, u16 *outside_port)
 {
-  const u16 port_thread_offset = (port_per_thread * snat_thread_index) + 1024;
+  const u16 port_thread_offset =
+    (port_per_thread * snat_thread_index) + ED_USER_PORT_OFFSET;
+
+  /* Backup original match in case of failure */
+  const nat_6t_t match = s->o2i.match;
 
   s->o2i.match.daddr = a->addr;
   /* first try port suggested by caller */
   u16 port = clib_net_to_host_u16 (*outside_port);
   u16 port_offset = port - port_thread_offset;
-  if (port <= port_thread_offset ||
-      port > port_thread_offset + port_per_thread)
+  if (port < port_thread_offset ||
+      port >= port_thread_offset + port_per_thread)
     {
       /* need to pick a different port, suggested port doesn't fit in
        * this thread's port range */
@@ -135,6 +139,9 @@ nat_ed_alloc_addr_and_port_with_snat_address (
       --attempts;
     }
   while (attempts > 0);
+
+  /* Revert match */
+  s->o2i.match = match;
   return 1;
 }
 
@@ -148,7 +155,9 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index,
 {
   if (vec_len (sm->addresses) > 0)
     {
-      u32 s_addr_offset = s_addr.as_u32 % vec_len (sm->addresses);
+      u32 s_addr_offset = (s_addr.as_u32 + (s_addr.as_u32 >> 8) +
+                          (s_addr.as_u32 >> 16) + (s_addr.as_u32 >> 24)) %
+                         vec_len (sm->addresses);
       snat_address_t *a, *ja = 0, *ra = 0, *ba = 0;
       int i;
 
@@ -514,6 +523,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
          nat_6t_flow_dport_rewrite_set (&s->o2i, l_port);
        }
       nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
+      nat_6t_flow_saddr_rewrite_set (&s->o2i, r_addr.as_u32);
 
       if (nat_ed_alloc_addr_and_port (
            sm, rx_fib_index, tx_sw_if_index, proto, thread_index, l_addr,
@@ -558,6 +568,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
        }
       nat_6t_flow_daddr_rewrite_set (&s->o2i, l_addr.as_u32);
       nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
+      nat_6t_flow_saddr_rewrite_set (&s->o2i, r_addr.as_u32);
       if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 2))
        {
          nat_elog_notice (sm, "out2in key add failed");
@@ -1193,7 +1204,8 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
          // session is closed, go slow path
          nat44_ed_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
-         next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
+         s0 = 0;
+         next[0] = def_slow;
          goto trace0;
        }
 
@@ -1205,6 +1217,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
        {
          nat44_ed_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         s0 = 0;
          // session is closed, go slow path
          next[0] = def_slow;
          goto trace0;
@@ -1226,6 +1239,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
          translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH;
          nat44_ed_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         s0 = 0;
          next[0] = NAT_NEXT_DROP;
          b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
          goto trace0;
@@ -1237,6 +1251,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
        {
          nat44_ed_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         s0 = 0;
          next[0] = NAT_NEXT_DROP;
          b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
          goto trace0;
@@ -1394,6 +1409,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm,
            {
              nat44_ed_free_session_data (sm, s0, thread_index, 0);
              nat_ed_session_delete (sm, s0, thread_index, 1);
+             s0 = 0;
              next[0] = NAT_NEXT_DROP;
              b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
              goto trace0;
@@ -1417,6 +1433,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm,
            {
              nat44_ed_free_session_data (sm, s0, thread_index, 0);
              nat_ed_session_delete (sm, s0, thread_index, 1);
+             s0 = 0;
              next[0] = NAT_NEXT_DROP;
              b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
              goto trace0;
@@ -1495,6 +1512,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm,
        {
          nat44_ed_free_session_data (sm, s0, thread_index, 0);
          nat_ed_session_delete (sm, s0, thread_index, 1);
+         s0 = 0;
          next[0] = NAT_NEXT_DROP;
          b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
          goto trace0;