ipsec: huge anti-replay window support
[vpp.git] / src / vnet / policer / node_funcs.c
index 30e5c50..efa2f83 100644 (file)
@@ -68,7 +68,7 @@ static char *vnet_policer_error_strings[] = {
 
 static inline uword
 vnet_policer_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
-                    vlib_frame_t *frame)
+                    vlib_frame_t *frame, vlib_dir_t dir)
 {
   u32 n_left_from, *from, *to_next;
   vnet_policer_next_t next_index;
@@ -120,35 +120,45 @@ vnet_policer_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
          b0 = vlib_get_buffer (vm, bi0);
          b1 = vlib_get_buffer (vm, bi1);
 
-         sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-         sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
+         sw_if_index0 = vnet_buffer (b0)->sw_if_index[dir];
+         sw_if_index1 = vnet_buffer (b1)->sw_if_index[dir];
 
-         pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
-         pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
+         pi0 = pm->policer_index_by_sw_if_index[dir][sw_if_index0];
+         pi1 = pm->policer_index_by_sw_if_index[dir][sw_if_index1];
 
          act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
-                                     POLICE_CONFORM /* no chaining */ );
+                                     POLICE_CONFORM /* no chaining */, true);
 
          act1 = vnet_policer_police (vm, b1, pi1, time_in_policer_periods,
-                                     POLICE_CONFORM /* no chaining */ );
+                                     POLICE_CONFORM /* no chaining */, true);
 
-         if (PREDICT_FALSE (act0 == QOS_ACTION_DROP)) /* drop action */
+         if (PREDICT_FALSE (act0 == QOS_ACTION_HANDOFF))
+           {
+             next0 = VNET_POLICER_NEXT_HANDOFF;
+             vnet_buffer (b0)->policer.index = pi0;
+           }
+         else if (PREDICT_FALSE (act0 == QOS_ACTION_DROP))
            {
              next0 = VNET_POLICER_NEXT_DROP;
              b0->error = node->errors[VNET_POLICER_ERROR_DROP];
            }
-         else                  /* transmit or mark-and-transmit action */
+         else /* transmit or mark-and-transmit action */
            {
              transmitted++;
              vnet_feature_next (&next0, b0);
            }
 
-         if (PREDICT_FALSE (act1 == QOS_ACTION_DROP)) /* drop action */
+         if (PREDICT_FALSE (act1 == QOS_ACTION_HANDOFF))
+           {
+             next1 = VNET_POLICER_NEXT_HANDOFF;
+             vnet_buffer (b1)->policer.index = pi1;
+           }
+         else if (PREDICT_FALSE (act1 == QOS_ACTION_DROP)) /* drop action */
            {
              next1 = VNET_POLICER_NEXT_DROP;
              b1->error = node->errors[VNET_POLICER_ERROR_DROP];
            }
-         else                  /* transmit or mark-and-transmit action */
+         else /* transmit or mark-and-transmit action */
            {
              transmitted++;
              vnet_feature_next (&next1, b1);
@@ -196,19 +206,23 @@ vnet_policer_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
 
          b0 = vlib_get_buffer (vm, bi0);
 
-         sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-
-         pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
+         sw_if_index0 = vnet_buffer (b0)->sw_if_index[dir];
+         pi0 = pm->policer_index_by_sw_if_index[dir][sw_if_index0];
 
          act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
-                                     POLICE_CONFORM /* no chaining */ );
+                                     POLICE_CONFORM /* no chaining */, true);
 
-         if (PREDICT_FALSE (act0 == QOS_ACTION_DROP)) /* drop action */
+         if (PREDICT_FALSE (act0 == QOS_ACTION_HANDOFF))
+           {
+             next0 = VNET_POLICER_NEXT_HANDOFF;
+             vnet_buffer (b0)->policer.index = pi0;
+           }
+         else if (PREDICT_FALSE (act0 == QOS_ACTION_DROP))
            {
              next0 = VNET_POLICER_NEXT_DROP;
              b0->error = node->errors[VNET_POLICER_ERROR_DROP];
            }
-         else                  /* transmit or mark-and-transmit action */
+         else /* transmit or mark-and-transmit action */
            {
              transmitted++;
              vnet_feature_next (&next0, b0);
@@ -241,7 +255,7 @@ vnet_policer_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
 VLIB_NODE_FN (policer_input_node)
 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
 {
-  return vnet_policer_inline (vm, node, frame);
+  return vnet_policer_inline (vm, node, frame, VLIB_RX);
 }
 
 VLIB_REGISTER_NODE (policer_input_node) = {
@@ -254,6 +268,7 @@ VLIB_REGISTER_NODE (policer_input_node) = {
   .n_next_nodes = VNET_POLICER_N_NEXT,
   .next_nodes = {
                 [VNET_POLICER_NEXT_DROP] = "error-drop",
+                [VNET_POLICER_NEXT_HANDOFF] = "policer-input-handoff",
                 },
 };
 
@@ -263,6 +278,79 @@ VNET_FEATURE_INIT (policer_input_node, static) = {
   .runs_before = VNET_FEATURES ("ethernet-input"),
 };
 
+VLIB_NODE_FN (policer_output_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+  return vnet_policer_inline (vm, node, frame, VLIB_TX);
+}
+
+VLIB_REGISTER_NODE (policer_output_node) = {
+  .name = "policer-output",
+  .vector_size = sizeof (u32),
+  .format_trace = format_policer_trace,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+  .n_errors = ARRAY_LEN(vnet_policer_error_strings),
+  .error_strings = vnet_policer_error_strings,
+  .n_next_nodes = VNET_POLICER_N_NEXT,
+  .next_nodes = {
+                [VNET_POLICER_NEXT_DROP] = "error-drop",
+                [VNET_POLICER_NEXT_HANDOFF] = "policer-output-handoff",
+                },
+};
+
+VNET_FEATURE_INIT (policer_output_node, static) = {
+  .arc_name = "ip4-output",
+  .node_name = "policer-output",
+};
+
+VNET_FEATURE_INIT (policer6_output_node, static) = {
+  .arc_name = "ip6-output",
+  .node_name = "policer-output",
+};
+
+static char *policer_input_handoff_error_strings[] = { "congestion drop" };
+
+VLIB_NODE_FN (policer_input_handoff_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+  return policer_handoff (vm, node, frame, vnet_policer_main.fq_index[VLIB_RX],
+                         ~0);
+}
+
+VLIB_REGISTER_NODE (policer_input_handoff_node) = {
+  .name = "policer-input-handoff",
+  .vector_size = sizeof (u32),
+  .format_trace = format_policer_handoff_trace,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+  .n_errors = ARRAY_LEN(policer_input_handoff_error_strings),
+  .error_strings = policer_input_handoff_error_strings,
+
+  .n_next_nodes = 1,
+  .next_nodes = {
+    [0] = "error-drop",
+  },
+};
+
+VLIB_NODE_FN (policer_output_handoff_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+  return policer_handoff (vm, node, frame, vnet_policer_main.fq_index[VLIB_TX],
+                         ~0);
+}
+
+VLIB_REGISTER_NODE (policer_output_handoff_node) = {
+  .name = "policer-output-handoff",
+  .vector_size = sizeof (u32),
+  .format_trace = format_policer_handoff_trace,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+  .n_errors = ARRAY_LEN(policer_input_handoff_error_strings),
+  .error_strings = policer_input_handoff_error_strings,
+
+  .n_next_nodes = 1,
+  .next_nodes = {
+    [0] = "error-drop",
+  },
+};
 typedef struct
 {
   u32 sw_if_index;
@@ -349,9 +437,9 @@ policer_classify_inline (vlib_main_t * vm,
        p2 = vlib_get_buffer (vm, from[2]);
 
        vlib_prefetch_buffer_header (p1, STORE);
-       CLIB_PREFETCH (p1->data, CLIB_CACHE_LINE_BYTES, STORE);
+       clib_prefetch_store (p1->data);
        vlib_prefetch_buffer_header (p2, STORE);
-       CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
+       clib_prefetch_store (p2->data);
       }
 
       bi0 = from[0];
@@ -439,7 +527,7 @@ policer_classify_inline (vlib_main_t * vm,
          u32 table_index0;
          vnet_classify_table_t *t0;
          vnet_classify_entry_t *e0;
-         u64 hash0;
+         u32 hash0;
          u8 *h0;
          u8 act0;
 
@@ -449,7 +537,7 @@ policer_classify_inline (vlib_main_t * vm,
              vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
              vnet_classify_table_t *tp1;
              u32 table_index1;
-             u64 phash1;
+             u32 phash1;
 
              table_index1 = vnet_buffer (p1)->l2_classify.table_index;
 
@@ -496,11 +584,9 @@ policer_classify_inline (vlib_main_t * vm,
 
              if (e0)
                {
-                 act0 = vnet_policer_police (vm,
-                                             b0,
-                                             e0->next_index,
+                 act0 = vnet_policer_police (vm, b0, e0->next_index,
                                              time_in_policer_periods,
-                                             e0->opaque_index);
+                                             e0->opaque_index, false);
                  if (PREDICT_FALSE (act0 == QOS_ACTION_DROP))
                    {
                      next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
@@ -530,11 +616,9 @@ policer_classify_inline (vlib_main_t * vm,
                        vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
                      if (e0)
                        {
-                         act0 = vnet_policer_police (vm,
-                                                     b0,
-                                                     e0->next_index,
+                         act0 = vnet_policer_police (vm, b0, e0->next_index,
                                                      time_in_policer_periods,
-                                                     e0->opaque_index);
+                                                     e0->opaque_index, false);
                          if (PREDICT_FALSE (act0 == QOS_ACTION_DROP))
                            {
                              next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;