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 unsigned int nb_supported_tpids = RTE_DIM(supported_tpids); 732 unsigned int ethertype_idx; 733 const uint8_t *valuep; 734 const uint8_t *maskp; 735 int rc; 736 737 if (pdata->innermost_ethertype_restriction.mask != 0 && 738 pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) { 739 /* 740 * If a single item VLAN is followed by a L3 item, value 741 * of "type" in item ETH can't be a double-tagging TPID. 742 */ 743 nb_supported_tpids = 1; 744 } 745 746 /* 747 * sfc_mae_rule_parse_item_vlan() has already made sure 748 * that pdata->nb_vlan_tags does not exceed this figure. 749 */ 750 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2); 751 752 for (ethertype_idx = 0; 753 ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) { 754 unsigned int tpid_idx; 755 756 /* Exact match is supported only. */ 757 if (ethertypes[ethertype_idx].mask != RTE_BE16(0xffff)) { 758 rc = EINVAL; 759 goto fail; 760 } 761 762 for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1; 763 tpid_idx < nb_supported_tpids; ++tpid_idx) { 764 if (ethertypes[ethertype_idx].value == 765 supported_tpids[tpid_idx]) 766 break; 767 } 768 769 if (tpid_idx == nb_supported_tpids) { 770 rc = EINVAL; 771 goto fail; 772 } 773 774 nb_supported_tpids = 1; 775 } 776 777 if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) { 778 struct sfc_mae_ethertype *et = ðertypes[ethertype_idx]; 779 780 if (et->mask == 0) { 781 et->mask = RTE_BE16(0xffff); 782 et->value = 783 pdata->innermost_ethertype_restriction.value; 784 } else if (et->mask != RTE_BE16(0xffff) || 785 et->value != 786 pdata->innermost_ethertype_restriction.value) { 787 rc = EINVAL; 788 goto fail; 789 } 790 } 791 792 /* 793 * Now, when the number of VLAN tags is known, set fields 794 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first 795 * one is either a valid L3 EtherType (or 0x0000/0x0000), 796 * and the last two are valid TPIDs (or 0x0000/0x0000). 797 */ 798 rc = sfc_mae_set_ethertypes(ctx); 799 if (rc != 0) 800 goto fail; 801 802 if (pdata->l3_next_proto_restriction_mask == 0xff) { 803 if (pdata->l3_next_proto_mask == 0) { 804 pdata->l3_next_proto_mask = 0xff; 805 pdata->l3_next_proto_value = 806 pdata->l3_next_proto_restriction_value; 807 } else if (pdata->l3_next_proto_mask != 0xff || 808 pdata->l3_next_proto_value != 809 pdata->l3_next_proto_restriction_value) { 810 rc = EINVAL; 811 goto fail; 812 } 813 } 814 815 valuep = (const uint8_t *)&pdata->l3_next_proto_value; 816 maskp = (const uint8_t *)&pdata->l3_next_proto_mask; 817 rc = efx_mae_match_spec_field_set(ctx->match_spec, 818 fremap[EFX_MAE_FIELD_IP_PROTO], 819 sizeof(pdata->l3_next_proto_value), 820 valuep, 821 sizeof(pdata->l3_next_proto_mask), 822 maskp); 823 if (rc != 0) 824 goto fail; 825 826 return 0; 827 828 fail: 829 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL, 830 "Failed to process pattern data"); 831 } 832 833 static int 834 sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item, 835 struct sfc_flow_parse_ctx *ctx, 836 struct rte_flow_error *error) 837 { 838 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 839 const struct rte_flow_item_port_id supp_mask = { 840 .id = 0xffffffff, 841 }; 842 const void *def_mask = &rte_flow_item_port_id_mask; 843 const struct rte_flow_item_port_id *spec = NULL; 844 const struct rte_flow_item_port_id *mask = NULL; 845 efx_mport_sel_t mport_sel; 846 int rc; 847 848 if (ctx_mae->match_mport_set) { 849 return rte_flow_error_set(error, ENOTSUP, 850 RTE_FLOW_ERROR_TYPE_ITEM, item, 851 "Can't handle multiple traffic source items"); 852 } 853 854 rc = sfc_flow_parse_init(item, 855 (const void **)&spec, (const void **)&mask, 856 (const void *)&supp_mask, def_mask, 857 sizeof(struct rte_flow_item_port_id), error); 858 if (rc != 0) 859 return rc; 860 861 if (mask->id != supp_mask.id) { 862 return rte_flow_error_set(error, EINVAL, 863 RTE_FLOW_ERROR_TYPE_ITEM, item, 864 "Bad mask in the PORT_ID pattern item"); 865 } 866 867 /* If "spec" is not set, could be any port ID */ 868 if (spec == NULL) 869 return 0; 870 871 if (spec->id > UINT16_MAX) { 872 return rte_flow_error_set(error, EOVERFLOW, 873 RTE_FLOW_ERROR_TYPE_ITEM, item, 874 "The port ID is too large"); 875 } 876 877 rc = sfc_mae_switch_port_by_ethdev(ctx_mae->sa->mae.switch_domain_id, 878 spec->id, &mport_sel); 879 if (rc != 0) { 880 return rte_flow_error_set(error, rc, 881 RTE_FLOW_ERROR_TYPE_ITEM, item, 882 "Can't find RTE ethdev by the port ID"); 883 } 884 885 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, 886 &mport_sel, NULL); 887 if (rc != 0) { 888 return rte_flow_error_set(error, rc, 889 RTE_FLOW_ERROR_TYPE_ITEM, item, 890 "Failed to set MPORT for the port ID"); 891 } 892 893 ctx_mae->match_mport_set = B_TRUE; 894 895 return 0; 896 } 897 898 static int 899 sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item, 900 struct sfc_flow_parse_ctx *ctx, 901 struct rte_flow_error *error) 902 { 903 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 904 const struct rte_flow_item_phy_port supp_mask = { 905 .index = 0xffffffff, 906 }; 907 const void *def_mask = &rte_flow_item_phy_port_mask; 908 const struct rte_flow_item_phy_port *spec = NULL; 909 const struct rte_flow_item_phy_port *mask = NULL; 910 efx_mport_sel_t mport_v; 911 int rc; 912 913 if (ctx_mae->match_mport_set) { 914 return rte_flow_error_set(error, ENOTSUP, 915 RTE_FLOW_ERROR_TYPE_ITEM, item, 916 "Can't handle multiple traffic source items"); 917 } 918 919 rc = sfc_flow_parse_init(item, 920 (const void **)&spec, (const void **)&mask, 921 (const void *)&supp_mask, def_mask, 922 sizeof(struct rte_flow_item_phy_port), error); 923 if (rc != 0) 924 return rc; 925 926 if (mask->index != supp_mask.index) { 927 return rte_flow_error_set(error, EINVAL, 928 RTE_FLOW_ERROR_TYPE_ITEM, item, 929 "Bad mask in the PHY_PORT pattern item"); 930 } 931 932 /* If "spec" is not set, could be any physical port */ 933 if (spec == NULL) 934 return 0; 935 936 rc = efx_mae_mport_by_phy_port(spec->index, &mport_v); 937 if (rc != 0) { 938 return rte_flow_error_set(error, rc, 939 RTE_FLOW_ERROR_TYPE_ITEM, item, 940 "Failed to convert the PHY_PORT index"); 941 } 942 943 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 944 if (rc != 0) { 945 return rte_flow_error_set(error, rc, 946 RTE_FLOW_ERROR_TYPE_ITEM, item, 947 "Failed to set MPORT for the PHY_PORT"); 948 } 949 950 ctx_mae->match_mport_set = B_TRUE; 951 952 return 0; 953 } 954 955 static int 956 sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item, 957 struct sfc_flow_parse_ctx *ctx, 958 struct rte_flow_error *error) 959 { 960 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 961 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic); 962 efx_mport_sel_t mport_v; 963 int rc; 964 965 if (ctx_mae->match_mport_set) { 966 return rte_flow_error_set(error, ENOTSUP, 967 RTE_FLOW_ERROR_TYPE_ITEM, item, 968 "Can't handle multiple traffic source items"); 969 } 970 971 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID, 972 &mport_v); 973 if (rc != 0) { 974 return rte_flow_error_set(error, rc, 975 RTE_FLOW_ERROR_TYPE_ITEM, item, 976 "Failed to convert the PF ID"); 977 } 978 979 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 980 if (rc != 0) { 981 return rte_flow_error_set(error, rc, 982 RTE_FLOW_ERROR_TYPE_ITEM, item, 983 "Failed to set MPORT for the PF"); 984 } 985 986 ctx_mae->match_mport_set = B_TRUE; 987 988 return 0; 989 } 990 991 static int 992 sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item, 993 struct sfc_flow_parse_ctx *ctx, 994 struct rte_flow_error *error) 995 { 996 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 997 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic); 998 const struct rte_flow_item_vf supp_mask = { 999 .id = 0xffffffff, 1000 }; 1001 const void *def_mask = &rte_flow_item_vf_mask; 1002 const struct rte_flow_item_vf *spec = NULL; 1003 const struct rte_flow_item_vf *mask = NULL; 1004 efx_mport_sel_t mport_v; 1005 int rc; 1006 1007 if (ctx_mae->match_mport_set) { 1008 return rte_flow_error_set(error, ENOTSUP, 1009 RTE_FLOW_ERROR_TYPE_ITEM, item, 1010 "Can't handle multiple traffic source items"); 1011 } 1012 1013 rc = sfc_flow_parse_init(item, 1014 (const void **)&spec, (const void **)&mask, 1015 (const void *)&supp_mask, def_mask, 1016 sizeof(struct rte_flow_item_vf), error); 1017 if (rc != 0) 1018 return rc; 1019 1020 if (mask->id != supp_mask.id) { 1021 return rte_flow_error_set(error, EINVAL, 1022 RTE_FLOW_ERROR_TYPE_ITEM, item, 1023 "Bad mask in the VF pattern item"); 1024 } 1025 1026 /* 1027 * If "spec" is not set, the item requests any VF related to the 1028 * PF of the current DPDK port (but not the PF itself). 1029 * Reject this match criterion as unsupported. 1030 */ 1031 if (spec == NULL) { 1032 return rte_flow_error_set(error, EINVAL, 1033 RTE_FLOW_ERROR_TYPE_ITEM, item, 1034 "Bad spec in the VF pattern item"); 1035 } 1036 1037 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v); 1038 if (rc != 0) { 1039 return rte_flow_error_set(error, rc, 1040 RTE_FLOW_ERROR_TYPE_ITEM, item, 1041 "Failed to convert the PF + VF IDs"); 1042 } 1043 1044 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL); 1045 if (rc != 0) { 1046 return rte_flow_error_set(error, rc, 1047 RTE_FLOW_ERROR_TYPE_ITEM, item, 1048 "Failed to set MPORT for the PF + VF"); 1049 } 1050 1051 ctx_mae->match_mport_set = B_TRUE; 1052 1053 return 0; 1054 } 1055 1056 /* 1057 * Having this field ID in a field locator means that this 1058 * locator cannot be used to actually set the field at the 1059 * time when the corresponding item gets encountered. Such 1060 * fields get stashed in the parsing context instead. This 1061 * is required to resolve dependencies between the stashed 1062 * fields. See sfc_mae_rule_process_pattern_data(). 1063 */ 1064 #define SFC_MAE_FIELD_HANDLING_DEFERRED EFX_MAE_FIELD_NIDS 1065 1066 struct sfc_mae_field_locator { 1067 efx_mae_field_id_t field_id; 1068 size_t size; 1069 /* Field offset in the corresponding rte_flow_item_ struct */ 1070 size_t ofst; 1071 }; 1072 1073 static void 1074 sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators, 1075 unsigned int nb_field_locators, void *mask_ptr, 1076 size_t mask_size) 1077 { 1078 unsigned int i; 1079 1080 memset(mask_ptr, 0, mask_size); 1081 1082 for (i = 0; i < nb_field_locators; ++i) { 1083 const struct sfc_mae_field_locator *fl = &field_locators[i]; 1084 1085 SFC_ASSERT(fl->ofst + fl->size <= mask_size); 1086 memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size); 1087 } 1088 } 1089 1090 static int 1091 sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators, 1092 unsigned int nb_field_locators, const uint8_t *spec, 1093 const uint8_t *mask, struct sfc_mae_parse_ctx *ctx, 1094 struct rte_flow_error *error) 1095 { 1096 const efx_mae_field_id_t *fremap = ctx->field_ids_remap; 1097 unsigned int i; 1098 int rc = 0; 1099 1100 for (i = 0; i < nb_field_locators; ++i) { 1101 const struct sfc_mae_field_locator *fl = &field_locators[i]; 1102 1103 if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED) 1104 continue; 1105 1106 rc = efx_mae_match_spec_field_set(ctx->match_spec, 1107 fremap[fl->field_id], 1108 fl->size, spec + fl->ofst, 1109 fl->size, mask + fl->ofst); 1110 if (rc != 0) 1111 break; 1112 } 1113 1114 if (rc != 0) { 1115 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1116 NULL, "Failed to process item fields"); 1117 } 1118 1119 return rc; 1120 } 1121 1122 static const struct sfc_mae_field_locator flocs_eth[] = { 1123 { 1124 /* 1125 * This locator is used only for building supported fields mask. 1126 * The field is handled by sfc_mae_rule_process_pattern_data(). 1127 */ 1128 SFC_MAE_FIELD_HANDLING_DEFERRED, 1129 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type), 1130 offsetof(struct rte_flow_item_eth, type), 1131 }, 1132 { 1133 EFX_MAE_FIELD_ETH_DADDR_BE, 1134 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst), 1135 offsetof(struct rte_flow_item_eth, dst), 1136 }, 1137 { 1138 EFX_MAE_FIELD_ETH_SADDR_BE, 1139 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src), 1140 offsetof(struct rte_flow_item_eth, src), 1141 }, 1142 }; 1143 1144 static int 1145 sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item, 1146 struct sfc_flow_parse_ctx *ctx, 1147 struct rte_flow_error *error) 1148 { 1149 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1150 struct rte_flow_item_eth supp_mask; 1151 const uint8_t *spec = NULL; 1152 const uint8_t *mask = NULL; 1153 int rc; 1154 1155 sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth), 1156 &supp_mask, sizeof(supp_mask)); 1157 1158 rc = sfc_flow_parse_init(item, 1159 (const void **)&spec, (const void **)&mask, 1160 (const void *)&supp_mask, 1161 &rte_flow_item_eth_mask, 1162 sizeof(struct rte_flow_item_eth), error); 1163 if (rc != 0) 1164 return rc; 1165 1166 if (spec != NULL) { 1167 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1168 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes; 1169 const struct rte_flow_item_eth *item_spec; 1170 const struct rte_flow_item_eth *item_mask; 1171 1172 item_spec = (const struct rte_flow_item_eth *)spec; 1173 item_mask = (const struct rte_flow_item_eth *)mask; 1174 1175 ethertypes[0].value = item_spec->type; 1176 ethertypes[0].mask = item_mask->type; 1177 } else { 1178 /* 1179 * The specification is empty. This is wrong in the case 1180 * when there are more network patterns in line. Other 1181 * than that, any Ethernet can match. All of that is 1182 * checked at the end of parsing. 1183 */ 1184 return 0; 1185 } 1186 1187 return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask, 1188 ctx_mae, error); 1189 } 1190 1191 static const struct sfc_mae_field_locator flocs_vlan[] = { 1192 /* Outermost tag */ 1193 { 1194 EFX_MAE_FIELD_VLAN0_TCI_BE, 1195 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci), 1196 offsetof(struct rte_flow_item_vlan, tci), 1197 }, 1198 { 1199 /* 1200 * This locator is used only for building supported fields mask. 1201 * The field is handled by sfc_mae_rule_process_pattern_data(). 1202 */ 1203 SFC_MAE_FIELD_HANDLING_DEFERRED, 1204 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type), 1205 offsetof(struct rte_flow_item_vlan, inner_type), 1206 }, 1207 1208 /* Innermost tag */ 1209 { 1210 EFX_MAE_FIELD_VLAN1_TCI_BE, 1211 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci), 1212 offsetof(struct rte_flow_item_vlan, tci), 1213 }, 1214 { 1215 /* 1216 * This locator is used only for building supported fields mask. 1217 * The field is handled by sfc_mae_rule_process_pattern_data(). 1218 */ 1219 SFC_MAE_FIELD_HANDLING_DEFERRED, 1220 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type), 1221 offsetof(struct rte_flow_item_vlan, inner_type), 1222 }, 1223 }; 1224 1225 static int 1226 sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item, 1227 struct sfc_flow_parse_ctx *ctx, 1228 struct rte_flow_error *error) 1229 { 1230 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1231 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1232 const struct sfc_mae_field_locator *flocs; 1233 struct rte_flow_item_vlan supp_mask; 1234 const uint8_t *spec = NULL; 1235 const uint8_t *mask = NULL; 1236 unsigned int nb_flocs; 1237 int rc; 1238 1239 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2); 1240 1241 if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) { 1242 return rte_flow_error_set(error, ENOTSUP, 1243 RTE_FLOW_ERROR_TYPE_ITEM, item, 1244 "Can't match that many VLAN tags"); 1245 } 1246 1247 nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS; 1248 flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs; 1249 1250 /* If parsing fails, this can remain incremented. */ 1251 ++pdata->nb_vlan_tags; 1252 1253 sfc_mae_item_build_supp_mask(flocs, nb_flocs, 1254 &supp_mask, sizeof(supp_mask)); 1255 1256 rc = sfc_flow_parse_init(item, 1257 (const void **)&spec, (const void **)&mask, 1258 (const void *)&supp_mask, 1259 &rte_flow_item_vlan_mask, 1260 sizeof(struct rte_flow_item_vlan), error); 1261 if (rc != 0) 1262 return rc; 1263 1264 if (spec != NULL) { 1265 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes; 1266 const struct rte_flow_item_vlan *item_spec; 1267 const struct rte_flow_item_vlan *item_mask; 1268 1269 item_spec = (const struct rte_flow_item_vlan *)spec; 1270 item_mask = (const struct rte_flow_item_vlan *)mask; 1271 1272 ethertypes[pdata->nb_vlan_tags].value = item_spec->inner_type; 1273 ethertypes[pdata->nb_vlan_tags].mask = item_mask->inner_type; 1274 } else { 1275 /* 1276 * The specification is empty. This is wrong in the case 1277 * when there are more network patterns in line. Other 1278 * than that, any Ethernet can match. All of that is 1279 * checked at the end of parsing. 1280 */ 1281 return 0; 1282 } 1283 1284 return sfc_mae_parse_item(flocs, nb_flocs, spec, mask, ctx_mae, error); 1285 } 1286 1287 static const struct sfc_mae_field_locator flocs_ipv4[] = { 1288 { 1289 EFX_MAE_FIELD_SRC_IP4_BE, 1290 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr), 1291 offsetof(struct rte_flow_item_ipv4, hdr.src_addr), 1292 }, 1293 { 1294 EFX_MAE_FIELD_DST_IP4_BE, 1295 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr), 1296 offsetof(struct rte_flow_item_ipv4, hdr.dst_addr), 1297 }, 1298 { 1299 /* 1300 * This locator is used only for building supported fields mask. 1301 * The field is handled by sfc_mae_rule_process_pattern_data(). 1302 */ 1303 SFC_MAE_FIELD_HANDLING_DEFERRED, 1304 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id), 1305 offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id), 1306 }, 1307 { 1308 EFX_MAE_FIELD_IP_TOS, 1309 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, 1310 hdr.type_of_service), 1311 offsetof(struct rte_flow_item_ipv4, hdr.type_of_service), 1312 }, 1313 { 1314 EFX_MAE_FIELD_IP_TTL, 1315 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live), 1316 offsetof(struct rte_flow_item_ipv4, hdr.time_to_live), 1317 }, 1318 }; 1319 1320 static int 1321 sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item, 1322 struct sfc_flow_parse_ctx *ctx, 1323 struct rte_flow_error *error) 1324 { 1325 rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4); 1326 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1327 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1328 struct rte_flow_item_ipv4 supp_mask; 1329 const uint8_t *spec = NULL; 1330 const uint8_t *mask = NULL; 1331 int rc; 1332 1333 sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4), 1334 &supp_mask, sizeof(supp_mask)); 1335 1336 rc = sfc_flow_parse_init(item, 1337 (const void **)&spec, (const void **)&mask, 1338 (const void *)&supp_mask, 1339 &rte_flow_item_ipv4_mask, 1340 sizeof(struct rte_flow_item_ipv4), error); 1341 if (rc != 0) 1342 return rc; 1343 1344 pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be; 1345 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff); 1346 1347 if (spec != NULL) { 1348 const struct rte_flow_item_ipv4 *item_spec; 1349 const struct rte_flow_item_ipv4 *item_mask; 1350 1351 item_spec = (const struct rte_flow_item_ipv4 *)spec; 1352 item_mask = (const struct rte_flow_item_ipv4 *)mask; 1353 1354 pdata->l3_next_proto_value = item_spec->hdr.next_proto_id; 1355 pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id; 1356 } else { 1357 return 0; 1358 } 1359 1360 return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask, 1361 ctx_mae, error); 1362 } 1363 1364 static const struct sfc_mae_field_locator flocs_ipv6[] = { 1365 { 1366 EFX_MAE_FIELD_SRC_IP6_BE, 1367 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr), 1368 offsetof(struct rte_flow_item_ipv6, hdr.src_addr), 1369 }, 1370 { 1371 EFX_MAE_FIELD_DST_IP6_BE, 1372 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr), 1373 offsetof(struct rte_flow_item_ipv6, hdr.dst_addr), 1374 }, 1375 { 1376 /* 1377 * This locator is used only for building supported fields mask. 1378 * The field is handled by sfc_mae_rule_process_pattern_data(). 1379 */ 1380 SFC_MAE_FIELD_HANDLING_DEFERRED, 1381 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto), 1382 offsetof(struct rte_flow_item_ipv6, hdr.proto), 1383 }, 1384 { 1385 EFX_MAE_FIELD_IP_TTL, 1386 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits), 1387 offsetof(struct rte_flow_item_ipv6, hdr.hop_limits), 1388 }, 1389 }; 1390 1391 static int 1392 sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item, 1393 struct sfc_flow_parse_ctx *ctx, 1394 struct rte_flow_error *error) 1395 { 1396 rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6); 1397 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1398 const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap; 1399 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1400 struct rte_flow_item_ipv6 supp_mask; 1401 const uint8_t *spec = NULL; 1402 const uint8_t *mask = NULL; 1403 rte_be32_t vtc_flow_be; 1404 uint32_t vtc_flow; 1405 uint8_t tc_value; 1406 uint8_t tc_mask; 1407 int rc; 1408 1409 sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6), 1410 &supp_mask, sizeof(supp_mask)); 1411 1412 vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK); 1413 memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be)); 1414 1415 rc = sfc_flow_parse_init(item, 1416 (const void **)&spec, (const void **)&mask, 1417 (const void *)&supp_mask, 1418 &rte_flow_item_ipv6_mask, 1419 sizeof(struct rte_flow_item_ipv6), error); 1420 if (rc != 0) 1421 return rc; 1422 1423 pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be; 1424 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff); 1425 1426 if (spec != NULL) { 1427 const struct rte_flow_item_ipv6 *item_spec; 1428 const struct rte_flow_item_ipv6 *item_mask; 1429 1430 item_spec = (const struct rte_flow_item_ipv6 *)spec; 1431 item_mask = (const struct rte_flow_item_ipv6 *)mask; 1432 1433 pdata->l3_next_proto_value = item_spec->hdr.proto; 1434 pdata->l3_next_proto_mask = item_mask->hdr.proto; 1435 } else { 1436 return 0; 1437 } 1438 1439 rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask, 1440 ctx_mae, error); 1441 if (rc != 0) 1442 return rc; 1443 1444 memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be)); 1445 vtc_flow = rte_be_to_cpu_32(vtc_flow_be); 1446 tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT; 1447 1448 memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be)); 1449 vtc_flow = rte_be_to_cpu_32(vtc_flow_be); 1450 tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT; 1451 1452 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec, 1453 fremap[EFX_MAE_FIELD_IP_TOS], 1454 sizeof(tc_value), &tc_value, 1455 sizeof(tc_mask), &tc_mask); 1456 if (rc != 0) { 1457 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1458 NULL, "Failed to process item fields"); 1459 } 1460 1461 return 0; 1462 } 1463 1464 static const struct sfc_mae_field_locator flocs_tcp[] = { 1465 { 1466 EFX_MAE_FIELD_L4_SPORT_BE, 1467 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port), 1468 offsetof(struct rte_flow_item_tcp, hdr.src_port), 1469 }, 1470 { 1471 EFX_MAE_FIELD_L4_DPORT_BE, 1472 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port), 1473 offsetof(struct rte_flow_item_tcp, hdr.dst_port), 1474 }, 1475 { 1476 EFX_MAE_FIELD_TCP_FLAGS_BE, 1477 /* 1478 * The values have been picked intentionally since the 1479 * target MAE field is oversize (16 bit). This mapping 1480 * relies on the fact that the MAE field is big-endian. 1481 */ 1482 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) + 1483 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags), 1484 offsetof(struct rte_flow_item_tcp, hdr.data_off), 1485 }, 1486 }; 1487 1488 static int 1489 sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item, 1490 struct sfc_flow_parse_ctx *ctx, 1491 struct rte_flow_error *error) 1492 { 1493 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1494 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1495 struct rte_flow_item_tcp supp_mask; 1496 const uint8_t *spec = NULL; 1497 const uint8_t *mask = NULL; 1498 int rc; 1499 1500 /* 1501 * When encountered among outermost items, item TCP is invalid. 1502 * Check which match specification is being constructed now. 1503 */ 1504 if (ctx_mae->match_spec != ctx_mae->match_spec_action) { 1505 return rte_flow_error_set(error, EINVAL, 1506 RTE_FLOW_ERROR_TYPE_ITEM, item, 1507 "TCP in outer frame is invalid"); 1508 } 1509 1510 sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp), 1511 &supp_mask, sizeof(supp_mask)); 1512 1513 rc = sfc_flow_parse_init(item, 1514 (const void **)&spec, (const void **)&mask, 1515 (const void *)&supp_mask, 1516 &rte_flow_item_tcp_mask, 1517 sizeof(struct rte_flow_item_tcp), error); 1518 if (rc != 0) 1519 return rc; 1520 1521 pdata->l3_next_proto_restriction_value = IPPROTO_TCP; 1522 pdata->l3_next_proto_restriction_mask = 0xff; 1523 1524 if (spec == NULL) 1525 return 0; 1526 1527 return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask, 1528 ctx_mae, error); 1529 } 1530 1531 static const struct sfc_mae_field_locator flocs_udp[] = { 1532 { 1533 EFX_MAE_FIELD_L4_SPORT_BE, 1534 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port), 1535 offsetof(struct rte_flow_item_udp, hdr.src_port), 1536 }, 1537 { 1538 EFX_MAE_FIELD_L4_DPORT_BE, 1539 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port), 1540 offsetof(struct rte_flow_item_udp, hdr.dst_port), 1541 }, 1542 }; 1543 1544 static int 1545 sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item, 1546 struct sfc_flow_parse_ctx *ctx, 1547 struct rte_flow_error *error) 1548 { 1549 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1550 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data; 1551 struct rte_flow_item_udp supp_mask; 1552 const uint8_t *spec = NULL; 1553 const uint8_t *mask = NULL; 1554 int rc; 1555 1556 sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp), 1557 &supp_mask, sizeof(supp_mask)); 1558 1559 rc = sfc_flow_parse_init(item, 1560 (const void **)&spec, (const void **)&mask, 1561 (const void *)&supp_mask, 1562 &rte_flow_item_udp_mask, 1563 sizeof(struct rte_flow_item_udp), error); 1564 if (rc != 0) 1565 return rc; 1566 1567 pdata->l3_next_proto_restriction_value = IPPROTO_UDP; 1568 pdata->l3_next_proto_restriction_mask = 0xff; 1569 1570 if (spec == NULL) 1571 return 0; 1572 1573 return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask, 1574 ctx_mae, error); 1575 } 1576 1577 static const struct sfc_mae_field_locator flocs_tunnel[] = { 1578 { 1579 /* 1580 * The size and offset values are relevant 1581 * for Geneve and NVGRE, too. 1582 */ 1583 .size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, vni), 1584 .ofst = offsetof(struct rte_flow_item_vxlan, vni), 1585 }, 1586 }; 1587 1588 /* 1589 * An auxiliary registry which allows using non-encap. field IDs 1590 * directly when building a match specification of type ACTION. 1591 * 1592 * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel(). 1593 */ 1594 static const efx_mae_field_id_t field_ids_no_remap[] = { 1595 #define FIELD_ID_NO_REMAP(_field) \ 1596 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field 1597 1598 FIELD_ID_NO_REMAP(ETHER_TYPE_BE), 1599 FIELD_ID_NO_REMAP(ETH_SADDR_BE), 1600 FIELD_ID_NO_REMAP(ETH_DADDR_BE), 1601 FIELD_ID_NO_REMAP(VLAN0_TCI_BE), 1602 FIELD_ID_NO_REMAP(VLAN0_PROTO_BE), 1603 FIELD_ID_NO_REMAP(VLAN1_TCI_BE), 1604 FIELD_ID_NO_REMAP(VLAN1_PROTO_BE), 1605 FIELD_ID_NO_REMAP(SRC_IP4_BE), 1606 FIELD_ID_NO_REMAP(DST_IP4_BE), 1607 FIELD_ID_NO_REMAP(IP_PROTO), 1608 FIELD_ID_NO_REMAP(IP_TOS), 1609 FIELD_ID_NO_REMAP(IP_TTL), 1610 FIELD_ID_NO_REMAP(SRC_IP6_BE), 1611 FIELD_ID_NO_REMAP(DST_IP6_BE), 1612 FIELD_ID_NO_REMAP(L4_SPORT_BE), 1613 FIELD_ID_NO_REMAP(L4_DPORT_BE), 1614 FIELD_ID_NO_REMAP(TCP_FLAGS_BE), 1615 1616 #undef FIELD_ID_NO_REMAP 1617 }; 1618 1619 /* 1620 * An auxiliary registry which allows using "ENC" field IDs 1621 * when building a match specification of type OUTER. 1622 * 1623 * See sfc_mae_rule_encap_parse_init(). 1624 */ 1625 static const efx_mae_field_id_t field_ids_remap_to_encap[] = { 1626 #define FIELD_ID_REMAP_TO_ENCAP(_field) \ 1627 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field 1628 1629 FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE), 1630 FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE), 1631 FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE), 1632 FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE), 1633 FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE), 1634 FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE), 1635 FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE), 1636 FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE), 1637 FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE), 1638 FIELD_ID_REMAP_TO_ENCAP(IP_PROTO), 1639 FIELD_ID_REMAP_TO_ENCAP(IP_TOS), 1640 FIELD_ID_REMAP_TO_ENCAP(IP_TTL), 1641 FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE), 1642 FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE), 1643 FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE), 1644 FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE), 1645 1646 #undef FIELD_ID_REMAP_TO_ENCAP 1647 }; 1648 1649 static int 1650 sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item, 1651 struct sfc_flow_parse_ctx *ctx, 1652 struct rte_flow_error *error) 1653 { 1654 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae; 1655 uint8_t vnet_id_v[sizeof(uint32_t)] = {0}; 1656 uint8_t vnet_id_m[sizeof(uint32_t)] = {0}; 1657 const struct rte_flow_item_vxlan *vxp; 1658 uint8_t supp_mask[sizeof(uint64_t)]; 1659 const uint8_t *spec = NULL; 1660 const uint8_t *mask = NULL; 1661 int rc; 1662 1663 /* 1664 * We're about to start processing inner frame items. 1665 * Process pattern data that has been deferred so far 1666 * and reset pattern data storage. 1667 */ 1668 rc = sfc_mae_rule_process_pattern_data(ctx_mae, error); 1669 if (rc != 0) 1670 return rc; 1671 1672 memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data)); 1673 1674 sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel), 1675 &supp_mask, sizeof(supp_mask)); 1676 1677 /* 1678 * This tunnel item was preliminarily detected by 1679 * sfc_mae_rule_encap_parse_init(). Default mask 1680 * was also picked by that helper. Use it here. 1681 */ 1682 rc = sfc_flow_parse_init(item, 1683 (const void **)&spec, (const void **)&mask, 1684 (const void *)&supp_mask, 1685 ctx_mae->tunnel_def_mask, 1686 ctx_mae->tunnel_def_mask_size, error); 1687 if (rc != 0) 1688 return rc; 1689 1690 /* 1691 * This item and later ones comprise a 1692 * match specification of type ACTION. 1693 */ 1694 ctx_mae->match_spec = ctx_mae->match_spec_action; 1695 1696 /* This item and later ones use non-encap. EFX MAE field IDs. */ 1697 ctx_mae->field_ids_remap = field_ids_no_remap; 1698 1699 if (spec == NULL) 1700 return 0; 1701 1702 /* 1703 * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one. 1704 * Copy 24-bit VNI, which is BE, at offset 1 in it. 1705 * The extra byte is 0 both in the mask and in the value. 1706 */ 1707 vxp = (const struct rte_flow_item_vxlan *)spec; 1708 memcpy(vnet_id_v + 1, &vxp->vni, sizeof(vxp->vni)); 1709 1710 vxp = (const struct rte_flow_item_vxlan *)mask; 1711 memcpy(vnet_id_m + 1, &vxp->vni, sizeof(vxp->vni)); 1712 1713 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec, 1714 EFX_MAE_FIELD_ENC_VNET_ID_BE, 1715 sizeof(vnet_id_v), vnet_id_v, 1716 sizeof(vnet_id_m), vnet_id_m); 1717 if (rc != 0) { 1718 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, 1719 item, "Failed to set VXLAN VNI"); 1720 } 1721 1722 return rc; 1723 } 1724 1725 static const struct sfc_flow_item sfc_flow_items[] = { 1726 { 1727 .type = RTE_FLOW_ITEM_TYPE_PORT_ID, 1728 /* 1729 * In terms of RTE flow, this item is a META one, 1730 * and its position in the pattern is don't care. 1731 */ 1732 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1733 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1734 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1735 .parse = sfc_mae_rule_parse_item_port_id, 1736 }, 1737 { 1738 .type = RTE_FLOW_ITEM_TYPE_PHY_PORT, 1739 /* 1740 * In terms of RTE flow, this item is a META one, 1741 * and its position in the pattern is don't care. 1742 */ 1743 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1744 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1745 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1746 .parse = sfc_mae_rule_parse_item_phy_port, 1747 }, 1748 { 1749 .type = RTE_FLOW_ITEM_TYPE_PF, 1750 /* 1751 * In terms of RTE flow, this item is a META one, 1752 * and its position in the pattern is don't care. 1753 */ 1754 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1755 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1756 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1757 .parse = sfc_mae_rule_parse_item_pf, 1758 }, 1759 { 1760 .type = RTE_FLOW_ITEM_TYPE_VF, 1761 /* 1762 * In terms of RTE flow, this item is a META one, 1763 * and its position in the pattern is don't care. 1764 */ 1765 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 1766 .layer = SFC_FLOW_ITEM_ANY_LAYER, 1767 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1768 .parse = sfc_mae_rule_parse_item_vf, 1769 }, 1770 { 1771 .type = RTE_FLOW_ITEM_TYPE_ETH, 1772 .prev_layer = SFC_FLOW_ITEM_START_LAYER, 1773 .layer = SFC_FLOW_ITEM_L2, 1774 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1775 .parse = sfc_mae_rule_parse_item_eth, 1776 }, 1777 { 1778 .type = RTE_FLOW_ITEM_TYPE_VLAN, 1779 .prev_layer = SFC_FLOW_ITEM_L2, 1780 .layer = SFC_FLOW_ITEM_L2, 1781 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1782 .parse = sfc_mae_rule_parse_item_vlan, 1783 }, 1784 { 1785 .type = RTE_FLOW_ITEM_TYPE_IPV4, 1786 .prev_layer = SFC_FLOW_ITEM_L2, 1787 .layer = SFC_FLOW_ITEM_L3, 1788 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1789 .parse = sfc_mae_rule_parse_item_ipv4, 1790 }, 1791 { 1792 .type = RTE_FLOW_ITEM_TYPE_IPV6, 1793 .prev_layer = SFC_FLOW_ITEM_L2, 1794 .layer = SFC_FLOW_ITEM_L3, 1795 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1796 .parse = sfc_mae_rule_parse_item_ipv6, 1797 }, 1798 { 1799 .type = RTE_FLOW_ITEM_TYPE_TCP, 1800 .prev_layer = SFC_FLOW_ITEM_L3, 1801 .layer = SFC_FLOW_ITEM_L4, 1802 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1803 .parse = sfc_mae_rule_parse_item_tcp, 1804 }, 1805 { 1806 .type = RTE_FLOW_ITEM_TYPE_UDP, 1807 .prev_layer = SFC_FLOW_ITEM_L3, 1808 .layer = SFC_FLOW_ITEM_L4, 1809 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1810 .parse = sfc_mae_rule_parse_item_udp, 1811 }, 1812 { 1813 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 1814 .prev_layer = SFC_FLOW_ITEM_L4, 1815 .layer = SFC_FLOW_ITEM_START_LAYER, 1816 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1817 .parse = sfc_mae_rule_parse_item_tunnel, 1818 }, 1819 { 1820 .type = RTE_FLOW_ITEM_TYPE_GENEVE, 1821 .prev_layer = SFC_FLOW_ITEM_L4, 1822 .layer = SFC_FLOW_ITEM_START_LAYER, 1823 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1824 .parse = sfc_mae_rule_parse_item_tunnel, 1825 }, 1826 { 1827 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 1828 .prev_layer = SFC_FLOW_ITEM_L3, 1829 .layer = SFC_FLOW_ITEM_START_LAYER, 1830 .ctx_type = SFC_FLOW_PARSE_CTX_MAE, 1831 .parse = sfc_mae_rule_parse_item_tunnel, 1832 }, 1833 }; 1834 1835 static int 1836 sfc_mae_rule_process_outer(struct sfc_adapter *sa, 1837 struct sfc_mae_parse_ctx *ctx, 1838 struct sfc_mae_outer_rule **rulep, 1839 struct rte_flow_error *error) 1840 { 1841 struct sfc_mae_outer_rule *rule; 1842 int rc; 1843 1844 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) { 1845 *rulep = NULL; 1846 return 0; 1847 } 1848 1849 SFC_ASSERT(ctx->match_spec_outer != NULL); 1850 1851 if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) { 1852 return rte_flow_error_set(error, ENOTSUP, 1853 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1854 "Inconsistent pattern (outer)"); 1855 } 1856 1857 *rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer, 1858 ctx->encap_type); 1859 if (*rulep != NULL) { 1860 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer); 1861 } else { 1862 rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer, 1863 ctx->encap_type, rulep); 1864 if (rc != 0) { 1865 return rte_flow_error_set(error, rc, 1866 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1867 "Failed to process the pattern"); 1868 } 1869 } 1870 1871 /* The spec has now been tracked by the outer rule entry. */ 1872 ctx->match_spec_outer = NULL; 1873 1874 /* 1875 * Depending on whether we reuse an existing outer rule or create a 1876 * new one (see above), outer rule ID is either a valid value or 1877 * EFX_MAE_RSRC_ID_INVALID. Set it in the action rule match 1878 * specification (and the full mask, too) in order to have correct 1879 * class comparisons of the new rule with existing ones. 1880 * Also, action rule match specification will be validated shortly, 1881 * and having the full mask set for outer rule ID indicates that we 1882 * will use this field, and support for this field has to be checked. 1883 */ 1884 rule = *rulep; 1885 rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action, 1886 &rule->fw_rsrc.rule_id); 1887 if (rc != 0) { 1888 sfc_mae_outer_rule_del(sa, *rulep); 1889 *rulep = NULL; 1890 1891 return rte_flow_error_set(error, rc, 1892 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1893 "Failed to process the pattern"); 1894 } 1895 1896 return 0; 1897 } 1898 1899 static int 1900 sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa, 1901 const struct rte_flow_item pattern[], 1902 struct sfc_mae_parse_ctx *ctx, 1903 struct rte_flow_error *error) 1904 { 1905 struct sfc_mae *mae = &sa->mae; 1906 int rc; 1907 1908 if (pattern == NULL) { 1909 rte_flow_error_set(error, EINVAL, 1910 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL, 1911 "NULL pattern"); 1912 return -rte_errno; 1913 } 1914 1915 for (;;) { 1916 switch (pattern->type) { 1917 case RTE_FLOW_ITEM_TYPE_VXLAN: 1918 ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN; 1919 ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask; 1920 ctx->tunnel_def_mask_size = 1921 sizeof(rte_flow_item_vxlan_mask); 1922 break; 1923 case RTE_FLOW_ITEM_TYPE_GENEVE: 1924 ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE; 1925 ctx->tunnel_def_mask = &rte_flow_item_geneve_mask; 1926 ctx->tunnel_def_mask_size = 1927 sizeof(rte_flow_item_geneve_mask); 1928 break; 1929 case RTE_FLOW_ITEM_TYPE_NVGRE: 1930 ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE; 1931 ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask; 1932 ctx->tunnel_def_mask_size = 1933 sizeof(rte_flow_item_nvgre_mask); 1934 break; 1935 case RTE_FLOW_ITEM_TYPE_END: 1936 break; 1937 default: 1938 ++pattern; 1939 continue; 1940 }; 1941 1942 break; 1943 } 1944 1945 if (pattern->type == RTE_FLOW_ITEM_TYPE_END) 1946 return 0; 1947 1948 if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) { 1949 return rte_flow_error_set(error, ENOTSUP, 1950 RTE_FLOW_ERROR_TYPE_ITEM, 1951 pattern, "Unsupported tunnel item"); 1952 } 1953 1954 if (ctx->priority >= mae->nb_outer_rule_prios_max) { 1955 return rte_flow_error_set(error, ENOTSUP, 1956 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1957 NULL, "Unsupported priority level"); 1958 } 1959 1960 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_OUTER, ctx->priority, 1961 &ctx->match_spec_outer); 1962 if (rc != 0) { 1963 return rte_flow_error_set(error, rc, 1964 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 1965 "Failed to initialise outer rule match specification"); 1966 } 1967 1968 /* Outermost items comprise a match specification of type OUTER. */ 1969 ctx->match_spec = ctx->match_spec_outer; 1970 1971 /* Outermost items use "ENC" EFX MAE field IDs. */ 1972 ctx->field_ids_remap = field_ids_remap_to_encap; 1973 1974 return 0; 1975 } 1976 1977 static void 1978 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa, 1979 struct sfc_mae_parse_ctx *ctx) 1980 { 1981 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) 1982 return; 1983 1984 if (ctx->match_spec_outer != NULL) 1985 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer); 1986 } 1987 1988 int 1989 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa, 1990 const struct rte_flow_item pattern[], 1991 struct sfc_flow_spec_mae *spec, 1992 struct rte_flow_error *error) 1993 { 1994 struct sfc_mae_parse_ctx ctx_mae; 1995 struct sfc_flow_parse_ctx ctx; 1996 int rc; 1997 1998 memset(&ctx_mae, 0, sizeof(ctx_mae)); 1999 ctx_mae.priority = spec->priority; 2000 ctx_mae.sa = sa; 2001 2002 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION, 2003 spec->priority, 2004 &ctx_mae.match_spec_action); 2005 if (rc != 0) { 2006 rc = rte_flow_error_set(error, rc, 2007 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2008 "Failed to initialise action rule match specification"); 2009 goto fail_init_match_spec_action; 2010 } 2011 2012 /* 2013 * As a preliminary setting, assume that there is no encapsulation 2014 * in the pattern. That is, pattern items are about to comprise a 2015 * match specification of type ACTION and use non-encap. field IDs. 2016 * 2017 * sfc_mae_rule_encap_parse_init() below may override this. 2018 */ 2019 ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE; 2020 ctx_mae.match_spec = ctx_mae.match_spec_action; 2021 ctx_mae.field_ids_remap = field_ids_no_remap; 2022 2023 ctx.type = SFC_FLOW_PARSE_CTX_MAE; 2024 ctx.mae = &ctx_mae; 2025 2026 rc = sfc_mae_rule_encap_parse_init(sa, pattern, &ctx_mae, error); 2027 if (rc != 0) 2028 goto fail_encap_parse_init; 2029 2030 rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items), 2031 pattern, &ctx, error); 2032 if (rc != 0) 2033 goto fail_parse_pattern; 2034 2035 rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error); 2036 if (rc != 0) 2037 goto fail_process_pattern_data; 2038 2039 rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error); 2040 if (rc != 0) 2041 goto fail_process_outer; 2042 2043 if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) { 2044 rc = rte_flow_error_set(error, ENOTSUP, 2045 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 2046 "Inconsistent pattern"); 2047 goto fail_validate_match_spec_action; 2048 } 2049 2050 spec->match_spec = ctx_mae.match_spec_action; 2051 2052 return 0; 2053 2054 fail_validate_match_spec_action: 2055 fail_process_outer: 2056 fail_process_pattern_data: 2057 fail_parse_pattern: 2058 sfc_mae_rule_encap_parse_fini(sa, &ctx_mae); 2059 2060 fail_encap_parse_init: 2061 efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action); 2062 2063 fail_init_match_spec_action: 2064 return rc; 2065 } 2066 2067 /* 2068 * An action supported by MAE may correspond to a bundle of RTE flow actions, 2069 * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP. 2070 * That is, related RTE flow actions need to be tracked as parts of a whole 2071 * so that they can be combined into a single action and submitted to MAE 2072 * representation of a given rule's action set. 2073 * 2074 * Each RTE flow action provided by an application gets classified as 2075 * one belonging to some bundle type. If an action is not supposed to 2076 * belong to any bundle, or if this action is END, it is described as 2077 * one belonging to a dummy bundle of type EMPTY. 2078 * 2079 * A currently tracked bundle will be submitted if a repeating 2080 * action or an action of different bundle type follows. 2081 */ 2082 2083 enum sfc_mae_actions_bundle_type { 2084 SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0, 2085 SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH, 2086 }; 2087 2088 struct sfc_mae_actions_bundle { 2089 enum sfc_mae_actions_bundle_type type; 2090 2091 /* Indicates actions already tracked by the current bundle */ 2092 uint64_t actions_mask; 2093 2094 /* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */ 2095 rte_be16_t vlan_push_tpid; 2096 rte_be16_t vlan_push_tci; 2097 }; 2098 2099 /* 2100 * Combine configuration of RTE flow actions tracked by the bundle into a 2101 * single action and submit the result to MAE action set specification. 2102 * Do nothing in the case of dummy action bundle. 2103 */ 2104 static int 2105 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle, 2106 efx_mae_actions_t *spec) 2107 { 2108 int rc = 0; 2109 2110 switch (bundle->type) { 2111 case SFC_MAE_ACTIONS_BUNDLE_EMPTY: 2112 break; 2113 case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH: 2114 rc = efx_mae_action_set_populate_vlan_push( 2115 spec, bundle->vlan_push_tpid, bundle->vlan_push_tci); 2116 break; 2117 default: 2118 SFC_ASSERT(B_FALSE); 2119 break; 2120 } 2121 2122 return rc; 2123 } 2124 2125 /* 2126 * Given the type of the next RTE flow action in the line, decide 2127 * whether a new bundle is about to start, and, if this is the case, 2128 * submit and reset the current bundle. 2129 */ 2130 static int 2131 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action, 2132 struct sfc_mae_actions_bundle *bundle, 2133 efx_mae_actions_t *spec, 2134 struct rte_flow_error *error) 2135 { 2136 enum sfc_mae_actions_bundle_type bundle_type_new; 2137 int rc; 2138 2139 switch (action->type) { 2140 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 2141 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 2142 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 2143 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH; 2144 break; 2145 default: 2146 /* 2147 * Self-sufficient actions, including END, are handled in this 2148 * case. No checks for unsupported actions are needed here 2149 * because parsing doesn't occur at this point. 2150 */ 2151 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY; 2152 break; 2153 } 2154 2155 if (bundle_type_new != bundle->type || 2156 (bundle->actions_mask & (1ULL << action->type)) != 0) { 2157 rc = sfc_mae_actions_bundle_submit(bundle, spec); 2158 if (rc != 0) 2159 goto fail_submit; 2160 2161 memset(bundle, 0, sizeof(*bundle)); 2162 } 2163 2164 bundle->type = bundle_type_new; 2165 2166 return 0; 2167 2168 fail_submit: 2169 return rte_flow_error_set(error, rc, 2170 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2171 "Failed to request the (group of) action(s)"); 2172 } 2173 2174 static void 2175 sfc_mae_rule_parse_action_of_push_vlan( 2176 const struct rte_flow_action_of_push_vlan *conf, 2177 struct sfc_mae_actions_bundle *bundle) 2178 { 2179 bundle->vlan_push_tpid = conf->ethertype; 2180 } 2181 2182 static void 2183 sfc_mae_rule_parse_action_of_set_vlan_vid( 2184 const struct rte_flow_action_of_set_vlan_vid *conf, 2185 struct sfc_mae_actions_bundle *bundle) 2186 { 2187 bundle->vlan_push_tci |= (conf->vlan_vid & 2188 rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t))); 2189 } 2190 2191 static void 2192 sfc_mae_rule_parse_action_of_set_vlan_pcp( 2193 const struct rte_flow_action_of_set_vlan_pcp *conf, 2194 struct sfc_mae_actions_bundle *bundle) 2195 { 2196 uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp & 2197 RTE_LEN2MASK(3, uint8_t)) << 13; 2198 2199 bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp); 2200 } 2201 2202 struct sfc_mae_parsed_item { 2203 const struct rte_flow_item *item; 2204 size_t proto_header_ofst; 2205 size_t proto_header_size; 2206 }; 2207 2208 /* 2209 * For each 16-bit word of the given header, override 2210 * bits enforced by the corresponding 16-bit mask. 2211 */ 2212 static void 2213 sfc_mae_header_force_item_masks(uint8_t *header_buf, 2214 const struct sfc_mae_parsed_item *parsed_items, 2215 unsigned int nb_parsed_items) 2216 { 2217 unsigned int item_idx; 2218 2219 for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) { 2220 const struct sfc_mae_parsed_item *parsed_item; 2221 const struct rte_flow_item *item; 2222 size_t proto_header_size; 2223 size_t ofst; 2224 2225 parsed_item = &parsed_items[item_idx]; 2226 proto_header_size = parsed_item->proto_header_size; 2227 item = parsed_item->item; 2228 2229 for (ofst = 0; ofst < proto_header_size; 2230 ofst += sizeof(rte_be16_t)) { 2231 rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst); 2232 const rte_be16_t *w_maskp; 2233 const rte_be16_t *w_specp; 2234 2235 w_maskp = RTE_PTR_ADD(item->mask, ofst); 2236 w_specp = RTE_PTR_ADD(item->spec, ofst); 2237 2238 *wp &= ~(*w_maskp); 2239 *wp |= (*w_specp & *w_maskp); 2240 } 2241 2242 header_buf += proto_header_size; 2243 } 2244 } 2245 2246 #define SFC_IPV4_TTL_DEF 0x40 2247 #define SFC_IPV6_VTC_FLOW_DEF 0x60000000 2248 #define SFC_IPV6_HOP_LIMITS_DEF 0xff 2249 #define SFC_VXLAN_FLAGS_DEF 0x08000000 2250 2251 static int 2252 sfc_mae_rule_parse_action_vxlan_encap( 2253 struct sfc_mae *mae, 2254 const struct rte_flow_action_vxlan_encap *conf, 2255 efx_mae_actions_t *spec, 2256 struct rte_flow_error *error) 2257 { 2258 struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh; 2259 struct rte_flow_item *pattern = conf->definition; 2260 uint8_t *buf = bounce_eh->buf; 2261 2262 /* This array will keep track of non-VOID pattern items. */ 2263 struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ + 2264 2 /* VLAN tags */ + 2265 1 /* IPv4 or IPv6 */ + 2266 1 /* UDP */ + 2267 1 /* VXLAN */]; 2268 unsigned int nb_parsed_items = 0; 2269 2270 size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type); 2271 uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr), 2272 sizeof(struct rte_ipv6_hdr))]; 2273 struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf; 2274 struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf; 2275 struct rte_vxlan_hdr *vxlan = NULL; 2276 struct rte_udp_hdr *udp = NULL; 2277 unsigned int nb_vlan_tags = 0; 2278 size_t next_proto_ofst = 0; 2279 size_t ethertype_ofst = 0; 2280 uint64_t exp_items; 2281 2282 if (pattern == NULL) { 2283 return rte_flow_error_set(error, EINVAL, 2284 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2285 "The encap. header definition is NULL"); 2286 } 2287 2288 bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN; 2289 bounce_eh->size = 0; 2290 2291 /* 2292 * Process pattern items and remember non-VOID ones. 2293 * Defer applying masks until after the complete header 2294 * has been built from the pattern items. 2295 */ 2296 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH); 2297 2298 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) { 2299 struct sfc_mae_parsed_item *parsed_item; 2300 const uint64_t exp_items_extra_vlan[] = { 2301 RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0 2302 }; 2303 size_t proto_header_size; 2304 rte_be16_t *ethertypep; 2305 uint8_t *next_protop; 2306 uint8_t *buf_cur; 2307 2308 if (pattern->spec == NULL) { 2309 return rte_flow_error_set(error, EINVAL, 2310 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2311 "NULL item spec in the encap. header"); 2312 } 2313 2314 if (pattern->mask == NULL) { 2315 return rte_flow_error_set(error, EINVAL, 2316 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2317 "NULL item mask in the encap. header"); 2318 } 2319 2320 if (pattern->last != NULL) { 2321 /* This is not a match pattern, so disallow range. */ 2322 return rte_flow_error_set(error, EINVAL, 2323 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2324 "Range item in the encap. header"); 2325 } 2326 2327 if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) { 2328 /* Handle VOID separately, for clarity. */ 2329 continue; 2330 } 2331 2332 if ((exp_items & RTE_BIT64(pattern->type)) == 0) { 2333 return rte_flow_error_set(error, ENOTSUP, 2334 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2335 "Unexpected item in the encap. header"); 2336 } 2337 2338 parsed_item = &parsed_items[nb_parsed_items]; 2339 buf_cur = buf + bounce_eh->size; 2340 2341 switch (pattern->type) { 2342 case RTE_FLOW_ITEM_TYPE_ETH: 2343 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH, 2344 exp_items); 2345 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth, 2346 hdr) != 0); 2347 2348 proto_header_size = sizeof(struct rte_ether_hdr); 2349 2350 ethertype_ofst = eth_ethertype_ofst; 2351 2352 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) | 2353 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) | 2354 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6); 2355 break; 2356 case RTE_FLOW_ITEM_TYPE_VLAN: 2357 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN, 2358 exp_items); 2359 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan, 2360 hdr) != 0); 2361 2362 proto_header_size = sizeof(struct rte_vlan_hdr); 2363 2364 ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst); 2365 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ); 2366 2367 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2368 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN); 2369 2370 ethertype_ofst = 2371 bounce_eh->size + 2372 offsetof(struct rte_vlan_hdr, eth_proto); 2373 2374 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) | 2375 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6); 2376 exp_items |= exp_items_extra_vlan[nb_vlan_tags]; 2377 2378 ++nb_vlan_tags; 2379 break; 2380 case RTE_FLOW_ITEM_TYPE_IPV4: 2381 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4, 2382 exp_items); 2383 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4, 2384 hdr) != 0); 2385 2386 proto_header_size = sizeof(struct rte_ipv4_hdr); 2387 2388 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2389 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4); 2390 2391 next_proto_ofst = 2392 bounce_eh->size + 2393 offsetof(struct rte_ipv4_hdr, next_proto_id); 2394 2395 ipv4 = (struct rte_ipv4_hdr *)buf_cur; 2396 2397 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP); 2398 break; 2399 case RTE_FLOW_ITEM_TYPE_IPV6: 2400 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6, 2401 exp_items); 2402 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6, 2403 hdr) != 0); 2404 2405 proto_header_size = sizeof(struct rte_ipv6_hdr); 2406 2407 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst); 2408 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6); 2409 2410 next_proto_ofst = bounce_eh->size + 2411 offsetof(struct rte_ipv6_hdr, proto); 2412 2413 ipv6 = (struct rte_ipv6_hdr *)buf_cur; 2414 2415 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP); 2416 break; 2417 case RTE_FLOW_ITEM_TYPE_UDP: 2418 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP, 2419 exp_items); 2420 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp, 2421 hdr) != 0); 2422 2423 proto_header_size = sizeof(struct rte_udp_hdr); 2424 2425 next_protop = RTE_PTR_ADD(buf, next_proto_ofst); 2426 *next_protop = IPPROTO_UDP; 2427 2428 udp = (struct rte_udp_hdr *)buf_cur; 2429 2430 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN); 2431 break; 2432 case RTE_FLOW_ITEM_TYPE_VXLAN: 2433 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN, 2434 exp_items); 2435 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan, 2436 hdr) != 0); 2437 2438 proto_header_size = sizeof(struct rte_vxlan_hdr); 2439 2440 vxlan = (struct rte_vxlan_hdr *)buf_cur; 2441 2442 udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT); 2443 udp->dgram_len = RTE_BE16(sizeof(*udp) + 2444 sizeof(*vxlan)); 2445 udp->dgram_cksum = 0; 2446 2447 exp_items = 0; 2448 break; 2449 default: 2450 return rte_flow_error_set(error, ENOTSUP, 2451 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2452 "Unknown item in the encap. header"); 2453 } 2454 2455 if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) { 2456 return rte_flow_error_set(error, E2BIG, 2457 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2458 "The encap. header is too big"); 2459 } 2460 2461 if ((proto_header_size & 1) != 0) { 2462 return rte_flow_error_set(error, EINVAL, 2463 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2464 "Odd layer size in the encap. header"); 2465 } 2466 2467 rte_memcpy(buf_cur, pattern->spec, proto_header_size); 2468 bounce_eh->size += proto_header_size; 2469 2470 parsed_item->item = pattern; 2471 parsed_item->proto_header_size = proto_header_size; 2472 ++nb_parsed_items; 2473 } 2474 2475 if (exp_items != 0) { 2476 /* Parsing item VXLAN would have reset exp_items to 0. */ 2477 return rte_flow_error_set(error, ENOTSUP, 2478 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2479 "No item VXLAN in the encap. header"); 2480 } 2481 2482 /* One of the pointers (ipv4, ipv6) refers to a dummy area. */ 2483 ipv4->version_ihl = RTE_IPV4_VHL_DEF; 2484 ipv4->time_to_live = SFC_IPV4_TTL_DEF; 2485 ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) + 2486 sizeof(*vxlan)); 2487 /* The HW cannot compute this checksum. */ 2488 ipv4->hdr_checksum = 0; 2489 ipv4->hdr_checksum = rte_ipv4_cksum(ipv4); 2490 2491 ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF); 2492 ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF; 2493 ipv6->payload_len = udp->dgram_len; 2494 2495 vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF); 2496 2497 /* Take care of the masks. */ 2498 sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items); 2499 2500 return (spec != NULL) ? efx_mae_action_set_populate_encap(spec) : 0; 2501 } 2502 2503 static int 2504 sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf, 2505 efx_mae_actions_t *spec) 2506 { 2507 return efx_mae_action_set_populate_mark(spec, conf->id); 2508 } 2509 2510 static int 2511 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa, 2512 const struct rte_flow_action_phy_port *conf, 2513 efx_mae_actions_t *spec) 2514 { 2515 efx_mport_sel_t mport; 2516 uint32_t phy_port; 2517 int rc; 2518 2519 if (conf->original != 0) 2520 phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port; 2521 else 2522 phy_port = conf->index; 2523 2524 rc = efx_mae_mport_by_phy_port(phy_port, &mport); 2525 if (rc != 0) 2526 return rc; 2527 2528 return efx_mae_action_set_populate_deliver(spec, &mport); 2529 } 2530 2531 static int 2532 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa, 2533 const struct rte_flow_action_vf *vf_conf, 2534 efx_mae_actions_t *spec) 2535 { 2536 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 2537 efx_mport_sel_t mport; 2538 uint32_t vf; 2539 int rc; 2540 2541 if (vf_conf == NULL) 2542 vf = EFX_PCI_VF_INVALID; 2543 else if (vf_conf->original != 0) 2544 vf = encp->enc_vf; 2545 else 2546 vf = vf_conf->id; 2547 2548 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport); 2549 if (rc != 0) 2550 return rc; 2551 2552 return efx_mae_action_set_populate_deliver(spec, &mport); 2553 } 2554 2555 static int 2556 sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa, 2557 const struct rte_flow_action_port_id *conf, 2558 efx_mae_actions_t *spec) 2559 { 2560 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); 2561 struct sfc_mae *mae = &sa->mae; 2562 efx_mport_sel_t mport; 2563 uint16_t port_id; 2564 int rc; 2565 2566 port_id = (conf->original != 0) ? sas->port_id : conf->id; 2567 2568 rc = sfc_mae_switch_port_by_ethdev(mae->switch_domain_id, 2569 port_id, &mport); 2570 if (rc != 0) 2571 return rc; 2572 2573 return efx_mae_action_set_populate_deliver(spec, &mport); 2574 } 2575 2576 static int 2577 sfc_mae_rule_parse_action(struct sfc_adapter *sa, 2578 const struct rte_flow_action *action, 2579 const struct sfc_mae_outer_rule *outer_rule, 2580 struct sfc_mae_actions_bundle *bundle, 2581 efx_mae_actions_t *spec, 2582 struct rte_flow_error *error) 2583 { 2584 bool custom_error = B_FALSE; 2585 int rc = 0; 2586 2587 switch (action->type) { 2588 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 2589 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, 2590 bundle->actions_mask); 2591 if (outer_rule == NULL || 2592 outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN) 2593 rc = EINVAL; 2594 else 2595 rc = efx_mae_action_set_populate_decap(spec); 2596 break; 2597 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 2598 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, 2599 bundle->actions_mask); 2600 rc = efx_mae_action_set_populate_vlan_pop(spec); 2601 break; 2602 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 2603 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, 2604 bundle->actions_mask); 2605 sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle); 2606 break; 2607 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 2608 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID, 2609 bundle->actions_mask); 2610 sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle); 2611 break; 2612 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 2613 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP, 2614 bundle->actions_mask); 2615 sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle); 2616 break; 2617 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 2618 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, 2619 bundle->actions_mask); 2620 rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae, 2621 action->conf, 2622 spec, error); 2623 custom_error = B_TRUE; 2624 break; 2625 case RTE_FLOW_ACTION_TYPE_FLAG: 2626 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG, 2627 bundle->actions_mask); 2628 rc = efx_mae_action_set_populate_flag(spec); 2629 break; 2630 case RTE_FLOW_ACTION_TYPE_MARK: 2631 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK, 2632 bundle->actions_mask); 2633 rc = sfc_mae_rule_parse_action_mark(action->conf, spec); 2634 break; 2635 case RTE_FLOW_ACTION_TYPE_PHY_PORT: 2636 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT, 2637 bundle->actions_mask); 2638 rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec); 2639 break; 2640 case RTE_FLOW_ACTION_TYPE_PF: 2641 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF, 2642 bundle->actions_mask); 2643 rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec); 2644 break; 2645 case RTE_FLOW_ACTION_TYPE_VF: 2646 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF, 2647 bundle->actions_mask); 2648 rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec); 2649 break; 2650 case RTE_FLOW_ACTION_TYPE_PORT_ID: 2651 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID, 2652 bundle->actions_mask); 2653 rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec); 2654 break; 2655 case RTE_FLOW_ACTION_TYPE_DROP: 2656 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP, 2657 bundle->actions_mask); 2658 rc = efx_mae_action_set_populate_drop(spec); 2659 break; 2660 default: 2661 return rte_flow_error_set(error, ENOTSUP, 2662 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2663 "Unsupported action"); 2664 } 2665 2666 if (rc == 0) { 2667 bundle->actions_mask |= (1ULL << action->type); 2668 } else if (!custom_error) { 2669 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, 2670 NULL, "Failed to request the action"); 2671 } 2672 2673 return rc; 2674 } 2675 2676 static void 2677 sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh) 2678 { 2679 bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE; 2680 } 2681 2682 static int 2683 sfc_mae_process_encap_header(struct sfc_adapter *sa, 2684 const struct sfc_mae_bounce_eh *bounce_eh, 2685 struct sfc_mae_encap_header **encap_headerp) 2686 { 2687 if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) { 2688 encap_headerp = NULL; 2689 return 0; 2690 } 2691 2692 *encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh); 2693 if (*encap_headerp != NULL) 2694 return 0; 2695 2696 return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp); 2697 } 2698 2699 int 2700 sfc_mae_rule_parse_actions(struct sfc_adapter *sa, 2701 const struct rte_flow_action actions[], 2702 struct sfc_flow_spec_mae *spec_mae, 2703 struct rte_flow_error *error) 2704 { 2705 struct sfc_mae_encap_header *encap_header = NULL; 2706 struct sfc_mae_actions_bundle bundle = {0}; 2707 const struct rte_flow_action *action; 2708 struct sfc_mae *mae = &sa->mae; 2709 efx_mae_actions_t *spec; 2710 int rc; 2711 2712 rte_errno = 0; 2713 2714 if (actions == NULL) { 2715 return rte_flow_error_set(error, EINVAL, 2716 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL, 2717 "NULL actions"); 2718 } 2719 2720 rc = efx_mae_action_set_spec_init(sa->nic, &spec); 2721 if (rc != 0) 2722 goto fail_action_set_spec_init; 2723 2724 /* Cleanup after previous encap. header bounce buffer usage. */ 2725 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh); 2726 2727 for (action = actions; 2728 action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { 2729 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); 2730 if (rc != 0) 2731 goto fail_rule_parse_action; 2732 2733 rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule, 2734 &bundle, spec, error); 2735 if (rc != 0) 2736 goto fail_rule_parse_action; 2737 } 2738 2739 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); 2740 if (rc != 0) 2741 goto fail_rule_parse_action; 2742 2743 rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header); 2744 if (rc != 0) 2745 goto fail_process_encap_header; 2746 2747 spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header, 2748 spec); 2749 if (spec_mae->action_set != NULL) { 2750 sfc_mae_encap_header_del(sa, encap_header); 2751 efx_mae_action_set_spec_fini(sa->nic, spec); 2752 return 0; 2753 } 2754 2755 rc = sfc_mae_action_set_add(sa, spec, encap_header, 2756 &spec_mae->action_set); 2757 if (rc != 0) 2758 goto fail_action_set_add; 2759 2760 return 0; 2761 2762 fail_action_set_add: 2763 sfc_mae_encap_header_del(sa, encap_header); 2764 2765 fail_process_encap_header: 2766 fail_rule_parse_action: 2767 efx_mae_action_set_spec_fini(sa->nic, spec); 2768 2769 fail_action_set_spec_init: 2770 if (rc > 0 && rte_errno == 0) { 2771 rc = rte_flow_error_set(error, rc, 2772 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2773 NULL, "Failed to process the action"); 2774 } 2775 return rc; 2776 } 2777 2778 static bool 2779 sfc_mae_rules_class_cmp(struct sfc_adapter *sa, 2780 const efx_mae_match_spec_t *left, 2781 const efx_mae_match_spec_t *right) 2782 { 2783 bool have_same_class; 2784 int rc; 2785 2786 rc = efx_mae_match_specs_class_cmp(sa->nic, left, right, 2787 &have_same_class); 2788 2789 return (rc == 0) ? have_same_class : false; 2790 } 2791 2792 static int 2793 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa, 2794 struct sfc_mae_outer_rule *rule) 2795 { 2796 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc; 2797 struct sfc_mae_outer_rule *entry; 2798 struct sfc_mae *mae = &sa->mae; 2799 2800 if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) { 2801 /* An active rule is reused. It's class is wittingly valid. */ 2802 return 0; 2803 } 2804 2805 TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules, 2806 sfc_mae_outer_rules, entries) { 2807 const efx_mae_match_spec_t *left = entry->match_spec; 2808 const efx_mae_match_spec_t *right = rule->match_spec; 2809 2810 if (entry == rule) 2811 continue; 2812 2813 if (sfc_mae_rules_class_cmp(sa, left, right)) 2814 return 0; 2815 } 2816 2817 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW " 2818 "support for outer frame pattern items is not guaranteed; " 2819 "other than that, the items are valid from SW standpoint"); 2820 return 0; 2821 } 2822 2823 static int 2824 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa, 2825 struct sfc_flow_spec_mae *spec) 2826 { 2827 const struct rte_flow *entry; 2828 2829 TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) { 2830 const struct sfc_flow_spec *entry_spec = &entry->spec; 2831 const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae; 2832 const efx_mae_match_spec_t *left = es_mae->match_spec; 2833 const efx_mae_match_spec_t *right = spec->match_spec; 2834 2835 switch (entry_spec->type) { 2836 case SFC_FLOW_SPEC_FILTER: 2837 /* Ignore VNIC-level flows */ 2838 break; 2839 case SFC_FLOW_SPEC_MAE: 2840 if (sfc_mae_rules_class_cmp(sa, left, right)) 2841 return 0; 2842 break; 2843 default: 2844 SFC_ASSERT(false); 2845 } 2846 } 2847 2848 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW " 2849 "support for inner frame pattern items is not guaranteed; " 2850 "other than that, the items are valid from SW standpoint"); 2851 return 0; 2852 } 2853 2854 /** 2855 * Confirm that a given flow can be accepted by the FW. 2856 * 2857 * @param sa 2858 * Software adapter context 2859 * @param flow 2860 * Flow to be verified 2861 * @return 2862 * Zero on success and non-zero in the case of error. 2863 * A special value of EAGAIN indicates that the adapter is 2864 * not in started state. This state is compulsory because 2865 * it only makes sense to compare the rule class of the flow 2866 * being validated with classes of the active rules. 2867 * Such classes are wittingly supported by the FW. 2868 */ 2869 int 2870 sfc_mae_flow_verify(struct sfc_adapter *sa, 2871 struct rte_flow *flow) 2872 { 2873 struct sfc_flow_spec *spec = &flow->spec; 2874 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 2875 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 2876 int rc; 2877 2878 SFC_ASSERT(sfc_adapter_is_locked(sa)); 2879 2880 if (sa->state != SFC_ADAPTER_STARTED) 2881 return EAGAIN; 2882 2883 if (outer_rule != NULL) { 2884 rc = sfc_mae_outer_rule_class_verify(sa, outer_rule); 2885 if (rc != 0) 2886 return rc; 2887 } 2888 2889 return sfc_mae_action_rule_class_verify(sa, spec_mae); 2890 } 2891 2892 int 2893 sfc_mae_flow_insert(struct sfc_adapter *sa, 2894 struct rte_flow *flow) 2895 { 2896 struct sfc_flow_spec *spec = &flow->spec; 2897 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 2898 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 2899 struct sfc_mae_action_set *action_set = spec_mae->action_set; 2900 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc; 2901 int rc; 2902 2903 SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID); 2904 SFC_ASSERT(action_set != NULL); 2905 2906 if (outer_rule != NULL) { 2907 rc = sfc_mae_outer_rule_enable(sa, outer_rule, 2908 spec_mae->match_spec); 2909 if (rc != 0) 2910 goto fail_outer_rule_enable; 2911 } 2912 2913 rc = sfc_mae_action_set_enable(sa, action_set); 2914 if (rc != 0) 2915 goto fail_action_set_enable; 2916 2917 rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec, 2918 NULL, &fw_rsrc->aset_id, 2919 &spec_mae->rule_id); 2920 if (rc != 0) 2921 goto fail_action_rule_insert; 2922 2923 sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x", 2924 flow, spec_mae->rule_id.id); 2925 2926 return 0; 2927 2928 fail_action_rule_insert: 2929 sfc_mae_action_set_disable(sa, action_set); 2930 2931 fail_action_set_enable: 2932 if (outer_rule != NULL) 2933 sfc_mae_outer_rule_disable(sa, outer_rule); 2934 2935 fail_outer_rule_enable: 2936 return rc; 2937 } 2938 2939 int 2940 sfc_mae_flow_remove(struct sfc_adapter *sa, 2941 struct rte_flow *flow) 2942 { 2943 struct sfc_flow_spec *spec = &flow->spec; 2944 struct sfc_flow_spec_mae *spec_mae = &spec->mae; 2945 struct sfc_mae_action_set *action_set = spec_mae->action_set; 2946 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule; 2947 int rc; 2948 2949 SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID); 2950 SFC_ASSERT(action_set != NULL); 2951 2952 rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id); 2953 if (rc != 0) { 2954 sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s", 2955 flow, spec_mae->rule_id.id, strerror(rc)); 2956 } 2957 sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x", 2958 flow, spec_mae->rule_id.id); 2959 spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID; 2960 2961 sfc_mae_action_set_disable(sa, action_set); 2962 2963 if (outer_rule != NULL) 2964 sfc_mae_outer_rule_disable(sa, outer_rule); 2965 2966 return 0; 2967 } 2968