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 int 25 npc_parse_cpt_hdr(struct npc_parse_state *pst) 26 { 27 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 28 struct npc_parse_item_info info; 29 int lid, lt; 30 int rc; 31 32 /* Identify the pattern type into lid, lt */ 33 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR) 34 return 0; 35 36 lid = NPC_LID_LA; 37 lt = NPC_LT_LA_CPT_HDR; 38 info.hw_hdr_len = 0; 39 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); 44 info.spec = NULL; 45 info.mask = NULL; 46 47 /* Basic validation of item parameters */ 48 rc = npc_parse_item_basic(pst->pattern, &info); 49 if (rc) 50 return rc; 51 52 /* Update pst if not validate only? clash check? */ 53 return npc_update_parse_state(pst, &info, lid, lt, 0); 54 } 55 56 int 57 npc_parse_higig2_hdr(struct npc_parse_state *pst) 58 { 59 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 60 struct npc_parse_item_info info; 61 int lid, lt; 62 int rc; 63 64 /* Identify the pattern type into lid, lt */ 65 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2) 66 return 0; 67 68 lid = NPC_LID_LA; 69 lt = NPC_LT_LA_HIGIG2_ETHER; 70 info.hw_hdr_len = 0; 71 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; 75 } 76 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); 81 info.spec = NULL; 82 info.mask = NULL; 83 84 /* Basic validation of item parameters */ 85 rc = npc_parse_item_basic(pst->pattern, &info); 86 if (rc) 87 return rc; 88 89 /* Update pst if not validate only? clash check? */ 90 return npc_update_parse_state(pst, &info, lid, lt, 0); 91 } 92 93 int 94 npc_parse_la(struct npc_parse_state *pst) 95 { 96 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 97 struct npc_parse_item_info info; 98 int lid, lt; 99 int rc; 100 101 /* Identify the pattern type into lid, lt */ 102 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH) 103 return 0; 104 105 lid = NPC_LID_LA; 106 lt = NPC_LT_LA_ETHER; 107 info.hw_hdr_len = 0; 108 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; 115 } 116 } else { 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; 120 } 121 } 122 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); 127 info.spec = NULL; 128 info.mask = NULL; 129 130 /* Basic validation of item parameters */ 131 rc = npc_parse_item_basic(pst->pattern, &info); 132 if (rc) 133 return rc; 134 135 /* Update pst if not validate only? clash check? */ 136 return npc_update_parse_state(pst, &info, lid, lt, 0); 137 } 138 139 static int 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, 143 uint8_t *mask_buf) 144 { 145 uint32_t custom_hdr_size = 0; 146 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; 150 151 memcpy(spec_buf + raw_spec->offset, raw_spec->pattern, 152 raw_spec->length); 153 154 if (raw_mask->pattern) { 155 memcpy(mask_buf + raw_spec->offset, raw_mask->pattern, 156 raw_spec->length); 157 } else { 158 memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length); 159 } 160 161 info->len = custom_hdr_size; 162 info->spec = spec_buf; 163 info->mask = mask_buf; 164 165 return 0; 166 } 167 168 int 169 npc_parse_lb(struct npc_parse_state *pst) 170 { 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; 179 int nr_vlans = 0; 180 int rc; 181 182 info.spec = NULL; 183 info.mask = NULL; 184 info.def_mask = NULL; 185 info.hw_hdr_len = NPC_TPID_LENGTH; 186 187 lid = NPC_LID_LB; 188 lflags = 0; 189 last_pattern = pattern; 190 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. 196 */ 197 info.hw_mask = NULL; 198 info.len = pst->pattern->size; 199 200 pattern = pst->pattern; 201 while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) { 202 nr_vlans++; 203 204 /* Basic validation of Second/Third vlan item */ 205 if (nr_vlans > 1) { 206 rc = npc_parse_item_basic(pattern, &info); 207 if (rc != 0) 208 return rc; 209 } 210 last_pattern = pattern; 211 pattern++; 212 pattern = npc_parse_skip_void_and_any_items(pattern); 213 } 214 215 switch (nr_vlans) { 216 case 1: 217 lt = NPC_LT_LB_CTAG; 218 break; 219 case 2: 220 lt = NPC_LT_LB_STAG_QINQ; 221 lflags = NPC_F_STAG_CTAG; 222 break; 223 case 3: 224 lt = NPC_LT_LB_STAG_QINQ; 225 lflags = NPC_F_STAG_STAG_CTAG; 226 break; 227 default: 228 return NPC_ERR_PATTERN_NOTSUP; 229 } 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. 233 */ 234 lt = NPC_LT_LB_ETAG; 235 lflags = 0; 236 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 */ 241 info.hw_mask = NULL; 242 info.len = pattern->size; 243 rc = npc_parse_item_basic(pattern, &info); 244 if (rc != 0) 245 return rc; 246 247 lflags = NPC_F_ETAG_CTAG; 248 last_pattern = pattern; 249 } 250 info.len = pattern->size; 251 } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) { 252 info.hw_mask = NULL; 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) 259 return 0; 260 len = raw_spec->length + raw_spec->offset; 261 if (len > NPC_MAX_RAW_ITEM_LEN) 262 return -EINVAL; 263 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; 269 } else { 270 return -EINVAL; 271 } 272 273 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *) 274 pst->pattern->spec, 275 (const struct roc_npc_flow_item_raw *) 276 pst->pattern->mask, 277 &info, raw_spec_buf, raw_mask_buf); 278 279 info.hw_hdr_len = 0; 280 } else { 281 return 0; 282 } 283 284 info.hw_mask = &hw_mask; 285 npc_get_hw_supp_mask(pst, &info, lid, lt); 286 287 rc = npc_parse_item_basic(pst->pattern, &info); 288 if (rc != 0) 289 return rc; 290 291 /* Point pattern to last item consumed */ 292 pst->pattern = last_pattern; 293 return npc_update_parse_state(pst, &info, lid, lt, lflags); 294 } 295 296 static int 297 npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag) 298 { 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; 303 int nr_labels = 0; 304 int rc; 305 306 /* 307 * pst->pattern points to first MPLS label. We only check 308 * that subsequent labels do not have anything to match. 309 */ 310 info.hw_mask = NULL; 311 info.len = pattern->size; 312 info.spec = NULL; 313 info.mask = NULL; 314 info.hw_hdr_len = 0; 315 info.def_mask = NULL; 316 317 while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) { 318 nr_labels++; 319 320 /* Basic validation of Second/Third/Fourth mpls item */ 321 if (nr_labels > 1) { 322 rc = npc_parse_item_basic(pattern, &info); 323 if (rc != 0) 324 return rc; 325 } 326 pst->last_pattern = pattern; 327 pattern++; 328 pattern = npc_parse_skip_void_and_any_items(pattern); 329 } 330 331 if (nr_labels < 1 || nr_labels > 4) 332 return NPC_ERR_PATTERN_NOTSUP; 333 334 *flag = flag_list[nr_labels - 1]; 335 return 0; 336 } 337 338 static int 339 npc_parse_mpls(struct npc_parse_state *pst, int lid) 340 { 341 /* Find number of MPLS labels */ 342 uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 343 struct npc_parse_item_info info; 344 int lt, lflags; 345 int rc; 346 347 lflags = 0; 348 349 if (lid == NPC_LID_LC) 350 lt = NPC_LT_LC_MPLS; 351 else if (lid == NPC_LID_LD) 352 lt = NPC_LT_LD_TU_MPLS_IN_IP; 353 else 354 lt = NPC_LT_LE_TU_MPLS_IN_UDP; 355 356 /* Prepare for parsing the first item */ 357 info.hw_mask = &hw_mask; 358 info.len = pst->pattern->size; 359 info.spec = NULL; 360 info.mask = NULL; 361 info.hw_hdr_len = 0; 362 363 npc_get_hw_supp_mask(pst, &info, lid, lt); 364 rc = npc_parse_item_basic(pst->pattern, &info); 365 if (rc != 0) 366 return rc; 367 368 /* 369 * Parse for more labels. 370 * This sets lflags and pst->last_pattern correctly. 371 */ 372 rc = npc_parse_mpls_label_stack(pst, &lflags); 373 if (rc != 0) 374 return rc; 375 376 pst->tunnel = 1; 377 pst->pattern = pst->last_pattern; 378 379 return npc_update_parse_state(pst, &info, lid, lt, lflags); 380 } 381 382 static inline void 383 npc_check_lc_ip_tunnel(struct npc_parse_state *pst) 384 { 385 const struct roc_npc_item_info *pattern = pst->pattern + 1; 386 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) 391 pst->tunnel = 1; 392 } 393 394 int 395 npc_parse_lc(struct npc_parse_state *pst) 396 { 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; 403 int rc; 404 405 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS) 406 return npc_parse_mpls(pst, NPC_LID_LC); 407 408 info.hw_mask = &hw_mask; 409 info.spec = NULL; 410 info.mask = NULL; 411 info.hw_hdr_len = 0; 412 lid = NPC_LID_LC; 413 414 switch (pst->pattern->type) { 415 case ROC_NPC_ITEM_TYPE_IPV4: 416 lt = NPC_LT_LC_IP; 417 info.len = pst->pattern->size; 418 break; 419 case ROC_NPC_ITEM_TYPE_IPV6: 420 lid = NPC_LID_LC; 421 lt = NPC_LT_LC_IP6; 422 info.len = pst->pattern->size; 423 break; 424 case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4: 425 lt = NPC_LT_LC_ARP; 426 info.len = pst->pattern->size; 427 break; 428 case ROC_NPC_ITEM_TYPE_IPV6_EXT: 429 lid = NPC_LID_LC; 430 lt = NPC_LT_LC_IP6_EXT; 431 info.len = pst->pattern->size; 432 info.hw_hdr_len = 40; 433 break; 434 case ROC_NPC_ITEM_TYPE_L3_CUSTOM: 435 lt = NPC_LT_LC_CUSTOM0; 436 info.len = pst->pattern->size; 437 break; 438 case ROC_NPC_ITEM_TYPE_RAW: 439 raw_spec = pst->pattern->spec; 440 if (!raw_spec->relative) 441 return 0; 442 443 len = raw_spec->length + raw_spec->offset; 444 if (len > NPC_MAX_RAW_ITEM_LEN) 445 return -EINVAL; 446 447 npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *) 448 pst->pattern->spec, 449 (const struct roc_npc_flow_item_raw *) 450 pst->pattern->mask, 451 &info, raw_spec_buf, raw_mask_buf); 452 453 lid = NPC_LID_LC; 454 lt = NPC_LT_LC_NGIO; 455 info.hw_mask = &hw_mask; 456 npc_get_hw_supp_mask(pst, &info, lid, lt); 457 break; 458 default: 459 /* No match at this layer */ 460 return 0; 461 } 462 463 /* Identify if IP tunnels MPLS or IPv4/v6 */ 464 npc_check_lc_ip_tunnel(pst); 465 466 npc_get_hw_supp_mask(pst, &info, lid, lt); 467 rc = npc_parse_item_basic(pst->pattern, &info); 468 469 if (rc != 0) 470 return rc; 471 472 return npc_update_parse_state(pst, &info, lid, lt, 0); 473 } 474 475 int 476 npc_parse_ld(struct npc_parse_state *pst) 477 { 478 char hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 479 struct npc_parse_item_info info; 480 int lid, lt, lflags; 481 int rc; 482 483 if (pst->tunnel) { 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 489 * labels. 490 */ 491 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS) 492 return npc_parse_mpls(pst, NPC_LID_LD); 493 return 0; 494 } 495 info.hw_mask = &hw_mask; 496 info.spec = NULL; 497 info.mask = NULL; 498 info.def_mask = NULL; 499 info.len = 0; 500 info.hw_hdr_len = 0; 501 502 lid = NPC_LID_LD; 503 lflags = 0; 504 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; 509 else 510 lt = NPC_LT_LD_ICMP; 511 info.len = pst->pattern->size; 512 break; 513 case ROC_NPC_ITEM_TYPE_UDP: 514 lt = NPC_LT_LD_UDP; 515 info.len = pst->pattern->size; 516 break; 517 case ROC_NPC_ITEM_TYPE_IGMP: 518 lt = NPC_LT_LD_IGMP; 519 info.len = pst->pattern->size; 520 break; 521 case ROC_NPC_ITEM_TYPE_TCP: 522 lt = NPC_LT_LD_TCP; 523 info.len = pst->pattern->size; 524 break; 525 case ROC_NPC_ITEM_TYPE_SCTP: 526 lt = NPC_LT_LD_SCTP; 527 info.len = pst->pattern->size; 528 break; 529 case ROC_NPC_ITEM_TYPE_GRE: 530 lt = NPC_LT_LD_GRE; 531 info.len = pst->pattern->size; 532 break; 533 case ROC_NPC_ITEM_TYPE_GRE_KEY: 534 lt = NPC_LT_LD_GRE; 535 info.len = pst->pattern->size; 536 info.hw_hdr_len = 4; 537 break; 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 */ 543 pst->tunnel = 1; 544 break; 545 default: 546 return 0; 547 } 548 549 npc_get_hw_supp_mask(pst, &info, lid, lt); 550 rc = npc_parse_item_basic(pst->pattern, &info); 551 if (rc != 0) 552 return rc; 553 554 return npc_update_parse_state(pst, &info, lid, lt, lflags); 555 } 556 557 int 558 npc_parse_le(struct npc_parse_state *pst) 559 { 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; 563 int lid, lt, lflags; 564 int rc; 565 566 if (pst->tunnel) 567 return 0; 568 569 if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS) 570 return npc_parse_mpls(pst, NPC_LID_LE); 571 572 info.spec = NULL; 573 info.mask = NULL; 574 info.hw_mask = NULL; 575 info.def_mask = NULL; 576 info.len = 0; 577 info.hw_hdr_len = 0; 578 lid = NPC_LID_LE; 579 lflags = 0; 580 581 /* Ensure we are not matching anything in UDP */ 582 rc = npc_parse_item_basic(pattern, &info); 583 if (rc) 584 return rc; 585 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; 593 break; 594 case ROC_NPC_ITEM_TYPE_GTPC: 595 lflags = NPC_F_UDP_GTP_GTPC; 596 info.len = pattern->size; 597 lt = NPC_LT_LE_GTPC; 598 break; 599 case ROC_NPC_ITEM_TYPE_GTPU: 600 lflags = NPC_F_UDP_GTP_GTPU_G_PDU; 601 info.len = pattern->size; 602 lt = NPC_LT_LE_GTPU; 603 break; 604 case ROC_NPC_ITEM_TYPE_GENEVE: 605 lflags = NPC_F_UDP_GENEVE; 606 info.len = pattern->size; 607 lt = NPC_LT_LE_GENEVE; 608 break; 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; 613 break; 614 case ROC_NPC_ITEM_TYPE_ESP: 615 lt = NPC_LT_LE_ESP; 616 info.len = pst->pattern->size; 617 break; 618 default: 619 return 0; 620 } 621 622 pst->tunnel = 1; 623 624 npc_get_hw_supp_mask(pst, &info, lid, lt); 625 rc = npc_parse_item_basic(pattern, &info); 626 if (rc != 0) 627 return rc; 628 629 return npc_update_parse_state(pst, &info, lid, lt, lflags); 630 } 631 632 int 633 npc_parse_lf(struct npc_parse_state *pst) 634 { 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; 638 int lid, lt, lflags; 639 int nr_vlans = 0; 640 int rc; 641 642 /* We hit this layer if there is a tunneling protocol */ 643 if (!pst->tunnel) 644 return 0; 645 646 if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH) 647 return 0; 648 649 lid = NPC_LID_LF; 650 lt = NPC_LT_LF_TU_ETHER; 651 lflags = 0; 652 653 /* No match support for vlan tags */ 654 info.hw_mask = NULL; 655 info.len = pst->pattern->size; 656 info.spec = NULL; 657 info.mask = NULL; 658 info.hw_hdr_len = 0; 659 660 /* Look ahead and find out any VLAN tags. These can be 661 * detected but no data matching is available. 662 */ 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) { 667 nr_vlans++; 668 last_pattern = pattern; 669 pattern++; 670 pattern = npc_parse_skip_void_and_any_items(pattern); 671 } 672 switch (nr_vlans) { 673 case 0: 674 break; 675 case 1: 676 lflags = NPC_F_TU_ETHER_CTAG; 677 break; 678 case 2: 679 lflags = NPC_F_TU_ETHER_STAG_CTAG; 680 break; 681 default: 682 return NPC_ERR_PATTERN_NOTSUP; 683 } 684 685 info.hw_mask = &hw_mask; 686 info.len = pst->pattern->size; 687 info.hw_hdr_len = 0; 688 npc_get_hw_supp_mask(pst, &info, lid, lt); 689 info.spec = NULL; 690 info.mask = NULL; 691 692 rc = npc_parse_item_basic(pst->pattern, &info); 693 if (rc != 0) 694 return rc; 695 696 pst->pattern = last_pattern; 697 698 return npc_update_parse_state(pst, &info, lid, lt, lflags); 699 } 700 701 int 702 npc_parse_lg(struct npc_parse_state *pst) 703 { 704 char hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 705 struct npc_parse_item_info info; 706 int lid, lt; 707 int rc; 708 709 if (!pst->tunnel) 710 return 0; 711 712 info.hw_mask = &hw_mask; 713 info.spec = NULL; 714 info.mask = NULL; 715 info.hw_hdr_len = 0; 716 lid = NPC_LID_LG; 717 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; 724 } else { 725 /* There is no tunneled IP header */ 726 return 0; 727 } 728 729 npc_get_hw_supp_mask(pst, &info, lid, lt); 730 rc = npc_parse_item_basic(pst->pattern, &info); 731 if (rc != 0) 732 return rc; 733 734 return npc_update_parse_state(pst, &info, lid, lt, 0); 735 } 736 737 int 738 npc_parse_lh(struct npc_parse_state *pst) 739 { 740 char hw_mask[NPC_MAX_EXTRACT_HW_LEN]; 741 struct npc_parse_item_info info; 742 int lid, lt; 743 int rc; 744 745 if (!pst->tunnel) 746 return 0; 747 748 info.hw_mask = &hw_mask; 749 info.spec = NULL; 750 info.mask = NULL; 751 info.hw_hdr_len = 0; 752 lid = NPC_LID_LH; 753 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; 758 break; 759 case ROC_NPC_ITEM_TYPE_TCP: 760 lt = NPC_LT_LH_TU_TCP; 761 info.len = pst->pattern->size; 762 break; 763 case ROC_NPC_ITEM_TYPE_SCTP: 764 lt = NPC_LT_LH_TU_SCTP; 765 info.len = pst->pattern->size; 766 break; 767 case ROC_NPC_ITEM_TYPE_ESP: 768 lt = NPC_LT_LH_TU_ESP; 769 info.len = pst->pattern->size; 770 break; 771 default: 772 return 0; 773 } 774 775 npc_get_hw_supp_mask(pst, &info, lid, lt); 776 rc = npc_parse_item_basic(pst->pattern, &info); 777 if (rc != 0) 778 return rc; 779 780 return npc_update_parse_state(pst, &info, lid, lt, 0); 781 } 782