1 /*- 2 * Copyright (c) 2017 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * This software was jointly developed between OKTET Labs (under contract 6 * for Solarflare) and Solarflare Communications, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <rte_tailq.h> 31 #include <rte_common.h> 32 #include <rte_ethdev.h> 33 #include <rte_eth_ctrl.h> 34 #include <rte_ether.h> 35 #include <rte_flow.h> 36 #include <rte_flow_driver.h> 37 38 #include "efx.h" 39 40 #include "sfc.h" 41 #include "sfc_rx.h" 42 #include "sfc_filter.h" 43 #include "sfc_flow.h" 44 #include "sfc_log.h" 45 46 /* 47 * At now flow API is implemented in such a manner that each 48 * flow rule is converted to a hardware filter. 49 * All elements of flow rule (attributes, pattern items, actions) 50 * correspond to one or more fields in the efx_filter_spec_s structure 51 * that is responsible for the hardware filter. 52 */ 53 54 enum sfc_flow_item_layers { 55 SFC_FLOW_ITEM_ANY_LAYER, 56 SFC_FLOW_ITEM_START_LAYER, 57 SFC_FLOW_ITEM_L2, 58 }; 59 60 typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item, 61 efx_filter_spec_t *spec, 62 struct rte_flow_error *error); 63 64 struct sfc_flow_item { 65 enum rte_flow_item_type type; /* Type of item */ 66 enum sfc_flow_item_layers layer; /* Layer of item */ 67 enum sfc_flow_item_layers prev_layer; /* Previous layer of item */ 68 sfc_flow_item_parse *parse; /* Parsing function */ 69 }; 70 71 static sfc_flow_item_parse sfc_flow_parse_void; 72 static sfc_flow_item_parse sfc_flow_parse_eth; 73 static sfc_flow_item_parse sfc_flow_parse_vlan; 74 75 static boolean_t 76 sfc_flow_is_zero(const uint8_t *buf, unsigned int size) 77 { 78 uint8_t sum = 0; 79 unsigned int i; 80 81 for (i = 0; i < size; i++) 82 sum |= buf[i]; 83 84 return (sum == 0) ? B_TRUE : B_FALSE; 85 } 86 87 /* 88 * Validate item and prepare structures spec and mask for parsing 89 */ 90 static int 91 sfc_flow_parse_init(const struct rte_flow_item *item, 92 const void **spec_ptr, 93 const void **mask_ptr, 94 const void *supp_mask, 95 const void *def_mask, 96 unsigned int size, 97 struct rte_flow_error *error) 98 { 99 const uint8_t *spec; 100 const uint8_t *mask; 101 const uint8_t *last; 102 uint8_t match; 103 uint8_t supp; 104 unsigned int i; 105 106 if (item == NULL) { 107 rte_flow_error_set(error, EINVAL, 108 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 109 "NULL item"); 110 return -rte_errno; 111 } 112 113 if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) { 114 rte_flow_error_set(error, EINVAL, 115 RTE_FLOW_ERROR_TYPE_ITEM, item, 116 "Mask or last is set without spec"); 117 return -rte_errno; 118 } 119 120 /* 121 * If "mask" is not set, default mask is used, 122 * but if default mask is NULL, "mask" should be set 123 */ 124 if (item->mask == NULL) { 125 if (def_mask == NULL) { 126 rte_flow_error_set(error, EINVAL, 127 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 128 "Mask should be specified"); 129 return -rte_errno; 130 } 131 132 mask = (const uint8_t *)def_mask; 133 } else { 134 mask = (const uint8_t *)item->mask; 135 } 136 137 spec = (const uint8_t *)item->spec; 138 last = (const uint8_t *)item->last; 139 140 if (spec == NULL) 141 goto exit; 142 143 /* 144 * If field values in "last" are either 0 or equal to the corresponding 145 * values in "spec" then they are ignored 146 */ 147 if (last != NULL && 148 !sfc_flow_is_zero(last, size) && 149 memcmp(last, spec, size) != 0) { 150 rte_flow_error_set(error, ENOTSUP, 151 RTE_FLOW_ERROR_TYPE_ITEM, item, 152 "Ranging is not supported"); 153 return -rte_errno; 154 } 155 156 if (supp_mask == NULL) { 157 rte_flow_error_set(error, EINVAL, 158 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 159 "Supported mask for item should be specified"); 160 return -rte_errno; 161 } 162 163 /* Check that mask and spec not asks for more match than supp_mask */ 164 for (i = 0; i < size; i++) { 165 match = spec[i] | mask[i]; 166 supp = ((const uint8_t *)supp_mask)[i]; 167 168 if ((match | supp) != supp) { 169 rte_flow_error_set(error, ENOTSUP, 170 RTE_FLOW_ERROR_TYPE_ITEM, item, 171 "Item's field is not supported"); 172 return -rte_errno; 173 } 174 } 175 176 exit: 177 *spec_ptr = spec; 178 *mask_ptr = mask; 179 return 0; 180 } 181 182 /* 183 * Protocol parsers. 184 * Masking is not supported, so masks in items should be either 185 * full or empty (zeroed) and set only for supported fields which 186 * are specified in the supp_mask. 187 */ 188 189 static int 190 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, 191 __rte_unused efx_filter_spec_t *efx_spec, 192 __rte_unused struct rte_flow_error *error) 193 { 194 return 0; 195 } 196 197 /** 198 * Convert Ethernet item to EFX filter specification. 199 * 200 * @param item[in] 201 * Item specification. Only source and destination addresses and 202 * Ethernet type fields are supported. If the mask is NULL, default 203 * mask will be used. Ranging is not supported. 204 * @param efx_spec[in, out] 205 * EFX filter specification to update. 206 * @param[out] error 207 * Perform verbose error reporting if not NULL. 208 */ 209 static int 210 sfc_flow_parse_eth(const struct rte_flow_item *item, 211 efx_filter_spec_t *efx_spec, 212 struct rte_flow_error *error) 213 { 214 int rc; 215 const struct rte_flow_item_eth *spec = NULL; 216 const struct rte_flow_item_eth *mask = NULL; 217 const struct rte_flow_item_eth supp_mask = { 218 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 219 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 220 .type = 0xffff, 221 }; 222 223 rc = sfc_flow_parse_init(item, 224 (const void **)&spec, 225 (const void **)&mask, 226 &supp_mask, 227 &rte_flow_item_eth_mask, 228 sizeof(struct rte_flow_item_eth), 229 error); 230 if (rc != 0) 231 return rc; 232 233 /* If "spec" is not set, could be any Ethernet */ 234 if (spec == NULL) 235 return 0; 236 237 if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { 238 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; 239 rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes, 240 EFX_MAC_ADDR_LEN); 241 } else if (!is_zero_ether_addr(&mask->dst)) { 242 goto fail_bad_mask; 243 } 244 245 if (is_same_ether_addr(&mask->src, &supp_mask.src)) { 246 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC; 247 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes, 248 EFX_MAC_ADDR_LEN); 249 } else if (!is_zero_ether_addr(&mask->src)) { 250 goto fail_bad_mask; 251 } 252 253 /* 254 * Ether type is in big-endian byte order in item and 255 * in little-endian in efx_spec, so byte swap is used 256 */ 257 if (mask->type == supp_mask.type) { 258 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; 259 efx_spec->efs_ether_type = rte_bswap16(spec->type); 260 } else if (mask->type != 0) { 261 goto fail_bad_mask; 262 } 263 264 return 0; 265 266 fail_bad_mask: 267 rte_flow_error_set(error, EINVAL, 268 RTE_FLOW_ERROR_TYPE_ITEM, item, 269 "Bad mask in the ETH pattern item"); 270 return -rte_errno; 271 } 272 273 /** 274 * Convert VLAN item to EFX filter specification. 275 * 276 * @param item[in] 277 * Item specification. Only VID field is supported. 278 * The mask can not be NULL. Ranging is not supported. 279 * @param efx_spec[in, out] 280 * EFX filter specification to update. 281 * @param[out] error 282 * Perform verbose error reporting if not NULL. 283 */ 284 static int 285 sfc_flow_parse_vlan(const struct rte_flow_item *item, 286 efx_filter_spec_t *efx_spec, 287 struct rte_flow_error *error) 288 { 289 int rc; 290 uint16_t vid; 291 const struct rte_flow_item_vlan *spec = NULL; 292 const struct rte_flow_item_vlan *mask = NULL; 293 const struct rte_flow_item_vlan supp_mask = { 294 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX), 295 }; 296 297 rc = sfc_flow_parse_init(item, 298 (const void **)&spec, 299 (const void **)&mask, 300 &supp_mask, 301 NULL, 302 sizeof(struct rte_flow_item_vlan), 303 error); 304 if (rc != 0) 305 return rc; 306 307 /* 308 * VID is in big-endian byte order in item and 309 * in little-endian in efx_spec, so byte swap is used. 310 * If two VLAN items are included, the first matches 311 * the outer tag and the next matches the inner tag. 312 */ 313 if (mask->tci == supp_mask.tci) { 314 vid = rte_bswap16(spec->tci); 315 316 if (!(efx_spec->efs_match_flags & 317 EFX_FILTER_MATCH_OUTER_VID)) { 318 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID; 319 efx_spec->efs_outer_vid = vid; 320 } else if (!(efx_spec->efs_match_flags & 321 EFX_FILTER_MATCH_INNER_VID)) { 322 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID; 323 efx_spec->efs_inner_vid = vid; 324 } else { 325 rte_flow_error_set(error, EINVAL, 326 RTE_FLOW_ERROR_TYPE_ITEM, item, 327 "More than two VLAN items"); 328 return -rte_errno; 329 } 330 } else { 331 rte_flow_error_set(error, EINVAL, 332 RTE_FLOW_ERROR_TYPE_ITEM, item, 333 "VLAN ID in TCI match is required"); 334 return -rte_errno; 335 } 336 337 return 0; 338 } 339 340 static const struct sfc_flow_item sfc_flow_items[] = { 341 { 342 .type = RTE_FLOW_ITEM_TYPE_VOID, 343 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 344 .layer = SFC_FLOW_ITEM_ANY_LAYER, 345 .parse = sfc_flow_parse_void, 346 }, 347 { 348 .type = RTE_FLOW_ITEM_TYPE_ETH, 349 .prev_layer = SFC_FLOW_ITEM_START_LAYER, 350 .layer = SFC_FLOW_ITEM_L2, 351 .parse = sfc_flow_parse_eth, 352 }, 353 { 354 .type = RTE_FLOW_ITEM_TYPE_VLAN, 355 .prev_layer = SFC_FLOW_ITEM_L2, 356 .layer = SFC_FLOW_ITEM_L2, 357 .parse = sfc_flow_parse_vlan, 358 }, 359 }; 360 361 /* 362 * Protocol-independent flow API support 363 */ 364 static int 365 sfc_flow_parse_attr(const struct rte_flow_attr *attr, 366 struct rte_flow *flow, 367 struct rte_flow_error *error) 368 { 369 if (attr == NULL) { 370 rte_flow_error_set(error, EINVAL, 371 RTE_FLOW_ERROR_TYPE_ATTR, NULL, 372 "NULL attribute"); 373 return -rte_errno; 374 } 375 if (attr->group != 0) { 376 rte_flow_error_set(error, ENOTSUP, 377 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr, 378 "Groups are not supported"); 379 return -rte_errno; 380 } 381 if (attr->priority != 0) { 382 rte_flow_error_set(error, ENOTSUP, 383 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr, 384 "Priorities are not supported"); 385 return -rte_errno; 386 } 387 if (attr->egress != 0) { 388 rte_flow_error_set(error, ENOTSUP, 389 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr, 390 "Egress is not supported"); 391 return -rte_errno; 392 } 393 if (attr->ingress == 0) { 394 rte_flow_error_set(error, ENOTSUP, 395 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr, 396 "Only ingress is supported"); 397 return -rte_errno; 398 } 399 400 flow->spec.efs_flags |= EFX_FILTER_FLAG_RX; 401 flow->spec.efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT; 402 403 return 0; 404 } 405 406 /* Get item from array sfc_flow_items */ 407 static const struct sfc_flow_item * 408 sfc_flow_get_item(enum rte_flow_item_type type) 409 { 410 unsigned int i; 411 412 for (i = 0; i < RTE_DIM(sfc_flow_items); i++) 413 if (sfc_flow_items[i].type == type) 414 return &sfc_flow_items[i]; 415 416 return NULL; 417 } 418 419 static int 420 sfc_flow_parse_pattern(const struct rte_flow_item pattern[], 421 struct rte_flow *flow, 422 struct rte_flow_error *error) 423 { 424 int rc; 425 unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER; 426 const struct sfc_flow_item *item; 427 428 if (pattern == NULL) { 429 rte_flow_error_set(error, EINVAL, 430 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL, 431 "NULL pattern"); 432 return -rte_errno; 433 } 434 435 for (; pattern != NULL && 436 pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { 437 item = sfc_flow_get_item(pattern->type); 438 if (item == NULL) { 439 rte_flow_error_set(error, ENOTSUP, 440 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 441 "Unsupported pattern item"); 442 return -rte_errno; 443 } 444 445 /* 446 * Omitting one or several protocol layers at the beginning 447 * of pattern is supported 448 */ 449 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 450 prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 451 item->prev_layer != prev_layer) { 452 rte_flow_error_set(error, ENOTSUP, 453 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 454 "Unexpected sequence of pattern items"); 455 return -rte_errno; 456 } 457 458 rc = item->parse(pattern, &flow->spec, error); 459 if (rc != 0) 460 return rc; 461 462 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER) 463 prev_layer = item->layer; 464 } 465 466 if (pattern == NULL) { 467 rte_flow_error_set(error, EINVAL, 468 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 469 "NULL item"); 470 return -rte_errno; 471 } 472 473 return 0; 474 } 475 476 static int 477 sfc_flow_parse_queue(struct sfc_adapter *sa, 478 const struct rte_flow_action_queue *queue, 479 struct rte_flow *flow) 480 { 481 struct sfc_rxq *rxq; 482 483 if (queue->index >= sa->rxq_count) 484 return -EINVAL; 485 486 rxq = sa->rxq_info[queue->index].rxq; 487 flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; 488 489 return 0; 490 } 491 492 static int 493 sfc_flow_parse_actions(struct sfc_adapter *sa, 494 const struct rte_flow_action actions[], 495 struct rte_flow *flow, 496 struct rte_flow_error *error) 497 { 498 int rc; 499 boolean_t is_specified = B_FALSE; 500 501 if (actions == NULL) { 502 rte_flow_error_set(error, EINVAL, 503 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL, 504 "NULL actions"); 505 return -rte_errno; 506 } 507 508 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 509 switch (actions->type) { 510 case RTE_FLOW_ACTION_TYPE_VOID: 511 break; 512 513 case RTE_FLOW_ACTION_TYPE_QUEUE: 514 rc = sfc_flow_parse_queue(sa, actions->conf, flow); 515 if (rc != 0) { 516 rte_flow_error_set(error, EINVAL, 517 RTE_FLOW_ERROR_TYPE_ACTION, actions, 518 "Bad QUEUE action"); 519 return -rte_errno; 520 } 521 522 is_specified = B_TRUE; 523 break; 524 525 default: 526 rte_flow_error_set(error, ENOTSUP, 527 RTE_FLOW_ERROR_TYPE_ACTION, actions, 528 "Action is not supported"); 529 return -rte_errno; 530 } 531 } 532 533 if (!is_specified) { 534 rte_flow_error_set(error, EINVAL, 535 RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions, 536 "Action is unspecified"); 537 return -rte_errno; 538 } 539 540 return 0; 541 } 542 543 static int 544 sfc_flow_parse(struct rte_eth_dev *dev, 545 const struct rte_flow_attr *attr, 546 const struct rte_flow_item pattern[], 547 const struct rte_flow_action actions[], 548 struct rte_flow *flow, 549 struct rte_flow_error *error) 550 { 551 struct sfc_adapter *sa = dev->data->dev_private; 552 int rc; 553 554 memset(&flow->spec, 0, sizeof(flow->spec)); 555 556 rc = sfc_flow_parse_attr(attr, flow, error); 557 if (rc != 0) 558 goto fail_bad_value; 559 560 rc = sfc_flow_parse_pattern(pattern, flow, error); 561 if (rc != 0) 562 goto fail_bad_value; 563 564 rc = sfc_flow_parse_actions(sa, actions, flow, error); 565 if (rc != 0) 566 goto fail_bad_value; 567 568 if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { 569 rte_flow_error_set(error, ENOTSUP, 570 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 571 "Flow rule pattern is not supported"); 572 return -rte_errno; 573 } 574 575 fail_bad_value: 576 return rc; 577 } 578 579 static int 580 sfc_flow_validate(struct rte_eth_dev *dev, 581 const struct rte_flow_attr *attr, 582 const struct rte_flow_item pattern[], 583 const struct rte_flow_action actions[], 584 struct rte_flow_error *error) 585 { 586 struct rte_flow flow; 587 588 return sfc_flow_parse(dev, attr, pattern, actions, &flow, error); 589 } 590 591 static struct rte_flow * 592 sfc_flow_create(struct rte_eth_dev *dev, 593 const struct rte_flow_attr *attr, 594 const struct rte_flow_item pattern[], 595 const struct rte_flow_action actions[], 596 struct rte_flow_error *error) 597 { 598 struct sfc_adapter *sa = dev->data->dev_private; 599 struct rte_flow *flow = NULL; 600 int rc; 601 602 flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0); 603 if (flow == NULL) { 604 rte_flow_error_set(error, ENOMEM, 605 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 606 "Failed to allocate memory"); 607 goto fail_no_mem; 608 } 609 610 rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error); 611 if (rc != 0) 612 goto fail_bad_value; 613 614 TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries); 615 616 sfc_adapter_lock(sa); 617 618 if (sa->state == SFC_ADAPTER_STARTED) { 619 rc = efx_filter_insert(sa->nic, &flow->spec); 620 if (rc != 0) { 621 rte_flow_error_set(error, rc, 622 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 623 "Failed to insert filter"); 624 goto fail_filter_insert; 625 } 626 } 627 628 sfc_adapter_unlock(sa); 629 630 return flow; 631 632 fail_filter_insert: 633 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 634 635 fail_bad_value: 636 rte_free(flow); 637 sfc_adapter_unlock(sa); 638 639 fail_no_mem: 640 return NULL; 641 } 642 643 static int 644 sfc_flow_remove(struct sfc_adapter *sa, 645 struct rte_flow *flow, 646 struct rte_flow_error *error) 647 { 648 int rc = 0; 649 650 SFC_ASSERT(sfc_adapter_is_locked(sa)); 651 652 if (sa->state == SFC_ADAPTER_STARTED) { 653 rc = efx_filter_remove(sa->nic, &flow->spec); 654 if (rc != 0) 655 rte_flow_error_set(error, rc, 656 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 657 "Failed to destroy flow rule"); 658 } 659 660 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 661 rte_free(flow); 662 663 return rc; 664 } 665 666 static int 667 sfc_flow_destroy(struct rte_eth_dev *dev, 668 struct rte_flow *flow, 669 struct rte_flow_error *error) 670 { 671 struct sfc_adapter *sa = dev->data->dev_private; 672 struct rte_flow *flow_ptr; 673 int rc = EINVAL; 674 675 sfc_adapter_lock(sa); 676 677 TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) { 678 if (flow_ptr == flow) 679 rc = 0; 680 } 681 if (rc != 0) { 682 rte_flow_error_set(error, rc, 683 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 684 "Failed to find flow rule to destroy"); 685 goto fail_bad_value; 686 } 687 688 rc = sfc_flow_remove(sa, flow, error); 689 690 fail_bad_value: 691 sfc_adapter_unlock(sa); 692 693 return -rc; 694 } 695 696 static int 697 sfc_flow_flush(struct rte_eth_dev *dev, 698 struct rte_flow_error *error) 699 { 700 struct sfc_adapter *sa = dev->data->dev_private; 701 struct rte_flow *flow; 702 int rc = 0; 703 int ret = 0; 704 705 sfc_adapter_lock(sa); 706 707 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 708 rc = sfc_flow_remove(sa, flow, error); 709 if (rc != 0) 710 ret = rc; 711 } 712 713 sfc_adapter_unlock(sa); 714 715 return -ret; 716 } 717 718 const struct rte_flow_ops sfc_flow_ops = { 719 .validate = sfc_flow_validate, 720 .create = sfc_flow_create, 721 .destroy = sfc_flow_destroy, 722 .flush = sfc_flow_flush, 723 .query = NULL, 724 }; 725 726 void 727 sfc_flow_init(struct sfc_adapter *sa) 728 { 729 SFC_ASSERT(sfc_adapter_is_locked(sa)); 730 731 TAILQ_INIT(&sa->filter.flow_list); 732 } 733 734 void 735 sfc_flow_fini(struct sfc_adapter *sa) 736 { 737 struct rte_flow *flow; 738 739 SFC_ASSERT(sfc_adapter_is_locked(sa)); 740 741 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 742 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 743 rte_free(flow); 744 } 745 } 746 747 void 748 sfc_flow_stop(struct sfc_adapter *sa) 749 { 750 struct rte_flow *flow; 751 752 SFC_ASSERT(sfc_adapter_is_locked(sa)); 753 754 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) 755 efx_filter_remove(sa->nic, &flow->spec); 756 } 757 758 int 759 sfc_flow_start(struct sfc_adapter *sa) 760 { 761 struct rte_flow *flow; 762 int rc = 0; 763 764 sfc_log_init(sa, "entry"); 765 766 SFC_ASSERT(sfc_adapter_is_locked(sa)); 767 768 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) { 769 rc = efx_filter_insert(sa->nic, &flow->spec); 770 if (rc != 0) 771 goto fail_bad_flow; 772 } 773 774 sfc_log_init(sa, "done"); 775 776 fail_bad_flow: 777 return rc; 778 } 779