2 * tracedump.c - skeleton vpp engine plug-in
4 * Copyright (c) <current-year> <your-organization>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <tracedump/tracedump.h>
21 #include <vlib/trace.h>
23 #include <vlibapi/api.h>
24 #include <vlibmemory/api.h>
25 #include <vpp/app/version.h>
28 #include <tracedump/tracedump.api_enum.h>
29 #include <tracedump/tracedump.api_types.h>
31 #define REPLY_MSG_ID_BASE tdmp->msg_id_base
32 #include <vlibapi/api_helper_macros.h>
34 tracedump_main_t tracedump_main;
37 trace_cmp (void *a1, void *a2)
39 vlib_trace_header_t **t1 = a1;
40 vlib_trace_header_t **t2 = a2;
41 i64 dt = t1[0]->time - t2[0]->time;
42 return dt < 0 ? -1 : (dt > 0 ? +1 : 0);
46 toss_client_cache (tracedump_main_t * tdmp, u32 client_index,
47 vlib_trace_header_t *** client_trace_cache)
49 vlib_trace_header_t **th;
52 /* Across each vlib main... */
53 for (i = 0; i < vec_len (client_trace_cache); i++)
55 th = client_trace_cache[i];
56 /* Toss the thread's cached data */
59 /* And toss the vector of threads */
60 vec_free (client_trace_cache);
61 tdmp->traces[client_index] = client_trace_cache;
64 /* API message handler */
66 vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
68 vl_api_registration_t *rp;
69 vl_api_trace_dump_reply_t *rmp;
70 vl_api_trace_details_t *dmp;
71 tracedump_main_t *tdmp = &tracedump_main;
72 vlib_trace_header_t ***client_trace_cache, **th;
75 u32 iterator_thread_id, iterator_position, max_records;
76 i32 retval = VNET_API_ERROR_NO_SUCH_ENTRY;
77 u32 last_thread_id = ~0, last_position = ~0;
79 u8 last_more_this_thread = 0;
80 u8 last_more_threads = 0;
83 rp = vl_api_client_index_to_registration (mp->client_index);
87 /* Use the registration pool index... */
88 client_index = rp->vl_api_registration_pool_index;
90 vec_validate_init_empty (tdmp->traces, client_index, 0);
92 client_trace_cache = tdmp->traces[client_index];
94 /* Clear the per-client cache if requested */
97 toss_client_cache (tdmp, client_index, client_trace_cache);
98 client_trace_cache = 0;
101 /* Now, where were we? */
102 iterator_thread_id = clib_net_to_host_u32 (mp->thread_id);
103 iterator_position = clib_net_to_host_u32 (mp->position);
104 max_records = clib_net_to_host_u32 (mp->max_records);
106 /* Need a fresh cache for this client? */
107 if (vec_len (client_trace_cache) == 0
108 && (iterator_thread_id != ~0 || iterator_position != ~0))
110 vlib_worker_thread_barrier_sync (&vlib_global_main);
112 /* Make a slot for each worker thread */
113 vec_validate (client_trace_cache, vec_len (vlib_mains) - 1);
119 vlib_trace_main_t *tm = &this_vlib_main->trace_main;
121 /* Filter as directed */
122 trace_apply_filter(this_vlib_main);
124 pool_foreach (th, tm->trace_buffer_pool,
126 vec_add1 (client_trace_cache[i], th[0]);
129 /* Sort them by increasing time. */
130 if (vec_len (client_trace_cache[i]))
131 vec_sort_with_function (client_trace_cache[i], trace_cmp);
136 vlib_worker_thread_barrier_release (&vlib_global_main);
139 /* Save the cache, one way or the other */
140 tdmp->traces[client_index] = client_trace_cache;
142 for (i = iterator_thread_id; i < vec_len (client_trace_cache); i++)
144 for (j = iterator_position; j < vec_len (client_trace_cache[i]); j++)
146 if (max_records == 0)
150 th = &client_trace_cache[i][j];
152 vec_reset_length (s);
154 s = format (s, "Packet %d\n%U\n\n", j + 1, format_vlib_trace,
155 &vlib_global_main, th[0]);
157 dmp = vl_msg_api_alloc (sizeof (*dmp) + vec_len (s));
159 htons (VL_API_TRACE_DETAILS + (tdmp->msg_id_base));
160 dmp->context = mp->context;
161 last_thread_id = dmp->thread_id = ntohl (i);
162 last_position = dmp->position = ntohl (j);
163 vl_api_vec_to_api_string (s, &dmp->trace_data);
164 dmp->more_threads = 0;
165 dmp->more_this_thread = 0;
167 /* Last record in the batch? */
168 if (max_records == 1)
170 /* More threads, but not more in this thread? */
171 if (j == (vec_len (client_trace_cache[i]) - 1))
172 dmp->more_threads = 1;
174 dmp->more_this_thread = 1;
176 /* Done, may or may not be at the end of a batch. */
178 if (i == (vec_len (client_trace_cache) - 1) &&
179 j == (vec_len (client_trace_cache[i]) - 1))
181 last_done = dmp->done = 1;
182 last_more_threads = dmp->more_threads = 0;
183 last_more_this_thread = dmp->more_this_thread = 0;
184 vl_api_send_msg (rp, (u8 *) dmp);
187 last_done = dmp->done;
188 vl_api_send_msg (rp, (u8 *) dmp);
192 iterator_position = 0;
197 rmp = vl_msg_api_alloc (sizeof (*rmp));
198 rmp->_vl_msg_id = htons (VL_API_TRACE_DUMP_REPLY + (tdmp->msg_id_base));
199 rmp->context = mp->context;
200 rmp->retval = clib_host_to_net_u32 (retval);
201 rmp->last_thread_id = last_thread_id;
202 rmp->last_position = last_position;
203 rmp->done = last_done;
204 rmp->more_this_thread = last_more_this_thread;
205 rmp->more_threads = last_more_threads;
207 /* Tag cleanup flushes to make life easy for the client */
208 if (iterator_thread_id == ~0 && iterator_position == ~0)
214 vl_api_send_msg (rp, (u8 *) rmp);
219 /* API definitions */
220 #include <tracedump/tracedump.api.c>
222 static clib_error_t *
223 tracedump_init (vlib_main_t * vm)
225 tracedump_main_t *tdmp = &tracedump_main;
226 api_main_t *am = vlibapi_get_main ();
228 clib_error_t *error = 0;
230 tdmp->vlib_main = vm;
231 tdmp->vnet_main = vnet_get_main ();
233 /* Add our API messages to the global name_crc hash table */
234 tdmp->msg_id_base = setup_message_id_table ();
236 am->is_mp_safe[tdmp->msg_id_base + VL_API_TRACE_DUMP] = 1;
241 VLIB_INIT_FUNCTION (tracedump_init);
243 VLIB_PLUGIN_REGISTER () =
245 .version = VPP_BUILD_VER,
246 .description = "Streaming packet trace dump plugin",
251 * fd.io coding-style-patch-verification: ON
254 * eval: (c-set-style "gnu")