From 7c5a3536ce4c2fd4157c466367c495cefecaa52e Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Wed, 4 Dec 2019 17:19:12 -0500 Subject: classify: vpp packet tracer support Configure n-tuple classifier filters which apply to the vpp packet tracer. Update the documentation to reflect the new feature. Add a test vector. Type: feature Signed-off-by: Dave Barach Change-Id: Iefa911716c670fc12e4825b937b62044433fec36 (cherry picked from commit 87d24db65facb89ca524c951b8379ca2ec4dbc7a) --- src/vlib/main.h | 10 +++ src/vlib/trace.c | 33 ++++++++- src/vlib/trace_funcs.h | 16 ++++ src/vnet/classify/vnet_classify.c | 151 ++++++++++++++++++++++++++++++-------- 4 files changed, 177 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/vlib/main.h b/src/vlib/main.h index e230ddf8419..af6539efc75 100644 --- a/src/vlib/main.h +++ b/src/vlib/main.h @@ -73,6 +73,13 @@ typedef struct u32 filter_classify_table_index; } vnet_pcap_t; +typedef struct +{ + u8 trace_filter_enable; + u32 trace_classify_table_index; + u32 trace_filter_set_index; +} vlib_trace_filter_t; + typedef struct vlib_main_t { CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); @@ -165,6 +172,9 @@ typedef struct vlib_main_t /* pcap rx / tx tracing */ vnet_pcap_t pcap; + /* Packet trace capture filter */ + vlib_trace_filter_t trace_filter; + /* Error handling. */ vlib_error_main_t error_main; diff --git a/src/vlib/trace.c b/src/vlib/trace.c index 530598d349d..7ee1b63f07e 100644 --- a/src/vlib/trace.c +++ b/src/vlib/trace.c @@ -351,6 +351,13 @@ VLIB_CLI_COMMAND (show_trace_cli,static) = { }; /* *INDENT-ON* */ +int vlib_enable_disable_pkt_trace_filter (int enable) __attribute__ ((weak)); +int +vlib_enable_disable_pkt_trace_filter (int enable) +{ + return 0; +} + static clib_error_t * cli_add_trace_buffer (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -361,6 +368,7 @@ cli_add_trace_buffer (vlib_main_t * vm, vlib_trace_node_t *tn; u32 node_index, add; u8 verbose = 0; + int filter = 0; clib_error_t *error = 0; if (!unformat_user (input, unformat_line_input, line_input)) @@ -376,6 +384,8 @@ cli_add_trace_buffer (vlib_main_t * vm, ; else if (unformat (line_input, "verbose")) verbose = 1; + else if (unformat (line_input, "filter")) + filter = 1; else { error = clib_error_create ("expected NODE COUNT, got `%U'", @@ -395,6 +405,15 @@ cli_add_trace_buffer (vlib_main_t * vm, goto done; } + if (filter) + { + if (vlib_enable_disable_pkt_trace_filter (1 /* enable */ )) + { + error = clib_error_create ("No packet trace filter configured..."); + goto done; + } + } + /* *INDENT-OFF* */ foreach_vlib_main (( { @@ -421,7 +440,6 @@ VLIB_CLI_COMMAND (add_trace_cli,static) = { }; /* *INDENT-ON* */ - /* * Configure a filter for packet traces. * @@ -523,6 +541,7 @@ static clib_error_t * cli_clear_trace_buffer (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + vlib_enable_disable_pkt_trace_filter (0 /* enable */ ); clear_trace_buffer (); return 0; } @@ -541,6 +560,18 @@ vlib_trace_cli_reference (void) { } +int +vnet_is_packet_traced (vlib_buffer_t * b, + u32 classify_table_index, int func) +__attribute__ ((weak)); + +int +vnet_is_packet_traced (vlib_buffer_t * b, u32 classify_table_index, int func) +{ + clib_warning ("BUG: STUB called"); + return 1; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlib/trace_funcs.h b/src/vlib/trace_funcs.h index 257c3a3a4ff..4261f675aec 100644 --- a/src/vlib/trace_funcs.h +++ b/src/vlib/trace_funcs.h @@ -61,6 +61,9 @@ vlib_add_trace (vlib_main_t * vm, ASSERT (vnet_trace_dummy); + if (PREDICT_FALSE ((b->flags & VLIB_BUFFER_IS_TRACED) == 0)) + return vnet_trace_dummy; + if (PREDICT_FALSE (tm->add_trace_callback != 0)) { return tm->add_trace_callback ((struct vlib_main_t *) vm, @@ -118,6 +121,9 @@ vlib_trace_next_frame (vlib_main_t * vm, } void trace_apply_filter (vlib_main_t * vm); +int vnet_is_packet_traced (vlib_buffer_t * b, + u32 classify_table_index, int func); + /* Mark buffer as traced and allocate trace buffer. */ always_inline void @@ -131,6 +137,16 @@ vlib_trace_buffer (vlib_main_t * vm, if (PREDICT_FALSE (tm->trace_enable == 0)) return; + /* Classifier filter in use? */ + if (PREDICT_FALSE (vlib_global_main.trace_filter.trace_filter_enable)) + { + /* See if we're supposed to trace this packet... */ + if (vnet_is_packet_traced + (b, vlib_global_main.trace_filter.trace_classify_table_index, + 0 /* full classify */ ) != 1) + return; + } + /* * Apply filter to existing traces to keep number of allocated traces low. * Performed each time around the main loop. diff --git a/src/vnet/classify/vnet_classify.c b/src/vnet/classify/vnet_classify.c index 938f583ef57..3d338d15d07 100755 --- a/src/vnet/classify/vnet_classify.c +++ b/src/vnet/classify/vnet_classify.c @@ -19,6 +19,7 @@ #include /* for L2_INPUT_CLASSIFY_NEXT_xxx */ #include #include +#include /** * @file @@ -1692,12 +1693,14 @@ classify_filter_command_fn (vlib_main_t * vm, u32 current_data_flag = 0; int current_data_offset = 0; u32 sw_if_index = ~0; + int pkt_trace = 0; int i; vnet_classify_table_t *t; u8 *mask = 0; vnet_classify_main_t *cm = &vnet_classify_main; int rv = 0; vnet_classify_filter_set_t *set = 0; + u32 set_index = ~0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -1705,6 +1708,8 @@ classify_filter_command_fn (vlib_main_t * vm, is_add = 0; else if (unformat (input, "pcap %=", &sw_if_index, 0)) ; + else if (unformat (input, "trace")) + pkt_trace = 1; else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; @@ -1720,6 +1725,9 @@ classify_filter_command_fn (vlib_main_t * vm, break; } + if (sw_if_index == 0) + return clib_error_return (0, "Local interface not supported..."); + if (is_add && mask == 0 && table_index == ~0) return clib_error_return (0, "Mask required"); @@ -1729,18 +1737,25 @@ classify_filter_command_fn (vlib_main_t * vm, if (is_add && match == ~0 && table_index == ~0) return clib_error_return (0, "match count required"); - if (sw_if_index == ~0) - return clib_error_return (0, "Must specify pcap or interface..."); + if (sw_if_index == ~0 && pkt_trace == 0) + return clib_error_return (0, "Must specify trace, pcap or interface..."); + + if (pkt_trace && sw_if_index != ~0) + return clib_error_return (0, "Packet trace filter is per-system"); if (!is_add) { - u32 set_index = 0; - if (sw_if_index < vec_len (cm->filter_set_by_sw_if_index)) + if (pkt_trace) + set_index = vlib_global_main.trace_filter.trace_filter_set_index; + else if (sw_if_index < vec_len (cm->filter_set_by_sw_if_index)) set_index = cm->filter_set_by_sw_if_index[sw_if_index]; - if (set_index == 0) + if (set_index == ~0) { + if (pkt_trace) + return clib_error_return (0, + "No pkt trace classify filter set..."); if (sw_if_index == 0) return clib_error_return (0, "No pcap classify filter set..."); else @@ -1759,27 +1774,36 @@ classify_filter_command_fn (vlib_main_t * vm, table_index = set->table_indices[0]; vec_reset_length (set->table_indices); pool_put (cm->filter_sets, set); - cm->filter_set_by_sw_if_index[sw_if_index] = 0; - if (sw_if_index > 0) + if (pkt_trace) { - vnet_hw_interface_t *hi = - vnet_get_sup_hw_interface (vnm, sw_if_index); - hi->trace_classify_table_index = ~0; + vlib_global_main.trace_filter.trace_filter_set_index = ~0; + vlib_global_main.trace_filter.trace_classify_table_index = ~0; + } + else + { + cm->filter_set_by_sw_if_index[sw_if_index] = ~0; + if (sw_if_index > 0) + { + vnet_hw_interface_t *hi = + vnet_get_sup_hw_interface (vnm, sw_if_index); + hi->trace_classify_table_index = ~0; + } } } } if (is_add) { - u32 set_index = 0; - - if (sw_if_index < vec_len (cm->filter_set_by_sw_if_index)) + if (pkt_trace) + set_index = vlib_global_main.trace_filter.trace_filter_set_index; + else if (sw_if_index < vec_len (cm->filter_set_by_sw_if_index)) set_index = cm->filter_set_by_sw_if_index[sw_if_index]; /* Do we have a filter set for this intfc / pcap yet? */ - if (set_index == 0) + if (set_index == ~0) { pool_get (cm->filter_sets, set); + set_index = set - cm->filter_sets; set->refcnt = 1; } else @@ -1826,11 +1850,18 @@ classify_filter_command_fn (vlib_main_t * vm, /* Remember the table */ vec_add1 (set->table_indices, table_index); - vec_validate_init_empty (cm->filter_set_by_sw_if_index, sw_if_index, 0); - cm->filter_set_by_sw_if_index[sw_if_index] = set - cm->filter_sets; + + if (pkt_trace) + vlib_global_main.trace_filter.trace_filter_set_index = set_index; + else + { + vec_validate_init_empty (cm->filter_set_by_sw_if_index, sw_if_index, + ~0); + cm->filter_set_by_sw_if_index[sw_if_index] = set - cm->filter_sets; + } /* Put top table index where device drivers can find them */ - if (sw_if_index > 0) + if (sw_if_index > 0 && pkt_trace == 0) { vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); ASSERT (vec_len (set->table_indices) > 0); @@ -1877,10 +1908,34 @@ found_table: return 0; } +/** Enable / disable packet trace filter */ +int +vlib_enable_disable_pkt_trace_filter (int enable) +{ + if (enable) + { + vnet_classify_main_t *cm = &vnet_classify_main; + vnet_classify_filter_set_t *set; + u32 set_index = vlib_global_main.trace_filter.trace_filter_set_index; + + if (set_index == ~0) + return -1; + + set = pool_elt_at_index (cm->filter_sets, set_index); + vlib_global_main.trace_filter.trace_classify_table_index = + set->table_indices[0]; + vlib_global_main.trace_filter.trace_filter_enable = 1; + } + else + { + vlib_global_main.trace_filter.trace_filter_enable = 0; + } + return 0; +} + /*? * Construct an arbitrary set of packet classifier tables for use with - * "pcap rx | tx trace," and (eventually) with the vpp packet - * tracer + * "pcap rx | tx trace," and with the vpp packet tracer * * Packets which match a rule in the classifier table chain * will be traced. The tables are automatically ordered so that @@ -1925,16 +1980,24 @@ found_table: * * Configure a simple classify filter, and configure pcap rx trace to use it: * - * classify filter mask l3 ip4 src match l3 ip4 src 192.168.1.11"
+ * classify filter rx mask l3 ip4 src match l3 ip4 src 192.168.1.11"
* pcap rx trace on max 100 filter * * Configure another fairly simple filter * * classify filter mask l3 ip4 src dst match l3 ip4 src 192.168.1.10 dst 192.168.2.10" * - * Clear all current classifier filters * - * classify filter del + * Configure a filter for use with the vpp packet tracer: + * classify filter trace mask l3 ip4 src dst match l3 ip4 src 192.168.1.10 dst 192.168.2.10" + * trace add dpdk-input 100 filter + * + * Clear classifier filters + * + * classify filter [trace | rx | tx | ] del + * + * To display the top-level classifier tables for each use case: + * show classify filter * * To inspect the classifier tables, use * @@ -1947,8 +2010,9 @@ VLIB_CLI_COMMAND (classify_filter, static) = { .path = "classify filter", .short_help = - "classify filter | pcap mask match [del]" - "[buckets ] [memory-size ]", + "classify filter | pcap mask match \n" + " | trace mask match [del]\n" + " [buckets ] [memory-size ]", .function = classify_filter_command_fn, }; /* *INDENT-ON* */ @@ -1966,26 +2030,39 @@ show_classify_filter_command_fn (vlib_main_t * vm, u32 set_index; u32 table_index; int verbose = 0; - int i, j; + int i, j, limit; (void) unformat (input, "verbose %=", &verbose, 1); vlib_cli_output (vm, "%-30s%s", "Filter Used By", " Table(s)"); vlib_cli_output (vm, "%-30s%s", "--------------", " --------"); - for (i = 0; i < vec_len (cm->filter_set_by_sw_if_index); i++) + limit = vec_len (cm->filter_set_by_sw_if_index); + + for (i = -1; i < limit; i++) { - set_index = cm->filter_set_by_sw_if_index[i]; + if (i < 0) + set_index = vlib_global_main.trace_filter.trace_filter_set_index; + else + set_index = cm->filter_set_by_sw_if_index[i]; - if (set_index == 0 && verbose == 0) + if (set_index == ~0) continue; set = pool_elt_at_index (cm->filter_sets, set_index); - if (i == 0) - name = format (0, "pcap rx/tx/drop:"); - else - name = format (0, "%U:", format_vnet_sw_if_index_name, vnm, i); + switch (i) + { + case -1: + name = format (0, "packet tracer:"); + break; + case 0: + name = format (0, "pcap rx/tx/drop:"); + break; + default: + name = format (0, "%U:", format_vnet_sw_if_index_name, vnm, i); + break; + } if (verbose) { @@ -2875,12 +2952,22 @@ vnet_classify_init (vlib_main_t * vm) set->table_indices[0] = ~0; /* Initialize the pcap filter set */ vec_validate (cm->filter_set_by_sw_if_index, 0); + cm->filter_set_by_sw_if_index[0] = ~0; + /* Initialize the packet tracer filter set */ + vlib_global_main.trace_filter.trace_filter_set_index = ~0; return 0; } VLIB_INIT_FUNCTION (vnet_classify_init); +int +vnet_is_packet_traced (vlib_buffer_t * b, u32 classify_table_index, int func) +{ + return vnet_is_packet_traced_inline (b, classify_table_index, func); +} + + #define TEST_CODE 0 #if TEST_CODE > 0 -- cgit 1.2.3-korg