aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnxt/bnxt_filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bnxt/bnxt_filter.c')
-rw-r--r--drivers/net/bnxt/bnxt_filter.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c
index 65d30fb3..032e8eed 100644
--- a/drivers/net/bnxt/bnxt_filter.c
+++ b/drivers/net/bnxt/bnxt_filter.c
@@ -56,7 +56,7 @@ struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp)
/* Find the 1st unused filter from the free_filter_list pool*/
filter = STAILQ_FIRST(&bp->free_filter_list);
if (!filter) {
- RTE_LOG(ERR, PMD, "No more free filter resources\n");
+ PMD_DRV_LOG(ERR, "No more free filter resources\n");
return NULL;
}
STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
@@ -77,7 +77,7 @@ struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf)
filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0);
if (!filter) {
- RTE_LOG(ERR, PMD, "Failed to alloc memory for VF %hu filters\n",
+ PMD_DRV_LOG(ERR, "Failed to alloc memory for VF %hu filters\n",
vf);
return NULL;
}
@@ -145,11 +145,11 @@ void bnxt_free_filter_mem(struct bnxt *bp)
for (i = 0; i < max_filters; i++) {
filter = &bp->filter_info[i];
if (filter->fw_l2_filter_id != ((uint64_t)-1)) {
- RTE_LOG(ERR, PMD, "HWRM filter is not freed??\n");
+ PMD_DRV_LOG(ERR, "HWRM filter is not freed??\n");
/* Call HWRM to try to free filter again */
rc = bnxt_hwrm_clear_l2_filter(bp, filter);
if (rc)
- RTE_LOG(ERR, PMD,
+ PMD_DRV_LOG(ERR,
"HWRM filter cannot be freed rc = %d\n",
rc);
}
@@ -172,7 +172,7 @@ int bnxt_alloc_filter_mem(struct bnxt *bp)
max_filters * sizeof(struct bnxt_filter_info),
0);
if (filter_mem == NULL) {
- RTE_LOG(ERR, PMD, "Failed to alloc memory for %d filters",
+ PMD_DRV_LOG(ERR, "Failed to alloc memory for %d filters",
max_filters);
return -ENOMEM;
}
@@ -187,7 +187,7 @@ struct bnxt_filter_info *bnxt_get_unused_filter(struct bnxt *bp)
/* Find the 1st unused filter from the free_filter_list pool*/
filter = STAILQ_FIRST(&bp->free_filter_list);
if (!filter) {
- RTE_LOG(ERR, PMD, "No more free filter resources\n");
+ PMD_DRV_LOG(ERR, "No more free filter resources\n");
return NULL;
}
STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
@@ -250,7 +250,7 @@ nxt_non_void_action(const struct rte_flow_action *cur)
}
}
-static inline int check_zero_bytes(const uint8_t *bytes, int len)
+int check_zero_bytes(const uint8_t *bytes, int len)
{
int i;
for (i = 0; i < len; i++)
@@ -281,7 +281,7 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[],
/* FALLTHROUGH */
/* need ntuple match, reset exact match */
if (!use_ntuple) {
- RTE_LOG(ERR, PMD,
+ PMD_DRV_LOG(ERR,
"VLAN flow cannot use NTUPLE filter\n");
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
@@ -292,7 +292,7 @@ bnxt_filter_type_check(const struct rte_flow_item pattern[],
use_ntuple |= 1;
break;
default:
- RTE_LOG(ERR, PMD, "Unknown Flow type");
+ PMD_DRV_LOG(ERR, "Unknown Flow type");
use_ntuple |= 1;
}
item++;
@@ -329,7 +329,7 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp,
int dflt_vnic;
use_ntuple = bnxt_filter_type_check(pattern, error);
- RTE_LOG(DEBUG, PMD, "Use NTUPLE %d\n", use_ntuple);
+ PMD_DRV_LOG(DEBUG, "Use NTUPLE %d\n", use_ntuple);
if (use_ntuple < 0)
return use_ntuple;
@@ -791,7 +791,7 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
return f0;
//This flow needs DST MAC which is not same as port/l2
- RTE_LOG(DEBUG, PMD, "Create L2 filter for DST MAC\n");
+ PMD_DRV_LOG(DEBUG, "Create L2 filter for DST MAC\n");
filter1 = bnxt_get_unused_filter(bp);
if (filter1 == NULL)
return NULL;
@@ -806,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;
}
@@ -829,7 +828,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
int rc;
if (bp->eth_dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS) {
- RTE_LOG(ERR, PMD, "Cannot create flow on RSS queues\n");
+ PMD_DRV_LOG(ERR, "Cannot create flow on RSS queues\n");
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"Cannot create flow on RSS queues");
@@ -858,7 +857,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
rc = -rte_errno;
goto ret;
}
- RTE_LOG(DEBUG, PMD, "Queue index %d\n", act_q->index);
+ PMD_DRV_LOG(DEBUG, "Queue index %d\n", act_q->index);
vnic0 = STAILQ_FIRST(&bp->ff_pool[0]);
vnic = STAILQ_FIRST(&bp->ff_pool[act_q->index]);
@@ -876,7 +875,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
goto ret;
}
filter->fw_l2_filter_id = filter1->fw_l2_filter_id;
- RTE_LOG(DEBUG, PMD, "VNIC found\n");
+ PMD_DRV_LOG(DEBUG, "VNIC found\n");
break;
case RTE_FLOW_ACTION_TYPE_DROP:
vnic0 = STAILQ_FIRST(&bp->ff_pool[0]);
@@ -957,7 +956,11 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
goto ret;
}
-//done:
+ 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,
@@ -987,7 +990,7 @@ bnxt_flow_validate(struct rte_eth_dev *dev,
filter = bnxt_get_unused_filter(bp);
if (filter == NULL) {
- RTE_LOG(ERR, PMD, "Not enough resources for a new flow.\n");
+ PMD_DRV_LOG(ERR, "Not enough resources for a new flow.\n");
return -ENOMEM;
}
@@ -1042,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;
@@ -1059,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;
@@ -1073,13 +1092,13 @@ bnxt_flow_create(struct rte_eth_dev *dev,
ret = bnxt_flow_agrs_validate(attr, pattern, actions, error);
if (ret != 0) {
- RTE_LOG(ERR, PMD, "Not a validate flow.\n");
+ PMD_DRV_LOG(ERR, "Not a validate flow.\n");
goto free_flow;
}
filter = bnxt_get_unused_filter(bp);
if (filter == NULL) {
- RTE_LOG(ERR, PMD, "Not enough resources for a new flow.\n");
+ PMD_DRV_LOG(ERR, "Not enough resources for a new flow.\n");
goto free_flow;
}
@@ -1089,9 +1108,17 @@ bnxt_flow_create(struct rte_eth_dev *dev,
goto free_filter;
ret = bnxt_match_filter(bp, filter);
- if (ret != 0) {
- RTE_LOG(DEBUG, PMD, "Flow already exists.\n");
+ if (ret == -EEXIST) {
+ PMD_DRV_LOG(DEBUG, "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) {
+ PMD_DRV_LOG(DEBUG, "Flow with same pattern exists");
+ PMD_DRV_LOG(DEBUG, "Updating with different destination\n");
+ update_flow = true;
}
if (filter->filter_type == HWRM_CFA_EM_FILTER) {
@@ -1114,22 +1141,29 @@ bnxt_flow_create(struct rte_eth_dev *dev,
if (!ret) {
flow->filter = filter;
flow->vnic = vnic;
- RTE_LOG(ERR, PMD, "Successfully created flow.\n");
+ if (update_flow) {
+ ret = -EXDEV;
+ goto free_flow;
+ }
+ PMD_DRV_LOG(ERR, "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;
@@ -1147,12 +1181,13 @@ bnxt_flow_destroy(struct rte_eth_dev *dev,
ret = bnxt_match_filter(bp, filter);
if (ret == 0)
- RTE_LOG(ERR, PMD, "Could not find matching flow\n");
+ PMD_DRV_LOG(ERR, "Could not find matching flow\n");
if (filter->filter_type == HWRM_CFA_EM_FILTER)
ret = bnxt_hwrm_clear_em_filter(bp, filter);
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);