xref: /dpdk/drivers/net/mlx5/mlx5_vlan.c (revision 465328609aeca77f455175b12440233dbcc5a826)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2e9086978SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
35feecc57SShahaf Shuler  * Copyright 2015 Mellanox Technologies, Ltd
4e9086978SAdrien Mazarguil  */
5e9086978SAdrien Mazarguil 
6e9086978SAdrien Mazarguil #include <stddef.h>
7e9086978SAdrien Mazarguil #include <errno.h>
8e9086978SAdrien Mazarguil #include <stdint.h>
9c12671e3SMatan Azrad #include <unistd.h>
10c12671e3SMatan Azrad 
11df96fd0dSBruce Richardson #include <ethdev_driver.h>
12e9086978SAdrien Mazarguil #include <rte_common.h>
13c12671e3SMatan Azrad #include <rte_malloc.h>
14c12671e3SMatan Azrad #include <rte_hypervisor.h>
15e9086978SAdrien Mazarguil 
16e9086978SAdrien Mazarguil #include "mlx5.h"
17f3db9489SYaacov Hazan #include "mlx5_autoconf.h"
18227684feSYongseok Koh #include "mlx5_rxtx.h"
19151cbe3aSMichael Baum #include "mlx5_rx.h"
20227684feSYongseok Koh #include "mlx5_utils.h"
218bb2410eSOphir Munk #include "mlx5_devx.h"
22e9086978SAdrien Mazarguil 
23e9086978SAdrien Mazarguil /**
24e9086978SAdrien Mazarguil  * DPDK callback to configure a VLAN filter.
25e9086978SAdrien Mazarguil  *
26e9086978SAdrien Mazarguil  * @param dev
27e9086978SAdrien Mazarguil  *   Pointer to Ethernet device structure.
28e9086978SAdrien Mazarguil  * @param vlan_id
29e9086978SAdrien Mazarguil  *   VLAN ID to filter.
30e9086978SAdrien Mazarguil  * @param on
31e9086978SAdrien Mazarguil  *   Toggle filter.
32e9086978SAdrien Mazarguil  *
33e9086978SAdrien Mazarguil  * @return
34a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
35e9086978SAdrien Mazarguil  */
36e9086978SAdrien Mazarguil int
37e9086978SAdrien Mazarguil mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
38e9086978SAdrien Mazarguil {
39dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
40272733b5SNélio Laranjeiro 	unsigned int i;
41e9086978SAdrien Mazarguil 
42a170a30dSNélio Laranjeiro 	DRV_LOG(DEBUG, "port %u %s VLAN filter ID %" PRIu16,
430f99970bSNélio Laranjeiro 		dev->data->port_id, (on ? "enable" : "disable"), vlan_id);
448e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(priv->vlan_filter_n <= RTE_DIM(priv->vlan_filter));
45272733b5SNélio Laranjeiro 	for (i = 0; (i != priv->vlan_filter_n); ++i)
46272733b5SNélio Laranjeiro 		if (priv->vlan_filter[i] == vlan_id)
47272733b5SNélio Laranjeiro 			break;
48e4aefd6dSNélio Laranjeiro 	/* Check if there's room for another VLAN filter. */
49e4aefd6dSNélio Laranjeiro 	if (i == RTE_DIM(priv->vlan_filter)) {
50a6d83b6aSNélio Laranjeiro 		rte_errno = ENOMEM;
51a6d83b6aSNélio Laranjeiro 		return -rte_errno;
52e4aefd6dSNélio Laranjeiro 	}
53272733b5SNélio Laranjeiro 	if (i < priv->vlan_filter_n) {
548e46d4e1SAlexander Kozyrev 		MLX5_ASSERT(priv->vlan_filter_n != 0);
55272733b5SNélio Laranjeiro 		/* Enabling an existing VLAN filter has no effect. */
56272733b5SNélio Laranjeiro 		if (on)
57*46532860SDariusz Sosnowski 			goto no_effect;
58272733b5SNélio Laranjeiro 		/* Remove VLAN filter from list. */
59272733b5SNélio Laranjeiro 		--priv->vlan_filter_n;
60272733b5SNélio Laranjeiro 		memmove(&priv->vlan_filter[i],
61272733b5SNélio Laranjeiro 			&priv->vlan_filter[i + 1],
62272733b5SNélio Laranjeiro 			sizeof(priv->vlan_filter[i]) *
63272733b5SNélio Laranjeiro 			(priv->vlan_filter_n - i));
64272733b5SNélio Laranjeiro 		priv->vlan_filter[priv->vlan_filter_n] = 0;
65272733b5SNélio Laranjeiro 	} else {
668e46d4e1SAlexander Kozyrev 		MLX5_ASSERT(i == priv->vlan_filter_n);
67272733b5SNélio Laranjeiro 		/* Disabling an unknown VLAN filter has no effect. */
68272733b5SNélio Laranjeiro 		if (!on)
69*46532860SDariusz Sosnowski 			goto no_effect;
70272733b5SNélio Laranjeiro 		/* Add new VLAN filter. */
71272733b5SNélio Laranjeiro 		priv->vlan_filter[priv->vlan_filter_n] = vlan_id;
72272733b5SNélio Laranjeiro 		++priv->vlan_filter_n;
73272733b5SNélio Laranjeiro 	}
74*46532860SDariusz Sosnowski 	return on ? mlx5_traffic_vlan_add(dev, vlan_id) : mlx5_traffic_vlan_remove(dev, vlan_id);
75*46532860SDariusz Sosnowski no_effect:
76a6d83b6aSNélio Laranjeiro 	return 0;
77e9086978SAdrien Mazarguil }
78f3db9489SYaacov Hazan 
79f3db9489SYaacov Hazan /**
80f3db9489SYaacov Hazan  * Callback to set/reset VLAN stripping for a specific queue.
81f3db9489SYaacov Hazan  *
82f3db9489SYaacov Hazan  * @param dev
83f3db9489SYaacov Hazan  *   Pointer to Ethernet device structure.
84f3db9489SYaacov Hazan  * @param queue
85f3db9489SYaacov Hazan  *   RX queue index.
86f3db9489SYaacov Hazan  * @param on
87f3db9489SYaacov Hazan  *   Enable/disable VLAN stripping.
88f3db9489SYaacov Hazan  */
89f3db9489SYaacov Hazan void
90f3db9489SYaacov Hazan mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on)
91f3db9489SYaacov Hazan {
92dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
935ceb3a02SXueming Li 	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queue);
945ceb3a02SXueming Li 	struct mlx5_rxq_data *rxq_data = &rxq->ctrl->rxq;
95dc9ceff7SDekel Peled 	int ret = 0;
96f3db9489SYaacov Hazan 
975ceb3a02SXueming Li 	MLX5_ASSERT(rxq != NULL && rxq->ctrl != NULL);
98f3db9489SYaacov Hazan 	/* Validate hw support */
9987af0d1eSMichael Baum 	if (!priv->sh->dev_cap.hw_vlan_strip) {
100a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u VLAN stripping is not supported",
1010f99970bSNélio Laranjeiro 			dev->data->port_id);
102f3db9489SYaacov Hazan 		return;
103f3db9489SYaacov Hazan 	}
104f3db9489SYaacov Hazan 	/* Validate queue number */
105f3db9489SYaacov Hazan 	if (queue >= priv->rxqs_n) {
106a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u VLAN stripping, invalid queue number %d",
1070f99970bSNélio Laranjeiro 			dev->data->port_id, queue);
108f3db9489SYaacov Hazan 		return;
109f3db9489SYaacov Hazan 	}
1108bb2410eSOphir Munk 	DRV_LOG(DEBUG, "port %u set VLAN stripping offloads %d for port %uqueue %d",
1115ceb3a02SXueming Li 		dev->data->port_id, on, rxq_data->port_id, queue);
1125ceb3a02SXueming Li 	if (rxq->ctrl->obj == NULL) {
113af4f09f2SNélio Laranjeiro 		/* Update related bits in RX queue. */
1145ceb3a02SXueming Li 		rxq_data->vlan_strip = !!on;
115af4f09f2SNélio Laranjeiro 		return;
116af4f09f2SNélio Laranjeiro 	}
1175ceb3a02SXueming Li 	ret = priv->obj_ops.rxq_obj_modify_vlan_strip(rxq, on);
118a6d83b6aSNélio Laranjeiro 	if (ret) {
119e96242efSMichael Baum 		DRV_LOG(ERR, "Port %u failed to modify object stripping mode:"
120e96242efSMichael Baum 			" %s", dev->data->port_id, strerror(rte_errno));
121af4f09f2SNélio Laranjeiro 		return;
122af4f09f2SNélio Laranjeiro 	}
123af4f09f2SNélio Laranjeiro 	/* Update related bits in RX queue. */
1245ceb3a02SXueming Li 	rxq_data->vlan_strip = !!on;
125f3db9489SYaacov Hazan }
126f3db9489SYaacov Hazan 
127f3db9489SYaacov Hazan /**
128f3db9489SYaacov Hazan  * Callback to set/reset VLAN offloads for a port.
129f3db9489SYaacov Hazan  *
130f3db9489SYaacov Hazan  * @param dev
131f3db9489SYaacov Hazan  *   Pointer to Ethernet device structure.
132f3db9489SYaacov Hazan  * @param mask
133f3db9489SYaacov Hazan  *   VLAN offload bit mask.
134a6d83b6aSNélio Laranjeiro  *
135a6d83b6aSNélio Laranjeiro  * @return
136a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
137f3db9489SYaacov Hazan  */
138289ba0c0SDavid Harton int
139f3db9489SYaacov Hazan mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask)
140f3db9489SYaacov Hazan {
141dbeba4cfSThomas Monjalon 	struct mlx5_priv *priv = dev->data->dev_private;
142f3db9489SYaacov Hazan 	unsigned int i;
143f3db9489SYaacov Hazan 
144295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
14517b843ebSShahaf Shuler 		int hw_vlan_strip = !!(dev->data->dev_conf.rxmode.offloads &
146295968d1SFerruh Yigit 				       RTE_ETH_RX_OFFLOAD_VLAN_STRIP);
147f3db9489SYaacov Hazan 
14887af0d1eSMichael Baum 		if (!priv->sh->dev_cap.hw_vlan_strip) {
149a170a30dSNélio Laranjeiro 			DRV_LOG(ERR, "port %u VLAN stripping is not supported",
1500f99970bSNélio Laranjeiro 				dev->data->port_id);
151289ba0c0SDavid Harton 			return 0;
152f3db9489SYaacov Hazan 		}
153f3db9489SYaacov Hazan 		/* Run on every RX queue and set/reset VLAN stripping. */
154f3db9489SYaacov Hazan 		for (i = 0; (i != priv->rxqs_n); i++)
155af4f09f2SNélio Laranjeiro 			mlx5_vlan_strip_queue_set(dev, i, hw_vlan_strip);
156f3db9489SYaacov Hazan 	}
157289ba0c0SDavid Harton 	return 0;
158f3db9489SYaacov Hazan }
159