xref: /dpdk/drivers/net/bnxt/bnxt_flow.c (revision dd0191d5e70d0e65a7f041a88af480fc673160e1)
15c1171c9SAjit Khaparde /* SPDX-License-Identifier: BSD-3-Clause
26d160d77SRandy Schacher  * Copyright(c) 2014-2023 Broadcom
35c1171c9SAjit Khaparde  * All rights reserved.
45c1171c9SAjit Khaparde  */
55c1171c9SAjit Khaparde 
65c1171c9SAjit Khaparde #include <sys/queue.h>
75c1171c9SAjit Khaparde 
85c1171c9SAjit Khaparde #include <rte_log.h>
95c1171c9SAjit Khaparde #include <rte_malloc.h>
105c1171c9SAjit Khaparde #include <rte_flow.h>
115c1171c9SAjit Khaparde #include <rte_flow_driver.h>
125c1171c9SAjit Khaparde #include <rte_tailq.h>
1302a95625SSomnath Kotur #include <rte_alarm.h>
1402a95625SSomnath Kotur #include <rte_cycles.h>
155c1171c9SAjit Khaparde 
165c1171c9SAjit Khaparde #include "bnxt.h"
175c1171c9SAjit Khaparde #include "bnxt_filter.h"
185c1171c9SAjit Khaparde #include "bnxt_hwrm.h"
19d24610f7SAjit Khaparde #include "bnxt_ring.h"
20d24610f7SAjit Khaparde #include "bnxt_rxq.h"
21ca03216fSLance Richardson #include "bnxt_rxr.h"
225c1171c9SAjit Khaparde #include "bnxt_vnic.h"
235c1171c9SAjit Khaparde #include "hsi_struct_def_dpdk.h"
245c1171c9SAjit Khaparde 
255c1171c9SAjit Khaparde static int
265c1171c9SAjit Khaparde bnxt_flow_args_validate(const struct rte_flow_attr *attr,
275c1171c9SAjit Khaparde 			const struct rte_flow_item pattern[],
285c1171c9SAjit Khaparde 			const struct rte_flow_action actions[],
295c1171c9SAjit Khaparde 			struct rte_flow_error *error)
305c1171c9SAjit Khaparde {
315c1171c9SAjit Khaparde 	if (!pattern) {
325c1171c9SAjit Khaparde 		rte_flow_error_set(error,
335c1171c9SAjit Khaparde 				   EINVAL,
345c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ITEM_NUM,
355c1171c9SAjit Khaparde 				   NULL,
365c1171c9SAjit Khaparde 				   "NULL pattern.");
375c1171c9SAjit Khaparde 		return -rte_errno;
385c1171c9SAjit Khaparde 	}
395c1171c9SAjit Khaparde 
405c1171c9SAjit Khaparde 	if (!actions) {
415c1171c9SAjit Khaparde 		rte_flow_error_set(error,
425c1171c9SAjit Khaparde 				   EINVAL,
435c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
445c1171c9SAjit Khaparde 				   NULL,
455c1171c9SAjit Khaparde 				   "NULL action.");
465c1171c9SAjit Khaparde 		return -rte_errno;
475c1171c9SAjit Khaparde 	}
485c1171c9SAjit Khaparde 
495c1171c9SAjit Khaparde 	if (!attr) {
505c1171c9SAjit Khaparde 		rte_flow_error_set(error,
515c1171c9SAjit Khaparde 				   EINVAL,
525c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ATTR,
535c1171c9SAjit Khaparde 				   NULL,
545c1171c9SAjit Khaparde 				   "NULL attribute.");
555c1171c9SAjit Khaparde 		return -rte_errno;
565c1171c9SAjit Khaparde 	}
575c1171c9SAjit Khaparde 
585c1171c9SAjit Khaparde 	return 0;
595c1171c9SAjit Khaparde }
605c1171c9SAjit Khaparde 
615c1171c9SAjit Khaparde static const struct rte_flow_item *
625c1171c9SAjit Khaparde bnxt_flow_non_void_item(const struct rte_flow_item *cur)
635c1171c9SAjit Khaparde {
645c1171c9SAjit Khaparde 	while (1) {
655c1171c9SAjit Khaparde 		if (cur->type != RTE_FLOW_ITEM_TYPE_VOID)
665c1171c9SAjit Khaparde 			return cur;
675c1171c9SAjit Khaparde 		cur++;
685c1171c9SAjit Khaparde 	}
695c1171c9SAjit Khaparde }
705c1171c9SAjit Khaparde 
715c1171c9SAjit Khaparde static const struct rte_flow_action *
725c1171c9SAjit Khaparde bnxt_flow_non_void_action(const struct rte_flow_action *cur)
735c1171c9SAjit Khaparde {
745c1171c9SAjit Khaparde 	while (1) {
755c1171c9SAjit Khaparde 		if (cur->type != RTE_FLOW_ACTION_TYPE_VOID)
765c1171c9SAjit Khaparde 			return cur;
775c1171c9SAjit Khaparde 		cur++;
785c1171c9SAjit Khaparde 	}
795c1171c9SAjit Khaparde }
805c1171c9SAjit Khaparde 
815c1171c9SAjit Khaparde static int
825c1171c9SAjit Khaparde bnxt_filter_type_check(const struct rte_flow_item pattern[],
83fd36aa85SKalesh AP 		       struct rte_flow_error *error)
845c1171c9SAjit Khaparde {
855c1171c9SAjit Khaparde 	const struct rte_flow_item *item =
865c1171c9SAjit Khaparde 		bnxt_flow_non_void_item(pattern);
875c1171c9SAjit Khaparde 	int use_ntuple = 1;
88afef822bSAjit Khaparde 	bool has_vlan = 0;
895c1171c9SAjit Khaparde 
905c1171c9SAjit Khaparde 	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
915c1171c9SAjit Khaparde 		switch (item->type) {
92afef822bSAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_ANY:
935c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_ETH:
94afef822bSAjit Khaparde 			use_ntuple = 0;
955c1171c9SAjit Khaparde 			break;
965c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_VLAN:
975c1171c9SAjit Khaparde 			use_ntuple = 0;
98afef822bSAjit Khaparde 			has_vlan = 1;
995c1171c9SAjit Khaparde 			break;
1005c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_IPV4:
1015c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_IPV6:
1025c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_TCP:
1035c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_UDP:
1045c1171c9SAjit Khaparde 			/* FALLTHROUGH */
1055c1171c9SAjit Khaparde 			/* need ntuple match, reset exact match */
1065c1171c9SAjit Khaparde 			use_ntuple |= 1;
1075c1171c9SAjit Khaparde 			break;
1085c1171c9SAjit Khaparde 		default:
109e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "Unknown Flow type");
11011e5e196SSomnath Kotur 			use_ntuple |= 0;
1115c1171c9SAjit Khaparde 		}
1125c1171c9SAjit Khaparde 		item++;
1135c1171c9SAjit Khaparde 	}
114afef822bSAjit Khaparde 
115afef822bSAjit Khaparde 	if (has_vlan && use_ntuple) {
116e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR,
117e99981afSDavid Marchand 			    "VLAN flow cannot use NTUPLE filter");
118afef822bSAjit Khaparde 		rte_flow_error_set(error, EINVAL,
119afef822bSAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ITEM,
120afef822bSAjit Khaparde 				   item,
121afef822bSAjit Khaparde 				   "Cannot use VLAN with NTUPLE");
122afef822bSAjit Khaparde 		return -rte_errno;
123afef822bSAjit Khaparde 	}
124afef822bSAjit Khaparde 
1255c1171c9SAjit Khaparde 	return use_ntuple;
1265c1171c9SAjit Khaparde }
1275c1171c9SAjit Khaparde 
1285c1171c9SAjit Khaparde static int
1295c45fde3SIvan Malov bnxt_validate_and_parse_flow_type(const struct rte_flow_attr *attr,
1305c1171c9SAjit Khaparde 				  const struct rte_flow_item pattern[],
1315c1171c9SAjit Khaparde 				  struct rte_flow_error *error,
1325c1171c9SAjit Khaparde 				  struct bnxt_filter_info *filter)
1335c1171c9SAjit Khaparde {
1345c1171c9SAjit Khaparde 	const struct rte_flow_item *item = bnxt_flow_non_void_item(pattern);
1355c1171c9SAjit Khaparde 	const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
1365c1171c9SAjit Khaparde 	const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
1375c1171c9SAjit Khaparde 	const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
1385c1171c9SAjit Khaparde 	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
1395c1171c9SAjit Khaparde 	const struct rte_flow_item_udp *udp_spec, *udp_mask;
1405c1171c9SAjit Khaparde 	const struct rte_flow_item_eth *eth_spec, *eth_mask;
14126f044ceSSomnath Kotur 	const struct rte_ether_addr *dst, *src;
1425c1171c9SAjit Khaparde 	const struct rte_flow_item_nvgre *nvgre_spec;
1435c1171c9SAjit Khaparde 	const struct rte_flow_item_nvgre *nvgre_mask;
14411e5e196SSomnath Kotur 	const struct rte_flow_item_gre *gre_spec;
14511e5e196SSomnath Kotur 	const struct rte_flow_item_gre *gre_mask;
1465c1171c9SAjit Khaparde 	const struct rte_flow_item_vxlan *vxlan_spec;
1475c1171c9SAjit Khaparde 	const struct rte_flow_item_vxlan *vxlan_mask;
1485c1171c9SAjit Khaparde 	uint8_t vni_mask[] = {0xFF, 0xFF, 0xFF};
1495c1171c9SAjit Khaparde 	uint8_t tni_mask[] = {0xFF, 0xFF, 0xFF};
150afef822bSAjit Khaparde 	uint32_t tenant_id_be = 0, valid_flags = 0;
1515c1171c9SAjit Khaparde 	bool vni_masked = 0;
1525c1171c9SAjit Khaparde 	bool tni_masked = 0;
1535c1171c9SAjit Khaparde 	uint32_t en_ethertype;
154afef822bSAjit Khaparde 	uint8_t inner = 0;
155afef822bSAjit Khaparde 	uint32_t en = 0;
156afef822bSAjit Khaparde 	int use_ntuple;
1575c1171c9SAjit Khaparde 
1585c1171c9SAjit Khaparde 	use_ntuple = bnxt_filter_type_check(pattern, error);
1595c1171c9SAjit Khaparde 	if (use_ntuple < 0)
1605c1171c9SAjit Khaparde 		return use_ntuple;
161e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG, "Use NTUPLE %d", use_ntuple);
1625c1171c9SAjit Khaparde 
1635c1171c9SAjit Khaparde 	filter->filter_type = use_ntuple ?
16424de0b60SRahul Gupta 		HWRM_CFA_NTUPLE_FILTER : HWRM_CFA_L2_FILTER;
1655c1171c9SAjit Khaparde 	en_ethertype = use_ntuple ?
1665c1171c9SAjit Khaparde 		NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE :
1675c1171c9SAjit Khaparde 		EM_FLOW_ALLOC_INPUT_EN_ETHERTYPE;
1685c1171c9SAjit Khaparde 
1695c1171c9SAjit Khaparde 	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
1705c1171c9SAjit Khaparde 		if (item->last) {
1715c1171c9SAjit Khaparde 			/* last or range is NOT supported as match criteria */
1725c1171c9SAjit Khaparde 			rte_flow_error_set(error, EINVAL,
1735c1171c9SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ITEM,
1745c1171c9SAjit Khaparde 					   item,
1755c1171c9SAjit Khaparde 					   "No support for range");
1765c1171c9SAjit Khaparde 			return -rte_errno;
1775c1171c9SAjit Khaparde 		}
1785c1171c9SAjit Khaparde 
1795c1171c9SAjit Khaparde 		switch (item->type) {
180afef822bSAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_ANY:
181afef822bSAjit Khaparde 			inner =
182afef822bSAjit Khaparde 			((const struct rte_flow_item_any *)item->spec)->num > 3;
183afef822bSAjit Khaparde 			if (inner)
184e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(DEBUG, "Parse inner header");
185afef822bSAjit Khaparde 			break;
1865c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_ETH:
187dea1afc7SLance Richardson 			if (!item->spec)
18811e5e196SSomnath Kotur 				break;
18911e5e196SSomnath Kotur 
1905c1171c9SAjit Khaparde 			eth_spec = item->spec;
191dea1afc7SLance Richardson 
192dea1afc7SLance Richardson 			if (item->mask)
1935c1171c9SAjit Khaparde 				eth_mask = item->mask;
194dea1afc7SLance Richardson 			else
195dea1afc7SLance Richardson 				eth_mask = &rte_flow_item_eth_mask;
1965c1171c9SAjit Khaparde 
1975c1171c9SAjit Khaparde 			/* Source MAC address mask cannot be partially set.
1985c1171c9SAjit Khaparde 			 * Should be All 0's or all 1's.
1995c1171c9SAjit Khaparde 			 * Destination MAC address mask must not be partially
2005c1171c9SAjit Khaparde 			 * set. Should be all 1's or all 0's.
2015c1171c9SAjit Khaparde 			 */
2028275d5fcSThomas Monjalon 			if ((!rte_is_zero_ether_addr(&eth_mask->hdr.src_addr) &&
2038275d5fcSThomas Monjalon 			     !rte_is_broadcast_ether_addr(&eth_mask->hdr.src_addr)) ||
2048275d5fcSThomas Monjalon 			    (!rte_is_zero_ether_addr(&eth_mask->hdr.dst_addr) &&
2058275d5fcSThomas Monjalon 			     !rte_is_broadcast_ether_addr(&eth_mask->hdr.dst_addr))) {
2065c1171c9SAjit Khaparde 				rte_flow_error_set(error,
2075c1171c9SAjit Khaparde 						   EINVAL,
2085c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
2095c1171c9SAjit Khaparde 						   item,
2105c1171c9SAjit Khaparde 						   "MAC_addr mask not valid");
2115c1171c9SAjit Khaparde 				return -rte_errno;
2125c1171c9SAjit Khaparde 			}
2135c1171c9SAjit Khaparde 
2145c1171c9SAjit Khaparde 			/* Mask is not allowed. Only exact matches are */
2158275d5fcSThomas Monjalon 			if (eth_mask->hdr.ether_type &&
2168275d5fcSThomas Monjalon 			    eth_mask->hdr.ether_type != RTE_BE16(0xffff)) {
2175c1171c9SAjit Khaparde 				rte_flow_error_set(error, EINVAL,
2185c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
2195c1171c9SAjit Khaparde 						   item,
2205c1171c9SAjit Khaparde 						   "ethertype mask not valid");
2215c1171c9SAjit Khaparde 				return -rte_errno;
2225c1171c9SAjit Khaparde 			}
2235c1171c9SAjit Khaparde 
2248275d5fcSThomas Monjalon 			if (rte_is_broadcast_ether_addr(&eth_mask->hdr.dst_addr)) {
2258275d5fcSThomas Monjalon 				dst = &eth_spec->hdr.dst_addr;
22626f044ceSSomnath Kotur 				if (!rte_is_valid_assigned_ether_addr(dst)) {
22740724480SAjit Khaparde 					rte_flow_error_set(error,
22840724480SAjit Khaparde 							   EINVAL,
22940724480SAjit Khaparde 							   RTE_FLOW_ERROR_TYPE_ITEM,
23040724480SAjit Khaparde 							   item,
23140724480SAjit Khaparde 							   "DMAC is invalid");
232e99981afSDavid Marchand 					PMD_DRV_LOG_LINE(ERR,
233e99981afSDavid Marchand 						    "DMAC is invalid!");
23440724480SAjit Khaparde 					return -rte_errno;
23540724480SAjit Khaparde 				}
2365c1171c9SAjit Khaparde 				rte_memcpy(filter->dst_macaddr,
2378275d5fcSThomas Monjalon 					   &eth_spec->hdr.dst_addr, RTE_ETHER_ADDR_LEN);
2385c1171c9SAjit Khaparde 				en |= use_ntuple ?
2395c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_DST_MACADDR :
2405c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_DST_MACADDR;
241afef822bSAjit Khaparde 				valid_flags |= inner ?
242afef822bSAjit Khaparde 					BNXT_FLOW_L2_INNER_DST_VALID_FLAG :
243afef822bSAjit Khaparde 					BNXT_FLOW_L2_DST_VALID_FLAG;
244749ba50dSAjit Khaparde 				filter->priority = attr->priority;
245e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(DEBUG,
246e99981afSDavid Marchand 					    "Creating a priority flow");
2475c1171c9SAjit Khaparde 			}
2488275d5fcSThomas Monjalon 			if (rte_is_broadcast_ether_addr(&eth_mask->hdr.src_addr)) {
2498275d5fcSThomas Monjalon 				src = &eth_spec->hdr.src_addr;
25026f044ceSSomnath Kotur 				if (!rte_is_valid_assigned_ether_addr(src)) {
25140724480SAjit Khaparde 					rte_flow_error_set(error,
25240724480SAjit Khaparde 							   EINVAL,
25340724480SAjit Khaparde 							   RTE_FLOW_ERROR_TYPE_ITEM,
25440724480SAjit Khaparde 							   item,
25540724480SAjit Khaparde 							   "SMAC is invalid");
256e99981afSDavid Marchand 					PMD_DRV_LOG_LINE(ERR,
257e99981afSDavid Marchand 						    "SMAC is invalid!");
25840724480SAjit Khaparde 					return -rte_errno;
25940724480SAjit Khaparde 				}
2605c1171c9SAjit Khaparde 				rte_memcpy(filter->src_macaddr,
2618275d5fcSThomas Monjalon 					   &eth_spec->hdr.src_addr, RTE_ETHER_ADDR_LEN);
2625c1171c9SAjit Khaparde 				en |= use_ntuple ?
2635c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_MACADDR :
2645c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_SRC_MACADDR;
265afef822bSAjit Khaparde 				valid_flags |= inner ?
266afef822bSAjit Khaparde 					BNXT_FLOW_L2_INNER_SRC_VALID_FLAG :
267afef822bSAjit Khaparde 					BNXT_FLOW_L2_SRC_VALID_FLAG;
2685c1171c9SAjit Khaparde 			} /*
2695c1171c9SAjit Khaparde 			   * else {
270e99981afSDavid Marchand 			   *  PMD_DRV_LOG_LINE(ERR, "Handle this condition");
2715c1171c9SAjit Khaparde 			   * }
2725c1171c9SAjit Khaparde 			   */
2738275d5fcSThomas Monjalon 			if (eth_mask->hdr.ether_type) {
2745c1171c9SAjit Khaparde 				filter->ethertype =
2758275d5fcSThomas Monjalon 					rte_be_to_cpu_16(eth_spec->hdr.ether_type);
2765c1171c9SAjit Khaparde 				en |= en_ethertype;
2775c1171c9SAjit Khaparde 			}
278b0d3c584SAjit Khaparde 			if (inner)
279b0d3c584SAjit Khaparde 				valid_flags |= BNXT_FLOW_PARSE_INNER_FLAG;
2805c1171c9SAjit Khaparde 
2815c1171c9SAjit Khaparde 			break;
2825c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_VLAN:
2835c1171c9SAjit Khaparde 			vlan_spec = item->spec;
284dea1afc7SLance Richardson 
285dea1afc7SLance Richardson 			if (item->mask)
2865c1171c9SAjit Khaparde 				vlan_mask = item->mask;
287dea1afc7SLance Richardson 			else
288dea1afc7SLance Richardson 				vlan_mask = &rte_flow_item_vlan_mask;
289dea1afc7SLance Richardson 
2905c1171c9SAjit Khaparde 			if (en & en_ethertype) {
2915c1171c9SAjit Khaparde 				rte_flow_error_set(error, EINVAL,
2925c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
2935c1171c9SAjit Khaparde 						   item,
2945c1171c9SAjit Khaparde 						   "VLAN TPID matching is not"
2955c1171c9SAjit Khaparde 						   " supported");
2965c1171c9SAjit Khaparde 				return -rte_errno;
2975c1171c9SAjit Khaparde 			}
2988275d5fcSThomas Monjalon 			if (vlan_mask->hdr.vlan_tci &&
2998275d5fcSThomas Monjalon 			    vlan_mask->hdr.vlan_tci == RTE_BE16(0x0fff)) {
3005c1171c9SAjit Khaparde 				/* Only the VLAN ID can be matched. */
3015c1171c9SAjit Khaparde 				filter->l2_ovlan =
3028275d5fcSThomas Monjalon 					rte_be_to_cpu_16(vlan_spec->hdr.vlan_tci &
3035c1171c9SAjit Khaparde 							 RTE_BE16(0x0fff));
3045c1171c9SAjit Khaparde 				en |= EM_FLOW_ALLOC_INPUT_EN_OVLAN_VID;
3055c1171c9SAjit Khaparde 			} else {
3065c1171c9SAjit Khaparde 				rte_flow_error_set(error,
3075c1171c9SAjit Khaparde 						   EINVAL,
3085c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
3095c1171c9SAjit Khaparde 						   item,
3105c1171c9SAjit Khaparde 						   "VLAN mask is invalid");
3115c1171c9SAjit Khaparde 				return -rte_errno;
3125c1171c9SAjit Khaparde 			}
3138275d5fcSThomas Monjalon 			if (vlan_mask->hdr.eth_proto &&
3148275d5fcSThomas Monjalon 			    vlan_mask->hdr.eth_proto != RTE_BE16(0xffff)) {
3155c1171c9SAjit Khaparde 				rte_flow_error_set(error, EINVAL,
3165c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
3175c1171c9SAjit Khaparde 						   item,
3185c1171c9SAjit Khaparde 						   "inner ethertype mask not"
3195c1171c9SAjit Khaparde 						   " valid");
3205c1171c9SAjit Khaparde 				return -rte_errno;
3215c1171c9SAjit Khaparde 			}
3228275d5fcSThomas Monjalon 			if (vlan_mask->hdr.eth_proto) {
3235c1171c9SAjit Khaparde 				filter->ethertype =
3248275d5fcSThomas Monjalon 					rte_be_to_cpu_16(vlan_spec->hdr.eth_proto);
3255c1171c9SAjit Khaparde 				en |= en_ethertype;
3265c1171c9SAjit Khaparde 			}
3275c1171c9SAjit Khaparde 
3285c1171c9SAjit Khaparde 			break;
3295c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_IPV4:
3305c1171c9SAjit Khaparde 			/* If mask is not involved, we could use EM filters. */
3315c1171c9SAjit Khaparde 			ipv4_spec = item->spec;
33211e5e196SSomnath Kotur 
333dea1afc7SLance Richardson 			if (!item->spec)
33411e5e196SSomnath Kotur 				break;
33511e5e196SSomnath Kotur 
336dea1afc7SLance Richardson 			if (item->mask)
337dea1afc7SLance Richardson 				ipv4_mask = item->mask;
338dea1afc7SLance Richardson 			else
339dea1afc7SLance Richardson 				ipv4_mask = &rte_flow_item_ipv4_mask;
340dea1afc7SLance Richardson 
3415c1171c9SAjit Khaparde 			/* Only IP DST and SRC fields are maskable. */
3425c1171c9SAjit Khaparde 			if (ipv4_mask->hdr.version_ihl ||
3435c1171c9SAjit Khaparde 			    ipv4_mask->hdr.type_of_service ||
3445c1171c9SAjit Khaparde 			    ipv4_mask->hdr.total_length ||
3455c1171c9SAjit Khaparde 			    ipv4_mask->hdr.packet_id ||
3465c1171c9SAjit Khaparde 			    ipv4_mask->hdr.fragment_offset ||
3475c1171c9SAjit Khaparde 			    ipv4_mask->hdr.time_to_live ||
3485c1171c9SAjit Khaparde 			    ipv4_mask->hdr.next_proto_id ||
3495c1171c9SAjit Khaparde 			    ipv4_mask->hdr.hdr_checksum) {
3505c1171c9SAjit Khaparde 				rte_flow_error_set(error,
3515c1171c9SAjit Khaparde 						   EINVAL,
3525c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
3535c1171c9SAjit Khaparde 						   item,
3545c1171c9SAjit Khaparde 						   "Invalid IPv4 mask.");
3555c1171c9SAjit Khaparde 				return -rte_errno;
3565c1171c9SAjit Khaparde 			}
3575c1171c9SAjit Khaparde 
3585c1171c9SAjit Khaparde 			filter->dst_ipaddr[0] = ipv4_spec->hdr.dst_addr;
3595c1171c9SAjit Khaparde 			filter->src_ipaddr[0] = ipv4_spec->hdr.src_addr;
3605c1171c9SAjit Khaparde 
3615c1171c9SAjit Khaparde 			if (use_ntuple)
3625c1171c9SAjit Khaparde 				en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR |
3635c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
3645c1171c9SAjit Khaparde 			else
3655c1171c9SAjit Khaparde 				en |= EM_FLOW_ALLOC_INPUT_EN_SRC_IPADDR |
3665c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_DST_IPADDR;
3675c1171c9SAjit Khaparde 
3685c1171c9SAjit Khaparde 			if (ipv4_mask->hdr.src_addr) {
3695c1171c9SAjit Khaparde 				filter->src_ipaddr_mask[0] =
3705c1171c9SAjit Khaparde 					ipv4_mask->hdr.src_addr;
3715c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
3725c1171c9SAjit Khaparde 				     NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
3735c1171c9SAjit Khaparde 			}
3745c1171c9SAjit Khaparde 
3755c1171c9SAjit Khaparde 			if (ipv4_mask->hdr.dst_addr) {
3765c1171c9SAjit Khaparde 				filter->dst_ipaddr_mask[0] =
3775c1171c9SAjit Khaparde 					ipv4_mask->hdr.dst_addr;
3785c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
3795c1171c9SAjit Khaparde 				     NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
3805c1171c9SAjit Khaparde 			}
3815c1171c9SAjit Khaparde 
3825c1171c9SAjit Khaparde 			filter->ip_addr_type = use_ntuple ?
3835c1171c9SAjit Khaparde 			 HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV4 :
3845c1171c9SAjit Khaparde 			 HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV4;
3855c1171c9SAjit Khaparde 
3865c1171c9SAjit Khaparde 			if (ipv4_spec->hdr.next_proto_id) {
3875c1171c9SAjit Khaparde 				filter->ip_protocol =
3885c1171c9SAjit Khaparde 					ipv4_spec->hdr.next_proto_id;
3895c1171c9SAjit Khaparde 				if (use_ntuple)
3905c1171c9SAjit Khaparde 					en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
3915c1171c9SAjit Khaparde 				else
3925c1171c9SAjit Khaparde 					en |= EM_FLOW_ALLOC_INPUT_EN_IP_PROTO;
3935c1171c9SAjit Khaparde 			}
3945c1171c9SAjit Khaparde 			break;
3955c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_IPV6:
3965c1171c9SAjit Khaparde 			ipv6_spec = item->spec;
3975c1171c9SAjit Khaparde 
398dea1afc7SLance Richardson 			if (!item->spec)
39911e5e196SSomnath Kotur 				break;
40011e5e196SSomnath Kotur 
401dea1afc7SLance Richardson 			if (item->mask)
402dea1afc7SLance Richardson 				ipv6_mask = item->mask;
403dea1afc7SLance Richardson 			else
404dea1afc7SLance Richardson 				ipv6_mask = &rte_flow_item_ipv6_mask;
405dea1afc7SLance Richardson 
4065c1171c9SAjit Khaparde 			/* Only IP DST and SRC fields are maskable. */
4075c1171c9SAjit Khaparde 			if (ipv6_mask->hdr.vtc_flow ||
4085c1171c9SAjit Khaparde 			    ipv6_mask->hdr.payload_len ||
4095c1171c9SAjit Khaparde 			    ipv6_mask->hdr.proto ||
4105c1171c9SAjit Khaparde 			    ipv6_mask->hdr.hop_limits) {
4115c1171c9SAjit Khaparde 				rte_flow_error_set(error,
4125c1171c9SAjit Khaparde 						   EINVAL,
4135c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
4145c1171c9SAjit Khaparde 						   item,
4155c1171c9SAjit Khaparde 						   "Invalid IPv6 mask.");
4165c1171c9SAjit Khaparde 				return -rte_errno;
4175c1171c9SAjit Khaparde 			}
4185c1171c9SAjit Khaparde 
4195c1171c9SAjit Khaparde 			if (use_ntuple)
4205c1171c9SAjit Khaparde 				en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR |
4215c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
4225c1171c9SAjit Khaparde 			else
4235c1171c9SAjit Khaparde 				en |= EM_FLOW_ALLOC_INPUT_EN_SRC_IPADDR |
4245c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_DST_IPADDR;
4255c1171c9SAjit Khaparde 
4265c1171c9SAjit Khaparde 			rte_memcpy(filter->src_ipaddr,
42789b5642dSRobin Jarry 				   &ipv6_spec->hdr.src_addr, 16);
4285c1171c9SAjit Khaparde 			rte_memcpy(filter->dst_ipaddr,
42989b5642dSRobin Jarry 				   &ipv6_spec->hdr.dst_addr, 16);
4305c1171c9SAjit Khaparde 
43189b5642dSRobin Jarry 			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.src_addr.a,
4325c1171c9SAjit Khaparde 						   16)) {
4335c1171c9SAjit Khaparde 				rte_memcpy(filter->src_ipaddr_mask,
43489b5642dSRobin Jarry 					   &ipv6_mask->hdr.src_addr, 16);
4355c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
4365c1171c9SAjit Khaparde 				    NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
4375c1171c9SAjit Khaparde 			}
4385c1171c9SAjit Khaparde 
43989b5642dSRobin Jarry 			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.dst_addr.a,
4405c1171c9SAjit Khaparde 						   16)) {
4415c1171c9SAjit Khaparde 				rte_memcpy(filter->dst_ipaddr_mask,
44289b5642dSRobin Jarry 					   &ipv6_mask->hdr.dst_addr, 16);
4435c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
4445c1171c9SAjit Khaparde 				     NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
4455c1171c9SAjit Khaparde 			}
4465c1171c9SAjit Khaparde 
4475c1171c9SAjit Khaparde 			filter->ip_addr_type = use_ntuple ?
4485c1171c9SAjit Khaparde 				NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 :
4495c1171c9SAjit Khaparde 				EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6;
4505c1171c9SAjit Khaparde 			break;
4515c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_TCP:
4525c1171c9SAjit Khaparde 			tcp_spec = item->spec;
4535c1171c9SAjit Khaparde 
454dea1afc7SLance Richardson 			if (!item->spec)
45511e5e196SSomnath Kotur 				break;
45611e5e196SSomnath Kotur 
457dea1afc7SLance Richardson 			if (item->mask)
458dea1afc7SLance Richardson 				tcp_mask = item->mask;
459dea1afc7SLance Richardson 			else
460dea1afc7SLance Richardson 				tcp_mask = &rte_flow_item_tcp_mask;
461dea1afc7SLance Richardson 
4625c1171c9SAjit Khaparde 			/* Check TCP mask. Only DST & SRC ports are maskable */
4635c1171c9SAjit Khaparde 			if (tcp_mask->hdr.sent_seq ||
4645c1171c9SAjit Khaparde 			    tcp_mask->hdr.recv_ack ||
4655c1171c9SAjit Khaparde 			    tcp_mask->hdr.data_off ||
4665c1171c9SAjit Khaparde 			    tcp_mask->hdr.tcp_flags ||
4675c1171c9SAjit Khaparde 			    tcp_mask->hdr.rx_win ||
4685c1171c9SAjit Khaparde 			    tcp_mask->hdr.cksum ||
4695c1171c9SAjit Khaparde 			    tcp_mask->hdr.tcp_urp) {
4705c1171c9SAjit Khaparde 				rte_flow_error_set(error,
4715c1171c9SAjit Khaparde 						   EINVAL,
4725c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
4735c1171c9SAjit Khaparde 						   item,
4745c1171c9SAjit Khaparde 						   "Invalid TCP mask");
4755c1171c9SAjit Khaparde 				return -rte_errno;
4765c1171c9SAjit Khaparde 			}
4775c1171c9SAjit Khaparde 
4785c1171c9SAjit Khaparde 			filter->src_port = tcp_spec->hdr.src_port;
4795c1171c9SAjit Khaparde 			filter->dst_port = tcp_spec->hdr.dst_port;
4805c1171c9SAjit Khaparde 
4815c1171c9SAjit Khaparde 			if (use_ntuple)
4825c1171c9SAjit Khaparde 				en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT |
4835c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
4845c1171c9SAjit Khaparde 			else
4855c1171c9SAjit Khaparde 				en |= EM_FLOW_ALLOC_INPUT_EN_SRC_PORT |
4865c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_DST_PORT;
4875c1171c9SAjit Khaparde 
4885c1171c9SAjit Khaparde 			if (tcp_mask->hdr.dst_port) {
4895c1171c9SAjit Khaparde 				filter->dst_port_mask = tcp_mask->hdr.dst_port;
4905c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
4915c1171c9SAjit Khaparde 				  NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
4925c1171c9SAjit Khaparde 			}
4935c1171c9SAjit Khaparde 
4945c1171c9SAjit Khaparde 			if (tcp_mask->hdr.src_port) {
4955c1171c9SAjit Khaparde 				filter->src_port_mask = tcp_mask->hdr.src_port;
4965c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
4975c1171c9SAjit Khaparde 				  NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
4985c1171c9SAjit Khaparde 			}
4995c1171c9SAjit Khaparde 			break;
5005c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_UDP:
5015c1171c9SAjit Khaparde 			udp_spec = item->spec;
5025c1171c9SAjit Khaparde 
503dea1afc7SLance Richardson 			if (!item->spec)
50411e5e196SSomnath Kotur 				break;
50511e5e196SSomnath Kotur 
506dea1afc7SLance Richardson 			if (item->mask)
507dea1afc7SLance Richardson 				udp_mask = item->mask;
508dea1afc7SLance Richardson 			else
509dea1afc7SLance Richardson 				udp_mask = &rte_flow_item_udp_mask;
510dea1afc7SLance Richardson 
5115c1171c9SAjit Khaparde 			if (udp_mask->hdr.dgram_len ||
5125c1171c9SAjit Khaparde 			    udp_mask->hdr.dgram_cksum) {
5135c1171c9SAjit Khaparde 				rte_flow_error_set(error,
5145c1171c9SAjit Khaparde 						   EINVAL,
5155c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
5165c1171c9SAjit Khaparde 						   item,
5175c1171c9SAjit Khaparde 						   "Invalid UDP mask");
5185c1171c9SAjit Khaparde 				return -rte_errno;
5195c1171c9SAjit Khaparde 			}
5205c1171c9SAjit Khaparde 
5215c1171c9SAjit Khaparde 			filter->src_port = udp_spec->hdr.src_port;
5225c1171c9SAjit Khaparde 			filter->dst_port = udp_spec->hdr.dst_port;
5235c1171c9SAjit Khaparde 
5245c1171c9SAjit Khaparde 			if (use_ntuple)
5255c1171c9SAjit Khaparde 				en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT |
5265c1171c9SAjit Khaparde 					NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
5275c1171c9SAjit Khaparde 			else
5285c1171c9SAjit Khaparde 				en |= EM_FLOW_ALLOC_INPUT_EN_SRC_PORT |
5295c1171c9SAjit Khaparde 					EM_FLOW_ALLOC_INPUT_EN_DST_PORT;
5305c1171c9SAjit Khaparde 
5315c1171c9SAjit Khaparde 			if (udp_mask->hdr.dst_port) {
5325c1171c9SAjit Khaparde 				filter->dst_port_mask = udp_mask->hdr.dst_port;
5335c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
5345c1171c9SAjit Khaparde 				  NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
5355c1171c9SAjit Khaparde 			}
5365c1171c9SAjit Khaparde 
5375c1171c9SAjit Khaparde 			if (udp_mask->hdr.src_port) {
5385c1171c9SAjit Khaparde 				filter->src_port_mask = udp_mask->hdr.src_port;
5395c1171c9SAjit Khaparde 				en |= !use_ntuple ? 0 :
5405c1171c9SAjit Khaparde 				  NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
5415c1171c9SAjit Khaparde 			}
5425c1171c9SAjit Khaparde 			break;
5435c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_VXLAN:
5445c1171c9SAjit Khaparde 			vxlan_spec = item->spec;
5455c1171c9SAjit Khaparde 			vxlan_mask = item->mask;
5465c1171c9SAjit Khaparde 			/* Check if VXLAN item is used to describe protocol.
5475c1171c9SAjit Khaparde 			 * If yes, both spec and mask should be NULL.
5485c1171c9SAjit Khaparde 			 * If no, both spec and mask shouldn't be NULL.
5495c1171c9SAjit Khaparde 			 */
5505c1171c9SAjit Khaparde 			if ((!vxlan_spec && vxlan_mask) ||
5515c1171c9SAjit Khaparde 			    (vxlan_spec && !vxlan_mask)) {
5525c1171c9SAjit Khaparde 				rte_flow_error_set(error,
5535c1171c9SAjit Khaparde 						   EINVAL,
5545c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
5555c1171c9SAjit Khaparde 						   item,
5565c1171c9SAjit Khaparde 						   "Invalid VXLAN item");
5575c1171c9SAjit Khaparde 				return -rte_errno;
5585c1171c9SAjit Khaparde 			}
5595c1171c9SAjit Khaparde 
56011e5e196SSomnath Kotur 			if (!vxlan_spec && !vxlan_mask) {
56111e5e196SSomnath Kotur 				filter->tunnel_type =
56211e5e196SSomnath Kotur 				CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN;
56311e5e196SSomnath Kotur 				break;
56411e5e196SSomnath Kotur 			}
56511e5e196SSomnath Kotur 
5665ec2a97eSThomas Monjalon 			if ((vxlan_spec->hdr.rsvd0[0] != 0) ||
5675ec2a97eSThomas Monjalon 			    (vxlan_spec->hdr.rsvd0[1] != 0) ||
5685ec2a97eSThomas Monjalon 			    (vxlan_spec->hdr.rsvd0[2] != 0) ||
5695ec2a97eSThomas Monjalon 			    (vxlan_spec->hdr.rsvd1 != 0) ||
5705ec2a97eSThomas Monjalon 			    (vxlan_spec->hdr.flags != 8)) {
5715c1171c9SAjit Khaparde 				rte_flow_error_set(error,
5725c1171c9SAjit Khaparde 						   EINVAL,
5735c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
5745c1171c9SAjit Khaparde 						   item,
5755c1171c9SAjit Khaparde 						   "Invalid VXLAN item");
5765c1171c9SAjit Khaparde 				return -rte_errno;
5775c1171c9SAjit Khaparde 			}
5785c1171c9SAjit Khaparde 
5795c1171c9SAjit Khaparde 			/* Check if VNI is masked. */
580d4cb1e71SGaurav Singh 			if (vxlan_mask != NULL) {
5815c1171c9SAjit Khaparde 				vni_masked =
5825ec2a97eSThomas Monjalon 					!!memcmp(vxlan_mask->hdr.vni, vni_mask,
5835c1171c9SAjit Khaparde 						 RTE_DIM(vni_mask));
5845c1171c9SAjit Khaparde 				if (vni_masked) {
5855c1171c9SAjit Khaparde 					rte_flow_error_set
5865c1171c9SAjit Khaparde 						(error,
5875c1171c9SAjit Khaparde 						 EINVAL,
5885c1171c9SAjit Khaparde 						 RTE_FLOW_ERROR_TYPE_ITEM,
5895c1171c9SAjit Khaparde 						 item,
5905c1171c9SAjit Khaparde 						 "Invalid VNI mask");
5915c1171c9SAjit Khaparde 					return -rte_errno;
5925c1171c9SAjit Khaparde 				}
5935c1171c9SAjit Khaparde 
5945c1171c9SAjit Khaparde 				rte_memcpy(((uint8_t *)&tenant_id_be + 1),
5955ec2a97eSThomas Monjalon 					   vxlan_spec->hdr.vni, 3);
5965c1171c9SAjit Khaparde 				filter->vni =
5975c1171c9SAjit Khaparde 					rte_be_to_cpu_32(tenant_id_be);
5985c1171c9SAjit Khaparde 				filter->tunnel_type =
5995c1171c9SAjit Khaparde 				 CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN;
6005c1171c9SAjit Khaparde 			}
6015c1171c9SAjit Khaparde 			break;
6025c1171c9SAjit Khaparde 		case RTE_FLOW_ITEM_TYPE_NVGRE:
6035c1171c9SAjit Khaparde 			nvgre_spec = item->spec;
6045c1171c9SAjit Khaparde 			nvgre_mask = item->mask;
6055c1171c9SAjit Khaparde 			/* Check if NVGRE item is used to describe protocol.
6065c1171c9SAjit Khaparde 			 * If yes, both spec and mask should be NULL.
6075c1171c9SAjit Khaparde 			 * If no, both spec and mask shouldn't be NULL.
6085c1171c9SAjit Khaparde 			 */
6095c1171c9SAjit Khaparde 			if ((!nvgre_spec && nvgre_mask) ||
6105c1171c9SAjit Khaparde 			    (nvgre_spec && !nvgre_mask)) {
6115c1171c9SAjit Khaparde 				rte_flow_error_set(error,
6125c1171c9SAjit Khaparde 						   EINVAL,
6135c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
6145c1171c9SAjit Khaparde 						   item,
6155c1171c9SAjit Khaparde 						   "Invalid NVGRE item");
6165c1171c9SAjit Khaparde 				return -rte_errno;
6175c1171c9SAjit Khaparde 			}
6185c1171c9SAjit Khaparde 
61911e5e196SSomnath Kotur 			if (!nvgre_spec && !nvgre_mask) {
62011e5e196SSomnath Kotur 				filter->tunnel_type =
62111e5e196SSomnath Kotur 				CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE;
62211e5e196SSomnath Kotur 				break;
62311e5e196SSomnath Kotur 			}
62411e5e196SSomnath Kotur 
6255c1171c9SAjit Khaparde 			if (nvgre_spec->c_k_s_rsvd0_ver != 0x2000 ||
6265c1171c9SAjit Khaparde 			    nvgre_spec->protocol != 0x6558) {
6275c1171c9SAjit Khaparde 				rte_flow_error_set(error,
6285c1171c9SAjit Khaparde 						   EINVAL,
6295c1171c9SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ITEM,
6305c1171c9SAjit Khaparde 						   item,
6315c1171c9SAjit Khaparde 						   "Invalid NVGRE item");
6325c1171c9SAjit Khaparde 				return -rte_errno;
6335c1171c9SAjit Khaparde 			}
6345c1171c9SAjit Khaparde 
6355c1171c9SAjit Khaparde 			if (nvgre_spec && nvgre_mask) {
6365c1171c9SAjit Khaparde 				tni_masked =
6375c1171c9SAjit Khaparde 					!!memcmp(nvgre_mask->tni, tni_mask,
6385c1171c9SAjit Khaparde 						 RTE_DIM(tni_mask));
6395c1171c9SAjit Khaparde 				if (tni_masked) {
6405c1171c9SAjit Khaparde 					rte_flow_error_set
6415c1171c9SAjit Khaparde 						(error,
6425c1171c9SAjit Khaparde 						 EINVAL,
6435c1171c9SAjit Khaparde 						 RTE_FLOW_ERROR_TYPE_ITEM,
6445c1171c9SAjit Khaparde 						 item,
6455c1171c9SAjit Khaparde 						 "Invalid TNI mask");
6465c1171c9SAjit Khaparde 					return -rte_errno;
6475c1171c9SAjit Khaparde 				}
6485c1171c9SAjit Khaparde 				rte_memcpy(((uint8_t *)&tenant_id_be + 1),
6495c1171c9SAjit Khaparde 					   nvgre_spec->tni, 3);
6505c1171c9SAjit Khaparde 				filter->vni =
6515c1171c9SAjit Khaparde 					rte_be_to_cpu_32(tenant_id_be);
6525c1171c9SAjit Khaparde 				filter->tunnel_type =
6535c1171c9SAjit Khaparde 				 CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE;
6545c1171c9SAjit Khaparde 			}
6555c1171c9SAjit Khaparde 			break;
65611e5e196SSomnath Kotur 
65711e5e196SSomnath Kotur 		case RTE_FLOW_ITEM_TYPE_GRE:
65811e5e196SSomnath Kotur 			gre_spec = (const struct rte_flow_item_gre *)item->spec;
65911e5e196SSomnath Kotur 			gre_mask = (const struct rte_flow_item_gre *)item->mask;
66011e5e196SSomnath Kotur 
66111e5e196SSomnath Kotur 			/*
66211e5e196SSomnath Kotur 			 *Check if GRE item is used to describe protocol.
66311e5e196SSomnath Kotur 			 * If yes, both spec and mask should be NULL.
66411e5e196SSomnath Kotur 			 * If no, both spec and mask shouldn't be NULL.
66511e5e196SSomnath Kotur 			 */
66611e5e196SSomnath Kotur 			if (!!gre_spec ^ !!gre_mask) {
66711e5e196SSomnath Kotur 				rte_flow_error_set(error, EINVAL,
66811e5e196SSomnath Kotur 						   RTE_FLOW_ERROR_TYPE_ITEM,
66911e5e196SSomnath Kotur 						   item,
67011e5e196SSomnath Kotur 						   "Invalid GRE item");
67111e5e196SSomnath Kotur 				return -rte_errno;
67211e5e196SSomnath Kotur 			}
67311e5e196SSomnath Kotur 
67411e5e196SSomnath Kotur 			if (!gre_spec && !gre_mask) {
67511e5e196SSomnath Kotur 				filter->tunnel_type =
67611e5e196SSomnath Kotur 				CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE;
67711e5e196SSomnath Kotur 				break;
67811e5e196SSomnath Kotur 			}
67911e5e196SSomnath Kotur 			break;
6805c1171c9SAjit Khaparde 		default:
6815c1171c9SAjit Khaparde 			break;
6825c1171c9SAjit Khaparde 		}
6835c1171c9SAjit Khaparde 		item++;
6845c1171c9SAjit Khaparde 	}
6855c1171c9SAjit Khaparde 	filter->enables = en;
686afef822bSAjit Khaparde 	filter->valid_flags = valid_flags;
6875c1171c9SAjit Khaparde 
688239695f7SAjit Khaparde 	/* Items parsed but no filter to create in HW. */
689239695f7SAjit Khaparde 	if (filter->enables == 0 && filter->valid_flags == 0)
690239695f7SAjit Khaparde 		filter->filter_type = HWRM_CFA_CONFIG;
691239695f7SAjit Khaparde 
6925c1171c9SAjit Khaparde 	return 0;
6935c1171c9SAjit Khaparde }
6945c1171c9SAjit Khaparde 
6955c1171c9SAjit Khaparde /* Parse attributes */
6965c1171c9SAjit Khaparde static int
6975c1171c9SAjit Khaparde bnxt_flow_parse_attr(const struct rte_flow_attr *attr,
6985c1171c9SAjit Khaparde 		     struct rte_flow_error *error)
6995c1171c9SAjit Khaparde {
7005c1171c9SAjit Khaparde 	/* Must be input direction */
7015c1171c9SAjit Khaparde 	if (!attr->ingress) {
7025c1171c9SAjit Khaparde 		rte_flow_error_set(error,
7035c1171c9SAjit Khaparde 				   EINVAL,
7045c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
7055c1171c9SAjit Khaparde 				   attr,
7065c1171c9SAjit Khaparde 				   "Only support ingress.");
7075c1171c9SAjit Khaparde 		return -rte_errno;
7085c1171c9SAjit Khaparde 	}
7095c1171c9SAjit Khaparde 
7105c1171c9SAjit Khaparde 	/* Not supported */
7115c1171c9SAjit Khaparde 	if (attr->egress) {
7125c1171c9SAjit Khaparde 		rte_flow_error_set(error,
7135c1171c9SAjit Khaparde 				   EINVAL,
7145c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
7155c1171c9SAjit Khaparde 				   attr,
7165c1171c9SAjit Khaparde 				   "No support for egress.");
7175c1171c9SAjit Khaparde 		return -rte_errno;
7185c1171c9SAjit Khaparde 	}
7195c1171c9SAjit Khaparde 
7205c1171c9SAjit Khaparde 	return 0;
7215c1171c9SAjit Khaparde }
7225c1171c9SAjit Khaparde 
723adc0f81cSAjit Khaparde static struct bnxt_filter_info *
724adc0f81cSAjit Khaparde bnxt_find_matching_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf)
7255c1171c9SAjit Khaparde {
726adc0f81cSAjit Khaparde 	struct bnxt_filter_info *mf, *f0;
7275c1171c9SAjit Khaparde 	struct bnxt_vnic_info *vnic0;
728adc0f81cSAjit Khaparde 	int i;
7295c1171c9SAjit Khaparde 
7306d160d77SRandy Schacher 	vnic0 = bnxt_get_default_vnic(bp);
7315c1171c9SAjit Khaparde 	f0 = STAILQ_FIRST(&vnic0->filter);
7325c1171c9SAjit Khaparde 
7335c1171c9SAjit Khaparde 	/* This flow has same DST MAC as the port/l2 filter. */
73435b2d13fSOlivier Matz 	if (memcmp(f0->l2_addr, nf->dst_macaddr, RTE_ETHER_ADDR_LEN) == 0)
7355c1171c9SAjit Khaparde 		return f0;
7365c1171c9SAjit Khaparde 
737adc0f81cSAjit Khaparde 	for (i = bp->max_vnics - 1; i >= 0; i--) {
738adc0f81cSAjit Khaparde 		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
739adc0f81cSAjit Khaparde 
740adc0f81cSAjit Khaparde 		if (vnic->fw_vnic_id == INVALID_VNIC_ID)
741adc0f81cSAjit Khaparde 			continue;
742adc0f81cSAjit Khaparde 
743f0f6b5e6SSomnath Kotur 		STAILQ_FOREACH(mf, &vnic->filter, next) {
744adc0f81cSAjit Khaparde 
745adc0f81cSAjit Khaparde 			if (mf->matching_l2_fltr_ptr)
746adc0f81cSAjit Khaparde 				continue;
747adc0f81cSAjit Khaparde 
748adc0f81cSAjit Khaparde 			if (mf->ethertype == nf->ethertype &&
749adc0f81cSAjit Khaparde 			    mf->l2_ovlan == nf->l2_ovlan &&
750adc0f81cSAjit Khaparde 			    mf->l2_ovlan_mask == nf->l2_ovlan_mask &&
751adc0f81cSAjit Khaparde 			    mf->l2_ivlan == nf->l2_ivlan &&
752adc0f81cSAjit Khaparde 			    mf->l2_ivlan_mask == nf->l2_ivlan_mask &&
753adc0f81cSAjit Khaparde 			    !memcmp(mf->src_macaddr, nf->src_macaddr,
754adc0f81cSAjit Khaparde 				    RTE_ETHER_ADDR_LEN) &&
755adc0f81cSAjit Khaparde 			    !memcmp(mf->dst_macaddr, nf->dst_macaddr,
756adc0f81cSAjit Khaparde 				    RTE_ETHER_ADDR_LEN))
757adc0f81cSAjit Khaparde 				return mf;
758adc0f81cSAjit Khaparde 		}
759adc0f81cSAjit Khaparde 	}
760adc0f81cSAjit Khaparde 	return NULL;
761adc0f81cSAjit Khaparde }
762adc0f81cSAjit Khaparde 
763adc0f81cSAjit Khaparde static struct bnxt_filter_info *
764adc0f81cSAjit Khaparde bnxt_create_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
765adc0f81cSAjit Khaparde 		      struct bnxt_vnic_info *vnic)
766adc0f81cSAjit Khaparde {
767adc0f81cSAjit Khaparde 	struct bnxt_filter_info *filter1;
768adc0f81cSAjit Khaparde 	int rc;
769adc0f81cSAjit Khaparde 
770afef822bSAjit Khaparde 	/* Alloc new L2 filter.
771adc0f81cSAjit Khaparde 	 * This flow needs MAC filter which does not match any existing
772adc0f81cSAjit Khaparde 	 * L2 filters.
773afef822bSAjit Khaparde 	 */
7745c1171c9SAjit Khaparde 	filter1 = bnxt_get_unused_filter(bp);
7755c1171c9SAjit Khaparde 	if (filter1 == NULL)
7765c1171c9SAjit Khaparde 		return NULL;
7775c1171c9SAjit Khaparde 
778f0f6b5e6SSomnath Kotur 	memcpy(filter1, nf, sizeof(*filter1));
779f0f6b5e6SSomnath Kotur 
780afef822bSAjit Khaparde 	filter1->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_XDP_DISABLE;
781afef822bSAjit Khaparde 	filter1->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
782afef822bSAjit Khaparde 	if (nf->valid_flags & BNXT_FLOW_L2_SRC_VALID_FLAG ||
783afef822bSAjit Khaparde 	    nf->valid_flags & BNXT_FLOW_L2_DST_VALID_FLAG) {
784afef822bSAjit Khaparde 		filter1->flags |=
785afef822bSAjit Khaparde 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST;
786e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Create Outer filter");
787afef822bSAjit Khaparde 	}
788afef822bSAjit Khaparde 
789afef822bSAjit Khaparde 	if (nf->filter_type == HWRM_CFA_L2_FILTER &&
790afef822bSAjit Khaparde 	    (nf->valid_flags & BNXT_FLOW_L2_SRC_VALID_FLAG ||
791afef822bSAjit Khaparde 	     nf->valid_flags & BNXT_FLOW_L2_INNER_SRC_VALID_FLAG)) {
792e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Create L2 filter for SRC MAC");
793afef822bSAjit Khaparde 		filter1->flags |=
794afef822bSAjit Khaparde 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_SOURCE_VALID;
795afef822bSAjit Khaparde 		memcpy(filter1->l2_addr, nf->src_macaddr, RTE_ETHER_ADDR_LEN);
796afef822bSAjit Khaparde 	} else {
797e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Create L2 filter for DST MAC");
798afef822bSAjit Khaparde 		memcpy(filter1->l2_addr, nf->dst_macaddr, RTE_ETHER_ADDR_LEN);
799afef822bSAjit Khaparde 	}
800afef822bSAjit Khaparde 
801749ba50dSAjit Khaparde 	if (nf->priority &&
802749ba50dSAjit Khaparde 	    (nf->valid_flags & BNXT_FLOW_L2_DST_VALID_FLAG ||
803749ba50dSAjit Khaparde 	     nf->valid_flags & BNXT_FLOW_L2_INNER_DST_VALID_FLAG)) {
804afef822bSAjit Khaparde 		/* Tell the FW where to place the filter in the table. */
805749ba50dSAjit Khaparde 		if (nf->priority > 65535) {
806afef822bSAjit Khaparde 			filter1->pri_hint =
807afef822bSAjit Khaparde 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_BELOW_FILTER;
808afef822bSAjit Khaparde 			/* This will place the filter in TCAM */
809afef822bSAjit Khaparde 			filter1->l2_filter_id_hint = (uint64_t)-1;
810afef822bSAjit Khaparde 		}
811749ba50dSAjit Khaparde 	}
812afef822bSAjit Khaparde 
813b0d3c584SAjit Khaparde 	if (nf->valid_flags & (BNXT_FLOW_L2_DST_VALID_FLAG |
814b0d3c584SAjit Khaparde 			       BNXT_FLOW_L2_SRC_VALID_FLAG |
815b0d3c584SAjit Khaparde 			       BNXT_FLOW_L2_INNER_SRC_VALID_FLAG |
816b0d3c584SAjit Khaparde 			       BNXT_FLOW_L2_INNER_DST_VALID_FLAG)) {
817b0d3c584SAjit Khaparde 		filter1->enables =
818b0d3c584SAjit Khaparde 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
8195c1171c9SAjit Khaparde 			L2_FILTER_ALLOC_INPUT_EN_L2_ADDR_MASK;
82035b2d13fSOlivier Matz 		memset(filter1->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
821b0d3c584SAjit Khaparde 	}
822b0d3c584SAjit Khaparde 
823b0d3c584SAjit Khaparde 	if (nf->valid_flags & BNXT_FLOW_L2_DROP_FLAG) {
824b0d3c584SAjit Khaparde 		filter1->flags |=
825b0d3c584SAjit Khaparde 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_DROP;
826b0d3c584SAjit Khaparde 		if (nf->ethertype == RTE_ETHER_TYPE_IPV4) {
827b0d3c584SAjit Khaparde 			/* Num VLANs for drop filter will/should be 0.
828b0d3c584SAjit Khaparde 			 * If the req is memset to 0, then the count will
829b0d3c584SAjit Khaparde 			 * be automatically set to 0.
830b0d3c584SAjit Khaparde 			 */
831b0d3c584SAjit Khaparde 			if (nf->valid_flags & BNXT_FLOW_PARSE_INNER_FLAG) {
832b0d3c584SAjit Khaparde 				filter1->enables |=
833b0d3c584SAjit Khaparde 					L2_FILTER_ALLOC_INPUT_EN_T_NUM_VLANS;
834b0d3c584SAjit Khaparde 			} else {
835b0d3c584SAjit Khaparde 				filter1->enables |=
836b0d3c584SAjit Khaparde 					L2_FILTER_ALLOC_INPUT_EN_NUM_VLANS;
837b0d3c584SAjit Khaparde 				filter1->flags |=
838b0d3c584SAjit Khaparde 				HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST;
839b0d3c584SAjit Khaparde 			}
840b0d3c584SAjit Khaparde 		}
841b0d3c584SAjit Khaparde 	}
842b0d3c584SAjit Khaparde 
8435c1171c9SAjit Khaparde 	rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id,
8445c1171c9SAjit Khaparde 				     filter1);
8455c1171c9SAjit Khaparde 	if (rc) {
8465c1171c9SAjit Khaparde 		bnxt_free_filter(bp, filter1);
8475c1171c9SAjit Khaparde 		return NULL;
8485c1171c9SAjit Khaparde 	}
8495c1171c9SAjit Khaparde 	return filter1;
8505c1171c9SAjit Khaparde }
8515c1171c9SAjit Khaparde 
852adc0f81cSAjit Khaparde struct bnxt_filter_info *
853adc0f81cSAjit Khaparde bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
854adc0f81cSAjit Khaparde 		   struct bnxt_vnic_info *vnic)
855adc0f81cSAjit Khaparde {
856adc0f81cSAjit Khaparde 	struct bnxt_filter_info *l2_filter = NULL;
857adc0f81cSAjit Khaparde 
858adc0f81cSAjit Khaparde 	l2_filter = bnxt_find_matching_l2_filter(bp, nf);
859adc0f81cSAjit Khaparde 	if (l2_filter) {
860adc0f81cSAjit Khaparde 		l2_filter->l2_ref_cnt++;
861adc0f81cSAjit Khaparde 	} else {
862adc0f81cSAjit Khaparde 		l2_filter = bnxt_create_l2_filter(bp, nf, vnic);
863f0f6b5e6SSomnath Kotur 		if (l2_filter) {
864f0f6b5e6SSomnath Kotur 			STAILQ_INSERT_TAIL(&vnic->filter, l2_filter, next);
865f0f6b5e6SSomnath Kotur 			l2_filter->vnic = vnic;
866adc0f81cSAjit Khaparde 		}
867f0f6b5e6SSomnath Kotur 	}
868f0f6b5e6SSomnath Kotur 	nf->matching_l2_fltr_ptr = l2_filter;
869adc0f81cSAjit Khaparde 
870adc0f81cSAjit Khaparde 	return l2_filter;
871adc0f81cSAjit Khaparde }
872adc0f81cSAjit Khaparde 
8734171ac66SKalesh AP static void bnxt_vnic_cleanup(struct bnxt *bp, struct bnxt_vnic_info *vnic)
8744171ac66SKalesh AP {
8754171ac66SKalesh AP 	if (vnic->rx_queue_cnt > 1)
8764171ac66SKalesh AP 		bnxt_hwrm_vnic_ctx_free(bp, vnic);
8774171ac66SKalesh AP 
8784171ac66SKalesh AP 	bnxt_hwrm_vnic_free(bp, vnic);
8794171ac66SKalesh AP 
8804171ac66SKalesh AP 	rte_free(vnic->fw_grp_ids);
8814171ac66SKalesh AP 	vnic->fw_grp_ids = NULL;
8824171ac66SKalesh AP 
8834171ac66SKalesh AP 	vnic->rx_queue_cnt = 0;
88435a03209SAjit Khaparde 	vnic->hash_type = 0;
8854171ac66SKalesh AP }
8864171ac66SKalesh AP 
88752b0e588SKalesh AP static int bnxt_vnic_prep(struct bnxt *bp, struct bnxt_vnic_info *vnic,
88852b0e588SKalesh AP 			  const struct rte_flow_action *act,
88952b0e588SKalesh AP 			  struct rte_flow_error *error)
890d24610f7SAjit Khaparde {
891d24610f7SAjit Khaparde 	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
892d24610f7SAjit Khaparde 	uint64_t rx_offloads = dev_conf->rxmode.offloads;
893d24610f7SAjit Khaparde 	int rc;
894d24610f7SAjit Khaparde 
895a0c2315aSLance Richardson 	if (bp->nr_vnics > bp->max_vnics - 1)
89652b0e588SKalesh AP 		return rte_flow_error_set(error, EINVAL,
89752b0e588SKalesh AP 					  RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
89852b0e588SKalesh AP 					  NULL,
89952b0e588SKalesh AP 					  "Group id is invalid");
900a0c2315aSLance Richardson 
901d24610f7SAjit Khaparde 	rc = bnxt_vnic_grp_alloc(bp, vnic);
902d24610f7SAjit Khaparde 	if (rc)
90352b0e588SKalesh AP 		return rte_flow_error_set(error, -rc,
90452b0e588SKalesh AP 					  RTE_FLOW_ERROR_TYPE_ACTION,
90552b0e588SKalesh AP 					  act,
90652b0e588SKalesh AP 					  "Failed to alloc VNIC group");
907d24610f7SAjit Khaparde 
9086d160d77SRandy Schacher 	/* populate the fw group table */
9096d160d77SRandy Schacher 	bnxt_vnic_ring_grp_populate(bp, vnic);
9106d160d77SRandy Schacher 	bnxt_vnic_rules_init(vnic);
9116d160d77SRandy Schacher 
912d24610f7SAjit Khaparde 	rc = bnxt_hwrm_vnic_alloc(bp, vnic);
913d24610f7SAjit Khaparde 	if (rc) {
91452b0e588SKalesh AP 		rte_flow_error_set(error, -rc,
91552b0e588SKalesh AP 				   RTE_FLOW_ERROR_TYPE_ACTION,
91652b0e588SKalesh AP 				   act,
91752b0e588SKalesh AP 				   "Failed to alloc VNIC");
918d24610f7SAjit Khaparde 		goto ret;
919d24610f7SAjit Khaparde 	}
92052b0e588SKalesh AP 
921d24610f7SAjit Khaparde 	/* RSS context is required only when there is more than one RSS ring */
922d24610f7SAjit Khaparde 	if (vnic->rx_queue_cnt > 1) {
923b93fe4dbSKalesh AP 		rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, 0);
924d24610f7SAjit Khaparde 		if (rc) {
92552b0e588SKalesh AP 			rte_flow_error_set(error, -rc,
92652b0e588SKalesh AP 					   RTE_FLOW_ERROR_TYPE_ACTION,
92752b0e588SKalesh AP 					   act,
92852b0e588SKalesh AP 					   "Failed to alloc VNIC context");
929d24610f7SAjit Khaparde 			goto ret;
930d24610f7SAjit Khaparde 		}
931d24610f7SAjit Khaparde 	}
932d24610f7SAjit Khaparde 
933295968d1SFerruh Yigit 	if (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
934d24610f7SAjit Khaparde 		vnic->vlan_strip = true;
935d24610f7SAjit Khaparde 	else
936d24610f7SAjit Khaparde 		vnic->vlan_strip = false;
937d24610f7SAjit Khaparde 
938d24610f7SAjit Khaparde 	rc = bnxt_hwrm_vnic_cfg(bp, vnic);
93952b0e588SKalesh AP 	if (rc) {
94052b0e588SKalesh AP 		rte_flow_error_set(error, -rc,
94152b0e588SKalesh AP 				   RTE_FLOW_ERROR_TYPE_ACTION,
94252b0e588SKalesh AP 				   act,
94352b0e588SKalesh AP 				   "Failed to configure VNIC");
944d24610f7SAjit Khaparde 		goto ret;
94552b0e588SKalesh AP 	}
946d24610f7SAjit Khaparde 
94752b0e588SKalesh AP 	rc = bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
94852b0e588SKalesh AP 	if (rc) {
94952b0e588SKalesh AP 		rte_flow_error_set(error, -rc,
95052b0e588SKalesh AP 				   RTE_FLOW_ERROR_TYPE_ACTION,
95152b0e588SKalesh AP 				   act,
95252b0e588SKalesh AP 				   "Failed to configure VNIC plcmode");
95352b0e588SKalesh AP 		goto ret;
95452b0e588SKalesh AP 	}
95552b0e588SKalesh AP 
9564171ac66SKalesh AP 	bp->nr_vnics++;
9574171ac66SKalesh AP 
95852b0e588SKalesh AP 	return 0;
959d24610f7SAjit Khaparde 
960d24610f7SAjit Khaparde ret:
9614171ac66SKalesh AP 	bnxt_vnic_cleanup(bp, vnic);
962d24610f7SAjit Khaparde 	return rc;
963d24610f7SAjit Khaparde }
964d24610f7SAjit Khaparde 
965adc0f81cSAjit Khaparde static int match_vnic_rss_cfg(struct bnxt *bp,
966adc0f81cSAjit Khaparde 			      struct bnxt_vnic_info *vnic,
967adc0f81cSAjit Khaparde 			      const struct rte_flow_action_rss *rss)
968adc0f81cSAjit Khaparde {
969adc0f81cSAjit Khaparde 	unsigned int match = 0, i;
970adc0f81cSAjit Khaparde 
971adc0f81cSAjit Khaparde 	if (vnic->rx_queue_cnt != rss->queue_num)
972adc0f81cSAjit Khaparde 		return -EINVAL;
973adc0f81cSAjit Khaparde 
974adc0f81cSAjit Khaparde 	for (i = 0; i < rss->queue_num; i++) {
975adc0f81cSAjit Khaparde 		if (!bp->rx_queues[rss->queue[i]]->vnic->rx_queue_cnt &&
976adc0f81cSAjit Khaparde 		    !bp->rx_queues[rss->queue[i]]->rx_started)
977adc0f81cSAjit Khaparde 			return -EINVAL;
978adc0f81cSAjit Khaparde 	}
979adc0f81cSAjit Khaparde 
980adc0f81cSAjit Khaparde 	for (i = 0; i < vnic->rx_queue_cnt; i++) {
981adc0f81cSAjit Khaparde 		int j;
982adc0f81cSAjit Khaparde 
983adc0f81cSAjit Khaparde 		for (j = 0; j < vnic->rx_queue_cnt; j++) {
984adc0f81cSAjit Khaparde 			if (bp->grp_info[rss->queue[i]].fw_grp_id ==
985adc0f81cSAjit Khaparde 			    vnic->fw_grp_ids[j])
986adc0f81cSAjit Khaparde 				match++;
987adc0f81cSAjit Khaparde 		}
988adc0f81cSAjit Khaparde 	}
989adc0f81cSAjit Khaparde 
990adc0f81cSAjit Khaparde 	if (match != vnic->rx_queue_cnt) {
991e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR,
992e99981afSDavid Marchand 			    "VNIC queue count %d vs queues matched %d",
993adc0f81cSAjit Khaparde 			    match, vnic->rx_queue_cnt);
994adc0f81cSAjit Khaparde 		return -EINVAL;
995adc0f81cSAjit Khaparde 	}
996adc0f81cSAjit Khaparde 
997adc0f81cSAjit Khaparde 	return 0;
998adc0f81cSAjit Khaparde }
999adc0f81cSAjit Khaparde 
1000adc0f81cSAjit Khaparde static void
1001adc0f81cSAjit Khaparde bnxt_update_filter_flags_en(struct bnxt_filter_info *filter,
1002adc0f81cSAjit Khaparde 			    struct bnxt_filter_info *filter1,
1003adc0f81cSAjit Khaparde 			    int use_ntuple)
1004adc0f81cSAjit Khaparde {
1005adc0f81cSAjit Khaparde 	if (!use_ntuple &&
1006adc0f81cSAjit Khaparde 	    !(filter->valid_flags &
1007adc0f81cSAjit Khaparde 	      ~(BNXT_FLOW_L2_DST_VALID_FLAG |
1008adc0f81cSAjit Khaparde 		BNXT_FLOW_L2_SRC_VALID_FLAG |
1009adc0f81cSAjit Khaparde 		BNXT_FLOW_L2_INNER_SRC_VALID_FLAG |
1010b0d3c584SAjit Khaparde 		BNXT_FLOW_L2_INNER_DST_VALID_FLAG |
1011b0d3c584SAjit Khaparde 		BNXT_FLOW_L2_DROP_FLAG |
1012b0d3c584SAjit Khaparde 		BNXT_FLOW_PARSE_INNER_FLAG))) {
1013adc0f81cSAjit Khaparde 		filter->flags = filter1->flags;
1014adc0f81cSAjit Khaparde 		filter->enables = filter1->enables;
1015adc0f81cSAjit Khaparde 		filter->filter_type = HWRM_CFA_L2_FILTER;
1016adc0f81cSAjit Khaparde 		memcpy(filter->l2_addr, filter1->l2_addr, RTE_ETHER_ADDR_LEN);
1017adc0f81cSAjit Khaparde 		memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
1018adc0f81cSAjit Khaparde 		filter->pri_hint = filter1->pri_hint;
1019adc0f81cSAjit Khaparde 		filter->l2_filter_id_hint = filter1->l2_filter_id_hint;
1020adc0f81cSAjit Khaparde 	}
1021adc0f81cSAjit Khaparde 	filter->fw_l2_filter_id = filter1->fw_l2_filter_id;
1022adc0f81cSAjit Khaparde 	filter->l2_ref_cnt = filter1->l2_ref_cnt;
102394eb699bSAjit Khaparde 	filter->flow_id = filter1->flow_id;
1024e99981afSDavid Marchand 	PMD_DRV_LOG_LINE(DEBUG,
1025e99981afSDavid Marchand 		"l2_filter: %p fw_l2_filter_id %" PRIx64 " l2_ref_cnt %u",
1026adc0f81cSAjit Khaparde 		filter1, filter->fw_l2_filter_id, filter->l2_ref_cnt);
1027adc0f81cSAjit Khaparde }
1028adc0f81cSAjit Khaparde 
1029239695f7SAjit Khaparde static int
1030239695f7SAjit Khaparde bnxt_validate_rss_action(const struct rte_flow_action actions[])
1031239695f7SAjit Khaparde {
1032239695f7SAjit Khaparde 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1033239695f7SAjit Khaparde 		switch (actions->type) {
1034239695f7SAjit Khaparde 		case RTE_FLOW_ACTION_TYPE_VOID:
1035239695f7SAjit Khaparde 			break;
1036239695f7SAjit Khaparde 		case RTE_FLOW_ACTION_TYPE_RSS:
1037239695f7SAjit Khaparde 			break;
1038239695f7SAjit Khaparde 		default:
1039239695f7SAjit Khaparde 			return -ENOTSUP;
1040239695f7SAjit Khaparde 		}
1041239695f7SAjit Khaparde 	}
1042239695f7SAjit Khaparde 
1043239695f7SAjit Khaparde 	return 0;
1044239695f7SAjit Khaparde }
1045239695f7SAjit Khaparde 
1046239695f7SAjit Khaparde static int
1047239695f7SAjit Khaparde bnxt_get_vnic(struct bnxt *bp, uint32_t group)
1048239695f7SAjit Khaparde {
1049239695f7SAjit Khaparde 	int vnic_id = 0;
1050239695f7SAjit Khaparde 
1051239695f7SAjit Khaparde 	/* For legacy NS3 based implementations,
1052239695f7SAjit Khaparde 	 * group_id will be mapped to a VNIC ID.
1053239695f7SAjit Khaparde 	 */
1054239695f7SAjit Khaparde 	if (BNXT_STINGRAY(bp))
1055239695f7SAjit Khaparde 		vnic_id = group;
1056239695f7SAjit Khaparde 
1057239695f7SAjit Khaparde 	/* Non NS3 cases, group_id will be ignored.
1058239695f7SAjit Khaparde 	 * Setting will be configured on default VNIC.
1059239695f7SAjit Khaparde 	 */
1060239695f7SAjit Khaparde 	return vnic_id;
1061239695f7SAjit Khaparde }
1062239695f7SAjit Khaparde 
1063239695f7SAjit Khaparde static int
1064239695f7SAjit Khaparde bnxt_vnic_rss_cfg_update(struct bnxt *bp,
1065239695f7SAjit Khaparde 			 struct bnxt_vnic_info *vnic,
1066239695f7SAjit Khaparde 			 const struct rte_flow_action *act,
1067239695f7SAjit Khaparde 			 struct rte_flow_error *error)
1068239695f7SAjit Khaparde {
1069239695f7SAjit Khaparde 	const struct rte_flow_action_rss *rss;
1070962a5212SSomnath Kotur 	unsigned int rss_idx, i, j, fw_idx;
107135a03209SAjit Khaparde 	uint32_t hash_type;
1072239695f7SAjit Khaparde 	uint64_t types;
1073239695f7SAjit Khaparde 	int rc;
1074239695f7SAjit Khaparde 
1075239695f7SAjit Khaparde 	rss = (const struct rte_flow_action_rss *)act->conf;
1076239695f7SAjit Khaparde 
1077202a1711SKalesh AP 	/* must specify either all the Rx queues created by application or zero queues */
1078202a1711SKalesh AP 	if (rss->queue_num && vnic->rx_queue_cnt != rss->queue_num) {
1079202a1711SKalesh AP 		rte_flow_error_set(error,
1080202a1711SKalesh AP 				   EINVAL,
1081202a1711SKalesh AP 				   RTE_FLOW_ERROR_TYPE_ACTION,
1082202a1711SKalesh AP 				   act,
1083202a1711SKalesh AP 				   "Incorrect RXQ count");
1084202a1711SKalesh AP 		rc = -rte_errno;
1085202a1711SKalesh AP 		goto ret;
1086202a1711SKalesh AP 	}
1087202a1711SKalesh AP 
1088447a0721SKalesh AP 	/* Validate Rx queues */
1089447a0721SKalesh AP 	for (i = 0; i < rss->queue_num; i++) {
1090e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "RSS action Queue %d", rss->queue[i]);
1091447a0721SKalesh AP 
1092447a0721SKalesh AP 		if (rss->queue[i] >= bp->rx_nr_rings ||
1093447a0721SKalesh AP 		    !bp->rx_queues[rss->queue[i]]) {
1094447a0721SKalesh AP 			rte_flow_error_set(error,
1095447a0721SKalesh AP 					   EINVAL,
1096447a0721SKalesh AP 					   RTE_FLOW_ERROR_TYPE_ACTION,
1097447a0721SKalesh AP 					   act,
1098447a0721SKalesh AP 					   "Invalid queue ID for RSS");
1099447a0721SKalesh AP 			rc = -rte_errno;
1100447a0721SKalesh AP 			goto ret;
1101447a0721SKalesh AP 		}
1102447a0721SKalesh AP 	}
1103447a0721SKalesh AP 
1104447a0721SKalesh AP 	/* Duplicate queue ids are not supported. */
1105447a0721SKalesh AP 	for (i = 0; i < rss->queue_num; i++) {
1106447a0721SKalesh AP 		for (j = i + 1; j < rss->queue_num; j++) {
1107447a0721SKalesh AP 			if (rss->queue[i] == rss->queue[j]) {
1108447a0721SKalesh AP 				rte_flow_error_set(error,
1109447a0721SKalesh AP 						   EINVAL,
1110447a0721SKalesh AP 						   RTE_FLOW_ERROR_TYPE_ACTION,
1111447a0721SKalesh AP 						   act,
1112447a0721SKalesh AP 						   "Duplicate queue ID for RSS");
1113447a0721SKalesh AP 				rc = -rte_errno;
1114447a0721SKalesh AP 				goto ret;
1115447a0721SKalesh AP 			}
1116447a0721SKalesh AP 		}
1117447a0721SKalesh AP 	}
1118447a0721SKalesh AP 
111935a03209SAjit Khaparde 	if (BNXT_IS_HASH_FUNC_DEFAULT(rss->func) &&
112035a03209SAjit Khaparde 	    BNXT_IS_HASH_FUNC_TOEPLITZ(rss->func) &&
112135a03209SAjit Khaparde 	    BNXT_IS_HASH_FUNC_SIMPLE_XOR(bp, rss->func)) {
1122239695f7SAjit Khaparde 		rte_flow_error_set(error,
1123239695f7SAjit Khaparde 				   ENOTSUP,
1124239695f7SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
1125239695f7SAjit Khaparde 				   act,
1126239695f7SAjit Khaparde 				   "Unsupported RSS hash function");
1127239695f7SAjit Khaparde 		rc = -rte_errno;
1128239695f7SAjit Khaparde 		goto ret;
1129239695f7SAjit Khaparde 	}
1130239695f7SAjit Khaparde 
1131239695f7SAjit Khaparde 	/* key_len should match the hash key supported by hardware */
1132239695f7SAjit Khaparde 	if (rss->key_len != 0 && rss->key_len != HW_HASH_KEY_SIZE) {
1133239695f7SAjit Khaparde 		rte_flow_error_set(error,
1134239695f7SAjit Khaparde 				   EINVAL,
1135239695f7SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
1136239695f7SAjit Khaparde 				   act,
1137239695f7SAjit Khaparde 				   "Incorrect hash key parameters");
1138239695f7SAjit Khaparde 		rc = -rte_errno;
1139239695f7SAjit Khaparde 		goto ret;
1140239695f7SAjit Khaparde 	}
1141239695f7SAjit Khaparde 
1142239695f7SAjit Khaparde 	/* Currently RSS hash on inner and outer headers are supported.
1143df07aa22SAjit Khaparde 	 * 0 => Default (innermost RSS) setting
1144df07aa22SAjit Khaparde 	 * 1 => Outermost
1145239695f7SAjit Khaparde 	 */
1146df07aa22SAjit Khaparde 	if (rss->level > 1) {
1147239695f7SAjit Khaparde 		rte_flow_error_set(error,
1148239695f7SAjit Khaparde 				   ENOTSUP,
1149239695f7SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
1150239695f7SAjit Khaparde 				   act,
1151239695f7SAjit Khaparde 				   "Unsupported hash level");
1152239695f7SAjit Khaparde 		rc = -rte_errno;
1153239695f7SAjit Khaparde 		goto ret;
1154239695f7SAjit Khaparde 	}
1155239695f7SAjit Khaparde 
1156239695f7SAjit Khaparde 	if ((rss->queue_num == 0 && rss->queue != NULL) ||
1157239695f7SAjit Khaparde 	    (rss->queue_num != 0 && rss->queue == NULL)) {
1158239695f7SAjit Khaparde 		rte_flow_error_set(error,
1159239695f7SAjit Khaparde 				   EINVAL,
1160239695f7SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
1161239695f7SAjit Khaparde 				   act,
1162239695f7SAjit Khaparde 				   "Invalid queue config specified");
1163239695f7SAjit Khaparde 		rc = -rte_errno;
1164239695f7SAjit Khaparde 		goto ret;
1165239695f7SAjit Khaparde 	}
1166239695f7SAjit Khaparde 
1167239695f7SAjit Khaparde 	/* If RSS types is 0, use a best effort configuration */
1168df07aa22SAjit Khaparde 	types = rss->types ? rss->types : RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6;
1169239695f7SAjit Khaparde 
1170239695f7SAjit Khaparde 	hash_type = bnxt_rte_to_hwrm_hash_types(types);
1171239695f7SAjit Khaparde 
1172239695f7SAjit Khaparde 	/* If requested types can't be supported, leave existing settings */
1173239695f7SAjit Khaparde 	if (hash_type)
1174239695f7SAjit Khaparde 		vnic->hash_type = hash_type;
1175239695f7SAjit Khaparde 
1176239695f7SAjit Khaparde 	vnic->hash_mode =
1177239695f7SAjit Khaparde 		bnxt_rte_to_hwrm_hash_level(bp, rss->types, rss->level);
1178239695f7SAjit Khaparde 
117935a03209SAjit Khaparde 	/* For P7 chips update the hash_type if hash_type not explicitly passed.
118035a03209SAjit Khaparde 	 * TODO: For P5 chips.
118135a03209SAjit Khaparde 	 */
118235a03209SAjit Khaparde 	if (BNXT_CHIP_P7(bp) &&
118335a03209SAjit Khaparde 	    vnic->hash_mode == BNXT_HASH_MODE_DEFAULT && !hash_type)
118435a03209SAjit Khaparde 		vnic->hash_type = HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
118535a03209SAjit Khaparde 			HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
118635a03209SAjit Khaparde 
118735a03209SAjit Khaparde 	/* TODO:
118835a03209SAjit Khaparde 	 * hash will be performed on the L3 and L4 packet headers.
118935a03209SAjit Khaparde 	 * specific RSS hash types like IPv4-TCP etc... or L4-chksum or IPV4-chksum
119035a03209SAjit Khaparde 	 * will NOT have any bearing and will not be honored.
119135a03209SAjit Khaparde 	 * Check and reject flow create accordingly. TODO.
119235a03209SAjit Khaparde 	 */
119335a03209SAjit Khaparde 
119435a03209SAjit Khaparde 	rc = bnxt_rte_flow_to_hwrm_ring_select_mode(rss->func,
119535a03209SAjit Khaparde 						    rss->types,
119635a03209SAjit Khaparde 						    bp, vnic);
119735a03209SAjit Khaparde 	if (rc) {
119835a03209SAjit Khaparde 		rte_flow_error_set(error,
119935a03209SAjit Khaparde 				   ENOTSUP,
120035a03209SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
120135a03209SAjit Khaparde 				   act,
120235a03209SAjit Khaparde 				   "Unsupported RSS hash parameters");
120335a03209SAjit Khaparde 		rc = -rte_errno;
120435a03209SAjit Khaparde 		goto ret;
120535a03209SAjit Khaparde 	}
120635a03209SAjit Khaparde 
1207239695f7SAjit Khaparde 	/* Update RSS key only if key_len != 0 */
1208239695f7SAjit Khaparde 	if (rss->key_len != 0)
1209239695f7SAjit Khaparde 		memcpy(vnic->rss_hash_key, rss->key, rss->key_len);
1210239695f7SAjit Khaparde 
1211239695f7SAjit Khaparde 	if (rss->queue_num == 0)
1212239695f7SAjit Khaparde 		goto skip_rss_table;
1213239695f7SAjit Khaparde 
1214239695f7SAjit Khaparde 	/* Prepare the indirection table */
1215962a5212SSomnath Kotur 	for (rss_idx = 0, fw_idx = 0; rss_idx < HW_HASH_INDEX_SIZE;
1216962a5212SSomnath Kotur 	     rss_idx++, fw_idx++) {
1217962a5212SSomnath Kotur 		uint8_t *rxq_state = bp->eth_dev->data->rx_queue_state;
1218239695f7SAjit Khaparde 		struct bnxt_rx_queue *rxq;
1219239695f7SAjit Khaparde 		uint32_t idx;
1220239695f7SAjit Khaparde 
1221962a5212SSomnath Kotur 		for (i = 0; i < bp->rx_cp_nr_rings; i++) {
1222962a5212SSomnath Kotur 			idx = rss->queue[fw_idx % rss->queue_num];
1223962a5212SSomnath Kotur 			if (rxq_state[idx] != RTE_ETH_QUEUE_STATE_STOPPED)
1224962a5212SSomnath Kotur 				break;
1225962a5212SSomnath Kotur 			fw_idx++;
1226962a5212SSomnath Kotur 		}
1227962a5212SSomnath Kotur 
1228962a5212SSomnath Kotur 		if (i == bp->rx_cp_nr_rings)
1229962a5212SSomnath Kotur 			return 0;
1230239695f7SAjit Khaparde 
12313b56c3ffSAjit Khaparde 		if (BNXT_CHIP_P5_P7(bp)) {
1232239695f7SAjit Khaparde 			rxq = bp->rx_queues[idx];
1233239695f7SAjit Khaparde 			vnic->rss_table[rss_idx * 2] =
1234239695f7SAjit Khaparde 				rxq->rx_ring->rx_ring_struct->fw_ring_id;
1235239695f7SAjit Khaparde 			vnic->rss_table[rss_idx * 2 + 1] =
1236239695f7SAjit Khaparde 				rxq->cp_ring->cp_ring_struct->fw_ring_id;
1237239695f7SAjit Khaparde 		} else {
1238239695f7SAjit Khaparde 			vnic->rss_table[rss_idx] = vnic->fw_grp_ids[idx];
1239239695f7SAjit Khaparde 		}
1240239695f7SAjit Khaparde 	}
1241239695f7SAjit Khaparde 
1242239695f7SAjit Khaparde skip_rss_table:
1243239695f7SAjit Khaparde 	rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
124426ba9e7bSKalesh AP 	if (rc != 0) {
124526ba9e7bSKalesh AP 		rte_flow_error_set(error,
124626ba9e7bSKalesh AP 				   -rc,
124726ba9e7bSKalesh AP 				   RTE_FLOW_ERROR_TYPE_ACTION,
124826ba9e7bSKalesh AP 				   act,
124926ba9e7bSKalesh AP 				   "VNIC RSS configure failed");
1250*dd0191d5SShuanglin Wang 		vnic->rss_types_local = 0;
125126ba9e7bSKalesh AP 		rc = -rte_errno;
125226ba9e7bSKalesh AP 		goto ret;
125326ba9e7bSKalesh AP 	}
1254239695f7SAjit Khaparde ret:
1255239695f7SAjit Khaparde 	return rc;
1256239695f7SAjit Khaparde }
1257239695f7SAjit Khaparde 
12585c1171c9SAjit Khaparde static int
12595c1171c9SAjit Khaparde bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
12605c1171c9SAjit Khaparde 			     const struct rte_flow_item pattern[],
12615c1171c9SAjit Khaparde 			     const struct rte_flow_action actions[],
12625c1171c9SAjit Khaparde 			     const struct rte_flow_attr *attr,
12635c1171c9SAjit Khaparde 			     struct rte_flow_error *error,
12645c1171c9SAjit Khaparde 			     struct bnxt_filter_info *filter)
12655c1171c9SAjit Khaparde {
12665c1171c9SAjit Khaparde 	const struct rte_flow_action *act =
12675c1171c9SAjit Khaparde 		bnxt_flow_non_void_action(actions);
126878466c95SStephen Hemminger 	struct bnxt *bp = dev->data->dev_private;
1269d24610f7SAjit Khaparde 	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
1270b7e01f38SAjit Khaparde 	struct bnxt_vnic_info *vnic = NULL, *vnic0 = NULL;
12715c1171c9SAjit Khaparde 	const struct rte_flow_action_queue *act_q;
12725c1171c9SAjit Khaparde 	const struct rte_flow_action_vf *act_vf;
1273adc0f81cSAjit Khaparde 	struct bnxt_filter_info *filter1 = NULL;
1274adc0f81cSAjit Khaparde 	const struct rte_flow_action_rss *rss;
1275d24610f7SAjit Khaparde 	struct bnxt_rx_queue *rxq = NULL;
1276d24610f7SAjit Khaparde 	int dflt_vnic, vnic_id;
1277adc0f81cSAjit Khaparde 	unsigned int rss_idx;
1278adc0f81cSAjit Khaparde 	uint32_t vf = 0, i;
1279adc0f81cSAjit Khaparde 	int rc, use_ntuple;
12805c1171c9SAjit Khaparde 
12815c1171c9SAjit Khaparde 	rc =
12825c45fde3SIvan Malov 	bnxt_validate_and_parse_flow_type(attr, pattern, error, filter);
12835c1171c9SAjit Khaparde 	if (rc != 0)
12845c1171c9SAjit Khaparde 		goto ret;
12855c1171c9SAjit Khaparde 
12865c1171c9SAjit Khaparde 	rc = bnxt_flow_parse_attr(attr, error);
12875c1171c9SAjit Khaparde 	if (rc != 0)
12885c1171c9SAjit Khaparde 		goto ret;
12895c1171c9SAjit Khaparde 
12905c1171c9SAjit Khaparde 	/* Since we support ingress attribute only - right now. */
12915c1171c9SAjit Khaparde 	if (filter->filter_type == HWRM_CFA_EM_FILTER)
12925c1171c9SAjit Khaparde 		filter->flags = HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX;
12935c1171c9SAjit Khaparde 
1294adc0f81cSAjit Khaparde 	use_ntuple = bnxt_filter_type_check(pattern, error);
129594eb699bSAjit Khaparde 
129694eb699bSAjit Khaparde start:
12975c1171c9SAjit Khaparde 	switch (act->type) {
12985c1171c9SAjit Khaparde 	case RTE_FLOW_ACTION_TYPE_QUEUE:
12995c1171c9SAjit Khaparde 		/* Allow this flow. Redirect to a VNIC. */
13005c1171c9SAjit Khaparde 		act_q = (const struct rte_flow_action_queue *)act->conf;
1301d24610f7SAjit Khaparde 		if (!act_q->index || act_q->index >= bp->rx_nr_rings) {
13025c1171c9SAjit Khaparde 			rte_flow_error_set(error,
13035c1171c9SAjit Khaparde 					   EINVAL,
13045c1171c9SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
13055c1171c9SAjit Khaparde 					   act,
13065c1171c9SAjit Khaparde 					   "Invalid queue ID.");
13075c1171c9SAjit Khaparde 			rc = -rte_errno;
13085c1171c9SAjit Khaparde 			goto ret;
13095c1171c9SAjit Khaparde 		}
1310e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Queue index %d", act_q->index);
13115c1171c9SAjit Khaparde 
1312d24610f7SAjit Khaparde 		vnic_id = attr->group;
1313d24610f7SAjit Khaparde 		if (!vnic_id) {
1314e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "Group id is 0");
1315d24610f7SAjit Khaparde 			vnic_id = act_q->index;
1316d24610f7SAjit Khaparde 		}
1317d24610f7SAjit Khaparde 
1318db8241feSSomnath Kotur 		BNXT_VALID_VNIC_OR_RET(bp, vnic_id);
1319db8241feSSomnath Kotur 
1320d24610f7SAjit Khaparde 		vnic = &bp->vnic_info[vnic_id];
1321d24610f7SAjit Khaparde 		if (vnic->rx_queue_cnt) {
1322d24610f7SAjit Khaparde 			if (vnic->start_grp_id != act_q->index) {
1323e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(ERR,
1324e99981afSDavid Marchand 					    "VNIC already in use");
1325d24610f7SAjit Khaparde 				rte_flow_error_set(error,
1326d24610f7SAjit Khaparde 						   EINVAL,
1327d24610f7SAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ACTION,
1328d24610f7SAjit Khaparde 						   act,
1329d24610f7SAjit Khaparde 						   "VNIC already in use");
1330d24610f7SAjit Khaparde 				rc = -rte_errno;
1331d24610f7SAjit Khaparde 				goto ret;
1332d24610f7SAjit Khaparde 			}
1333d24610f7SAjit Khaparde 			goto use_vnic;
1334d24610f7SAjit Khaparde 		}
1335d24610f7SAjit Khaparde 
1336d24610f7SAjit Khaparde 		rxq = bp->rx_queues[act_q->index];
1337d24610f7SAjit Khaparde 
1338295968d1SFerruh Yigit 		if (!(dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) && rxq &&
1339afef822bSAjit Khaparde 		    vnic->fw_vnic_id != INVALID_HW_RING_ID)
1340d24610f7SAjit Khaparde 			goto use_vnic;
1341d24610f7SAjit Khaparde 
1342fcdd7210SRahul Gupta 		if (!rxq) {
1343e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(ERR,
1344e99981afSDavid Marchand 				    "Queue invalid or used with other VNIC");
1345d24610f7SAjit Khaparde 			rte_flow_error_set(error,
1346d24610f7SAjit Khaparde 					   EINVAL,
1347d24610f7SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1348d24610f7SAjit Khaparde 					   act,
1349d24610f7SAjit Khaparde 					   "Queue invalid queue or in use");
13505c1171c9SAjit Khaparde 			rc = -rte_errno;
13515c1171c9SAjit Khaparde 			goto ret;
13525c1171c9SAjit Khaparde 		}
13535c1171c9SAjit Khaparde 
1354d24610f7SAjit Khaparde 		rxq->vnic = vnic;
1355adc0f81cSAjit Khaparde 		rxq->rx_started = 1;
1356d24610f7SAjit Khaparde 		vnic->rx_queue_cnt++;
1357d24610f7SAjit Khaparde 		vnic->start_grp_id = act_q->index;
1358d24610f7SAjit Khaparde 		vnic->end_grp_id = act_q->index;
1359d24610f7SAjit Khaparde 		vnic->func_default = 0;	//This is not a default VNIC.
1360d24610f7SAjit Khaparde 
1361e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "VNIC found");
1362d24610f7SAjit Khaparde 
136352b0e588SKalesh AP 		rc = bnxt_vnic_prep(bp, vnic, act, error);
136452b0e588SKalesh AP 		if (rc)
1365d24610f7SAjit Khaparde 			goto ret;
1366d24610f7SAjit Khaparde 
1367e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG,
1368e99981afSDavid Marchand 			    "vnic[%d] = %p vnic->fw_grp_ids = %p",
1369d24610f7SAjit Khaparde 			    act_q->index, vnic, vnic->fw_grp_ids);
1370d24610f7SAjit Khaparde 
1371adc0f81cSAjit Khaparde use_vnic:
1372d24610f7SAjit Khaparde 		vnic->ff_pool_idx = vnic_id;
1373e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG,
1374e99981afSDavid Marchand 			    "Setting vnic ff_idx %d", vnic->ff_pool_idx);
13755c1171c9SAjit Khaparde 		filter->dst_id = vnic->fw_vnic_id;
137659119d49SKalesh AP 
13775c631671SSantoshkumar Karanappa Rastapur 		/* For ntuple filter, create the L2 filter with default VNIC.
13785c631671SSantoshkumar Karanappa Rastapur 		 * The user specified redirect queue will be set while creating
13795c631671SSantoshkumar Karanappa Rastapur 		 * the ntuple filter in hardware.
13805c631671SSantoshkumar Karanappa Rastapur 		 */
13816d160d77SRandy Schacher 		vnic0 = bnxt_get_default_vnic(bp);
13825c631671SSantoshkumar Karanappa Rastapur 		if (use_ntuple)
13835c631671SSantoshkumar Karanappa Rastapur 			filter1 = bnxt_get_l2_filter(bp, filter, vnic0);
13845c631671SSantoshkumar Karanappa Rastapur 		else
13855c1171c9SAjit Khaparde 			filter1 = bnxt_get_l2_filter(bp, filter, vnic);
13865c1171c9SAjit Khaparde 		if (filter1 == NULL) {
1387b7e01f38SAjit Khaparde 			rte_flow_error_set(error,
1388b7e01f38SAjit Khaparde 					   ENOSPC,
1389b7e01f38SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1390b7e01f38SAjit Khaparde 					   act,
1391b7e01f38SAjit Khaparde 					   "Filter not available");
1392b7e01f38SAjit Khaparde 			rc = -rte_errno;
13935c1171c9SAjit Khaparde 			goto ret;
13945c1171c9SAjit Khaparde 		}
13955c1171c9SAjit Khaparde 
1396e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "new fltr: %p l2fltr: %p l2_ref_cnt: %d",
1397adc0f81cSAjit Khaparde 			    filter, filter1, filter1->l2_ref_cnt);
1398adc0f81cSAjit Khaparde 		bnxt_update_filter_flags_en(filter, filter1, use_ntuple);
13995c1171c9SAjit Khaparde 		break;
14005c1171c9SAjit Khaparde 	case RTE_FLOW_ACTION_TYPE_DROP:
140151fafb89SSomnath Kotur 		vnic0 = &bp->vnic_info[0];
1402b0d3c584SAjit Khaparde 		filter->dst_id = vnic0->fw_vnic_id;
1403b0d3c584SAjit Khaparde 		filter->valid_flags |= BNXT_FLOW_L2_DROP_FLAG;
14045c1171c9SAjit Khaparde 		filter1 = bnxt_get_l2_filter(bp, filter, vnic0);
14055c1171c9SAjit Khaparde 		if (filter1 == NULL) {
1406b0d3c584SAjit Khaparde 			rte_flow_error_set(error,
1407b0d3c584SAjit Khaparde 					   ENOSPC,
1408b0d3c584SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1409b0d3c584SAjit Khaparde 					   act,
1410b0d3c584SAjit Khaparde 					   "Filter not available");
141189278c59SAjit Khaparde 			rc = -rte_errno;
14125c1171c9SAjit Khaparde 			goto ret;
14135c1171c9SAjit Khaparde 		}
14145c1171c9SAjit Khaparde 
14155c1171c9SAjit Khaparde 		if (filter->filter_type == HWRM_CFA_EM_FILTER)
14165c1171c9SAjit Khaparde 			filter->flags =
14175c1171c9SAjit Khaparde 				HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_DROP;
1418b0d3c584SAjit Khaparde 		else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
14195c1171c9SAjit Khaparde 			filter->flags =
14205c1171c9SAjit Khaparde 				HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_DROP;
1421b0d3c584SAjit Khaparde 
1422b0d3c584SAjit Khaparde 		bnxt_update_filter_flags_en(filter, filter1, use_ntuple);
14235c1171c9SAjit Khaparde 		break;
14245c1171c9SAjit Khaparde 	case RTE_FLOW_ACTION_TYPE_VF:
14255c1171c9SAjit Khaparde 		act_vf = (const struct rte_flow_action_vf *)act->conf;
14265c1171c9SAjit Khaparde 		vf = act_vf->id;
14275c1171c9SAjit Khaparde 
142811e5e196SSomnath Kotur 		if (filter->tunnel_type ==
142911e5e196SSomnath Kotur 		    CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN ||
143011e5e196SSomnath Kotur 		    filter->tunnel_type ==
143111e5e196SSomnath Kotur 		    CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE) {
143211e5e196SSomnath Kotur 			/* If issued on a VF, ensure id is 0 and is trusted */
143311e5e196SSomnath Kotur 			if (BNXT_VF(bp)) {
143411e5e196SSomnath Kotur 				if (!BNXT_VF_IS_TRUSTED(bp) || vf) {
143511e5e196SSomnath Kotur 					rte_flow_error_set(error, EINVAL,
14365c1171c9SAjit Khaparde 						RTE_FLOW_ERROR_TYPE_ACTION,
14375c1171c9SAjit Khaparde 						act,
143811e5e196SSomnath Kotur 						"Incorrect VF");
14395c1171c9SAjit Khaparde 					rc = -rte_errno;
14405c1171c9SAjit Khaparde 					goto ret;
14415c1171c9SAjit Khaparde 				}
144211e5e196SSomnath Kotur 			}
144311e5e196SSomnath Kotur 
144411e5e196SSomnath Kotur 			filter->enables |= filter->tunnel_type;
144511e5e196SSomnath Kotur 			filter->filter_type = HWRM_CFA_TUNNEL_REDIRECT_FILTER;
144611e5e196SSomnath Kotur 			goto done;
144711e5e196SSomnath Kotur 		}
14485c1171c9SAjit Khaparde 
14495c1171c9SAjit Khaparde 		if (vf >= bp->pdev->max_vfs) {
14505c1171c9SAjit Khaparde 			rte_flow_error_set(error,
14515c1171c9SAjit Khaparde 					   EINVAL,
14525c1171c9SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
14535c1171c9SAjit Khaparde 					   act,
14545c1171c9SAjit Khaparde 					   "Incorrect VF id!");
14555c1171c9SAjit Khaparde 			rc = -rte_errno;
14565c1171c9SAjit Khaparde 			goto ret;
14575c1171c9SAjit Khaparde 		}
14585c1171c9SAjit Khaparde 
14595c1171c9SAjit Khaparde 		filter->mirror_vnic_id =
14605c1171c9SAjit Khaparde 		dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf);
14615c1171c9SAjit Khaparde 		if (dflt_vnic < 0) {
14625c1171c9SAjit Khaparde 			/* This simply indicates there's no driver loaded.
14635c1171c9SAjit Khaparde 			 * This is not an error.
14645c1171c9SAjit Khaparde 			 */
14655c1171c9SAjit Khaparde 			rte_flow_error_set(error,
14665c1171c9SAjit Khaparde 					   EINVAL,
14675c1171c9SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
14685c1171c9SAjit Khaparde 					   act,
14695c1171c9SAjit Khaparde 					   "Unable to get default VNIC for VF");
14705c1171c9SAjit Khaparde 			rc = -rte_errno;
14715c1171c9SAjit Khaparde 			goto ret;
14725c1171c9SAjit Khaparde 		}
14735c1171c9SAjit Khaparde 
14745c1171c9SAjit Khaparde 		filter->mirror_vnic_id = dflt_vnic;
14755c1171c9SAjit Khaparde 		filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_MIRROR_VNIC_ID;
14765c1171c9SAjit Khaparde 
147751fafb89SSomnath Kotur 		vnic0 = &bp->vnic_info[0];
14785c1171c9SAjit Khaparde 		filter1 = bnxt_get_l2_filter(bp, filter, vnic0);
14795c1171c9SAjit Khaparde 		if (filter1 == NULL) {
1480b7e01f38SAjit Khaparde 			rte_flow_error_set(error,
1481b7e01f38SAjit Khaparde 					   ENOSPC,
1482b7e01f38SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1483b7e01f38SAjit Khaparde 					   act,
1484b7e01f38SAjit Khaparde 					   "New filter not available");
148589278c59SAjit Khaparde 			rc = -rte_errno;
14865c1171c9SAjit Khaparde 			goto ret;
14875c1171c9SAjit Khaparde 		}
14885c1171c9SAjit Khaparde 
14895c1171c9SAjit Khaparde 		filter->fw_l2_filter_id = filter1->fw_l2_filter_id;
149094eb699bSAjit Khaparde 		filter->flow_id = filter1->flow_id;
14915c1171c9SAjit Khaparde 		break;
1492afef822bSAjit Khaparde 	case RTE_FLOW_ACTION_TYPE_RSS:
1493239695f7SAjit Khaparde 		rc = bnxt_validate_rss_action(actions);
1494239695f7SAjit Khaparde 		if (rc != 0) {
1495239695f7SAjit Khaparde 			rte_flow_error_set(error,
1496239695f7SAjit Khaparde 					   EINVAL,
1497239695f7SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1498239695f7SAjit Khaparde 					   act,
1499239695f7SAjit Khaparde 					   "Invalid actions specified with RSS");
1500239695f7SAjit Khaparde 			rc = -rte_errno;
1501239695f7SAjit Khaparde 			goto ret;
1502239695f7SAjit Khaparde 		}
1503239695f7SAjit Khaparde 
1504adc0f81cSAjit Khaparde 		rss = (const struct rte_flow_action_rss *)act->conf;
1505adc0f81cSAjit Khaparde 
1506239695f7SAjit Khaparde 		vnic_id = bnxt_get_vnic(bp, attr->group);
1507db8241feSSomnath Kotur 
1508db8241feSSomnath Kotur 		BNXT_VALID_VNIC_OR_RET(bp, vnic_id);
1509adc0f81cSAjit Khaparde 		vnic = &bp->vnic_info[vnic_id];
1510adc0f81cSAjit Khaparde 
1511239695f7SAjit Khaparde 		/*
1512239695f7SAjit Khaparde 		 * For non NS3 cases, rte_flow_items will not be considered
1513239695f7SAjit Khaparde 		 * for RSS updates.
1514239695f7SAjit Khaparde 		 */
1515239695f7SAjit Khaparde 		if (filter->filter_type == HWRM_CFA_CONFIG) {
1516239695f7SAjit Khaparde 			/* RSS config update requested */
1517239695f7SAjit Khaparde 			rc = bnxt_vnic_rss_cfg_update(bp, vnic, act, error);
1518239695f7SAjit Khaparde 			if (rc != 0)
151926ba9e7bSKalesh AP 				goto ret;
1520239695f7SAjit Khaparde 
1521239695f7SAjit Khaparde 			filter->dst_id = vnic->fw_vnic_id;
1522239695f7SAjit Khaparde 			break;
1523239695f7SAjit Khaparde 		}
1524239695f7SAjit Khaparde 
1525adc0f81cSAjit Khaparde 		/* Check if requested RSS config matches RSS config of VNIC
1526adc0f81cSAjit Khaparde 		 * only if it is not a fresh VNIC configuration.
1527adc0f81cSAjit Khaparde 		 * Otherwise the existing VNIC configuration can be used.
1528adc0f81cSAjit Khaparde 		 */
1529adc0f81cSAjit Khaparde 		if (vnic->rx_queue_cnt) {
1530adc0f81cSAjit Khaparde 			rc = match_vnic_rss_cfg(bp, vnic, rss);
1531adc0f81cSAjit Khaparde 			if (rc) {
1532e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(ERR,
1533e99981afSDavid Marchand 					    "VNIC and RSS config mismatch");
1534adc0f81cSAjit Khaparde 				rte_flow_error_set(error,
1535adc0f81cSAjit Khaparde 						   EINVAL,
1536adc0f81cSAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ACTION,
1537adc0f81cSAjit Khaparde 						   act,
1538adc0f81cSAjit Khaparde 						   "VNIC and RSS cfg mismatch");
1539adc0f81cSAjit Khaparde 				rc = -rte_errno;
1540adc0f81cSAjit Khaparde 				goto ret;
1541adc0f81cSAjit Khaparde 			}
1542adc0f81cSAjit Khaparde 			goto vnic_found;
1543adc0f81cSAjit Khaparde 		}
1544adc0f81cSAjit Khaparde 
1545adc0f81cSAjit Khaparde 		for (i = 0; i < rss->queue_num; i++) {
1546e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "RSS action Queue %d",
1547adc0f81cSAjit Khaparde 				    rss->queue[i]);
1548adc0f81cSAjit Khaparde 
1549adc0f81cSAjit Khaparde 			if (!rss->queue[i] ||
1550adc0f81cSAjit Khaparde 			    rss->queue[i] >= bp->rx_nr_rings ||
1551adc0f81cSAjit Khaparde 			    !bp->rx_queues[rss->queue[i]]) {
1552adc0f81cSAjit Khaparde 				rte_flow_error_set(error,
1553adc0f81cSAjit Khaparde 						   EINVAL,
1554adc0f81cSAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ACTION,
1555adc0f81cSAjit Khaparde 						   act,
1556adc0f81cSAjit Khaparde 						   "Invalid queue ID for RSS");
1557adc0f81cSAjit Khaparde 				rc = -rte_errno;
1558adc0f81cSAjit Khaparde 				goto ret;
1559adc0f81cSAjit Khaparde 			}
1560adc0f81cSAjit Khaparde 			rxq = bp->rx_queues[rss->queue[i]];
1561adc0f81cSAjit Khaparde 
1562adc0f81cSAjit Khaparde 			if (bp->vnic_info[0].fw_grp_ids[rss->queue[i]] !=
1563adc0f81cSAjit Khaparde 			    INVALID_HW_RING_ID) {
1564e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(ERR,
1565e99981afSDavid Marchand 					    "queue active with other VNIC");
1566adc0f81cSAjit Khaparde 				rte_flow_error_set(error,
1567adc0f81cSAjit Khaparde 						   EINVAL,
1568adc0f81cSAjit Khaparde 						   RTE_FLOW_ERROR_TYPE_ACTION,
1569adc0f81cSAjit Khaparde 						   act,
1570adc0f81cSAjit Khaparde 						   "Invalid queue ID for RSS");
1571adc0f81cSAjit Khaparde 				rc = -rte_errno;
1572adc0f81cSAjit Khaparde 				goto ret;
1573adc0f81cSAjit Khaparde 			}
1574adc0f81cSAjit Khaparde 
1575adc0f81cSAjit Khaparde 			rxq->vnic = vnic;
1576adc0f81cSAjit Khaparde 			rxq->rx_started = 1;
1577adc0f81cSAjit Khaparde 			vnic->rx_queue_cnt++;
1578adc0f81cSAjit Khaparde 		}
1579adc0f81cSAjit Khaparde 
1580adc0f81cSAjit Khaparde 		vnic->start_grp_id = rss->queue[0];
1581adc0f81cSAjit Khaparde 		vnic->end_grp_id = rss->queue[rss->queue_num - 1];
1582adc0f81cSAjit Khaparde 		vnic->func_default = 0;	//This is not a default VNIC.
1583adc0f81cSAjit Khaparde 
158452b0e588SKalesh AP 		rc = bnxt_vnic_prep(bp, vnic, act, error);
158552b0e588SKalesh AP 		if (rc)
1586adc0f81cSAjit Khaparde 			goto ret;
1587adc0f81cSAjit Khaparde 
1588e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG,
1589e99981afSDavid Marchand 			    "vnic[%d] = %p vnic->fw_grp_ids = %p",
1590adc0f81cSAjit Khaparde 			    vnic_id, vnic, vnic->fw_grp_ids);
1591adc0f81cSAjit Khaparde 
1592adc0f81cSAjit Khaparde 		vnic->ff_pool_idx = vnic_id;
1593e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG,
1594e99981afSDavid Marchand 			    "Setting vnic ff_pool_idx %d", vnic->ff_pool_idx);
1595adc0f81cSAjit Khaparde 
1596adc0f81cSAjit Khaparde 		/* This can be done only after vnic_grp_alloc is done. */
1597adc0f81cSAjit Khaparde 		for (i = 0; i < vnic->rx_queue_cnt; i++) {
1598adc0f81cSAjit Khaparde 			vnic->fw_grp_ids[i] =
1599adc0f81cSAjit Khaparde 				bp->grp_info[rss->queue[i]].fw_grp_id;
1600adc0f81cSAjit Khaparde 			/* Make sure vnic0 does not use these rings. */
1601adc0f81cSAjit Khaparde 			bp->vnic_info[0].fw_grp_ids[rss->queue[i]] =
1602adc0f81cSAjit Khaparde 				INVALID_HW_RING_ID;
1603adc0f81cSAjit Khaparde 		}
1604adc0f81cSAjit Khaparde 
1605adc0f81cSAjit Khaparde 		for (rss_idx = 0; rss_idx < HW_HASH_INDEX_SIZE; ) {
1606adc0f81cSAjit Khaparde 			for (i = 0; i < vnic->rx_queue_cnt; i++)
1607adc0f81cSAjit Khaparde 				vnic->rss_table[rss_idx++] =
1608adc0f81cSAjit Khaparde 					vnic->fw_grp_ids[i];
1609adc0f81cSAjit Khaparde 		}
1610adc0f81cSAjit Khaparde 
1611adc0f81cSAjit Khaparde 		/* Configure RSS only if the queue count is > 1 */
1612adc0f81cSAjit Khaparde 		if (vnic->rx_queue_cnt > 1) {
1613adc0f81cSAjit Khaparde 			vnic->hash_type =
1614adc0f81cSAjit Khaparde 				bnxt_rte_to_hwrm_hash_types(rss->types);
16157ed45b1aSAjit Khaparde 			vnic->hash_mode =
16167ed45b1aSAjit Khaparde 			bnxt_rte_to_hwrm_hash_level(bp, rss->types, rss->level);
1617adc0f81cSAjit Khaparde 
1618adc0f81cSAjit Khaparde 			if (!rss->key_len) {
1619adc0f81cSAjit Khaparde 				/* If hash key has not been specified,
1620adc0f81cSAjit Khaparde 				 * use random hash key.
1621adc0f81cSAjit Khaparde 				 */
1622c02bbaa9SStephen Hemminger 				bnxt_prandom_bytes(vnic->rss_hash_key,
1623adc0f81cSAjit Khaparde 						   HW_HASH_KEY_SIZE);
1624adc0f81cSAjit Khaparde 			} else {
1625adc0f81cSAjit Khaparde 				if (rss->key_len > HW_HASH_KEY_SIZE)
1626adc0f81cSAjit Khaparde 					memcpy(vnic->rss_hash_key,
1627adc0f81cSAjit Khaparde 					       rss->key,
1628adc0f81cSAjit Khaparde 					       HW_HASH_KEY_SIZE);
1629adc0f81cSAjit Khaparde 				else
1630adc0f81cSAjit Khaparde 					memcpy(vnic->rss_hash_key,
1631adc0f81cSAjit Khaparde 					       rss->key,
1632adc0f81cSAjit Khaparde 					       rss->key_len);
1633adc0f81cSAjit Khaparde 			}
1634adc0f81cSAjit Khaparde 			bnxt_hwrm_vnic_rss_cfg(bp, vnic);
1635adc0f81cSAjit Khaparde 		} else {
1636e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "No RSS config required");
1637adc0f81cSAjit Khaparde 		}
1638adc0f81cSAjit Khaparde 
1639adc0f81cSAjit Khaparde vnic_found:
1640adc0f81cSAjit Khaparde 		filter->dst_id = vnic->fw_vnic_id;
1641adc0f81cSAjit Khaparde 		filter1 = bnxt_get_l2_filter(bp, filter, vnic);
1642adc0f81cSAjit Khaparde 		if (filter1 == NULL) {
1643b7e01f38SAjit Khaparde 			rte_flow_error_set(error,
1644b7e01f38SAjit Khaparde 					   ENOSPC,
1645b7e01f38SAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
1646b7e01f38SAjit Khaparde 					   act,
1647b7e01f38SAjit Khaparde 					   "New filter not available");
164889278c59SAjit Khaparde 			rc = -rte_errno;
1649adc0f81cSAjit Khaparde 			goto ret;
1650adc0f81cSAjit Khaparde 		}
1651adc0f81cSAjit Khaparde 
1652e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "L2 filter created");
1653adc0f81cSAjit Khaparde 		bnxt_update_filter_flags_en(filter, filter1, use_ntuple);
1654adc0f81cSAjit Khaparde 		break;
165594eb699bSAjit Khaparde 	case RTE_FLOW_ACTION_TYPE_MARK:
165694eb699bSAjit Khaparde 		if (bp->mark_table == NULL) {
165794eb699bSAjit Khaparde 			rte_flow_error_set(error,
165894eb699bSAjit Khaparde 					   ENOMEM,
165994eb699bSAjit Khaparde 					   RTE_FLOW_ERROR_TYPE_ACTION,
166094eb699bSAjit Khaparde 					   act,
166194eb699bSAjit Khaparde 					   "Mark table not allocated.");
166294eb699bSAjit Khaparde 			rc = -rte_errno;
166394eb699bSAjit Khaparde 			goto ret;
166494eb699bSAjit Khaparde 		}
166594eb699bSAjit Khaparde 
1666ca03216fSLance Richardson 		if (bp->flags & BNXT_FLAG_RX_VECTOR_PKT_MODE) {
1667e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG,
1668e99981afSDavid Marchand 				    "Disabling vector processing for mark");
1669ca03216fSLance Richardson 			bp->eth_dev->rx_pkt_burst = bnxt_recv_pkts;
1670ca03216fSLance Richardson 			bp->flags &= ~BNXT_FLAG_RX_VECTOR_PKT_MODE;
1671ca03216fSLance Richardson 		}
1672ca03216fSLance Richardson 
167394eb699bSAjit Khaparde 		filter->valid_flags |= BNXT_FLOW_MARK_FLAG;
167494eb699bSAjit Khaparde 		filter->mark = ((const struct rte_flow_action_mark *)
167594eb699bSAjit Khaparde 				act->conf)->id;
1676e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Mark the flow %d", filter->mark);
167794eb699bSAjit Khaparde 		break;
16785c1171c9SAjit Khaparde 	default:
16795c1171c9SAjit Khaparde 		rte_flow_error_set(error,
16805c1171c9SAjit Khaparde 				   EINVAL,
16815c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_ACTION,
16825c1171c9SAjit Khaparde 				   act,
16835c1171c9SAjit Khaparde 				   "Invalid action.");
16845c1171c9SAjit Khaparde 		rc = -rte_errno;
16855c1171c9SAjit Khaparde 		goto ret;
16865c1171c9SAjit Khaparde 	}
16875c1171c9SAjit Khaparde 
168811e5e196SSomnath Kotur done:
16895c1171c9SAjit Khaparde 	act = bnxt_flow_non_void_action(++act);
169094eb699bSAjit Khaparde 	while (act->type != RTE_FLOW_ACTION_TYPE_END)
169194eb699bSAjit Khaparde 		goto start;
1692b7e01f38SAjit Khaparde 
1693b7e01f38SAjit Khaparde 	return rc;
16945c1171c9SAjit Khaparde ret:
1695b7e01f38SAjit Khaparde 
169694eb699bSAjit Khaparde 	if (filter1) {
169794eb699bSAjit Khaparde 		bnxt_hwrm_clear_l2_filter(bp, filter1);
169894eb699bSAjit Khaparde 		bnxt_free_filter(bp, filter1);
169994eb699bSAjit Khaparde 	}
170094eb699bSAjit Khaparde 
1701b7e01f38SAjit Khaparde 	if (rte_errno)  {
1702*dd0191d5SShuanglin Wang 		if (vnic && STAILQ_EMPTY(&vnic->filter)) {
1703b7e01f38SAjit Khaparde 			vnic->rx_queue_cnt = 0;
1704*dd0191d5SShuanglin Wang 			vnic->rss_types_local = 0;
1705*dd0191d5SShuanglin Wang 		}
1706b7e01f38SAjit Khaparde 
1707b7e01f38SAjit Khaparde 		if (rxq && !vnic->rx_queue_cnt)
1708b7e01f38SAjit Khaparde 			rxq->vnic = &bp->vnic_info[0];
1709b7e01f38SAjit Khaparde 	}
171088d57889SAjit Khaparde 	return -rte_errno;
17115c1171c9SAjit Khaparde }
17125c1171c9SAjit Khaparde 
17138d0a244bSAjit Khaparde static
17148d0a244bSAjit Khaparde struct bnxt_vnic_info *find_matching_vnic(struct bnxt *bp,
17158d0a244bSAjit Khaparde 					  struct bnxt_filter_info *filter)
17168d0a244bSAjit Khaparde {
17178d0a244bSAjit Khaparde 	struct bnxt_vnic_info *vnic = NULL;
17188d0a244bSAjit Khaparde 	unsigned int i;
17198d0a244bSAjit Khaparde 
17208d0a244bSAjit Khaparde 	for (i = 0; i < bp->max_vnics; i++) {
17218d0a244bSAjit Khaparde 		vnic = &bp->vnic_info[i];
17228d0a244bSAjit Khaparde 		if (vnic->fw_vnic_id != INVALID_VNIC_ID &&
17238d0a244bSAjit Khaparde 		    filter->dst_id == vnic->fw_vnic_id) {
1724e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "Found matching VNIC Id %d",
17258d0a244bSAjit Khaparde 				    vnic->ff_pool_idx);
17268d0a244bSAjit Khaparde 			return vnic;
17278d0a244bSAjit Khaparde 		}
17288d0a244bSAjit Khaparde 	}
17298d0a244bSAjit Khaparde 	return NULL;
17308d0a244bSAjit Khaparde }
17318d0a244bSAjit Khaparde 
17325c1171c9SAjit Khaparde static int
17335c1171c9SAjit Khaparde bnxt_flow_validate(struct rte_eth_dev *dev,
17345c1171c9SAjit Khaparde 		   const struct rte_flow_attr *attr,
17355c1171c9SAjit Khaparde 		   const struct rte_flow_item pattern[],
17365c1171c9SAjit Khaparde 		   const struct rte_flow_action actions[],
17375c1171c9SAjit Khaparde 		   struct rte_flow_error *error)
17385c1171c9SAjit Khaparde {
173978466c95SStephen Hemminger 	struct bnxt *bp = dev->data->dev_private;
17408d0a244bSAjit Khaparde 	struct bnxt_vnic_info *vnic = NULL;
17415c1171c9SAjit Khaparde 	struct bnxt_filter_info *filter;
17425c1171c9SAjit Khaparde 	int ret = 0;
17435c1171c9SAjit Khaparde 
17441cb3d39aSVenkat Duvvuru 	bnxt_acquire_flow_lock(bp);
17455c1171c9SAjit Khaparde 	ret = bnxt_flow_args_validate(attr, pattern, actions, error);
17461cb3d39aSVenkat Duvvuru 	if (ret != 0) {
17471cb3d39aSVenkat Duvvuru 		bnxt_release_flow_lock(bp);
17485c1171c9SAjit Khaparde 		return ret;
17491cb3d39aSVenkat Duvvuru 	}
17505c1171c9SAjit Khaparde 
17515c1171c9SAjit Khaparde 	filter = bnxt_get_unused_filter(bp);
17525c1171c9SAjit Khaparde 	if (filter == NULL) {
175394df7953SKalesh AP 		rte_flow_error_set(error, ENOSPC,
175494df7953SKalesh AP 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
175594df7953SKalesh AP 				   "Not enough resources for a new flow");
17561cb3d39aSVenkat Duvvuru 		bnxt_release_flow_lock(bp);
175794df7953SKalesh AP 		return -ENOSPC;
17585c1171c9SAjit Khaparde 	}
17595c1171c9SAjit Khaparde 
17605c1171c9SAjit Khaparde 	ret = bnxt_validate_and_parse_flow(dev, pattern, actions, attr,
17615c1171c9SAjit Khaparde 					   error, filter);
1762b7e01f38SAjit Khaparde 	if (ret)
1763b7e01f38SAjit Khaparde 		goto exit;
17648d0a244bSAjit Khaparde 
17658d0a244bSAjit Khaparde 	vnic = find_matching_vnic(bp, filter);
17668d0a244bSAjit Khaparde 	if (vnic) {
17678d0a244bSAjit Khaparde 		if (STAILQ_EMPTY(&vnic->filter)) {
17683e3fecf4SKalesh AP 			bnxt_vnic_cleanup(bp, vnic);
1769a0c2315aSLance Richardson 			bp->nr_vnics--;
1770e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG, "Free VNIC");
17718d0a244bSAjit Khaparde 		}
17728d0a244bSAjit Khaparde 	}
17738d0a244bSAjit Khaparde 
17748d0a244bSAjit Khaparde 	if (filter->filter_type == HWRM_CFA_EM_FILTER)
17758d0a244bSAjit Khaparde 		bnxt_hwrm_clear_em_filter(bp, filter);
17768d0a244bSAjit Khaparde 	else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
17778d0a244bSAjit Khaparde 		bnxt_hwrm_clear_ntuple_filter(bp, filter);
17788d0a244bSAjit Khaparde 	else
17798d0a244bSAjit Khaparde 		bnxt_hwrm_clear_l2_filter(bp, filter);
17808d0a244bSAjit Khaparde 
1781b7e01f38SAjit Khaparde exit:
17825c1171c9SAjit Khaparde 	/* No need to hold on to this filter if we are just validating flow */
17835c1171c9SAjit Khaparde 	bnxt_free_filter(bp, filter);
17841cb3d39aSVenkat Duvvuru 	bnxt_release_flow_lock(bp);
17855c1171c9SAjit Khaparde 
17865c1171c9SAjit Khaparde 	return ret;
17875c1171c9SAjit Khaparde }
17885c1171c9SAjit Khaparde 
1789adc0f81cSAjit Khaparde static void
1790adc0f81cSAjit Khaparde bnxt_update_filter(struct bnxt *bp, struct bnxt_filter_info *old_filter,
1791adc0f81cSAjit Khaparde 		   struct bnxt_filter_info *new_filter)
1792adc0f81cSAjit Khaparde {
1793adc0f81cSAjit Khaparde 	/* Clear the new L2 filter that was created in the previous step in
1794adc0f81cSAjit Khaparde 	 * bnxt_validate_and_parse_flow. For L2 filters, we will use the new
1795adc0f81cSAjit Khaparde 	 * filter which points to the new destination queue and so we clear
1796adc0f81cSAjit Khaparde 	 * the previous L2 filter. For ntuple filters, we are going to reuse
1797adc0f81cSAjit Khaparde 	 * the old L2 filter and create new NTUPLE filter with this new
1798e339ef6eSSomnath Kotur 	 * destination queue subsequently during bnxt_flow_create. So we
1799e339ef6eSSomnath Kotur 	 * decrement the ref cnt of the L2 filter that would've been bumped
1800e339ef6eSSomnath Kotur 	 * up previously in bnxt_validate_and_parse_flow as the old n-tuple
1801e339ef6eSSomnath Kotur 	 * filter that was referencing it will be deleted now.
1802adc0f81cSAjit Khaparde 	 */
1803adc0f81cSAjit Khaparde 	bnxt_hwrm_clear_l2_filter(bp, old_filter);
1804e339ef6eSSomnath Kotur 	if (new_filter->filter_type == HWRM_CFA_L2_FILTER) {
1805adc0f81cSAjit Khaparde 		bnxt_hwrm_set_l2_filter(bp, new_filter->dst_id, new_filter);
1806adc0f81cSAjit Khaparde 	} else {
1807adc0f81cSAjit Khaparde 		if (new_filter->filter_type == HWRM_CFA_EM_FILTER)
1808adc0f81cSAjit Khaparde 			bnxt_hwrm_clear_em_filter(bp, old_filter);
1809adc0f81cSAjit Khaparde 		if (new_filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
1810adc0f81cSAjit Khaparde 			bnxt_hwrm_clear_ntuple_filter(bp, old_filter);
1811adc0f81cSAjit Khaparde 	}
1812adc0f81cSAjit Khaparde }
1813adc0f81cSAjit Khaparde 
18145c1171c9SAjit Khaparde static int
18155c1171c9SAjit Khaparde bnxt_match_filter(struct bnxt *bp, struct bnxt_filter_info *nf)
18165c1171c9SAjit Khaparde {
18175c1171c9SAjit Khaparde 	struct bnxt_filter_info *mf;
18185c1171c9SAjit Khaparde 	struct rte_flow *flow;
18195c1171c9SAjit Khaparde 	int i;
18205c1171c9SAjit Khaparde 
18218d0a244bSAjit Khaparde 	for (i = bp->max_vnics - 1; i >= 0; i--) {
18225c1171c9SAjit Khaparde 		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
18235c1171c9SAjit Khaparde 
1824d24610f7SAjit Khaparde 		if (vnic->fw_vnic_id == INVALID_VNIC_ID)
1825d24610f7SAjit Khaparde 			continue;
1826d24610f7SAjit Khaparde 
18275c1171c9SAjit Khaparde 		STAILQ_FOREACH(flow, &vnic->flow_list, next) {
18285c1171c9SAjit Khaparde 			mf = flow->filter;
18295c1171c9SAjit Khaparde 
18305c1171c9SAjit Khaparde 			if (mf->filter_type == nf->filter_type &&
18315c1171c9SAjit Khaparde 			    mf->flags == nf->flags &&
18325c1171c9SAjit Khaparde 			    mf->src_port == nf->src_port &&
18335c1171c9SAjit Khaparde 			    mf->src_port_mask == nf->src_port_mask &&
18345c1171c9SAjit Khaparde 			    mf->dst_port == nf->dst_port &&
18355c1171c9SAjit Khaparde 			    mf->dst_port_mask == nf->dst_port_mask &&
18365c1171c9SAjit Khaparde 			    mf->ip_protocol == nf->ip_protocol &&
18375c1171c9SAjit Khaparde 			    mf->ip_addr_type == nf->ip_addr_type &&
18385c1171c9SAjit Khaparde 			    mf->ethertype == nf->ethertype &&
18395c1171c9SAjit Khaparde 			    mf->vni == nf->vni &&
18405c1171c9SAjit Khaparde 			    mf->tunnel_type == nf->tunnel_type &&
18415c1171c9SAjit Khaparde 			    mf->l2_ovlan == nf->l2_ovlan &&
18425c1171c9SAjit Khaparde 			    mf->l2_ovlan_mask == nf->l2_ovlan_mask &&
18435c1171c9SAjit Khaparde 			    mf->l2_ivlan == nf->l2_ivlan &&
18445c1171c9SAjit Khaparde 			    mf->l2_ivlan_mask == nf->l2_ivlan_mask &&
184535b2d13fSOlivier Matz 			    !memcmp(mf->l2_addr, nf->l2_addr,
184635b2d13fSOlivier Matz 				    RTE_ETHER_ADDR_LEN) &&
18475c1171c9SAjit Khaparde 			    !memcmp(mf->l2_addr_mask, nf->l2_addr_mask,
184835b2d13fSOlivier Matz 				    RTE_ETHER_ADDR_LEN) &&
18495c1171c9SAjit Khaparde 			    !memcmp(mf->src_macaddr, nf->src_macaddr,
185035b2d13fSOlivier Matz 				    RTE_ETHER_ADDR_LEN) &&
18515c1171c9SAjit Khaparde 			    !memcmp(mf->dst_macaddr, nf->dst_macaddr,
185235b2d13fSOlivier Matz 				    RTE_ETHER_ADDR_LEN) &&
18535c1171c9SAjit Khaparde 			    !memcmp(mf->src_ipaddr, nf->src_ipaddr,
18545c1171c9SAjit Khaparde 				    sizeof(nf->src_ipaddr)) &&
18555c1171c9SAjit Khaparde 			    !memcmp(mf->src_ipaddr_mask, nf->src_ipaddr_mask,
18565c1171c9SAjit Khaparde 				    sizeof(nf->src_ipaddr_mask)) &&
18575c1171c9SAjit Khaparde 			    !memcmp(mf->dst_ipaddr, nf->dst_ipaddr,
18585c1171c9SAjit Khaparde 				    sizeof(nf->dst_ipaddr)) &&
18595c1171c9SAjit Khaparde 			    !memcmp(mf->dst_ipaddr_mask, nf->dst_ipaddr_mask,
18605c1171c9SAjit Khaparde 				    sizeof(nf->dst_ipaddr_mask))) {
18615c1171c9SAjit Khaparde 				if (mf->dst_id == nf->dst_id)
18625c1171c9SAjit Khaparde 					return -EEXIST;
18635c1171c9SAjit Khaparde 				/* Free the old filter, update flow
18645c1171c9SAjit Khaparde 				 * with new filter
18655c1171c9SAjit Khaparde 				 */
1866adc0f81cSAjit Khaparde 				bnxt_update_filter(bp, mf, nf);
1867adc0f81cSAjit Khaparde 				STAILQ_REMOVE(&vnic->filter, mf,
1868adc0f81cSAjit Khaparde 					      bnxt_filter_info, next);
1869adc0f81cSAjit Khaparde 				STAILQ_INSERT_TAIL(&vnic->filter, nf, next);
18705c1171c9SAjit Khaparde 				bnxt_free_filter(bp, mf);
18715c1171c9SAjit Khaparde 				flow->filter = nf;
18725c1171c9SAjit Khaparde 				return -EXDEV;
18735c1171c9SAjit Khaparde 			}
18745c1171c9SAjit Khaparde 		}
18755c1171c9SAjit Khaparde 	}
18765c1171c9SAjit Khaparde 	return 0;
18775c1171c9SAjit Khaparde }
18785c1171c9SAjit Khaparde 
187902a95625SSomnath Kotur static void
188002a95625SSomnath Kotur bnxt_setup_flow_counter(struct bnxt *bp)
188102a95625SSomnath Kotur {
188202a95625SSomnath Kotur 	if (bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_COUNTERS &&
18831e2f8acaSAjit Khaparde 	    !(bp->flags & BNXT_FLAG_FC_THREAD) && BNXT_FLOW_XSTATS_EN(bp)) {
188402a95625SSomnath Kotur 		rte_eal_alarm_set(US_PER_S * BNXT_FC_TIMER,
188502a95625SSomnath Kotur 				  bnxt_flow_cnt_alarm_cb,
188602a95625SSomnath Kotur 				  (void *)bp);
188702a95625SSomnath Kotur 		bp->flags |= BNXT_FLAG_FC_THREAD;
188802a95625SSomnath Kotur 	}
188902a95625SSomnath Kotur }
189002a95625SSomnath Kotur 
189102a95625SSomnath Kotur void bnxt_flow_cnt_alarm_cb(void *arg)
189202a95625SSomnath Kotur {
189302a95625SSomnath Kotur 	int rc = 0;
189402a95625SSomnath Kotur 	struct bnxt *bp = arg;
189502a95625SSomnath Kotur 
18961e2f8acaSAjit Khaparde 	if (!bp->flow_stat->rx_fc_out_tbl.va) {
1897e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "bp->flow_stat->rx_fc_out_tbl.va is NULL?");
189802a95625SSomnath Kotur 		bnxt_cancel_fc_thread(bp);
189902a95625SSomnath Kotur 		return;
190002a95625SSomnath Kotur 	}
190102a95625SSomnath Kotur 
19021e2f8acaSAjit Khaparde 	if (!bp->flow_stat->flow_count) {
190302a95625SSomnath Kotur 		bnxt_cancel_fc_thread(bp);
190402a95625SSomnath Kotur 		return;
190502a95625SSomnath Kotur 	}
190602a95625SSomnath Kotur 
190702a95625SSomnath Kotur 	if (!bp->eth_dev->data->dev_started) {
190802a95625SSomnath Kotur 		bnxt_cancel_fc_thread(bp);
190902a95625SSomnath Kotur 		return;
191002a95625SSomnath Kotur 	}
191102a95625SSomnath Kotur 
191202a95625SSomnath Kotur 	rc = bnxt_flow_stats_req(bp);
191302a95625SSomnath Kotur 	if (rc) {
1914e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "Flow stat alarm not rescheduled.");
191502a95625SSomnath Kotur 		return;
191602a95625SSomnath Kotur 	}
191702a95625SSomnath Kotur 
191802a95625SSomnath Kotur 	rte_eal_alarm_set(US_PER_S * BNXT_FC_TIMER,
191902a95625SSomnath Kotur 			  bnxt_flow_cnt_alarm_cb,
192002a95625SSomnath Kotur 			  (void *)bp);
192102a95625SSomnath Kotur }
192202a95625SSomnath Kotur 
19232cc4ec01SDamodharam Ammepalli /* Query an requested flow rule. */
19242cc4ec01SDamodharam Ammepalli static int
19252cc4ec01SDamodharam Ammepalli bnxt_flow_query_all(struct rte_flow *flow,
19262cc4ec01SDamodharam Ammepalli 		    const struct rte_flow_action *actions, void *data,
19272cc4ec01SDamodharam Ammepalli 		    struct rte_flow_error *error)
19282cc4ec01SDamodharam Ammepalli {
19292cc4ec01SDamodharam Ammepalli 	struct rte_flow_action_rss *rss_conf;
19302cc4ec01SDamodharam Ammepalli 	struct bnxt_vnic_info *vnic;
19312cc4ec01SDamodharam Ammepalli 
19322cc4ec01SDamodharam Ammepalli 	vnic = flow->vnic;
19332cc4ec01SDamodharam Ammepalli 	if (vnic == NULL)
19342cc4ec01SDamodharam Ammepalli 		return rte_flow_error_set(error, EINVAL,
19352cc4ec01SDamodharam Ammepalli 					  RTE_FLOW_ERROR_TYPE_HANDLE, flow,
19362cc4ec01SDamodharam Ammepalli 					  "Invalid flow: failed to query flow.");
19372cc4ec01SDamodharam Ammepalli 
19382cc4ec01SDamodharam Ammepalli 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
19392cc4ec01SDamodharam Ammepalli 		switch (actions->type) {
19402cc4ec01SDamodharam Ammepalli 		case RTE_FLOW_ACTION_TYPE_VOID:
19412cc4ec01SDamodharam Ammepalli 			break;
19422cc4ec01SDamodharam Ammepalli 		case RTE_FLOW_ACTION_TYPE_COUNT:
19432cc4ec01SDamodharam Ammepalli 			break;
19442cc4ec01SDamodharam Ammepalli 		case RTE_FLOW_ACTION_TYPE_RSS:
19452cc4ec01SDamodharam Ammepalli 			/* Full details of rte_flow_action_rss not available yet TBD*/
19462cc4ec01SDamodharam Ammepalli 			rss_conf = (struct rte_flow_action_rss *)data;
19472cc4ec01SDamodharam Ammepalli 
19482cc4ec01SDamodharam Ammepalli 			/* toeplitz is default */
19492cc4ec01SDamodharam Ammepalli 			if (vnic->ring_select_mode ==
19502cc4ec01SDamodharam Ammepalli 					HWRM_VNIC_RSS_CFG_INPUT_RING_SELECT_MODE_TOEPLITZ)
19512cc4ec01SDamodharam Ammepalli 				rss_conf->func = vnic->hash_f_local;
19522cc4ec01SDamodharam Ammepalli 			else
19532cc4ec01SDamodharam Ammepalli 				rss_conf->func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
19542cc4ec01SDamodharam Ammepalli 
19552cc4ec01SDamodharam Ammepalli 			break;
19562cc4ec01SDamodharam Ammepalli 		default:
19572cc4ec01SDamodharam Ammepalli 			return rte_flow_error_set(error, ENOTSUP,
19582cc4ec01SDamodharam Ammepalli 						  RTE_FLOW_ERROR_TYPE_ACTION, actions,
19592cc4ec01SDamodharam Ammepalli 						  "action is not supported");
19602cc4ec01SDamodharam Ammepalli 		}
19612cc4ec01SDamodharam Ammepalli 	}
19622cc4ec01SDamodharam Ammepalli 
19632cc4ec01SDamodharam Ammepalli 	return 0;
19642cc4ec01SDamodharam Ammepalli }
19652cc4ec01SDamodharam Ammepalli 
19662cc4ec01SDamodharam Ammepalli static int
19672cc4ec01SDamodharam Ammepalli bnxt_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
19682cc4ec01SDamodharam Ammepalli 		const struct rte_flow_action *actions, void *data,
19692cc4ec01SDamodharam Ammepalli 		struct rte_flow_error *error)
19702cc4ec01SDamodharam Ammepalli {
19712cc4ec01SDamodharam Ammepalli 	struct bnxt *bp = dev->data->dev_private;
19722cc4ec01SDamodharam Ammepalli 	int ret = 0;
19732cc4ec01SDamodharam Ammepalli 
19742cc4ec01SDamodharam Ammepalli 	if (bp == NULL)
19752cc4ec01SDamodharam Ammepalli 		return -ENODEV;
19762cc4ec01SDamodharam Ammepalli 
19772cc4ec01SDamodharam Ammepalli 	bnxt_acquire_flow_lock(bp);
19782cc4ec01SDamodharam Ammepalli 	ret = bnxt_flow_query_all(flow, actions, data, error);
19792cc4ec01SDamodharam Ammepalli 	bnxt_release_flow_lock(bp);
19802cc4ec01SDamodharam Ammepalli 
19812cc4ec01SDamodharam Ammepalli 	return ret;
19822cc4ec01SDamodharam Ammepalli }
198302a95625SSomnath Kotur 
19845c1171c9SAjit Khaparde static struct rte_flow *
19855c1171c9SAjit Khaparde bnxt_flow_create(struct rte_eth_dev *dev,
19865c1171c9SAjit Khaparde 		 const struct rte_flow_attr *attr,
19875c1171c9SAjit Khaparde 		 const struct rte_flow_item pattern[],
19885c1171c9SAjit Khaparde 		 const struct rte_flow_action actions[],
19895c1171c9SAjit Khaparde 		 struct rte_flow_error *error)
19905c1171c9SAjit Khaparde {
199178466c95SStephen Hemminger 	struct bnxt *bp = dev->data->dev_private;
19925c1171c9SAjit Khaparde 	struct bnxt_vnic_info *vnic = NULL;
1993d24610f7SAjit Khaparde 	struct bnxt_filter_info *filter;
19945c1171c9SAjit Khaparde 	bool update_flow = false;
19955c1171c9SAjit Khaparde 	struct rte_flow *flow;
19965c1171c9SAjit Khaparde 	int ret = 0;
19979db66782SSomnath Kotur 	uint32_t tun_type, flow_id;
19985c1171c9SAjit Khaparde 
199936024b2eSAjit Khaparde 	if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
200036024b2eSAjit Khaparde 		rte_flow_error_set(error, EINVAL,
200136024b2eSAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
200236024b2eSAjit Khaparde 				   "Failed to create flow, Not a Trusted VF!");
200336024b2eSAjit Khaparde 		return NULL;
200436024b2eSAjit Khaparde 	}
200536024b2eSAjit Khaparde 
2006288d51ebSAjit Khaparde 	if (!dev->data->dev_started) {
2007288d51ebSAjit Khaparde 		rte_flow_error_set(error,
2008288d51ebSAjit Khaparde 				   EINVAL,
2009288d51ebSAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2010288d51ebSAjit Khaparde 				   NULL,
2011288d51ebSAjit Khaparde 				   "Device must be started");
2012288d51ebSAjit Khaparde 		return NULL;
2013288d51ebSAjit Khaparde 	}
2014288d51ebSAjit Khaparde 
20155c1171c9SAjit Khaparde 	flow = rte_zmalloc("bnxt_flow", sizeof(struct rte_flow), 0);
20165c1171c9SAjit Khaparde 	if (!flow) {
20175c1171c9SAjit Khaparde 		rte_flow_error_set(error, ENOMEM,
20185c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
20195c1171c9SAjit Khaparde 				   "Failed to allocate memory");
20205c1171c9SAjit Khaparde 		return flow;
20215c1171c9SAjit Khaparde 	}
20225c1171c9SAjit Khaparde 
20231cb3d39aSVenkat Duvvuru 	bnxt_acquire_flow_lock(bp);
20245c1171c9SAjit Khaparde 	ret = bnxt_flow_args_validate(attr, pattern, actions, error);
20255c1171c9SAjit Khaparde 	if (ret != 0) {
2026e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "Not a validate flow.");
20275c1171c9SAjit Khaparde 		goto free_flow;
20285c1171c9SAjit Khaparde 	}
20295c1171c9SAjit Khaparde 
20305c1171c9SAjit Khaparde 	filter = bnxt_get_unused_filter(bp);
20315c1171c9SAjit Khaparde 	if (filter == NULL) {
20329356d01dSKalesh AP 		rte_flow_error_set(error, ENOSPC,
20339356d01dSKalesh AP 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
20349356d01dSKalesh AP 				   "Not enough resources for a new flow");
20355c1171c9SAjit Khaparde 		goto free_flow;
20365c1171c9SAjit Khaparde 	}
20375c1171c9SAjit Khaparde 
20385c1171c9SAjit Khaparde 	ret = bnxt_validate_and_parse_flow(dev, pattern, actions, attr,
20395c1171c9SAjit Khaparde 					   error, filter);
20405c1171c9SAjit Khaparde 	if (ret != 0)
20415c1171c9SAjit Khaparde 		goto free_filter;
20425c1171c9SAjit Khaparde 
20435c1171c9SAjit Khaparde 	ret = bnxt_match_filter(bp, filter);
20445c1171c9SAjit Khaparde 	if (ret == -EEXIST) {
2045e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Flow already exists.");
20465c1171c9SAjit Khaparde 		/* Clear the filter that was created as part of
20475c1171c9SAjit Khaparde 		 * validate_and_parse_flow() above
20485c1171c9SAjit Khaparde 		 */
20495c1171c9SAjit Khaparde 		bnxt_hwrm_clear_l2_filter(bp, filter);
20505c1171c9SAjit Khaparde 		goto free_filter;
20515c1171c9SAjit Khaparde 	} else if (ret == -EXDEV) {
2052e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Flow with same pattern exists");
2053e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Updating with different destination");
20545c1171c9SAjit Khaparde 		update_flow = true;
20555c1171c9SAjit Khaparde 	}
20565c1171c9SAjit Khaparde 
205711e5e196SSomnath Kotur 	/* If tunnel redirection to a VF/PF is specified then only tunnel_type
205811e5e196SSomnath Kotur 	 * is set and enable is set to the tunnel type. Issue hwrm cmd directly
205911e5e196SSomnath Kotur 	 * in such a case.
206011e5e196SSomnath Kotur 	 */
206111e5e196SSomnath Kotur 	if (filter->filter_type == HWRM_CFA_TUNNEL_REDIRECT_FILTER &&
20626d160d77SRandy Schacher 	    (filter->enables == filter->tunnel_type ||
20636d160d77SRandy Schacher 	     filter->tunnel_type == CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN ||
20646d160d77SRandy Schacher 	     filter->tunnel_type == CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE)) {
20656d160d77SRandy Schacher 		if (filter->enables & NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT) {
20666d160d77SRandy Schacher 			struct rte_eth_udp_tunnel tunnel = {0};
20676d160d77SRandy Schacher 
20686d160d77SRandy Schacher 			/* hwrm_tunnel_dst_port_alloc converts to Big Endian */
20696d160d77SRandy Schacher 			tunnel.udp_port = BNXT_NTOHS(filter->dst_port);
20706d160d77SRandy Schacher 			if (filter->tunnel_type ==
20716d160d77SRandy Schacher 			    CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN) {
20726d160d77SRandy Schacher 				tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_VXLAN;
20736d160d77SRandy Schacher 			} else if (filter->tunnel_type ==
20746d160d77SRandy Schacher 				 CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE) {
20756d160d77SRandy Schacher 				tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_GENEVE;
20766d160d77SRandy Schacher 			} else {
20776d160d77SRandy Schacher 				rte_flow_error_set(error, EINVAL,
20786d160d77SRandy Schacher 						   RTE_FLOW_ERROR_TYPE_HANDLE,
20796d160d77SRandy Schacher 						   NULL,
20806d160d77SRandy Schacher 						   "Invalid tunnel type");
20816d160d77SRandy Schacher 				ret = -EINVAL;
20826d160d77SRandy Schacher 				goto free_filter;
20836d160d77SRandy Schacher 			}
20846d160d77SRandy Schacher 			ret = bnxt_udp_tunnel_port_add_op(bp->eth_dev, &tunnel);
20856d160d77SRandy Schacher 			if (ret != 0) {
20866d160d77SRandy Schacher 				rte_flow_error_set(error, -ret,
20876d160d77SRandy Schacher 						   RTE_FLOW_ERROR_TYPE_HANDLE,
20886d160d77SRandy Schacher 						   NULL,
20896d160d77SRandy Schacher 						   "Fail to add tunnel port");
20906d160d77SRandy Schacher 				goto free_filter;
20916d160d77SRandy Schacher 			}
20926d160d77SRandy Schacher 		}
209311e5e196SSomnath Kotur 		ret = bnxt_hwrm_tunnel_redirect_query(bp, &tun_type);
209411e5e196SSomnath Kotur 		if (ret) {
209511e5e196SSomnath Kotur 			rte_flow_error_set(error, -ret,
209611e5e196SSomnath Kotur 					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
209711e5e196SSomnath Kotur 					   "Unable to query tunnel to VF");
209811e5e196SSomnath Kotur 			goto free_filter;
209911e5e196SSomnath Kotur 		}
210011e5e196SSomnath Kotur 		if (tun_type == (1U << filter->tunnel_type)) {
210111e5e196SSomnath Kotur 			ret =
210211e5e196SSomnath Kotur 			bnxt_hwrm_tunnel_redirect_free(bp,
210311e5e196SSomnath Kotur 						       filter->tunnel_type);
210411e5e196SSomnath Kotur 			if (ret) {
2105e99981afSDavid Marchand 				PMD_DRV_LOG_LINE(ERR,
2106e99981afSDavid Marchand 					    "Unable to free existing tunnel");
210711e5e196SSomnath Kotur 				rte_flow_error_set(error, -ret,
210811e5e196SSomnath Kotur 						   RTE_FLOW_ERROR_TYPE_HANDLE,
210911e5e196SSomnath Kotur 						   NULL,
211011e5e196SSomnath Kotur 						   "Unable to free preexisting "
211111e5e196SSomnath Kotur 						   "tunnel on VF");
211211e5e196SSomnath Kotur 				goto free_filter;
211311e5e196SSomnath Kotur 			}
211411e5e196SSomnath Kotur 		}
211511e5e196SSomnath Kotur 		ret = bnxt_hwrm_tunnel_redirect(bp, filter->tunnel_type);
211611e5e196SSomnath Kotur 		if (ret) {
211711e5e196SSomnath Kotur 			rte_flow_error_set(error, -ret,
211811e5e196SSomnath Kotur 					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
211911e5e196SSomnath Kotur 					   "Unable to redirect tunnel to VF");
212011e5e196SSomnath Kotur 			goto free_filter;
212111e5e196SSomnath Kotur 		}
212211e5e196SSomnath Kotur 		vnic = &bp->vnic_info[0];
212311e5e196SSomnath Kotur 		goto done;
212411e5e196SSomnath Kotur 	}
212511e5e196SSomnath Kotur 
21265c1171c9SAjit Khaparde 	if (filter->filter_type == HWRM_CFA_EM_FILTER) {
21275c1171c9SAjit Khaparde 		filter->enables |=
21285c1171c9SAjit Khaparde 			HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_L2_FILTER_ID;
21295c1171c9SAjit Khaparde 		ret = bnxt_hwrm_set_em_filter(bp, filter->dst_id, filter);
213087aefef1SKalesh AP 		if (ret != 0) {
213187aefef1SKalesh AP 			rte_flow_error_set(error, -ret,
213287aefef1SKalesh AP 					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
213387aefef1SKalesh AP 					   "Failed to create EM filter");
213487aefef1SKalesh AP 			goto free_filter;
213587aefef1SKalesh AP 		}
21365c1171c9SAjit Khaparde 	}
21375c1171c9SAjit Khaparde 
21385c1171c9SAjit Khaparde 	if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER) {
21395c1171c9SAjit Khaparde 		filter->enables |=
21405c1171c9SAjit Khaparde 			HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID;
21415c1171c9SAjit Khaparde 		ret = bnxt_hwrm_set_ntuple_filter(bp, filter->dst_id, filter);
214287aefef1SKalesh AP 		if (ret != 0) {
214387aefef1SKalesh AP 			rte_flow_error_set(error, -ret,
214487aefef1SKalesh AP 					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
214587aefef1SKalesh AP 					   "Failed to create ntuple filter");
214687aefef1SKalesh AP 			goto free_filter;
214787aefef1SKalesh AP 		}
21485c1171c9SAjit Khaparde 	}
21495c1171c9SAjit Khaparde 
21508d0a244bSAjit Khaparde 	vnic = find_matching_vnic(bp, filter);
215111e5e196SSomnath Kotur done:
2152adc0f81cSAjit Khaparde 	if (!ret || update_flow) {
21535c1171c9SAjit Khaparde 		flow->filter = filter;
21545c1171c9SAjit Khaparde 		flow->vnic = vnic;
2155d24610f7SAjit Khaparde 		if (update_flow) {
2156d24610f7SAjit Khaparde 			ret = -EXDEV;
2157d24610f7SAjit Khaparde 			goto free_flow;
2158d24610f7SAjit Khaparde 		}
215989278c59SAjit Khaparde 
216094eb699bSAjit Khaparde 		if (filter->valid_flags & BNXT_FLOW_MARK_FLAG) {
2161e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(DEBUG,
2162e99981afSDavid Marchand 				    "Mark action: mark id 0x%x, flow id 0x%x",
216394eb699bSAjit Khaparde 				    filter->mark, filter->flow_id);
216494eb699bSAjit Khaparde 
216594eb699bSAjit Khaparde 			/* TCAM and EM should be 16-bit only.
216694eb699bSAjit Khaparde 			 * Other modes not supported.
216794eb699bSAjit Khaparde 			 */
21689db66782SSomnath Kotur 			flow_id = filter->flow_id & BNXT_FLOW_ID_MASK;
21699db66782SSomnath Kotur 			if (bp->mark_table[flow_id].valid) {
217087aefef1SKalesh AP 				rte_flow_error_set(error, EEXIST,
217187aefef1SKalesh AP 						   RTE_FLOW_ERROR_TYPE_HANDLE,
217287aefef1SKalesh AP 						   NULL,
217387aefef1SKalesh AP 						   "Flow with mark id exists");
217487520e59SKalesh AP 				bnxt_clear_one_vnic_filter(bp, filter);
21759db66782SSomnath Kotur 				goto free_filter;
21769db66782SSomnath Kotur 			}
21779db66782SSomnath Kotur 			bp->mark_table[flow_id].valid = true;
21789db66782SSomnath Kotur 			bp->mark_table[flow_id].mark_id = filter->mark;
217994eb699bSAjit Khaparde 		}
218087520e59SKalesh AP 
218187520e59SKalesh AP 		STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
218287520e59SKalesh AP 		STAILQ_INSERT_TAIL(&vnic->flow_list, flow, next);
218387520e59SKalesh AP 
21841e2f8acaSAjit Khaparde 		if (BNXT_FLOW_XSTATS_EN(bp))
21851e2f8acaSAjit Khaparde 			bp->flow_stat->flow_count++;
21861cb3d39aSVenkat Duvvuru 		bnxt_release_flow_lock(bp);
218702a95625SSomnath Kotur 		bnxt_setup_flow_counter(bp);
2188e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(DEBUG, "Successfully created flow.");
2189d24610f7SAjit Khaparde 		return flow;
2190d24610f7SAjit Khaparde 	}
219189278c59SAjit Khaparde 
21925c1171c9SAjit Khaparde free_filter:
21935c1171c9SAjit Khaparde 	bnxt_free_filter(bp, filter);
21945c1171c9SAjit Khaparde free_flow:
21955c1171c9SAjit Khaparde 	if (ret == -EEXIST)
21965c1171c9SAjit Khaparde 		rte_flow_error_set(error, ret,
21975c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
21985c1171c9SAjit Khaparde 				   "Matching Flow exists.");
21995c1171c9SAjit Khaparde 	else if (ret == -EXDEV)
2200adc0f81cSAjit Khaparde 		rte_flow_error_set(error, 0,
2201adc0f81cSAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_NONE, NULL,
22025c1171c9SAjit Khaparde 				   "Flow with pattern exists, updating destination queue");
220388d57889SAjit Khaparde 	else if (!rte_errno)
22045c1171c9SAjit Khaparde 		rte_flow_error_set(error, -ret,
22055c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
22065c1171c9SAjit Khaparde 				   "Failed to create flow.");
22075c1171c9SAjit Khaparde 	rte_free(flow);
22085c1171c9SAjit Khaparde 	flow = NULL;
22091cb3d39aSVenkat Duvvuru 	bnxt_release_flow_lock(bp);
22105c1171c9SAjit Khaparde 	return flow;
22115c1171c9SAjit Khaparde }
22125c1171c9SAjit Khaparde 
221311e5e196SSomnath Kotur static int bnxt_handle_tunnel_redirect_destroy(struct bnxt *bp,
221411e5e196SSomnath Kotur 					       struct bnxt_filter_info *filter,
221511e5e196SSomnath Kotur 					       struct rte_flow_error *error)
221611e5e196SSomnath Kotur {
221711e5e196SSomnath Kotur 	uint16_t tun_dst_fid;
221811e5e196SSomnath Kotur 	uint32_t tun_type;
221911e5e196SSomnath Kotur 	int ret = 0;
222011e5e196SSomnath Kotur 
222111e5e196SSomnath Kotur 	ret = bnxt_hwrm_tunnel_redirect_query(bp, &tun_type);
222211e5e196SSomnath Kotur 	if (ret) {
222311e5e196SSomnath Kotur 		rte_flow_error_set(error, -ret,
222411e5e196SSomnath Kotur 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
222511e5e196SSomnath Kotur 				   "Unable to query tunnel to VF");
222611e5e196SSomnath Kotur 		return ret;
222711e5e196SSomnath Kotur 	}
222811e5e196SSomnath Kotur 	if (tun_type == (1U << filter->tunnel_type)) {
222911e5e196SSomnath Kotur 		ret = bnxt_hwrm_tunnel_redirect_info(bp, filter->tunnel_type,
223011e5e196SSomnath Kotur 						     &tun_dst_fid);
223111e5e196SSomnath Kotur 		if (ret) {
223211e5e196SSomnath Kotur 			rte_flow_error_set(error, -ret,
223311e5e196SSomnath Kotur 					   RTE_FLOW_ERROR_TYPE_HANDLE,
223411e5e196SSomnath Kotur 					   NULL,
223511e5e196SSomnath Kotur 					   "tunnel_redirect info cmd fail");
223611e5e196SSomnath Kotur 			return ret;
223711e5e196SSomnath Kotur 		}
2238e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(INFO, "Pre-existing tunnel fid = %x vf->fid = %x",
223911e5e196SSomnath Kotur 			    tun_dst_fid + bp->first_vf_id, bp->fw_fid);
224011e5e196SSomnath Kotur 
224111e5e196SSomnath Kotur 		/* Tunnel doesn't belong to this VF, so don't send HWRM
224211e5e196SSomnath Kotur 		 * cmd, just delete the flow from driver
224311e5e196SSomnath Kotur 		 */
224425ee03f5SKalesh AP 		if (bp->fw_fid != (tun_dst_fid + bp->first_vf_id)) {
2245e99981afSDavid Marchand 			PMD_DRV_LOG_LINE(ERR,
2246e99981afSDavid Marchand 				    "Tunnel does not belong to this VF, skip hwrm_tunnel_redirect_free");
224725ee03f5SKalesh AP 		} else {
224811e5e196SSomnath Kotur 			ret = bnxt_hwrm_tunnel_redirect_free(bp,
224911e5e196SSomnath Kotur 							filter->tunnel_type);
225025ee03f5SKalesh AP 			if (ret) {
225125ee03f5SKalesh AP 				rte_flow_error_set(error, -ret,
225225ee03f5SKalesh AP 						   RTE_FLOW_ERROR_TYPE_HANDLE,
225325ee03f5SKalesh AP 						   NULL,
225425ee03f5SKalesh AP 						   "Unable to free tunnel redirection");
225525ee03f5SKalesh AP 				return ret;
225625ee03f5SKalesh AP 			}
225725ee03f5SKalesh AP 		}
225811e5e196SSomnath Kotur 	}
225911e5e196SSomnath Kotur 	return ret;
226011e5e196SSomnath Kotur }
226111e5e196SSomnath Kotur 
22625c1171c9SAjit Khaparde static int
2263e339ef6eSSomnath Kotur _bnxt_flow_destroy(struct bnxt *bp,
22645c1171c9SAjit Khaparde 		   struct rte_flow *flow,
22655c1171c9SAjit Khaparde 		    struct rte_flow_error *error)
22665c1171c9SAjit Khaparde {
22671cb3d39aSVenkat Duvvuru 	struct bnxt_filter_info *filter;
22681cb3d39aSVenkat Duvvuru 	struct bnxt_vnic_info *vnic;
22695c1171c9SAjit Khaparde 	int ret = 0;
22709db66782SSomnath Kotur 	uint32_t flow_id;
22715c1171c9SAjit Khaparde 
22721cb3d39aSVenkat Duvvuru 	filter = flow->filter;
22731cb3d39aSVenkat Duvvuru 	vnic = flow->vnic;
22741cb3d39aSVenkat Duvvuru 
22756d160d77SRandy Schacher 	/* If tunnel redirection to a VF/PF is specified then only tunnel_type
22766d160d77SRandy Schacher 	 * is set and enable is set to the tunnel type. Issue hwrm cmd directly
22776d160d77SRandy Schacher 	 * in such a case.
22786d160d77SRandy Schacher 	 */
227911e5e196SSomnath Kotur 	if (filter->filter_type == HWRM_CFA_TUNNEL_REDIRECT_FILTER &&
22806d160d77SRandy Schacher 	    (filter->enables == filter->tunnel_type ||
22816d160d77SRandy Schacher 	     filter->tunnel_type == CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN ||
22826d160d77SRandy Schacher 	     filter->tunnel_type == CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE)) {
22836d160d77SRandy Schacher 		if (filter->enables & NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT) {
22846d160d77SRandy Schacher 			struct rte_eth_udp_tunnel tunnel = {0};
22856d160d77SRandy Schacher 
22866d160d77SRandy Schacher 			/* hwrm_tunnel_dst_port_free converts to Big Endian */
22876d160d77SRandy Schacher 			tunnel.udp_port = BNXT_NTOHS(filter->dst_port);
22886d160d77SRandy Schacher 			if (filter->tunnel_type ==
22896d160d77SRandy Schacher 			    CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN) {
22906d160d77SRandy Schacher 				tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_VXLAN;
22916d160d77SRandy Schacher 			} else if (filter->tunnel_type ==
22926d160d77SRandy Schacher 				 CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE) {
22936d160d77SRandy Schacher 				tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_GENEVE;
22946d160d77SRandy Schacher 			} else {
22956d160d77SRandy Schacher 				rte_flow_error_set(error, EINVAL,
22966d160d77SRandy Schacher 						   RTE_FLOW_ERROR_TYPE_HANDLE,
22976d160d77SRandy Schacher 						   NULL,
22986d160d77SRandy Schacher 						   "Invalid tunnel type");
22996d160d77SRandy Schacher 				return ret;
23006d160d77SRandy Schacher 			}
23016d160d77SRandy Schacher 
23026d160d77SRandy Schacher 			ret = bnxt_udp_tunnel_port_del_op(bp->eth_dev,
23036d160d77SRandy Schacher 							  &tunnel);
23046d160d77SRandy Schacher 			if (ret)
23056d160d77SRandy Schacher 				return ret;
23066d160d77SRandy Schacher 		}
2307e339ef6eSSomnath Kotur 		ret = bnxt_handle_tunnel_redirect_destroy(bp, filter, error);
2308e339ef6eSSomnath Kotur 		if (!ret)
230911e5e196SSomnath Kotur 			goto done;
2310e339ef6eSSomnath Kotur 		else
231111e5e196SSomnath Kotur 			return ret;
231211e5e196SSomnath Kotur 	}
231311e5e196SSomnath Kotur 
2314239695f7SAjit Khaparde 	/* For config type, there is no filter in HW. Finish cleanup here */
2315239695f7SAjit Khaparde 	if (filter->filter_type == HWRM_CFA_CONFIG)
2316239695f7SAjit Khaparde 		goto done;
2317239695f7SAjit Khaparde 
23185c1171c9SAjit Khaparde 	ret = bnxt_match_filter(bp, filter);
23195c1171c9SAjit Khaparde 	if (ret == 0)
2320e99981afSDavid Marchand 		PMD_DRV_LOG_LINE(ERR, "Could not find matching flow");
232149d0709bSAjit Khaparde 
232294eb699bSAjit Khaparde 	if (filter->valid_flags & BNXT_FLOW_MARK_FLAG) {
23239db66782SSomnath Kotur 		flow_id = filter->flow_id & BNXT_FLOW_ID_MASK;
23249db66782SSomnath Kotur 		memset(&bp->mark_table[flow_id], 0,
23259db66782SSomnath Kotur 		       sizeof(bp->mark_table[flow_id]));
232694eb699bSAjit Khaparde 		filter->flow_id = 0;
232794eb699bSAjit Khaparde 	}
232894eb699bSAjit Khaparde 
232987520e59SKalesh AP 	ret = bnxt_clear_one_vnic_filter(bp, filter);
233011e5e196SSomnath Kotur 
233111e5e196SSomnath Kotur done:
23325c1171c9SAjit Khaparde 	if (!ret) {
2333b0d3c584SAjit Khaparde 		/* If it is a L2 drop filter, when the filter is created,
2334b0d3c584SAjit Khaparde 		 * the FW updates the BC/MC records.
2335b0d3c584SAjit Khaparde 		 * Once this filter is removed, issue the set_rx_mask command
2336b0d3c584SAjit Khaparde 		 * to reset the BC/MC records in the HW to the settings
2337b0d3c584SAjit Khaparde 		 * before the drop counter is created.
2338b0d3c584SAjit Khaparde 		 */
2339b0d3c584SAjit Khaparde 		if (filter->valid_flags & BNXT_FLOW_L2_DROP_FLAG)
2340b0d3c584SAjit Khaparde 			bnxt_set_rx_mask_no_vlan(bp, &bp->vnic_info[0]);
2341b0d3c584SAjit Khaparde 
234249d0709bSAjit Khaparde 		STAILQ_REMOVE(&vnic->filter, filter, bnxt_filter_info, next);
234311e5e196SSomnath Kotur 		bnxt_free_filter(bp, filter);
23445c1171c9SAjit Khaparde 		STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next);
23455c1171c9SAjit Khaparde 		rte_free(flow);
23461e2f8acaSAjit Khaparde 		if (BNXT_FLOW_XSTATS_EN(bp))
23471e2f8acaSAjit Khaparde 			bp->flow_stat->flow_count--;
234849d0709bSAjit Khaparde 
234949d0709bSAjit Khaparde 		/* If this was the last flow associated with this vnic,
235049d0709bSAjit Khaparde 		 * switch the queue back to RSS pool.
235149d0709bSAjit Khaparde 		 */
2352b0d3c584SAjit Khaparde 		if (vnic && !vnic->func_default &&
2353b0d3c584SAjit Khaparde 		    STAILQ_EMPTY(&vnic->flow_list)) {
23543e3fecf4SKalesh AP 			bnxt_vnic_cleanup(bp, vnic);
2355a0c2315aSLance Richardson 			bp->nr_vnics--;
235649d0709bSAjit Khaparde 		}
23575c1171c9SAjit Khaparde 	} else {
23585c1171c9SAjit Khaparde 		rte_flow_error_set(error, -ret,
23595c1171c9SAjit Khaparde 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
23605c1171c9SAjit Khaparde 				   "Failed to destroy flow.");
23615c1171c9SAjit Khaparde 	}
23625c1171c9SAjit Khaparde 
2363e339ef6eSSomnath Kotur 	return ret;
2364e339ef6eSSomnath Kotur }
2365e339ef6eSSomnath Kotur 
2366e339ef6eSSomnath Kotur static int
2367e339ef6eSSomnath Kotur bnxt_flow_destroy(struct rte_eth_dev *dev,
2368e339ef6eSSomnath Kotur 		  struct rte_flow *flow,
2369e339ef6eSSomnath Kotur 		  struct rte_flow_error *error)
2370e339ef6eSSomnath Kotur {
2371e339ef6eSSomnath Kotur 	struct bnxt *bp = dev->data->dev_private;
2372e339ef6eSSomnath Kotur 	int ret = 0;
2373e339ef6eSSomnath Kotur 
2374e339ef6eSSomnath Kotur 	bnxt_acquire_flow_lock(bp);
2375e339ef6eSSomnath Kotur 	if (!flow) {
2376e339ef6eSSomnath Kotur 		rte_flow_error_set(error, EINVAL,
2377e339ef6eSSomnath Kotur 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2378e339ef6eSSomnath Kotur 				   "Invalid flow: failed to destroy flow.");
23791cb3d39aSVenkat Duvvuru 		bnxt_release_flow_lock(bp);
2380e339ef6eSSomnath Kotur 		return -EINVAL;
2381e339ef6eSSomnath Kotur 	}
2382e339ef6eSSomnath Kotur 
2383e339ef6eSSomnath Kotur 	if (!flow->filter) {
2384e339ef6eSSomnath Kotur 		rte_flow_error_set(error, EINVAL,
2385e339ef6eSSomnath Kotur 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2386e339ef6eSSomnath Kotur 				   "Invalid flow: failed to destroy flow.");
2387e339ef6eSSomnath Kotur 		bnxt_release_flow_lock(bp);
2388e339ef6eSSomnath Kotur 		return -EINVAL;
2389e339ef6eSSomnath Kotur 	}
2390e339ef6eSSomnath Kotur 	ret = _bnxt_flow_destroy(bp, flow, error);
2391e339ef6eSSomnath Kotur 	bnxt_release_flow_lock(bp);
2392e339ef6eSSomnath Kotur 
23935c1171c9SAjit Khaparde 	return ret;
23945c1171c9SAjit Khaparde }
23955c1171c9SAjit Khaparde 
239602a95625SSomnath Kotur void bnxt_cancel_fc_thread(struct bnxt *bp)
239702a95625SSomnath Kotur {
239802a95625SSomnath Kotur 	bp->flags &= ~BNXT_FLAG_FC_THREAD;
239902a95625SSomnath Kotur 	rte_eal_alarm_cancel(bnxt_flow_cnt_alarm_cb, (void *)bp);
240002a95625SSomnath Kotur }
240102a95625SSomnath Kotur 
24025c1171c9SAjit Khaparde static int
24035c1171c9SAjit Khaparde bnxt_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
24045c1171c9SAjit Khaparde {
240578466c95SStephen Hemminger 	struct bnxt *bp = dev->data->dev_private;
24065c1171c9SAjit Khaparde 	struct bnxt_vnic_info *vnic;
24075c1171c9SAjit Khaparde 	struct rte_flow *flow;
24085c1171c9SAjit Khaparde 	unsigned int i;
24095c1171c9SAjit Khaparde 	int ret = 0;
24105c1171c9SAjit Khaparde 
24111cb3d39aSVenkat Duvvuru 	bnxt_acquire_flow_lock(bp);
241249d0709bSAjit Khaparde 	for (i = 0; i < bp->max_vnics; i++) {
24135c1171c9SAjit Khaparde 		vnic = &bp->vnic_info[i];
241489278c59SAjit Khaparde 		if (vnic && vnic->fw_vnic_id == INVALID_VNIC_ID)
241549d0709bSAjit Khaparde 			continue;
241649d0709bSAjit Khaparde 
241789278c59SAjit Khaparde 		while (!STAILQ_EMPTY(&vnic->flow_list)) {
241889278c59SAjit Khaparde 			flow = STAILQ_FIRST(&vnic->flow_list);
24195c1171c9SAjit Khaparde 
2420e339ef6eSSomnath Kotur 			if (!flow->filter)
2421e339ef6eSSomnath Kotur 				continue;
2422e339ef6eSSomnath Kotur 
2423e339ef6eSSomnath Kotur 			ret = _bnxt_flow_destroy(bp, flow, error);
2424e339ef6eSSomnath Kotur 			if (ret)
2425e339ef6eSSomnath Kotur 				break;
2426e339ef6eSSomnath Kotur 		}
2427e339ef6eSSomnath Kotur 	}
242802a95625SSomnath Kotur 
242902a95625SSomnath Kotur 	bnxt_cancel_fc_thread(bp);
24301cb3d39aSVenkat Duvvuru 	bnxt_release_flow_lock(bp);
243111e5e196SSomnath Kotur 
24325c1171c9SAjit Khaparde 	return ret;
24335c1171c9SAjit Khaparde }
24345c1171c9SAjit Khaparde 
24355c1171c9SAjit Khaparde const struct rte_flow_ops bnxt_flow_ops = {
24365c1171c9SAjit Khaparde 	.validate = bnxt_flow_validate,
24375c1171c9SAjit Khaparde 	.create = bnxt_flow_create,
24385c1171c9SAjit Khaparde 	.destroy = bnxt_flow_destroy,
24395c1171c9SAjit Khaparde 	.flush = bnxt_flow_flush,
24402cc4ec01SDamodharam Ammepalli 	.query = bnxt_flow_query,
24415c1171c9SAjit Khaparde };
2442