xref: /dpdk/drivers/net/mlx5/mlx5_rxmode.c (revision 1b37f5d898349d70aaf1b8427694ca5b7a669d8f)
11bdbe1afSAdrien Mazarguil /*-
21bdbe1afSAdrien Mazarguil  *   BSD LICENSE
31bdbe1afSAdrien Mazarguil  *
41bdbe1afSAdrien Mazarguil  *   Copyright 2015 6WIND S.A.
51bdbe1afSAdrien Mazarguil  *   Copyright 2015 Mellanox.
61bdbe1afSAdrien Mazarguil  *
71bdbe1afSAdrien Mazarguil  *   Redistribution and use in source and binary forms, with or without
81bdbe1afSAdrien Mazarguil  *   modification, are permitted provided that the following conditions
91bdbe1afSAdrien Mazarguil  *   are met:
101bdbe1afSAdrien Mazarguil  *
111bdbe1afSAdrien Mazarguil  *     * Redistributions of source code must retain the above copyright
121bdbe1afSAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer.
131bdbe1afSAdrien Mazarguil  *     * Redistributions in binary form must reproduce the above copyright
141bdbe1afSAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer in
151bdbe1afSAdrien Mazarguil  *       the documentation and/or other materials provided with the
161bdbe1afSAdrien Mazarguil  *       distribution.
171bdbe1afSAdrien Mazarguil  *     * Neither the name of 6WIND S.A. nor the names of its
181bdbe1afSAdrien Mazarguil  *       contributors may be used to endorse or promote products derived
191bdbe1afSAdrien Mazarguil  *       from this software without specific prior written permission.
201bdbe1afSAdrien Mazarguil  *
211bdbe1afSAdrien Mazarguil  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
221bdbe1afSAdrien Mazarguil  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
231bdbe1afSAdrien Mazarguil  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
241bdbe1afSAdrien Mazarguil  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
251bdbe1afSAdrien Mazarguil  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
261bdbe1afSAdrien Mazarguil  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
271bdbe1afSAdrien Mazarguil  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
281bdbe1afSAdrien Mazarguil  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
291bdbe1afSAdrien Mazarguil  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
301bdbe1afSAdrien Mazarguil  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
311bdbe1afSAdrien Mazarguil  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321bdbe1afSAdrien Mazarguil  */
331bdbe1afSAdrien Mazarguil 
341bdbe1afSAdrien Mazarguil #include <stddef.h>
351bdbe1afSAdrien Mazarguil #include <errno.h>
361bdbe1afSAdrien Mazarguil #include <string.h>
371bdbe1afSAdrien Mazarguil 
381bdbe1afSAdrien Mazarguil /* Verbs header. */
391bdbe1afSAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
401bdbe1afSAdrien Mazarguil #ifdef PEDANTIC
41fc5b160fSBruce Richardson #pragma GCC diagnostic ignored "-Wpedantic"
421bdbe1afSAdrien Mazarguil #endif
431bdbe1afSAdrien Mazarguil #include <infiniband/verbs.h>
441bdbe1afSAdrien Mazarguil #ifdef PEDANTIC
45fc5b160fSBruce Richardson #pragma GCC diagnostic error "-Wpedantic"
461bdbe1afSAdrien Mazarguil #endif
471bdbe1afSAdrien Mazarguil 
481bdbe1afSAdrien Mazarguil #include <rte_ethdev.h>
491bdbe1afSAdrien Mazarguil 
501bdbe1afSAdrien Mazarguil #include "mlx5.h"
511bdbe1afSAdrien Mazarguil #include "mlx5_rxtx.h"
521bdbe1afSAdrien Mazarguil #include "mlx5_utils.h"
531bdbe1afSAdrien Mazarguil 
54083c2dd3SYaacov Hazan /* Initialization data for special flows. */
55083c2dd3SYaacov Hazan static const struct special_flow_init special_flow_init[] = {
56083c2dd3SYaacov Hazan 	[HASH_RXQ_FLOW_TYPE_ALLMULTI] = {
57083c2dd3SYaacov Hazan 		.dst_mac_val = "\x01\x00\x00\x00\x00\x00",
58083c2dd3SYaacov Hazan 		.dst_mac_mask = "\x01\x00\x00\x00\x00\x00",
59083c2dd3SYaacov Hazan 		.hash_types =
60083c2dd3SYaacov Hazan 			1 << HASH_RXQ_UDPV4 |
61083c2dd3SYaacov Hazan 			1 << HASH_RXQ_IPV4 |
62083c2dd3SYaacov Hazan 			1 << HASH_RXQ_UDPV6 |
63083c2dd3SYaacov Hazan 			1 << HASH_RXQ_IPV6 |
64083c2dd3SYaacov Hazan 			1 << HASH_RXQ_ETH |
65083c2dd3SYaacov Hazan 			0,
66188b8ccdSAdrien Mazarguil 		.per_vlan = 0,
67083c2dd3SYaacov Hazan 	},
680497ddaaSYaacov Hazan 	[HASH_RXQ_FLOW_TYPE_BROADCAST] = {
690497ddaaSYaacov Hazan 		.dst_mac_val = "\xff\xff\xff\xff\xff\xff",
700497ddaaSYaacov Hazan 		.dst_mac_mask = "\xff\xff\xff\xff\xff\xff",
710497ddaaSYaacov Hazan 		.hash_types =
720497ddaaSYaacov Hazan 			1 << HASH_RXQ_UDPV4 |
730497ddaaSYaacov Hazan 			1 << HASH_RXQ_IPV4 |
740497ddaaSYaacov Hazan 			1 << HASH_RXQ_UDPV6 |
750497ddaaSYaacov Hazan 			1 << HASH_RXQ_IPV6 |
760497ddaaSYaacov Hazan 			1 << HASH_RXQ_ETH |
770497ddaaSYaacov Hazan 			0,
78188b8ccdSAdrien Mazarguil 		.per_vlan = 1,
790497ddaaSYaacov Hazan 	},
800497ddaaSYaacov Hazan 	[HASH_RXQ_FLOW_TYPE_IPV6MULTI] = {
810497ddaaSYaacov Hazan 		.dst_mac_val = "\x33\x33\x00\x00\x00\x00",
820497ddaaSYaacov Hazan 		.dst_mac_mask = "\xff\xff\x00\x00\x00\x00",
830497ddaaSYaacov Hazan 		.hash_types =
840497ddaaSYaacov Hazan 			1 << HASH_RXQ_UDPV6 |
850497ddaaSYaacov Hazan 			1 << HASH_RXQ_IPV6 |
860497ddaaSYaacov Hazan 			1 << HASH_RXQ_ETH |
870497ddaaSYaacov Hazan 			0,
88188b8ccdSAdrien Mazarguil 		.per_vlan = 1,
890497ddaaSYaacov Hazan 	},
90083c2dd3SYaacov Hazan };
91ecc1c29dSAdrien Mazarguil 
921bdbe1afSAdrien Mazarguil /**
93188b8ccdSAdrien Mazarguil  * Enable a special flow in a hash RX queue for a given VLAN index.
941bdbe1afSAdrien Mazarguil  *
95ecc1c29dSAdrien Mazarguil  * @param hash_rxq
96ecc1c29dSAdrien Mazarguil  *   Pointer to hash RX queue structure.
97083c2dd3SYaacov Hazan  * @param flow_type
98083c2dd3SYaacov Hazan  *   Special flow type.
99188b8ccdSAdrien Mazarguil  * @param vlan_index
100188b8ccdSAdrien Mazarguil  *   VLAN index to use.
1011bdbe1afSAdrien Mazarguil  *
1021bdbe1afSAdrien Mazarguil  * @return
1031bdbe1afSAdrien Mazarguil  *   0 on success, errno value on failure.
1041bdbe1afSAdrien Mazarguil  */
105ecc1c29dSAdrien Mazarguil static int
106188b8ccdSAdrien Mazarguil hash_rxq_special_flow_enable_vlan(struct hash_rxq *hash_rxq,
107188b8ccdSAdrien Mazarguil 				  enum hash_rxq_flow_type flow_type,
108188b8ccdSAdrien Mazarguil 				  unsigned int vlan_index)
1091bdbe1afSAdrien Mazarguil {
1101a56bdacSYaacov Hazan 	struct priv *priv = hash_rxq->priv;
11143e9d979SShachar Beiser 	struct ibv_flow *flow;
1121a56bdacSYaacov Hazan 	FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
11343e9d979SShachar Beiser 	struct ibv_flow_attr *attr = &data->attr;
11443e9d979SShachar Beiser 	struct ibv_flow_spec_eth *spec = &data->spec;
115083c2dd3SYaacov Hazan 	const uint8_t *mac;
116083c2dd3SYaacov Hazan 	const uint8_t *mask;
117188b8ccdSAdrien Mazarguil 	unsigned int vlan_enabled = (priv->vlan_filter_n &&
118188b8ccdSAdrien Mazarguil 				     special_flow_init[flow_type].per_vlan);
119188b8ccdSAdrien Mazarguil 	unsigned int vlan_id = priv->vlan_filter[vlan_index];
1201bdbe1afSAdrien Mazarguil 
121083c2dd3SYaacov Hazan 	/* Check if flow is relevant for this hash_rxq. */
122083c2dd3SYaacov Hazan 	if (!(special_flow_init[flow_type].hash_types & (1 << hash_rxq->type)))
1231bdbe1afSAdrien Mazarguil 		return 0;
124083c2dd3SYaacov Hazan 	/* Check if flow already exists. */
125188b8ccdSAdrien Mazarguil 	if (hash_rxq->special_flow[flow_type][vlan_index] != NULL)
126083c2dd3SYaacov Hazan 		return 0;
127083c2dd3SYaacov Hazan 
128083c2dd3SYaacov Hazan 	/*
129083c2dd3SYaacov Hazan 	 * No padding must be inserted by the compiler between attr and spec.
130083c2dd3SYaacov Hazan 	 * This layout is expected by libibverbs.
131083c2dd3SYaacov Hazan 	 */
132083c2dd3SYaacov Hazan 	assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
1331a56bdacSYaacov Hazan 	priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
134083c2dd3SYaacov Hazan 	/* The first specification must be Ethernet. */
13543e9d979SShachar Beiser 	assert(spec->type == IBV_FLOW_SPEC_ETH);
136083c2dd3SYaacov Hazan 	assert(spec->size == sizeof(*spec));
137083c2dd3SYaacov Hazan 
138083c2dd3SYaacov Hazan 	mac = special_flow_init[flow_type].dst_mac_val;
139083c2dd3SYaacov Hazan 	mask = special_flow_init[flow_type].dst_mac_mask;
14043e9d979SShachar Beiser 	*spec = (struct ibv_flow_spec_eth){
14143e9d979SShachar Beiser 		.type = IBV_FLOW_SPEC_ETH,
142083c2dd3SYaacov Hazan 		.size = sizeof(*spec),
143083c2dd3SYaacov Hazan 		.val = {
144083c2dd3SYaacov Hazan 			.dst_mac = {
145083c2dd3SYaacov Hazan 				mac[0], mac[1], mac[2],
146083c2dd3SYaacov Hazan 				mac[3], mac[4], mac[5],
147083c2dd3SYaacov Hazan 			},
1486b30a6a8SShachar Beiser 			.vlan_tag = (vlan_enabled ?
1496b30a6a8SShachar Beiser 				     rte_cpu_to_be_16(vlan_id) :
1506b30a6a8SShachar Beiser 				     0),
151083c2dd3SYaacov Hazan 		},
152083c2dd3SYaacov Hazan 		.mask = {
153083c2dd3SYaacov Hazan 			.dst_mac = {
154083c2dd3SYaacov Hazan 				mask[0], mask[1], mask[2],
155083c2dd3SYaacov Hazan 				mask[3], mask[4], mask[5],
156083c2dd3SYaacov Hazan 			},
1576b30a6a8SShachar Beiser 			.vlan_tag = (vlan_enabled ?
1586b30a6a8SShachar Beiser 				     rte_cpu_to_be_16(0xfff) :
1596b30a6a8SShachar Beiser 				     0),
160083c2dd3SYaacov Hazan 		},
161083c2dd3SYaacov Hazan 	};
162083c2dd3SYaacov Hazan 
1631bdbe1afSAdrien Mazarguil 	errno = 0;
16443e9d979SShachar Beiser 	flow = ibv_create_flow(hash_rxq->qp, attr);
1651bdbe1afSAdrien Mazarguil 	if (flow == NULL) {
1661bdbe1afSAdrien Mazarguil 		/* It's not clear whether errno is always set in this case. */
1671bdbe1afSAdrien Mazarguil 		ERROR("%p: flow configuration failed, errno=%d: %s",
168ecc1c29dSAdrien Mazarguil 		      (void *)hash_rxq, errno,
1691bdbe1afSAdrien Mazarguil 		      (errno ? strerror(errno) : "Unknown error"));
1701bdbe1afSAdrien Mazarguil 		if (errno)
1711bdbe1afSAdrien Mazarguil 			return errno;
1721bdbe1afSAdrien Mazarguil 		return EINVAL;
1731bdbe1afSAdrien Mazarguil 	}
174188b8ccdSAdrien Mazarguil 	hash_rxq->special_flow[flow_type][vlan_index] = flow;
175188b8ccdSAdrien Mazarguil 	DEBUG("%p: special flow %s (index %d) VLAN %u (index %u) enabled",
176188b8ccdSAdrien Mazarguil 	      (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type,
177188b8ccdSAdrien Mazarguil 	      vlan_id, vlan_index);
178188b8ccdSAdrien Mazarguil 	return 0;
179188b8ccdSAdrien Mazarguil }
180188b8ccdSAdrien Mazarguil 
181188b8ccdSAdrien Mazarguil /**
182188b8ccdSAdrien Mazarguil  * Disable a special flow in a hash RX queue for a given VLAN index.
183188b8ccdSAdrien Mazarguil  *
184188b8ccdSAdrien Mazarguil  * @param hash_rxq
185188b8ccdSAdrien Mazarguil  *   Pointer to hash RX queue structure.
186188b8ccdSAdrien Mazarguil  * @param flow_type
187188b8ccdSAdrien Mazarguil  *   Special flow type.
188188b8ccdSAdrien Mazarguil  * @param vlan_index
189188b8ccdSAdrien Mazarguil  *   VLAN index to use.
190188b8ccdSAdrien Mazarguil  */
191188b8ccdSAdrien Mazarguil static void
192188b8ccdSAdrien Mazarguil hash_rxq_special_flow_disable_vlan(struct hash_rxq *hash_rxq,
193188b8ccdSAdrien Mazarguil 				   enum hash_rxq_flow_type flow_type,
194188b8ccdSAdrien Mazarguil 				   unsigned int vlan_index)
195188b8ccdSAdrien Mazarguil {
19643e9d979SShachar Beiser 	struct ibv_flow *flow =
197188b8ccdSAdrien Mazarguil 		hash_rxq->special_flow[flow_type][vlan_index];
198188b8ccdSAdrien Mazarguil 
199188b8ccdSAdrien Mazarguil 	if (flow == NULL)
200188b8ccdSAdrien Mazarguil 		return;
20143e9d979SShachar Beiser 	claim_zero(ibv_destroy_flow(flow));
202188b8ccdSAdrien Mazarguil 	hash_rxq->special_flow[flow_type][vlan_index] = NULL;
203188b8ccdSAdrien Mazarguil 	DEBUG("%p: special flow %s (index %d) VLAN %u (index %u) disabled",
204188b8ccdSAdrien Mazarguil 	      (void *)hash_rxq, hash_rxq_flow_type_str(flow_type), flow_type,
205188b8ccdSAdrien Mazarguil 	      hash_rxq->priv->vlan_filter[vlan_index], vlan_index);
206188b8ccdSAdrien Mazarguil }
207188b8ccdSAdrien Mazarguil 
208188b8ccdSAdrien Mazarguil /**
209188b8ccdSAdrien Mazarguil  * Enable a special flow in a hash RX queue.
210188b8ccdSAdrien Mazarguil  *
211188b8ccdSAdrien Mazarguil  * @param hash_rxq
212188b8ccdSAdrien Mazarguil  *   Pointer to hash RX queue structure.
213188b8ccdSAdrien Mazarguil  * @param flow_type
214188b8ccdSAdrien Mazarguil  *   Special flow type.
215188b8ccdSAdrien Mazarguil  * @param vlan_index
216188b8ccdSAdrien Mazarguil  *   VLAN index to use.
217188b8ccdSAdrien Mazarguil  *
218188b8ccdSAdrien Mazarguil  * @return
219188b8ccdSAdrien Mazarguil  *   0 on success, errno value on failure.
220188b8ccdSAdrien Mazarguil  */
221188b8ccdSAdrien Mazarguil static int
222188b8ccdSAdrien Mazarguil hash_rxq_special_flow_enable(struct hash_rxq *hash_rxq,
223188b8ccdSAdrien Mazarguil 			     enum hash_rxq_flow_type flow_type)
224188b8ccdSAdrien Mazarguil {
225188b8ccdSAdrien Mazarguil 	struct priv *priv = hash_rxq->priv;
226188b8ccdSAdrien Mazarguil 	unsigned int i = 0;
227188b8ccdSAdrien Mazarguil 	int ret;
228188b8ccdSAdrien Mazarguil 
229188b8ccdSAdrien Mazarguil 	assert((unsigned int)flow_type < RTE_DIM(hash_rxq->special_flow));
230188b8ccdSAdrien Mazarguil 	assert(RTE_DIM(hash_rxq->special_flow[flow_type]) ==
231188b8ccdSAdrien Mazarguil 	       RTE_DIM(priv->vlan_filter));
232188b8ccdSAdrien Mazarguil 	/* Add a special flow for each VLAN filter when relevant. */
233188b8ccdSAdrien Mazarguil 	do {
234188b8ccdSAdrien Mazarguil 		ret = hash_rxq_special_flow_enable_vlan(hash_rxq, flow_type, i);
235188b8ccdSAdrien Mazarguil 		if (ret) {
236188b8ccdSAdrien Mazarguil 			/* Failure, rollback. */
237188b8ccdSAdrien Mazarguil 			while (i != 0)
238188b8ccdSAdrien Mazarguil 				hash_rxq_special_flow_disable_vlan(hash_rxq,
239188b8ccdSAdrien Mazarguil 								   flow_type,
240188b8ccdSAdrien Mazarguil 								   --i);
241188b8ccdSAdrien Mazarguil 			return ret;
242188b8ccdSAdrien Mazarguil 		}
243188b8ccdSAdrien Mazarguil 	} while (special_flow_init[flow_type].per_vlan &&
244188b8ccdSAdrien Mazarguil 		 ++i < priv->vlan_filter_n);
245ecc1c29dSAdrien Mazarguil 	return 0;
246ecc1c29dSAdrien Mazarguil }
247ecc1c29dSAdrien Mazarguil 
248ecc1c29dSAdrien Mazarguil /**
249083c2dd3SYaacov Hazan  * Disable a special flow in a hash RX queue.
250083c2dd3SYaacov Hazan  *
251083c2dd3SYaacov Hazan  * @param hash_rxq
252083c2dd3SYaacov Hazan  *   Pointer to hash RX queue structure.
253083c2dd3SYaacov Hazan  * @param flow_type
254083c2dd3SYaacov Hazan  *   Special flow type.
255083c2dd3SYaacov Hazan  */
256083c2dd3SYaacov Hazan static void
257083c2dd3SYaacov Hazan hash_rxq_special_flow_disable(struct hash_rxq *hash_rxq,
258083c2dd3SYaacov Hazan 			      enum hash_rxq_flow_type flow_type)
259083c2dd3SYaacov Hazan {
260188b8ccdSAdrien Mazarguil 	unsigned int i;
261188b8ccdSAdrien Mazarguil 
262188b8ccdSAdrien Mazarguil 	assert((unsigned int)flow_type < RTE_DIM(hash_rxq->special_flow));
263188b8ccdSAdrien Mazarguil 	for (i = 0; (i != RTE_DIM(hash_rxq->special_flow[flow_type])); ++i)
264188b8ccdSAdrien Mazarguil 		hash_rxq_special_flow_disable_vlan(hash_rxq, flow_type, i);
265083c2dd3SYaacov Hazan }
266083c2dd3SYaacov Hazan 
267083c2dd3SYaacov Hazan /**
268083c2dd3SYaacov Hazan  * Enable a special flow in all hash RX queues.
269ecc1c29dSAdrien Mazarguil  *
270ecc1c29dSAdrien Mazarguil  * @param priv
271ecc1c29dSAdrien Mazarguil  *   Private structure.
272083c2dd3SYaacov Hazan  * @param flow_type
273083c2dd3SYaacov Hazan  *   Special flow type.
274ecc1c29dSAdrien Mazarguil  *
275ecc1c29dSAdrien Mazarguil  * @return
276ecc1c29dSAdrien Mazarguil  *   0 on success, errno value on failure.
277ecc1c29dSAdrien Mazarguil  */
278ecc1c29dSAdrien Mazarguil int
279083c2dd3SYaacov Hazan priv_special_flow_enable(struct priv *priv, enum hash_rxq_flow_type flow_type)
280ecc1c29dSAdrien Mazarguil {
281ecc1c29dSAdrien Mazarguil 	unsigned int i;
282ecc1c29dSAdrien Mazarguil 
283083c2dd3SYaacov Hazan 	if (!priv_allow_flow_type(priv, flow_type))
2845b45c208SNelio Laranjeiro 		return 0;
285ecc1c29dSAdrien Mazarguil 	for (i = 0; (i != priv->hash_rxqs_n); ++i) {
286ecc1c29dSAdrien Mazarguil 		struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
287ecc1c29dSAdrien Mazarguil 		int ret;
288ecc1c29dSAdrien Mazarguil 
289083c2dd3SYaacov Hazan 		ret = hash_rxq_special_flow_enable(hash_rxq, flow_type);
290ecc1c29dSAdrien Mazarguil 		if (!ret)
291ecc1c29dSAdrien Mazarguil 			continue;
292ecc1c29dSAdrien Mazarguil 		/* Failure, rollback. */
293ecc1c29dSAdrien Mazarguil 		while (i != 0) {
294ecc1c29dSAdrien Mazarguil 			hash_rxq = &(*priv->hash_rxqs)[--i];
295083c2dd3SYaacov Hazan 			hash_rxq_special_flow_disable(hash_rxq, flow_type);
296ecc1c29dSAdrien Mazarguil 		}
297ecc1c29dSAdrien Mazarguil 		return ret;
298ecc1c29dSAdrien Mazarguil 	}
2991bdbe1afSAdrien Mazarguil 	return 0;
3001bdbe1afSAdrien Mazarguil }
3011bdbe1afSAdrien Mazarguil 
3021bdbe1afSAdrien Mazarguil /**
303083c2dd3SYaacov Hazan  * Disable a special flow in all hash RX queues.
304083c2dd3SYaacov Hazan  *
305083c2dd3SYaacov Hazan  * @param priv
306083c2dd3SYaacov Hazan  *   Private structure.
307083c2dd3SYaacov Hazan  * @param flow_type
308083c2dd3SYaacov Hazan  *   Special flow type.
309083c2dd3SYaacov Hazan  */
310083c2dd3SYaacov Hazan void
311083c2dd3SYaacov Hazan priv_special_flow_disable(struct priv *priv, enum hash_rxq_flow_type flow_type)
312083c2dd3SYaacov Hazan {
313083c2dd3SYaacov Hazan 	unsigned int i;
314083c2dd3SYaacov Hazan 
315083c2dd3SYaacov Hazan 	for (i = 0; (i != priv->hash_rxqs_n); ++i) {
316083c2dd3SYaacov Hazan 		struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
317083c2dd3SYaacov Hazan 
318083c2dd3SYaacov Hazan 		hash_rxq_special_flow_disable(hash_rxq, flow_type);
319083c2dd3SYaacov Hazan 	}
320083c2dd3SYaacov Hazan }
321083c2dd3SYaacov Hazan 
322083c2dd3SYaacov Hazan /**
3230d218674SAdrien Mazarguil  * Enable all special flows in all hash RX queues.
3240d218674SAdrien Mazarguil  *
3250d218674SAdrien Mazarguil  * @param priv
3260d218674SAdrien Mazarguil  *   Private structure.
3270d218674SAdrien Mazarguil  */
3280d218674SAdrien Mazarguil int
3290d218674SAdrien Mazarguil priv_special_flow_enable_all(struct priv *priv)
3300d218674SAdrien Mazarguil {
3310d218674SAdrien Mazarguil 	enum hash_rxq_flow_type flow_type;
3320d218674SAdrien Mazarguil 
33351d5f8ecSNélio Laranjeiro 	if (priv->isolated)
33451d5f8ecSNélio Laranjeiro 		return 0;
335*1b37f5d8SNélio Laranjeiro 	for (flow_type = HASH_RXQ_FLOW_TYPE_ALLMULTI;
33636351ea3SFerruh Yigit 			flow_type != HASH_RXQ_FLOW_TYPE_MAC;
33736351ea3SFerruh Yigit 			++flow_type) {
3380d218674SAdrien Mazarguil 		int ret;
3390d218674SAdrien Mazarguil 
3400d218674SAdrien Mazarguil 		ret = priv_special_flow_enable(priv, flow_type);
3410d218674SAdrien Mazarguil 		if (!ret)
3420d218674SAdrien Mazarguil 			continue;
3430d218674SAdrien Mazarguil 		/* Failure, rollback. */
3440d218674SAdrien Mazarguil 		while (flow_type)
3450d218674SAdrien Mazarguil 			priv_special_flow_disable(priv, --flow_type);
3460d218674SAdrien Mazarguil 		return ret;
3470d218674SAdrien Mazarguil 	}
3480d218674SAdrien Mazarguil 	return 0;
3490d218674SAdrien Mazarguil }
3500d218674SAdrien Mazarguil 
3510d218674SAdrien Mazarguil /**
3520d218674SAdrien Mazarguil  * Disable all special flows in all hash RX queues.
3530d218674SAdrien Mazarguil  *
3540d218674SAdrien Mazarguil  * @param priv
3550d218674SAdrien Mazarguil  *   Private structure.
3560d218674SAdrien Mazarguil  */
3570d218674SAdrien Mazarguil void
3580d218674SAdrien Mazarguil priv_special_flow_disable_all(struct priv *priv)
3590d218674SAdrien Mazarguil {
3600d218674SAdrien Mazarguil 	enum hash_rxq_flow_type flow_type;
3610d218674SAdrien Mazarguil 
362*1b37f5d8SNélio Laranjeiro 	for (flow_type = HASH_RXQ_FLOW_TYPE_ALLMULTI;
36336351ea3SFerruh Yigit 			flow_type != HASH_RXQ_FLOW_TYPE_MAC;
36436351ea3SFerruh Yigit 			++flow_type)
3650d218674SAdrien Mazarguil 		priv_special_flow_disable(priv, flow_type);
3660d218674SAdrien Mazarguil }
3670d218674SAdrien Mazarguil 
3680d218674SAdrien Mazarguil /**
3691bdbe1afSAdrien Mazarguil  * DPDK callback to enable promiscuous mode.
3701bdbe1afSAdrien Mazarguil  *
3711bdbe1afSAdrien Mazarguil  * @param dev
3721bdbe1afSAdrien Mazarguil  *   Pointer to Ethernet device structure.
3731bdbe1afSAdrien Mazarguil  */
3741bdbe1afSAdrien Mazarguil void
3751bdbe1afSAdrien Mazarguil mlx5_promiscuous_enable(struct rte_eth_dev *dev)
3761bdbe1afSAdrien Mazarguil {
377*1b37f5d8SNélio Laranjeiro 	struct rte_flow_item_eth eth = {
378*1b37f5d8SNélio Laranjeiro 		.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
379*1b37f5d8SNélio Laranjeiro 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
380*1b37f5d8SNélio Laranjeiro 		.type = 0,
381*1b37f5d8SNélio Laranjeiro 	};
3821bdbe1afSAdrien Mazarguil 
383a48deadaSOr Ami 	if (mlx5_is_secondary())
384a48deadaSOr Ami 		return;
385*1b37f5d8SNélio Laranjeiro 	dev->data->promiscuous = 1;
386*1b37f5d8SNélio Laranjeiro 	claim_zero(mlx5_ctrl_flow(dev, &eth, &eth, 1));
3871bdbe1afSAdrien Mazarguil }
3881bdbe1afSAdrien Mazarguil 
3891bdbe1afSAdrien Mazarguil /**
3901bdbe1afSAdrien Mazarguil  * DPDK callback to disable promiscuous mode.
3911bdbe1afSAdrien Mazarguil  *
3921bdbe1afSAdrien Mazarguil  * @param dev
3931bdbe1afSAdrien Mazarguil  *   Pointer to Ethernet device structure.
3941bdbe1afSAdrien Mazarguil  */
3951bdbe1afSAdrien Mazarguil void
3961bdbe1afSAdrien Mazarguil mlx5_promiscuous_disable(struct rte_eth_dev *dev)
3971bdbe1afSAdrien Mazarguil {
398*1b37f5d8SNélio Laranjeiro 	struct rte_flow_item_eth eth = {
399*1b37f5d8SNélio Laranjeiro 		.dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
400*1b37f5d8SNélio Laranjeiro 		.src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
401*1b37f5d8SNélio Laranjeiro 		.type = 0,
402*1b37f5d8SNélio Laranjeiro 	};
4031bdbe1afSAdrien Mazarguil 
404a48deadaSOr Ami 	if (mlx5_is_secondary())
405a48deadaSOr Ami 		return;
406*1b37f5d8SNélio Laranjeiro 	dev->data->promiscuous = 0;
407*1b37f5d8SNélio Laranjeiro 	claim_zero(mlx5_ctrl_flow(dev, &eth, &eth, 0));
4081bdbe1afSAdrien Mazarguil }
4091bdbe1afSAdrien Mazarguil 
4101bdbe1afSAdrien Mazarguil /**
4111bdbe1afSAdrien Mazarguil  * DPDK callback to enable allmulti mode.
4121bdbe1afSAdrien Mazarguil  *
4131bdbe1afSAdrien Mazarguil  * @param dev
4141bdbe1afSAdrien Mazarguil  *   Pointer to Ethernet device structure.
4151bdbe1afSAdrien Mazarguil  */
4161bdbe1afSAdrien Mazarguil void
4171bdbe1afSAdrien Mazarguil mlx5_allmulticast_enable(struct rte_eth_dev *dev)
4181bdbe1afSAdrien Mazarguil {
4191bdbe1afSAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
4201bdbe1afSAdrien Mazarguil 	int ret;
4211bdbe1afSAdrien Mazarguil 
422a48deadaSOr Ami 	if (mlx5_is_secondary())
423a48deadaSOr Ami 		return;
424a48deadaSOr Ami 
4251bdbe1afSAdrien Mazarguil 	priv_lock(priv);
4261bdbe1afSAdrien Mazarguil 	priv->allmulti_req = 1;
427083c2dd3SYaacov Hazan 	ret = priv_rehash_flows(priv);
428ecc1c29dSAdrien Mazarguil 	if (ret)
429083c2dd3SYaacov Hazan 		ERROR("error while enabling allmulticast mode: %s",
430083c2dd3SYaacov Hazan 		      strerror(ret));
4311bdbe1afSAdrien Mazarguil 	priv_unlock(priv);
4321bdbe1afSAdrien Mazarguil }
4331bdbe1afSAdrien Mazarguil 
4341bdbe1afSAdrien Mazarguil /**
4351bdbe1afSAdrien Mazarguil  * DPDK callback to disable allmulti mode.
4361bdbe1afSAdrien Mazarguil  *
4371bdbe1afSAdrien Mazarguil  * @param dev
4381bdbe1afSAdrien Mazarguil  *   Pointer to Ethernet device structure.
4391bdbe1afSAdrien Mazarguil  */
4401bdbe1afSAdrien Mazarguil void
4411bdbe1afSAdrien Mazarguil mlx5_allmulticast_disable(struct rte_eth_dev *dev)
4421bdbe1afSAdrien Mazarguil {
4431bdbe1afSAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
444083c2dd3SYaacov Hazan 	int ret;
4451bdbe1afSAdrien Mazarguil 
446a48deadaSOr Ami 	if (mlx5_is_secondary())
447a48deadaSOr Ami 		return;
448a48deadaSOr Ami 
4491bdbe1afSAdrien Mazarguil 	priv_lock(priv);
4501bdbe1afSAdrien Mazarguil 	priv->allmulti_req = 0;
451083c2dd3SYaacov Hazan 	ret = priv_rehash_flows(priv);
452083c2dd3SYaacov Hazan 	if (ret)
453083c2dd3SYaacov Hazan 		ERROR("error while disabling allmulticast mode: %s",
454083c2dd3SYaacov Hazan 		      strerror(ret));
4551bdbe1afSAdrien Mazarguil 	priv_unlock(priv);
4561bdbe1afSAdrien Mazarguil }
457