1
2
3
4#include "roc_api.h"
5#include "roc_priv.h"
6
7const struct roc_npc_item_info *
8npc_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
17int
18npc_parse_meta_items(struct npc_parse_state *pst)
19{
20 PLT_SET_USED(pst);
21 return 0;
22}
23
24int
25npc_parse_mark_item(struct npc_parse_state *pst)
26{
27 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MARK) {
28 if (pst->flow->nix_intf != NIX_INTF_RX)
29 return -EINVAL;
30
31 pst->is_second_pass_rule = true;
32 pst->pattern++;
33 }
34
35 return 0;
36}
37
38static int
39npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
40 const struct roc_npc_flow_item_raw *raw_mask,
41 struct npc_parse_item_info *info, uint8_t *spec_buf,
42 uint8_t *mask_buf)
43{
44
45 memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
46 memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
47
48 memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
49 raw_spec->length);
50
51 if (raw_mask && raw_mask->pattern) {
52 memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
53 raw_spec->length);
54 } else {
55 memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
56 }
57
58 info->len = NPC_MAX_RAW_ITEM_LEN;
59 info->spec = spec_buf;
60 info->mask = mask_buf;
61 return 0;
62}
63
64int
65npc_parse_pre_l2(struct npc_parse_state *pst)
66{
67 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
68 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
69 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN] = {0};
70 const struct roc_npc_flow_item_raw *raw_spec;
71 struct npc_parse_item_info info;
72 int lid, lt, len;
73 int rc;
74
75 if (pst->npc->switch_header_type != ROC_PRIV_FLAGS_PRE_L2)
76 return 0;
77
78
79 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_RAW)
80 return 0;
81
82 lid = NPC_LID_LA;
83 lt = NPC_LT_LA_CUSTOM_PRE_L2_ETHER;
84 info.hw_hdr_len = 0;
85
86 raw_spec = pst->pattern->spec;
87 len = raw_spec->length + raw_spec->offset;
88 if (len > NPC_MAX_RAW_ITEM_LEN)
89 return -EINVAL;
90
91 if (raw_spec->relative == 0 || raw_spec->search || raw_spec->limit ||
92 raw_spec->offset < 0)
93 return -EINVAL;
94
95 npc_flow_raw_item_prepare(
96 (const struct roc_npc_flow_item_raw *)pst->pattern->spec,
97 (const struct roc_npc_flow_item_raw *)pst->pattern->mask, &info,
98 raw_spec_buf, raw_mask_buf);
99
100 info.hw_mask = &hw_mask;
101 npc_get_hw_supp_mask(pst, &info, lid, lt);
102
103
104 rc = npc_parse_item_basic(pst->pattern, &info);
105 if (rc)
106 return rc;
107
108
109 return npc_update_parse_state(pst, &info, lid, lt, 0);
110}
111
112int
113npc_parse_cpt_hdr(struct npc_parse_state *pst)
114{
115 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
116 struct npc_parse_item_info info;
117 int lid, lt;
118 int rc;
119
120
121 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
122 return 0;
123
124 lid = NPC_LID_LA;
125 lt = NPC_LT_LA_CPT_HDR;
126 info.hw_hdr_len = 0;
127
128
129 info.def_mask = NULL;
130 info.hw_mask = &hw_mask;
131 info.len = pst->pattern->size;
132 npc_get_hw_supp_mask(pst, &info, lid, lt);
133 info.spec = NULL;
134 info.mask = NULL;
135
136
137 rc = npc_parse_item_basic(pst->pattern, &info);
138 if (rc)
139 return rc;
140
141
142 return npc_update_parse_state(pst, &info, lid, lt, 0);
143}
144
145int
146npc_parse_higig2_hdr(struct npc_parse_state *pst)
147{
148 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
149 struct npc_parse_item_info info;
150 int lid, lt;
151 int rc;
152
153
154 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
155 return 0;
156
157 lid = NPC_LID_LA;
158 lt = NPC_LT_LA_HIGIG2_ETHER;
159 info.hw_hdr_len = 0;
160
161 if (pst->flow->nix_intf == NIX_INTF_TX) {
162 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
163 info.hw_hdr_len = NPC_IH_LENGTH;
164 }
165
166
167 info.def_mask = NULL;
168 info.hw_mask = &hw_mask;
169 info.len = pst->pattern->size;
170 npc_get_hw_supp_mask(pst, &info, lid, lt);
171 info.spec = NULL;
172 info.mask = NULL;
173
174
175 rc = npc_parse_item_basic(pst->pattern, &info);
176 if (rc)
177 return rc;
178
179
180 return npc_update_parse_state(pst, &info, lid, lt, 0);
181}
182
183int
184npc_parse_la(struct npc_parse_state *pst)
185{
186 const struct roc_npc_flow_item_eth *eth_item;
187 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
188 struct npc_parse_item_info info;
189 int lid, lt;
190 int rc;
191
192
193 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
194 return 0;
195
196 eth_item = pst->pattern->spec;
197
198 lid = NPC_LID_LA;
199 lt = NPC_LT_LA_ETHER;
200 info.hw_hdr_len = 0;
201
202 if (pst->flow->nix_intf == NIX_INTF_TX) {
203 lt = NPC_LT_LA_IH_NIX_ETHER;
204 info.hw_hdr_len = NPC_IH_LENGTH;
205 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
206 lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
207 info.hw_hdr_len += NPC_HIGIG2_LENGTH;
208 }
209 } else {
210 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
211 lt = NPC_LT_LA_HIGIG2_ETHER;
212 info.hw_hdr_len = NPC_HIGIG2_LENGTH;
213 }
214 }
215
216
217 info.def_mask = NULL;
218 info.hw_mask = &hw_mask;
219 info.len = sizeof(eth_item->hdr);
220 npc_get_hw_supp_mask(pst, &info, lid, lt);
221 info.spec = NULL;
222 info.mask = NULL;
223
224
225 rc = npc_parse_item_basic(pst->pattern, &info);
226 if (rc)
227 return rc;
228
229 rc = npc_update_parse_state(pst, &info, lid, lt, 0);
230 if (rc)
231 return rc;
232
233 if (eth_item && eth_item->has_vlan)
234 pst->set_vlan_ltype_mask = true;
235
236 return 0;
237}
238
239#define NPC_MAX_SUPPORTED_VLANS 3
240
241int
242npc_parse_lb(struct npc_parse_state *pst)
243{
244 const struct roc_npc_flow_item_vlan *vlan_item[NPC_MAX_SUPPORTED_VLANS];
245 const struct roc_npc_item_info *pattern = pst->pattern;
246 const struct roc_npc_item_info *last_pattern;
247 const struct roc_npc_flow_item_raw *raw_spec;
248 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
249 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
250 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
251 struct npc_parse_item_info info;
252 int lid, lt, lflags, len = 0;
253 int nr_vlans = 0;
254 int rc;
255
256 info.def_mask = NULL;
257 info.spec = NULL;
258 info.mask = NULL;
259 info.def_mask = NULL;
260 info.hw_hdr_len = NPC_TPID_LENGTH;
261
262 lid = NPC_LID_LB;
263 lflags = 0;
264 last_pattern = pattern;
265
266 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
267
268
269
270
271
272 info.hw_mask = NULL;
273 info.len = sizeof(vlan_item[0]->hdr);
274
275 pattern = pst->pattern;
276 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
277 if (nr_vlans > NPC_MAX_SUPPORTED_VLANS - 1)
278 return NPC_ERR_PATTERN_NOTSUP;
279
280 vlan_item[nr_vlans] = pattern->spec;
281 nr_vlans++;
282
283
284 if (nr_vlans > 1) {
285 rc = npc_parse_item_basic(pattern, &info);
286 if (rc != 0)
287 return rc;
288 }
289 last_pattern = pattern;
290 pattern++;
291 pattern = npc_parse_skip_void_and_any_items(pattern);
292 }
293
294 switch (nr_vlans) {
295 case 1:
296 lt = NPC_LT_LB_CTAG;
297 if (vlan_item[0] && vlan_item[0]->has_more_vlan)
298 lt = NPC_LT_LB_STAG_QINQ;
299 break;
300 case 2:
301 if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
302 if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
303 0x3ULL << NPC_LFLAG_LB_OFFSET))
304 return NPC_ERR_PATTERN_NOTSUP;
305
306
307
308
309
310
311
312
313
314
315 lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
316 NPC_F_LB_L_WITH_QINQ_QINQ &
317 NPC_F_LB_L_WITH_STAG_STAG;
318 } else {
319 lflags = NPC_F_LB_L_WITH_CTAG;
320 }
321 lt = NPC_LT_LB_STAG_QINQ;
322 break;
323 case 3:
324 if (vlan_item[2] && vlan_item[2]->has_more_vlan)
325 return NPC_ERR_PATTERN_NOTSUP;
326 lt = NPC_LT_LB_STAG_QINQ;
327 lflags = NPC_F_STAG_STAG_CTAG;
328 break;
329 default:
330 return NPC_ERR_PATTERN_NOTSUP;
331 }
332 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
333
334
335
336 lt = NPC_LT_LB_ETAG;
337 lflags = 0;
338
339 last_pattern = pst->pattern;
340 pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
341 if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
342
343 info.hw_mask = NULL;
344 info.len = pattern->size;
345 rc = npc_parse_item_basic(pattern, &info);
346 if (rc != 0)
347 return rc;
348
349 lflags = NPC_F_ETAG_CTAG;
350 last_pattern = pattern;
351 }
352 info.len = pattern->size;
353 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
354 info.hw_mask = NULL;
355 info.len = pattern->size;
356 lt = NPC_LT_LB_STAG_QINQ;
357 lflags = NPC_F_STAG_CTAG;
358 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
359 raw_spec = pst->pattern->spec;
360 if (raw_spec->relative)
361 return 0;
362 len = raw_spec->length + raw_spec->offset;
363 if (len > NPC_MAX_RAW_ITEM_LEN)
364 return -EINVAL;
365
366 if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
367 lt = NPC_LT_LB_VLAN_EXDSA;
368 } else if (pst->npc->switch_header_type ==
369 ROC_PRIV_FLAGS_EXDSA) {
370 lt = NPC_LT_LB_EXDSA;
371 } else {
372 return -EINVAL;
373 }
374
375 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
376 pst->pattern->spec,
377 (const struct roc_npc_flow_item_raw *)
378 pst->pattern->mask,
379 &info, raw_spec_buf, raw_mask_buf);
380
381 info.hw_hdr_len = 0;
382 } else {
383 return 0;
384 }
385
386 info.hw_mask = &hw_mask;
387 npc_get_hw_supp_mask(pst, &info, lid, lt);
388
389 rc = npc_parse_item_basic(pst->pattern, &info);
390 if (rc != 0)
391 return rc;
392
393
394 pst->pattern = last_pattern;
395 return npc_update_parse_state(pst, &info, lid, lt, lflags);
396}
397
398static int
399npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
400{
401 uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
402 NPC_F_MPLS_4_LABELS};
403 const struct roc_npc_item_info *pattern = pst->pattern;
404 struct npc_parse_item_info info;
405 int nr_labels = 0;
406 int rc;
407
408
409
410
411
412 info.def_mask = NULL;
413 info.hw_mask = NULL;
414 info.len = pattern->size;
415 info.spec = NULL;
416 info.mask = NULL;
417 info.hw_hdr_len = 0;
418
419 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
420 nr_labels++;
421
422
423 if (nr_labels > 1) {
424 rc = npc_parse_item_basic(pattern, &info);
425 if (rc != 0)
426 return rc;
427 }
428 pst->last_pattern = pattern;
429 pattern++;
430 pattern = npc_parse_skip_void_and_any_items(pattern);
431 }
432
433 if (nr_labels < 1 || nr_labels > 4)
434 return NPC_ERR_PATTERN_NOTSUP;
435
436 *flag = flag_list[nr_labels - 1];
437 return 0;
438}
439
440static int
441npc_parse_mpls(struct npc_parse_state *pst, int lid)
442{
443
444 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
445 struct npc_parse_item_info info;
446 int lt, lflags;
447 int rc;
448
449 lflags = 0;
450
451 if (lid == NPC_LID_LC)
452 lt = NPC_LT_LC_MPLS;
453 else if (lid == NPC_LID_LD)
454 lt = NPC_LT_LD_TU_MPLS_IN_IP;
455 else
456 lt = NPC_LT_LE_TU_MPLS_IN_UDP;
457
458
459 info.hw_mask = &hw_mask;
460 info.len = pst->pattern->size;
461 info.spec = NULL;
462 info.mask = NULL;
463 info.def_mask = NULL;
464 info.hw_hdr_len = 0;
465
466 npc_get_hw_supp_mask(pst, &info, lid, lt);
467 rc = npc_parse_item_basic(pst->pattern, &info);
468 if (rc != 0)
469 return rc;
470
471
472
473
474
475 rc = npc_parse_mpls_label_stack(pst, &lflags);
476 if (rc != 0)
477 return rc;
478
479 pst->tunnel = 1;
480 pst->pattern = pst->last_pattern;
481
482 return npc_update_parse_state(pst, &info, lid, lt, lflags);
483}
484
485static inline void
486npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
487{
488 const struct roc_npc_item_info *pattern = pst->pattern + 1;
489
490 pattern = npc_parse_skip_void_and_any_items(pattern);
491 if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
492 pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
493 pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
494 pst->tunnel = 1;
495}
496
497static int
498npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
499 struct npc_parse_state *pst, uint8_t *flags)
500{
501 int flags_count = 0;
502
503 if (ipv6_spec->has_hop_ext) {
504 *flags = NPC_F_LC_L_EXT_HOP;
505 flags_count++;
506 }
507 if (ipv6_spec->has_route_ext) {
508 *flags = NPC_F_LC_L_EXT_ROUT;
509 flags_count++;
510 }
511 if (ipv6_spec->has_frag_ext) {
512 *flags = NPC_F_LC_U_IP6_FRAG;
513 flags_count++;
514 }
515 if (ipv6_spec->has_dest_ext) {
516 *flags = NPC_F_LC_L_EXT_DEST;
517 flags_count++;
518 }
519 if (ipv6_spec->has_mobil_ext) {
520 *flags = NPC_F_LC_L_EXT_MOBILITY;
521 flags_count++;
522 }
523 if (ipv6_spec->has_hip_ext) {
524 *flags = NPC_F_LC_L_EXT_HOSTID;
525 flags_count++;
526 }
527 if (ipv6_spec->has_shim6_ext) {
528 *flags = NPC_F_LC_L_EXT_SHIM6;
529 flags_count++;
530 }
531 if (ipv6_spec->has_auth_ext) {
532 pst->lt[NPC_LID_LD] = NPC_LT_LD_AH;
533 flags_count++;
534 }
535 if (ipv6_spec->has_esp_ext) {
536 pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP;
537 flags_count++;
538 }
539
540 if (flags_count > 1)
541 return -EINVAL;
542
543 if (flags_count)
544 pst->set_ipv6ext_ltype_mask = true;
545
546 return 0;
547}
548
549int
550npc_parse_lc(struct npc_parse_state *pst)
551{
552 const struct roc_npc_flow_item_ipv6 *ipv6_spec;
553 const struct roc_npc_flow_item_raw *raw_spec;
554 uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
555 uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
556 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
557 struct npc_parse_item_info info;
558 int rc, lid, lt, len = 0;
559 uint8_t flags = 0;
560
561 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
562 return npc_parse_mpls(pst, NPC_LID_LC);
563
564 info.def_mask = NULL;
565 info.hw_mask = &hw_mask;
566 info.spec = NULL;
567 info.mask = NULL;
568 info.hw_hdr_len = 0;
569 lid = NPC_LID_LC;
570
571 switch (pst->pattern->type) {
572 case ROC_NPC_ITEM_TYPE_IPV4:
573 lt = NPC_LT_LC_IP;
574 info.len = pst->pattern->size;
575 break;
576 case ROC_NPC_ITEM_TYPE_IPV6:
577 ipv6_spec = pst->pattern->spec;
578 lid = NPC_LID_LC;
579 lt = NPC_LT_LC_IP6;
580 if (ipv6_spec) {
581 rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags);
582 if (rc)
583 return rc;
584 }
585 info.len = sizeof(ipv6_spec->hdr);
586 break;
587 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
588 lt = NPC_LT_LC_ARP;
589 info.len = pst->pattern->size;
590 break;
591 case ROC_NPC_ITEM_TYPE_IPV6_EXT:
592 lid = NPC_LID_LC;
593 lt = NPC_LT_LC_IP6_EXT;
594 info.len = pst->pattern->size;
595 info.hw_hdr_len = 40;
596 break;
597 case ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT:
598 lid = NPC_LID_LC;
599 lt = NPC_LT_LC_IP6_EXT;
600 flags = NPC_F_LC_U_IP6_FRAG;
601 info.len = pst->pattern->size;
602 info.hw_hdr_len = 40;
603 break;
604 case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
605 lt = NPC_LT_LC_CUSTOM0;
606 info.len = pst->pattern->size;
607 break;
608 case ROC_NPC_ITEM_TYPE_RAW:
609 raw_spec = pst->pattern->spec;
610 if (!raw_spec->relative)
611 return 0;
612
613 len = raw_spec->length + raw_spec->offset;
614 if (len > NPC_MAX_RAW_ITEM_LEN)
615 return -EINVAL;
616
617 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
618 pst->pattern->spec,
619 (const struct roc_npc_flow_item_raw *)
620 pst->pattern->mask,
621 &info, raw_spec_buf, raw_mask_buf);
622
623 lid = NPC_LID_LC;
624 lt = NPC_LT_LC_NGIO;
625 info.hw_mask = &hw_mask;
626 npc_get_hw_supp_mask(pst, &info, lid, lt);
627 break;
628 default:
629
630 return 0;
631 }
632
633
634 npc_check_lc_ip_tunnel(pst);
635
636 npc_get_hw_supp_mask(pst, &info, lid, lt);
637 rc = npc_parse_item_basic(pst->pattern, &info);
638
639 if (rc != 0)
640 return rc;
641
642 return npc_update_parse_state(pst, &info, lid, lt, flags);
643}
644
645int
646npc_parse_ld(struct npc_parse_state *pst)
647{
648 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
649 struct npc_parse_item_info info;
650 int lid, lt, lflags;
651 int rc;
652
653 if (pst->tunnel) {
654
655
656
657
658
659
660
661 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
662 return npc_parse_mpls(pst, NPC_LID_LD);
663 return 0;
664 }
665 info.def_mask = NULL;
666 info.hw_mask = &hw_mask;
667 info.spec = NULL;
668 info.mask = NULL;
669 info.len = 0;
670 info.hw_hdr_len = 0;
671
672 lid = NPC_LID_LD;
673 lflags = 0;
674
675 switch (pst->pattern->type) {
676 case ROC_NPC_ITEM_TYPE_ICMP:
677 if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
678 lt = NPC_LT_LD_ICMP6;
679 else
680 lt = NPC_LT_LD_ICMP;
681 info.len = pst->pattern->size;
682 break;
683 case ROC_NPC_ITEM_TYPE_UDP:
684 lt = NPC_LT_LD_UDP;
685 info.len = pst->pattern->size;
686 break;
687 case ROC_NPC_ITEM_TYPE_IGMP:
688 lt = NPC_LT_LD_IGMP;
689 info.len = pst->pattern->size;
690 break;
691 case ROC_NPC_ITEM_TYPE_TCP:
692 lt = NPC_LT_LD_TCP;
693 info.len = pst->pattern->size;
694 break;
695 case ROC_NPC_ITEM_TYPE_SCTP:
696 lt = NPC_LT_LD_SCTP;
697 info.len = pst->pattern->size;
698 break;
699 case ROC_NPC_ITEM_TYPE_GRE:
700 lt = NPC_LT_LD_GRE;
701 info.len = pst->pattern->size;
702 pst->tunnel = 1;
703 break;
704 case ROC_NPC_ITEM_TYPE_GRE_KEY:
705 lt = NPC_LT_LD_GRE;
706 info.len = pst->pattern->size;
707 info.hw_hdr_len = 4;
708 pst->tunnel = 1;
709 break;
710 case ROC_NPC_ITEM_TYPE_NVGRE:
711 lt = NPC_LT_LD_NVGRE;
712 lflags = NPC_F_GRE_NVGRE;
713 info.len = pst->pattern->size;
714
715 pst->tunnel = 1;
716 break;
717 default:
718 return 0;
719 }
720
721 npc_get_hw_supp_mask(pst, &info, lid, lt);
722 rc = npc_parse_item_basic(pst->pattern, &info);
723 if (rc != 0)
724 return rc;
725
726 return npc_update_parse_state(pst, &info, lid, lt, lflags);
727}
728
729int
730npc_parse_le(struct npc_parse_state *pst)
731{
732 const struct roc_npc_item_info *pattern = pst->pattern;
733 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
734 struct npc_parse_item_info info;
735 int lid, lt, lflags;
736 int rc;
737
738 if (pst->tunnel)
739 return 0;
740
741 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
742 return npc_parse_mpls(pst, NPC_LID_LE);
743
744 info.spec = NULL;
745 info.mask = NULL;
746 info.hw_mask = NULL;
747 info.def_mask = NULL;
748 info.len = 0;
749 info.hw_hdr_len = 0;
750 lid = NPC_LID_LE;
751 lflags = 0;
752
753
754 rc = npc_parse_item_basic(pattern, &info);
755 if (rc)
756 return rc;
757
758 info.hw_mask = &hw_mask;
759 pattern = npc_parse_skip_void_and_any_items(pattern);
760 switch (pattern->type) {
761 case ROC_NPC_ITEM_TYPE_VXLAN:
762 lflags = NPC_F_UDP_VXLAN;
763 info.len = pattern->size;
764 lt = NPC_LT_LE_VXLAN;
765 break;
766 case ROC_NPC_ITEM_TYPE_GTPC:
767 lflags = NPC_F_UDP_GTP_GTPC;
768 info.len = pattern->size;
769 lt = NPC_LT_LE_GTPC;
770 break;
771 case ROC_NPC_ITEM_TYPE_GTPU:
772 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
773 info.len = pattern->size;
774 lt = NPC_LT_LE_GTPU;
775 break;
776 case ROC_NPC_ITEM_TYPE_GENEVE:
777 lflags = NPC_F_UDP_GENEVE;
778 info.len = pattern->size;
779 lt = NPC_LT_LE_GENEVE;
780 break;
781 case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
782 lflags = NPC_F_UDP_VXLANGPE;
783 info.len = pattern->size;
784 lt = NPC_LT_LE_VXLANGPE;
785 break;
786 case ROC_NPC_ITEM_TYPE_ESP:
787 lt = NPC_LT_LE_ESP;
788 info.len = pst->pattern->size;
789 break;
790 default:
791 return 0;
792 }
793
794 pst->tunnel = 1;
795
796 npc_get_hw_supp_mask(pst, &info, lid, lt);
797 rc = npc_parse_item_basic(pattern, &info);
798 if (rc != 0)
799 return rc;
800
801 return npc_update_parse_state(pst, &info, lid, lt, lflags);
802}
803
804int
805npc_parse_lf(struct npc_parse_state *pst)
806{
807 const struct roc_npc_item_info *pattern, *last_pattern;
808 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
809 struct npc_parse_item_info info;
810 int lid, lt, lflags;
811 int nr_vlans = 0;
812 int rc;
813
814
815 if (!pst->tunnel)
816 return 0;
817
818 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
819 return 0;
820
821 lid = NPC_LID_LF;
822 lt = NPC_LT_LF_TU_ETHER;
823 lflags = 0;
824
825
826 info.def_mask = NULL;
827 info.hw_mask = NULL;
828 info.len = pst->pattern->size;
829 info.spec = NULL;
830 info.mask = NULL;
831 info.hw_hdr_len = 0;
832
833
834
835
836 last_pattern = pst->pattern;
837 pattern = pst->pattern + 1;
838 pattern = npc_parse_skip_void_and_any_items(pattern);
839 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
840 nr_vlans++;
841 last_pattern = pattern;
842 pattern++;
843 pattern = npc_parse_skip_void_and_any_items(pattern);
844 }
845 switch (nr_vlans) {
846 case 0:
847 break;
848 case 1:
849 lflags = NPC_F_TU_ETHER_CTAG;
850 break;
851 case 2:
852 lflags = NPC_F_TU_ETHER_STAG_CTAG;
853 break;
854 default:
855 return NPC_ERR_PATTERN_NOTSUP;
856 }
857
858 info.hw_mask = &hw_mask;
859 info.len = pst->pattern->size;
860 info.hw_hdr_len = 0;
861 npc_get_hw_supp_mask(pst, &info, lid, lt);
862 info.spec = NULL;
863 info.mask = NULL;
864
865 rc = npc_parse_item_basic(pst->pattern, &info);
866 if (rc != 0)
867 return rc;
868
869 pst->pattern = last_pattern;
870
871 return npc_update_parse_state(pst, &info, lid, lt, lflags);
872}
873
874int
875npc_parse_lg(struct npc_parse_state *pst)
876{
877 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
878 struct npc_parse_item_info info;
879 int lid, lt;
880 int rc;
881
882 if (!pst->tunnel)
883 return 0;
884
885 info.def_mask = NULL;
886 info.hw_mask = &hw_mask;
887 info.spec = NULL;
888 info.mask = NULL;
889 info.hw_hdr_len = 0;
890 lid = NPC_LID_LG;
891
892 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
893 lt = NPC_LT_LG_TU_IP;
894 info.len = pst->pattern->size;
895 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
896 lt = NPC_LT_LG_TU_IP6;
897 info.len = pst->pattern->size;
898 } else {
899
900 return 0;
901 }
902
903 npc_get_hw_supp_mask(pst, &info, lid, lt);
904 rc = npc_parse_item_basic(pst->pattern, &info);
905 if (rc != 0)
906 return rc;
907
908 return npc_update_parse_state(pst, &info, lid, lt, 0);
909}
910
911int
912npc_parse_lh(struct npc_parse_state *pst)
913{
914 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
915 struct npc_parse_item_info info;
916 int lid, lt;
917 int rc;
918
919 if (!pst->tunnel)
920 return 0;
921
922 info.def_mask = NULL;
923 info.hw_mask = &hw_mask;
924 info.spec = NULL;
925 info.mask = NULL;
926 info.hw_hdr_len = 0;
927 lid = NPC_LID_LH;
928
929 switch (pst->pattern->type) {
930 case ROC_NPC_ITEM_TYPE_UDP:
931 lt = NPC_LT_LH_TU_UDP;
932 info.len = pst->pattern->size;
933 break;
934 case ROC_NPC_ITEM_TYPE_TCP:
935 lt = NPC_LT_LH_TU_TCP;
936 info.len = pst->pattern->size;
937 break;
938 case ROC_NPC_ITEM_TYPE_SCTP:
939 lt = NPC_LT_LH_TU_SCTP;
940 info.len = pst->pattern->size;
941 break;
942 case ROC_NPC_ITEM_TYPE_ESP:
943 lt = NPC_LT_LH_TU_ESP;
944 info.len = pst->pattern->size;
945 break;
946 default:
947 return 0;
948 }
949
950 npc_get_hw_supp_mask(pst, &info, lid, lt);
951 rc = npc_parse_item_basic(pst->pattern, &info);
952 if (rc != 0)
953 return rc;
954
955 return npc_update_parse_state(pst, &info, lid, lt, 0);
956}
957