NAT: fix maximum out of order fragments (VPP-1399)
[vpp.git] / src / plugins / nat / nat64_out2in.c
index 1ba73a4..54a7e82 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <nat/nat64.h>
 #include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
 #include <vnet/ip/ip4_to_ip6.h>
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/udp/udp.h>
@@ -159,8 +160,6 @@ nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6,
        nat64_db_st_entry_create (db, bibe, &ip6_saddr, &saddr.ip4, sport);
     }
 
-  nat64_session_reset_timeout (ste, ctx->vm);
-
   ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
   ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
 
@@ -171,13 +170,19 @@ nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6,
   if (proto == IP_PROTOCOL_UDP)
     checksum = &udp->checksum;
   else
-    checksum = &tcp->checksum;
+    {
+      checksum = &tcp->checksum;
+      nat64_tcp_session_set_state (ste, tcp, 0);
+    }
+
   csum = ip_csum_sub_even (*checksum, dport);
   csum = ip_csum_add_even (csum, udp->dst_port);
   *checksum = ip_csum_fold (csum);
 
   vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
 
+  nat64_session_reset_timeout (ste, ctx->vm);
+
   return 0;
 }
 
@@ -407,7 +412,7 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 n_left_from, *from, *to_next;
   nat64_out2in_next_t next_index;
   u32 pkts_processed = 0;
-  u32 thread_index = vlib_get_thread_index ();
+  u32 thread_index = vm->thread_index;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -572,8 +577,6 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg)
   if (!bibe)
     return -1;
 
-  nat64_session_reset_timeout (ste, ctx->vm);
-
   if (ctx->first_frag)
     {
       udp->dst_port = bibe->in_port;
@@ -614,6 +617,7 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg)
       else
        {
          tcp_header_t *tcp = ip4_next_header (ip4);
+         nat64_tcp_session_set_state (ste, tcp, 0);
          checksum = &tcp->checksum;
          csum = ip_csum_sub_even (*checksum, bibe->out_addr.as_u32);
          csum = ip_csum_sub_even (csum, ste->out_r_addr.as_u32);
@@ -636,6 +640,8 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg)
 
   vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
 
+  nat64_session_reset_timeout (ste, ctx->vm);
+
   return 0;
 }
 
@@ -649,7 +655,7 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 *fragments_to_drop = 0;
   u32 *fragments_to_loopback = 0;
   nat64_main_t *nm = &nat64_main;
-  u32 thread_index = vlib_get_thread_index ();
+  u32 thread_index = vm->thread_index;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -779,7 +785,8 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
 
              if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
                {
-                 if (nat_ip4_reass_add_fragment (reass0, bi0))
+                 if (nat_ip4_reass_add_fragment
+                     (reass0, bi0, &fragments_to_drop))
                    {
                      b0->error = node->errors[NAT64_OUT2IN_ERROR_MAX_FRAG];
                      next0 = NAT64_OUT2IN_NEXT_DROP;
@@ -929,7 +936,7 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 n_left_to_next_worker = 0, *to_next_worker = 0;
   u32 next_worker_index = 0;
   u32 current_worker_index = ~0;
-  u32 thread_index = vlib_get_thread_index ();
+  u32 thread_index = vm->thread_index;
   u32 fq_index;
   u32 to_node_index;
 
@@ -1003,6 +1010,8 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
              current_worker_index = next_worker_index;
            }
 
+         ASSERT (to_next_worker != 0);
+
          /* enqueue to correct worker thread */
          to_next_worker[0] = bi0;
          to_next_worker++;