aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/tracedump
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/tracedump')
-rw-r--r--src/plugins/tracedump/CMakeLists.txt6
-rw-r--r--src/plugins/tracedump/graph_api.c2
-rw-r--r--src/plugins/tracedump/graph_cli.c12
-rw-r--r--src/plugins/tracedump/graph_test.c2
-rw-r--r--src/plugins/tracedump/setup.pg52
-rw-r--r--src/plugins/tracedump/tracedump.api68
-rw-r--r--src/plugins/tracedump/tracedump.c217
-rw-r--r--src/plugins/tracedump/tracedump_test.c97
8 files changed, 399 insertions, 57 deletions
diff --git a/src/plugins/tracedump/CMakeLists.txt b/src/plugins/tracedump/CMakeLists.txt
index 7860d95bc11..6dffdedcc81 100644
--- a/src/plugins/tracedump/CMakeLists.txt
+++ b/src/plugins/tracedump/CMakeLists.txt
@@ -26,7 +26,7 @@ add_vpp_plugin(tracedump
API_TEST_SOURCES
graph_test.c
tracedump_test.c
-)
-# API_TEST_SOURCES
-# tracedump_test.c
+ COMPONENT
+ vpp-plugin-devtools
+)
diff --git a/src/plugins/tracedump/graph_api.c b/src/plugins/tracedump/graph_api.c
index 0626f7d6b42..20eb1b920fc 100644
--- a/src/plugins/tracedump/graph_api.c
+++ b/src/plugins/tracedump/graph_api.c
@@ -252,7 +252,7 @@ graph_api_hookup (vlib_main_t * vm)
gmp->msg_id_base = setup_message_id_table ();
- am->is_mp_safe[gmp->msg_id_base + VL_API_GRAPH_NODE_GET] = 1;
+ vl_api_set_msg_thread_safe (am, gmp->msg_id_base + VL_API_GRAPH_NODE_GET, 1);
return 0;
}
diff --git a/src/plugins/tracedump/graph_cli.c b/src/plugins/tracedump/graph_cli.c
index 2440295a1a7..6af4706f87d 100644
--- a/src/plugins/tracedump/graph_cli.c
+++ b/src/plugins/tracedump/graph_cli.c
@@ -16,7 +16,11 @@
*/
#include <sys/socket.h>
+#ifdef __linux__
#include <linux/if.h>
+#else
+#include <net/if.h>
+#endif /* __linux__ */
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
@@ -75,9 +79,9 @@ graph_node_show_cmd (vlib_main_t * vm,
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "node %d", &index))
- n = vlib_get_node (vm, index);
- else if (unformat (input, "node %v", &name))
- n = vlib_get_node_by_name (vm, name);
+ n = vlib_get_node (vm, index);
+ else if (unformat (input, "node %s", &name))
+ n = vlib_get_node_by_name (vm, name);
else if (unformat (input, "want_arcs"))
want_arcs = true;
@@ -132,13 +136,11 @@ graph_node_show_cmd (vlib_main_t * vm,
return 0;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (graph_node_show_command, static) = {
.path = "show graph",
.short_help = "show graph [node <index>|<name>] [want_arcs] [input|trace_supported] [drop] [output] [punt] [handoff] [no_free] [polling] [interrupt]",
.function = graph_node_show_cmd,
};
-/* *INDENT-ON* */
/*
diff --git a/src/plugins/tracedump/graph_test.c b/src/plugins/tracedump/graph_test.c
index 79e1df61c5f..37dfbcdcaa0 100644
--- a/src/plugins/tracedump/graph_test.c
+++ b/src/plugins/tracedump/graph_test.c
@@ -27,7 +27,7 @@
#include <vnet/format_fns.h>
#include <tracedump/graph.api_enum.h>
#include <tracedump/graph.api_types.h>
-#include <vpp/api/vpe.api_types.h>
+#include <vlibmemory/vlib.api_types.h>
typedef struct
{
diff --git a/src/plugins/tracedump/setup.pg b/src/plugins/tracedump/setup.pg
index 91d5ebe2d2a..1ebdb0dd7f0 100644
--- a/src/plugins/tracedump/setup.pg
+++ b/src/plugins/tracedump/setup.pg
@@ -1,33 +1,33 @@
set term pag off
-packet-generator new {
- name worker0
- worker 0
- limit 12
- rate 1.2e7
- size 128-128
- interface local0
- node ethernet-input
- data { IP4: 1.2.40 -> 3cfd.fed0.b6c8
- UDP: 192.168.40.1 - 192.168.40.100 -> 192.168.50.10
- UDP: 1234 -> 2345
- incrementing 114
- }
+packet-generator new { \
+ name worker0 \
+ worker 0 \
+ limit 12 \
+ rate 1.2e7 \
+ size 128-128 \
+ interface local0 \
+ node ethernet-input \
+ data { IP4: 1.2.40 -> 3cfd.fed0.b6c8 \
+ UDP: 192.168.40.1 - 192.168.40.100 -> 192.168.50.10 \
+ UDP: 1234 -> 2345 \
+ incrementing 114 \
+ } \
}
-packet-generator new {
- name worker1
- worker 1
- limit 12
- rate 1.2e7
- size 128-128
- interface local0
- node ethernet-input
- data { IP4: 1.2.4 -> 3cfd.fed0.b6c9
- UDP: 192.168.41.1 - 192.168.41.100 -> 192.168.51.10
- UDP: 1234 -> 2345
- incrementing 114
- }
+packet-generator new { \
+ name worker1 \
+ worker 1 \
+ limit 12 \
+ rate 1.2e7 \
+ size 128-128 \
+ interface local0 \
+ node ethernet-input \
+ data { IP4: 1.2.4 -> 3cfd.fed0.b6c9 \
+ UDP: 192.168.41.1 - 192.168.41.100 -> 192.168.51.10 \
+ UDP: 1234 -> 2345 \
+ incrementing 114 \
+ } \
}
trace add pg-input 20
diff --git a/src/plugins/tracedump/tracedump.api b/src/plugins/tracedump/tracedump.api
index 540b0664074..1b3813fb184 100644
--- a/src/plugins/tracedump/tracedump.api
+++ b/src/plugins/tracedump/tracedump.api
@@ -25,7 +25,7 @@
*/
-option version = "0.1.0";
+option version = "0.2.0";
enum trace_filter_flag : u32
{
@@ -147,3 +147,69 @@ define trace_details {
u32 packet_number;
string trace_data[];
};
+
+/** \brief trace_clear_cache
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+autoreply define trace_clear_cache {
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief trace_v2_dump
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param thread_id - specific thread to dump from, ~0 to dump from all
+ @param position - position of the first packet to dump in the per thread cache, ~0 to only clear the cache
+ @param max - maximum of packets to dump from each thread
+ @param clear_cache - dispose of any cached data before we begin
+*/
+define trace_v2_dump {
+ u32 client_index;
+ u32 context;
+
+ u32 thread_id [default=0xffffffff];
+ u32 position;
+ u32 max [default=50];
+ bool clear_cache;
+
+ option vat_help = "trace_v2_dump [thread_id <tid>] [position <pos>] [max <max>]";
+};
+
+/** \brief trace_v2_details
+ @param context - sender context, to match reply w/ request
+ @param thread_id - thread index from which the packet come from
+ @param position - position of the packet in its thread cache
+ @param more - true if there is still more packets to dump for this thread
+ @param trace_data - string packet data
+*/
+define trace_v2_details {
+ u32 context;
+
+ u32 thread_id;
+ u32 position;
+ bool more;
+
+ string trace_data[];
+};
+
+autoreply define trace_set_filter_function
+{
+ u32 client_index;
+ u32 context;
+
+ string filter_function_name[];
+};
+
+define trace_filter_function_dump {
+ u32 client_index;
+ u32 context;
+};
+
+define trace_filter_function_details {
+ u32 context;
+
+ bool selected;
+ string name[];
+}; \ No newline at end of file
diff --git a/src/plugins/tracedump/tracedump.c b/src/plugins/tracedump/tracedump.c
index f1073fe247d..6a26865c1f0 100644
--- a/src/plugins/tracedump/tracedump.c
+++ b/src/plugins/tracedump/tracedump.c
@@ -213,12 +213,15 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
iterator_position = clib_net_to_host_u32 (mp->position);
max_records = clib_net_to_host_u32 (mp->max_records);
- /* Don't overflow the existing queue space. */
- svm_queue_t *q = rp->vl_input_queue;
- u32 queue_slots_available = q->maxsize - q->cursize;
- int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
- if (chunk < max_records)
- max_records = chunk;
+ /* Don't overflow the existing queue space for shared memory API clients. */
+ if (rp->vl_input_queue)
+ {
+ svm_queue_t *q = rp->vl_input_queue;
+ u32 queue_slots_available = q->maxsize - q->cursize;
+ int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
+ if (chunk < max_records)
+ max_records = chunk;
+ }
/* Need a fresh cache for this client? */
if (vec_len (client_trace_cache) == 0
@@ -285,9 +288,9 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
{
/* More threads, but not more in this thread? */
if (j == (vec_len (client_trace_cache[i]) - 1))
- dmp->more_threads = 1;
+ last_more_threads = dmp->more_threads = 1;
else
- dmp->more_this_thread = 1;
+ last_more_this_thread = dmp->more_this_thread = 1;
}
/* Done, may or may not be at the end of a batch. */
dmp->done = 0;
@@ -332,6 +335,199 @@ doublebreak:;
vec_free (s);
}
+/* API message handler */
+static void
+vl_api_trace_v2_dump_t_handler (vl_api_trace_v2_dump_t *mp)
+{
+ vl_api_registration_t *rp;
+ vl_api_trace_v2_details_t *dmp;
+ tracedump_main_t *tdmp = &tracedump_main;
+ vlib_trace_header_t ***client_trace_cache, **th;
+ int i, j;
+ u32 client_index;
+ u32 first_position, max, first_thread_id, last_thread_id;
+ u32 n_threads = vlib_get_n_threads ();
+ u8 *s = 0;
+
+ rp = vl_api_client_index_to_registration (mp->client_index);
+ if (rp == 0)
+ return;
+
+ client_index = rp->vl_api_registration_pool_index;
+
+ vec_validate_init_empty (tdmp->traces, client_index, 0);
+
+ client_trace_cache = tdmp->traces[client_index];
+
+ if (mp->clear_cache)
+ {
+ toss_client_cache (tdmp, client_index, client_trace_cache);
+ client_trace_cache = 0;
+ }
+
+ /* Now, where were we? */
+ first_thread_id = last_thread_id = clib_net_to_host_u32 (mp->thread_id);
+ first_position = clib_net_to_host_u32 (mp->position);
+ max = clib_net_to_host_u32 (mp->max);
+
+ if (first_thread_id == ~0)
+ {
+ first_thread_id = 0;
+ last_thread_id = n_threads - 1;
+ }
+
+ /* Don't overflow the existing queue space for shared memory API clients. */
+ if (rp->vl_input_queue)
+ {
+ svm_queue_t *q = rp->vl_input_queue;
+ u32 queue_slots_available = q->maxsize - q->cursize;
+ int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
+ /* split available slots among requested threads */
+ if (chunk < max * (last_thread_id - first_thread_id + 1))
+ max = chunk / (last_thread_id - first_thread_id + 1);
+ }
+
+ /* Need a fresh cache for this client? */
+ if (vec_len (client_trace_cache) == 0 && first_position != ~0)
+ {
+ vlib_worker_thread_barrier_sync (vlib_get_first_main ());
+
+ /* Make a slot for each worker thread */
+ vec_validate (client_trace_cache, n_threads - 1);
+ i = 0;
+
+ foreach_vlib_main ()
+ {
+ vlib_trace_main_t *tm = &this_vlib_main->trace_main;
+
+ /* Filter as directed */
+ trace_apply_filter (this_vlib_main);
+
+ pool_foreach (th, tm->trace_buffer_pool)
+ {
+ vec_add1 (client_trace_cache[i], th[0]);
+ }
+
+ /* Sort them by increasing time. */
+ if (vec_len (client_trace_cache[i]))
+ vec_sort_with_function (client_trace_cache[i], trace_cmp);
+
+ i++;
+ }
+ vlib_worker_thread_barrier_release (vlib_get_first_main ());
+ }
+
+ /* Save the cache, one way or the other */
+ tdmp->traces[client_index] = client_trace_cache;
+
+ for (i = first_thread_id;
+ i <= last_thread_id && i < vec_len (client_trace_cache); i++)
+ {
+ // dump a number of 'max' packets per thead
+ for (j = first_position;
+ j < vec_len (client_trace_cache[i]) && j < first_position + max;
+ j++)
+ {
+ th = &client_trace_cache[i][j];
+
+ vec_reset_length (s);
+
+ s =
+ format (s, "%U", format_vlib_trace, vlib_get_first_main (), th[0]);
+
+ dmp = vl_msg_api_alloc (sizeof (*dmp) + vec_len (s));
+ dmp->_vl_msg_id =
+ htons (VL_API_TRACE_V2_DETAILS + (tdmp->msg_id_base));
+ dmp->context = mp->context;
+ dmp->thread_id = ntohl (i);
+ dmp->position = ntohl (j);
+ dmp->more = j < vec_len (client_trace_cache[i]) - 1;
+ vl_api_vec_to_api_string (s, &dmp->trace_data);
+
+ vl_api_send_msg (rp, (u8 *) dmp);
+ }
+ }
+
+ vec_free (s);
+}
+
+static void
+vl_api_trace_clear_cache_t_handler (vl_api_trace_clear_cache_t *mp)
+{
+ vl_api_registration_t *rp;
+ tracedump_main_t *tdmp = &tracedump_main;
+ vlib_trace_header_t ***client_trace_cache;
+ vl_api_trace_clear_cache_reply_t *rmp;
+ u32 client_index;
+
+ rp = vl_api_client_index_to_registration (mp->client_index);
+ if (rp == 0)
+ return;
+
+ client_index = rp->vl_api_registration_pool_index;
+ vec_validate_init_empty (tdmp->traces, client_index, 0);
+ client_trace_cache = tdmp->traces[client_index];
+ toss_client_cache (tdmp, client_index, client_trace_cache);
+
+ int rv = 0;
+ REPLY_MACRO (VL_API_TRACE_CLEAR_CACHE_REPLY);
+}
+
+static void
+vl_api_trace_set_filter_function_t_handler (
+ vl_api_trace_set_filter_function_t *mp)
+{
+ vl_api_trace_set_filter_function_reply_t *rmp;
+ tracedump_main_t *tdmp = &tracedump_main;
+ 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;
+ }
+ vlib_set_trace_filter_function (f);
+done:
+ unformat_free (&input);
+ vec_free (filter_name);
+ REPLY_MACRO (VL_API_TRACE_SET_FILTER_FUNCTION_REPLY);
+}
+
+static void
+vl_api_trace_filter_function_dump_t_handler (
+ vl_api_trace_filter_function_dump_t *mp)
+{
+ vl_api_registration_t *rp;
+ vl_api_trace_filter_function_details_t *dmp;
+ tracedump_main_t *tdmp = &tracedump_main;
+ vlib_trace_filter_main_t *tfm = &vlib_trace_filter_main;
+ vlib_trace_filter_function_registration_t *reg =
+ tfm->trace_filter_registration;
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_is_packet_traced_fn_t *current =
+ vm->trace_main.current_trace_filter_function;
+ rp = vl_api_client_index_to_registration (mp->client_index);
+
+ if (rp == 0)
+ return;
+
+ while (reg)
+ {
+ dmp = vl_msg_api_alloc (sizeof (*dmp) + strlen (reg->name));
+ dmp->_vl_msg_id =
+ htons (VL_API_TRACE_FILTER_FUNCTION_DETAILS + (tdmp->msg_id_base));
+ dmp->context = mp->context;
+ vl_api_c_string_to_api_string (reg->name, &dmp->name);
+ dmp->selected = current == reg->function;
+ vl_api_send_msg (rp, (u8 *) dmp);
+ reg = reg->next;
+ }
+}
+
/* API definitions */
#include <tracedump/tracedump.api.c>
@@ -349,19 +545,18 @@ tracedump_init (vlib_main_t * vm)
/* Add our API messages to the global name_crc hash table */
tdmp->msg_id_base = setup_message_id_table ();
- am->is_mp_safe[tdmp->msg_id_base + VL_API_TRACE_DUMP] = 1;
+ vl_api_set_msg_thread_safe (am, tdmp->msg_id_base + VL_API_TRACE_DUMP, 1);
+ vl_api_set_msg_thread_safe (am, tdmp->msg_id_base + VL_API_TRACE_V2_DUMP, 1);
return error;
}
VLIB_INIT_FUNCTION (tracedump_init);
-/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () =
{
.version = VPP_BUILD_VER,
.description = "Streaming packet trace dump plugin",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/tracedump/tracedump_test.c b/src/plugins/tracedump/tracedump_test.c
index 3bf50efb4ac..b813acc3ecc 100644
--- a/src/plugins/tracedump/tracedump_test.c
+++ b/src/plugins/tracedump/tracedump_test.c
@@ -155,6 +155,18 @@ vl_api_trace_details_t_handler (vl_api_trace_details_t * dmp)
packet_number, vl_api_format_string, (&dmp->trace_data));
}
+static void
+vl_api_trace_v2_details_t_handler (vl_api_trace_v2_details_t *dmp)
+{
+ u32 thread_id, position;
+
+ thread_id = clib_net_to_host_u32 (dmp->thread_id);
+ position = clib_net_to_host_u32 (dmp->position);
+ fformat (stdout, "thread %d position %d more %d", thread_id, position,
+ dmp->more);
+ fformat (stdout, "Packet %d\n%U\n\n", position, vl_api_format_string,
+ (&dmp->trace_data));
+}
static void
vl_api_trace_dump_reply_t_handler (vl_api_trace_dump_reply_t * rmp)
@@ -203,7 +215,7 @@ vl_api_trace_dump_reply_t_handler (vl_api_trace_dump_reply_t * rmp)
}
static int
-api_trace_dump (vat_main_t * vam)
+api_trace_dump (vat_main_t *vam)
{
vl_api_trace_dump_t *mp;
int ret;
@@ -220,8 +232,26 @@ api_trace_dump (vat_main_t * vam)
return ret;
}
+static int
+api_trace_v2_dump (vat_main_t *vam)
+{
+ vl_api_trace_v2_dump_t *mp;
+ int ret;
+
+ M (TRACE_V2_DUMP, mp);
+ mp->clear_cache = 1;
+ mp->thread_id = ~0;
+ mp->position = 0;
+ mp->max = clib_host_to_net_u32 (10);
+
+ S (mp);
+
+ W (ret);
+ return ret;
+}
+
int
-api_trace_clear_capture (vat_main_t * vam)
+api_trace_clear_capture (vat_main_t *vam)
{
vl_api_trace_clear_capture_t *mp;
int ret;
@@ -232,26 +262,75 @@ api_trace_clear_capture (vat_main_t * vam)
return ret;
}
+static int
+api_trace_clear_cache (vat_main_t *vam)
+{
+ vl_api_trace_clear_capture_t *mp;
+ int ret;
+
+ M (TRACE_CLEAR_CACHE, mp);
+ S (mp);
+ W (ret);
+ return ret;
+}
+
+static int
+api_trace_set_filter_function (vat_main_t *vam)
+{
+ vl_api_trace_set_filter_function_t *mp;
+ int ret;
+ M (TRACE_SET_FILTER_FUNCTION, mp);
+ S (mp);
+ W (ret);
+ return ret;
+}
+static int
+api_trace_filter_function_dump (vat_main_t *vam)
+{
+ vl_api_trace_filter_function_dump_t *mp;
+ int ret;
+
+ M (TRACE_FILTER_FUNCTION_DUMP, mp);
+ S (mp);
+ W (ret);
+ return ret;
+}
+
+static void
+vl_api_trace_filter_function_details_t_handler (
+ vl_api_trace_filter_function_details_t *dmp)
+{
+ fformat (stdout, "name: %U, selected: %u\n\n", vl_api_format_string,
+ &dmp->name, dmp->selected);
+}
-#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define vl_endianfun
#include <tracedump/tracedump.api.h>
#undef vl_endianfun
#define vl_printfun
#include <tracedump/tracedump.api.h>
#undef vl_printfun
+#define vl_calcsizefun
+#include <tracedump/tracedump.api.h>
+#undef vl_calcsizefun
void
manual_setup_message_id_table (vat_main_t * vam)
{
- vl_msg_api_set_handlers (VL_API_TRACE_DETAILS
- + tracedump_test_main.msg_id_base, "trace_details",
- vl_api_trace_details_t_handler, vl_noop_handler,
- vl_api_trace_details_t_endian,
- vl_api_trace_details_t_print,
- sizeof (vl_api_trace_details_t), 1);
+ vl_msg_api_config (&(vl_msg_api_msg_config_t){
+ .id = VL_API_TRACE_DETAILS + tracedump_test_main.msg_id_base,
+ .name = "trace_details",
+ .handler = vl_api_trace_details_t_handler,
+ .endian = vl_api_trace_details_t_endian,
+ .format_fn = vl_api_trace_details_t_format,
+ .size = sizeof (vl_api_trace_details_t),
+ .traced = 1,
+ .tojson = vl_api_trace_details_t_tojson,
+ .fromjson = vl_api_trace_details_t_fromjson,
+ .calc_size = vl_api_trace_details_t_calc_size,
+ });
}
#define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE manual_setup_message_id_table