From 3f40755749b07e5a936ad6d15622e371e7e5c25e Mon Sep 17 00:00:00 2001 From: Maxime Peim Date: Mon, 3 Jul 2023 17:45:51 +0200 Subject: classify: add bpf support to pcap classifier Type: feature Change-Id: I28fb38e49c89f4c4d4cc58c1a5c0aa8502678472 Signed-off-by: Maxime Peim --- src/vlib/trace.c | 2 +- src/vlib/trace.h | 2 +- src/vnet/classify/pcap_classify.h | 6 ++-- src/vnet/interface.api | 14 +++++++++ src/vnet/interface_api.c | 27 ++++++++++++++++ src/vnet/interface_cli.c | 66 +++++++++++++++++++++++++++++++++++++++ src/vnet/interface_test.c | 12 +++++++ src/vnet/misc.c | 3 ++ src/vnet/vnet.h | 1 + 9 files changed, 128 insertions(+), 5 deletions(-) diff --git a/src/vlib/trace.c b/src/vlib/trace.c index c6a0ef7ec0d..96da4975bc2 100644 --- a/src/vlib/trace.c +++ b/src/vlib/trace.c @@ -635,7 +635,7 @@ vlib_is_packet_traced_function_from_name (const char *name) return reg->function; } -static vlib_is_packet_traced_fn_t * +vlib_is_packet_traced_fn_t * vlib_is_packet_traced_default_function () { vlib_trace_filter_function_registration_t *reg = diff --git a/src/vlib/trace.h b/src/vlib/trace.h index 46256ce4e9e..196c691ece6 100644 --- a/src/vlib/trace.h +++ b/src/vlib/trace.h @@ -146,7 +146,7 @@ extern vlib_trace_filter_main_t vlib_trace_filter_main; vlib_is_packet_traced_fn_t * vlib_is_packet_traced_function_from_name (const char *name); - +vlib_is_packet_traced_fn_t *vlib_is_packet_traced_default_function (); void trace_apply_filter (struct vlib_main_t *vm); int trace_time_cmp (void *a1, void *a2); void vlib_trace_stop_and_clear (void); diff --git a/src/vnet/classify/pcap_classify.h b/src/vnet/classify/pcap_classify.h index e079816f62c..a4ebcd1241c 100644 --- a/src/vnet/classify/pcap_classify.h +++ b/src/vnet/classify/pcap_classify.h @@ -47,11 +47,11 @@ vnet_is_packet_pcaped (vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index) return 0; /* wrong error */ if (filter_classify_table_index != ~0 && - vnet_is_packet_traced_inline (b, filter_classify_table_index, - 0 /* full classify */) != 1) + pp->current_filter_function (b, filter_classify_table_index, + 0 /* full classify */) != 1) return 0; /* not matching the filter, skip */ - return 1; /* success */ + return 1; } /* diff --git a/src/vnet/interface.api b/src/vnet/interface.api index 4d28332a639..eea86aa1ac8 100644 --- a/src/vnet/interface.api +++ b/src/vnet/interface.api @@ -733,6 +733,20 @@ autoreply define collect_detailed_interface_stats bool enable_disable; }; +/** \brief pcap_set_filter_function + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param filter_function_name - the name of the filter function + to set for pcap capture +*/ +autoreply define pcap_set_filter_function +{ + u32 client_index; + u32 context; + + string filter_function_name[]; +}; + /** \brief pcap_trace_on @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 5b48fea02eb..01f2fd0c8b2 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -1603,6 +1603,33 @@ static void REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY); } +static void +vl_api_pcap_set_filter_function_t_handler ( + vl_api_pcap_set_filter_function_t *mp) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_pcap_t *pp = &vnm->pcap; + vl_api_pcap_set_filter_function_reply_t *rmp; + unformat_input_t input = { 0 }; + vlib_is_packet_traced_fn_t *f; + char *filter_name; + int rv = 0; + filter_name = vl_api_from_api_to_new_c_string (&mp->filter_function_name); + unformat_init_cstring (&input, filter_name); + if (unformat (&input, "%U", unformat_vlib_trace_filter_function, &f) == 0) + { + rv = -1; + goto done; + } + + pp->current_filter_function = f; + +done: + unformat_free (&input); + vec_free (filter_name); + REPLY_MACRO (VL_API_PCAP_SET_FILTER_FUNCTION_REPLY); +} + static void vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp) { diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c index 627af6f2b0d..74ac32522d7 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -2439,6 +2439,72 @@ VLIB_CLI_COMMAND (pcap_tx_trace_command, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +set_pcap_filter_function (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_pcap_t *pp = &vnet_get_main ()->pcap; + unformat_input_t _line_input, *line_input = &_line_input; + vlib_is_packet_traced_fn_t *res = 0; + clib_error_t *error = 0; + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != (uword) UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_vlib_trace_filter_function, + &res)) + ; + else + { + error = clib_error_create ( + "expected valid trace filter function, got `%U'", + format_unformat_error, line_input); + goto done; + } + } + pp->current_filter_function = res; + +done: + unformat_free (line_input); + + return error; +} + +VLIB_CLI_COMMAND (set_pcap_filter_function_cli, static) = { + .path = "set pcap filter function", + .short_help = "set pcap filter function ", + .function = set_pcap_filter_function, +}; + +static clib_error_t * +show_pcap_filter_function (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_pcap_t *pp = &vnet_get_main ()->pcap; + vlib_trace_filter_main_t *tfm = &vlib_trace_filter_main; + vlib_is_packet_traced_fn_t *current_trace_filter_fn = + pp->current_filter_function; + vlib_trace_filter_function_registration_t *reg = + tfm->trace_filter_registration; + + while (reg) + { + vlib_cli_output (vm, "%sname:%s description: %s priority: %u", + reg->function == current_trace_filter_fn ? "(*) " : "", + reg->name, reg->description, reg->priority); + reg = reg->next; + } + return 0; +} + +VLIB_CLI_COMMAND (show_pcap_filter_function_cli, static) = { + .path = "show pcap filter function", + .short_help = "show pcap filter function", + .function = show_pcap_filter_function, +}; + static clib_error_t * set_interface_name (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) diff --git a/src/vnet/interface_test.c b/src/vnet/interface_test.c index cc406bef23d..2d0c0ee81d1 100644 --- a/src/vnet/interface_test.c +++ b/src/vnet/interface_test.c @@ -1283,6 +1283,18 @@ api_sw_interface_set_interface_name (vat_main_t *vam) return -1; } +static int +api_pcap_set_filter_function (vat_main_t *vam) +{ + vl_api_pcap_set_filter_function_t *mp; + int ret; + + M (PCAP_SET_FILTER_FUNCTION, mp); + S (mp); + W (ret); + return ret; +} + static int api_pcap_trace_on (vat_main_t *vam) { diff --git a/src/vnet/misc.c b/src/vnet/misc.c index 18d4651cff3..d1dcd6ecb23 100644 --- a/src/vnet/misc.c +++ b/src/vnet/misc.c @@ -86,6 +86,9 @@ vnet_main_init (vlib_main_t * vm) vnm->local_interface_hw_if_index = hw_if_index; vnm->local_interface_sw_if_index = hw->sw_if_index; + vnm->pcap.current_filter_function = + vlib_is_packet_traced_default_function (); + return 0; } diff --git a/src/vnet/vnet.h b/src/vnet/vnet.h index 227fa5be30c..54988aec667 100644 --- a/src/vnet/vnet.h +++ b/src/vnet/vnet.h @@ -71,6 +71,7 @@ typedef struct u32 pcap_sw_if_index; pcap_main_t pcap_main; u32 filter_classify_table_index; + vlib_is_packet_traced_fn_t *current_filter_function; vlib_error_t pcap_error_index; } vnet_pcap_t; -- cgit 1.2.3-korg