1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. 3 */ 4 5 #include <errno.h> 6 #include <stdint.h> 7 #include <rte_log.h> 8 #include <rte_ethdev_driver.h> 9 #include <rte_flow_driver.h> 10 #include <rte_ether.h> 11 #include <rte_ip.h> 12 #include <rte_udp.h> 13 14 #include "enic_compat.h" 15 #include "enic.h" 16 #include "vnic_dev.h" 17 #include "vnic_nic.h" 18 19 #define FLOW_TRACE() \ 20 rte_log(RTE_LOG_DEBUG, enicpmd_logtype_flow, \ 21 "%s()\n", __func__) 22 #define FLOW_LOG(level, fmt, args...) \ 23 rte_log(RTE_LOG_ ## level, enicpmd_logtype_flow, \ 24 fmt "\n", ##args) 25 26 /* 27 * Common arguments passed to copy_item functions. Use this structure 28 * so we can easily add new arguments. 29 * item: Item specification. 30 * filter: Partially filled in NIC filter structure. 31 * inner_ofst: If zero, this is an outer header. If non-zero, this is 32 * the offset into L5 where the header begins. 33 * l2_proto_off: offset to EtherType eth or vlan header. 34 * l3_proto_off: offset to next protocol field in IPv4 or 6 header. 35 */ 36 struct copy_item_args { 37 const struct rte_flow_item *item; 38 struct filter_v2 *filter; 39 uint8_t *inner_ofst; 40 uint8_t l2_proto_off; 41 uint8_t l3_proto_off; 42 struct enic *enic; 43 }; 44 45 /* functions for copying items into enic filters */ 46 typedef int (enic_copy_item_fn)(struct copy_item_args *arg); 47 48 /** Info about how to copy items into enic filters. */ 49 struct enic_items { 50 /** Function for copying and validating an item. */ 51 enic_copy_item_fn *copy_item; 52 /** List of valid previous items. */ 53 const enum rte_flow_item_type * const prev_items; 54 /** True if it's OK for this item to be the first item. For some NIC 55 * versions, it's invalid to start the stack above layer 3. 56 */ 57 const u8 valid_start_item; 58 /* Inner packet version of copy_item. */ 59 enic_copy_item_fn *inner_copy_item; 60 }; 61 62 /** Filtering capabilities for various NIC and firmware versions. */ 63 struct enic_filter_cap { 64 /** list of valid items and their handlers and attributes. */ 65 const struct enic_items *item_info; 66 /* Max type in the above list, used to detect unsupported types */ 67 enum rte_flow_item_type max_item_type; 68 }; 69 70 /* functions for copying flow actions into enic actions */ 71 typedef int (copy_action_fn)(const struct rte_flow_action actions[], 72 struct filter_action_v2 *enic_action); 73 74 /** Action capabilities for various NICs. */ 75 struct enic_action_cap { 76 /** list of valid actions */ 77 const enum rte_flow_action_type *actions; 78 /** copy function for a particular NIC */ 79 int (*copy_fn)(const struct rte_flow_action actions[], 80 struct filter_action_v2 *enic_action); 81 }; 82 83 /* Forward declarations */ 84 static enic_copy_item_fn enic_copy_item_ipv4_v1; 85 static enic_copy_item_fn enic_copy_item_udp_v1; 86 static enic_copy_item_fn enic_copy_item_tcp_v1; 87 static enic_copy_item_fn enic_copy_item_eth_v2; 88 static enic_copy_item_fn enic_copy_item_vlan_v2; 89 static enic_copy_item_fn enic_copy_item_ipv4_v2; 90 static enic_copy_item_fn enic_copy_item_ipv6_v2; 91 static enic_copy_item_fn enic_copy_item_udp_v2; 92 static enic_copy_item_fn enic_copy_item_tcp_v2; 93 static enic_copy_item_fn enic_copy_item_sctp_v2; 94 static enic_copy_item_fn enic_copy_item_vxlan_v2; 95 static enic_copy_item_fn enic_copy_item_inner_eth_v2; 96 static enic_copy_item_fn enic_copy_item_inner_vlan_v2; 97 static enic_copy_item_fn enic_copy_item_inner_ipv4_v2; 98 static enic_copy_item_fn enic_copy_item_inner_ipv6_v2; 99 static enic_copy_item_fn enic_copy_item_inner_udp_v2; 100 static enic_copy_item_fn enic_copy_item_inner_tcp_v2; 101 static copy_action_fn enic_copy_action_v1; 102 static copy_action_fn enic_copy_action_v2; 103 104 /** 105 * Legacy NICs or NICs with outdated firmware. Only 5-tuple perfect match 106 * is supported. 107 */ 108 static const struct enic_items enic_items_v1[] = { 109 [RTE_FLOW_ITEM_TYPE_IPV4] = { 110 .copy_item = enic_copy_item_ipv4_v1, 111 .valid_start_item = 1, 112 .prev_items = (const enum rte_flow_item_type[]) { 113 RTE_FLOW_ITEM_TYPE_END, 114 }, 115 .inner_copy_item = NULL, 116 }, 117 [RTE_FLOW_ITEM_TYPE_UDP] = { 118 .copy_item = enic_copy_item_udp_v1, 119 .valid_start_item = 0, 120 .prev_items = (const enum rte_flow_item_type[]) { 121 RTE_FLOW_ITEM_TYPE_IPV4, 122 RTE_FLOW_ITEM_TYPE_END, 123 }, 124 .inner_copy_item = NULL, 125 }, 126 [RTE_FLOW_ITEM_TYPE_TCP] = { 127 .copy_item = enic_copy_item_tcp_v1, 128 .valid_start_item = 0, 129 .prev_items = (const enum rte_flow_item_type[]) { 130 RTE_FLOW_ITEM_TYPE_IPV4, 131 RTE_FLOW_ITEM_TYPE_END, 132 }, 133 .inner_copy_item = NULL, 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 .inner_copy_item = enic_copy_item_inner_eth_v2, 150 }, 151 [RTE_FLOW_ITEM_TYPE_VLAN] = { 152 .copy_item = enic_copy_item_vlan_v2, 153 .valid_start_item = 1, 154 .prev_items = (const enum rte_flow_item_type[]) { 155 RTE_FLOW_ITEM_TYPE_ETH, 156 RTE_FLOW_ITEM_TYPE_END, 157 }, 158 .inner_copy_item = enic_copy_item_inner_vlan_v2, 159 }, 160 [RTE_FLOW_ITEM_TYPE_IPV4] = { 161 .copy_item = enic_copy_item_ipv4_v2, 162 .valid_start_item = 1, 163 .prev_items = (const enum rte_flow_item_type[]) { 164 RTE_FLOW_ITEM_TYPE_ETH, 165 RTE_FLOW_ITEM_TYPE_VLAN, 166 RTE_FLOW_ITEM_TYPE_END, 167 }, 168 .inner_copy_item = enic_copy_item_inner_ipv4_v2, 169 }, 170 [RTE_FLOW_ITEM_TYPE_IPV6] = { 171 .copy_item = enic_copy_item_ipv6_v2, 172 .valid_start_item = 1, 173 .prev_items = (const enum rte_flow_item_type[]) { 174 RTE_FLOW_ITEM_TYPE_ETH, 175 RTE_FLOW_ITEM_TYPE_VLAN, 176 RTE_FLOW_ITEM_TYPE_END, 177 }, 178 .inner_copy_item = enic_copy_item_inner_ipv6_v2, 179 }, 180 [RTE_FLOW_ITEM_TYPE_UDP] = { 181 .copy_item = enic_copy_item_udp_v2, 182 .valid_start_item = 0, 183 .prev_items = (const enum rte_flow_item_type[]) { 184 RTE_FLOW_ITEM_TYPE_IPV4, 185 RTE_FLOW_ITEM_TYPE_IPV6, 186 RTE_FLOW_ITEM_TYPE_END, 187 }, 188 .inner_copy_item = enic_copy_item_inner_udp_v2, 189 }, 190 [RTE_FLOW_ITEM_TYPE_TCP] = { 191 .copy_item = enic_copy_item_tcp_v2, 192 .valid_start_item = 0, 193 .prev_items = (const enum rte_flow_item_type[]) { 194 RTE_FLOW_ITEM_TYPE_IPV4, 195 RTE_FLOW_ITEM_TYPE_IPV6, 196 RTE_FLOW_ITEM_TYPE_END, 197 }, 198 .inner_copy_item = enic_copy_item_inner_tcp_v2, 199 }, 200 [RTE_FLOW_ITEM_TYPE_SCTP] = { 201 .copy_item = enic_copy_item_sctp_v2, 202 .valid_start_item = 0, 203 .prev_items = (const enum rte_flow_item_type[]) { 204 RTE_FLOW_ITEM_TYPE_IPV4, 205 RTE_FLOW_ITEM_TYPE_IPV6, 206 RTE_FLOW_ITEM_TYPE_END, 207 }, 208 .inner_copy_item = NULL, 209 }, 210 [RTE_FLOW_ITEM_TYPE_VXLAN] = { 211 .copy_item = enic_copy_item_vxlan_v2, 212 .valid_start_item = 0, 213 .prev_items = (const enum rte_flow_item_type[]) { 214 RTE_FLOW_ITEM_TYPE_UDP, 215 RTE_FLOW_ITEM_TYPE_END, 216 }, 217 .inner_copy_item = NULL, 218 }, 219 }; 220 221 /** NICs with Advanced filters enabled */ 222 static const struct enic_items enic_items_v3[] = { 223 [RTE_FLOW_ITEM_TYPE_ETH] = { 224 .copy_item = enic_copy_item_eth_v2, 225 .valid_start_item = 1, 226 .prev_items = (const enum rte_flow_item_type[]) { 227 RTE_FLOW_ITEM_TYPE_VXLAN, 228 RTE_FLOW_ITEM_TYPE_END, 229 }, 230 .inner_copy_item = enic_copy_item_inner_eth_v2, 231 }, 232 [RTE_FLOW_ITEM_TYPE_VLAN] = { 233 .copy_item = enic_copy_item_vlan_v2, 234 .valid_start_item = 1, 235 .prev_items = (const enum rte_flow_item_type[]) { 236 RTE_FLOW_ITEM_TYPE_ETH, 237 RTE_FLOW_ITEM_TYPE_END, 238 }, 239 .inner_copy_item = enic_copy_item_inner_vlan_v2, 240 }, 241 [RTE_FLOW_ITEM_TYPE_IPV4] = { 242 .copy_item = enic_copy_item_ipv4_v2, 243 .valid_start_item = 1, 244 .prev_items = (const enum rte_flow_item_type[]) { 245 RTE_FLOW_ITEM_TYPE_ETH, 246 RTE_FLOW_ITEM_TYPE_VLAN, 247 RTE_FLOW_ITEM_TYPE_END, 248 }, 249 .inner_copy_item = enic_copy_item_inner_ipv4_v2, 250 }, 251 [RTE_FLOW_ITEM_TYPE_IPV6] = { 252 .copy_item = enic_copy_item_ipv6_v2, 253 .valid_start_item = 1, 254 .prev_items = (const enum rte_flow_item_type[]) { 255 RTE_FLOW_ITEM_TYPE_ETH, 256 RTE_FLOW_ITEM_TYPE_VLAN, 257 RTE_FLOW_ITEM_TYPE_END, 258 }, 259 .inner_copy_item = enic_copy_item_inner_ipv6_v2, 260 }, 261 [RTE_FLOW_ITEM_TYPE_UDP] = { 262 .copy_item = enic_copy_item_udp_v2, 263 .valid_start_item = 1, 264 .prev_items = (const enum rte_flow_item_type[]) { 265 RTE_FLOW_ITEM_TYPE_IPV4, 266 RTE_FLOW_ITEM_TYPE_IPV6, 267 RTE_FLOW_ITEM_TYPE_END, 268 }, 269 .inner_copy_item = enic_copy_item_inner_udp_v2, 270 }, 271 [RTE_FLOW_ITEM_TYPE_TCP] = { 272 .copy_item = enic_copy_item_tcp_v2, 273 .valid_start_item = 1, 274 .prev_items = (const enum rte_flow_item_type[]) { 275 RTE_FLOW_ITEM_TYPE_IPV4, 276 RTE_FLOW_ITEM_TYPE_IPV6, 277 RTE_FLOW_ITEM_TYPE_END, 278 }, 279 .inner_copy_item = enic_copy_item_inner_tcp_v2, 280 }, 281 [RTE_FLOW_ITEM_TYPE_SCTP] = { 282 .copy_item = enic_copy_item_sctp_v2, 283 .valid_start_item = 0, 284 .prev_items = (const enum rte_flow_item_type[]) { 285 RTE_FLOW_ITEM_TYPE_IPV4, 286 RTE_FLOW_ITEM_TYPE_IPV6, 287 RTE_FLOW_ITEM_TYPE_END, 288 }, 289 .inner_copy_item = NULL, 290 }, 291 [RTE_FLOW_ITEM_TYPE_VXLAN] = { 292 .copy_item = enic_copy_item_vxlan_v2, 293 .valid_start_item = 1, 294 .prev_items = (const enum rte_flow_item_type[]) { 295 RTE_FLOW_ITEM_TYPE_UDP, 296 RTE_FLOW_ITEM_TYPE_END, 297 }, 298 .inner_copy_item = NULL, 299 }, 300 }; 301 302 /** Filtering capabilities indexed this NICs supported filter type. */ 303 static const struct enic_filter_cap enic_filter_cap[] = { 304 [FILTER_IPV4_5TUPLE] = { 305 .item_info = enic_items_v1, 306 .max_item_type = RTE_FLOW_ITEM_TYPE_TCP, 307 }, 308 [FILTER_USNIC_IP] = { 309 .item_info = enic_items_v2, 310 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN, 311 }, 312 [FILTER_DPDK_1] = { 313 .item_info = enic_items_v3, 314 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN, 315 }, 316 }; 317 318 /** Supported actions for older NICs */ 319 static const enum rte_flow_action_type enic_supported_actions_v1[] = { 320 RTE_FLOW_ACTION_TYPE_QUEUE, 321 RTE_FLOW_ACTION_TYPE_END, 322 }; 323 324 /** Supported actions for newer NICs */ 325 static const enum rte_flow_action_type enic_supported_actions_v2_id[] = { 326 RTE_FLOW_ACTION_TYPE_QUEUE, 327 RTE_FLOW_ACTION_TYPE_MARK, 328 RTE_FLOW_ACTION_TYPE_FLAG, 329 RTE_FLOW_ACTION_TYPE_END, 330 }; 331 332 static const enum rte_flow_action_type enic_supported_actions_v2_drop[] = { 333 RTE_FLOW_ACTION_TYPE_QUEUE, 334 RTE_FLOW_ACTION_TYPE_MARK, 335 RTE_FLOW_ACTION_TYPE_FLAG, 336 RTE_FLOW_ACTION_TYPE_DROP, 337 RTE_FLOW_ACTION_TYPE_END, 338 }; 339 340 static const enum rte_flow_action_type enic_supported_actions_v2_count[] = { 341 RTE_FLOW_ACTION_TYPE_QUEUE, 342 RTE_FLOW_ACTION_TYPE_MARK, 343 RTE_FLOW_ACTION_TYPE_FLAG, 344 RTE_FLOW_ACTION_TYPE_DROP, 345 RTE_FLOW_ACTION_TYPE_COUNT, 346 RTE_FLOW_ACTION_TYPE_END, 347 }; 348 349 /** Action capabilities indexed by NIC version information */ 350 static const struct enic_action_cap enic_action_cap[] = { 351 [FILTER_ACTION_RQ_STEERING_FLAG] = { 352 .actions = enic_supported_actions_v1, 353 .copy_fn = enic_copy_action_v1, 354 }, 355 [FILTER_ACTION_FILTER_ID_FLAG] = { 356 .actions = enic_supported_actions_v2_id, 357 .copy_fn = enic_copy_action_v2, 358 }, 359 [FILTER_ACTION_DROP_FLAG] = { 360 .actions = enic_supported_actions_v2_drop, 361 .copy_fn = enic_copy_action_v2, 362 }, 363 [FILTER_ACTION_COUNTER_FLAG] = { 364 .actions = enic_supported_actions_v2_count, 365 .copy_fn = enic_copy_action_v2, 366 }, 367 }; 368 369 static int 370 mask_exact_match(const u8 *supported, const u8 *supplied, 371 unsigned int size) 372 { 373 unsigned int i; 374 for (i = 0; i < size; i++) { 375 if (supported[i] != supplied[i]) 376 return 0; 377 } 378 return 1; 379 } 380 381 static int 382 enic_copy_item_ipv4_v1(struct copy_item_args *arg) 383 { 384 const struct rte_flow_item *item = arg->item; 385 struct filter_v2 *enic_filter = arg->filter; 386 const struct rte_flow_item_ipv4 *spec = item->spec; 387 const struct rte_flow_item_ipv4 *mask = item->mask; 388 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 389 struct ipv4_hdr supported_mask = { 390 .src_addr = 0xffffffff, 391 .dst_addr = 0xffffffff, 392 }; 393 394 FLOW_TRACE(); 395 396 if (!mask) 397 mask = &rte_flow_item_ipv4_mask; 398 399 /* This is an exact match filter, both fields must be set */ 400 if (!spec || !spec->hdr.src_addr || !spec->hdr.dst_addr) { 401 FLOW_LOG(ERR, "IPv4 exact match src/dst addr"); 402 return ENOTSUP; 403 } 404 405 /* check that the suppied mask exactly matches capabilty */ 406 if (!mask_exact_match((const u8 *)&supported_mask, 407 (const u8 *)item->mask, sizeof(*mask))) { 408 FLOW_LOG(ERR, "IPv4 exact match mask"); 409 return ENOTSUP; 410 } 411 412 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 413 enic_5tup->src_addr = spec->hdr.src_addr; 414 enic_5tup->dst_addr = spec->hdr.dst_addr; 415 416 return 0; 417 } 418 419 static int 420 enic_copy_item_udp_v1(struct copy_item_args *arg) 421 { 422 const struct rte_flow_item *item = arg->item; 423 struct filter_v2 *enic_filter = arg->filter; 424 const struct rte_flow_item_udp *spec = item->spec; 425 const struct rte_flow_item_udp *mask = item->mask; 426 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 427 struct udp_hdr supported_mask = { 428 .src_port = 0xffff, 429 .dst_port = 0xffff, 430 }; 431 432 FLOW_TRACE(); 433 434 if (!mask) 435 mask = &rte_flow_item_udp_mask; 436 437 /* This is an exact match filter, both ports must be set */ 438 if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) { 439 FLOW_LOG(ERR, "UDP exact match src/dst addr"); 440 return ENOTSUP; 441 } 442 443 /* check that the suppied mask exactly matches capabilty */ 444 if (!mask_exact_match((const u8 *)&supported_mask, 445 (const u8 *)item->mask, sizeof(*mask))) { 446 FLOW_LOG(ERR, "UDP exact match mask"); 447 return ENOTSUP; 448 } 449 450 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 451 enic_5tup->src_port = spec->hdr.src_port; 452 enic_5tup->dst_port = spec->hdr.dst_port; 453 enic_5tup->protocol = PROTO_UDP; 454 455 return 0; 456 } 457 458 static int 459 enic_copy_item_tcp_v1(struct copy_item_args *arg) 460 { 461 const struct rte_flow_item *item = arg->item; 462 struct filter_v2 *enic_filter = arg->filter; 463 const struct rte_flow_item_tcp *spec = item->spec; 464 const struct rte_flow_item_tcp *mask = item->mask; 465 struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4; 466 struct tcp_hdr supported_mask = { 467 .src_port = 0xffff, 468 .dst_port = 0xffff, 469 }; 470 471 FLOW_TRACE(); 472 473 if (!mask) 474 mask = &rte_flow_item_tcp_mask; 475 476 /* This is an exact match filter, both ports must be set */ 477 if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) { 478 FLOW_LOG(ERR, "TCPIPv4 exact match src/dst addr"); 479 return ENOTSUP; 480 } 481 482 /* check that the suppied mask exactly matches capabilty */ 483 if (!mask_exact_match((const u8 *)&supported_mask, 484 (const u8 *)item->mask, sizeof(*mask))) { 485 FLOW_LOG(ERR, "TCP exact match mask"); 486 return ENOTSUP; 487 } 488 489 enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; 490 enic_5tup->src_port = spec->hdr.src_port; 491 enic_5tup->dst_port = spec->hdr.dst_port; 492 enic_5tup->protocol = PROTO_TCP; 493 494 return 0; 495 } 496 497 /* 498 * The common 'copy' function for all inner packet patterns. Patterns are 499 * first appended to the L5 pattern buffer. Then, since the NIC filter 500 * API has no special support for inner packet matching at the moment, 501 * we set EtherType and IP proto as necessary. 502 */ 503 static int 504 copy_inner_common(struct filter_generic_1 *gp, uint8_t *inner_ofst, 505 const void *val, const void *mask, uint8_t val_size, 506 uint8_t proto_off, uint16_t proto_val, uint8_t proto_size) 507 { 508 uint8_t *l5_mask, *l5_val; 509 uint8_t start_off; 510 511 /* No space left in the L5 pattern buffer. */ 512 start_off = *inner_ofst; 513 if ((start_off + val_size) > FILTER_GENERIC_1_KEY_LEN) 514 return ENOTSUP; 515 l5_mask = gp->layer[FILTER_GENERIC_1_L5].mask; 516 l5_val = gp->layer[FILTER_GENERIC_1_L5].val; 517 /* Copy the pattern into the L5 buffer. */ 518 if (val) { 519 memcpy(l5_mask + start_off, mask, val_size); 520 memcpy(l5_val + start_off, val, val_size); 521 } 522 /* Set the protocol field in the previous header. */ 523 if (proto_off) { 524 void *m, *v; 525 526 m = l5_mask + proto_off; 527 v = l5_val + proto_off; 528 if (proto_size == 1) { 529 *(uint8_t *)m = 0xff; 530 *(uint8_t *)v = (uint8_t)proto_val; 531 } else if (proto_size == 2) { 532 *(uint16_t *)m = 0xffff; 533 *(uint16_t *)v = proto_val; 534 } 535 } 536 /* All inner headers land in L5 buffer even if their spec is null. */ 537 *inner_ofst += val_size; 538 return 0; 539 } 540 541 static int 542 enic_copy_item_inner_eth_v2(struct copy_item_args *arg) 543 { 544 const void *mask = arg->item->mask; 545 uint8_t *off = arg->inner_ofst; 546 547 FLOW_TRACE(); 548 if (!mask) 549 mask = &rte_flow_item_eth_mask; 550 arg->l2_proto_off = *off + offsetof(struct ether_hdr, ether_type); 551 return copy_inner_common(&arg->filter->u.generic_1, off, 552 arg->item->spec, mask, sizeof(struct ether_hdr), 553 0 /* no previous protocol */, 0, 0); 554 } 555 556 static int 557 enic_copy_item_inner_vlan_v2(struct copy_item_args *arg) 558 { 559 const void *mask = arg->item->mask; 560 uint8_t *off = arg->inner_ofst; 561 uint8_t eth_type_off; 562 563 FLOW_TRACE(); 564 if (!mask) 565 mask = &rte_flow_item_vlan_mask; 566 /* Append vlan header to L5 and set ether type = TPID */ 567 eth_type_off = arg->l2_proto_off; 568 arg->l2_proto_off = *off + offsetof(struct vlan_hdr, eth_proto); 569 return copy_inner_common(&arg->filter->u.generic_1, off, 570 arg->item->spec, mask, sizeof(struct vlan_hdr), 571 eth_type_off, rte_cpu_to_be_16(ETHER_TYPE_VLAN), 2); 572 } 573 574 static int 575 enic_copy_item_inner_ipv4_v2(struct copy_item_args *arg) 576 { 577 const void *mask = arg->item->mask; 578 uint8_t *off = arg->inner_ofst; 579 580 FLOW_TRACE(); 581 if (!mask) 582 mask = &rte_flow_item_ipv4_mask; 583 /* Append ipv4 header to L5 and set ether type = ipv4 */ 584 arg->l3_proto_off = *off + offsetof(struct ipv4_hdr, next_proto_id); 585 return copy_inner_common(&arg->filter->u.generic_1, off, 586 arg->item->spec, mask, sizeof(struct ipv4_hdr), 587 arg->l2_proto_off, rte_cpu_to_be_16(ETHER_TYPE_IPv4), 2); 588 } 589 590 static int 591 enic_copy_item_inner_ipv6_v2(struct copy_item_args *arg) 592 { 593 const void *mask = arg->item->mask; 594 uint8_t *off = arg->inner_ofst; 595 596 FLOW_TRACE(); 597 if (!mask) 598 mask = &rte_flow_item_ipv6_mask; 599 /* Append ipv6 header to L5 and set ether type = ipv6 */ 600 arg->l3_proto_off = *off + offsetof(struct ipv6_hdr, proto); 601 return copy_inner_common(&arg->filter->u.generic_1, off, 602 arg->item->spec, mask, sizeof(struct ipv6_hdr), 603 arg->l2_proto_off, rte_cpu_to_be_16(ETHER_TYPE_IPv6), 2); 604 } 605 606 static int 607 enic_copy_item_inner_udp_v2(struct copy_item_args *arg) 608 { 609 const void *mask = arg->item->mask; 610 uint8_t *off = arg->inner_ofst; 611 612 FLOW_TRACE(); 613 if (!mask) 614 mask = &rte_flow_item_udp_mask; 615 /* Append udp header to L5 and set ip proto = udp */ 616 return copy_inner_common(&arg->filter->u.generic_1, off, 617 arg->item->spec, mask, sizeof(struct udp_hdr), 618 arg->l3_proto_off, IPPROTO_UDP, 1); 619 } 620 621 static int 622 enic_copy_item_inner_tcp_v2(struct copy_item_args *arg) 623 { 624 const void *mask = arg->item->mask; 625 uint8_t *off = arg->inner_ofst; 626 627 FLOW_TRACE(); 628 if (!mask) 629 mask = &rte_flow_item_tcp_mask; 630 /* Append tcp header to L5 and set ip proto = tcp */ 631 return copy_inner_common(&arg->filter->u.generic_1, off, 632 arg->item->spec, mask, sizeof(struct tcp_hdr), 633 arg->l3_proto_off, IPPROTO_TCP, 1); 634 } 635 636 static int 637 enic_copy_item_eth_v2(struct copy_item_args *arg) 638 { 639 const struct rte_flow_item *item = arg->item; 640 struct filter_v2 *enic_filter = arg->filter; 641 struct ether_hdr enic_spec; 642 struct ether_hdr enic_mask; 643 const struct rte_flow_item_eth *spec = item->spec; 644 const struct rte_flow_item_eth *mask = item->mask; 645 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 646 647 FLOW_TRACE(); 648 649 /* Match all if no spec */ 650 if (!spec) 651 return 0; 652 653 if (!mask) 654 mask = &rte_flow_item_eth_mask; 655 656 memcpy(enic_spec.d_addr.addr_bytes, spec->dst.addr_bytes, 657 ETHER_ADDR_LEN); 658 memcpy(enic_spec.s_addr.addr_bytes, spec->src.addr_bytes, 659 ETHER_ADDR_LEN); 660 661 memcpy(enic_mask.d_addr.addr_bytes, mask->dst.addr_bytes, 662 ETHER_ADDR_LEN); 663 memcpy(enic_mask.s_addr.addr_bytes, mask->src.addr_bytes, 664 ETHER_ADDR_LEN); 665 enic_spec.ether_type = spec->type; 666 enic_mask.ether_type = mask->type; 667 668 /* outer header */ 669 memcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask, 670 sizeof(struct ether_hdr)); 671 memcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec, 672 sizeof(struct ether_hdr)); 673 return 0; 674 } 675 676 static int 677 enic_copy_item_vlan_v2(struct copy_item_args *arg) 678 { 679 const struct rte_flow_item *item = arg->item; 680 struct filter_v2 *enic_filter = arg->filter; 681 const struct rte_flow_item_vlan *spec = item->spec; 682 const struct rte_flow_item_vlan *mask = item->mask; 683 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 684 struct ether_hdr *eth_mask; 685 struct ether_hdr *eth_val; 686 687 FLOW_TRACE(); 688 689 /* Match all if no spec */ 690 if (!spec) 691 return 0; 692 693 if (!mask) 694 mask = &rte_flow_item_vlan_mask; 695 696 eth_mask = (void *)gp->layer[FILTER_GENERIC_1_L2].mask; 697 eth_val = (void *)gp->layer[FILTER_GENERIC_1_L2].val; 698 /* Outer TPID cannot be matched */ 699 if (eth_mask->ether_type) 700 return ENOTSUP; 701 /* 702 * For recent models: 703 * When packet matching, the VIC always compares vlan-stripped 704 * L2, regardless of vlan stripping settings. So, the inner type 705 * from vlan becomes the ether type of the eth header. 706 * 707 * Older models w/o hardware vxlan parser have a different 708 * behavior when vlan stripping is disabled. In this case, 709 * vlan tag remains in the L2 buffer. 710 */ 711 if (!arg->enic->vxlan && !arg->enic->ig_vlan_strip_en) { 712 struct vlan_hdr *vlan; 713 714 vlan = (struct vlan_hdr *)(eth_mask + 1); 715 vlan->eth_proto = mask->inner_type; 716 vlan = (struct vlan_hdr *)(eth_val + 1); 717 vlan->eth_proto = spec->inner_type; 718 } else { 719 eth_mask->ether_type = mask->inner_type; 720 eth_val->ether_type = spec->inner_type; 721 } 722 /* For TCI, use the vlan mask/val fields (little endian). */ 723 gp->mask_vlan = rte_be_to_cpu_16(mask->tci); 724 gp->val_vlan = rte_be_to_cpu_16(spec->tci); 725 return 0; 726 } 727 728 static int 729 enic_copy_item_ipv4_v2(struct copy_item_args *arg) 730 { 731 const struct rte_flow_item *item = arg->item; 732 struct filter_v2 *enic_filter = arg->filter; 733 const struct rte_flow_item_ipv4 *spec = item->spec; 734 const struct rte_flow_item_ipv4 *mask = item->mask; 735 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 736 737 FLOW_TRACE(); 738 739 /* Match IPv4 */ 740 gp->mask_flags |= FILTER_GENERIC_1_IPV4; 741 gp->val_flags |= FILTER_GENERIC_1_IPV4; 742 743 /* Match all if no spec */ 744 if (!spec) 745 return 0; 746 747 if (!mask) 748 mask = &rte_flow_item_ipv4_mask; 749 750 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr, 751 sizeof(struct ipv4_hdr)); 752 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr, 753 sizeof(struct ipv4_hdr)); 754 return 0; 755 } 756 757 static int 758 enic_copy_item_ipv6_v2(struct copy_item_args *arg) 759 { 760 const struct rte_flow_item *item = arg->item; 761 struct filter_v2 *enic_filter = arg->filter; 762 const struct rte_flow_item_ipv6 *spec = item->spec; 763 const struct rte_flow_item_ipv6 *mask = item->mask; 764 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 765 766 FLOW_TRACE(); 767 768 /* Match IPv6 */ 769 gp->mask_flags |= FILTER_GENERIC_1_IPV6; 770 gp->val_flags |= FILTER_GENERIC_1_IPV6; 771 772 /* Match all if no spec */ 773 if (!spec) 774 return 0; 775 776 if (!mask) 777 mask = &rte_flow_item_ipv6_mask; 778 779 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr, 780 sizeof(struct ipv6_hdr)); 781 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr, 782 sizeof(struct ipv6_hdr)); 783 return 0; 784 } 785 786 static int 787 enic_copy_item_udp_v2(struct copy_item_args *arg) 788 { 789 const struct rte_flow_item *item = arg->item; 790 struct filter_v2 *enic_filter = arg->filter; 791 const struct rte_flow_item_udp *spec = item->spec; 792 const struct rte_flow_item_udp *mask = item->mask; 793 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 794 795 FLOW_TRACE(); 796 797 /* Match UDP */ 798 gp->mask_flags |= FILTER_GENERIC_1_UDP; 799 gp->val_flags |= FILTER_GENERIC_1_UDP; 800 801 /* Match all if no spec */ 802 if (!spec) 803 return 0; 804 805 if (!mask) 806 mask = &rte_flow_item_udp_mask; 807 808 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 809 sizeof(struct udp_hdr)); 810 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 811 sizeof(struct udp_hdr)); 812 return 0; 813 } 814 815 static int 816 enic_copy_item_tcp_v2(struct copy_item_args *arg) 817 { 818 const struct rte_flow_item *item = arg->item; 819 struct filter_v2 *enic_filter = arg->filter; 820 const struct rte_flow_item_tcp *spec = item->spec; 821 const struct rte_flow_item_tcp *mask = item->mask; 822 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 823 824 FLOW_TRACE(); 825 826 /* Match TCP */ 827 gp->mask_flags |= FILTER_GENERIC_1_TCP; 828 gp->val_flags |= FILTER_GENERIC_1_TCP; 829 830 /* Match all if no spec */ 831 if (!spec) 832 return 0; 833 834 if (!mask) 835 return ENOTSUP; 836 837 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 838 sizeof(struct tcp_hdr)); 839 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 840 sizeof(struct tcp_hdr)); 841 return 0; 842 } 843 844 static int 845 enic_copy_item_sctp_v2(struct copy_item_args *arg) 846 { 847 const struct rte_flow_item *item = arg->item; 848 struct filter_v2 *enic_filter = arg->filter; 849 const struct rte_flow_item_sctp *spec = item->spec; 850 const struct rte_flow_item_sctp *mask = item->mask; 851 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 852 uint8_t *ip_proto_mask = NULL; 853 uint8_t *ip_proto = NULL; 854 855 FLOW_TRACE(); 856 857 /* 858 * The NIC filter API has no flags for "match sctp", so explicitly set 859 * the protocol number in the IP pattern. 860 */ 861 if (gp->val_flags & FILTER_GENERIC_1_IPV4) { 862 struct ipv4_hdr *ip; 863 ip = (struct ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask; 864 ip_proto_mask = &ip->next_proto_id; 865 ip = (struct ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].val; 866 ip_proto = &ip->next_proto_id; 867 } else if (gp->val_flags & FILTER_GENERIC_1_IPV6) { 868 struct ipv6_hdr *ip; 869 ip = (struct ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask; 870 ip_proto_mask = &ip->proto; 871 ip = (struct ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].val; 872 ip_proto = &ip->proto; 873 } else { 874 /* Need IPv4/IPv6 pattern first */ 875 return EINVAL; 876 } 877 *ip_proto = IPPROTO_SCTP; 878 *ip_proto_mask = 0xff; 879 880 /* Match all if no spec */ 881 if (!spec) 882 return 0; 883 884 if (!mask) 885 mask = &rte_flow_item_sctp_mask; 886 887 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr, 888 sizeof(struct sctp_hdr)); 889 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr, 890 sizeof(struct sctp_hdr)); 891 return 0; 892 } 893 894 static int 895 enic_copy_item_vxlan_v2(struct copy_item_args *arg) 896 { 897 const struct rte_flow_item *item = arg->item; 898 struct filter_v2 *enic_filter = arg->filter; 899 uint8_t *inner_ofst = arg->inner_ofst; 900 const struct rte_flow_item_vxlan *spec = item->spec; 901 const struct rte_flow_item_vxlan *mask = item->mask; 902 struct filter_generic_1 *gp = &enic_filter->u.generic_1; 903 struct udp_hdr *udp; 904 905 FLOW_TRACE(); 906 907 /* 908 * The NIC filter API has no flags for "match vxlan". Set UDP port to 909 * avoid false positives. 910 */ 911 gp->mask_flags |= FILTER_GENERIC_1_UDP; 912 gp->val_flags |= FILTER_GENERIC_1_UDP; 913 udp = (struct udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].mask; 914 udp->dst_port = 0xffff; 915 udp = (struct udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].val; 916 udp->dst_port = RTE_BE16(4789); 917 /* Match all if no spec */ 918 if (!spec) 919 return 0; 920 921 if (!mask) 922 mask = &rte_flow_item_vxlan_mask; 923 924 memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, mask, 925 sizeof(struct vxlan_hdr)); 926 memcpy(gp->layer[FILTER_GENERIC_1_L5].val, spec, 927 sizeof(struct vxlan_hdr)); 928 929 *inner_ofst = sizeof(struct vxlan_hdr); 930 return 0; 931 } 932 933 /** 934 * Return 1 if current item is valid on top of the previous one. 935 * 936 * @param prev_item[in] 937 * The item before this one in the pattern or RTE_FLOW_ITEM_TYPE_END if this 938 * is the first item. 939 * @param item_info[in] 940 * Info about this item, like valid previous items. 941 * @param is_first[in] 942 * True if this the first item in the pattern. 943 */ 944 static int 945 item_stacking_valid(enum rte_flow_item_type prev_item, 946 const struct enic_items *item_info, u8 is_first_item) 947 { 948 enum rte_flow_item_type const *allowed_items = item_info->prev_items; 949 950 FLOW_TRACE(); 951 952 for (; *allowed_items != RTE_FLOW_ITEM_TYPE_END; allowed_items++) { 953 if (prev_item == *allowed_items) 954 return 1; 955 } 956 957 /* This is the first item in the stack. Check if that's cool */ 958 if (is_first_item && item_info->valid_start_item) 959 return 1; 960 961 return 0; 962 } 963 964 /* 965 * Fix up the L5 layer.. HW vxlan parsing removes vxlan header from L5. 966 * Instead it is in L4 following the UDP header. Append the vxlan 967 * pattern to L4 (udp) and shift any inner packet pattern in L5. 968 */ 969 static void 970 fixup_l5_layer(struct enic *enic, struct filter_generic_1 *gp, 971 uint8_t inner_ofst) 972 { 973 uint8_t layer[FILTER_GENERIC_1_KEY_LEN]; 974 uint8_t inner; 975 uint8_t vxlan; 976 977 if (!(inner_ofst > 0 && enic->vxlan)) 978 return; 979 FLOW_TRACE(); 980 vxlan = sizeof(struct vxlan_hdr); 981 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask + sizeof(struct udp_hdr), 982 gp->layer[FILTER_GENERIC_1_L5].mask, vxlan); 983 memcpy(gp->layer[FILTER_GENERIC_1_L4].val + sizeof(struct udp_hdr), 984 gp->layer[FILTER_GENERIC_1_L5].val, vxlan); 985 inner = inner_ofst - vxlan; 986 memset(layer, 0, sizeof(layer)); 987 memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].mask + vxlan, inner); 988 memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, layer, sizeof(layer)); 989 memset(layer, 0, sizeof(layer)); 990 memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].val + vxlan, inner); 991 memcpy(gp->layer[FILTER_GENERIC_1_L5].val, layer, sizeof(layer)); 992 } 993 994 /** 995 * Build the intenal enic filter structure from the provided pattern. The 996 * pattern is validated as the items are copied. 997 * 998 * @param pattern[in] 999 * @param items_info[in] 1000 * Info about this NICs item support, like valid previous items. 1001 * @param enic_filter[out] 1002 * NIC specfilc filters derived from the pattern. 1003 * @param error[out] 1004 */ 1005 static int 1006 enic_copy_filter(const struct rte_flow_item pattern[], 1007 const struct enic_filter_cap *cap, 1008 struct enic *enic, 1009 struct filter_v2 *enic_filter, 1010 struct rte_flow_error *error) 1011 { 1012 int ret; 1013 const struct rte_flow_item *item = pattern; 1014 u8 inner_ofst = 0; /* If encapsulated, ofst into L5 */ 1015 enum rte_flow_item_type prev_item; 1016 const struct enic_items *item_info; 1017 struct copy_item_args args; 1018 enic_copy_item_fn *copy_fn; 1019 u8 is_first_item = 1; 1020 1021 FLOW_TRACE(); 1022 1023 prev_item = 0; 1024 1025 args.filter = enic_filter; 1026 args.inner_ofst = &inner_ofst; 1027 args.enic = enic; 1028 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 1029 /* Get info about how to validate and copy the item. If NULL 1030 * is returned the nic does not support the item. 1031 */ 1032 if (item->type == RTE_FLOW_ITEM_TYPE_VOID) 1033 continue; 1034 1035 item_info = &cap->item_info[item->type]; 1036 if (item->type > cap->max_item_type || 1037 item_info->copy_item == NULL || 1038 (inner_ofst > 0 && item_info->inner_copy_item == NULL)) { 1039 rte_flow_error_set(error, ENOTSUP, 1040 RTE_FLOW_ERROR_TYPE_ITEM, 1041 NULL, "Unsupported item."); 1042 return -rte_errno; 1043 } 1044 1045 /* check to see if item stacking is valid */ 1046 if (!item_stacking_valid(prev_item, item_info, is_first_item)) 1047 goto stacking_error; 1048 1049 args.item = item; 1050 copy_fn = inner_ofst > 0 ? item_info->inner_copy_item : 1051 item_info->copy_item; 1052 ret = copy_fn(&args); 1053 if (ret) 1054 goto item_not_supported; 1055 prev_item = item->type; 1056 is_first_item = 0; 1057 } 1058 fixup_l5_layer(enic, &enic_filter->u.generic_1, inner_ofst); 1059 1060 return 0; 1061 1062 item_not_supported: 1063 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_ITEM, 1064 NULL, "enic type error"); 1065 return -rte_errno; 1066 1067 stacking_error: 1068 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 1069 item, "stacking error"); 1070 return -rte_errno; 1071 } 1072 1073 /** 1074 * Build the intenal version 1 NIC action structure from the provided pattern. 1075 * The pattern is validated as the items are copied. 1076 * 1077 * @param actions[in] 1078 * @param enic_action[out] 1079 * NIC specfilc actions derived from the actions. 1080 * @param error[out] 1081 */ 1082 static int 1083 enic_copy_action_v1(const struct rte_flow_action actions[], 1084 struct filter_action_v2 *enic_action) 1085 { 1086 enum { FATE = 1, }; 1087 uint32_t overlap = 0; 1088 1089 FLOW_TRACE(); 1090 1091 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 1092 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) 1093 continue; 1094 1095 switch (actions->type) { 1096 case RTE_FLOW_ACTION_TYPE_QUEUE: { 1097 const struct rte_flow_action_queue *queue = 1098 (const struct rte_flow_action_queue *) 1099 actions->conf; 1100 1101 if (overlap & FATE) 1102 return ENOTSUP; 1103 overlap |= FATE; 1104 enic_action->rq_idx = 1105 enic_rte_rq_idx_to_sop_idx(queue->index); 1106 break; 1107 } 1108 default: 1109 RTE_ASSERT(0); 1110 break; 1111 } 1112 } 1113 if (!(overlap & FATE)) 1114 return ENOTSUP; 1115 enic_action->type = FILTER_ACTION_RQ_STEERING; 1116 return 0; 1117 } 1118 1119 /** 1120 * Build the intenal version 2 NIC action structure from the provided pattern. 1121 * The pattern is validated as the items are copied. 1122 * 1123 * @param actions[in] 1124 * @param enic_action[out] 1125 * NIC specfilc actions derived from the actions. 1126 * @param error[out] 1127 */ 1128 static int 1129 enic_copy_action_v2(const struct rte_flow_action actions[], 1130 struct filter_action_v2 *enic_action) 1131 { 1132 enum { FATE = 1, MARK = 2, }; 1133 uint32_t overlap = 0; 1134 1135 FLOW_TRACE(); 1136 1137 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 1138 switch (actions->type) { 1139 case RTE_FLOW_ACTION_TYPE_QUEUE: { 1140 const struct rte_flow_action_queue *queue = 1141 (const struct rte_flow_action_queue *) 1142 actions->conf; 1143 1144 if (overlap & FATE) 1145 return ENOTSUP; 1146 overlap |= FATE; 1147 enic_action->rq_idx = 1148 enic_rte_rq_idx_to_sop_idx(queue->index); 1149 enic_action->flags |= FILTER_ACTION_RQ_STEERING_FLAG; 1150 break; 1151 } 1152 case RTE_FLOW_ACTION_TYPE_MARK: { 1153 const struct rte_flow_action_mark *mark = 1154 (const struct rte_flow_action_mark *) 1155 actions->conf; 1156 1157 if (overlap & MARK) 1158 return ENOTSUP; 1159 overlap |= MARK; 1160 /* 1161 * Map mark ID (32-bit) to filter ID (16-bit): 1162 * - Reject values > 16 bits 1163 * - Filter ID 0 is reserved for filters that steer 1164 * but not mark. So add 1 to the mark ID to avoid 1165 * using 0. 1166 * - Filter ID (ENIC_MAGIC_FILTER_ID = 0xffff) is 1167 * reserved for the "flag" action below. 1168 */ 1169 if (mark->id >= ENIC_MAGIC_FILTER_ID - 1) 1170 return EINVAL; 1171 enic_action->filter_id = mark->id + 1; 1172 enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG; 1173 break; 1174 } 1175 case RTE_FLOW_ACTION_TYPE_FLAG: { 1176 if (overlap & MARK) 1177 return ENOTSUP; 1178 overlap |= MARK; 1179 /* ENIC_MAGIC_FILTER_ID is reserved for flagging */ 1180 enic_action->filter_id = ENIC_MAGIC_FILTER_ID; 1181 enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG; 1182 break; 1183 } 1184 case RTE_FLOW_ACTION_TYPE_DROP: { 1185 if (overlap & FATE) 1186 return ENOTSUP; 1187 overlap |= FATE; 1188 enic_action->flags |= FILTER_ACTION_DROP_FLAG; 1189 break; 1190 } 1191 case RTE_FLOW_ACTION_TYPE_COUNT: { 1192 enic_action->flags |= FILTER_ACTION_COUNTER_FLAG; 1193 break; 1194 } 1195 case RTE_FLOW_ACTION_TYPE_VOID: 1196 continue; 1197 default: 1198 RTE_ASSERT(0); 1199 break; 1200 } 1201 } 1202 if (!(overlap & FATE)) 1203 return ENOTSUP; 1204 enic_action->type = FILTER_ACTION_V2; 1205 return 0; 1206 } 1207 1208 /** Check if the action is supported */ 1209 static int 1210 enic_match_action(const struct rte_flow_action *action, 1211 const enum rte_flow_action_type *supported_actions) 1212 { 1213 for (; *supported_actions != RTE_FLOW_ACTION_TYPE_END; 1214 supported_actions++) { 1215 if (action->type == *supported_actions) 1216 return 1; 1217 } 1218 return 0; 1219 } 1220 1221 /** Get the NIC filter capabilties structure */ 1222 static const struct enic_filter_cap * 1223 enic_get_filter_cap(struct enic *enic) 1224 { 1225 if (enic->flow_filter_mode) 1226 return &enic_filter_cap[enic->flow_filter_mode]; 1227 1228 return NULL; 1229 } 1230 1231 /** Get the actions for this NIC version. */ 1232 static const struct enic_action_cap * 1233 enic_get_action_cap(struct enic *enic) 1234 { 1235 const struct enic_action_cap *ea; 1236 uint8_t actions; 1237 1238 actions = enic->filter_actions; 1239 if (actions & FILTER_ACTION_COUNTER_FLAG) 1240 ea = &enic_action_cap[FILTER_ACTION_COUNTER_FLAG]; 1241 else if (actions & FILTER_ACTION_DROP_FLAG) 1242 ea = &enic_action_cap[FILTER_ACTION_DROP_FLAG]; 1243 else if (actions & FILTER_ACTION_FILTER_ID_FLAG) 1244 ea = &enic_action_cap[FILTER_ACTION_FILTER_ID_FLAG]; 1245 else 1246 ea = &enic_action_cap[FILTER_ACTION_RQ_STEERING_FLAG]; 1247 return ea; 1248 } 1249 1250 /* Debug function to dump internal NIC action structure. */ 1251 static void 1252 enic_dump_actions(const struct filter_action_v2 *ea) 1253 { 1254 if (ea->type == FILTER_ACTION_RQ_STEERING) { 1255 FLOW_LOG(INFO, "Action(V1), queue: %u\n", ea->rq_idx); 1256 } else if (ea->type == FILTER_ACTION_V2) { 1257 FLOW_LOG(INFO, "Actions(V2)\n"); 1258 if (ea->flags & FILTER_ACTION_RQ_STEERING_FLAG) 1259 FLOW_LOG(INFO, "\tqueue: %u\n", 1260 enic_sop_rq_idx_to_rte_idx(ea->rq_idx)); 1261 if (ea->flags & FILTER_ACTION_FILTER_ID_FLAG) 1262 FLOW_LOG(INFO, "\tfilter_id: %u\n", ea->filter_id); 1263 } 1264 } 1265 1266 /* Debug function to dump internal NIC filter structure. */ 1267 static void 1268 enic_dump_filter(const struct filter_v2 *filt) 1269 { 1270 const struct filter_generic_1 *gp; 1271 int i, j, mbyte; 1272 char buf[128], *bp; 1273 char ip4[16], ip6[16], udp[16], tcp[16], tcpudp[16], ip4csum[16]; 1274 char l4csum[16], ipfrag[16]; 1275 1276 switch (filt->type) { 1277 case FILTER_IPV4_5TUPLE: 1278 FLOW_LOG(INFO, "FILTER_IPV4_5TUPLE\n"); 1279 break; 1280 case FILTER_USNIC_IP: 1281 case FILTER_DPDK_1: 1282 /* FIXME: this should be a loop */ 1283 gp = &filt->u.generic_1; 1284 FLOW_LOG(INFO, "Filter: vlan: 0x%04x, mask: 0x%04x\n", 1285 gp->val_vlan, gp->mask_vlan); 1286 1287 if (gp->mask_flags & FILTER_GENERIC_1_IPV4) 1288 sprintf(ip4, "%s ", 1289 (gp->val_flags & FILTER_GENERIC_1_IPV4) 1290 ? "ip4(y)" : "ip4(n)"); 1291 else 1292 sprintf(ip4, "%s ", "ip4(x)"); 1293 1294 if (gp->mask_flags & FILTER_GENERIC_1_IPV6) 1295 sprintf(ip6, "%s ", 1296 (gp->val_flags & FILTER_GENERIC_1_IPV4) 1297 ? "ip6(y)" : "ip6(n)"); 1298 else 1299 sprintf(ip6, "%s ", "ip6(x)"); 1300 1301 if (gp->mask_flags & FILTER_GENERIC_1_UDP) 1302 sprintf(udp, "%s ", 1303 (gp->val_flags & FILTER_GENERIC_1_UDP) 1304 ? "udp(y)" : "udp(n)"); 1305 else 1306 sprintf(udp, "%s ", "udp(x)"); 1307 1308 if (gp->mask_flags & FILTER_GENERIC_1_TCP) 1309 sprintf(tcp, "%s ", 1310 (gp->val_flags & FILTER_GENERIC_1_TCP) 1311 ? "tcp(y)" : "tcp(n)"); 1312 else 1313 sprintf(tcp, "%s ", "tcp(x)"); 1314 1315 if (gp->mask_flags & FILTER_GENERIC_1_TCP_OR_UDP) 1316 sprintf(tcpudp, "%s ", 1317 (gp->val_flags & FILTER_GENERIC_1_TCP_OR_UDP) 1318 ? "tcpudp(y)" : "tcpudp(n)"); 1319 else 1320 sprintf(tcpudp, "%s ", "tcpudp(x)"); 1321 1322 if (gp->mask_flags & FILTER_GENERIC_1_IP4SUM_OK) 1323 sprintf(ip4csum, "%s ", 1324 (gp->val_flags & FILTER_GENERIC_1_IP4SUM_OK) 1325 ? "ip4csum(y)" : "ip4csum(n)"); 1326 else 1327 sprintf(ip4csum, "%s ", "ip4csum(x)"); 1328 1329 if (gp->mask_flags & FILTER_GENERIC_1_L4SUM_OK) 1330 sprintf(l4csum, "%s ", 1331 (gp->val_flags & FILTER_GENERIC_1_L4SUM_OK) 1332 ? "l4csum(y)" : "l4csum(n)"); 1333 else 1334 sprintf(l4csum, "%s ", "l4csum(x)"); 1335 1336 if (gp->mask_flags & FILTER_GENERIC_1_IPFRAG) 1337 sprintf(ipfrag, "%s ", 1338 (gp->val_flags & FILTER_GENERIC_1_IPFRAG) 1339 ? "ipfrag(y)" : "ipfrag(n)"); 1340 else 1341 sprintf(ipfrag, "%s ", "ipfrag(x)"); 1342 FLOW_LOG(INFO, "\tFlags: %s%s%s%s%s%s%s%s\n", ip4, ip6, udp, 1343 tcp, tcpudp, ip4csum, l4csum, ipfrag); 1344 1345 for (i = 0; i < FILTER_GENERIC_1_NUM_LAYERS; i++) { 1346 mbyte = FILTER_GENERIC_1_KEY_LEN - 1; 1347 while (mbyte && !gp->layer[i].mask[mbyte]) 1348 mbyte--; 1349 if (mbyte == 0) 1350 continue; 1351 1352 bp = buf; 1353 for (j = 0; j <= mbyte; j++) { 1354 sprintf(bp, "%02x", 1355 gp->layer[i].mask[j]); 1356 bp += 2; 1357 } 1358 *bp = '\0'; 1359 FLOW_LOG(INFO, "\tL%u mask: %s\n", i + 2, buf); 1360 bp = buf; 1361 for (j = 0; j <= mbyte; j++) { 1362 sprintf(bp, "%02x", 1363 gp->layer[i].val[j]); 1364 bp += 2; 1365 } 1366 *bp = '\0'; 1367 FLOW_LOG(INFO, "\tL%u val: %s\n", i + 2, buf); 1368 } 1369 break; 1370 default: 1371 FLOW_LOG(INFO, "FILTER UNKNOWN\n"); 1372 break; 1373 } 1374 } 1375 1376 /* Debug function to dump internal NIC flow structures. */ 1377 static void 1378 enic_dump_flow(const struct filter_action_v2 *ea, const struct filter_v2 *filt) 1379 { 1380 enic_dump_filter(filt); 1381 enic_dump_actions(ea); 1382 } 1383 1384 1385 /** 1386 * Internal flow parse/validate function. 1387 * 1388 * @param dev[in] 1389 * This device pointer. 1390 * @param pattern[in] 1391 * @param actions[in] 1392 * @param error[out] 1393 * @param enic_filter[out] 1394 * Internal NIC filter structure pointer. 1395 * @param enic_action[out] 1396 * Internal NIC action structure pointer. 1397 */ 1398 static int 1399 enic_flow_parse(struct rte_eth_dev *dev, 1400 const struct rte_flow_attr *attrs, 1401 const struct rte_flow_item pattern[], 1402 const struct rte_flow_action actions[], 1403 struct rte_flow_error *error, 1404 struct filter_v2 *enic_filter, 1405 struct filter_action_v2 *enic_action) 1406 { 1407 unsigned int ret = 0; 1408 struct enic *enic = pmd_priv(dev); 1409 const struct enic_filter_cap *enic_filter_cap; 1410 const struct enic_action_cap *enic_action_cap; 1411 const struct rte_flow_action *action; 1412 1413 FLOW_TRACE(); 1414 1415 memset(enic_filter, 0, sizeof(*enic_filter)); 1416 memset(enic_action, 0, sizeof(*enic_action)); 1417 1418 if (!pattern) { 1419 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, 1420 NULL, "No pattern specified"); 1421 return -rte_errno; 1422 } 1423 1424 if (!actions) { 1425 rte_flow_error_set(error, EINVAL, 1426 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 1427 NULL, "No action specified"); 1428 return -rte_errno; 1429 } 1430 1431 if (attrs) { 1432 if (attrs->group) { 1433 rte_flow_error_set(error, ENOTSUP, 1434 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 1435 NULL, 1436 "priority groups are not supported"); 1437 return -rte_errno; 1438 } else if (attrs->priority) { 1439 rte_flow_error_set(error, ENOTSUP, 1440 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1441 NULL, 1442 "priorities are not supported"); 1443 return -rte_errno; 1444 } else if (attrs->egress) { 1445 rte_flow_error_set(error, ENOTSUP, 1446 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 1447 NULL, 1448 "egress is not supported"); 1449 return -rte_errno; 1450 } else if (attrs->transfer) { 1451 rte_flow_error_set(error, ENOTSUP, 1452 RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 1453 NULL, 1454 "transfer is not supported"); 1455 return -rte_errno; 1456 } else if (!attrs->ingress) { 1457 rte_flow_error_set(error, ENOTSUP, 1458 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1459 NULL, 1460 "only ingress is supported"); 1461 return -rte_errno; 1462 } 1463 1464 } else { 1465 rte_flow_error_set(error, EINVAL, 1466 RTE_FLOW_ERROR_TYPE_ATTR, 1467 NULL, "No attribute specified"); 1468 return -rte_errno; 1469 } 1470 1471 /* Verify Actions. */ 1472 enic_action_cap = enic_get_action_cap(enic); 1473 for (action = &actions[0]; action->type != RTE_FLOW_ACTION_TYPE_END; 1474 action++) { 1475 if (action->type == RTE_FLOW_ACTION_TYPE_VOID) 1476 continue; 1477 else if (!enic_match_action(action, enic_action_cap->actions)) 1478 break; 1479 } 1480 if (action->type != RTE_FLOW_ACTION_TYPE_END) { 1481 rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_ACTION, 1482 action, "Invalid action."); 1483 return -rte_errno; 1484 } 1485 ret = enic_action_cap->copy_fn(actions, enic_action); 1486 if (ret) { 1487 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, 1488 NULL, "Unsupported action."); 1489 return -rte_errno; 1490 } 1491 1492 /* Verify Flow items. If copying the filter from flow format to enic 1493 * format fails, the flow is not supported 1494 */ 1495 enic_filter_cap = enic_get_filter_cap(enic); 1496 if (enic_filter_cap == NULL) { 1497 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, 1498 NULL, "Flow API not available"); 1499 return -rte_errno; 1500 } 1501 enic_filter->type = enic->flow_filter_mode; 1502 ret = enic_copy_filter(pattern, enic_filter_cap, enic, 1503 enic_filter, error); 1504 return ret; 1505 } 1506 1507 /** 1508 * Push filter/action to the NIC. 1509 * 1510 * @param enic[in] 1511 * Device structure pointer. 1512 * @param enic_filter[in] 1513 * Internal NIC filter structure pointer. 1514 * @param enic_action[in] 1515 * Internal NIC action structure pointer. 1516 * @param error[out] 1517 */ 1518 static struct rte_flow * 1519 enic_flow_add_filter(struct enic *enic, struct filter_v2 *enic_filter, 1520 struct filter_action_v2 *enic_action, 1521 struct rte_flow_error *error) 1522 { 1523 struct rte_flow *flow; 1524 int err; 1525 uint16_t entry; 1526 int ctr_idx; 1527 int last_max_flow_ctr; 1528 1529 FLOW_TRACE(); 1530 1531 flow = rte_calloc(__func__, 1, sizeof(*flow), 0); 1532 if (!flow) { 1533 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, 1534 NULL, "cannot allocate flow memory"); 1535 return NULL; 1536 } 1537 1538 flow->counter_idx = -1; 1539 last_max_flow_ctr = -1; 1540 if (enic_action->flags & FILTER_ACTION_COUNTER_FLAG) { 1541 if (!vnic_dev_counter_alloc(enic->vdev, (uint32_t *)&ctr_idx)) { 1542 rte_flow_error_set(error, ENOMEM, 1543 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1544 NULL, "cannot allocate counter"); 1545 goto unwind_flow_alloc; 1546 } 1547 flow->counter_idx = ctr_idx; 1548 enic_action->counter_index = ctr_idx; 1549 1550 /* If index is the largest, increase the counter DMA size */ 1551 if (ctr_idx > enic->max_flow_counter) { 1552 err = vnic_dev_counter_dma_cfg(enic->vdev, 1553 VNIC_FLOW_COUNTER_UPDATE_MSECS, 1554 ctr_idx + 1); 1555 if (err) { 1556 rte_flow_error_set(error, -err, 1557 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1558 NULL, "counter DMA config failed"); 1559 goto unwind_ctr_alloc; 1560 } 1561 last_max_flow_ctr = enic->max_flow_counter; 1562 enic->max_flow_counter = ctr_idx; 1563 } 1564 } 1565 1566 /* entry[in] is the queue id, entry[out] is the filter Id for delete */ 1567 entry = enic_action->rq_idx; 1568 err = vnic_dev_classifier(enic->vdev, CLSF_ADD, &entry, enic_filter, 1569 enic_action); 1570 if (err) { 1571 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE, 1572 NULL, "vnic_dev_classifier error"); 1573 goto unwind_ctr_dma_cfg; 1574 } 1575 1576 flow->enic_filter_id = entry; 1577 flow->enic_filter = *enic_filter; 1578 1579 return flow; 1580 1581 /* unwind if there are errors */ 1582 unwind_ctr_dma_cfg: 1583 if (last_max_flow_ctr != -1) { 1584 /* reduce counter DMA size */ 1585 vnic_dev_counter_dma_cfg(enic->vdev, 1586 VNIC_FLOW_COUNTER_UPDATE_MSECS, 1587 last_max_flow_ctr + 1); 1588 enic->max_flow_counter = last_max_flow_ctr; 1589 } 1590 unwind_ctr_alloc: 1591 if (flow->counter_idx != -1) 1592 vnic_dev_counter_free(enic->vdev, ctr_idx); 1593 unwind_flow_alloc: 1594 rte_free(flow); 1595 return NULL; 1596 } 1597 1598 /** 1599 * Remove filter/action from the NIC. 1600 * 1601 * @param enic[in] 1602 * Device structure pointer. 1603 * @param filter_id[in] 1604 * Id of NIC filter. 1605 * @param enic_action[in] 1606 * Internal NIC action structure pointer. 1607 * @param error[out] 1608 */ 1609 static int 1610 enic_flow_del_filter(struct enic *enic, struct rte_flow *flow, 1611 struct rte_flow_error *error) 1612 { 1613 u16 filter_id; 1614 int err; 1615 1616 FLOW_TRACE(); 1617 1618 filter_id = flow->enic_filter_id; 1619 err = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL, NULL); 1620 if (err) { 1621 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE, 1622 NULL, "vnic_dev_classifier failed"); 1623 return -err; 1624 } 1625 1626 if (flow->counter_idx != -1) { 1627 if (!vnic_dev_counter_free(enic->vdev, flow->counter_idx)) 1628 dev_err(enic, "counter free failed, idx: %d\n", 1629 flow->counter_idx); 1630 flow->counter_idx = -1; 1631 } 1632 return 0; 1633 } 1634 1635 /* 1636 * The following functions are callbacks for Generic flow API. 1637 */ 1638 1639 /** 1640 * Validate a flow supported by the NIC. 1641 * 1642 * @see rte_flow_validate() 1643 * @see rte_flow_ops 1644 */ 1645 static int 1646 enic_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attrs, 1647 const struct rte_flow_item pattern[], 1648 const struct rte_flow_action actions[], 1649 struct rte_flow_error *error) 1650 { 1651 struct filter_v2 enic_filter; 1652 struct filter_action_v2 enic_action; 1653 int ret; 1654 1655 FLOW_TRACE(); 1656 1657 ret = enic_flow_parse(dev, attrs, pattern, actions, error, 1658 &enic_filter, &enic_action); 1659 if (!ret) 1660 enic_dump_flow(&enic_action, &enic_filter); 1661 return ret; 1662 } 1663 1664 /** 1665 * Create a flow supported by the NIC. 1666 * 1667 * @see rte_flow_create() 1668 * @see rte_flow_ops 1669 */ 1670 static struct rte_flow * 1671 enic_flow_create(struct rte_eth_dev *dev, 1672 const struct rte_flow_attr *attrs, 1673 const struct rte_flow_item pattern[], 1674 const struct rte_flow_action actions[], 1675 struct rte_flow_error *error) 1676 { 1677 int ret; 1678 struct filter_v2 enic_filter; 1679 struct filter_action_v2 enic_action; 1680 struct rte_flow *flow; 1681 struct enic *enic = pmd_priv(dev); 1682 1683 FLOW_TRACE(); 1684 1685 ret = enic_flow_parse(dev, attrs, pattern, actions, error, &enic_filter, 1686 &enic_action); 1687 if (ret < 0) 1688 return NULL; 1689 1690 rte_spinlock_lock(&enic->flows_lock); 1691 flow = enic_flow_add_filter(enic, &enic_filter, &enic_action, 1692 error); 1693 if (flow) 1694 LIST_INSERT_HEAD(&enic->flows, flow, next); 1695 rte_spinlock_unlock(&enic->flows_lock); 1696 1697 return flow; 1698 } 1699 1700 /** 1701 * Destroy a flow supported by the NIC. 1702 * 1703 * @see rte_flow_destroy() 1704 * @see rte_flow_ops 1705 */ 1706 static int 1707 enic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, 1708 __rte_unused struct rte_flow_error *error) 1709 { 1710 struct enic *enic = pmd_priv(dev); 1711 1712 FLOW_TRACE(); 1713 1714 rte_spinlock_lock(&enic->flows_lock); 1715 enic_flow_del_filter(enic, flow, error); 1716 LIST_REMOVE(flow, next); 1717 rte_spinlock_unlock(&enic->flows_lock); 1718 rte_free(flow); 1719 return 0; 1720 } 1721 1722 /** 1723 * Flush all flows on the device. 1724 * 1725 * @see rte_flow_flush() 1726 * @see rte_flow_ops 1727 */ 1728 static int 1729 enic_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error) 1730 { 1731 struct rte_flow *flow; 1732 struct enic *enic = pmd_priv(dev); 1733 1734 FLOW_TRACE(); 1735 1736 rte_spinlock_lock(&enic->flows_lock); 1737 1738 while (!LIST_EMPTY(&enic->flows)) { 1739 flow = LIST_FIRST(&enic->flows); 1740 enic_flow_del_filter(enic, flow, error); 1741 LIST_REMOVE(flow, next); 1742 rte_free(flow); 1743 } 1744 rte_spinlock_unlock(&enic->flows_lock); 1745 return 0; 1746 } 1747 1748 static int 1749 enic_flow_query_count(struct rte_eth_dev *dev, 1750 struct rte_flow *flow, void *data, 1751 struct rte_flow_error *error) 1752 { 1753 struct enic *enic = pmd_priv(dev); 1754 struct rte_flow_query_count *query; 1755 uint64_t packets, bytes; 1756 1757 FLOW_TRACE(); 1758 1759 if (flow->counter_idx == -1) { 1760 return rte_flow_error_set(error, ENOTSUP, 1761 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1762 NULL, 1763 "flow does not have counter"); 1764 } 1765 query = (struct rte_flow_query_count *)data; 1766 if (!vnic_dev_counter_query(enic->vdev, flow->counter_idx, 1767 !!query->reset, &packets, &bytes)) { 1768 return rte_flow_error_set 1769 (error, EINVAL, 1770 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1771 NULL, 1772 "cannot read counter"); 1773 } 1774 query->hits_set = 1; 1775 query->bytes_set = 1; 1776 query->hits = packets; 1777 query->bytes = bytes; 1778 return 0; 1779 } 1780 1781 static int 1782 enic_flow_query(struct rte_eth_dev *dev, 1783 struct rte_flow *flow, 1784 const struct rte_flow_action *actions, 1785 void *data, 1786 struct rte_flow_error *error) 1787 { 1788 int ret = 0; 1789 1790 FLOW_TRACE(); 1791 1792 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 1793 switch (actions->type) { 1794 case RTE_FLOW_ACTION_TYPE_VOID: 1795 break; 1796 case RTE_FLOW_ACTION_TYPE_COUNT: 1797 ret = enic_flow_query_count(dev, flow, data, error); 1798 break; 1799 default: 1800 return rte_flow_error_set(error, ENOTSUP, 1801 RTE_FLOW_ERROR_TYPE_ACTION, 1802 actions, 1803 "action not supported"); 1804 } 1805 if (ret < 0) 1806 return ret; 1807 } 1808 return 0; 1809 } 1810 1811 /** 1812 * Flow callback registration. 1813 * 1814 * @see rte_flow_ops 1815 */ 1816 const struct rte_flow_ops enic_flow_ops = { 1817 .validate = enic_flow_validate, 1818 .create = enic_flow_create, 1819 .destroy = enic_flow_destroy, 1820 .flush = enic_flow_flush, 1821 .query = enic_flow_query, 1822 }; 1823