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_parse_cpt_hdr(struct npc_parse_state *pst)
27 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
28 struct npc_parse_item_info info;
32 /* Identify the pattern type into lid, lt */
33 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
37 lt = NPC_LT_LA_CPT_HDR;
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);
47 /* Basic validation of item parameters */
48 rc = npc_parse_item_basic(pst->pattern, &info);
52 /* Update pst if not validate only? clash check? */
53 return npc_update_parse_state(pst, &info, lid, lt, 0);
57 npc_parse_higig2_hdr(struct npc_parse_state *pst)
59 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
60 struct npc_parse_item_info info;
64 /* Identify the pattern type into lid, lt */
65 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
69 lt = NPC_LT_LA_HIGIG2_ETHER;
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;
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);
84 /* Basic validation of item parameters */
85 rc = npc_parse_item_basic(pst->pattern, &info);
89 /* Update pst if not validate only? clash check? */
90 return npc_update_parse_state(pst, &info, lid, lt, 0);
94 npc_parse_la(struct npc_parse_state *pst)
96 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
97 struct npc_parse_item_info info;
101 /* Identify the pattern type into lid, lt */
102 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
106 lt = NPC_LT_LA_ETHER;
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;
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;
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);
130 /* Basic validation of item parameters */
131 rc = npc_parse_item_basic(pst->pattern, &info);
135 /* Update pst if not validate only? clash check? */
136 return npc_update_parse_state(pst, &info, lid, lt, 0);
140 npc_parse_lb(struct npc_parse_state *pst)
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;
152 info.def_mask = NULL;
153 info.hw_hdr_len = NPC_TPID_LENGTH;
157 last_pattern = pattern;
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.
166 info.len = pst->pattern->size;
168 pattern = pst->pattern;
169 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
172 /* Basic validation of Second/Third vlan item */
174 rc = npc_parse_item_basic(pattern, &info);
178 last_pattern = pattern;
180 pattern = npc_parse_skip_void_and_any_items(pattern);
188 lt = NPC_LT_LB_STAG_QINQ;
189 lflags = NPC_F_STAG_CTAG;
192 lt = NPC_LT_LB_STAG_QINQ;
193 lflags = NPC_F_STAG_STAG_CTAG;
196 return NPC_ERR_PATTERN_NOTSUP;
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.
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 */
210 info.len = pattern->size;
211 rc = npc_parse_item_basic(pattern, &info);
215 lflags = NPC_F_ETAG_CTAG;
216 last_pattern = pattern;
218 info.len = pattern->size;
219 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
221 info.len = pst->pattern->size;
222 lt = NPC_LT_LB_STAG_QINQ;
223 lflags = NPC_F_STAG_CTAG;
228 info.hw_mask = &hw_mask;
231 npc_get_hw_supp_mask(pst, &info, lid, lt);
233 rc = npc_parse_item_basic(pst->pattern, &info);
237 /* Point pattern to last item consumed */
238 pst->pattern = last_pattern;
239 return npc_update_parse_state(pst, &info, lid, lt, lflags);
243 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
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;
253 * pst->pattern points to first MPLS label. We only check
254 * that subsequent labels do not have anything to match.
257 info.len = pattern->size;
261 info.def_mask = NULL;
263 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
266 /* Basic validation of Second/Third/Fourth mpls item */
268 rc = npc_parse_item_basic(pattern, &info);
272 pst->last_pattern = pattern;
274 pattern = npc_parse_skip_void_and_any_items(pattern);
277 if (nr_labels < 1 || nr_labels > 4)
278 return NPC_ERR_PATTERN_NOTSUP;
280 *flag = flag_list[nr_labels - 1];
285 npc_parse_mpls(struct npc_parse_state *pst, int lid)
287 /* Find number of MPLS labels */
288 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
289 struct npc_parse_item_info info;
295 if (lid == NPC_LID_LC)
297 else if (lid == NPC_LID_LD)
298 lt = NPC_LT_LD_TU_MPLS_IN_IP;
300 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
302 /* Prepare for parsing the first item */
303 info.hw_mask = &hw_mask;
304 info.len = pst->pattern->size;
309 npc_get_hw_supp_mask(pst, &info, lid, lt);
310 rc = npc_parse_item_basic(pst->pattern, &info);
315 * Parse for more labels.
316 * This sets lflags and pst->last_pattern correctly.
318 rc = npc_parse_mpls_label_stack(pst, &lflags);
323 pst->pattern = pst->last_pattern;
325 return npc_update_parse_state(pst, &info, lid, lt, lflags);
329 npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
331 const struct roc_npc_item_info *pattern = pst->pattern + 1;
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)
341 npc_parse_lc(struct npc_parse_state *pst)
343 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
344 struct npc_parse_item_info info;
348 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
349 return npc_parse_mpls(pst, NPC_LID_LC);
351 info.hw_mask = &hw_mask;
357 switch (pst->pattern->type) {
358 case ROC_NPC_ITEM_TYPE_IPV4:
360 info.len = pst->pattern->size;
362 case ROC_NPC_ITEM_TYPE_IPV6:
365 info.len = pst->pattern->size;
367 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
369 info.len = pst->pattern->size;
371 case ROC_NPC_ITEM_TYPE_IPV6_EXT:
373 lt = NPC_LT_LC_IP6_EXT;
374 info.len = pst->pattern->size;
375 info.hw_hdr_len = 40;
377 case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
378 lt = NPC_LT_LC_CUSTOM0;
379 info.len = pst->pattern->size;
382 /* No match at this layer */
386 /* Identify if IP tunnels MPLS or IPv4/v6 */
387 npc_check_lc_ip_tunnel(pst);
389 npc_get_hw_supp_mask(pst, &info, lid, lt);
390 rc = npc_parse_item_basic(pst->pattern, &info);
394 return npc_update_parse_state(pst, &info, lid, lt, 0);
398 npc_parse_ld(struct npc_parse_state *pst)
400 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
401 struct npc_parse_item_info info;
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
413 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
414 return npc_parse_mpls(pst, NPC_LID_LD);
417 info.hw_mask = &hw_mask;
420 info.def_mask = NULL;
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;
433 info.len = pst->pattern->size;
435 case ROC_NPC_ITEM_TYPE_UDP:
437 info.len = pst->pattern->size;
439 case ROC_NPC_ITEM_TYPE_IGMP:
441 info.len = pst->pattern->size;
443 case ROC_NPC_ITEM_TYPE_TCP:
445 info.len = pst->pattern->size;
447 case ROC_NPC_ITEM_TYPE_SCTP:
449 info.len = pst->pattern->size;
451 case ROC_NPC_ITEM_TYPE_GRE:
453 info.len = pst->pattern->size;
455 case ROC_NPC_ITEM_TYPE_GRE_KEY:
457 info.len = pst->pattern->size;
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 */
471 npc_get_hw_supp_mask(pst, &info, lid, lt);
472 rc = npc_parse_item_basic(pst->pattern, &info);
476 return npc_update_parse_state(pst, &info, lid, lt, lflags);
480 npc_parse_le(struct npc_parse_state *pst)
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;
491 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
492 return npc_parse_mpls(pst, NPC_LID_LE);
497 info.def_mask = NULL;
503 /* Ensure we are not matching anything in UDP */
504 rc = npc_parse_item_basic(pattern, &info);
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;
516 case ROC_NPC_ITEM_TYPE_GTPC:
517 lflags = NPC_F_UDP_GTP_GTPC;
518 info.len = pattern->size;
521 case ROC_NPC_ITEM_TYPE_GTPU:
522 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
523 info.len = pattern->size;
526 case ROC_NPC_ITEM_TYPE_GENEVE:
527 lflags = NPC_F_UDP_GENEVE;
528 info.len = pattern->size;
529 lt = NPC_LT_LE_GENEVE;
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;
536 case ROC_NPC_ITEM_TYPE_ESP:
538 info.len = pst->pattern->size;
546 npc_get_hw_supp_mask(pst, &info, lid, lt);
547 rc = npc_parse_item_basic(pattern, &info);
551 return npc_update_parse_state(pst, &info, lid, lt, lflags);
555 npc_parse_lf(struct npc_parse_state *pst)
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;
564 /* We hit this layer if there is a tunneling protocol */
568 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
572 lt = NPC_LT_LF_TU_ETHER;
575 /* No match support for vlan tags */
577 info.len = pst->pattern->size;
582 /* Look ahead and find out any VLAN tags. These can be
583 * detected but no data matching is available.
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) {
590 last_pattern = pattern;
592 pattern = npc_parse_skip_void_and_any_items(pattern);
598 lflags = NPC_F_TU_ETHER_CTAG;
601 lflags = NPC_F_TU_ETHER_STAG_CTAG;
604 return NPC_ERR_PATTERN_NOTSUP;
607 info.hw_mask = &hw_mask;
608 info.len = pst->pattern->size;
610 npc_get_hw_supp_mask(pst, &info, lid, lt);
614 rc = npc_parse_item_basic(pst->pattern, &info);
618 pst->pattern = last_pattern;
620 return npc_update_parse_state(pst, &info, lid, lt, lflags);
624 npc_parse_lg(struct npc_parse_state *pst)
626 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
627 struct npc_parse_item_info info;
634 info.hw_mask = &hw_mask;
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;
647 /* There is no tunneled IP header */
651 npc_get_hw_supp_mask(pst, &info, lid, lt);
652 rc = npc_parse_item_basic(pst->pattern, &info);
656 return npc_update_parse_state(pst, &info, lid, lt, 0);
660 npc_parse_lh(struct npc_parse_state *pst)
662 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
663 struct npc_parse_item_info info;
670 info.hw_mask = &hw_mask;
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;
681 case ROC_NPC_ITEM_TYPE_TCP:
682 lt = NPC_LT_LH_TU_TCP;
683 info.len = pst->pattern->size;
685 case ROC_NPC_ITEM_TYPE_SCTP:
686 lt = NPC_LT_LH_TU_SCTP;
687 info.len = pst->pattern->size;
689 case ROC_NPC_ITEM_TYPE_ESP:
690 lt = NPC_LT_LH_TU_ESP;
691 info.len = pst->pattern->size;
697 npc_get_hw_supp_mask(pst, &info, lid, lt);
698 rc = npc_parse_item_basic(pst->pattern, &info);
702 return npc_update_parse_state(pst, &info, lid, lt, 0);