1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) 2017 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * This software was jointly developed between OKTET Labs (under contract 8 * for Solarflare) and Solarflare Communications, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <rte_tailq.h> 33 #include <rte_common.h> 34 #include <rte_ethdev.h> 35 #include <rte_eth_ctrl.h> 36 #include <rte_ether.h> 37 #include <rte_flow.h> 38 #include <rte_flow_driver.h> 39 40 #include "efx.h" 41 42 #include "sfc.h" 43 #include "sfc_rx.h" 44 #include "sfc_filter.h" 45 #include "sfc_flow.h" 46 #include "sfc_log.h" 47 48 /* 49 * At now flow API is implemented in such a manner that each 50 * flow rule is converted to a hardware filter. 51 * All elements of flow rule (attributes, pattern items, actions) 52 * correspond to one or more fields in the efx_filter_spec_s structure 53 * that is responsible for the hardware filter. 54 */ 55 56 enum sfc_flow_item_layers { 57 SFC_FLOW_ITEM_ANY_LAYER, 58 SFC_FLOW_ITEM_START_LAYER, 59 SFC_FLOW_ITEM_L2, 60 SFC_FLOW_ITEM_L3, 61 SFC_FLOW_ITEM_L4, 62 }; 63 64 typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item, 65 efx_filter_spec_t *spec, 66 struct rte_flow_error *error); 67 68 struct sfc_flow_item { 69 enum rte_flow_item_type type; /* Type of item */ 70 enum sfc_flow_item_layers layer; /* Layer of item */ 71 enum sfc_flow_item_layers prev_layer; /* Previous layer of item */ 72 sfc_flow_item_parse *parse; /* Parsing function */ 73 }; 74 75 static sfc_flow_item_parse sfc_flow_parse_void; 76 static sfc_flow_item_parse sfc_flow_parse_eth; 77 static sfc_flow_item_parse sfc_flow_parse_vlan; 78 static sfc_flow_item_parse sfc_flow_parse_ipv4; 79 static sfc_flow_item_parse sfc_flow_parse_ipv6; 80 static sfc_flow_item_parse sfc_flow_parse_tcp; 81 static sfc_flow_item_parse sfc_flow_parse_udp; 82 83 static boolean_t 84 sfc_flow_is_zero(const uint8_t *buf, unsigned int size) 85 { 86 uint8_t sum = 0; 87 unsigned int i; 88 89 for (i = 0; i < size; i++) 90 sum |= buf[i]; 91 92 return (sum == 0) ? B_TRUE : B_FALSE; 93 } 94 95 /* 96 * Validate item and prepare structures spec and mask for parsing 97 */ 98 static int 99 sfc_flow_parse_init(const struct rte_flow_item *item, 100 const void **spec_ptr, 101 const void **mask_ptr, 102 const void *supp_mask, 103 const void *def_mask, 104 unsigned int size, 105 struct rte_flow_error *error) 106 { 107 const uint8_t *spec; 108 const uint8_t *mask; 109 const uint8_t *last; 110 uint8_t match; 111 uint8_t supp; 112 unsigned int i; 113 114 if (item == NULL) { 115 rte_flow_error_set(error, EINVAL, 116 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 117 "NULL item"); 118 return -rte_errno; 119 } 120 121 if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) { 122 rte_flow_error_set(error, EINVAL, 123 RTE_FLOW_ERROR_TYPE_ITEM, item, 124 "Mask or last is set without spec"); 125 return -rte_errno; 126 } 127 128 /* 129 * If "mask" is not set, default mask is used, 130 * but if default mask is NULL, "mask" should be set 131 */ 132 if (item->mask == NULL) { 133 if (def_mask == NULL) { 134 rte_flow_error_set(error, EINVAL, 135 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 136 "Mask should be specified"); 137 return -rte_errno; 138 } 139 140 mask = (const uint8_t *)def_mask; 141 } else { 142 mask = (const uint8_t *)item->mask; 143 } 144 145 spec = (const uint8_t *)item->spec; 146 last = (const uint8_t *)item->last; 147 148 if (spec == NULL) 149 goto exit; 150 151 /* 152 * If field values in "last" are either 0 or equal to the corresponding 153 * values in "spec" then they are ignored 154 */ 155 if (last != NULL && 156 !sfc_flow_is_zero(last, size) && 157 memcmp(last, spec, size) != 0) { 158 rte_flow_error_set(error, ENOTSUP, 159 RTE_FLOW_ERROR_TYPE_ITEM, item, 160 "Ranging is not supported"); 161 return -rte_errno; 162 } 163 164 if (supp_mask == NULL) { 165 rte_flow_error_set(error, EINVAL, 166 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 167 "Supported mask for item should be specified"); 168 return -rte_errno; 169 } 170 171 /* Check that mask and spec not asks for more match than supp_mask */ 172 for (i = 0; i < size; i++) { 173 match = spec[i] | mask[i]; 174 supp = ((const uint8_t *)supp_mask)[i]; 175 176 if ((match | supp) != supp) { 177 rte_flow_error_set(error, ENOTSUP, 178 RTE_FLOW_ERROR_TYPE_ITEM, item, 179 "Item's field is not supported"); 180 return -rte_errno; 181 } 182 } 183 184 exit: 185 *spec_ptr = spec; 186 *mask_ptr = mask; 187 return 0; 188 } 189 190 /* 191 * Protocol parsers. 192 * Masking is not supported, so masks in items should be either 193 * full or empty (zeroed) and set only for supported fields which 194 * are specified in the supp_mask. 195 */ 196 197 static int 198 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, 199 __rte_unused efx_filter_spec_t *efx_spec, 200 __rte_unused struct rte_flow_error *error) 201 { 202 return 0; 203 } 204 205 /** 206 * Convert Ethernet item to EFX filter specification. 207 * 208 * @param item[in] 209 * Item specification. Only source and destination addresses and 210 * Ethernet type fields are supported. In addition to full and 211 * empty masks of destination address, individual/group mask is 212 * also supported. If the mask is NULL, default mask will be used. 213 * Ranging is not supported. 214 * @param efx_spec[in, out] 215 * EFX filter specification to update. 216 * @param[out] error 217 * Perform verbose error reporting if not NULL. 218 */ 219 static int 220 sfc_flow_parse_eth(const struct rte_flow_item *item, 221 efx_filter_spec_t *efx_spec, 222 struct rte_flow_error *error) 223 { 224 int rc; 225 const struct rte_flow_item_eth *spec = NULL; 226 const struct rte_flow_item_eth *mask = NULL; 227 const struct rte_flow_item_eth supp_mask = { 228 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 229 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 230 .type = 0xffff, 231 }; 232 const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = { 233 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 234 }; 235 236 rc = sfc_flow_parse_init(item, 237 (const void **)&spec, 238 (const void **)&mask, 239 &supp_mask, 240 &rte_flow_item_eth_mask, 241 sizeof(struct rte_flow_item_eth), 242 error); 243 if (rc != 0) 244 return rc; 245 246 /* If "spec" is not set, could be any Ethernet */ 247 if (spec == NULL) 248 return 0; 249 250 if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) { 251 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC; 252 rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes, 253 EFX_MAC_ADDR_LEN); 254 } else if (memcmp(mask->dst.addr_bytes, ig_mask, 255 EFX_MAC_ADDR_LEN) == 0) { 256 if (is_unicast_ether_addr(&spec->dst)) 257 efx_spec->efs_match_flags |= 258 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST; 259 else 260 efx_spec->efs_match_flags |= 261 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST; 262 } else if (!is_zero_ether_addr(&mask->dst)) { 263 goto fail_bad_mask; 264 } 265 266 if (is_same_ether_addr(&mask->src, &supp_mask.src)) { 267 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC; 268 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes, 269 EFX_MAC_ADDR_LEN); 270 } else if (!is_zero_ether_addr(&mask->src)) { 271 goto fail_bad_mask; 272 } 273 274 /* 275 * Ether type is in big-endian byte order in item and 276 * in little-endian in efx_spec, so byte swap is used 277 */ 278 if (mask->type == supp_mask.type) { 279 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; 280 efx_spec->efs_ether_type = rte_bswap16(spec->type); 281 } else if (mask->type != 0) { 282 goto fail_bad_mask; 283 } 284 285 return 0; 286 287 fail_bad_mask: 288 rte_flow_error_set(error, EINVAL, 289 RTE_FLOW_ERROR_TYPE_ITEM, item, 290 "Bad mask in the ETH pattern item"); 291 return -rte_errno; 292 } 293 294 /** 295 * Convert VLAN item to EFX filter specification. 296 * 297 * @param item[in] 298 * Item specification. Only VID field is supported. 299 * The mask can not be NULL. Ranging is not supported. 300 * @param efx_spec[in, out] 301 * EFX filter specification to update. 302 * @param[out] error 303 * Perform verbose error reporting if not NULL. 304 */ 305 static int 306 sfc_flow_parse_vlan(const struct rte_flow_item *item, 307 efx_filter_spec_t *efx_spec, 308 struct rte_flow_error *error) 309 { 310 int rc; 311 uint16_t vid; 312 const struct rte_flow_item_vlan *spec = NULL; 313 const struct rte_flow_item_vlan *mask = NULL; 314 const struct rte_flow_item_vlan supp_mask = { 315 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX), 316 }; 317 318 rc = sfc_flow_parse_init(item, 319 (const void **)&spec, 320 (const void **)&mask, 321 &supp_mask, 322 NULL, 323 sizeof(struct rte_flow_item_vlan), 324 error); 325 if (rc != 0) 326 return rc; 327 328 /* 329 * VID is in big-endian byte order in item and 330 * in little-endian in efx_spec, so byte swap is used. 331 * If two VLAN items are included, the first matches 332 * the outer tag and the next matches the inner tag. 333 */ 334 if (mask->tci == supp_mask.tci) { 335 vid = rte_bswap16(spec->tci); 336 337 if (!(efx_spec->efs_match_flags & 338 EFX_FILTER_MATCH_OUTER_VID)) { 339 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID; 340 efx_spec->efs_outer_vid = vid; 341 } else if (!(efx_spec->efs_match_flags & 342 EFX_FILTER_MATCH_INNER_VID)) { 343 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID; 344 efx_spec->efs_inner_vid = vid; 345 } else { 346 rte_flow_error_set(error, EINVAL, 347 RTE_FLOW_ERROR_TYPE_ITEM, item, 348 "More than two VLAN items"); 349 return -rte_errno; 350 } 351 } else { 352 rte_flow_error_set(error, EINVAL, 353 RTE_FLOW_ERROR_TYPE_ITEM, item, 354 "VLAN ID in TCI match is required"); 355 return -rte_errno; 356 } 357 358 return 0; 359 } 360 361 /** 362 * Convert IPv4 item to EFX filter specification. 363 * 364 * @param item[in] 365 * Item specification. Only source and destination addresses and 366 * protocol fields are supported. If the mask is NULL, default 367 * mask will be used. Ranging is not supported. 368 * @param efx_spec[in, out] 369 * EFX filter specification to update. 370 * @param[out] error 371 * Perform verbose error reporting if not NULL. 372 */ 373 static int 374 sfc_flow_parse_ipv4(const struct rte_flow_item *item, 375 efx_filter_spec_t *efx_spec, 376 struct rte_flow_error *error) 377 { 378 int rc; 379 const struct rte_flow_item_ipv4 *spec = NULL; 380 const struct rte_flow_item_ipv4 *mask = NULL; 381 const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4); 382 const struct rte_flow_item_ipv4 supp_mask = { 383 .hdr = { 384 .src_addr = 0xffffffff, 385 .dst_addr = 0xffffffff, 386 .next_proto_id = 0xff, 387 } 388 }; 389 390 rc = sfc_flow_parse_init(item, 391 (const void **)&spec, 392 (const void **)&mask, 393 &supp_mask, 394 &rte_flow_item_ipv4_mask, 395 sizeof(struct rte_flow_item_ipv4), 396 error); 397 if (rc != 0) 398 return rc; 399 400 /* 401 * Filtering by IPv4 source and destination addresses requires 402 * the appropriate ETHER_TYPE in hardware filters 403 */ 404 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { 405 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; 406 efx_spec->efs_ether_type = ether_type_ipv4; 407 } else if (efx_spec->efs_ether_type != ether_type_ipv4) { 408 rte_flow_error_set(error, EINVAL, 409 RTE_FLOW_ERROR_TYPE_ITEM, item, 410 "Ethertype in pattern with IPV4 item should be appropriate"); 411 return -rte_errno; 412 } 413 414 if (spec == NULL) 415 return 0; 416 417 /* 418 * IPv4 addresses are in big-endian byte order in item and in 419 * efx_spec 420 */ 421 if (mask->hdr.src_addr == supp_mask.hdr.src_addr) { 422 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST; 423 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr; 424 } else if (mask->hdr.src_addr != 0) { 425 goto fail_bad_mask; 426 } 427 428 if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) { 429 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST; 430 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr; 431 } else if (mask->hdr.dst_addr != 0) { 432 goto fail_bad_mask; 433 } 434 435 if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) { 436 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; 437 efx_spec->efs_ip_proto = spec->hdr.next_proto_id; 438 } else if (mask->hdr.next_proto_id != 0) { 439 goto fail_bad_mask; 440 } 441 442 return 0; 443 444 fail_bad_mask: 445 rte_flow_error_set(error, EINVAL, 446 RTE_FLOW_ERROR_TYPE_ITEM, item, 447 "Bad mask in the IPV4 pattern item"); 448 return -rte_errno; 449 } 450 451 /** 452 * Convert IPv6 item to EFX filter specification. 453 * 454 * @param item[in] 455 * Item specification. Only source and destination addresses and 456 * next header fields are supported. If the mask is NULL, default 457 * mask will be used. Ranging is not supported. 458 * @param efx_spec[in, out] 459 * EFX filter specification to update. 460 * @param[out] error 461 * Perform verbose error reporting if not NULL. 462 */ 463 static int 464 sfc_flow_parse_ipv6(const struct rte_flow_item *item, 465 efx_filter_spec_t *efx_spec, 466 struct rte_flow_error *error) 467 { 468 int rc; 469 const struct rte_flow_item_ipv6 *spec = NULL; 470 const struct rte_flow_item_ipv6 *mask = NULL; 471 const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6); 472 const struct rte_flow_item_ipv6 supp_mask = { 473 .hdr = { 474 .src_addr = { 0xff, 0xff, 0xff, 0xff, 475 0xff, 0xff, 0xff, 0xff, 476 0xff, 0xff, 0xff, 0xff, 477 0xff, 0xff, 0xff, 0xff }, 478 .dst_addr = { 0xff, 0xff, 0xff, 0xff, 479 0xff, 0xff, 0xff, 0xff, 480 0xff, 0xff, 0xff, 0xff, 481 0xff, 0xff, 0xff, 0xff }, 482 .proto = 0xff, 483 } 484 }; 485 486 rc = sfc_flow_parse_init(item, 487 (const void **)&spec, 488 (const void **)&mask, 489 &supp_mask, 490 &rte_flow_item_ipv6_mask, 491 sizeof(struct rte_flow_item_ipv6), 492 error); 493 if (rc != 0) 494 return rc; 495 496 /* 497 * Filtering by IPv6 source and destination addresses requires 498 * the appropriate ETHER_TYPE in hardware filters 499 */ 500 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) { 501 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; 502 efx_spec->efs_ether_type = ether_type_ipv6; 503 } else if (efx_spec->efs_ether_type != ether_type_ipv6) { 504 rte_flow_error_set(error, EINVAL, 505 RTE_FLOW_ERROR_TYPE_ITEM, item, 506 "Ethertype in pattern with IPV6 item should be appropriate"); 507 return -rte_errno; 508 } 509 510 if (spec == NULL) 511 return 0; 512 513 /* 514 * IPv6 addresses are in big-endian byte order in item and in 515 * efx_spec 516 */ 517 if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr, 518 sizeof(mask->hdr.src_addr)) == 0) { 519 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST; 520 521 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) != 522 sizeof(spec->hdr.src_addr)); 523 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr, 524 sizeof(efx_spec->efs_rem_host)); 525 } else if (!sfc_flow_is_zero(mask->hdr.src_addr, 526 sizeof(mask->hdr.src_addr))) { 527 goto fail_bad_mask; 528 } 529 530 if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr, 531 sizeof(mask->hdr.dst_addr)) == 0) { 532 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST; 533 534 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) != 535 sizeof(spec->hdr.dst_addr)); 536 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr, 537 sizeof(efx_spec->efs_loc_host)); 538 } else if (!sfc_flow_is_zero(mask->hdr.dst_addr, 539 sizeof(mask->hdr.dst_addr))) { 540 goto fail_bad_mask; 541 } 542 543 if (mask->hdr.proto == supp_mask.hdr.proto) { 544 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; 545 efx_spec->efs_ip_proto = spec->hdr.proto; 546 } else if (mask->hdr.proto != 0) { 547 goto fail_bad_mask; 548 } 549 550 return 0; 551 552 fail_bad_mask: 553 rte_flow_error_set(error, EINVAL, 554 RTE_FLOW_ERROR_TYPE_ITEM, item, 555 "Bad mask in the IPV6 pattern item"); 556 return -rte_errno; 557 } 558 559 /** 560 * Convert TCP item to EFX filter specification. 561 * 562 * @param item[in] 563 * Item specification. Only source and destination ports fields 564 * are supported. If the mask is NULL, default mask will be used. 565 * Ranging is not supported. 566 * @param efx_spec[in, out] 567 * EFX filter specification to update. 568 * @param[out] error 569 * Perform verbose error reporting if not NULL. 570 */ 571 static int 572 sfc_flow_parse_tcp(const struct rte_flow_item *item, 573 efx_filter_spec_t *efx_spec, 574 struct rte_flow_error *error) 575 { 576 int rc; 577 const struct rte_flow_item_tcp *spec = NULL; 578 const struct rte_flow_item_tcp *mask = NULL; 579 const struct rte_flow_item_tcp supp_mask = { 580 .hdr = { 581 .src_port = 0xffff, 582 .dst_port = 0xffff, 583 } 584 }; 585 586 rc = sfc_flow_parse_init(item, 587 (const void **)&spec, 588 (const void **)&mask, 589 &supp_mask, 590 &rte_flow_item_tcp_mask, 591 sizeof(struct rte_flow_item_tcp), 592 error); 593 if (rc != 0) 594 return rc; 595 596 /* 597 * Filtering by TCP source and destination ports requires 598 * the appropriate IP_PROTO in hardware filters 599 */ 600 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) { 601 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; 602 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP; 603 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) { 604 rte_flow_error_set(error, EINVAL, 605 RTE_FLOW_ERROR_TYPE_ITEM, item, 606 "IP proto in pattern with TCP item should be appropriate"); 607 return -rte_errno; 608 } 609 610 if (spec == NULL) 611 return 0; 612 613 /* 614 * Source and destination ports are in big-endian byte order in item and 615 * in little-endian in efx_spec, so byte swap is used 616 */ 617 if (mask->hdr.src_port == supp_mask.hdr.src_port) { 618 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT; 619 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port); 620 } else if (mask->hdr.src_port != 0) { 621 goto fail_bad_mask; 622 } 623 624 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) { 625 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT; 626 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port); 627 } else if (mask->hdr.dst_port != 0) { 628 goto fail_bad_mask; 629 } 630 631 return 0; 632 633 fail_bad_mask: 634 rte_flow_error_set(error, EINVAL, 635 RTE_FLOW_ERROR_TYPE_ITEM, item, 636 "Bad mask in the TCP pattern item"); 637 return -rte_errno; 638 } 639 640 /** 641 * Convert UDP item to EFX filter specification. 642 * 643 * @param item[in] 644 * Item specification. Only source and destination ports fields 645 * are supported. If the mask is NULL, default mask will be used. 646 * Ranging is not supported. 647 * @param efx_spec[in, out] 648 * EFX filter specification to update. 649 * @param[out] error 650 * Perform verbose error reporting if not NULL. 651 */ 652 static int 653 sfc_flow_parse_udp(const struct rte_flow_item *item, 654 efx_filter_spec_t *efx_spec, 655 struct rte_flow_error *error) 656 { 657 int rc; 658 const struct rte_flow_item_udp *spec = NULL; 659 const struct rte_flow_item_udp *mask = NULL; 660 const struct rte_flow_item_udp supp_mask = { 661 .hdr = { 662 .src_port = 0xffff, 663 .dst_port = 0xffff, 664 } 665 }; 666 667 rc = sfc_flow_parse_init(item, 668 (const void **)&spec, 669 (const void **)&mask, 670 &supp_mask, 671 &rte_flow_item_udp_mask, 672 sizeof(struct rte_flow_item_udp), 673 error); 674 if (rc != 0) 675 return rc; 676 677 /* 678 * Filtering by UDP source and destination ports requires 679 * the appropriate IP_PROTO in hardware filters 680 */ 681 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) { 682 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO; 683 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP; 684 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) { 685 rte_flow_error_set(error, EINVAL, 686 RTE_FLOW_ERROR_TYPE_ITEM, item, 687 "IP proto in pattern with UDP item should be appropriate"); 688 return -rte_errno; 689 } 690 691 if (spec == NULL) 692 return 0; 693 694 /* 695 * Source and destination ports are in big-endian byte order in item and 696 * in little-endian in efx_spec, so byte swap is used 697 */ 698 if (mask->hdr.src_port == supp_mask.hdr.src_port) { 699 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT; 700 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port); 701 } else if (mask->hdr.src_port != 0) { 702 goto fail_bad_mask; 703 } 704 705 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) { 706 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT; 707 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port); 708 } else if (mask->hdr.dst_port != 0) { 709 goto fail_bad_mask; 710 } 711 712 return 0; 713 714 fail_bad_mask: 715 rte_flow_error_set(error, EINVAL, 716 RTE_FLOW_ERROR_TYPE_ITEM, item, 717 "Bad mask in the UDP pattern item"); 718 return -rte_errno; 719 } 720 721 static const struct sfc_flow_item sfc_flow_items[] = { 722 { 723 .type = RTE_FLOW_ITEM_TYPE_VOID, 724 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, 725 .layer = SFC_FLOW_ITEM_ANY_LAYER, 726 .parse = sfc_flow_parse_void, 727 }, 728 { 729 .type = RTE_FLOW_ITEM_TYPE_ETH, 730 .prev_layer = SFC_FLOW_ITEM_START_LAYER, 731 .layer = SFC_FLOW_ITEM_L2, 732 .parse = sfc_flow_parse_eth, 733 }, 734 { 735 .type = RTE_FLOW_ITEM_TYPE_VLAN, 736 .prev_layer = SFC_FLOW_ITEM_L2, 737 .layer = SFC_FLOW_ITEM_L2, 738 .parse = sfc_flow_parse_vlan, 739 }, 740 { 741 .type = RTE_FLOW_ITEM_TYPE_IPV4, 742 .prev_layer = SFC_FLOW_ITEM_L2, 743 .layer = SFC_FLOW_ITEM_L3, 744 .parse = sfc_flow_parse_ipv4, 745 }, 746 { 747 .type = RTE_FLOW_ITEM_TYPE_IPV6, 748 .prev_layer = SFC_FLOW_ITEM_L2, 749 .layer = SFC_FLOW_ITEM_L3, 750 .parse = sfc_flow_parse_ipv6, 751 }, 752 { 753 .type = RTE_FLOW_ITEM_TYPE_TCP, 754 .prev_layer = SFC_FLOW_ITEM_L3, 755 .layer = SFC_FLOW_ITEM_L4, 756 .parse = sfc_flow_parse_tcp, 757 }, 758 { 759 .type = RTE_FLOW_ITEM_TYPE_UDP, 760 .prev_layer = SFC_FLOW_ITEM_L3, 761 .layer = SFC_FLOW_ITEM_L4, 762 .parse = sfc_flow_parse_udp, 763 }, 764 }; 765 766 /* 767 * Protocol-independent flow API support 768 */ 769 static int 770 sfc_flow_parse_attr(const struct rte_flow_attr *attr, 771 struct rte_flow *flow, 772 struct rte_flow_error *error) 773 { 774 if (attr == NULL) { 775 rte_flow_error_set(error, EINVAL, 776 RTE_FLOW_ERROR_TYPE_ATTR, NULL, 777 "NULL attribute"); 778 return -rte_errno; 779 } 780 if (attr->group != 0) { 781 rte_flow_error_set(error, ENOTSUP, 782 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr, 783 "Groups are not supported"); 784 return -rte_errno; 785 } 786 if (attr->priority != 0) { 787 rte_flow_error_set(error, ENOTSUP, 788 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr, 789 "Priorities are not supported"); 790 return -rte_errno; 791 } 792 if (attr->egress != 0) { 793 rte_flow_error_set(error, ENOTSUP, 794 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr, 795 "Egress is not supported"); 796 return -rte_errno; 797 } 798 if (attr->ingress == 0) { 799 rte_flow_error_set(error, ENOTSUP, 800 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr, 801 "Only ingress is supported"); 802 return -rte_errno; 803 } 804 805 flow->spec.efs_flags |= EFX_FILTER_FLAG_RX; 806 flow->spec.efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT; 807 808 return 0; 809 } 810 811 /* Get item from array sfc_flow_items */ 812 static const struct sfc_flow_item * 813 sfc_flow_get_item(enum rte_flow_item_type type) 814 { 815 unsigned int i; 816 817 for (i = 0; i < RTE_DIM(sfc_flow_items); i++) 818 if (sfc_flow_items[i].type == type) 819 return &sfc_flow_items[i]; 820 821 return NULL; 822 } 823 824 static int 825 sfc_flow_parse_pattern(const struct rte_flow_item pattern[], 826 struct rte_flow *flow, 827 struct rte_flow_error *error) 828 { 829 int rc; 830 unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER; 831 const struct sfc_flow_item *item; 832 833 if (pattern == NULL) { 834 rte_flow_error_set(error, EINVAL, 835 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL, 836 "NULL pattern"); 837 return -rte_errno; 838 } 839 840 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { 841 item = sfc_flow_get_item(pattern->type); 842 if (item == NULL) { 843 rte_flow_error_set(error, ENOTSUP, 844 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 845 "Unsupported pattern item"); 846 return -rte_errno; 847 } 848 849 /* 850 * Omitting one or several protocol layers at the beginning 851 * of pattern is supported 852 */ 853 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 854 prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 855 item->prev_layer != prev_layer) { 856 rte_flow_error_set(error, ENOTSUP, 857 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 858 "Unexpected sequence of pattern items"); 859 return -rte_errno; 860 } 861 862 rc = item->parse(pattern, &flow->spec, error); 863 if (rc != 0) 864 return rc; 865 866 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER) 867 prev_layer = item->layer; 868 } 869 870 return 0; 871 } 872 873 static int 874 sfc_flow_parse_queue(struct sfc_adapter *sa, 875 const struct rte_flow_action_queue *queue, 876 struct rte_flow *flow) 877 { 878 struct sfc_rxq *rxq; 879 880 if (queue->index >= sa->rxq_count) 881 return -EINVAL; 882 883 rxq = sa->rxq_info[queue->index].rxq; 884 flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; 885 886 return 0; 887 } 888 889 static int 890 sfc_flow_parse_actions(struct sfc_adapter *sa, 891 const struct rte_flow_action actions[], 892 struct rte_flow *flow, 893 struct rte_flow_error *error) 894 { 895 int rc; 896 boolean_t is_specified = B_FALSE; 897 898 if (actions == NULL) { 899 rte_flow_error_set(error, EINVAL, 900 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL, 901 "NULL actions"); 902 return -rte_errno; 903 } 904 905 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 906 switch (actions->type) { 907 case RTE_FLOW_ACTION_TYPE_VOID: 908 break; 909 910 case RTE_FLOW_ACTION_TYPE_QUEUE: 911 rc = sfc_flow_parse_queue(sa, actions->conf, flow); 912 if (rc != 0) { 913 rte_flow_error_set(error, EINVAL, 914 RTE_FLOW_ERROR_TYPE_ACTION, actions, 915 "Bad QUEUE action"); 916 return -rte_errno; 917 } 918 919 is_specified = B_TRUE; 920 break; 921 922 default: 923 rte_flow_error_set(error, ENOTSUP, 924 RTE_FLOW_ERROR_TYPE_ACTION, actions, 925 "Action is not supported"); 926 return -rte_errno; 927 } 928 } 929 930 if (!is_specified) { 931 rte_flow_error_set(error, EINVAL, 932 RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions, 933 "Action is unspecified"); 934 return -rte_errno; 935 } 936 937 return 0; 938 } 939 940 static int 941 sfc_flow_parse(struct rte_eth_dev *dev, 942 const struct rte_flow_attr *attr, 943 const struct rte_flow_item pattern[], 944 const struct rte_flow_action actions[], 945 struct rte_flow *flow, 946 struct rte_flow_error *error) 947 { 948 struct sfc_adapter *sa = dev->data->dev_private; 949 int rc; 950 951 memset(&flow->spec, 0, sizeof(flow->spec)); 952 953 rc = sfc_flow_parse_attr(attr, flow, error); 954 if (rc != 0) 955 goto fail_bad_value; 956 957 rc = sfc_flow_parse_pattern(pattern, flow, error); 958 if (rc != 0) 959 goto fail_bad_value; 960 961 rc = sfc_flow_parse_actions(sa, actions, flow, error); 962 if (rc != 0) 963 goto fail_bad_value; 964 965 if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { 966 rte_flow_error_set(error, ENOTSUP, 967 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 968 "Flow rule pattern is not supported"); 969 return -rte_errno; 970 } 971 972 fail_bad_value: 973 return rc; 974 } 975 976 static int 977 sfc_flow_validate(struct rte_eth_dev *dev, 978 const struct rte_flow_attr *attr, 979 const struct rte_flow_item pattern[], 980 const struct rte_flow_action actions[], 981 struct rte_flow_error *error) 982 { 983 struct rte_flow flow; 984 985 return sfc_flow_parse(dev, attr, pattern, actions, &flow, error); 986 } 987 988 static struct rte_flow * 989 sfc_flow_create(struct rte_eth_dev *dev, 990 const struct rte_flow_attr *attr, 991 const struct rte_flow_item pattern[], 992 const struct rte_flow_action actions[], 993 struct rte_flow_error *error) 994 { 995 struct sfc_adapter *sa = dev->data->dev_private; 996 struct rte_flow *flow = NULL; 997 int rc; 998 999 flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0); 1000 if (flow == NULL) { 1001 rte_flow_error_set(error, ENOMEM, 1002 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1003 "Failed to allocate memory"); 1004 goto fail_no_mem; 1005 } 1006 1007 rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error); 1008 if (rc != 0) 1009 goto fail_bad_value; 1010 1011 TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries); 1012 1013 sfc_adapter_lock(sa); 1014 1015 if (sa->state == SFC_ADAPTER_STARTED) { 1016 rc = efx_filter_insert(sa->nic, &flow->spec); 1017 if (rc != 0) { 1018 rte_flow_error_set(error, rc, 1019 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1020 "Failed to insert filter"); 1021 goto fail_filter_insert; 1022 } 1023 } 1024 1025 sfc_adapter_unlock(sa); 1026 1027 return flow; 1028 1029 fail_filter_insert: 1030 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1031 1032 fail_bad_value: 1033 rte_free(flow); 1034 sfc_adapter_unlock(sa); 1035 1036 fail_no_mem: 1037 return NULL; 1038 } 1039 1040 static int 1041 sfc_flow_remove(struct sfc_adapter *sa, 1042 struct rte_flow *flow, 1043 struct rte_flow_error *error) 1044 { 1045 int rc = 0; 1046 1047 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1048 1049 if (sa->state == SFC_ADAPTER_STARTED) { 1050 rc = efx_filter_remove(sa->nic, &flow->spec); 1051 if (rc != 0) 1052 rte_flow_error_set(error, rc, 1053 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1054 "Failed to destroy flow rule"); 1055 } 1056 1057 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1058 rte_free(flow); 1059 1060 return rc; 1061 } 1062 1063 static int 1064 sfc_flow_destroy(struct rte_eth_dev *dev, 1065 struct rte_flow *flow, 1066 struct rte_flow_error *error) 1067 { 1068 struct sfc_adapter *sa = dev->data->dev_private; 1069 struct rte_flow *flow_ptr; 1070 int rc = EINVAL; 1071 1072 sfc_adapter_lock(sa); 1073 1074 TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) { 1075 if (flow_ptr == flow) 1076 rc = 0; 1077 } 1078 if (rc != 0) { 1079 rte_flow_error_set(error, rc, 1080 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 1081 "Failed to find flow rule to destroy"); 1082 goto fail_bad_value; 1083 } 1084 1085 rc = sfc_flow_remove(sa, flow, error); 1086 1087 fail_bad_value: 1088 sfc_adapter_unlock(sa); 1089 1090 return -rc; 1091 } 1092 1093 static int 1094 sfc_flow_flush(struct rte_eth_dev *dev, 1095 struct rte_flow_error *error) 1096 { 1097 struct sfc_adapter *sa = dev->data->dev_private; 1098 struct rte_flow *flow; 1099 int rc = 0; 1100 int ret = 0; 1101 1102 sfc_adapter_lock(sa); 1103 1104 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 1105 rc = sfc_flow_remove(sa, flow, error); 1106 if (rc != 0) 1107 ret = rc; 1108 } 1109 1110 sfc_adapter_unlock(sa); 1111 1112 return -ret; 1113 } 1114 1115 const struct rte_flow_ops sfc_flow_ops = { 1116 .validate = sfc_flow_validate, 1117 .create = sfc_flow_create, 1118 .destroy = sfc_flow_destroy, 1119 .flush = sfc_flow_flush, 1120 .query = NULL, 1121 }; 1122 1123 void 1124 sfc_flow_init(struct sfc_adapter *sa) 1125 { 1126 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1127 1128 TAILQ_INIT(&sa->filter.flow_list); 1129 } 1130 1131 void 1132 sfc_flow_fini(struct sfc_adapter *sa) 1133 { 1134 struct rte_flow *flow; 1135 1136 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1137 1138 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 1139 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1140 rte_free(flow); 1141 } 1142 } 1143 1144 void 1145 sfc_flow_stop(struct sfc_adapter *sa) 1146 { 1147 struct rte_flow *flow; 1148 1149 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1150 1151 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) 1152 efx_filter_remove(sa->nic, &flow->spec); 1153 } 1154 1155 int 1156 sfc_flow_start(struct sfc_adapter *sa) 1157 { 1158 struct rte_flow *flow; 1159 int rc = 0; 1160 1161 sfc_log_init(sa, "entry"); 1162 1163 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1164 1165 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) { 1166 rc = efx_filter_insert(sa->nic, &flow->spec); 1167 if (rc != 0) 1168 goto fail_bad_flow; 1169 } 1170 1171 sfc_log_init(sa, "done"); 1172 1173 fail_bad_flow: 1174 return rc; 1175 } 1176