1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2008-2019 Cisco Systems, Inc. All rights reserved. 3 */ 4 5 #include <errno.h> 6 #include <stdint.h> 7 #include <rte_log.h> 8 #include <ethdev_driver.h> 9 #include <rte_flow_driver.h> 10 #include <rte_ether.h> 11 #include <rte_hash.h> 12 #include <rte_jhash.h> 13 #include <rte_ip.h> 14 #include <rte_udp.h> 15 #include <rte_memzone.h> 16 17 #include "enic_compat.h" 18 #include "enic.h" 19 #include "vnic_dev.h" 20 #include "vnic_nic.h" 21 22 #define IP_DEFTTL 64 /* from RFC 1340. */ 23 #define IP6_VTC_FLOW 0x60000000 24 25 /* Highest Item type supported by Flowman */ 26 #define FM_MAX_ITEM_TYPE RTE_FLOW_ITEM_TYPE_VXLAN 27 28 /* Up to 1024 TCAM entries */ 29 #define FM_MAX_TCAM_TABLE_SIZE 1024 30 31 /* Up to 4096 entries per exact match table */ 32 #define FM_MAX_EXACT_TABLE_SIZE 4096 33 34 /* Number of counters to increase on for each increment */ 35 #define FM_COUNTERS_EXPAND 100 36 37 #define FM_INVALID_HANDLE 0 38 39 /* Low priority used for implicit VF -> representor flow */ 40 #define FM_LOWEST_PRIORITY 100000 41 42 /* High priority used for implicit representor -> VF flow */ 43 #define FM_HIGHEST_PRIORITY 0 44 45 /* Tag used for implicit VF <-> representor flows */ 46 #define FM_VF_REP_TAG 1 47 48 /* Max number of actions supported by VIC is 2K. Make hash table double that. */ 49 #define FM_MAX_ACTION_TABLE_SIZE 4096 50 51 /* 52 * Flow exact match tables (FET) in the VIC and rte_flow groups. 53 * Use a simple scheme to map groups to tables. 54 * Group 0 uses the single TCAM tables, one for each direction. 55 * Group 1, 2, ... uses its own exact match table. 56 * 57 * The TCAM tables are allocated upfront during init. 58 * 59 * Exact match tables are allocated on demand. 3 paths that lead allocations. 60 * 61 * 1. Add a flow that jumps from group 0 to group N. 62 * 63 * If N does not exist, we allocate an exact match table for it, using 64 * a dummy key. A key is required for the table. 65 * 66 * 2. Add a flow that uses group N. 67 * 68 * If N does not exist, we allocate an exact match table for it, using 69 * the flow's key. Subsequent flows to the same group all should have 70 * the same key. 71 * 72 * Without a jump flow to N, N is not reachable in hardware. No packets 73 * reach N and match. 74 * 75 * 3. Add a flow to an empty group N. 76 * 77 * N has been created via (1) and the dummy key. We free that table, allocate 78 * a new table using the new flow's key. Also re-do the existing jump flow to 79 * point to the new table. 80 */ 81 #define FM_TCAM_RTE_GROUP 0 82 83 struct enic_fm_fet { 84 TAILQ_ENTRY(enic_fm_fet) list; 85 uint32_t group; /* rte_flow group ID */ 86 uint64_t handle; /* Exact match table handle from flowman */ 87 uint8_t ingress; 88 uint8_t default_key; 89 int ref; /* Reference count via get/put */ 90 struct fm_key_template key; /* Key associated with the table */ 91 }; 92 93 struct enic_fm_counter { 94 SLIST_ENTRY(enic_fm_counter) next; 95 uint32_t handle; 96 }; 97 98 struct enic_fm_action { 99 int ref; 100 uint64_t handle; 101 struct fm_action key; 102 }; 103 104 /* rte_flow.fm */ 105 struct enic_fm_flow { 106 bool counter_valid; 107 uint64_t entry_handle; 108 struct enic_fm_action *action; 109 struct enic_fm_counter *counter; 110 struct enic_fm_fet *fet; 111 /* Auto-added steer action for hairpin flows (e.g. vnic->vnic) */ 112 struct enic_fm_flow *hairpin_steer_flow; 113 }; 114 115 struct enic_fm_jump_flow { 116 TAILQ_ENTRY(enic_fm_jump_flow) list; 117 struct rte_flow *flow; 118 uint32_t group; 119 struct fm_tcam_match_entry match; 120 struct fm_action action; 121 }; 122 123 /* 124 * Flowman uses host memory for commands. This structure is allocated 125 * in DMA-able memory. 126 */ 127 union enic_flowman_cmd_mem { 128 struct fm_tcam_match_table fm_tcam_match_table; 129 struct fm_exact_match_table fm_exact_match_table; 130 struct fm_tcam_match_entry fm_tcam_match_entry; 131 struct fm_exact_match_entry fm_exact_match_entry; 132 struct fm_action fm_action; 133 }; 134 135 /* 136 * PF has a flowman instance, and VF representors share it with PF. 137 * PF allocates this structure and owns it. VF representors borrow 138 * the PF's structure during API calls (e.g. create, query). 139 */ 140 struct enic_flowman { 141 struct enic *owner_enic; /* PF */ 142 struct enic *user_enic; /* API caller (PF or representor) */ 143 /* 144 * Representors and PF share the same underlying flowman. 145 * Lock API calls to serialize accesses from them. Only used 146 * when VF representors are present. 147 */ 148 rte_spinlock_t lock; 149 /* Command buffer */ 150 struct { 151 union enic_flowman_cmd_mem *va; 152 dma_addr_t pa; 153 } cmd; 154 /* TCAM tables allocated upfront, used for group 0 */ 155 uint64_t ig_tcam_hndl; 156 uint64_t eg_tcam_hndl; 157 /* Counters */ 158 SLIST_HEAD(enic_free_counters, enic_fm_counter) counters; 159 void *counter_stack; 160 uint32_t counters_alloced; 161 /* Exact match tables for groups != 0, dynamically allocated */ 162 TAILQ_HEAD(fet_list, enic_fm_fet) fet_list; 163 /* 164 * Default exact match tables used for jump actions to 165 * non-existent groups. 166 */ 167 struct enic_fm_fet *default_eg_fet; 168 struct enic_fm_fet *default_ig_fet; 169 /* hash table for Action reuse */ 170 struct rte_hash *action_hash; 171 /* Flows that jump to the default table above */ 172 TAILQ_HEAD(jump_flow_list, enic_fm_jump_flow) jump_list; 173 /* 174 * Scratch data used during each invocation of flow_create 175 * and flow_validate. 176 */ 177 struct enic_fm_fet *fet; 178 struct fm_tcam_match_entry tcam_entry; 179 struct fm_action action; 180 struct fm_action action_tmp; /* enic_fm_reorder_action_op */ 181 int action_op_count; 182 /* Tags used for representor flows */ 183 uint8_t vf_rep_tag; 184 /* For auto-added steer action for hairpin */ 185 int need_hairpin_steer; 186 uint64_t hairpin_steer_vnic_h; 187 }; 188 189 static int enic_fm_tbl_free(struct enic_flowman *fm, uint64_t handle); 190 /* 191 * API functions (create, destroy, validate, flush) call begin_fm() 192 * upon entering to save the caller enic (PF or VF representor) and 193 * lock. Upon exit, they call end_fm() to unlock. 194 */ 195 static struct enic_flowman *begin_fm(struct enic *enic); 196 static void end_fm(struct enic_flowman *fm); 197 /* Delete internal flows created for representor paths */ 198 static void delete_rep_flows(struct enic *enic); 199 200 /* 201 * Common arguments passed to copy_item functions. Use this structure 202 * so we can easily add new arguments. 203 * item: Item specification. 204 * fm_tcam_entry: Flowman TCAM match entry. 205 * header_level: 0 for outer header, 1 for inner header. 206 */ 207 struct copy_item_args { 208 const struct rte_flow_item *item; 209 struct fm_tcam_match_entry *fm_tcam_entry; 210 uint8_t header_level; 211 }; 212 213 /* functions for copying items into flowman match */ 214 typedef int (enic_copy_item_fn)(struct copy_item_args *arg); 215 216 /* Info about how to copy items into flowman match */ 217 struct enic_fm_items { 218 /* Function for copying and validating an item. */ 219 enic_copy_item_fn * const copy_item; 220 /* List of valid previous items. */ 221 const enum rte_flow_item_type * const prev_items; 222 /* 223 * True if it's OK for this item to be the first item. For some NIC 224 * versions, it's invalid to start the stack above layer 3. 225 */ 226 const uint8_t valid_start_item; 227 }; 228 229 static enic_copy_item_fn enic_fm_copy_item_eth; 230 static enic_copy_item_fn enic_fm_copy_item_ipv4; 231 static enic_copy_item_fn enic_fm_copy_item_ipv6; 232 static enic_copy_item_fn enic_fm_copy_item_raw; 233 static enic_copy_item_fn enic_fm_copy_item_sctp; 234 static enic_copy_item_fn enic_fm_copy_item_tcp; 235 static enic_copy_item_fn enic_fm_copy_item_udp; 236 static enic_copy_item_fn enic_fm_copy_item_vlan; 237 static enic_copy_item_fn enic_fm_copy_item_vxlan; 238 239 /* Ingress actions */ 240 static const enum rte_flow_action_type enic_fm_supported_ig_actions[] = { 241 RTE_FLOW_ACTION_TYPE_COUNT, 242 RTE_FLOW_ACTION_TYPE_DROP, 243 RTE_FLOW_ACTION_TYPE_FLAG, 244 RTE_FLOW_ACTION_TYPE_JUMP, 245 RTE_FLOW_ACTION_TYPE_MARK, 246 RTE_FLOW_ACTION_TYPE_OF_POP_VLAN, 247 RTE_FLOW_ACTION_TYPE_PORT_ID, 248 RTE_FLOW_ACTION_TYPE_PASSTHRU, 249 RTE_FLOW_ACTION_TYPE_QUEUE, 250 RTE_FLOW_ACTION_TYPE_RSS, 251 RTE_FLOW_ACTION_TYPE_VOID, 252 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, 253 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, 254 RTE_FLOW_ACTION_TYPE_END, /* END must be the last entry */ 255 }; 256 257 /* Egress actions */ 258 static const enum rte_flow_action_type enic_fm_supported_eg_actions[] = { 259 RTE_FLOW_ACTION_TYPE_COUNT, 260 RTE_FLOW_ACTION_TYPE_DROP, 261 RTE_FLOW_ACTION_TYPE_JUMP, 262 RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN, 263 RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP, 264 RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID, 265 RTE_FLOW_ACTION_TYPE_PORT_ID, 266 RTE_FLOW_ACTION_TYPE_PASSTHRU, 267 RTE_FLOW_ACTION_TYPE_VOID, 268 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP, 269 RTE_FLOW_ACTION_TYPE_END, 270 }; 271 272 static const struct enic_fm_items enic_fm_items[] = { 273 [RTE_FLOW_ITEM_TYPE_RAW] = { 274 .copy_item = enic_fm_copy_item_raw, 275 .valid_start_item = 0, 276 .prev_items = (const enum rte_flow_item_type[]) { 277 RTE_FLOW_ITEM_TYPE_UDP, 278 RTE_FLOW_ITEM_TYPE_END, 279 }, 280 }, 281 [RTE_FLOW_ITEM_TYPE_ETH] = { 282 .copy_item = enic_fm_copy_item_eth, 283 .valid_start_item = 1, 284 .prev_items = (const enum rte_flow_item_type[]) { 285 RTE_FLOW_ITEM_TYPE_END, 286 }, 287 }, 288 [RTE_FLOW_ITEM_TYPE_VLAN] = { 289 .copy_item = enic_fm_copy_item_vlan, 290 .valid_start_item = 1, 291 .prev_items = (const enum rte_flow_item_type[]) { 292 RTE_FLOW_ITEM_TYPE_ETH, 293 RTE_FLOW_ITEM_TYPE_END, 294 }, 295 }, 296 [RTE_FLOW_ITEM_TYPE_IPV4] = { 297 .copy_item = enic_fm_copy_item_ipv4, 298 .valid_start_item = 1, 299 .prev_items = (const enum rte_flow_item_type[]) { 300 RTE_FLOW_ITEM_TYPE_ETH, 301 RTE_FLOW_ITEM_TYPE_VLAN, 302 RTE_FLOW_ITEM_TYPE_END, 303 }, 304 }, 305 [RTE_FLOW_ITEM_TYPE_IPV6] = { 306 .copy_item = enic_fm_copy_item_ipv6, 307 .valid_start_item = 1, 308 .prev_items = (const enum rte_flow_item_type[]) { 309 RTE_FLOW_ITEM_TYPE_ETH, 310 RTE_FLOW_ITEM_TYPE_VLAN, 311 RTE_FLOW_ITEM_TYPE_END, 312 }, 313 }, 314 [RTE_FLOW_ITEM_TYPE_UDP] = { 315 .copy_item = enic_fm_copy_item_udp, 316 .valid_start_item = 1, 317 .prev_items = (const enum rte_flow_item_type[]) { 318 RTE_FLOW_ITEM_TYPE_IPV4, 319 RTE_FLOW_ITEM_TYPE_IPV6, 320 RTE_FLOW_ITEM_TYPE_END, 321 }, 322 }, 323 [RTE_FLOW_ITEM_TYPE_TCP] = { 324 .copy_item = enic_fm_copy_item_tcp, 325 .valid_start_item = 1, 326 .prev_items = (const enum rte_flow_item_type[]) { 327 RTE_FLOW_ITEM_TYPE_IPV4, 328 RTE_FLOW_ITEM_TYPE_IPV6, 329 RTE_FLOW_ITEM_TYPE_END, 330 }, 331 }, 332 [RTE_FLOW_ITEM_TYPE_SCTP] = { 333 .copy_item = enic_fm_copy_item_sctp, 334 .valid_start_item = 0, 335 .prev_items = (const enum rte_flow_item_type[]) { 336 RTE_FLOW_ITEM_TYPE_IPV4, 337 RTE_FLOW_ITEM_TYPE_IPV6, 338 RTE_FLOW_ITEM_TYPE_END, 339 }, 340 }, 341 [RTE_FLOW_ITEM_TYPE_VXLAN] = { 342 .copy_item = enic_fm_copy_item_vxlan, 343 .valid_start_item = 1, 344 .prev_items = (const enum rte_flow_item_type[]) { 345 RTE_FLOW_ITEM_TYPE_UDP, 346 RTE_FLOW_ITEM_TYPE_END, 347 }, 348 }, 349 }; 350 351 static int 352 enic_fm_copy_item_eth(struct copy_item_args *arg) 353 { 354 const struct rte_flow_item *item = arg->item; 355 const struct rte_flow_item_eth *spec = item->spec; 356 const struct rte_flow_item_eth *mask = item->mask; 357 const uint8_t lvl = arg->header_level; 358 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 359 struct fm_header_set *fm_data, *fm_mask; 360 361 ENICPMD_FUNC_TRACE(); 362 /* Match all if no spec */ 363 if (!spec) 364 return 0; 365 if (!mask) 366 mask = &rte_flow_item_eth_mask; 367 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 368 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 369 fm_data->fk_header_select |= FKH_ETHER; 370 fm_mask->fk_header_select |= FKH_ETHER; 371 memcpy(&fm_data->l2.eth, spec, sizeof(struct rte_ether_hdr)); 372 memcpy(&fm_mask->l2.eth, mask, sizeof(struct rte_ether_hdr)); 373 return 0; 374 } 375 376 static int 377 enic_fm_copy_item_vlan(struct copy_item_args *arg) 378 { 379 const struct rte_flow_item *item = arg->item; 380 const struct rte_flow_item_vlan *spec = item->spec; 381 const struct rte_flow_item_vlan *mask = item->mask; 382 const uint8_t lvl = arg->header_level; 383 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 384 struct fm_header_set *fm_data, *fm_mask; 385 struct rte_ether_hdr *eth_mask; 386 struct rte_ether_hdr *eth_val; 387 uint32_t meta; 388 389 ENICPMD_FUNC_TRACE(); 390 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 391 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 392 /* Outer and inner packet vlans need different flags */ 393 meta = FKM_VLAN_PRES; 394 if (lvl > 0) 395 meta = FKM_QTAG; 396 fm_data->fk_metadata |= meta; 397 fm_mask->fk_metadata |= meta; 398 399 /* Match all if no spec */ 400 if (!spec) 401 return 0; 402 if (!mask) 403 mask = &rte_flow_item_vlan_mask; 404 405 eth_mask = (void *)&fm_mask->l2.eth; 406 eth_val = (void *)&fm_data->l2.eth; 407 408 /* 409 * Outer TPID cannot be matched. If inner_type is 0, use what is 410 * in the eth header. 411 */ 412 if (eth_mask->ether_type && mask->inner_type) 413 return -ENOTSUP; 414 415 /* 416 * When packet matching, the VIC always compares vlan-stripped 417 * L2, regardless of vlan stripping settings. So, the inner type 418 * from vlan becomes the ether type of the eth header. 419 */ 420 if (mask->inner_type) { 421 eth_mask->ether_type = mask->inner_type; 422 eth_val->ether_type = spec->inner_type; 423 } 424 fm_data->fk_header_select |= FKH_ETHER | FKH_QTAG; 425 fm_mask->fk_header_select |= FKH_ETHER | FKH_QTAG; 426 fm_data->fk_vlan = rte_be_to_cpu_16(spec->tci); 427 fm_mask->fk_vlan = rte_be_to_cpu_16(mask->tci); 428 return 0; 429 } 430 431 static int 432 enic_fm_copy_item_ipv4(struct copy_item_args *arg) 433 { 434 const struct rte_flow_item *item = arg->item; 435 const struct rte_flow_item_ipv4 *spec = item->spec; 436 const struct rte_flow_item_ipv4 *mask = item->mask; 437 const uint8_t lvl = arg->header_level; 438 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 439 struct fm_header_set *fm_data, *fm_mask; 440 441 ENICPMD_FUNC_TRACE(); 442 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 443 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 444 fm_data->fk_metadata |= FKM_IPV4; 445 fm_mask->fk_metadata |= FKM_IPV4; 446 447 if (!spec) 448 return 0; 449 if (!mask) 450 mask = &rte_flow_item_ipv4_mask; 451 452 fm_data->fk_header_select |= FKH_IPV4; 453 fm_mask->fk_header_select |= FKH_IPV4; 454 memcpy(&fm_data->l3.ip4, spec, sizeof(*spec)); 455 memcpy(&fm_mask->l3.ip4, mask, sizeof(*mask)); 456 return 0; 457 } 458 459 static int 460 enic_fm_copy_item_ipv6(struct copy_item_args *arg) 461 { 462 const struct rte_flow_item *item = arg->item; 463 const struct rte_flow_item_ipv6 *spec = item->spec; 464 const struct rte_flow_item_ipv6 *mask = item->mask; 465 const uint8_t lvl = arg->header_level; 466 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 467 struct fm_header_set *fm_data, *fm_mask; 468 469 ENICPMD_FUNC_TRACE(); 470 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 471 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 472 fm_data->fk_metadata |= FKM_IPV6; 473 fm_mask->fk_metadata |= FKM_IPV6; 474 475 if (!spec) 476 return 0; 477 if (!mask) 478 mask = &rte_flow_item_ipv6_mask; 479 480 fm_data->fk_header_select |= FKH_IPV6; 481 fm_mask->fk_header_select |= FKH_IPV6; 482 memcpy(&fm_data->l3.ip6, spec, sizeof(struct rte_ipv6_hdr)); 483 memcpy(&fm_mask->l3.ip6, mask, sizeof(struct rte_ipv6_hdr)); 484 return 0; 485 } 486 487 static int 488 enic_fm_copy_item_udp(struct copy_item_args *arg) 489 { 490 const struct rte_flow_item *item = arg->item; 491 const struct rte_flow_item_udp *spec = item->spec; 492 const struct rte_flow_item_udp *mask = item->mask; 493 const uint8_t lvl = arg->header_level; 494 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 495 struct fm_header_set *fm_data, *fm_mask; 496 497 ENICPMD_FUNC_TRACE(); 498 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 499 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 500 fm_data->fk_metadata |= FKM_UDP; 501 fm_mask->fk_metadata |= FKM_UDP; 502 503 if (!spec) 504 return 0; 505 if (!mask) 506 mask = &rte_flow_item_udp_mask; 507 508 fm_data->fk_header_select |= FKH_UDP; 509 fm_mask->fk_header_select |= FKH_UDP; 510 memcpy(&fm_data->l4.udp, spec, sizeof(*spec)); 511 memcpy(&fm_mask->l4.udp, mask, sizeof(*mask)); 512 return 0; 513 } 514 515 static int 516 enic_fm_copy_item_tcp(struct copy_item_args *arg) 517 { 518 const struct rte_flow_item *item = arg->item; 519 const struct rte_flow_item_tcp *spec = item->spec; 520 const struct rte_flow_item_tcp *mask = item->mask; 521 const uint8_t lvl = arg->header_level; 522 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 523 struct fm_header_set *fm_data, *fm_mask; 524 525 ENICPMD_FUNC_TRACE(); 526 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 527 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 528 fm_data->fk_metadata |= FKM_TCP; 529 fm_mask->fk_metadata |= FKM_TCP; 530 531 if (!spec) 532 return 0; 533 if (!mask) 534 mask = &rte_flow_item_tcp_mask; 535 536 fm_data->fk_header_select |= FKH_TCP; 537 fm_mask->fk_header_select |= FKH_TCP; 538 memcpy(&fm_data->l4.tcp, spec, sizeof(*spec)); 539 memcpy(&fm_mask->l4.tcp, mask, sizeof(*mask)); 540 return 0; 541 } 542 543 static int 544 enic_fm_copy_item_sctp(struct copy_item_args *arg) 545 { 546 const struct rte_flow_item *item = arg->item; 547 const struct rte_flow_item_sctp *spec = item->spec; 548 const struct rte_flow_item_sctp *mask = item->mask; 549 const uint8_t lvl = arg->header_level; 550 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 551 struct fm_header_set *fm_data, *fm_mask; 552 uint8_t *ip_proto_mask = NULL; 553 uint8_t *ip_proto = NULL; 554 uint32_t l3_fkh; 555 556 ENICPMD_FUNC_TRACE(); 557 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 558 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 559 /* 560 * The NIC filter API has no flags for "match sctp", so explicitly 561 * set the protocol number in the IP pattern. 562 */ 563 if (fm_data->fk_metadata & FKM_IPV4) { 564 struct rte_ipv4_hdr *ip; 565 ip = (struct rte_ipv4_hdr *)&fm_mask->l3.ip4; 566 ip_proto_mask = &ip->next_proto_id; 567 ip = (struct rte_ipv4_hdr *)&fm_data->l3.ip4; 568 ip_proto = &ip->next_proto_id; 569 l3_fkh = FKH_IPV4; 570 } else if (fm_data->fk_metadata & FKM_IPV6) { 571 struct rte_ipv6_hdr *ip; 572 ip = (struct rte_ipv6_hdr *)&fm_mask->l3.ip6; 573 ip_proto_mask = &ip->proto; 574 ip = (struct rte_ipv6_hdr *)&fm_data->l3.ip6; 575 ip_proto = &ip->proto; 576 l3_fkh = FKH_IPV6; 577 } else { 578 /* Need IPv4/IPv6 pattern first */ 579 return -EINVAL; 580 } 581 *ip_proto = IPPROTO_SCTP; 582 *ip_proto_mask = 0xff; 583 fm_data->fk_header_select |= l3_fkh; 584 fm_mask->fk_header_select |= l3_fkh; 585 586 if (!spec) 587 return 0; 588 if (!mask) 589 mask = &rte_flow_item_sctp_mask; 590 591 fm_data->fk_header_select |= FKH_L4RAW; 592 fm_mask->fk_header_select |= FKH_L4RAW; 593 memcpy(fm_data->l4.rawdata, spec, sizeof(*spec)); 594 memcpy(fm_mask->l4.rawdata, mask, sizeof(*mask)); 595 return 0; 596 } 597 598 static int 599 enic_fm_copy_item_vxlan(struct copy_item_args *arg) 600 { 601 const struct rte_flow_item *item = arg->item; 602 const struct rte_flow_item_vxlan *spec = item->spec; 603 const struct rte_flow_item_vxlan *mask = item->mask; 604 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 605 struct fm_header_set *fm_data, *fm_mask; 606 607 ENICPMD_FUNC_TRACE(); 608 /* Only 2 header levels (outer and inner) allowed */ 609 if (arg->header_level > 0) 610 return -EINVAL; 611 612 fm_data = &entry->ftm_data.fk_hdrset[0]; 613 fm_mask = &entry->ftm_mask.fk_hdrset[0]; 614 fm_data->fk_metadata |= FKM_VXLAN; 615 fm_mask->fk_metadata |= FKM_VXLAN; 616 /* items from here on out are inner header items */ 617 arg->header_level = 1; 618 619 /* Match all if no spec */ 620 if (!spec) 621 return 0; 622 if (!mask) 623 mask = &rte_flow_item_vxlan_mask; 624 625 fm_data->fk_header_select |= FKH_VXLAN; 626 fm_mask->fk_header_select |= FKH_VXLAN; 627 memcpy(&fm_data->vxlan, spec, sizeof(*spec)); 628 memcpy(&fm_mask->vxlan, mask, sizeof(*mask)); 629 return 0; 630 } 631 632 /* 633 * Currently, raw pattern match is very limited. It is intended for matching 634 * UDP tunnel header (e.g. vxlan or geneve). 635 */ 636 static int 637 enic_fm_copy_item_raw(struct copy_item_args *arg) 638 { 639 const struct rte_flow_item *item = arg->item; 640 const struct rte_flow_item_raw *spec = item->spec; 641 const struct rte_flow_item_raw *mask = item->mask; 642 const uint8_t lvl = arg->header_level; 643 struct fm_tcam_match_entry *entry = arg->fm_tcam_entry; 644 struct fm_header_set *fm_data, *fm_mask; 645 646 ENICPMD_FUNC_TRACE(); 647 /* Cannot be used for inner packet */ 648 if (lvl > 0) 649 return -EINVAL; 650 /* Need both spec and mask */ 651 if (!spec || !mask) 652 return -EINVAL; 653 /* Only supports relative with offset 0 */ 654 if (!spec->relative || spec->offset != 0 || spec->search || 655 spec->limit) 656 return -EINVAL; 657 /* Need non-null pattern that fits within the NIC's filter pattern */ 658 if (spec->length == 0 || 659 spec->length + sizeof(struct rte_udp_hdr) > FM_LAYER_SIZE || 660 !spec->pattern || !mask->pattern) 661 return -EINVAL; 662 /* 663 * Mask fields, including length, are often set to zero. Assume that 664 * means "same as spec" to avoid breaking existing apps. If length 665 * is not zero, then it should be >= spec length. 666 * 667 * No more pattern follows this, so append to the L4 layer instead of 668 * L5 to work with both recent and older VICs. 669 */ 670 if (mask->length != 0 && mask->length < spec->length) 671 return -EINVAL; 672 673 fm_data = &entry->ftm_data.fk_hdrset[lvl]; 674 fm_mask = &entry->ftm_mask.fk_hdrset[lvl]; 675 fm_data->fk_header_select |= FKH_L4RAW; 676 fm_mask->fk_header_select |= FKH_L4RAW; 677 fm_data->fk_header_select &= ~FKH_UDP; 678 fm_mask->fk_header_select &= ~FKH_UDP; 679 memcpy(fm_data->l4.rawdata + sizeof(struct rte_udp_hdr), 680 spec->pattern, spec->length); 681 memcpy(fm_mask->l4.rawdata + sizeof(struct rte_udp_hdr), 682 mask->pattern, spec->length); 683 return 0; 684 } 685 686 static int 687 flowman_cmd(struct enic_flowman *fm, uint64_t *args, int nargs) 688 { 689 return vnic_dev_flowman_cmd(fm->owner_enic->vdev, args, nargs); 690 } 691 692 static int 693 enic_fet_alloc(struct enic_flowman *fm, uint8_t ingress, 694 struct fm_key_template *key, int entries, 695 struct enic_fm_fet **fet_out) 696 { 697 struct fm_exact_match_table *cmd; 698 struct fm_header_set *hdr; 699 struct enic_fm_fet *fet; 700 uint64_t args[3]; 701 int ret; 702 703 ENICPMD_FUNC_TRACE(); 704 fet = calloc(1, sizeof(struct enic_fm_fet)); 705 if (fet == NULL) 706 return -ENOMEM; 707 cmd = &fm->cmd.va->fm_exact_match_table; 708 memset(cmd, 0, sizeof(*cmd)); 709 cmd->fet_direction = ingress ? FM_INGRESS : FM_EGRESS; 710 cmd->fet_stage = FM_STAGE_LAST; 711 cmd->fet_max_entries = entries ? entries : FM_MAX_EXACT_TABLE_SIZE; 712 if (key == NULL) { 713 hdr = &cmd->fet_key.fk_hdrset[0]; 714 memset(hdr, 0, sizeof(*hdr)); 715 hdr->fk_header_select = FKH_IPV4 | FKH_UDP; 716 hdr->l3.ip4.fk_saddr = 0xFFFFFFFF; 717 hdr->l3.ip4.fk_daddr = 0xFFFFFFFF; 718 hdr->l4.udp.fk_source = 0xFFFF; 719 hdr->l4.udp.fk_dest = 0xFFFF; 720 fet->default_key = 1; 721 } else { 722 memcpy(&cmd->fet_key, key, sizeof(*key)); 723 memcpy(&fet->key, key, sizeof(*key)); 724 fet->default_key = 0; 725 } 726 cmd->fet_key.fk_packet_tag = 1; 727 728 args[0] = FM_EXACT_TABLE_ALLOC; 729 args[1] = fm->cmd.pa; 730 ret = flowman_cmd(fm, args, 2); 731 if (ret) { 732 ENICPMD_LOG(ERR, "cannot alloc exact match table: rc=%d", ret); 733 free(fet); 734 return ret; 735 } 736 fet->handle = args[0]; 737 fet->ingress = ingress; 738 ENICPMD_LOG(DEBUG, "allocated exact match table: handle=0x%" PRIx64, 739 fet->handle); 740 *fet_out = fet; 741 return 0; 742 } 743 744 static void 745 enic_fet_free(struct enic_flowman *fm, struct enic_fm_fet *fet) 746 { 747 ENICPMD_FUNC_TRACE(); 748 enic_fm_tbl_free(fm, fet->handle); 749 if (!fet->default_key) 750 TAILQ_REMOVE(&fm->fet_list, fet, list); 751 free(fet); 752 } 753 754 /* 755 * Get the exact match table for the given combination of 756 * <group, ingress, key>. Allocate one on the fly as necessary. 757 */ 758 static int 759 enic_fet_get(struct enic_flowman *fm, 760 uint32_t group, 761 uint8_t ingress, 762 struct fm_key_template *key, 763 struct enic_fm_fet **fet_out, 764 struct rte_flow_error *error) 765 { 766 struct enic_fm_fet *fet; 767 768 ENICPMD_FUNC_TRACE(); 769 /* See if we already have this table open */ 770 TAILQ_FOREACH(fet, &fm->fet_list, list) { 771 if (fet->group == group && fet->ingress == ingress) 772 break; 773 } 774 if (fet == NULL) { 775 /* Jumping to a non-existing group? Use the default table */ 776 if (key == NULL) { 777 fet = ingress ? fm->default_ig_fet : fm->default_eg_fet; 778 } else if (enic_fet_alloc(fm, ingress, key, 0, &fet)) { 779 return rte_flow_error_set(error, EINVAL, 780 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 781 NULL, "enic: cannot get exact match table"); 782 } 783 fet->group = group; 784 /* Default table is never on the open table list */ 785 if (!fet->default_key) 786 TAILQ_INSERT_HEAD(&fm->fet_list, fet, list); 787 } 788 fet->ref++; 789 *fet_out = fet; 790 ENICPMD_LOG(DEBUG, "fet_get: %s %s group=%u ref=%u", 791 fet->default_key ? "default" : "", 792 fet->ingress ? "ingress" : "egress", 793 fet->group, fet->ref); 794 return 0; 795 } 796 797 static void 798 enic_fet_put(struct enic_flowman *fm, struct enic_fm_fet *fet) 799 { 800 ENICPMD_FUNC_TRACE(); 801 RTE_ASSERT(fet->ref > 0); 802 fet->ref--; 803 ENICPMD_LOG(DEBUG, "fet_put: %s %s group=%u ref=%u", 804 fet->default_key ? "default" : "", 805 fet->ingress ? "ingress" : "egress", 806 fet->group, fet->ref); 807 if (fet->ref == 0) 808 enic_fet_free(fm, fet); 809 } 810 811 /* Return 1 if current item is valid on top of the previous one. */ 812 static int 813 fm_item_stacking_valid(enum rte_flow_item_type prev_item, 814 const struct enic_fm_items *item_info, 815 uint8_t is_first_item) 816 { 817 enum rte_flow_item_type const *allowed_items = item_info->prev_items; 818 819 ENICPMD_FUNC_TRACE(); 820 for (; *allowed_items != RTE_FLOW_ITEM_TYPE_END; allowed_items++) { 821 if (prev_item == *allowed_items) 822 return 1; 823 } 824 825 /* This is the first item in the stack. Check if that's cool */ 826 if (is_first_item && item_info->valid_start_item) 827 return 1; 828 return 0; 829 } 830 831 /* 832 * Build the flow manager match entry structure from the provided pattern. 833 * The pattern is validated as the items are copied. 834 */ 835 static int 836 enic_fm_copy_entry(struct enic_flowman *fm, 837 const struct rte_flow_item pattern[], 838 struct rte_flow_error *error) 839 { 840 const struct enic_fm_items *item_info; 841 enum rte_flow_item_type prev_item; 842 const struct rte_flow_item *item; 843 struct copy_item_args args; 844 uint8_t prev_header_level; 845 uint8_t is_first_item; 846 int ret; 847 848 ENICPMD_FUNC_TRACE(); 849 item = pattern; 850 is_first_item = 1; 851 prev_item = RTE_FLOW_ITEM_TYPE_END; 852 853 args.fm_tcam_entry = &fm->tcam_entry; 854 args.header_level = 0; 855 prev_header_level = 0; 856 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 857 /* 858 * Get info about how to validate and copy the item. If NULL 859 * is returned the nic does not support the item. 860 */ 861 if (item->type == RTE_FLOW_ITEM_TYPE_VOID) 862 continue; 863 864 item_info = &enic_fm_items[item->type]; 865 866 if (item->type > FM_MAX_ITEM_TYPE || 867 item_info->copy_item == NULL) { 868 return rte_flow_error_set(error, ENOTSUP, 869 RTE_FLOW_ERROR_TYPE_ITEM, 870 NULL, "enic: unsupported item"); 871 } 872 873 /* check to see if item stacking is valid */ 874 if (!fm_item_stacking_valid(prev_item, item_info, 875 is_first_item)) 876 goto stacking_error; 877 878 args.item = item; 879 ret = item_info->copy_item(&args); 880 if (ret) 881 goto item_not_supported; 882 /* Going from outer to inner? Treat it as a new packet start */ 883 if (prev_header_level != args.header_level) { 884 prev_item = RTE_FLOW_ITEM_TYPE_END; 885 is_first_item = 1; 886 } else { 887 prev_item = item->type; 888 is_first_item = 0; 889 } 890 prev_header_level = args.header_level; 891 } 892 return 0; 893 894 item_not_supported: 895 return rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_ITEM, 896 NULL, "enic: unsupported item type"); 897 898 stacking_error: 899 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, 900 item, "enic: unsupported item stack"); 901 } 902 903 static void 904 flow_item_skip_void(const struct rte_flow_item **item) 905 { 906 for ( ; ; (*item)++) 907 if ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID) 908 return; 909 } 910 911 static void 912 append_template(void **template, uint8_t *off, const void *data, int len) 913 { 914 memcpy(*template, data, len); 915 *template = (char *)*template + len; 916 *off = *off + len; 917 } 918 919 static int 920 enic_fm_append_action_op(struct enic_flowman *fm, 921 struct fm_action_op *fm_op, 922 struct rte_flow_error *error) 923 { 924 int count; 925 926 count = fm->action_op_count; 927 ENICPMD_LOG(DEBUG, "append action op: idx=%d op=%u", 928 count, fm_op->fa_op); 929 if (count == FM_ACTION_OP_MAX) { 930 return rte_flow_error_set(error, EINVAL, 931 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 932 "too many action operations"); 933 } 934 fm->action.fma_action_ops[count] = *fm_op; 935 fm->action_op_count = count + 1; 936 return 0; 937 } 938 939 static struct fm_action_op * 940 find_prev_action_op(struct enic_flowman *fm, uint32_t opcode) 941 { 942 struct fm_action_op *op; 943 int i; 944 945 for (i = 0; i < fm->action_op_count; i++) { 946 op = &fm->action.fma_action_ops[i]; 947 if (op->fa_op == opcode) 948 return op; 949 } 950 return NULL; 951 } 952 953 /* NIC requires that 1st steer appear before decap. 954 * Correct example: steer, decap, steer, steer, ... 955 */ 956 static void 957 enic_fm_reorder_action_op(struct enic_flowman *fm) 958 { 959 struct fm_action_op *op, *steer, *decap; 960 struct fm_action_op tmp_op; 961 962 ENICPMD_FUNC_TRACE(); 963 /* Find 1st steer and decap */ 964 op = fm->action.fma_action_ops; 965 steer = NULL; 966 decap = NULL; 967 while (op->fa_op != FMOP_END) { 968 if (!decap && (op->fa_op == FMOP_DECAP_NOSTRIP || 969 op->fa_op == FMOP_DECAP_STRIP)) 970 decap = op; 971 else if (!steer && op->fa_op == FMOP_RQ_STEER) 972 steer = op; 973 op++; 974 } 975 /* If decap is before steer, swap */ 976 if (steer && decap && decap < steer) { 977 op = fm->action.fma_action_ops; 978 ENICPMD_LOG(DEBUG, "swap decap %ld <-> steer %ld", 979 (long)(decap - op), (long)(steer - op)); 980 tmp_op = *decap; 981 *decap = *steer; 982 *steer = tmp_op; 983 } 984 } 985 986 /* VXLAN decap is done via flowman compound action */ 987 static int 988 enic_fm_copy_vxlan_decap(struct enic_flowman *fm, 989 struct fm_tcam_match_entry *fmt, 990 const struct rte_flow_action *action, 991 struct rte_flow_error *error) 992 { 993 struct fm_header_set *fm_data; 994 struct fm_action_op fm_op; 995 996 ENICPMD_FUNC_TRACE(); 997 fm_data = &fmt->ftm_data.fk_hdrset[0]; 998 if (!(fm_data->fk_metadata & FKM_VXLAN)) { 999 return rte_flow_error_set(error, EINVAL, 1000 RTE_FLOW_ERROR_TYPE_ACTION, action, 1001 "vxlan-decap: vxlan must be in pattern"); 1002 } 1003 1004 memset(&fm_op, 0, sizeof(fm_op)); 1005 fm_op.fa_op = FMOP_DECAP_NOSTRIP; 1006 return enic_fm_append_action_op(fm, &fm_op, error); 1007 } 1008 1009 /* Generate a reasonable source port number */ 1010 static uint16_t 1011 gen_src_port(void) 1012 { 1013 /* Min/max below are the default values in OVS-DPDK and Linux */ 1014 uint16_t p = rte_rand(); 1015 p = RTE_MAX(p, 32768); 1016 p = RTE_MIN(p, 61000); 1017 return rte_cpu_to_be_16(p); 1018 } 1019 1020 /* VXLAN encap is done via flowman compound action */ 1021 static int 1022 enic_fm_copy_vxlan_encap(struct enic_flowman *fm, 1023 const struct rte_flow_item *item, 1024 struct rte_flow_error *error) 1025 { 1026 struct fm_action_op fm_op; 1027 struct rte_ether_hdr *eth; 1028 struct rte_udp_hdr *udp; 1029 uint16_t *ethertype; 1030 void *template; 1031 uint8_t off; 1032 1033 ENICPMD_FUNC_TRACE(); 1034 memset(&fm_op, 0, sizeof(fm_op)); 1035 fm_op.fa_op = FMOP_ENCAP; 1036 template = fm->action.fma_data; 1037 off = 0; 1038 /* 1039 * Copy flow items to the flowman template starting L2. 1040 * L2 must be ethernet. 1041 */ 1042 flow_item_skip_void(&item); 1043 if (item->type != RTE_FLOW_ITEM_TYPE_ETH) 1044 return rte_flow_error_set(error, EINVAL, 1045 RTE_FLOW_ERROR_TYPE_ITEM, item, 1046 "vxlan-encap: first item should be ethernet"); 1047 eth = (struct rte_ether_hdr *)template; 1048 ethertype = ð->ether_type; 1049 append_template(&template, &off, item->spec, 1050 sizeof(struct rte_ether_hdr)); 1051 item++; 1052 flow_item_skip_void(&item); 1053 /* Optional VLAN */ 1054 if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) { 1055 const struct rte_flow_item_vlan *spec; 1056 1057 ENICPMD_LOG(DEBUG, "vxlan-encap: vlan"); 1058 spec = item->spec; 1059 fm_op.encap.outer_vlan = rte_be_to_cpu_16(spec->tci); 1060 item++; 1061 flow_item_skip_void(&item); 1062 } 1063 /* L3 must be IPv4, IPv6 */ 1064 switch (item->type) { 1065 case RTE_FLOW_ITEM_TYPE_IPV4: 1066 { 1067 struct rte_ipv4_hdr *ip4; 1068 1069 ENICPMD_LOG(DEBUG, "vxlan-encap: ipv4"); 1070 *ethertype = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 1071 ip4 = (struct rte_ipv4_hdr *)template; 1072 /* 1073 * Offset of IPv4 length field and its initial value 1074 * (IP + UDP + VXLAN) are specified in the action. The NIC 1075 * will add inner packet length. 1076 */ 1077 fm_op.encap.len1_offset = off + 1078 offsetof(struct rte_ipv4_hdr, total_length); 1079 fm_op.encap.len1_delta = sizeof(struct rte_ipv4_hdr) + 1080 sizeof(struct rte_udp_hdr) + 1081 sizeof(struct rte_vxlan_hdr); 1082 append_template(&template, &off, item->spec, 1083 sizeof(struct rte_ipv4_hdr)); 1084 ip4->version_ihl = RTE_IPV4_VHL_DEF; 1085 if (ip4->time_to_live == 0) 1086 ip4->time_to_live = IP_DEFTTL; 1087 ip4->next_proto_id = IPPROTO_UDP; 1088 break; 1089 } 1090 case RTE_FLOW_ITEM_TYPE_IPV6: 1091 { 1092 struct rte_ipv6_hdr *ip6; 1093 1094 ENICPMD_LOG(DEBUG, "vxlan-encap: ipv6"); 1095 *ethertype = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 1096 ip6 = (struct rte_ipv6_hdr *)template; 1097 fm_op.encap.len1_offset = off + 1098 offsetof(struct rte_ipv6_hdr, payload_len); 1099 fm_op.encap.len1_delta = sizeof(struct rte_udp_hdr) + 1100 sizeof(struct rte_vxlan_hdr); 1101 append_template(&template, &off, item->spec, 1102 sizeof(struct rte_ipv6_hdr)); 1103 ip6->vtc_flow |= rte_cpu_to_be_32(IP6_VTC_FLOW); 1104 if (ip6->hop_limits == 0) 1105 ip6->hop_limits = IP_DEFTTL; 1106 ip6->proto = IPPROTO_UDP; 1107 break; 1108 } 1109 default: 1110 return rte_flow_error_set(error, 1111 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, 1112 "vxlan-encap: L3 must be IPv4/IPv6"); 1113 } 1114 item++; 1115 flow_item_skip_void(&item); 1116 1117 /* L4 is UDP */ 1118 if (item->type != RTE_FLOW_ITEM_TYPE_UDP) 1119 return rte_flow_error_set(error, EINVAL, 1120 RTE_FLOW_ERROR_TYPE_ITEM, item, 1121 "vxlan-encap: UDP must follow IPv4/IPv6"); 1122 /* UDP length = UDP + VXLAN. NIC will add inner packet length. */ 1123 fm_op.encap.len2_offset = 1124 off + offsetof(struct rte_udp_hdr, dgram_len); 1125 fm_op.encap.len2_delta = 1126 sizeof(struct rte_udp_hdr) + sizeof(struct rte_vxlan_hdr); 1127 udp = (struct rte_udp_hdr *)template; 1128 append_template(&template, &off, item->spec, 1129 sizeof(struct rte_udp_hdr)); 1130 /* 1131 * Firmware does not hash/fill source port yet. Generate a 1132 * random port, as there is *usually* one rte_flow for the 1133 * given inner packet stream (i.e. a single stream has one 1134 * random port). 1135 */ 1136 if (udp->src_port == 0) 1137 udp->src_port = gen_src_port(); 1138 item++; 1139 flow_item_skip_void(&item); 1140 1141 /* Finally VXLAN */ 1142 if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) 1143 return rte_flow_error_set(error, 1144 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, 1145 "vxlan-encap: VXLAN must follow UDP"); 1146 append_template(&template, &off, item->spec, 1147 sizeof(struct rte_flow_item_vxlan)); 1148 1149 /* 1150 * Fill in the rest of the action structure. 1151 * Indicate that we want to encap with vxlan at packet start. 1152 */ 1153 fm_op.encap.template_offset = 0; 1154 fm_op.encap.template_len = off; 1155 return enic_fm_append_action_op(fm, &fm_op, error); 1156 } 1157 1158 static int 1159 enic_fm_find_vnic(struct enic *enic, const struct rte_pci_addr *addr, 1160 uint64_t *handle) 1161 { 1162 uint32_t bdf; 1163 uint64_t args[2]; 1164 int rc; 1165 1166 ENICPMD_FUNC_TRACE(); 1167 ENICPMD_LOG(DEBUG, "bdf=%x:%x:%x", addr->bus, addr->devid, 1168 addr->function); 1169 bdf = addr->bus << 8 | addr->devid << 3 | addr->function; 1170 args[0] = FM_VNIC_FIND; 1171 args[1] = bdf; 1172 rc = vnic_dev_flowman_cmd(enic->vdev, args, 2); 1173 if (rc != 0) { 1174 /* Expected to fail if BDF is not on the adapter */ 1175 ENICPMD_LOG(DEBUG, "cannot find vnic handle: rc=%d", rc); 1176 return rc; 1177 } 1178 *handle = args[0]; 1179 ENICPMD_LOG(DEBUG, "found vnic: handle=0x%" PRIx64, *handle); 1180 return 0; 1181 } 1182 1183 /* 1184 * Egress: target port should be either PF uplink or VF. 1185 * Supported cases 1186 * 1. VF egress -> PF uplink 1187 * PF may be this VF's PF, or another PF, as long as they are on the same VIC. 1188 * 2. VF egress -> VF 1189 * 1190 * Unsupported cases 1191 * 1. PF egress -> VF 1192 * App should be using representor to pass packets to VF 1193 */ 1194 static int 1195 vf_egress_port_id_action(struct enic_flowman *fm, 1196 struct rte_eth_dev *dst_dev, 1197 uint64_t dst_vnic_h, 1198 struct fm_action_op *fm_op, 1199 struct rte_flow_error *error) 1200 { 1201 struct enic *src_enic, *dst_enic; 1202 struct enic_vf_representor *vf; 1203 uint8_t uif; 1204 int ret; 1205 1206 ENICPMD_FUNC_TRACE(); 1207 src_enic = fm->user_enic; 1208 dst_enic = pmd_priv(dst_dev); 1209 if (!(src_enic->rte_dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR)) { 1210 return rte_flow_error_set(error, EINVAL, 1211 RTE_FLOW_ERROR_TYPE_ACTION, 1212 NULL, "source port is not VF representor"); 1213 } 1214 1215 /* VF -> PF uplink. dst is not VF representor */ 1216 if (!(dst_dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR)) { 1217 /* PF is the VF's PF? Then nothing to do */ 1218 vf = VF_ENIC_TO_VF_REP(src_enic); 1219 if (vf->pf == dst_enic) { 1220 ENICPMD_LOG(DEBUG, "destination port is VF's PF"); 1221 return 0; 1222 } 1223 /* If not, steer to the remote PF's uplink */ 1224 uif = dst_enic->fm_vnic_uif; 1225 ENICPMD_LOG(DEBUG, "steer to uplink %u", uif); 1226 memset(fm_op, 0, sizeof(*fm_op)); 1227 fm_op->fa_op = FMOP_SET_EGPORT; 1228 fm_op->set_egport.egport = uif; 1229 ret = enic_fm_append_action_op(fm, fm_op, error); 1230 return ret; 1231 } 1232 1233 /* VF -> VF loopback. Hairpin and steer to vnic */ 1234 memset(fm_op, 0, sizeof(*fm_op)); 1235 fm_op->fa_op = FMOP_EG_HAIRPIN; 1236 ret = enic_fm_append_action_op(fm, fm_op, error); 1237 if (ret) 1238 return ret; 1239 ENICPMD_LOG(DEBUG, "egress hairpin"); 1240 fm->hairpin_steer_vnic_h = dst_vnic_h; 1241 fm->need_hairpin_steer = 1; 1242 return 0; 1243 } 1244 1245 /* Translate flow actions to flowman TCAM entry actions */ 1246 static int 1247 enic_fm_copy_action(struct enic_flowman *fm, 1248 const struct rte_flow_action actions[], 1249 uint8_t ingress, 1250 struct rte_flow_error *error) 1251 { 1252 enum { 1253 FATE = 1 << 0, 1254 DECAP = 1 << 1, 1255 PASSTHRU = 1 << 2, 1256 COUNT = 1 << 3, 1257 ENCAP = 1 << 4, 1258 PUSH_VLAN = 1 << 5, 1259 PORT_ID = 1 << 6, 1260 }; 1261 struct fm_tcam_match_entry *fmt; 1262 struct fm_action_op fm_op; 1263 bool need_ovlan_action; 1264 struct enic *enic; 1265 uint32_t overlap; 1266 uint64_t vnic_h; 1267 uint16_t ovlan; 1268 bool first_rq; 1269 bool steer; 1270 int ret; 1271 1272 ENICPMD_FUNC_TRACE(); 1273 fmt = &fm->tcam_entry; 1274 need_ovlan_action = false; 1275 ovlan = 0; 1276 first_rq = true; 1277 steer = false; 1278 enic = fm->user_enic; 1279 overlap = 0; 1280 vnic_h = enic->fm_vnic_handle; 1281 1282 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 1283 switch (actions->type) { 1284 case RTE_FLOW_ACTION_TYPE_VOID: 1285 continue; 1286 case RTE_FLOW_ACTION_TYPE_PASSTHRU: { 1287 if (overlap & PASSTHRU) 1288 goto unsupported; 1289 overlap |= PASSTHRU; 1290 break; 1291 } 1292 case RTE_FLOW_ACTION_TYPE_JUMP: { 1293 const struct rte_flow_action_jump *jump = 1294 actions->conf; 1295 struct enic_fm_fet *fet; 1296 1297 if (overlap & FATE) 1298 goto unsupported; 1299 ret = enic_fet_get(fm, jump->group, ingress, NULL, 1300 &fet, error); 1301 if (ret) 1302 return ret; 1303 overlap |= FATE; 1304 memset(&fm_op, 0, sizeof(fm_op)); 1305 fm_op.fa_op = FMOP_EXACT_MATCH; 1306 fm_op.exact.handle = fet->handle; 1307 fm->fet = fet; 1308 ret = enic_fm_append_action_op(fm, &fm_op, error); 1309 if (ret) 1310 return ret; 1311 break; 1312 } 1313 case RTE_FLOW_ACTION_TYPE_MARK: { 1314 const struct rte_flow_action_mark *mark = 1315 actions->conf; 1316 1317 if (enic->use_noscatter_vec_rx_handler) 1318 goto unsupported; 1319 if (mark->id >= ENIC_MAGIC_FILTER_ID - 1) 1320 return rte_flow_error_set(error, EINVAL, 1321 RTE_FLOW_ERROR_TYPE_ACTION, 1322 NULL, "invalid mark id"); 1323 memset(&fm_op, 0, sizeof(fm_op)); 1324 fm_op.fa_op = FMOP_MARK; 1325 fm_op.mark.mark = mark->id + 1; 1326 ret = enic_fm_append_action_op(fm, &fm_op, error); 1327 if (ret) 1328 return ret; 1329 break; 1330 } 1331 case RTE_FLOW_ACTION_TYPE_FLAG: { 1332 if (enic->use_noscatter_vec_rx_handler) 1333 goto unsupported; 1334 /* ENIC_MAGIC_FILTER_ID is reserved for flagging */ 1335 memset(&fm_op, 0, sizeof(fm_op)); 1336 fm_op.fa_op = FMOP_MARK; 1337 fm_op.mark.mark = ENIC_MAGIC_FILTER_ID; 1338 ret = enic_fm_append_action_op(fm, &fm_op, error); 1339 if (ret) 1340 return ret; 1341 break; 1342 } 1343 case RTE_FLOW_ACTION_TYPE_QUEUE: { 1344 const struct rte_flow_action_queue *queue = 1345 actions->conf; 1346 1347 /* 1348 * If fate other than QUEUE or RSS, fail. Multiple 1349 * rss and queue actions are ok. 1350 */ 1351 if ((overlap & FATE) && first_rq) 1352 goto unsupported; 1353 first_rq = false; 1354 overlap |= FATE; 1355 memset(&fm_op, 0, sizeof(fm_op)); 1356 fm_op.fa_op = FMOP_RQ_STEER; 1357 fm_op.rq_steer.rq_index = 1358 enic_rte_rq_idx_to_sop_idx(queue->index); 1359 fm_op.rq_steer.rq_count = 1; 1360 fm_op.rq_steer.vnic_handle = vnic_h; 1361 ret = enic_fm_append_action_op(fm, &fm_op, error); 1362 if (ret) 1363 return ret; 1364 ENICPMD_LOG(DEBUG, "create QUEUE action rq: %u", 1365 fm_op.rq_steer.rq_index); 1366 steer = true; 1367 break; 1368 } 1369 case RTE_FLOW_ACTION_TYPE_DROP: { 1370 if (overlap & FATE) 1371 goto unsupported; 1372 overlap |= FATE; 1373 memset(&fm_op, 0, sizeof(fm_op)); 1374 fm_op.fa_op = FMOP_DROP; 1375 ret = enic_fm_append_action_op(fm, &fm_op, error); 1376 if (ret) 1377 return ret; 1378 ENICPMD_LOG(DEBUG, "create DROP action"); 1379 break; 1380 } 1381 case RTE_FLOW_ACTION_TYPE_COUNT: { 1382 if (overlap & COUNT) 1383 goto unsupported; 1384 overlap |= COUNT; 1385 /* Count is associated with entry not action on VIC. */ 1386 fmt->ftm_flags |= FMEF_COUNTER; 1387 break; 1388 } 1389 case RTE_FLOW_ACTION_TYPE_RSS: { 1390 const struct rte_flow_action_rss *rss = actions->conf; 1391 bool allow; 1392 uint16_t i; 1393 1394 /* 1395 * If fate other than QUEUE or RSS, fail. Multiple 1396 * rss and queue actions are ok. 1397 */ 1398 if ((overlap & FATE) && first_rq) 1399 goto unsupported; 1400 first_rq = false; 1401 overlap |= FATE; 1402 1403 /* 1404 * Hardware only supports RSS actions on outer level 1405 * with default type and function. Queues must be 1406 * sequential. 1407 */ 1408 allow = rss->func == RTE_ETH_HASH_FUNCTION_DEFAULT && 1409 rss->level == 0 && (rss->types == 0 || 1410 rss->types == enic->rss_hf) && 1411 rss->queue_num <= enic->rq_count && 1412 rss->queue[rss->queue_num - 1] < enic->rq_count; 1413 1414 1415 /* Identity queue map needs to be sequential */ 1416 for (i = 1; i < rss->queue_num; i++) 1417 allow = allow && (rss->queue[i] == 1418 rss->queue[i - 1] + 1); 1419 if (!allow) 1420 goto unsupported; 1421 1422 memset(&fm_op, 0, sizeof(fm_op)); 1423 fm_op.fa_op = FMOP_RQ_STEER; 1424 fm_op.rq_steer.rq_index = 1425 enic_rte_rq_idx_to_sop_idx(rss->queue[0]); 1426 fm_op.rq_steer.rq_count = rss->queue_num; 1427 fm_op.rq_steer.vnic_handle = vnic_h; 1428 ret = enic_fm_append_action_op(fm, &fm_op, error); 1429 if (ret) 1430 return ret; 1431 ENICPMD_LOG(DEBUG, "create QUEUE action rq: %u", 1432 fm_op.rq_steer.rq_index); 1433 steer = true; 1434 break; 1435 } 1436 case RTE_FLOW_ACTION_TYPE_PORT_ID: { 1437 const struct rte_flow_action_port_id *port; 1438 struct rte_eth_dev *dev; 1439 1440 if (!ingress && (overlap & PORT_ID)) { 1441 ENICPMD_LOG(DEBUG, "cannot have multiple egress PORT_ID actions"); 1442 goto unsupported; 1443 } 1444 port = actions->conf; 1445 if (port->original) { 1446 vnic_h = enic->fm_vnic_handle; /* This port */ 1447 break; 1448 } 1449 ENICPMD_LOG(DEBUG, "port id %u", port->id); 1450 if (!rte_eth_dev_is_valid_port(port->id)) { 1451 return rte_flow_error_set(error, EINVAL, 1452 RTE_FLOW_ERROR_TYPE_ACTION, 1453 NULL, "invalid port_id"); 1454 } 1455 dev = &rte_eth_devices[port->id]; 1456 if (!dev_is_enic(dev)) { 1457 return rte_flow_error_set(error, EINVAL, 1458 RTE_FLOW_ERROR_TYPE_ACTION, 1459 NULL, "port_id is not enic"); 1460 } 1461 if (enic->switch_domain_id != 1462 pmd_priv(dev)->switch_domain_id) { 1463 return rte_flow_error_set(error, EINVAL, 1464 RTE_FLOW_ERROR_TYPE_ACTION, 1465 NULL, "destination and source ports are not in the same switch domain"); 1466 } 1467 vnic_h = pmd_priv(dev)->fm_vnic_handle; 1468 overlap |= PORT_ID; 1469 /* 1470 * Ingress. Nothing more to do. We add an implicit 1471 * steer at the end if needed. 1472 */ 1473 if (ingress) 1474 break; 1475 /* Egress */ 1476 ret = vf_egress_port_id_action(fm, dev, vnic_h, &fm_op, 1477 error); 1478 if (ret) 1479 return ret; 1480 break; 1481 } 1482 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: { 1483 if (overlap & DECAP) 1484 goto unsupported; 1485 overlap |= DECAP; 1486 1487 ret = enic_fm_copy_vxlan_decap(fm, fmt, actions, 1488 error); 1489 if (ret != 0) 1490 return ret; 1491 break; 1492 } 1493 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: { 1494 const struct rte_flow_action_vxlan_encap *encap; 1495 1496 encap = actions->conf; 1497 if (overlap & ENCAP) 1498 goto unsupported; 1499 overlap |= ENCAP; 1500 ret = enic_fm_copy_vxlan_encap(fm, encap->definition, 1501 error); 1502 if (ret != 0) 1503 return ret; 1504 break; 1505 } 1506 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: { 1507 struct fm_action_op *decap; 1508 1509 /* 1510 * If decap-nostrip appears before pop vlan, this pop 1511 * applies to the inner packet vlan. Turn it into 1512 * decap-strip. 1513 */ 1514 decap = find_prev_action_op(fm, FMOP_DECAP_NOSTRIP); 1515 if (decap) { 1516 ENICPMD_LOG(DEBUG, "pop-vlan inner: decap-nostrip => decap-strip"); 1517 decap->fa_op = FMOP_DECAP_STRIP; 1518 break; 1519 } 1520 memset(&fm_op, 0, sizeof(fm_op)); 1521 fm_op.fa_op = FMOP_POP_VLAN; 1522 ret = enic_fm_append_action_op(fm, &fm_op, error); 1523 if (ret) 1524 return ret; 1525 break; 1526 } 1527 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: { 1528 const struct rte_flow_action_of_push_vlan *vlan; 1529 1530 if (overlap & PASSTHRU) 1531 goto unsupported; 1532 vlan = actions->conf; 1533 if (vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN)) { 1534 return rte_flow_error_set(error, EINVAL, 1535 RTE_FLOW_ERROR_TYPE_ACTION, 1536 NULL, "unexpected push_vlan ethertype"); 1537 } 1538 overlap |= PUSH_VLAN; 1539 need_ovlan_action = true; 1540 break; 1541 } 1542 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: { 1543 const struct rte_flow_action_of_set_vlan_pcp *pcp; 1544 1545 pcp = actions->conf; 1546 if (pcp->vlan_pcp > 7) { 1547 return rte_flow_error_set(error, EINVAL, 1548 RTE_FLOW_ERROR_TYPE_ACTION, 1549 NULL, "invalid vlan_pcp"); 1550 } 1551 need_ovlan_action = true; 1552 ovlan |= ((uint16_t)pcp->vlan_pcp) << 13; 1553 break; 1554 } 1555 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: { 1556 const struct rte_flow_action_of_set_vlan_vid *vid; 1557 1558 vid = actions->conf; 1559 need_ovlan_action = true; 1560 ovlan |= rte_be_to_cpu_16(vid->vlan_vid); 1561 break; 1562 } 1563 default: 1564 goto unsupported; 1565 } 1566 } 1567 1568 if (!(overlap & (FATE | PASSTHRU | COUNT | PORT_ID))) 1569 goto unsupported; 1570 /* Egress from VF: need implicit WQ match */ 1571 if (enic_is_vf_rep(enic) && !ingress) { 1572 fmt->ftm_data.fk_wq_id = 0; 1573 fmt->ftm_mask.fk_wq_id = 0xffff; 1574 fmt->ftm_data.fk_wq_vnic = enic->fm_vnic_handle; 1575 ENICPMD_LOG(DEBUG, "add implicit wq id match for vf %d", 1576 VF_ENIC_TO_VF_REP(enic)->vf_id); 1577 } 1578 if (need_ovlan_action) { 1579 memset(&fm_op, 0, sizeof(fm_op)); 1580 fm_op.fa_op = FMOP_SET_OVLAN; 1581 fm_op.ovlan.vlan = ovlan; 1582 ret = enic_fm_append_action_op(fm, &fm_op, error); 1583 if (ret) 1584 return ret; 1585 } 1586 /* Add steer op for PORT_ID without QUEUE */ 1587 if ((overlap & PORT_ID) && !steer && ingress) { 1588 memset(&fm_op, 0, sizeof(fm_op)); 1589 /* Always to queue 0 for now as generic RSS is not available */ 1590 fm_op.fa_op = FMOP_RQ_STEER; 1591 fm_op.rq_steer.rq_index = 0; 1592 fm_op.rq_steer.vnic_handle = vnic_h; 1593 ret = enic_fm_append_action_op(fm, &fm_op, error); 1594 if (ret) 1595 return ret; 1596 ENICPMD_LOG(DEBUG, "add implicit steer op"); 1597 } 1598 /* Add required END */ 1599 memset(&fm_op, 0, sizeof(fm_op)); 1600 fm_op.fa_op = FMOP_END; 1601 ret = enic_fm_append_action_op(fm, &fm_op, error); 1602 if (ret) 1603 return ret; 1604 enic_fm_reorder_action_op(fm); 1605 return 0; 1606 1607 unsupported: 1608 return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 1609 NULL, "enic: unsupported action"); 1610 } 1611 1612 /** Check if the action is supported */ 1613 static int 1614 enic_fm_match_action(const struct rte_flow_action *action, 1615 const enum rte_flow_action_type *supported_actions) 1616 { 1617 for (; *supported_actions != RTE_FLOW_ACTION_TYPE_END; 1618 supported_actions++) { 1619 if (action->type == *supported_actions) 1620 return 1; 1621 } 1622 return 0; 1623 } 1624 1625 /* Debug function to dump internal NIC action structure. */ 1626 static void 1627 enic_fm_dump_tcam_actions(const struct fm_action *fm_action) 1628 { 1629 /* Manually keep in sync with FMOP commands */ 1630 const char *fmop_str[FMOP_OP_MAX] = { 1631 [FMOP_END] = "end", 1632 [FMOP_DROP] = "drop", 1633 [FMOP_RQ_STEER] = "steer", 1634 [FMOP_EXACT_MATCH] = "exmatch", 1635 [FMOP_MARK] = "mark", 1636 [FMOP_EXT_MARK] = "ext_mark", 1637 [FMOP_TAG] = "tag", 1638 [FMOP_EG_HAIRPIN] = "eg_hairpin", 1639 [FMOP_IG_HAIRPIN] = "ig_hairpin", 1640 [FMOP_ENCAP_IVLAN] = "encap_ivlan", 1641 [FMOP_ENCAP_NOIVLAN] = "encap_noivlan", 1642 [FMOP_ENCAP] = "encap", 1643 [FMOP_SET_OVLAN] = "set_ovlan", 1644 [FMOP_DECAP_NOSTRIP] = "decap_nostrip", 1645 [FMOP_DECAP_STRIP] = "decap_strip", 1646 [FMOP_POP_VLAN] = "pop_vlan", 1647 [FMOP_SET_EGPORT] = "set_egport", 1648 [FMOP_RQ_STEER_ONLY] = "rq_steer_only", 1649 [FMOP_SET_ENCAP_VLAN] = "set_encap_vlan", 1650 [FMOP_EMIT] = "emit", 1651 [FMOP_MODIFY] = "modify", 1652 }; 1653 const struct fm_action_op *op = &fm_action->fma_action_ops[0]; 1654 char buf[128], *bp = buf; 1655 const char *op_str; 1656 int i, n, buf_len; 1657 1658 buf[0] = '\0'; 1659 buf_len = sizeof(buf); 1660 for (i = 0; i < FM_ACTION_OP_MAX; i++) { 1661 if (op->fa_op == FMOP_END) 1662 break; 1663 if (op->fa_op >= FMOP_OP_MAX) 1664 op_str = "unknown"; 1665 else 1666 op_str = fmop_str[op->fa_op]; 1667 n = snprintf(bp, buf_len, "%s,", op_str); 1668 if (n > 0 && n < buf_len) { 1669 bp += n; 1670 buf_len -= n; 1671 } 1672 op++; 1673 } 1674 /* Remove trailing comma */ 1675 if (buf[0]) 1676 *(bp - 1) = '\0'; 1677 ENICPMD_LOG(DEBUG, " Acions: %s", buf); 1678 } 1679 1680 static int 1681 bits_to_str(uint32_t bits, const char *strings[], int max, 1682 char *buf, int buf_len) 1683 { 1684 int i, n = 0, len = 0; 1685 1686 for (i = 0; i < max; i++) { 1687 if (bits & (1 << i)) { 1688 n = snprintf(buf, buf_len, "%s,", strings[i]); 1689 if (n > 0 && n < buf_len) { 1690 buf += n; 1691 buf_len -= n; 1692 len += n; 1693 } 1694 } 1695 } 1696 /* Remove trailing comma */ 1697 if (len) { 1698 *(buf - 1) = '\0'; 1699 len--; 1700 } 1701 return len; 1702 } 1703 1704 /* Debug function to dump internal NIC filter structure. */ 1705 static void 1706 __enic_fm_dump_tcam_match(const struct fm_header_set *fk_hdrset, char *buf, 1707 int buf_len) 1708 { 1709 /* Manually keep in sync with FKM_BITS */ 1710 const char *fm_fkm_str[FKM_BIT_COUNT] = { 1711 [FKM_QTAG_BIT] = "qtag", 1712 [FKM_CMD_BIT] = "cmd", 1713 [FKM_IPV4_BIT] = "ip4", 1714 [FKM_IPV6_BIT] = "ip6", 1715 [FKM_ROCE_BIT] = "roce", 1716 [FKM_UDP_BIT] = "udp", 1717 [FKM_TCP_BIT] = "tcp", 1718 [FKM_TCPORUDP_BIT] = "tcpportudp", 1719 [FKM_IPFRAG_BIT] = "ipfrag", 1720 [FKM_NVGRE_BIT] = "nvgre", 1721 [FKM_VXLAN_BIT] = "vxlan", 1722 [FKM_GENEVE_BIT] = "geneve", 1723 [FKM_NSH_BIT] = "nsh", 1724 [FKM_ROCEV2_BIT] = "rocev2", 1725 [FKM_VLAN_PRES_BIT] = "vlan_pres", 1726 [FKM_IPOK_BIT] = "ipok", 1727 [FKM_L4OK_BIT] = "l4ok", 1728 [FKM_ROCEOK_BIT] = "roceok", 1729 [FKM_FCSOK_BIT] = "fcsok", 1730 [FKM_EG_SPAN_BIT] = "eg_span", 1731 [FKM_IG_SPAN_BIT] = "ig_span", 1732 [FKM_EG_HAIRPINNED_BIT] = "eg_hairpinned", 1733 }; 1734 /* Manually keep in sync with FKH_BITS */ 1735 const char *fm_fkh_str[FKH_BIT_COUNT] = { 1736 [FKH_ETHER_BIT] = "eth", 1737 [FKH_QTAG_BIT] = "qtag", 1738 [FKH_L2RAW_BIT] = "l2raw", 1739 [FKH_IPV4_BIT] = "ip4", 1740 [FKH_IPV6_BIT] = "ip6", 1741 [FKH_L3RAW_BIT] = "l3raw", 1742 [FKH_UDP_BIT] = "udp", 1743 [FKH_TCP_BIT] = "tcp", 1744 [FKH_ICMP_BIT] = "icmp", 1745 [FKH_VXLAN_BIT] = "vxlan", 1746 [FKH_L4RAW_BIT] = "l4raw", 1747 }; 1748 uint32_t fkh_bits = fk_hdrset->fk_header_select; 1749 uint32_t fkm_bits = fk_hdrset->fk_metadata; 1750 int n; 1751 1752 if (!fkm_bits && !fkh_bits) 1753 return; 1754 n = snprintf(buf, buf_len, "metadata("); 1755 if (n > 0 && n < buf_len) { 1756 buf += n; 1757 buf_len -= n; 1758 } 1759 n = bits_to_str(fkm_bits, fm_fkm_str, FKM_BIT_COUNT, buf, buf_len); 1760 if (n > 0 && n < buf_len) { 1761 buf += n; 1762 buf_len -= n; 1763 } 1764 n = snprintf(buf, buf_len, ") valid hdr fields("); 1765 if (n > 0 && n < buf_len) { 1766 buf += n; 1767 buf_len -= n; 1768 } 1769 n = bits_to_str(fkh_bits, fm_fkh_str, FKH_BIT_COUNT, buf, buf_len); 1770 if (n > 0 && n < buf_len) { 1771 buf += n; 1772 buf_len -= n; 1773 } 1774 snprintf(buf, buf_len, ")"); 1775 } 1776 1777 static void 1778 enic_fm_dump_tcam_match(const struct fm_tcam_match_entry *match, 1779 uint8_t ingress) 1780 { 1781 char buf[256]; 1782 1783 memset(buf, 0, sizeof(buf)); 1784 __enic_fm_dump_tcam_match(&match->ftm_mask.fk_hdrset[0], 1785 buf, sizeof(buf)); 1786 ENICPMD_LOG(DEBUG, " TCAM %s Outer: %s %scounter position %u", 1787 (ingress) ? "IG" : "EG", buf, 1788 (match->ftm_flags & FMEF_COUNTER) ? "" : "no ", 1789 match->ftm_position); 1790 memset(buf, 0, sizeof(buf)); 1791 __enic_fm_dump_tcam_match(&match->ftm_mask.fk_hdrset[1], 1792 buf, sizeof(buf)); 1793 if (buf[0]) 1794 ENICPMD_LOG(DEBUG, " Inner: %s", buf); 1795 } 1796 1797 /* Debug function to dump internal NIC flow structures. */ 1798 static void 1799 enic_fm_dump_tcam_entry(const struct fm_tcam_match_entry *fm_match, 1800 const struct fm_action *fm_action, 1801 uint8_t ingress) 1802 { 1803 if (!rte_log_can_log(enic_pmd_logtype, RTE_LOG_DEBUG)) 1804 return; 1805 enic_fm_dump_tcam_match(fm_match, ingress); 1806 enic_fm_dump_tcam_actions(fm_action); 1807 } 1808 1809 static int 1810 enic_fm_flow_parse(struct enic_flowman *fm, 1811 const struct rte_flow_attr *attrs, 1812 const struct rte_flow_item pattern[], 1813 const struct rte_flow_action actions[], 1814 struct rte_flow_error *error) 1815 { 1816 const struct rte_flow_action *action; 1817 unsigned int ret; 1818 static const enum rte_flow_action_type *sa; 1819 1820 ENICPMD_FUNC_TRACE(); 1821 ret = 0; 1822 if (!pattern) { 1823 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, 1824 NULL, "no pattern specified"); 1825 return -rte_errno; 1826 } 1827 1828 if (!actions) { 1829 rte_flow_error_set(error, EINVAL, 1830 RTE_FLOW_ERROR_TYPE_ACTION_NUM, 1831 NULL, "no action specified"); 1832 return -rte_errno; 1833 } 1834 1835 if (attrs) { 1836 if (attrs->group != FM_TCAM_RTE_GROUP && attrs->priority) { 1837 rte_flow_error_set(error, ENOTSUP, 1838 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1839 NULL, 1840 "priorities are not supported for non-default (0) groups"); 1841 return -rte_errno; 1842 } else if (!fm->owner_enic->switchdev_mode && attrs->transfer) { 1843 rte_flow_error_set(error, ENOTSUP, 1844 RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 1845 NULL, 1846 "transfer is not supported"); 1847 return -rte_errno; 1848 } else if (attrs->ingress && attrs->egress) { 1849 rte_flow_error_set(error, ENOTSUP, 1850 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1851 NULL, 1852 "bidirectional rules not supported"); 1853 return -rte_errno; 1854 } 1855 1856 } else { 1857 rte_flow_error_set(error, EINVAL, 1858 RTE_FLOW_ERROR_TYPE_ATTR, 1859 NULL, "no attribute specified"); 1860 return -rte_errno; 1861 } 1862 1863 /* Verify Actions. */ 1864 sa = (attrs->ingress) ? enic_fm_supported_ig_actions : 1865 enic_fm_supported_eg_actions; 1866 for (action = &actions[0]; action->type != RTE_FLOW_ACTION_TYPE_END; 1867 action++) { 1868 if (action->type == RTE_FLOW_ACTION_TYPE_VOID) 1869 continue; 1870 else if (!enic_fm_match_action(action, sa)) 1871 break; 1872 } 1873 if (action->type != RTE_FLOW_ACTION_TYPE_END) { 1874 rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_ACTION, 1875 action, "invalid action"); 1876 return -rte_errno; 1877 } 1878 ret = enic_fm_copy_entry(fm, pattern, error); 1879 if (ret) 1880 return ret; 1881 ret = enic_fm_copy_action(fm, actions, attrs->ingress, error); 1882 return ret; 1883 } 1884 1885 static void 1886 enic_fm_counter_free(struct enic_flowman *fm, struct enic_fm_flow *fm_flow) 1887 { 1888 if (!fm_flow->counter_valid) 1889 return; 1890 SLIST_INSERT_HEAD(&fm->counters, fm_flow->counter, next); 1891 fm_flow->counter_valid = false; 1892 } 1893 1894 static int 1895 enic_fm_more_counters(struct enic_flowman *fm) 1896 { 1897 struct enic_fm_counter *new_stack; 1898 struct enic_fm_counter *ctrs; 1899 int i, rc; 1900 uint64_t args[2]; 1901 1902 ENICPMD_FUNC_TRACE(); 1903 new_stack = rte_realloc(fm->counter_stack, (fm->counters_alloced + 1904 FM_COUNTERS_EXPAND) * 1905 sizeof(struct enic_fm_counter), 0); 1906 if (new_stack == NULL) { 1907 ENICPMD_LOG(ERR, "cannot alloc counter memory"); 1908 return -ENOMEM; 1909 } 1910 fm->counter_stack = new_stack; 1911 1912 args[0] = FM_COUNTER_BRK; 1913 args[1] = fm->counters_alloced + FM_COUNTERS_EXPAND; 1914 rc = flowman_cmd(fm, args, 2); 1915 if (rc != 0) { 1916 ENICPMD_LOG(ERR, "cannot alloc counters rc=%d", rc); 1917 return rc; 1918 } 1919 ctrs = (struct enic_fm_counter *)fm->counter_stack + 1920 fm->counters_alloced; 1921 for (i = 0; i < FM_COUNTERS_EXPAND; i++, ctrs++) { 1922 ctrs->handle = fm->counters_alloced + i; 1923 SLIST_INSERT_HEAD(&fm->counters, ctrs, next); 1924 } 1925 fm->counters_alloced += FM_COUNTERS_EXPAND; 1926 ENICPMD_LOG(DEBUG, "%u counters allocated, total: %u", 1927 FM_COUNTERS_EXPAND, fm->counters_alloced); 1928 return 0; 1929 } 1930 1931 static int 1932 enic_fm_counter_zero(struct enic_flowman *fm, struct enic_fm_counter *c) 1933 { 1934 uint64_t args[3]; 1935 int ret; 1936 1937 ENICPMD_FUNC_TRACE(); 1938 args[0] = FM_COUNTER_QUERY; 1939 args[1] = c->handle; 1940 args[2] = 1; /* clear */ 1941 ret = flowman_cmd(fm, args, 3); 1942 if (ret) { 1943 ENICPMD_LOG(ERR, "counter init: rc=%d handle=0x%x", 1944 ret, c->handle); 1945 return ret; 1946 } 1947 return 0; 1948 } 1949 1950 static int 1951 enic_fm_counter_alloc(struct enic_flowman *fm, struct rte_flow_error *error, 1952 struct enic_fm_counter **ctr) 1953 { 1954 struct enic_fm_counter *c; 1955 int ret; 1956 1957 ENICPMD_FUNC_TRACE(); 1958 *ctr = NULL; 1959 if (SLIST_EMPTY(&fm->counters)) { 1960 ret = enic_fm_more_counters(fm); 1961 if (ret) 1962 return rte_flow_error_set(error, -ret, 1963 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1964 NULL, "enic: out of counters"); 1965 } 1966 c = SLIST_FIRST(&fm->counters); 1967 SLIST_REMOVE_HEAD(&fm->counters, next); 1968 *ctr = c; 1969 return 0; 1970 } 1971 1972 static int 1973 enic_fm_action_free(struct enic_flowman *fm, struct enic_fm_action *ah) 1974 { 1975 uint64_t args[2]; 1976 int ret = 0; 1977 1978 ENICPMD_FUNC_TRACE(); 1979 RTE_ASSERT(ah->ref > 0); 1980 ah->ref--; 1981 if (ah->ref == 0) { 1982 args[0] = FM_ACTION_FREE; 1983 args[1] = ah->handle; 1984 ret = flowman_cmd(fm, args, 2); 1985 if (ret) 1986 /* This is a "should never happen" error. */ 1987 ENICPMD_LOG(ERR, "freeing action rc=%d handle=0x%" 1988 PRIx64, ret, ah->handle); 1989 rte_hash_del_key(fm->action_hash, (const void *)&ah->key); 1990 free(ah); 1991 } 1992 return ret; 1993 } 1994 1995 static int 1996 enic_fm_entry_free(struct enic_flowman *fm, uint64_t handle) 1997 { 1998 uint64_t args[2]; 1999 int rc; 2000 2001 ENICPMD_FUNC_TRACE(); 2002 args[0] = FM_MATCH_ENTRY_REMOVE; 2003 args[1] = handle; 2004 rc = flowman_cmd(fm, args, 2); 2005 if (rc) 2006 ENICPMD_LOG(ERR, "cannot free match entry: rc=%d" 2007 " handle=0x%" PRIx64, rc, handle); 2008 return rc; 2009 } 2010 2011 static struct enic_fm_jump_flow * 2012 find_jump_flow(struct enic_flowman *fm, uint32_t group) 2013 { 2014 struct enic_fm_jump_flow *j; 2015 2016 ENICPMD_FUNC_TRACE(); 2017 TAILQ_FOREACH(j, &fm->jump_list, list) { 2018 if (j->group == group) 2019 return j; 2020 } 2021 return NULL; 2022 } 2023 2024 static void 2025 remove_jump_flow(struct enic_flowman *fm, struct rte_flow *flow) 2026 { 2027 struct enic_fm_jump_flow *j; 2028 2029 ENICPMD_FUNC_TRACE(); 2030 TAILQ_FOREACH(j, &fm->jump_list, list) { 2031 if (j->flow == flow) { 2032 TAILQ_REMOVE(&fm->jump_list, j, list); 2033 free(j); 2034 return; 2035 } 2036 } 2037 } 2038 2039 static int 2040 save_jump_flow(struct enic_flowman *fm, 2041 struct rte_flow *flow, 2042 uint32_t group, 2043 struct fm_tcam_match_entry *match, 2044 struct fm_action *action) 2045 { 2046 struct enic_fm_jump_flow *j; 2047 2048 ENICPMD_FUNC_TRACE(); 2049 j = calloc(1, sizeof(struct enic_fm_jump_flow)); 2050 if (j == NULL) 2051 return -ENOMEM; 2052 j->flow = flow; 2053 j->group = group; 2054 j->match = *match; 2055 j->action = *action; 2056 TAILQ_INSERT_HEAD(&fm->jump_list, j, list); 2057 ENICPMD_LOG(DEBUG, "saved jump flow: flow=%p group=%u", flow, group); 2058 return 0; 2059 } 2060 2061 static void 2062 __enic_fm_flow_free(struct enic_flowman *fm, struct enic_fm_flow *fm_flow) 2063 { 2064 if (fm_flow->entry_handle != FM_INVALID_HANDLE) { 2065 enic_fm_entry_free(fm, fm_flow->entry_handle); 2066 fm_flow->entry_handle = FM_INVALID_HANDLE; 2067 } 2068 if (fm_flow->action != NULL) { 2069 enic_fm_action_free(fm, fm_flow->action); 2070 fm_flow->action = NULL; 2071 } 2072 enic_fm_counter_free(fm, fm_flow); 2073 if (fm_flow->fet) { 2074 enic_fet_put(fm, fm_flow->fet); 2075 fm_flow->fet = NULL; 2076 } 2077 } 2078 2079 static void 2080 enic_fm_flow_free(struct enic_flowman *fm, struct rte_flow *flow) 2081 { 2082 struct enic_fm_flow *steer = flow->fm->hairpin_steer_flow; 2083 2084 if (flow->fm->fet && flow->fm->fet->default_key) 2085 remove_jump_flow(fm, flow); 2086 __enic_fm_flow_free(fm, flow->fm); 2087 if (steer) { 2088 __enic_fm_flow_free(fm, steer); 2089 free(steer); 2090 } 2091 free(flow->fm); 2092 free(flow); 2093 } 2094 2095 static int 2096 enic_fm_add_tcam_entry(struct enic_flowman *fm, 2097 struct fm_tcam_match_entry *match_in, 2098 uint64_t *entry_handle, 2099 uint8_t ingress, 2100 struct rte_flow_error *error) 2101 { 2102 struct fm_tcam_match_entry *ftm; 2103 uint64_t args[3]; 2104 int ret; 2105 2106 ENICPMD_FUNC_TRACE(); 2107 /* Copy entry to the command buffer */ 2108 ftm = &fm->cmd.va->fm_tcam_match_entry; 2109 memcpy(ftm, match_in, sizeof(*ftm)); 2110 /* Add TCAM entry */ 2111 args[0] = FM_TCAM_ENTRY_INSTALL; 2112 args[1] = ingress ? fm->ig_tcam_hndl : fm->eg_tcam_hndl; 2113 args[2] = fm->cmd.pa; 2114 ret = flowman_cmd(fm, args, 3); 2115 if (ret != 0) { 2116 ENICPMD_LOG(ERR, "cannot add %s TCAM entry: rc=%d", 2117 ingress ? "ingress" : "egress", ret); 2118 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2119 NULL, "enic: devcmd(tcam-entry-install)"); 2120 return ret; 2121 } 2122 ENICPMD_LOG(DEBUG, "installed %s TCAM entry: handle=0x%" PRIx64, 2123 ingress ? "ingress" : "egress", (uint64_t)args[0]); 2124 *entry_handle = args[0]; 2125 return 0; 2126 } 2127 2128 static int 2129 enic_fm_add_exact_entry(struct enic_flowman *fm, 2130 struct fm_tcam_match_entry *match_in, 2131 uint64_t *entry_handle, 2132 struct enic_fm_fet *fet, 2133 struct rte_flow_error *error) 2134 { 2135 struct fm_exact_match_entry *fem; 2136 uint64_t args[3]; 2137 int ret; 2138 2139 ENICPMD_FUNC_TRACE(); 2140 /* The new entry must have the table's key */ 2141 if (memcmp(fet->key.fk_hdrset, match_in->ftm_mask.fk_hdrset, 2142 sizeof(struct fm_header_set) * FM_HDRSET_MAX)) { 2143 return rte_flow_error_set(error, EINVAL, 2144 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 2145 "enic: key does not match group's key"); 2146 } 2147 2148 /* Copy entry to the command buffer */ 2149 fem = &fm->cmd.va->fm_exact_match_entry; 2150 /* 2151 * Translate TCAM entry to exact entry. As is only need to drop 2152 * position and mask. The mask is part of the exact match table. 2153 * Position (aka priority) is not supported in the exact match table. 2154 */ 2155 fem->fem_data = match_in->ftm_data; 2156 fem->fem_flags = match_in->ftm_flags; 2157 fem->fem_action = match_in->ftm_action; 2158 fem->fem_counter = match_in->ftm_counter; 2159 2160 /* Add exact entry */ 2161 args[0] = FM_EXACT_ENTRY_INSTALL; 2162 args[1] = fet->handle; 2163 args[2] = fm->cmd.pa; 2164 ret = flowman_cmd(fm, args, 3); 2165 if (ret != 0) { 2166 ENICPMD_LOG(ERR, "cannot add %s exact entry: group=%u", 2167 fet->ingress ? "ingress" : "egress", fet->group); 2168 rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2169 NULL, "enic: devcmd(exact-entry-install)"); 2170 return ret; 2171 } 2172 ENICPMD_LOG(DEBUG, "installed %s exact entry: group=%u" 2173 " handle=0x%" PRIx64, 2174 fet->ingress ? "ingress" : "egress", fet->group, 2175 (uint64_t)args[0]); 2176 *entry_handle = args[0]; 2177 return 0; 2178 } 2179 2180 static int 2181 enic_action_handle_get(struct enic_flowman *fm, struct fm_action *action_in, 2182 struct rte_flow_error *error, 2183 struct enic_fm_action **ah_o) 2184 { 2185 struct enic_fm_action *ah; 2186 struct fm_action *fma; 2187 uint64_t args[2]; 2188 int ret = 0; 2189 2190 ret = rte_hash_lookup_data(fm->action_hash, action_in, 2191 (void **)&ah); 2192 if (ret < 0 && ret != -ENOENT) 2193 return rte_flow_error_set(error, -ret, 2194 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2195 NULL, "enic: rte_hash_lookup(aciton)"); 2196 2197 if (ret == -ENOENT) { 2198 /* Allocate a new action on the NIC. */ 2199 fma = &fm->cmd.va->fm_action; 2200 memcpy(fma, action_in, sizeof(*fma)); 2201 2202 ah = calloc(1, sizeof(*ah)); 2203 memcpy(&ah->key, action_in, sizeof(struct fm_action)); 2204 if (ah == NULL) 2205 return rte_flow_error_set(error, ENOMEM, 2206 RTE_FLOW_ERROR_TYPE_HANDLE, 2207 NULL, "enic: calloc(fm-action)"); 2208 args[0] = FM_ACTION_ALLOC; 2209 args[1] = fm->cmd.pa; 2210 ret = flowman_cmd(fm, args, 2); 2211 if (ret != 0) { 2212 rte_flow_error_set(error, -ret, 2213 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2214 NULL, "enic: devcmd(action-alloc)"); 2215 goto error_with_ah; 2216 } 2217 ah->handle = args[0]; 2218 ret = rte_hash_add_key_data(fm->action_hash, 2219 (const void *)action_in, 2220 (void *)ah); 2221 if (ret != 0) { 2222 rte_flow_error_set(error, -ret, 2223 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2224 NULL, 2225 "enic: rte_hash_add_key_data(actn)"); 2226 goto error_with_action_handle; 2227 } 2228 ENICPMD_LOG(DEBUG, "action allocated: handle=0x%" PRIx64, 2229 ah->handle); 2230 } 2231 2232 /* Action handle struct is valid, increment reference count. */ 2233 ah->ref++; 2234 *ah_o = ah; 2235 return 0; 2236 error_with_action_handle: 2237 args[0] = FM_ACTION_FREE; 2238 args[1] = ah->handle; 2239 ret = flowman_cmd(fm, args, 2); 2240 if (ret != 0) 2241 rte_flow_error_set(error, -ret, 2242 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2243 NULL, "enic: devcmd(action-free)"); 2244 error_with_ah: 2245 free(ah); 2246 return ret; 2247 } 2248 2249 /* Push match-action to the NIC. */ 2250 static int 2251 __enic_fm_flow_add_entry(struct enic_flowman *fm, 2252 struct enic_fm_flow *fm_flow, 2253 struct fm_tcam_match_entry *match_in, 2254 struct fm_action *action_in, 2255 uint32_t group, 2256 uint8_t ingress, 2257 struct rte_flow_error *error) 2258 { 2259 struct enic_fm_counter *ctr; 2260 struct enic_fm_action *ah = NULL; 2261 uint64_t entry_h; 2262 int ret; 2263 2264 ENICPMD_FUNC_TRACE(); 2265 2266 /* Get or create an aciton handle. */ 2267 ret = enic_action_handle_get(fm, action_in, error, &ah); 2268 if (ret) 2269 return ret; 2270 match_in->ftm_action = ah->handle; 2271 fm_flow->action = ah; 2272 2273 /* Allocate counter if requested. */ 2274 if (match_in->ftm_flags & FMEF_COUNTER) { 2275 ret = enic_fm_counter_alloc(fm, error, &ctr); 2276 if (ret) /* error has been filled in */ 2277 return ret; 2278 fm_flow->counter_valid = true; 2279 fm_flow->counter = ctr; 2280 match_in->ftm_counter = ctr->handle; 2281 } 2282 2283 /* 2284 * Get the group's table (either TCAM or exact match table) and 2285 * add entry to it. If we use the exact match table, the handler 2286 * will translate the TCAM entry (match_in) to the appropriate 2287 * exact match entry and use that instead. 2288 */ 2289 entry_h = FM_INVALID_HANDLE; 2290 if (group == FM_TCAM_RTE_GROUP) { 2291 ret = enic_fm_add_tcam_entry(fm, match_in, &entry_h, ingress, 2292 error); 2293 if (ret) 2294 return ret; 2295 /* Jump action might have a ref to fet */ 2296 fm_flow->fet = fm->fet; 2297 fm->fet = NULL; 2298 } else { 2299 struct enic_fm_fet *fet = NULL; 2300 2301 ret = enic_fet_get(fm, group, ingress, 2302 &match_in->ftm_mask, &fet, error); 2303 if (ret) 2304 return ret; 2305 fm_flow->fet = fet; 2306 ret = enic_fm_add_exact_entry(fm, match_in, &entry_h, fet, 2307 error); 2308 if (ret) 2309 return ret; 2310 } 2311 /* Clear counter after adding entry, as it requires in-use counter */ 2312 if (fm_flow->counter_valid) { 2313 ret = enic_fm_counter_zero(fm, fm_flow->counter); 2314 if (ret) 2315 return ret; 2316 } 2317 fm_flow->entry_handle = entry_h; 2318 return 0; 2319 } 2320 2321 /* Push match-action to the NIC. */ 2322 static struct rte_flow * 2323 enic_fm_flow_add_entry(struct enic_flowman *fm, 2324 struct fm_tcam_match_entry *match_in, 2325 struct fm_action *action_in, 2326 const struct rte_flow_attr *attrs, 2327 struct rte_flow_error *error) 2328 { 2329 struct enic_fm_flow *fm_flow; 2330 struct rte_flow *flow; 2331 2332 ENICPMD_FUNC_TRACE(); 2333 match_in->ftm_position = attrs->priority; 2334 enic_fm_dump_tcam_entry(match_in, action_in, attrs->ingress); 2335 flow = calloc(1, sizeof(*flow)); 2336 fm_flow = calloc(1, sizeof(*fm_flow)); 2337 if (flow == NULL || fm_flow == NULL) { 2338 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, 2339 NULL, "enic: cannot allocate rte_flow"); 2340 free(flow); 2341 free(fm_flow); 2342 return NULL; 2343 } 2344 flow->fm = fm_flow; 2345 fm_flow->action = NULL; 2346 fm_flow->entry_handle = FM_INVALID_HANDLE; 2347 if (__enic_fm_flow_add_entry(fm, fm_flow, match_in, action_in, 2348 attrs->group, attrs->ingress, error)) { 2349 enic_fm_flow_free(fm, flow); 2350 return NULL; 2351 } 2352 return flow; 2353 } 2354 2355 static void 2356 convert_jump_flows(struct enic_flowman *fm, struct enic_fm_fet *fet, 2357 struct rte_flow_error *error) 2358 { 2359 struct enic_fm_flow *fm_flow; 2360 struct enic_fm_jump_flow *j; 2361 struct fm_action *fma; 2362 uint32_t group; 2363 2364 ENICPMD_FUNC_TRACE(); 2365 /* 2366 * Find the saved flows that should jump to the new table (fet). 2367 * Then delete the old TCAM entry that jumps to the default table, 2368 * and add a new one that jumps to the new table. 2369 */ 2370 group = fet->group; 2371 j = find_jump_flow(fm, group); 2372 while (j) { 2373 ENICPMD_LOG(DEBUG, "convert jump flow: flow=%p group=%u", 2374 j->flow, group); 2375 /* Delete old entry */ 2376 fm_flow = j->flow->fm; 2377 __enic_fm_flow_free(fm, fm_flow); 2378 2379 /* Add new entry */ 2380 fma = &j->action; 2381 fma->fma_action_ops[0].exact.handle = fet->handle; 2382 if (__enic_fm_flow_add_entry(fm, fm_flow, &j->match, fma, 2383 FM_TCAM_RTE_GROUP, fet->ingress, error)) { 2384 /* Cannot roll back changes at the moment */ 2385 ENICPMD_LOG(ERR, "cannot convert jump flow: flow=%p", 2386 j->flow); 2387 } else { 2388 fm_flow->fet = fet; 2389 fet->ref++; 2390 ENICPMD_LOG(DEBUG, "convert ok: group=%u ref=%u", 2391 fet->group, fet->ref); 2392 } 2393 2394 TAILQ_REMOVE(&fm->jump_list, j, list); 2395 free(j); 2396 j = find_jump_flow(fm, group); 2397 } 2398 } 2399 2400 static int 2401 add_hairpin_steer(struct enic_flowman *fm, struct rte_flow *flow, 2402 struct rte_flow_error *error) 2403 { 2404 struct fm_tcam_match_entry *fm_tcam_entry; 2405 struct enic_fm_flow *fm_flow; 2406 struct fm_action *fm_action; 2407 struct fm_action_op fm_op; 2408 int ret; 2409 2410 ENICPMD_FUNC_TRACE(); 2411 fm_flow = calloc(1, sizeof(*fm_flow)); 2412 if (fm_flow == NULL) { 2413 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, 2414 NULL, "enic: cannot allocate rte_flow"); 2415 return -ENOMEM; 2416 } 2417 /* Original egress hairpin flow */ 2418 fm_tcam_entry = &fm->tcam_entry; 2419 fm_action = &fm->action; 2420 /* Use the match pattern of the egress flow as is, without counters */ 2421 fm_tcam_entry->ftm_flags &= ~FMEF_COUNTER; 2422 /* The only action is steer to vnic */ 2423 fm->action_op_count = 0; 2424 memset(fm_action, 0, sizeof(*fm_action)); 2425 memset(&fm_op, 0, sizeof(fm_op)); 2426 /* Always to queue 0 for now */ 2427 fm_op.fa_op = FMOP_RQ_STEER; 2428 fm_op.rq_steer.rq_index = 0; 2429 fm_op.rq_steer.vnic_handle = fm->hairpin_steer_vnic_h; 2430 ret = enic_fm_append_action_op(fm, &fm_op, error); 2431 if (ret) 2432 goto error_with_flow; 2433 ENICPMD_LOG(DEBUG, "add steer op"); 2434 /* Add required END */ 2435 memset(&fm_op, 0, sizeof(fm_op)); 2436 fm_op.fa_op = FMOP_END; 2437 ret = enic_fm_append_action_op(fm, &fm_op, error); 2438 if (ret) 2439 goto error_with_flow; 2440 /* Add the ingress flow */ 2441 fm_flow->action = NULL; 2442 fm_flow->entry_handle = FM_INVALID_HANDLE; 2443 ret = __enic_fm_flow_add_entry(fm, fm_flow, fm_tcam_entry, fm_action, 2444 FM_TCAM_RTE_GROUP, 1 /* ingress */, error); 2445 if (ret) { 2446 ENICPMD_LOG(ERR, "cannot add hairpin-steer flow"); 2447 goto error_with_flow; 2448 } 2449 /* The new flow is now the egress flow's paired flow */ 2450 flow->fm->hairpin_steer_flow = fm_flow; 2451 return 0; 2452 2453 error_with_flow: 2454 free(fm_flow); 2455 return ret; 2456 } 2457 2458 static void 2459 enic_fm_open_scratch(struct enic_flowman *fm) 2460 { 2461 fm->action_op_count = 0; 2462 fm->fet = NULL; 2463 fm->need_hairpin_steer = 0; 2464 fm->hairpin_steer_vnic_h = 0; 2465 memset(&fm->tcam_entry, 0, sizeof(fm->tcam_entry)); 2466 memset(&fm->action, 0, sizeof(fm->action)); 2467 } 2468 2469 static void 2470 enic_fm_close_scratch(struct enic_flowman *fm) 2471 { 2472 if (fm->fet) { 2473 enic_fet_put(fm, fm->fet); 2474 fm->fet = NULL; 2475 } 2476 fm->action_op_count = 0; 2477 } 2478 2479 static int 2480 enic_fm_flow_validate(struct rte_eth_dev *dev, 2481 const struct rte_flow_attr *attrs, 2482 const struct rte_flow_item pattern[], 2483 const struct rte_flow_action actions[], 2484 struct rte_flow_error *error) 2485 { 2486 struct fm_tcam_match_entry *fm_tcam_entry; 2487 struct fm_action *fm_action; 2488 struct enic_flowman *fm; 2489 int ret; 2490 2491 ENICPMD_FUNC_TRACE(); 2492 fm = begin_fm(pmd_priv(dev)); 2493 if (fm == NULL) 2494 return -ENOTSUP; 2495 enic_fm_open_scratch(fm); 2496 ret = enic_fm_flow_parse(fm, attrs, pattern, actions, error); 2497 if (!ret) { 2498 fm_tcam_entry = &fm->tcam_entry; 2499 fm_action = &fm->action; 2500 enic_fm_dump_tcam_entry(fm_tcam_entry, fm_action, 2501 attrs->ingress); 2502 } 2503 enic_fm_close_scratch(fm); 2504 end_fm(fm); 2505 return ret; 2506 } 2507 2508 static int 2509 enic_fm_flow_query_count(struct rte_eth_dev *dev, 2510 struct rte_flow *flow, void *data, 2511 struct rte_flow_error *error) 2512 { 2513 struct rte_flow_query_count *query; 2514 struct enic_fm_flow *fm_flow; 2515 struct enic_flowman *fm; 2516 uint64_t args[3]; 2517 int rc; 2518 2519 ENICPMD_FUNC_TRACE(); 2520 fm = begin_fm(pmd_priv(dev)); 2521 query = data; 2522 fm_flow = flow->fm; 2523 if (!fm_flow->counter_valid) { 2524 rc = rte_flow_error_set(error, ENOTSUP, 2525 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2526 "enic: flow does not have counter"); 2527 goto exit; 2528 } 2529 2530 args[0] = FM_COUNTER_QUERY; 2531 args[1] = fm_flow->counter->handle; 2532 args[2] = query->reset; 2533 rc = flowman_cmd(fm, args, 3); 2534 if (rc) { 2535 ENICPMD_LOG(ERR, "cannot query counter: rc=%d handle=0x%x", 2536 rc, fm_flow->counter->handle); 2537 goto exit; 2538 } 2539 query->hits_set = 1; 2540 query->hits = args[0]; 2541 query->bytes_set = 1; 2542 query->bytes = args[1]; 2543 rc = 0; 2544 exit: 2545 end_fm(fm); 2546 return rc; 2547 } 2548 2549 static int 2550 enic_fm_flow_query(struct rte_eth_dev *dev, 2551 struct rte_flow *flow, 2552 const struct rte_flow_action *actions, 2553 void *data, 2554 struct rte_flow_error *error) 2555 { 2556 int ret = 0; 2557 2558 ENICPMD_FUNC_TRACE(); 2559 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2560 switch (actions->type) { 2561 case RTE_FLOW_ACTION_TYPE_VOID: 2562 break; 2563 case RTE_FLOW_ACTION_TYPE_COUNT: 2564 ret = enic_fm_flow_query_count(dev, flow, data, error); 2565 break; 2566 default: 2567 return rte_flow_error_set(error, ENOTSUP, 2568 RTE_FLOW_ERROR_TYPE_ACTION, 2569 actions, 2570 "action not supported"); 2571 } 2572 if (ret < 0) 2573 return ret; 2574 } 2575 return 0; 2576 } 2577 2578 static struct rte_flow * 2579 enic_fm_flow_create(struct rte_eth_dev *dev, 2580 const struct rte_flow_attr *attrs, 2581 const struct rte_flow_item pattern[], 2582 const struct rte_flow_action actions[], 2583 struct rte_flow_error *error) 2584 { 2585 struct fm_tcam_match_entry *fm_tcam_entry; 2586 struct fm_action *fm_action; 2587 struct enic_flowman *fm; 2588 struct enic_fm_fet *fet; 2589 struct rte_flow *flow; 2590 struct enic *enic; 2591 int ret; 2592 2593 ENICPMD_FUNC_TRACE(); 2594 enic = pmd_priv(dev); 2595 fm = begin_fm(enic); 2596 if (fm == NULL) { 2597 rte_flow_error_set(error, ENOTSUP, 2598 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2599 "flowman is not initialized"); 2600 return NULL; 2601 } 2602 enic_fm_open_scratch(fm); 2603 flow = NULL; 2604 ret = enic_fm_flow_parse(fm, attrs, pattern, actions, error); 2605 if (ret < 0) 2606 goto error_with_scratch; 2607 fm_tcam_entry = &fm->tcam_entry; 2608 fm_action = &fm->action; 2609 flow = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action, 2610 attrs, error); 2611 if (flow) { 2612 /* Add ingress rule that pairs with hairpin rule */ 2613 if (fm->need_hairpin_steer) { 2614 ret = add_hairpin_steer(fm, flow, error); 2615 if (ret) { 2616 enic_fm_flow_free(fm, flow); 2617 flow = NULL; 2618 goto error_with_scratch; 2619 } 2620 } 2621 LIST_INSERT_HEAD(&enic->flows, flow, next); 2622 fet = flow->fm->fet; 2623 if (fet && fet->default_key) { 2624 /* 2625 * Jump to non-existent group? Save the relevant info 2626 * so we can convert this flow when that group 2627 * materializes. 2628 */ 2629 save_jump_flow(fm, flow, fet->group, 2630 fm_tcam_entry, fm_action); 2631 } else if (fet && fet->ref == 1) { 2632 /* 2633 * A new table is created. Convert the saved flows 2634 * that should jump to this group. 2635 */ 2636 convert_jump_flows(fm, fet, error); 2637 } 2638 } 2639 2640 error_with_scratch: 2641 enic_fm_close_scratch(fm); 2642 end_fm(fm); 2643 return flow; 2644 } 2645 2646 static int 2647 enic_fm_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, 2648 __rte_unused struct rte_flow_error *error) 2649 { 2650 struct enic *enic = pmd_priv(dev); 2651 struct enic_flowman *fm; 2652 2653 ENICPMD_FUNC_TRACE(); 2654 fm = begin_fm(enic); 2655 if (fm == NULL) 2656 return 0; 2657 LIST_REMOVE(flow, next); 2658 enic_fm_flow_free(fm, flow); 2659 end_fm(fm); 2660 return 0; 2661 } 2662 2663 static int 2664 enic_fm_flow_flush(struct rte_eth_dev *dev, 2665 __rte_unused struct rte_flow_error *error) 2666 { 2667 LIST_HEAD(enic_flows, rte_flow) internal; 2668 struct enic_fm_flow *fm_flow; 2669 struct enic_flowman *fm; 2670 struct rte_flow *flow; 2671 struct enic *enic = pmd_priv(dev); 2672 2673 ENICPMD_FUNC_TRACE(); 2674 2675 fm = begin_fm(enic); 2676 if (fm == NULL) 2677 return 0; 2678 /* Destroy all non-internal flows */ 2679 LIST_INIT(&internal); 2680 while (!LIST_EMPTY(&enic->flows)) { 2681 flow = LIST_FIRST(&enic->flows); 2682 fm_flow = flow->fm; 2683 LIST_REMOVE(flow, next); 2684 if (flow->internal) { 2685 LIST_INSERT_HEAD(&internal, flow, next); 2686 continue; 2687 } 2688 /* 2689 * If tables are null, then vNIC is closing, and the firmware 2690 * has already cleaned up flowman state. So do not try to free 2691 * resources, as it only causes errors. 2692 */ 2693 if (fm->ig_tcam_hndl == FM_INVALID_HANDLE) { 2694 fm_flow->entry_handle = FM_INVALID_HANDLE; 2695 fm_flow->action = NULL; 2696 fm_flow->fet = NULL; 2697 } 2698 enic_fm_flow_free(fm, flow); 2699 } 2700 while (!LIST_EMPTY(&internal)) { 2701 flow = LIST_FIRST(&internal); 2702 LIST_REMOVE(flow, next); 2703 LIST_INSERT_HEAD(&enic->flows, flow, next); 2704 } 2705 end_fm(fm); 2706 return 0; 2707 } 2708 2709 static int 2710 enic_fm_tbl_free(struct enic_flowman *fm, uint64_t handle) 2711 { 2712 uint64_t args[2]; 2713 int rc; 2714 2715 args[0] = FM_MATCH_TABLE_FREE; 2716 args[1] = handle; 2717 rc = flowman_cmd(fm, args, 2); 2718 if (rc) 2719 ENICPMD_LOG(ERR, "cannot free table: rc=%d handle=0x%" PRIx64, 2720 rc, handle); 2721 return rc; 2722 } 2723 2724 static int 2725 enic_fm_tcam_tbl_alloc(struct enic_flowman *fm, uint32_t direction, 2726 uint32_t max_entries, uint64_t *handle) 2727 { 2728 struct fm_tcam_match_table *tcam_tbl; 2729 uint64_t args[2]; 2730 int rc; 2731 2732 ENICPMD_FUNC_TRACE(); 2733 tcam_tbl = &fm->cmd.va->fm_tcam_match_table; 2734 tcam_tbl->ftt_direction = direction; 2735 tcam_tbl->ftt_stage = FM_STAGE_LAST; 2736 tcam_tbl->ftt_max_entries = max_entries; 2737 args[0] = FM_TCAM_TABLE_ALLOC; 2738 args[1] = fm->cmd.pa; 2739 rc = flowman_cmd(fm, args, 2); 2740 if (rc) { 2741 ENICPMD_LOG(ERR, "cannot alloc %s TCAM table: rc=%d", 2742 (direction == FM_INGRESS) ? "IG" : "EG", rc); 2743 return rc; 2744 } 2745 *handle = args[0]; 2746 ENICPMD_LOG(DEBUG, "%s TCAM table allocated, handle=0x%" PRIx64, 2747 (direction == FM_INGRESS) ? "IG" : "EG", *handle); 2748 return 0; 2749 } 2750 2751 static int 2752 enic_fm_init_actions(struct enic_flowman *fm) 2753 { 2754 struct rte_hash *a_hash; 2755 char name[RTE_HASH_NAMESIZE]; 2756 struct rte_hash_parameters params = { 2757 .entries = FM_MAX_ACTION_TABLE_SIZE, 2758 .key_len = sizeof(struct fm_action), 2759 .hash_func = rte_jhash, 2760 .hash_func_init_val = 0, 2761 .socket_id = rte_socket_id(), 2762 }; 2763 2764 ENICPMD_FUNC_TRACE(); 2765 snprintf((char *)name, sizeof(name), "fm-ah-%s", 2766 fm->owner_enic->bdf_name); 2767 params.name = name; 2768 2769 a_hash = rte_hash_create(¶ms); 2770 if (a_hash == NULL) 2771 return -rte_errno; 2772 fm->action_hash = a_hash; 2773 return 0; 2774 } 2775 2776 static int 2777 enic_fm_init_counters(struct enic_flowman *fm) 2778 { 2779 ENICPMD_FUNC_TRACE(); 2780 SLIST_INIT(&fm->counters); 2781 return enic_fm_more_counters(fm); 2782 } 2783 2784 static void 2785 enic_fm_free_all_counters(struct enic_flowman *fm) 2786 { 2787 uint64_t args[2]; 2788 int rc; 2789 2790 args[0] = FM_COUNTER_BRK; 2791 args[1] = 0; 2792 rc = flowman_cmd(fm, args, 2); 2793 if (rc != 0) 2794 ENICPMD_LOG(ERR, "cannot free counters: rc=%d", rc); 2795 rte_free(fm->counter_stack); 2796 } 2797 2798 static int 2799 enic_fm_alloc_tcam_tables(struct enic_flowman *fm) 2800 { 2801 int rc; 2802 2803 ENICPMD_FUNC_TRACE(); 2804 rc = enic_fm_tcam_tbl_alloc(fm, FM_INGRESS, FM_MAX_TCAM_TABLE_SIZE, 2805 &fm->ig_tcam_hndl); 2806 if (rc) 2807 return rc; 2808 rc = enic_fm_tcam_tbl_alloc(fm, FM_EGRESS, FM_MAX_TCAM_TABLE_SIZE, 2809 &fm->eg_tcam_hndl); 2810 return rc; 2811 } 2812 2813 static void 2814 enic_fm_free_tcam_tables(struct enic_flowman *fm) 2815 { 2816 ENICPMD_FUNC_TRACE(); 2817 if (fm->ig_tcam_hndl) { 2818 ENICPMD_LOG(DEBUG, "free IG TCAM table handle=0x%" PRIx64, 2819 fm->ig_tcam_hndl); 2820 enic_fm_tbl_free(fm, fm->ig_tcam_hndl); 2821 fm->ig_tcam_hndl = FM_INVALID_HANDLE; 2822 } 2823 if (fm->eg_tcam_hndl) { 2824 ENICPMD_LOG(DEBUG, "free EG TCAM table handle=0x%" PRIx64, 2825 fm->eg_tcam_hndl); 2826 enic_fm_tbl_free(fm, fm->eg_tcam_hndl); 2827 fm->eg_tcam_hndl = FM_INVALID_HANDLE; 2828 } 2829 } 2830 2831 int 2832 enic_fm_init(struct enic *enic) 2833 { 2834 const struct rte_pci_addr *addr; 2835 struct enic_flowman *fm; 2836 uint8_t name[RTE_MEMZONE_NAMESIZE]; 2837 int rc; 2838 2839 if (enic->flow_filter_mode != FILTER_FLOWMAN) 2840 return 0; 2841 ENICPMD_FUNC_TRACE(); 2842 /* Get vnic handle and save for port-id action */ 2843 if (enic_is_vf_rep(enic)) 2844 addr = &VF_ENIC_TO_VF_REP(enic)->bdf; 2845 else 2846 addr = &RTE_ETH_DEV_TO_PCI(enic->rte_dev)->addr; 2847 rc = enic_fm_find_vnic(enic, addr, &enic->fm_vnic_handle); 2848 if (rc) { 2849 ENICPMD_LOG(ERR, "cannot find vnic handle for %x:%x:%x", 2850 addr->bus, addr->devid, addr->function); 2851 return rc; 2852 } 2853 /* Save UIF for egport action */ 2854 enic->fm_vnic_uif = vnic_dev_uif(enic->vdev); 2855 ENICPMD_LOG(DEBUG, "uif %u", enic->fm_vnic_uif); 2856 /* Nothing else to do for representor. It will share the PF flowman */ 2857 if (enic_is_vf_rep(enic)) 2858 return 0; 2859 fm = calloc(1, sizeof(*fm)); 2860 if (fm == NULL) { 2861 ENICPMD_LOG(ERR, "cannot alloc flowman struct"); 2862 return -ENOMEM; 2863 } 2864 fm->owner_enic = enic; 2865 rte_spinlock_init(&fm->lock); 2866 TAILQ_INIT(&fm->fet_list); 2867 TAILQ_INIT(&fm->jump_list); 2868 /* Allocate host memory for flowman commands */ 2869 snprintf((char *)name, sizeof(name), "fm-cmd-%s", enic->bdf_name); 2870 fm->cmd.va = enic_alloc_consistent(enic, 2871 sizeof(union enic_flowman_cmd_mem), &fm->cmd.pa, name); 2872 if (!fm->cmd.va) { 2873 ENICPMD_LOG(ERR, "cannot allocate flowman command memory"); 2874 rc = -ENOMEM; 2875 goto error_fm; 2876 } 2877 /* Allocate TCAM tables upfront as they are the main tables */ 2878 rc = enic_fm_alloc_tcam_tables(fm); 2879 if (rc) { 2880 ENICPMD_LOG(ERR, "cannot alloc TCAM tables"); 2881 goto error_cmd; 2882 } 2883 /* Then a number of counters */ 2884 rc = enic_fm_init_counters(fm); 2885 if (rc) { 2886 ENICPMD_LOG(ERR, "cannot alloc counters"); 2887 goto error_tables; 2888 } 2889 /* set up action handle hash */ 2890 rc = enic_fm_init_actions(fm); 2891 if (rc) { 2892 ENICPMD_LOG(ERR, "cannot create action hash, error:%d", rc); 2893 goto error_tables; 2894 } 2895 /* 2896 * One default exact match table for each direction. We hold onto 2897 * it until close. 2898 */ 2899 rc = enic_fet_alloc(fm, 1, NULL, 128, &fm->default_ig_fet); 2900 if (rc) { 2901 ENICPMD_LOG(ERR, "cannot alloc default IG exact match table"); 2902 goto error_counters; 2903 } 2904 fm->default_ig_fet->ref = 1; 2905 rc = enic_fet_alloc(fm, 0, NULL, 128, &fm->default_eg_fet); 2906 if (rc) { 2907 ENICPMD_LOG(ERR, "cannot alloc default EG exact match table"); 2908 goto error_ig_fet; 2909 } 2910 fm->default_eg_fet->ref = 1; 2911 fm->vf_rep_tag = FM_VF_REP_TAG; 2912 enic->fm = fm; 2913 return 0; 2914 2915 error_ig_fet: 2916 enic_fet_free(fm, fm->default_ig_fet); 2917 error_counters: 2918 enic_fm_free_all_counters(fm); 2919 error_tables: 2920 enic_fm_free_tcam_tables(fm); 2921 error_cmd: 2922 enic_free_consistent(enic, sizeof(union enic_flowman_cmd_mem), 2923 fm->cmd.va, fm->cmd.pa); 2924 error_fm: 2925 free(fm); 2926 return rc; 2927 } 2928 2929 void 2930 enic_fm_destroy(struct enic *enic) 2931 { 2932 struct enic_flowman *fm; 2933 struct enic_fm_fet *fet; 2934 2935 ENICPMD_FUNC_TRACE(); 2936 if (enic_is_vf_rep(enic)) { 2937 delete_rep_flows(enic); 2938 return; 2939 } 2940 if (enic->fm == NULL) 2941 return; 2942 fm = enic->fm; 2943 enic_fm_flow_flush(enic->rte_dev, NULL); 2944 enic_fet_free(fm, fm->default_eg_fet); 2945 enic_fet_free(fm, fm->default_ig_fet); 2946 /* Free all exact match tables still open */ 2947 while (!TAILQ_EMPTY(&fm->fet_list)) { 2948 fet = TAILQ_FIRST(&fm->fet_list); 2949 enic_fet_free(fm, fet); 2950 } 2951 enic_fm_free_tcam_tables(fm); 2952 enic_fm_free_all_counters(fm); 2953 rte_hash_free(fm->action_hash); 2954 enic_free_consistent(enic, sizeof(union enic_flowman_cmd_mem), 2955 fm->cmd.va, fm->cmd.pa); 2956 fm->cmd.va = NULL; 2957 free(fm); 2958 enic->fm = NULL; 2959 } 2960 2961 int 2962 enic_fm_allocate_switch_domain(struct enic *pf) 2963 { 2964 const struct rte_pci_addr *cur_a, *prev_a; 2965 struct rte_eth_dev *dev; 2966 struct enic *cur, *prev; 2967 uint16_t domain_id; 2968 uint64_t vnic_h; 2969 uint16_t pid; 2970 int ret; 2971 2972 ENICPMD_FUNC_TRACE(); 2973 if (enic_is_vf_rep(pf)) 2974 return -EINVAL; 2975 cur = pf; 2976 cur_a = &RTE_ETH_DEV_TO_PCI(cur->rte_dev)->addr; 2977 /* Go through ports and find another PF that is on the same adapter */ 2978 RTE_ETH_FOREACH_DEV(pid) { 2979 dev = &rte_eth_devices[pid]; 2980 if (!dev_is_enic(dev)) 2981 continue; 2982 if (dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) 2983 continue; 2984 if (dev == cur->rte_dev) 2985 continue; 2986 /* dev is another PF. Is it on the same adapter? */ 2987 prev = pmd_priv(dev); 2988 prev_a = &RTE_ETH_DEV_TO_PCI(dev)->addr; 2989 if (!enic_fm_find_vnic(cur, prev_a, &vnic_h)) { 2990 ENICPMD_LOG(DEBUG, "Port %u (PF BDF %x:%x:%x) and port %u (PF BDF %x:%x:%x domain %u) are on the same VIC", 2991 cur->rte_dev->data->port_id, 2992 cur_a->bus, cur_a->devid, cur_a->function, 2993 dev->data->port_id, 2994 prev_a->bus, prev_a->devid, prev_a->function, 2995 prev->switch_domain_id); 2996 cur->switch_domain_id = prev->switch_domain_id; 2997 return 0; 2998 } 2999 } 3000 ret = rte_eth_switch_domain_alloc(&domain_id); 3001 if (ret) { 3002 ENICPMD_LOG(WARNING, "failed to allocate switch domain for device %d", 3003 ret); 3004 } 3005 cur->switch_domain_id = domain_id; 3006 ENICPMD_LOG(DEBUG, "Port %u (PF BDF %x:%x:%x) is the 1st PF on the VIC. Allocated switch domain id %u", 3007 cur->rte_dev->data->port_id, 3008 cur_a->bus, cur_a->devid, cur_a->function, 3009 domain_id); 3010 return ret; 3011 } 3012 3013 const struct rte_flow_ops enic_fm_flow_ops = { 3014 .validate = enic_fm_flow_validate, 3015 .create = enic_fm_flow_create, 3016 .destroy = enic_fm_flow_destroy, 3017 .flush = enic_fm_flow_flush, 3018 .query = enic_fm_flow_query, 3019 }; 3020 3021 /* Add a high priority flow that loops representor packets to VF */ 3022 int 3023 enic_fm_add_rep2vf_flow(struct enic_vf_representor *vf) 3024 { 3025 struct fm_tcam_match_entry *fm_tcam_entry; 3026 struct rte_flow *flow0, *flow1; 3027 struct fm_action *fm_action; 3028 struct rte_flow_error error; 3029 struct rte_flow_attr attrs; 3030 struct fm_action_op fm_op; 3031 struct enic_flowman *fm; 3032 struct enic *pf; 3033 uint8_t tag; 3034 3035 pf = vf->pf; 3036 fm = pf->fm; 3037 tag = fm->vf_rep_tag; 3038 enic_fm_open_scratch(fm); 3039 fm_tcam_entry = &fm->tcam_entry; 3040 fm_action = &fm->action; 3041 /* Egress rule: match WQ ID and tag+hairpin */ 3042 fm_tcam_entry->ftm_data.fk_wq_id = vf->pf_wq_idx; 3043 fm_tcam_entry->ftm_mask.fk_wq_id = 0xffff; 3044 fm_tcam_entry->ftm_flags |= FMEF_COUNTER; 3045 memset(&fm_op, 0, sizeof(fm_op)); 3046 fm_op.fa_op = FMOP_TAG; 3047 fm_op.tag.tag = tag; 3048 enic_fm_append_action_op(fm, &fm_op, &error); 3049 memset(&fm_op, 0, sizeof(fm_op)); 3050 fm_op.fa_op = FMOP_EG_HAIRPIN; 3051 enic_fm_append_action_op(fm, &fm_op, &error); 3052 memset(&fm_op, 0, sizeof(fm_op)); 3053 fm_op.fa_op = FMOP_END; 3054 enic_fm_append_action_op(fm, &fm_op, &error); 3055 attrs.group = 0; 3056 attrs.ingress = 0; 3057 attrs.egress = 1; 3058 attrs.priority = FM_HIGHEST_PRIORITY; 3059 flow0 = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action, 3060 &attrs, &error); 3061 enic_fm_close_scratch(fm); 3062 if (flow0 == NULL) { 3063 ENICPMD_LOG(ERR, "Cannot create flow 0 for representor->VF"); 3064 return -EINVAL; 3065 } 3066 LIST_INSERT_HEAD(&pf->flows, flow0, next); 3067 /* Make this flow internal, so the user app cannot delete it */ 3068 flow0->internal = 1; 3069 ENICPMD_LOG(DEBUG, "representor->VF %d flow created: wq %d -> tag %d hairpin", 3070 vf->vf_id, vf->pf_wq_idx, tag); 3071 3072 /* Ingress: steer hairpinned to VF RQ 0 */ 3073 enic_fm_open_scratch(fm); 3074 fm_tcam_entry->ftm_flags |= FMEF_COUNTER; 3075 fm_tcam_entry->ftm_data.fk_hdrset[0].fk_metadata |= FKM_EG_HAIRPINNED; 3076 fm_tcam_entry->ftm_mask.fk_hdrset[0].fk_metadata |= FKM_EG_HAIRPINNED; 3077 fm_tcam_entry->ftm_data.fk_packet_tag = tag; 3078 fm_tcam_entry->ftm_mask.fk_packet_tag = 0xff; 3079 memset(&fm_op, 0, sizeof(fm_op)); 3080 fm_op.fa_op = FMOP_RQ_STEER; 3081 fm_op.rq_steer.rq_index = 0; 3082 fm_op.rq_steer.vnic_handle = vf->enic.fm_vnic_handle; 3083 enic_fm_append_action_op(fm, &fm_op, &error); 3084 memset(&fm_op, 0, sizeof(fm_op)); 3085 fm_op.fa_op = FMOP_END; 3086 enic_fm_append_action_op(fm, &fm_op, &error); 3087 attrs.group = 0; 3088 attrs.ingress = 1; 3089 attrs.egress = 0; 3090 attrs.priority = FM_HIGHEST_PRIORITY; 3091 flow1 = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action, 3092 &attrs, &error); 3093 enic_fm_close_scratch(fm); 3094 if (flow1 == NULL) { 3095 ENICPMD_LOG(ERR, "Cannot create flow 1 for representor->VF"); 3096 enic_fm_flow_destroy(pf->rte_dev, flow0, &error); 3097 return -EINVAL; 3098 } 3099 LIST_INSERT_HEAD(&pf->flows, flow1, next); 3100 flow1->internal = 1; 3101 ENICPMD_LOG(DEBUG, "representor->VF %d flow created: tag %d hairpinned -> VF RQ %d", 3102 vf->vf_id, tag, fm_op.rq_steer.rq_index); 3103 vf->rep2vf_flow[0] = flow0; 3104 vf->rep2vf_flow[1] = flow1; 3105 /* Done with this tag, use a different one next time */ 3106 fm->vf_rep_tag++; 3107 return 0; 3108 } 3109 3110 /* 3111 * Add a low priority flow that matches all packets from VF and loops them 3112 * back to the representor. 3113 */ 3114 int 3115 enic_fm_add_vf2rep_flow(struct enic_vf_representor *vf) 3116 { 3117 struct fm_tcam_match_entry *fm_tcam_entry; 3118 struct rte_flow *flow0, *flow1; 3119 struct fm_action *fm_action; 3120 struct rte_flow_error error; 3121 struct rte_flow_attr attrs; 3122 struct fm_action_op fm_op; 3123 struct enic_flowman *fm; 3124 struct enic *pf; 3125 uint8_t tag; 3126 3127 pf = vf->pf; 3128 fm = pf->fm; 3129 tag = fm->vf_rep_tag; 3130 enic_fm_open_scratch(fm); 3131 fm_tcam_entry = &fm->tcam_entry; 3132 fm_action = &fm->action; 3133 /* Egress rule: match-any and tag+hairpin */ 3134 fm_tcam_entry->ftm_data.fk_wq_id = 0; 3135 fm_tcam_entry->ftm_mask.fk_wq_id = 0xffff; 3136 fm_tcam_entry->ftm_data.fk_wq_vnic = vf->enic.fm_vnic_handle; 3137 fm_tcam_entry->ftm_flags |= FMEF_COUNTER; 3138 memset(&fm_op, 0, sizeof(fm_op)); 3139 fm_op.fa_op = FMOP_TAG; 3140 fm_op.tag.tag = tag; 3141 enic_fm_append_action_op(fm, &fm_op, &error); 3142 memset(&fm_op, 0, sizeof(fm_op)); 3143 fm_op.fa_op = FMOP_EG_HAIRPIN; 3144 enic_fm_append_action_op(fm, &fm_op, &error); 3145 memset(&fm_op, 0, sizeof(fm_op)); 3146 fm_op.fa_op = FMOP_END; 3147 enic_fm_append_action_op(fm, &fm_op, &error); 3148 attrs.group = 0; 3149 attrs.ingress = 0; 3150 attrs.egress = 1; 3151 attrs.priority = FM_LOWEST_PRIORITY; 3152 flow0 = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action, 3153 &attrs, &error); 3154 enic_fm_close_scratch(fm); 3155 if (flow0 == NULL) { 3156 ENICPMD_LOG(ERR, "Cannot create flow 0 for VF->representor"); 3157 return -EINVAL; 3158 } 3159 LIST_INSERT_HEAD(&pf->flows, flow0, next); 3160 /* Make this flow internal, so the user app cannot delete it */ 3161 flow0->internal = 1; 3162 ENICPMD_LOG(DEBUG, "VF %d->representor flow created: wq %d (low prio) -> tag %d hairpin", 3163 vf->vf_id, fm_tcam_entry->ftm_data.fk_wq_id, tag); 3164 3165 /* Ingress: steer hairpinned to VF rep RQ */ 3166 enic_fm_open_scratch(fm); 3167 fm_tcam_entry->ftm_flags |= FMEF_COUNTER; 3168 fm_tcam_entry->ftm_data.fk_hdrset[0].fk_metadata |= FKM_EG_HAIRPINNED; 3169 fm_tcam_entry->ftm_mask.fk_hdrset[0].fk_metadata |= FKM_EG_HAIRPINNED; 3170 fm_tcam_entry->ftm_data.fk_packet_tag = tag; 3171 fm_tcam_entry->ftm_mask.fk_packet_tag = 0xff; 3172 memset(&fm_op, 0, sizeof(fm_op)); 3173 fm_op.fa_op = FMOP_RQ_STEER; 3174 fm_op.rq_steer.rq_index = vf->pf_rq_sop_idx; 3175 fm_op.rq_steer.vnic_handle = pf->fm_vnic_handle; 3176 enic_fm_append_action_op(fm, &fm_op, &error); 3177 memset(&fm_op, 0, sizeof(fm_op)); 3178 fm_op.fa_op = FMOP_END; 3179 enic_fm_append_action_op(fm, &fm_op, &error); 3180 attrs.group = 0; 3181 attrs.ingress = 1; 3182 attrs.egress = 0; 3183 attrs.priority = FM_HIGHEST_PRIORITY; 3184 flow1 = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action, 3185 &attrs, &error); 3186 enic_fm_close_scratch(fm); 3187 if (flow1 == NULL) { 3188 ENICPMD_LOG(ERR, "Cannot create flow 1 for VF->representor"); 3189 enic_fm_flow_destroy(pf->rte_dev, flow0, &error); 3190 return -EINVAL; 3191 } 3192 LIST_INSERT_HEAD(&pf->flows, flow1, next); 3193 flow1->internal = 1; 3194 ENICPMD_LOG(DEBUG, "VF %d->representor flow created: tag %d hairpinned -> PF RQ %d", 3195 vf->vf_id, tag, vf->pf_rq_sop_idx); 3196 vf->vf2rep_flow[0] = flow0; 3197 vf->vf2rep_flow[1] = flow1; 3198 /* Done with this tag, use a different one next time */ 3199 fm->vf_rep_tag++; 3200 return 0; 3201 } 3202 3203 /* Destroy representor flows created by enic_fm_add_{rep2vf,vf2rep}_flow */ 3204 static void 3205 delete_rep_flows(struct enic *enic) 3206 { 3207 struct enic_vf_representor *vf; 3208 struct rte_flow_error error; 3209 struct rte_eth_dev *dev; 3210 uint32_t i; 3211 3212 RTE_ASSERT(enic_is_vf_rep(enic)); 3213 vf = VF_ENIC_TO_VF_REP(enic); 3214 dev = vf->pf->rte_dev; 3215 for (i = 0; i < ARRAY_SIZE(vf->vf2rep_flow); i++) { 3216 if (vf->vf2rep_flow[i]) 3217 enic_fm_flow_destroy(dev, vf->vf2rep_flow[i], &error); 3218 } 3219 for (i = 0; i < ARRAY_SIZE(vf->rep2vf_flow); i++) { 3220 if (vf->rep2vf_flow[i]) 3221 enic_fm_flow_destroy(dev, vf->rep2vf_flow[i], &error); 3222 } 3223 } 3224 3225 static struct enic_flowman * 3226 begin_fm(struct enic *enic) 3227 { 3228 struct enic_vf_representor *vf; 3229 struct enic_flowman *fm; 3230 3231 /* Representor uses PF flowman */ 3232 if (enic_is_vf_rep(enic)) { 3233 vf = VF_ENIC_TO_VF_REP(enic); 3234 fm = vf->pf->fm; 3235 } else { 3236 fm = enic->fm; 3237 } 3238 /* Save the API caller and lock if representors exist */ 3239 if (fm) { 3240 if (fm->owner_enic->switchdev_mode) 3241 rte_spinlock_lock(&fm->lock); 3242 fm->user_enic = enic; 3243 } 3244 return fm; 3245 } 3246 3247 static void 3248 end_fm(struct enic_flowman *fm) 3249 { 3250 fm->user_enic = NULL; 3251 if (fm->owner_enic->switchdev_mode) 3252 rte_spinlock_unlock(&fm->lock); 3253 } 3254