1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <dev_iavf/iavf.h>
10 #include <dev_iavf/iavf_regs.h>
11 #include <dev_iavf/virtchnl.h>
12 #include <dev_iavf/virtchnl_funcs.h>
13 #include <vnet/ethernet/ethernet.h>
15 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
17 .subclass_name = "port",
20 static const u8 default_rss_key[] = {
21 0x44, 0x39, 0x79, 0x6b, 0xb5, 0x4c, 0x50, 0x23, 0xb6, 0x75, 0xea, 0x5b, 0x12,
22 0x4f, 0x9f, 0x30, 0xb8, 0xa2, 0xc0, 0x3d, 0xdf, 0xdc, 0x4d, 0x02, 0xa0, 0x8c,
23 0x9b, 0x33, 0x4a, 0xf6, 0x4a, 0x4c, 0x05, 0xc6, 0xfa, 0x34, 0x39, 0x58, 0xd8,
24 0x55, 0x7d, 0x99, 0x58, 0x3a, 0xe1, 0x38, 0xc9, 0x2e, 0x81, 0x15, 0x03, 0x66,
27 const static iavf_dyn_ctln dyn_ctln_disabled = {};
28 const static iavf_dyn_ctln dyn_ctln_enabled = {
30 .interval = IAVF_ITR_INT / 2,
33 const static iavf_dyn_ctln dyn_ctln_wb_on_itr = {
41 iavf_port_vlan_strip_disable (vlib_main_t *vm, vnet_dev_port_t *port)
43 vnet_dev_t *dev = port->dev;
44 iavf_port_t *ap = vnet_dev_get_port_data (port);
45 virtchnl_vlan_caps_t vc;
48 const u32 mask = VIRTCHNL_VLAN_ETHERTYPE_8100;
50 if ((ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) == 0)
51 return iavf_vc_op_disable_vlan_stripping (vm, dev);
53 if ((rv = iavf_vc_op_get_offload_vlan_v2_caps (vm, dev, &vc)))
56 outer = vc.offloads.stripping_support.outer;
57 inner = vc.offloads.stripping_support.inner;
59 outer = outer & VIRTCHNL_VLAN_TOGGLE ? outer & mask : 0;
60 inner = inner & VIRTCHNL_VLAN_TOGGLE ? inner & mask : 0;
62 virtchnl_vlan_setting_t vs = {
63 .vport_id = ap->vsi_id,
64 .outer_ethertype_setting = outer,
65 .inner_ethertype_setting = inner,
68 return iavf_vc_op_disable_vlan_stripping_v2 (vm, dev, &vs);
72 iavf_port_init_rss (vlib_main_t *vm, vnet_dev_port_t *port)
74 vnet_dev_t *dev = port->dev;
75 iavf_port_t *ap = vnet_dev_get_port_data (port);
76 u16 keylen = clib_min (sizeof (default_rss_key), ap->rss_key_size);
77 u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_key_t, key, keylen)];
78 virtchnl_rss_key_t *key = (virtchnl_rss_key_t *) buffer;
80 if (!port->attr.caps.rss)
84 *key = (virtchnl_rss_key_t){
89 clib_memcpy (key->key, default_rss_key, sizeof (default_rss_key));
91 return iavf_vc_op_config_rss_key (vm, dev, key);
95 iavf_port_update_rss_lut (vlib_main_t *vm, vnet_dev_port_t *port)
97 vnet_dev_t *dev = port->dev;
98 iavf_port_t *ap = vnet_dev_get_port_data (port);
99 u16 lut_size = clib_min (IAVF_MAX_RSS_LUT_SIZE, ap->rss_lut_size);
100 u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_rss_lut_t, lut, lut_size)];
101 virtchnl_rss_lut_t *lut = (virtchnl_rss_lut_t *) buffer;
102 u32 enabled_rxq_bmp = 0;
104 if (!port->attr.caps.rss)
107 *lut = (virtchnl_rss_lut_t){
108 .vsi_id = ap->vsi_id,
109 .lut_entries = lut_size,
112 foreach_vnet_dev_port_rx_queue (q, port)
114 enabled_rxq_bmp |= 1ULL << q->queue_id;
117 for (u32 i = 0, j; i < lut->lut_entries;)
118 foreach_set_bit_index (j, enabled_rxq_bmp)
121 if (i >= lut->lut_entries)
125 return iavf_vc_op_config_rss_lut (vm, dev, lut);
129 iavf_port_init_vsi_queues (vlib_main_t *vm, vnet_dev_port_t *port)
131 vnet_dev_t *dev = port->dev;
132 iavf_port_t *ap = vnet_dev_get_port_data (port);
133 virtchnl_queue_pair_info_t *qpi;
134 u16 vsi_id = ap->vsi_id;
135 u16 data_size = vlib_buffer_get_default_data_size (vm);
136 u16 max_frame_size = port->max_frame_size;
137 u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_vsi_queue_config_info_t, qpair,
139 virtchnl_vsi_queue_config_info_t *ci =
140 (virtchnl_vsi_queue_config_info_t *) buffer;
142 *ci = (virtchnl_vsi_queue_config_info_t){
143 .num_queue_pairs = ap->num_qp,
147 for (u16 i = 0; i < ap->num_qp; i++)
148 ci->qpair[i] = (virtchnl_queue_pair_info_t){
149 .rxq = { .vsi_id = vsi_id, .queue_id = i },
150 .txq = { .vsi_id = vsi_id, .queue_id = i },
153 foreach_vnet_dev_port_rx_queue (q, port)
155 iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (q);
156 qpi = ci->qpair + q->queue_id;
157 qpi->rxq.ring_len = q->size;
158 qpi->rxq.databuffer_size = data_size;
159 qpi->rxq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, arq->descs);
160 qpi->rxq.max_pkt_size = max_frame_size;
163 foreach_vnet_dev_port_tx_queue (q, port)
165 iavf_txq_t *atq = vnet_dev_get_tx_queue_data (q);
166 qpi = ci->qpair + q->queue_id;
167 qpi->txq.ring_len = q->size;
168 qpi->txq.dma_ring_addr = vnet_dev_get_dma_addr (vm, dev, atq->descs);
171 return iavf_vc_op_config_vsi_queues (vm, dev, ci);
175 iavf_port_rx_irq_enable_disable (vlib_main_t *vm, vnet_dev_port_t *port,
178 vnet_dev_t *dev = port->dev;
179 iavf_device_t *ad = vnet_dev_get_data (dev);
180 iavf_port_t *ap = vnet_dev_get_port_data (port);
181 u16 n_threads = vlib_get_n_threads ();
182 u8 buffer[VIRTCHNL_MSG_SZ (virtchnl_irq_map_info_t, vecmap, n_threads)];
183 virtchnl_irq_map_info_t *im = (virtchnl_irq_map_info_t *) buffer;
186 if (port->attr.caps.interrupt_mode)
188 *im = (virtchnl_irq_map_info_t){
189 .num_vectors = n_threads,
191 for (u16 i = 0; i < im->num_vectors; i++)
192 im->vecmap[i] = (virtchnl_vector_map_t){
193 .vsi_id = ap->vsi_id,
197 foreach_vnet_dev_port_rx_queue (rxq, port)
199 im->vecmap[rxq->rx_thread_index].rxq_map |= 1 << rxq->queue_id;
203 *im = (virtchnl_irq_map_info_t){
206 .vsi_id = ap->vsi_id,
211 foreach_vnet_dev_port_rx_queue (rxq, port)
213 im->vecmap[0].rxq_map |= 1 << rxq->queue_id;
216 if ((rv = iavf_vc_op_config_irq_map (vm, dev, im)))
219 for (int i = 0; i < im->num_vectors; i++)
224 val = dyn_ctln_disabled.as_u32;
225 else if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
226 val = dyn_ctln_wb_on_itr.as_u32;
228 val = dyn_ctln_enabled.as_u32;
230 iavf_reg_write (ad, AVFINT_DYN_CTLN (im->vecmap[i].vector_id), val);
237 iavf_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
241 log_debug (port->dev, "port %u", port->port_id);
243 if ((rv = iavf_port_vlan_strip_disable (vm, port)))
246 if ((rv = iavf_port_init_rss (vm, port)))
249 if (port->dev->poll_stats)
250 iavf_port_add_counters (vm, port);
256 iavf_enable_disable_queues (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
258 iavf_port_t *ap = vnet_dev_get_port_data (port);
260 virtchnl_queue_select_t qs = {
261 .vsi_id = ap->vsi_id,
264 foreach_vnet_dev_port_rx_queue (q, port)
265 if ((enable && q->enabled) || (!enable && q->started))
266 qs.rx_queues |= 1ULL << q->queue_id;
268 foreach_vnet_dev_port_tx_queue (q, port)
269 if ((enable && q->enabled) || (!enable && q->started))
270 qs.tx_queues |= 1ULL << q->queue_id;
272 return enable ? iavf_vc_op_enable_queues (vm, port->dev, &qs) :
273 iavf_vc_op_disable_queues (vm, port->dev, &qs);
277 iavf_port_start (vlib_main_t *vm, vnet_dev_port_t *port)
281 log_debug (port->dev, "port %u", port->port_id);
283 foreach_vnet_dev_port_rx_queue (q, port)
285 if ((rv = iavf_rx_queue_start (vm, q)))
288 foreach_vnet_dev_port_tx_queue (q, port)
289 if ((rv = iavf_tx_queue_start (vm, q)))
292 if ((rv = iavf_port_update_rss_lut (vm, port)))
295 /* configure qpairs */
296 if ((rv = iavf_port_init_vsi_queues (vm, port)))
299 if ((rv = iavf_port_rx_irq_enable_disable (vm, port, /* enable */ 1)))
302 if ((rv = iavf_enable_disable_queues (vm, port, 1)))
305 if (port->dev->poll_stats)
306 vnet_dev_poll_port_add (vm, port, 1, iavf_port_poll_stats);
311 foreach_vnet_dev_port_rx_queue (q, port)
312 iavf_rx_queue_stop (vm, q);
313 foreach_vnet_dev_port_tx_queue (q, port)
314 iavf_tx_queue_stop (vm, q);
320 iavf_port_stop (vlib_main_t *vm, vnet_dev_port_t *port)
322 log_debug (port->dev, "port %u", port->port_id);
324 iavf_enable_disable_queues (vm, port, /* enable */ 0);
325 iavf_port_rx_irq_enable_disable (vm, port, /* disable */ 0);
327 if (port->dev->poll_stats)
328 vnet_dev_poll_port_remove (vm, port, iavf_port_poll_stats);
330 foreach_vnet_dev_port_rx_queue (rxq, port)
331 iavf_rx_queue_stop (vm, rxq);
333 foreach_vnet_dev_port_tx_queue (txq, port)
334 iavf_tx_queue_stop (vm, txq);
336 vnet_dev_port_state_change (vm, port,
337 (vnet_dev_port_state_changes_t){
338 .change.link_state = 1,
339 .change.link_speed = 1,
346 iavf_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
347 vnet_dev_port_cfg_change_req_t *req)
349 vnet_dev_rv_t rv = VNET_DEV_OK;
353 case VNET_DEV_PORT_CFG_MAX_FRAME_SIZE:
355 rv = VNET_DEV_ERR_PORT_STARTED;
358 case VNET_DEV_PORT_CFG_PROMISC_MODE:
359 case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
360 case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
361 case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
365 rv = VNET_DEV_ERR_NOT_SUPPORTED;
372 iavf_port_add_del_eth_addr (vlib_main_t *vm, vnet_dev_port_t *port,
373 vnet_dev_hw_addr_t *addr, int is_add,
376 iavf_port_t *ap = vnet_dev_get_port_data (port);
377 virtchnl_ether_addr_list_t al = {
378 .vsi_id = ap->vsi_id,
380 .list[0].primary = is_primary ? 1 : 0,
381 .list[0].extra = is_primary ? 0 : 1,
384 clib_memcpy (al.list[0].addr, addr, sizeof (al.list[0].addr));
386 return is_add ? iavf_vc_op_add_eth_addr (vm, port->dev, &al) :
387 iavf_vc_op_del_eth_addr (vm, port->dev, &al);
391 iavf_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
392 vnet_dev_port_cfg_change_req_t *req)
394 vnet_dev_t *dev = port->dev;
395 iavf_port_t *ap = vnet_dev_get_port_data (port);
396 vnet_dev_rv_t rv = VNET_DEV_OK;
400 case VNET_DEV_PORT_CFG_PROMISC_MODE:
402 virtchnl_promisc_info_t pi = {
403 .vsi_id = ap->vsi_id,
404 .unicast_promisc = req->promisc,
405 .multicast_promisc = req->promisc,
408 rv = iavf_vc_op_config_promisc_mode (vm, dev, &pi);
412 case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
413 rv = iavf_port_add_del_eth_addr (vm, port, &port->primary_hw_addr,
416 if (rv == VNET_DEV_OK)
417 rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
422 case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
423 rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
428 case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR:
429 rv = iavf_port_add_del_eth_addr (vm, port, &req->addr,
434 case VNET_DEV_PORT_CFG_MAX_FRAME_SIZE:
438 return VNET_DEV_ERR_NOT_SUPPORTED;