xref: /f-stack/dpdk/drivers/net/mlx5/mlx5_trigger.c (revision 579bf1e2)
1a9643ea8Slogwang /*-
2a9643ea8Slogwang  *   BSD LICENSE
3a9643ea8Slogwang  *
4a9643ea8Slogwang  *   Copyright 2015 6WIND S.A.
5a9643ea8Slogwang  *   Copyright 2015 Mellanox.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  *   Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  *   modification, are permitted provided that the following conditions
9a9643ea8Slogwang  *   are met:
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     * Redistributions of source code must retain the above copyright
12a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer.
13a9643ea8Slogwang  *     * Redistributions in binary form must reproduce the above copyright
14a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer in
15a9643ea8Slogwang  *       the documentation and/or other materials provided with the
16a9643ea8Slogwang  *       distribution.
17a9643ea8Slogwang  *     * Neither the name of 6WIND S.A. nor the names of its
18a9643ea8Slogwang  *       contributors may be used to endorse or promote products derived
19a9643ea8Slogwang  *       from this software without specific prior written permission.
20a9643ea8Slogwang  *
21a9643ea8Slogwang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22a9643ea8Slogwang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23a9643ea8Slogwang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24a9643ea8Slogwang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25a9643ea8Slogwang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26a9643ea8Slogwang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27a9643ea8Slogwang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28a9643ea8Slogwang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29a9643ea8Slogwang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30a9643ea8Slogwang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31a9643ea8Slogwang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32a9643ea8Slogwang  */
332bfe3f2eSlogwang #include <unistd.h>
34a9643ea8Slogwang 
35a9643ea8Slogwang #include <rte_ether.h>
36a9643ea8Slogwang #include <rte_ethdev.h>
37a9643ea8Slogwang #include <rte_interrupts.h>
38a9643ea8Slogwang #include <rte_alarm.h>
39a9643ea8Slogwang 
40a9643ea8Slogwang #include "mlx5.h"
41a9643ea8Slogwang #include "mlx5_rxtx.h"
42a9643ea8Slogwang #include "mlx5_utils.h"
43a9643ea8Slogwang 
44*579bf1e2Sjfb8856606 /**
45*579bf1e2Sjfb8856606  * Stop traffic on Tx queues.
46*579bf1e2Sjfb8856606  *
47*579bf1e2Sjfb8856606  * @param dev
48*579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
49*579bf1e2Sjfb8856606  */
502bfe3f2eSlogwang static void
51*579bf1e2Sjfb8856606 mlx5_txq_stop(struct rte_eth_dev *dev)
522bfe3f2eSlogwang {
53*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
542bfe3f2eSlogwang 	unsigned int i;
552bfe3f2eSlogwang 
562bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i)
57*579bf1e2Sjfb8856606 		mlx5_txq_release(dev, i);
582bfe3f2eSlogwang }
592bfe3f2eSlogwang 
60*579bf1e2Sjfb8856606 /**
61*579bf1e2Sjfb8856606  * Start traffic on Tx queues.
62*579bf1e2Sjfb8856606  *
63*579bf1e2Sjfb8856606  * @param dev
64*579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
65*579bf1e2Sjfb8856606  *
66*579bf1e2Sjfb8856606  * @return
67*579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
68*579bf1e2Sjfb8856606  */
692bfe3f2eSlogwang static int
70*579bf1e2Sjfb8856606 mlx5_txq_start(struct rte_eth_dev *dev)
712bfe3f2eSlogwang {
72*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
732bfe3f2eSlogwang 	unsigned int i;
74*579bf1e2Sjfb8856606 	int ret;
752bfe3f2eSlogwang 
762bfe3f2eSlogwang 	for (i = 0; i != priv->txqs_n; ++i) {
772bfe3f2eSlogwang 		unsigned int idx = 0;
782bfe3f2eSlogwang 		struct mlx5_mr *mr;
79*579bf1e2Sjfb8856606 		struct mlx5_txq_ctrl *txq_ctrl = mlx5_txq_get(dev, i);
802bfe3f2eSlogwang 
812bfe3f2eSlogwang 		if (!txq_ctrl)
822bfe3f2eSlogwang 			continue;
832bfe3f2eSlogwang 		LIST_FOREACH(mr, &priv->mr, next) {
84*579bf1e2Sjfb8856606 			mlx5_txq_mp2mr_reg(&txq_ctrl->txq, mr->mp, idx++);
852bfe3f2eSlogwang 			if (idx == MLX5_PMD_TX_MP_CACHE)
862bfe3f2eSlogwang 				break;
872bfe3f2eSlogwang 		}
882bfe3f2eSlogwang 		txq_alloc_elts(txq_ctrl);
89*579bf1e2Sjfb8856606 		txq_ctrl->ibv = mlx5_txq_ibv_new(dev, i);
902bfe3f2eSlogwang 		if (!txq_ctrl->ibv) {
91*579bf1e2Sjfb8856606 			rte_errno = ENOMEM;
922bfe3f2eSlogwang 			goto error;
932bfe3f2eSlogwang 		}
942bfe3f2eSlogwang 	}
95*579bf1e2Sjfb8856606 	ret = mlx5_tx_uar_remap(dev, priv->ctx->cmd_fd);
96*579bf1e2Sjfb8856606 	if (ret) {
97*579bf1e2Sjfb8856606 		/* Adjust index for rollback. */
98*579bf1e2Sjfb8856606 		i = priv->txqs_n - 1;
99*579bf1e2Sjfb8856606 		goto error;
100*579bf1e2Sjfb8856606 	}
101*579bf1e2Sjfb8856606 	return 0;
1022bfe3f2eSlogwang error:
103*579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
104*579bf1e2Sjfb8856606 	do {
105*579bf1e2Sjfb8856606 		mlx5_txq_release(dev, i);
106*579bf1e2Sjfb8856606 	} while (i-- != 0);
107*579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
108*579bf1e2Sjfb8856606 	return -rte_errno;
1092bfe3f2eSlogwang }
1102bfe3f2eSlogwang 
111*579bf1e2Sjfb8856606 /**
112*579bf1e2Sjfb8856606  * Stop traffic on Rx queues.
113*579bf1e2Sjfb8856606  *
114*579bf1e2Sjfb8856606  * @param dev
115*579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
116*579bf1e2Sjfb8856606  */
1172bfe3f2eSlogwang static void
118*579bf1e2Sjfb8856606 mlx5_rxq_stop(struct rte_eth_dev *dev)
1192bfe3f2eSlogwang {
120*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
1212bfe3f2eSlogwang 	unsigned int i;
1222bfe3f2eSlogwang 
1232bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i)
124*579bf1e2Sjfb8856606 		mlx5_rxq_release(dev, i);
1252bfe3f2eSlogwang }
1262bfe3f2eSlogwang 
127*579bf1e2Sjfb8856606 /**
128*579bf1e2Sjfb8856606  * Start traffic on Rx queues.
129*579bf1e2Sjfb8856606  *
130*579bf1e2Sjfb8856606  * @param dev
131*579bf1e2Sjfb8856606  *   Pointer to Ethernet device structure.
132*579bf1e2Sjfb8856606  *
133*579bf1e2Sjfb8856606  * @return
134*579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
135*579bf1e2Sjfb8856606  */
1362bfe3f2eSlogwang static int
137*579bf1e2Sjfb8856606 mlx5_rxq_start(struct rte_eth_dev *dev)
1382bfe3f2eSlogwang {
139*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
1402bfe3f2eSlogwang 	unsigned int i;
1412bfe3f2eSlogwang 	int ret = 0;
1422bfe3f2eSlogwang 
1432bfe3f2eSlogwang 	for (i = 0; i != priv->rxqs_n; ++i) {
144*579bf1e2Sjfb8856606 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i);
1452bfe3f2eSlogwang 
1462bfe3f2eSlogwang 		if (!rxq_ctrl)
1472bfe3f2eSlogwang 			continue;
1482bfe3f2eSlogwang 		ret = rxq_alloc_elts(rxq_ctrl);
1492bfe3f2eSlogwang 		if (ret)
1502bfe3f2eSlogwang 			goto error;
151*579bf1e2Sjfb8856606 		rxq_ctrl->ibv = mlx5_rxq_ibv_new(dev, i);
152*579bf1e2Sjfb8856606 		if (!rxq_ctrl->ibv)
1532bfe3f2eSlogwang 			goto error;
1542bfe3f2eSlogwang 	}
155*579bf1e2Sjfb8856606 	return 0;
1562bfe3f2eSlogwang error:
157*579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
158*579bf1e2Sjfb8856606 	do {
159*579bf1e2Sjfb8856606 		mlx5_rxq_release(dev, i);
160*579bf1e2Sjfb8856606 	} while (i-- != 0);
161*579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
162*579bf1e2Sjfb8856606 	return -rte_errno;
1632bfe3f2eSlogwang }
1642bfe3f2eSlogwang 
165a9643ea8Slogwang /**
166a9643ea8Slogwang  * DPDK callback to start the device.
167a9643ea8Slogwang  *
168a9643ea8Slogwang  * Simulate device start by attaching all configured flows.
169a9643ea8Slogwang  *
170a9643ea8Slogwang  * @param dev
171a9643ea8Slogwang  *   Pointer to Ethernet device structure.
172a9643ea8Slogwang  *
173a9643ea8Slogwang  * @return
174*579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
175a9643ea8Slogwang  */
176a9643ea8Slogwang int
177a9643ea8Slogwang mlx5_dev_start(struct rte_eth_dev *dev)
178a9643ea8Slogwang {
179a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
1802bfe3f2eSlogwang 	struct mlx5_mr *mr = NULL;
181*579bf1e2Sjfb8856606 	int ret;
182a9643ea8Slogwang 
183*579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id);
184*579bf1e2Sjfb8856606 	ret = mlx5_flow_create_drop_queue(dev);
185*579bf1e2Sjfb8856606 	if (ret) {
186*579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u drop queue allocation failed: %s",
187*579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
1882bfe3f2eSlogwang 		goto error;
189a9643ea8Slogwang 	}
1902bfe3f2eSlogwang 	rte_mempool_walk(mlx5_mp2mr_iter, priv);
191*579bf1e2Sjfb8856606 	ret = mlx5_txq_start(dev);
192*579bf1e2Sjfb8856606 	if (ret) {
193*579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Tx queue allocation failed: %s",
194*579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
195*579bf1e2Sjfb8856606 		return -rte_errno;
196a9643ea8Slogwang 	}
197*579bf1e2Sjfb8856606 	ret = mlx5_rxq_start(dev);
198*579bf1e2Sjfb8856606 	if (ret) {
199*579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx queue allocation failed: %s",
200*579bf1e2Sjfb8856606 			dev->data->port_id, strerror(rte_errno));
201*579bf1e2Sjfb8856606 		mlx5_txq_stop(dev);
202*579bf1e2Sjfb8856606 		return -rte_errno;
2032bfe3f2eSlogwang 	}
204*579bf1e2Sjfb8856606 	dev->data->dev_started = 1;
205*579bf1e2Sjfb8856606 	ret = mlx5_rx_intr_vec_enable(dev);
206*579bf1e2Sjfb8856606 	if (ret) {
207*579bf1e2Sjfb8856606 		DRV_LOG(ERR, "port %u Rx interrupt vector creation failed",
2082bfe3f2eSlogwang 			dev->data->port_id);
2092bfe3f2eSlogwang 		goto error;
2102bfe3f2eSlogwang 	}
211*579bf1e2Sjfb8856606 	mlx5_xstats_init(dev);
212*579bf1e2Sjfb8856606 	ret = mlx5_traffic_enable(dev);
213*579bf1e2Sjfb8856606 	if (ret) {
214*579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set defaults flows",
215*579bf1e2Sjfb8856606 			dev->data->port_id);
216*579bf1e2Sjfb8856606 		goto error;
217*579bf1e2Sjfb8856606 	}
218*579bf1e2Sjfb8856606 	ret = mlx5_flow_start(dev, &priv->flows);
219*579bf1e2Sjfb8856606 	if (ret) {
220*579bf1e2Sjfb8856606 		DRV_LOG(DEBUG, "port %u failed to set flows",
221*579bf1e2Sjfb8856606 			dev->data->port_id);
222*579bf1e2Sjfb8856606 		goto error;
223*579bf1e2Sjfb8856606 	}
224*579bf1e2Sjfb8856606 	dev->tx_pkt_burst = mlx5_select_tx_function(dev);
225*579bf1e2Sjfb8856606 	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
226*579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_install(dev);
2272bfe3f2eSlogwang 	return 0;
2282bfe3f2eSlogwang error:
229*579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
2302bfe3f2eSlogwang 	/* Rollback. */
2312bfe3f2eSlogwang 	dev->data->dev_started = 0;
2322bfe3f2eSlogwang 	for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr))
233*579bf1e2Sjfb8856606 		mlx5_mr_release(mr);
234*579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
235*579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
236*579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
237*579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
238*579bf1e2Sjfb8856606 	mlx5_flow_delete_drop_queue(dev);
239*579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
240*579bf1e2Sjfb8856606 	return -rte_errno;
241a9643ea8Slogwang }
242a9643ea8Slogwang 
243a9643ea8Slogwang /**
244a9643ea8Slogwang  * DPDK callback to stop the device.
245a9643ea8Slogwang  *
246a9643ea8Slogwang  * Simulate device stop by detaching all configured flows.
247a9643ea8Slogwang  *
248a9643ea8Slogwang  * @param dev
249a9643ea8Slogwang  *   Pointer to Ethernet device structure.
250a9643ea8Slogwang  */
251a9643ea8Slogwang void
252a9643ea8Slogwang mlx5_dev_stop(struct rte_eth_dev *dev)
253a9643ea8Slogwang {
254a9643ea8Slogwang 	struct priv *priv = dev->data->dev_private;
2552bfe3f2eSlogwang 	struct mlx5_mr *mr;
256a9643ea8Slogwang 
2572bfe3f2eSlogwang 	dev->data->dev_started = 0;
2582bfe3f2eSlogwang 	/* Prevent crashes when queues are still in use. */
2592bfe3f2eSlogwang 	dev->rx_pkt_burst = removed_rx_burst;
2602bfe3f2eSlogwang 	dev->tx_pkt_burst = removed_tx_burst;
2612bfe3f2eSlogwang 	rte_wmb();
2622bfe3f2eSlogwang 	usleep(1000 * priv->rxqs_n);
263*579bf1e2Sjfb8856606 	DRV_LOG(DEBUG, "port %u stopping device", dev->data->port_id);
264*579bf1e2Sjfb8856606 	mlx5_flow_stop(dev, &priv->flows);
265*579bf1e2Sjfb8856606 	mlx5_traffic_disable(dev);
266*579bf1e2Sjfb8856606 	mlx5_rx_intr_vec_disable(dev);
267*579bf1e2Sjfb8856606 	mlx5_dev_interrupt_handler_uninstall(dev);
268*579bf1e2Sjfb8856606 	mlx5_txq_stop(dev);
269*579bf1e2Sjfb8856606 	mlx5_rxq_stop(dev);
2702bfe3f2eSlogwang 	for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr))
271*579bf1e2Sjfb8856606 		mlx5_mr_release(mr);
272*579bf1e2Sjfb8856606 	mlx5_flow_delete_drop_queue(dev);
273a9643ea8Slogwang }
2742bfe3f2eSlogwang 
2752bfe3f2eSlogwang /**
2762bfe3f2eSlogwang  * Enable traffic flows configured by control plane
2772bfe3f2eSlogwang  *
278*579bf1e2Sjfb8856606  * @param dev
2792bfe3f2eSlogwang  *   Pointer to Ethernet device private data.
2802bfe3f2eSlogwang  * @param dev
2812bfe3f2eSlogwang  *   Pointer to Ethernet device structure.
2822bfe3f2eSlogwang  *
2832bfe3f2eSlogwang  * @return
284*579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
2852bfe3f2eSlogwang  */
2862bfe3f2eSlogwang int
287*579bf1e2Sjfb8856606 mlx5_traffic_enable(struct rte_eth_dev *dev)
2882bfe3f2eSlogwang {
289*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
2902bfe3f2eSlogwang 	struct rte_flow_item_eth bcast = {
2912bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
2922bfe3f2eSlogwang 	};
2932bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_spec = {
2942bfe3f2eSlogwang 		.dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
2952bfe3f2eSlogwang 	};
2962bfe3f2eSlogwang 	struct rte_flow_item_eth ipv6_multi_mask = {
2972bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\x00\x00\x00\x00",
2982bfe3f2eSlogwang 	};
2992bfe3f2eSlogwang 	struct rte_flow_item_eth unicast = {
3002bfe3f2eSlogwang 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3012bfe3f2eSlogwang 	};
3022bfe3f2eSlogwang 	struct rte_flow_item_eth unicast_mask = {
3032bfe3f2eSlogwang 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
3042bfe3f2eSlogwang 	};
3052bfe3f2eSlogwang 	const unsigned int vlan_filter_n = priv->vlan_filter_n;
3062bfe3f2eSlogwang 	const struct ether_addr cmp = {
3072bfe3f2eSlogwang 		.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3082bfe3f2eSlogwang 	};
3092bfe3f2eSlogwang 	unsigned int i;
3102bfe3f2eSlogwang 	unsigned int j;
3112bfe3f2eSlogwang 	int ret;
3122bfe3f2eSlogwang 
3132bfe3f2eSlogwang 	if (priv->isolated)
3142bfe3f2eSlogwang 		return 0;
3152bfe3f2eSlogwang 	if (dev->data->promiscuous) {
3162bfe3f2eSlogwang 		struct rte_flow_item_eth promisc = {
3172bfe3f2eSlogwang 			.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3182bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3192bfe3f2eSlogwang 			.type = 0,
3202bfe3f2eSlogwang 		};
3212bfe3f2eSlogwang 
322*579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &promisc, &promisc);
323*579bf1e2Sjfb8856606 		if (ret)
324*579bf1e2Sjfb8856606 			goto error;
3252bfe3f2eSlogwang 	}
3262bfe3f2eSlogwang 	if (dev->data->all_multicast) {
3272bfe3f2eSlogwang 		struct rte_flow_item_eth multicast = {
3282bfe3f2eSlogwang 			.dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
3292bfe3f2eSlogwang 			.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
3302bfe3f2eSlogwang 			.type = 0,
3312bfe3f2eSlogwang 		};
3322bfe3f2eSlogwang 
333*579bf1e2Sjfb8856606 		ret = mlx5_ctrl_flow(dev, &multicast, &multicast);
334*579bf1e2Sjfb8856606 		if (ret)
335*579bf1e2Sjfb8856606 			goto error;
3362bfe3f2eSlogwang 	} else {
3372bfe3f2eSlogwang 		/* Add broadcast/multicast flows. */
3382bfe3f2eSlogwang 		for (i = 0; i != vlan_filter_n; ++i) {
3392bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[i];
3402bfe3f2eSlogwang 
3412bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
3422bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
3432bfe3f2eSlogwang 			};
344*579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
345*579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
3462bfe3f2eSlogwang 
3472bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &bcast, &bcast,
3482bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
3492bfe3f2eSlogwang 			if (ret)
3502bfe3f2eSlogwang 				goto error;
3512bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &ipv6_multi_spec,
3522bfe3f2eSlogwang 						  &ipv6_multi_mask,
3532bfe3f2eSlogwang 						  &vlan_spec, &vlan_mask);
3542bfe3f2eSlogwang 			if (ret)
3552bfe3f2eSlogwang 				goto error;
3562bfe3f2eSlogwang 		}
3572bfe3f2eSlogwang 		if (!vlan_filter_n) {
3582bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &bcast, &bcast);
3592bfe3f2eSlogwang 			if (ret)
3602bfe3f2eSlogwang 				goto error;
3612bfe3f2eSlogwang 			ret = mlx5_ctrl_flow(dev, &ipv6_multi_spec,
3622bfe3f2eSlogwang 					     &ipv6_multi_mask);
3632bfe3f2eSlogwang 			if (ret)
3642bfe3f2eSlogwang 				goto error;
3652bfe3f2eSlogwang 		}
3662bfe3f2eSlogwang 	}
3672bfe3f2eSlogwang 	/* Add MAC address flows. */
3682bfe3f2eSlogwang 	for (i = 0; i != MLX5_MAX_MAC_ADDRESSES; ++i) {
3692bfe3f2eSlogwang 		struct ether_addr *mac = &dev->data->mac_addrs[i];
3702bfe3f2eSlogwang 
3712bfe3f2eSlogwang 		if (!memcmp(mac, &cmp, sizeof(*mac)))
3722bfe3f2eSlogwang 			continue;
3732bfe3f2eSlogwang 		memcpy(&unicast.dst.addr_bytes,
3742bfe3f2eSlogwang 		       mac->addr_bytes,
3752bfe3f2eSlogwang 		       ETHER_ADDR_LEN);
3762bfe3f2eSlogwang 		for (j = 0; j != vlan_filter_n; ++j) {
3772bfe3f2eSlogwang 			uint16_t vlan = priv->vlan_filter[j];
3782bfe3f2eSlogwang 
3792bfe3f2eSlogwang 			struct rte_flow_item_vlan vlan_spec = {
3802bfe3f2eSlogwang 				.tci = rte_cpu_to_be_16(vlan),
3812bfe3f2eSlogwang 			};
382*579bf1e2Sjfb8856606 			struct rte_flow_item_vlan vlan_mask =
383*579bf1e2Sjfb8856606 				rte_flow_item_vlan_mask;
3842bfe3f2eSlogwang 
3852bfe3f2eSlogwang 			ret = mlx5_ctrl_flow_vlan(dev, &unicast,
3862bfe3f2eSlogwang 						  &unicast_mask,
3872bfe3f2eSlogwang 						  &vlan_spec,
3882bfe3f2eSlogwang 						  &vlan_mask);
3892bfe3f2eSlogwang 			if (ret)
3902bfe3f2eSlogwang 				goto error;
3912bfe3f2eSlogwang 		}
3922bfe3f2eSlogwang 		if (!vlan_filter_n) {
393*579bf1e2Sjfb8856606 			ret = mlx5_ctrl_flow(dev, &unicast, &unicast_mask);
3942bfe3f2eSlogwang 			if (ret)
3952bfe3f2eSlogwang 				goto error;
3962bfe3f2eSlogwang 		}
3972bfe3f2eSlogwang 	}
3982bfe3f2eSlogwang 	return 0;
3992bfe3f2eSlogwang error:
400*579bf1e2Sjfb8856606 	ret = rte_errno; /* Save rte_errno before cleanup. */
401*579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
402*579bf1e2Sjfb8856606 	rte_errno = ret; /* Restore rte_errno. */
403*579bf1e2Sjfb8856606 	return -rte_errno;
4042bfe3f2eSlogwang }
4052bfe3f2eSlogwang 
4062bfe3f2eSlogwang 
4072bfe3f2eSlogwang /**
4082bfe3f2eSlogwang  * Disable traffic flows configured by control plane
4092bfe3f2eSlogwang  *
4102bfe3f2eSlogwang  * @param dev
411*579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
4122bfe3f2eSlogwang  */
413*579bf1e2Sjfb8856606 void
414*579bf1e2Sjfb8856606 mlx5_traffic_disable(struct rte_eth_dev *dev)
4152bfe3f2eSlogwang {
416*579bf1e2Sjfb8856606 	struct priv *priv = dev->data->dev_private;
4172bfe3f2eSlogwang 
418*579bf1e2Sjfb8856606 	mlx5_flow_list_flush(dev, &priv->ctrl_flows);
4192bfe3f2eSlogwang }
4202bfe3f2eSlogwang 
4212bfe3f2eSlogwang /**
4222bfe3f2eSlogwang  * Restart traffic flows configured by control plane
4232bfe3f2eSlogwang  *
4242bfe3f2eSlogwang  * @param dev
425*579bf1e2Sjfb8856606  *   Pointer to Ethernet device private data.
4262bfe3f2eSlogwang  *
4272bfe3f2eSlogwang  * @return
428*579bf1e2Sjfb8856606  *   0 on success, a negative errno value otherwise and rte_errno is set.
4292bfe3f2eSlogwang  */
4302bfe3f2eSlogwang int
4312bfe3f2eSlogwang mlx5_traffic_restart(struct rte_eth_dev *dev)
4322bfe3f2eSlogwang {
433*579bf1e2Sjfb8856606 	if (dev->data->dev_started) {
434*579bf1e2Sjfb8856606 		mlx5_traffic_disable(dev);
435*579bf1e2Sjfb8856606 		return mlx5_traffic_enable(dev);
436*579bf1e2Sjfb8856606 	}
4372bfe3f2eSlogwang 	return 0;
4382bfe3f2eSlogwang }
439