1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2019 Solarflare Communications Inc. 5 * 6 * This software was jointly developed between OKTET Labs (under contract 7 * for Solarflare) and Solarflare Communications, Inc. 8 */ 9 10 #include <stdbool.h> 11 12 #include <rte_bitops.h> 13 #include <rte_common.h> 14 #include <rte_vxlan.h> 15 16 #include "efx.h" 17 18 #include "sfc.h" 19 #include "sfc_log.h" 20 #include "sfc_switch.h" 21 22 static int 23 sfc_mae_assign_entity_mport(struct sfc_adapter *sa, 24 efx_mport_sel_t *mportp) 25 { 26 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 27 28 return efx_mae_mport_by_pcie_function(encp->enc_pf, encp->enc_vf, 29 mportp); 30 } 31 32 int 33 sfc_mae_attach(struct sfc_adapter *sa) 34 { 35 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); 36 struct sfc_mae_switch_port_request switch_port_request = {0}; 37 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 38 efx_mport_sel_t entity_mport; 39 struct sfc_mae *mae = &sa->mae; 40 struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh; 41 efx_mae_limits_t limits; 42 int rc; 43 44 sfc_log_init(sa, "entry"); 45 46 if (!encp->enc_mae_supported) { 47 mae->status = SFC_MAE_STATUS_UNSUPPORTED; 48 return 0; 49 } 50 51 sfc_log_init(sa, "init MAE"); 52 rc = efx_mae_init(sa->nic); 53 if (rc != 0) 54 goto fail_mae_init; 55 56 sfc_log_init(sa, "get MAE limits"); 57 rc = efx_mae_get_limits(sa->nic, &limits); 58 if (rc != 0) 59 goto fail_mae_get_limits; 60 61 sfc_log_init(sa, "assign entity MPORT"); 62 rc = sfc_mae_assign_entity_mport(sa, &entity_mport); 63 if (rc != 0) 64 goto fail_mae_assign_entity_mport; 65 66 sfc_log_init(sa, "assign RTE switch domain"); 67 rc = sfc_mae_assign_switch_domain(sa, &mae->switch_domain_id); 68 if (rc != 0) 69 goto fail_mae_assign_switch_domain; 70 71 sfc_log_init(sa, "assign RTE switch port"); 72 switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT; 73 switch_port_request.entity_mportp = &entity_mport; 74 /* 75 * As of now, the driver does not support representors, so 76 * RTE ethdev MPORT simply matches that of the entity. 77 */ 78 switch_port_request.ethdev_mportp = &entity_mport; 79 switch_port_request.ethdev_port_id = sas->port_id; 80 rc = sfc_mae_assign_switch_port(mae->switch_domain_id, 81 &switch_port_request, 82 &mae->switch_port_id); 83 if (rc != 0) 84 goto fail_mae_assign_switch_port; 85 86 sfc_log_init(sa, "allocate encap. header bounce buffer"); 87 bounce_eh->buf_size = limits.eml_encap_header_size_limit; 88 bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh", 89 bounce_eh->buf_size, 0); 90 if (bounce_eh->buf == NULL) 91 goto fail_mae_alloc_bounce_eh; 92 93 mae->status = SFC_MAE_STATUS_SUPPORTED; 94 mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios; 95 mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios; 96 mae->encap_types_supported = limits.eml_encap_types_supported; 97 TAILQ_INIT(&mae->outer_rules); 98 TAILQ_INIT(&mae->encap_headers); 99 TAILQ_INIT(&mae->action_sets); 100 101 sfc_log_init(sa, "done"); 102 103 return 0; 104 105 fail_mae_alloc_bounce_eh: 106 fail_mae_assign_switch_port: 107 fail_mae_assign_switch_domain: 108 fail_mae_assign_entity_mport: 109 fail_mae_get_limits: 110 efx_mae_fini(sa->nic); 111 112 fail_mae_init: 113 sfc_log_init(sa, "failed %d", rc); 114 115 return rc; 116 } 117 118 void 119 sfc_mae_detach(struct sfc_adapter *sa) 120 { 121 struct sfc_mae *mae = &sa->mae; 122 enum sfc_mae_status status_prev = mae->status; 123 124 sfc_log_init(sa, "entry"); 125 126 mae->nb_action_rule_prios_max = 0; 127 mae->status = SFC_MAE_STATUS_UNKNOWN; 128 129 if (status_prev != SFC_MAE_STATUS_SUPPORTED) 130 return; 131 132 rte_free(mae->bounce_eh.buf); 133 134 efx_mae_fini(sa->nic); 135 136 sfc_log_init(sa, "done"); 137 } 138 139 static struct sfc_mae_outer_rule * 140 sfc_mae_outer_rule_attach(struct sfc_adapter *sa, 141 const efx_mae_match_spec_t *match_spec, 142 efx_tunnel_protocol_t encap_type) 143 { 144 struct sfc_mae_outer_rule *rule; 145 struct sfc_mae *mae = &sa->mae; 146 147 SFC_ASSERT(sfc_adapter_is_locked(sa)); 148 149 TAILQ_FOREACH(rule, &mae->outer_rules, entries) { 150 if (efx_mae_match_specs_equal(rule->match_spec, match_spec) && 151 rule->encap_type == encap_type) { 152 sfc_dbg(sa, "attaching to outer_rule=%p", rule); 153 ++(rule->refcnt); 154 return rule; 155 } 156 } 157 158 return NULL; 159 } 160 161 static int 162 sfc_mae_outer_rule_add(struct sfc_adapter *sa, 163 efx_mae_match_spec_t *match_spec, 164 efx_tunnel_protocol_t encap_type, 165 struct sfc_mae_outer_rule **rulep) 166 { 167 struct sfc_mae_outer_rule *rule; 168 struct sfc_mae *mae = &sa->mae; 169 170 SFC_ASSERT(sfc_adapter_is_locked(sa)); 171 172 rule = rte_zmalloc("sfc_mae_outer_rule", sizeof(*rule), 0); 173 if (rule == NULL) 174 return ENOMEM; 175 176 rule->refcnt = 1; 177 rule->match_spec = match_spec; 178 rule->encap_type = encap_type; 179 180 rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID; 181 182 TAILQ_INSERT_TAIL(&mae->outer_rules, rule, entries); 183 184 *rulep = rule; 185 186 sfc_dbg(sa, "added outer_rule=%p", rule); 187 188 return 0; 189 } 190 191 static void 192 sfc_mae_outer_rule_del(struct sfc_adapter *sa, 193 struct sfc_mae_outer_rule *rule) 194 { 195 struct sfc_mae *mae = &sa->mae; 196 197 SFC_ASSERT(sfc_adapter_is_locked(sa)); 198 SFC_ASSERT(rule->refcnt != 0); 199 200 --(rule->refcnt); 201 202 if (rule->refcnt != 0) 203 return; 204 205 if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID || 206 rule->fw_rsrc.refcnt != 0) { 207 sfc_err(sa, "deleting outer_rule=%p abandons its FW resource: OR_ID=0x%08x, refcnt=%u", 208 rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt); 209 } 210 211 efx_mae_match_spec_fini(sa->nic, rule->match_spec); 212 213 TAILQ_REMOVE(&mae->outer_rules, rule, entries); 214 rte_free(rule); 215 216 sfc_dbg(sa, "deleted outer_rule=%p", rule); 217 } 218 219 static int 220 sfc_mae_outer_rule_enable(struct sfc_adapter *sa, 221 struct sfc_mae_outer_rule *rule, 222 efx_mae_match_spec_t *match_spec_action) 223 { 224 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc; 225 int rc; 226 227 SFC_ASSERT(sfc_adapter_is_locked(sa)); 228 229 if (fw_rsrc->refcnt == 0) { 230 SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID); 231 SFC_ASSERT(rule->match_spec != NULL); 232 233 rc = efx_mae_outer_rule_insert(sa->nic, rule->match_spec, 234 rule->encap_type, 235 &fw_rsrc->rule_id); 236 if (rc != 0) { 237 sfc_err(sa, "failed to enable outer_rule=%p: %s", 238 rule, strerror(rc)); 239 return rc; 240 } 241 } 242 243 rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action, 244 &fw_rsrc->rule_id); 245 if (rc != 0) { 246 if (fw_rsrc->refcnt == 0) { 247 (void)efx_mae_outer_rule_remove(sa->nic, 248 &fw_rsrc->rule_id); 249 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID; 250 } 251 252 sfc_err(sa, "can't match on outer rule ID: %s", strerror(rc)); 253 254 return rc; 255 } 256 257 if (fw_rsrc->refcnt == 0) { 258 sfc_dbg(sa, "enabled outer_rule=%p: OR_ID=0x%08x", 259 rule, fw_rsrc->rule_id.id); 260 } 261 262 ++(fw_rsrc->refcnt); 263 264 return 0; 265 } 266 267 static void 268 sfc_mae_outer_rule_disable(struct sfc_adapter *sa, 269 struct sfc_mae_outer_rule *rule) 270 { 271 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc; 272 int rc; 273 274 SFC_ASSERT(sfc_adapter_is_locked(sa)); 275 276 if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID || 277 fw_rsrc->refcnt == 0) { 278 sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u", 279 rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt); 280 return; 281 } 282 283 if (fw_rsrc->refcnt == 1) { 284 rc = efx_mae_outer_rule_remove(sa->nic, &fw_rsrc->rule_id); 285 if (rc == 0) { 286 sfc_dbg(sa, "disabled outer_rule=%p with OR_ID=0x%08x", 287 rule, fw_rsrc->rule_id.id); 288 } else { 289 sfc_err(sa, "failed to disable outer_rule=%p with OR_ID=0x%08x: %s", 290 rule, fw_rsrc->rule_id.id, strerror(rc)); 291 } 292 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID; 293 } 294 295 --(fw_rsrc->refcnt); 296 } 297 298 static struct sfc_mae_encap_header * 299 sfc_mae_encap_header_attach(struct sfc_adapter *sa, 300 const struct sfc_mae_bounce_eh *bounce_eh) 301 { 302 struct sfc_mae_encap_header *encap_header; 303 struct sfc_mae *mae = &sa->mae; 304 305 SFC_ASSERT(sfc_adapter_is_locked(sa)); 306 307 TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) { 308 if (encap_header->size == bounce_eh->size && 309 memcmp(encap_header->buf, bounce_eh->buf, 310 bounce_eh->size) == 0) { 311 sfc_dbg(sa, "attaching to encap_header=%p", 312 encap_header); 313 ++(encap_header->refcnt); 314 return encap_header; 315 } 316 } 317 318 return NULL; 319 } 320 321 static int 322 sfc_mae_encap_header_add(struct sfc_adapter *sa, 323 const struct sfc_mae_bounce_eh *bounce_eh, 324 struct sfc_mae_encap_header **encap_headerp) 325 { 326 struct sfc_mae_encap_header *encap_header; 327 struct sfc_mae *mae = &sa->mae; 328 329 SFC_ASSERT(sfc_adapter_is_locked(sa)); 330 331 encap_header = rte_zmalloc("sfc_mae_encap_header", 332 sizeof(*encap_header), 0); 333 if (encap_header == NULL) 334 return ENOMEM; 335 336 encap_header->size = bounce_eh->size; 337 338 encap_header->buf = rte_malloc("sfc_mae_encap_header_buf", 339 encap_header->size, 0); 340 if (encap_header->buf == NULL) { 341 rte_free(encap_header); 342 return ENOMEM; 343 } 344 345 rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size); 346 347 encap_header->refcnt = 1; 348 encap_header->type = bounce_eh->type; 349 encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID; 350 351 TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries); 352 353 *encap_headerp = encap_header; 354 355 sfc_dbg(sa, "added encap_header=%p", encap_header); 356 357 return 0; 358 } 359 360 static void 361 sfc_mae_encap_header_del(struct sfc_adapter *sa, 362 struct sfc_mae_encap_header *encap_header) 363 { 364 struct sfc_mae *mae = &sa->mae; 365 366 if (encap_header == NULL) 367 return; 368 369 SFC_ASSERT(sfc_adapter_is_locked(sa)); 370 SFC_ASSERT(encap_header->refcnt != 0); 371 372 --(encap_header->refcnt); 373 374 if (encap_header->refcnt != 0) 375 return; 376 377 if (encap_header->fw_rsrc.eh_id.id != EFX_MAE_RSRC_ID_INVALID || 378 encap_header->fw_rsrc.refcnt != 0) { 379 sfc_err(sa, "deleting encap_header=%p abandons its FW resource: EH_ID=0x%08x, refcnt=%u", 380 encap_header, encap_header->fw_rsrc.eh_id.id, 381 encap_header->fw_rsrc.refcnt); 382 } 383 384 TAILQ_REMOVE(&mae->encap_headers, encap_header, entries); 385 rte_free(encap_header->buf); 386 rte_free(encap_header); 387 388 sfc_dbg(sa, "deleted encap_header=%p", encap_header); 389 } 390 391 static int 392 sfc_mae_encap_header_enable(struct sfc_adapter *sa, 393 struct sfc_mae_encap_header *encap_header, 394 efx_mae_actions_t *action_set_spec) 395 { 396 struct sfc_mae_fw_rsrc *fw_rsrc; 397 int rc; 398 399 if (encap_header == NULL) 400 return 0; 401 402 SFC_ASSERT(sfc_adapter_is_locked(sa)); 403 404 fw_rsrc = &encap_header->fw_rsrc; 405 406 if (fw_rsrc->refcnt == 0) { 407 SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID); 408 SFC_ASSERT(encap_header->buf != NULL); 409 SFC_ASSERT(encap_header->size != 0); 410 411 rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type, 412 encap_header->buf, 413 encap_header->size, 414 &fw_rsrc->eh_id); 415 if (rc != 0) { 416 sfc_err(sa, "failed to enable encap_header=%p: %s", 417 encap_header, strerror(rc)); 418 return rc; 419 } 420 } 421 422 rc = efx_mae_action_set_fill_in_eh_id(action_set_spec, 423 &fw_rsrc->eh_id); 424 if (rc != 0) { 425 if (fw_rsrc->refcnt == 0) { 426 (void)efx_mae_encap_header_free(sa->nic, 427 &fw_rsrc->eh_id); 428 fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID; 429 } 430 431 sfc_err(sa, "can't fill in encap. header ID: %s", strerror(rc)); 432 433 return rc; 434 } 435 436 if (fw_rsrc->refcnt == 0) { 437 sfc_dbg(sa, "enabled encap_header=%p: EH_ID=0x%08x", 438 encap_header, fw_rsrc->eh_id.id); 439 } 440 441 ++(fw_rsrc->refcnt); 442 443 return 0; 444 } 445 446 static void 447 sfc_mae_encap_header_disable(struct sfc_adapter *sa, 448 struct sfc_mae_encap_header *encap_header) 449 { 450 struct sfc_mae_fw_rsrc *fw_rsrc; 451 int rc; 452 453 if (encap_header == NULL) 454 return; 455 456 SFC_ASSERT(sfc_adapter_is_locked(sa)); 457 458 fw_rsrc = &encap_header->fw_rsrc; 459 460 if (fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID || 461 fw_rsrc->refcnt == 0) { 462 sfc_err(sa, "failed to disable encap_header=%p: already disabled; EH_ID=0x%08x, refcnt=%u", 463 encap_header, fw_rsrc->eh_id.id, fw_rsrc->refcnt); 464 return; 465 } 466 467 if (fw_rsrc->refcnt == 1) { 468 rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id); 469 if (rc == 0) { 470 sfc_dbg(sa, "disabled encap_header=%p with EH_ID=0x%08x", 471 encap_header, fw_rsrc->eh_id.id); 472 } else { 473 sfc_err(sa, "failed to disable encap_header=%p with EH_ID=0x%08x: %s", 474 encap_header, fw_rsrc->eh_id.id, strerror(rc)); 475 } 476 fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID; 477 } 478 479 --(fw_rsrc->refcnt); 480 } 481 482 static struct sfc_mae_action_set * 483 sfc_mae_action_set_attach(struct sfc_adapter *sa, 484 const struct sfc_mae_encap_header *encap_header, 485 const efx_mae_actions_t *spec) 486 { 487 struct sfc_mae_action_set *action_set; 488 struct sfc_mae *mae = &sa->mae; 489 490 SFC_ASSERT(sfc_adapter_is_locked(sa)); 491 492 TAILQ_FOREACH(action_set, &mae->action_sets, entries) { 493 if (action_set->encap_header == encap_header && 494 efx_mae_action_set_specs_equal(action_set->spec, spec)) { 495 sfc_dbg(sa, "attaching to action_set=%p", action_set); 496 ++(action_set->refcnt); 497 return action_set; 498 } 499 } 500 501 return NULL; 502 } 503 504 static int 505 sfc_mae_action_set_add(struct sfc_adapter *sa, 506 efx_mae_actions_t *spec, 507 struct sfc_mae_encap_header *encap_header, 508 struct sfc_mae_action_set **action_setp) 509 { 510 struct sfc_mae_action_set *action_set; 511 struct sfc_mae *mae = &sa->mae; 512 513 SFC_ASSERT(sfc_adapter_is_locked(sa)); 514 515 action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0); 516 if (action_set == NULL) 517 return ENOMEM; 518 519 action_set->refcnt = 1; 520 action_set->spec = spec; 521 action_set->encap_header = encap_header; 522 523 action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID; 524 525 TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries); 526 527 *action_setp = action_set; 528 529 sfc_dbg(sa, "added action_set=%p", action_set); 530 531 return 0; 532 } 533 534 static void 535 sfc_mae_action_set_del(struct sfc_adapter *sa, 536 struct sfc_mae_action_set *action_set) 537 { 538 struct sfc_mae *mae = &sa->mae; 539 540 SFC_ASSERT(sfc_adapter_is_locked(sa)); 541 SFC_ASSERT(action_set->refcnt != 0); 542 543 --(action_set->refcnt); 544 545 if (action_set->refcnt != 0) 546 return; 547 548 if (action_set->fw_rsrc.aset_id.id != EFX_MAE_RSRC_ID_INVALID || 549 action_set->fw_rsrc.refcnt != 0) { 550 sfc_err(sa, "deleting action_set=%p abandons its FW resource: AS_ID=0x%08x, refcnt=%u", 551 action_set, action_set->fw_rsrc.aset_id.id, 552 action_set->fw_rsrc.refcnt); 553 } 554 555 efx_mae_action_set_spec_fini(sa->nic, action_set->spec); 556 sfc_mae_encap_header_del(sa, action_set->encap_header); 557 TAILQ_REMOVE(&mae->action_sets, action_set, entries); 558 rte_free(action_set); 559 560 sfc_dbg(sa, "deleted action_set=%p", action_set); 561 } 562 563 static int 564 sfc_mae_action_set_enable(struct sfc_adapter *sa, 565 struct sfc_mae_action_set *action_set) 566 { 567 struct sfc_mae_encap_header *encap_header = action_set->encap_header; 568 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; 569 int rc; 570 571 SFC_ASSERT(sfc_adapter_is_locked(sa)); 572 573 if (fw_rsrc->refcnt == 0) { 574 SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID); 575 SFC_ASSERT(action_set->spec != NULL); 576 577 rc = sfc_mae_encap_header_enable(sa, encap_header, 578 action_set->spec); 579 if (rc != 0) 580 return rc; 581 582 rc = efx_mae_action_set_alloc(sa->nic, action_set->spec, 583 &fw_rsrc->aset_id); 584 if (rc != 0) { 585 sfc_mae_encap_header_disable(sa, encap_header); 586 587 sfc_err(sa, "failed to enable action_set=%p: %s", 588 action_set, strerror(rc)); 589 590 return rc; 591 } 592 593 sfc_dbg(sa, "enabled action_set=%p: AS_ID=0x%08x", 594 action_set, fw_rsrc->aset_id.id); 595 } 596 597 ++(fw_rsrc->refcnt); 598 599 return 0; 600 } 601 602 static void 603 sfc_mae_action_set_disable(struct sfc_adapter *sa, 604 struct sfc_mae_action_set *action_set) 605 { 606 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; 607 int rc; 608 609 SFC_ASSERT(sfc_adapter_is_locked(sa)); 610 611 if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID || 612 fw_rsrc->refcnt == 0) { 613 sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u", 614 action_set, fw_rsrc->aset_id.id, fw_rsrc->refcnt); 615 return; 616 } 617 618 if (fw_rsrc->refcnt == 1) { 619 rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id); 620 if (rc == 0) { 621 sfc_dbg(sa, "disabled action_set=%p with AS_ID=0x%08x", 622 action_set, fw_rsrc->aset_id.id); 623 } else { 624 sfc_err(sa, "failed to disable action_set=%p with AS_ID=0x%08x: %s", 625 action_set, fw_rsrc->aset_id.id, strerror(rc)); 626 } 627 fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID; 628 629 sfc_mae_encap_header_disable(sa, action_set->encap_header); 630 } 631 632 --(fw_rsrc->refcnt); 633 } 634 635 void 636 sfc_mae_flow_cleanup(struct sfc_adapter *sa, 637 struct rte_flow *flow) 638 { 639 struct sfc_flow_spec *spec; 640 struct sfc_flow_spec_mae *spec_mae; 641 642 if (flow == NULL) 643 return; 644 645 spec = &flow->spec; 646 647 if (spec == NULL) 648 return; 649 650 spec_mae = &spec->mae; 651 652 SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID); 653 654 if (spec_mae->outer_rule != NULL) 655 sfc_mae_outer_rule_del(sa, spec_mae->outer_rule); 656 657 if (spec_mae->action_set != NULL) 658 sfc_mae_action_set_del(sa, spec_mae->action_set); 659 660 if (spec_mae->match_spec != NULL) 661 efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec); 662 } 663 664 static int 665 sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx) 666 { 667 struct sfc_mae_pattern_data *pdata = &ctx->pattern_data; 668 const efx_mae_field_id_t *fremap = ctx->field_ids_remap; 669 const efx_mae_field_id_t field_ids[] = { 670 EFX_MAE_FIELD_VLAN0_PROTO_BE, 671 EFX_MAE_FIELD_VLAN1_PROTO_BE, 672 }; 673 const struct sfc_mae_ethertype *et; 674 unsigned int i; 675 int rc; 676 677 /* 678 * In accordance with RTE flow API convention, the innermost L2 679 * item's "type" ("inner_type") is a L3 EtherType. If there is 680 * no L3 item, it's 0x0000/0x0000. 681 */ 682 et = &pdata->ethertypes[pdata->nb_vlan_tags]; 683 rc = efx_mae_match_spec_field_set(ctx->match_spec, 684 fremap[EFX_MAE_FIELD_ETHER_TYPE_BE], 685 sizeof(et->value), 686 (const uint8_t *)&et->value, 687 sizeof(et->mask), 688 (const uint8_t *)&et->mask); 689 if (rc != 0) 690 return rc; 691 692 /* 693 * sfc_mae_rule_parse_item_vlan() has already made sure 694 * that pdata->nb_vlan_tags does not exceed this figure. 695 */ 696 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2); 697 698 for (i = 0; i < pdata->nb_vlan_tags; ++i) { 699 et = &pdata->ethertypes[i]; 700 701 rc = efx_mae_match_spec_field_set(ctx->match_spec, 702 fremap[field_ids[i]], 703 sizeof(et->value), 704 (const uint8_t *)&et->value, 705 sizeof(et->mask), 706 (const uint8_t *)&et->mask); 707 if (rc != 0) 708 return rc; 709 } 710 711 return 0; 712 } 713 714 static int 715 sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx, 716 struct rte_flow_error *error) 717 { 718 const efx_mae_field_id_t *fremap = ctx->field_ids_remap; 719 struct sfc_mae_pattern_data *pdata = &ctx->pattern_data; 720 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes; 721 const rte_be16_t supported_tpids[] = { 722 /* VLAN standard TPID (always the first element) */ 723 RTE_BE16(RTE_ETHER_TYPE_VLAN), 724 725 /* Double-tagging TPIDs */ 726 RTE_BE16(RTE_ETHER_TYPE_QINQ), 727 RTE_BE16(RTE_ETHER_TYPE_QINQ1), 728 RTE_BE16(RTE_ETHER_TYPE_QINQ2), 729 RTE_BE16(RTE_ETHER_TYPE_QINQ3), 730 }; 731 bool enforce_tag_presence[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {0}; 732 unsigned int nb_supported_tpids = RTE_DIM(supported_tpids); 733 unsigned int ethertype_idx; 734 const uint8_t *valuep; 735 const uint8_t *maskp; 736 int rc; 737 738 if (pdata->innermost_ethertype_restriction.mask != 0 && 739 pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) { 740 /* 741 * If a single item VLAN is followed by a L3 item, value 742 * of "type" in item ETH can't be a double-tagging TPID. 743 */ 744 nb_supported_tpids = 1; 745 } 746 747 /* 748 * sfc_mae_rule_parse_item_vlan() has already made sure 749 * that pdata->nb_vlan_tags does not exceed this figure. 750 */ 751 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2); 752 753 for (ethertype_idx = 0; 754 ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) { 755 unsigned int tpid_idx; 756 757 /* 758 * This loop can have only two iterations. On the second one, 759 * drop outer tag presence enforcement bit because the inner 760 * tag presence automatically assumes that for the outer tag. 761 */ 762 enforce_tag_presence[0] = B_FALSE; 763 764 if (ethertypes[ethertype_idx].mask == RTE_BE16(0)) { 765 if (pdata->tci_masks[ethertype_idx] == RTE_BE16(0)) 766 enforce_tag_presence[ethertype_idx] = B_TRUE; 767 768 /* No match on this field, and no value check. */ 769 nb_supported_tpids = 1; 770 continue; 771 } 772 773 /* Exact match is supported only. */ 774 if (ethertypes[ethertype_idx].mask != RTE_BE16(0xffff)) { 775 rc = EINVAL; 776 goto fail; 777 } 778 779 for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1; 780 tpid_idx < nb_supported_tpids; ++tpid_idx) { 781 if (ethertypes[ethertype_idx].value == 782 supported_tpids[tpid_idx]) 783 break; 784 } 785 786 if (tpid_idx == nb_supported_tpids) { 787 rc = EINVAL; 788 goto fail; 789 } 790 791 nb_supported_tpids = 1; 792 } 793 794 if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) { 795 struct sfc_mae_ethertype *et = ðertypes[ethertype_idx]; 796 797 if (et->mask == 0) { 798 et->mask = RTE_BE16(0xffff); 799 et->value = 800 pdata->innermost_ethertype_restriction.value; 801 } else if (et->mask != RTE_BE16(0xffff) || 802 et->value != 803 pdata->innermost_ethertype_restriction.value) { 804 rc = EINVAL; 805 goto fail; 806 } 807 } 808 809 /* 810 * Now, when the number of VLAN tags is known, set fields 811 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first 812 * one is either a valid L3 EtherType (or 0x0000/0x0000), 813 * and the last two are valid TPIDs (or 0x0000/0x0000). 814 */ 815 rc = sfc_mae_set_ethertypes(ctx); 816 if (rc != 0) 817 goto fail; 818 819 if (pdata->l3_next_proto_restriction_mask == 0xff) { 820 if (pdata->l3_next_proto_mask == 0) { 821 pdata->l3_next_proto_mask = 0xff; 822 pdata->l3_next_proto_value = 823 pdata->l3_next_proto_restriction_value; 824 } else if (pdata->l3_next_proto_mask != 0xff || 825 pdata->l3_next_proto_value != 826 pdata->l3_next_proto_restriction_value) { 827 rc = EINVAL; 828 goto fail; 829 } 830 } 831 832 if (enforce_tag_presence[0] || pdata->has_ovlan_mask) { 833 rc = efx_mae_match_spec_bit_set(ctx->match_spec, 834 fremap[EFX_MAE_FIELD_HAS_OVLAN], 835 enforce_tag_presence[0] || 836 pdata->has_ovlan_value); 837 if (rc != 0) 838 goto fail; 839 } 840 841 if (enforce_tag_presence[1] || pdata->has_ivlan_mask) { 842 rc = efx_mae_match_spec_bit_set(ctx->match_spec, 843 fremap[EFX_MAE_FIELD_HAS_IVLAN], 844 enforce_tag_presence[1] || 845 pdata->has_ivlan_value); 846 if (rc != 0) 847 goto fail; 848 } 849 850 valuep = (const uint8_t *)&pdata->l3_next_proto_value; 851 maskp = (const uint8_t *)&pdata->l3_next_proto_mask; 852 rc = efx_mae_match_spec_field_set(ctx->match_spec, 853 fremap[EFX_MAE_FIELD_IP_PROTO], 854 sizeof(pdata->l3_next_proto_value), 855 valuep, 856 sizeof(pdata->l3_next_proto_mask), 857 maskp); 858 if (rc != 0) 859 goto fail; 860 861 return 0; 862 863 fail: 864 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL, 865 "Failed to process pattern data"); 866 } 867 868 static int 869 sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item, 870 struct sfc_flow_parse_ctx *ctx, 871 struct rte_flow_error *error) 872 { 873 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 874 const struct rte_flow_item_port_id supp_mask = { 875 .id = 0xffffffff, 876 }; 877 const void *def_mask = &rte_flow_item_port_id_mask; 878 const struct rte_flow_item_port_id *spec = NULL; 879 const struct rte_flow_item_port_id *mask = NULL; 880 efx_mport_sel_t mport_sel; 881 int rc; 882 883 if (ctx_mae->match_mport_set) { 884 return rte_flow_error_set(error, ENOTSUP, 885 RTE_FLOW_ERROR_TYPE_ITEM, item, 886 "Can't handle multiple traffic source items"); 887 } 888 889 rc = sfc_flow_parse_init(item, 890 (const void **)&spec, (const void **)&mask, 891 (const void *)&supp_mask, def_mask, 892 sizeof(struct rte_flow_item_port_id), error); 893 if (rc != 0) 894 return rc; 895 896 if (mask->id != supp_mask.id) { 897 return rte_flow_error_set(error, EINVAL, 898 RTE_FLOW_ERROR_TYPE_ITEM, item, 899 "Bad mask in the PORT_ID pattern item"); 900 } 901 902 /* If "spec" is not set, could be any port ID */ 903 if (spec == NULL) 904 return 0; 905 906 if (spec->id > UINT16_MAX) { 907 return rte_flow_error_set(error, EOVERFLOW, 908 RTE_FLOW_ERROR_TYPE_ITEM, item, 909 "The port ID is too large"); 910 } 911 912 rc = sfc_mae_switch_port_by_ethdev(ctx_mae->sa->mae.switch_domain_id, 913 spec->id, &mport_sel); 914 if (rc != 0) { 915 return rte_flow_error_set(error, rc, 916 RTE_FLOW_ERROR_TYPE_ITEM, item, 917 "Can't find RTE ethdev by the port ID"); 918 } 919 920 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, 921 &mport_sel, NULL); 922 if (rc != 0) { 923 return rte_flow_error_set(error, rc, 924 RTE_FLOW_ERROR_TYPE_ITEM, item, 925 "Failed to set MPORT for the port ID"); 926 } 927 928 ctx_mae->match_mport_set = B_TRUE; 929 930 return 0; 931 } 932 933 static int 934 sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item, 935 struct sfc_flow_parse_ctx *ctx, 936 struct rte_flow_error *error) 937 { 938 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 939 const struct rte_flow_item_phy_port supp_mask = { 940 .index = 0xffffffff, 941 }; 942 const void *def_mask = &rte_flow_item_phy_port_mask; 943 const struct rte_flow_item_phy_port *spec = NULL; 944 const struct rte_flow_item_phy_port *mask = NULL; 945 efx_mport_sel_t mport_v; 946 int rc; 947 948 if (ctx_mae->match_mport_set) { 949 return rte_flow_error_set(error, ENOTSUP, 950 RTE_FLOW_ERROR_TYPE_ITEM, item, 951 "Can't handle multiple traffic source items"); 952 } 953 954 rc = sfc_flow_parse_init(item, 955 (const void **)&spec, (const void **)&mask, 956 (const void *)&supp_mask, def_mask, 957 sizeof(struct rte_flow_item_phy_port), error); 958 if (rc != 0) 959 return rc; 960 961 if (mask->index != supp_mask.index) { 962 return rte_flow_error_set(error, EINVAL, 963 RTE_FLOW_ERROR_TYPE_ITEM, item, 964 "Bad mask in the PHY_PORT pattern item"); 965 } 966 967 /* If "spec" is not set, could be any physical port */ 968 if (spec == NULL) 969 return 0; 970 971 rc = efx_mae_mport_by_phy_port(spec->index, &mport_v); 972 if (rc != 0) { 973 return rte_flow_error_set(error, rc, 974 RTE_FLOW_ERROR_TYPE_ITEM, item, 975 "Failed to convert the PHY_PORT index"); 976 } 977 978 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 979 if (rc != 0) { 980 return rte_flow_error_set(error, rc, 981 RTE_FLOW_ERROR_TYPE_ITEM, item, 982 "Failed to set MPORT for the PHY_PORT"); 983 } 984 985 ctx_mae->match_mport_set = B_TRUE; 986 987 return 0; 988 } 989 990 static int 991 sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item, 992 struct sfc_flow_parse_ctx *ctx, 993 struct rte_flow_error *error) 994 { 995 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 996 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic); 997 efx_mport_sel_t mport_v; 998 int rc; 999 1000 if (ctx_mae->match_mport_set) { 1001 return rte_flow_error_set(error, ENOTSUP, 1002 RTE_FLOW_ERROR_TYPE_ITEM, item, 1003 "Can't handle multiple traffic source items"); 1004 } 1005 1006 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID, 1007 &mport_v); 1008 if (rc != 0) { 1009 return rte_flow_error_set(error, rc, 1010 RTE_FLOW_ERROR_TYPE_ITEM, item, 1011 "Failed to convert the PF ID"); 1012 } 1013 1014 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 1015 if (rc != 0) { 1016 return rte_flow_error_set(error, rc, 1017 RTE_FLOW_ERROR_TYPE_ITEM, item, 1018 "Failed to set MPORT for the PF"); 1019 } 1020 1021 ctx_mae->match_mport_set = B_TRUE; 1022 1023 return 0; 1024 } 1025 1026 static int 1027 sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item, 1028 struct sfc_flow_parse_ctx *ctx, 1029 struct rte_flow_error *error) 1030 { 1031 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1032 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic); 1033 const struct rte_flow_item_vf supp_mask = { 1034 .id = 0xffffffff, 1035 }; 1036 const void *def_mask = &rte_flow_item_vf_mask; 1037 const struct rte_flow_item_vf *spec = NULL; 1038 const struct rte_flow_item_vf *mask = NULL; 1039 efx_mport_sel_t mport_v; 1040 int rc; 1041 1042 if (ctx_mae->match_mport_set) { 1043 return rte_flow_error_set(error, ENOTSUP, 1044 RTE_FLOW_ERROR_TYPE_ITEM, item, 1045 "Can't handle multiple traffic source items"); 1046 } 1047 1048 rc = sfc_flow_parse_init(item, 1049 (const void **)&spec, (const void **)&mask, 1050 (const void *)&supp_mask, def_mask, 1051 sizeof(struct rte_flow_item_vf), error); 1052 if (rc != 0) 1053 return rc; 1054 1055 if (mask->id != supp_mask.id) { 1056 return rte_flow_error_set(error, EINVAL, 1057 RTE_FLOW_ERROR_TYPE_ITEM, item, 1058 "Bad mask in the VF pattern item"); 1059 } 1060 1061 /* 1062 * If "spec" is not set, the item requests any VF related to the 1063 * PF of the current DPDK port (but not the PF itself). 1064 * Reject this match criterion as unsupported. 1065 */ 1066 if (spec == NULL) { 1067 return rte_flow_error_set(error, EINVAL, 1068 RTE_FLOW_ERROR_TYPE_ITEM, item, 1069 "Bad spec in the VF pattern item"); 1070 } 1071 1072 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v); 1073 if (rc != 0) { 1074 return rte_flow_error_set(error, rc, 1075 RTE_FLOW_ERROR_TYPE_ITEM, item, 1076 "Failed to convert the PF + VF IDs"); 1077 } 1078 1079 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 1080 if (rc != 0) { 1081 return rte_flow_error_set(error, rc, 1082 RTE_FLOW_ERROR_TYPE_ITEM, item, 1083 "Failed to set MPORT for the PF + VF"); 1084 } 1085 1086 ctx_mae->match_mport_set = B_TRUE; 1087 1088 return 0; 1089 } 1090 1091 /* 1092 * Having this field ID in a field locator means that this 1093 * locator cannot be used to actually set the field at the 1094 * time when the corresponding item gets encountered. Such 1095 * fields get stashed in the parsing context instead. This 1096 * is required to resolve dependencies between the stashed 1097 * fields. See sfc_mae_rule_process_pattern_data(). 1098 */ 1099 #define SFC_MAE_FIELD_HANDLING_DEFERRED EFX_MAE_FIELD_NIDS 1100 1101 struct sfc_mae_field_locator { 1102 efx_mae_field_id_t field_id; 1103 size_t size; 1104 /* Field offset in the corresponding rte_flow_item_ struct */ 1105 size_t ofst; 1106 }; 1107 1108 static void 1109 sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators, 1110 unsigned int nb_field_locators, void *mask_ptr, 1111 size_t mask_size) 1112 { 1113 unsigned int i; 1114 1115 memset(mask_ptr, 0, mask_size); 1116 1117 for (i = 0; i < nb_field_locators; ++i) { 1118 const struct sfc_mae_field_locator *fl = &field_locators[i]; 1119 1120 SFC_ASSERT(fl->ofst + fl->size <= mask_size); 1121 memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size); 1122 } 1123 } 1124 1125 static int 1126 sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators, 1127 unsigned int nb_field_locators, const uint8_t *spec, 1128 const uint8_t *mask, struct sfc_mae_parse_ctx *ctx, 1129 struct rte_flow_error *error) 1130 { 1131 const efx_mae_field_id_t *fremap = ctx->field_ids_remap; 1132 unsigned int i; 1133 int rc = 0; 1134 1135 for (i = 0; i < nb_field_locators; ++i) { 1136 const struct sfc_mae_field_locator *fl = &field_locators[i]; 1137 1138 if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED) 1139 continue; 1140 1141 rc = efx_mae_match_spec_field_set(ctx->match_spec, 1142 fremap[fl->field_id], 1143 fl->size, spec + fl->ofst, 1144 fl->size, mask + fl->ofst); 1145 if (rc != 0) 1146 break; 1147 } 1148 1149 if (rc != 0) { 1150 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1151 NULL, "Failed to process item fields"); 1152 } 1153 1154 return rc; 1155 } 1156 1157 static const struct sfc_mae_field_locator flocs_eth[] = { 1158 { 1159 /* 1160 * This locator is used only for building supported fields mask. 1161 * The field is handled by sfc_mae_rule_process_pattern_data(). 1162 */ 1163 SFC_MAE_FIELD_HANDLING_DEFERRED, 1164 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type), 1165 offsetof(struct rte_flow_item_eth, type), 1166 }, 1167 { 1168 EFX_MAE_FIELD_ETH_DADDR_BE, 1169 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst), 1170 offsetof(struct rte_flow_item_eth, dst), 1171 }, 1172 { 1173 EFX_MAE_FIELD_ETH_SADDR_BE, 1174 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src), 1175 offsetof(struct rte_flow_item_eth, src), 1176 }, 1177 }; 1178 1179 static int 1180 sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item, 1181 struct sfc_flow_parse_ctx *ctx, 1182 struct rte_flow_error *error) 1183 { 1184 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1185 struct rte_flow_item_eth supp_mask; 1186 const uint8_t *spec = NULL; 1187 const uint8_t *mask = NULL; 1188 int rc; 1189 1190 sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth), 1191 &supp_mask, sizeof(supp_mask)); 1192 supp_mask.has_vlan = 1; 1193 1194 rc = sfc_flow_parse_init(item, 1195 (const void **)&spec, (const void **)&mask, 1196 (const void *)&supp_mask, 1197 &rte_flow_item_eth_mask, 1198 sizeof(struct rte_flow_item_eth), error); 1199 if (rc != 0) 1200 return rc; 1201 1202 if (spec != NULL) { 1203 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1204 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes; 1205 const struct rte_flow_item_eth *item_spec; 1206 const struct rte_flow_item_eth *item_mask; 1207 1208 item_spec = (const struct rte_flow_item_eth *)spec; 1209 item_mask = (const struct rte_flow_item_eth *)mask; 1210 1211 /* 1212 * Remember various match criteria in the parsing context. 1213 * sfc_mae_rule_process_pattern_data() will consider them 1214 * altogether when the rest of the items have been parsed. 1215 */ 1216 ethertypes[0].value = item_spec->type; 1217 ethertypes[0].mask = item_mask->type; 1218 if (item_mask->has_vlan) { 1219 pdata->has_ovlan_mask = B_TRUE; 1220 if (item_spec->has_vlan) 1221 pdata->has_ovlan_value = B_TRUE; 1222 } 1223 } else { 1224 /* 1225 * The specification is empty. The overall pattern 1226 * validity will be enforced at the end of parsing. 1227 * See sfc_mae_rule_process_pattern_data(). 1228 */ 1229 return 0; 1230 } 1231 1232 return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask, 1233 ctx_mae, error); 1234 } 1235 1236 static const struct sfc_mae_field_locator flocs_vlan[] = { 1237 /* Outermost tag */ 1238 { 1239 EFX_MAE_FIELD_VLAN0_TCI_BE, 1240 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci), 1241 offsetof(struct rte_flow_item_vlan, tci), 1242 }, 1243 { 1244 /* 1245 * This locator is used only for building supported fields mask. 1246 * The field is handled by sfc_mae_rule_process_pattern_data(). 1247 */ 1248 SFC_MAE_FIELD_HANDLING_DEFERRED, 1249 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type), 1250 offsetof(struct rte_flow_item_vlan, inner_type), 1251 }, 1252 1253 /* Innermost tag */ 1254 { 1255 EFX_MAE_FIELD_VLAN1_TCI_BE, 1256 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci), 1257 offsetof(struct rte_flow_item_vlan, tci), 1258 }, 1259 { 1260 /* 1261 * This locator is used only for building supported fields mask. 1262 * The field is handled by sfc_mae_rule_process_pattern_data(). 1263 */ 1264 SFC_MAE_FIELD_HANDLING_DEFERRED, 1265 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type), 1266 offsetof(struct rte_flow_item_vlan, inner_type), 1267 }, 1268 }; 1269 1270 static int 1271 sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item, 1272 struct sfc_flow_parse_ctx *ctx, 1273 struct rte_flow_error *error) 1274 { 1275 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1276 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1277 boolean_t *has_vlan_mp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = { 1278 &pdata->has_ovlan_mask, 1279 &pdata->has_ivlan_mask, 1280 }; 1281 boolean_t *has_vlan_vp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = { 1282 &pdata->has_ovlan_value, 1283 &pdata->has_ivlan_value, 1284 }; 1285 boolean_t *cur_tag_presence_bit_mp; 1286 boolean_t *cur_tag_presence_bit_vp; 1287 const struct sfc_mae_field_locator *flocs; 1288 struct rte_flow_item_vlan supp_mask; 1289 const uint8_t *spec = NULL; 1290 const uint8_t *mask = NULL; 1291 unsigned int nb_flocs; 1292 int rc; 1293 1294 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2); 1295 1296 if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) { 1297 return rte_flow_error_set(error, ENOTSUP, 1298 RTE_FLOW_ERROR_TYPE_ITEM, item, 1299 "Can't match that many VLAN tags"); 1300 } 1301 1302 cur_tag_presence_bit_mp = has_vlan_mp_by_nb_tags[pdata->nb_vlan_tags]; 1303 cur_tag_presence_bit_vp = has_vlan_vp_by_nb_tags[pdata->nb_vlan_tags]; 1304 1305 if (*cur_tag_presence_bit_mp == B_TRUE && 1306 *cur_tag_presence_bit_vp == B_FALSE) { 1307 return rte_flow_error_set(error, EINVAL, 1308 RTE_FLOW_ERROR_TYPE_ITEM, item, 1309 "The previous item enforces no (more) VLAN, " 1310 "so the current item (VLAN) must not exist"); 1311 } 1312 1313 nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS; 1314 flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs; 1315 1316 sfc_mae_item_build_supp_mask(flocs, nb_flocs, 1317 &supp_mask, sizeof(supp_mask)); 1318 /* 1319 * This only means that the field is supported by the driver and libefx. 1320 * Support on NIC level will be checked when all items have been parsed. 1321 */ 1322 supp_mask.has_more_vlan = 1; 1323 1324 rc = sfc_flow_parse_init(item, 1325 (const void **)&spec, (const void **)&mask, 1326 (const void *)&supp_mask, 1327 &rte_flow_item_vlan_mask, 1328 sizeof(struct rte_flow_item_vlan), error); 1329 if (rc != 0) 1330 return rc; 1331 1332 if (spec != NULL) { 1333 struct sfc_mae_ethertype *et = pdata->ethertypes; 1334 const struct rte_flow_item_vlan *item_spec; 1335 const struct rte_flow_item_vlan *item_mask; 1336 1337 item_spec = (const struct rte_flow_item_vlan *)spec; 1338 item_mask = (const struct rte_flow_item_vlan *)mask; 1339 1340 /* 1341 * Remember various match criteria in the parsing context. 1342 * sfc_mae_rule_process_pattern_data() will consider them 1343 * altogether when the rest of the items have been parsed. 1344 */ 1345 et[pdata->nb_vlan_tags + 1].value = item_spec->inner_type; 1346 et[pdata->nb_vlan_tags + 1].mask = item_mask->inner_type; 1347 pdata->tci_masks[pdata->nb_vlan_tags] = item_mask->tci; 1348 if (item_mask->has_more_vlan) { 1349 if (pdata->nb_vlan_tags == 1350 SFC_MAE_MATCH_VLAN_MAX_NTAGS) { 1351 return rte_flow_error_set(error, ENOTSUP, 1352 RTE_FLOW_ERROR_TYPE_ITEM, item, 1353 "Can't use 'has_more_vlan' in " 1354 "the second item VLAN"); 1355 } 1356 pdata->has_ivlan_mask = B_TRUE; 1357 if (item_spec->has_more_vlan) 1358 pdata->has_ivlan_value = B_TRUE; 1359 } 1360 1361 /* Convert TCI to MAE representation right now. */ 1362 rc = sfc_mae_parse_item(flocs, nb_flocs, spec, mask, 1363 ctx_mae, error); 1364 if (rc != 0) 1365 return rc; 1366 } 1367 1368 ++(pdata->nb_vlan_tags); 1369 1370 return 0; 1371 } 1372 1373 static const struct sfc_mae_field_locator flocs_ipv4[] = { 1374 { 1375 EFX_MAE_FIELD_SRC_IP4_BE, 1376 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr), 1377 offsetof(struct rte_flow_item_ipv4, hdr.src_addr), 1378 }, 1379 { 1380 EFX_MAE_FIELD_DST_IP4_BE, 1381 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr), 1382 offsetof(struct rte_flow_item_ipv4, hdr.dst_addr), 1383 }, 1384 { 1385 /* 1386 * This locator is used only for building supported fields mask. 1387 * The field is handled by sfc_mae_rule_process_pattern_data(). 1388 */ 1389 SFC_MAE_FIELD_HANDLING_DEFERRED, 1390 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id), 1391 offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id), 1392 }, 1393 { 1394 EFX_MAE_FIELD_IP_TOS, 1395 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, 1396 hdr.type_of_service), 1397 offsetof(struct rte_flow_item_ipv4, hdr.type_of_service), 1398 }, 1399 { 1400 EFX_MAE_FIELD_IP_TTL, 1401 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live), 1402 offsetof(struct rte_flow_item_ipv4, hdr.time_to_live), 1403 }, 1404 }; 1405 1406 static int 1407 sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item, 1408 struct sfc_flow_parse_ctx *ctx, 1409 struct rte_flow_error *error) 1410 { 1411 rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4); 1412 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1413 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1414 struct rte_flow_item_ipv4 supp_mask; 1415 const uint8_t *spec = NULL; 1416 const uint8_t *mask = NULL; 1417 int rc; 1418 1419 sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4), 1420 &supp_mask, sizeof(supp_mask)); 1421 1422 rc = sfc_flow_parse_init(item, 1423 (const void **)&spec, (const void **)&mask, 1424 (const void *)&supp_mask, 1425 &rte_flow_item_ipv4_mask, 1426 sizeof(struct rte_flow_item_ipv4), error); 1427 if (rc != 0) 1428 return rc; 1429 1430 pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be; 1431 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff); 1432 1433 if (spec != NULL) { 1434 const struct rte_flow_item_ipv4 *item_spec; 1435 const struct rte_flow_item_ipv4 *item_mask; 1436 1437 item_spec = (const struct rte_flow_item_ipv4 *)spec; 1438 item_mask = (const struct rte_flow_item_ipv4 *)mask; 1439 1440 pdata->l3_next_proto_value = item_spec->hdr.next_proto_id; 1441 pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id; 1442 } else { 1443 return 0; 1444 } 1445 1446 return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask, 1447 ctx_mae, error); 1448 } 1449 1450 static const struct sfc_mae_field_locator flocs_ipv6[] = { 1451 { 1452 EFX_MAE_FIELD_SRC_IP6_BE, 1453 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr), 1454 offsetof(struct rte_flow_item_ipv6, hdr.src_addr), 1455 }, 1456 { 1457 EFX_MAE_FIELD_DST_IP6_BE, 1458 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr), 1459 offsetof(struct rte_flow_item_ipv6, hdr.dst_addr), 1460 }, 1461 { 1462 /* 1463 * This locator is used only for building supported fields mask. 1464 * The field is handled by sfc_mae_rule_process_pattern_data(). 1465 */ 1466 SFC_MAE_FIELD_HANDLING_DEFERRED, 1467 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto), 1468 offsetof(struct rte_flow_item_ipv6, hdr.proto), 1469 }, 1470 { 1471 EFX_MAE_FIELD_IP_TTL, 1472 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits), 1473 offsetof(struct rte_flow_item_ipv6, hdr.hop_limits), 1474 }, 1475 }; 1476 1477 static int 1478 sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item, 1479 struct sfc_flow_parse_ctx *ctx, 1480 struct rte_flow_error *error) 1481 { 1482 rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6); 1483 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1484 const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap; 1485 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1486 struct rte_flow_item_ipv6 supp_mask; 1487 const uint8_t *spec = NULL; 1488 const uint8_t *mask = NULL; 1489 rte_be32_t vtc_flow_be; 1490 uint32_t vtc_flow; 1491 uint8_t tc_value; 1492 uint8_t tc_mask; 1493 int rc; 1494 1495 sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6), 1496 &supp_mask, sizeof(supp_mask)); 1497 1498 vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK); 1499 memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be)); 1500 1501 rc = sfc_flow_parse_init(item, 1502 (const void **)&spec, (const void **)&mask, 1503 (const void *)&supp_mask, 1504 &rte_flow_item_ipv6_mask, 1505 sizeof(struct rte_flow_item_ipv6), error); 1506 if (rc != 0) 1507 return rc; 1508 1509 pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be; 1510 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff); 1511 1512 if (spec != NULL) { 1513 const struct rte_flow_item_ipv6 *item_spec; 1514 const struct rte_flow_item_ipv6 *item_mask; 1515 1516 item_spec = (const struct rte_flow_item_ipv6 *)spec; 1517 item_mask = (const struct rte_flow_item_ipv6 *)mask; 1518 1519 pdata->l3_next_proto_value = item_spec->hdr.proto; 1520 pdata->l3_next_proto_mask = item_mask->hdr.proto; 1521 } else { 1522 return 0; 1523 } 1524 1525 rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask, 1526 ctx_mae, error); 1527 if (rc != 0) 1528 return rc; 1529 1530 memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be)); 1531 vtc_flow = rte_be_to_cpu_32(vtc_flow_be); 1532 tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT; 1533 1534 memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be)); 1535 vtc_flow = rte_be_to_cpu_32(vtc_flow_be); 1536 tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT; 1537 1538 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec, 1539 fremap[EFX_MAE_FIELD_IP_TOS], 1540 sizeof(tc_value), &tc_value, 1541 sizeof(tc_mask), &tc_mask); 1542 if (rc != 0) { 1543 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1544 NULL, "Failed to process item fields"); 1545 } 1546 1547 return 0; 1548 } 1549 1550 static const struct sfc_mae_field_locator flocs_tcp[] = { 1551 { 1552 EFX_MAE_FIELD_L4_SPORT_BE, 1553 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port), 1554 offsetof(struct rte_flow_item_tcp, hdr.src_port), 1555 }, 1556 { 1557 EFX_MAE_FIELD_L4_DPORT_BE, 1558 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port), 1559 offsetof(struct rte_flow_item_tcp, hdr.dst_port), 1560 }, 1561 { 1562 EFX_MAE_FIELD_TCP_FLAGS_BE, 1563 /* 1564 * The values have been picked intentionally since the 1565 * target MAE field is oversize (16 bit). This mapping 1566 * relies on the fact that the MAE field is big-endian. 1567 */ 1568 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) + 1569 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags), 1570 offsetof(struct rte_flow_item_tcp, hdr.data_off), 1571 }, 1572 }; 1573 1574 static int 1575 sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item, 1576 struct sfc_flow_parse_ctx *ctx, 1577 struct rte_flow_error *error) 1578 { 1579 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1580 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1581 struct rte_flow_item_tcp supp_mask; 1582 const uint8_t *spec = NULL; 1583 const uint8_t *mask = NULL; 1584 int rc; 1585 1586 /* 1587 * When encountered among outermost items, item TCP is invalid. 1588 * Check which match specification is being constructed now. 1589 */ 1590 if (ctx_mae->match_spec != ctx_mae->match_spec_action) { 1591 return rte_flow_error_set(error, EINVAL, 1592 RTE_FLOW_ERROR_TYPE_ITEM, item, 1593 "TCP in outer frame is invalid"); 1594 } 1595 1596 sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp), 1597 &supp_mask, sizeof(supp_mask)); 1598 1599 rc = sfc_flow_parse_init(item, 1600 (const void **)&spec, (const void **)&mask, 1601 (const void *)&supp_mask, 1602 &rte_flow_item_tcp_mask, 1603 sizeof(struct rte_flow_item_tcp), error); 1604 if (rc != 0) 1605 return rc; 1606 1607 pdata->l3_next_proto_restriction_value = IPPROTO_TCP; 1608 pdata->l3_next_proto_restriction_mask = 0xff; 1609 1610 if (spec == NULL) 1611 return 0; 1612 1613 return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask, 1614 ctx_mae, error); 1615 } 1616 1617 static const struct sfc_mae_field_locator flocs_udp[] = { 1618 { 1619 EFX_MAE_FIELD_L4_SPORT_BE, 1620 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port), 1621 offsetof(struct rte_flow_item_udp, hdr.src_port), 1622 }, 1623 { 1624 EFX_MAE_FIELD_L4_DPORT_BE, 1625 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port), 1626 offsetof(struct rte_flow_item_udp, hdr.dst_port), 1627 }, 1628 }; 1629 1630 static int 1631 sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item, 1632 struct sfc_flow_parse_ctx *ctx, 1633 struct rte_flow_error *error) 1634 { 1635 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1636 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1637 struct rte_flow_item_udp supp_mask; 1638 const uint8_t *spec = NULL; 1639 const uint8_t *mask = NULL; 1640 int rc; 1641 1642 sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp), 1643 &supp_mask, sizeof(supp_mask)); 1644 1645 rc = sfc_flow_parse_init(item, 1646 (const void **)&spec, (const void **)&mask, 1647 (const void *)&supp_mask, 1648 &rte_flow_item_udp_mask, 1649 sizeof(struct rte_flow_item_udp), error); 1650 if (rc != 0) 1651 return rc; 1652 1653 pdata->l3_next_proto_restriction_value = IPPROTO_UDP; 1654 pdata->l3_next_proto_restriction_mask = 0xff; 1655 1656 if (spec == NULL) 1657 return 0; 1658 1659 return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask, 1660 ctx_mae, error); 1661 } 1662 1663 static const struct sfc_mae_field_locator flocs_tunnel[] = { 1664 { 1665 /* 1666 * The size and offset values are relevant 1667 * for Geneve and NVGRE, too. 1668 */ 1669 .size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, vni), 1670 .ofst = offsetof(struct rte_flow_item_vxlan, vni), 1671 }, 1672 }; 1673 1674 /* 1675 * An auxiliary registry which allows using non-encap. field IDs 1676 * directly when building a match specification of type ACTION. 1677 * 1678 * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel(). 1679 */ 1680 static const efx_mae_field_id_t field_ids_no_remap[] = { 1681 #define FIELD_ID_NO_REMAP(_field) \ 1682 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field 1683 1684 FIELD_ID_NO_REMAP(ETHER_TYPE_BE), 1685 FIELD_ID_NO_REMAP(ETH_SADDR_BE), 1686 FIELD_ID_NO_REMAP(ETH_DADDR_BE), 1687 FIELD_ID_NO_REMAP(VLAN0_TCI_BE), 1688 FIELD_ID_NO_REMAP(VLAN0_PROTO_BE), 1689 FIELD_ID_NO_REMAP(VLAN1_TCI_BE), 1690 FIELD_ID_NO_REMAP(VLAN1_PROTO_BE), 1691 FIELD_ID_NO_REMAP(SRC_IP4_BE), 1692 FIELD_ID_NO_REMAP(DST_IP4_BE), 1693 FIELD_ID_NO_REMAP(IP_PROTO), 1694 FIELD_ID_NO_REMAP(IP_TOS), 1695 FIELD_ID_NO_REMAP(IP_TTL), 1696 FIELD_ID_NO_REMAP(SRC_IP6_BE), 1697 FIELD_ID_NO_REMAP(DST_IP6_BE), 1698 FIELD_ID_NO_REMAP(L4_SPORT_BE), 1699 FIELD_ID_NO_REMAP(L4_DPORT_BE), 1700 FIELD_ID_NO_REMAP(TCP_FLAGS_BE), 1701 FIELD_ID_NO_REMAP(HAS_OVLAN), 1702 FIELD_ID_NO_REMAP(HAS_IVLAN), 1703 1704 #undef FIELD_ID_NO_REMAP 1705 }; 1706 1707 /* 1708 * An auxiliary registry which allows using "ENC" field IDs 1709 * when building a match specification of type OUTER. 1710 * 1711 * See sfc_mae_rule_encap_parse_init(). 1712 */ 1713 static const efx_mae_field_id_t field_ids_remap_to_encap[] = { 1714 #define FIELD_ID_REMAP_TO_ENCAP(_field) \ 1715 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field 1716 1717 FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE), 1718 FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE), 1719 FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE), 1720 FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE), 1721 FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE), 1722 FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE), 1723 FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE), 1724 FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE), 1725 FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE), 1726 FIELD_ID_REMAP_TO_ENCAP(IP_PROTO), 1727 FIELD_ID_REMAP_TO_ENCAP(IP_TOS), 1728 FIELD_ID_REMAP_TO_ENCAP(IP_TTL), 1729 FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE), 1730 FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE), 1731 FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE), 1732 FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE), 1733 FIELD_ID_REMAP_TO_ENCAP(HAS_OVLAN), 1734 FIELD_ID_REMAP_TO_ENCAP(HAS_IVLAN), 1735 1736 #undef FIELD_ID_REMAP_TO_ENCAP 1737 }; 1738 1739 static int 1740 sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item, 1741 struct sfc_flow_parse_ctx *ctx, 1742 struct rte_flow_error *error) 1743 { 1744 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1745 uint8_t vnet_id_v[sizeof(uint32_t)] = {0}; 1746 uint8_t vnet_id_m[sizeof(uint32_t)] = {0}; 1747 const struct rte_flow_item_vxlan *vxp; 1748 uint8_t supp_mask[sizeof(uint64_t)]; 1749 const uint8_t *spec = NULL; 1750 const uint8_t *mask = NULL; 1751 int rc; 1752 1753 /* 1754 * We're about to start processing inner frame items. 1755 * Process pattern data that has been deferred so far 1756 * and reset pattern data storage. 1757 */ 1758 rc = sfc_mae_rule_process_pattern_data(ctx_mae, error); 1759 if (rc != 0) 1760 return rc; 1761 1762 memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data)); 1763 1764 sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel), 1765 &supp_mask, sizeof(supp_mask)); 1766 1767 /* 1768 * This tunnel item was preliminarily detected by 1769 * sfc_mae_rule_encap_parse_init(). Default mask 1770 * was also picked by that helper. Use it here. 1771 */ 1772 rc = sfc_flow_parse_init(item, 1773 (const void **)&spec, (const void **)&mask, 1774 (const void *)&supp_mask, 1775 ctx_mae->tunnel_def_mask, 1776 ctx_mae->tunnel_def_mask_size, error); 1777 if (rc != 0) 1778 return rc; 1779 1780 /* 1781 * This item and later ones comprise a 1782 * match specification of type ACTION. 1783 */ 1784 ctx_mae->match_spec = ctx_mae->match_spec_action; 1785 1786 /* This item and later ones use non-encap. EFX MAE field IDs. */ 1787 ctx_mae->field_ids_remap = field_ids_no_remap; 1788 1789 if (spec == NULL) 1790 return 0; 1791 1792 /* 1793 * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one. 1794 * Copy 24-bit VNI, which is BE, at offset 1 in it. 1795 * The extra byte is 0 both in the mask and in the value. 1796 */ 1797 vxp = (const struct rte_flow_item_vxlan *)spec; 1798 memcpy(vnet_id_v + 1, &vxp->vni, sizeof(vxp->vni)); 1799 1800 vxp = (const struct rte_flow_item_vxlan *)mask; 1801 memcpy(vnet_id_m + 1, &vxp->vni, sizeof(vxp->vni)); 1802 1803 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec, 1804 EFX_MAE_FIELD_ENC_VNET_ID_BE, 1805 sizeof(vnet_id_v), vnet_id_v, 1806 sizeof(vnet_id_m), vnet_id_m); 1807 if (rc != 0) { 1808 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1809 item, "Failed to set VXLAN VNI"); 1810 } 1811 1812 return rc; 1813 } 1814 1815 static const struct sfc_flow_item sfc_flow_items[] = { 1816 { 1817 .type = RTE_FLOW_ITEM_TYPE_PORT_ID, 1818 /* 1819 * In terms of RTE flow, this item is a META one, 1820 * and its position in the pattern is don't care. 1821 */ 1822 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1823 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1824 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1825 .parse = sfc_mae_rule_parse_item_port_id, 1826 }, 1827 { 1828 .type = RTE_FLOW_ITEM_TYPE_PHY_PORT, 1829 /* 1830 * In terms of RTE flow, this item is a META one, 1831 * and its position in the pattern is don't care. 1832 */ 1833 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1834 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1835 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1836 .parse = sfc_mae_rule_parse_item_phy_port, 1837 }, 1838 { 1839 .type = RTE_FLOW_ITEM_TYPE_PF, 1840 /* 1841 * In terms of RTE flow, this item is a META one, 1842 * and its position in the pattern is don't care. 1843 */ 1844 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1845 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1846 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1847 .parse = sfc_mae_rule_parse_item_pf, 1848 }, 1849 { 1850 .type = RTE_FLOW_ITEM_TYPE_VF, 1851 /* 1852 * In terms of RTE flow, this item is a META one, 1853 * and its position in the pattern is don't care. 1854 */ 1855 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1856 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1857 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1858 .parse = sfc_mae_rule_parse_item_vf, 1859 }, 1860 { 1861 .type = RTE_FLOW_ITEM_TYPE_ETH, 1862 .prev_layer = SFC_FLOW_ITEM_START_LAYER, 1863 .layer = SFC_FLOW_ITEM_L2, 1864 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1865 .parse = sfc_mae_rule_parse_item_eth, 1866 }, 1867 { 1868 .type = RTE_FLOW_ITEM_TYPE_VLAN, 1869 .prev_layer = SFC_FLOW_ITEM_L2, 1870 .layer = SFC_FLOW_ITEM_L2, 1871 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1872 .parse = sfc_mae_rule_parse_item_vlan, 1873 }, 1874 { 1875 .type = RTE_FLOW_ITEM_TYPE_IPV4, 1876 .prev_layer = SFC_FLOW_ITEM_L2, 1877 .layer = SFC_FLOW_ITEM_L3, 1878 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1879 .parse = sfc_mae_rule_parse_item_ipv4, 1880 }, 1881 { 1882 .type = RTE_FLOW_ITEM_TYPE_IPV6, 1883 .prev_layer = SFC_FLOW_ITEM_L2, 1884 .layer = SFC_FLOW_ITEM_L3, 1885 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1886 .parse = sfc_mae_rule_parse_item_ipv6, 1887 }, 1888 { 1889 .type = RTE_FLOW_ITEM_TYPE_TCP, 1890 .prev_layer = SFC_FLOW_ITEM_L3, 1891 .layer = SFC_FLOW_ITEM_L4, 1892 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1893 .parse = sfc_mae_rule_parse_item_tcp, 1894 }, 1895 { 1896 .type = RTE_FLOW_ITEM_TYPE_UDP, 1897 .prev_layer = SFC_FLOW_ITEM_L3, 1898 .layer = SFC_FLOW_ITEM_L4, 1899 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1900 .parse = sfc_mae_rule_parse_item_udp, 1901 }, 1902 { 1903 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 1904 .prev_layer = SFC_FLOW_ITEM_L4, 1905 .layer = SFC_FLOW_ITEM_START_LAYER, 1906 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1907 .parse = sfc_mae_rule_parse_item_tunnel, 1908 }, 1909 { 1910 .type = RTE_FLOW_ITEM_TYPE_GENEVE, 1911 .prev_layer = SFC_FLOW_ITEM_L4, 1912 .layer = SFC_FLOW_ITEM_START_LAYER, 1913 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1914 .parse = sfc_mae_rule_parse_item_tunnel, 1915 }, 1916 { 1917 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 1918 .prev_layer = SFC_FLOW_ITEM_L3, 1919 .layer = SFC_FLOW_ITEM_START_LAYER, 1920 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1921 .parse = sfc_mae_rule_parse_item_tunnel, 1922 }, 1923 }; 1924 1925 static int 1926 sfc_mae_rule_process_outer(struct sfc_adapter *sa, 1927 struct sfc_mae_parse_ctx *ctx, 1928 struct sfc_mae_outer_rule **rulep, 1929 struct rte_flow_error *error) 1930 { 1931 efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID }; 1932 int rc; 1933 1934 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) { 1935 *rulep = NULL; 1936 goto no_or_id; 1937 } 1938 1939 SFC_ASSERT(ctx->match_spec_outer != NULL); 1940 1941 if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) { 1942 return rte_flow_error_set(error, ENOTSUP, 1943 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1944 "Inconsistent pattern (outer)"); 1945 } 1946 1947 *rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer, 1948 ctx->encap_type); 1949 if (*rulep != NULL) { 1950 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer); 1951 } else { 1952 rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer, 1953 ctx->encap_type, rulep); 1954 if (rc != 0) { 1955 return rte_flow_error_set(error, rc, 1956 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1957 "Failed to process the pattern"); 1958 } 1959 } 1960 1961 /* The spec has now been tracked by the outer rule entry. */ 1962 ctx->match_spec_outer = NULL; 1963 1964 no_or_id: 1965 /* 1966 * In MAE, lookup sequence comprises outer parse, outer rule lookup, 1967 * inner parse (when some outer rule is hit) and action rule lookup. 1968 * If the currently processed flow does not come with an outer rule, 1969 * its action rule must be available only for packets which miss in 1970 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff 1971 * in the action rule specification; this ensures correct behaviour. 1972 * 1973 * If, on the other hand, this flow does have an outer rule, its ID 1974 * may be unknown at the moment (not yet allocated), but OR_ID mask 1975 * has to be set to 0xffffffff anyway for correct class comparisons. 1976 * When the outer rule has been allocated, this match field will be 1977 * overridden by sfc_mae_outer_rule_enable() to use the right value. 1978 */ 1979 rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action, 1980 &invalid_rule_id); 1981 if (rc != 0) { 1982 if (*rulep != NULL) 1983 sfc_mae_outer_rule_del(sa, *rulep); 1984 1985 *rulep = NULL; 1986 1987 return rte_flow_error_set(error, rc, 1988 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1989 "Failed to process the pattern"); 1990 } 1991 1992 return 0; 1993 } 1994 1995 static int 1996 sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa, 1997 const struct rte_flow_item pattern[], 1998 struct sfc_mae_parse_ctx *ctx, 1999 struct rte_flow_error *error) 2000 { 2001 struct sfc_mae *mae = &sa->mae; 2002 int rc; 2003 2004 if (pattern == NULL) { 2005 rte_flow_error_set(error, EINVAL, 2006 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL, 2007 "NULL pattern"); 2008 return -rte_errno; 2009 } 2010 2011 for (;;) { 2012 switch (pattern->type) { 2013 case RTE_FLOW_ITEM_TYPE_VXLAN: 2014 ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; 2015 ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask; 2016 ctx->tunnel_def_mask_size = 2017 sizeof(rte_flow_item_vxlan_mask); 2018 break; 2019 case RTE_FLOW_ITEM_TYPE_GENEVE: 2020 ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE; 2021 ctx->tunnel_def_mask = &rte_flow_item_geneve_mask; 2022 ctx->tunnel_def_mask_size = 2023 sizeof(rte_flow_item_geneve_mask); 2024 break; 2025 case RTE_FLOW_ITEM_TYPE_NVGRE: 2026 ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE; 2027 ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask; 2028 ctx->tunnel_def_mask_size = 2029 sizeof(rte_flow_item_nvgre_mask); 2030 break; 2031 case RTE_FLOW_ITEM_TYPE_END: 2032 break; 2033 default: 2034 ++pattern; 2035 continue; 2036 }; 2037 2038 break; 2039 } 2040 2041 if (pattern->type == RTE_FLOW_ITEM_TYPE_END) 2042 return 0; 2043 2044 if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) { 2045 return rte_flow_error_set(error, ENOTSUP, 2046 RTE_FLOW_ERROR_TYPE_ITEM, 2047 pattern, "Unsupported tunnel item"); 2048 } 2049 2050 if (ctx->priority >= mae->nb_outer_rule_prios_max) { 2051 return rte_flow_error_set(error, ENOTSUP, 2052 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 2053 NULL, "Unsupported priority level"); 2054 } 2055 2056 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_OUTER, ctx->priority, 2057 &ctx->match_spec_outer); 2058 if (rc != 0) { 2059 return rte_flow_error_set(error, rc, 2060 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 2061 "Failed to initialise outer rule match specification"); 2062 } 2063 2064 /* Outermost items comprise a match specification of type OUTER. */ 2065 ctx->match_spec = ctx->match_spec_outer; 2066 2067 /* Outermost items use "ENC" EFX MAE field IDs. */ 2068 ctx->field_ids_remap = field_ids_remap_to_encap; 2069 2070 return 0; 2071 } 2072 2073 static void 2074 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa, 2075 struct sfc_mae_parse_ctx *ctx) 2076 { 2077 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) 2078 return; 2079 2080 if (ctx->match_spec_outer != NULL) 2081 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer); 2082 } 2083 2084 int 2085 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa, 2086 const struct rte_flow_item pattern[], 2087 struct sfc_flow_spec_mae *spec, 2088 struct rte_flow_error *error) 2089 { 2090 struct sfc_mae_parse_ctx ctx_mae; 2091 struct sfc_flow_parse_ctx ctx; 2092 int rc; 2093 2094 memset(&ctx_mae, 0, sizeof(ctx_mae)); 2095 ctx_mae.priority = spec->priority; 2096 ctx_mae.sa = sa; 2097 2098 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION, 2099 spec->priority, 2100 &ctx_mae.match_spec_action); 2101 if (rc != 0) { 2102 rc = rte_flow_error_set(error, rc, 2103 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2104 "Failed to initialise action rule match specification"); 2105 goto fail_init_match_spec_action; 2106 } 2107 2108 /* 2109 * As a preliminary setting, assume that there is no encapsulation 2110 * in the pattern. That is, pattern items are about to comprise a 2111 * match specification of type ACTION and use non-encap. field IDs. 2112 * 2113 * sfc_mae_rule_encap_parse_init() below may override this. 2114 */ 2115 ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE; 2116 ctx_mae.match_spec = ctx_mae.match_spec_action; 2117 ctx_mae.field_ids_remap = field_ids_no_remap; 2118 2119 ctx.type = SFC_FLOW_PARSE_CTX_MAE; 2120 ctx.mae = &ctx_mae; 2121 2122 rc = sfc_mae_rule_encap_parse_init(sa, pattern, &ctx_mae, error); 2123 if (rc != 0) 2124 goto fail_encap_parse_init; 2125 2126 rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items), 2127 pattern, &ctx, error); 2128 if (rc != 0) 2129 goto fail_parse_pattern; 2130 2131 rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error); 2132 if (rc != 0) 2133 goto fail_process_pattern_data; 2134 2135 rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error); 2136 if (rc != 0) 2137 goto fail_process_outer; 2138 2139 if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) { 2140 rc = rte_flow_error_set(error, ENOTSUP, 2141 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 2142 "Inconsistent pattern"); 2143 goto fail_validate_match_spec_action; 2144 } 2145 2146 spec->match_spec = ctx_mae.match_spec_action; 2147 2148 return 0; 2149 2150 fail_validate_match_spec_action: 2151 fail_process_outer: 2152 fail_process_pattern_data: 2153 fail_parse_pattern: 2154 sfc_mae_rule_encap_parse_fini(sa, &ctx_mae); 2155 2156 fail_encap_parse_init: 2157 efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action); 2158 2159 fail_init_match_spec_action: 2160 return rc; 2161 } 2162 2163 /* 2164 * An action supported by MAE may correspond to a bundle of RTE flow actions, 2165 * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP. 2166 * That is, related RTE flow actions need to be tracked as parts of a whole 2167 * so that they can be combined into a single action and submitted to MAE 2168 * representation of a given rule's action set. 2169 * 2170 * Each RTE flow action provided by an application gets classified as 2171 * one belonging to some bundle type. If an action is not supposed to 2172 * belong to any bundle, or if this action is END, it is described as 2173 * one belonging to a dummy bundle of type EMPTY. 2174 * 2175 * A currently tracked bundle will be submitted if a repeating 2176 * action or an action of different bundle type follows. 2177 */ 2178 2179 enum sfc_mae_actions_bundle_type { 2180 SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0, 2181 SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH, 2182 }; 2183 2184 struct sfc_mae_actions_bundle { 2185 enum sfc_mae_actions_bundle_type type; 2186 2187 /* Indicates actions already tracked by the current bundle */ 2188 uint64_t actions_mask; 2189 2190 /* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */ 2191 rte_be16_t vlan_push_tpid; 2192 rte_be16_t vlan_push_tci; 2193 }; 2194 2195 /* 2196 * Combine configuration of RTE flow actions tracked by the bundle into a 2197 * single action and submit the result to MAE action set specification. 2198 * Do nothing in the case of dummy action bundle. 2199 */ 2200 static int 2201 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle, 2202 efx_mae_actions_t *spec) 2203 { 2204 int rc = 0; 2205 2206 switch (bundle->type) { 2207 case SFC_MAE_ACTIONS_BUNDLE_EMPTY: 2208 break; 2209 case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH: 2210 rc = efx_mae_action_set_populate_vlan_push( 2211 spec, bundle->vlan_push_tpid, bundle->vlan_push_tci); 2212 break; 2213 default: 2214 SFC_ASSERT(B_FALSE); 2215 break; 2216 } 2217 2218 return rc; 2219 } 2220 2221 /* 2222 * Given the type of the next RTE flow action in the line, decide 2223 * whether a new bundle is about to start, and, if this is the case, 2224 * submit and reset the current bundle. 2225 */ 2226 static int 2227 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action, 2228 struct sfc_mae_actions_bundle *bundle, 2229 efx_mae_actions_t *spec, 2230 struct rte_flow_error *error) 2231 { 2232 enum sfc_mae_actions_bundle_type bundle_type_new; 2233 int rc; 2234 2235 switch (action->type) { 2236 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 2237 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 2238 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 2239 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH; 2240 break; 2241 default: 2242 /* 2243 * Self-sufficient actions, including END, are handled in this 2244 * case. No checks for unsupported actions are needed here 2245 * because parsing doesn't occur at this point. 2246 */ 2247 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY; 2248 break; 2249 } 2250 2251 if (bundle_type_new != bundle->type || 2252 (bundle->actions_mask & (1ULL << action->type)) != 0) { 2253 rc = sfc_mae_actions_bundle_submit(bundle, spec); 2254 if (rc != 0) 2255 goto fail_submit; 2256 2257 memset(bundle, 0, sizeof(*bundle)); 2258 } 2259 2260 bundle->type = bundle_type_new; 2261 2262 return 0; 2263 2264 fail_submit: 2265 return rte_flow_error_set(error, rc, 2266 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2267 "Failed to request the (group of) action(s)"); 2268 } 2269 2270 static void 2271 sfc_mae_rule_parse_action_of_push_vlan( 2272 const struct rte_flow_action_of_push_vlan *conf, 2273 struct sfc_mae_actions_bundle *bundle) 2274 { 2275 bundle->vlan_push_tpid = conf->ethertype; 2276 } 2277 2278 static void 2279 sfc_mae_rule_parse_action_of_set_vlan_vid( 2280 const struct rte_flow_action_of_set_vlan_vid *conf, 2281 struct sfc_mae_actions_bundle *bundle) 2282 { 2283 bundle->vlan_push_tci |= (conf->vlan_vid & 2284 rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t))); 2285 } 2286 2287 static void 2288 sfc_mae_rule_parse_action_of_set_vlan_pcp( 2289 const struct rte_flow_action_of_set_vlan_pcp *conf, 2290 struct sfc_mae_actions_bundle *bundle) 2291 { 2292 uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp & 2293 RTE_LEN2MASK(3, uint8_t)) << 13; 2294 2295 bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp); 2296 } 2297 2298 struct sfc_mae_parsed_item { 2299 const struct rte_flow_item *item; 2300 size_t proto_header_ofst; 2301 size_t proto_header_size; 2302 }; 2303 2304 /* 2305 * For each 16-bit word of the given header, override 2306 * bits enforced by the corresponding 16-bit mask. 2307 */ 2308 static void 2309 sfc_mae_header_force_item_masks(uint8_t *header_buf, 2310 const struct sfc_mae_parsed_item *parsed_items, 2311 unsigned int nb_parsed_items) 2312 { 2313 unsigned int item_idx; 2314 2315 for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) { 2316 const struct sfc_mae_parsed_item *parsed_item; 2317 const struct rte_flow_item *item; 2318 size_t proto_header_size; 2319 size_t ofst; 2320 2321 parsed_item = &parsed_items[item_idx]; 2322 proto_header_size = parsed_item->proto_header_size; 2323 item = parsed_item->item; 2324 2325 for (ofst = 0; ofst < proto_header_size; 2326 ofst += sizeof(rte_be16_t)) { 2327 rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst); 2328 const rte_be16_t *w_maskp; 2329 const rte_be16_t *w_specp; 2330 2331 w_maskp = RTE_PTR_ADD(item->mask, ofst); 2332 w_specp = RTE_PTR_ADD(item->spec, ofst); 2333 2334 *wp &= ~(*w_maskp); 2335 *wp |= (*w_specp & *w_maskp); 2336 } 2337 2338 header_buf += proto_header_size; 2339 } 2340 } 2341 2342 #define SFC_IPV4_TTL_DEF 0x40 2343 #define SFC_IPV6_VTC_FLOW_DEF 0x60000000 2344 #define SFC_IPV6_HOP_LIMITS_DEF 0xff 2345 #define SFC_VXLAN_FLAGS_DEF 0x08000000 2346 2347 static int 2348 sfc_mae_rule_parse_action_vxlan_encap( 2349 struct sfc_mae *mae, 2350 const struct rte_flow_action_vxlan_encap *conf, 2351 efx_mae_actions_t *spec, 2352 struct rte_flow_error *error) 2353 { 2354 struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh; 2355 struct rte_flow_item *pattern = conf->definition; 2356 uint8_t *buf = bounce_eh->buf; 2357 2358 /* This array will keep track of non-VOID pattern items. */ 2359 struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ + 2360 2 /* VLAN tags */ + 2361 1 /* IPv4 or IPv6 */ + 2362 1 /* UDP */ + 2363 1 /* VXLAN */]; 2364 unsigned int nb_parsed_items = 0; 2365 2366 size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type); 2367 uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr), 2368 sizeof(struct rte_ipv6_hdr))]; 2369 struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf; 2370 struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf; 2371 struct rte_vxlan_hdr *vxlan = NULL; 2372 struct rte_udp_hdr *udp = NULL; 2373 unsigned int nb_vlan_tags = 0; 2374 size_t next_proto_ofst = 0; 2375 size_t ethertype_ofst = 0; 2376 uint64_t exp_items; 2377 2378 if (pattern == NULL) { 2379 return rte_flow_error_set(error, EINVAL, 2380 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2381 "The encap. header definition is NULL"); 2382 } 2383 2384 bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN; 2385 bounce_eh->size = 0; 2386 2387 /* 2388 * Process pattern items and remember non-VOID ones. 2389 * Defer applying masks until after the complete header 2390 * has been built from the pattern items. 2391 */ 2392 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH); 2393 2394 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) { 2395 struct sfc_mae_parsed_item *parsed_item; 2396 const uint64_t exp_items_extra_vlan[] = { 2397 RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0 2398 }; 2399 size_t proto_header_size; 2400 rte_be16_t *ethertypep; 2401 uint8_t *next_protop; 2402 uint8_t *buf_cur; 2403 2404 if (pattern->spec == NULL) { 2405 return rte_flow_error_set(error, EINVAL, 2406 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2407 "NULL item spec in the encap. header"); 2408 } 2409 2410 if (pattern->mask == NULL) { 2411 return rte_flow_error_set(error, EINVAL, 2412 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2413 "NULL item mask in the encap. header"); 2414 } 2415 2416 if (pattern->last != NULL) { 2417 /* This is not a match pattern, so disallow range. */ 2418 return rte_flow_error_set(error, EINVAL, 2419 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2420 "Range item in the encap. header"); 2421 } 2422 2423 if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) { 2424 /* Handle VOID separately, for clarity. */ 2425 continue; 2426 } 2427 2428 if ((exp_items & RTE_BIT64(pattern->type)) == 0) { 2429 return rte_flow_error_set(error, ENOTSUP, 2430 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2431 "Unexpected item in the encap. header"); 2432 } 2433 2434 parsed_item = &parsed_items[nb_parsed_items]; 2435 buf_cur = buf + bounce_eh->size; 2436 2437 switch (pattern->type) { 2438 case RTE_FLOW_ITEM_TYPE_ETH: 2439 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH, 2440 exp_items); 2441 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth, 2442 hdr) != 0); 2443 2444 proto_header_size = sizeof(struct rte_ether_hdr); 2445 2446 ethertype_ofst = eth_ethertype_ofst; 2447 2448 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) | 2449 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) | 2450 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6); 2451 break; 2452 case RTE_FLOW_ITEM_TYPE_VLAN: 2453 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN, 2454 exp_items); 2455 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan, 2456 hdr) != 0); 2457 2458 proto_header_size = sizeof(struct rte_vlan_hdr); 2459 2460 ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst); 2461 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ); 2462 2463 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2464 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN); 2465 2466 ethertype_ofst = 2467 bounce_eh->size + 2468 offsetof(struct rte_vlan_hdr, eth_proto); 2469 2470 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) | 2471 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6); 2472 exp_items |= exp_items_extra_vlan[nb_vlan_tags]; 2473 2474 ++nb_vlan_tags; 2475 break; 2476 case RTE_FLOW_ITEM_TYPE_IPV4: 2477 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4, 2478 exp_items); 2479 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4, 2480 hdr) != 0); 2481 2482 proto_header_size = sizeof(struct rte_ipv4_hdr); 2483 2484 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2485 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4); 2486 2487 next_proto_ofst = 2488 bounce_eh->size + 2489 offsetof(struct rte_ipv4_hdr, next_proto_id); 2490 2491 ipv4 = (struct rte_ipv4_hdr *)buf_cur; 2492 2493 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP); 2494 break; 2495 case RTE_FLOW_ITEM_TYPE_IPV6: 2496 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6, 2497 exp_items); 2498 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6, 2499 hdr) != 0); 2500 2501 proto_header_size = sizeof(struct rte_ipv6_hdr); 2502 2503 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2504 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6); 2505 2506 next_proto_ofst = bounce_eh->size + 2507 offsetof(struct rte_ipv6_hdr, proto); 2508 2509 ipv6 = (struct rte_ipv6_hdr *)buf_cur; 2510 2511 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP); 2512 break; 2513 case RTE_FLOW_ITEM_TYPE_UDP: 2514 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP, 2515 exp_items); 2516 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp, 2517 hdr) != 0); 2518 2519 proto_header_size = sizeof(struct rte_udp_hdr); 2520 2521 next_protop = RTE_PTR_ADD(buf, next_proto_ofst); 2522 *next_protop = IPPROTO_UDP; 2523 2524 udp = (struct rte_udp_hdr *)buf_cur; 2525 2526 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN); 2527 break; 2528 case RTE_FLOW_ITEM_TYPE_VXLAN: 2529 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN, 2530 exp_items); 2531 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan, 2532 hdr) != 0); 2533 2534 proto_header_size = sizeof(struct rte_vxlan_hdr); 2535 2536 vxlan = (struct rte_vxlan_hdr *)buf_cur; 2537 2538 udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT); 2539 udp->dgram_len = RTE_BE16(sizeof(*udp) + 2540 sizeof(*vxlan)); 2541 udp->dgram_cksum = 0; 2542 2543 exp_items = 0; 2544 break; 2545 default: 2546 return rte_flow_error_set(error, ENOTSUP, 2547 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2548 "Unknown item in the encap. header"); 2549 } 2550 2551 if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) { 2552 return rte_flow_error_set(error, E2BIG, 2553 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2554 "The encap. header is too big"); 2555 } 2556 2557 if ((proto_header_size & 1) != 0) { 2558 return rte_flow_error_set(error, EINVAL, 2559 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2560 "Odd layer size in the encap. header"); 2561 } 2562 2563 rte_memcpy(buf_cur, pattern->spec, proto_header_size); 2564 bounce_eh->size += proto_header_size; 2565 2566 parsed_item->item = pattern; 2567 parsed_item->proto_header_size = proto_header_size; 2568 ++nb_parsed_items; 2569 } 2570 2571 if (exp_items != 0) { 2572 /* Parsing item VXLAN would have reset exp_items to 0. */ 2573 return rte_flow_error_set(error, ENOTSUP, 2574 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2575 "No item VXLAN in the encap. header"); 2576 } 2577 2578 /* One of the pointers (ipv4, ipv6) refers to a dummy area. */ 2579 ipv4->version_ihl = RTE_IPV4_VHL_DEF; 2580 ipv4->time_to_live = SFC_IPV4_TTL_DEF; 2581 ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) + 2582 sizeof(*vxlan)); 2583 /* The HW cannot compute this checksum. */ 2584 ipv4->hdr_checksum = 0; 2585 ipv4->hdr_checksum = rte_ipv4_cksum(ipv4); 2586 2587 ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF); 2588 ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF; 2589 ipv6->payload_len = udp->dgram_len; 2590 2591 vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF); 2592 2593 /* Take care of the masks. */ 2594 sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items); 2595 2596 return (spec != NULL) ? efx_mae_action_set_populate_encap(spec) : 0; 2597 } 2598 2599 static int 2600 sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf, 2601 efx_mae_actions_t *spec) 2602 { 2603 return efx_mae_action_set_populate_mark(spec, conf->id); 2604 } 2605 2606 static int 2607 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa, 2608 const struct rte_flow_action_phy_port *conf, 2609 efx_mae_actions_t *spec) 2610 { 2611 efx_mport_sel_t mport; 2612 uint32_t phy_port; 2613 int rc; 2614 2615 if (conf->original != 0) 2616 phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port; 2617 else 2618 phy_port = conf->index; 2619 2620 rc = efx_mae_mport_by_phy_port(phy_port, &mport); 2621 if (rc != 0) 2622 return rc; 2623 2624 return efx_mae_action_set_populate_deliver(spec, &mport); 2625 } 2626 2627 static int 2628 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa, 2629 const struct rte_flow_action_vf *vf_conf, 2630 efx_mae_actions_t *spec) 2631 { 2632 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 2633 efx_mport_sel_t mport; 2634 uint32_t vf; 2635 int rc; 2636 2637 if (vf_conf == NULL) 2638 vf = EFX_PCI_VF_INVALID; 2639 else if (vf_conf->original != 0) 2640 vf = encp->enc_vf; 2641 else 2642 vf = vf_conf->id; 2643 2644 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport); 2645 if (rc != 0) 2646 return rc; 2647 2648 return efx_mae_action_set_populate_deliver(spec, &mport); 2649 } 2650 2651 static int 2652 sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa, 2653 const struct rte_flow_action_port_id *conf, 2654 efx_mae_actions_t *spec) 2655 { 2656 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); 2657 struct sfc_mae *mae = &sa->mae; 2658 efx_mport_sel_t mport; 2659 uint16_t port_id; 2660 int rc; 2661 2662 if (conf->id > UINT16_MAX) 2663 return EOVERFLOW; 2664 2665 port_id = (conf->original != 0) ? sas->port_id : conf->id; 2666 2667 rc = sfc_mae_switch_port_by_ethdev(mae->switch_domain_id, 2668 port_id, &mport); 2669 if (rc != 0) 2670 return rc; 2671 2672 return efx_mae_action_set_populate_deliver(spec, &mport); 2673 } 2674 2675 static int 2676 sfc_mae_rule_parse_action(struct sfc_adapter *sa, 2677 const struct rte_flow_action *action, 2678 const struct sfc_mae_outer_rule *outer_rule, 2679 struct sfc_mae_actions_bundle *bundle, 2680 efx_mae_actions_t *spec, 2681 struct rte_flow_error *error) 2682 { 2683 bool custom_error = B_FALSE; 2684 int rc = 0; 2685 2686 switch (action->type) { 2687 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 2688 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, 2689 bundle->actions_mask); 2690 if (outer_rule == NULL || 2691 outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN) 2692 rc = EINVAL; 2693 else 2694 rc = efx_mae_action_set_populate_decap(spec); 2695 break; 2696 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 2697 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, 2698 bundle->actions_mask); 2699 rc = efx_mae_action_set_populate_vlan_pop(spec); 2700 break; 2701 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 2702 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, 2703 bundle->actions_mask); 2704 sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle); 2705 break; 2706 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 2707 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID, 2708 bundle->actions_mask); 2709 sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle); 2710 break; 2711 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 2712 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP, 2713 bundle->actions_mask); 2714 sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle); 2715 break; 2716 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 2717 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, 2718 bundle->actions_mask); 2719 rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae, 2720 action->conf, 2721 spec, error); 2722 custom_error = B_TRUE; 2723 break; 2724 case RTE_FLOW_ACTION_TYPE_FLAG: 2725 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG, 2726 bundle->actions_mask); 2727 rc = efx_mae_action_set_populate_flag(spec); 2728 break; 2729 case RTE_FLOW_ACTION_TYPE_MARK: 2730 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK, 2731 bundle->actions_mask); 2732 rc = sfc_mae_rule_parse_action_mark(action->conf, spec); 2733 break; 2734 case RTE_FLOW_ACTION_TYPE_PHY_PORT: 2735 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT, 2736 bundle->actions_mask); 2737 rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec); 2738 break; 2739 case RTE_FLOW_ACTION_TYPE_PF: 2740 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF, 2741 bundle->actions_mask); 2742 rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec); 2743 break; 2744 case RTE_FLOW_ACTION_TYPE_VF: 2745 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF, 2746 bundle->actions_mask); 2747 rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec); 2748 break; 2749 case RTE_FLOW_ACTION_TYPE_PORT_ID: 2750 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID, 2751 bundle->actions_mask); 2752 rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec); 2753 break; 2754 case RTE_FLOW_ACTION_TYPE_DROP: 2755 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP, 2756 bundle->actions_mask); 2757 rc = efx_mae_action_set_populate_drop(spec); 2758 break; 2759 default: 2760 return rte_flow_error_set(error, ENOTSUP, 2761 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2762 "Unsupported action"); 2763 } 2764 2765 if (rc == 0) { 2766 bundle->actions_mask |= (1ULL << action->type); 2767 } else if (!custom_error) { 2768 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, 2769 NULL, "Failed to request the action"); 2770 } 2771 2772 return rc; 2773 } 2774 2775 static void 2776 sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh) 2777 { 2778 bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE; 2779 } 2780 2781 static int 2782 sfc_mae_process_encap_header(struct sfc_adapter *sa, 2783 const struct sfc_mae_bounce_eh *bounce_eh, 2784 struct sfc_mae_encap_header **encap_headerp) 2785 { 2786 if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) { 2787 encap_headerp = NULL; 2788 return 0; 2789 } 2790 2791 *encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh); 2792 if (*encap_headerp != NULL) 2793 return 0; 2794 2795 return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp); 2796 } 2797 2798 int 2799 sfc_mae_rule_parse_actions(struct sfc_adapter *sa, 2800 const struct rte_flow_action actions[], 2801 struct sfc_flow_spec_mae *spec_mae, 2802 struct rte_flow_error *error) 2803 { 2804 struct sfc_mae_encap_header *encap_header = NULL; 2805 struct sfc_mae_actions_bundle bundle = {0}; 2806 const struct rte_flow_action *action; 2807 struct sfc_mae *mae = &sa->mae; 2808 efx_mae_actions_t *spec; 2809 int rc; 2810 2811 rte_errno = 0; 2812 2813 if (actions == NULL) { 2814 return rte_flow_error_set(error, EINVAL, 2815 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL, 2816 "NULL actions"); 2817 } 2818 2819 rc = efx_mae_action_set_spec_init(sa->nic, &spec); 2820 if (rc != 0) 2821 goto fail_action_set_spec_init; 2822 2823 /* Cleanup after previous encap. header bounce buffer usage. */ 2824 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh); 2825 2826 for (action = actions; 2827 action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { 2828 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); 2829 if (rc != 0) 2830 goto fail_rule_parse_action; 2831 2832 rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule, 2833 &bundle, spec, error); 2834 if (rc != 0) 2835 goto fail_rule_parse_action; 2836 } 2837 2838 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); 2839 if (rc != 0) 2840 goto fail_rule_parse_action; 2841 2842 rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header); 2843 if (rc != 0) 2844 goto fail_process_encap_header; 2845 2846 spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header, 2847 spec); 2848 if (spec_mae->action_set != NULL) { 2849 sfc_mae_encap_header_del(sa, encap_header); 2850 efx_mae_action_set_spec_fini(sa->nic, spec); 2851 return 0; 2852 } 2853 2854 rc = sfc_mae_action_set_add(sa, spec, encap_header, 2855 &spec_mae->action_set); 2856 if (rc != 0) 2857 goto fail_action_set_add; 2858 2859 return 0; 2860 2861 fail_action_set_add: 2862 sfc_mae_encap_header_del(sa, encap_header); 2863 2864 fail_process_encap_header: 2865 fail_rule_parse_action: 2866 efx_mae_action_set_spec_fini(sa->nic, spec); 2867 2868 fail_action_set_spec_init: 2869 if (rc > 0 && rte_errno == 0) { 2870 rc = rte_flow_error_set(error, rc, 2871 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2872 NULL, "Failed to process the action"); 2873 } 2874 return rc; 2875 } 2876 2877 static bool 2878 sfc_mae_rules_class_cmp(struct sfc_adapter *sa, 2879 const efx_mae_match_spec_t *left, 2880 const efx_mae_match_spec_t *right) 2881 { 2882 bool have_same_class; 2883 int rc; 2884 2885 rc = efx_mae_match_specs_class_cmp(sa->nic, left, right, 2886 &have_same_class); 2887 2888 return (rc == 0) ? have_same_class : false; 2889 } 2890 2891 static int 2892 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa, 2893 struct sfc_mae_outer_rule *rule) 2894 { 2895 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc; 2896 struct sfc_mae_outer_rule *entry; 2897 struct sfc_mae *mae = &sa->mae; 2898 2899 if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) { 2900 /* An active rule is reused. It's class is wittingly valid. */ 2901 return 0; 2902 } 2903 2904 TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules, 2905 sfc_mae_outer_rules, entries) { 2906 const efx_mae_match_spec_t *left = entry->match_spec; 2907 const efx_mae_match_spec_t *right = rule->match_spec; 2908 2909 if (entry == rule) 2910 continue; 2911 2912 if (sfc_mae_rules_class_cmp(sa, left, right)) 2913 return 0; 2914 } 2915 2916 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW " 2917 "support for outer frame pattern items is not guaranteed; " 2918 "other than that, the items are valid from SW standpoint"); 2919 return 0; 2920 } 2921 2922 static int 2923 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa, 2924 struct sfc_flow_spec_mae *spec) 2925 { 2926 const struct rte_flow *entry; 2927 2928 TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) { 2929 const struct sfc_flow_spec *entry_spec = &entry->spec; 2930 const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae; 2931 const efx_mae_match_spec_t *left = es_mae->match_spec; 2932 const efx_mae_match_spec_t *right = spec->match_spec; 2933 2934 switch (entry_spec->type) { 2935 case SFC_FLOW_SPEC_FILTER: 2936 /* Ignore VNIC-level flows */ 2937 break; 2938 case SFC_FLOW_SPEC_MAE: 2939 if (sfc_mae_rules_class_cmp(sa, left, right)) 2940 return 0; 2941 break; 2942 default: 2943 SFC_ASSERT(false); 2944 } 2945 } 2946 2947 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW " 2948 "support for inner frame pattern items is not guaranteed; " 2949 "other than that, the items are valid from SW standpoint"); 2950 return 0; 2951 } 2952 2953 /** 2954 * Confirm that a given flow can be accepted by the FW. 2955 * 2956 * @param sa 2957 * Software adapter context 2958 * @param flow 2959 * Flow to be verified 2960 * @return 2961 * Zero on success and non-zero in the case of error. 2962 * A special value of EAGAIN indicates that the adapter is 2963 * not in started state. This state is compulsory because 2964 * it only makes sense to compare the rule class of the flow 2965 * being validated with classes of the active rules. 2966 * Such classes are wittingly supported by the FW. 2967 */ 2968 int 2969 sfc_mae_flow_verify(struct sfc_adapter *sa, 2970 struct rte_flow *flow) 2971 { 2972 struct sfc_flow_spec *spec = &flow->spec; 2973 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 2974 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 2975 int rc; 2976 2977 SFC_ASSERT(sfc_adapter_is_locked(sa)); 2978 2979 if (sa->state != SFC_ADAPTER_STARTED) 2980 return EAGAIN; 2981 2982 if (outer_rule != NULL) { 2983 rc = sfc_mae_outer_rule_class_verify(sa, outer_rule); 2984 if (rc != 0) 2985 return rc; 2986 } 2987 2988 return sfc_mae_action_rule_class_verify(sa, spec_mae); 2989 } 2990 2991 int 2992 sfc_mae_flow_insert(struct sfc_adapter *sa, 2993 struct rte_flow *flow) 2994 { 2995 struct sfc_flow_spec *spec = &flow->spec; 2996 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 2997 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 2998 struct sfc_mae_action_set *action_set = spec_mae->action_set; 2999 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; 3000 int rc; 3001 3002 SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID); 3003 SFC_ASSERT(action_set != NULL); 3004 3005 if (outer_rule != NULL) { 3006 rc = sfc_mae_outer_rule_enable(sa, outer_rule, 3007 spec_mae->match_spec); 3008 if (rc != 0) 3009 goto fail_outer_rule_enable; 3010 } 3011 3012 rc = sfc_mae_action_set_enable(sa, action_set); 3013 if (rc != 0) 3014 goto fail_action_set_enable; 3015 3016 rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec, 3017 NULL, &fw_rsrc->aset_id, 3018 &spec_mae->rule_id); 3019 if (rc != 0) 3020 goto fail_action_rule_insert; 3021 3022 sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x", 3023 flow, spec_mae->rule_id.id); 3024 3025 return 0; 3026 3027 fail_action_rule_insert: 3028 sfc_mae_action_set_disable(sa, action_set); 3029 3030 fail_action_set_enable: 3031 if (outer_rule != NULL) 3032 sfc_mae_outer_rule_disable(sa, outer_rule); 3033 3034 fail_outer_rule_enable: 3035 return rc; 3036 } 3037 3038 int 3039 sfc_mae_flow_remove(struct sfc_adapter *sa, 3040 struct rte_flow *flow) 3041 { 3042 struct sfc_flow_spec *spec = &flow->spec; 3043 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 3044 struct sfc_mae_action_set *action_set = spec_mae->action_set; 3045 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 3046 int rc; 3047 3048 SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID); 3049 SFC_ASSERT(action_set != NULL); 3050 3051 rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id); 3052 if (rc != 0) { 3053 sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s", 3054 flow, spec_mae->rule_id.id, strerror(rc)); 3055 } 3056 sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x", 3057 flow, spec_mae->rule_id.id); 3058 spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID; 3059 3060 sfc_mae_action_set_disable(sa, action_set); 3061 3062 if (outer_rule != NULL) 3063 sfc_mae_outer_rule_disable(sa, outer_rule); 3064 3065 return 0; 3066 } 3067