blob: 2a55affe3e3667a0c41aa7da6acbb3e683e852c3 [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/ethernet/ethernet.h>
7#include <vnet/dev/dev.h>
8#include <vnet/dev/counters.h>
9#include <vnet/dev/log.h>
10#include <vnet/flow/flow.h>
11
12VLIB_REGISTER_LOG_CLASS (dev_log, static) = {
13 .class_name = "dev",
14 .subclass_name = "handler",
15};
16
17clib_error_t *
18vnet_dev_port_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hw,
19 u32 frame_size)
20{
21 vlib_main_t *vm = vlib_get_main ();
22 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
23 vnet_dev_rv_t rv;
24
25 vnet_dev_port_cfg_change_req_t req = {
Damjan Marione596ca12023-11-08 19:12:27 +000026 .type = VNET_DEV_PORT_CFG_MAX_RX_FRAME_SIZE,
27 .max_rx_frame_size = frame_size,
Damjan Marion38c61912023-10-17 16:06:26 +000028 };
29
30 log_debug (p->dev, "size %u", frame_size);
31
32 rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
33 if (rv == VNET_DEV_ERR_NO_CHANGE)
34 return 0;
35
36 if (rv != VNET_DEV_OK)
37 return vnet_dev_port_err (vm, p, rv,
38 "new max frame size is not valid for port");
39
40 if ((rv = vnet_dev_process_port_cfg_change_req (vm, p, &req)) != VNET_DEV_OK)
41 return vnet_dev_port_err (vm, p, rv,
42 "device failed to change max frame size");
43
44 return 0;
45}
46
47u32
48vnet_dev_port_eth_flag_change (vnet_main_t *vnm, vnet_hw_interface_t *hw,
49 u32 flags)
50{
51 vlib_main_t *vm = vlib_get_main ();
52 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hw->dev_instance);
53 vnet_dev_rv_t rv;
54
55 vnet_dev_port_cfg_change_req_t req = {
56 .type = VNET_DEV_PORT_CFG_PROMISC_MODE,
57 };
58
59 switch (flags)
60 {
61 case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:
62 log_debug (p->dev, "promisc off");
63 break;
64 case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL:
65 log_debug (p->dev, "promisc on");
66 req.promisc = 1;
67 break;
68 default:
69 return ~0;
70 }
71
72 rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
73 if (rv == VNET_DEV_ERR_NO_CHANGE)
74 return 0;
75
76 if (rv != VNET_DEV_OK)
77 return ~0;
78
79 rv = vnet_dev_process_port_cfg_change_req (vm, p, &req);
80 if (rv == VNET_DEV_OK || rv == VNET_DEV_ERR_NO_CHANGE)
81 return 0;
82 return ~0;
83}
84
85clib_error_t *
86vnet_dev_port_mac_change (vnet_hw_interface_t *hi, const u8 *old,
87 const u8 *new)
88{
89 vlib_main_t *vm = vlib_get_main ();
90 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
91 vnet_dev_rv_t rv;
92
93 vnet_dev_port_cfg_change_req_t req = {
94 .type = VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR,
95 };
96
97 vnet_dev_set_hw_addr_eth_mac (&req.addr, new);
98
99 log_debug (p->dev, "new mac %U", format_vnet_dev_hw_addr, &req.addr);
100
101 rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
102 if (rv == VNET_DEV_ERR_NO_CHANGE)
103 return 0;
104
105 if (rv != VNET_DEV_OK)
106 return vnet_dev_port_err (vm, p, rv, "hw address is not valid for port");
107
108 if ((rv = vnet_dev_process_port_cfg_change_req (vm, p, &req)) != VNET_DEV_OK)
109 return vnet_dev_port_err (vm, p, rv, "device failed to change hw address");
110
111 return 0;
112}
113
114clib_error_t *
115vnet_dev_add_del_mac_address (vnet_hw_interface_t *hi, const u8 *address,
116 u8 is_add)
117{
118 vlib_main_t *vm = vlib_get_main ();
119 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
120 vnet_dev_rv_t rv;
121
122 vnet_dev_port_cfg_change_req_t req = {
123 .type = is_add ? VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR :
124 VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR,
125 };
126
127 vnet_dev_set_hw_addr_eth_mac (&req.addr, address);
128
129 log_debug (p->dev, "received (addr %U is_add %u", format_vnet_dev_hw_addr,
130 &req.addr, is_add);
131
132 rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
133 if (rv != VNET_DEV_OK)
134 return vnet_dev_port_err (vm, p, rv,
135 "provided secondary hw addresses cannot "
136 "be added/removed");
137
138 if ((rv = vnet_dev_process_port_cfg_change_req (vm, p, &req)) != VNET_DEV_OK)
139 return vnet_dev_port_err (
140 vm, p, rv, "device failed to add/remove secondary hw address");
141
142 return 0;
143}
144
145int
146vnet_dev_flow_ops_fn (vnet_main_t *vnm, vnet_flow_dev_op_t op,
147 u32 dev_instance, u32 flow_index, uword *private_data)
148{
Monendra Singh Kushwaha4af3fdf2024-02-06 14:02:43 +0530149 vlib_main_t *vm = vlib_get_main ();
Damjan Marion38c61912023-10-17 16:06:26 +0000150 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (dev_instance);
Monendra Singh Kushwaha4af3fdf2024-02-06 14:02:43 +0530151 vnet_dev_port_cfg_change_req_t req;
152 vnet_dev_rv_t rv;
153
154 switch (op)
155 {
156 case VNET_FLOW_DEV_OP_ADD_FLOW:
157 req.type = VNET_DEV_PORT_CFG_ADD_RX_FLOW;
158 break;
159 case VNET_FLOW_DEV_OP_DEL_FLOW:
160 req.type = VNET_DEV_PORT_CFG_DEL_RX_FLOW;
161 break;
162 case VNET_FLOW_DEV_OP_GET_COUNTER:
163 req.type = VNET_DEV_PORT_CFG_GET_RX_FLOW_COUNTER;
164 break;
165 case VNET_FLOW_DEV_OP_RESET_COUNTER:
166 req.type = VNET_DEV_PORT_CFG_RESET_RX_FLOW_COUNTER;
167 break;
168 default:
169 log_warn (p->dev, "unsupported request for flow_ops received");
170 return VNET_FLOW_ERROR_NOT_SUPPORTED;
171 }
172
173 req.flow_index = flow_index;
174 req.private_data = private_data;
175
176 rv = vnet_dev_port_cfg_change_req_validate (vm, p, &req);
177 if (rv != VNET_DEV_OK)
178 {
179 log_err (p->dev, "validation failed for flow_ops");
180 return VNET_FLOW_ERROR_NOT_SUPPORTED;
181 }
182
183 if ((rv = vnet_dev_process_port_cfg_change_req (vm, p, &req)) != VNET_DEV_OK)
184 {
185 log_err (p->dev, "request for flow_ops failed");
186 return vnet_dev_flow_err (vm, rv);
187 }
188
189 return 0;
Damjan Marion38c61912023-10-17 16:06:26 +0000190}
191
192clib_error_t *
193vnet_dev_interface_set_rss_queues (vnet_main_t *vnm, vnet_hw_interface_t *hi,
194 clib_bitmap_t *bitmap)
195{
196 vnet_dev_port_t *p = vnet_dev_get_port_from_dev_instance (hi->dev_instance);
197 log_warn (p->dev, "unsupported request for flow_ops received");
198 return vnet_error (VNET_ERR_UNSUPPORTED, "not implemented");
199}
200
201void
202vnet_dev_clear_hw_interface_counters (u32 instance)
203{
204 vnet_dev_port_t *port = vnet_dev_get_port_from_dev_instance (instance);
205 vlib_main_t *vm = vlib_get_main ();
206
207 vnet_dev_process_call_port_op_no_rv (vm, port, vnet_dev_port_clear_counters);
208}
209
Damjan Marion38c61912023-10-17 16:06:26 +0000210void
211vnet_dev_set_interface_next_node (vnet_main_t *vnm, u32 hw_if_index,
212 u32 node_index)
213{
214 vlib_main_t *vm = vlib_get_main ();
215 vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
216 vnet_dev_port_t *port =
217 vnet_dev_get_port_from_dev_instance (hw->dev_instance);
218 int runtime_update = 0;
219
220 if (node_index == ~0)
221 {
222 port->intf.redirect_to_node_next_index = 0;
223 if (port->intf.feature_arc == 0)
224 {
225 port->intf.rx_next_index =
226 vnet_dev_default_next_index_by_port_type[port->attr.type];
227 runtime_update = 1;
228 }
229 port->intf.redirect_to_node = 0;
230 }
231 else
232 {
233 u16 next_index = vlib_node_add_next (vlib_get_main (),
234 port_rx_eth_node.index, node_index);
235 port->intf.redirect_to_node_next_index = next_index;
236 if (port->intf.feature_arc == 0)
237 {
238 port->intf.rx_next_index = next_index;
239 runtime_update = 1;
240 }
241 port->intf.redirect_to_node = 1;
242 }
243 port->intf.rx_next_index =
244 node_index == ~0 ?
245 vnet_dev_default_next_index_by_port_type[port->attr.type] :
246 node_index;
247
248 if (runtime_update)
249 {
250 foreach_vnet_dev_port_rx_queue (rxq, port)
251 vnet_dev_rx_queue_rt_request (
252 vm, rxq, (vnet_dev_rx_queue_rt_req_t){ .update_next_index = 1 });
253 log_debug (port->dev, "runtime update requested due to chgange in "
254 "reditect-to-next configuration");
255 }
256}