1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation 3 */ 4 5 #include <sys/queue.h> 6 #include <stdio.h> 7 #include <errno.h> 8 #include <stdint.h> 9 #include <stdarg.h> 10 11 #include <rte_common.h> 12 #include <rte_interrupts.h> 13 #include <rte_byteorder.h> 14 #include <rte_log.h> 15 #include <rte_debug.h> 16 #include <rte_pci.h> 17 #include <rte_ether.h> 18 #include <rte_ethdev_driver.h> 19 #include <rte_ethdev_pci.h> 20 #include <rte_memory.h> 21 #include <rte_eal.h> 22 #include <rte_atomic.h> 23 #include <rte_malloc.h> 24 #include <rte_dev.h> 25 #include <rte_flow.h> 26 #include <rte_flow_driver.h> 27 28 #include "e1000_logs.h" 29 #include "base/e1000_api.h" 30 #include "e1000_ethdev.h" 31 32 #define NEXT_ITEM_OF_PATTERN(item, pattern, index) \ 33 do { \ 34 item = (pattern) + (index); \ 35 while (item->type == RTE_FLOW_ITEM_TYPE_VOID) { \ 36 (index)++; \ 37 item = (pattern) + (index); \ 38 } \ 39 } while (0) 40 41 #define NEXT_ITEM_OF_ACTION(act, actions, index) \ 42 do { \ 43 act = (actions) + (index); \ 44 while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {\ 45 (index)++; \ 46 act = (actions) + (index); \ 47 } \ 48 } while (0) 49 50 #define IGB_FLEX_RAW_NUM 12 51 52 /** 53 * Please aware there's an asumption for all the parsers. 54 * rte_flow_item is using big endian, rte_flow_attr and 55 * rte_flow_action are using CPU order. 56 * Because the pattern is used to describe the packets, 57 * normally the packets should use network order. 58 */ 59 60 /** 61 * Parse the rule to see if it is a n-tuple rule. 62 * And get the n-tuple filter info BTW. 63 * pattern: 64 * The first not void item can be ETH or IPV4. 65 * The second not void item must be IPV4 if the first one is ETH. 66 * The third not void item must be UDP or TCP or SCTP 67 * The next not void item must be END. 68 * action: 69 * The first not void action should be QUEUE. 70 * The next not void action should be END. 71 * pattern example: 72 * ITEM Spec Mask 73 * ETH NULL NULL 74 * IPV4 src_addr 192.168.1.20 0xFFFFFFFF 75 * dst_addr 192.167.3.50 0xFFFFFFFF 76 * next_proto_id 17 0xFF 77 * UDP/TCP/ src_port 80 0xFFFF 78 * SCTP dst_port 80 0xFFFF 79 * END 80 * other members in mask and spec should set to 0x00. 81 * item->last should be NULL. 82 */ 83 static int 84 cons_parse_ntuple_filter(const struct rte_flow_attr *attr, 85 const struct rte_flow_item pattern[], 86 const struct rte_flow_action actions[], 87 struct rte_eth_ntuple_filter *filter, 88 struct rte_flow_error *error) 89 { 90 const struct rte_flow_item *item; 91 const struct rte_flow_action *act; 92 const struct rte_flow_item_ipv4 *ipv4_spec; 93 const struct rte_flow_item_ipv4 *ipv4_mask; 94 const struct rte_flow_item_tcp *tcp_spec; 95 const struct rte_flow_item_tcp *tcp_mask; 96 const struct rte_flow_item_udp *udp_spec; 97 const struct rte_flow_item_udp *udp_mask; 98 const struct rte_flow_item_sctp *sctp_spec; 99 const struct rte_flow_item_sctp *sctp_mask; 100 uint32_t index; 101 102 if (!pattern) { 103 rte_flow_error_set(error, 104 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, 105 NULL, "NULL pattern."); 106 return -rte_errno; 107 } 108 109 if (!actions) { 110 rte_flow_error_set(error, EINVAL, 111 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 112 NULL, "NULL action."); 113 return -rte_errno; 114 } 115 if (!attr) { 116 rte_flow_error_set(error, EINVAL, 117 RTE_FLOW_ERROR_TYPE_ATTR, 118 NULL, "NULL attribute."); 119 return -rte_errno; 120 } 121 122 /* parse pattern */ 123 index = 0; 124 125 /* the first not void item can be MAC or IPv4 */ 126 NEXT_ITEM_OF_PATTERN(item, pattern, index); 127 128 if (item->type != RTE_FLOW_ITEM_TYPE_ETH && 129 item->type != RTE_FLOW_ITEM_TYPE_IPV4) { 130 rte_flow_error_set(error, EINVAL, 131 RTE_FLOW_ERROR_TYPE_ITEM, 132 item, "Not supported by ntuple filter"); 133 return -rte_errno; 134 } 135 /* Skip Ethernet */ 136 if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { 137 /*Not supported last point for range*/ 138 if (item->last) { 139 rte_flow_error_set(error, 140 EINVAL, 141 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 142 item, "Not supported last point for range"); 143 return -rte_errno; 144 } 145 /* if the first item is MAC, the content should be NULL */ 146 if (item->spec || item->mask) { 147 rte_flow_error_set(error, EINVAL, 148 RTE_FLOW_ERROR_TYPE_ITEM, 149 item, "Not supported by ntuple filter"); 150 return -rte_errno; 151 } 152 /* check if the next not void item is IPv4 */ 153 index++; 154 NEXT_ITEM_OF_PATTERN(item, pattern, index); 155 if (item->type != RTE_FLOW_ITEM_TYPE_IPV4) { 156 rte_flow_error_set(error, 157 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 158 item, "Not supported by ntuple filter"); 159 return -rte_errno; 160 } 161 } 162 163 /* get the IPv4 info */ 164 if (!item->spec || !item->mask) { 165 rte_flow_error_set(error, EINVAL, 166 RTE_FLOW_ERROR_TYPE_ITEM, 167 item, "Invalid ntuple mask"); 168 return -rte_errno; 169 } 170 /* Not supported last point for range */ 171 if (item->last) { 172 rte_flow_error_set(error, EINVAL, 173 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 174 item, "Not supported last point for range"); 175 return -rte_errno; 176 } 177 178 ipv4_mask = item->mask; 179 /** 180 * Only support src & dst addresses, protocol, 181 * others should be masked. 182 */ 183 184 if (ipv4_mask->hdr.version_ihl || 185 ipv4_mask->hdr.type_of_service || 186 ipv4_mask->hdr.total_length || 187 ipv4_mask->hdr.packet_id || 188 ipv4_mask->hdr.fragment_offset || 189 ipv4_mask->hdr.time_to_live || 190 ipv4_mask->hdr.hdr_checksum) { 191 rte_flow_error_set(error, 192 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 193 item, "Not supported by ntuple filter"); 194 return -rte_errno; 195 } 196 197 filter->dst_ip_mask = ipv4_mask->hdr.dst_addr; 198 filter->src_ip_mask = ipv4_mask->hdr.src_addr; 199 filter->proto_mask = ipv4_mask->hdr.next_proto_id; 200 201 ipv4_spec = item->spec; 202 filter->dst_ip = ipv4_spec->hdr.dst_addr; 203 filter->src_ip = ipv4_spec->hdr.src_addr; 204 filter->proto = ipv4_spec->hdr.next_proto_id; 205 206 /* check if the next not void item is TCP or UDP or SCTP */ 207 index++; 208 NEXT_ITEM_OF_PATTERN(item, pattern, index); 209 if (item->type != RTE_FLOW_ITEM_TYPE_TCP && 210 item->type != RTE_FLOW_ITEM_TYPE_UDP && 211 item->type != RTE_FLOW_ITEM_TYPE_SCTP) { 212 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 213 rte_flow_error_set(error, EINVAL, 214 RTE_FLOW_ERROR_TYPE_ITEM, 215 item, "Not supported by ntuple filter"); 216 return -rte_errno; 217 } 218 219 /* Not supported last point for range */ 220 if (item->last) { 221 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 222 rte_flow_error_set(error, EINVAL, 223 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 224 item, "Not supported last point for range"); 225 return -rte_errno; 226 } 227 228 /* get the TCP/UDP/SCTP info */ 229 if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { 230 if (item->spec && item->mask) { 231 tcp_mask = item->mask; 232 233 /** 234 * Only support src & dst ports, tcp flags, 235 * others should be masked. 236 */ 237 if (tcp_mask->hdr.sent_seq || 238 tcp_mask->hdr.recv_ack || 239 tcp_mask->hdr.data_off || 240 tcp_mask->hdr.rx_win || 241 tcp_mask->hdr.cksum || 242 tcp_mask->hdr.tcp_urp) { 243 memset(filter, 0, 244 sizeof(struct rte_eth_ntuple_filter)); 245 rte_flow_error_set(error, EINVAL, 246 RTE_FLOW_ERROR_TYPE_ITEM, 247 item, "Not supported by ntuple filter"); 248 return -rte_errno; 249 } 250 251 filter->dst_port_mask = tcp_mask->hdr.dst_port; 252 filter->src_port_mask = tcp_mask->hdr.src_port; 253 if (tcp_mask->hdr.tcp_flags == 0xFF) { 254 filter->flags |= RTE_NTUPLE_FLAGS_TCP_FLAG; 255 } else if (!tcp_mask->hdr.tcp_flags) { 256 filter->flags &= ~RTE_NTUPLE_FLAGS_TCP_FLAG; 257 } else { 258 memset(filter, 0, 259 sizeof(struct rte_eth_ntuple_filter)); 260 rte_flow_error_set(error, EINVAL, 261 RTE_FLOW_ERROR_TYPE_ITEM, 262 item, "Not supported by ntuple filter"); 263 return -rte_errno; 264 } 265 266 tcp_spec = item->spec; 267 filter->dst_port = tcp_spec->hdr.dst_port; 268 filter->src_port = tcp_spec->hdr.src_port; 269 filter->tcp_flags = tcp_spec->hdr.tcp_flags; 270 } 271 } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { 272 if (item->spec && item->mask) { 273 udp_mask = item->mask; 274 275 /** 276 * Only support src & dst ports, 277 * others should be masked. 278 */ 279 if (udp_mask->hdr.dgram_len || 280 udp_mask->hdr.dgram_cksum) { 281 memset(filter, 0, 282 sizeof(struct rte_eth_ntuple_filter)); 283 rte_flow_error_set(error, EINVAL, 284 RTE_FLOW_ERROR_TYPE_ITEM, 285 item, "Not supported by ntuple filter"); 286 return -rte_errno; 287 } 288 289 filter->dst_port_mask = udp_mask->hdr.dst_port; 290 filter->src_port_mask = udp_mask->hdr.src_port; 291 292 udp_spec = item->spec; 293 filter->dst_port = udp_spec->hdr.dst_port; 294 filter->src_port = udp_spec->hdr.src_port; 295 } 296 } else { 297 if (item->spec && item->mask) { 298 sctp_mask = item->mask; 299 300 /** 301 * Only support src & dst ports, 302 * others should be masked. 303 */ 304 if (sctp_mask->hdr.tag || 305 sctp_mask->hdr.cksum) { 306 memset(filter, 0, 307 sizeof(struct rte_eth_ntuple_filter)); 308 rte_flow_error_set(error, EINVAL, 309 RTE_FLOW_ERROR_TYPE_ITEM, 310 item, "Not supported by ntuple filter"); 311 return -rte_errno; 312 } 313 314 filter->dst_port_mask = sctp_mask->hdr.dst_port; 315 filter->src_port_mask = sctp_mask->hdr.src_port; 316 317 sctp_spec = (const struct rte_flow_item_sctp *) 318 item->spec; 319 filter->dst_port = sctp_spec->hdr.dst_port; 320 filter->src_port = sctp_spec->hdr.src_port; 321 } 322 } 323 /* check if the next not void item is END */ 324 index++; 325 NEXT_ITEM_OF_PATTERN(item, pattern, index); 326 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 327 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 328 rte_flow_error_set(error, EINVAL, 329 RTE_FLOW_ERROR_TYPE_ITEM, 330 item, "Not supported by ntuple filter"); 331 return -rte_errno; 332 } 333 334 /* parse action */ 335 index = 0; 336 337 /** 338 * n-tuple only supports forwarding, 339 * check if the first not void action is QUEUE. 340 */ 341 NEXT_ITEM_OF_ACTION(act, actions, index); 342 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) { 343 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 344 rte_flow_error_set(error, EINVAL, 345 RTE_FLOW_ERROR_TYPE_ACTION, 346 item, "Not supported action."); 347 return -rte_errno; 348 } 349 filter->queue = 350 ((const struct rte_flow_action_queue *)act->conf)->index; 351 352 /* check if the next not void item is END */ 353 index++; 354 NEXT_ITEM_OF_ACTION(act, actions, index); 355 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 356 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 357 rte_flow_error_set(error, EINVAL, 358 RTE_FLOW_ERROR_TYPE_ACTION, 359 act, "Not supported action."); 360 return -rte_errno; 361 } 362 363 /* parse attr */ 364 /* must be input direction */ 365 if (!attr->ingress) { 366 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 367 rte_flow_error_set(error, EINVAL, 368 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 369 attr, "Only support ingress."); 370 return -rte_errno; 371 } 372 373 /* not supported */ 374 if (attr->egress) { 375 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 376 rte_flow_error_set(error, EINVAL, 377 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 378 attr, "Not support egress."); 379 return -rte_errno; 380 } 381 382 if (attr->priority > 0xFFFF) { 383 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 384 rte_flow_error_set(error, EINVAL, 385 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 386 attr, "Error priority."); 387 return -rte_errno; 388 } 389 filter->priority = (uint16_t)attr->priority; 390 391 return 0; 392 } 393 394 /* a specific function for igb because the flags is specific */ 395 static int 396 igb_parse_ntuple_filter(struct rte_eth_dev *dev, 397 const struct rte_flow_attr *attr, 398 const struct rte_flow_item pattern[], 399 const struct rte_flow_action actions[], 400 struct rte_eth_ntuple_filter *filter, 401 struct rte_flow_error *error) 402 { 403 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 404 int ret; 405 406 MAC_TYPE_FILTER_SUP(hw->mac.type); 407 408 ret = cons_parse_ntuple_filter(attr, pattern, actions, filter, error); 409 410 if (ret) 411 return ret; 412 413 /* Igb doesn't support many priorities. */ 414 if (filter->priority > E1000_2TUPLE_MAX_PRI) { 415 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 416 rte_flow_error_set(error, EINVAL, 417 RTE_FLOW_ERROR_TYPE_ITEM, 418 NULL, "Priority not supported by ntuple filter"); 419 return -rte_errno; 420 } 421 422 if (hw->mac.type == e1000_82576) { 423 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576) { 424 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 425 rte_flow_error_set(error, EINVAL, 426 RTE_FLOW_ERROR_TYPE_ITEM, 427 NULL, "queue number not " 428 "supported by ntuple filter"); 429 return -rte_errno; 430 } 431 filter->flags |= RTE_5TUPLE_FLAGS; 432 } else { 433 if (filter->src_ip_mask || filter->dst_ip_mask || 434 filter->src_port_mask) { 435 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 436 rte_flow_error_set(error, EINVAL, 437 RTE_FLOW_ERROR_TYPE_ITEM, 438 NULL, "only two tuple are " 439 "supported by this filter"); 440 return -rte_errno; 441 } 442 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) { 443 memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); 444 rte_flow_error_set(error, EINVAL, 445 RTE_FLOW_ERROR_TYPE_ITEM, 446 NULL, "queue number not " 447 "supported by ntuple filter"); 448 return -rte_errno; 449 } 450 filter->flags |= RTE_2TUPLE_FLAGS; 451 } 452 453 return 0; 454 } 455 456 /** 457 * Parse the rule to see if it is a ethertype rule. 458 * And get the ethertype filter info BTW. 459 * pattern: 460 * The first not void item can be ETH. 461 * The next not void item must be END. 462 * action: 463 * The first not void action should be QUEUE. 464 * The next not void action should be END. 465 * pattern example: 466 * ITEM Spec Mask 467 * ETH type 0x0807 0xFFFF 468 * END 469 * other members in mask and spec should set to 0x00. 470 * item->last should be NULL. 471 */ 472 static int 473 cons_parse_ethertype_filter(const struct rte_flow_attr *attr, 474 const struct rte_flow_item *pattern, 475 const struct rte_flow_action *actions, 476 struct rte_eth_ethertype_filter *filter, 477 struct rte_flow_error *error) 478 { 479 const struct rte_flow_item *item; 480 const struct rte_flow_action *act; 481 const struct rte_flow_item_eth *eth_spec; 482 const struct rte_flow_item_eth *eth_mask; 483 const struct rte_flow_action_queue *act_q; 484 uint32_t index; 485 486 if (!pattern) { 487 rte_flow_error_set(error, EINVAL, 488 RTE_FLOW_ERROR_TYPE_ITEM_NUM, 489 NULL, "NULL pattern."); 490 return -rte_errno; 491 } 492 493 if (!actions) { 494 rte_flow_error_set(error, EINVAL, 495 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 496 NULL, "NULL action."); 497 return -rte_errno; 498 } 499 500 if (!attr) { 501 rte_flow_error_set(error, EINVAL, 502 RTE_FLOW_ERROR_TYPE_ATTR, 503 NULL, "NULL attribute."); 504 return -rte_errno; 505 } 506 507 /* Parse pattern */ 508 index = 0; 509 510 /* The first non-void item should be MAC. */ 511 NEXT_ITEM_OF_PATTERN(item, pattern, index); 512 if (item->type != RTE_FLOW_ITEM_TYPE_ETH) { 513 rte_flow_error_set(error, EINVAL, 514 RTE_FLOW_ERROR_TYPE_ITEM, 515 item, "Not supported by ethertype filter"); 516 return -rte_errno; 517 } 518 519 /*Not supported last point for range*/ 520 if (item->last) { 521 rte_flow_error_set(error, EINVAL, 522 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 523 item, "Not supported last point for range"); 524 return -rte_errno; 525 } 526 527 /* Get the MAC info. */ 528 if (!item->spec || !item->mask) { 529 rte_flow_error_set(error, EINVAL, 530 RTE_FLOW_ERROR_TYPE_ITEM, 531 item, "Not supported by ethertype filter"); 532 return -rte_errno; 533 } 534 535 eth_spec = item->spec; 536 eth_mask = item->mask; 537 538 /* Mask bits of source MAC address must be full of 0. 539 * Mask bits of destination MAC address must be full 540 * of 1 or full of 0. 541 */ 542 if (!is_zero_ether_addr(ð_mask->src) || 543 (!is_zero_ether_addr(ð_mask->dst) && 544 !is_broadcast_ether_addr(ð_mask->dst))) { 545 rte_flow_error_set(error, EINVAL, 546 RTE_FLOW_ERROR_TYPE_ITEM, 547 item, "Invalid ether address mask"); 548 return -rte_errno; 549 } 550 551 if ((eth_mask->type & UINT16_MAX) != UINT16_MAX) { 552 rte_flow_error_set(error, EINVAL, 553 RTE_FLOW_ERROR_TYPE_ITEM, 554 item, "Invalid ethertype mask"); 555 return -rte_errno; 556 } 557 558 /* If mask bits of destination MAC address 559 * are full of 1, set RTE_ETHTYPE_FLAGS_MAC. 560 */ 561 if (is_broadcast_ether_addr(ð_mask->dst)) { 562 filter->mac_addr = eth_spec->dst; 563 filter->flags |= RTE_ETHTYPE_FLAGS_MAC; 564 } else { 565 filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC; 566 } 567 filter->ether_type = rte_be_to_cpu_16(eth_spec->type); 568 569 /* Check if the next non-void item is END. */ 570 index++; 571 NEXT_ITEM_OF_PATTERN(item, pattern, index); 572 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 573 rte_flow_error_set(error, EINVAL, 574 RTE_FLOW_ERROR_TYPE_ITEM, 575 item, "Not supported by ethertype filter."); 576 return -rte_errno; 577 } 578 579 /* Parse action */ 580 581 index = 0; 582 /* Check if the first non-void action is QUEUE or DROP. */ 583 NEXT_ITEM_OF_ACTION(act, actions, index); 584 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE && 585 act->type != RTE_FLOW_ACTION_TYPE_DROP) { 586 rte_flow_error_set(error, EINVAL, 587 RTE_FLOW_ERROR_TYPE_ACTION, 588 act, "Not supported action."); 589 return -rte_errno; 590 } 591 592 if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) { 593 act_q = (const struct rte_flow_action_queue *)act->conf; 594 filter->queue = act_q->index; 595 } else { 596 filter->flags |= RTE_ETHTYPE_FLAGS_DROP; 597 } 598 599 /* Check if the next non-void item is END */ 600 index++; 601 NEXT_ITEM_OF_ACTION(act, actions, index); 602 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 603 rte_flow_error_set(error, EINVAL, 604 RTE_FLOW_ERROR_TYPE_ACTION, 605 act, "Not supported action."); 606 return -rte_errno; 607 } 608 609 /* Parse attr */ 610 /* Must be input direction */ 611 if (!attr->ingress) { 612 rte_flow_error_set(error, EINVAL, 613 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 614 attr, "Only support ingress."); 615 return -rte_errno; 616 } 617 618 /* Not supported */ 619 if (attr->egress) { 620 rte_flow_error_set(error, EINVAL, 621 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 622 attr, "Not support egress."); 623 return -rte_errno; 624 } 625 626 /* Not supported */ 627 if (attr->priority) { 628 rte_flow_error_set(error, EINVAL, 629 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 630 attr, "Not support priority."); 631 return -rte_errno; 632 } 633 634 /* Not supported */ 635 if (attr->group) { 636 rte_flow_error_set(error, EINVAL, 637 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 638 attr, "Not support group."); 639 return -rte_errno; 640 } 641 642 return 0; 643 } 644 645 static int 646 igb_parse_ethertype_filter(struct rte_eth_dev *dev, 647 const struct rte_flow_attr *attr, 648 const struct rte_flow_item pattern[], 649 const struct rte_flow_action actions[], 650 struct rte_eth_ethertype_filter *filter, 651 struct rte_flow_error *error) 652 { 653 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 654 int ret; 655 656 MAC_TYPE_FILTER_SUP(hw->mac.type); 657 658 ret = cons_parse_ethertype_filter(attr, pattern, 659 actions, filter, error); 660 661 if (ret) 662 return ret; 663 664 if (hw->mac.type == e1000_82576) { 665 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576) { 666 memset(filter, 0, sizeof( 667 struct rte_eth_ethertype_filter)); 668 rte_flow_error_set(error, EINVAL, 669 RTE_FLOW_ERROR_TYPE_ITEM, 670 NULL, "queue number not supported " 671 "by ethertype filter"); 672 return -rte_errno; 673 } 674 } else { 675 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) { 676 memset(filter, 0, sizeof( 677 struct rte_eth_ethertype_filter)); 678 rte_flow_error_set(error, EINVAL, 679 RTE_FLOW_ERROR_TYPE_ITEM, 680 NULL, "queue number not supported " 681 "by ethertype filter"); 682 return -rte_errno; 683 } 684 } 685 686 if (filter->ether_type == ETHER_TYPE_IPv4 || 687 filter->ether_type == ETHER_TYPE_IPv6) { 688 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 689 rte_flow_error_set(error, EINVAL, 690 RTE_FLOW_ERROR_TYPE_ITEM, 691 NULL, "IPv4/IPv6 not supported by ethertype filter"); 692 return -rte_errno; 693 } 694 695 if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { 696 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 697 rte_flow_error_set(error, EINVAL, 698 RTE_FLOW_ERROR_TYPE_ITEM, 699 NULL, "mac compare is unsupported"); 700 return -rte_errno; 701 } 702 703 if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { 704 memset(filter, 0, sizeof(struct rte_eth_ethertype_filter)); 705 rte_flow_error_set(error, EINVAL, 706 RTE_FLOW_ERROR_TYPE_ITEM, 707 NULL, "drop option is unsupported"); 708 return -rte_errno; 709 } 710 711 return 0; 712 } 713 714 /** 715 * Parse the rule to see if it is a TCP SYN rule. 716 * And get the TCP SYN filter info BTW. 717 * pattern: 718 * The first not void item must be ETH. 719 * The second not void item must be IPV4 or IPV6. 720 * The third not void item must be TCP. 721 * The next not void item must be END. 722 * action: 723 * The first not void action should be QUEUE. 724 * The next not void action should be END. 725 * pattern example: 726 * ITEM Spec Mask 727 * ETH NULL NULL 728 * IPV4/IPV6 NULL NULL 729 * TCP tcp_flags 0x02 0xFF 730 * END 731 * other members in mask and spec should set to 0x00. 732 * item->last should be NULL. 733 */ 734 static int 735 cons_parse_syn_filter(const struct rte_flow_attr *attr, 736 const struct rte_flow_item pattern[], 737 const struct rte_flow_action actions[], 738 struct rte_eth_syn_filter *filter, 739 struct rte_flow_error *error) 740 { 741 const struct rte_flow_item *item; 742 const struct rte_flow_action *act; 743 const struct rte_flow_item_tcp *tcp_spec; 744 const struct rte_flow_item_tcp *tcp_mask; 745 const struct rte_flow_action_queue *act_q; 746 uint32_t index; 747 748 if (!pattern) { 749 rte_flow_error_set(error, EINVAL, 750 RTE_FLOW_ERROR_TYPE_ITEM_NUM, 751 NULL, "NULL pattern."); 752 return -rte_errno; 753 } 754 755 if (!actions) { 756 rte_flow_error_set(error, EINVAL, 757 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 758 NULL, "NULL action."); 759 return -rte_errno; 760 } 761 762 if (!attr) { 763 rte_flow_error_set(error, EINVAL, 764 RTE_FLOW_ERROR_TYPE_ATTR, 765 NULL, "NULL attribute."); 766 return -rte_errno; 767 } 768 769 /* parse pattern */ 770 index = 0; 771 772 /* the first not void item should be MAC or IPv4 or IPv6 or TCP */ 773 NEXT_ITEM_OF_PATTERN(item, pattern, index); 774 if (item->type != RTE_FLOW_ITEM_TYPE_ETH && 775 item->type != RTE_FLOW_ITEM_TYPE_IPV4 && 776 item->type != RTE_FLOW_ITEM_TYPE_IPV6 && 777 item->type != RTE_FLOW_ITEM_TYPE_TCP) { 778 rte_flow_error_set(error, EINVAL, 779 RTE_FLOW_ERROR_TYPE_ITEM, 780 item, "Not supported by syn filter"); 781 return -rte_errno; 782 } 783 /*Not supported last point for range*/ 784 if (item->last) { 785 rte_flow_error_set(error, EINVAL, 786 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 787 item, "Not supported last point for range"); 788 return -rte_errno; 789 } 790 791 /* Skip Ethernet */ 792 if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { 793 /* if the item is MAC, the content should be NULL */ 794 if (item->spec || item->mask) { 795 rte_flow_error_set(error, EINVAL, 796 RTE_FLOW_ERROR_TYPE_ITEM, 797 item, "Invalid SYN address mask"); 798 return -rte_errno; 799 } 800 801 /* check if the next not void item is IPv4 or IPv6 */ 802 index++; 803 NEXT_ITEM_OF_PATTERN(item, pattern, index); 804 if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 && 805 item->type != RTE_FLOW_ITEM_TYPE_IPV6) { 806 rte_flow_error_set(error, EINVAL, 807 RTE_FLOW_ERROR_TYPE_ITEM, 808 item, "Not supported by syn filter"); 809 return -rte_errno; 810 } 811 } 812 813 /* Skip IP */ 814 if (item->type == RTE_FLOW_ITEM_TYPE_IPV4 || 815 item->type == RTE_FLOW_ITEM_TYPE_IPV6) { 816 /* if the item is IP, the content should be NULL */ 817 if (item->spec || item->mask) { 818 rte_flow_error_set(error, EINVAL, 819 RTE_FLOW_ERROR_TYPE_ITEM, 820 item, "Invalid SYN mask"); 821 return -rte_errno; 822 } 823 824 /* check if the next not void item is TCP */ 825 index++; 826 NEXT_ITEM_OF_PATTERN(item, pattern, index); 827 if (item->type != RTE_FLOW_ITEM_TYPE_TCP) { 828 rte_flow_error_set(error, EINVAL, 829 RTE_FLOW_ERROR_TYPE_ITEM, 830 item, "Not supported by syn filter"); 831 return -rte_errno; 832 } 833 } 834 835 /* Get the TCP info. Only support SYN. */ 836 if (!item->spec || !item->mask) { 837 rte_flow_error_set(error, EINVAL, 838 RTE_FLOW_ERROR_TYPE_ITEM, 839 item, "Invalid SYN mask"); 840 return -rte_errno; 841 } 842 /*Not supported last point for range*/ 843 if (item->last) { 844 rte_flow_error_set(error, EINVAL, 845 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 846 item, "Not supported last point for range"); 847 return -rte_errno; 848 } 849 850 tcp_spec = item->spec; 851 tcp_mask = item->mask; 852 if (!(tcp_spec->hdr.tcp_flags & TCP_SYN_FLAG) || 853 tcp_mask->hdr.src_port || 854 tcp_mask->hdr.dst_port || 855 tcp_mask->hdr.sent_seq || 856 tcp_mask->hdr.recv_ack || 857 tcp_mask->hdr.data_off || 858 tcp_mask->hdr.tcp_flags != TCP_SYN_FLAG || 859 tcp_mask->hdr.rx_win || 860 tcp_mask->hdr.cksum || 861 tcp_mask->hdr.tcp_urp) { 862 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 863 rte_flow_error_set(error, EINVAL, 864 RTE_FLOW_ERROR_TYPE_ITEM, 865 item, "Not supported by syn filter"); 866 return -rte_errno; 867 } 868 869 /* check if the next not void item is END */ 870 index++; 871 NEXT_ITEM_OF_PATTERN(item, pattern, index); 872 if (item->type != RTE_FLOW_ITEM_TYPE_END) { 873 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 874 rte_flow_error_set(error, EINVAL, 875 RTE_FLOW_ERROR_TYPE_ITEM, 876 item, "Not supported by syn filter"); 877 return -rte_errno; 878 } 879 880 /* parse action */ 881 index = 0; 882 883 /* check if the first not void action is QUEUE. */ 884 NEXT_ITEM_OF_ACTION(act, actions, index); 885 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) { 886 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 887 rte_flow_error_set(error, EINVAL, 888 RTE_FLOW_ERROR_TYPE_ACTION, 889 act, "Not supported action."); 890 return -rte_errno; 891 } 892 893 act_q = (const struct rte_flow_action_queue *)act->conf; 894 filter->queue = act_q->index; 895 896 /* check if the next not void item is END */ 897 index++; 898 NEXT_ITEM_OF_ACTION(act, actions, index); 899 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 900 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 901 rte_flow_error_set(error, EINVAL, 902 RTE_FLOW_ERROR_TYPE_ACTION, 903 act, "Not supported action."); 904 return -rte_errno; 905 } 906 907 /* parse attr */ 908 /* must be input direction */ 909 if (!attr->ingress) { 910 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 911 rte_flow_error_set(error, EINVAL, 912 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 913 attr, "Only support ingress."); 914 return -rte_errno; 915 } 916 917 /* not supported */ 918 if (attr->egress) { 919 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 920 rte_flow_error_set(error, EINVAL, 921 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 922 attr, "Not support egress."); 923 return -rte_errno; 924 } 925 926 /* Support 2 priorities, the lowest or highest. */ 927 if (!attr->priority) { 928 filter->hig_pri = 0; 929 } else if (attr->priority == (uint32_t)~0U) { 930 filter->hig_pri = 1; 931 } else { 932 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 933 rte_flow_error_set(error, EINVAL, 934 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 935 attr, "Not support priority."); 936 return -rte_errno; 937 } 938 939 return 0; 940 } 941 942 static int 943 igb_parse_syn_filter(struct rte_eth_dev *dev, 944 const struct rte_flow_attr *attr, 945 const struct rte_flow_item pattern[], 946 const struct rte_flow_action actions[], 947 struct rte_eth_syn_filter *filter, 948 struct rte_flow_error *error) 949 { 950 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 951 int ret; 952 953 MAC_TYPE_FILTER_SUP(hw->mac.type); 954 955 ret = cons_parse_syn_filter(attr, pattern, 956 actions, filter, error); 957 958 if (hw->mac.type == e1000_82576) { 959 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576) { 960 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 961 rte_flow_error_set(error, EINVAL, 962 RTE_FLOW_ERROR_TYPE_ITEM, 963 NULL, "queue number not " 964 "supported by syn filter"); 965 return -rte_errno; 966 } 967 } else { 968 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) { 969 memset(filter, 0, sizeof(struct rte_eth_syn_filter)); 970 rte_flow_error_set(error, EINVAL, 971 RTE_FLOW_ERROR_TYPE_ITEM, 972 NULL, "queue number not " 973 "supported by syn filter"); 974 return -rte_errno; 975 } 976 } 977 978 if (ret) 979 return ret; 980 981 return 0; 982 } 983 984 /** 985 * Parse the rule to see if it is a flex byte rule. 986 * And get the flex byte filter info BTW. 987 * pattern: 988 * The first not void item must be RAW. 989 * The second not void item can be RAW or END. 990 * The third not void item can be RAW or END. 991 * The last not void item must be END. 992 * action: 993 * The first not void action should be QUEUE. 994 * The next not void action should be END. 995 * pattern example: 996 * ITEM Spec Mask 997 * RAW relative 0 0x1 998 * offset 0 0xFFFFFFFF 999 * pattern {0x08, 0x06} {0xFF, 0xFF} 1000 * RAW relative 1 0x1 1001 * offset 100 0xFFFFFFFF 1002 * pattern {0x11, 0x22, 0x33} {0xFF, 0xFF, 0xFF} 1003 * END 1004 * other members in mask and spec should set to 0x00. 1005 * item->last should be NULL. 1006 */ 1007 static int 1008 cons_parse_flex_filter(const struct rte_flow_attr *attr, 1009 const struct rte_flow_item pattern[], 1010 const struct rte_flow_action actions[], 1011 struct rte_eth_flex_filter *filter, 1012 struct rte_flow_error *error) 1013 { 1014 const struct rte_flow_item *item; 1015 const struct rte_flow_action *act; 1016 const struct rte_flow_item_raw *raw_spec; 1017 const struct rte_flow_item_raw *raw_mask; 1018 const struct rte_flow_action_queue *act_q; 1019 uint32_t index, i, offset, total_offset; 1020 uint32_t max_offset = 0; 1021 int32_t shift, j, raw_index = 0; 1022 int32_t relative[IGB_FLEX_RAW_NUM] = {0}; 1023 int32_t raw_offset[IGB_FLEX_RAW_NUM] = {0}; 1024 1025 if (!pattern) { 1026 rte_flow_error_set(error, EINVAL, 1027 RTE_FLOW_ERROR_TYPE_ITEM_NUM, 1028 NULL, "NULL pattern."); 1029 return -rte_errno; 1030 } 1031 1032 if (!actions) { 1033 rte_flow_error_set(error, EINVAL, 1034 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 1035 NULL, "NULL action."); 1036 return -rte_errno; 1037 } 1038 1039 if (!attr) { 1040 rte_flow_error_set(error, EINVAL, 1041 RTE_FLOW_ERROR_TYPE_ATTR, 1042 NULL, "NULL attribute."); 1043 return -rte_errno; 1044 } 1045 1046 /* parse pattern */ 1047 index = 0; 1048 1049 item_loop: 1050 1051 /* the first not void item should be RAW */ 1052 NEXT_ITEM_OF_PATTERN(item, pattern, index); 1053 if (item->type != RTE_FLOW_ITEM_TYPE_RAW) { 1054 rte_flow_error_set(error, EINVAL, 1055 RTE_FLOW_ERROR_TYPE_ITEM, 1056 item, "Not supported by flex filter"); 1057 return -rte_errno; 1058 } 1059 /*Not supported last point for range*/ 1060 if (item->last) { 1061 rte_flow_error_set(error, EINVAL, 1062 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1063 item, "Not supported last point for range"); 1064 return -rte_errno; 1065 } 1066 1067 raw_spec = item->spec; 1068 raw_mask = item->mask; 1069 1070 if (!raw_mask->length || 1071 !raw_mask->relative) { 1072 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1073 rte_flow_error_set(error, EINVAL, 1074 RTE_FLOW_ERROR_TYPE_ITEM, 1075 item, "Not supported by flex filter"); 1076 return -rte_errno; 1077 } 1078 1079 if (raw_mask->offset) 1080 offset = raw_spec->offset; 1081 else 1082 offset = 0; 1083 1084 for (j = 0; j < raw_spec->length; j++) { 1085 if (raw_mask->pattern[j] != 0xFF) { 1086 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1087 rte_flow_error_set(error, EINVAL, 1088 RTE_FLOW_ERROR_TYPE_ITEM, 1089 item, "Not supported by flex filter"); 1090 return -rte_errno; 1091 } 1092 } 1093 1094 total_offset = 0; 1095 1096 if (raw_spec->relative) { 1097 for (j = raw_index; j > 0; j--) { 1098 total_offset += raw_offset[j - 1]; 1099 if (!relative[j - 1]) 1100 break; 1101 } 1102 if (total_offset + raw_spec->length + offset > max_offset) 1103 max_offset = total_offset + raw_spec->length + offset; 1104 } else { 1105 if (raw_spec->length + offset > max_offset) 1106 max_offset = raw_spec->length + offset; 1107 } 1108 1109 if ((raw_spec->length + offset + total_offset) > 1110 RTE_FLEX_FILTER_MAXLEN) { 1111 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1112 rte_flow_error_set(error, EINVAL, 1113 RTE_FLOW_ERROR_TYPE_ITEM, 1114 item, "Not supported by flex filter"); 1115 return -rte_errno; 1116 } 1117 1118 if (raw_spec->relative == 0) { 1119 for (j = 0; j < raw_spec->length; j++) 1120 filter->bytes[offset + j] = 1121 raw_spec->pattern[j]; 1122 j = offset / CHAR_BIT; 1123 shift = offset % CHAR_BIT; 1124 } else { 1125 for (j = 0; j < raw_spec->length; j++) 1126 filter->bytes[total_offset + offset + j] = 1127 raw_spec->pattern[j]; 1128 j = (total_offset + offset) / CHAR_BIT; 1129 shift = (total_offset + offset) % CHAR_BIT; 1130 } 1131 1132 i = 0; 1133 1134 for ( ; shift < CHAR_BIT; shift++) { 1135 filter->mask[j] |= (0x80 >> shift); 1136 i++; 1137 if (i == raw_spec->length) 1138 break; 1139 if (shift == (CHAR_BIT - 1)) { 1140 j++; 1141 shift = -1; 1142 } 1143 } 1144 1145 relative[raw_index] = raw_spec->relative; 1146 raw_offset[raw_index] = offset + raw_spec->length; 1147 raw_index++; 1148 1149 /* check if the next not void item is RAW */ 1150 index++; 1151 NEXT_ITEM_OF_PATTERN(item, pattern, index); 1152 if (item->type != RTE_FLOW_ITEM_TYPE_RAW && 1153 item->type != RTE_FLOW_ITEM_TYPE_END) { 1154 rte_flow_error_set(error, EINVAL, 1155 RTE_FLOW_ERROR_TYPE_ITEM, 1156 item, "Not supported by flex filter"); 1157 return -rte_errno; 1158 } 1159 1160 /* go back to parser */ 1161 if (item->type == RTE_FLOW_ITEM_TYPE_RAW) { 1162 /* if the item is RAW, the content should be parse */ 1163 goto item_loop; 1164 } 1165 1166 filter->len = RTE_ALIGN(max_offset, 8); 1167 1168 /* parse action */ 1169 index = 0; 1170 1171 /* check if the first not void action is QUEUE. */ 1172 NEXT_ITEM_OF_ACTION(act, actions, index); 1173 if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) { 1174 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1175 rte_flow_error_set(error, EINVAL, 1176 RTE_FLOW_ERROR_TYPE_ACTION, 1177 act, "Not supported action."); 1178 return -rte_errno; 1179 } 1180 1181 act_q = (const struct rte_flow_action_queue *)act->conf; 1182 filter->queue = act_q->index; 1183 1184 /* check if the next not void item is END */ 1185 index++; 1186 NEXT_ITEM_OF_ACTION(act, actions, index); 1187 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 1188 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1189 rte_flow_error_set(error, EINVAL, 1190 RTE_FLOW_ERROR_TYPE_ACTION, 1191 act, "Not supported action."); 1192 return -rte_errno; 1193 } 1194 1195 /* parse attr */ 1196 /* must be input direction */ 1197 if (!attr->ingress) { 1198 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1199 rte_flow_error_set(error, EINVAL, 1200 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1201 attr, "Only support ingress."); 1202 return -rte_errno; 1203 } 1204 1205 /* not supported */ 1206 if (attr->egress) { 1207 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1208 rte_flow_error_set(error, EINVAL, 1209 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 1210 attr, "Not support egress."); 1211 return -rte_errno; 1212 } 1213 1214 if (attr->priority > 0xFFFF) { 1215 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1216 rte_flow_error_set(error, EINVAL, 1217 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1218 attr, "Error priority."); 1219 return -rte_errno; 1220 } 1221 1222 filter->priority = (uint16_t)attr->priority; 1223 1224 return 0; 1225 } 1226 1227 static int 1228 igb_parse_flex_filter(struct rte_eth_dev *dev, 1229 const struct rte_flow_attr *attr, 1230 const struct rte_flow_item pattern[], 1231 const struct rte_flow_action actions[], 1232 struct rte_eth_flex_filter *filter, 1233 struct rte_flow_error *error) 1234 { 1235 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1236 int ret; 1237 1238 MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); 1239 1240 ret = cons_parse_flex_filter(attr, pattern, 1241 actions, filter, error); 1242 1243 if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) { 1244 memset(filter, 0, sizeof(struct rte_eth_flex_filter)); 1245 rte_flow_error_set(error, EINVAL, 1246 RTE_FLOW_ERROR_TYPE_ITEM, 1247 NULL, "queue number not supported by flex filter"); 1248 return -rte_errno; 1249 } 1250 1251 if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN || 1252 filter->len % sizeof(uint64_t) != 0) { 1253 PMD_DRV_LOG(ERR, "filter's length is out of range"); 1254 return -EINVAL; 1255 } 1256 1257 if (filter->priority > E1000_MAX_FLEX_FILTER_PRI) { 1258 PMD_DRV_LOG(ERR, "filter's priority is out of range"); 1259 return -EINVAL; 1260 } 1261 1262 if (ret) 1263 return ret; 1264 1265 return 0; 1266 } 1267 1268 static int 1269 igb_parse_rss_filter(struct rte_eth_dev *dev, 1270 const struct rte_flow_attr *attr, 1271 const struct rte_flow_action actions[], 1272 struct igb_rte_flow_rss_conf *rss_conf, 1273 struct rte_flow_error *error) 1274 { 1275 const struct rte_flow_action *act; 1276 const struct rte_flow_action_rss *rss; 1277 uint16_t n, index; 1278 1279 /** 1280 * rss only supports forwarding, 1281 * check if the first not void action is RSS. 1282 */ 1283 index = 0; 1284 NEXT_ITEM_OF_ACTION(act, actions, index); 1285 if (act->type != RTE_FLOW_ACTION_TYPE_RSS) { 1286 memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1287 rte_flow_error_set(error, EINVAL, 1288 RTE_FLOW_ERROR_TYPE_ACTION, 1289 act, "Not supported action."); 1290 return -rte_errno; 1291 } 1292 1293 rss = (const struct rte_flow_action_rss *)act->conf; 1294 1295 if (!rss || !rss->num) { 1296 rte_flow_error_set(error, EINVAL, 1297 RTE_FLOW_ERROR_TYPE_ACTION, 1298 act, 1299 "no valid queues"); 1300 return -rte_errno; 1301 } 1302 1303 for (n = 0; n < rss->num; n++) { 1304 if (rss->queue[n] >= dev->data->nb_rx_queues) { 1305 rte_flow_error_set(error, EINVAL, 1306 RTE_FLOW_ERROR_TYPE_ACTION, 1307 act, 1308 "queue id > max number of queues"); 1309 return -rte_errno; 1310 } 1311 } 1312 1313 if (rss->rss_conf) 1314 rss_conf->rss_conf = *rss->rss_conf; 1315 else 1316 rss_conf->rss_conf.rss_hf = IGB_RSS_OFFLOAD_ALL; 1317 1318 for (n = 0; n < rss->num; ++n) 1319 rss_conf->queue[n] = rss->queue[n]; 1320 rss_conf->num = rss->num; 1321 1322 /* check if the next not void item is END */ 1323 index++; 1324 NEXT_ITEM_OF_ACTION(act, actions, index); 1325 if (act->type != RTE_FLOW_ACTION_TYPE_END) { 1326 memset(rss_conf, 0, sizeof(struct rte_eth_rss_conf)); 1327 rte_flow_error_set(error, EINVAL, 1328 RTE_FLOW_ERROR_TYPE_ACTION, 1329 act, "Not supported action."); 1330 return -rte_errno; 1331 } 1332 1333 /* parse attr */ 1334 /* must be input direction */ 1335 if (!attr->ingress) { 1336 memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1337 rte_flow_error_set(error, EINVAL, 1338 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1339 attr, "Only support ingress."); 1340 return -rte_errno; 1341 } 1342 1343 /* not supported */ 1344 if (attr->egress) { 1345 memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1346 rte_flow_error_set(error, EINVAL, 1347 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 1348 attr, "Not support egress."); 1349 return -rte_errno; 1350 } 1351 1352 if (attr->priority > 0xFFFF) { 1353 memset(rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1354 rte_flow_error_set(error, EINVAL, 1355 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1356 attr, "Error priority."); 1357 return -rte_errno; 1358 } 1359 1360 return 0; 1361 } 1362 1363 /** 1364 * Create a flow rule. 1365 * Theorically one rule can match more than one filters. 1366 * We will let it use the filter which it hitt first. 1367 * So, the sequence matters. 1368 */ 1369 static struct rte_flow * 1370 igb_flow_create(struct rte_eth_dev *dev, 1371 const struct rte_flow_attr *attr, 1372 const struct rte_flow_item pattern[], 1373 const struct rte_flow_action actions[], 1374 struct rte_flow_error *error) 1375 { 1376 int ret; 1377 struct rte_eth_ntuple_filter ntuple_filter; 1378 struct rte_eth_ethertype_filter ethertype_filter; 1379 struct rte_eth_syn_filter syn_filter; 1380 struct rte_eth_flex_filter flex_filter; 1381 struct igb_rte_flow_rss_conf rss_conf; 1382 struct rte_flow *flow = NULL; 1383 struct igb_ntuple_filter_ele *ntuple_filter_ptr; 1384 struct igb_ethertype_filter_ele *ethertype_filter_ptr; 1385 struct igb_eth_syn_filter_ele *syn_filter_ptr; 1386 struct igb_flex_filter_ele *flex_filter_ptr; 1387 struct igb_rss_conf_ele *rss_filter_ptr; 1388 struct igb_flow_mem *igb_flow_mem_ptr; 1389 1390 flow = rte_zmalloc("igb_rte_flow", sizeof(struct rte_flow), 0); 1391 if (!flow) { 1392 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1393 return (struct rte_flow *)flow; 1394 } 1395 igb_flow_mem_ptr = rte_zmalloc("igb_flow_mem", 1396 sizeof(struct igb_flow_mem), 0); 1397 if (!igb_flow_mem_ptr) { 1398 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1399 rte_free(flow); 1400 return NULL; 1401 } 1402 igb_flow_mem_ptr->flow = flow; 1403 igb_flow_mem_ptr->dev = dev; 1404 TAILQ_INSERT_TAIL(&igb_flow_list, 1405 igb_flow_mem_ptr, entries); 1406 1407 memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter)); 1408 ret = igb_parse_ntuple_filter(dev, attr, pattern, 1409 actions, &ntuple_filter, error); 1410 if (!ret) { 1411 ret = igb_add_del_ntuple_filter(dev, &ntuple_filter, TRUE); 1412 if (!ret) { 1413 ntuple_filter_ptr = rte_zmalloc("igb_ntuple_filter", 1414 sizeof(struct igb_ntuple_filter_ele), 0); 1415 if (!ntuple_filter_ptr) { 1416 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1417 goto out; 1418 } 1419 1420 rte_memcpy(&ntuple_filter_ptr->filter_info, 1421 &ntuple_filter, 1422 sizeof(struct rte_eth_ntuple_filter)); 1423 TAILQ_INSERT_TAIL(&igb_filter_ntuple_list, 1424 ntuple_filter_ptr, entries); 1425 flow->rule = ntuple_filter_ptr; 1426 flow->filter_type = RTE_ETH_FILTER_NTUPLE; 1427 return flow; 1428 } 1429 goto out; 1430 } 1431 1432 memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter)); 1433 ret = igb_parse_ethertype_filter(dev, attr, pattern, 1434 actions, ðertype_filter, error); 1435 if (!ret) { 1436 ret = igb_add_del_ethertype_filter(dev, 1437 ðertype_filter, TRUE); 1438 if (!ret) { 1439 ethertype_filter_ptr = rte_zmalloc( 1440 "igb_ethertype_filter", 1441 sizeof(struct igb_ethertype_filter_ele), 0); 1442 if (!ethertype_filter_ptr) { 1443 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1444 goto out; 1445 } 1446 1447 rte_memcpy(ðertype_filter_ptr->filter_info, 1448 ðertype_filter, 1449 sizeof(struct rte_eth_ethertype_filter)); 1450 TAILQ_INSERT_TAIL(&igb_filter_ethertype_list, 1451 ethertype_filter_ptr, entries); 1452 flow->rule = ethertype_filter_ptr; 1453 flow->filter_type = RTE_ETH_FILTER_ETHERTYPE; 1454 return flow; 1455 } 1456 goto out; 1457 } 1458 1459 memset(&syn_filter, 0, sizeof(struct rte_eth_syn_filter)); 1460 ret = igb_parse_syn_filter(dev, attr, pattern, 1461 actions, &syn_filter, error); 1462 if (!ret) { 1463 ret = eth_igb_syn_filter_set(dev, &syn_filter, TRUE); 1464 if (!ret) { 1465 syn_filter_ptr = rte_zmalloc("igb_syn_filter", 1466 sizeof(struct igb_eth_syn_filter_ele), 0); 1467 if (!syn_filter_ptr) { 1468 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1469 goto out; 1470 } 1471 1472 rte_memcpy(&syn_filter_ptr->filter_info, 1473 &syn_filter, 1474 sizeof(struct rte_eth_syn_filter)); 1475 TAILQ_INSERT_TAIL(&igb_filter_syn_list, 1476 syn_filter_ptr, 1477 entries); 1478 flow->rule = syn_filter_ptr; 1479 flow->filter_type = RTE_ETH_FILTER_SYN; 1480 return flow; 1481 } 1482 goto out; 1483 } 1484 1485 memset(&flex_filter, 0, sizeof(struct rte_eth_flex_filter)); 1486 ret = igb_parse_flex_filter(dev, attr, pattern, 1487 actions, &flex_filter, error); 1488 if (!ret) { 1489 ret = eth_igb_add_del_flex_filter(dev, &flex_filter, TRUE); 1490 if (!ret) { 1491 flex_filter_ptr = rte_zmalloc("igb_flex_filter", 1492 sizeof(struct igb_flex_filter_ele), 0); 1493 if (!flex_filter_ptr) { 1494 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1495 goto out; 1496 } 1497 1498 rte_memcpy(&flex_filter_ptr->filter_info, 1499 &flex_filter, 1500 sizeof(struct rte_eth_flex_filter)); 1501 TAILQ_INSERT_TAIL(&igb_filter_flex_list, 1502 flex_filter_ptr, entries); 1503 flow->rule = flex_filter_ptr; 1504 flow->filter_type = RTE_ETH_FILTER_FLEXIBLE; 1505 return flow; 1506 } 1507 } 1508 1509 memset(&rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1510 ret = igb_parse_rss_filter(dev, attr, 1511 actions, &rss_conf, error); 1512 if (!ret) { 1513 ret = igb_config_rss_filter(dev, &rss_conf, TRUE); 1514 if (!ret) { 1515 rss_filter_ptr = rte_zmalloc("igb_rss_filter", 1516 sizeof(struct igb_rss_conf_ele), 0); 1517 if (!rss_filter_ptr) { 1518 PMD_DRV_LOG(ERR, "failed to allocate memory"); 1519 goto out; 1520 } 1521 rte_memcpy(&rss_filter_ptr->filter_info, 1522 &rss_conf, 1523 sizeof(struct igb_rte_flow_rss_conf)); 1524 TAILQ_INSERT_TAIL(&igb_filter_rss_list, 1525 rss_filter_ptr, entries); 1526 flow->rule = rss_filter_ptr; 1527 flow->filter_type = RTE_ETH_FILTER_HASH; 1528 return flow; 1529 } 1530 } 1531 1532 out: 1533 TAILQ_REMOVE(&igb_flow_list, 1534 igb_flow_mem_ptr, entries); 1535 rte_flow_error_set(error, -ret, 1536 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 1537 "Failed to create flow."); 1538 rte_free(igb_flow_mem_ptr); 1539 rte_free(flow); 1540 return NULL; 1541 } 1542 1543 /** 1544 * Check if the flow rule is supported by igb. 1545 * It only checkes the format. Don't guarantee the rule can be programmed into 1546 * the HW. Because there can be no enough room for the rule. 1547 */ 1548 static int 1549 igb_flow_validate(__rte_unused struct rte_eth_dev *dev, 1550 const struct rte_flow_attr *attr, 1551 const struct rte_flow_item pattern[], 1552 const struct rte_flow_action actions[], 1553 struct rte_flow_error *error) 1554 { 1555 struct rte_eth_ntuple_filter ntuple_filter; 1556 struct rte_eth_ethertype_filter ethertype_filter; 1557 struct rte_eth_syn_filter syn_filter; 1558 struct rte_eth_flex_filter flex_filter; 1559 struct igb_rte_flow_rss_conf rss_conf; 1560 int ret; 1561 1562 memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter)); 1563 ret = igb_parse_ntuple_filter(dev, attr, pattern, 1564 actions, &ntuple_filter, error); 1565 if (!ret) 1566 return 0; 1567 1568 memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter)); 1569 ret = igb_parse_ethertype_filter(dev, attr, pattern, 1570 actions, ðertype_filter, error); 1571 if (!ret) 1572 return 0; 1573 1574 memset(&syn_filter, 0, sizeof(struct rte_eth_syn_filter)); 1575 ret = igb_parse_syn_filter(dev, attr, pattern, 1576 actions, &syn_filter, error); 1577 if (!ret) 1578 return 0; 1579 1580 memset(&flex_filter, 0, sizeof(struct rte_eth_flex_filter)); 1581 ret = igb_parse_flex_filter(dev, attr, pattern, 1582 actions, &flex_filter, error); 1583 if (!ret) 1584 return 0; 1585 1586 memset(&rss_conf, 0, sizeof(struct igb_rte_flow_rss_conf)); 1587 ret = igb_parse_rss_filter(dev, attr, 1588 actions, &rss_conf, error); 1589 1590 return ret; 1591 } 1592 1593 /* Destroy a flow rule on igb. */ 1594 static int 1595 igb_flow_destroy(struct rte_eth_dev *dev, 1596 struct rte_flow *flow, 1597 struct rte_flow_error *error) 1598 { 1599 int ret; 1600 struct rte_flow *pmd_flow = flow; 1601 enum rte_filter_type filter_type = pmd_flow->filter_type; 1602 struct igb_ntuple_filter_ele *ntuple_filter_ptr; 1603 struct igb_ethertype_filter_ele *ethertype_filter_ptr; 1604 struct igb_eth_syn_filter_ele *syn_filter_ptr; 1605 struct igb_flex_filter_ele *flex_filter_ptr; 1606 struct igb_flow_mem *igb_flow_mem_ptr; 1607 struct igb_rss_conf_ele *rss_filter_ptr; 1608 1609 switch (filter_type) { 1610 case RTE_ETH_FILTER_NTUPLE: 1611 ntuple_filter_ptr = (struct igb_ntuple_filter_ele *) 1612 pmd_flow->rule; 1613 ret = igb_add_del_ntuple_filter(dev, 1614 &ntuple_filter_ptr->filter_info, FALSE); 1615 if (!ret) { 1616 TAILQ_REMOVE(&igb_filter_ntuple_list, 1617 ntuple_filter_ptr, entries); 1618 rte_free(ntuple_filter_ptr); 1619 } 1620 break; 1621 case RTE_ETH_FILTER_ETHERTYPE: 1622 ethertype_filter_ptr = (struct igb_ethertype_filter_ele *) 1623 pmd_flow->rule; 1624 ret = igb_add_del_ethertype_filter(dev, 1625 ðertype_filter_ptr->filter_info, FALSE); 1626 if (!ret) { 1627 TAILQ_REMOVE(&igb_filter_ethertype_list, 1628 ethertype_filter_ptr, entries); 1629 rte_free(ethertype_filter_ptr); 1630 } 1631 break; 1632 case RTE_ETH_FILTER_SYN: 1633 syn_filter_ptr = (struct igb_eth_syn_filter_ele *) 1634 pmd_flow->rule; 1635 ret = eth_igb_syn_filter_set(dev, 1636 &syn_filter_ptr->filter_info, FALSE); 1637 if (!ret) { 1638 TAILQ_REMOVE(&igb_filter_syn_list, 1639 syn_filter_ptr, entries); 1640 rte_free(syn_filter_ptr); 1641 } 1642 break; 1643 case RTE_ETH_FILTER_FLEXIBLE: 1644 flex_filter_ptr = (struct igb_flex_filter_ele *) 1645 pmd_flow->rule; 1646 ret = eth_igb_add_del_flex_filter(dev, 1647 &flex_filter_ptr->filter_info, FALSE); 1648 if (!ret) { 1649 TAILQ_REMOVE(&igb_filter_flex_list, 1650 flex_filter_ptr, entries); 1651 rte_free(flex_filter_ptr); 1652 } 1653 break; 1654 case RTE_ETH_FILTER_HASH: 1655 rss_filter_ptr = (struct igb_rss_conf_ele *) 1656 pmd_flow->rule; 1657 ret = igb_config_rss_filter(dev, 1658 &rss_filter_ptr->filter_info, FALSE); 1659 if (!ret) { 1660 TAILQ_REMOVE(&igb_filter_rss_list, 1661 rss_filter_ptr, entries); 1662 rte_free(rss_filter_ptr); 1663 } 1664 break; 1665 default: 1666 PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", 1667 filter_type); 1668 ret = -EINVAL; 1669 break; 1670 } 1671 1672 if (ret) { 1673 rte_flow_error_set(error, EINVAL, 1674 RTE_FLOW_ERROR_TYPE_HANDLE, 1675 NULL, "Failed to destroy flow"); 1676 return ret; 1677 } 1678 1679 TAILQ_FOREACH(igb_flow_mem_ptr, &igb_flow_list, entries) { 1680 if (igb_flow_mem_ptr->flow == pmd_flow) { 1681 TAILQ_REMOVE(&igb_flow_list, 1682 igb_flow_mem_ptr, entries); 1683 rte_free(igb_flow_mem_ptr); 1684 } 1685 } 1686 rte_free(flow); 1687 1688 return ret; 1689 } 1690 1691 /* remove all the n-tuple filters */ 1692 static void 1693 igb_clear_all_ntuple_filter(struct rte_eth_dev *dev) 1694 { 1695 struct e1000_filter_info *filter_info = 1696 E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 1697 struct e1000_5tuple_filter *p_5tuple; 1698 struct e1000_2tuple_filter *p_2tuple; 1699 1700 while ((p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list))) 1701 igb_delete_5tuple_filter_82576(dev, p_5tuple); 1702 1703 while ((p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list))) 1704 igb_delete_2tuple_filter(dev, p_2tuple); 1705 } 1706 1707 /* remove all the ether type filters */ 1708 static void 1709 igb_clear_all_ethertype_filter(struct rte_eth_dev *dev) 1710 { 1711 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1712 struct e1000_filter_info *filter_info = 1713 E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 1714 int i; 1715 1716 for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) { 1717 if (filter_info->ethertype_mask & (1 << i)) { 1718 (void)igb_ethertype_filter_remove(filter_info, 1719 (uint8_t)i); 1720 E1000_WRITE_REG(hw, E1000_ETQF(i), 0); 1721 E1000_WRITE_FLUSH(hw); 1722 } 1723 } 1724 } 1725 1726 /* remove the SYN filter */ 1727 static void 1728 igb_clear_syn_filter(struct rte_eth_dev *dev) 1729 { 1730 struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1731 struct e1000_filter_info *filter_info = 1732 E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 1733 1734 if (filter_info->syn_info & E1000_SYN_FILTER_ENABLE) { 1735 filter_info->syn_info = 0; 1736 E1000_WRITE_REG(hw, E1000_SYNQF(0), 0); 1737 E1000_WRITE_FLUSH(hw); 1738 } 1739 } 1740 1741 /* remove all the flex filters */ 1742 static void 1743 igb_clear_all_flex_filter(struct rte_eth_dev *dev) 1744 { 1745 struct e1000_filter_info *filter_info = 1746 E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 1747 struct e1000_flex_filter *flex_filter; 1748 1749 while ((flex_filter = TAILQ_FIRST(&filter_info->flex_list))) 1750 igb_remove_flex_filter(dev, flex_filter); 1751 } 1752 1753 /* remove the rss filter */ 1754 static void 1755 igb_clear_rss_filter(struct rte_eth_dev *dev) 1756 { 1757 struct e1000_filter_info *filter = 1758 E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); 1759 1760 if (filter->rss_info.num) 1761 igb_config_rss_filter(dev, &filter->rss_info, FALSE); 1762 } 1763 1764 void 1765 igb_filterlist_flush(struct rte_eth_dev *dev) 1766 { 1767 struct igb_ntuple_filter_ele *ntuple_filter_ptr; 1768 struct igb_ethertype_filter_ele *ethertype_filter_ptr; 1769 struct igb_eth_syn_filter_ele *syn_filter_ptr; 1770 struct igb_flex_filter_ele *flex_filter_ptr; 1771 struct igb_rss_conf_ele *rss_filter_ptr; 1772 struct igb_flow_mem *igb_flow_mem_ptr; 1773 enum rte_filter_type filter_type; 1774 struct rte_flow *pmd_flow; 1775 1776 TAILQ_FOREACH(igb_flow_mem_ptr, &igb_flow_list, entries) { 1777 if (igb_flow_mem_ptr->dev == dev) { 1778 pmd_flow = igb_flow_mem_ptr->flow; 1779 filter_type = pmd_flow->filter_type; 1780 1781 switch (filter_type) { 1782 case RTE_ETH_FILTER_NTUPLE: 1783 ntuple_filter_ptr = 1784 (struct igb_ntuple_filter_ele *) 1785 pmd_flow->rule; 1786 TAILQ_REMOVE(&igb_filter_ntuple_list, 1787 ntuple_filter_ptr, entries); 1788 rte_free(ntuple_filter_ptr); 1789 break; 1790 case RTE_ETH_FILTER_ETHERTYPE: 1791 ethertype_filter_ptr = 1792 (struct igb_ethertype_filter_ele *) 1793 pmd_flow->rule; 1794 TAILQ_REMOVE(&igb_filter_ethertype_list, 1795 ethertype_filter_ptr, entries); 1796 rte_free(ethertype_filter_ptr); 1797 break; 1798 case RTE_ETH_FILTER_SYN: 1799 syn_filter_ptr = 1800 (struct igb_eth_syn_filter_ele *) 1801 pmd_flow->rule; 1802 TAILQ_REMOVE(&igb_filter_syn_list, 1803 syn_filter_ptr, entries); 1804 rte_free(syn_filter_ptr); 1805 break; 1806 case RTE_ETH_FILTER_FLEXIBLE: 1807 flex_filter_ptr = 1808 (struct igb_flex_filter_ele *) 1809 pmd_flow->rule; 1810 TAILQ_REMOVE(&igb_filter_flex_list, 1811 flex_filter_ptr, entries); 1812 rte_free(flex_filter_ptr); 1813 break; 1814 case RTE_ETH_FILTER_HASH: 1815 rss_filter_ptr = 1816 (struct igb_rss_conf_ele *) 1817 pmd_flow->rule; 1818 TAILQ_REMOVE(&igb_filter_rss_list, 1819 rss_filter_ptr, entries); 1820 rte_free(rss_filter_ptr); 1821 break; 1822 default: 1823 PMD_DRV_LOG(WARNING, "Filter type" 1824 "(%d) not supported", filter_type); 1825 break; 1826 } 1827 TAILQ_REMOVE(&igb_flow_list, 1828 igb_flow_mem_ptr, 1829 entries); 1830 rte_free(igb_flow_mem_ptr->flow); 1831 rte_free(igb_flow_mem_ptr); 1832 } 1833 } 1834 } 1835 1836 /* Destroy all flow rules associated with a port on igb. */ 1837 static int 1838 igb_flow_flush(struct rte_eth_dev *dev, 1839 __rte_unused struct rte_flow_error *error) 1840 { 1841 igb_clear_all_ntuple_filter(dev); 1842 igb_clear_all_ethertype_filter(dev); 1843 igb_clear_syn_filter(dev); 1844 igb_clear_all_flex_filter(dev); 1845 igb_clear_rss_filter(dev); 1846 igb_filterlist_flush(dev); 1847 1848 return 0; 1849 } 1850 1851 const struct rte_flow_ops igb_flow_ops = { 1852 .validate = igb_flow_validate, 1853 .create = igb_flow_create, 1854 .destroy = igb_flow_destroy, 1855 .flush = igb_flow_flush, 1856 }; 1857