misc: move to new pool_foreach macros
[vpp.git] / src / vnet / ip / reass / ip6_sv_reass.c
index 0837f06..c5c84e5 100644 (file)
@@ -96,6 +96,9 @@ typedef struct
   bool is_complete;
   // ip protocol
   u8 ip_proto;
+  u8 icmp_type_or_tcp_flags;
+  u32 tcp_ack_number;
+  u32 tcp_seq_number;
   // l4 src port
   u16 l4_src_port;
   // l4 dst port
@@ -170,6 +173,7 @@ typedef enum
   REASS_FRAGMENT_CACHE,
   REASS_FINISH,
   REASS_FRAGMENT_FORWARD,
+  REASS_PASSTHROUGH,
 } ip6_sv_reass_trace_operation_e;
 
 typedef struct
@@ -188,7 +192,10 @@ format_ip6_sv_reass_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   ip6_sv_reass_trace_t *t = va_arg (*args, ip6_sv_reass_trace_t *);
-  s = format (s, "reass id: %u, op id: %u ", t->reass_id, t->op_id);
+  if (REASS_PASSTHROUGH != t->action)
+    {
+      s = format (s, "reass id: %u, op id: %u ", t->reass_id, t->op_id);
+    }
   switch (t->action)
     {
     case REASS_FRAGMENT_CACHE:
@@ -206,6 +213,9 @@ format_ip6_sv_reass_trace (u8 * s, va_list * args)
                t->ip_proto, clib_net_to_host_u16 (t->l4_src_port),
                clib_net_to_host_u16 (t->l4_dst_port));
       break;
+    case REASS_PASSTHROUGH:
+      s = format (s, "[not-fragmented]");
+      break;
     }
   return s;
 }
@@ -219,13 +229,16 @@ ip6_sv_reass_add_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
 {
   vlib_buffer_t *b = vlib_get_buffer (vm, bi);
   ip6_sv_reass_trace_t *t = vlib_add_trace (vm, node, b, sizeof (t[0]));
-  t->reass_id = reass->id;
+  if (reass)
+    {
+      t->reass_id = reass->id;
+      t->op_id = reass->trace_op_counter;
+      ++reass->trace_op_counter;
+    }
   t->action = action;
-  t->op_id = reass->trace_op_counter;
   t->ip_proto = ip_proto;
   t->l4_src_port = l4_src_port;
   t->l4_dst_port = l4_dst_port;
-  ++reass->trace_op_counter;
 #if 0
   static u8 *s = NULL;
   s = format (s, "%U", format_ip6_sv_reass_trace, NULL, NULL, t);
@@ -290,10 +303,9 @@ ip6_sv_reass_find_or_create (vlib_main_t * vm, vlib_node_runtime_t * node,
                             u8 * do_handoff)
 {
   ip6_sv_reass_t *reass = NULL;
-  f64 now = vlib_time_now (rm->vlib_main);
+  f64 now = vlib_time_now (vm);
 
-  if (!clib_bihash_search_48_8
-      (&rm->hash, (clib_bihash_kv_48_8_t *) kv, (clib_bihash_kv_48_8_t *) kv))
+  if (!clib_bihash_search_48_8 (&rm->hash, &kv->kv, &kv->kv))
     {
       if (vm->thread_index != kv->v.thread_index)
        {
@@ -317,7 +329,7 @@ ip6_sv_reass_find_or_create (vlib_main_t * vm, vlib_node_runtime_t * node,
 
   if (rt->reass_n >= rm->max_reass_n)
     {
-      reass = pool_elt_at_index (rt->pool, rt->lru_last);
+      reass = pool_elt_at_index (rt->pool, rt->lru_first);
       ip6_sv_reass_free (vm, rm, rt, reass);
     }
 
@@ -342,17 +354,17 @@ ip6_sv_reass_find_or_create (vlib_main_t * vm, vlib_node_runtime_t * node,
       rt->lru_first = rt->lru_last = reass - rt->pool;
     }
 
-  reass->key.as_u64[0] = ((clib_bihash_kv_48_8_t *) kv)->key[0];
-  reass->key.as_u64[1] = ((clib_bihash_kv_48_8_t *) kv)->key[1];
-  reass->key.as_u64[2] = ((clib_bihash_kv_48_8_t *) kv)->key[2];
-  reass->key.as_u64[3] = ((clib_bihash_kv_48_8_t *) kv)->key[3];
-  reass->key.as_u64[4] = ((clib_bihash_kv_48_8_t *) kv)->key[4];
-  reass->key.as_u64[5] = ((clib_bihash_kv_48_8_t *) kv)->key[5];
+  reass->key.as_u64[0] = kv->kv.key[0];
+  reass->key.as_u64[1] = kv->kv.key[1];
+  reass->key.as_u64[2] = kv->kv.key[2];
+  reass->key.as_u64[3] = kv->kv.key[3];
+  reass->key.as_u64[4] = kv->kv.key[4];
+  reass->key.as_u64[5] = kv->kv.key[5];
   kv->v.reass_index = (reass - rt->pool);
   kv->v.thread_index = vm->thread_index;
   reass->last_heard = now;
 
-  if (clib_bihash_add_del_48_8 (&rm->hash, (clib_bihash_kv_48_8_t *) kv, 1))
+  if (clib_bihash_add_del_48_8 (&rm->hash, &kv->kv, 1))
     {
       ip6_sv_reass_free (vm, rm, rt, reass);
       reass = NULL;
@@ -391,18 +403,13 @@ ip6_sv_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node,
   fvnb->ip.reass.next_range_bi = ~0;
   if (0 == fragment_first)
     {
-      ip6_ext_header_t *ext_hdr = (void *) frag_hdr;
-      while (ip6_ext_hdr (ext_hdr->next_hdr)
-            && vlib_object_within_buffer_data (vm, fb, ext_hdr,
-                                               ext_hdr->n_data_u64s * 8))
-       {
-         ext_hdr = ip6_ext_next_header (ext_hdr);
-       }
-      reass->ip_proto = ext_hdr->next_hdr;
-      reass->l4_src_port = ip6_get_port (fip, 1, fb->current_length);
-      reass->l4_dst_port = ip6_get_port (fip, 0, fb->current_length);
-      if (!reass->l4_src_port || !reass->l4_dst_port)
+      if (!ip6_get_port
+         (vm, fb, fip, fb->current_length, &reass->ip_proto,
+          &reass->l4_src_port, &reass->l4_dst_port,
+          &reass->icmp_type_or_tcp_flags, &reass->tcp_ack_number,
+          &reass->tcp_seq_number))
        return IP6_SV_REASS_RC_UNSUPP_IP_PROTO;
+
       reass->is_complete = true;
       vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
       if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -538,12 +545,32 @@ ip6_sv_reassembly_inline (vlib_main_t * vm,
          if (!frag_hdr)
            {
              // this is a regular packet - no fragmentation
-             vnet_buffer (b0)->ip.reass.ip_proto = ip0->protocol;
-             vnet_buffer (b0)->ip.reass.l4_src_port =
-               ip6_get_port (ip0, 1, b0->current_length);
-             vnet_buffer (b0)->ip.reass.l4_dst_port =
-               ip6_get_port (ip0, 0, b0->current_length);
+             if (!ip6_get_port
+                 (vm, b0, ip0, b0->current_length,
+                  &(vnet_buffer (b0)->ip.reass.ip_proto),
+                  &(vnet_buffer (b0)->ip.reass.l4_src_port),
+                  &(vnet_buffer (b0)->ip.reass.l4_dst_port),
+                  &(vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags),
+                  &(vnet_buffer (b0)->ip.reass.tcp_ack_number),
+                  &(vnet_buffer (b0)->ip.reass.tcp_seq_number)))
+               {
+                 error0 = IP6_ERROR_REASS_UNSUPP_IP_PROTO;
+                 b0->error = node->errors[error0];
+                 next0 = IP6_SV_REASSEMBLY_NEXT_DROP;
+                 goto packet_enqueue;
+               }
+             vnet_buffer (b0)->ip.reass.is_non_first_fragment = 0;
              next0 = IP6_SV_REASSEMBLY_NEXT_INPUT;
+             if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+               {
+                 ip6_sv_reass_add_trace (vm, node, rm, NULL, bi0,
+                                         REASS_PASSTHROUGH,
+                                         vnet_buffer (b0)->ip.reass.ip_proto,
+                                         vnet_buffer (b0)->ip.
+                                         reass.l4_src_port,
+                                         vnet_buffer (b0)->ip.
+                                         reass.l4_dst_port);
+               }
              goto packet_enqueue;
            }
          vnet_buffer (b0)->ip.reass.ip6_frag_hdr_offset =
@@ -596,16 +623,24 @@ ip6_sv_reassembly_inline (vlib_main_t * vm,
            {
              next0 = IP6_SV_REASSEMBLY_NEXT_DROP;
              error0 = IP6_ERROR_REASS_LIMIT_REACHED;
+             b0->error = node->errors[error0];
              goto packet_enqueue;
            }
 
          if (reass->is_complete)
            {
+             vnet_buffer (b0)->ip.reass.is_non_first_fragment =
+               ! !ip6_frag_hdr_offset (frag_hdr);
              vnet_buffer (b0)->ip.reass.ip_proto = reass->ip_proto;
+             vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags =
+               reass->icmp_type_or_tcp_flags;
+             vnet_buffer (b0)->ip.reass.tcp_ack_number =
+               reass->tcp_ack_number;
+             vnet_buffer (b0)->ip.reass.tcp_seq_number =
+               reass->tcp_seq_number;
              vnet_buffer (b0)->ip.reass.l4_src_port = reass->l4_src_port;
              vnet_buffer (b0)->ip.reass.l4_dst_port = reass->l4_dst_port;
              next0 = IP6_SV_REASSEMBLY_NEXT_INPUT;
-             error0 = IP6_ERROR_NONE;
              if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
                {
                  ip6_sv_reass_add_trace (vm, node, rm, reass, bi0,
@@ -645,8 +680,6 @@ ip6_sv_reassembly_inline (vlib_main_t * vm,
              break;
            }
 
-         b0->error = node->errors[error0];
-
          if (reass->is_complete)
            {
              u32 idx;
@@ -668,7 +701,18 @@ ip6_sv_reassembly_inline (vlib_main_t * vm,
                  {
                    vnet_feature_next (&next0, b0);
                  }
+               frag_hdr =
+                 vlib_buffer_get_current (b0) +
+                 vnet_buffer (b0)->ip.reass.ip6_frag_hdr_offset;
+               vnet_buffer (b0)->ip.reass.is_non_first_fragment =
+                 ! !ip6_frag_hdr_offset (frag_hdr);
                vnet_buffer (b0)->ip.reass.ip_proto = reass->ip_proto;
+               vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags =
+                 reass->icmp_type_or_tcp_flags;
+               vnet_buffer (b0)->ip.reass.tcp_ack_number =
+                 reass->tcp_ack_number;
+               vnet_buffer (b0)->ip.reass.tcp_seq_number =
+                 reass->tcp_seq_number;
                vnet_buffer (b0)->ip.reass.l4_src_port = reass->l4_src_port;
                vnet_buffer (b0)->ip.reass.l4_dst_port = reass->l4_dst_port;
                if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -987,13 +1031,13 @@ ip6_sv_reass_walk_expired (vlib_main_t * vm,
 
          vec_reset_length (pool_indexes_to_free);
           /* *INDENT-OFF* */
-          pool_foreach_index (index, rt->pool, ({
+          pool_foreach_index (index, rt->pool)  {
                                 reass = pool_elt_at_index (rt->pool, index);
                                 if (now > reass->last_heard + rm->timeout)
                                   {
                                     vec_add1 (pool_indexes_to_free, index);
                                   }
-                              }));
+                              }
           /* *INDENT-ON* */
          int *i;
           /* *INDENT-OFF* */
@@ -1094,9 +1138,9 @@ show_ip6_sv_reass (vlib_main_t * vm, unformat_input_t * input,
       if (details)
        {
           /* *INDENT-OFF* */
-          pool_foreach (reass, rt->pool, {
+          pool_foreach (reass, rt->pool) {
             vlib_cli_output (vm, "%U", format_ip6_sv_reass, vm, reass);
-          });
+          }
           /* *INDENT-ON* */
        }
       sum_reass_n += rt->reass_n;
@@ -1105,8 +1149,15 @@ show_ip6_sv_reass (vlib_main_t * vm, unformat_input_t * input,
   vlib_cli_output (vm, "---------------------");
   vlib_cli_output (vm, "Current IP6 reassemblies count: %lu\n",
                   (long unsigned) sum_reass_n);
-  vlib_cli_output (vm, "Maximum configured concurrent IP6 reassemblies per "
-                  "worker-thread: %lu\n", (long unsigned) rm->max_reass_n);
+  vlib_cli_output (vm,
+                  "Maximum configured concurrent shallow virtual IP6 reassemblies per worker-thread: %lu\n",
+                  (long unsigned) rm->max_reass_n);
+  vlib_cli_output (vm,
+                  "Maximum configured shallow virtual IP6 reassembly timeout: %lums\n",
+                  (long unsigned) rm->timeout_ms);
+  vlib_cli_output (vm,
+                  "Maximum configured shallow virtual IP6 reassembly expire walk interval: %lums\n",
+                  (long unsigned) rm->expire_walk_interval_ms);
   vlib_cli_output (vm, "Buffers in use: %lu\n",
                   (long unsigned) sum_buffers_n);
   return 0;
@@ -1124,9 +1175,8 @@ VLIB_CLI_COMMAND (show_ip6_sv_reassembly_cmd, static) = {
 vnet_api_error_t
 ip6_sv_reass_enable_disable (u32 sw_if_index, u8 enable_disable)
 {
-  return vnet_feature_enable_disable ("ip6-unicast",
-                                     "ip6-sv-reassembly-feature",
-                                     sw_if_index, enable_disable, 0, 0);
+  return ip6_sv_reass_enable_disable_with_refcnt (sw_if_index,
+                                                 enable_disable);
 }
 #endif /* CLIB_MARCH_VARIANT */