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 <psatheesh@marvell.com> Acked-by: Jerin Jacob <jerinj@marvell.com>
This commit is contained in:
parent
cc7f749488
commit
8ca851cdc5
@ -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.
|
||||
|
@ -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,34 +902,168 @@ 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)
|
||||
{
|
||||
bool vlan_id_found = false, ethtype_found = false, pcp_found = false;
|
||||
int count = 0;
|
||||
|
||||
*parsed_cnt = 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.
|
||||
*/
|
||||
|
||||
for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) {
|
||||
if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
|
||||
if (vlan_id_found)
|
||||
return 0;
|
||||
|
||||
const struct roc_npc_action_of_set_vlan_vid *vtag =
|
||||
(const struct roc_npc_action_of_set_vlan_vid *)
|
||||
actions->conf;
|
||||
|
||||
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_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_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;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow,
|
||||
struct npc_action_vtag_info *vlan_info)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
|
||||
|
||||
flow->vtag_insert_enabled = false;
|
||||
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 = 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;
|
||||
|
||||
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)++;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -923,77 +1079,94 @@ npc_vtag_action_program(struct roc_npc *roc_npc,
|
||||
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;
|
||||
} 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 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;
|
||||
}
|
||||
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 ==
|
||||
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) {
|
||||
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");
|
||||
if (vlan_insert_parsed) {
|
||||
plt_err("Incorrect VLAN insert actions");
|
||||
return -EINVAL;
|
||||
}
|
||||
flow->vtag_insert_enabled = true;
|
||||
|
||||
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) {
|
||||
vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
|
||||
rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user