From 612ce5cf7d98929d6ba36de8ad6f7da7cc03e746 Mon Sep 17 00:00:00 2001 From: Satheesh Paul Date: Mon, 12 Jul 2021 12:19:00 +0530 Subject: [PATCH] common/cnxk: support custom L2/L3 protocols parsing Add roc API for parsing custom L2 and L3 protocols. Signed-off-by: Satheesh Paul Reviewed-by: Kiran Kumar K --- drivers/common/cnxk/roc_mbox.h | 24 ++++++-- drivers/common/cnxk/roc_nix_ops.c | 14 +++++ drivers/common/cnxk/roc_npc.h | 11 ++++ drivers/common/cnxk/roc_npc_parse.c | 86 +++++++++++++++++++++++++++-- drivers/common/cnxk/roc_npc_priv.h | 9 +-- drivers/common/cnxk/roc_npc_utils.c | 6 +- drivers/common/cnxk/roc_utils.c | 2 +- 7 files changed, 136 insertions(+), 16 deletions(-) diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h index ea1138208d..b5da931b81 100644 --- a/drivers/common/cnxk/roc_mbox.h +++ b/drivers/common/cnxk/roc_mbox.h @@ -278,14 +278,28 @@ struct ready_msg_rsp { uint16_t __io rclk_freq; /* RCLK frequency */ }; +enum npc_pkind_type { + NPC_RX_VLAN_EXDSA_PKIND = 56ULL, + NPC_RX_CHLEN24B_PKIND, + NPC_RX_CPT_HDR_PKIND, + NPC_RX_CHLEN90B_PKIND, + NPC_TX_HIGIG_PKIND, + NPC_RX_HIGIG_PKIND, + NPC_RX_EXDSA_PKIND, + NPC_RX_EDSA_PKIND, + NPC_TX_DEF_PKIND, +}; + /* Struct to set pkind */ struct npc_set_pkind { struct mbox_msghdr hdr; -#define ROC_PRIV_FLAGS_DEFAULT BIT_ULL(0) -#define ROC_PRIV_FLAGS_EDSA BIT_ULL(1) -#define ROC_PRIV_FLAGS_HIGIG BIT_ULL(2) -#define ROC_PRIV_FLAGS_LEN_90B BIT_ULL(3) -#define ROC_PRIV_FLAGS_CUSTOM BIT_ULL(63) +#define ROC_PRIV_FLAGS_DEFAULT BIT_ULL(0) +#define ROC_PRIV_FLAGS_EDSA BIT_ULL(1) +#define ROC_PRIV_FLAGS_HIGIG BIT_ULL(2) +#define ROC_PRIV_FLAGS_LEN_90B BIT_ULL(3) +#define ROC_PRIV_FLAGS_EXDSA BIT_ULL(4) +#define ROC_PRIV_FLAGS_VLAN_EXDSA BIT_ULL(5) +#define ROC_PRIV_FLAGS_CUSTOM BIT_ULL(63) uint64_t __io mode; #define PKIND_TX BIT_ULL(0) #define PKIND_RX BIT_ULL(1) diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c index eeb85a54f9..0e28302e74 100644 --- a/drivers/common/cnxk/roc_nix_ops.c +++ b/drivers/common/cnxk/roc_nix_ops.c @@ -378,6 +378,8 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type) switch_header_type != ROC_PRIV_FLAGS_EDSA && switch_header_type != ROC_PRIV_FLAGS_HIGIG && switch_header_type != ROC_PRIV_FLAGS_LEN_90B && + switch_header_type != ROC_PRIV_FLAGS_EXDSA && + switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA && switch_header_type != ROC_PRIV_FLAGS_CUSTOM) { plt_err("switch header type is not supported"); return NIX_ERR_PARAM; @@ -399,6 +401,18 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type) if (req == NULL) return rc; req->mode = switch_header_type; + + if (switch_header_type == ROC_PRIV_FLAGS_LEN_90B) { + req->mode = ROC_PRIV_FLAGS_CUSTOM; + req->pkind = NPC_RX_CHLEN90B_PKIND; + } else if (switch_header_type == ROC_PRIV_FLAGS_EXDSA) { + req->mode = ROC_PRIV_FLAGS_CUSTOM; + req->pkind = NPC_RX_EXDSA_PKIND; + } else if (switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) { + req->mode = ROC_PRIV_FLAGS_CUSTOM; + req->pkind = NPC_RX_VLAN_EXDSA_PKIND; + } + req->dir = PKIND_RX; rc = mbox_process_msg(mbox, (void *)&rsp); if (rc) diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index 2c0a536c93..bab25fd72e 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -36,6 +36,7 @@ enum roc_npc_item_type { ROC_NPC_ITEM_TYPE_CPT_HDR, ROC_NPC_ITEM_TYPE_L3_CUSTOM, ROC_NPC_ITEM_TYPE_QINQ, + ROC_NPC_ITEM_TYPE_RAW, ROC_NPC_ITEM_TYPE_END, }; @@ -47,6 +48,16 @@ struct roc_npc_item_info { const void *last; /* For range */ }; +struct roc_npc_flow_item_raw { + uint32_t relative : 1; /**< Look for pattern after the previous item. */ + uint32_t search : 1; /**< Search pattern from offset. */ + uint32_t reserved : 30; /**< Reserved, must be set to zero. */ + int32_t offset; /**< Absolute or relative offset for pattern. */ + uint16_t limit; /**< Search area limit for start of pattern. */ + uint16_t length; /**< Pattern length. */ + const uint8_t *pattern; /**< Byte string to look for. */ +}; + #define ROC_NPC_MAX_ACTION_COUNT 12 enum roc_npc_action_type { diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c index d07f91db3f..8125035dd8 100644 --- a/drivers/common/cnxk/roc_npc_parse.c +++ b/drivers/common/cnxk/roc_npc_parse.c @@ -136,14 +136,46 @@ npc_parse_la(struct npc_parse_state *pst) return npc_update_parse_state(pst, &info, lid, lt, 0); } +static int +npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec, + const struct roc_npc_flow_item_raw *raw_mask, + struct npc_parse_item_info *info, uint8_t *spec_buf, + uint8_t *mask_buf) +{ + uint32_t custom_hdr_size = 0; + + memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN); + memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN); + custom_hdr_size = raw_spec->offset + raw_spec->length; + + memcpy(spec_buf + raw_spec->offset, raw_spec->pattern, + raw_spec->length); + + if (raw_mask->pattern) { + memcpy(mask_buf + raw_spec->offset, raw_mask->pattern, + raw_spec->length); + } else { + memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length); + } + + info->len = custom_hdr_size; + info->spec = spec_buf; + info->mask = mask_buf; + + return 0; +} + int npc_parse_lb(struct npc_parse_state *pst) { 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; + uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN]; + uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN]; char hw_mask[NPC_MAX_EXTRACT_HW_LEN]; struct npc_parse_item_info info; - int lid, lt, lflags; + int lid, lt, lflags, len = 0; int nr_vlans = 0; int rc; @@ -221,13 +253,35 @@ npc_parse_lb(struct npc_parse_state *pst) info.len = pst->pattern->size; lt = NPC_LT_LB_STAG_QINQ; lflags = NPC_F_STAG_CTAG; + } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) { + raw_spec = pst->pattern->spec; + if (raw_spec->relative) + return 0; + len = raw_spec->length + raw_spec->offset; + if (len > NPC_MAX_RAW_ITEM_LEN) + return -EINVAL; + + if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) { + lt = NPC_LT_LB_VLAN_EXDSA; + } else if (pst->npc->switch_header_type == + ROC_PRIV_FLAGS_EXDSA) { + lt = NPC_LT_LB_EXDSA; + } else { + return -EINVAL; + } + + npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *) + pst->pattern->spec, + (const struct roc_npc_flow_item_raw *) + pst->pattern->mask, + &info, raw_spec_buf, raw_mask_buf); + + info.hw_hdr_len = 0; } else { return 0; } info.hw_mask = &hw_mask; - info.spec = NULL; - info.mask = NULL; npc_get_hw_supp_mask(pst, &info, lid, lt); rc = npc_parse_item_basic(pst->pattern, &info); @@ -340,9 +394,12 @@ npc_check_lc_ip_tunnel(struct npc_parse_state *pst) int npc_parse_lc(struct npc_parse_state *pst) { + const struct roc_npc_flow_item_raw *raw_spec; + uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN]; + uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN]; uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; struct npc_parse_item_info info; - int lid, lt; + int lid, lt, len = 0; int rc; if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS) @@ -378,6 +435,26 @@ npc_parse_lc(struct npc_parse_state *pst) lt = NPC_LT_LC_CUSTOM0; info.len = pst->pattern->size; break; + case ROC_NPC_ITEM_TYPE_RAW: + raw_spec = pst->pattern->spec; + if (!raw_spec->relative) + return 0; + + len = raw_spec->length + raw_spec->offset; + if (len > NPC_MAX_RAW_ITEM_LEN) + return -EINVAL; + + npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *) + pst->pattern->spec, + (const struct roc_npc_flow_item_raw *) + pst->pattern->mask, + &info, raw_spec_buf, raw_mask_buf); + + lid = NPC_LID_LC; + lt = NPC_LT_LC_NGIO; + info.hw_mask = &hw_mask; + npc_get_hw_supp_mask(pst, &info, lid, lt); + break; default: /* No match at this layer */ return 0; @@ -388,6 +465,7 @@ npc_parse_lc(struct npc_parse_state *pst) npc_get_hw_supp_mask(pst, &info, lid, lt); rc = npc_parse_item_basic(pst->pattern, &info); + if (rc != 0) return rc; diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 484c3aeb1f..5b884e3fd4 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -5,10 +5,11 @@ #ifndef _ROC_NPC_PRIV_H_ #define _ROC_NPC_PRIV_H_ -#define NPC_IH_LENGTH 8 -#define NPC_TPID_LENGTH 2 -#define NPC_HIGIG2_LENGTH 16 -#define NPC_COUNTER_NONE (-1) +#define NPC_IH_LENGTH 8 +#define NPC_TPID_LENGTH 2 +#define NPC_HIGIG2_LENGTH 16 +#define NPC_MAX_RAW_ITEM_LEN 16 +#define NPC_COUNTER_NONE (-1) #define NPC_RSS_GRPS 8 diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c index 5c97588e68..5fcb56c35b 100644 --- a/drivers/common/cnxk/roc_npc_utils.c +++ b/drivers/common/cnxk/roc_npc_utils.c @@ -130,7 +130,8 @@ npc_parse_item_basic(const struct roc_npc_item_info *item, } /* We have valid spec */ - info->spec = item->spec; + if (item->type != ROC_NPC_ITEM_TYPE_RAW) + info->spec = item->spec; /* If mask is not set, use default mask, err if default mask is * also NULL. @@ -140,7 +141,8 @@ npc_parse_item_basic(const struct roc_npc_item_info *item, return NPC_ERR_PARAM; info->mask = info->def_mask; } else { - info->mask = item->mask; + if (item->type != ROC_NPC_ITEM_TYPE_RAW) + info->mask = item->mask; } /* mask specified must be subset of hw supported mask diff --git a/drivers/common/cnxk/roc_utils.c b/drivers/common/cnxk/roc_utils.c index 542252fe4c..9cb8708a74 100644 --- a/drivers/common/cnxk/roc_utils.c +++ b/drivers/common/cnxk/roc_utils.c @@ -113,7 +113,7 @@ roc_error_msg_get(int errorcode) err_msg = "NPC invalid spec"; break; case NPC_ERR_INVALID_MASK: - err_msg = "NPC invalid mask"; + err_msg = "NPC invalid mask"; break; case NPC_ERR_INVALID_KEX: err_msg = "NPC invalid key"; -- 2.20.1