1 /* 2 * Copyright (c) 2017, Cisco Systems, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 #include <errno.h> 33 #include <rte_log.h> 34 #include <rte_ethdev.h> 35 #include <rte_flow_driver.h> 36 #include <rte_ether.h> 37 #include <rte_ip.h> 38 #include <rte_udp.h> 39 40 #include "enic_compat.h" 41 #include "enic.h" 42 #include "vnic_dev.h" 43 #include "vnic_nic.h" 44 45 #ifdef RTE_LIBRTE_ENIC_DEBUG_FLOW 46 #define FLOW_TRACE() \ 47 RTE_LOG(DEBUG, PMD, "%s()\n", __func__) 48 #define FLOW_LOG(level, fmt, args...) \ 49 RTE_LOG(level, PMD, fmt, ## args) 50 #else 51 #define FLOW_TRACE() do { } while (0) 52 #define FLOW_LOG(level, fmt, args...) do { } while (0) 53 #endif 54 55 /** Info about how to copy items into enic filters. */ 56 struct enic_items { 57 /** Function for copying and validating an item. */ 58 int (*copy_item)(const struct rte_flow_item *item, 59 struct filter_v2 *enic_filter, u8 *inner_ofst); 60 /** List of valid previous items. */ 61 const enum rte_flow_item_type * const prev_items; 62 /** True if it's OK for this item to be the first item. For some NIC 63 * versions, it's invalid to start the stack above layer 3. 64 */ 65 const u8 valid_start_item; 66 }; 67 68 /** Filtering capabilities for various NIC and firmware versions. */ 69 struct enic_filter_cap { 70 /** list of valid items and their handlers and attributes. */ 71 const struct enic_items *item_info; 72 }; 73 74 /* functions for copying flow actions into enic actions */ 75 typedef int (copy_action_fn)(const struct rte_flow_action actions[], 76 struct filter_action_v2 *enic_action); 77 78 /* functions for copying items into enic filters */ 79 typedef int(enic_copy_item_fn)(const struct rte_flow_item *item, 80 struct filter_v2 *enic_filter, u8 *inner_ofst); 81 82 /** Action capabilities for various NICs. */ 83 struct enic_action_cap { 84 /** list of valid actions */ 85 const enum rte_flow_action_type *actions; 86 /** copy function for a particular NIC */ 87 int (*copy_fn)(const struct rte_flow_action actions[], 88 struct filter_action_v2 *enic_action); 89 }; 90 91 /* Forward declarations */ 92 static enic_copy_item_fn enic_copy_item_ipv4_v1; 93 static enic_copy_item_fn enic_copy_item_udp_v1; 94 static enic_copy_item_fn enic_copy_item_tcp_v1; 95 static enic_copy_item_fn enic_copy_item_eth_v2; 96 static enic_copy_item_fn enic_copy_item_vlan_v2; 97 static enic_copy_item_fn enic_copy_item_ipv4_v2; 98 static enic_copy_item_fn enic_copy_item_ipv6_v2; 99 static enic_copy_item_fn enic_copy_item_udp_v2; 100 static enic_copy_item_fn enic_copy_item_tcp_v2; 101 static enic_copy_item_fn enic_copy_item_sctp_v2; 102 static enic_copy_item_fn enic_copy_item_sctp_v2; 103 static enic_copy_item_fn enic_copy_item_vxlan_v2; 104 static copy_action_fn enic_copy_action_v1; 105 static copy_action_fn enic_copy_action_v2; 106 107 /** 108 * Legacy NICs or NICs with outdated firmware. Only 5-tuple perfect match 109 * is supported. 110 */ 111 static const struct enic_items enic_items_v1[] = { 112 [RTE_FLOW_ITEM_TYPE_IPV4] = { 113 .copy_item = enic_copy_item_ipv4_v1, 114 .valid_start_item = 1, 115 .prev_items = (const enum rte_flow_item_type[]) { 116 RTE_FLOW_ITEM_TYPE_END, 117 }, 118 }, 119 [RTE_FLOW_ITEM_TYPE_UDP] = { 120 .copy_item = enic_copy_item_udp_v1, 121 .valid_start_item = 0, 122 .prev_items = (const enum rte_flow_item_type[]) { 123 RTE_FLOW_ITEM_TYPE_IPV4, 124 RTE_FLOW_ITEM_TYPE_END, 125 }, 126 }, 127 [RTE_FLOW_ITEM_TYPE_TCP] = { 128 .copy_item = enic_copy_item_tcp_v1, 129 .valid_start_item = 0, 130 .prev_items = (const enum rte_flow_item_type[]) { 131 RTE_FLOW_ITEM_TYPE_IPV4, 132 RTE_FLOW_ITEM_TYPE_END, 133 }, 134 }, 135 }; 136 137 /** 138 * NICs have Advanced Filters capability but they are disabled. This means 139 * that layer 3 must be specified. 140 */ 141 static const struct enic_items enic_items_v2[] = { 142 [RTE_FLOW_ITEM_TYPE_ETH] = { 143 .copy_item = enic_copy_item_eth_v2, 144 .valid_start_item = 1, 145 .prev_items = (const enum rte_flow_item_type[]) { 146 RTE_FLOW_ITEM_TYPE_VXLAN, 147 RTE_FLOW_ITEM_TYPE_END, 148 }, 149 }, 150 [RTE_FLOW_ITEM_TYPE_VLAN] = { 151 .copy_item = enic_copy_item_vlan_v2, 152 .valid_start_item = 1, 153 .prev_items = (const enum rte_flow_item_type[]) { 154 RTE_FLOW_ITEM_TYPE_ETH, 155 RTE_FLOW_ITEM_TYPE_END, 156 }, 157 }, 158 [RTE_FLOW_ITEM_TYPE_IPV4] = { 159 .copy_item = enic_copy_item_ipv4_v2, 160 .valid_start_item = 1, 161 .prev_items = (const enum rte_flow_item_type[]) { 162 RTE_FLOW_ITEM_TYPE_ETH, 163 RTE_FLOW_ITEM_TYPE_VLAN, 164 RTE_FLOW_ITEM_TYPE_END, 165 }, 166 }, 167 [RTE_FLOW_ITEM_TYPE_IPV6] = { 168 .copy_item = enic_copy_item_ipv6_v2, 169 .valid_start_item = 1, 170 .prev_items = (const enum rte_flow_item_type[]) { 171 RTE_FLOW_ITEM_TYPE_ETH, 172 RTE_FLOW_ITEM_TYPE_VLAN, 173 RTE_FLOW_ITEM_TYPE_END, 174 }, 175 }, 176 [RTE_FLOW_ITEM_TYPE_UDP] = { 177 .copy_item = enic_copy_item_udp_v2, 178 .valid_start_item = 0, 179 .prev_items = (const enum rte_flow_item_type[]) { 180 RTE_FLOW_ITEM_TYPE_IPV4, 181 RTE_FLOW_ITEM_TYPE_IPV6, 182 RTE_FLOW_ITEM_TYPE_END, 183 }, 184 }, 185 [RTE_FLOW_ITEM_TYPE_TCP] = { 186 .copy_item = enic_copy_item_tcp_v2, 187 .valid_start_item = 0, 188 .prev_items = (const enum rte_flow_item_type[]) { 189 RTE_FLOW_ITEM_TYPE_IPV4, 190 RTE_FLOW_ITEM_TYPE_IPV6, 191 RTE_FLOW_ITEM_TYPE_END, 192 }, 193 }, 194 [RTE_FLOW_ITEM_TYPE_SCTP] = { 195 .copy_item = enic_copy_item_sctp_v2, 196 .valid_start_item = 0, 197 .prev_items = (const enum rte_flow_item_type[]) { 198 RTE_FLOW_ITEM_TYPE_IPV4, 199 RTE_FLOW_ITEM_TYPE_IPV6, 200 RTE_FLOW_ITEM_TYPE_END, 201 }, 202 }, 203 [RTE_FLOW_ITEM_TYPE_VXLAN] = { 204 .copy_item = enic_copy_item_vxlan_v2, 205 .valid_start_item = 0, 206 .prev_items = (const enum rte_flow_item_type[]) { 207 RTE_FLOW_ITEM_TYPE_UDP, 208 RTE_FLOW_ITEM_TYPE_END, 209 }, 210 }, 211 }; 212 213 /** NICs with Advanced filters enabled */ 214 static const struct enic_items enic_items_v3[] = { 215 [RTE_FLOW_ITEM_TYPE_ETH] = { 216 .copy_item = enic_copy_item_eth_v2, 217 .valid_start_item = 1, 218 .prev_items = (const enum rte_flow_item_type[]) { 219 RTE_FLOW_ITEM_TYPE_VXLAN, 220 RTE_FLOW_ITEM_TYPE_END, 221 }, 222 }, 223 [RTE_FLOW_ITEM_TYPE_VLAN] = { 224 .copy_item = enic_copy_item_vlan_v2, 225 .valid_start_item = 1, 226 .prev_items = (const enum rte_flow_item_type[]) { 227 RTE_FLOW_ITEM_TYPE_ETH, 228 RTE_FLOW_ITEM_TYPE_END, 229 }, 230 }, 231 [RTE_FLOW_ITEM_TYPE_IPV4] = { 232 .copy_item = enic_copy_item_ipv4_v2, 233 .valid_start_item = 1, 234 .prev_items = (const enum rte_flow_item_type[]) { 235 RTE_FLOW_ITEM_TYPE_ETH, 236 RTE_FLOW_ITEM_TYPE_VLAN, 237 RTE_FLOW_ITEM_TYPE_END, 238 }, 239 }, 240 [RTE_FLOW_ITEM_TYPE_IPV6] = { 241 .copy_item = enic_copy_item_ipv6_v2, 242 .valid_start_item = 1, 243 .prev_items = (const enum rte_flow_item_type[]) { 244 RTE_FLOW_ITEM_TYPE_ETH, 245 RTE_FLOW_ITEM_TYPE_VLAN, 246 RTE_FLOW_ITEM_TYPE_END, 247 }, 248 }, 249 [RTE_FLOW_ITEM_TYPE_UDP] = { 250 .copy_item = enic_copy_item_udp_v2, 251 .valid_start_item = 1, 252 .prev_items = (const enum rte_flow_item_type[]) { 253 RTE_FLOW_ITEM_TYPE_IPV4, 254 RTE_FLOW_ITEM_TYPE_IPV6, 255 RTE_FLOW_ITEM_TYPE_END, 256 }, 257 }, 258 [RTE_FLOW_ITEM_TYPE_TCP] = { 259 .copy_item = enic_copy_item_tcp_v2, 260 .valid_start_item = 1, 261 .prev_items = (const enum rte_flow_item_type[]) { 262 RTE_FLOW_ITEM_TYPE_IPV4, 263 RTE_FLOW_ITEM_TYPE_IPV6, 264 RTE_FLOW_ITEM_TYPE_END, 265 }, 266 }, 267 [RTE_FLOW_ITEM_TYPE_SCTP] = { 268 .copy_item = enic_copy_item_sctp_v2, 269 .valid_start_item = 1, 270 .prev_items = (const enum rte_flow_item_type[]) { 271 RTE_FLOW_ITEM_TYPE_IPV4, 272 RTE_FLOW_ITEM_TYPE_IPV6, 273 RTE_FLOW_ITEM_TYPE_END, 274 }, 275 }, 276 [RTE_FLOW_ITEM_TYPE_VXLAN] = { 277 .copy_item = enic_copy_item_vxlan_v2, 278 .valid_start_item = 1, 279 .prev_items = (const enum rte_flow_item_type[]) { 280 RTE_FLOW_ITEM_TYPE_UDP, 281 RTE_FLOW_ITEM_TYPE_END, 282 }, 283 }, 284 }; 285 286 /** Filtering capabilities indexed this NICs supported filter type. */ 287 static const struct enic_filter_cap enic_filter_cap[] = { 288 [FILTER_IPV4_5TUPLE] = { 289 .item_info = enic_items_v1, 290 }, 291 [FILTER_USNIC_IP] = { 292 .item_info = enic_items_v2, 293 }, 294 [FILTER_DPDK_1] = { 295 .item_info = enic_items_v3, 296 }, 297 }; 298 299 /** Supported actions for older NICs */ 300 static const enum rte_flow_action_type enic_supported_actions_v1[] = { 301 RTE_FLOW_ACTION_TYPE_QUEUE, 302 RTE_FLOW_ACTION_TYPE_END, 303 }; 304 305 /** Supported actions for newer NICs */ 306 static const enum rte_flow_action_type enic_supported_actions_v2[] = { 307 RTE_FLOW_ACTION_TYPE_QUEUE, 308 RTE_FLOW_ACTION_TYPE_MARK, 309 RTE_FLOW_ACTION_TYPE_FLAG, 310 RTE_FLOW_ACTION_TYPE_END, 311 }; 312 313 /** Action capabilities indexed by NIC version information */ 314 static const struct enic_action_cap enic_action_cap[] = { 315 [FILTER_ACTION_RQ_STEERING_FLAG] = { 316 .actions = enic_supported_actions_v1, 317 .copy_fn = enic_copy_action_v1, 318 }, 319 [FILTER_ACTION_V2_ALL] = { 320 .actions = enic_supported_actions_v2, 321 .copy_fn = enic_copy_action_v2, 322 }, 323 }; 324 325 static int 326 mask_exact_match(const u8 *supported, const u8 *supplied, 327 unsigned int size) 328 { 329 unsigned int i; 330 for (i = 0; i < size; i++) { 331 if (supported[i] != supplied[i]) 332 return 0; 333 } 334 return 1; 335 } 336 337 /** 338 * Copy IPv4 item into version 1 NIC filter. 339 * 340 * @param item[in] 341 * Item specification. 342 * @param enic_filter[out] 343 * Partially filled in NIC filter structure. 344 * @param inner_ofst[in] 345 * Should always be 0 for version 1. 346 */ 347 static int 348 enic_copy_item_ipv4_v1(const struct rte_flow_item *item, 349 struct filter_v2 *enic_filter, u8 *inner_ofst) 350 { 351 const struct rte_flow_item_ipv4 *spec = item->spec; 352 const struct rte_flow_item_ipv4 *mask = item->mask; 353 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 354 struct ipv4_hdr supported_mask = { 355 .src_addr = 0xffffffff, 356 .dst_addr = 0xffffffff, 357 }; 358 359 FLOW_TRACE(); 360 361 if (*inner_ofst) 362 return ENOTSUP; 363 364 if (!mask) 365 mask = &rte_flow_item_ipv4_mask; 366 367 /* This is an exact match filter, both fields must be set */ 368 if (!spec || !spec->hdr.src_addr || !spec->hdr.dst_addr) { 369 FLOW_LOG(ERR, "IPv4 exact match src/dst addr"); 370 return ENOTSUP; 371 } 372 373 /* check that the suppied mask exactly matches capabilty */ 374 if (!mask_exact_match((const u8 *)&supported_mask, 375 (const u8 *)item->mask, sizeof(*mask))) { 376 FLOW_LOG(ERR, "IPv4 exact match mask"); 377 return ENOTSUP; 378 } 379 380 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 381 enic_5tup->src_addr = spec->hdr.src_addr; 382 enic_5tup->dst_addr = spec->hdr.dst_addr; 383 384 return 0; 385 } 386 387 /** 388 * Copy UDP item into version 1 NIC filter. 389 * 390 * @param item[in] 391 * Item specification. 392 * @param enic_filter[out] 393 * Partially filled in NIC filter structure. 394 * @param inner_ofst[in] 395 * Should always be 0 for version 1. 396 */ 397 static int 398 enic_copy_item_udp_v1(const struct rte_flow_item *item, 399 struct filter_v2 *enic_filter, u8 *inner_ofst) 400 { 401 const struct rte_flow_item_udp *spec = item->spec; 402 const struct rte_flow_item_udp *mask = item->mask; 403 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 404 struct udp_hdr supported_mask = { 405 .src_port = 0xffff, 406 .dst_port = 0xffff, 407 }; 408 409 FLOW_TRACE(); 410 411 if (*inner_ofst) 412 return ENOTSUP; 413 414 if (!mask) 415 mask = &rte_flow_item_udp_mask; 416 417 /* This is an exact match filter, both ports must be set */ 418 if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) { 419 FLOW_LOG(ERR, "UDP exact match src/dst addr"); 420 return ENOTSUP; 421 } 422 423 /* check that the suppied mask exactly matches capabilty */ 424 if (!mask_exact_match((const u8 *)&supported_mask, 425 (const u8 *)item->mask, sizeof(*mask))) { 426 FLOW_LOG(ERR, "UDP exact match mask"); 427 return ENOTSUP; 428 } 429 430 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 431 enic_5tup->src_port = spec->hdr.src_port; 432 enic_5tup->dst_port = spec->hdr.dst_port; 433 enic_5tup->protocol = PROTO_UDP; 434 435 return 0; 436 } 437 438 /** 439 * Copy TCP item into version 1 NIC filter. 440 * 441 * @param item[in] 442 * Item specification. 443 * @param enic_filter[out] 444 * Partially filled in NIC filter structure. 445 * @param inner_ofst[in] 446 * Should always be 0 for version 1. 447 */ 448 static int 449 enic_copy_item_tcp_v1(const struct rte_flow_item *item, 450 struct filter_v2 *enic_filter, u8 *inner_ofst) 451 { 452 const struct rte_flow_item_tcp *spec = item->spec; 453 const struct rte_flow_item_tcp *mask = item->mask; 454 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 455 struct tcp_hdr supported_mask = { 456 .src_port = 0xffff, 457 .dst_port = 0xffff, 458 }; 459 460 FLOW_TRACE(); 461 462 if (*inner_ofst) 463 return ENOTSUP; 464 465 if (!mask) 466 mask = &rte_flow_item_tcp_mask; 467 468 /* This is an exact match filter, both ports must be set */ 469 if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) { 470 FLOW_LOG(ERR, "TCPIPv4 exact match src/dst addr"); 471 return ENOTSUP; 472 } 473 474 /* check that the suppied mask exactly matches capabilty */ 475 if (!mask_exact_match((const u8 *)&supported_mask, 476 (const u8 *)item->mask, sizeof(*mask))) { 477 FLOW_LOG(ERR, "TCP exact match mask"); 478 return ENOTSUP; 479 } 480 481 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 482 enic_5tup->src_port = spec->hdr.src_port; 483 enic_5tup->dst_port = spec->hdr.dst_port; 484 enic_5tup->protocol = PROTO_TCP; 485 486 return 0; 487 } 488 489 /** 490 * Copy ETH item into version 2 NIC filter. 491 * 492 * @param item[in] 493 * Item specification. 494 * @param enic_filter[out] 495 * Partially filled in NIC filter structure. 496 * @param inner_ofst[in] 497 * If zero, this is an outer header. If non-zero, this is the offset into L5 498 * where the header begins. 499 */ 500 static int 501 enic_copy_item_eth_v2(const struct rte_flow_item *item, 502 struct filter_v2 *enic_filter, u8 *inner_ofst) 503 { 504 struct ether_hdr enic_spec; 505 struct ether_hdr enic_mask; 506 const struct rte_flow_item_eth *spec = item->spec; 507 const struct rte_flow_item_eth *mask = item->mask; 508 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 509 510 FLOW_TRACE(); 511 512 /* Match all if no spec */ 513 if (!spec) 514 return 0; 515 516 if (!mask) 517 mask = &rte_flow_item_eth_mask; 518 519 memcpy(enic_spec.d_addr.addr_bytes, spec->dst.addr_bytes, 520 ETHER_ADDR_LEN); 521 memcpy(enic_spec.s_addr.addr_bytes, spec->src.addr_bytes, 522 ETHER_ADDR_LEN); 523 524 memcpy(enic_mask.d_addr.addr_bytes, mask->dst.addr_bytes, 525 ETHER_ADDR_LEN); 526 memcpy(enic_mask.s_addr.addr_bytes, mask->src.addr_bytes, 527 ETHER_ADDR_LEN); 528 enic_spec.ether_type = spec->type; 529 enic_mask.ether_type = mask->type; 530 531 if (*inner_ofst == 0) { 532 /* outer header */ 533 memcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask, 534 sizeof(struct ether_hdr)); 535 memcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec, 536 sizeof(struct ether_hdr)); 537 } else { 538 /* inner header */ 539 if ((*inner_ofst + sizeof(struct ether_hdr)) > 540 FILTER_GENERIC_1_KEY_LEN) 541 return ENOTSUP; 542 /* Offset into L5 where inner Ethernet header goes */ 543 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 544 &enic_mask, sizeof(struct ether_hdr)); 545 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 546 &enic_spec, sizeof(struct ether_hdr)); 547 *inner_ofst += sizeof(struct ether_hdr); 548 } 549 return 0; 550 } 551 552 /** 553 * Copy VLAN item into version 2 NIC filter. 554 * 555 * @param item[in] 556 * Item specification. 557 * @param enic_filter[out] 558 * Partially filled in NIC filter structure. 559 * @param inner_ofst[in] 560 * If zero, this is an outer header. If non-zero, this is the offset into L5 561 * where the header begins. 562 */ 563 static int 564 enic_copy_item_vlan_v2(const struct rte_flow_item *item, 565 struct filter_v2 *enic_filter, u8 *inner_ofst) 566 { 567 const struct rte_flow_item_vlan *spec = item->spec; 568 const struct rte_flow_item_vlan *mask = item->mask; 569 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 570 571 FLOW_TRACE(); 572 573 /* Match all if no spec */ 574 if (!spec) 575 return 0; 576 577 /* Don't support filtering in tpid */ 578 if (mask) { 579 if (mask->tpid != 0) 580 return ENOTSUP; 581 } else { 582 mask = &rte_flow_item_vlan_mask; 583 RTE_ASSERT(mask->tpid == 0); 584 } 585 586 if (*inner_ofst == 0) { 587 /* Outer header. Use the vlan mask/val fields */ 588 gp->mask_vlan = mask->tci; 589 gp->val_vlan = spec->tci; 590 } else { 591 /* Inner header. Mask/Val start at *inner_ofst into L5 */ 592 if ((*inner_ofst + sizeof(struct vlan_hdr)) > 593 FILTER_GENERIC_1_KEY_LEN) 594 return ENOTSUP; 595 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 596 mask, sizeof(struct vlan_hdr)); 597 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 598 spec, sizeof(struct vlan_hdr)); 599 *inner_ofst += sizeof(struct vlan_hdr); 600 } 601 return 0; 602 } 603 604 /** 605 * Copy IPv4 item into version 2 NIC filter. 606 * 607 * @param item[in] 608 * Item specification. 609 * @param enic_filter[out] 610 * Partially filled in NIC filter structure. 611 * @param inner_ofst[in] 612 * Must be 0. Don't support inner IPv4 filtering. 613 */ 614 static int 615 enic_copy_item_ipv4_v2(const struct rte_flow_item *item, 616 struct filter_v2 *enic_filter, u8 *inner_ofst) 617 { 618 const struct rte_flow_item_ipv4 *spec = item->spec; 619 const struct rte_flow_item_ipv4 *mask = item->mask; 620 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 621 622 FLOW_TRACE(); 623 624 if (*inner_ofst == 0) { 625 /* Match IPv4 */ 626 gp->mask_flags |= FILTER_GENERIC_1_IPV4; 627 gp->val_flags |= FILTER_GENERIC_1_IPV4; 628 629 /* Match all if no spec */ 630 if (!spec) 631 return 0; 632 633 if (!mask) 634 mask = &rte_flow_item_ipv4_mask; 635 636 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr, 637 sizeof(struct ipv4_hdr)); 638 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr, 639 sizeof(struct ipv4_hdr)); 640 } else { 641 /* Inner IPv4 header. Mask/Val start at *inner_ofst into L5 */ 642 if ((*inner_ofst + sizeof(struct ipv4_hdr)) > 643 FILTER_GENERIC_1_KEY_LEN) 644 return ENOTSUP; 645 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 646 mask, sizeof(struct ipv4_hdr)); 647 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 648 spec, sizeof(struct ipv4_hdr)); 649 *inner_ofst += sizeof(struct ipv4_hdr); 650 } 651 return 0; 652 } 653 654 /** 655 * Copy IPv6 item into version 2 NIC filter. 656 * 657 * @param item[in] 658 * Item specification. 659 * @param enic_filter[out] 660 * Partially filled in NIC filter structure. 661 * @param inner_ofst[in] 662 * Must be 0. Don't support inner IPv6 filtering. 663 */ 664 static int 665 enic_copy_item_ipv6_v2(const struct rte_flow_item *item, 666 struct filter_v2 *enic_filter, u8 *inner_ofst) 667 { 668 const struct rte_flow_item_ipv6 *spec = item->spec; 669 const struct rte_flow_item_ipv6 *mask = item->mask; 670 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 671 672 FLOW_TRACE(); 673 674 /* Match IPv6 */ 675 gp->mask_flags |= FILTER_GENERIC_1_IPV6; 676 gp->val_flags |= FILTER_GENERIC_1_IPV6; 677 678 /* Match all if no spec */ 679 if (!spec) 680 return 0; 681 682 if (!mask) 683 mask = &rte_flow_item_ipv6_mask; 684 685 if (*inner_ofst == 0) { 686 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr, 687 sizeof(struct ipv6_hdr)); 688 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr, 689 sizeof(struct ipv6_hdr)); 690 } else { 691 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */ 692 if ((*inner_ofst + sizeof(struct ipv6_hdr)) > 693 FILTER_GENERIC_1_KEY_LEN) 694 return ENOTSUP; 695 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 696 mask, sizeof(struct ipv6_hdr)); 697 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 698 spec, sizeof(struct ipv6_hdr)); 699 *inner_ofst += sizeof(struct ipv6_hdr); 700 } 701 return 0; 702 } 703 704 /** 705 * Copy UDP item into version 2 NIC filter. 706 * 707 * @param item[in] 708 * Item specification. 709 * @param enic_filter[out] 710 * Partially filled in NIC filter structure. 711 * @param inner_ofst[in] 712 * Must be 0. Don't support inner UDP filtering. 713 */ 714 static int 715 enic_copy_item_udp_v2(const struct rte_flow_item *item, 716 struct filter_v2 *enic_filter, u8 *inner_ofst) 717 { 718 const struct rte_flow_item_udp *spec = item->spec; 719 const struct rte_flow_item_udp *mask = item->mask; 720 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 721 722 FLOW_TRACE(); 723 724 /* Match UDP */ 725 gp->mask_flags |= FILTER_GENERIC_1_UDP; 726 gp->val_flags |= FILTER_GENERIC_1_UDP; 727 728 /* Match all if no spec */ 729 if (!spec) 730 return 0; 731 732 if (!mask) 733 mask = &rte_flow_item_udp_mask; 734 735 if (*inner_ofst == 0) { 736 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 737 sizeof(struct udp_hdr)); 738 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 739 sizeof(struct udp_hdr)); 740 } else { 741 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */ 742 if ((*inner_ofst + sizeof(struct udp_hdr)) > 743 FILTER_GENERIC_1_KEY_LEN) 744 return ENOTSUP; 745 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 746 mask, sizeof(struct udp_hdr)); 747 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 748 spec, sizeof(struct udp_hdr)); 749 *inner_ofst += sizeof(struct udp_hdr); 750 } 751 return 0; 752 } 753 754 /** 755 * Copy TCP item into version 2 NIC filter. 756 * 757 * @param item[in] 758 * Item specification. 759 * @param enic_filter[out] 760 * Partially filled in NIC filter structure. 761 * @param inner_ofst[in] 762 * Must be 0. Don't support inner TCP filtering. 763 */ 764 static int 765 enic_copy_item_tcp_v2(const struct rte_flow_item *item, 766 struct filter_v2 *enic_filter, u8 *inner_ofst) 767 { 768 const struct rte_flow_item_tcp *spec = item->spec; 769 const struct rte_flow_item_tcp *mask = item->mask; 770 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 771 772 FLOW_TRACE(); 773 774 /* Match TCP */ 775 gp->mask_flags |= FILTER_GENERIC_1_TCP; 776 gp->val_flags |= FILTER_GENERIC_1_TCP; 777 778 /* Match all if no spec */ 779 if (!spec) 780 return 0; 781 782 if (!mask) 783 return ENOTSUP; 784 785 if (*inner_ofst == 0) { 786 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 787 sizeof(struct tcp_hdr)); 788 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 789 sizeof(struct tcp_hdr)); 790 } else { 791 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */ 792 if ((*inner_ofst + sizeof(struct tcp_hdr)) > 793 FILTER_GENERIC_1_KEY_LEN) 794 return ENOTSUP; 795 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst], 796 mask, sizeof(struct tcp_hdr)); 797 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst], 798 spec, sizeof(struct tcp_hdr)); 799 *inner_ofst += sizeof(struct tcp_hdr); 800 } 801 return 0; 802 } 803 804 /** 805 * Copy SCTP item into version 2 NIC filter. 806 * 807 * @param item[in] 808 * Item specification. 809 * @param enic_filter[out] 810 * Partially filled in NIC filter structure. 811 * @param inner_ofst[in] 812 * Must be 0. Don't support inner SCTP filtering. 813 */ 814 static int 815 enic_copy_item_sctp_v2(const struct rte_flow_item *item, 816 struct filter_v2 *enic_filter, u8 *inner_ofst) 817 { 818 const struct rte_flow_item_sctp *spec = item->spec; 819 const struct rte_flow_item_sctp *mask = item->mask; 820 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 821 822 FLOW_TRACE(); 823 824 if (*inner_ofst) 825 return ENOTSUP; 826 827 /* Match all if no spec */ 828 if (!spec) 829 return 0; 830 831 if (!mask) 832 mask = &rte_flow_item_sctp_mask; 833 834 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 835 sizeof(struct sctp_hdr)); 836 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 837 sizeof(struct sctp_hdr)); 838 return 0; 839 } 840 841 /** 842 * Copy UDP item into version 2 NIC filter. 843 * 844 * @param item[in] 845 * Item specification. 846 * @param enic_filter[out] 847 * Partially filled in NIC filter structure. 848 * @param inner_ofst[in] 849 * Must be 0. VxLAN headers always start at the beginning of L5. 850 */ 851 static int 852 enic_copy_item_vxlan_v2(const struct rte_flow_item *item, 853 struct filter_v2 *enic_filter, u8 *inner_ofst) 854 { 855 const struct rte_flow_item_vxlan *spec = item->spec; 856 const struct rte_flow_item_vxlan *mask = item->mask; 857 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 858 859 FLOW_TRACE(); 860 861 if (*inner_ofst) 862 return EINVAL; 863 864 /* Match all if no spec */ 865 if (!spec) 866 return 0; 867 868 if (!mask) 869 mask = &rte_flow_item_vxlan_mask; 870 871 memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, mask, 872 sizeof(struct vxlan_hdr)); 873 memcpy(gp->layer[FILTER_GENERIC_1_L5].val, spec, 874 sizeof(struct vxlan_hdr)); 875 876 *inner_ofst = sizeof(struct vxlan_hdr); 877 return 0; 878 } 879 880 /** 881 * Return 1 if current item is valid on top of the previous one. 882 * 883 * @param prev_item[in] 884 * The item before this one in the pattern or RTE_FLOW_ITEM_TYPE_END if this 885 * is the first item. 886 * @param item_info[in] 887 * Info about this item, like valid previous items. 888 * @param is_first[in] 889 * True if this the first item in the pattern. 890 */ 891 static int 892 item_stacking_valid(enum rte_flow_item_type prev_item, 893 const struct enic_items *item_info, u8 is_first_item) 894 { 895 enum rte_flow_item_type const *allowed_items = item_info->prev_items; 896 897 FLOW_TRACE(); 898 899 for (; *allowed_items != RTE_FLOW_ITEM_TYPE_END; allowed_items++) { 900 if (prev_item == *allowed_items) 901 return 1; 902 } 903 904 /* This is the first item in the stack. Check if that's cool */ 905 if (is_first_item && item_info->valid_start_item) 906 return 1; 907 908 return 0; 909 } 910 911 /** 912 * Build the intenal enic filter structure from the provided pattern. The 913 * pattern is validated as the items are copied. 914 * 915 * @param pattern[in] 916 * @param items_info[in] 917 * Info about this NICs item support, like valid previous items. 918 * @param enic_filter[out] 919 * NIC specfilc filters derived from the pattern. 920 * @param error[out] 921 */ 922 static int 923 enic_copy_filter(const struct rte_flow_item pattern[], 924 const struct enic_items *items_info, 925 struct filter_v2 *enic_filter, 926 struct rte_flow_error *error) 927 { 928 int ret; 929 const struct rte_flow_item *item = pattern; 930 u8 inner_ofst = 0; /* If encapsulated, ofst into L5 */ 931 enum rte_flow_item_type prev_item; 932 const struct enic_items *item_info; 933 934 u8 is_first_item = 1; 935 936 FLOW_TRACE(); 937 938 prev_item = 0; 939 940 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 941 /* Get info about how to validate and copy the item. If NULL 942 * is returned the nic does not support the item. 943 */ 944 if (item->type == RTE_FLOW_ITEM_TYPE_VOID) 945 continue; 946 947 item_info = &items_info[item->type]; 948 949 /* check to see if item stacking is valid */ 950 if (!item_stacking_valid(prev_item, item_info, is_first_item)) 951 goto stacking_error; 952 953 ret = item_info->copy_item(item, enic_filter, &inner_ofst); 954 if (ret) 955 goto item_not_supported; 956 prev_item = item->type; 957 is_first_item = 0; 958 } 959 return 0; 960 961 item_not_supported: 962 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_ITEM, 963 NULL, "enic type error"); 964 return -rte_errno; 965 966 stacking_error: 967 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 968 item, "stacking error"); 969 return -rte_errno; 970 } 971 972 /** 973 * Build the intenal version 1 NIC action structure from the provided pattern. 974 * The pattern is validated as the items are copied. 975 * 976 * @param actions[in] 977 * @param enic_action[out] 978 * NIC specfilc actions derived from the actions. 979 * @param error[out] 980 */ 981 static int 982 enic_copy_action_v1(const struct rte_flow_action actions[], 983 struct filter_action_v2 *enic_action) 984 { 985 FLOW_TRACE(); 986 987 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 988 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) 989 continue; 990 991 switch (actions->type) { 992 case RTE_FLOW_ACTION_TYPE_QUEUE: { 993 const struct rte_flow_action_queue *queue = 994 (const struct rte_flow_action_queue *) 995 actions->conf; 996 enic_action->rq_idx = 997 enic_rte_rq_idx_to_sop_idx(queue->index); 998 break; 999 } 1000 default: 1001 RTE_ASSERT(0); 1002 break; 1003 } 1004 } 1005 enic_action->type = FILTER_ACTION_RQ_STEERING; 1006 return 0; 1007 } 1008 1009 /** 1010 * Build the intenal version 2 NIC action structure from the provided pattern. 1011 * The pattern is validated as the items are copied. 1012 * 1013 * @param actions[in] 1014 * @param enic_action[out] 1015 * NIC specfilc actions derived from the actions. 1016 * @param error[out] 1017 */ 1018 static int 1019 enic_copy_action_v2(const struct rte_flow_action actions[], 1020 struct filter_action_v2 *enic_action) 1021 { 1022 FLOW_TRACE(); 1023 1024 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 1025 switch (actions->type) { 1026 case RTE_FLOW_ACTION_TYPE_QUEUE: { 1027 const struct rte_flow_action_queue *queue = 1028 (const struct rte_flow_action_queue *) 1029 actions->conf; 1030 enic_action->rq_idx = 1031 enic_rte_rq_idx_to_sop_idx(queue->index); 1032 enic_action->flags |= FILTER_ACTION_RQ_STEERING_FLAG; 1033 break; 1034 } 1035 case RTE_FLOW_ACTION_TYPE_MARK: { 1036 const struct rte_flow_action_mark *mark = 1037 (const struct rte_flow_action_mark *) 1038 actions->conf; 1039 1040 /* ENIC_MAGIC_FILTER_ID is reserved and is the highest 1041 * in the range of allows mark ids. 1042 */ 1043 if (mark->id >= ENIC_MAGIC_FILTER_ID) 1044 return EINVAL; 1045 enic_action->filter_id = mark->id; 1046 enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG; 1047 break; 1048 } 1049 case RTE_FLOW_ACTION_TYPE_FLAG: { 1050 enic_action->filter_id = ENIC_MAGIC_FILTER_ID; 1051 enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG; 1052 break; 1053 } 1054 case RTE_FLOW_ACTION_TYPE_VOID: 1055 continue; 1056 default: 1057 RTE_ASSERT(0); 1058 break; 1059 } 1060 } 1061 enic_action->type = FILTER_ACTION_V2; 1062 return 0; 1063 } 1064 1065 /** Check if the action is supported */ 1066 static int 1067 enic_match_action(const struct rte_flow_action *action, 1068 const enum rte_flow_action_type *supported_actions) 1069 { 1070 for (; *supported_actions != RTE_FLOW_ACTION_TYPE_END; 1071 supported_actions++) { 1072 if (action->type == *supported_actions) 1073 return 1; 1074 } 1075 return 0; 1076 } 1077 1078 /** Get the NIC filter capabilties structure */ 1079 static const struct enic_filter_cap * 1080 enic_get_filter_cap(struct enic *enic) 1081 { 1082 if (enic->flow_filter_mode) 1083 return &enic_filter_cap[enic->flow_filter_mode]; 1084 1085 return NULL; 1086 } 1087 1088 /** Get the actions for this NIC version. */ 1089 static const struct enic_action_cap * 1090 enic_get_action_cap(struct enic *enic) 1091 { 1092 static const struct enic_action_cap *ea; 1093 1094 if (enic->filter_tags) 1095 ea = &enic_action_cap[FILTER_ACTION_V2_ALL]; 1096 else 1097 ea = &enic_action_cap[FILTER_ACTION_RQ_STEERING_FLAG]; 1098 return ea; 1099 } 1100 1101 /* Debug function to dump internal NIC action structure. */ 1102 static void 1103 enic_dump_actions(const struct filter_action_v2 *ea) 1104 { 1105 if (ea->type == FILTER_ACTION_RQ_STEERING) { 1106 FLOW_LOG(INFO, "Action(V1), queue: %u\n", ea->rq_idx); 1107 } else if (ea->type == FILTER_ACTION_V2) { 1108 FLOW_LOG(INFO, "Actions(V2)\n"); 1109 if (ea->flags & FILTER_ACTION_RQ_STEERING_FLAG) 1110 FLOW_LOG(INFO, "\tqueue: %u\n", 1111 enic_sop_rq_idx_to_rte_idx(ea->rq_idx)); 1112 if (ea->flags & FILTER_ACTION_FILTER_ID_FLAG) 1113 FLOW_LOG(INFO, "\tfilter_id: %u\n", ea->filter_id); 1114 } 1115 } 1116 1117 /* Debug function to dump internal NIC filter structure. */ 1118 static void 1119 enic_dump_filter(const struct filter_v2 *filt) 1120 { 1121 const struct filter_generic_1 *gp; 1122 int i, j, mbyte; 1123 char buf[128], *bp; 1124 char ip4[16], ip6[16], udp[16], tcp[16], tcpudp[16], ip4csum[16]; 1125 char l4csum[16], ipfrag[16]; 1126 1127 switch (filt->type) { 1128 case FILTER_IPV4_5TUPLE: 1129 FLOW_LOG(INFO, "FILTER_IPV4_5TUPLE\n"); 1130 break; 1131 case FILTER_USNIC_IP: 1132 case FILTER_DPDK_1: 1133 /* FIXME: this should be a loop */ 1134 gp = &filt->u.generic_1; 1135 FLOW_LOG(INFO, "Filter: vlan: 0x%04x, mask: 0x%04x\n", 1136 gp->val_vlan, gp->mask_vlan); 1137 1138 if (gp->mask_flags & FILTER_GENERIC_1_IPV4) 1139 sprintf(ip4, "%s ", 1140 (gp->val_flags & FILTER_GENERIC_1_IPV4) 1141 ? "ip4(y)" : "ip4(n)"); 1142 else 1143 sprintf(ip4, "%s ", "ip4(x)"); 1144 1145 if (gp->mask_flags & FILTER_GENERIC_1_IPV6) 1146 sprintf(ip6, "%s ", 1147 (gp->val_flags & FILTER_GENERIC_1_IPV4) 1148 ? "ip6(y)" : "ip6(n)"); 1149 else 1150 sprintf(ip6, "%s ", "ip6(x)"); 1151 1152 if (gp->mask_flags & FILTER_GENERIC_1_UDP) 1153 sprintf(udp, "%s ", 1154 (gp->val_flags & FILTER_GENERIC_1_UDP) 1155 ? "udp(y)" : "udp(n)"); 1156 else 1157 sprintf(udp, "%s ", "udp(x)"); 1158 1159 if (gp->mask_flags & FILTER_GENERIC_1_TCP) 1160 sprintf(tcp, "%s ", 1161 (gp->val_flags & FILTER_GENERIC_1_TCP) 1162 ? "tcp(y)" : "tcp(n)"); 1163 else 1164 sprintf(tcp, "%s ", "tcp(x)"); 1165 1166 if (gp->mask_flags & FILTER_GENERIC_1_TCP_OR_UDP) 1167 sprintf(tcpudp, "%s ", 1168 (gp->val_flags & FILTER_GENERIC_1_TCP_OR_UDP) 1169 ? "tcpudp(y)" : "tcpudp(n)"); 1170 else 1171 sprintf(tcpudp, "%s ", "tcpudp(x)"); 1172 1173 if (gp->mask_flags & FILTER_GENERIC_1_IP4SUM_OK) 1174 sprintf(ip4csum, "%s ", 1175 (gp->val_flags & FILTER_GENERIC_1_IP4SUM_OK) 1176 ? "ip4csum(y)" : "ip4csum(n)"); 1177 else 1178 sprintf(ip4csum, "%s ", "ip4csum(x)"); 1179 1180 if (gp->mask_flags & FILTER_GENERIC_1_L4SUM_OK) 1181 sprintf(l4csum, "%s ", 1182 (gp->val_flags & FILTER_GENERIC_1_L4SUM_OK) 1183 ? "l4csum(y)" : "l4csum(n)"); 1184 else 1185 sprintf(l4csum, "%s ", "l4csum(x)"); 1186 1187 if (gp->mask_flags & FILTER_GENERIC_1_IPFRAG) 1188 sprintf(ipfrag, "%s ", 1189 (gp->val_flags & FILTER_GENERIC_1_IPFRAG) 1190 ? "ipfrag(y)" : "ipfrag(n)"); 1191 else 1192 sprintf(ipfrag, "%s ", "ipfrag(x)"); 1193 FLOW_LOG(INFO, "\tFlags: %s%s%s%s%s%s%s%s\n", ip4, ip6, udp, 1194 tcp, tcpudp, ip4csum, l4csum, ipfrag); 1195 1196 for (i = 0; i < FILTER_GENERIC_1_NUM_LAYERS; i++) { 1197 mbyte = FILTER_GENERIC_1_KEY_LEN - 1; 1198 while (mbyte && !gp->layer[i].mask[mbyte]) 1199 mbyte--; 1200 if (mbyte == 0) 1201 continue; 1202 1203 bp = buf; 1204 for (j = 0; j <= mbyte; j++) { 1205 sprintf(bp, "%02x", 1206 gp->layer[i].mask[j]); 1207 bp += 2; 1208 } 1209 *bp = '\0'; 1210 FLOW_LOG(INFO, "\tL%u mask: %s\n", i + 2, buf); 1211 bp = buf; 1212 for (j = 0; j <= mbyte; j++) { 1213 sprintf(bp, "%02x", 1214 gp->layer[i].val[j]); 1215 bp += 2; 1216 } 1217 *bp = '\0'; 1218 FLOW_LOG(INFO, "\tL%u val: %s\n", i + 2, buf); 1219 } 1220 break; 1221 default: 1222 FLOW_LOG(INFO, "FILTER UNKNOWN\n"); 1223 break; 1224 } 1225 } 1226 1227 /* Debug function to dump internal NIC flow structures. */ 1228 static void 1229 enic_dump_flow(const struct filter_action_v2 *ea, const struct filter_v2 *filt) 1230 { 1231 enic_dump_filter(filt); 1232 enic_dump_actions(ea); 1233 } 1234 1235 1236 /** 1237 * Internal flow parse/validate function. 1238 * 1239 * @param dev[in] 1240 * This device pointer. 1241 * @param pattern[in] 1242 * @param actions[in] 1243 * @param error[out] 1244 * @param enic_filter[out] 1245 * Internal NIC filter structure pointer. 1246 * @param enic_action[out] 1247 * Internal NIC action structure pointer. 1248 */ 1249 static int 1250 enic_flow_parse(struct rte_eth_dev *dev, 1251 const struct rte_flow_attr *attrs, 1252 const struct rte_flow_item pattern[], 1253 const struct rte_flow_action actions[], 1254 struct rte_flow_error *error, 1255 struct filter_v2 *enic_filter, 1256 struct filter_action_v2 *enic_action) 1257 { 1258 unsigned int ret = 0; 1259 struct enic *enic = pmd_priv(dev); 1260 const struct enic_filter_cap *enic_filter_cap; 1261 const struct enic_action_cap *enic_action_cap; 1262 const struct rte_flow_action *action; 1263 1264 FLOW_TRACE(); 1265 1266 memset(enic_filter, 0, sizeof(*enic_filter)); 1267 memset(enic_action, 0, sizeof(*enic_action)); 1268 1269 if (!pattern) { 1270 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, 1271 NULL, "No pattern specified"); 1272 return -rte_errno; 1273 } 1274 1275 if (!actions) { 1276 rte_flow_error_set(error, EINVAL, 1277 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 1278 NULL, "No action specified"); 1279 return -rte_errno; 1280 } 1281 1282 if (attrs) { 1283 if (attrs->group) { 1284 rte_flow_error_set(error, ENOTSUP, 1285 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 1286 NULL, 1287 "priority groups are not supported"); 1288 return -rte_errno; 1289 } else if (attrs->priority) { 1290 rte_flow_error_set(error, ENOTSUP, 1291 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1292 NULL, 1293 "priorities are not supported"); 1294 return -rte_errno; 1295 } else if (attrs->egress) { 1296 rte_flow_error_set(error, ENOTSUP, 1297 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 1298 NULL, 1299 "egress is not supported"); 1300 return -rte_errno; 1301 } else if (!attrs->ingress) { 1302 rte_flow_error_set(error, ENOTSUP, 1303 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1304 NULL, 1305 "only ingress is supported"); 1306 return -rte_errno; 1307 } 1308 1309 } else { 1310 rte_flow_error_set(error, EINVAL, 1311 RTE_FLOW_ERROR_TYPE_ATTR, 1312 NULL, "No attribute specified"); 1313 return -rte_errno; 1314 } 1315 1316 /* Verify Actions. */ 1317 enic_action_cap = enic_get_action_cap(enic); 1318 for (action = &actions[0]; action->type != RTE_FLOW_ACTION_TYPE_END; 1319 action++) { 1320 if (action->type == RTE_FLOW_ACTION_TYPE_VOID) 1321 continue; 1322 else if (!enic_match_action(action, enic_action_cap->actions)) 1323 break; 1324 } 1325 if (action->type != RTE_FLOW_ACTION_TYPE_END) { 1326 rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_ACTION, 1327 action, "Invalid action."); 1328 return -rte_errno; 1329 } 1330 ret = enic_action_cap->copy_fn(actions, enic_action); 1331 if (ret) { 1332 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, 1333 NULL, "Unsupported action."); 1334 return -rte_errno; 1335 } 1336 1337 /* Verify Flow items. If copying the filter from flow format to enic 1338 * format fails, the flow is not supported 1339 */ 1340 enic_filter_cap = enic_get_filter_cap(enic); 1341 if (enic_filter_cap == NULL) { 1342 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, 1343 NULL, "Flow API not available"); 1344 return -rte_errno; 1345 } 1346 enic_filter->type = enic->flow_filter_mode; 1347 ret = enic_copy_filter(pattern, enic_filter_cap->item_info, 1348 enic_filter, error); 1349 return ret; 1350 } 1351 1352 /** 1353 * Push filter/action to the NIC. 1354 * 1355 * @param enic[in] 1356 * Device structure pointer. 1357 * @param enic_filter[in] 1358 * Internal NIC filter structure pointer. 1359 * @param enic_action[in] 1360 * Internal NIC action structure pointer. 1361 * @param error[out] 1362 */ 1363 static struct rte_flow * 1364 enic_flow_add_filter(struct enic *enic, struct filter_v2 *enic_filter, 1365 struct filter_action_v2 *enic_action, 1366 struct rte_flow_error *error) 1367 { 1368 struct rte_flow *flow; 1369 int ret; 1370 u16 entry; 1371 1372 FLOW_TRACE(); 1373 1374 flow = rte_calloc(__func__, 1, sizeof(*flow), 0); 1375 if (!flow) { 1376 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, 1377 NULL, "cannot allocate flow memory"); 1378 return NULL; 1379 } 1380 1381 /* entry[in] is the queue id, entry[out] is the filter Id for delete */ 1382 entry = enic_action->rq_idx; 1383 ret = vnic_dev_classifier(enic->vdev, CLSF_ADD, &entry, enic_filter, 1384 enic_action); 1385 if (!ret) { 1386 flow->enic_filter_id = entry; 1387 flow->enic_filter = *enic_filter; 1388 } else { 1389 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, 1390 NULL, "vnic_dev_classifier error"); 1391 rte_free(flow); 1392 return NULL; 1393 } 1394 return flow; 1395 } 1396 1397 /** 1398 * Remove filter/action from the NIC. 1399 * 1400 * @param enic[in] 1401 * Device structure pointer. 1402 * @param filter_id[in] 1403 * Id of NIC filter. 1404 * @param enic_action[in] 1405 * Internal NIC action structure pointer. 1406 * @param error[out] 1407 */ 1408 static int 1409 enic_flow_del_filter(struct enic *enic, u16 filter_id, 1410 struct rte_flow_error *error) 1411 { 1412 int ret; 1413 1414 FLOW_TRACE(); 1415 1416 ret = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL, NULL); 1417 if (!ret) 1418 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE, 1419 NULL, "vnic_dev_classifier failed"); 1420 return ret; 1421 } 1422 1423 /* 1424 * The following functions are callbacks for Generic flow API. 1425 */ 1426 1427 /** 1428 * Validate a flow supported by the NIC. 1429 * 1430 * @see rte_flow_validate() 1431 * @see rte_flow_ops 1432 */ 1433 static int 1434 enic_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attrs, 1435 const struct rte_flow_item pattern[], 1436 const struct rte_flow_action actions[], 1437 struct rte_flow_error *error) 1438 { 1439 struct filter_v2 enic_filter; 1440 struct filter_action_v2 enic_action; 1441 int ret; 1442 1443 FLOW_TRACE(); 1444 1445 ret = enic_flow_parse(dev, attrs, pattern, actions, error, 1446 &enic_filter, &enic_action); 1447 if (!ret) 1448 enic_dump_flow(&enic_action, &enic_filter); 1449 return ret; 1450 } 1451 1452 /** 1453 * Create a flow supported by the NIC. 1454 * 1455 * @see rte_flow_create() 1456 * @see rte_flow_ops 1457 */ 1458 static struct rte_flow * 1459 enic_flow_create(struct rte_eth_dev *dev, 1460 const struct rte_flow_attr *attrs, 1461 const struct rte_flow_item pattern[], 1462 const struct rte_flow_action actions[], 1463 struct rte_flow_error *error) 1464 { 1465 int ret; 1466 struct filter_v2 enic_filter; 1467 struct filter_action_v2 enic_action; 1468 struct rte_flow *flow; 1469 struct enic *enic = pmd_priv(dev); 1470 1471 FLOW_TRACE(); 1472 1473 ret = enic_flow_parse(dev, attrs, pattern, actions, error, &enic_filter, 1474 &enic_action); 1475 if (ret < 0) 1476 return NULL; 1477 1478 rte_spinlock_lock(&enic->flows_lock); 1479 flow = enic_flow_add_filter(enic, &enic_filter, &enic_action, 1480 error); 1481 if (flow) 1482 LIST_INSERT_HEAD(&enic->flows, flow, next); 1483 rte_spinlock_unlock(&enic->flows_lock); 1484 1485 return flow; 1486 } 1487 1488 /** 1489 * Destroy a flow supported by the NIC. 1490 * 1491 * @see rte_flow_destroy() 1492 * @see rte_flow_ops 1493 */ 1494 static int 1495 enic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, 1496 __rte_unused struct rte_flow_error *error) 1497 { 1498 struct enic *enic = pmd_priv(dev); 1499 1500 FLOW_TRACE(); 1501 1502 rte_spinlock_lock(&enic->flows_lock); 1503 enic_flow_del_filter(enic, flow->enic_filter_id, error); 1504 LIST_REMOVE(flow, next); 1505 rte_spinlock_unlock(&enic->flows_lock); 1506 return 0; 1507 } 1508 1509 /** 1510 * Flush all flows on the device. 1511 * 1512 * @see rte_flow_flush() 1513 * @see rte_flow_ops 1514 */ 1515 static int 1516 enic_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error) 1517 { 1518 struct rte_flow *flow; 1519 struct enic *enic = pmd_priv(dev); 1520 1521 FLOW_TRACE(); 1522 1523 rte_spinlock_lock(&enic->flows_lock); 1524 1525 while (!LIST_EMPTY(&enic->flows)) { 1526 flow = LIST_FIRST(&enic->flows); 1527 enic_flow_del_filter(enic, flow->enic_filter_id, error); 1528 LIST_REMOVE(flow, next); 1529 } 1530 rte_spinlock_unlock(&enic->flows_lock); 1531 return 0; 1532 } 1533 1534 /** 1535 * Flow callback registration. 1536 * 1537 * @see rte_flow_ops 1538 */ 1539 const struct rte_flow_ops enic_flow_ops = { 1540 .validate = enic_flow_validate, 1541 .create = enic_flow_create, 1542 .destroy = enic_flow_destroy, 1543 .flush = enic_flow_flush, 1544 }; 1545