The software L2 filter was being released back to the free pool,
though it was created in HW and the filter corresponding to an actual
'flow' would have reference to the HW L2 filter.
But if this 'flow were to be deleted, then this HW L2 filter also
would be gone.
Fix this by storing the L2 filter created originally either for an
n-tuple flow or otherwise as part of the vnic's filter list.
This would require the filter_info struct to have a backptr to the
vnic which it came from.
Now that L2 filters can be re-used for an n-tuple filter(s), delete
L2 filter as well so the reference count of an L2 filter (if reused)
can be decremented appropriately.
Fixes:
5c1171c97216 ("net/bnxt: refactor filter/flow")
Cc: stable@dpdk.org
Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
uint16_t ip_addr_type;
uint16_t ethertype;
uint32_t priority;
uint16_t ip_addr_type;
uint16_t ethertype;
uint32_t priority;
+ /* Backptr to vnic. As of now, used only by an L2 filter
+ * to remember which vnic it was created on
+ */
+ struct bnxt_vnic_info *vnic;
};
struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp);
};
struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp);
{
struct bnxt_filter_info *mf, *f0;
struct bnxt_vnic_info *vnic0;
{
struct bnxt_filter_info *mf, *f0;
struct bnxt_vnic_info *vnic0;
- vnic0 = &bp->vnic_info[0];
+ vnic0 = BNXT_GET_DEFAULT_VNIC(bp);
f0 = STAILQ_FIRST(&vnic0->filter);
/* This flow has same DST MAC as the port/l2 filter. */
f0 = STAILQ_FIRST(&vnic0->filter);
/* This flow has same DST MAC as the port/l2 filter. */
if (vnic->fw_vnic_id == INVALID_VNIC_ID)
continue;
if (vnic->fw_vnic_id == INVALID_VNIC_ID)
continue;
- STAILQ_FOREACH(flow, &vnic->flow_list, next) {
- mf = flow->filter;
+ STAILQ_FOREACH(mf, &vnic->filter, next) {
if (mf->matching_l2_fltr_ptr)
continue;
if (mf->matching_l2_fltr_ptr)
continue;
if (filter1 == NULL)
return NULL;
if (filter1 == NULL)
return NULL;
+ memcpy(filter1, nf, sizeof(*filter1));
+
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 ||
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 ||
l2_filter = bnxt_find_matching_l2_filter(bp, nf);
if (l2_filter) {
l2_filter->l2_ref_cnt++;
l2_filter = bnxt_find_matching_l2_filter(bp, nf);
if (l2_filter) {
l2_filter->l2_ref_cnt++;
- nf->matching_l2_fltr_ptr = l2_filter;
} else {
l2_filter = bnxt_create_l2_filter(bp, nf, vnic);
} else {
l2_filter = bnxt_create_l2_filter(bp, nf, vnic);
- nf->matching_l2_fltr_ptr = NULL;
+ if (l2_filter) {
+ STAILQ_INSERT_TAIL(&vnic->filter, l2_filter, next);
+ l2_filter->vnic = vnic;
+ }
+ nf->matching_l2_fltr_ptr = l2_filter;
- if (filter1 && !filter->matching_l2_fltr_ptr) {
- bnxt_free_filter(bp, filter1);
- filter1->fw_l2_filter_id = -1;
- }
-
done:
act = bnxt_flow_non_void_action(++act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
done:
act = bnxt_flow_non_void_action(++act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
}
int bnxt_hwrm_clear_l2_filter(struct bnxt *bp,
}
int bnxt_hwrm_clear_l2_filter(struct bnxt *bp,
- struct bnxt_filter_info *filter)
+ struct bnxt_filter_info *filter)
{
int rc = 0;
struct bnxt_filter_info *l2_filter = filter;
{
int rc = 0;
struct bnxt_filter_info *l2_filter = filter;
+ struct bnxt_vnic_info *vnic = NULL;
struct hwrm_cfa_l2_filter_free_input req = {.req_type = 0 };
struct hwrm_cfa_l2_filter_free_output *resp = bp->hwrm_cmd_resp_addr;
struct hwrm_cfa_l2_filter_free_input req = {.req_type = 0 };
struct hwrm_cfa_l2_filter_free_output *resp = bp->hwrm_cmd_resp_addr;
PMD_DRV_LOG(DEBUG, "filter: %p l2_filter: %p ref_cnt: %d\n",
filter, l2_filter, l2_filter->l2_ref_cnt);
PMD_DRV_LOG(DEBUG, "filter: %p l2_filter: %p ref_cnt: %d\n",
filter, l2_filter, l2_filter->l2_ref_cnt);
+ if (l2_filter->l2_ref_cnt == 0)
+ return 0;
+
if (l2_filter->l2_ref_cnt > 0)
l2_filter->l2_ref_cnt--;
if (l2_filter->l2_ref_cnt > 0)
l2_filter->l2_ref_cnt--;
HWRM_UNLOCK();
filter->fw_l2_filter_id = UINT64_MAX;
HWRM_UNLOCK();
filter->fw_l2_filter_id = UINT64_MAX;
+ if (l2_filter->l2_ref_cnt == 0) {
+ vnic = l2_filter->vnic;
+ if (vnic) {
+ STAILQ_REMOVE(&vnic->filter, l2_filter,
+ bnxt_filter_info, next);
+ bnxt_free_filter(bp, l2_filter);
+ }
+ }
rc = bnxt_hwrm_clear_em_filter(bp, filter);
else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
rc = bnxt_hwrm_clear_em_filter(bp, filter);
else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
- else
- rc = bnxt_hwrm_clear_l2_filter(bp, filter);
+ rc = bnxt_hwrm_clear_l2_filter(bp, filter);
STAILQ_REMOVE(&vnic->filter, filter, bnxt_filter_info, next);
bnxt_free_filter(bp, filter);
}
STAILQ_REMOVE(&vnic->filter, filter, bnxt_filter_info, next);
bnxt_free_filter(bp, filter);
}
rc = bnxt_hwrm_clear_em_filter(bp, filter);
else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
rc = bnxt_hwrm_clear_em_filter(bp, filter);
else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
- else
- rc = bnxt_hwrm_clear_l2_filter(bp, filter);
+ rc = bnxt_hwrm_clear_l2_filter(bp, filter);
STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next);
rte_free(flow);
STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next);
rte_free(flow);