From: Satheesh Paul Date: Wed, 23 Jun 2021 04:46:08 +0000 (+0530) Subject: common/cnxk: support VLAN push/pop flow actions X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=19f3cc2374d0e5d2cb35bede4198911a8401c901;p=dpdk.git common/cnxk: support VLAN push/pop flow actions Add roc API to configure VLAN tag addition and removal. This patch also adds 98xx support for increased MCAM entries for rte flow. Signed-off-by: Satheesh Paul Reviewed-by: Kiran Kumar K --- diff --git a/drivers/common/cnxk/roc_model.h b/drivers/common/cnxk/roc_model.h index 5aaad53f99..c1d11b77c6 100644 --- a/drivers/common/cnxk/roc_model.h +++ b/drivers/common/cnxk/roc_model.h @@ -87,6 +87,12 @@ roc_model_is_cn10k(void) return roc_model_runtime_is_cn10k(); } +static inline uint64_t +roc_model_is_cn98xx(void) +{ + return (roc_model->flag & ROC_MODEL_CN98xx_A0); +} + static inline uint64_t roc_model_is_cn96_a0(void) { diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index e6a5036483..8a76823698 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -5,6 +5,23 @@ #include "roc_api.h" #include "roc_priv.h" +int +roc_npc_vtag_actions_get(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc->vtag_actions; +} + +int +roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + npc->vtag_actions -= count; + return npc->vtag_actions; +} + int roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) { @@ -101,7 +118,7 @@ npc_mcam_tot_entries(void) /* FIXME: change to reading in AF from NPC_AF_CONST1/2 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS */ - if (roc_model_is_cn10k()) + if (roc_model_is_cn10k() || roc_model_is_cn98xx()) return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ else return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ @@ -330,6 +347,7 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, const struct roc_npc_action_mark *act_mark; const struct roc_npc_action_queue *act_q; const struct roc_npc_action_vf *vf_act; + bool vlan_insert_action = false; int sel_act, req_act = 0; uint16_t pf_func, vf_id; int errcode = 0; @@ -417,25 +435,69 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, req_act |= ROC_NPC_ACTION_TYPE_SEC; rq = 0; break; + case ROC_NPC_ACTION_TYPE_VLAN_STRIP: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP; + break; + case ROC_NPC_ACTION_TYPE_VLAN_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT; + break; + case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT; + break; + case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT; + break; default: errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; } } + if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) + vlan_insert_action = true; + + if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + plt_err("PCP insert action can't be supported alone"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + /* Both STRIP and INSERT actions are not supported */ + if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + /* Check if actions specified are compatible */ if (attr->egress) { - /* Only DROP/COUNT is supported */ - if (!(req_act & ROC_NPC_ACTION_TYPE_DROP)) { + if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + plt_err("VLAN pop action is not supported on Egress"); errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; - } else if (req_act & ~(ROC_NPC_ACTION_TYPE_DROP | - ROC_NPC_ACTION_TYPE_COUNT)) { + } + + if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + flow->npc_action = NIX_TX_ACTIONOP_DROP; + } else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) || + vlan_insert_action) { + flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT; + } else { + plt_err("Unsupported action for egress"); errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; } - flow->npc_action = NIX_TX_ACTIONOP_DROP; + goto set_pf_func; + } else { + if (vlan_insert_action) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } } /* We have already verified the attr, this is ingress. @@ -463,6 +525,13 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, goto err_exit; } + if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) + npc->vtag_actions++; + + /* Only VLAN action is provided */ + if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + /* Set NIX_RX_ACTIONOP */ if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { flow->npc_action = NIX_RX_ACTIONOP_UCAST; @@ -774,6 +843,161 @@ roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) return npc->mark_actions; } +static int +npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct roc_nix *roc_nix = roc_npc->roc_nix; + struct nix_vtag_config *vtag_cfg; + struct nix_vtag_config_rsp *rsp; + struct mbox *mbox; + struct nix *nix; + int rc = 0; + + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; + + nix = roc_nix_to_nix_priv(roc_nix); + mbox = (&nix->dev)->mbox; + + tx_vtag_action.reg = flow->vtag_action; + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_TX; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def; + vtag_cfg->tx.free_vtag0 = true; + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return rc; + + return 0; +} + +static int +npc_vtag_action_program(struct roc_npc *roc_npc, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + uint16_t vlan_id = 0, vlan_ethtype = ROC_ETHER_TYPE_VLAN; + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct roc_nix *roc_nix = roc_npc->roc_nix; + struct nix_vtag_config *vtag_cfg; + struct nix_vtag_config_rsp *rsp; + uint64_t rx_vtag_action = 0; + uint8_t vlan_pcp = 0; + struct mbox *mbox; + struct nix *nix; + int rc; + + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; + + nix = roc_nix_to_nix_priv(roc_nix); + mbox = (&nix->dev)->mbox; + + flow->vtag_insert_enabled = false; + + for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + if (npc->vtag_actions == 1) { + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_RX; + vtag_cfg->rx.strip_vtag = 1; + /* Always capture */ + vtag_cfg->rx.capture_vtag = 1; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->rx.vtag_type = 0; + + rc = mbox_process(mbox); + if (rc) + return rc; + } + + rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15); + rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8); + rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR; + flow->vtag_action = rx_vtag_action; + } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { + const struct roc_npc_action_of_set_vlan_vid *vtag = + (const struct roc_npc_action_of_set_vlan_vid *) + actions->conf; + vlan_id = plt_be_to_cpu_16(vtag->vlan_vid); + if (vlan_id > 0xfff) { + plt_err("Invalid vlan_id for set vlan action"); + return -EINVAL; + } + flow->vtag_insert_enabled = true; + } else if (actions->type == + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) { + const struct roc_npc_action_of_push_vlan *ethtype = + (const struct roc_npc_action_of_push_vlan *) + actions->conf; + vlan_ethtype = plt_be_to_cpu_16(ethtype->ethertype); + if (vlan_ethtype != ROC_ETHER_TYPE_VLAN && + vlan_ethtype != ROC_ETHER_TYPE_QINQ) { + plt_err("Invalid ethtype specified for push" + " vlan action"); + return -EINVAL; + } + flow->vtag_insert_enabled = true; + } else if (actions->type == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + const struct roc_npc_action_of_set_vlan_pcp *pcp = + (const struct roc_npc_action_of_set_vlan_pcp *) + actions->conf; + vlan_pcp = pcp->vlan_pcp; + if (vlan_pcp > 0x7) { + plt_err("Invalid PCP value for pcp action"); + return -EINVAL; + } + flow->vtag_insert_enabled = true; + } + } + + if (flow->vtag_insert_enabled) { + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_TX; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->tx.vtag0 = + ((vlan_ethtype << 16) | (vlan_pcp << 13) | vlan_id); + + vtag_cfg->tx.cfg_vtag0 = 1; + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return rc; + + if (rsp->vtag0_idx < 0) { + plt_err("Failed to config TX VTAG action"); + return -EINVAL; + } + + tx_vtag_action.reg = 0; + tx_vtag_action.act.vtag0_def = rsp->vtag0_idx; + tx_vtag_action.act.vtag0_lid = NPC_LID_LA; + tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT; + tx_vtag_action.act.vtag0_relptr = + NIX_TX_VTAGACTION_VTAG0_RELPTR; + flow->vtag_action = tx_vtag_action.reg; + } + return 0; +} + struct roc_npc_flow * roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, const struct roc_npc_item_info pattern[], @@ -798,6 +1022,12 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, goto err_exit; } + rc = npc_vtag_action_program(roc_npc, actions, flow); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); rc = npc_program_mcam(npc, &parse_state, 1); @@ -858,23 +1088,20 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) { struct npc *npc = roc_npc_to_npc_priv(roc_npc); struct plt_bitmap *bmap; - uint16_t match_id; int rc; - match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & - NPC_RX_ACT_MATCH_MASK; - - if (match_id && match_id < NPC_ACTION_FLAG_DEFAULT) { - if (npc->mark_actions == 0) - return NPC_ERR_PARAM; - } - rc = npc_rss_group_free(npc, flow); if (rc != 0) { plt_err("Failed to free rss action rc = %d", rc); return rc; } + if (flow->vtag_insert_enabled) { + rc = npc_vtag_cfg_delete(roc_npc, flow); + if (rc != 0) + return rc; + } + rc = npc_mcam_free_entry(npc, flow->mcam_id); if (rc != 0) return rc; diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index cf6f7320fa..2c0a536c93 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -62,6 +62,10 @@ enum roc_npc_action_type { ROC_NPC_ACTION_TYPE_COUNT = (1 << 9), ROC_NPC_ACTION_TYPE_PF = (1 << 10), ROC_NPC_ACTION_TYPE_VF = (1 << 11), + ROC_NPC_ACTION_TYPE_VLAN_STRIP = (1 << 12), + ROC_NPC_ACTION_TYPE_VLAN_INSERT = (1 << 13), + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT = (1 << 14), + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT = (1 << 15), }; struct roc_npc_action { @@ -83,6 +87,18 @@ struct roc_npc_action_queue { uint16_t index; /**< Queue index to use. */ }; +struct roc_npc_action_of_push_vlan { + uint16_t ethertype; /**< EtherType. */ +}; + +struct roc_npc_action_of_set_vlan_vid { + uint16_t vlan_vid; /**< VLAN id. */ +}; + +struct roc_npc_action_of_set_vlan_pcp { + uint8_t vlan_pcp; /**< VLAN priority. */ +}; + struct roc_npc_attr { uint32_t priority; /**< Rule priority level within group. */ uint32_t ingress : 1; /**< Rule applies to ingress traffic. */ @@ -107,6 +123,7 @@ struct roc_npc_flow { uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS]; uint64_t npc_action; uint64_t vtag_action; + bool vtag_insert_enabled; #define ROC_NPC_MAX_FLOW_PATTERNS 32 struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS]; uint16_t num_patterns; @@ -138,6 +155,10 @@ enum roc_npc_intf { ROC_NPC_INTF_MAX = 2, }; +enum flow_vtag_cfg_dir { VTAG_TX, VTAG_RX }; +#define ROC_ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ +#define ROC_ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ + struct roc_npc { struct roc_nix *roc_nix; uint8_t switch_header_type; @@ -199,4 +220,7 @@ void __roc_api roc_npc_flow_mcam_dump(FILE *file, struct roc_npc *roc_npc, int __roc_api roc_npc_mark_actions_get(struct roc_npc *roc_npc); int __roc_api roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count); +int __roc_api roc_npc_vtag_actions_get(struct roc_npc *roc_npc); +int __roc_api roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, + uint32_t count); #endif /* _ROC_NPC_H_ */ diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c index ff0676d605..8ccaaad0af 100644 --- a/drivers/common/cnxk/roc_npc_mcam.c +++ b/drivers/common/cnxk/roc_npc_mcam.c @@ -546,7 +546,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, * * Second approach is used now. */ - req->entry_data.vtag_action = 0ULL; + req->entry_data.vtag_action = flow->vtag_action; for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) { req->entry_data.kw[idx] = flow->mcam_data[idx]; diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 961583b79b..484c3aeb1f 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -350,6 +350,7 @@ struct npc { uint16_t flow_max_priority; /* Max priority for flow */ uint16_t switch_header_type; /* Suppprted switch header type */ uint32_t mark_actions; /* Number of mark actions */ + uint32_t vtag_actions; /* vtag insert/strip actions */ uint16_t pf_func; /* pf_func of device */ npc_dxcfg_t prx_dxcfg; /* intf, lid, lt, extract */ npc_fxcfg_t prx_fxcfg; /* Flag extract */ diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index a99ec2f9d7..4da0cc82b7 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -189,6 +189,8 @@ INTERNAL { roc_npc_init; roc_npc_mark_actions_get; roc_npc_mark_actions_sub_return; + roc_npc_vtag_actions_get; + roc_npc_vtag_actions_sub_return; roc_npc_mcam_alloc_entries; roc_npc_mcam_alloc_entry; roc_npc_mcam_clear_counter;