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_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
141 const struct roc_npc_flow_item_raw *raw_mask,
142 struct npc_parse_item_info *info, uint8_t *spec_buf,
145 uint32_t custom_hdr_size = 0;
147 memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
148 memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
149 custom_hdr_size = raw_spec->offset + raw_spec->length;
151 memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
154 if (raw_mask->pattern) {
155 memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
158 memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
161 info->len = custom_hdr_size;
162 info->spec = spec_buf;
163 info->mask = mask_buf;
169 npc_parse_lb(struct npc_parse_state *pst)
171 const struct roc_npc_item_info *pattern = pst->pattern;
172 const struct roc_npc_item_info *last_pattern;
173 const struct roc_npc_flow_item_raw *raw_spec;
174 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
175 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
176 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
177 struct npc_parse_item_info info;
178 int lid, lt, lflags, len = 0;
184 info.def_mask = NULL;
185 info.hw_hdr_len = NPC_TPID_LENGTH;
189 last_pattern = pattern;
191 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
192 /* RTE vlan is either 802.1q or 802.1ad,
193 * this maps to either CTAG/STAG. We need to decide
194 * based on number of VLANS present. Matching is
195 * supported on first tag only.
198 info.len = pst->pattern->size;
200 pattern = pst->pattern;
201 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
204 /* Basic validation of Second/Third vlan item */
206 rc = npc_parse_item_basic(pattern, &info);
210 last_pattern = pattern;
212 pattern = npc_parse_skip_void_and_any_items(pattern);
220 lt = NPC_LT_LB_STAG_QINQ;
221 lflags = NPC_F_STAG_CTAG;
224 lt = NPC_LT_LB_STAG_QINQ;
225 lflags = NPC_F_STAG_STAG_CTAG;
228 return NPC_ERR_PATTERN_NOTSUP;
230 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
231 /* we can support ETAG and match a subsequent CTAG
232 * without any matching support.
237 last_pattern = pst->pattern;
238 pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
239 if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
240 /* set supported mask to NULL for vlan tag */
242 info.len = pattern->size;
243 rc = npc_parse_item_basic(pattern, &info);
247 lflags = NPC_F_ETAG_CTAG;
248 last_pattern = pattern;
250 info.len = pattern->size;
251 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
253 info.len = pst->pattern->size;
254 lt = NPC_LT_LB_STAG_QINQ;
255 lflags = NPC_F_STAG_CTAG;
256 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
257 raw_spec = pst->pattern->spec;
258 if (raw_spec->relative)
260 len = raw_spec->length + raw_spec->offset;
261 if (len > NPC_MAX_RAW_ITEM_LEN)
264 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
265 lt = NPC_LT_LB_VLAN_EXDSA;
266 } else if (pst->npc->switch_header_type ==
267 ROC_PRIV_FLAGS_EXDSA) {
268 lt = NPC_LT_LB_EXDSA;
273 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
275 (const struct roc_npc_flow_item_raw *)
277 &info, raw_spec_buf, raw_mask_buf);
284 info.hw_mask = &hw_mask;
285 npc_get_hw_supp_mask(pst, &info, lid, lt);
287 rc = npc_parse_item_basic(pst->pattern, &info);
291 /* Point pattern to last item consumed */
292 pst->pattern = last_pattern;
293 return npc_update_parse_state(pst, &info, lid, lt, lflags);
297 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
299 uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
300 NPC_F_MPLS_4_LABELS};
301 const struct roc_npc_item_info *pattern = pst->pattern;
302 struct npc_parse_item_info info;
307 * pst->pattern points to first MPLS label. We only check
308 * that subsequent labels do not have anything to match.
311 info.len = pattern->size;
315 info.def_mask = NULL;
317 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
320 /* Basic validation of Second/Third/Fourth mpls item */
322 rc = npc_parse_item_basic(pattern, &info);
326 pst->last_pattern = pattern;
328 pattern = npc_parse_skip_void_and_any_items(pattern);
331 if (nr_labels < 1 || nr_labels > 4)
332 return NPC_ERR_PATTERN_NOTSUP;
334 *flag = flag_list[nr_labels - 1];
339 npc_parse_mpls(struct npc_parse_state *pst, int lid)
341 /* Find number of MPLS labels */
342 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
343 struct npc_parse_item_info info;
349 if (lid == NPC_LID_LC)
351 else if (lid == NPC_LID_LD)
352 lt = NPC_LT_LD_TU_MPLS_IN_IP;
354 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
356 /* Prepare for parsing the first item */
357 info.hw_mask = &hw_mask;
358 info.len = pst->pattern->size;
363 npc_get_hw_supp_mask(pst, &info, lid, lt);
364 rc = npc_parse_item_basic(pst->pattern, &info);
369 * Parse for more labels.
370 * This sets lflags and pst->last_pattern correctly.
372 rc = npc_parse_mpls_label_stack(pst, &lflags);
377 pst->pattern = pst->last_pattern;
379 return npc_update_parse_state(pst, &info, lid, lt, lflags);
383 npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
385 const struct roc_npc_item_info *pattern = pst->pattern + 1;
387 pattern = npc_parse_skip_void_and_any_items(pattern);
388 if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
389 pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
390 pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
395 npc_parse_lc(struct npc_parse_state *pst)
397 const struct roc_npc_flow_item_raw *raw_spec;
398 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
399 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
400 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
401 struct npc_parse_item_info info;
402 int lid, lt, len = 0;
405 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
406 return npc_parse_mpls(pst, NPC_LID_LC);
408 info.hw_mask = &hw_mask;
414 switch (pst->pattern->type) {
415 case ROC_NPC_ITEM_TYPE_IPV4:
417 info.len = pst->pattern->size;
419 case ROC_NPC_ITEM_TYPE_IPV6:
422 info.len = pst->pattern->size;
424 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
426 info.len = pst->pattern->size;
428 case ROC_NPC_ITEM_TYPE_IPV6_EXT:
430 lt = NPC_LT_LC_IP6_EXT;
431 info.len = pst->pattern->size;
432 info.hw_hdr_len = 40;
434 case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
435 lt = NPC_LT_LC_CUSTOM0;
436 info.len = pst->pattern->size;
438 case ROC_NPC_ITEM_TYPE_RAW:
439 raw_spec = pst->pattern->spec;
440 if (!raw_spec->relative)
443 len = raw_spec->length + raw_spec->offset;
444 if (len > NPC_MAX_RAW_ITEM_LEN)
447 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
449 (const struct roc_npc_flow_item_raw *)
451 &info, raw_spec_buf, raw_mask_buf);
455 info.hw_mask = &hw_mask;
456 npc_get_hw_supp_mask(pst, &info, lid, lt);
459 /* No match at this layer */
463 /* Identify if IP tunnels MPLS or IPv4/v6 */
464 npc_check_lc_ip_tunnel(pst);
466 npc_get_hw_supp_mask(pst, &info, lid, lt);
467 rc = npc_parse_item_basic(pst->pattern, &info);
472 return npc_update_parse_state(pst, &info, lid, lt, 0);
476 npc_parse_ld(struct npc_parse_state *pst)
478 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
479 struct npc_parse_item_info info;
484 /* We have already parsed MPLS or IPv4/v6 followed
485 * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
486 * would be parsed as tunneled versions. Skip
487 * this layer, except for tunneled MPLS. If LC is
488 * MPLS, we have anyway skipped all stacked MPLS
491 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
492 return npc_parse_mpls(pst, NPC_LID_LD);
495 info.hw_mask = &hw_mask;
498 info.def_mask = NULL;
505 switch (pst->pattern->type) {
506 case ROC_NPC_ITEM_TYPE_ICMP:
507 if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
508 lt = NPC_LT_LD_ICMP6;
511 info.len = pst->pattern->size;
513 case ROC_NPC_ITEM_TYPE_UDP:
515 info.len = pst->pattern->size;
517 case ROC_NPC_ITEM_TYPE_IGMP:
519 info.len = pst->pattern->size;
521 case ROC_NPC_ITEM_TYPE_TCP:
523 info.len = pst->pattern->size;
525 case ROC_NPC_ITEM_TYPE_SCTP:
527 info.len = pst->pattern->size;
529 case ROC_NPC_ITEM_TYPE_GRE:
531 info.len = pst->pattern->size;
533 case ROC_NPC_ITEM_TYPE_GRE_KEY:
535 info.len = pst->pattern->size;
538 case ROC_NPC_ITEM_TYPE_NVGRE:
539 lt = NPC_LT_LD_NVGRE;
540 lflags = NPC_F_GRE_NVGRE;
541 info.len = pst->pattern->size;
542 /* Further IP/Ethernet are parsed as tunneled */
549 npc_get_hw_supp_mask(pst, &info, lid, lt);
550 rc = npc_parse_item_basic(pst->pattern, &info);
554 return npc_update_parse_state(pst, &info, lid, lt, lflags);
558 npc_parse_le(struct npc_parse_state *pst)
560 const struct roc_npc_item_info *pattern = pst->pattern;
561 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
562 struct npc_parse_item_info info;
569 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
570 return npc_parse_mpls(pst, NPC_LID_LE);
575 info.def_mask = NULL;
581 /* Ensure we are not matching anything in UDP */
582 rc = npc_parse_item_basic(pattern, &info);
586 info.hw_mask = &hw_mask;
587 pattern = npc_parse_skip_void_and_any_items(pattern);
588 switch (pattern->type) {
589 case ROC_NPC_ITEM_TYPE_VXLAN:
590 lflags = NPC_F_UDP_VXLAN;
591 info.len = pattern->size;
592 lt = NPC_LT_LE_VXLAN;
594 case ROC_NPC_ITEM_TYPE_GTPC:
595 lflags = NPC_F_UDP_GTP_GTPC;
596 info.len = pattern->size;
599 case ROC_NPC_ITEM_TYPE_GTPU:
600 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
601 info.len = pattern->size;
604 case ROC_NPC_ITEM_TYPE_GENEVE:
605 lflags = NPC_F_UDP_GENEVE;
606 info.len = pattern->size;
607 lt = NPC_LT_LE_GENEVE;
609 case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
610 lflags = NPC_F_UDP_VXLANGPE;
611 info.len = pattern->size;
612 lt = NPC_LT_LE_VXLANGPE;
614 case ROC_NPC_ITEM_TYPE_ESP:
616 info.len = pst->pattern->size;
624 npc_get_hw_supp_mask(pst, &info, lid, lt);
625 rc = npc_parse_item_basic(pattern, &info);
629 return npc_update_parse_state(pst, &info, lid, lt, lflags);
633 npc_parse_lf(struct npc_parse_state *pst)
635 const struct roc_npc_item_info *pattern, *last_pattern;
636 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
637 struct npc_parse_item_info info;
642 /* We hit this layer if there is a tunneling protocol */
646 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
650 lt = NPC_LT_LF_TU_ETHER;
653 /* No match support for vlan tags */
655 info.len = pst->pattern->size;
660 /* Look ahead and find out any VLAN tags. These can be
661 * detected but no data matching is available.
663 last_pattern = pst->pattern;
664 pattern = pst->pattern + 1;
665 pattern = npc_parse_skip_void_and_any_items(pattern);
666 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
668 last_pattern = pattern;
670 pattern = npc_parse_skip_void_and_any_items(pattern);
676 lflags = NPC_F_TU_ETHER_CTAG;
679 lflags = NPC_F_TU_ETHER_STAG_CTAG;
682 return NPC_ERR_PATTERN_NOTSUP;
685 info.hw_mask = &hw_mask;
686 info.len = pst->pattern->size;
688 npc_get_hw_supp_mask(pst, &info, lid, lt);
692 rc = npc_parse_item_basic(pst->pattern, &info);
696 pst->pattern = last_pattern;
698 return npc_update_parse_state(pst, &info, lid, lt, lflags);
702 npc_parse_lg(struct npc_parse_state *pst)
704 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
705 struct npc_parse_item_info info;
712 info.hw_mask = &hw_mask;
718 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
719 lt = NPC_LT_LG_TU_IP;
720 info.len = pst->pattern->size;
721 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
722 lt = NPC_LT_LG_TU_IP6;
723 info.len = pst->pattern->size;
725 /* There is no tunneled IP header */
729 npc_get_hw_supp_mask(pst, &info, lid, lt);
730 rc = npc_parse_item_basic(pst->pattern, &info);
734 return npc_update_parse_state(pst, &info, lid, lt, 0);
738 npc_parse_lh(struct npc_parse_state *pst)
740 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
741 struct npc_parse_item_info info;
748 info.hw_mask = &hw_mask;
754 switch (pst->pattern->type) {
755 case ROC_NPC_ITEM_TYPE_UDP:
756 lt = NPC_LT_LH_TU_UDP;
757 info.len = pst->pattern->size;
759 case ROC_NPC_ITEM_TYPE_TCP:
760 lt = NPC_LT_LH_TU_TCP;
761 info.len = pst->pattern->size;
763 case ROC_NPC_ITEM_TYPE_SCTP:
764 lt = NPC_LT_LH_TU_SCTP;
765 info.len = pst->pattern->size;
767 case ROC_NPC_ITEM_TYPE_ESP:
768 lt = NPC_LT_LH_TU_ESP;
769 info.len = pst->pattern->size;
775 npc_get_hw_supp_mask(pst, &info, lid, lt);
776 rc = npc_parse_item_basic(pst->pattern, &info);
780 return npc_update_parse_state(pst, &info, lid, lt, 0);