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.hw_mask = &hw_mask;
116 info.len = pst->pattern->size;
117 npc_get_hw_supp_mask(pst, &info, lid, lt);
121 /* Basic validation of item parameters */
122 rc = npc_parse_item_basic(pst->pattern, &info);
126 /* Update pst if not validate only? clash check? */
127 return npc_update_parse_state(pst, &info, lid, lt, 0);
131 npc_parse_higig2_hdr(struct npc_parse_state *pst)
133 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
134 struct npc_parse_item_info info;
138 /* Identify the pattern type into lid, lt */
139 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
143 lt = NPC_LT_LA_HIGIG2_ETHER;
146 if (pst->flow->nix_intf == NIX_INTF_TX) {
147 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
148 info.hw_hdr_len = NPC_IH_LENGTH;
151 /* Prepare for parsing the item */
152 info.hw_mask = &hw_mask;
153 info.len = pst->pattern->size;
154 npc_get_hw_supp_mask(pst, &info, lid, lt);
158 /* Basic validation of item parameters */
159 rc = npc_parse_item_basic(pst->pattern, &info);
163 /* Update pst if not validate only? clash check? */
164 return npc_update_parse_state(pst, &info, lid, lt, 0);
168 npc_parse_la(struct npc_parse_state *pst)
170 const struct roc_npc_flow_item_eth *eth_item;
171 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
172 struct npc_parse_item_info info;
176 /* Identify the pattern type into lid, lt */
177 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
180 eth_item = pst->pattern->spec;
183 lt = NPC_LT_LA_ETHER;
186 if (pst->flow->nix_intf == NIX_INTF_TX) {
187 lt = NPC_LT_LA_IH_NIX_ETHER;
188 info.hw_hdr_len = NPC_IH_LENGTH;
189 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
190 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
191 info.hw_hdr_len += NPC_HIGIG2_LENGTH;
194 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
195 lt = NPC_LT_LA_HIGIG2_ETHER;
196 info.hw_hdr_len = NPC_HIGIG2_LENGTH;
200 /* Prepare for parsing the item */
201 info.hw_mask = &hw_mask;
202 info.len = sizeof(eth_item->hdr);
203 npc_get_hw_supp_mask(pst, &info, lid, lt);
207 /* Basic validation of item parameters */
208 rc = npc_parse_item_basic(pst->pattern, &info);
212 rc = npc_update_parse_state(pst, &info, lid, lt, 0);
216 if (eth_item && eth_item->has_vlan)
217 pst->set_vlan_ltype_mask = true;
222 #define NPC_MAX_SUPPORTED_VLANS 3
225 npc_parse_lb(struct npc_parse_state *pst)
227 const struct roc_npc_flow_item_vlan *vlan_item[NPC_MAX_SUPPORTED_VLANS];
228 const struct roc_npc_item_info *pattern = pst->pattern;
229 const struct roc_npc_item_info *last_pattern;
230 const struct roc_npc_flow_item_raw *raw_spec;
231 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
232 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
233 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
234 struct npc_parse_item_info info;
235 int lid, lt, lflags, len = 0;
241 info.def_mask = NULL;
242 info.hw_hdr_len = NPC_TPID_LENGTH;
246 last_pattern = pattern;
248 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
249 /* RTE vlan is either 802.1q or 802.1ad,
250 * this maps to either CTAG/STAG. We need to decide
251 * based on number of VLANS present. Matching is
252 * supported on first tag only.
255 info.len = sizeof(vlan_item[0]->hdr);
257 pattern = pst->pattern;
258 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
259 if (nr_vlans > NPC_MAX_SUPPORTED_VLANS - 1)
260 return NPC_ERR_PATTERN_NOTSUP;
262 vlan_item[nr_vlans] = pattern->spec;
265 /* Basic validation of Second/Third vlan item */
267 rc = npc_parse_item_basic(pattern, &info);
271 last_pattern = pattern;
273 pattern = npc_parse_skip_void_and_any_items(pattern);
279 if (vlan_item[0] && vlan_item[0]->has_more_vlan)
280 lt = NPC_LT_LB_STAG_QINQ;
283 if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
284 if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
285 0x3ULL << NPC_LFLAG_LB_OFFSET))
286 return NPC_ERR_PATTERN_NOTSUP;
288 /* This lflag value will match either one of
289 * NPC_F_LB_L_WITH_STAG_STAG,
290 * NPC_F_LB_L_WITH_QINQ_CTAG,
291 * NPC_F_LB_L_WITH_QINQ_QINQ and
292 * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
293 * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
294 * hence will not match.
297 lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
298 NPC_F_LB_L_WITH_QINQ_QINQ &
299 NPC_F_LB_L_WITH_STAG_STAG;
301 lflags = NPC_F_LB_L_WITH_CTAG;
303 lt = NPC_LT_LB_STAG_QINQ;
306 if (vlan_item[2] && vlan_item[2]->has_more_vlan)
307 return NPC_ERR_PATTERN_NOTSUP;
308 lt = NPC_LT_LB_STAG_QINQ;
309 lflags = NPC_F_STAG_STAG_CTAG;
312 return NPC_ERR_PATTERN_NOTSUP;
314 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
315 /* we can support ETAG and match a subsequent CTAG
316 * without any matching support.
321 last_pattern = pst->pattern;
322 pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
323 if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
324 /* set supported mask to NULL for vlan tag */
326 info.len = pattern->size;
327 rc = npc_parse_item_basic(pattern, &info);
331 lflags = NPC_F_ETAG_CTAG;
332 last_pattern = pattern;
334 info.len = pattern->size;
335 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
336 vlan_item[0] = pst->pattern->spec;
338 info.len = sizeof(vlan_item[0]->hdr);
339 lt = NPC_LT_LB_STAG_QINQ;
340 lflags = NPC_F_STAG_CTAG;
341 if (vlan_item[0] && vlan_item[0]->has_more_vlan) {
342 lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
343 NPC_F_LB_L_WITH_QINQ_QINQ;
345 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
346 raw_spec = pst->pattern->spec;
347 if (raw_spec->relative)
349 len = raw_spec->length + raw_spec->offset;
350 if (len > NPC_MAX_RAW_ITEM_LEN)
353 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
354 lt = NPC_LT_LB_VLAN_EXDSA;
355 } else if (pst->npc->switch_header_type ==
356 ROC_PRIV_FLAGS_EXDSA) {
357 lt = NPC_LT_LB_EXDSA;
362 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
364 (const struct roc_npc_flow_item_raw *)
366 &info, raw_spec_buf, raw_mask_buf);
373 info.hw_mask = &hw_mask;
374 npc_get_hw_supp_mask(pst, &info, lid, lt);
376 rc = npc_parse_item_basic(pst->pattern, &info);
380 /* Point pattern to last item consumed */
381 pst->pattern = last_pattern;
382 return npc_update_parse_state(pst, &info, lid, lt, lflags);
386 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
388 uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
389 NPC_F_MPLS_4_LABELS};
390 const struct roc_npc_item_info *pattern = pst->pattern;
391 struct npc_parse_item_info info;
396 * pst->pattern points to first MPLS label. We only check
397 * that subsequent labels do not have anything to match.
400 info.len = pattern->size;
404 info.def_mask = NULL;
406 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
409 /* Basic validation of Second/Third/Fourth mpls item */
411 rc = npc_parse_item_basic(pattern, &info);
415 pst->last_pattern = pattern;
417 pattern = npc_parse_skip_void_and_any_items(pattern);
420 if (nr_labels < 1 || nr_labels > 4)
421 return NPC_ERR_PATTERN_NOTSUP;
423 *flag = flag_list[nr_labels - 1];
428 npc_parse_mpls(struct npc_parse_state *pst, int lid)
430 /* Find number of MPLS labels */
431 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
432 struct npc_parse_item_info info;
438 if (lid == NPC_LID_LC)
440 else if (lid == NPC_LID_LD)
441 lt = NPC_LT_LD_TU_MPLS_IN_IP;
443 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
445 /* Prepare for parsing the first item */
446 info.hw_mask = &hw_mask;
447 info.len = pst->pattern->size;
452 npc_get_hw_supp_mask(pst, &info, lid, lt);
453 rc = npc_parse_item_basic(pst->pattern, &info);
458 * Parse for more labels.
459 * This sets lflags and pst->last_pattern correctly.
461 rc = npc_parse_mpls_label_stack(pst, &lflags);
466 pst->pattern = pst->last_pattern;
468 return npc_update_parse_state(pst, &info, lid, lt, lflags);
472 npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
474 const struct roc_npc_item_info *pattern = pst->pattern + 1;
476 pattern = npc_parse_skip_void_and_any_items(pattern);
477 if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
478 pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
479 pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
484 npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
485 struct npc_parse_state *pst, uint8_t *flags)
489 if (ipv6_spec->has_hop_ext) {
490 *flags = NPC_F_LC_L_EXT_HOP;
493 if (ipv6_spec->has_route_ext) {
494 *flags = NPC_F_LC_L_EXT_ROUT;
497 if (ipv6_spec->has_frag_ext) {
498 *flags = NPC_F_LC_U_IP6_FRAG;
501 if (ipv6_spec->has_dest_ext) {
502 *flags = NPC_F_LC_L_EXT_DEST;
505 if (ipv6_spec->has_mobil_ext) {
506 *flags = NPC_F_LC_L_EXT_MOBILITY;
509 if (ipv6_spec->has_hip_ext) {
510 *flags = NPC_F_LC_L_EXT_HOSTID;
513 if (ipv6_spec->has_shim6_ext) {
514 *flags = NPC_F_LC_L_EXT_SHIM6;
517 if (ipv6_spec->has_auth_ext) {
518 pst->lt[NPC_LID_LD] = NPC_LT_LD_AH;
521 if (ipv6_spec->has_esp_ext) {
522 pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP;
530 pst->set_ipv6ext_ltype_mask = true;
536 npc_parse_lc(struct npc_parse_state *pst)
538 const struct roc_npc_flow_item_ipv6 *ipv6_spec;
539 const struct roc_npc_flow_item_raw *raw_spec;
540 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
541 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
542 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
543 struct npc_parse_item_info info;
544 int rc, lid, lt, len = 0;
547 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
548 return npc_parse_mpls(pst, NPC_LID_LC);
550 info.hw_mask = &hw_mask;
556 switch (pst->pattern->type) {
557 case ROC_NPC_ITEM_TYPE_IPV4:
559 info.len = pst->pattern->size;
561 case ROC_NPC_ITEM_TYPE_IPV6:
562 ipv6_spec = pst->pattern->spec;
565 rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags);
568 info.len = sizeof(ipv6_spec->hdr);
570 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
572 info.len = pst->pattern->size;
574 case ROC_NPC_ITEM_TYPE_IPV6_EXT:
576 lt = NPC_LT_LC_IP6_EXT;
577 info.len = pst->pattern->size;
578 info.hw_hdr_len = 40;
580 case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
581 lt = NPC_LT_LC_CUSTOM0;
582 info.len = pst->pattern->size;
584 case ROC_NPC_ITEM_TYPE_RAW:
585 raw_spec = pst->pattern->spec;
586 if (!raw_spec->relative)
589 len = raw_spec->length + raw_spec->offset;
590 if (len > NPC_MAX_RAW_ITEM_LEN)
593 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
595 (const struct roc_npc_flow_item_raw *)
597 &info, raw_spec_buf, raw_mask_buf);
601 info.hw_mask = &hw_mask;
602 npc_get_hw_supp_mask(pst, &info, lid, lt);
605 /* No match at this layer */
609 /* Identify if IP tunnels MPLS or IPv4/v6 */
610 npc_check_lc_ip_tunnel(pst);
612 npc_get_hw_supp_mask(pst, &info, lid, lt);
613 rc = npc_parse_item_basic(pst->pattern, &info);
618 return npc_update_parse_state(pst, &info, lid, lt, flags);
622 npc_parse_ld(struct npc_parse_state *pst)
624 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
625 struct npc_parse_item_info info;
630 /* We have already parsed MPLS or IPv4/v6 followed
631 * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
632 * would be parsed as tunneled versions. Skip
633 * this layer, except for tunneled MPLS. If LC is
634 * MPLS, we have anyway skipped all stacked MPLS
637 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
638 return npc_parse_mpls(pst, NPC_LID_LD);
641 info.hw_mask = &hw_mask;
644 info.def_mask = NULL;
651 switch (pst->pattern->type) {
652 case ROC_NPC_ITEM_TYPE_ICMP:
653 if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
654 lt = NPC_LT_LD_ICMP6;
657 info.len = pst->pattern->size;
659 case ROC_NPC_ITEM_TYPE_UDP:
661 info.len = pst->pattern->size;
663 case ROC_NPC_ITEM_TYPE_IGMP:
665 info.len = pst->pattern->size;
667 case ROC_NPC_ITEM_TYPE_TCP:
669 info.len = pst->pattern->size;
671 case ROC_NPC_ITEM_TYPE_SCTP:
673 info.len = pst->pattern->size;
675 case ROC_NPC_ITEM_TYPE_GRE:
677 info.len = pst->pattern->size;
679 case ROC_NPC_ITEM_TYPE_GRE_KEY:
681 info.len = pst->pattern->size;
684 case ROC_NPC_ITEM_TYPE_NVGRE:
685 lt = NPC_LT_LD_NVGRE;
686 lflags = NPC_F_GRE_NVGRE;
687 info.len = pst->pattern->size;
688 /* Further IP/Ethernet are parsed as tunneled */
695 npc_get_hw_supp_mask(pst, &info, lid, lt);
696 rc = npc_parse_item_basic(pst->pattern, &info);
700 return npc_update_parse_state(pst, &info, lid, lt, lflags);
704 npc_parse_le(struct npc_parse_state *pst)
706 const struct roc_npc_item_info *pattern = pst->pattern;
707 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
708 struct npc_parse_item_info info;
715 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
716 return npc_parse_mpls(pst, NPC_LID_LE);
721 info.def_mask = NULL;
727 /* Ensure we are not matching anything in UDP */
728 rc = npc_parse_item_basic(pattern, &info);
732 info.hw_mask = &hw_mask;
733 pattern = npc_parse_skip_void_and_any_items(pattern);
734 switch (pattern->type) {
735 case ROC_NPC_ITEM_TYPE_VXLAN:
736 lflags = NPC_F_UDP_VXLAN;
737 info.len = pattern->size;
738 lt = NPC_LT_LE_VXLAN;
740 case ROC_NPC_ITEM_TYPE_GTPC:
741 lflags = NPC_F_UDP_GTP_GTPC;
742 info.len = pattern->size;
745 case ROC_NPC_ITEM_TYPE_GTPU:
746 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
747 info.len = pattern->size;
750 case ROC_NPC_ITEM_TYPE_GENEVE:
751 lflags = NPC_F_UDP_GENEVE;
752 info.len = pattern->size;
753 lt = NPC_LT_LE_GENEVE;
755 case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
756 lflags = NPC_F_UDP_VXLANGPE;
757 info.len = pattern->size;
758 lt = NPC_LT_LE_VXLANGPE;
760 case ROC_NPC_ITEM_TYPE_ESP:
762 info.len = pst->pattern->size;
770 npc_get_hw_supp_mask(pst, &info, lid, lt);
771 rc = npc_parse_item_basic(pattern, &info);
775 return npc_update_parse_state(pst, &info, lid, lt, lflags);
779 npc_parse_lf(struct npc_parse_state *pst)
781 const struct roc_npc_item_info *pattern, *last_pattern;
782 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
783 struct npc_parse_item_info info;
788 /* We hit this layer if there is a tunneling protocol */
792 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
796 lt = NPC_LT_LF_TU_ETHER;
799 /* No match support for vlan tags */
801 info.len = pst->pattern->size;
806 /* Look ahead and find out any VLAN tags. These can be
807 * detected but no data matching is available.
809 last_pattern = pst->pattern;
810 pattern = pst->pattern + 1;
811 pattern = npc_parse_skip_void_and_any_items(pattern);
812 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
814 last_pattern = pattern;
816 pattern = npc_parse_skip_void_and_any_items(pattern);
822 lflags = NPC_F_TU_ETHER_CTAG;
825 lflags = NPC_F_TU_ETHER_STAG_CTAG;
828 return NPC_ERR_PATTERN_NOTSUP;
831 info.hw_mask = &hw_mask;
832 info.len = pst->pattern->size;
834 npc_get_hw_supp_mask(pst, &info, lid, lt);
838 rc = npc_parse_item_basic(pst->pattern, &info);
842 pst->pattern = last_pattern;
844 return npc_update_parse_state(pst, &info, lid, lt, lflags);
848 npc_parse_lg(struct npc_parse_state *pst)
850 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
851 struct npc_parse_item_info info;
858 info.hw_mask = &hw_mask;
864 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
865 lt = NPC_LT_LG_TU_IP;
866 info.len = pst->pattern->size;
867 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
868 lt = NPC_LT_LG_TU_IP6;
869 info.len = pst->pattern->size;
871 /* There is no tunneled IP header */
875 npc_get_hw_supp_mask(pst, &info, lid, lt);
876 rc = npc_parse_item_basic(pst->pattern, &info);
880 return npc_update_parse_state(pst, &info, lid, lt, 0);
884 npc_parse_lh(struct npc_parse_state *pst)
886 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
887 struct npc_parse_item_info info;
894 info.hw_mask = &hw_mask;
900 switch (pst->pattern->type) {
901 case ROC_NPC_ITEM_TYPE_UDP:
902 lt = NPC_LT_LH_TU_UDP;
903 info.len = pst->pattern->size;
905 case ROC_NPC_ITEM_TYPE_TCP:
906 lt = NPC_LT_LH_TU_TCP;
907 info.len = pst->pattern->size;
909 case ROC_NPC_ITEM_TYPE_SCTP:
910 lt = NPC_LT_LH_TU_SCTP;
911 info.len = pst->pattern->size;
913 case ROC_NPC_ITEM_TYPE_ESP:
914 lt = NPC_LT_LH_TU_ESP;
915 info.len = pst->pattern->size;
921 npc_get_hw_supp_mask(pst, &info, lid, lt);
922 rc = npc_parse_item_basic(pst->pattern, &info);
926 return npc_update_parse_state(pst, &info, lid, lt, 0);