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