From e5a3ae0179b807efc2202a47e11d698396dd0780 Mon Sep 17 00:00:00 2001 From: Stanislav Zaikin Date: Tue, 5 Apr 2022 19:23:12 +0200 Subject: policer: output interface policer Type: improvement Change-Id: Ibc1b5059ed51c34334340534e9eb68121f556bce Signed-off-by: Stanislav Zaikin --- src/vnet/policer/node_funcs.c | 70 ++++++++++++++++++++++++++++++++++++------ src/vnet/policer/policer.api | 17 ++++++++++ src/vnet/policer/policer.c | 44 ++++++++++++++++++++------ src/vnet/policer/policer.h | 7 +++-- src/vnet/policer/policer_api.c | 26 +++++++++++++++- 5 files changed, 140 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/vnet/policer/node_funcs.c b/src/vnet/policer/node_funcs.c index 21b9393a222..5fa0c8563be 100644 --- a/src/vnet/policer/node_funcs.c +++ b/src/vnet/policer/node_funcs.c @@ -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,11 +120,11 @@ 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 */, true); @@ -206,9 +206,8 @@ 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 */, true); @@ -256,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) = { @@ -279,12 +278,43 @@ 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, ~0); + return policer_handoff (vm, node, frame, vnet_policer_main.fq_index[VLIB_RX], + ~0); } VLIB_REGISTER_NODE (policer_input_handoff_node) = { @@ -301,6 +331,26 @@ VLIB_REGISTER_NODE (policer_input_handoff_node) = { }, }; +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; diff --git a/src/vnet/policer/policer.api b/src/vnet/policer/policer.api index a664ab0be76..f4bf9384f10 100644 --- a/src/vnet/policer/policer.api +++ b/src/vnet/policer/policer.api @@ -52,6 +52,23 @@ autoreply define policer_input bool apply; }; +/** \brief policer output: Apply policer as an output feature. + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param name - policer name + @param sw_if_index - interface to apply the policer + @param apply - Apply/remove +*/ +autoreply define policer_output +{ + u32 client_index; + u32 context; + + string name[64]; + vl_api_interface_index_t sw_if_index; + bool apply; +}; + /** \brief Add/del policer @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/policer/policer.c b/src/vnet/policer/policer.c index 9eb56414561..0513563e1ec 100644 --- a/src/vnet/policer/policer.c +++ b/src/vnet/policer/policer.c @@ -166,7 +166,7 @@ policer_bind_worker (u8 *name, u32 worker, bool bind) } int -policer_input (u8 *name, u32 sw_if_index, bool apply) +policer_input (u8 *name, u32 sw_if_index, vlib_dir_t dir, bool apply) { vnet_policer_main_t *pm = &vnet_policer_main; policer_t *policer; @@ -184,16 +184,26 @@ policer_input (u8 *name, u32 sw_if_index, bool apply) if (apply) { - vec_validate (pm->policer_index_by_sw_if_index, sw_if_index); - pm->policer_index_by_sw_if_index[sw_if_index] = policer_index; + vec_validate (pm->policer_index_by_sw_if_index[dir], sw_if_index); + pm->policer_index_by_sw_if_index[dir][sw_if_index] = policer_index; } else { - pm->policer_index_by_sw_if_index[sw_if_index] = ~0; + pm->policer_index_by_sw_if_index[dir][sw_if_index] = ~0; } - vnet_feature_enable_disable ("device-input", "policer-input", sw_if_index, - apply, 0, 0); + if (dir == VLIB_RX) + { + vnet_feature_enable_disable ("device-input", "policer-input", + sw_if_index, apply, 0, 0); + } + else + { + vnet_feature_enable_disable ("ip4-output", "policer-output", sw_if_index, + apply, 0, 0); + vnet_feature_enable_disable ("ip6-output", "policer-output", sw_if_index, + apply, 0, 0); + } return 0; } @@ -637,6 +647,7 @@ policer_input_command_fn (vlib_main_t *vm, unformat_input_t *input, u8 apply, *name = 0; u32 sw_if_index; int rv; + vlib_dir_t dir = cmd->function_arg; apply = 1; sw_if_index = ~0; @@ -669,7 +680,7 @@ policer_input_command_fn (vlib_main_t *vm, unformat_input_t *input, } else { - rv = policer_input (name, sw_if_index, apply); + rv = policer_input (name, sw_if_index, dir, apply); if (rv) error = clib_error_return (0, "failed: `%d'", rv); @@ -681,33 +692,43 @@ done: return error; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (configure_policer_command, static) = { .path = "configure policer", .short_help = "configure policer name ", .function = policer_add_command_fn, }; + VLIB_CLI_COMMAND (policer_add_command, static) = { .path = "policer add", .short_help = "policer name ", .function = policer_add_command_fn, }; + VLIB_CLI_COMMAND (policer_del_command, static) = { .path = "policer del", .short_help = "policer del name ", .function = policer_del_command_fn, }; + VLIB_CLI_COMMAND (policer_bind_command, static) = { .path = "policer bind", .short_help = "policer bind [unbind] name ", .function = policer_bind_command_fn, }; + VLIB_CLI_COMMAND (policer_input_command, static) = { .path = "policer input", .short_help = "policer input [unapply] name ", .function = policer_input_command_fn, + .function_arg = VLIB_RX, +}; + +VLIB_CLI_COMMAND (policer_output_command, static) = { + .path = "policer output", + .short_help = "policer output [unapply] name ", + .function = policer_input_command_fn, + .function_arg = VLIB_TX, }; -/* *INDENT-ON* */ static clib_error_t * show_policer_command_fn (vlib_main_t * vm, @@ -792,7 +813,10 @@ policer_init (vlib_main_t * vm) pm->vlib_main = vm; pm->vnet_main = vnet_get_main (); pm->log_class = vlib_log_register_class ("policer", 0); - pm->fq_index = vlib_frame_queue_main_init (policer_input_node.index, 0); + pm->fq_index[VLIB_RX] = + vlib_frame_queue_main_init (policer_input_node.index, 0); + pm->fq_index[VLIB_TX] = + vlib_frame_queue_main_init (policer_output_node.index, 0); pm->policer_config_by_name = hash_create_string (0, sizeof (uword)); pm->policer_index_by_name = hash_create_string (0, sizeof (uword)); diff --git a/src/vnet/policer/policer.h b/src/vnet/policer/policer.h index 2687064bf0d..f5b6c0d3b31 100644 --- a/src/vnet/policer/policer.h +++ b/src/vnet/policer/policer.h @@ -39,7 +39,7 @@ typedef struct uword *policer_index_by_name; /* Policer by sw_if_index vector */ - u32 *policer_index_by_sw_if_index; + u32 *policer_index_by_sw_if_index[VLIB_N_RX_TX]; /* convenience */ vlib_main_t *vlib_main; @@ -48,7 +48,7 @@ typedef struct vlib_log_class_t log_class; /* frame queue for thread handoff */ - u32 fq_index; + u32 fq_index[VLIB_N_RX_TX]; u16 msg_id_base; } vnet_policer_main_t; @@ -58,6 +58,7 @@ extern vnet_policer_main_t vnet_policer_main; extern vlib_combined_counter_main_t policer_counters[]; extern vlib_node_registration_t policer_input_node; +extern vlib_node_registration_t policer_output_node; typedef enum { @@ -71,7 +72,7 @@ clib_error_t *policer_add_del (vlib_main_t *vm, u8 *name, qos_pol_cfg_params_st *cfg, u32 *policer_index, u8 is_add); int policer_bind_worker (u8 *name, u32 worker, bool bind); -int policer_input (u8 *name, u32 sw_if_index, bool apply); +int policer_input (u8 *name, u32 sw_if_index, vlib_dir_t dir, bool apply); #endif /* __included_policer_h__ */ diff --git a/src/vnet/policer/policer_api.c b/src/vnet/policer/policer_api.c index 8c958e79676..4f9baa09feb 100644 --- a/src/vnet/policer/policer_api.c +++ b/src/vnet/policer/policer_api.c @@ -120,13 +120,37 @@ vl_api_policer_input_t_handler (vl_api_policer_input_t *mp) sw_if_index = ntohl (mp->sw_if_index); apply = mp->apply; - rv = policer_input (name, sw_if_index, apply); + rv = policer_input (name, sw_if_index, VLIB_RX, apply); vec_free (name); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_POLICER_INPUT_REPLY); } +static void +vl_api_policer_output_t_handler (vl_api_policer_input_t *mp) +{ + vl_api_policer_bind_reply_t *rmp; + u8 *name; + u32 sw_if_index; + u8 apply; + int rv; + + VALIDATE_SW_IF_INDEX (mp); + + name = format (0, "%s", mp->name); + vec_terminate_c_string (name); + + sw_if_index = ntohl (mp->sw_if_index); + apply = mp->apply; + + rv = policer_input (name, sw_if_index, VLIB_TX, apply); + vec_free (name); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_POLICER_OUTPUT_REPLY); +} + static void send_policer_details (u8 *name, qos_pol_cfg_params_st *config, policer_t *templ, vl_api_registration_t *reg, -- cgit 1.2.3-korg