2 #include <vnet/plugin/plugin.h>
3 #include <vpp/app/version.h>
11 } bufmon_per_node_data_t;
15 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
16 bufmon_per_node_data_t *pnd;
18 } bufmon_per_thread_data_t;
22 bufmon_per_thread_data_t *ptd;
26 static bufmon_main_t bufmon_main;
29 bufmon_alloc_free_callback (vlib_main_t *vm, u32 n_buffers, const int is_free)
31 bufmon_main_t *bm = &bufmon_main;
32 bufmon_per_thread_data_t *ptd;
33 bufmon_per_node_data_t *pnd;
36 if (PREDICT_FALSE (vm->thread_index >= vec_len (bm->ptd)))
38 clib_warning ("bufmon: thread index %d unknown for buffer %s (%d)",
39 vm->thread_index, is_free ? "free" : "alloc", n_buffers);
43 ptd = vec_elt_at_index (bm->ptd, vm->thread_index);
45 cur_node = ptd->cur_node;
46 if (cur_node >= vec_len (ptd->pnd))
48 cur_node = vlib_get_current_process_node_index (vm);
49 vec_validate_aligned (ptd->pnd, cur_node, CLIB_CACHE_LINE_BYTES);
52 pnd = vec_elt_at_index (ptd->pnd, cur_node);
55 pnd->free += n_buffers;
57 pnd->alloc += n_buffers;
63 bufmon_alloc_callback (vlib_main_t *vm, u8 buffer_pool_index, u32 *buffers,
66 return bufmon_alloc_free_callback (vm, n_buffers, 0 /* is_free */);
70 bufmon_free_callback (vlib_main_t *vm, u8 buffer_pool_index, u32 *buffers,
73 return bufmon_alloc_free_callback (vm, n_buffers, 1 /* is_free */);
77 bufmon_count_buffers (vlib_main_t *vm, vlib_frame_t *frame)
79 vlib_buffer_t *b[VLIB_FRAME_SIZE];
80 u32 *from = vlib_frame_vector_args (frame);
81 const u32 n = frame->n_vectors;
85 vlib_get_buffers (vm, from, b, n);
87 for (i = 0; i < n; i++)
89 const vlib_buffer_t *cb = b[i];
90 while (cb->flags & VLIB_BUFFER_NEXT_PRESENT)
93 cb = vlib_get_buffer (vm, cb->next_buffer);
101 bufmon_dispatch_wrapper (vlib_main_t *vm, vlib_node_runtime_t *node,
104 vlib_node_main_t *nm = &vm->node_main;
105 bufmon_main_t *bm = &bufmon_main;
106 bufmon_per_thread_data_t *ptd;
107 bufmon_per_node_data_t *pnd;
111 vec_validate_aligned (bm->ptd, vm->thread_index, CLIB_CACHE_LINE_BYTES);
112 ptd = vec_elt_at_index (bm->ptd, vm->thread_index);
113 vec_validate_aligned (ptd->pnd, node->node_index, CLIB_CACHE_LINE_BYTES);
114 pnd = vec_elt_at_index (ptd->pnd, node->node_index);
117 pnd->in += bufmon_count_buffers (vm, frame);
119 pending_frames = vec_len (nm->pending_frames);
120 ptd->cur_node = node->node_index;
122 rv = node->function (vm, node, frame);
125 for (; pending_frames < vec_len (nm->pending_frames); pending_frames++)
127 vlib_pending_frame_t *p =
128 vec_elt_at_index (nm->pending_frames, pending_frames);
129 pnd->out += bufmon_count_buffers (vm, vlib_get_frame (vm, p->frame));
136 bufmon_unregister_callbacks (vlib_main_t *vm)
138 vlib_buffer_set_alloc_free_callback (vm, 0, 0);
140 vlib_node_set_dispatch_wrapper (this_vlib_main, 0);
143 static clib_error_t *
144 bufmon_register_callbacks (vlib_main_t *vm)
146 if (vlib_buffer_set_alloc_free_callback (vm, bufmon_alloc_callback,
147 bufmon_free_callback))
151 if (vlib_node_set_dispatch_wrapper (this_vlib_main,
152 bufmon_dispatch_wrapper))
159 vlib_node_set_dispatch_wrapper (this_vlib_main, 0);
161 vlib_buffer_set_alloc_free_callback (vm, 0, 0);
162 return clib_error_return (0, "failed to register callback");
165 static clib_error_t *
166 bufmon_enable_disable (vlib_main_t *vm, int enable)
168 bufmon_main_t *bm = &bufmon_main;
174 clib_error_t *error = bufmon_register_callbacks (vm);
183 bufmon_unregister_callbacks (vm);
190 static clib_error_t *
191 set_buffer_traces (vlib_main_t *vm, unformat_input_t *input,
192 vlib_cli_command_t *cmd)
194 unformat_input_t _line_input, *line_input = &_line_input;
197 if (unformat_user (input, unformat_line_input, line_input))
199 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
201 if (unformat (line_input, "on"))
203 else if (unformat (line_input, "off"))
207 unformat_free (line_input);
208 return clib_error_return (0, "unknown input `%U'",
209 format_unformat_error, line_input);
212 unformat_free (line_input);
215 return bufmon_enable_disable (vm, on);
218 VLIB_CLI_COMMAND (set_buffer_traces_command, static) = {
219 .path = "set buffer traces",
220 .short_help = "set buffer traces [on|off]",
221 .function = set_buffer_traces,
224 static clib_error_t *
225 show_buffer_traces (vlib_main_t *vm, unformat_input_t *input,
226 vlib_cli_command_t *cmd)
228 unformat_input_t _line_input, *line_input = &_line_input;
229 const bufmon_main_t *bm = &bufmon_main;
230 const bufmon_per_thread_data_t *ptd;
231 const bufmon_per_node_data_t *pnd;
235 if (unformat_user (input, unformat_line_input, line_input))
237 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
239 if (unformat (line_input, "verbose"))
241 else if (unformat (line_input, "status"))
245 unformat_free (line_input);
246 return clib_error_return (0, "unknown input `%U'",
247 format_unformat_error, line_input);
250 unformat_free (line_input);
255 vlib_cli_output (vm, "buffers tracing is %s",
256 bm->enabled ? "on" : "off");
260 vlib_cli_output (vm, "%U\n\n", format_vlib_buffer_pool_all, vm);
261 vlib_cli_output (vm, "%30s%20s%20s%20s%20s%20s", "Node", "Allocated",
262 "Freed", "In", "Out", "Buffered");
263 vec_foreach (ptd, bm->ptd)
265 vec_foreach (pnd, ptd->pnd)
267 const u64 in = pnd->alloc + pnd->in;
268 const u64 out = pnd->free + pnd->out;
269 const i64 buffered = in - out;
270 if (0 == in && 0 == out)
271 continue; /* skip nodes w/o activity */
272 if (0 == buffered && !verbose)
273 continue; /* if not verbose, skip nodes w/o buffered buffers */
274 vlib_cli_output (vm, "%30U%20lu%20lu%20lu%20lu%20ld",
275 format_vlib_node_name, vm, pnd - ptd->pnd,
276 pnd->alloc, pnd->free, pnd->in, pnd->out, buffered);
283 VLIB_CLI_COMMAND (show_buffer_traces_command, static) = {
284 .path = "show buffer traces",
285 .short_help = "show buffer traces [status|verbose]",
286 .function = show_buffer_traces,
289 static clib_error_t *
290 clear_buffer_traces (vlib_main_t *vm, unformat_input_t *input,
291 vlib_cli_command_t *cmd)
293 const bufmon_main_t *bm = &bufmon_main;
294 const bufmon_per_thread_data_t *ptd;
295 const bufmon_per_node_data_t *pnd;
297 vec_foreach (ptd, bm->ptd)
298 vec_foreach (pnd, ptd->pnd)
299 vec_reset_length (pnd);
304 VLIB_CLI_COMMAND (clear_buffers_trace_command, static) = {
305 .path = "clear buffer traces",
306 .short_help = "clear buffer traces",
307 .function = clear_buffer_traces,
310 VLIB_PLUGIN_REGISTER () = {
311 .version = VPP_BUILD_VER,
312 .description = "Buffers monitoring plugin",