dev: new device driver infra
[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_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
75 VLIB_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
82 static clib_error_t *
83 device_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
102 VLIB_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
109 static clib_error_t *
110 device_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
162 VLIB_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
170 static clib_error_t *
171 device_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
202 VLIB_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
209 static clib_error_t *
210 show_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
259 VLIB_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
266 static clib_error_t *
267 show_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
310 VLIB_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 };