From: Satheesh Paul Date: Fri, 21 Jan 2022 06:26:40 +0000 (+0530) Subject: common/cnxk: support matching VLAN existence X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=b8ac8b089cebd5d415641c4a5fb7f7a955c296b7;p=dpdk.git common/cnxk: support matching VLAN existence Support matching existence of VLAN after RTE_FLOW_ITEM_TYPE_ETH and RTE_FLOW_ITEM_TYPE_VLAN items. Signed-off-by: Satheesh Paul Reviewed-by: Kiran Kumar K --- diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index 8b57678863..6ab185e188 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -58,6 +58,60 @@ struct roc_npc_flow_item_raw { const uint8_t *pattern; /**< Byte string to look for. */ }; +struct roc_ether_addr { + uint8_t addr_bytes[PLT_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ +} plt_aligned(2); + +struct roc_ether_hdr { + struct roc_ether_addr d_addr; /**< Destination address. */ + PLT_STD_C11 + union { + struct roc_ether_addr s_addr; /**< Source address. */ + struct { + struct roc_ether_addr S_addr; + } S_un; /**< Do not use directly; use s_addr instead.*/ + }; + uint16_t ether_type; /**< Frame type. */ +} plt_aligned(2); + +PLT_STD_C11 +struct roc_npc_flow_item_eth { + union { + struct { + /* + * These fields are retained + * for compatibility. + * Please switch to the new header field below. + */ + struct roc_ether_addr dst; /**< Destination MAC. */ + struct roc_ether_addr src; /**< Source MAC. */ + uint16_t type; /**< EtherType or TPID. */ + }; + struct roc_ether_hdr hdr; + }; + uint32_t has_vlan : 1; /**< Packet header contains at least one VLAN. */ + uint32_t reserved : 31; /**< Reserved, must be zero. */ +}; + +struct roc_vlan_hdr { + uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ + uint16_t eth_proto; /**< Ethernet type of encapsulated frame. */ +} __plt_packed; + +PLT_STD_C11 +struct roc_npc_flow_item_vlan { + union { + struct { + uint16_t tci; /**< Tag control information. */ + uint16_t inner_type; /**< Inner EtherType or TPID. */ + }; + struct roc_vlan_hdr hdr; + }; + uint32_t has_more_vlan : 1; + /**< Packet header contains at least one more VLAN, after this VLAN. */ + uint32_t reserved : 31; /**< Reserved, must be zero. */ +}; + #define ROC_NPC_MAX_ACTION_COUNT 19 enum roc_npc_action_type { @@ -97,7 +151,7 @@ struct roc_npc_action_vf { }; struct roc_npc_action_port_id { - uint32_t original : 1; /**< Use original DPDK port ID if possible. */ + uint32_t original : 1; /**< Use original port ID if possible. */ uint32_t reserved : 31; /**< Reserved, must be zero. */ uint32_t id; /**< port ID. */ }; diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c index 7ed1fd3d6b..29bfc072c9 100644 --- a/drivers/common/cnxk/roc_npc_mcam.c +++ b/drivers/common/cnxk/roc_npc_mcam.c @@ -613,6 +613,28 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, return 0; } +static void +npc_set_vlan_ltype(struct npc_parse_state *pst) +{ + uint64_t val, mask; + uint8_t lb_offset; + + lb_offset = + __builtin_popcount(pst->npc->keyx_supp_nmask[pst->nix_intf] & + ((1ULL << NPC_LTYPE_LB_OFFSET) - 1)); + lb_offset *= 4; + + mask = ~((0xfULL << lb_offset)); + pst->flow->mcam_data[0] &= mask; + pst->flow->mcam_mask[0] &= mask; + /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011 + * Set LB layertype/mask as 0b0010/0b1110 to match both. + */ + val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset; + pst->flow->mcam_data[0] |= val; + pst->flow->mcam_mask[0] |= (0xeULL << lb_offset); +} + int npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) { @@ -651,12 +673,16 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) if (layer_info) { for (idx = 0; idx <= 2; idx++) { if (layer_info & (1 << idx)) { - if (idx == 2) + if (idx == 2) { data = lt; - else if (idx == 1) + mask = 0xf; + } else if (idx == 1) { data = ((flags >> 4) & 0xf); - else + mask = ((flags >> 4) & 0xf); + } else { data = (flags & 0xf); + mask = (flags & 0xf); + } if (data_off >= 64) { data_off = 0; @@ -664,7 +690,7 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) } key_data[index] |= ((uint64_t)data << data_off); - mask = 0xf; + if (lt == 0) mask = 0; key_mask[index] |= @@ -680,6 +706,9 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) memcpy(pst->flow->mcam_data, key_data, key_len); memcpy(pst->flow->mcam_mask, key_mask, key_len); + if (pst->set_vlan_ltype_mask) + npc_set_vlan_ltype(pst); + if (pst->is_vf) { (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox); rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp); diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c index c9ab9aef28..75724661da 100644 --- a/drivers/common/cnxk/roc_npc_parse.c +++ b/drivers/common/cnxk/roc_npc_parse.c @@ -167,6 +167,7 @@ npc_parse_higig2_hdr(struct npc_parse_state *pst) int npc_parse_la(struct npc_parse_state *pst) { + const struct roc_npc_flow_item_eth *eth_item; uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; struct npc_parse_item_info info; int lid, lt; @@ -176,6 +177,8 @@ npc_parse_la(struct npc_parse_state *pst) if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH) return 0; + eth_item = pst->pattern->spec; + lid = NPC_LID_LA; lt = NPC_LT_LA_ETHER; info.hw_hdr_len = 0; @@ -196,7 +199,7 @@ npc_parse_la(struct npc_parse_state *pst) /* Prepare for parsing the item */ info.hw_mask = &hw_mask; - info.len = pst->pattern->size; + info.len = sizeof(eth_item->hdr); npc_get_hw_supp_mask(pst, &info, lid, lt); info.spec = NULL; info.mask = NULL; @@ -206,13 +209,22 @@ npc_parse_la(struct npc_parse_state *pst) if (rc) return rc; - /* Update pst if not validate only? clash check? */ - return npc_update_parse_state(pst, &info, lid, lt, 0); + rc = npc_update_parse_state(pst, &info, lid, lt, 0); + if (rc) + return rc; + + if (eth_item && eth_item->has_vlan) + pst->set_vlan_ltype_mask = true; + + return 0; } +#define NPC_MAX_SUPPORTED_VLANS 3 + int npc_parse_lb(struct npc_parse_state *pst) { + const struct roc_npc_flow_item_vlan *vlan_item[NPC_MAX_SUPPORTED_VLANS]; const struct roc_npc_item_info *pattern = pst->pattern; const struct roc_npc_item_info *last_pattern; const struct roc_npc_flow_item_raw *raw_spec; @@ -240,10 +252,14 @@ npc_parse_lb(struct npc_parse_state *pst) * supported on first tag only. */ info.hw_mask = NULL; - info.len = pst->pattern->size; + info.len = sizeof(vlan_item[0]->hdr); pattern = pst->pattern; while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) { + if (nr_vlans > NPC_MAX_SUPPORTED_VLANS - 1) + return NPC_ERR_PATTERN_NOTSUP; + + vlan_item[nr_vlans] = pattern->spec; nr_vlans++; /* Basic validation of Second/Third vlan item */ @@ -260,12 +276,35 @@ npc_parse_lb(struct npc_parse_state *pst) switch (nr_vlans) { case 1: lt = NPC_LT_LB_CTAG; + if (vlan_item[0] && vlan_item[0]->has_more_vlan) + lt = NPC_LT_LB_STAG_QINQ; break; case 2: + if (vlan_item[1] && vlan_item[1]->has_more_vlan) { + if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] & + 0x3ULL << NPC_LFLAG_LB_OFFSET)) + return NPC_ERR_PATTERN_NOTSUP; + + /* This lflag value will match either one of + * NPC_F_LB_L_WITH_STAG_STAG, + * NPC_F_LB_L_WITH_QINQ_CTAG, + * NPC_F_LB_L_WITH_QINQ_QINQ and + * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For + * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG + * hence will not match. + */ + + lflags = NPC_F_LB_L_WITH_QINQ_CTAG & + NPC_F_LB_L_WITH_QINQ_QINQ & + NPC_F_LB_L_WITH_STAG_STAG; + } else { + lflags = NPC_F_LB_L_WITH_CTAG; + } lt = NPC_LT_LB_STAG_QINQ; - lflags = NPC_F_STAG_CTAG; break; case 3: + if (vlan_item[2] && vlan_item[2]->has_more_vlan) + return NPC_ERR_PATTERN_NOTSUP; lt = NPC_LT_LB_STAG_QINQ; lflags = NPC_F_STAG_STAG_CTAG; break; @@ -294,10 +333,15 @@ npc_parse_lb(struct npc_parse_state *pst) } info.len = pattern->size; } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) { + vlan_item[0] = pst->pattern->spec; info.hw_mask = NULL; - info.len = pst->pattern->size; + info.len = sizeof(vlan_item[0]->hdr); lt = NPC_LT_LB_STAG_QINQ; lflags = NPC_F_STAG_CTAG; + if (vlan_item[0] && vlan_item[0]->has_more_vlan) { + lflags = NPC_F_LB_L_WITH_QINQ_CTAG & + NPC_F_LB_L_WITH_QINQ_QINQ; + } } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) { raw_spec = pst->pattern->spec; if (raw_spec->relative) diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 59e6c307cd..12320f0ced 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -67,6 +67,11 @@ #define NPC_ACTION_MAX_VLAN_PARAMS 3 #define NPC_ACTION_MAX_VLANS_STRIPPED 2 +#define NPC_LTYPE_OFFSET_START 7 +/* LB OFFSET : START + LA (2b flags + 1b ltype) + LB (2b flags) */ +#define NPC_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 5) +#define NPC_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3) + struct npc_action_vtag_info { uint16_t vlan_id; uint16_t vlan_ethtype; @@ -176,6 +181,8 @@ struct npc_parse_state { uint8_t *mcam_data; /* point to flow->mcam_data + key_len */ uint8_t *mcam_mask; /* point to flow->mcam_mask + key_len */ bool is_vf; + /* adjust ltype in MCAM to match at least one vlan */ + bool set_vlan_ltype_mask; }; enum npc_kpu_parser_flag { diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h index b055dd349e..63be311f4d 100644 --- a/drivers/common/cnxk/roc_platform.h +++ b/drivers/common/cnxk/roc_platform.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,9 @@ #define PLT_ALIGN_CEIL RTE_ALIGN_CEIL #define PLT_INIT RTE_INIT +#ifndef PLT_ETHER_ADDR_LEN +#define PLT_ETHER_ADDR_LEN RTE_ETHER_ADDR_LEN +#endif /** Divide ceil */ #define PLT_DIV_CEIL(x, y) \ ({ \ @@ -83,6 +87,7 @@ #define plt_cpu_to_be_64 rte_cpu_to_be_64 #define plt_be_to_cpu_64 rte_be_to_cpu_64 +#define plt_aligned __rte_aligned #define plt_align32pow2 rte_align32pow2 #define plt_align32prevpow2 rte_align32prevpow2