X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Fbnxt_filter.c;h=22cfbd3729b4d821af5ffc31d4dafebeaf5351d5;hb=46667f9377ffcb48af3c6d8998dd4bc6df8436f5;hp=029a4eb4bf4bf63e2143ce8f21280d89684f8be3;hpb=18b54a7e88547a460ca89b925bba13c426c67e68;p=dpdk.git diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c index 029a4eb4bf..22cfbd3729 100644 --- a/drivers/net/bnxt/bnxt_filter.c +++ b/drivers/net/bnxt/bnxt_filter.c @@ -301,7 +301,8 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[], } static int -bnxt_validate_and_parse_flow_type(const struct rte_flow_item pattern[], +bnxt_validate_and_parse_flow_type(struct bnxt *bp, + const struct rte_flow_item pattern[], struct rte_flow_error *error, struct bnxt_filter_info *filter) { @@ -318,11 +319,14 @@ bnxt_validate_and_parse_flow_type(const struct rte_flow_item pattern[], const struct rte_flow_item_vxlan *vxlan_mask; 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; bool vni_masked = 0; bool tni_masked = 0; + uint32_t vf = 0; int use_ntuple; uint32_t en = 0; + int dflt_vnic; use_ntuple = bnxt_filter_type_check(pattern, error); RTE_LOG(DEBUG, PMD, "Use NTUPLE %d\n", use_ntuple); @@ -687,6 +691,40 @@ bnxt_validate_and_parse_flow_type(const struct rte_flow_item pattern[], CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE; } break; + case RTE_FLOW_ITEM_TYPE_VF: + vf_spec = (const struct rte_flow_item_vf *)item->spec; + vf = vf_spec->id; + if (!BNXT_PF(bp)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Configuring on a VF!"); + return -rte_errno; + } + + if (vf >= bp->pdev->max_vfs) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Incorrect VF id!"); + return -rte_errno; + } + + filter->mirror_vnic_id = + dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf); + if (dflt_vnic < 0) { + /* This simply indicates there's no driver + * loaded. This is not an error. + */ + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Unable to get default VNIC for VF"); + return -rte_errno; + } + filter->mirror_vnic_id = dflt_vnic; + en |= NTUPLE_FLTR_ALLOC_INPUT_EN_MIRROR_VNIC_ID; + break; default: break; } @@ -755,6 +793,8 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf, //This flow needs DST MAC which is not same as port/l2 RTE_LOG(DEBUG, PMD, "Create L2 filter for DST MAC\n"); filter1 = bnxt_get_unused_filter(bp); + if (filter1 == NULL) + return NULL; filter1->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; filter1->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | L2_FILTER_ALLOC_INPUT_EN_L2_ADDR_MASK; @@ -766,7 +806,6 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf, bnxt_free_filter(bp, filter1); return NULL; } - STAILQ_INSERT_TAIL(&vnic->filter, filter1, next); return filter1; } @@ -781,8 +820,11 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, const struct rte_flow_action *act = nxt_non_void_action(actions); struct bnxt *bp = (struct bnxt *)dev->data->dev_private; const struct rte_flow_action_queue *act_q; + const struct rte_flow_action_vf *act_vf; struct bnxt_vnic_info *vnic, *vnic0; struct bnxt_filter_info *filter1; + uint32_t vf = 0; + int dflt_vnic; int rc; if (bp->eth_dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS) { @@ -794,7 +836,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, goto ret; } - rc = bnxt_validate_and_parse_flow_type(pattern, error, filter); + rc = bnxt_validate_and_parse_flow_type(bp, pattern, error, filter); if (rc != 0) goto ret; @@ -860,6 +902,52 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, filter->fw_l2_filter_id = filter1->fw_l2_filter_id; filter->flags = HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_METER; break; + case RTE_FLOW_ACTION_TYPE_VF: + act_vf = (const struct rte_flow_action_vf *)act->conf; + vf = act_vf->id; + if (!BNXT_PF(bp)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "Configuring on a VF!"); + rc = -rte_errno; + goto ret; + } + + if (vf >= bp->pdev->max_vfs) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "Incorrect VF id!"); + rc = -rte_errno; + goto ret; + } + + filter->mirror_vnic_id = + dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf); + if (dflt_vnic < 0) { + /* This simply indicates there's no driver loaded. + * This is not an error. + */ + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "Unable to get default VNIC for VF"); + rc = -rte_errno; + goto ret; + } + filter->mirror_vnic_id = dflt_vnic; + filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_MIRROR_VNIC_ID; + + vnic0 = STAILQ_FIRST(&bp->ff_pool[0]); + filter1 = bnxt_get_l2_filter(bp, filter, vnic0); + if (filter1 == NULL) { + rc = -ENOSPC; + goto ret; + } + filter->fw_l2_filter_id = filter1->fw_l2_filter_id; + break; + default: rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, act, @@ -868,6 +956,11 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, goto ret; } + if (filter1) { + bnxt_free_filter(bp, filter1); + filter1->fw_l2_filter_id = -1; + } + act = nxt_non_void_action(++act); if (act->type != RTE_FLOW_ACTION_TYPE_END) { rte_flow_error_set(error, EINVAL, @@ -952,8 +1045,23 @@ bnxt_match_filter(struct bnxt *bp, struct bnxt_filter_info *nf) !memcmp(mf->dst_ipaddr, nf->dst_ipaddr, sizeof(nf->dst_ipaddr)) && !memcmp(mf->dst_ipaddr_mask, nf->dst_ipaddr_mask, - sizeof(nf->dst_ipaddr_mask))) - return -EEXIST; + sizeof(nf->dst_ipaddr_mask))) { + if (mf->dst_id == nf->dst_id) + return -EEXIST; + /* Same Flow, Different queue + * Clear the old ntuple filter + */ + if (nf->filter_type == HWRM_CFA_EM_FILTER) + bnxt_hwrm_clear_em_filter(bp, mf); + if (nf->filter_type == HWRM_CFA_NTUPLE_FILTER) + bnxt_hwrm_clear_ntuple_filter(bp, mf); + /* Free the old filter, update flow + * with new filter + */ + bnxt_free_filter(bp, mf); + flow->filter = nf; + return -EXDEV; + } } } return 0; @@ -969,6 +1077,7 @@ bnxt_flow_create(struct rte_eth_dev *dev, struct bnxt *bp = (struct bnxt *)dev->data->dev_private; struct bnxt_filter_info *filter; struct bnxt_vnic_info *vnic = NULL; + bool update_flow = false; struct rte_flow *flow; unsigned int i; int ret = 0; @@ -999,9 +1108,17 @@ bnxt_flow_create(struct rte_eth_dev *dev, goto free_filter; ret = bnxt_match_filter(bp, filter); - if (ret != 0) { + if (ret == -EEXIST) { RTE_LOG(DEBUG, PMD, "Flow already exists.\n"); + /* Clear the filter that was created as part of + * validate_and_parse_flow() above + */ + bnxt_hwrm_clear_l2_filter(bp, filter); goto free_filter; + } else if (ret == -EXDEV) { + RTE_LOG(DEBUG, PMD, "Flow with same pattern exists"); + RTE_LOG(DEBUG, PMD, "Updating with different destination\n"); + update_flow = true; } if (filter->filter_type == HWRM_CFA_EM_FILTER) { @@ -1024,22 +1141,29 @@ bnxt_flow_create(struct rte_eth_dev *dev, if (!ret) { flow->filter = filter; flow->vnic = vnic; + if (update_flow) { + ret = -EXDEV; + goto free_flow; + } RTE_LOG(ERR, PMD, "Successfully created flow.\n"); STAILQ_INSERT_TAIL(&vnic->flow_list, flow, next); return flow; } free_filter: - filter->fw_l2_filter_id = -1; bnxt_free_filter(bp, filter); free_flow: if (ret == -EEXIST) rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Matching Flow exists."); + else if (ret == -EXDEV) + rte_flow_error_set(error, ret, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "Flow with pattern exists, updating destination queue"); else rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, - "Failed to create flow."); + "Failed to create flow."); rte_free(flow); flow = NULL; return flow; @@ -1063,6 +1187,7 @@ bnxt_flow_destroy(struct rte_eth_dev *dev, if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER) ret = bnxt_hwrm_clear_ntuple_filter(bp, filter); + bnxt_hwrm_clear_l2_filter(bp, filter); if (!ret) { STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next); rte_free(flow);