From 474e275b1bc6e048fd9e07d775db1cb958e30786 Mon Sep 17 00:00:00 2001 From: Satheesh Paul Date: Fri, 21 Jan 2022 11:56:41 +0530 Subject: [PATCH] common/cnxk: support extensions attributes in IPv6 item Support matching existence of specific extension headers after RTE_FLOW_ITEM_TYPE_IPV6 item. Signed-off-by: Satheesh Paul Reviewed-by: Kiran Kumar K --- drivers/common/cnxk/hw/npc.h | 17 ++++++++ drivers/common/cnxk/roc_npc.h | 33 +++++++++++++++ drivers/common/cnxk/roc_npc_mcam.c | 43 +++++++++++++++++++ drivers/common/cnxk/roc_npc_parse.c | 65 +++++++++++++++++++++++++++-- drivers/common/cnxk/roc_npc_priv.h | 6 +++ 5 files changed, 160 insertions(+), 4 deletions(-) diff --git a/drivers/common/cnxk/hw/npc.h b/drivers/common/cnxk/hw/npc.h index 6f896de9f0..b8218e25af 100644 --- a/drivers/common/cnxk/hw/npc.h +++ b/drivers/common/cnxk/hw/npc.h @@ -320,6 +320,23 @@ enum npc_kpu_lc_uflag { NPC_F_LC_U_IP6_FRAG = 0x40, }; +enum npc_kpu_lc_lflag { + NPC_F_LC_L_IP_IN_IP = 1, + NPC_F_LC_L_6TO4, + NPC_F_LC_L_MPLS_IN_IP, + NPC_F_LC_L_IP6_TUN_IP6, + NPC_F_LC_L_IP6_MPLS_IN_IP, + NPC_F_LC_L_MPLS_4_LABELS, + NPC_F_LC_L_MPLS_3_LABELS, + NPC_F_LC_L_MPLS_2_LABELS, + NPC_F_LC_L_EXT_HOP, + NPC_F_LC_L_EXT_DEST, + NPC_F_LC_L_EXT_ROUT, + NPC_F_LC_L_EXT_MOBILITY, + NPC_F_LC_L_EXT_HOSTID, + NPC_F_LC_L_EXT_SHIM6, +}; + /* Structures definitions */ struct npc_kpu_profile_cam { uint8_t state; diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index 6ab185e188..b836e264c6 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -112,6 +112,39 @@ struct roc_npc_flow_item_vlan { uint32_t reserved : 31; /**< Reserved, must be zero. */ }; +struct roc_ipv6_hdr { + uint32_t vtc_flow; /**< IP version, traffic class & flow label. */ + uint16_t payload_len; /**< IP payload size, including ext. headers */ + uint8_t proto; /**< Protocol, next header. */ + uint8_t hop_limits; /**< Hop limits. */ + uint8_t src_addr[16]; /**< IP address of source host. */ + uint8_t dst_addr[16]; /**< IP address of destination host(s). */ +} __plt_packed; + +struct roc_npc_flow_item_ipv6 { + struct roc_ipv6_hdr hdr; /**< IPv6 header definition. */ + uint32_t has_hop_ext : 1; + /**< Header contains Hop-by-Hop Options extension header. */ + uint32_t has_route_ext : 1; + /**< Header contains Routing extension header. */ + uint32_t has_frag_ext : 1; + /**< Header contains Fragment extension header. */ + uint32_t has_auth_ext : 1; + /**< Header contains Authentication extension header. */ + uint32_t has_esp_ext : 1; + /**< Header contains Encapsulation Security Payload extension header. */ + uint32_t has_dest_ext : 1; + /**< Header contains Destination Options extension header. */ + uint32_t has_mobil_ext : 1; + /**< Header contains Mobility extension header. */ + uint32_t has_hip_ext : 1; + /**< Header contains Host Identity Protocol extension header. */ + uint32_t has_shim6_ext : 1; + /**< Header contains Shim6 Protocol extension header. */ + uint32_t reserved : 23; + /**< Reserved for future extension headers, must be zero. */ +}; + #define ROC_NPC_MAX_ACTION_COUNT 19 enum roc_npc_action_type { diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c index 29bfc072c9..b251f643bc 100644 --- a/drivers/common/cnxk/roc_npc_mcam.c +++ b/drivers/common/cnxk/roc_npc_mcam.c @@ -635,6 +635,46 @@ npc_set_vlan_ltype(struct npc_parse_state *pst) pst->flow->mcam_mask[0] |= (0xeULL << lb_offset); } +static void +npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst) +{ + uint8_t lc_offset, lcflag_offset; + uint64_t val, mask; + + lc_offset = + __builtin_popcount(pst->npc->keyx_supp_nmask[pst->nix_intf] & + ((1ULL << NPC_LTYPE_LC_OFFSET) - 1)); + lc_offset *= 4; + + mask = ~((0xfULL << lc_offset)); + pst->flow->mcam_data[0] &= mask; + pst->flow->mcam_mask[0] &= mask; + /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101 + * Set LC layertype/mask as 0b0100/0b1110 to match both. + */ + val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset; + pst->flow->mcam_data[0] |= val; + pst->flow->mcam_mask[0] |= (0xeULL << lc_offset); + + /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general + * case flag mask is set same as the value in data. For example, to + * match 3 VLANs, flags have to match a range of values. But, for IPv6 + * extended attributes matching, we need an exact match. Hence, set the + * mask as 0xF. This is done only if LC LFLAG value is non-zero, + * because for AH and ESP, LC LFLAG is zero and we don't want to match + * zero in LFLAG. + */ + lcflag_offset = + __builtin_popcount(pst->npc->keyx_supp_nmask[pst->nix_intf] & + ((1ULL << NPC_LFLAG_LC_OFFSET) - 1)); + lcflag_offset *= 4; + + mask = (0xfULL << lcflag_offset); + val = pst->flow->mcam_data[0] & mask; + if (val) + pst->flow->mcam_mask[0] |= mask; +} + int npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) { @@ -709,6 +749,9 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc) if (pst->set_vlan_ltype_mask) npc_set_vlan_ltype(pst); + if (pst->set_ipv6ext_ltype_mask) + npc_set_ipv6ext_ltype_mask(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 75724661da..1f21693369 100644 --- a/drivers/common/cnxk/roc_npc_parse.c +++ b/drivers/common/cnxk/roc_npc_parse.c @@ -480,16 +480,69 @@ npc_check_lc_ip_tunnel(struct npc_parse_state *pst) pst->tunnel = 1; } +static int +npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec, + struct npc_parse_state *pst, uint8_t *flags) +{ + int flags_count = 0; + + if (ipv6_spec->has_hop_ext) { + *flags = NPC_F_LC_L_EXT_HOP; + flags_count++; + } + if (ipv6_spec->has_route_ext) { + *flags = NPC_F_LC_L_EXT_ROUT; + flags_count++; + } + if (ipv6_spec->has_frag_ext) { + *flags = NPC_F_LC_U_IP6_FRAG; + flags_count++; + } + if (ipv6_spec->has_dest_ext) { + *flags = NPC_F_LC_L_EXT_DEST; + flags_count++; + } + if (ipv6_spec->has_mobil_ext) { + *flags = NPC_F_LC_L_EXT_MOBILITY; + flags_count++; + } + if (ipv6_spec->has_hip_ext) { + *flags = NPC_F_LC_L_EXT_HOSTID; + flags_count++; + } + if (ipv6_spec->has_shim6_ext) { + *flags = NPC_F_LC_L_EXT_SHIM6; + flags_count++; + } + if (ipv6_spec->has_auth_ext) { + pst->lt[NPC_LID_LD] = NPC_LT_LD_AH; + flags_count++; + } + if (ipv6_spec->has_esp_ext) { + pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP; + flags_count++; + } + + if (flags_count > 1) + return -EINVAL; + + if (flags_count) + pst->set_ipv6ext_ltype_mask = true; + + return 0; +} + int npc_parse_lc(struct npc_parse_state *pst) { + const struct roc_npc_flow_item_ipv6 *ipv6_spec; 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, len = 0; - int rc; + int rc, lid, lt, len = 0; + uint8_t flags = 0; if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS) return npc_parse_mpls(pst, NPC_LID_LC); @@ -506,9 +559,13 @@ npc_parse_lc(struct npc_parse_state *pst) info.len = pst->pattern->size; break; case ROC_NPC_ITEM_TYPE_IPV6: + ipv6_spec = pst->pattern->spec; lid = NPC_LID_LC; lt = NPC_LT_LC_IP6; - info.len = pst->pattern->size; + rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags); + if (rc) + return rc; + info.len = sizeof(ipv6_spec->hdr); break; case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4: lt = NPC_LT_LC_ARP; @@ -558,7 +615,7 @@ npc_parse_lc(struct npc_parse_state *pst) if (rc != 0) return rc; - return npc_update_parse_state(pst, &info, lid, lt, 0); + return npc_update_parse_state(pst, &info, lid, lt, flags); } int diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 12320f0ced..afd11add9a 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -71,6 +71,11 @@ /* 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) +/* LC OFFSET : START + LA (2b flags + 1b ltype) + LB (2b flags + 1b ltype) + LC + * (2b flags) + */ +#define NPC_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 6) +#define NPC_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 8) struct npc_action_vtag_info { uint16_t vlan_id; @@ -183,6 +188,7 @@ struct npc_parse_state { bool is_vf; /* adjust ltype in MCAM to match at least one vlan */ bool set_vlan_ltype_mask; + bool set_ipv6ext_ltype_mask; }; enum npc_kpu_parser_flag {