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 != NULL && 841 pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { 842 item = sfc_flow_get_item(pattern->type); 843 if (item == NULL) { 844 rte_flow_error_set(error, ENOTSUP, 845 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 846 "Unsupported pattern item"); 847 return -rte_errno; 848 } 849 850 /* 851 * Omitting one or several protocol layers at the beginning 852 * of pattern is supported 853 */ 854 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 855 prev_layer != SFC_FLOW_ITEM_ANY_LAYER && 856 item->prev_layer != prev_layer) { 857 rte_flow_error_set(error, ENOTSUP, 858 RTE_FLOW_ERROR_TYPE_ITEM, pattern, 859 "Unexpected sequence of pattern items"); 860 return -rte_errno; 861 } 862 863 rc = item->parse(pattern, &flow->spec, error); 864 if (rc != 0) 865 return rc; 866 867 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER) 868 prev_layer = item->layer; 869 } 870 871 if (pattern == NULL) { 872 rte_flow_error_set(error, EINVAL, 873 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 874 "NULL item"); 875 return -rte_errno; 876 } 877 878 return 0; 879 } 880 881 static int 882 sfc_flow_parse_queue(struct sfc_adapter *sa, 883 const struct rte_flow_action_queue *queue, 884 struct rte_flow *flow) 885 { 886 struct sfc_rxq *rxq; 887 888 if (queue->index >= sa->rxq_count) 889 return -EINVAL; 890 891 rxq = sa->rxq_info[queue->index].rxq; 892 flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; 893 894 return 0; 895 } 896 897 static int 898 sfc_flow_parse_actions(struct sfc_adapter *sa, 899 const struct rte_flow_action actions[], 900 struct rte_flow *flow, 901 struct rte_flow_error *error) 902 { 903 int rc; 904 boolean_t is_specified = B_FALSE; 905 906 if (actions == NULL) { 907 rte_flow_error_set(error, EINVAL, 908 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL, 909 "NULL actions"); 910 return -rte_errno; 911 } 912 913 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 914 switch (actions->type) { 915 case RTE_FLOW_ACTION_TYPE_VOID: 916 break; 917 918 case RTE_FLOW_ACTION_TYPE_QUEUE: 919 rc = sfc_flow_parse_queue(sa, actions->conf, flow); 920 if (rc != 0) { 921 rte_flow_error_set(error, EINVAL, 922 RTE_FLOW_ERROR_TYPE_ACTION, actions, 923 "Bad QUEUE action"); 924 return -rte_errno; 925 } 926 927 is_specified = B_TRUE; 928 break; 929 930 default: 931 rte_flow_error_set(error, ENOTSUP, 932 RTE_FLOW_ERROR_TYPE_ACTION, actions, 933 "Action is not supported"); 934 return -rte_errno; 935 } 936 } 937 938 if (!is_specified) { 939 rte_flow_error_set(error, EINVAL, 940 RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions, 941 "Action is unspecified"); 942 return -rte_errno; 943 } 944 945 return 0; 946 } 947 948 static int 949 sfc_flow_parse(struct rte_eth_dev *dev, 950 const struct rte_flow_attr *attr, 951 const struct rte_flow_item pattern[], 952 const struct rte_flow_action actions[], 953 struct rte_flow *flow, 954 struct rte_flow_error *error) 955 { 956 struct sfc_adapter *sa = dev->data->dev_private; 957 int rc; 958 959 memset(&flow->spec, 0, sizeof(flow->spec)); 960 961 rc = sfc_flow_parse_attr(attr, flow, error); 962 if (rc != 0) 963 goto fail_bad_value; 964 965 rc = sfc_flow_parse_pattern(pattern, flow, error); 966 if (rc != 0) 967 goto fail_bad_value; 968 969 rc = sfc_flow_parse_actions(sa, actions, flow, error); 970 if (rc != 0) 971 goto fail_bad_value; 972 973 if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { 974 rte_flow_error_set(error, ENOTSUP, 975 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 976 "Flow rule pattern is not supported"); 977 return -rte_errno; 978 } 979 980 fail_bad_value: 981 return rc; 982 } 983 984 static int 985 sfc_flow_validate(struct rte_eth_dev *dev, 986 const struct rte_flow_attr *attr, 987 const struct rte_flow_item pattern[], 988 const struct rte_flow_action actions[], 989 struct rte_flow_error *error) 990 { 991 struct rte_flow flow; 992 993 return sfc_flow_parse(dev, attr, pattern, actions, &flow, error); 994 } 995 996 static struct rte_flow * 997 sfc_flow_create(struct rte_eth_dev *dev, 998 const struct rte_flow_attr *attr, 999 const struct rte_flow_item pattern[], 1000 const struct rte_flow_action actions[], 1001 struct rte_flow_error *error) 1002 { 1003 struct sfc_adapter *sa = dev->data->dev_private; 1004 struct rte_flow *flow = NULL; 1005 int rc; 1006 1007 flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0); 1008 if (flow == NULL) { 1009 rte_flow_error_set(error, ENOMEM, 1010 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1011 "Failed to allocate memory"); 1012 goto fail_no_mem; 1013 } 1014 1015 rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error); 1016 if (rc != 0) 1017 goto fail_bad_value; 1018 1019 TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries); 1020 1021 sfc_adapter_lock(sa); 1022 1023 if (sa->state == SFC_ADAPTER_STARTED) { 1024 rc = efx_filter_insert(sa->nic, &flow->spec); 1025 if (rc != 0) { 1026 rte_flow_error_set(error, rc, 1027 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1028 "Failed to insert filter"); 1029 goto fail_filter_insert; 1030 } 1031 } 1032 1033 sfc_adapter_unlock(sa); 1034 1035 return flow; 1036 1037 fail_filter_insert: 1038 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1039 1040 fail_bad_value: 1041 rte_free(flow); 1042 sfc_adapter_unlock(sa); 1043 1044 fail_no_mem: 1045 return NULL; 1046 } 1047 1048 static int 1049 sfc_flow_remove(struct sfc_adapter *sa, 1050 struct rte_flow *flow, 1051 struct rte_flow_error *error) 1052 { 1053 int rc = 0; 1054 1055 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1056 1057 if (sa->state == SFC_ADAPTER_STARTED) { 1058 rc = efx_filter_remove(sa->nic, &flow->spec); 1059 if (rc != 0) 1060 rte_flow_error_set(error, rc, 1061 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1062 "Failed to destroy flow rule"); 1063 } 1064 1065 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1066 rte_free(flow); 1067 1068 return rc; 1069 } 1070 1071 static int 1072 sfc_flow_destroy(struct rte_eth_dev *dev, 1073 struct rte_flow *flow, 1074 struct rte_flow_error *error) 1075 { 1076 struct sfc_adapter *sa = dev->data->dev_private; 1077 struct rte_flow *flow_ptr; 1078 int rc = EINVAL; 1079 1080 sfc_adapter_lock(sa); 1081 1082 TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) { 1083 if (flow_ptr == flow) 1084 rc = 0; 1085 } 1086 if (rc != 0) { 1087 rte_flow_error_set(error, rc, 1088 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 1089 "Failed to find flow rule to destroy"); 1090 goto fail_bad_value; 1091 } 1092 1093 rc = sfc_flow_remove(sa, flow, error); 1094 1095 fail_bad_value: 1096 sfc_adapter_unlock(sa); 1097 1098 return -rc; 1099 } 1100 1101 static int 1102 sfc_flow_flush(struct rte_eth_dev *dev, 1103 struct rte_flow_error *error) 1104 { 1105 struct sfc_adapter *sa = dev->data->dev_private; 1106 struct rte_flow *flow; 1107 int rc = 0; 1108 int ret = 0; 1109 1110 sfc_adapter_lock(sa); 1111 1112 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 1113 rc = sfc_flow_remove(sa, flow, error); 1114 if (rc != 0) 1115 ret = rc; 1116 } 1117 1118 sfc_adapter_unlock(sa); 1119 1120 return -ret; 1121 } 1122 1123 const struct rte_flow_ops sfc_flow_ops = { 1124 .validate = sfc_flow_validate, 1125 .create = sfc_flow_create, 1126 .destroy = sfc_flow_destroy, 1127 .flush = sfc_flow_flush, 1128 .query = NULL, 1129 }; 1130 1131 void 1132 sfc_flow_init(struct sfc_adapter *sa) 1133 { 1134 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1135 1136 TAILQ_INIT(&sa->filter.flow_list); 1137 } 1138 1139 void 1140 sfc_flow_fini(struct sfc_adapter *sa) 1141 { 1142 struct rte_flow *flow; 1143 1144 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1145 1146 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) { 1147 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries); 1148 rte_free(flow); 1149 } 1150 } 1151 1152 void 1153 sfc_flow_stop(struct sfc_adapter *sa) 1154 { 1155 struct rte_flow *flow; 1156 1157 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1158 1159 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) 1160 efx_filter_remove(sa->nic, &flow->spec); 1161 } 1162 1163 int 1164 sfc_flow_start(struct sfc_adapter *sa) 1165 { 1166 struct rte_flow *flow; 1167 int rc = 0; 1168 1169 sfc_log_init(sa, "entry"); 1170 1171 SFC_ASSERT(sfc_adapter_is_locked(sa)); 1172 1173 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) { 1174 rc = efx_filter_insert(sa->nic, &flow->spec); 1175 if (rc != 0) 1176 goto fail_bad_flow; 1177 } 1178 1179 sfc_log_init(sa, "done"); 1180 1181 fail_bad_flow: 1182 return rc; 1183 } 1184