From afef822b2e1bdf56a3e2a55d8f76025e0e1764fb Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 2 Oct 2019 16:25:45 -0700 Subject: [PATCH] net/bnxt: support creating SMAC and inner DMAC filters We are currently creating only outer DMAC filters. Create SMAC and inner DMAC filters using HWRM_CFA_L2_FILTER_ALLOC. For this the HWRM_CFA_L2_FILTER_ALLOC has already been updated. Reviewed-by: Somnath Kotur Reviewed-by: Rahul Gupta Signed-off-by: Kalesh AP Signed-off-by: Ajit Khaparde --- drivers/net/bnxt/bnxt.h | 4 ++ drivers/net/bnxt/bnxt_ethdev.c | 9 ++- drivers/net/bnxt/bnxt_filter.h | 8 +++ drivers/net/bnxt/bnxt_flow.c | 118 +++++++++++++++++++++++++-------- drivers/net/bnxt/bnxt_hwrm.c | 44 +++++++++++- drivers/net/bnxt/bnxt_hwrm.h | 4 ++ drivers/net/bnxt/bnxt_rxq.c | 2 + 7 files changed, 160 insertions(+), 29 deletions(-) diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index c5dceb7d28..8602ab3346 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -439,6 +439,7 @@ struct bnxt { #define BNXT_FLAG_NEW_RM BIT(23) #define BNXT_FLAG_INIT_DONE BIT(24) #define BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS BIT(25) +#define BNXT_FLAG_ADV_FLOW_MGMT BIT(26) #define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF)) #define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF) #define BNXT_NPAR(bp) ((bp)->port_partition_type) @@ -452,6 +453,9 @@ struct bnxt { #define BNXT_HAS_NQ(bp) BNXT_CHIP_THOR(bp) #define BNXT_HAS_RING_GRPS(bp) (!BNXT_CHIP_THOR(bp)) + uint32_t flow_flags; +#define BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN BIT(0) + unsigned int rx_nr_rings; unsigned int rx_cp_nr_rings; unsigned int rx_num_qs_per_vnic; diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index c953979cca..7cd3213558 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -1039,6 +1039,7 @@ static int bnxt_mac_addr_add_op(struct rte_eth_dev *eth_dev, filter->mac_index = index; memcpy(filter->l2_addr, mac_addr, RTE_ETHER_ADDR_LEN); + filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter); if (!rc) { @@ -1739,6 +1740,7 @@ static int bnxt_add_vlan_filter(struct bnxt *bp, uint16_t vlan_id) filter->l2_ivlan = vlan_id; filter->l2_ivlan_mask = 0x0FFF; filter->enables |= en; + filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter); if (rc) { /* Free the newly allocated filter as we were @@ -1904,7 +1906,8 @@ bnxt_set_default_mac_addr_op(struct rte_eth_dev *dev, memcpy(filter->l2_addr, bp->mac_addr, RTE_ETHER_ADDR_LEN); memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN); - filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; + filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX | + HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; filter->enables |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK; @@ -4433,6 +4436,10 @@ static int bnxt_init_fw(struct bnxt *bp) if (rc) return -EIO; + rc = bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(bp); + if (rc) + return rc; + rc = bnxt_hwrm_queue_qportcfg(bp); if (rc) return rc; diff --git a/drivers/net/bnxt/bnxt_filter.h b/drivers/net/bnxt/bnxt_filter.h index 4fda3f03a0..52d3582ba0 100644 --- a/drivers/net/bnxt/bnxt_filter.h +++ b/drivers/net/bnxt/bnxt_filter.h @@ -9,6 +9,13 @@ #include struct bnxt; + +#define BNXT_FLOW_L2_VALID_FLAG BIT(0) +#define BNXT_FLOW_L2_SRC_VALID_FLAG BIT(1) +#define BNXT_FLOW_L2_INNER_SRC_VALID_FLAG BIT(2) +#define BNXT_FLOW_L2_DST_VALID_FLAG BIT(3) +#define BNXT_FLOW_L2_INNER_DST_VALID_FLAG BIT(4) + struct bnxt_filter_info { STAILQ_ENTRY(bnxt_filter_info) next; uint64_t fw_l2_filter_id; @@ -28,6 +35,7 @@ struct bnxt_filter_info { uint32_t enables; uint8_t l2_addr[RTE_ETHER_ADDR_LEN]; uint8_t l2_addr_mask[RTE_ETHER_ADDR_LEN]; + uint32_t valid_flags; uint16_t l2_ovlan; uint16_t l2_ovlan_mask; uint16_t l2_ivlan; diff --git a/drivers/net/bnxt/bnxt_flow.c b/drivers/net/bnxt/bnxt_flow.c index af86be63b8..8cc8c1367a 100644 --- a/drivers/net/bnxt/bnxt_flow.c +++ b/drivers/net/bnxt/bnxt_flow.c @@ -83,14 +83,17 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[], const struct rte_flow_item *item = bnxt_flow_non_void_item(pattern); int use_ntuple = 1; + bool has_vlan = 0; while (item->type != RTE_FLOW_ITEM_TYPE_END) { switch (item->type) { + case RTE_FLOW_ITEM_TYPE_ANY: case RTE_FLOW_ITEM_TYPE_ETH: - use_ntuple = 1; + use_ntuple = 0; break; case RTE_FLOW_ITEM_TYPE_VLAN: use_ntuple = 0; + has_vlan = 1; break; case RTE_FLOW_ITEM_TYPE_IPV4: case RTE_FLOW_ITEM_TYPE_IPV6: @@ -98,28 +101,25 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[], case RTE_FLOW_ITEM_TYPE_UDP: /* FALLTHROUGH */ /* need ntuple match, reset exact match */ - if (!use_ntuple) { - PMD_DRV_LOG(ERR, - "VLAN flow cannot use NTUPLE filter\n"); - rte_flow_error_set - (error, - EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, - "Cannot use VLAN with NTUPLE"); - return -rte_errno; - } use_ntuple |= 1; break; - case RTE_FLOW_ITEM_TYPE_ANY: - use_ntuple = 0; - break; default: PMD_DRV_LOG(DEBUG, "Unknown Flow type\n"); use_ntuple |= 0; } item++; } + + if (has_vlan && use_ntuple) { + PMD_DRV_LOG(ERR, + "VLAN flow cannot use NTUPLE filter\n"); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Cannot use VLAN with NTUPLE"); + return -rte_errno; + } + return use_ntuple; } @@ -146,13 +146,14 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, uint8_t vni_mask[] = {0xFF, 0xFF, 0xFF}; uint8_t tni_mask[] = {0xFF, 0xFF, 0xFF}; const struct rte_flow_item_vf *vf_spec; - uint32_t tenant_id_be = 0; + uint32_t tenant_id_be = 0, valid_flags = 0; bool vni_masked = 0; bool tni_masked = 0; + uint32_t en_ethertype; + uint8_t inner = 0; uint32_t vf = 0; - int use_ntuple; uint32_t en = 0; - uint32_t en_ethertype; + int use_ntuple; int dflt_vnic; use_ntuple = bnxt_filter_type_check(pattern, error); @@ -177,6 +178,12 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, } switch (item->type) { + case RTE_FLOW_ITEM_TYPE_ANY: + inner = + ((const struct rte_flow_item_any *)item->spec)->num > 3; + if (inner) + PMD_DRV_LOG(DEBUG, "Parse inner header\n"); + break; case RTE_FLOW_ITEM_TYPE_ETH: if (!item->spec || !item->mask) break; @@ -213,18 +220,24 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, if (rte_is_broadcast_ether_addr(ð_mask->dst)) { rte_memcpy(filter->dst_macaddr, - ð_spec->dst, 6); + ð_spec->dst, RTE_ETHER_ADDR_LEN); en |= use_ntuple ? NTUPLE_FLTR_ALLOC_INPUT_EN_DST_MACADDR : EM_FLOW_ALLOC_INPUT_EN_DST_MACADDR; + valid_flags |= inner ? + BNXT_FLOW_L2_INNER_DST_VALID_FLAG : + BNXT_FLOW_L2_DST_VALID_FLAG; } if (rte_is_broadcast_ether_addr(ð_mask->src)) { rte_memcpy(filter->src_macaddr, - ð_spec->src, 6); + ð_spec->src, RTE_ETHER_ADDR_LEN); en |= use_ntuple ? NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_MACADDR : EM_FLOW_ALLOC_INPUT_EN_SRC_MACADDR; + valid_flags |= inner ? + BNXT_FLOW_L2_INNER_SRC_VALID_FLAG : + BNXT_FLOW_L2_SRC_VALID_FLAG; } /* * else { * PMD_DRV_LOG(ERR, "Handle this condition\n"); @@ -669,6 +682,7 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, item++; } filter->enables = en; + filter->valid_flags = valid_flags; return 0; } @@ -725,16 +739,45 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf, if (memcmp(f0->l2_addr, nf->dst_macaddr, RTE_ETHER_ADDR_LEN) == 0) return f0; - /* This flow needs DST MAC which is not same as port/l2 */ - PMD_DRV_LOG(DEBUG, "Create L2 filter for DST MAC\n"); + /* Alloc new L2 filter. + * This flow needs MAC filter which does not match port/l2 MAC. + */ filter1 = bnxt_get_unused_filter(bp); if (filter1 == NULL) return NULL; - filter1->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; + filter1->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_XDP_DISABLE; + filter1->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; + if (nf->valid_flags & BNXT_FLOW_L2_SRC_VALID_FLAG || + nf->valid_flags & BNXT_FLOW_L2_DST_VALID_FLAG) { + filter1->flags |= + HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; + PMD_DRV_LOG(DEBUG, "Create Outer filter\n"); + } + + if (nf->filter_type == HWRM_CFA_L2_FILTER && + (nf->valid_flags & BNXT_FLOW_L2_SRC_VALID_FLAG || + nf->valid_flags & BNXT_FLOW_L2_INNER_SRC_VALID_FLAG)) { + PMD_DRV_LOG(DEBUG, "Create L2 filter for SRC MAC\n"); + filter1->flags |= + HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_SOURCE_VALID; + memcpy(filter1->l2_addr, nf->src_macaddr, RTE_ETHER_ADDR_LEN); + } else { + PMD_DRV_LOG(DEBUG, "Create L2 filter for DST MAC\n"); + memcpy(filter1->l2_addr, nf->dst_macaddr, RTE_ETHER_ADDR_LEN); + } + + if (nf->valid_flags & BNXT_FLOW_L2_DST_VALID_FLAG || + nf->valid_flags & BNXT_FLOW_L2_INNER_DST_VALID_FLAG) { + /* Tell the FW where to place the filter in the table. */ + filter1->pri_hint = + HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_BELOW_FILTER; + /* This will place the filter in TCAM */ + filter1->l2_filter_id_hint = (uint64_t)-1; + } + filter1->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | L2_FILTER_ALLOC_INPUT_EN_L2_ADDR_MASK; - memcpy(filter1->l2_addr, nf->dst_macaddr, RTE_ETHER_ADDR_LEN); memset(filter1->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN); rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter1); @@ -843,6 +886,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, PMD_DRV_LOG(DEBUG, "Group id is 0\n"); vnic_id = act_q->index; } + PMD_DRV_LOG(DEBUG, "VNIC found\n"); vnic = &bp->vnic_info[vnic_id]; if (vnic == NULL) { @@ -871,7 +915,8 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, rxq = bp->rx_queues[act_q->index]; - if (!(dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) && rxq) + if (!(dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) && rxq && + vnic->fw_vnic_id != INVALID_HW_RING_ID) goto use_vnic; if (!rxq || @@ -916,8 +961,20 @@ use_vnic: goto ret; } + if (!(filter->valid_flags & + ~(BNXT_FLOW_L2_DST_VALID_FLAG | + BNXT_FLOW_L2_SRC_VALID_FLAG | + BNXT_FLOW_L2_INNER_SRC_VALID_FLAG | + BNXT_FLOW_L2_INNER_DST_VALID_FLAG))) { + PMD_DRV_LOG(DEBUG, "L2 filter created\n"); + filter->flags = filter1->flags; + filter->enables = filter1->enables; + filter->filter_type = HWRM_CFA_L2_FILTER; + memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN); + filter->pri_hint = filter1->pri_hint; + filter->l2_filter_id_hint = filter1->l2_filter_id_hint; + } filter->fw_l2_filter_id = filter1->fw_l2_filter_id; - PMD_DRV_LOG(DEBUG, "VNIC found\n"); break; case RTE_FLOW_ACTION_TYPE_DROP: vnic0 = &bp->vnic_info[0]; @@ -1008,6 +1065,15 @@ use_vnic: filter->fw_l2_filter_id = filter1->fw_l2_filter_id; break; + case RTE_FLOW_ACTION_TYPE_RSS: + rte_flow_error_set(error, + ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "This action is not supported right now."); + rc = -rte_errno; + goto ret; + //break; default: rte_flow_error_set(error, diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c index 35fb7dca25..ceaeb609a4 100644 --- a/drivers/net/bnxt/bnxt_hwrm.c +++ b/drivers/net/bnxt/bnxt_hwrm.c @@ -425,8 +425,6 @@ int bnxt_hwrm_set_l2_filter(struct bnxt *bp, HWRM_PREP(req, CFA_L2_FILTER_ALLOC, BNXT_USE_CHIMP_MB); req.flags = rte_cpu_to_le_32(filter->flags); - req.flags |= - rte_cpu_to_le_32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST); enables = filter->enables | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID; @@ -456,6 +454,11 @@ int bnxt_hwrm_set_l2_filter(struct bnxt *bp, req.src_id = rte_cpu_to_le_32(filter->src_id); if (enables & HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_SRC_TYPE) req.src_type = filter->src_type; + if (filter->pri_hint) { + req.pri_hint = filter->pri_hint; + req.l2_filter_id_hint = + rte_cpu_to_le_64(filter->l2_filter_id_hint); + } req.enables = rte_cpu_to_le_32(enables); @@ -1017,6 +1020,11 @@ int bnxt_hwrm_ver_get(struct bnxt *bp) if (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED) PMD_DRV_LOG(DEBUG, "FW supports Trusted VFs\n"); + if (dev_caps_cfg & + HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED) { + bp->flags |= BNXT_FLAG_ADV_FLOW_MGMT; + PMD_DRV_LOG(DEBUG, "FW supports advanced flow management\n"); + } error: HWRM_UNLOCK(); @@ -4912,3 +4920,35 @@ int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path, uint64_t *timestamp) return rc; } + +int bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(struct bnxt *bp) +{ + struct hwrm_cfa_adv_flow_mgnt_qcaps_output *resp = + bp->hwrm_cmd_resp_addr; + struct hwrm_cfa_adv_flow_mgnt_qcaps_input req = {0}; + uint32_t flags = 0; + int rc = 0; + + if (!(bp->flags & BNXT_FLAG_ADV_FLOW_MGMT)) + return rc; + + if (!(BNXT_PF(bp) || BNXT_VF_IS_TRUSTED(bp))) { + PMD_DRV_LOG(DEBUG, + "Not a PF or trusted VF. Command not supported\n"); + return 0; + } + + HWRM_PREP(req, CFA_ADV_FLOW_MGNT_QCAPS, BNXT_USE_KONG(bp)); + rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp)); + + HWRM_CHECK_RESULT(); + flags = rte_le_to_cpu_32(resp->flags); + HWRM_UNLOCK(); + + if (flags & HWRM_CFA_ADV_FLOW_MGNT_QCAPS_L2_HDR_SRC_FILTER_EN) { + bp->flow_flags |= BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN; + PMD_DRV_LOG(INFO, "Source L2 header filtering enabled\n"); + } + + return rc; +} diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h index 5190f43290..3a49c493db 100644 --- a/drivers/net/bnxt/bnxt_hwrm.h +++ b/drivers/net/bnxt/bnxt_hwrm.h @@ -38,6 +38,9 @@ struct bnxt_cp_ring_info; #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESV_STRATEGY_MINIMAL_STATIC \ HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MINIMAL_STATIC +#define HWRM_CFA_ADV_FLOW_MGNT_QCAPS_L2_HDR_SRC_FILTER_EN \ +HWRM_CFA_ADV_FLOW_MGNT_QCAPS_OUTPUT_FLAGS_L2_HEADER_SOURCE_FIELDS_SUPPORTED + #define HWRM_SPEC_CODE_1_8_4 0x10804 #define HWRM_SPEC_CODE_1_9_0 0x10900 #define HWRM_SPEC_CODE_1_9_2 0x10902 @@ -210,4 +213,5 @@ int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp); int bnxt_hwrm_fw_reset(struct bnxt *bp); int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path, uint64_t *timestamp); +int bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(struct bnxt *bp); #endif diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c index 667d0486e3..371534db6b 100644 --- a/drivers/net/bnxt/bnxt_rxq.c +++ b/drivers/net/bnxt/bnxt_rxq.c @@ -64,6 +64,7 @@ int bnxt_mq_rx_configure(struct bnxt *bp) rc = -ENOMEM; goto err_out; } + filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; STAILQ_INSERT_TAIL(&vnic->filter, filter, next); goto out; } @@ -145,6 +146,7 @@ int bnxt_mq_rx_configure(struct bnxt *bp) rc = -ENOMEM; goto err_out; } + filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST; /* * TODO: Configure & associate CFA rule for * each VNIC for each VMDq with MACVLAN, MACVLAN+TC -- 2.20.1