From: Satheesh Paul Date: Mon, 19 Jul 2021 05:41:57 +0000 (+0530) Subject: common/cnxk: support dual VLAN insert and strip actions X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=8ca851cdc59835c2191e3d369a36313d78c0e8c4;hp=cc7f74948817d11b0fd5bdc1b82a936daf23282f;p=dpdk.git common/cnxk: support dual VLAN insert and strip actions Add ROC API to configure dual VLAN tag addition and removal. Signed-off-by: Satheesh Paul Acked-by: Jerin Jacob --- diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index 1d56fa9bf2..68b6405ae0 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -62,6 +62,10 @@ New Features * Added bus-level parsing of the devargs syntax. * Kept compatibility with the legacy syntax as parsing fallback. +* **Updated Marvell cnxk ethdev driver.** + + * Added rte_flow support for dual VLAN insert and strip actions. + * **Updated Marvell cnxk crypto PMD.** * Added AES-CBC SHA1-HMAC support in lookaside protocol (IPsec) for CN10K. diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index aff4eef554..52a54b3990 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -10,7 +10,7 @@ roc_npc_vtag_actions_get(struct roc_npc *roc_npc) { struct npc *npc = roc_npc_to_npc_priv(roc_npc); - return npc->vtag_actions; + return npc->vtag_strip_actions; } int @@ -18,8 +18,8 @@ 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; + npc->vtag_strip_actions -= count; + return npc->vtag_strip_actions; } int @@ -481,6 +481,23 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, 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 | + ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) { + plt_err("Only VLAN insert, drop, count supported on Egress"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (vlan_insert_action && + (req_act & ROC_NPC_ACTION_TYPE_DROP)) { + plt_err("Both VLAN insert and drop actions cannot be supported"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + if (req_act & ROC_NPC_ACTION_TYPE_DROP) { flow->npc_action = NIX_TX_ACTIONOP_DROP; } else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) || @@ -526,14 +543,14 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, } 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; + npc->vtag_strip_actions++; /* Set NIX_RX_ACTIONOP */ - if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { + if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + /* Only VLAN action is provided */ + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else if (req_act & + (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { flow->npc_action = NIX_RX_ACTIONOP_UCAST; if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) flow->npc_action |= (uint64_t)rq << 20; @@ -872,6 +889,11 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def; vtag_cfg->tx.free_vtag0 = true; + if (flow->vtag_insert_count == 2) { + vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def; + vtag_cfg->tx.free_vtag1 = true; + } + rc = mbox_process_msg(mbox, (void *)&rsp); if (rc) return rc; @@ -880,120 +902,271 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) } static int -npc_vtag_action_program(struct roc_npc *roc_npc, - const struct roc_npc_action actions[], - struct roc_npc_flow *flow) +npc_vtag_insert_action_parse(const struct roc_npc_action actions[], + struct roc_npc_flow *flow, + struct npc_action_vtag_info *vlan_info, + int *parsed_cnt) { - 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); + bool vlan_id_found = false, ethtype_found = false, pcp_found = false; + int count = 0; - if (vtag_cfg == NULL) - return -ENOSPC; + *parsed_cnt = 0; - 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; + /* This function parses parameters of one VLAN. When a parameter is + * found repeated, it treats it as the end of first VLAN's parameters + * and returns. The caller calls again to parse the parameters of the + * second VLAN. + */ - rc = mbox_process(mbox); - if (rc) - return rc; - } + for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { + if (vlan_id_found) + return 0; - 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) { + + vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid); + + if (vlan_info->vlan_id > 0xfff) { plt_err("Invalid vlan_id for set vlan action"); return -EINVAL; } + flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + vlan_id_found = true; } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) { + if (ethtype_found) + return 0; + 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) { + vlan_info->vlan_ethtype = + plt_be_to_cpu_16(ethtype->ethertype); + if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN && + vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) { plt_err("Invalid ethtype specified for push" " vlan action"); return -EINVAL; } flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + ethtype_found = true; } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + if (pcp_found) + return 0; 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) { + vlan_info->vlan_pcp = pcp->vlan_pcp; + if (vlan_info->vlan_pcp > 0x7) { plt_err("Invalid PCP value for pcp action"); return -EINVAL; } flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + pcp_found = true; + } else { + return 0; } } - if (flow->vtag_insert_enabled) { - vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + return 0; +} - if (vtag_cfg == NULL) - return -ENOSPC; +static int +npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow, + struct npc_action_vtag_info *vlan_info) +{ + struct nix_vtag_config *vtag_cfg; + struct nix_vtag_config_rsp *rsp; + int rc = 0; - 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); + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; - vtag_cfg->tx.cfg_vtag0 = 1; - rc = mbox_process_msg(mbox, (void *)&rsp); - if (rc) - return rc; + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); - if (rsp->vtag0_idx < 0) { - plt_err("Failed to config TX VTAG action"); - return -EINVAL; - } + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_TX; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->tx.vtag0 = + ((vlan_info[0].vlan_ethtype << 16) | + (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id); + + vtag_cfg->tx.cfg_vtag0 = 1; + + if (flow->vtag_insert_count == 2) { + vtag_cfg->tx.vtag1 = + ((vlan_info[1].vlan_ethtype << 16) | + (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id); + + vtag_cfg->tx.cfg_vtag1 = 1; + } + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return rc; + + if (rsp->vtag0_idx < 0 || + ((flow->vtag_insert_count == 2) && (rsp->vtag1_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 = + 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; + + if (flow->vtag_insert_count == 2) { + tx_vtag_action.act.vtag1_def = rsp->vtag1_idx; + tx_vtag_action.act.vtag1_lid = NPC_LID_LA; + tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT; + /* NIX_TX_VTAG_ACTION_S + * If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte + * offset accordingly. Thus, if the two offsets are equal in + * the structure, hardware inserts Vtag 1 immediately after + * Vtag 0 in the packet. + */ + tx_vtag_action.act.vtag1_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR; - flow->vtag_action = tx_vtag_action.reg; + } + + flow->vtag_action = tx_vtag_action.reg; + + return 0; +} + +static int +npc_vtag_strip_action_configure(struct mbox *mbox, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow, int *strip_cnt) +{ + struct nix_vtag_config *vtag_cfg; + uint64_t rx_vtag_action = 0; + int count = 0, rc = 0; + + *strip_cnt = 0; + + for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) + (*strip_cnt)++; + } + + 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; + + if (*strip_cnt == 2) { + rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47); + rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40); + rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32; + } + flow->vtag_action = rx_vtag_action; + + return 0; +} + +static int +npc_vtag_action_program(struct roc_npc *roc_npc, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + bool vlan_strip_parsed = false, vlan_insert_parsed = false; + const struct roc_npc_action *insert_actions; + struct roc_nix *roc_nix = roc_npc->roc_nix; + struct npc_action_vtag_info vlan_info[2]; + int parsed_cnt = 0, strip_cnt = 0; + int tot_vlan_params = 0; + struct mbox *mbox; + struct nix *nix; + int i, rc; + + nix = roc_nix_to_nix_priv(roc_nix); + mbox = (&nix->dev)->mbox; + + memset(vlan_info, 0, sizeof(vlan_info)); + + flow->vtag_insert_enabled = false; + + for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + if (vlan_strip_parsed) { + plt_err("Incorrect VLAN strip actions"); + return -EINVAL; + } + rc = npc_vtag_strip_action_configure(mbox, actions, + flow, &strip_cnt); + if (rc) + return rc; + + if (strip_cnt == 2) + actions++; + + vlan_strip_parsed = true; + } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT || + actions->type == + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT || + actions->type == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + if (vlan_insert_parsed) { + plt_err("Incorrect VLAN insert actions"); + return -EINVAL; + } + + insert_actions = actions; + + for (i = 0; i < 2; i++) { + rc = npc_vtag_insert_action_parse( + insert_actions, flow, &vlan_info[i], + &parsed_cnt); + + if (rc) + return rc; + + if (parsed_cnt) { + insert_actions += parsed_cnt; + tot_vlan_params += parsed_cnt; + flow->vtag_insert_count++; + } + } + actions += tot_vlan_params - 1; + vlan_insert_parsed = true; + } + } + + if (flow->vtag_insert_enabled) { + rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info); + + if (rc) + return rc; } return 0; } diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index bab25fd72e..4d6f8f8cd9 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -135,6 +135,7 @@ struct roc_npc_flow { uint64_t npc_action; uint64_t vtag_action; bool vtag_insert_enabled; + uint8_t vtag_insert_count; #define ROC_NPC_MAX_FLOW_PATTERNS 32 struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS]; uint16_t num_patterns; diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 5b884e3fd4..b11f5b5027 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -58,6 +58,15 @@ (NPC_NIXLF_MAX * NPC_MCAME_PER_LF + \ (NPC_RVUPF_MAX_10XX - 1) * NPC_MCAME_PER_PF) +#define NPC_ACTION_MAX_VLAN_PARAMS 3 +#define NPC_ACTION_MAX_VLANS_STRIPPED 2 + +struct npc_action_vtag_info { + uint16_t vlan_id; + uint16_t vlan_ethtype; + uint8_t vlan_pcp; +}; + enum npc_err_status { NPC_ERR_PARAM = -1024, NPC_ERR_NO_MEM, @@ -351,7 +360,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 */ + uint32_t vtag_strip_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 */