diff options
author | Maxime Peim <mpeim@cisco.com> | 2023-04-11 15:45:59 +0000 |
---|---|---|
committer | Beno�t Ganne <bganne@cisco.com> | 2023-05-23 11:40:29 +0000 |
commit | 02063b985ac2fd3ce24a42fe9e27f434ea088053 (patch) | |
tree | 601ee00fac0d921105d9e190ec19efa4745ffc42 /src/plugins/tracedump/tracedump.c | |
parent | eed42b0efa576a6a0efa93df7c3e96ce3296f7af (diff) |
misc: fix tracedump API to match CLI behavior
When dumping packets from multiple threads using the API, first all
packets from thread 0 are dumped then all ones from thread 1, etc
Until we reach the limit specified by the API call, so we could never
get packets trace from threads with higher ids.
However, the tracedump CLI dump a maximum number of packets from all
threads, which we can expect from the API to do.
We also add a trace_clear_cache API so the client gets an answer when
he only wants to clear its packet cache.
Type: improvement
Change-Id: I0d4df8f6210a298ac3f22cd651eb4d8f445e1034
Signed-off-by: Maxime Peim <mpeim@cisco.com>
Diffstat (limited to 'src/plugins/tracedump/tracedump.c')
-rw-r--r-- | src/plugins/tracedump/tracedump.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/plugins/tracedump/tracedump.c b/src/plugins/tracedump/tracedump.c index 0f1612c70cd..0c0f3b493b3 100644 --- a/src/plugins/tracedump/tracedump.c +++ b/src/plugins/tracedump/tracedump.c @@ -335,6 +335,143 @@ 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++) + { + // 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); +} + /* API definitions */ #include <tracedump/tracedump.api.c> @@ -353,6 +490,7 @@ tracedump_init (vlib_main_t * vm) tdmp->msg_id_base = setup_message_id_table (); 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; } |