blob: d478f1d233c7894b65e2e5989b43eedd20a0c823 [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{
59 vnet_dev_api_detach_args_t a = {};
60 vnet_dev_rv_t rv;
61
62 if (!unformat_user (input, unformat_c_string_array, a.device_id,
63 sizeof (a.device_id)))
64 return clib_error_return (0, "please specify valid device id");
65
66 rv = vnet_dev_api_detach (vm, &a);
67
68 if (rv != VNET_DEV_OK)
69 return clib_error_return (0, "unable to detach '%s': %U", a.device_id,
70 format_vnet_dev_rv, rv);
71
72 return 0;
73}
74
75VLIB_CLI_COMMAND (device_detach_cmd, static) = {
76 .path = "device detach",
77 .short_help = "device detach <device-id>",
78 .function = device_detach_cmd_fn,
79 .is_mp_safe = 1,
80};
81
82static clib_error_t *
83device_reset_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
84 vlib_cli_command_t *cmd)
85{
86 vnet_dev_api_reset_args_t a = {};
87 vnet_dev_rv_t rv;
88
89 if (!unformat_user (input, unformat_c_string_array, a.device_id,
90 sizeof (a.device_id)))
91 return clib_error_return (0, "please specify valid device id");
92
93 rv = vnet_dev_api_reset (vm, &a);
94
95 if (rv != VNET_DEV_OK)
96 return clib_error_return (0, "unable to reset '%s': %U", a.device_id,
97 format_vnet_dev_rv, rv);
98
99 return 0;
100}
101
102VLIB_CLI_COMMAND (device_reset_cmd, static) = {
103 .path = "device reset",
104 .short_help = "device reset <device-id>",
105 .function = device_reset_cmd_fn,
106 .is_mp_safe = 1,
107};
108
109static clib_error_t *
110device_create_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
111 vlib_cli_command_t *cmd)
112{
113 vnet_dev_api_create_port_if_args_t a = {};
114 vnet_dev_rv_t rv;
115 u32 n;
116
117 if (!unformat_user (input, unformat_c_string_array, a.device_id,
118 sizeof (a.device_id)))
119 return clib_error_return (0, "please specify valid device id");
120
121 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
122 {
123 if (!a.intf_name[0] &&
124 unformat (input, "if-name %U", unformat_c_string_array, a.intf_name,
125 sizeof (a.intf_name)))
126 ;
127 else if (!a.port_id && unformat (input, "port %u", &n))
128 a.port_id = n;
129 else if (!a.flags.n && unformat (input, "flags %U",
130 unformat_vnet_dev_port_flags, &a.flags))
131 ;
132 else if (!a.num_rx_queues && unformat (input, "num-rx-queues %u", &n))
133 a.num_rx_queues = n;
134 else if (!a.num_tx_queues && unformat (input, "num-tx-queues %u", &n))
135 a.num_tx_queues = n;
136 else if (!a.rx_queue_size && unformat (input, "rx-queues-size %u", &n))
137 a.rx_queue_size = n;
138 else if (!a.tx_queue_size && unformat (input, "tx-queues-size %u", &n))
139 a.tx_queue_size = n;
140 else if (!a.intf_name[0] &&
141 unformat (input, "name %U", unformat_c_string_array,
142 &a.intf_name, sizeof (a.intf_name)))
143 ;
144 else if (!a.args && unformat (input, "args %v", &a.args))
145 ;
146 else
147 return clib_error_return (0, "unknown input `%U'",
148 format_unformat_error, input);
149 }
150
151 rv = vnet_dev_api_create_port_if (vm, &a);
152
153 vec_free (a.args);
154
155 if (rv != VNET_DEV_OK)
156 return clib_error_return (0, "unable to create_if '%s': %U", a.device_id,
157 format_vnet_dev_rv, rv);
158
159 return 0;
160}
161
162VLIB_CLI_COMMAND (device_create_if_cmd, static) = {
163 .path = "device create-interface",
164 .short_help = "device create-interface <device-id> [port <port-id>] "
165 "[args <iface-args>]",
166 .function = device_create_if_cmd_fn,
167 .is_mp_safe = 1,
168};
169
170static clib_error_t *
171device_remove_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
172 vlib_cli_command_t *cmd)
173{
174 vnet_dev_api_remove_port_if_args_t a = { .sw_if_index = ~0 };
175 vnet_main_t *vnm = vnet_get_main ();
176 vnet_dev_rv_t rv;
177
178 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
179 {
180 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
181 &a.sw_if_index))
182 ;
183 else if (unformat (input, "sw-if-index %u", &a.sw_if_index))
184 ;
185 else
186 return clib_error_return (0, "unknown input `%U'",
187 format_unformat_error, input);
188 }
189
190 if (a.sw_if_index == ~0)
191 return clib_error_return (0, "please specify existing interface name");
192
193 rv = vnet_dev_api_remove_port_if (vm, &a);
194
195 if (rv != VNET_DEV_OK)
196 return clib_error_return (0, "unable to remove interface: %U",
197 format_vnet_dev_rv, rv);
198
199 return 0;
200}
201
202VLIB_CLI_COMMAND (device_remove_if_cmd, static) = {
203 .path = "device remove-interface",
204 .short_help = "device remove-interface [<interface-name> | sw-if-index <n>]",
205 .function = device_remove_if_cmd_fn,
206 .is_mp_safe = 1,
207};
208
209static clib_error_t *
210show_devices_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
211 vlib_cli_command_t *cmd)
212{
213 vnet_dev_main_t *dm = &vnet_dev_main;
214 vnet_dev_format_args_t fa = {}, *a = &fa;
215
216 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
217 {
218 if (unformat (input, "counters"))
219 fa.counters = 1;
220 else if (unformat (input, "all"))
221 fa.show_zero_counters = 1;
222 else if (unformat (input, "debug"))
223 fa.debug = 1;
224 else
225 return clib_error_return (0, "unknown input `%U'",
226 format_unformat_error, input);
227 }
228
229 pool_foreach_pointer (dev, dm->devices)
230 {
231 vlib_cli_output (vm, "device '%s':", dev->device_id);
232 vlib_cli_output (vm, " %U", format_vnet_dev_info, a, dev);
233 foreach_vnet_dev_port (p, dev)
234 {
235 vlib_cli_output (vm, " Port %u:", p->port_id);
236 vlib_cli_output (vm, " %U", format_vnet_dev_port_info, a, p);
237 if (fa.counters)
238 vlib_cli_output (vm, " %U", format_vnet_dev_counters, a,
239 p->counter_main);
240
241 foreach_vnet_dev_port_rx_queue (q, p)
242 {
243 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
244 vlib_cli_output (vm, " %U", format_vnet_dev_rx_queue_info,
245 a, q);
246 }
247
248 foreach_vnet_dev_port_tx_queue (q, p)
249 {
250 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
251 vlib_cli_output (vm, " %U", format_vnet_dev_tx_queue_info,
252 a, q);
253 }
254 }
255 }
256 return 0;
257}
258
259VLIB_CLI_COMMAND (show_devices_cmd, static) = {
260 .path = "show device",
261 .short_help = "show device [counters]",
262 .function = show_devices_cmd_fn,
263 .is_mp_safe = 1,
264};
265
266static clib_error_t *
267show_device_counters_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
268 vlib_cli_command_t *cmd)
269{
270 vnet_dev_main_t *dm = &vnet_dev_main;
271 vnet_dev_format_args_t fa = { .counters = 1 };
272
273 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
274 {
275 if (unformat (input, "all"))
276 fa.show_zero_counters = 1;
277 else
278 return clib_error_return (0, "unknown input `%U'",
279 format_unformat_error, input);
280 }
281
282 pool_foreach_pointer (dev, dm->devices)
283 {
284 vlib_cli_output (vm, "device '%s':", dev->device_id);
285 foreach_vnet_dev_port (p, dev)
286 {
287 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
288 p->counter_main);
289
290 foreach_vnet_dev_port_rx_queue (q, p)
291 if (q->counter_main)
292 {
293 vlib_cli_output (vm, " RX queue %u:", q->queue_id);
294 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
295 q->counter_main);
296 }
297
298 foreach_vnet_dev_port_tx_queue (q, p)
299 if (q->counter_main)
300 {
301 vlib_cli_output (vm, " TX queue %u:", q->queue_id);
302 vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa,
303 q->counter_main);
304 }
305 }
306 }
307 return 0;
308}
309
310VLIB_CLI_COMMAND (show_device_counters_cmd, static) = {
311 .path = "show device counters",
312 .short_help = "show device counters [all]",
313 .function = show_device_counters_cmd_fn,
314 .is_mp_safe = 1,
315};