blob: 6002a2f0dee551070bc132ca82ad7e11b892d70a [file] [log] [blame]
Damjan Marion38c61912023-10-17 16:06:26 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
3 */
4
5#include <vnet/vnet.h>
6#include <vnet/dev/dev.h>
7#include <vnet/dev/counters.h>
8#include <vnet/dev/api.h>
9
10static clib_error_t *
11device_attach_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
12 vlib_cli_command_t *cmd)
13{
14 vnet_dev_api_attach_args_t a = {};
15 vnet_dev_rv_t rv;
16
17 if (!unformat_user (input, unformat_c_string_array, a.device_id,
18 sizeof (a.device_id)))
19 return clib_error_return (0, "please specify valid device id");
20
21 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
22 {
23 if (!a.driver_name[0] &&
24 unformat (input, "driver %U", unformat_c_string_array, a.driver_name,
25 sizeof (a.driver_name)))
26 ;
27 else if (!a.flags.n &&
28 unformat (input, "flags %U", unformat_vnet_dev_flags, &a.flags))
29 ;
30 else if (!a.args && unformat (input, "args %v", &a.args))
31 ;
32 else
33 return clib_error_return (0, "unknown input `%U'",
34 format_unformat_error, input);
35 }
36
37 rv = vnet_dev_api_attach (vm, &a);
38
39 vec_free (a.args);
40
41 if (rv != VNET_DEV_OK)
42 return clib_error_return (0, "unable to attach '%s': %U", a.device_id,
43 format_vnet_dev_rv, rv);
44
45 return 0;
46}
47
48VLIB_CLI_COMMAND (device_attach_cmd, static) = {
49 .path = "device attach",
50 .short_help = "device attach <device-id> [driver <name>] "
51 "[args <dev-args>]",
52 .function = device_attach_cmd_fn,
53};
54
55static clib_error_t *
56device_detach_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
57 vlib_cli_command_t *cmd)
58{
Damjan Marion38c61912023-10-17 16:06:26 +000059 vnet_dev_rv_t rv;
Damjan Marionddf6cec2023-11-22 16:25:55 +000060 vnet_dev_device_id_t device_id = {};
61 vnet_dev_t *dev;
Damjan Marion38c61912023-10-17 16:06:26 +000062
Damjan Marionddf6cec2023-11-22 16:25:55 +000063 if (!unformat_user (input, unformat_c_string_array, device_id,
64 sizeof (device_id)))
Damjan Marion38c61912023-10-17 16:06:26 +000065 return clib_error_return (0, "please specify valid device id");
66
Damjan Marionddf6cec2023-11-22 16:25:55 +000067 dev = vnet_dev_by_id (device_id);
68
69 if (dev)
70 {
71 vnet_dev_api_detach_args_t a = { .dev_index = dev->index };
72 rv = vnet_dev_api_detach (vm, &a);
73 }
74 else
75 rv = VNET_DEV_ERR_UNKNOWN_DEVICE;
Damjan Marion38c61912023-10-17 16:06:26 +000076
77 if (rv != VNET_DEV_OK)
Damjan Marionddf6cec2023-11-22 16:25:55 +000078 return clib_error_return (0, "unable to detach '%s': %U", device_id,
Damjan Marion38c61912023-10-17 16:06:26 +000079 format_vnet_dev_rv, rv);
80
81 return 0;
82}
83
84VLIB_CLI_COMMAND (device_detach_cmd, static) = {
85 .path = "device detach",
86 .short_help = "device detach <device-id>",
87 .function = device_detach_cmd_fn,
88 .is_mp_safe = 1,
89};
90
91static clib_error_t *
92device_reset_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
93 vlib_cli_command_t *cmd)
94{
95 vnet_dev_api_reset_args_t a = {};
96 vnet_dev_rv_t rv;
97
98 if (!unformat_user (input, unformat_c_string_array, a.device_id,
99 sizeof (a.device_id)))
100 return clib_error_return (0, "please specify valid device id");
101
102 rv = vnet_dev_api_reset (vm, &a);
103
104 if (rv != VNET_DEV_OK)
105 return clib_error_return (0, "unable to reset '%s': %U", a.device_id,
106 format_vnet_dev_rv, rv);
107
108 return 0;
109}
110
111VLIB_CLI_COMMAND (device_reset_cmd, static) = {
112 .path = "device reset",
113 .short_help = "device reset <device-id>",
114 .function = device_reset_cmd_fn,
115 .is_mp_safe = 1,
116};
117
118static clib_error_t *
119device_create_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
120 vlib_cli_command_t *cmd)
121{
122 vnet_dev_api_create_port_if_args_t a = {};
123 vnet_dev_rv_t rv;
Damjan Marionddf6cec2023-11-22 16:25:55 +0000124 vnet_dev_device_id_t device_id = {};
125 vnet_dev_t *dev = 0;
Damjan Marion38c61912023-10-17 16:06:26 +0000126 u32 n;
127
Damjan Marionddf6cec2023-11-22 16:25:55 +0000128 if (unformat_user (input, unformat_c_string_array, device_id,
129 sizeof (device_id)))
130 dev = vnet_dev_by_id (device_id);
131
132 if (!dev)
Damjan Marion38c61912023-10-17 16:06:26 +0000133 return clib_error_return (0, "please specify valid device id");
134
Damjan Marionddf6cec2023-11-22 16:25:55 +0000135 a.dev_index = dev->index;
136
Damjan Marion38c61912023-10-17 16:06:26 +0000137 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
138 {
139 if (!a.intf_name[0] &&
140 unformat (input, "if-name %U", unformat_c_string_array, a.intf_name,
141 sizeof (a.intf_name)))
142 ;
143 else if (!a.port_id && unformat (input, "port %u", &n))
144 a.port_id = n;
145 else if (!a.flags.n && unformat (input, "flags %U",
146 unformat_vnet_dev_port_flags, &a.flags))
147 ;
148 else if (!a.num_rx_queues && unformat (input, "num-rx-queues %u", &n))
149 a.num_rx_queues = n;
150 else if (!a.num_tx_queues && unformat (input, "num-tx-queues %u", &n))
151 a.num_tx_queues = n;
152 else if (!a.rx_queue_size && unformat (input, "rx-queues-size %u", &n))
153 a.rx_queue_size = n;
154 else if (!a.tx_queue_size && unformat (input, "tx-queues-size %u", &n))
155 a.tx_queue_size = n;
156 else if (!a.intf_name[0] &&
157 unformat (input, "name %U", unformat_c_string_array,
158 &a.intf_name, sizeof (a.intf_name)))
159 ;
160 else if (!a.args && unformat (input, "args %v", &a.args))
161 ;
162 else
163 return clib_error_return (0, "unknown input `%U'",
164 format_unformat_error, input);
165 }
166
167 rv = vnet_dev_api_create_port_if (vm, &a);
168
169 vec_free (a.args);
170
171 if (rv != VNET_DEV_OK)
Damjan Marionddf6cec2023-11-22 16:25:55 +0000172 return clib_error_return (0, "unable to create_if '%s': %U", device_id,
Damjan Marion38c61912023-10-17 16:06:26 +0000173 format_vnet_dev_rv, rv);
174
175 return 0;
176}
177
178VLIB_CLI_COMMAND (device_create_if_cmd, static) = {
179 .path = "device create-interface",
180 .short_help = "device create-interface <device-id> [port <port-id>] "
181 "[args <iface-args>]",
182 .function = device_create_if_cmd_fn,
183 .is_mp_safe = 1,
184};
185
186static clib_error_t *
187device_remove_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
188 vlib_cli_command_t *cmd)
189{
190 vnet_dev_api_remove_port_if_args_t a = { .sw_if_index = ~0 };
191 vnet_main_t *vnm = vnet_get_main ();
192 vnet_dev_rv_t rv;
193
194 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
195 {
196 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
197 &a.sw_if_index))
198 ;
199 else if (unformat (input, "sw-if-index %u", &a.sw_if_index))
200 ;
201 else
202 return clib_error_return (0, "unknown input `%U'",
203 format_unformat_error, input);
204 }
205
206 if (a.sw_if_index == ~0)
207 return clib_error_return (0, "please specify existing interface name");
208
209 rv = vnet_dev_api_remove_port_if (vm, &a);
210
211 if (rv != VNET_DEV_OK)
212 return clib_error_return (0, "unable to remove interface: %U",
213 format_vnet_dev_rv, rv);
214
215 return 0;
216}
217
218VLIB_CLI_COMMAND (device_remove_if_cmd, static) = {
219 .path = "device remove-interface",
220 .short_help = "device remove-interface [<interface-name> | sw-if-index <n>]",
221 .function = device_remove_if_cmd_fn,
222 .is_mp_safe = 1,
223};
224
225static clib_error_t *
Damjan Marion61e287b2024-10-08 20:50:56 +0200226device_create_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
227 vlib_cli_command_t *cmd)
228{
229 vnet_dev_api_port_add_sec_if_args_t a = {};
230 vnet_main_t *vnm = vnet_get_main ();
231 vnet_dev_rv_t rv;
232
233 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
234 {
235 if (!a.intf_name[0] &&
236 unformat (input, "if-name %U", unformat_c_string_array, a.intf_name,
237 sizeof (a.intf_name)))
238 ;
239 else if (unformat (input, "primary-if-name %U",
240 unformat_vnet_sw_interface, vnm,
241 &a.primary_sw_if_index))
242 ;
243 else if (unformat (input, "primary-sw-if-index %u",
244 &a.primary_sw_if_index))
245 ;
246 else if (!a.args && unformat (input, "args %v", &a.args))
247 ;
248 else
249 return clib_error_return (0, "unknown input `%U'",
250 format_unformat_error, input);
251 }
252
253 rv = vnet_dev_api_port_add_sec_if (vm, &a);
254
255 vec_free (a.args);
256
257 if (rv != VNET_DEV_OK)
258 return clib_error_return (0, "unable to create secondary interface: %U",
259 format_vnet_dev_rv, rv);
260
261 return 0;
262}
263
264VLIB_CLI_COMMAND (device_create_sec_if_cmd, static) = {
265 .path = "device create-secondary-interface",
266 .short_help = "device create-secondary-interface [<interface-name> | "
267 "sw-if-index <n>] id <n> [args <sec-if-args>]",
268 .function = device_create_sec_if_cmd_fn,
269 .is_mp_safe = 1,
270};
271
272static clib_error_t *
273device_remove_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
274 vlib_cli_command_t *cmd)
275{
276 vnet_dev_api_port_del_sec_if_args_t a = { .sw_if_index = ~0 };
277 vnet_main_t *vnm = vnet_get_main ();
278 vnet_dev_rv_t rv;
279
280 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
281 {
282 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
283 &a.sw_if_index))
284 ;
285 else if (unformat (input, "sw-if-index %u", &a.sw_if_index))
286 ;
287 else
288 return clib_error_return (0, "unknown input `%U'",
289 format_unformat_error, input);
290 }
291
292 if (a.sw_if_index == ~0)
293 return clib_error_return (
294 0, "please specify existing secondary interface name");
295
296 rv = vnet_dev_api_port_del_sec_if (vm, &a);
297
298 if (rv != VNET_DEV_OK)
299 return clib_error_return (0, "unable to remove secondary interface: %U",
300 format_vnet_dev_rv, rv);
301
302 return 0;
303}
304
305VLIB_CLI_COMMAND (device_remove_sec_if_cmd, static) = {
306 .path = "device remove-secondary-interface",
307 .short_help =
308 "device remove-secondary-interface [<interface-name> | sw-if-index <n>]",
309 .function = device_remove_sec_if_cmd_fn,
310 .is_mp_safe = 1,
311};
312
313static clib_error_t *
Damjan Marion38c61912023-10-17 16:06:26 +0000314show_devices_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
315 vlib_cli_command_t *cmd)
316{
317 vnet_dev_main_t *dm = &vnet_dev_main;
318 vnet_dev_format_args_t fa = {}, *a = &fa;
319
320 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
321 {
322 if (unformat (input, "counters"))
323 fa.counters = 1;
324 else if (unformat (input, "all"))
325 fa.show_zero_counters = 1;
326 else if (unformat (input, "debug"))
327 fa.debug = 1;
328 else
329 return clib_error_return (0, "unknown input `%U'",
330 format_unformat_error, input);
331 }
332
333 pool_foreach_pointer (dev, dm->devices)
334 {
335 vlib_cli_output (vm, "device '%s':", dev->device_id);
336 vlib_cli_output (vm, " %U", format_vnet_dev_info, a, dev);
337 foreach_vnet_dev_port (p, dev)
338 {
339 vlib_cli_output (vm, " Port %u:", p->port_id);
340 vlib_cli_output (vm, " %U", format_vnet_dev_port_info, a, p);
341 if (fa.counters)
342 vlib_cli_output (vm, " %U", format_vnet_dev_counters, a,
343 p->counter_main);
344
345 foreach_vnet_dev_port_rx_queue (q, p)
346 {
347 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
348 vlib_cli_output (vm, " %U", format_vnet_dev_rx_queue_info,
349 a, q);
350 }
351
352 foreach_vnet_dev_port_tx_queue (q, p)
353 {
354 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
355 vlib_cli_output (vm, " %U", format_vnet_dev_tx_queue_info,
356 a, q);
357 }
358 }
359 }
360 return 0;
361}
362
363VLIB_CLI_COMMAND (show_devices_cmd, static) = {
364 .path = "show device",
365 .short_help = "show device [counters]",
366 .function = show_devices_cmd_fn,
367 .is_mp_safe = 1,
368};
369
370static clib_error_t *
371show_device_counters_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
372 vlib_cli_command_t *cmd)
373{
374 vnet_dev_main_t *dm = &vnet_dev_main;
375 vnet_dev_format_args_t fa = { .counters = 1 };
376
377 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
378 {
379 if (unformat (input, "all"))
380 fa.show_zero_counters = 1;
381 else
382 return clib_error_return (0, "unknown input `%U'",
383 format_unformat_error, input);
384 }
385
386 pool_foreach_pointer (dev, dm->devices)
387 {
388 vlib_cli_output (vm, "device '%s':", dev->device_id);
389 foreach_vnet_dev_port (p, dev)
390 {
Damjan Marionc849be72024-10-23 15:19:46 +0200391 vlib_cli_output (vm, " Port %u:", p->port_id);
Damjan Marion38c61912023-10-17 16:06:26 +0000392 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
393 p->counter_main);
394
395 foreach_vnet_dev_port_rx_queue (q, p)
396 if (q->counter_main)
397 {
Damjan Marionc849be72024-10-23 15:19:46 +0200398 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
399 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
Damjan Marion38c61912023-10-17 16:06:26 +0000400 q->counter_main);
401 }
402
403 foreach_vnet_dev_port_tx_queue (q, p)
404 if (q->counter_main)
405 {
Damjan Marionc849be72024-10-23 15:19:46 +0200406 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
407 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
Damjan Marion38c61912023-10-17 16:06:26 +0000408 q->counter_main);
409 }
410 }
411 }
412 return 0;
413}
414
415VLIB_CLI_COMMAND (show_device_counters_cmd, static) = {
416 .path = "show device counters",
417 .short_help = "show device counters [all]",
418 .function = show_device_counters_cmd_fn,
419 .is_mp_safe = 1,
420};