xref: /dpdk/drivers/net/i40e/i40e_vf_representor.c (revision 4e2cf9af)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation.
3  */
4 
5 #include <rte_bus_pci.h>
6 #include <rte_ethdev.h>
7 #include <rte_pci.h>
8 #include <rte_malloc.h>
9 
10 #include "rte_ethdev_driver.h"
11 #include "base/i40e_type.h"
12 #include "base/virtchnl.h"
13 #include "i40e_ethdev.h"
14 #include "i40e_rxtx.h"
15 #include "rte_pmd_i40e.h"
16 
17 static int
18 i40e_vf_representor_link_update(struct rte_eth_dev *ethdev,
19 	int wait_to_complete)
20 {
21 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
22 
23 	return i40e_dev_link_update(representor->adapter->eth_dev,
24 		wait_to_complete);
25 }
26 static int
27 i40e_vf_representor_dev_infos_get(struct rte_eth_dev *ethdev,
28 	struct rte_eth_dev_info *dev_info)
29 {
30 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
31 
32 	/* get dev info for the vdev */
33 	dev_info->device = ethdev->device;
34 
35 	dev_info->max_rx_queues = ethdev->data->nb_rx_queues;
36 	dev_info->max_tx_queues = ethdev->data->nb_tx_queues;
37 
38 	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
39 	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
40 	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
41 		sizeof(uint32_t);
42 	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
43 	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
44 	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
45 	dev_info->rx_offload_capa =
46 		DEV_RX_OFFLOAD_VLAN_STRIP |
47 		DEV_RX_OFFLOAD_QINQ_STRIP |
48 		DEV_RX_OFFLOAD_IPV4_CKSUM |
49 		DEV_RX_OFFLOAD_UDP_CKSUM |
50 		DEV_RX_OFFLOAD_TCP_CKSUM |
51 		DEV_RX_OFFLOAD_VLAN_FILTER;
52 	dev_info->tx_offload_capa =
53 		DEV_TX_OFFLOAD_MULTI_SEGS  |
54 		DEV_TX_OFFLOAD_VLAN_INSERT |
55 		DEV_TX_OFFLOAD_QINQ_INSERT |
56 		DEV_TX_OFFLOAD_IPV4_CKSUM |
57 		DEV_TX_OFFLOAD_UDP_CKSUM |
58 		DEV_TX_OFFLOAD_TCP_CKSUM |
59 		DEV_TX_OFFLOAD_SCTP_CKSUM |
60 		DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
61 		DEV_TX_OFFLOAD_TCP_TSO |
62 		DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
63 		DEV_TX_OFFLOAD_GRE_TNL_TSO |
64 		DEV_TX_OFFLOAD_IPIP_TNL_TSO |
65 		DEV_TX_OFFLOAD_GENEVE_TNL_TSO;
66 
67 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
68 		.rx_thresh = {
69 			.pthresh = I40E_DEFAULT_RX_PTHRESH,
70 			.hthresh = I40E_DEFAULT_RX_HTHRESH,
71 			.wthresh = I40E_DEFAULT_RX_WTHRESH,
72 		},
73 		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
74 		.rx_drop_en = 0,
75 		.offloads = 0,
76 	};
77 
78 	dev_info->default_txconf = (struct rte_eth_txconf) {
79 		.tx_thresh = {
80 			.pthresh = I40E_DEFAULT_TX_PTHRESH,
81 			.hthresh = I40E_DEFAULT_TX_HTHRESH,
82 			.wthresh = I40E_DEFAULT_TX_WTHRESH,
83 		},
84 		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
85 		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
86 		.offloads = 0,
87 	};
88 
89 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
90 		.nb_max = I40E_MAX_RING_DESC,
91 		.nb_min = I40E_MIN_RING_DESC,
92 		.nb_align = I40E_ALIGN_RING_DESC,
93 	};
94 
95 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
96 		.nb_max = I40E_MAX_RING_DESC,
97 		.nb_min = I40E_MIN_RING_DESC,
98 		.nb_align = I40E_ALIGN_RING_DESC,
99 	};
100 
101 	dev_info->switch_info.name =
102 		representor->adapter->eth_dev->device->name;
103 	dev_info->switch_info.domain_id = representor->switch_domain_id;
104 	dev_info->switch_info.port_id = representor->vf_id;
105 
106 	return 0;
107 }
108 
109 static int
110 i40e_vf_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
111 {
112 	return 0;
113 }
114 
115 static int
116 i40e_vf_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
117 {
118 	return 0;
119 }
120 
121 static void
122 i40e_vf_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
123 {
124 }
125 
126 static int
127 i40e_vf_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
128 	__rte_unused uint16_t rx_queue_id,
129 	__rte_unused uint16_t nb_rx_desc,
130 	__rte_unused unsigned int socket_id,
131 	__rte_unused const struct rte_eth_rxconf *rx_conf,
132 	__rte_unused struct rte_mempool *mb_pool)
133 {
134 	return 0;
135 }
136 
137 static int
138 i40e_vf_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
139 	__rte_unused uint16_t rx_queue_id,
140 	__rte_unused uint16_t nb_rx_desc,
141 	__rte_unused unsigned int socket_id,
142 	__rte_unused const struct rte_eth_txconf *tx_conf)
143 {
144 	return 0;
145 }
146 
147 static void
148 i40evf_stat_update_48(uint64_t *offset,
149 		   uint64_t *stat)
150 {
151 	if (*stat >= *offset)
152 		*stat = *stat - *offset;
153 	else
154 		*stat = (uint64_t)((*stat +
155 			((uint64_t)1 << I40E_48_BIT_WIDTH)) - *offset);
156 
157 	*stat &= I40E_48_BIT_MASK;
158 }
159 
160 static void
161 i40evf_stat_update_32(uint64_t *offset,
162 		   uint64_t *stat)
163 {
164 	if (*stat >= *offset)
165 		*stat = (uint64_t)(*stat - *offset);
166 	else
167 		*stat = (uint64_t)((*stat +
168 			((uint64_t)1 << I40E_32_BIT_WIDTH)) - *offset);
169 }
170 
171 static int
172 rte_pmd_i40e_get_vf_native_stats(uint16_t port,
173 			  uint16_t vf_id,
174 			  struct i40e_eth_stats *stats)
175 {
176 	struct rte_eth_dev *dev;
177 	struct i40e_pf *pf;
178 	struct i40e_vsi *vsi;
179 
180 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
181 
182 	dev = &rte_eth_devices[port];
183 
184 	if (!is_i40e_supported(dev))
185 		return -ENOTSUP;
186 
187 	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
188 
189 	if (vf_id >= pf->vf_num || !pf->vfs) {
190 		PMD_DRV_LOG(ERR, "Invalid VF ID.");
191 		return -EINVAL;
192 	}
193 
194 	vsi = pf->vfs[vf_id].vsi;
195 	if (!vsi) {
196 		PMD_DRV_LOG(ERR, "Invalid VSI.");
197 		return -EINVAL;
198 	}
199 
200 	i40e_update_vsi_stats(vsi);
201 	memcpy(stats, &vsi->eth_stats, sizeof(vsi->eth_stats));
202 
203 	return 0;
204 }
205 
206 static int
207 i40e_vf_representor_stats_get(struct rte_eth_dev *ethdev,
208 		struct rte_eth_stats *stats)
209 {
210 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
211 	struct i40e_eth_stats native_stats;
212 	int ret;
213 
214 	ret = rte_pmd_i40e_get_vf_native_stats(
215 		representor->adapter->eth_dev->data->port_id,
216 		representor->vf_id, &native_stats);
217 	if (ret == 0) {
218 		i40evf_stat_update_48(
219 			&representor->stats_offset.rx_bytes,
220 			&native_stats.rx_bytes);
221 		i40evf_stat_update_48(
222 			&representor->stats_offset.rx_unicast,
223 			&native_stats.rx_unicast);
224 		i40evf_stat_update_48(
225 			&representor->stats_offset.rx_multicast,
226 			&native_stats.rx_multicast);
227 		i40evf_stat_update_48(
228 			&representor->stats_offset.rx_broadcast,
229 			&native_stats.rx_broadcast);
230 		i40evf_stat_update_32(
231 			&representor->stats_offset.rx_discards,
232 			&native_stats.rx_discards);
233 		i40evf_stat_update_32(
234 			&representor->stats_offset.rx_unknown_protocol,
235 			&native_stats.rx_unknown_protocol);
236 		i40evf_stat_update_48(
237 			&representor->stats_offset.tx_bytes,
238 			&native_stats.tx_bytes);
239 		i40evf_stat_update_48(
240 			&representor->stats_offset.tx_unicast,
241 			&native_stats.tx_unicast);
242 		i40evf_stat_update_48(
243 			&representor->stats_offset.tx_multicast,
244 			&native_stats.tx_multicast);
245 		i40evf_stat_update_48(
246 			&representor->stats_offset.tx_broadcast,
247 			&native_stats.tx_broadcast);
248 		i40evf_stat_update_32(
249 			&representor->stats_offset.tx_errors,
250 			&native_stats.tx_errors);
251 		i40evf_stat_update_32(
252 			&representor->stats_offset.tx_discards,
253 			&native_stats.tx_discards);
254 
255 		stats->ipackets = native_stats.rx_unicast +
256 			native_stats.rx_multicast +
257 			native_stats.rx_broadcast;
258 		stats->opackets = native_stats.tx_unicast +
259 			native_stats.tx_multicast +
260 			native_stats.tx_broadcast;
261 		stats->ibytes   = native_stats.rx_bytes;
262 		stats->obytes   = native_stats.tx_bytes;
263 		stats->ierrors  = native_stats.rx_discards;
264 		stats->oerrors  = native_stats.tx_errors + native_stats.tx_discards;
265 	}
266 	return ret;
267 }
268 
269 static int
270 i40e_vf_representor_stats_reset(struct rte_eth_dev *ethdev)
271 {
272 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
273 
274 	return rte_pmd_i40e_get_vf_native_stats(
275 		representor->adapter->eth_dev->data->port_id,
276 		representor->vf_id, &representor->stats_offset);
277 }
278 
279 static int
280 i40e_vf_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
281 {
282 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
283 
284 	return rte_pmd_i40e_set_vf_unicast_promisc(
285 		representor->adapter->eth_dev->data->port_id,
286 		representor->vf_id, 1);
287 }
288 
289 static int
290 i40e_vf_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
291 {
292 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
293 
294 	return rte_pmd_i40e_set_vf_unicast_promisc(
295 		representor->adapter->eth_dev->data->port_id,
296 		representor->vf_id, 0);
297 }
298 
299 static int
300 i40e_vf_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
301 {
302 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
303 
304 	return rte_pmd_i40e_set_vf_multicast_promisc(
305 		representor->adapter->eth_dev->data->port_id,
306 		representor->vf_id,  1);
307 }
308 
309 static int
310 i40e_vf_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
311 {
312 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
313 
314 	return rte_pmd_i40e_set_vf_multicast_promisc(
315 		representor->adapter->eth_dev->data->port_id,
316 		representor->vf_id,  0);
317 }
318 
319 static void
320 i40e_vf_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
321 {
322 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
323 
324 	rte_pmd_i40e_remove_vf_mac_addr(
325 		representor->adapter->eth_dev->data->port_id,
326 		representor->vf_id, &ethdev->data->mac_addrs[index]);
327 }
328 
329 static int
330 i40e_vf_representor_mac_addr_set(struct rte_eth_dev *ethdev,
331 		struct rte_ether_addr *mac_addr)
332 {
333 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
334 
335 	return rte_pmd_i40e_set_vf_mac_addr(
336 		representor->adapter->eth_dev->data->port_id,
337 		representor->vf_id, mac_addr);
338 }
339 
340 static int
341 i40e_vf_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
342 		uint16_t vlan_id, int on)
343 {
344 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
345 	uint64_t vf_mask = 1ULL << representor->vf_id;
346 
347 	return rte_pmd_i40e_set_vf_vlan_filter(
348 		representor->adapter->eth_dev->data->port_id,
349 		vlan_id, vf_mask, on);
350 }
351 
352 static int
353 i40e_vf_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
354 {
355 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
356 	struct rte_eth_dev *pdev;
357 	struct i40e_pf_vf *vf;
358 	struct i40e_vsi *vsi;
359 	struct i40e_pf *pf;
360 	uint32_t vfid;
361 
362 	pdev = representor->adapter->eth_dev;
363 	vfid = representor->vf_id;
364 
365 	if (!is_i40e_supported(pdev)) {
366 		PMD_DRV_LOG(ERR, "Invalid PF dev.");
367 		return -EINVAL;
368 	}
369 
370 	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
371 
372 	if (vfid >= pf->vf_num || !pf->vfs) {
373 		PMD_DRV_LOG(ERR, "Invalid VF ID.");
374 		return -EINVAL;
375 	}
376 
377 	vf = &pf->vfs[vfid];
378 	vsi = vf->vsi;
379 	if (!vsi) {
380 		PMD_DRV_LOG(ERR, "Invalid VSI.");
381 		return -EINVAL;
382 	}
383 
384 	if (mask & ETH_VLAN_FILTER_MASK) {
385 		/* Enable or disable VLAN filtering offload */
386 		if (ethdev->data->dev_conf.rxmode.offloads &
387 		    DEV_RX_OFFLOAD_VLAN_FILTER)
388 			return i40e_vsi_config_vlan_filter(vsi, TRUE);
389 		else
390 			return i40e_vsi_config_vlan_filter(vsi, FALSE);
391 	}
392 
393 	if (mask & ETH_VLAN_STRIP_MASK) {
394 		/* Enable or disable VLAN stripping offload */
395 		if (ethdev->data->dev_conf.rxmode.offloads &
396 		    DEV_RX_OFFLOAD_VLAN_STRIP)
397 			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
398 		else
399 			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
400 	}
401 
402 	return -EINVAL;
403 }
404 
405 static void
406 i40e_vf_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
407 	__rte_unused uint16_t rx_queue_id, int on)
408 {
409 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
410 
411 	rte_pmd_i40e_set_vf_vlan_stripq(
412 		representor->adapter->eth_dev->data->port_id,
413 		representor->vf_id, on);
414 }
415 
416 static int
417 i40e_vf_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
418 	__rte_unused int on)
419 {
420 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
421 
422 	return rte_pmd_i40e_set_vf_vlan_insert(
423 		representor->adapter->eth_dev->data->port_id,
424 		representor->vf_id, vlan_id);
425 }
426 
427 static const struct eth_dev_ops i40e_representor_dev_ops = {
428 	.dev_infos_get        = i40e_vf_representor_dev_infos_get,
429 
430 	.dev_start            = i40e_vf_representor_dev_start,
431 	.dev_configure        = i40e_vf_representor_dev_configure,
432 	.dev_stop             = i40e_vf_representor_dev_stop,
433 
434 	.rx_queue_setup       = i40e_vf_representor_rx_queue_setup,
435 	.tx_queue_setup       = i40e_vf_representor_tx_queue_setup,
436 
437 	.link_update          = i40e_vf_representor_link_update,
438 
439 	.stats_get            = i40e_vf_representor_stats_get,
440 	.stats_reset          = i40e_vf_representor_stats_reset,
441 
442 	.promiscuous_enable   = i40e_vf_representor_promiscuous_enable,
443 	.promiscuous_disable  = i40e_vf_representor_promiscuous_disable,
444 
445 	.allmulticast_enable  = i40e_vf_representor_allmulticast_enable,
446 	.allmulticast_disable = i40e_vf_representor_allmulticast_disable,
447 
448 	.mac_addr_remove      = i40e_vf_representor_mac_addr_remove,
449 	.mac_addr_set         = i40e_vf_representor_mac_addr_set,
450 
451 	.vlan_filter_set      = i40e_vf_representor_vlan_filter_set,
452 	.vlan_offload_set     = i40e_vf_representor_vlan_offload_set,
453 	.vlan_strip_queue_set = i40e_vf_representor_vlan_strip_queue_set,
454 	.vlan_pvid_set        = i40e_vf_representor_vlan_pvid_set
455 
456 };
457 
458 static uint16_t
459 i40e_vf_representor_rx_burst(__rte_unused void *rx_queue,
460 	__rte_unused struct rte_mbuf **rx_pkts, __rte_unused uint16_t nb_pkts)
461 {
462 	return 0;
463 }
464 
465 static uint16_t
466 i40e_vf_representor_tx_burst(__rte_unused void *tx_queue,
467 	__rte_unused struct rte_mbuf **tx_pkts, __rte_unused uint16_t nb_pkts)
468 {
469 	return 0;
470 }
471 
472 int
473 i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
474 {
475 	struct i40e_vf_representor *representor = ethdev->data->dev_private;
476 
477 	struct i40e_pf *pf;
478 	struct i40e_pf_vf *vf;
479 	struct rte_eth_link *link;
480 
481 	representor->vf_id =
482 		((struct i40e_vf_representor *)init_params)->vf_id;
483 	representor->switch_domain_id =
484 		((struct i40e_vf_representor *)init_params)->switch_domain_id;
485 	representor->adapter =
486 		((struct i40e_vf_representor *)init_params)->adapter;
487 
488 	pf = I40E_DEV_PRIVATE_TO_PF(
489 		representor->adapter->eth_dev->data->dev_private);
490 
491 	if (representor->vf_id >= pf->vf_num)
492 		return -ENODEV;
493 
494 	/* Set representor device ops */
495 	ethdev->dev_ops = &i40e_representor_dev_ops;
496 
497 	/* No data-path, but need stub Rx/Tx functions to avoid crash
498 	 * when testing with the likes of testpmd.
499 	 */
500 	ethdev->rx_pkt_burst = i40e_vf_representor_rx_burst;
501 	ethdev->tx_pkt_burst = i40e_vf_representor_tx_burst;
502 
503 	vf = &pf->vfs[representor->vf_id];
504 
505 	if (!vf->vsi) {
506 		PMD_DRV_LOG(ERR, "Invalid VSI.");
507 		return -ENODEV;
508 	}
509 
510 	ethdev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
511 	ethdev->data->representor_id = representor->vf_id;
512 
513 	/* Setting the number queues allocated to the VF */
514 	ethdev->data->nb_rx_queues = vf->vsi->nb_qps;
515 	ethdev->data->nb_tx_queues = vf->vsi->nb_qps;
516 
517 	ethdev->data->mac_addrs = &vf->mac_addr;
518 
519 	/* Link state. Inherited from PF */
520 	link = &representor->adapter->eth_dev->data->dev_link;
521 
522 	ethdev->data->dev_link.link_speed = link->link_speed;
523 	ethdev->data->dev_link.link_duplex = link->link_duplex;
524 	ethdev->data->dev_link.link_status = link->link_status;
525 	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
526 
527 	return 0;
528 }
529 
530 int
531 i40e_vf_representor_uninit(struct rte_eth_dev *ethdev)
532 {
533 	/* mac_addrs must not be freed because part of i40e_pf_vf */
534 	ethdev->data->mac_addrs = NULL;
535 
536 	return 0;
537 }
538