net/mlx5: support meter PPS profile
[dpdk.git] / drivers / common / cnxk / roc_npc_parse.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 #include "roc_api.h"
5 #include "roc_priv.h"
6
7 const struct roc_npc_item_info *
8 npc_parse_skip_void_and_any_items(const struct roc_npc_item_info *pattern)
9 {
10         while ((pattern->type == ROC_NPC_ITEM_TYPE_VOID) ||
11                (pattern->type == ROC_NPC_ITEM_TYPE_ANY))
12                 pattern++;
13
14         return pattern;
15 }
16
17 int
18 npc_parse_meta_items(struct npc_parse_state *pst)
19 {
20         PLT_SET_USED(pst);
21         return 0;
22 }
23
24 int
25 npc_parse_cpt_hdr(struct npc_parse_state *pst)
26 {
27         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
28         struct npc_parse_item_info info;
29         int lid, lt;
30         int rc;
31
32         /* Identify the pattern type into lid, lt */
33         if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
34                 return 0;
35
36         lid = NPC_LID_LA;
37         lt = NPC_LT_LA_CPT_HDR;
38         info.hw_hdr_len = 0;
39
40         /* Prepare for parsing the item */
41         info.hw_mask = &hw_mask;
42         info.len = pst->pattern->size;
43         npc_get_hw_supp_mask(pst, &info, lid, lt);
44         info.spec = NULL;
45         info.mask = NULL;
46
47         /* Basic validation of item parameters */
48         rc = npc_parse_item_basic(pst->pattern, &info);
49         if (rc)
50                 return rc;
51
52         /* Update pst if not validate only? clash check? */
53         return npc_update_parse_state(pst, &info, lid, lt, 0);
54 }
55
56 int
57 npc_parse_higig2_hdr(struct npc_parse_state *pst)
58 {
59         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
60         struct npc_parse_item_info info;
61         int lid, lt;
62         int rc;
63
64         /* Identify the pattern type into lid, lt */
65         if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
66                 return 0;
67
68         lid = NPC_LID_LA;
69         lt = NPC_LT_LA_HIGIG2_ETHER;
70         info.hw_hdr_len = 0;
71
72         if (pst->flow->nix_intf == NIX_INTF_TX) {
73                 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
74                 info.hw_hdr_len = NPC_IH_LENGTH;
75         }
76
77         /* Prepare for parsing the item */
78         info.hw_mask = &hw_mask;
79         info.len = pst->pattern->size;
80         npc_get_hw_supp_mask(pst, &info, lid, lt);
81         info.spec = NULL;
82         info.mask = NULL;
83
84         /* Basic validation of item parameters */
85         rc = npc_parse_item_basic(pst->pattern, &info);
86         if (rc)
87                 return rc;
88
89         /* Update pst if not validate only? clash check? */
90         return npc_update_parse_state(pst, &info, lid, lt, 0);
91 }
92
93 int
94 npc_parse_la(struct npc_parse_state *pst)
95 {
96         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
97         struct npc_parse_item_info info;
98         int lid, lt;
99         int rc;
100
101         /* Identify the pattern type into lid, lt */
102         if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
103                 return 0;
104
105         lid = NPC_LID_LA;
106         lt = NPC_LT_LA_ETHER;
107         info.hw_hdr_len = 0;
108
109         if (pst->flow->nix_intf == NIX_INTF_TX) {
110                 lt = NPC_LT_LA_IH_NIX_ETHER;
111                 info.hw_hdr_len = NPC_IH_LENGTH;
112                 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
113                         lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
114                         info.hw_hdr_len += NPC_HIGIG2_LENGTH;
115                 }
116         } else {
117                 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
118                         lt = NPC_LT_LA_HIGIG2_ETHER;
119                         info.hw_hdr_len = NPC_HIGIG2_LENGTH;
120                 }
121         }
122
123         /* Prepare for parsing the item */
124         info.hw_mask = &hw_mask;
125         info.len = pst->pattern->size;
126         npc_get_hw_supp_mask(pst, &info, lid, lt);
127         info.spec = NULL;
128         info.mask = NULL;
129
130         /* Basic validation of item parameters */
131         rc = npc_parse_item_basic(pst->pattern, &info);
132         if (rc)
133                 return rc;
134
135         /* Update pst if not validate only? clash check? */
136         return npc_update_parse_state(pst, &info, lid, lt, 0);
137 }
138
139 int
140 npc_parse_lb(struct npc_parse_state *pst)
141 {
142         const struct roc_npc_item_info *pattern = pst->pattern;
143         const struct roc_npc_item_info *last_pattern;
144         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
145         struct npc_parse_item_info info;
146         int lid, lt, lflags;
147         int nr_vlans = 0;
148         int rc;
149
150         info.spec = NULL;
151         info.mask = NULL;
152         info.def_mask = NULL;
153         info.hw_hdr_len = NPC_TPID_LENGTH;
154
155         lid = NPC_LID_LB;
156         lflags = 0;
157         last_pattern = pattern;
158
159         if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
160                 /* RTE vlan is either 802.1q or 802.1ad,
161                  * this maps to either CTAG/STAG. We need to decide
162                  * based on number of VLANS present. Matching is
163                  * supported on first tag only.
164                  */
165                 info.hw_mask = NULL;
166                 info.len = pst->pattern->size;
167
168                 pattern = pst->pattern;
169                 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
170                         nr_vlans++;
171
172                         /* Basic validation of Second/Third vlan item */
173                         if (nr_vlans > 1) {
174                                 rc = npc_parse_item_basic(pattern, &info);
175                                 if (rc != 0)
176                                         return rc;
177                         }
178                         last_pattern = pattern;
179                         pattern++;
180                         pattern = npc_parse_skip_void_and_any_items(pattern);
181                 }
182
183                 switch (nr_vlans) {
184                 case 1:
185                         lt = NPC_LT_LB_CTAG;
186                         break;
187                 case 2:
188                         lt = NPC_LT_LB_STAG_QINQ;
189                         lflags = NPC_F_STAG_CTAG;
190                         break;
191                 case 3:
192                         lt = NPC_LT_LB_STAG_QINQ;
193                         lflags = NPC_F_STAG_STAG_CTAG;
194                         break;
195                 default:
196                         return NPC_ERR_PATTERN_NOTSUP;
197                 }
198         } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
199                 /* we can support ETAG and match a subsequent CTAG
200                  * without any matching support.
201                  */
202                 lt = NPC_LT_LB_ETAG;
203                 lflags = 0;
204
205                 last_pattern = pst->pattern;
206                 pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
207                 if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
208                         /* set supported mask to NULL for vlan tag */
209                         info.hw_mask = NULL;
210                         info.len = pattern->size;
211                         rc = npc_parse_item_basic(pattern, &info);
212                         if (rc != 0)
213                                 return rc;
214
215                         lflags = NPC_F_ETAG_CTAG;
216                         last_pattern = pattern;
217                 }
218                 info.len = pattern->size;
219         } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
220                 info.hw_mask = NULL;
221                 info.len = pst->pattern->size;
222                 lt = NPC_LT_LB_STAG_QINQ;
223                 lflags = NPC_F_STAG_CTAG;
224         } else {
225                 return 0;
226         }
227
228         info.hw_mask = &hw_mask;
229         info.spec = NULL;
230         info.mask = NULL;
231         npc_get_hw_supp_mask(pst, &info, lid, lt);
232
233         rc = npc_parse_item_basic(pst->pattern, &info);
234         if (rc != 0)
235                 return rc;
236
237         /* Point pattern to last item consumed */
238         pst->pattern = last_pattern;
239         return npc_update_parse_state(pst, &info, lid, lt, lflags);
240 }
241
242 static int
243 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
244 {
245         uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
246                                NPC_F_MPLS_4_LABELS};
247         const struct roc_npc_item_info *pattern = pst->pattern;
248         struct npc_parse_item_info info;
249         int nr_labels = 0;
250         int rc;
251
252         /*
253          * pst->pattern points to first MPLS label. We only check
254          * that subsequent labels do not have anything to match.
255          */
256         info.hw_mask = NULL;
257         info.len = pattern->size;
258         info.spec = NULL;
259         info.mask = NULL;
260         info.hw_hdr_len = 0;
261         info.def_mask = NULL;
262
263         while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
264                 nr_labels++;
265
266                 /* Basic validation of Second/Third/Fourth mpls item */
267                 if (nr_labels > 1) {
268                         rc = npc_parse_item_basic(pattern, &info);
269                         if (rc != 0)
270                                 return rc;
271                 }
272                 pst->last_pattern = pattern;
273                 pattern++;
274                 pattern = npc_parse_skip_void_and_any_items(pattern);
275         }
276
277         if (nr_labels < 1 || nr_labels > 4)
278                 return NPC_ERR_PATTERN_NOTSUP;
279
280         *flag = flag_list[nr_labels - 1];
281         return 0;
282 }
283
284 static int
285 npc_parse_mpls(struct npc_parse_state *pst, int lid)
286 {
287         /* Find number of MPLS labels */
288         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
289         struct npc_parse_item_info info;
290         int lt, lflags;
291         int rc;
292
293         lflags = 0;
294
295         if (lid == NPC_LID_LC)
296                 lt = NPC_LT_LC_MPLS;
297         else if (lid == NPC_LID_LD)
298                 lt = NPC_LT_LD_TU_MPLS_IN_IP;
299         else
300                 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
301
302         /* Prepare for parsing the first item */
303         info.hw_mask = &hw_mask;
304         info.len = pst->pattern->size;
305         info.spec = NULL;
306         info.mask = NULL;
307         info.hw_hdr_len = 0;
308
309         npc_get_hw_supp_mask(pst, &info, lid, lt);
310         rc = npc_parse_item_basic(pst->pattern, &info);
311         if (rc != 0)
312                 return rc;
313
314         /*
315          * Parse for more labels.
316          * This sets lflags and pst->last_pattern correctly.
317          */
318         rc = npc_parse_mpls_label_stack(pst, &lflags);
319         if (rc != 0)
320                 return rc;
321
322         pst->tunnel = 1;
323         pst->pattern = pst->last_pattern;
324
325         return npc_update_parse_state(pst, &info, lid, lt, lflags);
326 }
327
328 static inline void
329 npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
330 {
331         const struct roc_npc_item_info *pattern = pst->pattern + 1;
332
333         pattern = npc_parse_skip_void_and_any_items(pattern);
334         if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
335             pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
336             pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
337                 pst->tunnel = 1;
338 }
339
340 int
341 npc_parse_lc(struct npc_parse_state *pst)
342 {
343         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
344         struct npc_parse_item_info info;
345         int lid, lt;
346         int rc;
347
348         if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
349                 return npc_parse_mpls(pst, NPC_LID_LC);
350
351         info.hw_mask = &hw_mask;
352         info.spec = NULL;
353         info.mask = NULL;
354         info.hw_hdr_len = 0;
355         lid = NPC_LID_LC;
356
357         switch (pst->pattern->type) {
358         case ROC_NPC_ITEM_TYPE_IPV4:
359                 lt = NPC_LT_LC_IP;
360                 info.len = pst->pattern->size;
361                 break;
362         case ROC_NPC_ITEM_TYPE_IPV6:
363                 lid = NPC_LID_LC;
364                 lt = NPC_LT_LC_IP6;
365                 info.len = pst->pattern->size;
366                 break;
367         case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
368                 lt = NPC_LT_LC_ARP;
369                 info.len = pst->pattern->size;
370                 break;
371         case ROC_NPC_ITEM_TYPE_IPV6_EXT:
372                 lid = NPC_LID_LC;
373                 lt = NPC_LT_LC_IP6_EXT;
374                 info.len = pst->pattern->size;
375                 info.hw_hdr_len = 40;
376                 break;
377         case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
378                 lt = NPC_LT_LC_CUSTOM0;
379                 info.len = pst->pattern->size;
380                 break;
381         default:
382                 /* No match at this layer */
383                 return 0;
384         }
385
386         /* Identify if IP tunnels MPLS or IPv4/v6 */
387         npc_check_lc_ip_tunnel(pst);
388
389         npc_get_hw_supp_mask(pst, &info, lid, lt);
390         rc = npc_parse_item_basic(pst->pattern, &info);
391         if (rc != 0)
392                 return rc;
393
394         return npc_update_parse_state(pst, &info, lid, lt, 0);
395 }
396
397 int
398 npc_parse_ld(struct npc_parse_state *pst)
399 {
400         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
401         struct npc_parse_item_info info;
402         int lid, lt, lflags;
403         int rc;
404
405         if (pst->tunnel) {
406                 /* We have already parsed MPLS or IPv4/v6 followed
407                  * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
408                  * would be parsed as tunneled versions. Skip
409                  * this layer, except for tunneled MPLS. If LC is
410                  * MPLS, we have anyway skipped all stacked MPLS
411                  * labels.
412                  */
413                 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
414                         return npc_parse_mpls(pst, NPC_LID_LD);
415                 return 0;
416         }
417         info.hw_mask = &hw_mask;
418         info.spec = NULL;
419         info.mask = NULL;
420         info.def_mask = NULL;
421         info.len = 0;
422         info.hw_hdr_len = 0;
423
424         lid = NPC_LID_LD;
425         lflags = 0;
426
427         switch (pst->pattern->type) {
428         case ROC_NPC_ITEM_TYPE_ICMP:
429                 if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
430                         lt = NPC_LT_LD_ICMP6;
431                 else
432                         lt = NPC_LT_LD_ICMP;
433                 info.len = pst->pattern->size;
434                 break;
435         case ROC_NPC_ITEM_TYPE_UDP:
436                 lt = NPC_LT_LD_UDP;
437                 info.len = pst->pattern->size;
438                 break;
439         case ROC_NPC_ITEM_TYPE_IGMP:
440                 lt = NPC_LT_LD_IGMP;
441                 info.len = pst->pattern->size;
442                 break;
443         case ROC_NPC_ITEM_TYPE_TCP:
444                 lt = NPC_LT_LD_TCP;
445                 info.len = pst->pattern->size;
446                 break;
447         case ROC_NPC_ITEM_TYPE_SCTP:
448                 lt = NPC_LT_LD_SCTP;
449                 info.len = pst->pattern->size;
450                 break;
451         case ROC_NPC_ITEM_TYPE_GRE:
452                 lt = NPC_LT_LD_GRE;
453                 info.len = pst->pattern->size;
454                 break;
455         case ROC_NPC_ITEM_TYPE_GRE_KEY:
456                 lt = NPC_LT_LD_GRE;
457                 info.len = pst->pattern->size;
458                 info.hw_hdr_len = 4;
459                 break;
460         case ROC_NPC_ITEM_TYPE_NVGRE:
461                 lt = NPC_LT_LD_NVGRE;
462                 lflags = NPC_F_GRE_NVGRE;
463                 info.len = pst->pattern->size;
464                 /* Further IP/Ethernet are parsed as tunneled */
465                 pst->tunnel = 1;
466                 break;
467         default:
468                 return 0;
469         }
470
471         npc_get_hw_supp_mask(pst, &info, lid, lt);
472         rc = npc_parse_item_basic(pst->pattern, &info);
473         if (rc != 0)
474                 return rc;
475
476         return npc_update_parse_state(pst, &info, lid, lt, lflags);
477 }
478
479 int
480 npc_parse_le(struct npc_parse_state *pst)
481 {
482         const struct roc_npc_item_info *pattern = pst->pattern;
483         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
484         struct npc_parse_item_info info;
485         int lid, lt, lflags;
486         int rc;
487
488         if (pst->tunnel)
489                 return 0;
490
491         if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
492                 return npc_parse_mpls(pst, NPC_LID_LE);
493
494         info.spec = NULL;
495         info.mask = NULL;
496         info.hw_mask = NULL;
497         info.def_mask = NULL;
498         info.len = 0;
499         info.hw_hdr_len = 0;
500         lid = NPC_LID_LE;
501         lflags = 0;
502
503         /* Ensure we are not matching anything in UDP */
504         rc = npc_parse_item_basic(pattern, &info);
505         if (rc)
506                 return rc;
507
508         info.hw_mask = &hw_mask;
509         pattern = npc_parse_skip_void_and_any_items(pattern);
510         switch (pattern->type) {
511         case ROC_NPC_ITEM_TYPE_VXLAN:
512                 lflags = NPC_F_UDP_VXLAN;
513                 info.len = pattern->size;
514                 lt = NPC_LT_LE_VXLAN;
515                 break;
516         case ROC_NPC_ITEM_TYPE_GTPC:
517                 lflags = NPC_F_UDP_GTP_GTPC;
518                 info.len = pattern->size;
519                 lt = NPC_LT_LE_GTPC;
520                 break;
521         case ROC_NPC_ITEM_TYPE_GTPU:
522                 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
523                 info.len = pattern->size;
524                 lt = NPC_LT_LE_GTPU;
525                 break;
526         case ROC_NPC_ITEM_TYPE_GENEVE:
527                 lflags = NPC_F_UDP_GENEVE;
528                 info.len = pattern->size;
529                 lt = NPC_LT_LE_GENEVE;
530                 break;
531         case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
532                 lflags = NPC_F_UDP_VXLANGPE;
533                 info.len = pattern->size;
534                 lt = NPC_LT_LE_VXLANGPE;
535                 break;
536         case ROC_NPC_ITEM_TYPE_ESP:
537                 lt = NPC_LT_LE_ESP;
538                 info.len = pst->pattern->size;
539                 break;
540         default:
541                 return 0;
542         }
543
544         pst->tunnel = 1;
545
546         npc_get_hw_supp_mask(pst, &info, lid, lt);
547         rc = npc_parse_item_basic(pattern, &info);
548         if (rc != 0)
549                 return rc;
550
551         return npc_update_parse_state(pst, &info, lid, lt, lflags);
552 }
553
554 int
555 npc_parse_lf(struct npc_parse_state *pst)
556 {
557         const struct roc_npc_item_info *pattern, *last_pattern;
558         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
559         struct npc_parse_item_info info;
560         int lid, lt, lflags;
561         int nr_vlans = 0;
562         int rc;
563
564         /* We hit this layer if there is a tunneling protocol */
565         if (!pst->tunnel)
566                 return 0;
567
568         if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
569                 return 0;
570
571         lid = NPC_LID_LF;
572         lt = NPC_LT_LF_TU_ETHER;
573         lflags = 0;
574
575         /* No match support for vlan tags */
576         info.hw_mask = NULL;
577         info.len = pst->pattern->size;
578         info.spec = NULL;
579         info.mask = NULL;
580         info.hw_hdr_len = 0;
581
582         /* Look ahead and find out any VLAN tags. These can be
583          * detected but no data matching is available.
584          */
585         last_pattern = pst->pattern;
586         pattern = pst->pattern + 1;
587         pattern = npc_parse_skip_void_and_any_items(pattern);
588         while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
589                 nr_vlans++;
590                 last_pattern = pattern;
591                 pattern++;
592                 pattern = npc_parse_skip_void_and_any_items(pattern);
593         }
594         switch (nr_vlans) {
595         case 0:
596                 break;
597         case 1:
598                 lflags = NPC_F_TU_ETHER_CTAG;
599                 break;
600         case 2:
601                 lflags = NPC_F_TU_ETHER_STAG_CTAG;
602                 break;
603         default:
604                 return NPC_ERR_PATTERN_NOTSUP;
605         }
606
607         info.hw_mask = &hw_mask;
608         info.len = pst->pattern->size;
609         info.hw_hdr_len = 0;
610         npc_get_hw_supp_mask(pst, &info, lid, lt);
611         info.spec = NULL;
612         info.mask = NULL;
613
614         rc = npc_parse_item_basic(pst->pattern, &info);
615         if (rc != 0)
616                 return rc;
617
618         pst->pattern = last_pattern;
619
620         return npc_update_parse_state(pst, &info, lid, lt, lflags);
621 }
622
623 int
624 npc_parse_lg(struct npc_parse_state *pst)
625 {
626         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
627         struct npc_parse_item_info info;
628         int lid, lt;
629         int rc;
630
631         if (!pst->tunnel)
632                 return 0;
633
634         info.hw_mask = &hw_mask;
635         info.spec = NULL;
636         info.mask = NULL;
637         info.hw_hdr_len = 0;
638         lid = NPC_LID_LG;
639
640         if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
641                 lt = NPC_LT_LG_TU_IP;
642                 info.len = pst->pattern->size;
643         } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
644                 lt = NPC_LT_LG_TU_IP6;
645                 info.len = pst->pattern->size;
646         } else {
647                 /* There is no tunneled IP header */
648                 return 0;
649         }
650
651         npc_get_hw_supp_mask(pst, &info, lid, lt);
652         rc = npc_parse_item_basic(pst->pattern, &info);
653         if (rc != 0)
654                 return rc;
655
656         return npc_update_parse_state(pst, &info, lid, lt, 0);
657 }
658
659 int
660 npc_parse_lh(struct npc_parse_state *pst)
661 {
662         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
663         struct npc_parse_item_info info;
664         int lid, lt;
665         int rc;
666
667         if (!pst->tunnel)
668                 return 0;
669
670         info.hw_mask = &hw_mask;
671         info.spec = NULL;
672         info.mask = NULL;
673         info.hw_hdr_len = 0;
674         lid = NPC_LID_LH;
675
676         switch (pst->pattern->type) {
677         case ROC_NPC_ITEM_TYPE_UDP:
678                 lt = NPC_LT_LH_TU_UDP;
679                 info.len = pst->pattern->size;
680                 break;
681         case ROC_NPC_ITEM_TYPE_TCP:
682                 lt = NPC_LT_LH_TU_TCP;
683                 info.len = pst->pattern->size;
684                 break;
685         case ROC_NPC_ITEM_TYPE_SCTP:
686                 lt = NPC_LT_LH_TU_SCTP;
687                 info.len = pst->pattern->size;
688                 break;
689         case ROC_NPC_ITEM_TYPE_ESP:
690                 lt = NPC_LT_LH_TU_ESP;
691                 info.len = pst->pattern->size;
692                 break;
693         default:
694                 return 0;
695         }
696
697         npc_get_hw_supp_mask(pst, &info, lid, lt);
698         rc = npc_parse_item_basic(pst->pattern, &info);
699         if (rc != 0)
700                 return rc;
701
702         return npc_update_parse_state(pst, &info, lid, lt, 0);
703 }