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(ð_mask->hdr.src_addr) && 2038275d5fcSThomas Monjalon !rte_is_broadcast_ether_addr(ð_mask->hdr.src_addr)) || 2048275d5fcSThomas Monjalon (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr) && 2058275d5fcSThomas Monjalon !rte_is_broadcast_ether_addr(ð_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(ð_mask->hdr.dst_addr)) { 2258275d5fcSThomas Monjalon dst = ð_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 ð_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(ð_mask->hdr.src_addr)) { 2498275d5fcSThomas Monjalon src = ð_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 ð_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