feature: provide a u16 version of vnet_feature_next
[vpp.git] / src / plugins / acl / dataplane_node.c
index 8f0b0ea..5034f94 100644 (file)
@@ -452,26 +452,19 @@ process_established_session (vlib_main_t * vm, acl_main_t * am,
 #define ACL_PLUGIN_VECTOR_SIZE 4
 #define ACL_PLUGIN_PREFETCH_GAP 3
 
-always_inline uword
-acl_fa_inner_node_fn (vlib_main_t * vm,
-                     vlib_node_runtime_t * node, vlib_frame_t * frame,
-                     int is_ip6, int is_input, int is_l2_path,
-                     int with_stateful_datapath, int node_trace_on,
-                     int reclassify_sessions)
+always_inline void
+acl_fa_node_common_prepare_fn (vlib_main_t * vm,
+                              vlib_node_runtime_t * node,
+                              vlib_frame_t * frame, int is_ip6, int is_input,
+                              int is_l2_path, int with_stateful_datapath)
+       /* , int node_trace_on,
+          int reclassify_sessions) */
 {
   u32 n_left, *from;
-  u32 pkts_exist_session = 0;
-  u32 pkts_new_session = 0;
-  u32 pkts_acl_permit = 0;
-  u32 trace_bitmap = 0;
   acl_main_t *am = &acl_main;
-  vlib_node_runtime_t *error_node;
-  vlib_error_t no_error_existing_session;
-  u64 now = clib_cpu_time_now ();
   uword thread_index = os_get_thread_index ();
   acl_fa_per_worker_data_t *pw = &am->per_worker_data[thread_index];
 
-  u16 *next;
   vlib_buffer_t **b;
   u32 *sw_if_index;
   fa_5tuple_t *fa_5tuple;
@@ -480,15 +473,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm,
 
 
   from = vlib_frame_vector_args (frame);
-  error_node = vlib_node_get_runtime (vm, node->node_index);
-  no_error_existing_session =
-    error_node->errors[ACL_FA_ERROR_ACL_EXIST_SESSION];
-
   vlib_get_buffers (vm, from, pw->bufs, frame->n_vectors);
 
   /* set the initial values for the current buffer the next pointers */
   b = pw->bufs;
-  next = pw->nexts;
   sw_if_index = pw->sw_if_indices;
   fa_5tuple = pw->fa_5tuples;
   hash = pw->hashes;
@@ -550,6 +538,43 @@ acl_fa_inner_node_fn (vlib_main_t * vm,
       sw_if_index += vec_sz;
       hash += vec_sz;
     }
+}
+
+
+always_inline uword
+acl_fa_inner_node_fn (vlib_main_t * vm,
+                     vlib_node_runtime_t * node, vlib_frame_t * frame,
+                     int is_ip6, int is_input, int is_l2_path,
+                     int with_stateful_datapath, int node_trace_on,
+                     int reclassify_sessions)
+{
+  u32 n_left, *from;
+  u32 pkts_exist_session = 0;
+  u32 pkts_new_session = 0;
+  u32 pkts_acl_permit = 0;
+  u32 trace_bitmap = 0;
+  acl_main_t *am = &acl_main;
+  vlib_node_runtime_t *error_node;
+  vlib_error_t no_error_existing_session;
+  u64 now = clib_cpu_time_now ();
+  uword thread_index = os_get_thread_index ();
+  acl_fa_per_worker_data_t *pw = &am->per_worker_data[thread_index];
+
+  u16 *next;
+  vlib_buffer_t **b;
+  u32 *sw_if_index;
+  fa_5tuple_t *fa_5tuple;
+  u64 *hash;
+  /* for the delayed counters */
+  u32 saved_matched_acl_index = 0;
+  u32 saved_matched_ace_index = 0;
+  u32 saved_packet_count = 0;
+  u32 saved_byte_count = 0;
+
+  from = vlib_frame_vector_args (frame);
+  error_node = vlib_node_get_runtime (vm, node->node_index);
+  no_error_existing_session =
+    error_node->errors[ACL_FA_ERROR_ACL_EXIST_SESSION];
 
   b = pw->bufs;
   next = pw->nexts;
@@ -670,13 +695,34 @@ acl_fa_inner_node_fn (vlib_main_t * vm,
                  am->output_lc_index_by_sw_if_index[sw_if_index[0]];
 
              action = 0;       /* deny by default */
-             acl_plugin_match_5tuple_inline (am, lc_index0,
-                                             (fa_5tuple_opaque_t *) &
-                                             fa_5tuple[0], is_ip6, &action,
-                                             &match_acl_pos,
-                                             &match_acl_in_index,
-                                             &match_rule_index,
-                                             &trace_bitmap);
+             int is_match = acl_plugin_match_5tuple_inline (am, lc_index0,
+                                                            (fa_5tuple_opaque_t *) & fa_5tuple[0], is_ip6,
+                                                            &action,
+                                                            &match_acl_pos,
+                                                            &match_acl_in_index,
+                                                            &match_rule_index,
+                                                            &trace_bitmap);
+             if (PREDICT_FALSE
+                 (is_match && am->interface_acl_counters_enabled))
+               {
+                 u32 buf_len = vlib_buffer_length_in_chain (vm, b[0]);
+                 vlib_increment_combined_counter (am->combined_acl_counters +
+                                                  saved_matched_acl_index,
+                                                  thread_index,
+                                                  saved_matched_ace_index,
+                                                  saved_packet_count,
+                                                  saved_byte_count);
+                 saved_matched_acl_index = match_acl_in_index;
+                 saved_matched_ace_index = match_rule_index;
+                 saved_packet_count = 1;
+                 saved_byte_count = buf_len;
+                 /* prefetch the counter that we are going to increment */
+                 vlib_prefetch_combined_counter (am->combined_acl_counters +
+                                                 saved_matched_acl_index,
+                                                 thread_index,
+                                                 saved_matched_ace_index);
+               }
+
              b[0]->error = error_node->errors[action];
 
              if (1 == action)
@@ -732,11 +778,10 @@ acl_fa_inner_node_fn (vlib_main_t * vm,
            }
 
          {
-           u32 next0;
            /* speculatively get the next0 */
-           vnet_feature_next (&next0, b[0]);
+           vnet_feature_next_u16 (&next[0], b[0]);
            /* if the action is not deny - then use that next */
-           next[0] = action ? next0 : 0;
+           next[0] = action ? next[0] : 0;
          }
 
          if (node_trace_on)    // PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
@@ -758,6 +803,16 @@ acl_fa_inner_node_fn (vlib_main_t * vm,
 
   vlib_buffer_enqueue_to_next (vm, node, from, pw->nexts, frame->n_vectors);
 
+  /*
+   * if we were had an acl match then we have a counter to increment.
+   * else it is all zeroes, so this will be harmless.
+   */
+  vlib_increment_combined_counter (am->combined_acl_counters +
+                                  saved_matched_acl_index,
+                                  thread_index,
+                                  saved_matched_ace_index,
+                                  saved_packet_count, saved_byte_count);
+
   vlib_node_increment_counter (vm, node->node_index,
                               ACL_FA_ERROR_ACL_CHECK, frame->n_vectors);
   vlib_node_increment_counter (vm, node->node_index,
@@ -775,33 +830,35 @@ always_inline uword
 acl_fa_outer_node_fn (vlib_main_t * vm,
                      vlib_node_runtime_t * node, vlib_frame_t * frame,
                      int is_ip6, int is_input, int is_l2_path,
-                     int do_reclassify)
+                     int do_stateful_datapath)
 {
   acl_main_t *am = &acl_main;
 
-  if (am->fa_sessions_hash_is_initialized)
+  acl_fa_node_common_prepare_fn (vm, node, frame, is_ip6, is_input,
+                                is_l2_path, do_stateful_datapath);
+
+  if (am->reclassify_sessions)
     {
       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
        return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
-                                    is_l2_path, 1 /* stateful */ ,
+                                    is_l2_path, do_stateful_datapath,
                                     1 /* trace */ ,
-                                    do_reclassify);
+                                    1 /* reclassify */ );
       else
        return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
-                                    is_l2_path, 1 /* stateful */ , 0,
-                                    do_reclassify);
+                                    is_l2_path, do_stateful_datapath, 0,
+                                    1 /* reclassify */ );
     }
   else
     {
       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
        return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
-                                    is_l2_path, 0 /* no state */ ,
+                                    is_l2_path, do_stateful_datapath,
                                     1 /* trace */ ,
-                                    do_reclassify);
+                                    0);
       else
        return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
-                                    is_l2_path, 0 /* no state */ , 0,
-                                    do_reclassify);
+                                    is_l2_path, do_stateful_datapath, 0, 0);
     }
 }
 
@@ -813,7 +870,7 @@ acl_fa_node_fn (vlib_main_t * vm,
   /* select the reclassify/no-reclassify version of the datapath */
   acl_main_t *am = &acl_main;
 
-  if (am->reclassify_sessions)
+  if (am->fa_sessions_hash_is_initialized)
     return acl_fa_outer_node_fn (vm, node, frame, is_ip6, is_input,
                                 is_l2_path, 1);
   else
@@ -821,63 +878,6 @@ acl_fa_node_fn (vlib_main_t * vm,
                                 is_l2_path, 0);
 }
 
-VLIB_NODE_FN (acl_in_l2_ip6_node) (vlib_main_t * vm,
-                                  vlib_node_runtime_t * node,
-                                  vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 1, 1, 1);
-}
-
-VLIB_NODE_FN (acl_in_l2_ip4_node) (vlib_main_t * vm,
-                                  vlib_node_runtime_t * node,
-                                  vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 0, 1, 1);
-}
-
-VLIB_NODE_FN (acl_out_l2_ip6_node) (vlib_main_t * vm,
-                                   vlib_node_runtime_t * node,
-                                   vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 1, 0, 1);
-}
-
-VLIB_NODE_FN (acl_out_l2_ip4_node) (vlib_main_t * vm,
-                                   vlib_node_runtime_t * node,
-                                   vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 0, 0, 1);
-}
-
-/**** L3 processing path nodes ****/
-
-VLIB_NODE_FN (acl_in_fa_ip6_node) (vlib_main_t * vm,
-                                  vlib_node_runtime_t * node,
-                                  vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 1, 1, 0);
-}
-
-VLIB_NODE_FN (acl_in_fa_ip4_node) (vlib_main_t * vm,
-                                  vlib_node_runtime_t * node,
-                                  vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 0, 1, 0);
-}
-
-VLIB_NODE_FN (acl_out_fa_ip6_node) (vlib_main_t * vm,
-                                   vlib_node_runtime_t * node,
-                                   vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 1, 0, 0);
-}
-
-VLIB_NODE_FN (acl_out_fa_ip4_node) (vlib_main_t * vm,
-                                   vlib_node_runtime_t * node,
-                                   vlib_frame_t * frame)
-{
-  return acl_fa_node_fn (vm, node, frame, 0, 0, 0);
-}
 
 static u8 *
 format_fa_5tuple (u8 * s, va_list * args)
@@ -955,6 +955,64 @@ static char *acl_fa_error_strings[] = {
 #undef _
 };
 
+VLIB_NODE_FN (acl_in_l2_ip6_node) (vlib_main_t * vm,
+                                  vlib_node_runtime_t * node,
+                                  vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 1, 1, 1);
+}
+
+VLIB_NODE_FN (acl_in_l2_ip4_node) (vlib_main_t * vm,
+                                  vlib_node_runtime_t * node,
+                                  vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 0, 1, 1);
+}
+
+VLIB_NODE_FN (acl_out_l2_ip6_node) (vlib_main_t * vm,
+                                   vlib_node_runtime_t * node,
+                                   vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 1, 0, 1);
+}
+
+VLIB_NODE_FN (acl_out_l2_ip4_node) (vlib_main_t * vm,
+                                   vlib_node_runtime_t * node,
+                                   vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 0, 0, 1);
+}
+
+/**** L3 processing path nodes ****/
+
+VLIB_NODE_FN (acl_in_fa_ip6_node) (vlib_main_t * vm,
+                                  vlib_node_runtime_t * node,
+                                  vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 1, 1, 0);
+}
+
+VLIB_NODE_FN (acl_in_fa_ip4_node) (vlib_main_t * vm,
+                                  vlib_node_runtime_t * node,
+                                  vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 0, 1, 0);
+}
+
+VLIB_NODE_FN (acl_out_fa_ip6_node) (vlib_main_t * vm,
+                                   vlib_node_runtime_t * node,
+                                   vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 1, 0, 0);
+}
+
+VLIB_NODE_FN (acl_out_fa_ip4_node) (vlib_main_t * vm,
+                                   vlib_node_runtime_t * node,
+                                   vlib_frame_t * frame)
+{
+  return acl_fa_node_fn (vm, node, frame, 0, 0, 0);
+}
+
 VLIB_REGISTER_NODE (acl_in_l2_ip6_node) =
 {
   .name = "acl-plugin-in-ip6-l2",