dev: initial set of APIs
[vpp.git] / src / vnet / dev / cli.c
1 /* 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
10 static clib_error_t *
11 device_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
48 VLIB_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
55 static clib_error_t *
56 device_detach_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
57                       vlib_cli_command_t *cmd)
58 {
59   vnet_dev_rv_t rv;
60   vnet_dev_device_id_t device_id = {};
61   vnet_dev_t *dev;
62
63   if (!unformat_user (input, unformat_c_string_array, device_id,
64                       sizeof (device_id)))
65     return clib_error_return (0, "please specify valid device id");
66
67   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;
76
77   if (rv != VNET_DEV_OK)
78     return clib_error_return (0, "unable to detach '%s': %U", device_id,
79                               format_vnet_dev_rv, rv);
80
81   return 0;
82 }
83
84 VLIB_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
91 static clib_error_t *
92 device_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
111 VLIB_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
118 static clib_error_t *
119 device_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;
124   vnet_dev_device_id_t device_id = {};
125   vnet_dev_t *dev = 0;
126   u32 n;
127
128   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)
133     return clib_error_return (0, "please specify valid device id");
134
135   a.dev_index = dev->index;
136
137   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)
172     return clib_error_return (0, "unable to create_if '%s': %U", device_id,
173                               format_vnet_dev_rv, rv);
174
175   return 0;
176 }
177
178 VLIB_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
186 static clib_error_t *
187 device_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
218 VLIB_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
225 static clib_error_t *
226 show_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
275 VLIB_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
282 static clib_error_t *
283 show_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
326 VLIB_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 };