blob: 53be44831838f18b592a90a0ecdaaa300a42338b [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 *
226show_devices_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
227 vlib_cli_command_t *cmd)
228{
229 vnet_dev_main_t *dm = &vnet_dev_main;
230 vnet_dev_format_args_t fa = {}, *a = &fa;
231
232 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
233 {
234 if (unformat (input, "counters"))
235 fa.counters = 1;
236 else if (unformat (input, "all"))
237 fa.show_zero_counters = 1;
238 else if (unformat (input, "debug"))
239 fa.debug = 1;
240 else
241 return clib_error_return (0, "unknown input `%U'",
242 format_unformat_error, input);
243 }
244
245 pool_foreach_pointer (dev, dm->devices)
246 {
247 vlib_cli_output (vm, "device '%s':", dev->device_id);
248 vlib_cli_output (vm, " %U", format_vnet_dev_info, a, dev);
249 foreach_vnet_dev_port (p, dev)
250 {
251 vlib_cli_output (vm, " Port %u:", p->port_id);
252 vlib_cli_output (vm, " %U", format_vnet_dev_port_info, a, p);
253 if (fa.counters)
254 vlib_cli_output (vm, " %U", format_vnet_dev_counters, a,
255 p->counter_main);
256
257 foreach_vnet_dev_port_rx_queue (q, p)
258 {
259 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
260 vlib_cli_output (vm, " %U", format_vnet_dev_rx_queue_info,
261 a, q);
262 }
263
264 foreach_vnet_dev_port_tx_queue (q, p)
265 {
266 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
267 vlib_cli_output (vm, " %U", format_vnet_dev_tx_queue_info,
268 a, q);
269 }
270 }
271 }
272 return 0;
273}
274
275VLIB_CLI_COMMAND (show_devices_cmd, static) = {
276 .path = "show device",
277 .short_help = "show device [counters]",
278 .function = show_devices_cmd_fn,
279 .is_mp_safe = 1,
280};
281
282static clib_error_t *
283show_device_counters_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
284 vlib_cli_command_t *cmd)
285{
286 vnet_dev_main_t *dm = &vnet_dev_main;
287 vnet_dev_format_args_t fa = { .counters = 1 };
288
289 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
290 {
291 if (unformat (input, "all"))
292 fa.show_zero_counters = 1;
293 else
294 return clib_error_return (0, "unknown input `%U'",
295 format_unformat_error, input);
296 }
297
298 pool_foreach_pointer (dev, dm->devices)
299 {
300 vlib_cli_output (vm, "device '%s':", dev->device_id);
301 foreach_vnet_dev_port (p, dev)
302 {
303 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
304 p->counter_main);
305
306 foreach_vnet_dev_port_rx_queue (q, p)
307 if (q->counter_main)
308 {
309 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
310 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
311 q->counter_main);
312 }
313
314 foreach_vnet_dev_port_tx_queue (q, p)
315 if (q->counter_main)
316 {
317 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
318 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
319 q->counter_main);
320 }
321 }
322 }
323 return 0;
324}
325
326VLIB_CLI_COMMAND (show_device_counters_cmd, static) = {
327 .path = "show device counters",
328 .short_help = "show device counters [all]",
329 .function = show_device_counters_cmd_fn,
330 .is_mp_safe = 1,
331};