]> git.droids-corp.org - dpdk.git/commitdiff
common/cnxk: support matching VLAN existence
authorSatheesh Paul <psatheesh@marvell.com>
Fri, 21 Jan 2022 06:26:40 +0000 (11:56 +0530)
committerJerin Jacob <jerinj@marvell.com>
Sat, 22 Jan 2022 14:06:56 +0000 (15:06 +0100)
Support matching existence of VLAN after
RTE_FLOW_ITEM_TYPE_ETH and RTE_FLOW_ITEM_TYPE_VLAN items.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
drivers/common/cnxk/roc_npc.h
drivers/common/cnxk/roc_npc_mcam.c
drivers/common/cnxk/roc_npc_parse.c
drivers/common/cnxk/roc_npc_priv.h
drivers/common/cnxk/roc_platform.h

index 8b576788632875c5dff6cbc4681e1af8b54025aa..6ab185e1880e7ff0014f2bd92c848166c91b6223 100644 (file)
@@ -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. */
 };
index 7ed1fd3d6bf0101014a0db7df8375dacf541a9ce..29bfc072c9b79f555007923529ab938a53cf9d03 100644 (file)
@@ -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);
index c9ab9aef289a574fcbbfe2b18202861ceb66ee4b..75724661da39541234ac69aa4d3dca8d7a331c24 100644 (file)
@@ -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)
index 59e6c307cd458af4a25c58715f53f566b2a90241..12320f0cedca5bfd7376a598317b19ec61fc0eb5 100644 (file)
 #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 {
index b055dd349e0507c46e7e94b28b9d9ac8248dc5a3..63be311f4db2c4ad05ca345e004a1f396e03ad54 100644 (file)
@@ -11,6 +11,7 @@
 #include <rte_byteorder.h>
 #include <rte_common.h>
 #include <rte_cycles.h>
+#include <rte_ether.h>
 #include <rte_interrupts.h>
 #include <rte_io.h>
 #include <rte_log.h>
@@ -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