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 *
npc_parse_skip_void_and_any_items(const struct roc_npc_item_info * pattern)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
npc_parse_meta_items(struct npc_parse_state * pst)18 npc_parse_meta_items(struct npc_parse_state *pst)
19 {
20 PLT_SET_USED(pst);
21 return 0;
22 }
23
24 int
npc_parse_mark_item(struct npc_parse_state * pst)25 npc_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
38 static int
npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw * raw_spec,const struct roc_npc_flow_item_raw * raw_mask,struct npc_parse_item_info * info,uint8_t * spec_buf,uint8_t * mask_buf)39 npc_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
64 int
npc_parse_pre_l2(struct npc_parse_state * pst)65 npc_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 /* Identify the pattern type into lid, lt */
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 /* Basic validation of item parameters */
104 rc = npc_parse_item_basic(pst->pattern, &info);
105 if (rc)
106 return rc;
107
108 /* Update pst if not validate only? clash check? */
109 return npc_update_parse_state(pst, &info, lid, lt, 0);
110 }
111
112 int
npc_parse_cpt_hdr(struct npc_parse_state * pst)113 npc_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 /* Identify the pattern type into lid, lt */
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 /* Prepare for parsing the item */
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 /* Basic validation of item parameters */
137 rc = npc_parse_item_basic(pst->pattern, &info);
138 if (rc)
139 return rc;
140
141 /* Update pst if not validate only? clash check? */
142 return npc_update_parse_state(pst, &info, lid, lt, 0);
143 }
144
145 int
npc_parse_higig2_hdr(struct npc_parse_state * pst)146 npc_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 /* Identify the pattern type into lid, lt */
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 /* Prepare for parsing the item */
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 /* Basic validation of item parameters */
175 rc = npc_parse_item_basic(pst->pattern, &info);
176 if (rc)
177 return rc;
178
179 /* Update pst if not validate only? clash check? */
180 return npc_update_parse_state(pst, &info, lid, lt, 0);
181 }
182
183 int
npc_parse_la(struct npc_parse_state * pst)184 npc_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 /* Identify the pattern type into lid, lt */
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 /* Prepare for parsing the item */
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 /* Basic validation of item parameters */
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
241 int
npc_parse_lb(struct npc_parse_state * pst)242 npc_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 /* RTE vlan is either 802.1q or 802.1ad,
268 * this maps to either CTAG/STAG. We need to decide
269 * based on number of VLANS present. Matching is
270 * supported on first tag only.
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 /* Basic validation of Second/Third vlan item */
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 /* This lflag value will match either one of
307 * NPC_F_LB_L_WITH_STAG_STAG,
308 * NPC_F_LB_L_WITH_QINQ_CTAG,
309 * NPC_F_LB_L_WITH_QINQ_QINQ and
310 * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
311 * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
312 * hence will not match.
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 /* we can support ETAG and match a subsequent CTAG
334 * without any matching support.
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 /* set supported mask to NULL for vlan tag */
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 /* Point pattern to last item consumed */
394 pst->pattern = last_pattern;
395 return npc_update_parse_state(pst, &info, lid, lt, lflags);
396 }
397
398 static int
npc_parse_mpls_label_stack(struct npc_parse_state * pst,int * flag)399 npc_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 * pst->pattern points to first MPLS label. We only check
410 * that subsequent labels do not have anything to match.
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 /* Basic validation of Second/Third/Fourth mpls item */
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
440 static int
npc_parse_mpls(struct npc_parse_state * pst,int lid)441 npc_parse_mpls(struct npc_parse_state *pst, int lid)
442 {
443 /* Find number of MPLS labels */
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 /* Prepare for parsing the first item */
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 * Parse for more labels.
473 * This sets lflags and pst->last_pattern correctly.
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
485 static inline void
npc_check_lc_ip_tunnel(struct npc_parse_state * pst)486 npc_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
497 static int
npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 * ipv6_spec,struct npc_parse_state * pst,uint8_t * flags)498 npc_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
549 int
npc_parse_lc(struct npc_parse_state * pst)550 npc_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 /* No match at this layer */
630 return 0;
631 }
632
633 /* Identify if IP tunnels MPLS or IPv4/v6 */
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
645 int
npc_parse_ld(struct npc_parse_state * pst)646 npc_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 /* We have already parsed MPLS or IPv4/v6 followed
655 * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
656 * would be parsed as tunneled versions. Skip
657 * this layer, except for tunneled MPLS. If LC is
658 * MPLS, we have anyway skipped all stacked MPLS
659 * labels.
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 break;
703 case ROC_NPC_ITEM_TYPE_GRE_KEY:
704 lt = NPC_LT_LD_GRE;
705 info.len = pst->pattern->size;
706 info.hw_hdr_len = 4;
707 break;
708 case ROC_NPC_ITEM_TYPE_NVGRE:
709 lt = NPC_LT_LD_NVGRE;
710 lflags = NPC_F_GRE_NVGRE;
711 info.len = pst->pattern->size;
712 /* Further IP/Ethernet are parsed as tunneled */
713 pst->tunnel = 1;
714 break;
715 default:
716 return 0;
717 }
718
719 npc_get_hw_supp_mask(pst, &info, lid, lt);
720 rc = npc_parse_item_basic(pst->pattern, &info);
721 if (rc != 0)
722 return rc;
723
724 return npc_update_parse_state(pst, &info, lid, lt, lflags);
725 }
726
727 int
npc_parse_le(struct npc_parse_state * pst)728 npc_parse_le(struct npc_parse_state *pst)
729 {
730 const struct roc_npc_item_info *pattern = pst->pattern;
731 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
732 struct npc_parse_item_info info;
733 int lid, lt, lflags;
734 int rc;
735
736 if (pst->tunnel)
737 return 0;
738
739 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
740 return npc_parse_mpls(pst, NPC_LID_LE);
741
742 info.spec = NULL;
743 info.mask = NULL;
744 info.hw_mask = NULL;
745 info.def_mask = NULL;
746 info.len = 0;
747 info.hw_hdr_len = 0;
748 lid = NPC_LID_LE;
749 lflags = 0;
750
751 /* Ensure we are not matching anything in UDP */
752 rc = npc_parse_item_basic(pattern, &info);
753 if (rc)
754 return rc;
755
756 info.hw_mask = &hw_mask;
757 pattern = npc_parse_skip_void_and_any_items(pattern);
758 switch (pattern->type) {
759 case ROC_NPC_ITEM_TYPE_VXLAN:
760 lflags = NPC_F_UDP_VXLAN;
761 info.len = pattern->size;
762 lt = NPC_LT_LE_VXLAN;
763 break;
764 case ROC_NPC_ITEM_TYPE_GTPC:
765 lflags = NPC_F_UDP_GTP_GTPC;
766 info.len = pattern->size;
767 lt = NPC_LT_LE_GTPC;
768 break;
769 case ROC_NPC_ITEM_TYPE_GTPU:
770 lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
771 info.len = pattern->size;
772 lt = NPC_LT_LE_GTPU;
773 break;
774 case ROC_NPC_ITEM_TYPE_GENEVE:
775 lflags = NPC_F_UDP_GENEVE;
776 info.len = pattern->size;
777 lt = NPC_LT_LE_GENEVE;
778 break;
779 case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
780 lflags = NPC_F_UDP_VXLANGPE;
781 info.len = pattern->size;
782 lt = NPC_LT_LE_VXLANGPE;
783 break;
784 case ROC_NPC_ITEM_TYPE_ESP:
785 lt = NPC_LT_LE_ESP;
786 info.len = pst->pattern->size;
787 break;
788 default:
789 return 0;
790 }
791
792 pst->tunnel = 1;
793
794 npc_get_hw_supp_mask(pst, &info, lid, lt);
795 rc = npc_parse_item_basic(pattern, &info);
796 if (rc != 0)
797 return rc;
798
799 return npc_update_parse_state(pst, &info, lid, lt, lflags);
800 }
801
802 int
npc_parse_lf(struct npc_parse_state * pst)803 npc_parse_lf(struct npc_parse_state *pst)
804 {
805 const struct roc_npc_item_info *pattern, *last_pattern;
806 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
807 struct npc_parse_item_info info;
808 int lid, lt, lflags;
809 int nr_vlans = 0;
810 int rc;
811
812 /* We hit this layer if there is a tunneling protocol */
813 if (!pst->tunnel)
814 return 0;
815
816 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
817 return 0;
818
819 lid = NPC_LID_LF;
820 lt = NPC_LT_LF_TU_ETHER;
821 lflags = 0;
822
823 /* No match support for vlan tags */
824 info.def_mask = NULL;
825 info.hw_mask = NULL;
826 info.len = pst->pattern->size;
827 info.spec = NULL;
828 info.mask = NULL;
829 info.hw_hdr_len = 0;
830
831 /* Look ahead and find out any VLAN tags. These can be
832 * detected but no data matching is available.
833 */
834 last_pattern = pst->pattern;
835 pattern = pst->pattern + 1;
836 pattern = npc_parse_skip_void_and_any_items(pattern);
837 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
838 nr_vlans++;
839 last_pattern = pattern;
840 pattern++;
841 pattern = npc_parse_skip_void_and_any_items(pattern);
842 }
843 switch (nr_vlans) {
844 case 0:
845 break;
846 case 1:
847 lflags = NPC_F_TU_ETHER_CTAG;
848 break;
849 case 2:
850 lflags = NPC_F_TU_ETHER_STAG_CTAG;
851 break;
852 default:
853 return NPC_ERR_PATTERN_NOTSUP;
854 }
855
856 info.hw_mask = &hw_mask;
857 info.len = pst->pattern->size;
858 info.hw_hdr_len = 0;
859 npc_get_hw_supp_mask(pst, &info, lid, lt);
860 info.spec = NULL;
861 info.mask = NULL;
862
863 rc = npc_parse_item_basic(pst->pattern, &info);
864 if (rc != 0)
865 return rc;
866
867 pst->pattern = last_pattern;
868
869 return npc_update_parse_state(pst, &info, lid, lt, lflags);
870 }
871
872 int
npc_parse_lg(struct npc_parse_state * pst)873 npc_parse_lg(struct npc_parse_state *pst)
874 {
875 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
876 struct npc_parse_item_info info;
877 int lid, lt;
878 int rc;
879
880 if (!pst->tunnel)
881 return 0;
882
883 info.def_mask = NULL;
884 info.hw_mask = &hw_mask;
885 info.spec = NULL;
886 info.mask = NULL;
887 info.hw_hdr_len = 0;
888 lid = NPC_LID_LG;
889
890 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
891 lt = NPC_LT_LG_TU_IP;
892 info.len = pst->pattern->size;
893 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
894 lt = NPC_LT_LG_TU_IP6;
895 info.len = pst->pattern->size;
896 } else {
897 /* There is no tunneled IP header */
898 return 0;
899 }
900
901 npc_get_hw_supp_mask(pst, &info, lid, lt);
902 rc = npc_parse_item_basic(pst->pattern, &info);
903 if (rc != 0)
904 return rc;
905
906 return npc_update_parse_state(pst, &info, lid, lt, 0);
907 }
908
909 int
npc_parse_lh(struct npc_parse_state * pst)910 npc_parse_lh(struct npc_parse_state *pst)
911 {
912 char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
913 struct npc_parse_item_info info;
914 int lid, lt;
915 int rc;
916
917 if (!pst->tunnel)
918 return 0;
919
920 info.def_mask = NULL;
921 info.hw_mask = &hw_mask;
922 info.spec = NULL;
923 info.mask = NULL;
924 info.hw_hdr_len = 0;
925 lid = NPC_LID_LH;
926
927 switch (pst->pattern->type) {
928 case ROC_NPC_ITEM_TYPE_UDP:
929 lt = NPC_LT_LH_TU_UDP;
930 info.len = pst->pattern->size;
931 break;
932 case ROC_NPC_ITEM_TYPE_TCP:
933 lt = NPC_LT_LH_TU_TCP;
934 info.len = pst->pattern->size;
935 break;
936 case ROC_NPC_ITEM_TYPE_SCTP:
937 lt = NPC_LT_LH_TU_SCTP;
938 info.len = pst->pattern->size;
939 break;
940 case ROC_NPC_ITEM_TYPE_ESP:
941 lt = NPC_LT_LH_TU_ESP;
942 info.len = pst->pattern->size;
943 break;
944 default:
945 return 0;
946 }
947
948 npc_get_hw_supp_mask(pst, &info, lid, lt);
949 rc = npc_parse_item_basic(pst->pattern, &info);
950 if (rc != 0)
951 return rc;
952
953 return npc_update_parse_state(pst, &info, lid, lt, 0);
954 }
955