From d24610f7bfdaa4eb12ca1aed04d60a73b8ea7745 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 2 Oct 2019 16:25:44 -0700 Subject: [PATCH] net/bnxt: allow flow creation when RSS is enabled Currently flow creation is allowed with queue action only when RSS is disabled. Remove this restriction. Flows can be created when RSS is enabled. Signed-off-by: Ajit Khaparde Reviewed-by: Rahul Gupta Reviewed-by: Venkat Duvvuru --- drivers/net/bnxt/bnxt.h | 1 + drivers/net/bnxt/bnxt_ethdev.c | 2 +- drivers/net/bnxt/bnxt_flow.c | 176 +++++++++++++++++++++++++++------ drivers/net/bnxt/bnxt_vnic.h | 2 + 4 files changed, 148 insertions(+), 33 deletions(-) diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index a383ad4af6..c5dceb7d28 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -554,6 +554,7 @@ struct bnxt { int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete); int bnxt_rcv_msg_from_vf(struct bnxt *bp, uint16_t vf_id, void *msg); int is_bnxt_in_error(struct bnxt *bp); +uint16_t bnxt_rss_ctxts(const struct bnxt *bp); int bnxt_map_fw_health_status_regs(struct bnxt *bp); uint32_t bnxt_read_fw_status_reg(struct bnxt *bp, uint32_t index); diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index d8ffe45f63..c953979cca 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -189,7 +189,7 @@ int is_bnxt_in_error(struct bnxt *bp) * High level utility functions */ -static uint16_t bnxt_rss_ctxts(const struct bnxt *bp) +uint16_t bnxt_rss_ctxts(const struct bnxt *bp) { if (!BNXT_CHIP_THOR(bp)) return 1; diff --git a/drivers/net/bnxt/bnxt_flow.c b/drivers/net/bnxt/bnxt_flow.c index 13bdaf0340..af86be63b8 100644 --- a/drivers/net/bnxt/bnxt_flow.c +++ b/drivers/net/bnxt/bnxt_flow.c @@ -14,6 +14,8 @@ #include "bnxt.h" #include "bnxt_filter.h" #include "bnxt_hwrm.h" +#include "bnxt_ring.h" +#include "bnxt_rxq.h" #include "bnxt_vnic.h" #include "bnxt_util.h" #include "hsi_struct_def_dpdk.h" @@ -151,23 +153,13 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, int use_ntuple; uint32_t en = 0; uint32_t en_ethertype; - int dflt_vnic, rc = 0; + int dflt_vnic; use_ntuple = bnxt_filter_type_check(pattern, error); PMD_DRV_LOG(DEBUG, "Use NTUPLE %d\n", use_ntuple); if (use_ntuple < 0) return use_ntuple; - if (use_ntuple && (bp->eth_dev->data->dev_conf.rxmode.mq_mode & - ETH_MQ_RX_RSS)) { - PMD_DRV_LOG(ERR, "Cannot create ntuple flow on RSS queues\n"); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "Cannot create flow on RSS queues"); - rc = -rte_errno; - return rc; - } - filter->filter_type = use_ntuple ? HWRM_CFA_NTUPLE_FILTER : HWRM_CFA_EM_FILTER; en_ethertype = use_ntuple ? @@ -715,17 +707,6 @@ bnxt_flow_parse_attr(const struct rte_flow_attr *attr, "No support for priority."); return -rte_errno; } - - /* Not supported */ - if (attr->group) { - rte_flow_error_set(error, - EINVAL, - RTE_FLOW_ERROR_TYPE_ATTR_GROUP, - attr, - "No support for group."); - return -rte_errno; - } - return 0; } @@ -764,6 +745,50 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf, return filter1; } +static int bnxt_vnic_prep(struct bnxt *bp, struct bnxt_vnic_info *vnic) +{ + struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf; + uint64_t rx_offloads = dev_conf->rxmode.offloads; + int rc; + + rc = bnxt_vnic_grp_alloc(bp, vnic); + if (rc) + goto ret; + + rc = bnxt_hwrm_vnic_alloc(bp, vnic); + if (rc) { + PMD_DRV_LOG(ERR, "HWRM vnic alloc failure rc: %x\n", rc); + goto ret; + } + bp->nr_vnics++; + + /* RSS context is required only when there is more than one RSS ring */ + if (vnic->rx_queue_cnt > 1) { + rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, 0 /* ctx_idx 0 */); + if (rc) { + PMD_DRV_LOG(ERR, + "HWRM vnic ctx alloc failure: %x\n", rc); + goto ret; + } + } else { + PMD_DRV_LOG(DEBUG, "No RSS context required\n"); + } + + if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + vnic->vlan_strip = true; + else + vnic->vlan_strip = false; + + rc = bnxt_hwrm_vnic_cfg(bp, vnic); + if (rc) + goto ret; + + bnxt_hwrm_vnic_plcmode_cfg(bp, vnic); + +ret: + return rc; +} + static int bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, const struct rte_flow_item pattern[], @@ -775,12 +800,14 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, const struct rte_flow_action *act = bnxt_flow_non_void_action(actions); struct bnxt *bp = dev->data->dev_private; + struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf; 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; + struct bnxt_rx_queue *rxq = NULL; + int dflt_vnic, vnic_id; uint32_t vf = 0; - int dflt_vnic; int rc; rc = @@ -800,7 +827,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, case RTE_FLOW_ACTION_TYPE_QUEUE: /* Allow this flow. Redirect to a VNIC. */ act_q = (const struct rte_flow_action_queue *)act->conf; - if (act_q->index >= bp->rx_nr_rings) { + if (!act_q->index || act_q->index >= bp->rx_nr_rings) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, @@ -811,18 +838,77 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev, } PMD_DRV_LOG(DEBUG, "Queue index %d\n", act_q->index); - vnic0 = &bp->vnic_info[0]; - vnic = &bp->vnic_info[act_q->index]; + vnic_id = attr->group; + if (!vnic_id) { + PMD_DRV_LOG(DEBUG, "Group id is 0\n"); + vnic_id = act_q->index; + } + + vnic = &bp->vnic_info[vnic_id]; if (vnic == NULL) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, act, - "No matching VNIC for queue ID."); + "No matching VNIC found."); rc = -rte_errno; goto ret; } + if (vnic->rx_queue_cnt) { + if (vnic->start_grp_id != act_q->index) { + PMD_DRV_LOG(ERR, + "VNIC already in use\n"); + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "VNIC already in use"); + rc = -rte_errno; + goto ret; + } + goto use_vnic; + } + + rxq = bp->rx_queues[act_q->index]; + + if (!(dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) && rxq) + goto use_vnic; + + if (!rxq || + bp->vnic_info[0].fw_grp_ids[act_q->index] != + INVALID_HW_RING_ID || + !rxq->rx_deferred_start) { + PMD_DRV_LOG(ERR, + "Queue invalid or used with other VNIC\n"); + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "Queue invalid queue or in use"); + rc = -rte_errno; + goto ret; + } + +use_vnic: + rxq->vnic = vnic; + vnic->rx_queue_cnt++; + vnic->start_grp_id = act_q->index; + vnic->end_grp_id = act_q->index; + vnic->func_default = 0; //This is not a default VNIC. + + PMD_DRV_LOG(DEBUG, "VNIC found\n"); + + rc = bnxt_vnic_prep(bp, vnic); + if (rc) + goto ret; + + PMD_DRV_LOG(DEBUG, + "vnic[%d] = %p vnic->fw_grp_ids = %p\n", + act_q->index, vnic, vnic->fw_grp_ids); + vnic->ff_pool_idx = vnic_id; + PMD_DRV_LOG(DEBUG, + "Setting vnic ff_idx %d\n", vnic->ff_pool_idx); filter->dst_id = vnic->fw_vnic_id; filter1 = bnxt_get_l2_filter(bp, filter, vnic); if (filter1 == NULL) { @@ -989,9 +1075,12 @@ bnxt_match_filter(struct bnxt *bp, struct bnxt_filter_info *nf) struct rte_flow *flow; int i; - for (i = bp->nr_vnics - 1; i >= 0; i--) { + for (i = bp->max_vnics; i >= 0; i--) { struct bnxt_vnic_info *vnic = &bp->vnic_info[i]; + if (vnic->fw_vnic_id == INVALID_VNIC_ID) + continue; + STAILQ_FOREACH(flow, &vnic->flow_list, next) { mf = flow->filter; @@ -1063,8 +1152,8 @@ bnxt_flow_create(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct bnxt *bp = dev->data->dev_private; - struct bnxt_filter_info *filter; struct bnxt_vnic_info *vnic = NULL; + struct bnxt_filter_info *filter; bool update_flow = false; struct rte_flow *flow; unsigned int i; @@ -1168,12 +1257,35 @@ bnxt_flow_create(struct rte_eth_dev *dev, ret = bnxt_hwrm_set_ntuple_filter(bp, filter->dst_id, filter); } - for (i = 0; i < bp->nr_vnics; i++) { + for (i = 0; i < bp->max_vnics; i++) { vnic = &bp->vnic_info[i]; - if (filter->dst_id == vnic->fw_vnic_id) + if (vnic->fw_vnic_id != INVALID_VNIC_ID && + filter->dst_id == vnic->fw_vnic_id) { + PMD_DRV_LOG(ERR, "Found matching VNIC Id %d\n", + vnic->ff_pool_idx); break; + } } done: + if (!ret) { + flow->filter = filter; + flow->vnic = vnic; + /* VNIC is set only in case of queue or RSS action */ + if (vnic) { + /* + * RxQ0 is not used for flow filters. + */ + + if (update_flow) { + ret = -EXDEV; + goto free_flow; + } + STAILQ_INSERT_TAIL(&vnic->filter, filter, next); + } + PMD_DRV_LOG(ERR, "Successfully created flow.\n"); + STAILQ_INSERT_TAIL(&vnic->flow_list, flow, next); + return flow; + } if (!ret) { flow->filter = filter; flow->vnic = vnic; @@ -1196,7 +1308,7 @@ free_flow: rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Flow with pattern exists, updating destination queue"); - else + else if (!rte_errno) rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Failed to create flow."); diff --git a/drivers/net/bnxt/bnxt_vnic.h b/drivers/net/bnxt/bnxt_vnic.h index cb2707f36a..ec3a3ff51f 100644 --- a/drivers/net/bnxt/bnxt_vnic.h +++ b/drivers/net/bnxt/bnxt_vnic.h @@ -9,6 +9,8 @@ #include #include +#define INVALID_VNIC_ID ((uint16_t)-1) + struct bnxt_vnic_info { STAILQ_ENTRY(bnxt_vnic_info) next; uint8_t ff_pool_idx; -- 2.20.1