1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
7 const struct roc_npc_item_info *
8 npc_parse_skip_void_and_any_items(const struct roc_npc_item_info *pattern)
10 while ((pattern->type == ROC_NPC_ITEM_TYPE_VOID) ||
11 (pattern->type == ROC_NPC_ITEM_TYPE_ANY))
18 npc_parse_meta_items(struct npc_parse_state *pst)
25 npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
26 const struct roc_npc_flow_item_raw *raw_mask,
27 struct npc_parse_item_info *info, uint8_t *spec_buf,
31 memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
32 memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
34 memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
37 if (raw_mask && raw_mask->pattern) {
38 memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
41 memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
44 info->len = NPC_MAX_RAW_ITEM_LEN;
45 info->spec = spec_buf;
46 info->mask = mask_buf;
51 npc_parse_pre_l2(struct npc_parse_state *pst)
53 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
54 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
55 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN] = {0};
56 const struct roc_npc_flow_item_raw *raw_spec;
57 struct npc_parse_item_info info;
61 if (pst->npc->switch_header_type != ROC_PRIV_FLAGS_PRE_L2)
64 /* Identify the pattern type into lid, lt */
65 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_RAW)
69 lt = NPC_LT_LA_CUSTOM_PRE_L2_ETHER;
72 raw_spec = pst->pattern->spec;
73 len = raw_spec->length + raw_spec->offset;
74 if (len > NPC_MAX_RAW_ITEM_LEN)
77 if (raw_spec->relative == 0 || raw_spec->search || raw_spec->limit ||
81 npc_flow_raw_item_prepare(
82 (const struct roc_npc_flow_item_raw *)pst->pattern->spec,
83 (const struct roc_npc_flow_item_raw *)pst->pattern->mask, &info,
84 raw_spec_buf, raw_mask_buf);
86 info.hw_mask = &hw_mask;
87 npc_get_hw_supp_mask(pst, &info, lid, lt);
89 /* Basic validation of item parameters */
90 rc = npc_parse_item_basic(pst->pattern, &info);
94 /* Update pst if not validate only? clash check? */
95 return npc_update_parse_state(pst, &info, lid, lt, 0);
99 npc_parse_cpt_hdr(struct npc_parse_state *pst)
101 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
102 struct npc_parse_item_info info;
106 /* Identify the pattern type into lid, lt */
107 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
111 lt = NPC_LT_LA_CPT_HDR;
114 /* Prepare for parsing the item */
115 info.def_mask = NULL;
116 info.hw_mask = &hw_mask;
117 info.len = pst->pattern->size;
118 npc_get_hw_supp_mask(pst, &info, lid, lt);
122 /* Basic validation of item parameters */
123 rc = npc_parse_item_basic(pst->pattern, &info);
127 /* Update pst if not validate only? clash check? */
128 return npc_update_parse_state(pst, &info, lid, lt, 0);
132 npc_parse_higig2_hdr(struct npc_parse_state *pst)
134 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
135 struct npc_parse_item_info info;
139 /* Identify the pattern type into lid, lt */
140 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
144 lt = NPC_LT_LA_HIGIG2_ETHER;
147 if (pst->flow->nix_intf == NIX_INTF_TX) {
148 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
149 info.hw_hdr_len = NPC_IH_LENGTH;
152 /* Prepare for parsing the item */
153 info.def_mask = NULL;
154 info.hw_mask = &hw_mask;
155 info.len = pst->pattern->size;
156 npc_get_hw_supp_mask(pst, &info, lid, lt);
160 /* Basic validation of item parameters */
161 rc = npc_parse_item_basic(pst->pattern, &info);
165 /* Update pst if not validate only? clash check? */
166 return npc_update_parse_state(pst, &info, lid, lt, 0);
170 npc_parse_la(struct npc_parse_state *pst)
172 const struct roc_npc_flow_item_eth *eth_item;
173 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
174 struct npc_parse_item_info info;
178 /* Identify the pattern type into lid, lt */
179 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
182 eth_item = pst->pattern->spec;
185 lt = NPC_LT_LA_ETHER;
188 if (pst->flow->nix_intf == NIX_INTF_TX) {
189 lt = NPC_LT_LA_IH_NIX_ETHER;
190 info.hw_hdr_len = NPC_IH_LENGTH;
191 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
192 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
193 info.hw_hdr_len += NPC_HIGIG2_LENGTH;
196 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
197 lt = NPC_LT_LA_HIGIG2_ETHER;
198 info.hw_hdr_len = NPC_HIGIG2_LENGTH;
202 /* Prepare for parsing the item */
203 info.def_mask = NULL;
204 info.hw_mask = &hw_mask;
205 info.len = sizeof(eth_item->hdr);
206 npc_get_hw_supp_mask(pst, &info, lid, lt);
210 /* Basic validation of item parameters */
211 rc = npc_parse_item_basic(pst->pattern, &info);
215 rc = npc_update_parse_state(pst, &info, lid, lt, 0);
219 if (eth_item && eth_item->has_vlan)
220 pst->set_vlan_ltype_mask = true;
225 #define NPC_MAX_SUPPORTED_VLANS 3
228 npc_parse_lb(struct npc_parse_state *pst)
230 const struct roc_npc_flow_item_vlan *vlan_item[NPC_MAX_SUPPORTED_VLANS];
231 const struct roc_npc_item_info *pattern = pst->pattern;
232 const struct roc_npc_item_info *last_pattern;
233 const struct roc_npc_flow_item_raw *raw_spec;
234 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
235 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
236 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
237 struct npc_parse_item_info info;
238 int lid, lt, lflags, len = 0;
242 info.def_mask = NULL;
245 info.def_mask = NULL;
246 info.hw_hdr_len = NPC_TPID_LENGTH;
250 last_pattern = pattern;
252 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
253 /* RTE vlan is either 802.1q or 802.1ad,
254 * this maps to either CTAG/STAG. We need to decide
255 * based on number of VLANS present. Matching is
256 * supported on first tag only.
259 info.len = sizeof(vlan_item[0]->hdr);
261 pattern = pst->pattern;
262 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
263 if (nr_vlans > NPC_MAX_SUPPORTED_VLANS - 1)
264 return NPC_ERR_PATTERN_NOTSUP;
266 vlan_item[nr_vlans] = pattern->spec;
269 /* Basic validation of Second/Third vlan item */
271 rc = npc_parse_item_basic(pattern, &info);
275 last_pattern = pattern;
277 pattern = npc_parse_skip_void_and_any_items(pattern);
283 if (vlan_item[0] && vlan_item[0]->has_more_vlan)
284 lt = NPC_LT_LB_STAG_QINQ;
287 if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
288 if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
289 0x3ULL << NPC_LFLAG_LB_OFFSET))
290 return NPC_ERR_PATTERN_NOTSUP;
292 /* This lflag value will match either one of
293 * NPC_F_LB_L_WITH_STAG_STAG,
294 * NPC_F_LB_L_WITH_QINQ_CTAG,
295 * NPC_F_LB_L_WITH_QINQ_QINQ and
296 * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
297 * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
298 * hence will not match.
301 lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
302 NPC_F_LB_L_WITH_QINQ_QINQ &
303 NPC_F_LB_L_WITH_STAG_STAG;
305 lflags = NPC_F_LB_L_WITH_CTAG;
307 lt = NPC_LT_LB_STAG_QINQ;
310 if (vlan_item[2] && vlan_item[2]->has_more_vlan)
311 return NPC_ERR_PATTERN_NOTSUP;
312 lt = NPC_LT_LB_STAG_QINQ;
313 lflags = NPC_F_STAG_STAG_CTAG;
316 return NPC_ERR_PATTERN_NOTSUP;
318 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
319 /* we can support ETAG and match a subsequent CTAG
320 * without any matching support.
325 last_pattern = pst->pattern;
326 pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
327 if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
328 /* set supported mask to NULL for vlan tag */
330 info.len = pattern->size;
331 rc = npc_parse_item_basic(pattern, &info);
335 lflags = NPC_F_ETAG_CTAG;
336 last_pattern = pattern;
338 info.len = pattern->size;
339 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
340 vlan_item[0] = pst->pattern->spec;
342 info.len = sizeof(vlan_item[0]->hdr);
343 lt = NPC_LT_LB_STAG_QINQ;
344 lflags = NPC_F_STAG_CTAG;
345 if (vlan_item[0] && vlan_item[0]->has_more_vlan) {
346 lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
347 NPC_F_LB_L_WITH_QINQ_QINQ;
349 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
350 raw_spec = pst->pattern->spec;
351 if (raw_spec->relative)
353 len = raw_spec->length + raw_spec->offset;
354 if (len > NPC_MAX_RAW_ITEM_LEN)
357 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
358 lt = NPC_LT_LB_VLAN_EXDSA;
359 } else if (pst->npc->switch_header_type ==
360 ROC_PRIV_FLAGS_EXDSA) {
361 lt = NPC_LT_LB_EXDSA;
366 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
368 (const struct roc_npc_flow_item_raw *)
370 &info, raw_spec_buf, raw_mask_buf);
377 info.hw_mask = &hw_mask;
378 npc_get_hw_supp_mask(pst, &info, lid, lt);
380 rc = npc_parse_item_basic(pst->pattern, &info);
384 /* Point pattern to last item consumed */
385 pst->pattern = last_pattern;
386 return npc_update_parse_state(pst, &info, lid, lt, lflags);
390 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
392 uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
393 NPC_F_MPLS_4_LABELS};
394 const struct roc_npc_item_info *pattern = pst->pattern;
395 struct npc_parse_item_info info;
400 * pst->pattern points to first MPLS label. We only check
401 * that subsequent labels do not have anything to match.
403 info.def_mask = NULL;
405 info.len = pattern->size;
410 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
413 /* Basic validation of Second/Third/Fourth mpls item */
415 rc = npc_parse_item_basic(pattern, &info);
419 pst->last_pattern = pattern;
421 pattern = npc_parse_skip_void_and_any_items(pattern);
424 if (nr_labels < 1 || nr_labels > 4)
425 return NPC_ERR_PATTERN_NOTSUP;
427 *flag = flag_list[nr_labels - 1];
432 npc_parse_mpls(struct npc_parse_state *pst, int lid)
434 /* Find number of MPLS labels */
435 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
436 struct npc_parse_item_info info;
442 if (lid == NPC_LID_LC)
444 else if (lid == NPC_LID_LD)
445 lt = NPC_LT_LD_TU_MPLS_IN_IP;
447 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
449 /* Prepare for parsing the first item */
450 info.hw_mask = &hw_mask;
451 info.len = pst->pattern->size;
454 info.def_mask = NULL;
457 npc_get_hw_supp_mask(pst, &info, lid, lt);
458 rc = npc_parse_item_basic(pst->pattern, &info);
463 * Parse for more labels.
464 * This sets lflags and pst->last_pattern correctly.
466 rc = npc_parse_mpls_label_stack(pst, &lflags);
471 pst->pattern = pst->last_pattern;
473 return npc_update_parse_state(pst, &info, lid, lt, lflags);
477 npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
479 const struct roc_npc_item_info *pattern = pst->pattern + 1;
481 pattern = npc_parse_skip_void_and_any_items(pattern);
482 if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
483 pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
484 pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
489 npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
490 struct npc_parse_state *pst, uint8_t *flags)
494 if (ipv6_spec->has_hop_ext) {
495 *flags = NPC_F_LC_L_EXT_HOP;
498 if (ipv6_spec->has_route_ext) {
499 *flags = NPC_F_LC_L_EXT_ROUT;
502 if (ipv6_spec->has_frag_ext) {
503 *flags = NPC_F_LC_U_IP6_FRAG;
506 if (ipv6_spec->has_dest_ext) {
507 *flags = NPC_F_LC_L_EXT_DEST;
510 if (ipv6_spec->has_mobil_ext) {
511 *flags = NPC_F_LC_L_EXT_MOBILITY;
514 if (ipv6_spec->has_hip_ext) {
515 *flags = NPC_F_LC_L_EXT_HOSTID;
518 if (ipv6_spec->has_shim6_ext) {
519 *flags = NPC_F_LC_L_EXT_SHIM6;
522 if (ipv6_spec->has_auth_ext) {
523 pst->lt[NPC_LID_LD] = NPC_LT_LD_AH;
526 if (ipv6_spec->has_esp_ext) {
527 pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP;
535 pst->set_ipv6ext_ltype_mask = true;
541 npc_parse_lc(struct npc_parse_state *pst)
543 const struct roc_npc_flow_item_ipv6 *ipv6_spec;
544 const struct roc_npc_flow_item_raw *raw_spec;
545 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
546 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
547 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
548 struct npc_parse_item_info info;
549 int rc, lid, lt, len = 0;
552 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
553 return npc_parse_mpls(pst, NPC_LID_LC);
555 info.def_mask = NULL;
556 info.hw_mask = &hw_mask;
562 switch (pst->pattern->type) {
563 case ROC_NPC_ITEM_TYPE_IPV4:
565 info.len = pst->pattern->size;
567 case ROC_NPC_ITEM_TYPE_IPV6:
568 ipv6_spec = pst->pattern->spec;
572 rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags);
576 info.len = sizeof(ipv6_spec->hdr);
578 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
580 info.len = pst->pattern->size;
582 case ROC_NPC_ITEM_TYPE_IPV6_EXT:
584 lt = NPC_LT_LC_IP6_EXT;
585 info.len = pst->pattern->size;
586 info.hw_hdr_len = 40;
588 case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
589 lt = NPC_LT_LC_CUSTOM0;
590 info.len = pst->pattern->size;
592 case ROC_NPC_ITEM_TYPE_RAW:
593 raw_spec = pst->pattern->spec;
594 if (!raw_spec->relative)
597 len = raw_spec->length + raw_spec->offset;
598 if (len > NPC_MAX_RAW_ITEM_LEN)
601 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
603 (const struct roc_npc_flow_item_raw *)
605 &info, raw_spec_buf, raw_mask_buf);
609 info.hw_mask = &hw_mask;
610 npc_get_hw_supp_mask(pst, &info, lid, lt);
613 /* No match at this layer */
617 /* Identify if IP tunnels MPLS or IPv4/v6 */
618 npc_check_lc_ip_tunnel(pst);
620 npc_get_hw_supp_mask(pst, &info, lid, lt);
621 rc = npc_parse_item_basic(pst->pattern, &info);
626 return npc_update_parse_state(pst, &info, lid, lt, flags);
630 npc_parse_ld(struct npc_parse_state *pst)
632 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
633 struct npc_parse_item_info info;
638 /* We have already parsed MPLS or IPv4/v6 followed
639 * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
640 * would be parsed as tunneled versions. Skip
641 * this layer, except for tunneled MPLS. If LC is
642 * MPLS, we have anyway skipped all stacked MPLS
645 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
646 return npc_parse_mpls(pst, NPC_LID_LD);
649 info.def_mask = NULL;
650 info.hw_mask = &hw_mask;
659 switch (pst->pattern->type) {
660 case ROC_NPC_ITEM_TYPE_ICMP:
661 if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
662 lt = NPC_LT_LD_ICMP6;
665 info.len = pst->pattern->size;
667 case ROC_NPC_ITEM_TYPE_UDP:
669 info.len = pst->pattern->size;
671 case ROC_NPC_ITEM_TYPE_IGMP:
673 info.len = pst->pattern->size;
675 case ROC_NPC_ITEM_TYPE_TCP:
677 info.len = pst->pattern->size;
679 case ROC_NPC_ITEM_TYPE_SCTP:
681 info.len = pst->pattern->size;
683 case ROC_NPC_ITEM_TYPE_GRE:
685 info.len = pst->pattern->size;
687 case ROC_NPC_ITEM_TYPE_GRE_KEY:
689 info.len = pst->pattern->size;
692 case ROC_NPC_ITEM_TYPE_NVGRE:
693 lt = NPC_LT_LD_NVGRE;
694 lflags = NPC_F_GRE_NVGRE;
695 info.len = pst->pattern->size;
696 /* Further IP/Ethernet are parsed as tunneled */
703 npc_get_hw_supp_mask(pst, &info, lid, lt);
704 rc = npc_parse_item_basic(pst->pattern, &info);
708 return npc_update_parse_state(pst, &info, lid, lt, lflags);
712 npc_parse_le(struct npc_parse_state *pst)
714 const struct roc_npc_item_info *pattern = pst->pattern;
715 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
716 struct npc_parse_item_info info;
723 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
724 return npc_parse_mpls(pst, NPC_LID_LE);
729 info.def_mask = NULL;
735 /* Ensure we are not matching anything in UDP */
736 rc = npc_parse_item_basic(pattern, &info);
740 info.hw_mask = &hw_mask;
741 pattern = npc_parse_skip_void_and_any_items(pattern);
742 switch (pattern->type) {
743 case ROC_NPC_ITEM_TYPE_VXLAN:
744 lflags = NPC_F_UDP_VXLAN;
745 info.len = pattern->size;
746 lt = NPC_LT_LE_VXLAN;
748 case ROC_NPC_ITEM_TYPE_GTPC:
749 lflags = NPC_F_UDP_GTP_GTPC;
750 info.len = pattern->size;
753 case ROC_NPC_ITEM_TYPE_GTPU:
754 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
755 info.len = pattern->size;
758 case ROC_NPC_ITEM_TYPE_GENEVE:
759 lflags = NPC_F_UDP_GENEVE;
760 info.len = pattern->size;
761 lt = NPC_LT_LE_GENEVE;
763 case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
764 lflags = NPC_F_UDP_VXLANGPE;
765 info.len = pattern->size;
766 lt = NPC_LT_LE_VXLANGPE;
768 case ROC_NPC_ITEM_TYPE_ESP:
770 info.len = pst->pattern->size;
778 npc_get_hw_supp_mask(pst, &info, lid, lt);
779 rc = npc_parse_item_basic(pattern, &info);
783 return npc_update_parse_state(pst, &info, lid, lt, lflags);
787 npc_parse_lf(struct npc_parse_state *pst)
789 const struct roc_npc_item_info *pattern, *last_pattern;
790 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
791 struct npc_parse_item_info info;
796 /* We hit this layer if there is a tunneling protocol */
800 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
804 lt = NPC_LT_LF_TU_ETHER;
807 /* No match support for vlan tags */
808 info.def_mask = NULL;
810 info.len = pst->pattern->size;
815 /* Look ahead and find out any VLAN tags. These can be
816 * detected but no data matching is available.
818 last_pattern = pst->pattern;
819 pattern = pst->pattern + 1;
820 pattern = npc_parse_skip_void_and_any_items(pattern);
821 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
823 last_pattern = pattern;
825 pattern = npc_parse_skip_void_and_any_items(pattern);
831 lflags = NPC_F_TU_ETHER_CTAG;
834 lflags = NPC_F_TU_ETHER_STAG_CTAG;
837 return NPC_ERR_PATTERN_NOTSUP;
840 info.hw_mask = &hw_mask;
841 info.len = pst->pattern->size;
843 npc_get_hw_supp_mask(pst, &info, lid, lt);
847 rc = npc_parse_item_basic(pst->pattern, &info);
851 pst->pattern = last_pattern;
853 return npc_update_parse_state(pst, &info, lid, lt, lflags);
857 npc_parse_lg(struct npc_parse_state *pst)
859 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
860 struct npc_parse_item_info info;
867 info.def_mask = NULL;
868 info.hw_mask = &hw_mask;
874 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
875 lt = NPC_LT_LG_TU_IP;
876 info.len = pst->pattern->size;
877 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
878 lt = NPC_LT_LG_TU_IP6;
879 info.len = pst->pattern->size;
881 /* There is no tunneled IP header */
885 npc_get_hw_supp_mask(pst, &info, lid, lt);
886 rc = npc_parse_item_basic(pst->pattern, &info);
890 return npc_update_parse_state(pst, &info, lid, lt, 0);
894 npc_parse_lh(struct npc_parse_state *pst)
896 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
897 struct npc_parse_item_info info;
904 info.def_mask = NULL;
905 info.hw_mask = &hw_mask;
911 switch (pst->pattern->type) {
912 case ROC_NPC_ITEM_TYPE_UDP:
913 lt = NPC_LT_LH_TU_UDP;
914 info.len = pst->pattern->size;
916 case ROC_NPC_ITEM_TYPE_TCP:
917 lt = NPC_LT_LH_TU_TCP;
918 info.len = pst->pattern->size;
920 case ROC_NPC_ITEM_TYPE_SCTP:
921 lt = NPC_LT_LH_TU_SCTP;
922 info.len = pst->pattern->size;
924 case ROC_NPC_ITEM_TYPE_ESP:
925 lt = NPC_LT_LH_TU_ESP;
926 info.len = pst->pattern->size;
932 npc_get_hw_supp_mask(pst, &info, lid, lt);
933 rc = npc_parse_item_basic(pst->pattern, &info);
937 return npc_update_parse_state(pst, &info, lid, lt, 0);