};
static inline uword
-vnet_policer_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame, vnet_policer_index_t which)
+vnet_policer_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
{
u32 n_left_from, *from, *to_next;
vnet_policer_next_t next_index;
b1 = vlib_get_buffer (vm, bi1);
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- next0 = VNET_POLICER_NEXT_TRANSMIT;
-
sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
- next1 = VNET_POLICER_NEXT_TRANSMIT;
-
-
- if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
- {
- pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
- pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
- }
-
- if (which == VNET_POLICER_INDEX_BY_OPAQUE)
- {
- pi0 = vnet_buffer (b0)->policer.index;
- pi1 = vnet_buffer (b1)->policer.index;
- }
- if (which == VNET_POLICER_INDEX_BY_EITHER)
- {
- pi0 = vnet_buffer (b0)->policer.index;
- pi0 = (pi0 != ~0) ? pi0 :
- pm->policer_index_by_sw_if_index[sw_if_index0];
- pi1 = vnet_buffer (b1)->policer.index;
- pi1 = (pi1 != ~0) ? pi1 :
- pm->policer_index_by_sw_if_index[sw_if_index1];
- }
+ pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
+ pi1 = pm->policer_index_by_sw_if_index[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);
}
-
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
{
if (b0->flags & VLIB_BUFFER_IS_TRACED)
b0 = vlib_get_buffer (vm, bi0);
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- next0 = VNET_POLICER_NEXT_TRANSMIT;
- if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
- pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
+ pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
- if (which == VNET_POLICER_INDEX_BY_OPAQUE)
- pi0 = vnet_buffer (b0)->policer.index;
+ act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
+ POLICE_CONFORM /* no chaining */, true);
- if (which == VNET_POLICER_INDEX_BY_EITHER)
+ if (PREDICT_FALSE (act0 == QOS_ACTION_HANDOFF))
{
- pi0 = vnet_buffer (b0)->policer.index;
- pi0 = (pi0 != ~0) ? pi0 :
- pm->policer_index_by_sw_if_index[sw_if_index0];
+ next0 = VNET_POLICER_NEXT_HANDOFF;
+ vnet_buffer (b0)->policer.index = pi0;
}
-
- act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
- POLICE_CONFORM /* no chaining */ );
-
- if (PREDICT_FALSE (act0 == QOS_ACTION_DROP)) /* drop action */
+ 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 ((node->flags & VLIB_NODE_FLAG_TRACE)
return frame->n_vectors;
}
-VLIB_NODE_FN (policer_by_sw_if_index_node) (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return vnet_policer_inline (vm, node, frame,
- VNET_POLICER_INDEX_BY_SW_IF_INDEX);
-}
-
-#ifndef CLIB_MARCH_VARIANT
-uword
-vnet_policer_by_opaque (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
-}
-
-uword
-vnet_policer_by_either (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
-}
-
-void
-vnet_policer_node_funcs_reference (void)
+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);
}
-#endif /* CLIB_MARCH_VARIANT */
-
-
-#define TEST_CODE 1
-#ifdef TEST_CODE
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (policer_by_sw_if_index_node) = {
- .name = "policer-by-sw-if-index",
+VLIB_REGISTER_NODE (policer_input_node) = {
+ .name = "policer-input",
.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,
-
- /* edit / add dispositions here */
.next_nodes = {
- [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
- [VNET_POLICER_NEXT_DROP] = "error-drop",
- },
+ [VNET_POLICER_NEXT_DROP] = "error-drop",
+ [VNET_POLICER_NEXT_HANDOFF] = "policer-input-handoff",
+ },
};
-/* *INDENT-ON* */
-
-
-#ifndef CLIB_MARCH_VARIANT
-int
-test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
-{
- vnet_policer_main_t *pm = &vnet_policer_main;
- policer_t *template;
- policer_t *policer;
- vnet_hw_interface_t *rxhi;
- uword *p;
-
- rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
-
- /* Make sure caller didn't pass a vlan subif, etc. */
- if (rxhi->sw_if_index != rx_sw_if_index)
- return VNET_API_ERROR_INVALID_SW_IF_INDEX;
- if (is_add)
- {
-
- p = hash_get_mem (pm->policer_config_by_name, config_name);
-
- if (p == 0)
- return -2;
-
- template = pool_elt_at_index (pm->policer_templates, p[0]);
-
- vnet_hw_interface_rx_redirect_to_node
- (pm->vnet_main, rxhi->hw_if_index, policer_by_sw_if_index_node.index);
-
- pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
-
- policer[0] = template[0];
+VNET_FEATURE_INIT (policer_input_node, static) = {
+ .arc_name = "device-input",
+ .node_name = "policer-input",
+ .runs_before = VNET_FEATURES ("ethernet-input"),
+};
- vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
- pm->policer_index_by_sw_if_index[rx_sw_if_index]
- = policer - pm->policers;
- }
- else
- {
- u32 pi;
- vnet_hw_interface_rx_redirect_to_node (pm->vnet_main,
- rxhi->hw_if_index,
- ~0 /* disable */ );
-
- pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
- pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
- pool_put_index (pm->policers, pi);
- }
+static char *policer_input_handoff_error_strings[] = { "congestion drop" };
- return 0;
-}
-
-static clib_error_t *
-test_policer_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+VLIB_NODE_FN (policer_input_handoff_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
- vnet_policer_main_t *pm = &vnet_policer_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- u32 rx_sw_if_index;
- int rv;
- u8 *config_name = 0;
- int rx_set = 0;
- int is_add = 1;
- int is_show = 0;
- clib_error_t *error = NULL;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
- pm->vnet_main, &rx_sw_if_index))
- rx_set = 1;
- else if (unformat (line_input, "show"))
- is_show = 1;
- else if (unformat (line_input, "policer %s", &config_name))
- ;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- break;
- }
-
- if (rx_set == 0)
- {
- error = clib_error_return (0, "interface not set");
- goto done;
- }
-
- if (is_show)
- {
- u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
- policer_t *policer;
- policer = pool_elt_at_index (pm->policers, pi);
-
- vlib_cli_output (vm, "%U", format_policer_instance, policer);
- goto done;
- }
-
- if (is_add && config_name == 0)
- {
- error = clib_error_return (0, "policer config name required");
- goto done;
- }
-
- rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
-
- switch (rv)
- {
- case 0:
- break;
-
- default:
- error = clib_error_return
- (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
- goto done;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
+ return policer_handoff (vm, node, frame, vnet_policer_main.fq_index, ~0);
}
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (test_patch_command, static) = {
- .path = "test policer",
- .short_help =
- "intfc <intfc> policer <policer-config-name> [del]",
- .function = test_policer_command_fn,
-};
-/* *INDENT-ON* */
-#endif /* CLIB_MARCH_VARIANT */
-
-#endif /* TEST_CODE */
+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",
+ },
+};
typedef struct
{
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;
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;