blob: c98524c9b7edc6dfa0164bdba1b5d592bd5cc7d3 [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 "vppinfra/error.h"
6#include "vppinfra/pool.h"
7#include <vnet/vnet.h>
8#include <vnet/ethernet/ethernet.h>
9#include <vnet/dev/dev.h>
10#include <vnet/dev/api.h>
11#include <vnet/dev/log.h>
12
13VLIB_REGISTER_LOG_CLASS (dev_log, static) = {
14 .class_name = "dev",
15 .subclass_name = "config",
16};
17
18static clib_error_t *
19vnet_dev_config_one_interface (vlib_main_t *vm, unformat_input_t *input,
20 vnet_dev_api_create_port_if_args_t *args)
21{
22 clib_error_t *err = 0;
23
24 log_debug (0, "port %u %U", args->port_id, format_unformat_input, input);
25
26 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
27 {
28 u32 n;
29
30 if (unformat (input, "name %U", unformat_c_string_array, args->intf_name,
31 sizeof (args->intf_name)))
32 ;
33 else if (unformat (input, "num-rx-queues %u", &n))
34 args->num_rx_queues = n;
35 else if (unformat (input, "num-tx-queues %u", &n))
36 args->num_tx_queues = n;
37 else if (unformat (input, "rx-queue-size %u", &n))
38 args->rx_queue_size = n;
39 else if (unformat (input, "tx-queue-size %u", &n))
40 args->tx_queue_size = n;
41 else if (unformat (input, "flags %U", unformat_vnet_dev_port_flags,
42 &args->flags))
43 ;
44 else
45 {
46 err = clib_error_return (0, "unknown input '%U'",
47 format_unformat_error, input);
48 break;
49 }
50 }
51 return err;
52}
53
54static clib_error_t *
55vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input,
56 char *device_id)
57{
58 log_debug (0, "device %s %U", device_id, format_unformat_input, input);
59 clib_error_t *err = 0;
60 vnet_dev_api_attach_args_t args = {};
61 vnet_dev_api_create_port_if_args_t *if_args_vec = 0, *if_args;
62
63 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
64 {
65 unformat_input_t sub_input;
66 u32 n;
67
68 if (unformat (input, "driver %U", unformat_c_string_array,
69 args.driver_name, sizeof (args.driver_name)))
70 ;
71 else if (unformat (input, "flags %U", unformat_vnet_dev_flags,
72 &args.flags))
73 ;
74 else if (unformat (input, "port %u %U", &n, unformat_vlib_cli_sub_input,
75 &sub_input))
76 {
77 vnet_dev_api_create_port_if_args_t *if_args;
78 vec_add2 (if_args_vec, if_args, 1);
79 if_args->port_id = n;
80 err = vnet_dev_config_one_interface (vm, &sub_input, if_args);
81 unformat_free (&sub_input);
82 if (err)
83 break;
84 }
85 else
86 {
87 err = clib_error_return (0, "unknown input '%U'",
88 format_unformat_error, input);
89 break;
90 }
91 }
92
93 if (err == 0)
94 {
95 vnet_dev_rv_t rv;
96
97 clib_memcpy (args.device_id, device_id, sizeof (args.device_id));
98 rv = vnet_dev_api_attach (vm, &args);
99
100 if (rv == VNET_DEV_OK)
101 {
102 vec_foreach (if_args, if_args_vec)
103 {
104 clib_memcpy (if_args->device_id, device_id,
105 sizeof (if_args->device_id));
106 rv = vnet_dev_api_create_port_if (vm, if_args);
107 if (rv != VNET_DEV_OK)
108 break;
109 }
110
111 if (rv != VNET_DEV_OK)
112 err = clib_error_return (0, "error: %U for device '%s'",
113 format_vnet_dev_rv, rv, device_id);
114 }
115 }
116
117 vec_free (if_args_vec);
118 return err;
119}
120
121uword
122dev_config_process_node_fn (vlib_main_t *vm, vlib_node_runtime_t *rt,
123 vlib_frame_t *f)
124{
125 vnet_dev_main_t *dm = &vnet_dev_main;
126 unformat_input_t input;
127 clib_error_t *err = 0;
128
129 if (dm->startup_config == 0)
130 return 0;
131
132 unformat_init_vector (&input, dm->startup_config);
133 dm->startup_config = 0;
134
135 while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
136 {
137 unformat_input_t sub_input;
138 vnet_dev_device_id_t device_id;
139 if (unformat (&input, "dev %U %U", unformat_c_string_array, device_id,
140 sizeof (device_id), unformat_vlib_cli_sub_input,
141 &sub_input))
142 {
143 err = vnet_dev_config_one_device (vm, &sub_input, device_id);
144 unformat_free (&sub_input);
145 if (err)
146 break;
147 }
148 else
149 {
150 err = clib_error_return (0, "unknown input '%U'",
151 format_unformat_error, input);
152 break;
153 }
154 }
155
156 unformat_free (&input);
157
158 vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
159 vlib_node_rename (vm, rt->node_index, "deleted-%u", rt->node_index);
160 vec_add1 (dm->free_process_node_indices, rt->node_index);
161 return 0;
162}
163
164VLIB_REGISTER_NODE (dev_config_process_node) = {
165 .function = dev_config_process_node_fn,
166 .type = VLIB_NODE_TYPE_PROCESS,
167 .name = "dev-config",
168};
169
170static clib_error_t *
171devices_config (vlib_main_t *vm, unformat_input_t *input)
172{
173 vnet_dev_main_t *dm = &vnet_dev_main;
174 uword c;
175
176 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
177 vec_add1 (dm->startup_config, c);
178
179 return 0;
180}
181
182VLIB_CONFIG_FUNCTION (devices_config, "devices");