1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018 Mellanox Technologies, Ltd 3 */ 4 5 #include <sys/queue.h> 6 #include <stdalign.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include <rte_common.h> 12 #include <rte_ether.h> 13 #include <ethdev_driver.h> 14 #include <rte_flow.h> 15 #include <rte_flow_driver.h> 16 #include <rte_malloc.h> 17 #include <rte_cycles.h> 18 #include <rte_ip.h> 19 #include <rte_gre.h> 20 #include <rte_vxlan.h> 21 #include <rte_gtp.h> 22 #include <rte_eal_paging.h> 23 #include <rte_mpls.h> 24 25 #include <mlx5_glue.h> 26 #include <mlx5_devx_cmds.h> 27 #include <mlx5_prm.h> 28 #include <mlx5_malloc.h> 29 30 #include "mlx5_defs.h" 31 #include "mlx5.h" 32 #include "mlx5_common_os.h" 33 #include "mlx5_flow.h" 34 #include "mlx5_flow_os.h" 35 #include "mlx5_rxtx.h" 36 #include "rte_pmd_mlx5.h" 37 38 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H) 39 40 #ifndef HAVE_IBV_FLOW_DEVX_COUNTERS 41 #define MLX5DV_FLOW_ACTION_COUNTERS_DEVX 0 42 #endif 43 44 #ifndef HAVE_MLX5DV_DR_ESWITCH 45 #ifndef MLX5DV_FLOW_TABLE_TYPE_FDB 46 #define MLX5DV_FLOW_TABLE_TYPE_FDB 0 47 #endif 48 #endif 49 50 #ifndef HAVE_MLX5DV_DR 51 #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1 52 #endif 53 54 /* VLAN header definitions */ 55 #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13 56 #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT) 57 #define MLX5DV_FLOW_VLAN_VID_MASK 0x0fff 58 #define MLX5DV_FLOW_VLAN_PCP_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK) 59 #define MLX5DV_FLOW_VLAN_VID_MASK_BE RTE_BE16(MLX5DV_FLOW_VLAN_VID_MASK) 60 61 union flow_dv_attr { 62 struct { 63 uint32_t valid:1; 64 uint32_t ipv4:1; 65 uint32_t ipv6:1; 66 uint32_t tcp:1; 67 uint32_t udp:1; 68 uint32_t reserved:27; 69 }; 70 uint32_t attr; 71 }; 72 73 static int 74 flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh, 75 struct mlx5_flow_tbl_resource *tbl); 76 77 static int 78 flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev, 79 uint32_t encap_decap_idx); 80 81 static int 82 flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev, 83 uint32_t port_id); 84 static void 85 flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss); 86 87 static int 88 flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev, 89 uint32_t rix_jump); 90 91 /** 92 * Initialize flow attributes structure according to flow items' types. 93 * 94 * flow_dv_validate() avoids multiple L3/L4 layers cases other than tunnel 95 * mode. For tunnel mode, the items to be modified are the outermost ones. 96 * 97 * @param[in] item 98 * Pointer to item specification. 99 * @param[out] attr 100 * Pointer to flow attributes structure. 101 * @param[in] dev_flow 102 * Pointer to the sub flow. 103 * @param[in] tunnel_decap 104 * Whether action is after tunnel decapsulation. 105 */ 106 static void 107 flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr, 108 struct mlx5_flow *dev_flow, bool tunnel_decap) 109 { 110 uint64_t layers = dev_flow->handle->layers; 111 112 /* 113 * If layers is already initialized, it means this dev_flow is the 114 * suffix flow, the layers flags is set by the prefix flow. Need to 115 * use the layer flags from prefix flow as the suffix flow may not 116 * have the user defined items as the flow is split. 117 */ 118 if (layers) { 119 if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV4) 120 attr->ipv4 = 1; 121 else if (layers & MLX5_FLOW_LAYER_OUTER_L3_IPV6) 122 attr->ipv6 = 1; 123 if (layers & MLX5_FLOW_LAYER_OUTER_L4_TCP) 124 attr->tcp = 1; 125 else if (layers & MLX5_FLOW_LAYER_OUTER_L4_UDP) 126 attr->udp = 1; 127 attr->valid = 1; 128 return; 129 } 130 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 131 uint8_t next_protocol = 0xff; 132 switch (item->type) { 133 case RTE_FLOW_ITEM_TYPE_GRE: 134 case RTE_FLOW_ITEM_TYPE_NVGRE: 135 case RTE_FLOW_ITEM_TYPE_VXLAN: 136 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 137 case RTE_FLOW_ITEM_TYPE_GENEVE: 138 case RTE_FLOW_ITEM_TYPE_MPLS: 139 if (tunnel_decap) 140 attr->attr = 0; 141 break; 142 case RTE_FLOW_ITEM_TYPE_IPV4: 143 if (!attr->ipv6) 144 attr->ipv4 = 1; 145 if (item->mask != NULL && 146 ((const struct rte_flow_item_ipv4 *) 147 item->mask)->hdr.next_proto_id) 148 next_protocol = 149 ((const struct rte_flow_item_ipv4 *) 150 (item->spec))->hdr.next_proto_id & 151 ((const struct rte_flow_item_ipv4 *) 152 (item->mask))->hdr.next_proto_id; 153 if ((next_protocol == IPPROTO_IPIP || 154 next_protocol == IPPROTO_IPV6) && tunnel_decap) 155 attr->attr = 0; 156 break; 157 case RTE_FLOW_ITEM_TYPE_IPV6: 158 if (!attr->ipv4) 159 attr->ipv6 = 1; 160 if (item->mask != NULL && 161 ((const struct rte_flow_item_ipv6 *) 162 item->mask)->hdr.proto) 163 next_protocol = 164 ((const struct rte_flow_item_ipv6 *) 165 (item->spec))->hdr.proto & 166 ((const struct rte_flow_item_ipv6 *) 167 (item->mask))->hdr.proto; 168 if ((next_protocol == IPPROTO_IPIP || 169 next_protocol == IPPROTO_IPV6) && tunnel_decap) 170 attr->attr = 0; 171 break; 172 case RTE_FLOW_ITEM_TYPE_UDP: 173 if (!attr->tcp) 174 attr->udp = 1; 175 break; 176 case RTE_FLOW_ITEM_TYPE_TCP: 177 if (!attr->udp) 178 attr->tcp = 1; 179 break; 180 default: 181 break; 182 } 183 } 184 attr->valid = 1; 185 } 186 187 /** 188 * Convert rte_mtr_color to mlx5 color. 189 * 190 * @param[in] rcol 191 * rte_mtr_color. 192 * 193 * @return 194 * mlx5 color. 195 */ 196 static int 197 rte_col_2_mlx5_col(enum rte_color rcol) 198 { 199 switch (rcol) { 200 case RTE_COLOR_GREEN: 201 return MLX5_FLOW_COLOR_GREEN; 202 case RTE_COLOR_YELLOW: 203 return MLX5_FLOW_COLOR_YELLOW; 204 case RTE_COLOR_RED: 205 return MLX5_FLOW_COLOR_RED; 206 default: 207 break; 208 } 209 return MLX5_FLOW_COLOR_UNDEFINED; 210 } 211 212 struct field_modify_info { 213 uint32_t size; /* Size of field in protocol header, in bytes. */ 214 uint32_t offset; /* Offset of field in protocol header, in bytes. */ 215 enum mlx5_modification_field id; 216 }; 217 218 struct field_modify_info modify_eth[] = { 219 {4, 0, MLX5_MODI_OUT_DMAC_47_16}, 220 {2, 4, MLX5_MODI_OUT_DMAC_15_0}, 221 {4, 6, MLX5_MODI_OUT_SMAC_47_16}, 222 {2, 10, MLX5_MODI_OUT_SMAC_15_0}, 223 {0, 0, 0}, 224 }; 225 226 struct field_modify_info modify_vlan_out_first_vid[] = { 227 /* Size in bits !!! */ 228 {12, 0, MLX5_MODI_OUT_FIRST_VID}, 229 {0, 0, 0}, 230 }; 231 232 struct field_modify_info modify_ipv4[] = { 233 {1, 1, MLX5_MODI_OUT_IP_DSCP}, 234 {1, 8, MLX5_MODI_OUT_IPV4_TTL}, 235 {4, 12, MLX5_MODI_OUT_SIPV4}, 236 {4, 16, MLX5_MODI_OUT_DIPV4}, 237 {0, 0, 0}, 238 }; 239 240 struct field_modify_info modify_ipv6[] = { 241 {1, 0, MLX5_MODI_OUT_IP_DSCP}, 242 {1, 7, MLX5_MODI_OUT_IPV6_HOPLIMIT}, 243 {4, 8, MLX5_MODI_OUT_SIPV6_127_96}, 244 {4, 12, MLX5_MODI_OUT_SIPV6_95_64}, 245 {4, 16, MLX5_MODI_OUT_SIPV6_63_32}, 246 {4, 20, MLX5_MODI_OUT_SIPV6_31_0}, 247 {4, 24, MLX5_MODI_OUT_DIPV6_127_96}, 248 {4, 28, MLX5_MODI_OUT_DIPV6_95_64}, 249 {4, 32, MLX5_MODI_OUT_DIPV6_63_32}, 250 {4, 36, MLX5_MODI_OUT_DIPV6_31_0}, 251 {0, 0, 0}, 252 }; 253 254 struct field_modify_info modify_udp[] = { 255 {2, 0, MLX5_MODI_OUT_UDP_SPORT}, 256 {2, 2, MLX5_MODI_OUT_UDP_DPORT}, 257 {0, 0, 0}, 258 }; 259 260 struct field_modify_info modify_tcp[] = { 261 {2, 0, MLX5_MODI_OUT_TCP_SPORT}, 262 {2, 2, MLX5_MODI_OUT_TCP_DPORT}, 263 {4, 4, MLX5_MODI_OUT_TCP_SEQ_NUM}, 264 {4, 8, MLX5_MODI_OUT_TCP_ACK_NUM}, 265 {0, 0, 0}, 266 }; 267 268 static void 269 mlx5_flow_tunnel_ip_check(const struct rte_flow_item *item __rte_unused, 270 uint8_t next_protocol, uint64_t *item_flags, 271 int *tunnel) 272 { 273 MLX5_ASSERT(item->type == RTE_FLOW_ITEM_TYPE_IPV4 || 274 item->type == RTE_FLOW_ITEM_TYPE_IPV6); 275 if (next_protocol == IPPROTO_IPIP) { 276 *item_flags |= MLX5_FLOW_LAYER_IPIP; 277 *tunnel = 1; 278 } 279 if (next_protocol == IPPROTO_IPV6) { 280 *item_flags |= MLX5_FLOW_LAYER_IPV6_ENCAP; 281 *tunnel = 1; 282 } 283 } 284 285 /* Update VLAN's VID/PCP based on input rte_flow_action. 286 * 287 * @param[in] action 288 * Pointer to struct rte_flow_action. 289 * @param[out] vlan 290 * Pointer to struct rte_vlan_hdr. 291 */ 292 static void 293 mlx5_update_vlan_vid_pcp(const struct rte_flow_action *action, 294 struct rte_vlan_hdr *vlan) 295 { 296 uint16_t vlan_tci; 297 if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) { 298 vlan_tci = 299 ((const struct rte_flow_action_of_set_vlan_pcp *) 300 action->conf)->vlan_pcp; 301 vlan_tci = vlan_tci << MLX5DV_FLOW_VLAN_PCP_SHIFT; 302 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK; 303 vlan->vlan_tci |= vlan_tci; 304 } else if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) { 305 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK; 306 vlan->vlan_tci |= rte_be_to_cpu_16 307 (((const struct rte_flow_action_of_set_vlan_vid *) 308 action->conf)->vlan_vid); 309 } 310 } 311 312 /** 313 * Fetch 1, 2, 3 or 4 byte field from the byte array 314 * and return as unsigned integer in host-endian format. 315 * 316 * @param[in] data 317 * Pointer to data array. 318 * @param[in] size 319 * Size of field to extract. 320 * 321 * @return 322 * converted field in host endian format. 323 */ 324 static inline uint32_t 325 flow_dv_fetch_field(const uint8_t *data, uint32_t size) 326 { 327 uint32_t ret; 328 329 switch (size) { 330 case 1: 331 ret = *data; 332 break; 333 case 2: 334 ret = rte_be_to_cpu_16(*(const unaligned_uint16_t *)data); 335 break; 336 case 3: 337 ret = rte_be_to_cpu_16(*(const unaligned_uint16_t *)data); 338 ret = (ret << 8) | *(data + sizeof(uint16_t)); 339 break; 340 case 4: 341 ret = rte_be_to_cpu_32(*(const unaligned_uint32_t *)data); 342 break; 343 default: 344 MLX5_ASSERT(false); 345 ret = 0; 346 break; 347 } 348 return ret; 349 } 350 351 /** 352 * Convert modify-header action to DV specification. 353 * 354 * Data length of each action is determined by provided field description 355 * and the item mask. Data bit offset and width of each action is determined 356 * by provided item mask. 357 * 358 * @param[in] item 359 * Pointer to item specification. 360 * @param[in] field 361 * Pointer to field modification information. 362 * For MLX5_MODIFICATION_TYPE_SET specifies destination field. 363 * For MLX5_MODIFICATION_TYPE_ADD specifies destination field. 364 * For MLX5_MODIFICATION_TYPE_COPY specifies source field. 365 * @param[in] dcopy 366 * Destination field info for MLX5_MODIFICATION_TYPE_COPY in @type. 367 * Negative offset value sets the same offset as source offset. 368 * size field is ignored, value is taken from source field. 369 * @param[in,out] resource 370 * Pointer to the modify-header resource. 371 * @param[in] type 372 * Type of modification. 373 * @param[out] error 374 * Pointer to the error structure. 375 * 376 * @return 377 * 0 on success, a negative errno value otherwise and rte_errno is set. 378 */ 379 static int 380 flow_dv_convert_modify_action(struct rte_flow_item *item, 381 struct field_modify_info *field, 382 struct field_modify_info *dcopy, 383 struct mlx5_flow_dv_modify_hdr_resource *resource, 384 uint32_t type, struct rte_flow_error *error) 385 { 386 uint32_t i = resource->actions_num; 387 struct mlx5_modification_cmd *actions = resource->actions; 388 389 /* 390 * The item and mask are provided in big-endian format. 391 * The fields should be presented as in big-endian format either. 392 * Mask must be always present, it defines the actual field width. 393 */ 394 MLX5_ASSERT(item->mask); 395 MLX5_ASSERT(field->size); 396 do { 397 unsigned int size_b; 398 unsigned int off_b; 399 uint32_t mask; 400 uint32_t data; 401 402 if (i >= MLX5_MAX_MODIFY_NUM) 403 return rte_flow_error_set(error, EINVAL, 404 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 405 "too many items to modify"); 406 /* Fetch variable byte size mask from the array. */ 407 mask = flow_dv_fetch_field((const uint8_t *)item->mask + 408 field->offset, field->size); 409 if (!mask) { 410 ++field; 411 continue; 412 } 413 /* Deduce actual data width in bits from mask value. */ 414 off_b = rte_bsf32(mask); 415 size_b = sizeof(uint32_t) * CHAR_BIT - 416 off_b - __builtin_clz(mask); 417 MLX5_ASSERT(size_b); 418 size_b = size_b == sizeof(uint32_t) * CHAR_BIT ? 0 : size_b; 419 actions[i] = (struct mlx5_modification_cmd) { 420 .action_type = type, 421 .field = field->id, 422 .offset = off_b, 423 .length = size_b, 424 }; 425 /* Convert entire record to expected big-endian format. */ 426 actions[i].data0 = rte_cpu_to_be_32(actions[i].data0); 427 if (type == MLX5_MODIFICATION_TYPE_COPY) { 428 MLX5_ASSERT(dcopy); 429 actions[i].dst_field = dcopy->id; 430 actions[i].dst_offset = 431 (int)dcopy->offset < 0 ? off_b : dcopy->offset; 432 /* Convert entire record to big-endian format. */ 433 actions[i].data1 = rte_cpu_to_be_32(actions[i].data1); 434 ++dcopy; 435 } else { 436 MLX5_ASSERT(item->spec); 437 data = flow_dv_fetch_field((const uint8_t *)item->spec + 438 field->offset, field->size); 439 /* Shift out the trailing masked bits from data. */ 440 data = (data & mask) >> off_b; 441 actions[i].data1 = rte_cpu_to_be_32(data); 442 } 443 ++i; 444 ++field; 445 } while (field->size); 446 if (resource->actions_num == i) 447 return rte_flow_error_set(error, EINVAL, 448 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 449 "invalid modification flow item"); 450 resource->actions_num = i; 451 return 0; 452 } 453 454 /** 455 * Convert modify-header set IPv4 address action to DV specification. 456 * 457 * @param[in,out] resource 458 * Pointer to the modify-header resource. 459 * @param[in] action 460 * Pointer to action specification. 461 * @param[out] error 462 * Pointer to the error structure. 463 * 464 * @return 465 * 0 on success, a negative errno value otherwise and rte_errno is set. 466 */ 467 static int 468 flow_dv_convert_action_modify_ipv4 469 (struct mlx5_flow_dv_modify_hdr_resource *resource, 470 const struct rte_flow_action *action, 471 struct rte_flow_error *error) 472 { 473 const struct rte_flow_action_set_ipv4 *conf = 474 (const struct rte_flow_action_set_ipv4 *)(action->conf); 475 struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 }; 476 struct rte_flow_item_ipv4 ipv4; 477 struct rte_flow_item_ipv4 ipv4_mask; 478 479 memset(&ipv4, 0, sizeof(ipv4)); 480 memset(&ipv4_mask, 0, sizeof(ipv4_mask)); 481 if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC) { 482 ipv4.hdr.src_addr = conf->ipv4_addr; 483 ipv4_mask.hdr.src_addr = rte_flow_item_ipv4_mask.hdr.src_addr; 484 } else { 485 ipv4.hdr.dst_addr = conf->ipv4_addr; 486 ipv4_mask.hdr.dst_addr = rte_flow_item_ipv4_mask.hdr.dst_addr; 487 } 488 item.spec = &ipv4; 489 item.mask = &ipv4_mask; 490 return flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource, 491 MLX5_MODIFICATION_TYPE_SET, error); 492 } 493 494 /** 495 * Convert modify-header set IPv6 address action to DV specification. 496 * 497 * @param[in,out] resource 498 * Pointer to the modify-header resource. 499 * @param[in] action 500 * Pointer to action specification. 501 * @param[out] error 502 * Pointer to the error structure. 503 * 504 * @return 505 * 0 on success, a negative errno value otherwise and rte_errno is set. 506 */ 507 static int 508 flow_dv_convert_action_modify_ipv6 509 (struct mlx5_flow_dv_modify_hdr_resource *resource, 510 const struct rte_flow_action *action, 511 struct rte_flow_error *error) 512 { 513 const struct rte_flow_action_set_ipv6 *conf = 514 (const struct rte_flow_action_set_ipv6 *)(action->conf); 515 struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 }; 516 struct rte_flow_item_ipv6 ipv6; 517 struct rte_flow_item_ipv6 ipv6_mask; 518 519 memset(&ipv6, 0, sizeof(ipv6)); 520 memset(&ipv6_mask, 0, sizeof(ipv6_mask)); 521 if (action->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC) { 522 memcpy(&ipv6.hdr.src_addr, &conf->ipv6_addr, 523 sizeof(ipv6.hdr.src_addr)); 524 memcpy(&ipv6_mask.hdr.src_addr, 525 &rte_flow_item_ipv6_mask.hdr.src_addr, 526 sizeof(ipv6.hdr.src_addr)); 527 } else { 528 memcpy(&ipv6.hdr.dst_addr, &conf->ipv6_addr, 529 sizeof(ipv6.hdr.dst_addr)); 530 memcpy(&ipv6_mask.hdr.dst_addr, 531 &rte_flow_item_ipv6_mask.hdr.dst_addr, 532 sizeof(ipv6.hdr.dst_addr)); 533 } 534 item.spec = &ipv6; 535 item.mask = &ipv6_mask; 536 return flow_dv_convert_modify_action(&item, modify_ipv6, NULL, resource, 537 MLX5_MODIFICATION_TYPE_SET, error); 538 } 539 540 /** 541 * Convert modify-header set MAC address action to DV specification. 542 * 543 * @param[in,out] resource 544 * Pointer to the modify-header resource. 545 * @param[in] action 546 * Pointer to action specification. 547 * @param[out] error 548 * Pointer to the error structure. 549 * 550 * @return 551 * 0 on success, a negative errno value otherwise and rte_errno is set. 552 */ 553 static int 554 flow_dv_convert_action_modify_mac 555 (struct mlx5_flow_dv_modify_hdr_resource *resource, 556 const struct rte_flow_action *action, 557 struct rte_flow_error *error) 558 { 559 const struct rte_flow_action_set_mac *conf = 560 (const struct rte_flow_action_set_mac *)(action->conf); 561 struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_ETH }; 562 struct rte_flow_item_eth eth; 563 struct rte_flow_item_eth eth_mask; 564 565 memset(ð, 0, sizeof(eth)); 566 memset(ð_mask, 0, sizeof(eth_mask)); 567 if (action->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC) { 568 memcpy(ð.src.addr_bytes, &conf->mac_addr, 569 sizeof(eth.src.addr_bytes)); 570 memcpy(ð_mask.src.addr_bytes, 571 &rte_flow_item_eth_mask.src.addr_bytes, 572 sizeof(eth_mask.src.addr_bytes)); 573 } else { 574 memcpy(ð.dst.addr_bytes, &conf->mac_addr, 575 sizeof(eth.dst.addr_bytes)); 576 memcpy(ð_mask.dst.addr_bytes, 577 &rte_flow_item_eth_mask.dst.addr_bytes, 578 sizeof(eth_mask.dst.addr_bytes)); 579 } 580 item.spec = ð 581 item.mask = ð_mask; 582 return flow_dv_convert_modify_action(&item, modify_eth, NULL, resource, 583 MLX5_MODIFICATION_TYPE_SET, error); 584 } 585 586 /** 587 * Convert modify-header set VLAN VID action to DV specification. 588 * 589 * @param[in,out] resource 590 * Pointer to the modify-header resource. 591 * @param[in] action 592 * Pointer to action specification. 593 * @param[out] error 594 * Pointer to the error structure. 595 * 596 * @return 597 * 0 on success, a negative errno value otherwise and rte_errno is set. 598 */ 599 static int 600 flow_dv_convert_action_modify_vlan_vid 601 (struct mlx5_flow_dv_modify_hdr_resource *resource, 602 const struct rte_flow_action *action, 603 struct rte_flow_error *error) 604 { 605 const struct rte_flow_action_of_set_vlan_vid *conf = 606 (const struct rte_flow_action_of_set_vlan_vid *)(action->conf); 607 int i = resource->actions_num; 608 struct mlx5_modification_cmd *actions = resource->actions; 609 struct field_modify_info *field = modify_vlan_out_first_vid; 610 611 if (i >= MLX5_MAX_MODIFY_NUM) 612 return rte_flow_error_set(error, EINVAL, 613 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 614 "too many items to modify"); 615 actions[i] = (struct mlx5_modification_cmd) { 616 .action_type = MLX5_MODIFICATION_TYPE_SET, 617 .field = field->id, 618 .length = field->size, 619 .offset = field->offset, 620 }; 621 actions[i].data0 = rte_cpu_to_be_32(actions[i].data0); 622 actions[i].data1 = conf->vlan_vid; 623 actions[i].data1 = actions[i].data1 << 16; 624 resource->actions_num = ++i; 625 return 0; 626 } 627 628 /** 629 * Convert modify-header set TP action to DV specification. 630 * 631 * @param[in,out] resource 632 * Pointer to the modify-header resource. 633 * @param[in] action 634 * Pointer to action specification. 635 * @param[in] items 636 * Pointer to rte_flow_item objects list. 637 * @param[in] attr 638 * Pointer to flow attributes structure. 639 * @param[in] dev_flow 640 * Pointer to the sub flow. 641 * @param[in] tunnel_decap 642 * Whether action is after tunnel decapsulation. 643 * @param[out] error 644 * Pointer to the error structure. 645 * 646 * @return 647 * 0 on success, a negative errno value otherwise and rte_errno is set. 648 */ 649 static int 650 flow_dv_convert_action_modify_tp 651 (struct mlx5_flow_dv_modify_hdr_resource *resource, 652 const struct rte_flow_action *action, 653 const struct rte_flow_item *items, 654 union flow_dv_attr *attr, struct mlx5_flow *dev_flow, 655 bool tunnel_decap, struct rte_flow_error *error) 656 { 657 const struct rte_flow_action_set_tp *conf = 658 (const struct rte_flow_action_set_tp *)(action->conf); 659 struct rte_flow_item item; 660 struct rte_flow_item_udp udp; 661 struct rte_flow_item_udp udp_mask; 662 struct rte_flow_item_tcp tcp; 663 struct rte_flow_item_tcp tcp_mask; 664 struct field_modify_info *field; 665 666 if (!attr->valid) 667 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap); 668 if (attr->udp) { 669 memset(&udp, 0, sizeof(udp)); 670 memset(&udp_mask, 0, sizeof(udp_mask)); 671 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) { 672 udp.hdr.src_port = conf->port; 673 udp_mask.hdr.src_port = 674 rte_flow_item_udp_mask.hdr.src_port; 675 } else { 676 udp.hdr.dst_port = conf->port; 677 udp_mask.hdr.dst_port = 678 rte_flow_item_udp_mask.hdr.dst_port; 679 } 680 item.type = RTE_FLOW_ITEM_TYPE_UDP; 681 item.spec = &udp; 682 item.mask = &udp_mask; 683 field = modify_udp; 684 } else { 685 MLX5_ASSERT(attr->tcp); 686 memset(&tcp, 0, sizeof(tcp)); 687 memset(&tcp_mask, 0, sizeof(tcp_mask)); 688 if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) { 689 tcp.hdr.src_port = conf->port; 690 tcp_mask.hdr.src_port = 691 rte_flow_item_tcp_mask.hdr.src_port; 692 } else { 693 tcp.hdr.dst_port = conf->port; 694 tcp_mask.hdr.dst_port = 695 rte_flow_item_tcp_mask.hdr.dst_port; 696 } 697 item.type = RTE_FLOW_ITEM_TYPE_TCP; 698 item.spec = &tcp; 699 item.mask = &tcp_mask; 700 field = modify_tcp; 701 } 702 return flow_dv_convert_modify_action(&item, field, NULL, resource, 703 MLX5_MODIFICATION_TYPE_SET, error); 704 } 705 706 /** 707 * Convert modify-header set TTL action to DV specification. 708 * 709 * @param[in,out] resource 710 * Pointer to the modify-header resource. 711 * @param[in] action 712 * Pointer to action specification. 713 * @param[in] items 714 * Pointer to rte_flow_item objects list. 715 * @param[in] attr 716 * Pointer to flow attributes structure. 717 * @param[in] dev_flow 718 * Pointer to the sub flow. 719 * @param[in] tunnel_decap 720 * Whether action is after tunnel decapsulation. 721 * @param[out] error 722 * Pointer to the error structure. 723 * 724 * @return 725 * 0 on success, a negative errno value otherwise and rte_errno is set. 726 */ 727 static int 728 flow_dv_convert_action_modify_ttl 729 (struct mlx5_flow_dv_modify_hdr_resource *resource, 730 const struct rte_flow_action *action, 731 const struct rte_flow_item *items, 732 union flow_dv_attr *attr, struct mlx5_flow *dev_flow, 733 bool tunnel_decap, struct rte_flow_error *error) 734 { 735 const struct rte_flow_action_set_ttl *conf = 736 (const struct rte_flow_action_set_ttl *)(action->conf); 737 struct rte_flow_item item; 738 struct rte_flow_item_ipv4 ipv4; 739 struct rte_flow_item_ipv4 ipv4_mask; 740 struct rte_flow_item_ipv6 ipv6; 741 struct rte_flow_item_ipv6 ipv6_mask; 742 struct field_modify_info *field; 743 744 if (!attr->valid) 745 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap); 746 if (attr->ipv4) { 747 memset(&ipv4, 0, sizeof(ipv4)); 748 memset(&ipv4_mask, 0, sizeof(ipv4_mask)); 749 ipv4.hdr.time_to_live = conf->ttl_value; 750 ipv4_mask.hdr.time_to_live = 0xFF; 751 item.type = RTE_FLOW_ITEM_TYPE_IPV4; 752 item.spec = &ipv4; 753 item.mask = &ipv4_mask; 754 field = modify_ipv4; 755 } else { 756 MLX5_ASSERT(attr->ipv6); 757 memset(&ipv6, 0, sizeof(ipv6)); 758 memset(&ipv6_mask, 0, sizeof(ipv6_mask)); 759 ipv6.hdr.hop_limits = conf->ttl_value; 760 ipv6_mask.hdr.hop_limits = 0xFF; 761 item.type = RTE_FLOW_ITEM_TYPE_IPV6; 762 item.spec = &ipv6; 763 item.mask = &ipv6_mask; 764 field = modify_ipv6; 765 } 766 return flow_dv_convert_modify_action(&item, field, NULL, resource, 767 MLX5_MODIFICATION_TYPE_SET, error); 768 } 769 770 /** 771 * Convert modify-header decrement TTL action to DV specification. 772 * 773 * @param[in,out] resource 774 * Pointer to the modify-header resource. 775 * @param[in] action 776 * Pointer to action specification. 777 * @param[in] items 778 * Pointer to rte_flow_item objects list. 779 * @param[in] attr 780 * Pointer to flow attributes structure. 781 * @param[in] dev_flow 782 * Pointer to the sub flow. 783 * @param[in] tunnel_decap 784 * Whether action is after tunnel decapsulation. 785 * @param[out] error 786 * Pointer to the error structure. 787 * 788 * @return 789 * 0 on success, a negative errno value otherwise and rte_errno is set. 790 */ 791 static int 792 flow_dv_convert_action_modify_dec_ttl 793 (struct mlx5_flow_dv_modify_hdr_resource *resource, 794 const struct rte_flow_item *items, 795 union flow_dv_attr *attr, struct mlx5_flow *dev_flow, 796 bool tunnel_decap, struct rte_flow_error *error) 797 { 798 struct rte_flow_item item; 799 struct rte_flow_item_ipv4 ipv4; 800 struct rte_flow_item_ipv4 ipv4_mask; 801 struct rte_flow_item_ipv6 ipv6; 802 struct rte_flow_item_ipv6 ipv6_mask; 803 struct field_modify_info *field; 804 805 if (!attr->valid) 806 flow_dv_attr_init(items, attr, dev_flow, tunnel_decap); 807 if (attr->ipv4) { 808 memset(&ipv4, 0, sizeof(ipv4)); 809 memset(&ipv4_mask, 0, sizeof(ipv4_mask)); 810 ipv4.hdr.time_to_live = 0xFF; 811 ipv4_mask.hdr.time_to_live = 0xFF; 812 item.type = RTE_FLOW_ITEM_TYPE_IPV4; 813 item.spec = &ipv4; 814 item.mask = &ipv4_mask; 815 field = modify_ipv4; 816 } else { 817 MLX5_ASSERT(attr->ipv6); 818 memset(&ipv6, 0, sizeof(ipv6)); 819 memset(&ipv6_mask, 0, sizeof(ipv6_mask)); 820 ipv6.hdr.hop_limits = 0xFF; 821 ipv6_mask.hdr.hop_limits = 0xFF; 822 item.type = RTE_FLOW_ITEM_TYPE_IPV6; 823 item.spec = &ipv6; 824 item.mask = &ipv6_mask; 825 field = modify_ipv6; 826 } 827 return flow_dv_convert_modify_action(&item, field, NULL, resource, 828 MLX5_MODIFICATION_TYPE_ADD, error); 829 } 830 831 /** 832 * Convert modify-header increment/decrement TCP Sequence number 833 * to DV specification. 834 * 835 * @param[in,out] resource 836 * Pointer to the modify-header resource. 837 * @param[in] action 838 * Pointer to action specification. 839 * @param[out] error 840 * Pointer to the error structure. 841 * 842 * @return 843 * 0 on success, a negative errno value otherwise and rte_errno is set. 844 */ 845 static int 846 flow_dv_convert_action_modify_tcp_seq 847 (struct mlx5_flow_dv_modify_hdr_resource *resource, 848 const struct rte_flow_action *action, 849 struct rte_flow_error *error) 850 { 851 const rte_be32_t *conf = (const rte_be32_t *)(action->conf); 852 uint64_t value = rte_be_to_cpu_32(*conf); 853 struct rte_flow_item item; 854 struct rte_flow_item_tcp tcp; 855 struct rte_flow_item_tcp tcp_mask; 856 857 memset(&tcp, 0, sizeof(tcp)); 858 memset(&tcp_mask, 0, sizeof(tcp_mask)); 859 if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ) 860 /* 861 * The HW has no decrement operation, only increment operation. 862 * To simulate decrement X from Y using increment operation 863 * we need to add UINT32_MAX X times to Y. 864 * Each adding of UINT32_MAX decrements Y by 1. 865 */ 866 value *= UINT32_MAX; 867 tcp.hdr.sent_seq = rte_cpu_to_be_32((uint32_t)value); 868 tcp_mask.hdr.sent_seq = RTE_BE32(UINT32_MAX); 869 item.type = RTE_FLOW_ITEM_TYPE_TCP; 870 item.spec = &tcp; 871 item.mask = &tcp_mask; 872 return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource, 873 MLX5_MODIFICATION_TYPE_ADD, error); 874 } 875 876 /** 877 * Convert modify-header increment/decrement TCP Acknowledgment number 878 * to DV specification. 879 * 880 * @param[in,out] resource 881 * Pointer to the modify-header resource. 882 * @param[in] action 883 * Pointer to action specification. 884 * @param[out] error 885 * Pointer to the error structure. 886 * 887 * @return 888 * 0 on success, a negative errno value otherwise and rte_errno is set. 889 */ 890 static int 891 flow_dv_convert_action_modify_tcp_ack 892 (struct mlx5_flow_dv_modify_hdr_resource *resource, 893 const struct rte_flow_action *action, 894 struct rte_flow_error *error) 895 { 896 const rte_be32_t *conf = (const rte_be32_t *)(action->conf); 897 uint64_t value = rte_be_to_cpu_32(*conf); 898 struct rte_flow_item item; 899 struct rte_flow_item_tcp tcp; 900 struct rte_flow_item_tcp tcp_mask; 901 902 memset(&tcp, 0, sizeof(tcp)); 903 memset(&tcp_mask, 0, sizeof(tcp_mask)); 904 if (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK) 905 /* 906 * The HW has no decrement operation, only increment operation. 907 * To simulate decrement X from Y using increment operation 908 * we need to add UINT32_MAX X times to Y. 909 * Each adding of UINT32_MAX decrements Y by 1. 910 */ 911 value *= UINT32_MAX; 912 tcp.hdr.recv_ack = rte_cpu_to_be_32((uint32_t)value); 913 tcp_mask.hdr.recv_ack = RTE_BE32(UINT32_MAX); 914 item.type = RTE_FLOW_ITEM_TYPE_TCP; 915 item.spec = &tcp; 916 item.mask = &tcp_mask; 917 return flow_dv_convert_modify_action(&item, modify_tcp, NULL, resource, 918 MLX5_MODIFICATION_TYPE_ADD, error); 919 } 920 921 static enum mlx5_modification_field reg_to_field[] = { 922 [REG_NON] = MLX5_MODI_OUT_NONE, 923 [REG_A] = MLX5_MODI_META_DATA_REG_A, 924 [REG_B] = MLX5_MODI_META_DATA_REG_B, 925 [REG_C_0] = MLX5_MODI_META_REG_C_0, 926 [REG_C_1] = MLX5_MODI_META_REG_C_1, 927 [REG_C_2] = MLX5_MODI_META_REG_C_2, 928 [REG_C_3] = MLX5_MODI_META_REG_C_3, 929 [REG_C_4] = MLX5_MODI_META_REG_C_4, 930 [REG_C_5] = MLX5_MODI_META_REG_C_5, 931 [REG_C_6] = MLX5_MODI_META_REG_C_6, 932 [REG_C_7] = MLX5_MODI_META_REG_C_7, 933 }; 934 935 /** 936 * Convert register set to DV specification. 937 * 938 * @param[in,out] resource 939 * Pointer to the modify-header resource. 940 * @param[in] action 941 * Pointer to action specification. 942 * @param[out] error 943 * Pointer to the error structure. 944 * 945 * @return 946 * 0 on success, a negative errno value otherwise and rte_errno is set. 947 */ 948 static int 949 flow_dv_convert_action_set_reg 950 (struct mlx5_flow_dv_modify_hdr_resource *resource, 951 const struct rte_flow_action *action, 952 struct rte_flow_error *error) 953 { 954 const struct mlx5_rte_flow_action_set_tag *conf = action->conf; 955 struct mlx5_modification_cmd *actions = resource->actions; 956 uint32_t i = resource->actions_num; 957 958 if (i >= MLX5_MAX_MODIFY_NUM) 959 return rte_flow_error_set(error, EINVAL, 960 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 961 "too many items to modify"); 962 MLX5_ASSERT(conf->id != REG_NON); 963 MLX5_ASSERT(conf->id < (enum modify_reg)RTE_DIM(reg_to_field)); 964 actions[i] = (struct mlx5_modification_cmd) { 965 .action_type = MLX5_MODIFICATION_TYPE_SET, 966 .field = reg_to_field[conf->id], 967 }; 968 actions[i].data0 = rte_cpu_to_be_32(actions[i].data0); 969 actions[i].data1 = rte_cpu_to_be_32(conf->data); 970 ++i; 971 resource->actions_num = i; 972 return 0; 973 } 974 975 /** 976 * Convert SET_TAG action to DV specification. 977 * 978 * @param[in] dev 979 * Pointer to the rte_eth_dev structure. 980 * @param[in,out] resource 981 * Pointer to the modify-header resource. 982 * @param[in] conf 983 * Pointer to action specification. 984 * @param[out] error 985 * Pointer to the error structure. 986 * 987 * @return 988 * 0 on success, a negative errno value otherwise and rte_errno is set. 989 */ 990 static int 991 flow_dv_convert_action_set_tag 992 (struct rte_eth_dev *dev, 993 struct mlx5_flow_dv_modify_hdr_resource *resource, 994 const struct rte_flow_action_set_tag *conf, 995 struct rte_flow_error *error) 996 { 997 rte_be32_t data = rte_cpu_to_be_32(conf->data); 998 rte_be32_t mask = rte_cpu_to_be_32(conf->mask); 999 struct rte_flow_item item = { 1000 .spec = &data, 1001 .mask = &mask, 1002 }; 1003 struct field_modify_info reg_c_x[] = { 1004 [1] = {0, 0, 0}, 1005 }; 1006 enum mlx5_modification_field reg_type; 1007 int ret; 1008 1009 ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error); 1010 if (ret < 0) 1011 return ret; 1012 MLX5_ASSERT(ret != REG_NON); 1013 MLX5_ASSERT((unsigned int)ret < RTE_DIM(reg_to_field)); 1014 reg_type = reg_to_field[ret]; 1015 MLX5_ASSERT(reg_type > 0); 1016 reg_c_x[0] = (struct field_modify_info){4, 0, reg_type}; 1017 return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource, 1018 MLX5_MODIFICATION_TYPE_SET, error); 1019 } 1020 1021 /** 1022 * Convert internal COPY_REG action to DV specification. 1023 * 1024 * @param[in] dev 1025 * Pointer to the rte_eth_dev structure. 1026 * @param[in,out] res 1027 * Pointer to the modify-header resource. 1028 * @param[in] action 1029 * Pointer to action specification. 1030 * @param[out] error 1031 * Pointer to the error structure. 1032 * 1033 * @return 1034 * 0 on success, a negative errno value otherwise and rte_errno is set. 1035 */ 1036 static int 1037 flow_dv_convert_action_copy_mreg(struct rte_eth_dev *dev, 1038 struct mlx5_flow_dv_modify_hdr_resource *res, 1039 const struct rte_flow_action *action, 1040 struct rte_flow_error *error) 1041 { 1042 const struct mlx5_flow_action_copy_mreg *conf = action->conf; 1043 rte_be32_t mask = RTE_BE32(UINT32_MAX); 1044 struct rte_flow_item item = { 1045 .spec = NULL, 1046 .mask = &mask, 1047 }; 1048 struct field_modify_info reg_src[] = { 1049 {4, 0, reg_to_field[conf->src]}, 1050 {0, 0, 0}, 1051 }; 1052 struct field_modify_info reg_dst = { 1053 .offset = 0, 1054 .id = reg_to_field[conf->dst], 1055 }; 1056 /* Adjust reg_c[0] usage according to reported mask. */ 1057 if (conf->dst == REG_C_0 || conf->src == REG_C_0) { 1058 struct mlx5_priv *priv = dev->data->dev_private; 1059 uint32_t reg_c0 = priv->sh->dv_regc0_mask; 1060 1061 MLX5_ASSERT(reg_c0); 1062 MLX5_ASSERT(priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY); 1063 if (conf->dst == REG_C_0) { 1064 /* Copy to reg_c[0], within mask only. */ 1065 reg_dst.offset = rte_bsf32(reg_c0); 1066 /* 1067 * Mask is ignoring the enianness, because 1068 * there is no conversion in datapath. 1069 */ 1070 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 1071 /* Copy from destination lower bits to reg_c[0]. */ 1072 mask = reg_c0 >> reg_dst.offset; 1073 #else 1074 /* Copy from destination upper bits to reg_c[0]. */ 1075 mask = reg_c0 << (sizeof(reg_c0) * CHAR_BIT - 1076 rte_fls_u32(reg_c0)); 1077 #endif 1078 } else { 1079 mask = rte_cpu_to_be_32(reg_c0); 1080 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 1081 /* Copy from reg_c[0] to destination lower bits. */ 1082 reg_dst.offset = 0; 1083 #else 1084 /* Copy from reg_c[0] to destination upper bits. */ 1085 reg_dst.offset = sizeof(reg_c0) * CHAR_BIT - 1086 (rte_fls_u32(reg_c0) - 1087 rte_bsf32(reg_c0)); 1088 #endif 1089 } 1090 } 1091 return flow_dv_convert_modify_action(&item, 1092 reg_src, ®_dst, res, 1093 MLX5_MODIFICATION_TYPE_COPY, 1094 error); 1095 } 1096 1097 /** 1098 * Convert MARK action to DV specification. This routine is used 1099 * in extensive metadata only and requires metadata register to be 1100 * handled. In legacy mode hardware tag resource is engaged. 1101 * 1102 * @param[in] dev 1103 * Pointer to the rte_eth_dev structure. 1104 * @param[in] conf 1105 * Pointer to MARK action specification. 1106 * @param[in,out] resource 1107 * Pointer to the modify-header resource. 1108 * @param[out] error 1109 * Pointer to the error structure. 1110 * 1111 * @return 1112 * 0 on success, a negative errno value otherwise and rte_errno is set. 1113 */ 1114 static int 1115 flow_dv_convert_action_mark(struct rte_eth_dev *dev, 1116 const struct rte_flow_action_mark *conf, 1117 struct mlx5_flow_dv_modify_hdr_resource *resource, 1118 struct rte_flow_error *error) 1119 { 1120 struct mlx5_priv *priv = dev->data->dev_private; 1121 rte_be32_t mask = rte_cpu_to_be_32(MLX5_FLOW_MARK_MASK & 1122 priv->sh->dv_mark_mask); 1123 rte_be32_t data = rte_cpu_to_be_32(conf->id) & mask; 1124 struct rte_flow_item item = { 1125 .spec = &data, 1126 .mask = &mask, 1127 }; 1128 struct field_modify_info reg_c_x[] = { 1129 [1] = {0, 0, 0}, 1130 }; 1131 int reg; 1132 1133 if (!mask) 1134 return rte_flow_error_set(error, EINVAL, 1135 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1136 NULL, "zero mark action mask"); 1137 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 1138 if (reg < 0) 1139 return reg; 1140 MLX5_ASSERT(reg > 0); 1141 if (reg == REG_C_0) { 1142 uint32_t msk_c0 = priv->sh->dv_regc0_mask; 1143 uint32_t shl_c0 = rte_bsf32(msk_c0); 1144 1145 data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0); 1146 mask = rte_cpu_to_be_32(mask) & msk_c0; 1147 mask = rte_cpu_to_be_32(mask << shl_c0); 1148 } 1149 reg_c_x[0] = (struct field_modify_info){4, 0, reg_to_field[reg]}; 1150 return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource, 1151 MLX5_MODIFICATION_TYPE_SET, error); 1152 } 1153 1154 /** 1155 * Get metadata register index for specified steering domain. 1156 * 1157 * @param[in] dev 1158 * Pointer to the rte_eth_dev structure. 1159 * @param[in] attr 1160 * Attributes of flow to determine steering domain. 1161 * @param[out] error 1162 * Pointer to the error structure. 1163 * 1164 * @return 1165 * positive index on success, a negative errno value otherwise 1166 * and rte_errno is set. 1167 */ 1168 static enum modify_reg 1169 flow_dv_get_metadata_reg(struct rte_eth_dev *dev, 1170 const struct rte_flow_attr *attr, 1171 struct rte_flow_error *error) 1172 { 1173 int reg = 1174 mlx5_flow_get_reg_id(dev, attr->transfer ? 1175 MLX5_METADATA_FDB : 1176 attr->egress ? 1177 MLX5_METADATA_TX : 1178 MLX5_METADATA_RX, 0, error); 1179 if (reg < 0) 1180 return rte_flow_error_set(error, 1181 ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, 1182 NULL, "unavailable " 1183 "metadata register"); 1184 return reg; 1185 } 1186 1187 /** 1188 * Convert SET_META action to DV specification. 1189 * 1190 * @param[in] dev 1191 * Pointer to the rte_eth_dev structure. 1192 * @param[in,out] resource 1193 * Pointer to the modify-header resource. 1194 * @param[in] attr 1195 * Attributes of flow that includes this item. 1196 * @param[in] conf 1197 * Pointer to action specification. 1198 * @param[out] error 1199 * Pointer to the error structure. 1200 * 1201 * @return 1202 * 0 on success, a negative errno value otherwise and rte_errno is set. 1203 */ 1204 static int 1205 flow_dv_convert_action_set_meta 1206 (struct rte_eth_dev *dev, 1207 struct mlx5_flow_dv_modify_hdr_resource *resource, 1208 const struct rte_flow_attr *attr, 1209 const struct rte_flow_action_set_meta *conf, 1210 struct rte_flow_error *error) 1211 { 1212 uint32_t data = conf->data; 1213 uint32_t mask = conf->mask; 1214 struct rte_flow_item item = { 1215 .spec = &data, 1216 .mask = &mask, 1217 }; 1218 struct field_modify_info reg_c_x[] = { 1219 [1] = {0, 0, 0}, 1220 }; 1221 int reg = flow_dv_get_metadata_reg(dev, attr, error); 1222 1223 if (reg < 0) 1224 return reg; 1225 MLX5_ASSERT(reg != REG_NON); 1226 /* 1227 * In datapath code there is no endianness 1228 * coversions for perfromance reasons, all 1229 * pattern conversions are done in rte_flow. 1230 */ 1231 if (reg == REG_C_0) { 1232 struct mlx5_priv *priv = dev->data->dev_private; 1233 uint32_t msk_c0 = priv->sh->dv_regc0_mask; 1234 uint32_t shl_c0; 1235 1236 MLX5_ASSERT(msk_c0); 1237 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 1238 shl_c0 = rte_bsf32(msk_c0); 1239 #else 1240 shl_c0 = sizeof(msk_c0) * CHAR_BIT - rte_fls_u32(msk_c0); 1241 #endif 1242 mask <<= shl_c0; 1243 data <<= shl_c0; 1244 MLX5_ASSERT(!(~msk_c0 & rte_cpu_to_be_32(mask))); 1245 } 1246 reg_c_x[0] = (struct field_modify_info){4, 0, reg_to_field[reg]}; 1247 /* The routine expects parameters in memory as big-endian ones. */ 1248 return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource, 1249 MLX5_MODIFICATION_TYPE_SET, error); 1250 } 1251 1252 /** 1253 * Convert modify-header set IPv4 DSCP action to DV specification. 1254 * 1255 * @param[in,out] resource 1256 * Pointer to the modify-header resource. 1257 * @param[in] action 1258 * Pointer to action specification. 1259 * @param[out] error 1260 * Pointer to the error structure. 1261 * 1262 * @return 1263 * 0 on success, a negative errno value otherwise and rte_errno is set. 1264 */ 1265 static int 1266 flow_dv_convert_action_modify_ipv4_dscp 1267 (struct mlx5_flow_dv_modify_hdr_resource *resource, 1268 const struct rte_flow_action *action, 1269 struct rte_flow_error *error) 1270 { 1271 const struct rte_flow_action_set_dscp *conf = 1272 (const struct rte_flow_action_set_dscp *)(action->conf); 1273 struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV4 }; 1274 struct rte_flow_item_ipv4 ipv4; 1275 struct rte_flow_item_ipv4 ipv4_mask; 1276 1277 memset(&ipv4, 0, sizeof(ipv4)); 1278 memset(&ipv4_mask, 0, sizeof(ipv4_mask)); 1279 ipv4.hdr.type_of_service = conf->dscp; 1280 ipv4_mask.hdr.type_of_service = RTE_IPV4_HDR_DSCP_MASK >> 2; 1281 item.spec = &ipv4; 1282 item.mask = &ipv4_mask; 1283 return flow_dv_convert_modify_action(&item, modify_ipv4, NULL, resource, 1284 MLX5_MODIFICATION_TYPE_SET, error); 1285 } 1286 1287 /** 1288 * Convert modify-header set IPv6 DSCP action to DV specification. 1289 * 1290 * @param[in,out] resource 1291 * Pointer to the modify-header resource. 1292 * @param[in] action 1293 * Pointer to action specification. 1294 * @param[out] error 1295 * Pointer to the error structure. 1296 * 1297 * @return 1298 * 0 on success, a negative errno value otherwise and rte_errno is set. 1299 */ 1300 static int 1301 flow_dv_convert_action_modify_ipv6_dscp 1302 (struct mlx5_flow_dv_modify_hdr_resource *resource, 1303 const struct rte_flow_action *action, 1304 struct rte_flow_error *error) 1305 { 1306 const struct rte_flow_action_set_dscp *conf = 1307 (const struct rte_flow_action_set_dscp *)(action->conf); 1308 struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_IPV6 }; 1309 struct rte_flow_item_ipv6 ipv6; 1310 struct rte_flow_item_ipv6 ipv6_mask; 1311 1312 memset(&ipv6, 0, sizeof(ipv6)); 1313 memset(&ipv6_mask, 0, sizeof(ipv6_mask)); 1314 /* 1315 * Even though the DSCP bits offset of IPv6 is not byte aligned, 1316 * rdma-core only accept the DSCP bits byte aligned start from 1317 * bit 0 to 5 as to be compatible with IPv4. No need to shift the 1318 * bits in IPv6 case as rdma-core requires byte aligned value. 1319 */ 1320 ipv6.hdr.vtc_flow = conf->dscp; 1321 ipv6_mask.hdr.vtc_flow = RTE_IPV6_HDR_DSCP_MASK >> 22; 1322 item.spec = &ipv6; 1323 item.mask = &ipv6_mask; 1324 return flow_dv_convert_modify_action(&item, modify_ipv6, NULL, resource, 1325 MLX5_MODIFICATION_TYPE_SET, error); 1326 } 1327 1328 static void 1329 mlx5_flow_field_id_to_modify_info 1330 (const struct rte_flow_action_modify_data *data, 1331 struct field_modify_info *info, 1332 uint32_t *mask, uint32_t *value, uint32_t width, 1333 struct rte_eth_dev *dev, 1334 const struct rte_flow_attr *attr, 1335 struct rte_flow_error *error) 1336 { 1337 uint32_t idx = 0; 1338 switch (data->field) { 1339 case RTE_FLOW_FIELD_START: 1340 /* not supported yet */ 1341 MLX5_ASSERT(false); 1342 break; 1343 case RTE_FLOW_FIELD_MAC_DST: 1344 if (mask) { 1345 if (data->offset < 32) { 1346 info[idx] = (struct field_modify_info){4, 0, 1347 MLX5_MODI_OUT_DMAC_47_16}; 1348 mask[idx] = 0xffffffff; 1349 if (width < 32) { 1350 mask[idx] = mask[idx] << (32 - width); 1351 width = 0; 1352 } else { 1353 width -= 32; 1354 } 1355 if (!width) 1356 break; 1357 ++idx; 1358 } 1359 info[idx] = (struct field_modify_info){2, 4 * idx, 1360 MLX5_MODI_OUT_DMAC_15_0}; 1361 mask[idx] = (width) ? 0x0000ffff : 0x0; 1362 if (width < 16) 1363 mask[idx] = (mask[idx] << (16 - width)) & 1364 0x0000ffff; 1365 } else { 1366 if (data->offset < 32) 1367 info[idx++] = (struct field_modify_info){4, 0, 1368 MLX5_MODI_OUT_DMAC_47_16}; 1369 info[idx] = (struct field_modify_info){2, 0, 1370 MLX5_MODI_OUT_DMAC_15_0}; 1371 } 1372 break; 1373 case RTE_FLOW_FIELD_MAC_SRC: 1374 if (mask) { 1375 if (data->offset < 32) { 1376 info[idx] = (struct field_modify_info){4, 0, 1377 MLX5_MODI_OUT_SMAC_47_16}; 1378 mask[idx] = 0xffffffff; 1379 if (width < 32) { 1380 mask[idx] = mask[idx] << (32 - width); 1381 width = 0; 1382 } else { 1383 width -= 32; 1384 } 1385 if (!width) 1386 break; 1387 ++idx; 1388 } 1389 info[idx] = (struct field_modify_info){2, 4 * idx, 1390 MLX5_MODI_OUT_SMAC_15_0}; 1391 mask[idx] = (width) ? 0x0000ffff : 0x0; 1392 if (width < 16) 1393 mask[idx] = (mask[idx] << (16 - width)) & 1394 0x0000ffff; 1395 } else { 1396 if (data->offset < 32) 1397 info[idx++] = (struct field_modify_info){4, 0, 1398 MLX5_MODI_OUT_SMAC_47_16}; 1399 info[idx] = (struct field_modify_info){2, 0, 1400 MLX5_MODI_OUT_SMAC_15_0}; 1401 } 1402 break; 1403 case RTE_FLOW_FIELD_VLAN_TYPE: 1404 /* not supported yet */ 1405 break; 1406 case RTE_FLOW_FIELD_VLAN_ID: 1407 info[idx] = (struct field_modify_info){2, 0, 1408 MLX5_MODI_OUT_FIRST_VID}; 1409 if (mask) { 1410 mask[idx] = 0x00000fff; 1411 if (width < 12) 1412 mask[idx] = (mask[idx] << (12 - width)) & 1413 0x00000fff; 1414 } 1415 break; 1416 case RTE_FLOW_FIELD_MAC_TYPE: 1417 info[idx] = (struct field_modify_info){2, 0, 1418 MLX5_MODI_OUT_ETHERTYPE}; 1419 if (mask) { 1420 mask[idx] = 0x0000ffff; 1421 if (width < 16) 1422 mask[idx] = (mask[idx] << (16 - width)) & 1423 0x0000ffff; 1424 } 1425 break; 1426 case RTE_FLOW_FIELD_IPV4_DSCP: 1427 info[idx] = (struct field_modify_info){1, 0, 1428 MLX5_MODI_OUT_IP_DSCP}; 1429 if (mask) { 1430 mask[idx] = 0x0000003f; 1431 if (width < 6) 1432 mask[idx] = (mask[idx] << (6 - width)) & 1433 0x0000003f; 1434 } 1435 break; 1436 case RTE_FLOW_FIELD_IPV4_TTL: 1437 info[idx] = (struct field_modify_info){1, 0, 1438 MLX5_MODI_OUT_IPV4_TTL}; 1439 if (mask) { 1440 mask[idx] = 0x000000ff; 1441 if (width < 8) 1442 mask[idx] = (mask[idx] << (8 - width)) & 1443 0x000000ff; 1444 } 1445 break; 1446 case RTE_FLOW_FIELD_IPV4_SRC: 1447 info[idx] = (struct field_modify_info){4, 0, 1448 MLX5_MODI_OUT_SIPV4}; 1449 if (mask) { 1450 mask[idx] = 0xffffffff; 1451 if (width < 32) 1452 mask[idx] = mask[idx] << (32 - width); 1453 } 1454 break; 1455 case RTE_FLOW_FIELD_IPV4_DST: 1456 info[idx] = (struct field_modify_info){4, 0, 1457 MLX5_MODI_OUT_DIPV4}; 1458 if (mask) { 1459 mask[idx] = 0xffffffff; 1460 if (width < 32) 1461 mask[idx] = mask[idx] << (32 - width); 1462 } 1463 break; 1464 case RTE_FLOW_FIELD_IPV6_DSCP: 1465 info[idx] = (struct field_modify_info){1, 0, 1466 MLX5_MODI_OUT_IP_DSCP}; 1467 if (mask) { 1468 mask[idx] = 0x0000003f; 1469 if (width < 6) 1470 mask[idx] = (mask[idx] << (6 - width)) & 1471 0x0000003f; 1472 } 1473 break; 1474 case RTE_FLOW_FIELD_IPV6_HOPLIMIT: 1475 info[idx] = (struct field_modify_info){1, 0, 1476 MLX5_MODI_OUT_IPV6_HOPLIMIT}; 1477 if (mask) { 1478 mask[idx] = 0x000000ff; 1479 if (width < 8) 1480 mask[idx] = (mask[idx] << (8 - width)) & 1481 0x000000ff; 1482 } 1483 break; 1484 case RTE_FLOW_FIELD_IPV6_SRC: 1485 if (mask) { 1486 if (data->offset < 32) { 1487 info[idx] = (struct field_modify_info){4, 0, 1488 MLX5_MODI_OUT_SIPV6_127_96}; 1489 mask[idx] = 0xffffffff; 1490 if (width < 32) { 1491 mask[idx] = mask[idx] << (32 - width); 1492 width = 0; 1493 } else { 1494 width -= 32; 1495 } 1496 if (!width) 1497 break; 1498 ++idx; 1499 } 1500 if (data->offset < 64) { 1501 info[idx] = (struct field_modify_info){4, 1502 4 * idx, 1503 MLX5_MODI_OUT_SIPV6_95_64}; 1504 mask[idx] = 0xffffffff; 1505 if (width < 32) { 1506 mask[idx] = mask[idx] << (32 - width); 1507 width = 0; 1508 } else { 1509 width -= 32; 1510 } 1511 if (!width) 1512 break; 1513 ++idx; 1514 } 1515 if (data->offset < 96) { 1516 info[idx] = (struct field_modify_info){4, 1517 8 * idx, 1518 MLX5_MODI_OUT_SIPV6_63_32}; 1519 mask[idx] = 0xffffffff; 1520 if (width < 32) { 1521 mask[idx] = mask[idx] << (32 - width); 1522 width = 0; 1523 } else { 1524 width -= 32; 1525 } 1526 if (!width) 1527 break; 1528 ++idx; 1529 } 1530 info[idx] = (struct field_modify_info){4, 12 * idx, 1531 MLX5_MODI_OUT_SIPV6_31_0}; 1532 mask[idx] = 0xffffffff; 1533 if (width < 32) 1534 mask[idx] = mask[idx] << (32 - width); 1535 } else { 1536 if (data->offset < 32) 1537 info[idx++] = (struct field_modify_info){4, 0, 1538 MLX5_MODI_OUT_SIPV6_127_96}; 1539 if (data->offset < 64) 1540 info[idx++] = (struct field_modify_info){4, 0, 1541 MLX5_MODI_OUT_SIPV6_95_64}; 1542 if (data->offset < 96) 1543 info[idx++] = (struct field_modify_info){4, 0, 1544 MLX5_MODI_OUT_SIPV6_63_32}; 1545 if (data->offset < 128) 1546 info[idx++] = (struct field_modify_info){4, 0, 1547 MLX5_MODI_OUT_SIPV6_31_0}; 1548 } 1549 break; 1550 case RTE_FLOW_FIELD_IPV6_DST: 1551 if (mask) { 1552 if (data->offset < 32) { 1553 info[idx] = (struct field_modify_info){4, 0, 1554 MLX5_MODI_OUT_DIPV6_127_96}; 1555 mask[idx] = 0xffffffff; 1556 if (width < 32) { 1557 mask[idx] = mask[idx] << (32 - width); 1558 width = 0; 1559 } else { 1560 width -= 32; 1561 } 1562 if (!width) 1563 break; 1564 ++idx; 1565 } 1566 if (data->offset < 64) { 1567 info[idx] = (struct field_modify_info){4, 1568 4 * idx, 1569 MLX5_MODI_OUT_DIPV6_95_64}; 1570 mask[idx] = 0xffffffff; 1571 if (width < 32) { 1572 mask[idx] = mask[idx] << (32 - width); 1573 width = 0; 1574 } else { 1575 width -= 32; 1576 } 1577 if (!width) 1578 break; 1579 ++idx; 1580 } 1581 if (data->offset < 96) { 1582 info[idx] = (struct field_modify_info){4, 1583 8 * idx, 1584 MLX5_MODI_OUT_DIPV6_63_32}; 1585 mask[idx] = 0xffffffff; 1586 if (width < 32) { 1587 mask[idx] = mask[idx] << (32 - width); 1588 width = 0; 1589 } else { 1590 width -= 32; 1591 } 1592 if (!width) 1593 break; 1594 ++idx; 1595 } 1596 info[idx] = (struct field_modify_info){4, 12 * idx, 1597 MLX5_MODI_OUT_DIPV6_31_0}; 1598 mask[idx] = 0xffffffff; 1599 if (width < 32) 1600 mask[idx] = mask[idx] << (32 - width); 1601 } else { 1602 if (data->offset < 32) 1603 info[idx++] = (struct field_modify_info){4, 0, 1604 MLX5_MODI_OUT_DIPV6_127_96}; 1605 if (data->offset < 64) 1606 info[idx++] = (struct field_modify_info){4, 0, 1607 MLX5_MODI_OUT_DIPV6_95_64}; 1608 if (data->offset < 96) 1609 info[idx++] = (struct field_modify_info){4, 0, 1610 MLX5_MODI_OUT_DIPV6_63_32}; 1611 if (data->offset < 128) 1612 info[idx++] = (struct field_modify_info){4, 0, 1613 MLX5_MODI_OUT_DIPV6_31_0}; 1614 } 1615 break; 1616 case RTE_FLOW_FIELD_TCP_PORT_SRC: 1617 info[idx] = (struct field_modify_info){2, 0, 1618 MLX5_MODI_OUT_TCP_SPORT}; 1619 if (mask) { 1620 mask[idx] = 0x0000ffff; 1621 if (width < 16) 1622 mask[idx] = (mask[idx] << (16 - width)) & 1623 0x0000ffff; 1624 } 1625 break; 1626 case RTE_FLOW_FIELD_TCP_PORT_DST: 1627 info[idx] = (struct field_modify_info){2, 0, 1628 MLX5_MODI_OUT_TCP_DPORT}; 1629 if (mask) { 1630 mask[idx] = 0x0000ffff; 1631 if (width < 16) 1632 mask[idx] = (mask[idx] << (16 - width)) & 1633 0x0000ffff; 1634 } 1635 break; 1636 case RTE_FLOW_FIELD_TCP_SEQ_NUM: 1637 info[idx] = (struct field_modify_info){4, 0, 1638 MLX5_MODI_OUT_TCP_SEQ_NUM}; 1639 if (mask) { 1640 mask[idx] = 0xffffffff; 1641 if (width < 32) 1642 mask[idx] = (mask[idx] << (32 - width)); 1643 } 1644 break; 1645 case RTE_FLOW_FIELD_TCP_ACK_NUM: 1646 info[idx] = (struct field_modify_info){4, 0, 1647 MLX5_MODI_OUT_TCP_ACK_NUM}; 1648 if (mask) { 1649 mask[idx] = 0xffffffff; 1650 if (width < 32) 1651 mask[idx] = (mask[idx] << (32 - width)); 1652 } 1653 break; 1654 case RTE_FLOW_FIELD_TCP_FLAGS: 1655 info[idx] = (struct field_modify_info){1, 0, 1656 MLX5_MODI_OUT_TCP_FLAGS}; 1657 if (mask) { 1658 mask[idx] = 0x0000003f; 1659 if (width < 6) 1660 mask[idx] = (mask[idx] << (6 - width)) & 1661 0x0000003f; 1662 } 1663 break; 1664 case RTE_FLOW_FIELD_UDP_PORT_SRC: 1665 info[idx] = (struct field_modify_info){2, 0, 1666 MLX5_MODI_OUT_UDP_SPORT}; 1667 if (mask) { 1668 mask[idx] = 0x0000ffff; 1669 if (width < 16) 1670 mask[idx] = (mask[idx] << (16 - width)) & 1671 0x0000ffff; 1672 } 1673 break; 1674 case RTE_FLOW_FIELD_UDP_PORT_DST: 1675 info[idx] = (struct field_modify_info){2, 0, 1676 MLX5_MODI_OUT_UDP_DPORT}; 1677 if (mask) { 1678 mask[idx] = 0x0000ffff; 1679 if (width < 16) 1680 mask[idx] = (mask[idx] << (16 - width)) & 1681 0x0000ffff; 1682 } 1683 break; 1684 case RTE_FLOW_FIELD_VXLAN_VNI: 1685 /* not supported yet */ 1686 break; 1687 case RTE_FLOW_FIELD_GENEVE_VNI: 1688 /* not supported yet*/ 1689 break; 1690 case RTE_FLOW_FIELD_GTP_TEID: 1691 info[idx] = (struct field_modify_info){4, 0, 1692 MLX5_MODI_GTP_TEID}; 1693 if (mask) { 1694 mask[idx] = 0xffffffff; 1695 if (width < 32) 1696 mask[idx] = mask[idx] << (32 - width); 1697 } 1698 break; 1699 case RTE_FLOW_FIELD_TAG: 1700 { 1701 int reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 1702 data->level, error); 1703 if (reg < 0) 1704 return; 1705 MLX5_ASSERT(reg != REG_NON); 1706 MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field)); 1707 info[idx] = (struct field_modify_info){4, 0, 1708 reg_to_field[reg]}; 1709 if (mask) { 1710 mask[idx] = 0xffffffff; 1711 if (width < 32) 1712 mask[idx] = mask[idx] << (32 - width); 1713 } 1714 } 1715 break; 1716 case RTE_FLOW_FIELD_MARK: 1717 { 1718 int reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 1719 0, error); 1720 if (reg < 0) 1721 return; 1722 MLX5_ASSERT(reg != REG_NON); 1723 MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field)); 1724 info[idx] = (struct field_modify_info){4, 0, 1725 reg_to_field[reg]}; 1726 if (mask) { 1727 mask[idx] = 0xffffffff; 1728 if (width < 32) 1729 mask[idx] = mask[idx] << (32 - width); 1730 } 1731 } 1732 break; 1733 case RTE_FLOW_FIELD_META: 1734 { 1735 int reg = flow_dv_get_metadata_reg(dev, attr, error); 1736 if (reg < 0) 1737 return; 1738 MLX5_ASSERT(reg != REG_NON); 1739 MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field)); 1740 info[idx] = (struct field_modify_info){4, 0, 1741 reg_to_field[reg]}; 1742 if (mask) { 1743 mask[idx] = 0xffffffff; 1744 if (width < 32) 1745 mask[idx] = mask[idx] << (32 - width); 1746 } 1747 } 1748 break; 1749 case RTE_FLOW_FIELD_POINTER: 1750 for (idx = 0; idx < MLX5_ACT_MAX_MOD_FIELDS; idx++) { 1751 if (mask[idx]) { 1752 memcpy(&value[idx], 1753 (void *)(uintptr_t)data->value, 32); 1754 value[idx] = RTE_BE32(value[idx]); 1755 break; 1756 } 1757 } 1758 break; 1759 case RTE_FLOW_FIELD_VALUE: 1760 for (idx = 0; idx < MLX5_ACT_MAX_MOD_FIELDS; idx++) { 1761 if (mask[idx]) { 1762 value[idx] = RTE_BE32((uint32_t)data->value); 1763 break; 1764 } 1765 } 1766 break; 1767 default: 1768 MLX5_ASSERT(false); 1769 break; 1770 } 1771 } 1772 1773 /** 1774 * Convert modify_field action to DV specification. 1775 * 1776 * @param[in] dev 1777 * Pointer to the rte_eth_dev structure. 1778 * @param[in,out] resource 1779 * Pointer to the modify-header resource. 1780 * @param[in] action 1781 * Pointer to action specification. 1782 * @param[in] attr 1783 * Attributes of flow that includes this item. 1784 * @param[out] error 1785 * Pointer to the error structure. 1786 * 1787 * @return 1788 * 0 on success, a negative errno value otherwise and rte_errno is set. 1789 */ 1790 static int 1791 flow_dv_convert_action_modify_field 1792 (struct rte_eth_dev *dev, 1793 struct mlx5_flow_dv_modify_hdr_resource *resource, 1794 const struct rte_flow_action *action, 1795 const struct rte_flow_attr *attr, 1796 struct rte_flow_error *error) 1797 { 1798 const struct rte_flow_action_modify_field *conf = 1799 (const struct rte_flow_action_modify_field *)(action->conf); 1800 struct rte_flow_item item; 1801 struct field_modify_info field[MLX5_ACT_MAX_MOD_FIELDS] = { 1802 {0, 0, 0} }; 1803 struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = { 1804 {0, 0, 0} }; 1805 uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0}; 1806 uint32_t value[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0}; 1807 uint32_t type; 1808 1809 if (conf->src.field == RTE_FLOW_FIELD_POINTER || 1810 conf->src.field == RTE_FLOW_FIELD_VALUE) { 1811 type = MLX5_MODIFICATION_TYPE_SET; 1812 /** For SET fill the destination field (field) first. */ 1813 mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask, 1814 value, conf->width, dev, attr, error); 1815 /** Then copy immediate value from source as per mask. */ 1816 mlx5_flow_field_id_to_modify_info(&conf->src, dcopy, mask, 1817 value, conf->width, dev, attr, error); 1818 item.spec = &value; 1819 } else { 1820 type = MLX5_MODIFICATION_TYPE_COPY; 1821 /** For COPY fill the destination field (dcopy) without mask. */ 1822 mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL, 1823 value, conf->width, dev, attr, error); 1824 /** Then construct the source field (field) with mask. */ 1825 mlx5_flow_field_id_to_modify_info(&conf->src, field, mask, 1826 value, conf->width, dev, attr, error); 1827 } 1828 item.mask = &mask; 1829 return flow_dv_convert_modify_action(&item, 1830 field, dcopy, resource, type, error); 1831 } 1832 1833 /** 1834 * Validate MARK item. 1835 * 1836 * @param[in] dev 1837 * Pointer to the rte_eth_dev structure. 1838 * @param[in] item 1839 * Item specification. 1840 * @param[in] attr 1841 * Attributes of flow that includes this item. 1842 * @param[out] error 1843 * Pointer to error structure. 1844 * 1845 * @return 1846 * 0 on success, a negative errno value otherwise and rte_errno is set. 1847 */ 1848 static int 1849 flow_dv_validate_item_mark(struct rte_eth_dev *dev, 1850 const struct rte_flow_item *item, 1851 const struct rte_flow_attr *attr __rte_unused, 1852 struct rte_flow_error *error) 1853 { 1854 struct mlx5_priv *priv = dev->data->dev_private; 1855 struct mlx5_dev_config *config = &priv->config; 1856 const struct rte_flow_item_mark *spec = item->spec; 1857 const struct rte_flow_item_mark *mask = item->mask; 1858 const struct rte_flow_item_mark nic_mask = { 1859 .id = priv->sh->dv_mark_mask, 1860 }; 1861 int ret; 1862 1863 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY) 1864 return rte_flow_error_set(error, ENOTSUP, 1865 RTE_FLOW_ERROR_TYPE_ITEM, item, 1866 "extended metadata feature" 1867 " isn't enabled"); 1868 if (!mlx5_flow_ext_mreg_supported(dev)) 1869 return rte_flow_error_set(error, ENOTSUP, 1870 RTE_FLOW_ERROR_TYPE_ITEM, item, 1871 "extended metadata register" 1872 " isn't supported"); 1873 if (!nic_mask.id) 1874 return rte_flow_error_set(error, ENOTSUP, 1875 RTE_FLOW_ERROR_TYPE_ITEM, item, 1876 "extended metadata register" 1877 " isn't available"); 1878 ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 1879 if (ret < 0) 1880 return ret; 1881 if (!spec) 1882 return rte_flow_error_set(error, EINVAL, 1883 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 1884 item->spec, 1885 "data cannot be empty"); 1886 if (spec->id >= (MLX5_FLOW_MARK_MAX & nic_mask.id)) 1887 return rte_flow_error_set(error, EINVAL, 1888 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1889 &spec->id, 1890 "mark id exceeds the limit"); 1891 if (!mask) 1892 mask = &nic_mask; 1893 if (!mask->id) 1894 return rte_flow_error_set(error, EINVAL, 1895 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, 1896 "mask cannot be zero"); 1897 1898 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1899 (const uint8_t *)&nic_mask, 1900 sizeof(struct rte_flow_item_mark), 1901 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 1902 if (ret < 0) 1903 return ret; 1904 return 0; 1905 } 1906 1907 /** 1908 * Validate META item. 1909 * 1910 * @param[in] dev 1911 * Pointer to the rte_eth_dev structure. 1912 * @param[in] item 1913 * Item specification. 1914 * @param[in] attr 1915 * Attributes of flow that includes this item. 1916 * @param[out] error 1917 * Pointer to error structure. 1918 * 1919 * @return 1920 * 0 on success, a negative errno value otherwise and rte_errno is set. 1921 */ 1922 static int 1923 flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused, 1924 const struct rte_flow_item *item, 1925 const struct rte_flow_attr *attr, 1926 struct rte_flow_error *error) 1927 { 1928 struct mlx5_priv *priv = dev->data->dev_private; 1929 struct mlx5_dev_config *config = &priv->config; 1930 const struct rte_flow_item_meta *spec = item->spec; 1931 const struct rte_flow_item_meta *mask = item->mask; 1932 struct rte_flow_item_meta nic_mask = { 1933 .data = UINT32_MAX 1934 }; 1935 int reg; 1936 int ret; 1937 1938 if (!spec) 1939 return rte_flow_error_set(error, EINVAL, 1940 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 1941 item->spec, 1942 "data cannot be empty"); 1943 if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 1944 if (!mlx5_flow_ext_mreg_supported(dev)) 1945 return rte_flow_error_set(error, ENOTSUP, 1946 RTE_FLOW_ERROR_TYPE_ITEM, item, 1947 "extended metadata register" 1948 " isn't supported"); 1949 reg = flow_dv_get_metadata_reg(dev, attr, error); 1950 if (reg < 0) 1951 return reg; 1952 if (reg == REG_NON) 1953 return rte_flow_error_set(error, ENOTSUP, 1954 RTE_FLOW_ERROR_TYPE_ITEM, item, 1955 "unavalable extended metadata register"); 1956 if (reg == REG_B) 1957 return rte_flow_error_set(error, ENOTSUP, 1958 RTE_FLOW_ERROR_TYPE_ITEM, item, 1959 "match on reg_b " 1960 "isn't supported"); 1961 if (reg != REG_A) 1962 nic_mask.data = priv->sh->dv_meta_mask; 1963 } else { 1964 if (attr->transfer) 1965 return rte_flow_error_set(error, ENOTSUP, 1966 RTE_FLOW_ERROR_TYPE_ITEM, item, 1967 "extended metadata feature " 1968 "should be enabled when " 1969 "meta item is requested " 1970 "with e-switch mode "); 1971 if (attr->ingress) 1972 return rte_flow_error_set(error, ENOTSUP, 1973 RTE_FLOW_ERROR_TYPE_ITEM, item, 1974 "match on metadata for ingress " 1975 "is not supported in legacy " 1976 "metadata mode"); 1977 } 1978 if (!mask) 1979 mask = &rte_flow_item_meta_mask; 1980 if (!mask->data) 1981 return rte_flow_error_set(error, EINVAL, 1982 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, 1983 "mask cannot be zero"); 1984 1985 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1986 (const uint8_t *)&nic_mask, 1987 sizeof(struct rte_flow_item_meta), 1988 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 1989 return ret; 1990 } 1991 1992 /** 1993 * Validate TAG item. 1994 * 1995 * @param[in] dev 1996 * Pointer to the rte_eth_dev structure. 1997 * @param[in] item 1998 * Item specification. 1999 * @param[in] attr 2000 * Attributes of flow that includes this item. 2001 * @param[out] error 2002 * Pointer to error structure. 2003 * 2004 * @return 2005 * 0 on success, a negative errno value otherwise and rte_errno is set. 2006 */ 2007 static int 2008 flow_dv_validate_item_tag(struct rte_eth_dev *dev, 2009 const struct rte_flow_item *item, 2010 const struct rte_flow_attr *attr __rte_unused, 2011 struct rte_flow_error *error) 2012 { 2013 const struct rte_flow_item_tag *spec = item->spec; 2014 const struct rte_flow_item_tag *mask = item->mask; 2015 const struct rte_flow_item_tag nic_mask = { 2016 .data = RTE_BE32(UINT32_MAX), 2017 .index = 0xff, 2018 }; 2019 int ret; 2020 2021 if (!mlx5_flow_ext_mreg_supported(dev)) 2022 return rte_flow_error_set(error, ENOTSUP, 2023 RTE_FLOW_ERROR_TYPE_ITEM, item, 2024 "extensive metadata register" 2025 " isn't supported"); 2026 if (!spec) 2027 return rte_flow_error_set(error, EINVAL, 2028 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 2029 item->spec, 2030 "data cannot be empty"); 2031 if (!mask) 2032 mask = &rte_flow_item_tag_mask; 2033 if (!mask->data) 2034 return rte_flow_error_set(error, EINVAL, 2035 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, 2036 "mask cannot be zero"); 2037 2038 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2039 (const uint8_t *)&nic_mask, 2040 sizeof(struct rte_flow_item_tag), 2041 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2042 if (ret < 0) 2043 return ret; 2044 if (mask->index != 0xff) 2045 return rte_flow_error_set(error, EINVAL, 2046 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL, 2047 "partial mask for tag index" 2048 " is not supported"); 2049 ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, spec->index, error); 2050 if (ret < 0) 2051 return ret; 2052 MLX5_ASSERT(ret != REG_NON); 2053 return 0; 2054 } 2055 2056 /** 2057 * Validate vport item. 2058 * 2059 * @param[in] dev 2060 * Pointer to the rte_eth_dev structure. 2061 * @param[in] item 2062 * Item specification. 2063 * @param[in] attr 2064 * Attributes of flow that includes this item. 2065 * @param[in] item_flags 2066 * Bit-fields that holds the items detected until now. 2067 * @param[out] error 2068 * Pointer to error structure. 2069 * 2070 * @return 2071 * 0 on success, a negative errno value otherwise and rte_errno is set. 2072 */ 2073 static int 2074 flow_dv_validate_item_port_id(struct rte_eth_dev *dev, 2075 const struct rte_flow_item *item, 2076 const struct rte_flow_attr *attr, 2077 uint64_t item_flags, 2078 struct rte_flow_error *error) 2079 { 2080 const struct rte_flow_item_port_id *spec = item->spec; 2081 const struct rte_flow_item_port_id *mask = item->mask; 2082 const struct rte_flow_item_port_id switch_mask = { 2083 .id = 0xffffffff, 2084 }; 2085 struct mlx5_priv *esw_priv; 2086 struct mlx5_priv *dev_priv; 2087 int ret; 2088 2089 if (!attr->transfer) 2090 return rte_flow_error_set(error, EINVAL, 2091 RTE_FLOW_ERROR_TYPE_ITEM, 2092 NULL, 2093 "match on port id is valid only" 2094 " when transfer flag is enabled"); 2095 if (item_flags & MLX5_FLOW_ITEM_PORT_ID) 2096 return rte_flow_error_set(error, ENOTSUP, 2097 RTE_FLOW_ERROR_TYPE_ITEM, item, 2098 "multiple source ports are not" 2099 " supported"); 2100 if (!mask) 2101 mask = &switch_mask; 2102 if (mask->id != 0xffffffff) 2103 return rte_flow_error_set(error, ENOTSUP, 2104 RTE_FLOW_ERROR_TYPE_ITEM_MASK, 2105 mask, 2106 "no support for partial mask on" 2107 " \"id\" field"); 2108 ret = mlx5_flow_item_acceptable 2109 (item, (const uint8_t *)mask, 2110 (const uint8_t *)&rte_flow_item_port_id_mask, 2111 sizeof(struct rte_flow_item_port_id), 2112 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2113 if (ret) 2114 return ret; 2115 if (!spec) 2116 return 0; 2117 esw_priv = mlx5_port_to_eswitch_info(spec->id, false); 2118 if (!esw_priv) 2119 return rte_flow_error_set(error, rte_errno, 2120 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec, 2121 "failed to obtain E-Switch info for" 2122 " port"); 2123 dev_priv = mlx5_dev_to_eswitch_info(dev); 2124 if (!dev_priv) 2125 return rte_flow_error_set(error, rte_errno, 2126 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2127 NULL, 2128 "failed to obtain E-Switch info"); 2129 if (esw_priv->domain_id != dev_priv->domain_id) 2130 return rte_flow_error_set(error, EINVAL, 2131 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec, 2132 "cannot match on a port from a" 2133 " different E-Switch"); 2134 return 0; 2135 } 2136 2137 /** 2138 * Validate VLAN item. 2139 * 2140 * @param[in] item 2141 * Item specification. 2142 * @param[in] item_flags 2143 * Bit-fields that holds the items detected until now. 2144 * @param[in] dev 2145 * Ethernet device flow is being created on. 2146 * @param[out] error 2147 * Pointer to error structure. 2148 * 2149 * @return 2150 * 0 on success, a negative errno value otherwise and rte_errno is set. 2151 */ 2152 static int 2153 flow_dv_validate_item_vlan(const struct rte_flow_item *item, 2154 uint64_t item_flags, 2155 struct rte_eth_dev *dev, 2156 struct rte_flow_error *error) 2157 { 2158 const struct rte_flow_item_vlan *mask = item->mask; 2159 const struct rte_flow_item_vlan nic_mask = { 2160 .tci = RTE_BE16(UINT16_MAX), 2161 .inner_type = RTE_BE16(UINT16_MAX), 2162 .has_more_vlan = 1, 2163 }; 2164 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2165 int ret; 2166 const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 | 2167 MLX5_FLOW_LAYER_INNER_L4) : 2168 (MLX5_FLOW_LAYER_OUTER_L3 | 2169 MLX5_FLOW_LAYER_OUTER_L4); 2170 const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN : 2171 MLX5_FLOW_LAYER_OUTER_VLAN; 2172 2173 if (item_flags & vlanm) 2174 return rte_flow_error_set(error, EINVAL, 2175 RTE_FLOW_ERROR_TYPE_ITEM, item, 2176 "multiple VLAN layers not supported"); 2177 else if ((item_flags & l34m) != 0) 2178 return rte_flow_error_set(error, EINVAL, 2179 RTE_FLOW_ERROR_TYPE_ITEM, item, 2180 "VLAN cannot follow L3/L4 layer"); 2181 if (!mask) 2182 mask = &rte_flow_item_vlan_mask; 2183 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2184 (const uint8_t *)&nic_mask, 2185 sizeof(struct rte_flow_item_vlan), 2186 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2187 if (ret) 2188 return ret; 2189 if (!tunnel && mask->tci != RTE_BE16(0x0fff)) { 2190 struct mlx5_priv *priv = dev->data->dev_private; 2191 2192 if (priv->vmwa_context) { 2193 /* 2194 * Non-NULL context means we have a virtual machine 2195 * and SR-IOV enabled, we have to create VLAN interface 2196 * to make hypervisor to setup E-Switch vport 2197 * context correctly. We avoid creating the multiple 2198 * VLAN interfaces, so we cannot support VLAN tag mask. 2199 */ 2200 return rte_flow_error_set(error, EINVAL, 2201 RTE_FLOW_ERROR_TYPE_ITEM, 2202 item, 2203 "VLAN tag mask is not" 2204 " supported in virtual" 2205 " environment"); 2206 } 2207 } 2208 return 0; 2209 } 2210 2211 /* 2212 * GTP flags are contained in 1 byte of the format: 2213 * ------------------------------------------- 2214 * | bit | 0 - 2 | 3 | 4 | 5 | 6 | 7 | 2215 * |-----------------------------------------| 2216 * | value | Version | PT | Res | E | S | PN | 2217 * ------------------------------------------- 2218 * 2219 * Matching is supported only for GTP flags E, S, PN. 2220 */ 2221 #define MLX5_GTP_FLAGS_MASK 0x07 2222 2223 /** 2224 * Validate GTP item. 2225 * 2226 * @param[in] dev 2227 * Pointer to the rte_eth_dev structure. 2228 * @param[in] item 2229 * Item specification. 2230 * @param[in] item_flags 2231 * Bit-fields that holds the items detected until now. 2232 * @param[out] error 2233 * Pointer to error structure. 2234 * 2235 * @return 2236 * 0 on success, a negative errno value otherwise and rte_errno is set. 2237 */ 2238 static int 2239 flow_dv_validate_item_gtp(struct rte_eth_dev *dev, 2240 const struct rte_flow_item *item, 2241 uint64_t item_flags, 2242 struct rte_flow_error *error) 2243 { 2244 struct mlx5_priv *priv = dev->data->dev_private; 2245 const struct rte_flow_item_gtp *spec = item->spec; 2246 const struct rte_flow_item_gtp *mask = item->mask; 2247 const struct rte_flow_item_gtp nic_mask = { 2248 .v_pt_rsv_flags = MLX5_GTP_FLAGS_MASK, 2249 .msg_type = 0xff, 2250 .teid = RTE_BE32(0xffffffff), 2251 }; 2252 2253 if (!priv->config.hca_attr.tunnel_stateless_gtp) 2254 return rte_flow_error_set(error, ENOTSUP, 2255 RTE_FLOW_ERROR_TYPE_ITEM, item, 2256 "GTP support is not enabled"); 2257 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2258 return rte_flow_error_set(error, ENOTSUP, 2259 RTE_FLOW_ERROR_TYPE_ITEM, item, 2260 "multiple tunnel layers not" 2261 " supported"); 2262 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 2263 return rte_flow_error_set(error, EINVAL, 2264 RTE_FLOW_ERROR_TYPE_ITEM, item, 2265 "no outer UDP layer found"); 2266 if (!mask) 2267 mask = &rte_flow_item_gtp_mask; 2268 if (spec && spec->v_pt_rsv_flags & ~MLX5_GTP_FLAGS_MASK) 2269 return rte_flow_error_set(error, ENOTSUP, 2270 RTE_FLOW_ERROR_TYPE_ITEM, item, 2271 "Match is supported for GTP" 2272 " flags only"); 2273 return mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2274 (const uint8_t *)&nic_mask, 2275 sizeof(struct rte_flow_item_gtp), 2276 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2277 } 2278 2279 /** 2280 * Validate GTP PSC item. 2281 * 2282 * @param[in] item 2283 * Item specification. 2284 * @param[in] last_item 2285 * Previous validated item in the pattern items. 2286 * @param[in] gtp_item 2287 * Previous GTP item specification. 2288 * @param[in] attr 2289 * Pointer to flow attributes. 2290 * @param[out] error 2291 * Pointer to error structure. 2292 * 2293 * @return 2294 * 0 on success, a negative errno value otherwise and rte_errno is set. 2295 */ 2296 static int 2297 flow_dv_validate_item_gtp_psc(const struct rte_flow_item *item, 2298 uint64_t last_item, 2299 const struct rte_flow_item *gtp_item, 2300 const struct rte_flow_attr *attr, 2301 struct rte_flow_error *error) 2302 { 2303 const struct rte_flow_item_gtp *gtp_spec; 2304 const struct rte_flow_item_gtp *gtp_mask; 2305 const struct rte_flow_item_gtp_psc *spec; 2306 const struct rte_flow_item_gtp_psc *mask; 2307 const struct rte_flow_item_gtp_psc nic_mask = { 2308 .pdu_type = 0xFF, 2309 .qfi = 0xFF, 2310 }; 2311 2312 if (!gtp_item || !(last_item & MLX5_FLOW_LAYER_GTP)) 2313 return rte_flow_error_set 2314 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 2315 "GTP PSC item must be preceded with GTP item"); 2316 gtp_spec = gtp_item->spec; 2317 gtp_mask = gtp_item->mask ? gtp_item->mask : &rte_flow_item_gtp_mask; 2318 /* GTP spec and E flag is requested to match zero. */ 2319 if (gtp_spec && 2320 (gtp_mask->v_pt_rsv_flags & 2321 ~gtp_spec->v_pt_rsv_flags & MLX5_GTP_EXT_HEADER_FLAG)) 2322 return rte_flow_error_set 2323 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 2324 "GTP E flag must be 1 to match GTP PSC"); 2325 /* Check the flow is not created in group zero. */ 2326 if (!attr->transfer && !attr->group) 2327 return rte_flow_error_set 2328 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2329 "GTP PSC is not supported for group 0"); 2330 /* GTP spec is here and E flag is requested to match zero. */ 2331 if (!item->spec) 2332 return 0; 2333 spec = item->spec; 2334 mask = item->mask ? item->mask : &rte_flow_item_gtp_psc_mask; 2335 if (spec->pdu_type > MLX5_GTP_EXT_MAX_PDU_TYPE) 2336 return rte_flow_error_set 2337 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 2338 "PDU type should be smaller than 16"); 2339 return mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2340 (const uint8_t *)&nic_mask, 2341 sizeof(struct rte_flow_item_gtp_psc), 2342 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2343 } 2344 2345 /** 2346 * Validate IPV4 item. 2347 * Use existing validation function mlx5_flow_validate_item_ipv4(), and 2348 * add specific validation of fragment_offset field, 2349 * 2350 * @param[in] item 2351 * Item specification. 2352 * @param[in] item_flags 2353 * Bit-fields that holds the items detected until now. 2354 * @param[out] error 2355 * Pointer to error structure. 2356 * 2357 * @return 2358 * 0 on success, a negative errno value otherwise and rte_errno is set. 2359 */ 2360 static int 2361 flow_dv_validate_item_ipv4(const struct rte_flow_item *item, 2362 uint64_t item_flags, 2363 uint64_t last_item, 2364 uint16_t ether_type, 2365 struct rte_flow_error *error) 2366 { 2367 int ret; 2368 const struct rte_flow_item_ipv4 *spec = item->spec; 2369 const struct rte_flow_item_ipv4 *last = item->last; 2370 const struct rte_flow_item_ipv4 *mask = item->mask; 2371 rte_be16_t fragment_offset_spec = 0; 2372 rte_be16_t fragment_offset_last = 0; 2373 const struct rte_flow_item_ipv4 nic_ipv4_mask = { 2374 .hdr = { 2375 .src_addr = RTE_BE32(0xffffffff), 2376 .dst_addr = RTE_BE32(0xffffffff), 2377 .type_of_service = 0xff, 2378 .fragment_offset = RTE_BE16(0xffff), 2379 .next_proto_id = 0xff, 2380 .time_to_live = 0xff, 2381 }, 2382 }; 2383 2384 ret = mlx5_flow_validate_item_ipv4(item, item_flags, last_item, 2385 ether_type, &nic_ipv4_mask, 2386 MLX5_ITEM_RANGE_ACCEPTED, error); 2387 if (ret < 0) 2388 return ret; 2389 if (spec && mask) 2390 fragment_offset_spec = spec->hdr.fragment_offset & 2391 mask->hdr.fragment_offset; 2392 if (!fragment_offset_spec) 2393 return 0; 2394 /* 2395 * spec and mask are valid, enforce using full mask to make sure the 2396 * complete value is used correctly. 2397 */ 2398 if ((mask->hdr.fragment_offset & RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK)) 2399 != RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK)) 2400 return rte_flow_error_set(error, EINVAL, 2401 RTE_FLOW_ERROR_TYPE_ITEM_MASK, 2402 item, "must use full mask for" 2403 " fragment_offset"); 2404 /* 2405 * Match on fragment_offset 0x2000 means MF is 1 and frag-offset is 0, 2406 * indicating this is 1st fragment of fragmented packet. 2407 * This is not yet supported in MLX5, return appropriate error message. 2408 */ 2409 if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG)) 2410 return rte_flow_error_set(error, ENOTSUP, 2411 RTE_FLOW_ERROR_TYPE_ITEM, item, 2412 "match on first fragment not " 2413 "supported"); 2414 if (fragment_offset_spec && !last) 2415 return rte_flow_error_set(error, ENOTSUP, 2416 RTE_FLOW_ERROR_TYPE_ITEM, item, 2417 "specified value not supported"); 2418 /* spec and last are valid, validate the specified range. */ 2419 fragment_offset_last = last->hdr.fragment_offset & 2420 mask->hdr.fragment_offset; 2421 /* 2422 * Match on fragment_offset spec 0x2001 and last 0x3fff 2423 * means MF is 1 and frag-offset is > 0. 2424 * This packet is fragment 2nd and onward, excluding last. 2425 * This is not yet supported in MLX5, return appropriate 2426 * error message. 2427 */ 2428 if (fragment_offset_spec == RTE_BE16(RTE_IPV4_HDR_MF_FLAG + 1) && 2429 fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK)) 2430 return rte_flow_error_set(error, ENOTSUP, 2431 RTE_FLOW_ERROR_TYPE_ITEM_LAST, 2432 last, "match on following " 2433 "fragments not supported"); 2434 /* 2435 * Match on fragment_offset spec 0x0001 and last 0x1fff 2436 * means MF is 0 and frag-offset is > 0. 2437 * This packet is last fragment of fragmented packet. 2438 * This is not yet supported in MLX5, return appropriate 2439 * error message. 2440 */ 2441 if (fragment_offset_spec == RTE_BE16(1) && 2442 fragment_offset_last == RTE_BE16(RTE_IPV4_HDR_OFFSET_MASK)) 2443 return rte_flow_error_set(error, ENOTSUP, 2444 RTE_FLOW_ERROR_TYPE_ITEM_LAST, 2445 last, "match on last " 2446 "fragment not supported"); 2447 /* 2448 * Match on fragment_offset spec 0x0001 and last 0x3fff 2449 * means MF and/or frag-offset is not 0. 2450 * This is a fragmented packet. 2451 * Other range values are invalid and rejected. 2452 */ 2453 if (!(fragment_offset_spec == RTE_BE16(1) && 2454 fragment_offset_last == RTE_BE16(MLX5_IPV4_FRAG_OFFSET_MASK))) 2455 return rte_flow_error_set(error, ENOTSUP, 2456 RTE_FLOW_ERROR_TYPE_ITEM_LAST, last, 2457 "specified range not supported"); 2458 return 0; 2459 } 2460 2461 /** 2462 * Validate IPV6 fragment extension item. 2463 * 2464 * @param[in] item 2465 * Item specification. 2466 * @param[in] item_flags 2467 * Bit-fields that holds the items detected until now. 2468 * @param[out] error 2469 * Pointer to error structure. 2470 * 2471 * @return 2472 * 0 on success, a negative errno value otherwise and rte_errno is set. 2473 */ 2474 static int 2475 flow_dv_validate_item_ipv6_frag_ext(const struct rte_flow_item *item, 2476 uint64_t item_flags, 2477 struct rte_flow_error *error) 2478 { 2479 const struct rte_flow_item_ipv6_frag_ext *spec = item->spec; 2480 const struct rte_flow_item_ipv6_frag_ext *last = item->last; 2481 const struct rte_flow_item_ipv6_frag_ext *mask = item->mask; 2482 rte_be16_t frag_data_spec = 0; 2483 rte_be16_t frag_data_last = 0; 2484 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2485 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2486 MLX5_FLOW_LAYER_OUTER_L4; 2487 int ret = 0; 2488 struct rte_flow_item_ipv6_frag_ext nic_mask = { 2489 .hdr = { 2490 .next_header = 0xff, 2491 .frag_data = RTE_BE16(0xffff), 2492 }, 2493 }; 2494 2495 if (item_flags & l4m) 2496 return rte_flow_error_set(error, EINVAL, 2497 RTE_FLOW_ERROR_TYPE_ITEM, item, 2498 "ipv6 fragment extension item cannot " 2499 "follow L4 item."); 2500 if ((tunnel && !(item_flags & MLX5_FLOW_LAYER_INNER_L3_IPV6)) || 2501 (!tunnel && !(item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) 2502 return rte_flow_error_set(error, EINVAL, 2503 RTE_FLOW_ERROR_TYPE_ITEM, item, 2504 "ipv6 fragment extension item must " 2505 "follow ipv6 item"); 2506 if (spec && mask) 2507 frag_data_spec = spec->hdr.frag_data & mask->hdr.frag_data; 2508 if (!frag_data_spec) 2509 return 0; 2510 /* 2511 * spec and mask are valid, enforce using full mask to make sure the 2512 * complete value is used correctly. 2513 */ 2514 if ((mask->hdr.frag_data & RTE_BE16(RTE_IPV6_FRAG_USED_MASK)) != 2515 RTE_BE16(RTE_IPV6_FRAG_USED_MASK)) 2516 return rte_flow_error_set(error, EINVAL, 2517 RTE_FLOW_ERROR_TYPE_ITEM_MASK, 2518 item, "must use full mask for" 2519 " frag_data"); 2520 /* 2521 * Match on frag_data 0x00001 means M is 1 and frag-offset is 0. 2522 * This is 1st fragment of fragmented packet. 2523 */ 2524 if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_MF_MASK)) 2525 return rte_flow_error_set(error, ENOTSUP, 2526 RTE_FLOW_ERROR_TYPE_ITEM, item, 2527 "match on first fragment not " 2528 "supported"); 2529 if (frag_data_spec && !last) 2530 return rte_flow_error_set(error, EINVAL, 2531 RTE_FLOW_ERROR_TYPE_ITEM, item, 2532 "specified value not supported"); 2533 ret = mlx5_flow_item_acceptable 2534 (item, (const uint8_t *)mask, 2535 (const uint8_t *)&nic_mask, 2536 sizeof(struct rte_flow_item_ipv6_frag_ext), 2537 MLX5_ITEM_RANGE_ACCEPTED, error); 2538 if (ret) 2539 return ret; 2540 /* spec and last are valid, validate the specified range. */ 2541 frag_data_last = last->hdr.frag_data & mask->hdr.frag_data; 2542 /* 2543 * Match on frag_data spec 0x0009 and last 0xfff9 2544 * means M is 1 and frag-offset is > 0. 2545 * This packet is fragment 2nd and onward, excluding last. 2546 * This is not yet supported in MLX5, return appropriate 2547 * error message. 2548 */ 2549 if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN | 2550 RTE_IPV6_EHDR_MF_MASK) && 2551 frag_data_last == RTE_BE16(RTE_IPV6_FRAG_USED_MASK)) 2552 return rte_flow_error_set(error, ENOTSUP, 2553 RTE_FLOW_ERROR_TYPE_ITEM_LAST, 2554 last, "match on following " 2555 "fragments not supported"); 2556 /* 2557 * Match on frag_data spec 0x0008 and last 0xfff8 2558 * means M is 0 and frag-offset is > 0. 2559 * This packet is last fragment of fragmented packet. 2560 * This is not yet supported in MLX5, return appropriate 2561 * error message. 2562 */ 2563 if (frag_data_spec == RTE_BE16(RTE_IPV6_EHDR_FO_ALIGN) && 2564 frag_data_last == RTE_BE16(RTE_IPV6_EHDR_FO_MASK)) 2565 return rte_flow_error_set(error, ENOTSUP, 2566 RTE_FLOW_ERROR_TYPE_ITEM_LAST, 2567 last, "match on last " 2568 "fragment not supported"); 2569 /* Other range values are invalid and rejected. */ 2570 return rte_flow_error_set(error, EINVAL, 2571 RTE_FLOW_ERROR_TYPE_ITEM_LAST, last, 2572 "specified range not supported"); 2573 } 2574 2575 /** 2576 * Validate the pop VLAN action. 2577 * 2578 * @param[in] dev 2579 * Pointer to the rte_eth_dev structure. 2580 * @param[in] action_flags 2581 * Holds the actions detected until now. 2582 * @param[in] action 2583 * Pointer to the pop vlan action. 2584 * @param[in] item_flags 2585 * The items found in this flow rule. 2586 * @param[in] attr 2587 * Pointer to flow attributes. 2588 * @param[out] error 2589 * Pointer to error structure. 2590 * 2591 * @return 2592 * 0 on success, a negative errno value otherwise and rte_errno is set. 2593 */ 2594 static int 2595 flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev, 2596 uint64_t action_flags, 2597 const struct rte_flow_action *action, 2598 uint64_t item_flags, 2599 const struct rte_flow_attr *attr, 2600 struct rte_flow_error *error) 2601 { 2602 const struct mlx5_priv *priv = dev->data->dev_private; 2603 2604 (void)action; 2605 (void)attr; 2606 if (!priv->sh->pop_vlan_action) 2607 return rte_flow_error_set(error, ENOTSUP, 2608 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2609 NULL, 2610 "pop vlan action is not supported"); 2611 if (attr->egress) 2612 return rte_flow_error_set(error, ENOTSUP, 2613 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 2614 NULL, 2615 "pop vlan action not supported for " 2616 "egress"); 2617 if (action_flags & MLX5_FLOW_VLAN_ACTIONS) 2618 return rte_flow_error_set(error, ENOTSUP, 2619 RTE_FLOW_ERROR_TYPE_ACTION, action, 2620 "no support for multiple VLAN " 2621 "actions"); 2622 /* Pop VLAN with preceding Decap requires inner header with VLAN. */ 2623 if ((action_flags & MLX5_FLOW_ACTION_DECAP) && 2624 !(item_flags & MLX5_FLOW_LAYER_INNER_VLAN)) 2625 return rte_flow_error_set(error, ENOTSUP, 2626 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2627 NULL, 2628 "cannot pop vlan after decap without " 2629 "match on inner vlan in the flow"); 2630 /* Pop VLAN without preceding Decap requires outer header with VLAN. */ 2631 if (!(action_flags & MLX5_FLOW_ACTION_DECAP) && 2632 !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)) 2633 return rte_flow_error_set(error, ENOTSUP, 2634 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 2635 NULL, 2636 "cannot pop vlan without a " 2637 "match on (outer) vlan in the flow"); 2638 if (action_flags & MLX5_FLOW_ACTION_PORT_ID) 2639 return rte_flow_error_set(error, EINVAL, 2640 RTE_FLOW_ERROR_TYPE_ACTION, action, 2641 "wrong action order, port_id should " 2642 "be after pop VLAN action"); 2643 if (!attr->transfer && priv->representor) 2644 return rte_flow_error_set(error, ENOTSUP, 2645 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2646 "pop vlan action for VF representor " 2647 "not supported on NIC table"); 2648 return 0; 2649 } 2650 2651 /** 2652 * Get VLAN default info from vlan match info. 2653 * 2654 * @param[in] items 2655 * the list of item specifications. 2656 * @param[out] vlan 2657 * pointer VLAN info to fill to. 2658 * 2659 * @return 2660 * 0 on success, a negative errno value otherwise and rte_errno is set. 2661 */ 2662 static void 2663 flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items, 2664 struct rte_vlan_hdr *vlan) 2665 { 2666 const struct rte_flow_item_vlan nic_mask = { 2667 .tci = RTE_BE16(MLX5DV_FLOW_VLAN_PCP_MASK | 2668 MLX5DV_FLOW_VLAN_VID_MASK), 2669 .inner_type = RTE_BE16(0xffff), 2670 }; 2671 2672 if (items == NULL) 2673 return; 2674 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 2675 int type = items->type; 2676 2677 if (type == RTE_FLOW_ITEM_TYPE_VLAN || 2678 type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN) 2679 break; 2680 } 2681 if (items->type != RTE_FLOW_ITEM_TYPE_END) { 2682 const struct rte_flow_item_vlan *vlan_m = items->mask; 2683 const struct rte_flow_item_vlan *vlan_v = items->spec; 2684 2685 /* If VLAN item in pattern doesn't contain data, return here. */ 2686 if (!vlan_v) 2687 return; 2688 if (!vlan_m) 2689 vlan_m = &nic_mask; 2690 /* Only full match values are accepted */ 2691 if ((vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) == 2692 MLX5DV_FLOW_VLAN_PCP_MASK_BE) { 2693 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK; 2694 vlan->vlan_tci |= 2695 rte_be_to_cpu_16(vlan_v->tci & 2696 MLX5DV_FLOW_VLAN_PCP_MASK_BE); 2697 } 2698 if ((vlan_m->tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) == 2699 MLX5DV_FLOW_VLAN_VID_MASK_BE) { 2700 vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK; 2701 vlan->vlan_tci |= 2702 rte_be_to_cpu_16(vlan_v->tci & 2703 MLX5DV_FLOW_VLAN_VID_MASK_BE); 2704 } 2705 if (vlan_m->inner_type == nic_mask.inner_type) 2706 vlan->eth_proto = rte_be_to_cpu_16(vlan_v->inner_type & 2707 vlan_m->inner_type); 2708 } 2709 } 2710 2711 /** 2712 * Validate the push VLAN action. 2713 * 2714 * @param[in] dev 2715 * Pointer to the rte_eth_dev structure. 2716 * @param[in] action_flags 2717 * Holds the actions detected until now. 2718 * @param[in] item_flags 2719 * The items found in this flow rule. 2720 * @param[in] action 2721 * Pointer to the action structure. 2722 * @param[in] attr 2723 * Pointer to flow attributes 2724 * @param[out] error 2725 * Pointer to error structure. 2726 * 2727 * @return 2728 * 0 on success, a negative errno value otherwise and rte_errno is set. 2729 */ 2730 static int 2731 flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev, 2732 uint64_t action_flags, 2733 const struct rte_flow_item_vlan *vlan_m, 2734 const struct rte_flow_action *action, 2735 const struct rte_flow_attr *attr, 2736 struct rte_flow_error *error) 2737 { 2738 const struct rte_flow_action_of_push_vlan *push_vlan = action->conf; 2739 const struct mlx5_priv *priv = dev->data->dev_private; 2740 2741 if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) && 2742 push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ)) 2743 return rte_flow_error_set(error, EINVAL, 2744 RTE_FLOW_ERROR_TYPE_ACTION, action, 2745 "invalid vlan ethertype"); 2746 if (action_flags & MLX5_FLOW_ACTION_PORT_ID) 2747 return rte_flow_error_set(error, EINVAL, 2748 RTE_FLOW_ERROR_TYPE_ACTION, action, 2749 "wrong action order, port_id should " 2750 "be after push VLAN"); 2751 if (!attr->transfer && priv->representor) 2752 return rte_flow_error_set(error, ENOTSUP, 2753 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 2754 "push vlan action for VF representor " 2755 "not supported on NIC table"); 2756 if (vlan_m && 2757 (vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) && 2758 (vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) != 2759 MLX5DV_FLOW_VLAN_PCP_MASK_BE && 2760 !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) && 2761 !(mlx5_flow_find_action 2762 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP))) 2763 return rte_flow_error_set(error, EINVAL, 2764 RTE_FLOW_ERROR_TYPE_ACTION, action, 2765 "not full match mask on VLAN PCP and " 2766 "there is no of_set_vlan_pcp action, " 2767 "push VLAN action cannot figure out " 2768 "PCP value"); 2769 if (vlan_m && 2770 (vlan_m->tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) && 2771 (vlan_m->tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) != 2772 MLX5DV_FLOW_VLAN_VID_MASK_BE && 2773 !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) && 2774 !(mlx5_flow_find_action 2775 (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID))) 2776 return rte_flow_error_set(error, EINVAL, 2777 RTE_FLOW_ERROR_TYPE_ACTION, action, 2778 "not full match mask on VLAN VID and " 2779 "there is no of_set_vlan_vid action, " 2780 "push VLAN action cannot figure out " 2781 "VID value"); 2782 (void)attr; 2783 return 0; 2784 } 2785 2786 /** 2787 * Validate the set VLAN PCP. 2788 * 2789 * @param[in] action_flags 2790 * Holds the actions detected until now. 2791 * @param[in] actions 2792 * Pointer to the list of actions remaining in the flow rule. 2793 * @param[out] error 2794 * Pointer to error structure. 2795 * 2796 * @return 2797 * 0 on success, a negative errno value otherwise and rte_errno is set. 2798 */ 2799 static int 2800 flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags, 2801 const struct rte_flow_action actions[], 2802 struct rte_flow_error *error) 2803 { 2804 const struct rte_flow_action *action = actions; 2805 const struct rte_flow_action_of_set_vlan_pcp *conf = action->conf; 2806 2807 if (conf->vlan_pcp > 7) 2808 return rte_flow_error_set(error, EINVAL, 2809 RTE_FLOW_ERROR_TYPE_ACTION, action, 2810 "VLAN PCP value is too big"); 2811 if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)) 2812 return rte_flow_error_set(error, ENOTSUP, 2813 RTE_FLOW_ERROR_TYPE_ACTION, action, 2814 "set VLAN PCP action must follow " 2815 "the push VLAN action"); 2816 if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) 2817 return rte_flow_error_set(error, ENOTSUP, 2818 RTE_FLOW_ERROR_TYPE_ACTION, action, 2819 "Multiple VLAN PCP modification are " 2820 "not supported"); 2821 if (action_flags & MLX5_FLOW_ACTION_PORT_ID) 2822 return rte_flow_error_set(error, EINVAL, 2823 RTE_FLOW_ERROR_TYPE_ACTION, action, 2824 "wrong action order, port_id should " 2825 "be after set VLAN PCP"); 2826 return 0; 2827 } 2828 2829 /** 2830 * Validate the set VLAN VID. 2831 * 2832 * @param[in] item_flags 2833 * Holds the items detected in this rule. 2834 * @param[in] action_flags 2835 * Holds the actions detected until now. 2836 * @param[in] actions 2837 * Pointer to the list of actions remaining in the flow rule. 2838 * @param[out] error 2839 * Pointer to error structure. 2840 * 2841 * @return 2842 * 0 on success, a negative errno value otherwise and rte_errno is set. 2843 */ 2844 static int 2845 flow_dv_validate_action_set_vlan_vid(uint64_t item_flags, 2846 uint64_t action_flags, 2847 const struct rte_flow_action actions[], 2848 struct rte_flow_error *error) 2849 { 2850 const struct rte_flow_action *action = actions; 2851 const struct rte_flow_action_of_set_vlan_vid *conf = action->conf; 2852 2853 if (rte_be_to_cpu_16(conf->vlan_vid) > 0xFFE) 2854 return rte_flow_error_set(error, EINVAL, 2855 RTE_FLOW_ERROR_TYPE_ACTION, action, 2856 "VLAN VID value is too big"); 2857 if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) && 2858 !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)) 2859 return rte_flow_error_set(error, ENOTSUP, 2860 RTE_FLOW_ERROR_TYPE_ACTION, action, 2861 "set VLAN VID action must follow push" 2862 " VLAN action or match on VLAN item"); 2863 if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) 2864 return rte_flow_error_set(error, ENOTSUP, 2865 RTE_FLOW_ERROR_TYPE_ACTION, action, 2866 "Multiple VLAN VID modifications are " 2867 "not supported"); 2868 if (action_flags & MLX5_FLOW_ACTION_PORT_ID) 2869 return rte_flow_error_set(error, EINVAL, 2870 RTE_FLOW_ERROR_TYPE_ACTION, action, 2871 "wrong action order, port_id should " 2872 "be after set VLAN VID"); 2873 return 0; 2874 } 2875 2876 /* 2877 * Validate the FLAG action. 2878 * 2879 * @param[in] dev 2880 * Pointer to the rte_eth_dev structure. 2881 * @param[in] action_flags 2882 * Holds the actions detected until now. 2883 * @param[in] attr 2884 * Pointer to flow attributes 2885 * @param[out] error 2886 * Pointer to error structure. 2887 * 2888 * @return 2889 * 0 on success, a negative errno value otherwise and rte_errno is set. 2890 */ 2891 static int 2892 flow_dv_validate_action_flag(struct rte_eth_dev *dev, 2893 uint64_t action_flags, 2894 const struct rte_flow_attr *attr, 2895 struct rte_flow_error *error) 2896 { 2897 struct mlx5_priv *priv = dev->data->dev_private; 2898 struct mlx5_dev_config *config = &priv->config; 2899 int ret; 2900 2901 /* Fall back if no extended metadata register support. */ 2902 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY) 2903 return mlx5_flow_validate_action_flag(action_flags, attr, 2904 error); 2905 /* Extensive metadata mode requires registers. */ 2906 if (!mlx5_flow_ext_mreg_supported(dev)) 2907 return rte_flow_error_set(error, ENOTSUP, 2908 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2909 "no metadata registers " 2910 "to support flag action"); 2911 if (!(priv->sh->dv_mark_mask & MLX5_FLOW_MARK_DEFAULT)) 2912 return rte_flow_error_set(error, ENOTSUP, 2913 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2914 "extended metadata register" 2915 " isn't available"); 2916 ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 2917 if (ret < 0) 2918 return ret; 2919 MLX5_ASSERT(ret > 0); 2920 if (action_flags & MLX5_FLOW_ACTION_MARK) 2921 return rte_flow_error_set(error, EINVAL, 2922 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2923 "can't mark and flag in same flow"); 2924 if (action_flags & MLX5_FLOW_ACTION_FLAG) 2925 return rte_flow_error_set(error, EINVAL, 2926 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2927 "can't have 2 flag" 2928 " actions in same flow"); 2929 return 0; 2930 } 2931 2932 /** 2933 * Validate MARK action. 2934 * 2935 * @param[in] dev 2936 * Pointer to the rte_eth_dev structure. 2937 * @param[in] action 2938 * Pointer to action. 2939 * @param[in] action_flags 2940 * Holds the actions detected until now. 2941 * @param[in] attr 2942 * Pointer to flow attributes 2943 * @param[out] error 2944 * Pointer to error structure. 2945 * 2946 * @return 2947 * 0 on success, a negative errno value otherwise and rte_errno is set. 2948 */ 2949 static int 2950 flow_dv_validate_action_mark(struct rte_eth_dev *dev, 2951 const struct rte_flow_action *action, 2952 uint64_t action_flags, 2953 const struct rte_flow_attr *attr, 2954 struct rte_flow_error *error) 2955 { 2956 struct mlx5_priv *priv = dev->data->dev_private; 2957 struct mlx5_dev_config *config = &priv->config; 2958 const struct rte_flow_action_mark *mark = action->conf; 2959 int ret; 2960 2961 if (is_tunnel_offload_active(dev)) 2962 return rte_flow_error_set(error, ENOTSUP, 2963 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2964 "no mark action " 2965 "if tunnel offload active"); 2966 /* Fall back if no extended metadata register support. */ 2967 if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY) 2968 return mlx5_flow_validate_action_mark(action, action_flags, 2969 attr, error); 2970 /* Extensive metadata mode requires registers. */ 2971 if (!mlx5_flow_ext_mreg_supported(dev)) 2972 return rte_flow_error_set(error, ENOTSUP, 2973 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2974 "no metadata registers " 2975 "to support mark action"); 2976 if (!priv->sh->dv_mark_mask) 2977 return rte_flow_error_set(error, ENOTSUP, 2978 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2979 "extended metadata register" 2980 " isn't available"); 2981 ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 2982 if (ret < 0) 2983 return ret; 2984 MLX5_ASSERT(ret > 0); 2985 if (!mark) 2986 return rte_flow_error_set(error, EINVAL, 2987 RTE_FLOW_ERROR_TYPE_ACTION, action, 2988 "configuration cannot be null"); 2989 if (mark->id >= (MLX5_FLOW_MARK_MAX & priv->sh->dv_mark_mask)) 2990 return rte_flow_error_set(error, EINVAL, 2991 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 2992 &mark->id, 2993 "mark id exceeds the limit"); 2994 if (action_flags & MLX5_FLOW_ACTION_FLAG) 2995 return rte_flow_error_set(error, EINVAL, 2996 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2997 "can't flag and mark in same flow"); 2998 if (action_flags & MLX5_FLOW_ACTION_MARK) 2999 return rte_flow_error_set(error, EINVAL, 3000 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3001 "can't have 2 mark actions in same" 3002 " flow"); 3003 return 0; 3004 } 3005 3006 /** 3007 * Validate SET_META action. 3008 * 3009 * @param[in] dev 3010 * Pointer to the rte_eth_dev structure. 3011 * @param[in] action 3012 * Pointer to the action structure. 3013 * @param[in] action_flags 3014 * Holds the actions detected until now. 3015 * @param[in] attr 3016 * Pointer to flow attributes 3017 * @param[out] error 3018 * Pointer to error structure. 3019 * 3020 * @return 3021 * 0 on success, a negative errno value otherwise and rte_errno is set. 3022 */ 3023 static int 3024 flow_dv_validate_action_set_meta(struct rte_eth_dev *dev, 3025 const struct rte_flow_action *action, 3026 uint64_t action_flags __rte_unused, 3027 const struct rte_flow_attr *attr, 3028 struct rte_flow_error *error) 3029 { 3030 const struct rte_flow_action_set_meta *conf; 3031 uint32_t nic_mask = UINT32_MAX; 3032 int reg; 3033 3034 if (!mlx5_flow_ext_mreg_supported(dev)) 3035 return rte_flow_error_set(error, ENOTSUP, 3036 RTE_FLOW_ERROR_TYPE_ACTION, action, 3037 "extended metadata register" 3038 " isn't supported"); 3039 reg = flow_dv_get_metadata_reg(dev, attr, error); 3040 if (reg < 0) 3041 return reg; 3042 if (reg == REG_NON) 3043 return rte_flow_error_set(error, ENOTSUP, 3044 RTE_FLOW_ERROR_TYPE_ACTION, action, 3045 "unavalable extended metadata register"); 3046 if (reg != REG_A && reg != REG_B) { 3047 struct mlx5_priv *priv = dev->data->dev_private; 3048 3049 nic_mask = priv->sh->dv_meta_mask; 3050 } 3051 if (!(action->conf)) 3052 return rte_flow_error_set(error, EINVAL, 3053 RTE_FLOW_ERROR_TYPE_ACTION, action, 3054 "configuration cannot be null"); 3055 conf = (const struct rte_flow_action_set_meta *)action->conf; 3056 if (!conf->mask) 3057 return rte_flow_error_set(error, EINVAL, 3058 RTE_FLOW_ERROR_TYPE_ACTION, action, 3059 "zero mask doesn't have any effect"); 3060 if (conf->mask & ~nic_mask) 3061 return rte_flow_error_set(error, EINVAL, 3062 RTE_FLOW_ERROR_TYPE_ACTION, action, 3063 "meta data must be within reg C0"); 3064 return 0; 3065 } 3066 3067 /** 3068 * Validate SET_TAG action. 3069 * 3070 * @param[in] dev 3071 * Pointer to the rte_eth_dev structure. 3072 * @param[in] action 3073 * Pointer to the action structure. 3074 * @param[in] action_flags 3075 * Holds the actions detected until now. 3076 * @param[in] attr 3077 * Pointer to flow attributes 3078 * @param[out] error 3079 * Pointer to error structure. 3080 * 3081 * @return 3082 * 0 on success, a negative errno value otherwise and rte_errno is set. 3083 */ 3084 static int 3085 flow_dv_validate_action_set_tag(struct rte_eth_dev *dev, 3086 const struct rte_flow_action *action, 3087 uint64_t action_flags, 3088 const struct rte_flow_attr *attr, 3089 struct rte_flow_error *error) 3090 { 3091 const struct rte_flow_action_set_tag *conf; 3092 const uint64_t terminal_action_flags = 3093 MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | 3094 MLX5_FLOW_ACTION_RSS; 3095 int ret; 3096 3097 if (!mlx5_flow_ext_mreg_supported(dev)) 3098 return rte_flow_error_set(error, ENOTSUP, 3099 RTE_FLOW_ERROR_TYPE_ACTION, action, 3100 "extensive metadata register" 3101 " isn't supported"); 3102 if (!(action->conf)) 3103 return rte_flow_error_set(error, EINVAL, 3104 RTE_FLOW_ERROR_TYPE_ACTION, action, 3105 "configuration cannot be null"); 3106 conf = (const struct rte_flow_action_set_tag *)action->conf; 3107 if (!conf->mask) 3108 return rte_flow_error_set(error, EINVAL, 3109 RTE_FLOW_ERROR_TYPE_ACTION, action, 3110 "zero mask doesn't have any effect"); 3111 ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, conf->index, error); 3112 if (ret < 0) 3113 return ret; 3114 if (!attr->transfer && attr->ingress && 3115 (action_flags & terminal_action_flags)) 3116 return rte_flow_error_set(error, EINVAL, 3117 RTE_FLOW_ERROR_TYPE_ACTION, action, 3118 "set_tag has no effect" 3119 " with terminal actions"); 3120 return 0; 3121 } 3122 3123 /** 3124 * Validate count action. 3125 * 3126 * @param[in] dev 3127 * Pointer to rte_eth_dev structure. 3128 * @param[in] action 3129 * Pointer to the action structure. 3130 * @param[in] action_flags 3131 * Holds the actions detected until now. 3132 * @param[out] error 3133 * Pointer to error structure. 3134 * 3135 * @return 3136 * 0 on success, a negative errno value otherwise and rte_errno is set. 3137 */ 3138 static int 3139 flow_dv_validate_action_count(struct rte_eth_dev *dev, 3140 const struct rte_flow_action *action, 3141 uint64_t action_flags, 3142 struct rte_flow_error *error) 3143 { 3144 struct mlx5_priv *priv = dev->data->dev_private; 3145 const struct rte_flow_action_count *count; 3146 3147 if (!priv->config.devx) 3148 goto notsup_err; 3149 if (action_flags & MLX5_FLOW_ACTION_COUNT) 3150 return rte_flow_error_set(error, EINVAL, 3151 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3152 "duplicate count actions set"); 3153 count = (const struct rte_flow_action_count *)action->conf; 3154 if (count && count->shared && (action_flags & MLX5_FLOW_ACTION_AGE) && 3155 !priv->sh->flow_hit_aso_en) 3156 return rte_flow_error_set(error, EINVAL, 3157 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3158 "old age and shared count combination is not supported"); 3159 #ifdef HAVE_IBV_FLOW_DEVX_COUNTERS 3160 return 0; 3161 #endif 3162 notsup_err: 3163 return rte_flow_error_set 3164 (error, ENOTSUP, 3165 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 3166 NULL, 3167 "count action not supported"); 3168 } 3169 3170 /** 3171 * Validate the L2 encap action. 3172 * 3173 * @param[in] dev 3174 * Pointer to the rte_eth_dev structure. 3175 * @param[in] action_flags 3176 * Holds the actions detected until now. 3177 * @param[in] action 3178 * Pointer to the action structure. 3179 * @param[in] attr 3180 * Pointer to flow attributes. 3181 * @param[out] error 3182 * Pointer to error structure. 3183 * 3184 * @return 3185 * 0 on success, a negative errno value otherwise and rte_errno is set. 3186 */ 3187 static int 3188 flow_dv_validate_action_l2_encap(struct rte_eth_dev *dev, 3189 uint64_t action_flags, 3190 const struct rte_flow_action *action, 3191 const struct rte_flow_attr *attr, 3192 struct rte_flow_error *error) 3193 { 3194 const struct mlx5_priv *priv = dev->data->dev_private; 3195 3196 if (!(action->conf)) 3197 return rte_flow_error_set(error, EINVAL, 3198 RTE_FLOW_ERROR_TYPE_ACTION, action, 3199 "configuration cannot be null"); 3200 if (action_flags & MLX5_FLOW_ACTION_ENCAP) 3201 return rte_flow_error_set(error, EINVAL, 3202 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3203 "can only have a single encap action " 3204 "in a flow"); 3205 if (!attr->transfer && priv->representor) 3206 return rte_flow_error_set(error, ENOTSUP, 3207 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3208 "encap action for VF representor " 3209 "not supported on NIC table"); 3210 return 0; 3211 } 3212 3213 /** 3214 * Validate a decap action. 3215 * 3216 * @param[in] dev 3217 * Pointer to the rte_eth_dev structure. 3218 * @param[in] action_flags 3219 * Holds the actions detected until now. 3220 * @param[in] action 3221 * Pointer to the action structure. 3222 * @param[in] item_flags 3223 * Holds the items detected. 3224 * @param[in] attr 3225 * Pointer to flow attributes 3226 * @param[out] error 3227 * Pointer to error structure. 3228 * 3229 * @return 3230 * 0 on success, a negative errno value otherwise and rte_errno is set. 3231 */ 3232 static int 3233 flow_dv_validate_action_decap(struct rte_eth_dev *dev, 3234 uint64_t action_flags, 3235 const struct rte_flow_action *action, 3236 const uint64_t item_flags, 3237 const struct rte_flow_attr *attr, 3238 struct rte_flow_error *error) 3239 { 3240 const struct mlx5_priv *priv = dev->data->dev_private; 3241 3242 if (priv->config.hca_attr.scatter_fcs_w_decap_disable && 3243 !priv->config.decap_en) 3244 return rte_flow_error_set(error, ENOTSUP, 3245 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3246 "decap is not enabled"); 3247 if (action_flags & MLX5_FLOW_XCAP_ACTIONS) 3248 return rte_flow_error_set(error, ENOTSUP, 3249 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3250 action_flags & 3251 MLX5_FLOW_ACTION_DECAP ? "can only " 3252 "have a single decap action" : "decap " 3253 "after encap is not supported"); 3254 if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS) 3255 return rte_flow_error_set(error, EINVAL, 3256 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3257 "can't have decap action after" 3258 " modify action"); 3259 if (attr->egress) 3260 return rte_flow_error_set(error, ENOTSUP, 3261 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, 3262 NULL, 3263 "decap action not supported for " 3264 "egress"); 3265 if (!attr->transfer && priv->representor) 3266 return rte_flow_error_set(error, ENOTSUP, 3267 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3268 "decap action for VF representor " 3269 "not supported on NIC table"); 3270 if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP && 3271 !(item_flags & MLX5_FLOW_LAYER_VXLAN)) 3272 return rte_flow_error_set(error, ENOTSUP, 3273 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3274 "VXLAN item should be present for VXLAN decap"); 3275 return 0; 3276 } 3277 3278 const struct rte_flow_action_raw_decap empty_decap = {.data = NULL, .size = 0,}; 3279 3280 /** 3281 * Validate the raw encap and decap actions. 3282 * 3283 * @param[in] dev 3284 * Pointer to the rte_eth_dev structure. 3285 * @param[in] decap 3286 * Pointer to the decap action. 3287 * @param[in] encap 3288 * Pointer to the encap action. 3289 * @param[in] attr 3290 * Pointer to flow attributes 3291 * @param[in/out] action_flags 3292 * Holds the actions detected until now. 3293 * @param[out] actions_n 3294 * pointer to the number of actions counter. 3295 * @param[in] action 3296 * Pointer to the action structure. 3297 * @param[in] item_flags 3298 * Holds the items detected. 3299 * @param[out] error 3300 * Pointer to error structure. 3301 * 3302 * @return 3303 * 0 on success, a negative errno value otherwise and rte_errno is set. 3304 */ 3305 static int 3306 flow_dv_validate_action_raw_encap_decap 3307 (struct rte_eth_dev *dev, 3308 const struct rte_flow_action_raw_decap *decap, 3309 const struct rte_flow_action_raw_encap *encap, 3310 const struct rte_flow_attr *attr, uint64_t *action_flags, 3311 int *actions_n, const struct rte_flow_action *action, 3312 uint64_t item_flags, struct rte_flow_error *error) 3313 { 3314 const struct mlx5_priv *priv = dev->data->dev_private; 3315 int ret; 3316 3317 if (encap && (!encap->size || !encap->data)) 3318 return rte_flow_error_set(error, EINVAL, 3319 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 3320 "raw encap data cannot be empty"); 3321 if (decap && encap) { 3322 if (decap->size <= MLX5_ENCAPSULATION_DECISION_SIZE && 3323 encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 3324 /* L3 encap. */ 3325 decap = NULL; 3326 else if (encap->size <= 3327 MLX5_ENCAPSULATION_DECISION_SIZE && 3328 decap->size > 3329 MLX5_ENCAPSULATION_DECISION_SIZE) 3330 /* L3 decap. */ 3331 encap = NULL; 3332 else if (encap->size > 3333 MLX5_ENCAPSULATION_DECISION_SIZE && 3334 decap->size > 3335 MLX5_ENCAPSULATION_DECISION_SIZE) 3336 /* 2 L2 actions: encap and decap. */ 3337 ; 3338 else 3339 return rte_flow_error_set(error, 3340 ENOTSUP, 3341 RTE_FLOW_ERROR_TYPE_ACTION, 3342 NULL, "unsupported too small " 3343 "raw decap and too small raw " 3344 "encap combination"); 3345 } 3346 if (decap) { 3347 ret = flow_dv_validate_action_decap(dev, *action_flags, action, 3348 item_flags, attr, error); 3349 if (ret < 0) 3350 return ret; 3351 *action_flags |= MLX5_FLOW_ACTION_DECAP; 3352 ++(*actions_n); 3353 } 3354 if (encap) { 3355 if (encap->size <= MLX5_ENCAPSULATION_DECISION_SIZE) 3356 return rte_flow_error_set(error, ENOTSUP, 3357 RTE_FLOW_ERROR_TYPE_ACTION, 3358 NULL, 3359 "small raw encap size"); 3360 if (*action_flags & MLX5_FLOW_ACTION_ENCAP) 3361 return rte_flow_error_set(error, EINVAL, 3362 RTE_FLOW_ERROR_TYPE_ACTION, 3363 NULL, 3364 "more than one encap action"); 3365 if (!attr->transfer && priv->representor) 3366 return rte_flow_error_set 3367 (error, ENOTSUP, 3368 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3369 "encap action for VF representor " 3370 "not supported on NIC table"); 3371 *action_flags |= MLX5_FLOW_ACTION_ENCAP; 3372 ++(*actions_n); 3373 } 3374 return 0; 3375 } 3376 3377 /** 3378 * Match encap_decap resource. 3379 * 3380 * @param list 3381 * Pointer to the hash list. 3382 * @param entry 3383 * Pointer to exist resource entry object. 3384 * @param key 3385 * Key of the new entry. 3386 * @param ctx_cb 3387 * Pointer to new encap_decap resource. 3388 * 3389 * @return 3390 * 0 on matching, none-zero otherwise. 3391 */ 3392 int 3393 flow_dv_encap_decap_match_cb(struct mlx5_hlist *list __rte_unused, 3394 struct mlx5_hlist_entry *entry, 3395 uint64_t key __rte_unused, void *cb_ctx) 3396 { 3397 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3398 struct mlx5_flow_dv_encap_decap_resource *resource = ctx->data; 3399 struct mlx5_flow_dv_encap_decap_resource *cache_resource; 3400 3401 cache_resource = container_of(entry, 3402 struct mlx5_flow_dv_encap_decap_resource, 3403 entry); 3404 if (resource->reformat_type == cache_resource->reformat_type && 3405 resource->ft_type == cache_resource->ft_type && 3406 resource->flags == cache_resource->flags && 3407 resource->size == cache_resource->size && 3408 !memcmp((const void *)resource->buf, 3409 (const void *)cache_resource->buf, 3410 resource->size)) 3411 return 0; 3412 return -1; 3413 } 3414 3415 /** 3416 * Allocate encap_decap resource. 3417 * 3418 * @param list 3419 * Pointer to the hash list. 3420 * @param entry 3421 * Pointer to exist resource entry object. 3422 * @param ctx_cb 3423 * Pointer to new encap_decap resource. 3424 * 3425 * @return 3426 * 0 on matching, none-zero otherwise. 3427 */ 3428 struct mlx5_hlist_entry * 3429 flow_dv_encap_decap_create_cb(struct mlx5_hlist *list, 3430 uint64_t key __rte_unused, 3431 void *cb_ctx) 3432 { 3433 struct mlx5_dev_ctx_shared *sh = list->ctx; 3434 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3435 struct mlx5dv_dr_domain *domain; 3436 struct mlx5_flow_dv_encap_decap_resource *resource = ctx->data; 3437 struct mlx5_flow_dv_encap_decap_resource *cache_resource; 3438 uint32_t idx; 3439 int ret; 3440 3441 if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) 3442 domain = sh->fdb_domain; 3443 else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX) 3444 domain = sh->rx_domain; 3445 else 3446 domain = sh->tx_domain; 3447 /* Register new encap/decap resource. */ 3448 cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], 3449 &idx); 3450 if (!cache_resource) { 3451 rte_flow_error_set(ctx->error, ENOMEM, 3452 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3453 "cannot allocate resource memory"); 3454 return NULL; 3455 } 3456 *cache_resource = *resource; 3457 cache_resource->idx = idx; 3458 ret = mlx5_flow_os_create_flow_action_packet_reformat 3459 (sh->ctx, domain, cache_resource, 3460 &cache_resource->action); 3461 if (ret) { 3462 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], idx); 3463 rte_flow_error_set(ctx->error, ENOMEM, 3464 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 3465 NULL, "cannot create action"); 3466 return NULL; 3467 } 3468 3469 return &cache_resource->entry; 3470 } 3471 3472 /** 3473 * Find existing encap/decap resource or create and register a new one. 3474 * 3475 * @param[in, out] dev 3476 * Pointer to rte_eth_dev structure. 3477 * @param[in, out] resource 3478 * Pointer to encap/decap resource. 3479 * @parm[in, out] dev_flow 3480 * Pointer to the dev_flow. 3481 * @param[out] error 3482 * pointer to error structure. 3483 * 3484 * @return 3485 * 0 on success otherwise -errno and errno is set. 3486 */ 3487 static int 3488 flow_dv_encap_decap_resource_register 3489 (struct rte_eth_dev *dev, 3490 struct mlx5_flow_dv_encap_decap_resource *resource, 3491 struct mlx5_flow *dev_flow, 3492 struct rte_flow_error *error) 3493 { 3494 struct mlx5_priv *priv = dev->data->dev_private; 3495 struct mlx5_dev_ctx_shared *sh = priv->sh; 3496 struct mlx5_hlist_entry *entry; 3497 union { 3498 struct { 3499 uint32_t ft_type:8; 3500 uint32_t refmt_type:8; 3501 /* 3502 * Header reformat actions can be shared between 3503 * non-root tables. One bit to indicate non-root 3504 * table or not. 3505 */ 3506 uint32_t is_root:1; 3507 uint32_t reserve:15; 3508 }; 3509 uint32_t v32; 3510 } encap_decap_key = { 3511 { 3512 .ft_type = resource->ft_type, 3513 .refmt_type = resource->reformat_type, 3514 .is_root = !!dev_flow->dv.group, 3515 .reserve = 0, 3516 } 3517 }; 3518 struct mlx5_flow_cb_ctx ctx = { 3519 .error = error, 3520 .data = resource, 3521 }; 3522 uint64_t key64; 3523 3524 resource->flags = dev_flow->dv.group ? 0 : 1; 3525 key64 = __rte_raw_cksum(&encap_decap_key.v32, 3526 sizeof(encap_decap_key.v32), 0); 3527 if (resource->reformat_type != 3528 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 && 3529 resource->size) 3530 key64 = __rte_raw_cksum(resource->buf, resource->size, key64); 3531 entry = mlx5_hlist_register(sh->encaps_decaps, key64, &ctx); 3532 if (!entry) 3533 return -rte_errno; 3534 resource = container_of(entry, typeof(*resource), entry); 3535 dev_flow->dv.encap_decap = resource; 3536 dev_flow->handle->dvh.rix_encap_decap = resource->idx; 3537 return 0; 3538 } 3539 3540 /** 3541 * Find existing table jump resource or create and register a new one. 3542 * 3543 * @param[in, out] dev 3544 * Pointer to rte_eth_dev structure. 3545 * @param[in, out] tbl 3546 * Pointer to flow table resource. 3547 * @parm[in, out] dev_flow 3548 * Pointer to the dev_flow. 3549 * @param[out] error 3550 * pointer to error structure. 3551 * 3552 * @return 3553 * 0 on success otherwise -errno and errno is set. 3554 */ 3555 static int 3556 flow_dv_jump_tbl_resource_register 3557 (struct rte_eth_dev *dev __rte_unused, 3558 struct mlx5_flow_tbl_resource *tbl, 3559 struct mlx5_flow *dev_flow, 3560 struct rte_flow_error *error __rte_unused) 3561 { 3562 struct mlx5_flow_tbl_data_entry *tbl_data = 3563 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl); 3564 3565 MLX5_ASSERT(tbl); 3566 MLX5_ASSERT(tbl_data->jump.action); 3567 dev_flow->handle->rix_jump = tbl_data->idx; 3568 dev_flow->dv.jump = &tbl_data->jump; 3569 return 0; 3570 } 3571 3572 int 3573 flow_dv_port_id_match_cb(struct mlx5_cache_list *list __rte_unused, 3574 struct mlx5_cache_entry *entry, void *cb_ctx) 3575 { 3576 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3577 struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data; 3578 struct mlx5_flow_dv_port_id_action_resource *res = 3579 container_of(entry, typeof(*res), entry); 3580 3581 return ref->port_id != res->port_id; 3582 } 3583 3584 struct mlx5_cache_entry * 3585 flow_dv_port_id_create_cb(struct mlx5_cache_list *list, 3586 struct mlx5_cache_entry *entry __rte_unused, 3587 void *cb_ctx) 3588 { 3589 struct mlx5_dev_ctx_shared *sh = list->ctx; 3590 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3591 struct mlx5_flow_dv_port_id_action_resource *ref = ctx->data; 3592 struct mlx5_flow_dv_port_id_action_resource *cache; 3593 uint32_t idx; 3594 int ret; 3595 3596 /* Register new port id action resource. */ 3597 cache = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID], &idx); 3598 if (!cache) { 3599 rte_flow_error_set(ctx->error, ENOMEM, 3600 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3601 "cannot allocate port_id action cache memory"); 3602 return NULL; 3603 } 3604 *cache = *ref; 3605 ret = mlx5_flow_os_create_flow_action_dest_port(sh->fdb_domain, 3606 ref->port_id, 3607 &cache->action); 3608 if (ret) { 3609 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], idx); 3610 rte_flow_error_set(ctx->error, ENOMEM, 3611 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3612 "cannot create action"); 3613 return NULL; 3614 } 3615 return &cache->entry; 3616 } 3617 3618 /** 3619 * Find existing table port ID resource or create and register a new one. 3620 * 3621 * @param[in, out] dev 3622 * Pointer to rte_eth_dev structure. 3623 * @param[in, out] resource 3624 * Pointer to port ID action resource. 3625 * @parm[in, out] dev_flow 3626 * Pointer to the dev_flow. 3627 * @param[out] error 3628 * pointer to error structure. 3629 * 3630 * @return 3631 * 0 on success otherwise -errno and errno is set. 3632 */ 3633 static int 3634 flow_dv_port_id_action_resource_register 3635 (struct rte_eth_dev *dev, 3636 struct mlx5_flow_dv_port_id_action_resource *resource, 3637 struct mlx5_flow *dev_flow, 3638 struct rte_flow_error *error) 3639 { 3640 struct mlx5_priv *priv = dev->data->dev_private; 3641 struct mlx5_cache_entry *entry; 3642 struct mlx5_flow_dv_port_id_action_resource *cache; 3643 struct mlx5_flow_cb_ctx ctx = { 3644 .error = error, 3645 .data = resource, 3646 }; 3647 3648 entry = mlx5_cache_register(&priv->sh->port_id_action_list, &ctx); 3649 if (!entry) 3650 return -rte_errno; 3651 cache = container_of(entry, typeof(*cache), entry); 3652 dev_flow->dv.port_id_action = cache; 3653 dev_flow->handle->rix_port_id_action = cache->idx; 3654 return 0; 3655 } 3656 3657 int 3658 flow_dv_push_vlan_match_cb(struct mlx5_cache_list *list __rte_unused, 3659 struct mlx5_cache_entry *entry, void *cb_ctx) 3660 { 3661 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3662 struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data; 3663 struct mlx5_flow_dv_push_vlan_action_resource *res = 3664 container_of(entry, typeof(*res), entry); 3665 3666 return ref->vlan_tag != res->vlan_tag || ref->ft_type != res->ft_type; 3667 } 3668 3669 struct mlx5_cache_entry * 3670 flow_dv_push_vlan_create_cb(struct mlx5_cache_list *list, 3671 struct mlx5_cache_entry *entry __rte_unused, 3672 void *cb_ctx) 3673 { 3674 struct mlx5_dev_ctx_shared *sh = list->ctx; 3675 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 3676 struct mlx5_flow_dv_push_vlan_action_resource *ref = ctx->data; 3677 struct mlx5_flow_dv_push_vlan_action_resource *cache; 3678 struct mlx5dv_dr_domain *domain; 3679 uint32_t idx; 3680 int ret; 3681 3682 /* Register new port id action resource. */ 3683 cache = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN], &idx); 3684 if (!cache) { 3685 rte_flow_error_set(ctx->error, ENOMEM, 3686 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3687 "cannot allocate push_vlan action cache memory"); 3688 return NULL; 3689 } 3690 *cache = *ref; 3691 if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) 3692 domain = sh->fdb_domain; 3693 else if (ref->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX) 3694 domain = sh->rx_domain; 3695 else 3696 domain = sh->tx_domain; 3697 ret = mlx5_flow_os_create_flow_action_push_vlan(domain, ref->vlan_tag, 3698 &cache->action); 3699 if (ret) { 3700 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx); 3701 rte_flow_error_set(ctx->error, ENOMEM, 3702 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 3703 "cannot create push vlan action"); 3704 return NULL; 3705 } 3706 return &cache->entry; 3707 } 3708 3709 /** 3710 * Find existing push vlan resource or create and register a new one. 3711 * 3712 * @param [in, out] dev 3713 * Pointer to rte_eth_dev structure. 3714 * @param[in, out] resource 3715 * Pointer to port ID action resource. 3716 * @parm[in, out] dev_flow 3717 * Pointer to the dev_flow. 3718 * @param[out] error 3719 * pointer to error structure. 3720 * 3721 * @return 3722 * 0 on success otherwise -errno and errno is set. 3723 */ 3724 static int 3725 flow_dv_push_vlan_action_resource_register 3726 (struct rte_eth_dev *dev, 3727 struct mlx5_flow_dv_push_vlan_action_resource *resource, 3728 struct mlx5_flow *dev_flow, 3729 struct rte_flow_error *error) 3730 { 3731 struct mlx5_priv *priv = dev->data->dev_private; 3732 struct mlx5_flow_dv_push_vlan_action_resource *cache; 3733 struct mlx5_cache_entry *entry; 3734 struct mlx5_flow_cb_ctx ctx = { 3735 .error = error, 3736 .data = resource, 3737 }; 3738 3739 entry = mlx5_cache_register(&priv->sh->push_vlan_action_list, &ctx); 3740 if (!entry) 3741 return -rte_errno; 3742 cache = container_of(entry, typeof(*cache), entry); 3743 3744 dev_flow->handle->dvh.rix_push_vlan = cache->idx; 3745 dev_flow->dv.push_vlan_res = cache; 3746 return 0; 3747 } 3748 3749 /** 3750 * Get the size of specific rte_flow_item_type hdr size 3751 * 3752 * @param[in] item_type 3753 * Tested rte_flow_item_type. 3754 * 3755 * @return 3756 * sizeof struct item_type, 0 if void or irrelevant. 3757 */ 3758 static size_t 3759 flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type) 3760 { 3761 size_t retval; 3762 3763 switch (item_type) { 3764 case RTE_FLOW_ITEM_TYPE_ETH: 3765 retval = sizeof(struct rte_ether_hdr); 3766 break; 3767 case RTE_FLOW_ITEM_TYPE_VLAN: 3768 retval = sizeof(struct rte_vlan_hdr); 3769 break; 3770 case RTE_FLOW_ITEM_TYPE_IPV4: 3771 retval = sizeof(struct rte_ipv4_hdr); 3772 break; 3773 case RTE_FLOW_ITEM_TYPE_IPV6: 3774 retval = sizeof(struct rte_ipv6_hdr); 3775 break; 3776 case RTE_FLOW_ITEM_TYPE_UDP: 3777 retval = sizeof(struct rte_udp_hdr); 3778 break; 3779 case RTE_FLOW_ITEM_TYPE_TCP: 3780 retval = sizeof(struct rte_tcp_hdr); 3781 break; 3782 case RTE_FLOW_ITEM_TYPE_VXLAN: 3783 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 3784 retval = sizeof(struct rte_vxlan_hdr); 3785 break; 3786 case RTE_FLOW_ITEM_TYPE_GRE: 3787 case RTE_FLOW_ITEM_TYPE_NVGRE: 3788 retval = sizeof(struct rte_gre_hdr); 3789 break; 3790 case RTE_FLOW_ITEM_TYPE_MPLS: 3791 retval = sizeof(struct rte_mpls_hdr); 3792 break; 3793 case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */ 3794 default: 3795 retval = 0; 3796 break; 3797 } 3798 return retval; 3799 } 3800 3801 #define MLX5_ENCAP_IPV4_VERSION 0x40 3802 #define MLX5_ENCAP_IPV4_IHL_MIN 0x05 3803 #define MLX5_ENCAP_IPV4_TTL_DEF 0x40 3804 #define MLX5_ENCAP_IPV6_VTC_FLOW 0x60000000 3805 #define MLX5_ENCAP_IPV6_HOP_LIMIT 0xff 3806 #define MLX5_ENCAP_VXLAN_FLAGS 0x08000000 3807 #define MLX5_ENCAP_VXLAN_GPE_FLAGS 0x04 3808 3809 /** 3810 * Convert the encap action data from list of rte_flow_item to raw buffer 3811 * 3812 * @param[in] items 3813 * Pointer to rte_flow_item objects list. 3814 * @param[out] buf 3815 * Pointer to the output buffer. 3816 * @param[out] size 3817 * Pointer to the output buffer size. 3818 * @param[out] error 3819 * Pointer to the error structure. 3820 * 3821 * @return 3822 * 0 on success, a negative errno value otherwise and rte_errno is set. 3823 */ 3824 static int 3825 flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf, 3826 size_t *size, struct rte_flow_error *error) 3827 { 3828 struct rte_ether_hdr *eth = NULL; 3829 struct rte_vlan_hdr *vlan = NULL; 3830 struct rte_ipv4_hdr *ipv4 = NULL; 3831 struct rte_ipv6_hdr *ipv6 = NULL; 3832 struct rte_udp_hdr *udp = NULL; 3833 struct rte_vxlan_hdr *vxlan = NULL; 3834 struct rte_vxlan_gpe_hdr *vxlan_gpe = NULL; 3835 struct rte_gre_hdr *gre = NULL; 3836 size_t len; 3837 size_t temp_size = 0; 3838 3839 if (!items) 3840 return rte_flow_error_set(error, EINVAL, 3841 RTE_FLOW_ERROR_TYPE_ACTION, 3842 NULL, "invalid empty data"); 3843 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 3844 len = flow_dv_get_item_hdr_len(items->type); 3845 if (len + temp_size > MLX5_ENCAP_MAX_LEN) 3846 return rte_flow_error_set(error, EINVAL, 3847 RTE_FLOW_ERROR_TYPE_ACTION, 3848 (void *)items->type, 3849 "items total size is too big" 3850 " for encap action"); 3851 rte_memcpy((void *)&buf[temp_size], items->spec, len); 3852 switch (items->type) { 3853 case RTE_FLOW_ITEM_TYPE_ETH: 3854 eth = (struct rte_ether_hdr *)&buf[temp_size]; 3855 break; 3856 case RTE_FLOW_ITEM_TYPE_VLAN: 3857 vlan = (struct rte_vlan_hdr *)&buf[temp_size]; 3858 if (!eth) 3859 return rte_flow_error_set(error, EINVAL, 3860 RTE_FLOW_ERROR_TYPE_ACTION, 3861 (void *)items->type, 3862 "eth header not found"); 3863 if (!eth->ether_type) 3864 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_VLAN); 3865 break; 3866 case RTE_FLOW_ITEM_TYPE_IPV4: 3867 ipv4 = (struct rte_ipv4_hdr *)&buf[temp_size]; 3868 if (!vlan && !eth) 3869 return rte_flow_error_set(error, EINVAL, 3870 RTE_FLOW_ERROR_TYPE_ACTION, 3871 (void *)items->type, 3872 "neither eth nor vlan" 3873 " header found"); 3874 if (vlan && !vlan->eth_proto) 3875 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV4); 3876 else if (eth && !eth->ether_type) 3877 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV4); 3878 if (!ipv4->version_ihl) 3879 ipv4->version_ihl = MLX5_ENCAP_IPV4_VERSION | 3880 MLX5_ENCAP_IPV4_IHL_MIN; 3881 if (!ipv4->time_to_live) 3882 ipv4->time_to_live = MLX5_ENCAP_IPV4_TTL_DEF; 3883 break; 3884 case RTE_FLOW_ITEM_TYPE_IPV6: 3885 ipv6 = (struct rte_ipv6_hdr *)&buf[temp_size]; 3886 if (!vlan && !eth) 3887 return rte_flow_error_set(error, EINVAL, 3888 RTE_FLOW_ERROR_TYPE_ACTION, 3889 (void *)items->type, 3890 "neither eth nor vlan" 3891 " header found"); 3892 if (vlan && !vlan->eth_proto) 3893 vlan->eth_proto = RTE_BE16(RTE_ETHER_TYPE_IPV6); 3894 else if (eth && !eth->ether_type) 3895 eth->ether_type = RTE_BE16(RTE_ETHER_TYPE_IPV6); 3896 if (!ipv6->vtc_flow) 3897 ipv6->vtc_flow = 3898 RTE_BE32(MLX5_ENCAP_IPV6_VTC_FLOW); 3899 if (!ipv6->hop_limits) 3900 ipv6->hop_limits = MLX5_ENCAP_IPV6_HOP_LIMIT; 3901 break; 3902 case RTE_FLOW_ITEM_TYPE_UDP: 3903 udp = (struct rte_udp_hdr *)&buf[temp_size]; 3904 if (!ipv4 && !ipv6) 3905 return rte_flow_error_set(error, EINVAL, 3906 RTE_FLOW_ERROR_TYPE_ACTION, 3907 (void *)items->type, 3908 "ip header not found"); 3909 if (ipv4 && !ipv4->next_proto_id) 3910 ipv4->next_proto_id = IPPROTO_UDP; 3911 else if (ipv6 && !ipv6->proto) 3912 ipv6->proto = IPPROTO_UDP; 3913 break; 3914 case RTE_FLOW_ITEM_TYPE_VXLAN: 3915 vxlan = (struct rte_vxlan_hdr *)&buf[temp_size]; 3916 if (!udp) 3917 return rte_flow_error_set(error, EINVAL, 3918 RTE_FLOW_ERROR_TYPE_ACTION, 3919 (void *)items->type, 3920 "udp header not found"); 3921 if (!udp->dst_port) 3922 udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN); 3923 if (!vxlan->vx_flags) 3924 vxlan->vx_flags = 3925 RTE_BE32(MLX5_ENCAP_VXLAN_FLAGS); 3926 break; 3927 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 3928 vxlan_gpe = (struct rte_vxlan_gpe_hdr *)&buf[temp_size]; 3929 if (!udp) 3930 return rte_flow_error_set(error, EINVAL, 3931 RTE_FLOW_ERROR_TYPE_ACTION, 3932 (void *)items->type, 3933 "udp header not found"); 3934 if (!vxlan_gpe->proto) 3935 return rte_flow_error_set(error, EINVAL, 3936 RTE_FLOW_ERROR_TYPE_ACTION, 3937 (void *)items->type, 3938 "next protocol not found"); 3939 if (!udp->dst_port) 3940 udp->dst_port = 3941 RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE); 3942 if (!vxlan_gpe->vx_flags) 3943 vxlan_gpe->vx_flags = 3944 MLX5_ENCAP_VXLAN_GPE_FLAGS; 3945 break; 3946 case RTE_FLOW_ITEM_TYPE_GRE: 3947 case RTE_FLOW_ITEM_TYPE_NVGRE: 3948 gre = (struct rte_gre_hdr *)&buf[temp_size]; 3949 if (!gre->proto) 3950 return rte_flow_error_set(error, EINVAL, 3951 RTE_FLOW_ERROR_TYPE_ACTION, 3952 (void *)items->type, 3953 "next protocol not found"); 3954 if (!ipv4 && !ipv6) 3955 return rte_flow_error_set(error, EINVAL, 3956 RTE_FLOW_ERROR_TYPE_ACTION, 3957 (void *)items->type, 3958 "ip header not found"); 3959 if (ipv4 && !ipv4->next_proto_id) 3960 ipv4->next_proto_id = IPPROTO_GRE; 3961 else if (ipv6 && !ipv6->proto) 3962 ipv6->proto = IPPROTO_GRE; 3963 break; 3964 case RTE_FLOW_ITEM_TYPE_VOID: 3965 break; 3966 default: 3967 return rte_flow_error_set(error, EINVAL, 3968 RTE_FLOW_ERROR_TYPE_ACTION, 3969 (void *)items->type, 3970 "unsupported item type"); 3971 break; 3972 } 3973 temp_size += len; 3974 } 3975 *size = temp_size; 3976 return 0; 3977 } 3978 3979 static int 3980 flow_dv_zero_encap_udp_csum(void *data, struct rte_flow_error *error) 3981 { 3982 struct rte_ether_hdr *eth = NULL; 3983 struct rte_vlan_hdr *vlan = NULL; 3984 struct rte_ipv6_hdr *ipv6 = NULL; 3985 struct rte_udp_hdr *udp = NULL; 3986 char *next_hdr; 3987 uint16_t proto; 3988 3989 eth = (struct rte_ether_hdr *)data; 3990 next_hdr = (char *)(eth + 1); 3991 proto = RTE_BE16(eth->ether_type); 3992 3993 /* VLAN skipping */ 3994 while (proto == RTE_ETHER_TYPE_VLAN || proto == RTE_ETHER_TYPE_QINQ) { 3995 vlan = (struct rte_vlan_hdr *)next_hdr; 3996 proto = RTE_BE16(vlan->eth_proto); 3997 next_hdr += sizeof(struct rte_vlan_hdr); 3998 } 3999 4000 /* HW calculates IPv4 csum. no need to proceed */ 4001 if (proto == RTE_ETHER_TYPE_IPV4) 4002 return 0; 4003 4004 /* non IPv4/IPv6 header. not supported */ 4005 if (proto != RTE_ETHER_TYPE_IPV6) { 4006 return rte_flow_error_set(error, ENOTSUP, 4007 RTE_FLOW_ERROR_TYPE_ACTION, 4008 NULL, "Cannot offload non IPv4/IPv6"); 4009 } 4010 4011 ipv6 = (struct rte_ipv6_hdr *)next_hdr; 4012 4013 /* ignore non UDP */ 4014 if (ipv6->proto != IPPROTO_UDP) 4015 return 0; 4016 4017 udp = (struct rte_udp_hdr *)(ipv6 + 1); 4018 udp->dgram_cksum = 0; 4019 4020 return 0; 4021 } 4022 4023 /** 4024 * Convert L2 encap action to DV specification. 4025 * 4026 * @param[in] dev 4027 * Pointer to rte_eth_dev structure. 4028 * @param[in] action 4029 * Pointer to action structure. 4030 * @param[in, out] dev_flow 4031 * Pointer to the mlx5_flow. 4032 * @param[in] transfer 4033 * Mark if the flow is E-Switch flow. 4034 * @param[out] error 4035 * Pointer to the error structure. 4036 * 4037 * @return 4038 * 0 on success, a negative errno value otherwise and rte_errno is set. 4039 */ 4040 static int 4041 flow_dv_create_action_l2_encap(struct rte_eth_dev *dev, 4042 const struct rte_flow_action *action, 4043 struct mlx5_flow *dev_flow, 4044 uint8_t transfer, 4045 struct rte_flow_error *error) 4046 { 4047 const struct rte_flow_item *encap_data; 4048 const struct rte_flow_action_raw_encap *raw_encap_data; 4049 struct mlx5_flow_dv_encap_decap_resource res = { 4050 .reformat_type = 4051 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL, 4052 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB : 4053 MLX5DV_FLOW_TABLE_TYPE_NIC_TX, 4054 }; 4055 4056 if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { 4057 raw_encap_data = 4058 (const struct rte_flow_action_raw_encap *)action->conf; 4059 res.size = raw_encap_data->size; 4060 memcpy(res.buf, raw_encap_data->data, res.size); 4061 } else { 4062 if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) 4063 encap_data = 4064 ((const struct rte_flow_action_vxlan_encap *) 4065 action->conf)->definition; 4066 else 4067 encap_data = 4068 ((const struct rte_flow_action_nvgre_encap *) 4069 action->conf)->definition; 4070 if (flow_dv_convert_encap_data(encap_data, res.buf, 4071 &res.size, error)) 4072 return -rte_errno; 4073 } 4074 if (flow_dv_zero_encap_udp_csum(res.buf, error)) 4075 return -rte_errno; 4076 if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error)) 4077 return rte_flow_error_set(error, EINVAL, 4078 RTE_FLOW_ERROR_TYPE_ACTION, 4079 NULL, "can't create L2 encap action"); 4080 return 0; 4081 } 4082 4083 /** 4084 * Convert L2 decap action to DV specification. 4085 * 4086 * @param[in] dev 4087 * Pointer to rte_eth_dev structure. 4088 * @param[in, out] dev_flow 4089 * Pointer to the mlx5_flow. 4090 * @param[in] transfer 4091 * Mark if the flow is E-Switch flow. 4092 * @param[out] error 4093 * Pointer to the error structure. 4094 * 4095 * @return 4096 * 0 on success, a negative errno value otherwise and rte_errno is set. 4097 */ 4098 static int 4099 flow_dv_create_action_l2_decap(struct rte_eth_dev *dev, 4100 struct mlx5_flow *dev_flow, 4101 uint8_t transfer, 4102 struct rte_flow_error *error) 4103 { 4104 struct mlx5_flow_dv_encap_decap_resource res = { 4105 .size = 0, 4106 .reformat_type = 4107 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2, 4108 .ft_type = transfer ? MLX5DV_FLOW_TABLE_TYPE_FDB : 4109 MLX5DV_FLOW_TABLE_TYPE_NIC_RX, 4110 }; 4111 4112 if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error)) 4113 return rte_flow_error_set(error, EINVAL, 4114 RTE_FLOW_ERROR_TYPE_ACTION, 4115 NULL, "can't create L2 decap action"); 4116 return 0; 4117 } 4118 4119 /** 4120 * Convert raw decap/encap (L3 tunnel) action to DV specification. 4121 * 4122 * @param[in] dev 4123 * Pointer to rte_eth_dev structure. 4124 * @param[in] action 4125 * Pointer to action structure. 4126 * @param[in, out] dev_flow 4127 * Pointer to the mlx5_flow. 4128 * @param[in] attr 4129 * Pointer to the flow attributes. 4130 * @param[out] error 4131 * Pointer to the error structure. 4132 * 4133 * @return 4134 * 0 on success, a negative errno value otherwise and rte_errno is set. 4135 */ 4136 static int 4137 flow_dv_create_action_raw_encap(struct rte_eth_dev *dev, 4138 const struct rte_flow_action *action, 4139 struct mlx5_flow *dev_flow, 4140 const struct rte_flow_attr *attr, 4141 struct rte_flow_error *error) 4142 { 4143 const struct rte_flow_action_raw_encap *encap_data; 4144 struct mlx5_flow_dv_encap_decap_resource res; 4145 4146 memset(&res, 0, sizeof(res)); 4147 encap_data = (const struct rte_flow_action_raw_encap *)action->conf; 4148 res.size = encap_data->size; 4149 memcpy(res.buf, encap_data->data, res.size); 4150 res.reformat_type = res.size < MLX5_ENCAPSULATION_DECISION_SIZE ? 4151 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 : 4152 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL; 4153 if (attr->transfer) 4154 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 4155 else 4156 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX : 4157 MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 4158 if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error)) 4159 return rte_flow_error_set(error, EINVAL, 4160 RTE_FLOW_ERROR_TYPE_ACTION, 4161 NULL, "can't create encap action"); 4162 return 0; 4163 } 4164 4165 /** 4166 * Create action push VLAN. 4167 * 4168 * @param[in] dev 4169 * Pointer to rte_eth_dev structure. 4170 * @param[in] attr 4171 * Pointer to the flow attributes. 4172 * @param[in] vlan 4173 * Pointer to the vlan to push to the Ethernet header. 4174 * @param[in, out] dev_flow 4175 * Pointer to the mlx5_flow. 4176 * @param[out] error 4177 * Pointer to the error structure. 4178 * 4179 * @return 4180 * 0 on success, a negative errno value otherwise and rte_errno is set. 4181 */ 4182 static int 4183 flow_dv_create_action_push_vlan(struct rte_eth_dev *dev, 4184 const struct rte_flow_attr *attr, 4185 const struct rte_vlan_hdr *vlan, 4186 struct mlx5_flow *dev_flow, 4187 struct rte_flow_error *error) 4188 { 4189 struct mlx5_flow_dv_push_vlan_action_resource res; 4190 4191 memset(&res, 0, sizeof(res)); 4192 res.vlan_tag = 4193 rte_cpu_to_be_32(((uint32_t)vlan->eth_proto) << 16 | 4194 vlan->vlan_tci); 4195 if (attr->transfer) 4196 res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 4197 else 4198 res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX : 4199 MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 4200 return flow_dv_push_vlan_action_resource_register 4201 (dev, &res, dev_flow, error); 4202 } 4203 4204 /** 4205 * Validate the modify-header actions. 4206 * 4207 * @param[in] action_flags 4208 * Holds the actions detected until now. 4209 * @param[in] action 4210 * Pointer to the modify action. 4211 * @param[out] error 4212 * Pointer to error structure. 4213 * 4214 * @return 4215 * 0 on success, a negative errno value otherwise and rte_errno is set. 4216 */ 4217 static int 4218 flow_dv_validate_action_modify_hdr(const uint64_t action_flags, 4219 const struct rte_flow_action *action, 4220 struct rte_flow_error *error) 4221 { 4222 if (action->type != RTE_FLOW_ACTION_TYPE_DEC_TTL && !action->conf) 4223 return rte_flow_error_set(error, EINVAL, 4224 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 4225 NULL, "action configuration not set"); 4226 if (action_flags & MLX5_FLOW_ACTION_ENCAP) 4227 return rte_flow_error_set(error, EINVAL, 4228 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4229 "can't have encap action before" 4230 " modify action"); 4231 return 0; 4232 } 4233 4234 /** 4235 * Validate the modify-header MAC address actions. 4236 * 4237 * @param[in] action_flags 4238 * Holds the actions detected until now. 4239 * @param[in] action 4240 * Pointer to the modify action. 4241 * @param[in] item_flags 4242 * Holds the items detected. 4243 * @param[out] error 4244 * Pointer to error structure. 4245 * 4246 * @return 4247 * 0 on success, a negative errno value otherwise and rte_errno is set. 4248 */ 4249 static int 4250 flow_dv_validate_action_modify_mac(const uint64_t action_flags, 4251 const struct rte_flow_action *action, 4252 const uint64_t item_flags, 4253 struct rte_flow_error *error) 4254 { 4255 int ret = 0; 4256 4257 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4258 if (!ret) { 4259 if (!(item_flags & MLX5_FLOW_LAYER_L2)) 4260 return rte_flow_error_set(error, EINVAL, 4261 RTE_FLOW_ERROR_TYPE_ACTION, 4262 NULL, 4263 "no L2 item in pattern"); 4264 } 4265 return ret; 4266 } 4267 4268 /** 4269 * Validate the modify-header IPv4 address actions. 4270 * 4271 * @param[in] action_flags 4272 * Holds the actions detected until now. 4273 * @param[in] action 4274 * Pointer to the modify action. 4275 * @param[in] item_flags 4276 * Holds the items detected. 4277 * @param[out] error 4278 * Pointer to error structure. 4279 * 4280 * @return 4281 * 0 on success, a negative errno value otherwise and rte_errno is set. 4282 */ 4283 static int 4284 flow_dv_validate_action_modify_ipv4(const uint64_t action_flags, 4285 const struct rte_flow_action *action, 4286 const uint64_t item_flags, 4287 struct rte_flow_error *error) 4288 { 4289 int ret = 0; 4290 uint64_t layer; 4291 4292 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4293 if (!ret) { 4294 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4295 MLX5_FLOW_LAYER_INNER_L3_IPV4 : 4296 MLX5_FLOW_LAYER_OUTER_L3_IPV4; 4297 if (!(item_flags & layer)) 4298 return rte_flow_error_set(error, EINVAL, 4299 RTE_FLOW_ERROR_TYPE_ACTION, 4300 NULL, 4301 "no ipv4 item in pattern"); 4302 } 4303 return ret; 4304 } 4305 4306 /** 4307 * Validate the modify-header IPv6 address actions. 4308 * 4309 * @param[in] action_flags 4310 * Holds the actions detected until now. 4311 * @param[in] action 4312 * Pointer to the modify action. 4313 * @param[in] item_flags 4314 * Holds the items detected. 4315 * @param[out] error 4316 * Pointer to error structure. 4317 * 4318 * @return 4319 * 0 on success, a negative errno value otherwise and rte_errno is set. 4320 */ 4321 static int 4322 flow_dv_validate_action_modify_ipv6(const uint64_t action_flags, 4323 const struct rte_flow_action *action, 4324 const uint64_t item_flags, 4325 struct rte_flow_error *error) 4326 { 4327 int ret = 0; 4328 uint64_t layer; 4329 4330 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4331 if (!ret) { 4332 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4333 MLX5_FLOW_LAYER_INNER_L3_IPV6 : 4334 MLX5_FLOW_LAYER_OUTER_L3_IPV6; 4335 if (!(item_flags & layer)) 4336 return rte_flow_error_set(error, EINVAL, 4337 RTE_FLOW_ERROR_TYPE_ACTION, 4338 NULL, 4339 "no ipv6 item in pattern"); 4340 } 4341 return ret; 4342 } 4343 4344 /** 4345 * Validate the modify-header TP actions. 4346 * 4347 * @param[in] action_flags 4348 * Holds the actions detected until now. 4349 * @param[in] action 4350 * Pointer to the modify action. 4351 * @param[in] item_flags 4352 * Holds the items detected. 4353 * @param[out] error 4354 * Pointer to error structure. 4355 * 4356 * @return 4357 * 0 on success, a negative errno value otherwise and rte_errno is set. 4358 */ 4359 static int 4360 flow_dv_validate_action_modify_tp(const uint64_t action_flags, 4361 const struct rte_flow_action *action, 4362 const uint64_t item_flags, 4363 struct rte_flow_error *error) 4364 { 4365 int ret = 0; 4366 uint64_t layer; 4367 4368 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4369 if (!ret) { 4370 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4371 MLX5_FLOW_LAYER_INNER_L4 : 4372 MLX5_FLOW_LAYER_OUTER_L4; 4373 if (!(item_flags & layer)) 4374 return rte_flow_error_set(error, EINVAL, 4375 RTE_FLOW_ERROR_TYPE_ACTION, 4376 NULL, "no transport layer " 4377 "in pattern"); 4378 } 4379 return ret; 4380 } 4381 4382 /** 4383 * Validate the modify-header actions of increment/decrement 4384 * TCP Sequence-number. 4385 * 4386 * @param[in] action_flags 4387 * Holds the actions detected until now. 4388 * @param[in] action 4389 * Pointer to the modify action. 4390 * @param[in] item_flags 4391 * Holds the items detected. 4392 * @param[out] error 4393 * Pointer to error structure. 4394 * 4395 * @return 4396 * 0 on success, a negative errno value otherwise and rte_errno is set. 4397 */ 4398 static int 4399 flow_dv_validate_action_modify_tcp_seq(const uint64_t action_flags, 4400 const struct rte_flow_action *action, 4401 const uint64_t item_flags, 4402 struct rte_flow_error *error) 4403 { 4404 int ret = 0; 4405 uint64_t layer; 4406 4407 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4408 if (!ret) { 4409 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4410 MLX5_FLOW_LAYER_INNER_L4_TCP : 4411 MLX5_FLOW_LAYER_OUTER_L4_TCP; 4412 if (!(item_flags & layer)) 4413 return rte_flow_error_set(error, EINVAL, 4414 RTE_FLOW_ERROR_TYPE_ACTION, 4415 NULL, "no TCP item in" 4416 " pattern"); 4417 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ && 4418 (action_flags & MLX5_FLOW_ACTION_DEC_TCP_SEQ)) || 4419 (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ && 4420 (action_flags & MLX5_FLOW_ACTION_INC_TCP_SEQ))) 4421 return rte_flow_error_set(error, EINVAL, 4422 RTE_FLOW_ERROR_TYPE_ACTION, 4423 NULL, 4424 "cannot decrease and increase" 4425 " TCP sequence number" 4426 " at the same time"); 4427 } 4428 return ret; 4429 } 4430 4431 /** 4432 * Validate the modify-header actions of increment/decrement 4433 * TCP Acknowledgment number. 4434 * 4435 * @param[in] action_flags 4436 * Holds the actions detected until now. 4437 * @param[in] action 4438 * Pointer to the modify action. 4439 * @param[in] item_flags 4440 * Holds the items detected. 4441 * @param[out] error 4442 * Pointer to error structure. 4443 * 4444 * @return 4445 * 0 on success, a negative errno value otherwise and rte_errno is set. 4446 */ 4447 static int 4448 flow_dv_validate_action_modify_tcp_ack(const uint64_t action_flags, 4449 const struct rte_flow_action *action, 4450 const uint64_t item_flags, 4451 struct rte_flow_error *error) 4452 { 4453 int ret = 0; 4454 uint64_t layer; 4455 4456 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4457 if (!ret) { 4458 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4459 MLX5_FLOW_LAYER_INNER_L4_TCP : 4460 MLX5_FLOW_LAYER_OUTER_L4_TCP; 4461 if (!(item_flags & layer)) 4462 return rte_flow_error_set(error, EINVAL, 4463 RTE_FLOW_ERROR_TYPE_ACTION, 4464 NULL, "no TCP item in" 4465 " pattern"); 4466 if ((action->type == RTE_FLOW_ACTION_TYPE_INC_TCP_ACK && 4467 (action_flags & MLX5_FLOW_ACTION_DEC_TCP_ACK)) || 4468 (action->type == RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK && 4469 (action_flags & MLX5_FLOW_ACTION_INC_TCP_ACK))) 4470 return rte_flow_error_set(error, EINVAL, 4471 RTE_FLOW_ERROR_TYPE_ACTION, 4472 NULL, 4473 "cannot decrease and increase" 4474 " TCP acknowledgment number" 4475 " at the same time"); 4476 } 4477 return ret; 4478 } 4479 4480 /** 4481 * Validate the modify-header TTL actions. 4482 * 4483 * @param[in] action_flags 4484 * Holds the actions detected until now. 4485 * @param[in] action 4486 * Pointer to the modify action. 4487 * @param[in] item_flags 4488 * Holds the items detected. 4489 * @param[out] error 4490 * Pointer to error structure. 4491 * 4492 * @return 4493 * 0 on success, a negative errno value otherwise and rte_errno is set. 4494 */ 4495 static int 4496 flow_dv_validate_action_modify_ttl(const uint64_t action_flags, 4497 const struct rte_flow_action *action, 4498 const uint64_t item_flags, 4499 struct rte_flow_error *error) 4500 { 4501 int ret = 0; 4502 uint64_t layer; 4503 4504 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4505 if (!ret) { 4506 layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ? 4507 MLX5_FLOW_LAYER_INNER_L3 : 4508 MLX5_FLOW_LAYER_OUTER_L3; 4509 if (!(item_flags & layer)) 4510 return rte_flow_error_set(error, EINVAL, 4511 RTE_FLOW_ERROR_TYPE_ACTION, 4512 NULL, 4513 "no IP protocol in pattern"); 4514 } 4515 return ret; 4516 } 4517 4518 static int 4519 mlx5_flow_item_field_width(enum rte_flow_field_id field) 4520 { 4521 switch (field) { 4522 case RTE_FLOW_FIELD_START: 4523 return 32; 4524 case RTE_FLOW_FIELD_MAC_DST: 4525 case RTE_FLOW_FIELD_MAC_SRC: 4526 return 48; 4527 case RTE_FLOW_FIELD_VLAN_TYPE: 4528 return 16; 4529 case RTE_FLOW_FIELD_VLAN_ID: 4530 return 12; 4531 case RTE_FLOW_FIELD_MAC_TYPE: 4532 return 16; 4533 case RTE_FLOW_FIELD_IPV4_DSCP: 4534 return 6; 4535 case RTE_FLOW_FIELD_IPV4_TTL: 4536 return 8; 4537 case RTE_FLOW_FIELD_IPV4_SRC: 4538 case RTE_FLOW_FIELD_IPV4_DST: 4539 return 32; 4540 case RTE_FLOW_FIELD_IPV6_DSCP: 4541 return 6; 4542 case RTE_FLOW_FIELD_IPV6_HOPLIMIT: 4543 return 8; 4544 case RTE_FLOW_FIELD_IPV6_SRC: 4545 case RTE_FLOW_FIELD_IPV6_DST: 4546 return 128; 4547 case RTE_FLOW_FIELD_TCP_PORT_SRC: 4548 case RTE_FLOW_FIELD_TCP_PORT_DST: 4549 return 16; 4550 case RTE_FLOW_FIELD_TCP_SEQ_NUM: 4551 case RTE_FLOW_FIELD_TCP_ACK_NUM: 4552 return 32; 4553 case RTE_FLOW_FIELD_TCP_FLAGS: 4554 return 6; 4555 case RTE_FLOW_FIELD_UDP_PORT_SRC: 4556 case RTE_FLOW_FIELD_UDP_PORT_DST: 4557 return 16; 4558 case RTE_FLOW_FIELD_VXLAN_VNI: 4559 case RTE_FLOW_FIELD_GENEVE_VNI: 4560 return 24; 4561 case RTE_FLOW_FIELD_GTP_TEID: 4562 case RTE_FLOW_FIELD_TAG: 4563 return 32; 4564 case RTE_FLOW_FIELD_MARK: 4565 return 24; 4566 case RTE_FLOW_FIELD_META: 4567 case RTE_FLOW_FIELD_POINTER: 4568 case RTE_FLOW_FIELD_VALUE: 4569 return 32; 4570 default: 4571 MLX5_ASSERT(false); 4572 } 4573 return 0; 4574 } 4575 4576 /** 4577 * Validate the generic modify field actions. 4578 * 4579 * @param[in] action_flags 4580 * Holds the actions detected until now. 4581 * @param[in] action 4582 * Pointer to the modify action. 4583 * @param[in] item_flags 4584 * Holds the items detected. 4585 * @param[out] error 4586 * Pointer to error structure. 4587 * 4588 * @return 4589 * Number of header fields to modify (0 or more) on success, 4590 * a negative errno value otherwise and rte_errno is set. 4591 */ 4592 static int 4593 flow_dv_validate_action_modify_field(const uint64_t action_flags, 4594 const struct rte_flow_action *action, 4595 struct rte_flow_error *error) 4596 { 4597 int ret = 0; 4598 const struct rte_flow_action_modify_field *action_modify_field = 4599 action->conf; 4600 uint32_t dst_width = 4601 mlx5_flow_item_field_width(action_modify_field->dst.field); 4602 uint32_t src_width = 4603 mlx5_flow_item_field_width(action_modify_field->src.field); 4604 4605 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4606 if (ret) 4607 return ret; 4608 4609 if (action_modify_field->dst.field != RTE_FLOW_FIELD_VALUE && 4610 action_modify_field->dst.field != RTE_FLOW_FIELD_POINTER) { 4611 if (action_modify_field->dst.offset >= dst_width || 4612 (action_modify_field->dst.offset % 32)) 4613 return rte_flow_error_set(error, EINVAL, 4614 RTE_FLOW_ERROR_TYPE_ACTION, 4615 NULL, 4616 "destination offset is too big" 4617 " or not aligned to 4 bytes"); 4618 if (action_modify_field->dst.level && 4619 action_modify_field->dst.field != RTE_FLOW_FIELD_TAG) 4620 return rte_flow_error_set(error, EINVAL, 4621 RTE_FLOW_ERROR_TYPE_ACTION, 4622 NULL, 4623 "cannot modify inner headers"); 4624 } 4625 if (action_modify_field->src.field != RTE_FLOW_FIELD_VALUE && 4626 action_modify_field->src.field != RTE_FLOW_FIELD_POINTER) { 4627 if (action_modify_field->src.offset >= src_width || 4628 (action_modify_field->src.offset % 32)) 4629 return rte_flow_error_set(error, EINVAL, 4630 RTE_FLOW_ERROR_TYPE_ACTION, 4631 NULL, 4632 "source offset is too big" 4633 " or not aligned to 4 bytes"); 4634 if (action_modify_field->src.level && 4635 action_modify_field->src.field != RTE_FLOW_FIELD_TAG) 4636 return rte_flow_error_set(error, EINVAL, 4637 RTE_FLOW_ERROR_TYPE_ACTION, 4638 NULL, 4639 "cannot copy from inner headers"); 4640 } 4641 if (action_modify_field->width == 0) 4642 return rte_flow_error_set(error, EINVAL, 4643 RTE_FLOW_ERROR_TYPE_ACTION, 4644 NULL, 4645 "width is required for modify action"); 4646 if (action_modify_field->dst.field == 4647 action_modify_field->src.field) 4648 return rte_flow_error_set(error, EINVAL, 4649 RTE_FLOW_ERROR_TYPE_ACTION, 4650 NULL, 4651 "source and destination fields" 4652 " cannot be the same"); 4653 if (action_modify_field->dst.field == RTE_FLOW_FIELD_VALUE || 4654 action_modify_field->dst.field == RTE_FLOW_FIELD_POINTER) 4655 return rte_flow_error_set(error, EINVAL, 4656 RTE_FLOW_ERROR_TYPE_ACTION, 4657 NULL, 4658 "immediate value or a pointer to it" 4659 " cannot be used as a destination"); 4660 if (action_modify_field->dst.field == RTE_FLOW_FIELD_START || 4661 action_modify_field->src.field == RTE_FLOW_FIELD_START) 4662 return rte_flow_error_set(error, EINVAL, 4663 RTE_FLOW_ERROR_TYPE_ACTION, 4664 NULL, 4665 "modifications of an arbitrary" 4666 " place in a packet is not supported"); 4667 if (action_modify_field->operation != RTE_FLOW_MODIFY_SET) 4668 return rte_flow_error_set(error, EINVAL, 4669 RTE_FLOW_ERROR_TYPE_ACTION, 4670 NULL, 4671 "add and sub operations" 4672 " are not supported"); 4673 return (action_modify_field->width / 32) + 4674 !!(action_modify_field->width % 32); 4675 } 4676 4677 /** 4678 * Validate jump action. 4679 * 4680 * @param[in] action 4681 * Pointer to the jump action. 4682 * @param[in] action_flags 4683 * Holds the actions detected until now. 4684 * @param[in] attributes 4685 * Pointer to flow attributes 4686 * @param[in] external 4687 * Action belongs to flow rule created by request external to PMD. 4688 * @param[out] error 4689 * Pointer to error structure. 4690 * 4691 * @return 4692 * 0 on success, a negative errno value otherwise and rte_errno is set. 4693 */ 4694 static int 4695 flow_dv_validate_action_jump(struct rte_eth_dev *dev, 4696 const struct mlx5_flow_tunnel *tunnel, 4697 const struct rte_flow_action *action, 4698 uint64_t action_flags, 4699 const struct rte_flow_attr *attributes, 4700 bool external, struct rte_flow_error *error) 4701 { 4702 uint32_t target_group, table; 4703 int ret = 0; 4704 struct flow_grp_info grp_info = { 4705 .external = !!external, 4706 .transfer = !!attributes->transfer, 4707 .fdb_def_rule = 1, 4708 .std_tbl_fix = 0 4709 }; 4710 if (action_flags & (MLX5_FLOW_FATE_ACTIONS | 4711 MLX5_FLOW_FATE_ESWITCH_ACTIONS)) 4712 return rte_flow_error_set(error, EINVAL, 4713 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4714 "can't have 2 fate actions in" 4715 " same flow"); 4716 if (action_flags & MLX5_FLOW_ACTION_METER) 4717 return rte_flow_error_set(error, ENOTSUP, 4718 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4719 "jump with meter not support"); 4720 if (!action->conf) 4721 return rte_flow_error_set(error, EINVAL, 4722 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 4723 NULL, "action configuration not set"); 4724 target_group = 4725 ((const struct rte_flow_action_jump *)action->conf)->group; 4726 ret = mlx5_flow_group_to_table(dev, tunnel, target_group, &table, 4727 &grp_info, error); 4728 if (ret) 4729 return ret; 4730 if (attributes->group == target_group && 4731 !(action_flags & (MLX5_FLOW_ACTION_TUNNEL_SET | 4732 MLX5_FLOW_ACTION_TUNNEL_MATCH))) 4733 return rte_flow_error_set(error, EINVAL, 4734 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4735 "target group must be other than" 4736 " the current flow group"); 4737 return 0; 4738 } 4739 4740 /* 4741 * Validate the port_id action. 4742 * 4743 * @param[in] dev 4744 * Pointer to rte_eth_dev structure. 4745 * @param[in] action_flags 4746 * Bit-fields that holds the actions detected until now. 4747 * @param[in] action 4748 * Port_id RTE action structure. 4749 * @param[in] attr 4750 * Attributes of flow that includes this action. 4751 * @param[out] error 4752 * Pointer to error structure. 4753 * 4754 * @return 4755 * 0 on success, a negative errno value otherwise and rte_errno is set. 4756 */ 4757 static int 4758 flow_dv_validate_action_port_id(struct rte_eth_dev *dev, 4759 uint64_t action_flags, 4760 const struct rte_flow_action *action, 4761 const struct rte_flow_attr *attr, 4762 struct rte_flow_error *error) 4763 { 4764 const struct rte_flow_action_port_id *port_id; 4765 struct mlx5_priv *act_priv; 4766 struct mlx5_priv *dev_priv; 4767 uint16_t port; 4768 4769 if (!attr->transfer) 4770 return rte_flow_error_set(error, ENOTSUP, 4771 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4772 NULL, 4773 "port id action is valid in transfer" 4774 " mode only"); 4775 if (!action || !action->conf) 4776 return rte_flow_error_set(error, ENOTSUP, 4777 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 4778 NULL, 4779 "port id action parameters must be" 4780 " specified"); 4781 if (action_flags & (MLX5_FLOW_FATE_ACTIONS | 4782 MLX5_FLOW_FATE_ESWITCH_ACTIONS)) 4783 return rte_flow_error_set(error, EINVAL, 4784 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4785 "can have only one fate actions in" 4786 " a flow"); 4787 dev_priv = mlx5_dev_to_eswitch_info(dev); 4788 if (!dev_priv) 4789 return rte_flow_error_set(error, rte_errno, 4790 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4791 NULL, 4792 "failed to obtain E-Switch info"); 4793 port_id = action->conf; 4794 port = port_id->original ? dev->data->port_id : port_id->id; 4795 act_priv = mlx5_port_to_eswitch_info(port, false); 4796 if (!act_priv) 4797 return rte_flow_error_set 4798 (error, rte_errno, 4799 RTE_FLOW_ERROR_TYPE_ACTION_CONF, port_id, 4800 "failed to obtain E-Switch port id for port"); 4801 if (act_priv->domain_id != dev_priv->domain_id) 4802 return rte_flow_error_set 4803 (error, EINVAL, 4804 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4805 "port does not belong to" 4806 " E-Switch being configured"); 4807 return 0; 4808 } 4809 4810 /** 4811 * Get the maximum number of modify header actions. 4812 * 4813 * @param dev 4814 * Pointer to rte_eth_dev structure. 4815 * @param flags 4816 * Flags bits to check if root level. 4817 * 4818 * @return 4819 * Max number of modify header actions device can support. 4820 */ 4821 static inline unsigned int 4822 flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused, 4823 uint64_t flags) 4824 { 4825 /* 4826 * There's no way to directly query the max capacity from FW. 4827 * The maximal value on root table should be assumed to be supported. 4828 */ 4829 if (!(flags & MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL)) 4830 return MLX5_MAX_MODIFY_NUM; 4831 else 4832 return MLX5_ROOT_TBL_MODIFY_NUM; 4833 } 4834 4835 /** 4836 * Validate the meter action. 4837 * 4838 * @param[in] dev 4839 * Pointer to rte_eth_dev structure. 4840 * @param[in] action_flags 4841 * Bit-fields that holds the actions detected until now. 4842 * @param[in] action 4843 * Pointer to the meter action. 4844 * @param[in] attr 4845 * Attributes of flow that includes this action. 4846 * @param[out] error 4847 * Pointer to error structure. 4848 * 4849 * @return 4850 * 0 on success, a negative errno value otherwise and rte_ernno is set. 4851 */ 4852 static int 4853 mlx5_flow_validate_action_meter(struct rte_eth_dev *dev, 4854 uint64_t action_flags, 4855 const struct rte_flow_action *action, 4856 const struct rte_flow_attr *attr, 4857 struct rte_flow_error *error) 4858 { 4859 struct mlx5_priv *priv = dev->data->dev_private; 4860 const struct rte_flow_action_meter *am = action->conf; 4861 struct mlx5_flow_meter *fm; 4862 4863 if (!am) 4864 return rte_flow_error_set(error, EINVAL, 4865 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4866 "meter action conf is NULL"); 4867 4868 if (action_flags & MLX5_FLOW_ACTION_METER) 4869 return rte_flow_error_set(error, ENOTSUP, 4870 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4871 "meter chaining not support"); 4872 if (action_flags & MLX5_FLOW_ACTION_JUMP) 4873 return rte_flow_error_set(error, ENOTSUP, 4874 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4875 "meter with jump not support"); 4876 if (!priv->mtr_en) 4877 return rte_flow_error_set(error, ENOTSUP, 4878 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4879 NULL, 4880 "meter action not supported"); 4881 fm = mlx5_flow_meter_find(priv, am->mtr_id); 4882 if (!fm) 4883 return rte_flow_error_set(error, EINVAL, 4884 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4885 "Meter not found"); 4886 if (fm->ref_cnt && (!(fm->transfer == attr->transfer || 4887 (!fm->ingress && !attr->ingress && attr->egress) || 4888 (!fm->egress && !attr->egress && attr->ingress)))) 4889 return rte_flow_error_set(error, EINVAL, 4890 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4891 "Flow attributes are either invalid " 4892 "or have a conflict with current " 4893 "meter attributes"); 4894 return 0; 4895 } 4896 4897 /** 4898 * Validate the age action. 4899 * 4900 * @param[in] action_flags 4901 * Holds the actions detected until now. 4902 * @param[in] action 4903 * Pointer to the age action. 4904 * @param[in] dev 4905 * Pointer to the Ethernet device structure. 4906 * @param[out] error 4907 * Pointer to error structure. 4908 * 4909 * @return 4910 * 0 on success, a negative errno value otherwise and rte_errno is set. 4911 */ 4912 static int 4913 flow_dv_validate_action_age(uint64_t action_flags, 4914 const struct rte_flow_action *action, 4915 struct rte_eth_dev *dev, 4916 struct rte_flow_error *error) 4917 { 4918 struct mlx5_priv *priv = dev->data->dev_private; 4919 const struct rte_flow_action_age *age = action->conf; 4920 4921 if (!priv->config.devx || (priv->sh->cmng.counter_fallback && 4922 !priv->sh->aso_age_mng)) 4923 return rte_flow_error_set(error, ENOTSUP, 4924 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4925 NULL, 4926 "age action not supported"); 4927 if (!(action->conf)) 4928 return rte_flow_error_set(error, EINVAL, 4929 RTE_FLOW_ERROR_TYPE_ACTION, action, 4930 "configuration cannot be null"); 4931 if (!(age->timeout)) 4932 return rte_flow_error_set(error, EINVAL, 4933 RTE_FLOW_ERROR_TYPE_ACTION, action, 4934 "invalid timeout value 0"); 4935 if (action_flags & MLX5_FLOW_ACTION_AGE) 4936 return rte_flow_error_set(error, EINVAL, 4937 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 4938 "duplicate age actions set"); 4939 return 0; 4940 } 4941 4942 /** 4943 * Validate the modify-header IPv4 DSCP actions. 4944 * 4945 * @param[in] action_flags 4946 * Holds the actions detected until now. 4947 * @param[in] action 4948 * Pointer to the modify action. 4949 * @param[in] item_flags 4950 * Holds the items detected. 4951 * @param[out] error 4952 * Pointer to error structure. 4953 * 4954 * @return 4955 * 0 on success, a negative errno value otherwise and rte_errno is set. 4956 */ 4957 static int 4958 flow_dv_validate_action_modify_ipv4_dscp(const uint64_t action_flags, 4959 const struct rte_flow_action *action, 4960 const uint64_t item_flags, 4961 struct rte_flow_error *error) 4962 { 4963 int ret = 0; 4964 4965 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 4966 if (!ret) { 4967 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV4)) 4968 return rte_flow_error_set(error, EINVAL, 4969 RTE_FLOW_ERROR_TYPE_ACTION, 4970 NULL, 4971 "no ipv4 item in pattern"); 4972 } 4973 return ret; 4974 } 4975 4976 /** 4977 * Validate the modify-header IPv6 DSCP actions. 4978 * 4979 * @param[in] action_flags 4980 * Holds the actions detected until now. 4981 * @param[in] action 4982 * Pointer to the modify action. 4983 * @param[in] item_flags 4984 * Holds the items detected. 4985 * @param[out] error 4986 * Pointer to error structure. 4987 * 4988 * @return 4989 * 0 on success, a negative errno value otherwise and rte_errno is set. 4990 */ 4991 static int 4992 flow_dv_validate_action_modify_ipv6_dscp(const uint64_t action_flags, 4993 const struct rte_flow_action *action, 4994 const uint64_t item_flags, 4995 struct rte_flow_error *error) 4996 { 4997 int ret = 0; 4998 4999 ret = flow_dv_validate_action_modify_hdr(action_flags, action, error); 5000 if (!ret) { 5001 if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV6)) 5002 return rte_flow_error_set(error, EINVAL, 5003 RTE_FLOW_ERROR_TYPE_ACTION, 5004 NULL, 5005 "no ipv6 item in pattern"); 5006 } 5007 return ret; 5008 } 5009 5010 /** 5011 * Match modify-header resource. 5012 * 5013 * @param list 5014 * Pointer to the hash list. 5015 * @param entry 5016 * Pointer to exist resource entry object. 5017 * @param key 5018 * Key of the new entry. 5019 * @param ctx 5020 * Pointer to new modify-header resource. 5021 * 5022 * @return 5023 * 0 on matching, non-zero otherwise. 5024 */ 5025 int 5026 flow_dv_modify_match_cb(struct mlx5_hlist *list __rte_unused, 5027 struct mlx5_hlist_entry *entry, 5028 uint64_t key __rte_unused, void *cb_ctx) 5029 { 5030 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 5031 struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data; 5032 struct mlx5_flow_dv_modify_hdr_resource *resource = 5033 container_of(entry, typeof(*resource), entry); 5034 uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type); 5035 5036 key_len += ref->actions_num * sizeof(ref->actions[0]); 5037 return ref->actions_num != resource->actions_num || 5038 memcmp(&ref->ft_type, &resource->ft_type, key_len); 5039 } 5040 5041 struct mlx5_hlist_entry * 5042 flow_dv_modify_create_cb(struct mlx5_hlist *list, uint64_t key __rte_unused, 5043 void *cb_ctx) 5044 { 5045 struct mlx5_dev_ctx_shared *sh = list->ctx; 5046 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 5047 struct mlx5dv_dr_domain *ns; 5048 struct mlx5_flow_dv_modify_hdr_resource *entry; 5049 struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data; 5050 int ret; 5051 uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]); 5052 uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type); 5053 5054 entry = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*entry) + data_len, 0, 5055 SOCKET_ID_ANY); 5056 if (!entry) { 5057 rte_flow_error_set(ctx->error, ENOMEM, 5058 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 5059 "cannot allocate resource memory"); 5060 return NULL; 5061 } 5062 rte_memcpy(&entry->ft_type, 5063 RTE_PTR_ADD(ref, offsetof(typeof(*ref), ft_type)), 5064 key_len + data_len); 5065 if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) 5066 ns = sh->fdb_domain; 5067 else if (entry->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX) 5068 ns = sh->tx_domain; 5069 else 5070 ns = sh->rx_domain; 5071 ret = mlx5_flow_os_create_flow_action_modify_header 5072 (sh->ctx, ns, entry, 5073 data_len, &entry->action); 5074 if (ret) { 5075 mlx5_free(entry); 5076 rte_flow_error_set(ctx->error, ENOMEM, 5077 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 5078 NULL, "cannot create modification action"); 5079 return NULL; 5080 } 5081 return &entry->entry; 5082 } 5083 5084 /** 5085 * Validate the sample action. 5086 * 5087 * @param[in, out] action_flags 5088 * Holds the actions detected until now. 5089 * @param[in] action 5090 * Pointer to the sample action. 5091 * @param[in] dev 5092 * Pointer to the Ethernet device structure. 5093 * @param[in] attr 5094 * Attributes of flow that includes this action. 5095 * @param[in] item_flags 5096 * Holds the items detected. 5097 * @param[in] rss 5098 * Pointer to the RSS action. 5099 * @param[out] sample_rss 5100 * Pointer to the RSS action in sample action list. 5101 * @param[out] count 5102 * Pointer to the COUNT action in sample action list. 5103 * @param[out] fdb_mirror_limit 5104 * Pointer to the FDB mirror limitation flag. 5105 * @param[out] error 5106 * Pointer to error structure. 5107 * 5108 * @return 5109 * 0 on success, a negative errno value otherwise and rte_errno is set. 5110 */ 5111 static int 5112 flow_dv_validate_action_sample(uint64_t *action_flags, 5113 const struct rte_flow_action *action, 5114 struct rte_eth_dev *dev, 5115 const struct rte_flow_attr *attr, 5116 uint64_t item_flags, 5117 const struct rte_flow_action_rss *rss, 5118 const struct rte_flow_action_rss **sample_rss, 5119 const struct rte_flow_action_count **count, 5120 int *fdb_mirror_limit, 5121 struct rte_flow_error *error) 5122 { 5123 struct mlx5_priv *priv = dev->data->dev_private; 5124 struct mlx5_dev_config *dev_conf = &priv->config; 5125 const struct rte_flow_action_sample *sample = action->conf; 5126 const struct rte_flow_action *act; 5127 uint64_t sub_action_flags = 0; 5128 uint16_t queue_index = 0xFFFF; 5129 int actions_n = 0; 5130 int ret; 5131 5132 if (!sample) 5133 return rte_flow_error_set(error, EINVAL, 5134 RTE_FLOW_ERROR_TYPE_ACTION, action, 5135 "configuration cannot be NULL"); 5136 if (sample->ratio == 0) 5137 return rte_flow_error_set(error, EINVAL, 5138 RTE_FLOW_ERROR_TYPE_ACTION, action, 5139 "ratio value starts from 1"); 5140 if (!priv->config.devx || (sample->ratio > 0 && !priv->sampler_en)) 5141 return rte_flow_error_set(error, ENOTSUP, 5142 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 5143 NULL, 5144 "sample action not supported"); 5145 if (*action_flags & MLX5_FLOW_ACTION_SAMPLE) 5146 return rte_flow_error_set(error, EINVAL, 5147 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 5148 "Multiple sample actions not " 5149 "supported"); 5150 if (*action_flags & MLX5_FLOW_ACTION_METER) 5151 return rte_flow_error_set(error, EINVAL, 5152 RTE_FLOW_ERROR_TYPE_ACTION, action, 5153 "wrong action order, meter should " 5154 "be after sample action"); 5155 if (*action_flags & MLX5_FLOW_ACTION_JUMP) 5156 return rte_flow_error_set(error, EINVAL, 5157 RTE_FLOW_ERROR_TYPE_ACTION, action, 5158 "wrong action order, jump should " 5159 "be after sample action"); 5160 act = sample->actions; 5161 for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++) { 5162 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS) 5163 return rte_flow_error_set(error, ENOTSUP, 5164 RTE_FLOW_ERROR_TYPE_ACTION, 5165 act, "too many actions"); 5166 switch (act->type) { 5167 case RTE_FLOW_ACTION_TYPE_QUEUE: 5168 ret = mlx5_flow_validate_action_queue(act, 5169 sub_action_flags, 5170 dev, 5171 attr, error); 5172 if (ret < 0) 5173 return ret; 5174 queue_index = ((const struct rte_flow_action_queue *) 5175 (act->conf))->index; 5176 sub_action_flags |= MLX5_FLOW_ACTION_QUEUE; 5177 ++actions_n; 5178 break; 5179 case RTE_FLOW_ACTION_TYPE_RSS: 5180 *sample_rss = act->conf; 5181 ret = mlx5_flow_validate_action_rss(act, 5182 sub_action_flags, 5183 dev, attr, 5184 item_flags, 5185 error); 5186 if (ret < 0) 5187 return ret; 5188 if (rss && *sample_rss && 5189 ((*sample_rss)->level != rss->level || 5190 (*sample_rss)->types != rss->types)) 5191 return rte_flow_error_set(error, ENOTSUP, 5192 RTE_FLOW_ERROR_TYPE_ACTION, 5193 NULL, 5194 "Can't use the different RSS types " 5195 "or level in the same flow"); 5196 if (*sample_rss != NULL && (*sample_rss)->queue_num) 5197 queue_index = (*sample_rss)->queue[0]; 5198 sub_action_flags |= MLX5_FLOW_ACTION_RSS; 5199 ++actions_n; 5200 break; 5201 case RTE_FLOW_ACTION_TYPE_MARK: 5202 ret = flow_dv_validate_action_mark(dev, act, 5203 sub_action_flags, 5204 attr, error); 5205 if (ret < 0) 5206 return ret; 5207 if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) 5208 sub_action_flags |= MLX5_FLOW_ACTION_MARK | 5209 MLX5_FLOW_ACTION_MARK_EXT; 5210 else 5211 sub_action_flags |= MLX5_FLOW_ACTION_MARK; 5212 ++actions_n; 5213 break; 5214 case RTE_FLOW_ACTION_TYPE_COUNT: 5215 ret = flow_dv_validate_action_count 5216 (dev, act, 5217 *action_flags | sub_action_flags, 5218 error); 5219 if (ret < 0) 5220 return ret; 5221 *count = act->conf; 5222 sub_action_flags |= MLX5_FLOW_ACTION_COUNT; 5223 *action_flags |= MLX5_FLOW_ACTION_COUNT; 5224 ++actions_n; 5225 break; 5226 case RTE_FLOW_ACTION_TYPE_PORT_ID: 5227 ret = flow_dv_validate_action_port_id(dev, 5228 sub_action_flags, 5229 act, 5230 attr, 5231 error); 5232 if (ret) 5233 return ret; 5234 sub_action_flags |= MLX5_FLOW_ACTION_PORT_ID; 5235 ++actions_n; 5236 break; 5237 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 5238 ret = flow_dv_validate_action_raw_encap_decap 5239 (dev, NULL, act->conf, attr, &sub_action_flags, 5240 &actions_n, action, item_flags, error); 5241 if (ret < 0) 5242 return ret; 5243 ++actions_n; 5244 break; 5245 default: 5246 return rte_flow_error_set(error, ENOTSUP, 5247 RTE_FLOW_ERROR_TYPE_ACTION, 5248 NULL, 5249 "Doesn't support optional " 5250 "action"); 5251 } 5252 } 5253 if (attr->ingress && !attr->transfer) { 5254 if (!(sub_action_flags & (MLX5_FLOW_ACTION_QUEUE | 5255 MLX5_FLOW_ACTION_RSS))) 5256 return rte_flow_error_set(error, EINVAL, 5257 RTE_FLOW_ERROR_TYPE_ACTION, 5258 NULL, 5259 "Ingress must has a dest " 5260 "QUEUE for Sample"); 5261 } else if (attr->egress && !attr->transfer) { 5262 return rte_flow_error_set(error, ENOTSUP, 5263 RTE_FLOW_ERROR_TYPE_ACTION, 5264 NULL, 5265 "Sample Only support Ingress " 5266 "or E-Switch"); 5267 } else if (sample->actions->type != RTE_FLOW_ACTION_TYPE_END) { 5268 MLX5_ASSERT(attr->transfer); 5269 if (sample->ratio > 1) 5270 return rte_flow_error_set(error, ENOTSUP, 5271 RTE_FLOW_ERROR_TYPE_ACTION, 5272 NULL, 5273 "E-Switch doesn't support " 5274 "any optional action " 5275 "for sampling"); 5276 if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE) 5277 return rte_flow_error_set(error, ENOTSUP, 5278 RTE_FLOW_ERROR_TYPE_ACTION, 5279 NULL, 5280 "unsupported action QUEUE"); 5281 if (sub_action_flags & MLX5_FLOW_ACTION_RSS) 5282 return rte_flow_error_set(error, ENOTSUP, 5283 RTE_FLOW_ERROR_TYPE_ACTION, 5284 NULL, 5285 "unsupported action QUEUE"); 5286 if (!(sub_action_flags & MLX5_FLOW_ACTION_PORT_ID)) 5287 return rte_flow_error_set(error, EINVAL, 5288 RTE_FLOW_ERROR_TYPE_ACTION, 5289 NULL, 5290 "E-Switch must has a dest " 5291 "port for mirroring"); 5292 if (!priv->config.hca_attr.reg_c_preserve && 5293 priv->representor_id != -1) 5294 *fdb_mirror_limit = 1; 5295 } 5296 /* Continue validation for Xcap actions.*/ 5297 if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) && 5298 (queue_index == 0xFFFF || 5299 mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) { 5300 if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) == 5301 MLX5_FLOW_XCAP_ACTIONS) 5302 return rte_flow_error_set(error, ENOTSUP, 5303 RTE_FLOW_ERROR_TYPE_ACTION, 5304 NULL, "encap and decap " 5305 "combination aren't " 5306 "supported"); 5307 if (!attr->transfer && attr->ingress && (sub_action_flags & 5308 MLX5_FLOW_ACTION_ENCAP)) 5309 return rte_flow_error_set(error, ENOTSUP, 5310 RTE_FLOW_ERROR_TYPE_ACTION, 5311 NULL, "encap is not supported" 5312 " for ingress traffic"); 5313 } 5314 return 0; 5315 } 5316 5317 /** 5318 * Find existing modify-header resource or create and register a new one. 5319 * 5320 * @param dev[in, out] 5321 * Pointer to rte_eth_dev structure. 5322 * @param[in, out] resource 5323 * Pointer to modify-header resource. 5324 * @parm[in, out] dev_flow 5325 * Pointer to the dev_flow. 5326 * @param[out] error 5327 * pointer to error structure. 5328 * 5329 * @return 5330 * 0 on success otherwise -errno and errno is set. 5331 */ 5332 static int 5333 flow_dv_modify_hdr_resource_register 5334 (struct rte_eth_dev *dev, 5335 struct mlx5_flow_dv_modify_hdr_resource *resource, 5336 struct mlx5_flow *dev_flow, 5337 struct rte_flow_error *error) 5338 { 5339 struct mlx5_priv *priv = dev->data->dev_private; 5340 struct mlx5_dev_ctx_shared *sh = priv->sh; 5341 uint32_t key_len = sizeof(*resource) - 5342 offsetof(typeof(*resource), ft_type) + 5343 resource->actions_num * sizeof(resource->actions[0]); 5344 struct mlx5_hlist_entry *entry; 5345 struct mlx5_flow_cb_ctx ctx = { 5346 .error = error, 5347 .data = resource, 5348 }; 5349 uint64_t key64; 5350 5351 resource->flags = dev_flow->dv.group ? 0 : 5352 MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL; 5353 if (resource->actions_num > flow_dv_modify_hdr_action_max(dev, 5354 resource->flags)) 5355 return rte_flow_error_set(error, EOVERFLOW, 5356 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 5357 "too many modify header items"); 5358 key64 = __rte_raw_cksum(&resource->ft_type, key_len, 0); 5359 entry = mlx5_hlist_register(sh->modify_cmds, key64, &ctx); 5360 if (!entry) 5361 return -rte_errno; 5362 resource = container_of(entry, typeof(*resource), entry); 5363 dev_flow->handle->dvh.modify_hdr = resource; 5364 return 0; 5365 } 5366 5367 /** 5368 * Get DV flow counter by index. 5369 * 5370 * @param[in] dev 5371 * Pointer to the Ethernet device structure. 5372 * @param[in] idx 5373 * mlx5 flow counter index in the container. 5374 * @param[out] ppool 5375 * mlx5 flow counter pool in the container, 5376 * 5377 * @return 5378 * Pointer to the counter, NULL otherwise. 5379 */ 5380 static struct mlx5_flow_counter * 5381 flow_dv_counter_get_by_idx(struct rte_eth_dev *dev, 5382 uint32_t idx, 5383 struct mlx5_flow_counter_pool **ppool) 5384 { 5385 struct mlx5_priv *priv = dev->data->dev_private; 5386 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 5387 struct mlx5_flow_counter_pool *pool; 5388 5389 /* Decrease to original index and clear shared bit. */ 5390 idx = (idx - 1) & (MLX5_CNT_SHARED_OFFSET - 1); 5391 MLX5_ASSERT(idx / MLX5_COUNTERS_PER_POOL < cmng->n); 5392 pool = cmng->pools[idx / MLX5_COUNTERS_PER_POOL]; 5393 MLX5_ASSERT(pool); 5394 if (ppool) 5395 *ppool = pool; 5396 return MLX5_POOL_GET_CNT(pool, idx % MLX5_COUNTERS_PER_POOL); 5397 } 5398 5399 /** 5400 * Check the devx counter belongs to the pool. 5401 * 5402 * @param[in] pool 5403 * Pointer to the counter pool. 5404 * @param[in] id 5405 * The counter devx ID. 5406 * 5407 * @return 5408 * True if counter belongs to the pool, false otherwise. 5409 */ 5410 static bool 5411 flow_dv_is_counter_in_pool(struct mlx5_flow_counter_pool *pool, int id) 5412 { 5413 int base = (pool->min_dcs->id / MLX5_COUNTERS_PER_POOL) * 5414 MLX5_COUNTERS_PER_POOL; 5415 5416 if (id >= base && id < base + MLX5_COUNTERS_PER_POOL) 5417 return true; 5418 return false; 5419 } 5420 5421 /** 5422 * Get a pool by devx counter ID. 5423 * 5424 * @param[in] cmng 5425 * Pointer to the counter management. 5426 * @param[in] id 5427 * The counter devx ID. 5428 * 5429 * @return 5430 * The counter pool pointer if exists, NULL otherwise, 5431 */ 5432 static struct mlx5_flow_counter_pool * 5433 flow_dv_find_pool_by_id(struct mlx5_flow_counter_mng *cmng, int id) 5434 { 5435 uint32_t i; 5436 struct mlx5_flow_counter_pool *pool = NULL; 5437 5438 rte_spinlock_lock(&cmng->pool_update_sl); 5439 /* Check last used pool. */ 5440 if (cmng->last_pool_idx != POOL_IDX_INVALID && 5441 flow_dv_is_counter_in_pool(cmng->pools[cmng->last_pool_idx], id)) { 5442 pool = cmng->pools[cmng->last_pool_idx]; 5443 goto out; 5444 } 5445 /* ID out of range means no suitable pool in the container. */ 5446 if (id > cmng->max_id || id < cmng->min_id) 5447 goto out; 5448 /* 5449 * Find the pool from the end of the container, since mostly counter 5450 * ID is sequence increasing, and the last pool should be the needed 5451 * one. 5452 */ 5453 i = cmng->n_valid; 5454 while (i--) { 5455 struct mlx5_flow_counter_pool *pool_tmp = cmng->pools[i]; 5456 5457 if (flow_dv_is_counter_in_pool(pool_tmp, id)) { 5458 pool = pool_tmp; 5459 break; 5460 } 5461 } 5462 out: 5463 rte_spinlock_unlock(&cmng->pool_update_sl); 5464 return pool; 5465 } 5466 5467 /** 5468 * Resize a counter container. 5469 * 5470 * @param[in] dev 5471 * Pointer to the Ethernet device structure. 5472 * 5473 * @return 5474 * 0 on success, otherwise negative errno value and rte_errno is set. 5475 */ 5476 static int 5477 flow_dv_container_resize(struct rte_eth_dev *dev) 5478 { 5479 struct mlx5_priv *priv = dev->data->dev_private; 5480 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 5481 void *old_pools = cmng->pools; 5482 uint32_t resize = cmng->n + MLX5_CNT_CONTAINER_RESIZE; 5483 uint32_t mem_size = sizeof(struct mlx5_flow_counter_pool *) * resize; 5484 void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY); 5485 5486 if (!pools) { 5487 rte_errno = ENOMEM; 5488 return -ENOMEM; 5489 } 5490 if (old_pools) 5491 memcpy(pools, old_pools, cmng->n * 5492 sizeof(struct mlx5_flow_counter_pool *)); 5493 cmng->n = resize; 5494 cmng->pools = pools; 5495 if (old_pools) 5496 mlx5_free(old_pools); 5497 return 0; 5498 } 5499 5500 /** 5501 * Query a devx flow counter. 5502 * 5503 * @param[in] dev 5504 * Pointer to the Ethernet device structure. 5505 * @param[in] cnt 5506 * Index to the flow counter. 5507 * @param[out] pkts 5508 * The statistics value of packets. 5509 * @param[out] bytes 5510 * The statistics value of bytes. 5511 * 5512 * @return 5513 * 0 on success, otherwise a negative errno value and rte_errno is set. 5514 */ 5515 static inline int 5516 _flow_dv_query_count(struct rte_eth_dev *dev, uint32_t counter, uint64_t *pkts, 5517 uint64_t *bytes) 5518 { 5519 struct mlx5_priv *priv = dev->data->dev_private; 5520 struct mlx5_flow_counter_pool *pool = NULL; 5521 struct mlx5_flow_counter *cnt; 5522 int offset; 5523 5524 cnt = flow_dv_counter_get_by_idx(dev, counter, &pool); 5525 MLX5_ASSERT(pool); 5526 if (priv->sh->cmng.counter_fallback) 5527 return mlx5_devx_cmd_flow_counter_query(cnt->dcs_when_active, 0, 5528 0, pkts, bytes, 0, NULL, NULL, 0); 5529 rte_spinlock_lock(&pool->sl); 5530 if (!pool->raw) { 5531 *pkts = 0; 5532 *bytes = 0; 5533 } else { 5534 offset = MLX5_CNT_ARRAY_IDX(pool, cnt); 5535 *pkts = rte_be_to_cpu_64(pool->raw->data[offset].hits); 5536 *bytes = rte_be_to_cpu_64(pool->raw->data[offset].bytes); 5537 } 5538 rte_spinlock_unlock(&pool->sl); 5539 return 0; 5540 } 5541 5542 /** 5543 * Create and initialize a new counter pool. 5544 * 5545 * @param[in] dev 5546 * Pointer to the Ethernet device structure. 5547 * @param[out] dcs 5548 * The devX counter handle. 5549 * @param[in] age 5550 * Whether the pool is for counter that was allocated for aging. 5551 * @param[in/out] cont_cur 5552 * Pointer to the container pointer, it will be update in pool resize. 5553 * 5554 * @return 5555 * The pool container pointer on success, NULL otherwise and rte_errno is set. 5556 */ 5557 static struct mlx5_flow_counter_pool * 5558 flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs, 5559 uint32_t age) 5560 { 5561 struct mlx5_priv *priv = dev->data->dev_private; 5562 struct mlx5_flow_counter_pool *pool; 5563 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 5564 bool fallback = priv->sh->cmng.counter_fallback; 5565 uint32_t size = sizeof(*pool); 5566 5567 size += MLX5_COUNTERS_PER_POOL * MLX5_CNT_SIZE; 5568 size += (!age ? 0 : MLX5_COUNTERS_PER_POOL * MLX5_AGE_SIZE); 5569 pool = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY); 5570 if (!pool) { 5571 rte_errno = ENOMEM; 5572 return NULL; 5573 } 5574 pool->raw = NULL; 5575 pool->is_aged = !!age; 5576 pool->query_gen = 0; 5577 pool->min_dcs = dcs; 5578 rte_spinlock_init(&pool->sl); 5579 rte_spinlock_init(&pool->csl); 5580 TAILQ_INIT(&pool->counters[0]); 5581 TAILQ_INIT(&pool->counters[1]); 5582 pool->time_of_last_age_check = MLX5_CURR_TIME_SEC; 5583 rte_spinlock_lock(&cmng->pool_update_sl); 5584 pool->index = cmng->n_valid; 5585 if (pool->index == cmng->n && flow_dv_container_resize(dev)) { 5586 mlx5_free(pool); 5587 rte_spinlock_unlock(&cmng->pool_update_sl); 5588 return NULL; 5589 } 5590 cmng->pools[pool->index] = pool; 5591 cmng->n_valid++; 5592 if (unlikely(fallback)) { 5593 int base = RTE_ALIGN_FLOOR(dcs->id, MLX5_COUNTERS_PER_POOL); 5594 5595 if (base < cmng->min_id) 5596 cmng->min_id = base; 5597 if (base > cmng->max_id) 5598 cmng->max_id = base + MLX5_COUNTERS_PER_POOL - 1; 5599 cmng->last_pool_idx = pool->index; 5600 } 5601 rte_spinlock_unlock(&cmng->pool_update_sl); 5602 return pool; 5603 } 5604 5605 /** 5606 * Prepare a new counter and/or a new counter pool. 5607 * 5608 * @param[in] dev 5609 * Pointer to the Ethernet device structure. 5610 * @param[out] cnt_free 5611 * Where to put the pointer of a new counter. 5612 * @param[in] age 5613 * Whether the pool is for counter that was allocated for aging. 5614 * 5615 * @return 5616 * The counter pool pointer and @p cnt_free is set on success, 5617 * NULL otherwise and rte_errno is set. 5618 */ 5619 static struct mlx5_flow_counter_pool * 5620 flow_dv_counter_pool_prepare(struct rte_eth_dev *dev, 5621 struct mlx5_flow_counter **cnt_free, 5622 uint32_t age) 5623 { 5624 struct mlx5_priv *priv = dev->data->dev_private; 5625 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 5626 struct mlx5_flow_counter_pool *pool; 5627 struct mlx5_counters tmp_tq; 5628 struct mlx5_devx_obj *dcs = NULL; 5629 struct mlx5_flow_counter *cnt; 5630 enum mlx5_counter_type cnt_type = 5631 age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN; 5632 bool fallback = priv->sh->cmng.counter_fallback; 5633 uint32_t i; 5634 5635 if (fallback) { 5636 /* bulk_bitmap must be 0 for single counter allocation. */ 5637 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->ctx, 0); 5638 if (!dcs) 5639 return NULL; 5640 pool = flow_dv_find_pool_by_id(cmng, dcs->id); 5641 if (!pool) { 5642 pool = flow_dv_pool_create(dev, dcs, age); 5643 if (!pool) { 5644 mlx5_devx_cmd_destroy(dcs); 5645 return NULL; 5646 } 5647 } 5648 i = dcs->id % MLX5_COUNTERS_PER_POOL; 5649 cnt = MLX5_POOL_GET_CNT(pool, i); 5650 cnt->pool = pool; 5651 cnt->dcs_when_free = dcs; 5652 *cnt_free = cnt; 5653 return pool; 5654 } 5655 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->ctx, 0x4); 5656 if (!dcs) { 5657 rte_errno = ENODATA; 5658 return NULL; 5659 } 5660 pool = flow_dv_pool_create(dev, dcs, age); 5661 if (!pool) { 5662 mlx5_devx_cmd_destroy(dcs); 5663 return NULL; 5664 } 5665 TAILQ_INIT(&tmp_tq); 5666 for (i = 1; i < MLX5_COUNTERS_PER_POOL; ++i) { 5667 cnt = MLX5_POOL_GET_CNT(pool, i); 5668 cnt->pool = pool; 5669 TAILQ_INSERT_HEAD(&tmp_tq, cnt, next); 5670 } 5671 rte_spinlock_lock(&cmng->csl[cnt_type]); 5672 TAILQ_CONCAT(&cmng->counters[cnt_type], &tmp_tq, next); 5673 rte_spinlock_unlock(&cmng->csl[cnt_type]); 5674 *cnt_free = MLX5_POOL_GET_CNT(pool, 0); 5675 (*cnt_free)->pool = pool; 5676 return pool; 5677 } 5678 5679 /** 5680 * Allocate a flow counter. 5681 * 5682 * @param[in] dev 5683 * Pointer to the Ethernet device structure. 5684 * @param[in] age 5685 * Whether the counter was allocated for aging. 5686 * 5687 * @return 5688 * Index to flow counter on success, 0 otherwise and rte_errno is set. 5689 */ 5690 static uint32_t 5691 flow_dv_counter_alloc(struct rte_eth_dev *dev, uint32_t age) 5692 { 5693 struct mlx5_priv *priv = dev->data->dev_private; 5694 struct mlx5_flow_counter_pool *pool = NULL; 5695 struct mlx5_flow_counter *cnt_free = NULL; 5696 bool fallback = priv->sh->cmng.counter_fallback; 5697 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 5698 enum mlx5_counter_type cnt_type = 5699 age ? MLX5_COUNTER_TYPE_AGE : MLX5_COUNTER_TYPE_ORIGIN; 5700 uint32_t cnt_idx; 5701 5702 if (!priv->config.devx) { 5703 rte_errno = ENOTSUP; 5704 return 0; 5705 } 5706 /* Get free counters from container. */ 5707 rte_spinlock_lock(&cmng->csl[cnt_type]); 5708 cnt_free = TAILQ_FIRST(&cmng->counters[cnt_type]); 5709 if (cnt_free) 5710 TAILQ_REMOVE(&cmng->counters[cnt_type], cnt_free, next); 5711 rte_spinlock_unlock(&cmng->csl[cnt_type]); 5712 if (!cnt_free && !flow_dv_counter_pool_prepare(dev, &cnt_free, age)) 5713 goto err; 5714 pool = cnt_free->pool; 5715 if (fallback) 5716 cnt_free->dcs_when_active = cnt_free->dcs_when_free; 5717 /* Create a DV counter action only in the first time usage. */ 5718 if (!cnt_free->action) { 5719 uint16_t offset; 5720 struct mlx5_devx_obj *dcs; 5721 int ret; 5722 5723 if (!fallback) { 5724 offset = MLX5_CNT_ARRAY_IDX(pool, cnt_free); 5725 dcs = pool->min_dcs; 5726 } else { 5727 offset = 0; 5728 dcs = cnt_free->dcs_when_free; 5729 } 5730 ret = mlx5_flow_os_create_flow_action_count(dcs->obj, offset, 5731 &cnt_free->action); 5732 if (ret) { 5733 rte_errno = errno; 5734 goto err; 5735 } 5736 } 5737 cnt_idx = MLX5_MAKE_CNT_IDX(pool->index, 5738 MLX5_CNT_ARRAY_IDX(pool, cnt_free)); 5739 /* Update the counter reset values. */ 5740 if (_flow_dv_query_count(dev, cnt_idx, &cnt_free->hits, 5741 &cnt_free->bytes)) 5742 goto err; 5743 if (!fallback && !priv->sh->cmng.query_thread_on) 5744 /* Start the asynchronous batch query by the host thread. */ 5745 mlx5_set_query_alarm(priv->sh); 5746 return cnt_idx; 5747 err: 5748 if (cnt_free) { 5749 cnt_free->pool = pool; 5750 if (fallback) 5751 cnt_free->dcs_when_free = cnt_free->dcs_when_active; 5752 rte_spinlock_lock(&cmng->csl[cnt_type]); 5753 TAILQ_INSERT_TAIL(&cmng->counters[cnt_type], cnt_free, next); 5754 rte_spinlock_unlock(&cmng->csl[cnt_type]); 5755 } 5756 return 0; 5757 } 5758 5759 /** 5760 * Allocate a shared flow counter. 5761 * 5762 * @param[in] ctx 5763 * Pointer to the shared counter configuration. 5764 * @param[in] data 5765 * Pointer to save the allocated counter index. 5766 * 5767 * @return 5768 * Index to flow counter on success, 0 otherwise and rte_errno is set. 5769 */ 5770 5771 static int32_t 5772 flow_dv_counter_alloc_shared_cb(void *ctx, union mlx5_l3t_data *data) 5773 { 5774 struct mlx5_shared_counter_conf *conf = ctx; 5775 struct rte_eth_dev *dev = conf->dev; 5776 struct mlx5_flow_counter *cnt; 5777 5778 data->dword = flow_dv_counter_alloc(dev, 0); 5779 data->dword |= MLX5_CNT_SHARED_OFFSET; 5780 cnt = flow_dv_counter_get_by_idx(dev, data->dword, NULL); 5781 cnt->shared_info.id = conf->id; 5782 return 0; 5783 } 5784 5785 /** 5786 * Get a shared flow counter. 5787 * 5788 * @param[in] dev 5789 * Pointer to the Ethernet device structure. 5790 * @param[in] id 5791 * Counter identifier. 5792 * 5793 * @return 5794 * Index to flow counter on success, 0 otherwise and rte_errno is set. 5795 */ 5796 static uint32_t 5797 flow_dv_counter_get_shared(struct rte_eth_dev *dev, uint32_t id) 5798 { 5799 struct mlx5_priv *priv = dev->data->dev_private; 5800 struct mlx5_shared_counter_conf conf = { 5801 .dev = dev, 5802 .id = id, 5803 }; 5804 union mlx5_l3t_data data = { 5805 .dword = 0, 5806 }; 5807 5808 mlx5_l3t_prepare_entry(priv->sh->cnt_id_tbl, id, &data, 5809 flow_dv_counter_alloc_shared_cb, &conf); 5810 return data.dword; 5811 } 5812 5813 /** 5814 * Get age param from counter index. 5815 * 5816 * @param[in] dev 5817 * Pointer to the Ethernet device structure. 5818 * @param[in] counter 5819 * Index to the counter handler. 5820 * 5821 * @return 5822 * The aging parameter specified for the counter index. 5823 */ 5824 static struct mlx5_age_param* 5825 flow_dv_counter_idx_get_age(struct rte_eth_dev *dev, 5826 uint32_t counter) 5827 { 5828 struct mlx5_flow_counter *cnt; 5829 struct mlx5_flow_counter_pool *pool = NULL; 5830 5831 flow_dv_counter_get_by_idx(dev, counter, &pool); 5832 counter = (counter - 1) % MLX5_COUNTERS_PER_POOL; 5833 cnt = MLX5_POOL_GET_CNT(pool, counter); 5834 return MLX5_CNT_TO_AGE(cnt); 5835 } 5836 5837 /** 5838 * Remove a flow counter from aged counter list. 5839 * 5840 * @param[in] dev 5841 * Pointer to the Ethernet device structure. 5842 * @param[in] counter 5843 * Index to the counter handler. 5844 * @param[in] cnt 5845 * Pointer to the counter handler. 5846 */ 5847 static void 5848 flow_dv_counter_remove_from_age(struct rte_eth_dev *dev, 5849 uint32_t counter, struct mlx5_flow_counter *cnt) 5850 { 5851 struct mlx5_age_info *age_info; 5852 struct mlx5_age_param *age_param; 5853 struct mlx5_priv *priv = dev->data->dev_private; 5854 uint16_t expected = AGE_CANDIDATE; 5855 5856 age_info = GET_PORT_AGE_INFO(priv); 5857 age_param = flow_dv_counter_idx_get_age(dev, counter); 5858 if (!__atomic_compare_exchange_n(&age_param->state, &expected, 5859 AGE_FREE, false, __ATOMIC_RELAXED, 5860 __ATOMIC_RELAXED)) { 5861 /** 5862 * We need the lock even it is age timeout, 5863 * since counter may still in process. 5864 */ 5865 rte_spinlock_lock(&age_info->aged_sl); 5866 TAILQ_REMOVE(&age_info->aged_counters, cnt, next); 5867 rte_spinlock_unlock(&age_info->aged_sl); 5868 __atomic_store_n(&age_param->state, AGE_FREE, __ATOMIC_RELAXED); 5869 } 5870 } 5871 5872 /** 5873 * Release a flow counter. 5874 * 5875 * @param[in] dev 5876 * Pointer to the Ethernet device structure. 5877 * @param[in] counter 5878 * Index to the counter handler. 5879 */ 5880 static void 5881 flow_dv_counter_free(struct rte_eth_dev *dev, uint32_t counter) 5882 { 5883 struct mlx5_priv *priv = dev->data->dev_private; 5884 struct mlx5_flow_counter_pool *pool = NULL; 5885 struct mlx5_flow_counter *cnt; 5886 enum mlx5_counter_type cnt_type; 5887 5888 if (!counter) 5889 return; 5890 cnt = flow_dv_counter_get_by_idx(dev, counter, &pool); 5891 MLX5_ASSERT(pool); 5892 if (IS_SHARED_CNT(counter) && 5893 mlx5_l3t_clear_entry(priv->sh->cnt_id_tbl, cnt->shared_info.id)) 5894 return; 5895 if (pool->is_aged) 5896 flow_dv_counter_remove_from_age(dev, counter, cnt); 5897 cnt->pool = pool; 5898 /* 5899 * Put the counter back to list to be updated in none fallback mode. 5900 * Currently, we are using two list alternately, while one is in query, 5901 * add the freed counter to the other list based on the pool query_gen 5902 * value. After query finishes, add counter the list to the global 5903 * container counter list. The list changes while query starts. In 5904 * this case, lock will not be needed as query callback and release 5905 * function both operate with the different list. 5906 * 5907 */ 5908 if (!priv->sh->cmng.counter_fallback) { 5909 rte_spinlock_lock(&pool->csl); 5910 TAILQ_INSERT_TAIL(&pool->counters[pool->query_gen], cnt, next); 5911 rte_spinlock_unlock(&pool->csl); 5912 } else { 5913 cnt->dcs_when_free = cnt->dcs_when_active; 5914 cnt_type = pool->is_aged ? MLX5_COUNTER_TYPE_AGE : 5915 MLX5_COUNTER_TYPE_ORIGIN; 5916 rte_spinlock_lock(&priv->sh->cmng.csl[cnt_type]); 5917 TAILQ_INSERT_TAIL(&priv->sh->cmng.counters[cnt_type], 5918 cnt, next); 5919 rte_spinlock_unlock(&priv->sh->cmng.csl[cnt_type]); 5920 } 5921 } 5922 5923 /** 5924 * Verify the @p attributes will be correctly understood by the NIC and store 5925 * them in the @p flow if everything is correct. 5926 * 5927 * @param[in] dev 5928 * Pointer to dev struct. 5929 * @param[in] attributes 5930 * Pointer to flow attributes 5931 * @param[in] external 5932 * This flow rule is created by request external to PMD. 5933 * @param[out] error 5934 * Pointer to error structure. 5935 * 5936 * @return 5937 * - 0 on success and non root table. 5938 * - 1 on success and root table. 5939 * - a negative errno value otherwise and rte_errno is set. 5940 */ 5941 static int 5942 flow_dv_validate_attributes(struct rte_eth_dev *dev, 5943 const struct mlx5_flow_tunnel *tunnel, 5944 const struct rte_flow_attr *attributes, 5945 const struct flow_grp_info *grp_info, 5946 struct rte_flow_error *error) 5947 { 5948 struct mlx5_priv *priv = dev->data->dev_private; 5949 uint32_t lowest_priority = mlx5_get_lowest_priority(dev, attributes); 5950 int ret = 0; 5951 5952 #ifndef HAVE_MLX5DV_DR 5953 RTE_SET_USED(tunnel); 5954 RTE_SET_USED(grp_info); 5955 if (attributes->group) 5956 return rte_flow_error_set(error, ENOTSUP, 5957 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 5958 NULL, 5959 "groups are not supported"); 5960 #else 5961 uint32_t table = 0; 5962 5963 ret = mlx5_flow_group_to_table(dev, tunnel, attributes->group, &table, 5964 grp_info, error); 5965 if (ret) 5966 return ret; 5967 if (!table) 5968 ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL; 5969 #endif 5970 if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR && 5971 attributes->priority > lowest_priority) 5972 return rte_flow_error_set(error, ENOTSUP, 5973 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 5974 NULL, 5975 "priority out of range"); 5976 if (attributes->transfer) { 5977 if (!priv->config.dv_esw_en) 5978 return rte_flow_error_set 5979 (error, ENOTSUP, 5980 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 5981 "E-Switch dr is not supported"); 5982 if (!(priv->representor || priv->master)) 5983 return rte_flow_error_set 5984 (error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 5985 NULL, "E-Switch configuration can only be" 5986 " done by a master or a representor device"); 5987 if (attributes->egress) 5988 return rte_flow_error_set 5989 (error, ENOTSUP, 5990 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attributes, 5991 "egress is not supported"); 5992 } 5993 if (!(attributes->egress ^ attributes->ingress)) 5994 return rte_flow_error_set(error, ENOTSUP, 5995 RTE_FLOW_ERROR_TYPE_ATTR, NULL, 5996 "must specify exactly one of " 5997 "ingress or egress"); 5998 return ret; 5999 } 6000 6001 /** 6002 * Internal validation function. For validating both actions and items. 6003 * 6004 * @param[in] dev 6005 * Pointer to the rte_eth_dev structure. 6006 * @param[in] attr 6007 * Pointer to the flow attributes. 6008 * @param[in] items 6009 * Pointer to the list of items. 6010 * @param[in] actions 6011 * Pointer to the list of actions. 6012 * @param[in] external 6013 * This flow rule is created by request external to PMD. 6014 * @param[in] hairpin 6015 * Number of hairpin TX actions, 0 means classic flow. 6016 * @param[out] error 6017 * Pointer to the error structure. 6018 * 6019 * @return 6020 * 0 on success, a negative errno value otherwise and rte_errno is set. 6021 */ 6022 static int 6023 flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, 6024 const struct rte_flow_item items[], 6025 const struct rte_flow_action actions[], 6026 bool external, int hairpin, struct rte_flow_error *error) 6027 { 6028 int ret; 6029 uint64_t action_flags = 0; 6030 uint64_t item_flags = 0; 6031 uint64_t last_item = 0; 6032 uint8_t next_protocol = 0xff; 6033 uint16_t ether_type = 0; 6034 int actions_n = 0; 6035 uint8_t item_ipv6_proto = 0; 6036 int fdb_mirror_limit = 0; 6037 int modify_after_mirror = 0; 6038 const struct rte_flow_item *geneve_item = NULL; 6039 const struct rte_flow_item *gre_item = NULL; 6040 const struct rte_flow_item *gtp_item = NULL; 6041 const struct rte_flow_action_raw_decap *decap; 6042 const struct rte_flow_action_raw_encap *encap; 6043 const struct rte_flow_action_rss *rss = NULL; 6044 const struct rte_flow_action_rss *sample_rss = NULL; 6045 const struct rte_flow_action_count *count = NULL; 6046 const struct rte_flow_action_count *sample_count = NULL; 6047 const struct rte_flow_item_tcp nic_tcp_mask = { 6048 .hdr = { 6049 .tcp_flags = 0xFF, 6050 .src_port = RTE_BE16(UINT16_MAX), 6051 .dst_port = RTE_BE16(UINT16_MAX), 6052 } 6053 }; 6054 const struct rte_flow_item_ipv6 nic_ipv6_mask = { 6055 .hdr = { 6056 .src_addr = 6057 "\xff\xff\xff\xff\xff\xff\xff\xff" 6058 "\xff\xff\xff\xff\xff\xff\xff\xff", 6059 .dst_addr = 6060 "\xff\xff\xff\xff\xff\xff\xff\xff" 6061 "\xff\xff\xff\xff\xff\xff\xff\xff", 6062 .vtc_flow = RTE_BE32(0xffffffff), 6063 .proto = 0xff, 6064 .hop_limits = 0xff, 6065 }, 6066 .has_frag_ext = 1, 6067 }; 6068 const struct rte_flow_item_ecpri nic_ecpri_mask = { 6069 .hdr = { 6070 .common = { 6071 .u32 = 6072 RTE_BE32(((const struct rte_ecpri_common_hdr) { 6073 .type = 0xFF, 6074 }).u32), 6075 }, 6076 .dummy[0] = 0xffffffff, 6077 }, 6078 }; 6079 struct mlx5_priv *priv = dev->data->dev_private; 6080 struct mlx5_dev_config *dev_conf = &priv->config; 6081 uint16_t queue_index = 0xFFFF; 6082 const struct rte_flow_item_vlan *vlan_m = NULL; 6083 uint32_t rw_act_num = 0; 6084 uint64_t is_root; 6085 const struct mlx5_flow_tunnel *tunnel; 6086 struct flow_grp_info grp_info = { 6087 .external = !!external, 6088 .transfer = !!attr->transfer, 6089 .fdb_def_rule = !!priv->fdb_def_rule, 6090 }; 6091 const struct rte_eth_hairpin_conf *conf; 6092 6093 if (items == NULL) 6094 return -1; 6095 if (is_flow_tunnel_match_rule(dev, attr, items, actions)) { 6096 tunnel = flow_items_to_tunnel(items); 6097 action_flags |= MLX5_FLOW_ACTION_TUNNEL_MATCH | 6098 MLX5_FLOW_ACTION_DECAP; 6099 } else if (is_flow_tunnel_steer_rule(dev, attr, items, actions)) { 6100 tunnel = flow_actions_to_tunnel(actions); 6101 action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET; 6102 } else { 6103 tunnel = NULL; 6104 } 6105 if (tunnel && priv->representor) 6106 return rte_flow_error_set(error, ENOTSUP, 6107 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 6108 "decap not supported " 6109 "for VF representor"); 6110 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate 6111 (dev, tunnel, attr, items, actions); 6112 ret = flow_dv_validate_attributes(dev, tunnel, attr, &grp_info, error); 6113 if (ret < 0) 6114 return ret; 6115 is_root = (uint64_t)ret; 6116 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 6117 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 6118 int type = items->type; 6119 6120 if (!mlx5_flow_os_item_supported(type)) 6121 return rte_flow_error_set(error, ENOTSUP, 6122 RTE_FLOW_ERROR_TYPE_ITEM, 6123 NULL, "item not supported"); 6124 switch (type) { 6125 case MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL: 6126 if (items[0].type != (typeof(items[0].type)) 6127 MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL) 6128 return rte_flow_error_set 6129 (error, EINVAL, 6130 RTE_FLOW_ERROR_TYPE_ITEM, 6131 NULL, "MLX5 private items " 6132 "must be the first"); 6133 break; 6134 case RTE_FLOW_ITEM_TYPE_VOID: 6135 break; 6136 case RTE_FLOW_ITEM_TYPE_PORT_ID: 6137 ret = flow_dv_validate_item_port_id 6138 (dev, items, attr, item_flags, error); 6139 if (ret < 0) 6140 return ret; 6141 last_item = MLX5_FLOW_ITEM_PORT_ID; 6142 break; 6143 case RTE_FLOW_ITEM_TYPE_ETH: 6144 ret = mlx5_flow_validate_item_eth(items, item_flags, 6145 true, error); 6146 if (ret < 0) 6147 return ret; 6148 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 6149 MLX5_FLOW_LAYER_OUTER_L2; 6150 if (items->mask != NULL && items->spec != NULL) { 6151 ether_type = 6152 ((const struct rte_flow_item_eth *) 6153 items->spec)->type; 6154 ether_type &= 6155 ((const struct rte_flow_item_eth *) 6156 items->mask)->type; 6157 ether_type = rte_be_to_cpu_16(ether_type); 6158 } else { 6159 ether_type = 0; 6160 } 6161 break; 6162 case RTE_FLOW_ITEM_TYPE_VLAN: 6163 ret = flow_dv_validate_item_vlan(items, item_flags, 6164 dev, error); 6165 if (ret < 0) 6166 return ret; 6167 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN : 6168 MLX5_FLOW_LAYER_OUTER_VLAN; 6169 if (items->mask != NULL && items->spec != NULL) { 6170 ether_type = 6171 ((const struct rte_flow_item_vlan *) 6172 items->spec)->inner_type; 6173 ether_type &= 6174 ((const struct rte_flow_item_vlan *) 6175 items->mask)->inner_type; 6176 ether_type = rte_be_to_cpu_16(ether_type); 6177 } else { 6178 ether_type = 0; 6179 } 6180 /* Store outer VLAN mask for of_push_vlan action. */ 6181 if (!tunnel) 6182 vlan_m = items->mask; 6183 break; 6184 case RTE_FLOW_ITEM_TYPE_IPV4: 6185 mlx5_flow_tunnel_ip_check(items, next_protocol, 6186 &item_flags, &tunnel); 6187 ret = flow_dv_validate_item_ipv4(items, item_flags, 6188 last_item, ether_type, 6189 error); 6190 if (ret < 0) 6191 return ret; 6192 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 6193 MLX5_FLOW_LAYER_OUTER_L3_IPV4; 6194 if (items->mask != NULL && 6195 ((const struct rte_flow_item_ipv4 *) 6196 items->mask)->hdr.next_proto_id) { 6197 next_protocol = 6198 ((const struct rte_flow_item_ipv4 *) 6199 (items->spec))->hdr.next_proto_id; 6200 next_protocol &= 6201 ((const struct rte_flow_item_ipv4 *) 6202 (items->mask))->hdr.next_proto_id; 6203 } else { 6204 /* Reset for inner layer. */ 6205 next_protocol = 0xff; 6206 } 6207 break; 6208 case RTE_FLOW_ITEM_TYPE_IPV6: 6209 mlx5_flow_tunnel_ip_check(items, next_protocol, 6210 &item_flags, &tunnel); 6211 ret = mlx5_flow_validate_item_ipv6(items, item_flags, 6212 last_item, 6213 ether_type, 6214 &nic_ipv6_mask, 6215 error); 6216 if (ret < 0) 6217 return ret; 6218 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 6219 MLX5_FLOW_LAYER_OUTER_L3_IPV6; 6220 if (items->mask != NULL && 6221 ((const struct rte_flow_item_ipv6 *) 6222 items->mask)->hdr.proto) { 6223 item_ipv6_proto = 6224 ((const struct rte_flow_item_ipv6 *) 6225 items->spec)->hdr.proto; 6226 next_protocol = 6227 ((const struct rte_flow_item_ipv6 *) 6228 items->spec)->hdr.proto; 6229 next_protocol &= 6230 ((const struct rte_flow_item_ipv6 *) 6231 items->mask)->hdr.proto; 6232 } else { 6233 /* Reset for inner layer. */ 6234 next_protocol = 0xff; 6235 } 6236 break; 6237 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT: 6238 ret = flow_dv_validate_item_ipv6_frag_ext(items, 6239 item_flags, 6240 error); 6241 if (ret < 0) 6242 return ret; 6243 last_item = tunnel ? 6244 MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT : 6245 MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT; 6246 if (items->mask != NULL && 6247 ((const struct rte_flow_item_ipv6_frag_ext *) 6248 items->mask)->hdr.next_header) { 6249 next_protocol = 6250 ((const struct rte_flow_item_ipv6_frag_ext *) 6251 items->spec)->hdr.next_header; 6252 next_protocol &= 6253 ((const struct rte_flow_item_ipv6_frag_ext *) 6254 items->mask)->hdr.next_header; 6255 } else { 6256 /* Reset for inner layer. */ 6257 next_protocol = 0xff; 6258 } 6259 break; 6260 case RTE_FLOW_ITEM_TYPE_TCP: 6261 ret = mlx5_flow_validate_item_tcp 6262 (items, item_flags, 6263 next_protocol, 6264 &nic_tcp_mask, 6265 error); 6266 if (ret < 0) 6267 return ret; 6268 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 6269 MLX5_FLOW_LAYER_OUTER_L4_TCP; 6270 break; 6271 case RTE_FLOW_ITEM_TYPE_UDP: 6272 ret = mlx5_flow_validate_item_udp(items, item_flags, 6273 next_protocol, 6274 error); 6275 if (ret < 0) 6276 return ret; 6277 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 6278 MLX5_FLOW_LAYER_OUTER_L4_UDP; 6279 break; 6280 case RTE_FLOW_ITEM_TYPE_GRE: 6281 ret = mlx5_flow_validate_item_gre(items, item_flags, 6282 next_protocol, error); 6283 if (ret < 0) 6284 return ret; 6285 gre_item = items; 6286 last_item = MLX5_FLOW_LAYER_GRE; 6287 break; 6288 case RTE_FLOW_ITEM_TYPE_NVGRE: 6289 ret = mlx5_flow_validate_item_nvgre(items, item_flags, 6290 next_protocol, 6291 error); 6292 if (ret < 0) 6293 return ret; 6294 last_item = MLX5_FLOW_LAYER_NVGRE; 6295 break; 6296 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 6297 ret = mlx5_flow_validate_item_gre_key 6298 (items, item_flags, gre_item, error); 6299 if (ret < 0) 6300 return ret; 6301 last_item = MLX5_FLOW_LAYER_GRE_KEY; 6302 break; 6303 case RTE_FLOW_ITEM_TYPE_VXLAN: 6304 ret = mlx5_flow_validate_item_vxlan(items, item_flags, 6305 error); 6306 if (ret < 0) 6307 return ret; 6308 last_item = MLX5_FLOW_LAYER_VXLAN; 6309 break; 6310 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 6311 ret = mlx5_flow_validate_item_vxlan_gpe(items, 6312 item_flags, dev, 6313 error); 6314 if (ret < 0) 6315 return ret; 6316 last_item = MLX5_FLOW_LAYER_VXLAN_GPE; 6317 break; 6318 case RTE_FLOW_ITEM_TYPE_GENEVE: 6319 ret = mlx5_flow_validate_item_geneve(items, 6320 item_flags, dev, 6321 error); 6322 if (ret < 0) 6323 return ret; 6324 geneve_item = items; 6325 last_item = MLX5_FLOW_LAYER_GENEVE; 6326 break; 6327 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 6328 ret = mlx5_flow_validate_item_geneve_opt(items, 6329 last_item, 6330 geneve_item, 6331 dev, 6332 error); 6333 if (ret < 0) 6334 return ret; 6335 last_item = MLX5_FLOW_LAYER_GENEVE_OPT; 6336 break; 6337 case RTE_FLOW_ITEM_TYPE_MPLS: 6338 ret = mlx5_flow_validate_item_mpls(dev, items, 6339 item_flags, 6340 last_item, error); 6341 if (ret < 0) 6342 return ret; 6343 last_item = MLX5_FLOW_LAYER_MPLS; 6344 break; 6345 6346 case RTE_FLOW_ITEM_TYPE_MARK: 6347 ret = flow_dv_validate_item_mark(dev, items, attr, 6348 error); 6349 if (ret < 0) 6350 return ret; 6351 last_item = MLX5_FLOW_ITEM_MARK; 6352 break; 6353 case RTE_FLOW_ITEM_TYPE_META: 6354 ret = flow_dv_validate_item_meta(dev, items, attr, 6355 error); 6356 if (ret < 0) 6357 return ret; 6358 last_item = MLX5_FLOW_ITEM_METADATA; 6359 break; 6360 case RTE_FLOW_ITEM_TYPE_ICMP: 6361 ret = mlx5_flow_validate_item_icmp(items, item_flags, 6362 next_protocol, 6363 error); 6364 if (ret < 0) 6365 return ret; 6366 last_item = MLX5_FLOW_LAYER_ICMP; 6367 break; 6368 case RTE_FLOW_ITEM_TYPE_ICMP6: 6369 ret = mlx5_flow_validate_item_icmp6(items, item_flags, 6370 next_protocol, 6371 error); 6372 if (ret < 0) 6373 return ret; 6374 item_ipv6_proto = IPPROTO_ICMPV6; 6375 last_item = MLX5_FLOW_LAYER_ICMP6; 6376 break; 6377 case RTE_FLOW_ITEM_TYPE_TAG: 6378 ret = flow_dv_validate_item_tag(dev, items, 6379 attr, error); 6380 if (ret < 0) 6381 return ret; 6382 last_item = MLX5_FLOW_ITEM_TAG; 6383 break; 6384 case MLX5_RTE_FLOW_ITEM_TYPE_TAG: 6385 case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE: 6386 break; 6387 case RTE_FLOW_ITEM_TYPE_GTP: 6388 ret = flow_dv_validate_item_gtp(dev, items, item_flags, 6389 error); 6390 if (ret < 0) 6391 return ret; 6392 gtp_item = items; 6393 last_item = MLX5_FLOW_LAYER_GTP; 6394 break; 6395 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 6396 ret = flow_dv_validate_item_gtp_psc(items, last_item, 6397 gtp_item, attr, 6398 error); 6399 if (ret < 0) 6400 return ret; 6401 last_item = MLX5_FLOW_LAYER_GTP_PSC; 6402 break; 6403 case RTE_FLOW_ITEM_TYPE_ECPRI: 6404 /* Capacity will be checked in the translate stage. */ 6405 ret = mlx5_flow_validate_item_ecpri(items, item_flags, 6406 last_item, 6407 ether_type, 6408 &nic_ecpri_mask, 6409 error); 6410 if (ret < 0) 6411 return ret; 6412 last_item = MLX5_FLOW_LAYER_ECPRI; 6413 break; 6414 default: 6415 return rte_flow_error_set(error, ENOTSUP, 6416 RTE_FLOW_ERROR_TYPE_ITEM, 6417 NULL, "item not supported"); 6418 } 6419 item_flags |= last_item; 6420 } 6421 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 6422 int type = actions->type; 6423 6424 if (!mlx5_flow_os_action_supported(type)) 6425 return rte_flow_error_set(error, ENOTSUP, 6426 RTE_FLOW_ERROR_TYPE_ACTION, 6427 actions, 6428 "action not supported"); 6429 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS) 6430 return rte_flow_error_set(error, ENOTSUP, 6431 RTE_FLOW_ERROR_TYPE_ACTION, 6432 actions, "too many actions"); 6433 switch (type) { 6434 case RTE_FLOW_ACTION_TYPE_VOID: 6435 break; 6436 case RTE_FLOW_ACTION_TYPE_PORT_ID: 6437 ret = flow_dv_validate_action_port_id(dev, 6438 action_flags, 6439 actions, 6440 attr, 6441 error); 6442 if (ret) 6443 return ret; 6444 action_flags |= MLX5_FLOW_ACTION_PORT_ID; 6445 ++actions_n; 6446 break; 6447 case RTE_FLOW_ACTION_TYPE_FLAG: 6448 ret = flow_dv_validate_action_flag(dev, action_flags, 6449 attr, error); 6450 if (ret < 0) 6451 return ret; 6452 if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 6453 /* Count all modify-header actions as one. */ 6454 if (!(action_flags & 6455 MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6456 ++actions_n; 6457 action_flags |= MLX5_FLOW_ACTION_FLAG | 6458 MLX5_FLOW_ACTION_MARK_EXT; 6459 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6460 modify_after_mirror = 1; 6461 6462 } else { 6463 action_flags |= MLX5_FLOW_ACTION_FLAG; 6464 ++actions_n; 6465 } 6466 rw_act_num += MLX5_ACT_NUM_SET_MARK; 6467 break; 6468 case RTE_FLOW_ACTION_TYPE_MARK: 6469 ret = flow_dv_validate_action_mark(dev, actions, 6470 action_flags, 6471 attr, error); 6472 if (ret < 0) 6473 return ret; 6474 if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 6475 /* Count all modify-header actions as one. */ 6476 if (!(action_flags & 6477 MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6478 ++actions_n; 6479 action_flags |= MLX5_FLOW_ACTION_MARK | 6480 MLX5_FLOW_ACTION_MARK_EXT; 6481 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6482 modify_after_mirror = 1; 6483 } else { 6484 action_flags |= MLX5_FLOW_ACTION_MARK; 6485 ++actions_n; 6486 } 6487 rw_act_num += MLX5_ACT_NUM_SET_MARK; 6488 break; 6489 case RTE_FLOW_ACTION_TYPE_SET_META: 6490 ret = flow_dv_validate_action_set_meta(dev, actions, 6491 action_flags, 6492 attr, error); 6493 if (ret < 0) 6494 return ret; 6495 /* Count all modify-header actions as one action. */ 6496 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6497 ++actions_n; 6498 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6499 modify_after_mirror = 1; 6500 action_flags |= MLX5_FLOW_ACTION_SET_META; 6501 rw_act_num += MLX5_ACT_NUM_SET_META; 6502 break; 6503 case RTE_FLOW_ACTION_TYPE_SET_TAG: 6504 ret = flow_dv_validate_action_set_tag(dev, actions, 6505 action_flags, 6506 attr, error); 6507 if (ret < 0) 6508 return ret; 6509 /* Count all modify-header actions as one action. */ 6510 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6511 ++actions_n; 6512 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6513 modify_after_mirror = 1; 6514 action_flags |= MLX5_FLOW_ACTION_SET_TAG; 6515 rw_act_num += MLX5_ACT_NUM_SET_TAG; 6516 break; 6517 case RTE_FLOW_ACTION_TYPE_DROP: 6518 ret = mlx5_flow_validate_action_drop(action_flags, 6519 attr, error); 6520 if (ret < 0) 6521 return ret; 6522 action_flags |= MLX5_FLOW_ACTION_DROP; 6523 ++actions_n; 6524 break; 6525 case RTE_FLOW_ACTION_TYPE_QUEUE: 6526 ret = mlx5_flow_validate_action_queue(actions, 6527 action_flags, dev, 6528 attr, error); 6529 if (ret < 0) 6530 return ret; 6531 queue_index = ((const struct rte_flow_action_queue *) 6532 (actions->conf))->index; 6533 action_flags |= MLX5_FLOW_ACTION_QUEUE; 6534 ++actions_n; 6535 break; 6536 case RTE_FLOW_ACTION_TYPE_RSS: 6537 rss = actions->conf; 6538 ret = mlx5_flow_validate_action_rss(actions, 6539 action_flags, dev, 6540 attr, item_flags, 6541 error); 6542 if (ret < 0) 6543 return ret; 6544 if (rss && sample_rss && 6545 (sample_rss->level != rss->level || 6546 sample_rss->types != rss->types)) 6547 return rte_flow_error_set(error, ENOTSUP, 6548 RTE_FLOW_ERROR_TYPE_ACTION, 6549 NULL, 6550 "Can't use the different RSS types " 6551 "or level in the same flow"); 6552 if (rss != NULL && rss->queue_num) 6553 queue_index = rss->queue[0]; 6554 action_flags |= MLX5_FLOW_ACTION_RSS; 6555 ++actions_n; 6556 break; 6557 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS: 6558 ret = 6559 mlx5_flow_validate_action_default_miss(action_flags, 6560 attr, error); 6561 if (ret < 0) 6562 return ret; 6563 action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS; 6564 ++actions_n; 6565 break; 6566 case RTE_FLOW_ACTION_TYPE_COUNT: 6567 ret = flow_dv_validate_action_count(dev, actions, 6568 action_flags, 6569 error); 6570 if (ret < 0) 6571 return ret; 6572 count = actions->conf; 6573 action_flags |= MLX5_FLOW_ACTION_COUNT; 6574 ++actions_n; 6575 break; 6576 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 6577 if (flow_dv_validate_action_pop_vlan(dev, 6578 action_flags, 6579 actions, 6580 item_flags, attr, 6581 error)) 6582 return -rte_errno; 6583 action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN; 6584 ++actions_n; 6585 break; 6586 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 6587 ret = flow_dv_validate_action_push_vlan(dev, 6588 action_flags, 6589 vlan_m, 6590 actions, attr, 6591 error); 6592 if (ret < 0) 6593 return ret; 6594 action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN; 6595 ++actions_n; 6596 break; 6597 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 6598 ret = flow_dv_validate_action_set_vlan_pcp 6599 (action_flags, actions, error); 6600 if (ret < 0) 6601 return ret; 6602 /* Count PCP with push_vlan command. */ 6603 action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP; 6604 break; 6605 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 6606 ret = flow_dv_validate_action_set_vlan_vid 6607 (item_flags, action_flags, 6608 actions, error); 6609 if (ret < 0) 6610 return ret; 6611 /* Count VID with push_vlan command. */ 6612 action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID; 6613 rw_act_num += MLX5_ACT_NUM_MDF_VID; 6614 break; 6615 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 6616 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 6617 ret = flow_dv_validate_action_l2_encap(dev, 6618 action_flags, 6619 actions, attr, 6620 error); 6621 if (ret < 0) 6622 return ret; 6623 action_flags |= MLX5_FLOW_ACTION_ENCAP; 6624 ++actions_n; 6625 break; 6626 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 6627 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 6628 ret = flow_dv_validate_action_decap(dev, action_flags, 6629 actions, item_flags, 6630 attr, error); 6631 if (ret < 0) 6632 return ret; 6633 action_flags |= MLX5_FLOW_ACTION_DECAP; 6634 ++actions_n; 6635 break; 6636 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 6637 ret = flow_dv_validate_action_raw_encap_decap 6638 (dev, NULL, actions->conf, attr, &action_flags, 6639 &actions_n, actions, item_flags, error); 6640 if (ret < 0) 6641 return ret; 6642 break; 6643 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 6644 decap = actions->conf; 6645 while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID) 6646 ; 6647 if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { 6648 encap = NULL; 6649 actions--; 6650 } else { 6651 encap = actions->conf; 6652 } 6653 ret = flow_dv_validate_action_raw_encap_decap 6654 (dev, 6655 decap ? decap : &empty_decap, encap, 6656 attr, &action_flags, &actions_n, 6657 actions, item_flags, error); 6658 if (ret < 0) 6659 return ret; 6660 break; 6661 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: 6662 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: 6663 ret = flow_dv_validate_action_modify_mac(action_flags, 6664 actions, 6665 item_flags, 6666 error); 6667 if (ret < 0) 6668 return ret; 6669 /* Count all modify-header actions as one action. */ 6670 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6671 ++actions_n; 6672 action_flags |= actions->type == 6673 RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ? 6674 MLX5_FLOW_ACTION_SET_MAC_SRC : 6675 MLX5_FLOW_ACTION_SET_MAC_DST; 6676 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6677 modify_after_mirror = 1; 6678 /* 6679 * Even if the source and destination MAC addresses have 6680 * overlap in the header with 4B alignment, the convert 6681 * function will handle them separately and 4 SW actions 6682 * will be created. And 2 actions will be added each 6683 * time no matter how many bytes of address will be set. 6684 */ 6685 rw_act_num += MLX5_ACT_NUM_MDF_MAC; 6686 break; 6687 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: 6688 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: 6689 ret = flow_dv_validate_action_modify_ipv4(action_flags, 6690 actions, 6691 item_flags, 6692 error); 6693 if (ret < 0) 6694 return ret; 6695 /* Count all modify-header actions as one action. */ 6696 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6697 ++actions_n; 6698 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6699 modify_after_mirror = 1; 6700 action_flags |= actions->type == 6701 RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ? 6702 MLX5_FLOW_ACTION_SET_IPV4_SRC : 6703 MLX5_FLOW_ACTION_SET_IPV4_DST; 6704 rw_act_num += MLX5_ACT_NUM_MDF_IPV4; 6705 break; 6706 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: 6707 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: 6708 ret = flow_dv_validate_action_modify_ipv6(action_flags, 6709 actions, 6710 item_flags, 6711 error); 6712 if (ret < 0) 6713 return ret; 6714 if (item_ipv6_proto == IPPROTO_ICMPV6) 6715 return rte_flow_error_set(error, ENOTSUP, 6716 RTE_FLOW_ERROR_TYPE_ACTION, 6717 actions, 6718 "Can't change header " 6719 "with ICMPv6 proto"); 6720 /* Count all modify-header actions as one action. */ 6721 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6722 ++actions_n; 6723 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6724 modify_after_mirror = 1; 6725 action_flags |= actions->type == 6726 RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ? 6727 MLX5_FLOW_ACTION_SET_IPV6_SRC : 6728 MLX5_FLOW_ACTION_SET_IPV6_DST; 6729 rw_act_num += MLX5_ACT_NUM_MDF_IPV6; 6730 break; 6731 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: 6732 case RTE_FLOW_ACTION_TYPE_SET_TP_DST: 6733 ret = flow_dv_validate_action_modify_tp(action_flags, 6734 actions, 6735 item_flags, 6736 error); 6737 if (ret < 0) 6738 return ret; 6739 /* Count all modify-header actions as one action. */ 6740 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6741 ++actions_n; 6742 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6743 modify_after_mirror = 1; 6744 action_flags |= actions->type == 6745 RTE_FLOW_ACTION_TYPE_SET_TP_SRC ? 6746 MLX5_FLOW_ACTION_SET_TP_SRC : 6747 MLX5_FLOW_ACTION_SET_TP_DST; 6748 rw_act_num += MLX5_ACT_NUM_MDF_PORT; 6749 break; 6750 case RTE_FLOW_ACTION_TYPE_DEC_TTL: 6751 case RTE_FLOW_ACTION_TYPE_SET_TTL: 6752 ret = flow_dv_validate_action_modify_ttl(action_flags, 6753 actions, 6754 item_flags, 6755 error); 6756 if (ret < 0) 6757 return ret; 6758 /* Count all modify-header actions as one action. */ 6759 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6760 ++actions_n; 6761 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6762 modify_after_mirror = 1; 6763 action_flags |= actions->type == 6764 RTE_FLOW_ACTION_TYPE_SET_TTL ? 6765 MLX5_FLOW_ACTION_SET_TTL : 6766 MLX5_FLOW_ACTION_DEC_TTL; 6767 rw_act_num += MLX5_ACT_NUM_MDF_TTL; 6768 break; 6769 case RTE_FLOW_ACTION_TYPE_JUMP: 6770 ret = flow_dv_validate_action_jump(dev, tunnel, actions, 6771 action_flags, 6772 attr, external, 6773 error); 6774 if (ret) 6775 return ret; 6776 if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && 6777 fdb_mirror_limit) 6778 return rte_flow_error_set(error, EINVAL, 6779 RTE_FLOW_ERROR_TYPE_ACTION, 6780 NULL, 6781 "sample and jump action combination is not supported"); 6782 ++actions_n; 6783 action_flags |= MLX5_FLOW_ACTION_JUMP; 6784 break; 6785 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ: 6786 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ: 6787 ret = flow_dv_validate_action_modify_tcp_seq 6788 (action_flags, 6789 actions, 6790 item_flags, 6791 error); 6792 if (ret < 0) 6793 return ret; 6794 /* Count all modify-header actions as one action. */ 6795 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6796 ++actions_n; 6797 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6798 modify_after_mirror = 1; 6799 action_flags |= actions->type == 6800 RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ? 6801 MLX5_FLOW_ACTION_INC_TCP_SEQ : 6802 MLX5_FLOW_ACTION_DEC_TCP_SEQ; 6803 rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ; 6804 break; 6805 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK: 6806 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK: 6807 ret = flow_dv_validate_action_modify_tcp_ack 6808 (action_flags, 6809 actions, 6810 item_flags, 6811 error); 6812 if (ret < 0) 6813 return ret; 6814 /* Count all modify-header actions as one action. */ 6815 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6816 ++actions_n; 6817 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6818 modify_after_mirror = 1; 6819 action_flags |= actions->type == 6820 RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ? 6821 MLX5_FLOW_ACTION_INC_TCP_ACK : 6822 MLX5_FLOW_ACTION_DEC_TCP_ACK; 6823 rw_act_num += MLX5_ACT_NUM_MDF_TCPACK; 6824 break; 6825 case MLX5_RTE_FLOW_ACTION_TYPE_MARK: 6826 break; 6827 case MLX5_RTE_FLOW_ACTION_TYPE_TAG: 6828 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG: 6829 rw_act_num += MLX5_ACT_NUM_SET_TAG; 6830 break; 6831 case RTE_FLOW_ACTION_TYPE_METER: 6832 ret = mlx5_flow_validate_action_meter(dev, 6833 action_flags, 6834 actions, attr, 6835 error); 6836 if (ret < 0) 6837 return ret; 6838 action_flags |= MLX5_FLOW_ACTION_METER; 6839 ++actions_n; 6840 /* Meter action will add one more TAG action. */ 6841 rw_act_num += MLX5_ACT_NUM_SET_TAG; 6842 break; 6843 case MLX5_RTE_FLOW_ACTION_TYPE_AGE: 6844 if (!attr->transfer && !attr->group) 6845 return rte_flow_error_set(error, ENOTSUP, 6846 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 6847 NULL, 6848 "Shared ASO age action is not supported for group 0"); 6849 action_flags |= MLX5_FLOW_ACTION_AGE; 6850 ++actions_n; 6851 break; 6852 case RTE_FLOW_ACTION_TYPE_AGE: 6853 ret = flow_dv_validate_action_age(action_flags, 6854 actions, dev, 6855 error); 6856 if (ret < 0) 6857 return ret; 6858 /* 6859 * Validate the regular AGE action (using counter) 6860 * mutual exclusion with share counter actions. 6861 */ 6862 if (!priv->sh->flow_hit_aso_en) { 6863 if (count && count->shared) 6864 return rte_flow_error_set 6865 (error, EINVAL, 6866 RTE_FLOW_ERROR_TYPE_ACTION, 6867 NULL, 6868 "old age and shared count combination is not supported"); 6869 if (sample_count) 6870 return rte_flow_error_set 6871 (error, EINVAL, 6872 RTE_FLOW_ERROR_TYPE_ACTION, 6873 NULL, 6874 "old age action and count must be in the same sub flow"); 6875 } 6876 action_flags |= MLX5_FLOW_ACTION_AGE; 6877 ++actions_n; 6878 break; 6879 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: 6880 ret = flow_dv_validate_action_modify_ipv4_dscp 6881 (action_flags, 6882 actions, 6883 item_flags, 6884 error); 6885 if (ret < 0) 6886 return ret; 6887 /* Count all modify-header actions as one action. */ 6888 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6889 ++actions_n; 6890 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6891 modify_after_mirror = 1; 6892 action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP; 6893 rw_act_num += MLX5_ACT_NUM_SET_DSCP; 6894 break; 6895 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: 6896 ret = flow_dv_validate_action_modify_ipv6_dscp 6897 (action_flags, 6898 actions, 6899 item_flags, 6900 error); 6901 if (ret < 0) 6902 return ret; 6903 /* Count all modify-header actions as one action. */ 6904 if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) 6905 ++actions_n; 6906 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 6907 modify_after_mirror = 1; 6908 action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP; 6909 rw_act_num += MLX5_ACT_NUM_SET_DSCP; 6910 break; 6911 case RTE_FLOW_ACTION_TYPE_SAMPLE: 6912 ret = flow_dv_validate_action_sample(&action_flags, 6913 actions, dev, 6914 attr, item_flags, 6915 rss, &sample_rss, 6916 &sample_count, 6917 &fdb_mirror_limit, 6918 error); 6919 if (ret < 0) 6920 return ret; 6921 action_flags |= MLX5_FLOW_ACTION_SAMPLE; 6922 ++actions_n; 6923 break; 6924 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET: 6925 if (actions[0].type != (typeof(actions[0].type)) 6926 MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET) 6927 return rte_flow_error_set 6928 (error, EINVAL, 6929 RTE_FLOW_ERROR_TYPE_ACTION, 6930 NULL, "MLX5 private action " 6931 "must be the first"); 6932 6933 action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET; 6934 break; 6935 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD: 6936 if (!attr->transfer && !attr->group) 6937 return rte_flow_error_set(error, ENOTSUP, 6938 RTE_FLOW_ERROR_TYPE_ACTION, 6939 NULL, "modify field action " 6940 "is not supported for group 0"); 6941 ret = flow_dv_validate_action_modify_field(action_flags, 6942 actions, 6943 error); 6944 if (ret < 0) 6945 return ret; 6946 /* Count all modify-header actions as one action. */ 6947 if (!(action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD)) 6948 ++actions_n; 6949 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD; 6950 rw_act_num += ret; 6951 break; 6952 default: 6953 return rte_flow_error_set(error, ENOTSUP, 6954 RTE_FLOW_ERROR_TYPE_ACTION, 6955 actions, 6956 "action not supported"); 6957 } 6958 } 6959 /* 6960 * Validate actions in flow rules 6961 * - Explicit decap action is prohibited by the tunnel offload API. 6962 * - Drop action in tunnel steer rule is prohibited by the API. 6963 * - Application cannot use MARK action because it's value can mask 6964 * tunnel default miss nitification. 6965 * - JUMP in tunnel match rule has no support in current PMD 6966 * implementation. 6967 * - TAG & META are reserved for future uses. 6968 */ 6969 if (action_flags & MLX5_FLOW_ACTION_TUNNEL_SET) { 6970 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_DECAP | 6971 MLX5_FLOW_ACTION_MARK | 6972 MLX5_FLOW_ACTION_SET_TAG | 6973 MLX5_FLOW_ACTION_SET_META | 6974 MLX5_FLOW_ACTION_DROP; 6975 6976 if (action_flags & bad_actions_mask) 6977 return rte_flow_error_set 6978 (error, EINVAL, 6979 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 6980 "Invalid RTE action in tunnel " 6981 "set decap rule"); 6982 if (!(action_flags & MLX5_FLOW_ACTION_JUMP)) 6983 return rte_flow_error_set 6984 (error, EINVAL, 6985 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 6986 "tunnel set decap rule must terminate " 6987 "with JUMP"); 6988 if (!attr->ingress) 6989 return rte_flow_error_set 6990 (error, EINVAL, 6991 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 6992 "tunnel flows for ingress traffic only"); 6993 } 6994 if (action_flags & MLX5_FLOW_ACTION_TUNNEL_MATCH) { 6995 uint64_t bad_actions_mask = MLX5_FLOW_ACTION_JUMP | 6996 MLX5_FLOW_ACTION_MARK | 6997 MLX5_FLOW_ACTION_SET_TAG | 6998 MLX5_FLOW_ACTION_SET_META; 6999 7000 if (action_flags & bad_actions_mask) 7001 return rte_flow_error_set 7002 (error, EINVAL, 7003 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 7004 "Invalid RTE action in tunnel " 7005 "set match rule"); 7006 } 7007 /* 7008 * Validate the drop action mutual exclusion with other actions. 7009 * Drop action is mutually-exclusive with any other action, except for 7010 * Count action. 7011 * Drop action compatibility with tunnel offload was already validated. 7012 */ 7013 if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_MATCH | 7014 MLX5_FLOW_ACTION_TUNNEL_MATCH)); 7015 else if ((action_flags & MLX5_FLOW_ACTION_DROP) && 7016 (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT))) 7017 return rte_flow_error_set(error, EINVAL, 7018 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 7019 "Drop action is mutually-exclusive " 7020 "with any other action, except for " 7021 "Count action"); 7022 /* Eswitch has few restrictions on using items and actions */ 7023 if (attr->transfer) { 7024 if (!mlx5_flow_ext_mreg_supported(dev) && 7025 action_flags & MLX5_FLOW_ACTION_FLAG) 7026 return rte_flow_error_set(error, ENOTSUP, 7027 RTE_FLOW_ERROR_TYPE_ACTION, 7028 NULL, 7029 "unsupported action FLAG"); 7030 if (!mlx5_flow_ext_mreg_supported(dev) && 7031 action_flags & MLX5_FLOW_ACTION_MARK) 7032 return rte_flow_error_set(error, ENOTSUP, 7033 RTE_FLOW_ERROR_TYPE_ACTION, 7034 NULL, 7035 "unsupported action MARK"); 7036 if (action_flags & MLX5_FLOW_ACTION_QUEUE) 7037 return rte_flow_error_set(error, ENOTSUP, 7038 RTE_FLOW_ERROR_TYPE_ACTION, 7039 NULL, 7040 "unsupported action QUEUE"); 7041 if (action_flags & MLX5_FLOW_ACTION_RSS) 7042 return rte_flow_error_set(error, ENOTSUP, 7043 RTE_FLOW_ERROR_TYPE_ACTION, 7044 NULL, 7045 "unsupported action RSS"); 7046 if (!(action_flags & MLX5_FLOW_FATE_ESWITCH_ACTIONS)) 7047 return rte_flow_error_set(error, EINVAL, 7048 RTE_FLOW_ERROR_TYPE_ACTION, 7049 actions, 7050 "no fate action is found"); 7051 } else { 7052 if (!(action_flags & MLX5_FLOW_FATE_ACTIONS) && attr->ingress) 7053 return rte_flow_error_set(error, EINVAL, 7054 RTE_FLOW_ERROR_TYPE_ACTION, 7055 actions, 7056 "no fate action is found"); 7057 } 7058 /* 7059 * Continue validation for Xcap and VLAN actions. 7060 * If hairpin is working in explicit TX rule mode, there is no actions 7061 * splitting and the validation of hairpin ingress flow should be the 7062 * same as other standard flows. 7063 */ 7064 if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS | 7065 MLX5_FLOW_VLAN_ACTIONS)) && 7066 (queue_index == 0xFFFF || 7067 mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN || 7068 ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL && 7069 conf->tx_explicit != 0))) { 7070 if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) == 7071 MLX5_FLOW_XCAP_ACTIONS) 7072 return rte_flow_error_set(error, ENOTSUP, 7073 RTE_FLOW_ERROR_TYPE_ACTION, 7074 NULL, "encap and decap " 7075 "combination aren't supported"); 7076 if (!attr->transfer && attr->ingress) { 7077 if (action_flags & MLX5_FLOW_ACTION_ENCAP) 7078 return rte_flow_error_set 7079 (error, ENOTSUP, 7080 RTE_FLOW_ERROR_TYPE_ACTION, 7081 NULL, "encap is not supported" 7082 " for ingress traffic"); 7083 else if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) 7084 return rte_flow_error_set 7085 (error, ENOTSUP, 7086 RTE_FLOW_ERROR_TYPE_ACTION, 7087 NULL, "push VLAN action not " 7088 "supported for ingress"); 7089 else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) == 7090 MLX5_FLOW_VLAN_ACTIONS) 7091 return rte_flow_error_set 7092 (error, ENOTSUP, 7093 RTE_FLOW_ERROR_TYPE_ACTION, 7094 NULL, "no support for " 7095 "multiple VLAN actions"); 7096 } 7097 } 7098 /* 7099 * Hairpin flow will add one more TAG action in TX implicit mode. 7100 * In TX explicit mode, there will be no hairpin flow ID. 7101 */ 7102 if (hairpin > 0) 7103 rw_act_num += MLX5_ACT_NUM_SET_TAG; 7104 /* extra metadata enabled: one more TAG action will be add. */ 7105 if (dev_conf->dv_flow_en && 7106 dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 7107 mlx5_flow_ext_mreg_supported(dev)) 7108 rw_act_num += MLX5_ACT_NUM_SET_TAG; 7109 if (rw_act_num > 7110 flow_dv_modify_hdr_action_max(dev, is_root)) { 7111 return rte_flow_error_set(error, ENOTSUP, 7112 RTE_FLOW_ERROR_TYPE_ACTION, 7113 NULL, "too many header modify" 7114 " actions to support"); 7115 } 7116 /* Eswitch egress mirror and modify flow has limitation on CX5 */ 7117 if (fdb_mirror_limit && modify_after_mirror) 7118 return rte_flow_error_set(error, EINVAL, 7119 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 7120 "sample before modify action is not supported"); 7121 return 0; 7122 } 7123 7124 /** 7125 * Internal preparation function. Allocates the DV flow size, 7126 * this size is constant. 7127 * 7128 * @param[in] dev 7129 * Pointer to the rte_eth_dev structure. 7130 * @param[in] attr 7131 * Pointer to the flow attributes. 7132 * @param[in] items 7133 * Pointer to the list of items. 7134 * @param[in] actions 7135 * Pointer to the list of actions. 7136 * @param[out] error 7137 * Pointer to the error structure. 7138 * 7139 * @return 7140 * Pointer to mlx5_flow object on success, 7141 * otherwise NULL and rte_errno is set. 7142 */ 7143 static struct mlx5_flow * 7144 flow_dv_prepare(struct rte_eth_dev *dev, 7145 const struct rte_flow_attr *attr __rte_unused, 7146 const struct rte_flow_item items[] __rte_unused, 7147 const struct rte_flow_action actions[] __rte_unused, 7148 struct rte_flow_error *error) 7149 { 7150 uint32_t handle_idx = 0; 7151 struct mlx5_flow *dev_flow; 7152 struct mlx5_flow_handle *dev_handle; 7153 struct mlx5_priv *priv = dev->data->dev_private; 7154 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 7155 7156 MLX5_ASSERT(wks); 7157 /* In case of corrupting the memory. */ 7158 if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) { 7159 rte_flow_error_set(error, ENOSPC, 7160 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 7161 "not free temporary device flow"); 7162 return NULL; 7163 } 7164 dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 7165 &handle_idx); 7166 if (!dev_handle) { 7167 rte_flow_error_set(error, ENOMEM, 7168 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 7169 "not enough memory to create flow handle"); 7170 return NULL; 7171 } 7172 MLX5_ASSERT(wks->flow_idx < RTE_DIM(wks->flows)); 7173 dev_flow = &wks->flows[wks->flow_idx++]; 7174 memset(dev_flow, 0, sizeof(*dev_flow)); 7175 dev_flow->handle = dev_handle; 7176 dev_flow->handle_idx = handle_idx; 7177 /* 7178 * In some old rdma-core releases, before continuing, a check of the 7179 * length of matching parameter will be done at first. It needs to use 7180 * the length without misc4 param. If the flow has misc4 support, then 7181 * the length needs to be adjusted accordingly. Each param member is 7182 * aligned with a 64B boundary naturally. 7183 */ 7184 dev_flow->dv.value.size = MLX5_ST_SZ_BYTES(fte_match_param) - 7185 MLX5_ST_SZ_BYTES(fte_match_set_misc4); 7186 dev_flow->ingress = attr->ingress; 7187 dev_flow->dv.transfer = attr->transfer; 7188 return dev_flow; 7189 } 7190 7191 #ifdef RTE_LIBRTE_MLX5_DEBUG 7192 /** 7193 * Sanity check for match mask and value. Similar to check_valid_spec() in 7194 * kernel driver. If unmasked bit is present in value, it returns failure. 7195 * 7196 * @param match_mask 7197 * pointer to match mask buffer. 7198 * @param match_value 7199 * pointer to match value buffer. 7200 * 7201 * @return 7202 * 0 if valid, -EINVAL otherwise. 7203 */ 7204 static int 7205 flow_dv_check_valid_spec(void *match_mask, void *match_value) 7206 { 7207 uint8_t *m = match_mask; 7208 uint8_t *v = match_value; 7209 unsigned int i; 7210 7211 for (i = 0; i < MLX5_ST_SZ_BYTES(fte_match_param); ++i) { 7212 if (v[i] & ~m[i]) { 7213 DRV_LOG(ERR, 7214 "match_value differs from match_criteria" 7215 " %p[%u] != %p[%u]", 7216 match_value, i, match_mask, i); 7217 return -EINVAL; 7218 } 7219 } 7220 return 0; 7221 } 7222 #endif 7223 7224 /** 7225 * Add match of ip_version. 7226 * 7227 * @param[in] group 7228 * Flow group. 7229 * @param[in] headers_v 7230 * Values header pointer. 7231 * @param[in] headers_m 7232 * Masks header pointer. 7233 * @param[in] ip_version 7234 * The IP version to set. 7235 */ 7236 static inline void 7237 flow_dv_set_match_ip_version(uint32_t group, 7238 void *headers_v, 7239 void *headers_m, 7240 uint8_t ip_version) 7241 { 7242 if (group == 0) 7243 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 0xf); 7244 else 7245 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 7246 ip_version); 7247 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, ip_version); 7248 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, 0); 7249 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype, 0); 7250 } 7251 7252 /** 7253 * Add Ethernet item to matcher and to the value. 7254 * 7255 * @param[in, out] matcher 7256 * Flow matcher. 7257 * @param[in, out] key 7258 * Flow matcher value. 7259 * @param[in] item 7260 * Flow pattern to translate. 7261 * @param[in] inner 7262 * Item is inner pattern. 7263 */ 7264 static void 7265 flow_dv_translate_item_eth(void *matcher, void *key, 7266 const struct rte_flow_item *item, int inner, 7267 uint32_t group) 7268 { 7269 const struct rte_flow_item_eth *eth_m = item->mask; 7270 const struct rte_flow_item_eth *eth_v = item->spec; 7271 const struct rte_flow_item_eth nic_mask = { 7272 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 7273 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", 7274 .type = RTE_BE16(0xffff), 7275 .has_vlan = 0, 7276 }; 7277 void *hdrs_m; 7278 void *hdrs_v; 7279 char *l24_v; 7280 unsigned int i; 7281 7282 if (!eth_v) 7283 return; 7284 if (!eth_m) 7285 eth_m = &nic_mask; 7286 if (inner) { 7287 hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher, 7288 inner_headers); 7289 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7290 } else { 7291 hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher, 7292 outer_headers); 7293 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7294 } 7295 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m, dmac_47_16), 7296 ð_m->dst, sizeof(eth_m->dst)); 7297 /* The value must be in the range of the mask. */ 7298 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16); 7299 for (i = 0; i < sizeof(eth_m->dst); ++i) 7300 l24_v[i] = eth_m->dst.addr_bytes[i] & eth_v->dst.addr_bytes[i]; 7301 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m, smac_47_16), 7302 ð_m->src, sizeof(eth_m->src)); 7303 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16); 7304 /* The value must be in the range of the mask. */ 7305 for (i = 0; i < sizeof(eth_m->dst); ++i) 7306 l24_v[i] = eth_m->src.addr_bytes[i] & eth_v->src.addr_bytes[i]; 7307 /* 7308 * HW supports match on one Ethertype, the Ethertype following the last 7309 * VLAN tag of the packet (see PRM). 7310 * Set match on ethertype only if ETH header is not followed by VLAN. 7311 * HW is optimized for IPv4/IPv6. In such cases, avoid setting 7312 * ethertype, and use ip_version field instead. 7313 * eCPRI over Ether layer will use type value 0xAEFE. 7314 */ 7315 if (eth_m->type == 0xFFFF) { 7316 /* Set cvlan_tag mask for any single\multi\un-tagged case. */ 7317 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1); 7318 switch (eth_v->type) { 7319 case RTE_BE16(RTE_ETHER_TYPE_VLAN): 7320 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1); 7321 return; 7322 case RTE_BE16(RTE_ETHER_TYPE_QINQ): 7323 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1); 7324 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1); 7325 return; 7326 case RTE_BE16(RTE_ETHER_TYPE_IPV4): 7327 flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 4); 7328 return; 7329 case RTE_BE16(RTE_ETHER_TYPE_IPV6): 7330 flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 6); 7331 return; 7332 default: 7333 break; 7334 } 7335 } 7336 if (eth_m->has_vlan) { 7337 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1); 7338 if (eth_v->has_vlan) { 7339 /* 7340 * Here, when also has_more_vlan field in VLAN item is 7341 * not set, only single-tagged packets will be matched. 7342 */ 7343 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1); 7344 return; 7345 } 7346 } 7347 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype, 7348 rte_be_to_cpu_16(eth_m->type)); 7349 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype); 7350 *(uint16_t *)(l24_v) = eth_m->type & eth_v->type; 7351 } 7352 7353 /** 7354 * Add VLAN item to matcher and to the value. 7355 * 7356 * @param[in, out] dev_flow 7357 * Flow descriptor. 7358 * @param[in, out] matcher 7359 * Flow matcher. 7360 * @param[in, out] key 7361 * Flow matcher value. 7362 * @param[in] item 7363 * Flow pattern to translate. 7364 * @param[in] inner 7365 * Item is inner pattern. 7366 */ 7367 static void 7368 flow_dv_translate_item_vlan(struct mlx5_flow *dev_flow, 7369 void *matcher, void *key, 7370 const struct rte_flow_item *item, 7371 int inner, uint32_t group) 7372 { 7373 const struct rte_flow_item_vlan *vlan_m = item->mask; 7374 const struct rte_flow_item_vlan *vlan_v = item->spec; 7375 void *hdrs_m; 7376 void *hdrs_v; 7377 uint16_t tci_m; 7378 uint16_t tci_v; 7379 7380 if (inner) { 7381 hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher, 7382 inner_headers); 7383 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7384 } else { 7385 hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher, 7386 outer_headers); 7387 hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7388 /* 7389 * This is workaround, masks are not supported, 7390 * and pre-validated. 7391 */ 7392 if (vlan_v) 7393 dev_flow->handle->vf_vlan.tag = 7394 rte_be_to_cpu_16(vlan_v->tci) & 0x0fff; 7395 } 7396 /* 7397 * When VLAN item exists in flow, mark packet as tagged, 7398 * even if TCI is not specified. 7399 */ 7400 if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag)) { 7401 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1); 7402 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1); 7403 } 7404 if (!vlan_v) 7405 return; 7406 if (!vlan_m) 7407 vlan_m = &rte_flow_item_vlan_mask; 7408 tci_m = rte_be_to_cpu_16(vlan_m->tci); 7409 tci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci); 7410 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_vid, tci_m); 7411 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v); 7412 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_cfi, tci_m >> 12); 7413 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12); 7414 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_prio, tci_m >> 13); 7415 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13); 7416 /* 7417 * HW is optimized for IPv4/IPv6. In such cases, avoid setting 7418 * ethertype, and use ip_version field instead. 7419 */ 7420 if (vlan_m->inner_type == 0xFFFF) { 7421 switch (vlan_v->inner_type) { 7422 case RTE_BE16(RTE_ETHER_TYPE_VLAN): 7423 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1); 7424 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1); 7425 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0); 7426 return; 7427 case RTE_BE16(RTE_ETHER_TYPE_IPV4): 7428 flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 4); 7429 return; 7430 case RTE_BE16(RTE_ETHER_TYPE_IPV6): 7431 flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 6); 7432 return; 7433 default: 7434 break; 7435 } 7436 } 7437 if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) { 7438 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1); 7439 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1); 7440 /* Only one vlan_tag bit can be set. */ 7441 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0); 7442 return; 7443 } 7444 MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype, 7445 rte_be_to_cpu_16(vlan_m->inner_type)); 7446 MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype, 7447 rte_be_to_cpu_16(vlan_m->inner_type & vlan_v->inner_type)); 7448 } 7449 7450 /** 7451 * Add IPV4 item to matcher and to the value. 7452 * 7453 * @param[in, out] matcher 7454 * Flow matcher. 7455 * @param[in, out] key 7456 * Flow matcher value. 7457 * @param[in] item 7458 * Flow pattern to translate. 7459 * @param[in] inner 7460 * Item is inner pattern. 7461 * @param[in] group 7462 * The group to insert the rule. 7463 */ 7464 static void 7465 flow_dv_translate_item_ipv4(void *matcher, void *key, 7466 const struct rte_flow_item *item, 7467 int inner, uint32_t group) 7468 { 7469 const struct rte_flow_item_ipv4 *ipv4_m = item->mask; 7470 const struct rte_flow_item_ipv4 *ipv4_v = item->spec; 7471 const struct rte_flow_item_ipv4 nic_mask = { 7472 .hdr = { 7473 .src_addr = RTE_BE32(0xffffffff), 7474 .dst_addr = RTE_BE32(0xffffffff), 7475 .type_of_service = 0xff, 7476 .next_proto_id = 0xff, 7477 .time_to_live = 0xff, 7478 }, 7479 }; 7480 void *headers_m; 7481 void *headers_v; 7482 char *l24_m; 7483 char *l24_v; 7484 uint8_t tos; 7485 7486 if (inner) { 7487 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7488 inner_headers); 7489 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7490 } else { 7491 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7492 outer_headers); 7493 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7494 } 7495 flow_dv_set_match_ip_version(group, headers_v, headers_m, 4); 7496 if (!ipv4_v) 7497 return; 7498 if (!ipv4_m) 7499 ipv4_m = &nic_mask; 7500 l24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, 7501 dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 7502 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 7503 dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 7504 *(uint32_t *)l24_m = ipv4_m->hdr.dst_addr; 7505 *(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr; 7506 l24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, 7507 src_ipv4_src_ipv6.ipv4_layout.ipv4); 7508 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 7509 src_ipv4_src_ipv6.ipv4_layout.ipv4); 7510 *(uint32_t *)l24_m = ipv4_m->hdr.src_addr; 7511 *(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr; 7512 tos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service; 7513 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ecn, 7514 ipv4_m->hdr.type_of_service); 7515 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos); 7516 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_dscp, 7517 ipv4_m->hdr.type_of_service >> 2); 7518 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2); 7519 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 7520 ipv4_m->hdr.next_proto_id); 7521 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 7522 ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id); 7523 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ttl_hoplimit, 7524 ipv4_m->hdr.time_to_live); 7525 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit, 7526 ipv4_v->hdr.time_to_live & ipv4_m->hdr.time_to_live); 7527 MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 7528 !!(ipv4_m->hdr.fragment_offset)); 7529 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 7530 !!(ipv4_v->hdr.fragment_offset & ipv4_m->hdr.fragment_offset)); 7531 } 7532 7533 /** 7534 * Add IPV6 item to matcher and to the value. 7535 * 7536 * @param[in, out] matcher 7537 * Flow matcher. 7538 * @param[in, out] key 7539 * Flow matcher value. 7540 * @param[in] item 7541 * Flow pattern to translate. 7542 * @param[in] inner 7543 * Item is inner pattern. 7544 * @param[in] group 7545 * The group to insert the rule. 7546 */ 7547 static void 7548 flow_dv_translate_item_ipv6(void *matcher, void *key, 7549 const struct rte_flow_item *item, 7550 int inner, uint32_t group) 7551 { 7552 const struct rte_flow_item_ipv6 *ipv6_m = item->mask; 7553 const struct rte_flow_item_ipv6 *ipv6_v = item->spec; 7554 const struct rte_flow_item_ipv6 nic_mask = { 7555 .hdr = { 7556 .src_addr = 7557 "\xff\xff\xff\xff\xff\xff\xff\xff" 7558 "\xff\xff\xff\xff\xff\xff\xff\xff", 7559 .dst_addr = 7560 "\xff\xff\xff\xff\xff\xff\xff\xff" 7561 "\xff\xff\xff\xff\xff\xff\xff\xff", 7562 .vtc_flow = RTE_BE32(0xffffffff), 7563 .proto = 0xff, 7564 .hop_limits = 0xff, 7565 }, 7566 }; 7567 void *headers_m; 7568 void *headers_v; 7569 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 7570 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 7571 char *l24_m; 7572 char *l24_v; 7573 uint32_t vtc_m; 7574 uint32_t vtc_v; 7575 int i; 7576 int size; 7577 7578 if (inner) { 7579 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7580 inner_headers); 7581 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7582 } else { 7583 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7584 outer_headers); 7585 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7586 } 7587 flow_dv_set_match_ip_version(group, headers_v, headers_m, 6); 7588 if (!ipv6_v) 7589 return; 7590 if (!ipv6_m) 7591 ipv6_m = &nic_mask; 7592 size = sizeof(ipv6_m->hdr.dst_addr); 7593 l24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, 7594 dst_ipv4_dst_ipv6.ipv6_layout.ipv6); 7595 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 7596 dst_ipv4_dst_ipv6.ipv6_layout.ipv6); 7597 memcpy(l24_m, ipv6_m->hdr.dst_addr, size); 7598 for (i = 0; i < size; ++i) 7599 l24_v[i] = l24_m[i] & ipv6_v->hdr.dst_addr[i]; 7600 l24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, 7601 src_ipv4_src_ipv6.ipv6_layout.ipv6); 7602 l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, 7603 src_ipv4_src_ipv6.ipv6_layout.ipv6); 7604 memcpy(l24_m, ipv6_m->hdr.src_addr, size); 7605 for (i = 0; i < size; ++i) 7606 l24_v[i] = l24_m[i] & ipv6_v->hdr.src_addr[i]; 7607 /* TOS. */ 7608 vtc_m = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow); 7609 vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow); 7610 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ecn, vtc_m >> 20); 7611 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20); 7612 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_dscp, vtc_m >> 22); 7613 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22); 7614 /* Label. */ 7615 if (inner) { 7616 MLX5_SET(fte_match_set_misc, misc_m, inner_ipv6_flow_label, 7617 vtc_m); 7618 MLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label, 7619 vtc_v); 7620 } else { 7621 MLX5_SET(fte_match_set_misc, misc_m, outer_ipv6_flow_label, 7622 vtc_m); 7623 MLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label, 7624 vtc_v); 7625 } 7626 /* Protocol. */ 7627 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 7628 ipv6_m->hdr.proto); 7629 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 7630 ipv6_v->hdr.proto & ipv6_m->hdr.proto); 7631 /* Hop limit. */ 7632 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ttl_hoplimit, 7633 ipv6_m->hdr.hop_limits); 7634 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ttl_hoplimit, 7635 ipv6_v->hdr.hop_limits & ipv6_m->hdr.hop_limits); 7636 MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 7637 !!(ipv6_m->has_frag_ext)); 7638 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 7639 !!(ipv6_v->has_frag_ext & ipv6_m->has_frag_ext)); 7640 } 7641 7642 /** 7643 * Add IPV6 fragment extension item to matcher and to the value. 7644 * 7645 * @param[in, out] matcher 7646 * Flow matcher. 7647 * @param[in, out] key 7648 * Flow matcher value. 7649 * @param[in] item 7650 * Flow pattern to translate. 7651 * @param[in] inner 7652 * Item is inner pattern. 7653 */ 7654 static void 7655 flow_dv_translate_item_ipv6_frag_ext(void *matcher, void *key, 7656 const struct rte_flow_item *item, 7657 int inner) 7658 { 7659 const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_m = item->mask; 7660 const struct rte_flow_item_ipv6_frag_ext *ipv6_frag_ext_v = item->spec; 7661 const struct rte_flow_item_ipv6_frag_ext nic_mask = { 7662 .hdr = { 7663 .next_header = 0xff, 7664 .frag_data = RTE_BE16(0xffff), 7665 }, 7666 }; 7667 void *headers_m; 7668 void *headers_v; 7669 7670 if (inner) { 7671 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7672 inner_headers); 7673 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7674 } else { 7675 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7676 outer_headers); 7677 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7678 } 7679 /* IPv6 fragment extension item exists, so packet is IP fragment. */ 7680 MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 1); 7681 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 1); 7682 if (!ipv6_frag_ext_v) 7683 return; 7684 if (!ipv6_frag_ext_m) 7685 ipv6_frag_ext_m = &nic_mask; 7686 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 7687 ipv6_frag_ext_m->hdr.next_header); 7688 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 7689 ipv6_frag_ext_v->hdr.next_header & 7690 ipv6_frag_ext_m->hdr.next_header); 7691 } 7692 7693 /** 7694 * Add TCP item to matcher and to the value. 7695 * 7696 * @param[in, out] matcher 7697 * Flow matcher. 7698 * @param[in, out] key 7699 * Flow matcher value. 7700 * @param[in] item 7701 * Flow pattern to translate. 7702 * @param[in] inner 7703 * Item is inner pattern. 7704 */ 7705 static void 7706 flow_dv_translate_item_tcp(void *matcher, void *key, 7707 const struct rte_flow_item *item, 7708 int inner) 7709 { 7710 const struct rte_flow_item_tcp *tcp_m = item->mask; 7711 const struct rte_flow_item_tcp *tcp_v = item->spec; 7712 void *headers_m; 7713 void *headers_v; 7714 7715 if (inner) { 7716 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7717 inner_headers); 7718 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7719 } else { 7720 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7721 outer_headers); 7722 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7723 } 7724 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff); 7725 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_TCP); 7726 if (!tcp_v) 7727 return; 7728 if (!tcp_m) 7729 tcp_m = &rte_flow_item_tcp_mask; 7730 MLX5_SET(fte_match_set_lyr_2_4, headers_m, tcp_sport, 7731 rte_be_to_cpu_16(tcp_m->hdr.src_port)); 7732 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport, 7733 rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port)); 7734 MLX5_SET(fte_match_set_lyr_2_4, headers_m, tcp_dport, 7735 rte_be_to_cpu_16(tcp_m->hdr.dst_port)); 7736 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport, 7737 rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port)); 7738 MLX5_SET(fte_match_set_lyr_2_4, headers_m, tcp_flags, 7739 tcp_m->hdr.tcp_flags); 7740 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags, 7741 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags)); 7742 } 7743 7744 /** 7745 * Add UDP item to matcher and to the value. 7746 * 7747 * @param[in, out] matcher 7748 * Flow matcher. 7749 * @param[in, out] key 7750 * Flow matcher value. 7751 * @param[in] item 7752 * Flow pattern to translate. 7753 * @param[in] inner 7754 * Item is inner pattern. 7755 */ 7756 static void 7757 flow_dv_translate_item_udp(void *matcher, void *key, 7758 const struct rte_flow_item *item, 7759 int inner) 7760 { 7761 const struct rte_flow_item_udp *udp_m = item->mask; 7762 const struct rte_flow_item_udp *udp_v = item->spec; 7763 void *headers_m; 7764 void *headers_v; 7765 7766 if (inner) { 7767 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7768 inner_headers); 7769 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7770 } else { 7771 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7772 outer_headers); 7773 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7774 } 7775 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff); 7776 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP); 7777 if (!udp_v) 7778 return; 7779 if (!udp_m) 7780 udp_m = &rte_flow_item_udp_mask; 7781 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_sport, 7782 rte_be_to_cpu_16(udp_m->hdr.src_port)); 7783 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, 7784 rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port)); 7785 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 7786 rte_be_to_cpu_16(udp_m->hdr.dst_port)); 7787 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, 7788 rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port)); 7789 } 7790 7791 /** 7792 * Add GRE optional Key item to matcher and to the value. 7793 * 7794 * @param[in, out] matcher 7795 * Flow matcher. 7796 * @param[in, out] key 7797 * Flow matcher value. 7798 * @param[in] item 7799 * Flow pattern to translate. 7800 * @param[in] inner 7801 * Item is inner pattern. 7802 */ 7803 static void 7804 flow_dv_translate_item_gre_key(void *matcher, void *key, 7805 const struct rte_flow_item *item) 7806 { 7807 const rte_be32_t *key_m = item->mask; 7808 const rte_be32_t *key_v = item->spec; 7809 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 7810 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 7811 rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 7812 7813 /* GRE K bit must be on and should already be validated */ 7814 MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1); 7815 MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1); 7816 if (!key_v) 7817 return; 7818 if (!key_m) 7819 key_m = &gre_key_default_mask; 7820 MLX5_SET(fte_match_set_misc, misc_m, gre_key_h, 7821 rte_be_to_cpu_32(*key_m) >> 8); 7822 MLX5_SET(fte_match_set_misc, misc_v, gre_key_h, 7823 rte_be_to_cpu_32((*key_v) & (*key_m)) >> 8); 7824 MLX5_SET(fte_match_set_misc, misc_m, gre_key_l, 7825 rte_be_to_cpu_32(*key_m) & 0xFF); 7826 MLX5_SET(fte_match_set_misc, misc_v, gre_key_l, 7827 rte_be_to_cpu_32((*key_v) & (*key_m)) & 0xFF); 7828 } 7829 7830 /** 7831 * Add GRE item to matcher and to the value. 7832 * 7833 * @param[in, out] matcher 7834 * Flow matcher. 7835 * @param[in, out] key 7836 * Flow matcher value. 7837 * @param[in] item 7838 * Flow pattern to translate. 7839 * @param[in] inner 7840 * Item is inner pattern. 7841 */ 7842 static void 7843 flow_dv_translate_item_gre(void *matcher, void *key, 7844 const struct rte_flow_item *item, 7845 int inner) 7846 { 7847 const struct rte_flow_item_gre *gre_m = item->mask; 7848 const struct rte_flow_item_gre *gre_v = item->spec; 7849 void *headers_m; 7850 void *headers_v; 7851 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 7852 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 7853 struct { 7854 union { 7855 __extension__ 7856 struct { 7857 uint16_t version:3; 7858 uint16_t rsvd0:9; 7859 uint16_t s_present:1; 7860 uint16_t k_present:1; 7861 uint16_t rsvd_bit1:1; 7862 uint16_t c_present:1; 7863 }; 7864 uint16_t value; 7865 }; 7866 } gre_crks_rsvd0_ver_m, gre_crks_rsvd0_ver_v; 7867 7868 if (inner) { 7869 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7870 inner_headers); 7871 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7872 } else { 7873 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7874 outer_headers); 7875 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 7876 } 7877 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff); 7878 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_GRE); 7879 if (!gre_v) 7880 return; 7881 if (!gre_m) 7882 gre_m = &rte_flow_item_gre_mask; 7883 MLX5_SET(fte_match_set_misc, misc_m, gre_protocol, 7884 rte_be_to_cpu_16(gre_m->protocol)); 7885 MLX5_SET(fte_match_set_misc, misc_v, gre_protocol, 7886 rte_be_to_cpu_16(gre_v->protocol & gre_m->protocol)); 7887 gre_crks_rsvd0_ver_m.value = rte_be_to_cpu_16(gre_m->c_rsvd0_ver); 7888 gre_crks_rsvd0_ver_v.value = rte_be_to_cpu_16(gre_v->c_rsvd0_ver); 7889 MLX5_SET(fte_match_set_misc, misc_m, gre_c_present, 7890 gre_crks_rsvd0_ver_m.c_present); 7891 MLX5_SET(fte_match_set_misc, misc_v, gre_c_present, 7892 gre_crks_rsvd0_ver_v.c_present & 7893 gre_crks_rsvd0_ver_m.c_present); 7894 MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 7895 gre_crks_rsvd0_ver_m.k_present); 7896 MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 7897 gre_crks_rsvd0_ver_v.k_present & 7898 gre_crks_rsvd0_ver_m.k_present); 7899 MLX5_SET(fte_match_set_misc, misc_m, gre_s_present, 7900 gre_crks_rsvd0_ver_m.s_present); 7901 MLX5_SET(fte_match_set_misc, misc_v, gre_s_present, 7902 gre_crks_rsvd0_ver_v.s_present & 7903 gre_crks_rsvd0_ver_m.s_present); 7904 } 7905 7906 /** 7907 * Add NVGRE item to matcher and to the value. 7908 * 7909 * @param[in, out] matcher 7910 * Flow matcher. 7911 * @param[in, out] key 7912 * Flow matcher value. 7913 * @param[in] item 7914 * Flow pattern to translate. 7915 * @param[in] inner 7916 * Item is inner pattern. 7917 */ 7918 static void 7919 flow_dv_translate_item_nvgre(void *matcher, void *key, 7920 const struct rte_flow_item *item, 7921 int inner) 7922 { 7923 const struct rte_flow_item_nvgre *nvgre_m = item->mask; 7924 const struct rte_flow_item_nvgre *nvgre_v = item->spec; 7925 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 7926 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 7927 const char *tni_flow_id_m; 7928 const char *tni_flow_id_v; 7929 char *gre_key_m; 7930 char *gre_key_v; 7931 int size; 7932 int i; 7933 7934 /* For NVGRE, GRE header fields must be set with defined values. */ 7935 const struct rte_flow_item_gre gre_spec = { 7936 .c_rsvd0_ver = RTE_BE16(0x2000), 7937 .protocol = RTE_BE16(RTE_ETHER_TYPE_TEB) 7938 }; 7939 const struct rte_flow_item_gre gre_mask = { 7940 .c_rsvd0_ver = RTE_BE16(0xB000), 7941 .protocol = RTE_BE16(UINT16_MAX), 7942 }; 7943 const struct rte_flow_item gre_item = { 7944 .spec = &gre_spec, 7945 .mask = &gre_mask, 7946 .last = NULL, 7947 }; 7948 flow_dv_translate_item_gre(matcher, key, &gre_item, inner); 7949 if (!nvgre_v) 7950 return; 7951 if (!nvgre_m) 7952 nvgre_m = &rte_flow_item_nvgre_mask; 7953 tni_flow_id_m = (const char *)nvgre_m->tni; 7954 tni_flow_id_v = (const char *)nvgre_v->tni; 7955 size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id); 7956 gre_key_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, gre_key_h); 7957 gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h); 7958 memcpy(gre_key_m, tni_flow_id_m, size); 7959 for (i = 0; i < size; ++i) 7960 gre_key_v[i] = gre_key_m[i] & tni_flow_id_v[i]; 7961 } 7962 7963 /** 7964 * Add VXLAN item to matcher and to the value. 7965 * 7966 * @param[in, out] matcher 7967 * Flow matcher. 7968 * @param[in, out] key 7969 * Flow matcher value. 7970 * @param[in] item 7971 * Flow pattern to translate. 7972 * @param[in] inner 7973 * Item is inner pattern. 7974 */ 7975 static void 7976 flow_dv_translate_item_vxlan(void *matcher, void *key, 7977 const struct rte_flow_item *item, 7978 int inner) 7979 { 7980 const struct rte_flow_item_vxlan *vxlan_m = item->mask; 7981 const struct rte_flow_item_vxlan *vxlan_v = item->spec; 7982 void *headers_m; 7983 void *headers_v; 7984 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 7985 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 7986 char *vni_m; 7987 char *vni_v; 7988 uint16_t dport; 7989 int size; 7990 int i; 7991 7992 if (inner) { 7993 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7994 inner_headers); 7995 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 7996 } else { 7997 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 7998 outer_headers); 7999 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8000 } 8001 dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ? 8002 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE; 8003 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) { 8004 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF); 8005 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport); 8006 } 8007 if (!vxlan_v) 8008 return; 8009 if (!vxlan_m) 8010 vxlan_m = &rte_flow_item_vxlan_mask; 8011 size = sizeof(vxlan_m->vni); 8012 vni_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, vxlan_vni); 8013 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni); 8014 memcpy(vni_m, vxlan_m->vni, size); 8015 for (i = 0; i < size; ++i) 8016 vni_v[i] = vni_m[i] & vxlan_v->vni[i]; 8017 } 8018 8019 /** 8020 * Add VXLAN-GPE item to matcher and to the value. 8021 * 8022 * @param[in, out] matcher 8023 * Flow matcher. 8024 * @param[in, out] key 8025 * Flow matcher value. 8026 * @param[in] item 8027 * Flow pattern to translate. 8028 * @param[in] inner 8029 * Item is inner pattern. 8030 */ 8031 8032 static void 8033 flow_dv_translate_item_vxlan_gpe(void *matcher, void *key, 8034 const struct rte_flow_item *item, int inner) 8035 { 8036 const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask; 8037 const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec; 8038 void *headers_m; 8039 void *headers_v; 8040 void *misc_m = 8041 MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_3); 8042 void *misc_v = 8043 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8044 char *vni_m; 8045 char *vni_v; 8046 uint16_t dport; 8047 int size; 8048 int i; 8049 uint8_t flags_m = 0xff; 8050 uint8_t flags_v = 0xc; 8051 8052 if (inner) { 8053 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8054 inner_headers); 8055 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 8056 } else { 8057 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8058 outer_headers); 8059 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8060 } 8061 dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ? 8062 MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE; 8063 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) { 8064 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF); 8065 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport); 8066 } 8067 if (!vxlan_v) 8068 return; 8069 if (!vxlan_m) 8070 vxlan_m = &rte_flow_item_vxlan_gpe_mask; 8071 size = sizeof(vxlan_m->vni); 8072 vni_m = MLX5_ADDR_OF(fte_match_set_misc3, misc_m, outer_vxlan_gpe_vni); 8073 vni_v = MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni); 8074 memcpy(vni_m, vxlan_m->vni, size); 8075 for (i = 0; i < size; ++i) 8076 vni_v[i] = vni_m[i] & vxlan_v->vni[i]; 8077 if (vxlan_m->flags) { 8078 flags_m = vxlan_m->flags; 8079 flags_v = vxlan_v->flags; 8080 } 8081 MLX5_SET(fte_match_set_misc3, misc_m, outer_vxlan_gpe_flags, flags_m); 8082 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags, flags_v); 8083 MLX5_SET(fte_match_set_misc3, misc_m, outer_vxlan_gpe_next_protocol, 8084 vxlan_m->protocol); 8085 MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_next_protocol, 8086 vxlan_v->protocol); 8087 } 8088 8089 /** 8090 * Add Geneve item to matcher and to the value. 8091 * 8092 * @param[in, out] matcher 8093 * Flow matcher. 8094 * @param[in, out] key 8095 * Flow matcher value. 8096 * @param[in] item 8097 * Flow pattern to translate. 8098 * @param[in] inner 8099 * Item is inner pattern. 8100 */ 8101 8102 static void 8103 flow_dv_translate_item_geneve(void *matcher, void *key, 8104 const struct rte_flow_item *item, int inner) 8105 { 8106 const struct rte_flow_item_geneve *geneve_m = item->mask; 8107 const struct rte_flow_item_geneve *geneve_v = item->spec; 8108 void *headers_m; 8109 void *headers_v; 8110 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 8111 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 8112 uint16_t dport; 8113 uint16_t gbhdr_m; 8114 uint16_t gbhdr_v; 8115 char *vni_m; 8116 char *vni_v; 8117 size_t size, i; 8118 8119 if (inner) { 8120 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8121 inner_headers); 8122 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 8123 } else { 8124 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8125 outer_headers); 8126 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8127 } 8128 dport = MLX5_UDP_PORT_GENEVE; 8129 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) { 8130 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF); 8131 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport); 8132 } 8133 if (!geneve_v) 8134 return; 8135 if (!geneve_m) 8136 geneve_m = &rte_flow_item_geneve_mask; 8137 size = sizeof(geneve_m->vni); 8138 vni_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, geneve_vni); 8139 vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni); 8140 memcpy(vni_m, geneve_m->vni, size); 8141 for (i = 0; i < size; ++i) 8142 vni_v[i] = vni_m[i] & geneve_v->vni[i]; 8143 MLX5_SET(fte_match_set_misc, misc_m, geneve_protocol_type, 8144 rte_be_to_cpu_16(geneve_m->protocol)); 8145 MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type, 8146 rte_be_to_cpu_16(geneve_v->protocol & geneve_m->protocol)); 8147 gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0); 8148 gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0); 8149 MLX5_SET(fte_match_set_misc, misc_m, geneve_oam, 8150 MLX5_GENEVE_OAMF_VAL(gbhdr_m)); 8151 MLX5_SET(fte_match_set_misc, misc_v, geneve_oam, 8152 MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m)); 8153 MLX5_SET(fte_match_set_misc, misc_m, geneve_opt_len, 8154 MLX5_GENEVE_OPTLEN_VAL(gbhdr_m)); 8155 MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len, 8156 MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) & 8157 MLX5_GENEVE_OPTLEN_VAL(gbhdr_m)); 8158 } 8159 8160 /** 8161 * Create Geneve TLV option resource. 8162 * 8163 * @param dev[in, out] 8164 * Pointer to rte_eth_dev structure. 8165 * @param[in, out] tag_be24 8166 * Tag value in big endian then R-shift 8. 8167 * @parm[in, out] dev_flow 8168 * Pointer to the dev_flow. 8169 * @param[out] error 8170 * pointer to error structure. 8171 * 8172 * @return 8173 * 0 on success otherwise -errno and errno is set. 8174 */ 8175 8176 int 8177 flow_dev_geneve_tlv_option_resource_register(struct rte_eth_dev *dev, 8178 const struct rte_flow_item *item, 8179 struct rte_flow_error *error) 8180 { 8181 struct mlx5_priv *priv = dev->data->dev_private; 8182 struct mlx5_dev_ctx_shared *sh = priv->sh; 8183 struct mlx5_geneve_tlv_option_resource *geneve_opt_resource = 8184 sh->geneve_tlv_option_resource; 8185 struct mlx5_devx_obj *obj; 8186 const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec; 8187 int ret = 0; 8188 8189 if (!geneve_opt_v) 8190 return -1; 8191 rte_spinlock_lock(&sh->geneve_tlv_opt_sl); 8192 if (geneve_opt_resource != NULL) { 8193 if (geneve_opt_resource->option_class == 8194 geneve_opt_v->option_class && 8195 geneve_opt_resource->option_type == 8196 geneve_opt_v->option_type && 8197 geneve_opt_resource->length == 8198 geneve_opt_v->option_len) { 8199 /* We already have GENVE TLV option obj allocated. */ 8200 __atomic_fetch_add(&geneve_opt_resource->refcnt, 1, 8201 __ATOMIC_RELAXED); 8202 } else { 8203 ret = rte_flow_error_set(error, ENOMEM, 8204 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 8205 "Only one GENEVE TLV option supported"); 8206 goto exit; 8207 } 8208 } else { 8209 /* Create a GENEVE TLV object and resource. */ 8210 obj = mlx5_devx_cmd_create_geneve_tlv_option(sh->ctx, 8211 geneve_opt_v->option_class, 8212 geneve_opt_v->option_type, 8213 geneve_opt_v->option_len); 8214 if (!obj) { 8215 ret = rte_flow_error_set(error, ENODATA, 8216 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 8217 "Failed to create GENEVE TLV Devx object"); 8218 goto exit; 8219 } 8220 sh->geneve_tlv_option_resource = 8221 mlx5_malloc(MLX5_MEM_ZERO, 8222 sizeof(*geneve_opt_resource), 8223 0, SOCKET_ID_ANY); 8224 if (!sh->geneve_tlv_option_resource) { 8225 claim_zero(mlx5_devx_cmd_destroy(obj)); 8226 ret = rte_flow_error_set(error, ENOMEM, 8227 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 8228 "GENEVE TLV object memory allocation failed"); 8229 goto exit; 8230 } 8231 geneve_opt_resource = sh->geneve_tlv_option_resource; 8232 geneve_opt_resource->obj = obj; 8233 geneve_opt_resource->option_class = geneve_opt_v->option_class; 8234 geneve_opt_resource->option_type = geneve_opt_v->option_type; 8235 geneve_opt_resource->length = geneve_opt_v->option_len; 8236 __atomic_store_n(&geneve_opt_resource->refcnt, 1, 8237 __ATOMIC_RELAXED); 8238 } 8239 exit: 8240 rte_spinlock_unlock(&sh->geneve_tlv_opt_sl); 8241 return ret; 8242 } 8243 8244 /** 8245 * Add Geneve TLV option item to matcher. 8246 * 8247 * @param[in, out] dev 8248 * Pointer to rte_eth_dev structure. 8249 * @param[in, out] matcher 8250 * Flow matcher. 8251 * @param[in, out] key 8252 * Flow matcher value. 8253 * @param[in] item 8254 * Flow pattern to translate. 8255 * @param[out] error 8256 * Pointer to error structure. 8257 */ 8258 static int 8259 flow_dv_translate_item_geneve_opt(struct rte_eth_dev *dev, void *matcher, 8260 void *key, const struct rte_flow_item *item, 8261 struct rte_flow_error *error) 8262 { 8263 const struct rte_flow_item_geneve_opt *geneve_opt_m = item->mask; 8264 const struct rte_flow_item_geneve_opt *geneve_opt_v = item->spec; 8265 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 8266 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 8267 void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher, 8268 misc_parameters_3); 8269 void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8270 rte_be32_t opt_data_key = 0, opt_data_mask = 0; 8271 int ret = 0; 8272 8273 if (!geneve_opt_v) 8274 return -1; 8275 if (!geneve_opt_m) 8276 geneve_opt_m = &rte_flow_item_geneve_opt_mask; 8277 ret = flow_dev_geneve_tlv_option_resource_register(dev, item, 8278 error); 8279 if (ret) { 8280 DRV_LOG(ERR, "Failed to create geneve_tlv_obj"); 8281 return ret; 8282 } 8283 /* 8284 * Set the option length in GENEVE header if not requested. 8285 * The GENEVE TLV option length is expressed by the option length field 8286 * in the GENEVE header. 8287 * If the option length was not requested but the GENEVE TLV option item 8288 * is present we set the option length field implicitly. 8289 */ 8290 if (!MLX5_GET16(fte_match_set_misc, misc_m, geneve_opt_len)) { 8291 MLX5_SET(fte_match_set_misc, misc_m, geneve_opt_len, 8292 MLX5_GENEVE_OPTLEN_MASK); 8293 MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len, 8294 geneve_opt_v->option_len + 1); 8295 } 8296 /* Set the data. */ 8297 if (geneve_opt_v->data) { 8298 memcpy(&opt_data_key, geneve_opt_v->data, 8299 RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4), 8300 sizeof(opt_data_key))); 8301 MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <= 8302 sizeof(opt_data_key)); 8303 memcpy(&opt_data_mask, geneve_opt_m->data, 8304 RTE_MIN((uint32_t)(geneve_opt_v->option_len * 4), 8305 sizeof(opt_data_mask))); 8306 MLX5_ASSERT((uint32_t)(geneve_opt_v->option_len * 4) <= 8307 sizeof(opt_data_mask)); 8308 MLX5_SET(fte_match_set_misc3, misc3_m, 8309 geneve_tlv_option_0_data, 8310 rte_be_to_cpu_32(opt_data_mask)); 8311 MLX5_SET(fte_match_set_misc3, misc3_v, 8312 geneve_tlv_option_0_data, 8313 rte_be_to_cpu_32(opt_data_key & opt_data_mask)); 8314 } 8315 return ret; 8316 } 8317 8318 /** 8319 * Add MPLS item to matcher and to the value. 8320 * 8321 * @param[in, out] matcher 8322 * Flow matcher. 8323 * @param[in, out] key 8324 * Flow matcher value. 8325 * @param[in] item 8326 * Flow pattern to translate. 8327 * @param[in] prev_layer 8328 * The protocol layer indicated in previous item. 8329 * @param[in] inner 8330 * Item is inner pattern. 8331 */ 8332 static void 8333 flow_dv_translate_item_mpls(void *matcher, void *key, 8334 const struct rte_flow_item *item, 8335 uint64_t prev_layer, 8336 int inner) 8337 { 8338 const uint32_t *in_mpls_m = item->mask; 8339 const uint32_t *in_mpls_v = item->spec; 8340 uint32_t *out_mpls_m = 0; 8341 uint32_t *out_mpls_v = 0; 8342 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 8343 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 8344 void *misc2_m = MLX5_ADDR_OF(fte_match_param, matcher, 8345 misc_parameters_2); 8346 void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2); 8347 void *headers_m = MLX5_ADDR_OF(fte_match_param, matcher, outer_headers); 8348 void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8349 8350 switch (prev_layer) { 8351 case MLX5_FLOW_LAYER_OUTER_L4_UDP: 8352 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xffff); 8353 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, 8354 MLX5_UDP_PORT_MPLS); 8355 break; 8356 case MLX5_FLOW_LAYER_GRE: 8357 MLX5_SET(fte_match_set_misc, misc_m, gre_protocol, 0xffff); 8358 MLX5_SET(fte_match_set_misc, misc_v, gre_protocol, 8359 RTE_ETHER_TYPE_MPLS); 8360 break; 8361 default: 8362 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff); 8363 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, 8364 IPPROTO_MPLS); 8365 break; 8366 } 8367 if (!in_mpls_v) 8368 return; 8369 if (!in_mpls_m) 8370 in_mpls_m = (const uint32_t *)&rte_flow_item_mpls_mask; 8371 switch (prev_layer) { 8372 case MLX5_FLOW_LAYER_OUTER_L4_UDP: 8373 out_mpls_m = 8374 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m, 8375 outer_first_mpls_over_udp); 8376 out_mpls_v = 8377 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v, 8378 outer_first_mpls_over_udp); 8379 break; 8380 case MLX5_FLOW_LAYER_GRE: 8381 out_mpls_m = 8382 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m, 8383 outer_first_mpls_over_gre); 8384 out_mpls_v = 8385 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v, 8386 outer_first_mpls_over_gre); 8387 break; 8388 default: 8389 /* Inner MPLS not over GRE is not supported. */ 8390 if (!inner) { 8391 out_mpls_m = 8392 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, 8393 misc2_m, 8394 outer_first_mpls); 8395 out_mpls_v = 8396 (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, 8397 misc2_v, 8398 outer_first_mpls); 8399 } 8400 break; 8401 } 8402 if (out_mpls_m && out_mpls_v) { 8403 *out_mpls_m = *in_mpls_m; 8404 *out_mpls_v = *in_mpls_v & *in_mpls_m; 8405 } 8406 } 8407 8408 /** 8409 * Add metadata register item to matcher 8410 * 8411 * @param[in, out] matcher 8412 * Flow matcher. 8413 * @param[in, out] key 8414 * Flow matcher value. 8415 * @param[in] reg_type 8416 * Type of device metadata register 8417 * @param[in] value 8418 * Register value 8419 * @param[in] mask 8420 * Register mask 8421 */ 8422 static void 8423 flow_dv_match_meta_reg(void *matcher, void *key, 8424 enum modify_reg reg_type, 8425 uint32_t data, uint32_t mask) 8426 { 8427 void *misc2_m = 8428 MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_2); 8429 void *misc2_v = 8430 MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2); 8431 uint32_t temp; 8432 8433 data &= mask; 8434 switch (reg_type) { 8435 case REG_A: 8436 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_a, mask); 8437 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a, data); 8438 break; 8439 case REG_B: 8440 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_b, mask); 8441 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data); 8442 break; 8443 case REG_C_0: 8444 /* 8445 * The metadata register C0 field might be divided into 8446 * source vport index and META item value, we should set 8447 * this field according to specified mask, not as whole one. 8448 */ 8449 temp = MLX5_GET(fte_match_set_misc2, misc2_m, metadata_reg_c_0); 8450 temp |= mask; 8451 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0, temp); 8452 temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0); 8453 temp &= ~mask; 8454 temp |= data; 8455 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp); 8456 break; 8457 case REG_C_1: 8458 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_1, mask); 8459 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1, data); 8460 break; 8461 case REG_C_2: 8462 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_2, mask); 8463 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2, data); 8464 break; 8465 case REG_C_3: 8466 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_3, mask); 8467 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3, data); 8468 break; 8469 case REG_C_4: 8470 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_4, mask); 8471 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4, data); 8472 break; 8473 case REG_C_5: 8474 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_5, mask); 8475 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5, data); 8476 break; 8477 case REG_C_6: 8478 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_6, mask); 8479 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6, data); 8480 break; 8481 case REG_C_7: 8482 MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_7, mask); 8483 MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7, data); 8484 break; 8485 default: 8486 MLX5_ASSERT(false); 8487 break; 8488 } 8489 } 8490 8491 /** 8492 * Add MARK item to matcher 8493 * 8494 * @param[in] dev 8495 * The device to configure through. 8496 * @param[in, out] matcher 8497 * Flow matcher. 8498 * @param[in, out] key 8499 * Flow matcher value. 8500 * @param[in] item 8501 * Flow pattern to translate. 8502 */ 8503 static void 8504 flow_dv_translate_item_mark(struct rte_eth_dev *dev, 8505 void *matcher, void *key, 8506 const struct rte_flow_item *item) 8507 { 8508 struct mlx5_priv *priv = dev->data->dev_private; 8509 const struct rte_flow_item_mark *mark; 8510 uint32_t value; 8511 uint32_t mask; 8512 8513 mark = item->mask ? (const void *)item->mask : 8514 &rte_flow_item_mark_mask; 8515 mask = mark->id & priv->sh->dv_mark_mask; 8516 mark = (const void *)item->spec; 8517 MLX5_ASSERT(mark); 8518 value = mark->id & priv->sh->dv_mark_mask & mask; 8519 if (mask) { 8520 enum modify_reg reg; 8521 8522 /* Get the metadata register index for the mark. */ 8523 reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL); 8524 MLX5_ASSERT(reg > 0); 8525 if (reg == REG_C_0) { 8526 struct mlx5_priv *priv = dev->data->dev_private; 8527 uint32_t msk_c0 = priv->sh->dv_regc0_mask; 8528 uint32_t shl_c0 = rte_bsf32(msk_c0); 8529 8530 mask &= msk_c0; 8531 mask <<= shl_c0; 8532 value <<= shl_c0; 8533 } 8534 flow_dv_match_meta_reg(matcher, key, reg, value, mask); 8535 } 8536 } 8537 8538 /** 8539 * Add META item to matcher 8540 * 8541 * @param[in] dev 8542 * The devich to configure through. 8543 * @param[in, out] matcher 8544 * Flow matcher. 8545 * @param[in, out] key 8546 * Flow matcher value. 8547 * @param[in] attr 8548 * Attributes of flow that includes this item. 8549 * @param[in] item 8550 * Flow pattern to translate. 8551 */ 8552 static void 8553 flow_dv_translate_item_meta(struct rte_eth_dev *dev, 8554 void *matcher, void *key, 8555 const struct rte_flow_attr *attr, 8556 const struct rte_flow_item *item) 8557 { 8558 const struct rte_flow_item_meta *meta_m; 8559 const struct rte_flow_item_meta *meta_v; 8560 8561 meta_m = (const void *)item->mask; 8562 if (!meta_m) 8563 meta_m = &rte_flow_item_meta_mask; 8564 meta_v = (const void *)item->spec; 8565 if (meta_v) { 8566 int reg; 8567 uint32_t value = meta_v->data; 8568 uint32_t mask = meta_m->data; 8569 8570 reg = flow_dv_get_metadata_reg(dev, attr, NULL); 8571 if (reg < 0) 8572 return; 8573 MLX5_ASSERT(reg != REG_NON); 8574 /* 8575 * In datapath code there is no endianness 8576 * coversions for perfromance reasons, all 8577 * pattern conversions are done in rte_flow. 8578 */ 8579 value = rte_cpu_to_be_32(value); 8580 mask = rte_cpu_to_be_32(mask); 8581 if (reg == REG_C_0) { 8582 struct mlx5_priv *priv = dev->data->dev_private; 8583 uint32_t msk_c0 = priv->sh->dv_regc0_mask; 8584 uint32_t shl_c0 = rte_bsf32(msk_c0); 8585 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 8586 uint32_t shr_c0 = __builtin_clz(priv->sh->dv_meta_mask); 8587 8588 value >>= shr_c0; 8589 mask >>= shr_c0; 8590 #endif 8591 value <<= shl_c0; 8592 mask <<= shl_c0; 8593 MLX5_ASSERT(msk_c0); 8594 MLX5_ASSERT(!(~msk_c0 & mask)); 8595 } 8596 flow_dv_match_meta_reg(matcher, key, reg, value, mask); 8597 } 8598 } 8599 8600 /** 8601 * Add vport metadata Reg C0 item to matcher 8602 * 8603 * @param[in, out] matcher 8604 * Flow matcher. 8605 * @param[in, out] key 8606 * Flow matcher value. 8607 * @param[in] reg 8608 * Flow pattern to translate. 8609 */ 8610 static void 8611 flow_dv_translate_item_meta_vport(void *matcher, void *key, 8612 uint32_t value, uint32_t mask) 8613 { 8614 flow_dv_match_meta_reg(matcher, key, REG_C_0, value, mask); 8615 } 8616 8617 /** 8618 * Add tag item to matcher 8619 * 8620 * @param[in] dev 8621 * The devich to configure through. 8622 * @param[in, out] matcher 8623 * Flow matcher. 8624 * @param[in, out] key 8625 * Flow matcher value. 8626 * @param[in] item 8627 * Flow pattern to translate. 8628 */ 8629 static void 8630 flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev, 8631 void *matcher, void *key, 8632 const struct rte_flow_item *item) 8633 { 8634 const struct mlx5_rte_flow_item_tag *tag_v = item->spec; 8635 const struct mlx5_rte_flow_item_tag *tag_m = item->mask; 8636 uint32_t mask, value; 8637 8638 MLX5_ASSERT(tag_v); 8639 value = tag_v->data; 8640 mask = tag_m ? tag_m->data : UINT32_MAX; 8641 if (tag_v->id == REG_C_0) { 8642 struct mlx5_priv *priv = dev->data->dev_private; 8643 uint32_t msk_c0 = priv->sh->dv_regc0_mask; 8644 uint32_t shl_c0 = rte_bsf32(msk_c0); 8645 8646 mask &= msk_c0; 8647 mask <<= shl_c0; 8648 value <<= shl_c0; 8649 } 8650 flow_dv_match_meta_reg(matcher, key, tag_v->id, value, mask); 8651 } 8652 8653 /** 8654 * Add TAG item to matcher 8655 * 8656 * @param[in] dev 8657 * The devich to configure through. 8658 * @param[in, out] matcher 8659 * Flow matcher. 8660 * @param[in, out] key 8661 * Flow matcher value. 8662 * @param[in] item 8663 * Flow pattern to translate. 8664 */ 8665 static void 8666 flow_dv_translate_item_tag(struct rte_eth_dev *dev, 8667 void *matcher, void *key, 8668 const struct rte_flow_item *item) 8669 { 8670 const struct rte_flow_item_tag *tag_v = item->spec; 8671 const struct rte_flow_item_tag *tag_m = item->mask; 8672 enum modify_reg reg; 8673 8674 MLX5_ASSERT(tag_v); 8675 tag_m = tag_m ? tag_m : &rte_flow_item_tag_mask; 8676 /* Get the metadata register index for the tag. */ 8677 reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, tag_v->index, NULL); 8678 MLX5_ASSERT(reg > 0); 8679 flow_dv_match_meta_reg(matcher, key, reg, tag_v->data, tag_m->data); 8680 } 8681 8682 /** 8683 * Add source vport match to the specified matcher. 8684 * 8685 * @param[in, out] matcher 8686 * Flow matcher. 8687 * @param[in, out] key 8688 * Flow matcher value. 8689 * @param[in] port 8690 * Source vport value to match 8691 * @param[in] mask 8692 * Mask 8693 */ 8694 static void 8695 flow_dv_translate_item_source_vport(void *matcher, void *key, 8696 int16_t port, uint16_t mask) 8697 { 8698 void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 8699 void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 8700 8701 MLX5_SET(fte_match_set_misc, misc_m, source_port, mask); 8702 MLX5_SET(fte_match_set_misc, misc_v, source_port, port); 8703 } 8704 8705 /** 8706 * Translate port-id item to eswitch match on port-id. 8707 * 8708 * @param[in] dev 8709 * The devich to configure through. 8710 * @param[in, out] matcher 8711 * Flow matcher. 8712 * @param[in, out] key 8713 * Flow matcher value. 8714 * @param[in] item 8715 * Flow pattern to translate. 8716 * @param[in] 8717 * Flow attributes. 8718 * 8719 * @return 8720 * 0 on success, a negative errno value otherwise. 8721 */ 8722 static int 8723 flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *matcher, 8724 void *key, const struct rte_flow_item *item, 8725 const struct rte_flow_attr *attr) 8726 { 8727 const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL; 8728 const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL; 8729 struct mlx5_priv *priv; 8730 uint16_t mask, id; 8731 8732 mask = pid_m ? pid_m->id : 0xffff; 8733 id = pid_v ? pid_v->id : dev->data->port_id; 8734 priv = mlx5_port_to_eswitch_info(id, item == NULL); 8735 if (!priv) 8736 return -rte_errno; 8737 /* 8738 * Translate to vport field or to metadata, depending on mode. 8739 * Kernel can use either misc.source_port or half of C0 metadata 8740 * register. 8741 */ 8742 if (priv->vport_meta_mask) { 8743 /* 8744 * Provide the hint for SW steering library 8745 * to insert the flow into ingress domain and 8746 * save the extra vport match. 8747 */ 8748 if (mask == 0xffff && priv->vport_id == 0xffff && 8749 priv->pf_bond < 0 && attr->transfer) 8750 flow_dv_translate_item_source_vport 8751 (matcher, key, priv->vport_id, mask); 8752 /* 8753 * We should always set the vport metadata register, 8754 * otherwise the SW steering library can drop 8755 * the rule if wire vport metadata value is not zero, 8756 * it depends on kernel configuration. 8757 */ 8758 flow_dv_translate_item_meta_vport(matcher, key, 8759 priv->vport_meta_tag, 8760 priv->vport_meta_mask); 8761 } else { 8762 flow_dv_translate_item_source_vport(matcher, key, 8763 priv->vport_id, mask); 8764 } 8765 return 0; 8766 } 8767 8768 /** 8769 * Add ICMP6 item to matcher and to the value. 8770 * 8771 * @param[in, out] matcher 8772 * Flow matcher. 8773 * @param[in, out] key 8774 * Flow matcher value. 8775 * @param[in] item 8776 * Flow pattern to translate. 8777 * @param[in] inner 8778 * Item is inner pattern. 8779 */ 8780 static void 8781 flow_dv_translate_item_icmp6(void *matcher, void *key, 8782 const struct rte_flow_item *item, 8783 int inner) 8784 { 8785 const struct rte_flow_item_icmp6 *icmp6_m = item->mask; 8786 const struct rte_flow_item_icmp6 *icmp6_v = item->spec; 8787 void *headers_m; 8788 void *headers_v; 8789 void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher, 8790 misc_parameters_3); 8791 void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8792 if (inner) { 8793 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8794 inner_headers); 8795 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 8796 } else { 8797 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8798 outer_headers); 8799 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8800 } 8801 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xFF); 8802 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ICMPV6); 8803 if (!icmp6_v) 8804 return; 8805 if (!icmp6_m) 8806 icmp6_m = &rte_flow_item_icmp6_mask; 8807 MLX5_SET(fte_match_set_misc3, misc3_m, icmpv6_type, icmp6_m->type); 8808 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type, 8809 icmp6_v->type & icmp6_m->type); 8810 MLX5_SET(fte_match_set_misc3, misc3_m, icmpv6_code, icmp6_m->code); 8811 MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_code, 8812 icmp6_v->code & icmp6_m->code); 8813 } 8814 8815 /** 8816 * Add ICMP item to matcher and to the value. 8817 * 8818 * @param[in, out] matcher 8819 * Flow matcher. 8820 * @param[in, out] key 8821 * Flow matcher value. 8822 * @param[in] item 8823 * Flow pattern to translate. 8824 * @param[in] inner 8825 * Item is inner pattern. 8826 */ 8827 static void 8828 flow_dv_translate_item_icmp(void *matcher, void *key, 8829 const struct rte_flow_item *item, 8830 int inner) 8831 { 8832 const struct rte_flow_item_icmp *icmp_m = item->mask; 8833 const struct rte_flow_item_icmp *icmp_v = item->spec; 8834 uint32_t icmp_header_data_m = 0; 8835 uint32_t icmp_header_data_v = 0; 8836 void *headers_m; 8837 void *headers_v; 8838 void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher, 8839 misc_parameters_3); 8840 void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8841 if (inner) { 8842 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8843 inner_headers); 8844 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 8845 } else { 8846 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8847 outer_headers); 8848 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8849 } 8850 MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xFF); 8851 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ICMP); 8852 if (!icmp_v) 8853 return; 8854 if (!icmp_m) 8855 icmp_m = &rte_flow_item_icmp_mask; 8856 MLX5_SET(fte_match_set_misc3, misc3_m, icmp_type, 8857 icmp_m->hdr.icmp_type); 8858 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type, 8859 icmp_v->hdr.icmp_type & icmp_m->hdr.icmp_type); 8860 MLX5_SET(fte_match_set_misc3, misc3_m, icmp_code, 8861 icmp_m->hdr.icmp_code); 8862 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_code, 8863 icmp_v->hdr.icmp_code & icmp_m->hdr.icmp_code); 8864 icmp_header_data_m = rte_be_to_cpu_16(icmp_m->hdr.icmp_seq_nb); 8865 icmp_header_data_m |= rte_be_to_cpu_16(icmp_m->hdr.icmp_ident) << 16; 8866 if (icmp_header_data_m) { 8867 icmp_header_data_v = rte_be_to_cpu_16(icmp_v->hdr.icmp_seq_nb); 8868 icmp_header_data_v |= 8869 rte_be_to_cpu_16(icmp_v->hdr.icmp_ident) << 16; 8870 MLX5_SET(fte_match_set_misc3, misc3_m, icmp_header_data, 8871 icmp_header_data_m); 8872 MLX5_SET(fte_match_set_misc3, misc3_v, icmp_header_data, 8873 icmp_header_data_v & icmp_header_data_m); 8874 } 8875 } 8876 8877 /** 8878 * Add GTP item to matcher and to the value. 8879 * 8880 * @param[in, out] matcher 8881 * Flow matcher. 8882 * @param[in, out] key 8883 * Flow matcher value. 8884 * @param[in] item 8885 * Flow pattern to translate. 8886 * @param[in] inner 8887 * Item is inner pattern. 8888 */ 8889 static void 8890 flow_dv_translate_item_gtp(void *matcher, void *key, 8891 const struct rte_flow_item *item, int inner) 8892 { 8893 const struct rte_flow_item_gtp *gtp_m = item->mask; 8894 const struct rte_flow_item_gtp *gtp_v = item->spec; 8895 void *headers_m; 8896 void *headers_v; 8897 void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher, 8898 misc_parameters_3); 8899 void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8900 uint16_t dport = RTE_GTPU_UDP_PORT; 8901 8902 if (inner) { 8903 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8904 inner_headers); 8905 headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers); 8906 } else { 8907 headers_m = MLX5_ADDR_OF(fte_match_param, matcher, 8908 outer_headers); 8909 headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers); 8910 } 8911 if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) { 8912 MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF); 8913 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport); 8914 } 8915 if (!gtp_v) 8916 return; 8917 if (!gtp_m) 8918 gtp_m = &rte_flow_item_gtp_mask; 8919 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_msg_flags, 8920 gtp_m->v_pt_rsv_flags); 8921 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, 8922 gtp_v->v_pt_rsv_flags & gtp_m->v_pt_rsv_flags); 8923 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_msg_type, gtp_m->msg_type); 8924 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type, 8925 gtp_v->msg_type & gtp_m->msg_type); 8926 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_teid, 8927 rte_be_to_cpu_32(gtp_m->teid)); 8928 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid, 8929 rte_be_to_cpu_32(gtp_v->teid & gtp_m->teid)); 8930 } 8931 8932 /** 8933 * Add GTP PSC item to matcher. 8934 * 8935 * @param[in, out] matcher 8936 * Flow matcher. 8937 * @param[in, out] key 8938 * Flow matcher value. 8939 * @param[in] item 8940 * Flow pattern to translate. 8941 */ 8942 static int 8943 flow_dv_translate_item_gtp_psc(void *matcher, void *key, 8944 const struct rte_flow_item *item) 8945 { 8946 const struct rte_flow_item_gtp_psc *gtp_psc_m = item->mask; 8947 const struct rte_flow_item_gtp_psc *gtp_psc_v = item->spec; 8948 void *misc3_m = MLX5_ADDR_OF(fte_match_param, matcher, 8949 misc_parameters_3); 8950 void *misc3_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3); 8951 union { 8952 uint32_t w32; 8953 struct { 8954 uint16_t seq_num; 8955 uint8_t npdu_num; 8956 uint8_t next_ext_header_type; 8957 }; 8958 } dw_2; 8959 uint8_t gtp_flags; 8960 8961 /* Always set E-flag match on one, regardless of GTP item settings. */ 8962 gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_m, gtpu_msg_flags); 8963 gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG; 8964 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_msg_flags, gtp_flags); 8965 gtp_flags = MLX5_GET(fte_match_set_misc3, misc3_v, gtpu_msg_flags); 8966 gtp_flags |= MLX5_GTP_EXT_HEADER_FLAG; 8967 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags, gtp_flags); 8968 /*Set next extension header type. */ 8969 dw_2.seq_num = 0; 8970 dw_2.npdu_num = 0; 8971 dw_2.next_ext_header_type = 0xff; 8972 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_dw_2, 8973 rte_cpu_to_be_32(dw_2.w32)); 8974 dw_2.seq_num = 0; 8975 dw_2.npdu_num = 0; 8976 dw_2.next_ext_header_type = 0x85; 8977 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_dw_2, 8978 rte_cpu_to_be_32(dw_2.w32)); 8979 if (gtp_psc_v) { 8980 union { 8981 uint32_t w32; 8982 struct { 8983 uint8_t len; 8984 uint8_t type_flags; 8985 uint8_t qfi; 8986 uint8_t reserved; 8987 }; 8988 } dw_0; 8989 8990 /*Set extension header PDU type and Qos. */ 8991 if (!gtp_psc_m) 8992 gtp_psc_m = &rte_flow_item_gtp_psc_mask; 8993 dw_0.w32 = 0; 8994 dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_m->pdu_type); 8995 dw_0.qfi = gtp_psc_m->qfi; 8996 MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_first_ext_dw_0, 8997 rte_cpu_to_be_32(dw_0.w32)); 8998 dw_0.w32 = 0; 8999 dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->pdu_type & 9000 gtp_psc_m->pdu_type); 9001 dw_0.qfi = gtp_psc_v->qfi & gtp_psc_m->qfi; 9002 MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0, 9003 rte_cpu_to_be_32(dw_0.w32)); 9004 } 9005 return 0; 9006 } 9007 9008 /** 9009 * Add eCPRI item to matcher and to the value. 9010 * 9011 * @param[in] dev 9012 * The devich to configure through. 9013 * @param[in, out] matcher 9014 * Flow matcher. 9015 * @param[in, out] key 9016 * Flow matcher value. 9017 * @param[in] item 9018 * Flow pattern to translate. 9019 * @param[in] samples 9020 * Sample IDs to be used in the matching. 9021 */ 9022 static void 9023 flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *matcher, 9024 void *key, const struct rte_flow_item *item) 9025 { 9026 struct mlx5_priv *priv = dev->data->dev_private; 9027 const struct rte_flow_item_ecpri *ecpri_m = item->mask; 9028 const struct rte_flow_item_ecpri *ecpri_v = item->spec; 9029 struct rte_ecpri_common_hdr common; 9030 void *misc4_m = MLX5_ADDR_OF(fte_match_param, matcher, 9031 misc_parameters_4); 9032 void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4); 9033 uint32_t *samples; 9034 void *dw_m; 9035 void *dw_v; 9036 9037 if (!ecpri_v) 9038 return; 9039 if (!ecpri_m) 9040 ecpri_m = &rte_flow_item_ecpri_mask; 9041 /* 9042 * Maximal four DW samples are supported in a single matching now. 9043 * Two are used now for a eCPRI matching: 9044 * 1. Type: one byte, mask should be 0x00ff0000 in network order 9045 * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000 9046 * if any. 9047 */ 9048 if (!ecpri_m->hdr.common.u32) 9049 return; 9050 samples = priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0].ids; 9051 /* Need to take the whole DW as the mask to fill the entry. */ 9052 dw_m = MLX5_ADDR_OF(fte_match_set_misc4, misc4_m, 9053 prog_sample_field_value_0); 9054 dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v, 9055 prog_sample_field_value_0); 9056 /* Already big endian (network order) in the header. */ 9057 *(uint32_t *)dw_m = ecpri_m->hdr.common.u32; 9058 *(uint32_t *)dw_v = ecpri_v->hdr.common.u32 & ecpri_m->hdr.common.u32; 9059 /* Sample#0, used for matching type, offset 0. */ 9060 MLX5_SET(fte_match_set_misc4, misc4_m, 9061 prog_sample_field_id_0, samples[0]); 9062 /* It makes no sense to set the sample ID in the mask field. */ 9063 MLX5_SET(fte_match_set_misc4, misc4_v, 9064 prog_sample_field_id_0, samples[0]); 9065 /* 9066 * Checking if message body part needs to be matched. 9067 * Some wildcard rules only matching type field should be supported. 9068 */ 9069 if (ecpri_m->hdr.dummy[0]) { 9070 common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32); 9071 switch (common.type) { 9072 case RTE_ECPRI_MSG_TYPE_IQ_DATA: 9073 case RTE_ECPRI_MSG_TYPE_RTC_CTRL: 9074 case RTE_ECPRI_MSG_TYPE_DLY_MSR: 9075 dw_m = MLX5_ADDR_OF(fte_match_set_misc4, misc4_m, 9076 prog_sample_field_value_1); 9077 dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v, 9078 prog_sample_field_value_1); 9079 *(uint32_t *)dw_m = ecpri_m->hdr.dummy[0]; 9080 *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] & 9081 ecpri_m->hdr.dummy[0]; 9082 /* Sample#1, to match message body, offset 4. */ 9083 MLX5_SET(fte_match_set_misc4, misc4_m, 9084 prog_sample_field_id_1, samples[1]); 9085 MLX5_SET(fte_match_set_misc4, misc4_v, 9086 prog_sample_field_id_1, samples[1]); 9087 break; 9088 default: 9089 /* Others, do not match any sample ID. */ 9090 break; 9091 } 9092 } 9093 } 9094 9095 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 }; 9096 9097 #define HEADER_IS_ZERO(match_criteria, headers) \ 9098 !(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \ 9099 matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \ 9100 9101 /** 9102 * Calculate flow matcher enable bitmap. 9103 * 9104 * @param match_criteria 9105 * Pointer to flow matcher criteria. 9106 * 9107 * @return 9108 * Bitmap of enabled fields. 9109 */ 9110 static uint8_t 9111 flow_dv_matcher_enable(uint32_t *match_criteria) 9112 { 9113 uint8_t match_criteria_enable; 9114 9115 match_criteria_enable = 9116 (!HEADER_IS_ZERO(match_criteria, outer_headers)) << 9117 MLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT; 9118 match_criteria_enable |= 9119 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) << 9120 MLX5_MATCH_CRITERIA_ENABLE_MISC_BIT; 9121 match_criteria_enable |= 9122 (!HEADER_IS_ZERO(match_criteria, inner_headers)) << 9123 MLX5_MATCH_CRITERIA_ENABLE_INNER_BIT; 9124 match_criteria_enable |= 9125 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) << 9126 MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT; 9127 match_criteria_enable |= 9128 (!HEADER_IS_ZERO(match_criteria, misc_parameters_3)) << 9129 MLX5_MATCH_CRITERIA_ENABLE_MISC3_BIT; 9130 match_criteria_enable |= 9131 (!HEADER_IS_ZERO(match_criteria, misc_parameters_4)) << 9132 MLX5_MATCH_CRITERIA_ENABLE_MISC4_BIT; 9133 return match_criteria_enable; 9134 } 9135 9136 struct mlx5_hlist_entry * 9137 flow_dv_tbl_create_cb(struct mlx5_hlist *list, uint64_t key64, void *cb_ctx) 9138 { 9139 struct mlx5_dev_ctx_shared *sh = list->ctx; 9140 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 9141 struct rte_eth_dev *dev = ctx->dev; 9142 struct mlx5_flow_tbl_data_entry *tbl_data; 9143 struct mlx5_flow_tbl_tunnel_prm *tt_prm = ctx->data; 9144 struct rte_flow_error *error = ctx->error; 9145 union mlx5_flow_tbl_key key = { .v64 = key64 }; 9146 struct mlx5_flow_tbl_resource *tbl; 9147 void *domain; 9148 uint32_t idx = 0; 9149 int ret; 9150 9151 tbl_data = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_JUMP], &idx); 9152 if (!tbl_data) { 9153 rte_flow_error_set(error, ENOMEM, 9154 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9155 NULL, 9156 "cannot allocate flow table data entry"); 9157 return NULL; 9158 } 9159 tbl_data->idx = idx; 9160 tbl_data->tunnel = tt_prm->tunnel; 9161 tbl_data->group_id = tt_prm->group_id; 9162 tbl_data->external = !!tt_prm->external; 9163 tbl_data->tunnel_offload = is_tunnel_offload_active(dev); 9164 tbl_data->is_egress = !!key.direction; 9165 tbl_data->is_transfer = !!key.domain; 9166 tbl_data->dummy = !!key.dummy; 9167 tbl_data->table_id = key.table_id; 9168 tbl = &tbl_data->tbl; 9169 if (key.dummy) 9170 return &tbl_data->entry; 9171 if (key.domain) 9172 domain = sh->fdb_domain; 9173 else if (key.direction) 9174 domain = sh->tx_domain; 9175 else 9176 domain = sh->rx_domain; 9177 ret = mlx5_flow_os_create_flow_tbl(domain, key.table_id, &tbl->obj); 9178 if (ret) { 9179 rte_flow_error_set(error, ENOMEM, 9180 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9181 NULL, "cannot create flow table object"); 9182 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx); 9183 return NULL; 9184 } 9185 if (key.table_id) { 9186 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl 9187 (tbl->obj, &tbl_data->jump.action); 9188 if (ret) { 9189 rte_flow_error_set(error, ENOMEM, 9190 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9191 NULL, 9192 "cannot create flow jump action"); 9193 mlx5_flow_os_destroy_flow_tbl(tbl->obj); 9194 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], idx); 9195 return NULL; 9196 } 9197 } 9198 MKSTR(matcher_name, "%s_%s_%u_matcher_cache", 9199 key.domain ? "FDB" : "NIC", key.direction ? "egress" : "ingress", 9200 key.table_id); 9201 mlx5_cache_list_init(&tbl_data->matchers, matcher_name, 0, sh, 9202 flow_dv_matcher_create_cb, 9203 flow_dv_matcher_match_cb, 9204 flow_dv_matcher_remove_cb); 9205 return &tbl_data->entry; 9206 } 9207 9208 int 9209 flow_dv_tbl_match_cb(struct mlx5_hlist *list __rte_unused, 9210 struct mlx5_hlist_entry *entry, uint64_t key64, 9211 void *cb_ctx __rte_unused) 9212 { 9213 struct mlx5_flow_tbl_data_entry *tbl_data = 9214 container_of(entry, struct mlx5_flow_tbl_data_entry, entry); 9215 union mlx5_flow_tbl_key key = { .v64 = key64 }; 9216 9217 return tbl_data->table_id != key.table_id || 9218 tbl_data->dummy != key.dummy || 9219 tbl_data->is_transfer != key.domain || 9220 tbl_data->is_egress != key.direction; 9221 } 9222 9223 /** 9224 * Get a flow table. 9225 * 9226 * @param[in, out] dev 9227 * Pointer to rte_eth_dev structure. 9228 * @param[in] table_id 9229 * Table id to use. 9230 * @param[in] egress 9231 * Direction of the table. 9232 * @param[in] transfer 9233 * E-Switch or NIC flow. 9234 * @param[in] dummy 9235 * Dummy entry for dv API. 9236 * @param[out] error 9237 * pointer to error structure. 9238 * 9239 * @return 9240 * Returns tables resource based on the index, NULL in case of failed. 9241 */ 9242 struct mlx5_flow_tbl_resource * 9243 flow_dv_tbl_resource_get(struct rte_eth_dev *dev, 9244 uint32_t table_id, uint8_t egress, 9245 uint8_t transfer, 9246 bool external, 9247 const struct mlx5_flow_tunnel *tunnel, 9248 uint32_t group_id, uint8_t dummy, 9249 struct rte_flow_error *error) 9250 { 9251 struct mlx5_priv *priv = dev->data->dev_private; 9252 union mlx5_flow_tbl_key table_key = { 9253 { 9254 .table_id = table_id, 9255 .dummy = dummy, 9256 .domain = !!transfer, 9257 .direction = !!egress, 9258 } 9259 }; 9260 struct mlx5_flow_tbl_tunnel_prm tt_prm = { 9261 .tunnel = tunnel, 9262 .group_id = group_id, 9263 .external = external, 9264 }; 9265 struct mlx5_flow_cb_ctx ctx = { 9266 .dev = dev, 9267 .error = error, 9268 .data = &tt_prm, 9269 }; 9270 struct mlx5_hlist_entry *entry; 9271 struct mlx5_flow_tbl_data_entry *tbl_data; 9272 9273 entry = mlx5_hlist_register(priv->sh->flow_tbls, table_key.v64, &ctx); 9274 if (!entry) { 9275 rte_flow_error_set(error, ENOMEM, 9276 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 9277 "cannot get table"); 9278 return NULL; 9279 } 9280 DRV_LOG(DEBUG, "Table_id %u tunnel %u group %u registered.", 9281 table_id, tunnel ? tunnel->tunnel_id : 0, group_id); 9282 tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry); 9283 return &tbl_data->tbl; 9284 } 9285 9286 void 9287 flow_dv_tbl_remove_cb(struct mlx5_hlist *list, 9288 struct mlx5_hlist_entry *entry) 9289 { 9290 struct mlx5_dev_ctx_shared *sh = list->ctx; 9291 struct mlx5_flow_tbl_data_entry *tbl_data = 9292 container_of(entry, struct mlx5_flow_tbl_data_entry, entry); 9293 9294 MLX5_ASSERT(entry && sh); 9295 if (tbl_data->jump.action) 9296 mlx5_flow_os_destroy_flow_action(tbl_data->jump.action); 9297 if (tbl_data->tbl.obj) 9298 mlx5_flow_os_destroy_flow_tbl(tbl_data->tbl.obj); 9299 if (tbl_data->tunnel_offload && tbl_data->external) { 9300 struct mlx5_hlist_entry *he; 9301 struct mlx5_hlist *tunnel_grp_hash; 9302 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub; 9303 union tunnel_tbl_key tunnel_key = { 9304 .tunnel_id = tbl_data->tunnel ? 9305 tbl_data->tunnel->tunnel_id : 0, 9306 .group = tbl_data->group_id 9307 }; 9308 uint32_t table_id = tbl_data->table_id; 9309 9310 tunnel_grp_hash = tbl_data->tunnel ? 9311 tbl_data->tunnel->groups : 9312 thub->groups; 9313 he = mlx5_hlist_lookup(tunnel_grp_hash, tunnel_key.val, NULL); 9314 if (he) 9315 mlx5_hlist_unregister(tunnel_grp_hash, he); 9316 DRV_LOG(DEBUG, 9317 "Table_id %u tunnel %u group %u released.", 9318 table_id, 9319 tbl_data->tunnel ? 9320 tbl_data->tunnel->tunnel_id : 0, 9321 tbl_data->group_id); 9322 } 9323 mlx5_cache_list_destroy(&tbl_data->matchers); 9324 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_JUMP], tbl_data->idx); 9325 } 9326 9327 /** 9328 * Release a flow table. 9329 * 9330 * @param[in] sh 9331 * Pointer to device shared structure. 9332 * @param[in] tbl 9333 * Table resource to be released. 9334 * 9335 * @return 9336 * Returns 0 if table was released, else return 1; 9337 */ 9338 static int 9339 flow_dv_tbl_resource_release(struct mlx5_dev_ctx_shared *sh, 9340 struct mlx5_flow_tbl_resource *tbl) 9341 { 9342 struct mlx5_flow_tbl_data_entry *tbl_data = 9343 container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl); 9344 9345 if (!tbl) 9346 return 0; 9347 return mlx5_hlist_unregister(sh->flow_tbls, &tbl_data->entry); 9348 } 9349 9350 int 9351 flow_dv_matcher_match_cb(struct mlx5_cache_list *list __rte_unused, 9352 struct mlx5_cache_entry *entry, void *cb_ctx) 9353 { 9354 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 9355 struct mlx5_flow_dv_matcher *ref = ctx->data; 9356 struct mlx5_flow_dv_matcher *cur = container_of(entry, typeof(*cur), 9357 entry); 9358 9359 return cur->crc != ref->crc || 9360 cur->priority != ref->priority || 9361 memcmp((const void *)cur->mask.buf, 9362 (const void *)ref->mask.buf, ref->mask.size); 9363 } 9364 9365 struct mlx5_cache_entry * 9366 flow_dv_matcher_create_cb(struct mlx5_cache_list *list, 9367 struct mlx5_cache_entry *entry __rte_unused, 9368 void *cb_ctx) 9369 { 9370 struct mlx5_dev_ctx_shared *sh = list->ctx; 9371 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 9372 struct mlx5_flow_dv_matcher *ref = ctx->data; 9373 struct mlx5_flow_dv_matcher *cache; 9374 struct mlx5dv_flow_matcher_attr dv_attr = { 9375 .type = IBV_FLOW_ATTR_NORMAL, 9376 .match_mask = (void *)&ref->mask, 9377 }; 9378 struct mlx5_flow_tbl_data_entry *tbl = container_of(ref->tbl, 9379 typeof(*tbl), tbl); 9380 int ret; 9381 9382 cache = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*cache), 0, SOCKET_ID_ANY); 9383 if (!cache) { 9384 rte_flow_error_set(ctx->error, ENOMEM, 9385 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 9386 "cannot create matcher"); 9387 return NULL; 9388 } 9389 *cache = *ref; 9390 dv_attr.match_criteria_enable = 9391 flow_dv_matcher_enable(cache->mask.buf); 9392 dv_attr.priority = ref->priority; 9393 if (tbl->is_egress) 9394 dv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS; 9395 ret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, tbl->tbl.obj, 9396 &cache->matcher_object); 9397 if (ret) { 9398 mlx5_free(cache); 9399 rte_flow_error_set(ctx->error, ENOMEM, 9400 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 9401 "cannot create matcher"); 9402 return NULL; 9403 } 9404 return &cache->entry; 9405 } 9406 9407 /** 9408 * Register the flow matcher. 9409 * 9410 * @param[in, out] dev 9411 * Pointer to rte_eth_dev structure. 9412 * @param[in, out] matcher 9413 * Pointer to flow matcher. 9414 * @param[in, out] key 9415 * Pointer to flow table key. 9416 * @parm[in, out] dev_flow 9417 * Pointer to the dev_flow. 9418 * @param[out] error 9419 * pointer to error structure. 9420 * 9421 * @return 9422 * 0 on success otherwise -errno and errno is set. 9423 */ 9424 static int 9425 flow_dv_matcher_register(struct rte_eth_dev *dev, 9426 struct mlx5_flow_dv_matcher *ref, 9427 union mlx5_flow_tbl_key *key, 9428 struct mlx5_flow *dev_flow, 9429 const struct mlx5_flow_tunnel *tunnel, 9430 uint32_t group_id, 9431 struct rte_flow_error *error) 9432 { 9433 struct mlx5_cache_entry *entry; 9434 struct mlx5_flow_dv_matcher *cache; 9435 struct mlx5_flow_tbl_resource *tbl; 9436 struct mlx5_flow_tbl_data_entry *tbl_data; 9437 struct mlx5_flow_cb_ctx ctx = { 9438 .error = error, 9439 .data = ref, 9440 }; 9441 9442 /** 9443 * tunnel offload API requires this registration for cases when 9444 * tunnel match rule was inserted before tunnel set rule. 9445 */ 9446 tbl = flow_dv_tbl_resource_get(dev, key->table_id, 9447 key->direction, key->domain, 9448 dev_flow->external, tunnel, 9449 group_id, 0, error); 9450 if (!tbl) 9451 return -rte_errno; /* No need to refill the error info */ 9452 tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl); 9453 ref->tbl = tbl; 9454 entry = mlx5_cache_register(&tbl_data->matchers, &ctx); 9455 if (!entry) { 9456 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl); 9457 return rte_flow_error_set(error, ENOMEM, 9458 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 9459 "cannot allocate ref memory"); 9460 } 9461 cache = container_of(entry, typeof(*cache), entry); 9462 dev_flow->handle->dvh.matcher = cache; 9463 return 0; 9464 } 9465 9466 struct mlx5_hlist_entry * 9467 flow_dv_tag_create_cb(struct mlx5_hlist *list, uint64_t key, void *ctx) 9468 { 9469 struct mlx5_dev_ctx_shared *sh = list->ctx; 9470 struct rte_flow_error *error = ctx; 9471 struct mlx5_flow_dv_tag_resource *entry; 9472 uint32_t idx = 0; 9473 int ret; 9474 9475 entry = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG], &idx); 9476 if (!entry) { 9477 rte_flow_error_set(error, ENOMEM, 9478 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 9479 "cannot allocate resource memory"); 9480 return NULL; 9481 } 9482 entry->idx = idx; 9483 entry->tag_id = key; 9484 ret = mlx5_flow_os_create_flow_action_tag(key, 9485 &entry->action); 9486 if (ret) { 9487 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], idx); 9488 rte_flow_error_set(error, ENOMEM, 9489 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9490 NULL, "cannot create action"); 9491 return NULL; 9492 } 9493 return &entry->entry; 9494 } 9495 9496 int 9497 flow_dv_tag_match_cb(struct mlx5_hlist *list __rte_unused, 9498 struct mlx5_hlist_entry *entry, uint64_t key, 9499 void *cb_ctx __rte_unused) 9500 { 9501 struct mlx5_flow_dv_tag_resource *tag = 9502 container_of(entry, struct mlx5_flow_dv_tag_resource, entry); 9503 9504 return key != tag->tag_id; 9505 } 9506 9507 /** 9508 * Find existing tag resource or create and register a new one. 9509 * 9510 * @param dev[in, out] 9511 * Pointer to rte_eth_dev structure. 9512 * @param[in, out] tag_be24 9513 * Tag value in big endian then R-shift 8. 9514 * @parm[in, out] dev_flow 9515 * Pointer to the dev_flow. 9516 * @param[out] error 9517 * pointer to error structure. 9518 * 9519 * @return 9520 * 0 on success otherwise -errno and errno is set. 9521 */ 9522 static int 9523 flow_dv_tag_resource_register 9524 (struct rte_eth_dev *dev, 9525 uint32_t tag_be24, 9526 struct mlx5_flow *dev_flow, 9527 struct rte_flow_error *error) 9528 { 9529 struct mlx5_priv *priv = dev->data->dev_private; 9530 struct mlx5_flow_dv_tag_resource *cache_resource; 9531 struct mlx5_hlist_entry *entry; 9532 9533 entry = mlx5_hlist_register(priv->sh->tag_table, tag_be24, error); 9534 if (entry) { 9535 cache_resource = container_of 9536 (entry, struct mlx5_flow_dv_tag_resource, entry); 9537 dev_flow->handle->dvh.rix_tag = cache_resource->idx; 9538 dev_flow->dv.tag_resource = cache_resource; 9539 return 0; 9540 } 9541 return -rte_errno; 9542 } 9543 9544 void 9545 flow_dv_tag_remove_cb(struct mlx5_hlist *list, 9546 struct mlx5_hlist_entry *entry) 9547 { 9548 struct mlx5_dev_ctx_shared *sh = list->ctx; 9549 struct mlx5_flow_dv_tag_resource *tag = 9550 container_of(entry, struct mlx5_flow_dv_tag_resource, entry); 9551 9552 MLX5_ASSERT(tag && sh && tag->action); 9553 claim_zero(mlx5_flow_os_destroy_flow_action(tag->action)); 9554 DRV_LOG(DEBUG, "Tag %p: removed.", (void *)tag); 9555 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TAG], tag->idx); 9556 } 9557 9558 /** 9559 * Release the tag. 9560 * 9561 * @param dev 9562 * Pointer to Ethernet device. 9563 * @param tag_idx 9564 * Tag index. 9565 * 9566 * @return 9567 * 1 while a reference on it exists, 0 when freed. 9568 */ 9569 static int 9570 flow_dv_tag_release(struct rte_eth_dev *dev, 9571 uint32_t tag_idx) 9572 { 9573 struct mlx5_priv *priv = dev->data->dev_private; 9574 struct mlx5_flow_dv_tag_resource *tag; 9575 9576 tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx); 9577 if (!tag) 9578 return 0; 9579 DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--", 9580 dev->data->port_id, (void *)tag, tag->entry.ref_cnt); 9581 return mlx5_hlist_unregister(priv->sh->tag_table, &tag->entry); 9582 } 9583 9584 /** 9585 * Translate port ID action to vport. 9586 * 9587 * @param[in] dev 9588 * Pointer to rte_eth_dev structure. 9589 * @param[in] action 9590 * Pointer to the port ID action. 9591 * @param[out] dst_port_id 9592 * The target port ID. 9593 * @param[out] error 9594 * Pointer to the error structure. 9595 * 9596 * @return 9597 * 0 on success, a negative errno value otherwise and rte_errno is set. 9598 */ 9599 static int 9600 flow_dv_translate_action_port_id(struct rte_eth_dev *dev, 9601 const struct rte_flow_action *action, 9602 uint32_t *dst_port_id, 9603 struct rte_flow_error *error) 9604 { 9605 uint32_t port; 9606 struct mlx5_priv *priv; 9607 const struct rte_flow_action_port_id *conf = 9608 (const struct rte_flow_action_port_id *)action->conf; 9609 9610 port = conf->original ? dev->data->port_id : conf->id; 9611 priv = mlx5_port_to_eswitch_info(port, false); 9612 if (!priv) 9613 return rte_flow_error_set(error, -rte_errno, 9614 RTE_FLOW_ERROR_TYPE_ACTION, 9615 NULL, 9616 "No eswitch info was found for port"); 9617 #ifdef HAVE_MLX5DV_DR_DEVX_PORT 9618 /* 9619 * This parameter is transferred to 9620 * mlx5dv_dr_action_create_dest_ib_port(). 9621 */ 9622 *dst_port_id = priv->dev_port; 9623 #else 9624 /* 9625 * Legacy mode, no LAG configurations is supported. 9626 * This parameter is transferred to 9627 * mlx5dv_dr_action_create_dest_vport(). 9628 */ 9629 *dst_port_id = priv->vport_id; 9630 #endif 9631 return 0; 9632 } 9633 9634 /** 9635 * Create a counter with aging configuration. 9636 * 9637 * @param[in] dev 9638 * Pointer to rte_eth_dev structure. 9639 * @param[out] count 9640 * Pointer to the counter action configuration. 9641 * @param[in] age 9642 * Pointer to the aging action configuration. 9643 * 9644 * @return 9645 * Index to flow counter on success, 0 otherwise. 9646 */ 9647 static uint32_t 9648 flow_dv_translate_create_counter(struct rte_eth_dev *dev, 9649 struct mlx5_flow *dev_flow, 9650 const struct rte_flow_action_count *count, 9651 const struct rte_flow_action_age *age) 9652 { 9653 uint32_t counter; 9654 struct mlx5_age_param *age_param; 9655 9656 if (count && count->shared) 9657 counter = flow_dv_counter_get_shared(dev, count->id); 9658 else 9659 counter = flow_dv_counter_alloc(dev, !!age); 9660 if (!counter || age == NULL) 9661 return counter; 9662 age_param = flow_dv_counter_idx_get_age(dev, counter); 9663 age_param->context = age->context ? age->context : 9664 (void *)(uintptr_t)(dev_flow->flow_idx); 9665 age_param->timeout = age->timeout; 9666 age_param->port_id = dev->data->port_id; 9667 __atomic_store_n(&age_param->sec_since_last_hit, 0, __ATOMIC_RELAXED); 9668 __atomic_store_n(&age_param->state, AGE_CANDIDATE, __ATOMIC_RELAXED); 9669 return counter; 9670 } 9671 9672 /** 9673 * Add Tx queue matcher 9674 * 9675 * @param[in] dev 9676 * Pointer to the dev struct. 9677 * @param[in, out] matcher 9678 * Flow matcher. 9679 * @param[in, out] key 9680 * Flow matcher value. 9681 * @param[in] item 9682 * Flow pattern to translate. 9683 * @param[in] inner 9684 * Item is inner pattern. 9685 */ 9686 static void 9687 flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev, 9688 void *matcher, void *key, 9689 const struct rte_flow_item *item) 9690 { 9691 const struct mlx5_rte_flow_item_tx_queue *queue_m; 9692 const struct mlx5_rte_flow_item_tx_queue *queue_v; 9693 void *misc_m = 9694 MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters); 9695 void *misc_v = 9696 MLX5_ADDR_OF(fte_match_param, key, misc_parameters); 9697 struct mlx5_txq_ctrl *txq; 9698 uint32_t queue; 9699 9700 9701 queue_m = (const void *)item->mask; 9702 if (!queue_m) 9703 return; 9704 queue_v = (const void *)item->spec; 9705 if (!queue_v) 9706 return; 9707 txq = mlx5_txq_get(dev, queue_v->queue); 9708 if (!txq) 9709 return; 9710 queue = txq->obj->sq->id; 9711 MLX5_SET(fte_match_set_misc, misc_m, source_sqn, queue_m->queue); 9712 MLX5_SET(fte_match_set_misc, misc_v, source_sqn, 9713 queue & queue_m->queue); 9714 mlx5_txq_release(dev, queue_v->queue); 9715 } 9716 9717 /** 9718 * Set the hash fields according to the @p flow information. 9719 * 9720 * @param[in] dev_flow 9721 * Pointer to the mlx5_flow. 9722 * @param[in] rss_desc 9723 * Pointer to the mlx5_flow_rss_desc. 9724 */ 9725 static void 9726 flow_dv_hashfields_set(struct mlx5_flow *dev_flow, 9727 struct mlx5_flow_rss_desc *rss_desc) 9728 { 9729 uint64_t items = dev_flow->handle->layers; 9730 int rss_inner = 0; 9731 uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types); 9732 9733 dev_flow->hash_fields = 0; 9734 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 9735 if (rss_desc->level >= 2) { 9736 dev_flow->hash_fields |= IBV_RX_HASH_INNER; 9737 rss_inner = 1; 9738 } 9739 #endif 9740 if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) || 9741 (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) { 9742 if (rss_types & MLX5_IPV4_LAYER_TYPES) { 9743 if (rss_types & ETH_RSS_L3_SRC_ONLY) 9744 dev_flow->hash_fields |= IBV_RX_HASH_SRC_IPV4; 9745 else if (rss_types & ETH_RSS_L3_DST_ONLY) 9746 dev_flow->hash_fields |= IBV_RX_HASH_DST_IPV4; 9747 else 9748 dev_flow->hash_fields |= MLX5_IPV4_IBV_RX_HASH; 9749 } 9750 } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV6)) || 9751 (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV6))) { 9752 if (rss_types & MLX5_IPV6_LAYER_TYPES) { 9753 if (rss_types & ETH_RSS_L3_SRC_ONLY) 9754 dev_flow->hash_fields |= IBV_RX_HASH_SRC_IPV6; 9755 else if (rss_types & ETH_RSS_L3_DST_ONLY) 9756 dev_flow->hash_fields |= IBV_RX_HASH_DST_IPV6; 9757 else 9758 dev_flow->hash_fields |= MLX5_IPV6_IBV_RX_HASH; 9759 } 9760 } 9761 if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) || 9762 (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) { 9763 if (rss_types & ETH_RSS_UDP) { 9764 if (rss_types & ETH_RSS_L4_SRC_ONLY) 9765 dev_flow->hash_fields |= 9766 IBV_RX_HASH_SRC_PORT_UDP; 9767 else if (rss_types & ETH_RSS_L4_DST_ONLY) 9768 dev_flow->hash_fields |= 9769 IBV_RX_HASH_DST_PORT_UDP; 9770 else 9771 dev_flow->hash_fields |= MLX5_UDP_IBV_RX_HASH; 9772 } 9773 } else if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_TCP)) || 9774 (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_TCP))) { 9775 if (rss_types & ETH_RSS_TCP) { 9776 if (rss_types & ETH_RSS_L4_SRC_ONLY) 9777 dev_flow->hash_fields |= 9778 IBV_RX_HASH_SRC_PORT_TCP; 9779 else if (rss_types & ETH_RSS_L4_DST_ONLY) 9780 dev_flow->hash_fields |= 9781 IBV_RX_HASH_DST_PORT_TCP; 9782 else 9783 dev_flow->hash_fields |= MLX5_TCP_IBV_RX_HASH; 9784 } 9785 } 9786 } 9787 9788 /** 9789 * Prepare an Rx Hash queue. 9790 * 9791 * @param dev 9792 * Pointer to Ethernet device. 9793 * @param[in] dev_flow 9794 * Pointer to the mlx5_flow. 9795 * @param[in] rss_desc 9796 * Pointer to the mlx5_flow_rss_desc. 9797 * @param[out] hrxq_idx 9798 * Hash Rx queue index. 9799 * 9800 * @return 9801 * The Verbs/DevX object initialised, NULL otherwise and rte_errno is set. 9802 */ 9803 static struct mlx5_hrxq * 9804 flow_dv_hrxq_prepare(struct rte_eth_dev *dev, 9805 struct mlx5_flow *dev_flow, 9806 struct mlx5_flow_rss_desc *rss_desc, 9807 uint32_t *hrxq_idx) 9808 { 9809 struct mlx5_priv *priv = dev->data->dev_private; 9810 struct mlx5_flow_handle *dh = dev_flow->handle; 9811 struct mlx5_hrxq *hrxq; 9812 9813 MLX5_ASSERT(rss_desc->queue_num); 9814 rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN; 9815 rss_desc->hash_fields = dev_flow->hash_fields; 9816 rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL); 9817 rss_desc->shared_rss = 0; 9818 *hrxq_idx = mlx5_hrxq_get(dev, rss_desc); 9819 if (!*hrxq_idx) 9820 return NULL; 9821 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], 9822 *hrxq_idx); 9823 return hrxq; 9824 } 9825 9826 /** 9827 * Release sample sub action resource. 9828 * 9829 * @param[in, out] dev 9830 * Pointer to rte_eth_dev structure. 9831 * @param[in] act_res 9832 * Pointer to sample sub action resource. 9833 */ 9834 static void 9835 flow_dv_sample_sub_actions_release(struct rte_eth_dev *dev, 9836 struct mlx5_flow_sub_actions_idx *act_res) 9837 { 9838 if (act_res->rix_hrxq) { 9839 mlx5_hrxq_release(dev, act_res->rix_hrxq); 9840 act_res->rix_hrxq = 0; 9841 } 9842 if (act_res->rix_encap_decap) { 9843 flow_dv_encap_decap_resource_release(dev, 9844 act_res->rix_encap_decap); 9845 act_res->rix_encap_decap = 0; 9846 } 9847 if (act_res->rix_port_id_action) { 9848 flow_dv_port_id_action_resource_release(dev, 9849 act_res->rix_port_id_action); 9850 act_res->rix_port_id_action = 0; 9851 } 9852 if (act_res->rix_tag) { 9853 flow_dv_tag_release(dev, act_res->rix_tag); 9854 act_res->rix_tag = 0; 9855 } 9856 if (act_res->rix_jump) { 9857 flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump); 9858 act_res->rix_jump = 0; 9859 } 9860 } 9861 9862 int 9863 flow_dv_sample_match_cb(struct mlx5_cache_list *list __rte_unused, 9864 struct mlx5_cache_entry *entry, void *cb_ctx) 9865 { 9866 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 9867 struct rte_eth_dev *dev = ctx->dev; 9868 struct mlx5_flow_dv_sample_resource *resource = ctx->data; 9869 struct mlx5_flow_dv_sample_resource *cache_resource = 9870 container_of(entry, typeof(*cache_resource), entry); 9871 9872 if (resource->ratio == cache_resource->ratio && 9873 resource->ft_type == cache_resource->ft_type && 9874 resource->ft_id == cache_resource->ft_id && 9875 resource->set_action == cache_resource->set_action && 9876 !memcmp((void *)&resource->sample_act, 9877 (void *)&cache_resource->sample_act, 9878 sizeof(struct mlx5_flow_sub_actions_list))) { 9879 /* 9880 * Existing sample action should release the prepared 9881 * sub-actions reference counter. 9882 */ 9883 flow_dv_sample_sub_actions_release(dev, 9884 &resource->sample_idx); 9885 return 0; 9886 } 9887 return 1; 9888 } 9889 9890 struct mlx5_cache_entry * 9891 flow_dv_sample_create_cb(struct mlx5_cache_list *list __rte_unused, 9892 struct mlx5_cache_entry *entry __rte_unused, 9893 void *cb_ctx) 9894 { 9895 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 9896 struct rte_eth_dev *dev = ctx->dev; 9897 struct mlx5_flow_dv_sample_resource *resource = ctx->data; 9898 void **sample_dv_actions = resource->sub_actions; 9899 struct mlx5_flow_dv_sample_resource *cache_resource; 9900 struct mlx5dv_dr_flow_sampler_attr sampler_attr; 9901 struct mlx5_priv *priv = dev->data->dev_private; 9902 struct mlx5_dev_ctx_shared *sh = priv->sh; 9903 struct mlx5_flow_tbl_resource *tbl; 9904 uint32_t idx = 0; 9905 const uint32_t next_ft_step = 1; 9906 uint32_t next_ft_id = resource->ft_id + next_ft_step; 9907 uint8_t is_egress = 0; 9908 uint8_t is_transfer = 0; 9909 struct rte_flow_error *error = ctx->error; 9910 9911 /* Register new sample resource. */ 9912 cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE], &idx); 9913 if (!cache_resource) { 9914 rte_flow_error_set(error, ENOMEM, 9915 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9916 NULL, 9917 "cannot allocate resource memory"); 9918 return NULL; 9919 } 9920 *cache_resource = *resource; 9921 /* Create normal path table level */ 9922 if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) 9923 is_transfer = 1; 9924 else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_TX) 9925 is_egress = 1; 9926 tbl = flow_dv_tbl_resource_get(dev, next_ft_id, 9927 is_egress, is_transfer, 9928 true, NULL, 0, 0, error); 9929 if (!tbl) { 9930 rte_flow_error_set(error, ENOMEM, 9931 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9932 NULL, 9933 "fail to create normal path table " 9934 "for sample"); 9935 goto error; 9936 } 9937 cache_resource->normal_path_tbl = tbl; 9938 if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) { 9939 if (!sh->default_miss_action) { 9940 rte_flow_error_set(error, ENOMEM, 9941 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9942 NULL, 9943 "default miss action was not " 9944 "created"); 9945 goto error; 9946 } 9947 sample_dv_actions[resource->sample_act.actions_num++] = 9948 sh->default_miss_action; 9949 } 9950 /* Create a DR sample action */ 9951 sampler_attr.sample_ratio = cache_resource->ratio; 9952 sampler_attr.default_next_table = tbl->obj; 9953 sampler_attr.num_sample_actions = resource->sample_act.actions_num; 9954 sampler_attr.sample_actions = (struct mlx5dv_dr_action **) 9955 &sample_dv_actions[0]; 9956 sampler_attr.action = cache_resource->set_action; 9957 if (mlx5_os_flow_dr_create_flow_action_sampler 9958 (&sampler_attr, &cache_resource->verbs_action)) { 9959 rte_flow_error_set(error, ENOMEM, 9960 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9961 NULL, "cannot create sample action"); 9962 goto error; 9963 } 9964 cache_resource->idx = idx; 9965 cache_resource->dev = dev; 9966 return &cache_resource->entry; 9967 error: 9968 if (cache_resource->ft_type != MLX5DV_FLOW_TABLE_TYPE_FDB) 9969 flow_dv_sample_sub_actions_release(dev, 9970 &cache_resource->sample_idx); 9971 if (cache_resource->normal_path_tbl) 9972 flow_dv_tbl_resource_release(MLX5_SH(dev), 9973 cache_resource->normal_path_tbl); 9974 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE], idx); 9975 return NULL; 9976 9977 } 9978 9979 /** 9980 * Find existing sample resource or create and register a new one. 9981 * 9982 * @param[in, out] dev 9983 * Pointer to rte_eth_dev structure. 9984 * @param[in] resource 9985 * Pointer to sample resource. 9986 * @parm[in, out] dev_flow 9987 * Pointer to the dev_flow. 9988 * @param[out] error 9989 * pointer to error structure. 9990 * 9991 * @return 9992 * 0 on success otherwise -errno and errno is set. 9993 */ 9994 static int 9995 flow_dv_sample_resource_register(struct rte_eth_dev *dev, 9996 struct mlx5_flow_dv_sample_resource *resource, 9997 struct mlx5_flow *dev_flow, 9998 struct rte_flow_error *error) 9999 { 10000 struct mlx5_flow_dv_sample_resource *cache_resource; 10001 struct mlx5_cache_entry *entry; 10002 struct mlx5_priv *priv = dev->data->dev_private; 10003 struct mlx5_flow_cb_ctx ctx = { 10004 .dev = dev, 10005 .error = error, 10006 .data = resource, 10007 }; 10008 10009 entry = mlx5_cache_register(&priv->sh->sample_action_list, &ctx); 10010 if (!entry) 10011 return -rte_errno; 10012 cache_resource = container_of(entry, typeof(*cache_resource), entry); 10013 dev_flow->handle->dvh.rix_sample = cache_resource->idx; 10014 dev_flow->dv.sample_res = cache_resource; 10015 return 0; 10016 } 10017 10018 int 10019 flow_dv_dest_array_match_cb(struct mlx5_cache_list *list __rte_unused, 10020 struct mlx5_cache_entry *entry, void *cb_ctx) 10021 { 10022 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 10023 struct mlx5_flow_dv_dest_array_resource *resource = ctx->data; 10024 struct rte_eth_dev *dev = ctx->dev; 10025 struct mlx5_flow_dv_dest_array_resource *cache_resource = 10026 container_of(entry, typeof(*cache_resource), entry); 10027 uint32_t idx = 0; 10028 10029 if (resource->num_of_dest == cache_resource->num_of_dest && 10030 resource->ft_type == cache_resource->ft_type && 10031 !memcmp((void *)cache_resource->sample_act, 10032 (void *)resource->sample_act, 10033 (resource->num_of_dest * 10034 sizeof(struct mlx5_flow_sub_actions_list)))) { 10035 /* 10036 * Existing sample action should release the prepared 10037 * sub-actions reference counter. 10038 */ 10039 for (idx = 0; idx < resource->num_of_dest; idx++) 10040 flow_dv_sample_sub_actions_release(dev, 10041 &resource->sample_idx[idx]); 10042 return 0; 10043 } 10044 return 1; 10045 } 10046 10047 struct mlx5_cache_entry * 10048 flow_dv_dest_array_create_cb(struct mlx5_cache_list *list __rte_unused, 10049 struct mlx5_cache_entry *entry __rte_unused, 10050 void *cb_ctx) 10051 { 10052 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 10053 struct rte_eth_dev *dev = ctx->dev; 10054 struct mlx5_flow_dv_dest_array_resource *cache_resource; 10055 struct mlx5_flow_dv_dest_array_resource *resource = ctx->data; 10056 struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 }; 10057 struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM]; 10058 struct mlx5_priv *priv = dev->data->dev_private; 10059 struct mlx5_dev_ctx_shared *sh = priv->sh; 10060 struct mlx5_flow_sub_actions_list *sample_act; 10061 struct mlx5dv_dr_domain *domain; 10062 uint32_t idx = 0, res_idx = 0; 10063 struct rte_flow_error *error = ctx->error; 10064 uint64_t action_flags; 10065 int ret; 10066 10067 /* Register new destination array resource. */ 10068 cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY], 10069 &res_idx); 10070 if (!cache_resource) { 10071 rte_flow_error_set(error, ENOMEM, 10072 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 10073 NULL, 10074 "cannot allocate resource memory"); 10075 return NULL; 10076 } 10077 *cache_resource = *resource; 10078 if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) 10079 domain = sh->fdb_domain; 10080 else if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_NIC_RX) 10081 domain = sh->rx_domain; 10082 else 10083 domain = sh->tx_domain; 10084 for (idx = 0; idx < resource->num_of_dest; idx++) { 10085 dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *) 10086 mlx5_malloc(MLX5_MEM_ZERO, 10087 sizeof(struct mlx5dv_dr_action_dest_attr), 10088 0, SOCKET_ID_ANY); 10089 if (!dest_attr[idx]) { 10090 rte_flow_error_set(error, ENOMEM, 10091 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 10092 NULL, 10093 "cannot allocate resource memory"); 10094 goto error; 10095 } 10096 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST; 10097 sample_act = &resource->sample_act[idx]; 10098 action_flags = sample_act->action_flags; 10099 switch (action_flags) { 10100 case MLX5_FLOW_ACTION_QUEUE: 10101 dest_attr[idx]->dest = sample_act->dr_queue_action; 10102 break; 10103 case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP): 10104 dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT; 10105 dest_attr[idx]->dest_reformat = &dest_reformat[idx]; 10106 dest_attr[idx]->dest_reformat->reformat = 10107 sample_act->dr_encap_action; 10108 dest_attr[idx]->dest_reformat->dest = 10109 sample_act->dr_port_id_action; 10110 break; 10111 case MLX5_FLOW_ACTION_PORT_ID: 10112 dest_attr[idx]->dest = sample_act->dr_port_id_action; 10113 break; 10114 case MLX5_FLOW_ACTION_JUMP: 10115 dest_attr[idx]->dest = sample_act->dr_jump_action; 10116 break; 10117 default: 10118 rte_flow_error_set(error, EINVAL, 10119 RTE_FLOW_ERROR_TYPE_ACTION, 10120 NULL, 10121 "unsupported actions type"); 10122 goto error; 10123 } 10124 } 10125 /* create a dest array actioin */ 10126 ret = mlx5_os_flow_dr_create_flow_action_dest_array 10127 (domain, 10128 cache_resource->num_of_dest, 10129 dest_attr, 10130 &cache_resource->action); 10131 if (ret) { 10132 rte_flow_error_set(error, ENOMEM, 10133 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 10134 NULL, 10135 "cannot create destination array action"); 10136 goto error; 10137 } 10138 cache_resource->idx = res_idx; 10139 cache_resource->dev = dev; 10140 for (idx = 0; idx < resource->num_of_dest; idx++) 10141 mlx5_free(dest_attr[idx]); 10142 return &cache_resource->entry; 10143 error: 10144 for (idx = 0; idx < resource->num_of_dest; idx++) { 10145 struct mlx5_flow_sub_actions_idx *act_res = 10146 &cache_resource->sample_idx[idx]; 10147 if (act_res->rix_hrxq && 10148 !mlx5_hrxq_release(dev, 10149 act_res->rix_hrxq)) 10150 act_res->rix_hrxq = 0; 10151 if (act_res->rix_encap_decap && 10152 !flow_dv_encap_decap_resource_release(dev, 10153 act_res->rix_encap_decap)) 10154 act_res->rix_encap_decap = 0; 10155 if (act_res->rix_port_id_action && 10156 !flow_dv_port_id_action_resource_release(dev, 10157 act_res->rix_port_id_action)) 10158 act_res->rix_port_id_action = 0; 10159 if (act_res->rix_jump && 10160 !flow_dv_jump_tbl_resource_release(dev, 10161 act_res->rix_jump)) 10162 act_res->rix_jump = 0; 10163 if (dest_attr[idx]) 10164 mlx5_free(dest_attr[idx]); 10165 } 10166 10167 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY], res_idx); 10168 return NULL; 10169 } 10170 10171 /** 10172 * Find existing destination array resource or create and register a new one. 10173 * 10174 * @param[in, out] dev 10175 * Pointer to rte_eth_dev structure. 10176 * @param[in] resource 10177 * Pointer to destination array resource. 10178 * @parm[in, out] dev_flow 10179 * Pointer to the dev_flow. 10180 * @param[out] error 10181 * pointer to error structure. 10182 * 10183 * @return 10184 * 0 on success otherwise -errno and errno is set. 10185 */ 10186 static int 10187 flow_dv_dest_array_resource_register(struct rte_eth_dev *dev, 10188 struct mlx5_flow_dv_dest_array_resource *resource, 10189 struct mlx5_flow *dev_flow, 10190 struct rte_flow_error *error) 10191 { 10192 struct mlx5_flow_dv_dest_array_resource *cache_resource; 10193 struct mlx5_priv *priv = dev->data->dev_private; 10194 struct mlx5_cache_entry *entry; 10195 struct mlx5_flow_cb_ctx ctx = { 10196 .dev = dev, 10197 .error = error, 10198 .data = resource, 10199 }; 10200 10201 entry = mlx5_cache_register(&priv->sh->dest_array_list, &ctx); 10202 if (!entry) 10203 return -rte_errno; 10204 cache_resource = container_of(entry, typeof(*cache_resource), entry); 10205 dev_flow->handle->dvh.rix_dest_array = cache_resource->idx; 10206 dev_flow->dv.dest_array_res = cache_resource; 10207 return 0; 10208 } 10209 10210 /** 10211 * Convert Sample action to DV specification. 10212 * 10213 * @param[in] dev 10214 * Pointer to rte_eth_dev structure. 10215 * @param[in] action 10216 * Pointer to sample action structure. 10217 * @param[in, out] dev_flow 10218 * Pointer to the mlx5_flow. 10219 * @param[in] attr 10220 * Pointer to the flow attributes. 10221 * @param[in, out] num_of_dest 10222 * Pointer to the num of destination. 10223 * @param[in, out] sample_actions 10224 * Pointer to sample actions list. 10225 * @param[in, out] res 10226 * Pointer to sample resource. 10227 * @param[out] error 10228 * Pointer to the error structure. 10229 * 10230 * @return 10231 * 0 on success, a negative errno value otherwise and rte_errno is set. 10232 */ 10233 static int 10234 flow_dv_translate_action_sample(struct rte_eth_dev *dev, 10235 const struct rte_flow_action_sample *action, 10236 struct mlx5_flow *dev_flow, 10237 const struct rte_flow_attr *attr, 10238 uint32_t *num_of_dest, 10239 void **sample_actions, 10240 struct mlx5_flow_dv_sample_resource *res, 10241 struct rte_flow_error *error) 10242 { 10243 struct mlx5_priv *priv = dev->data->dev_private; 10244 const struct rte_flow_action *sub_actions; 10245 struct mlx5_flow_sub_actions_list *sample_act; 10246 struct mlx5_flow_sub_actions_idx *sample_idx; 10247 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 10248 struct rte_flow *flow = dev_flow->flow; 10249 struct mlx5_flow_rss_desc *rss_desc; 10250 uint64_t action_flags = 0; 10251 10252 MLX5_ASSERT(wks); 10253 rss_desc = &wks->rss_desc; 10254 sample_act = &res->sample_act; 10255 sample_idx = &res->sample_idx; 10256 res->ratio = action->ratio; 10257 sub_actions = action->actions; 10258 for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) { 10259 int type = sub_actions->type; 10260 uint32_t pre_rix = 0; 10261 void *pre_r; 10262 switch (type) { 10263 case RTE_FLOW_ACTION_TYPE_QUEUE: 10264 { 10265 const struct rte_flow_action_queue *queue; 10266 struct mlx5_hrxq *hrxq; 10267 uint32_t hrxq_idx; 10268 10269 queue = sub_actions->conf; 10270 rss_desc->queue_num = 1; 10271 rss_desc->queue[0] = queue->index; 10272 hrxq = flow_dv_hrxq_prepare(dev, dev_flow, 10273 rss_desc, &hrxq_idx); 10274 if (!hrxq) 10275 return rte_flow_error_set 10276 (error, rte_errno, 10277 RTE_FLOW_ERROR_TYPE_ACTION, 10278 NULL, 10279 "cannot create fate queue"); 10280 sample_act->dr_queue_action = hrxq->action; 10281 sample_idx->rix_hrxq = hrxq_idx; 10282 sample_actions[sample_act->actions_num++] = 10283 hrxq->action; 10284 (*num_of_dest)++; 10285 action_flags |= MLX5_FLOW_ACTION_QUEUE; 10286 if (action_flags & MLX5_FLOW_ACTION_MARK) 10287 dev_flow->handle->rix_hrxq = hrxq_idx; 10288 dev_flow->handle->fate_action = 10289 MLX5_FLOW_FATE_QUEUE; 10290 break; 10291 } 10292 case RTE_FLOW_ACTION_TYPE_RSS: 10293 { 10294 struct mlx5_hrxq *hrxq; 10295 uint32_t hrxq_idx; 10296 const struct rte_flow_action_rss *rss; 10297 const uint8_t *rss_key; 10298 10299 rss = sub_actions->conf; 10300 memcpy(rss_desc->queue, rss->queue, 10301 rss->queue_num * sizeof(uint16_t)); 10302 rss_desc->queue_num = rss->queue_num; 10303 /* NULL RSS key indicates default RSS key. */ 10304 rss_key = !rss->key ? rss_hash_default_key : rss->key; 10305 memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN); 10306 /* 10307 * rss->level and rss.types should be set in advance 10308 * when expanding items for RSS. 10309 */ 10310 flow_dv_hashfields_set(dev_flow, rss_desc); 10311 hrxq = flow_dv_hrxq_prepare(dev, dev_flow, 10312 rss_desc, &hrxq_idx); 10313 if (!hrxq) 10314 return rte_flow_error_set 10315 (error, rte_errno, 10316 RTE_FLOW_ERROR_TYPE_ACTION, 10317 NULL, 10318 "cannot create fate queue"); 10319 sample_act->dr_queue_action = hrxq->action; 10320 sample_idx->rix_hrxq = hrxq_idx; 10321 sample_actions[sample_act->actions_num++] = 10322 hrxq->action; 10323 (*num_of_dest)++; 10324 action_flags |= MLX5_FLOW_ACTION_RSS; 10325 if (action_flags & MLX5_FLOW_ACTION_MARK) 10326 dev_flow->handle->rix_hrxq = hrxq_idx; 10327 dev_flow->handle->fate_action = 10328 MLX5_FLOW_FATE_QUEUE; 10329 break; 10330 } 10331 case RTE_FLOW_ACTION_TYPE_MARK: 10332 { 10333 uint32_t tag_be = mlx5_flow_mark_set 10334 (((const struct rte_flow_action_mark *) 10335 (sub_actions->conf))->id); 10336 10337 dev_flow->handle->mark = 1; 10338 pre_rix = dev_flow->handle->dvh.rix_tag; 10339 /* Save the mark resource before sample */ 10340 pre_r = dev_flow->dv.tag_resource; 10341 if (flow_dv_tag_resource_register(dev, tag_be, 10342 dev_flow, error)) 10343 return -rte_errno; 10344 MLX5_ASSERT(dev_flow->dv.tag_resource); 10345 sample_act->dr_tag_action = 10346 dev_flow->dv.tag_resource->action; 10347 sample_idx->rix_tag = 10348 dev_flow->handle->dvh.rix_tag; 10349 sample_actions[sample_act->actions_num++] = 10350 sample_act->dr_tag_action; 10351 /* Recover the mark resource after sample */ 10352 dev_flow->dv.tag_resource = pre_r; 10353 dev_flow->handle->dvh.rix_tag = pre_rix; 10354 action_flags |= MLX5_FLOW_ACTION_MARK; 10355 break; 10356 } 10357 case RTE_FLOW_ACTION_TYPE_COUNT: 10358 { 10359 if (!flow->counter) { 10360 flow->counter = 10361 flow_dv_translate_create_counter(dev, 10362 dev_flow, sub_actions->conf, 10363 0); 10364 if (!flow->counter) 10365 return rte_flow_error_set 10366 (error, rte_errno, 10367 RTE_FLOW_ERROR_TYPE_ACTION, 10368 NULL, 10369 "cannot create counter" 10370 " object."); 10371 } 10372 sample_act->dr_cnt_action = 10373 (flow_dv_counter_get_by_idx(dev, 10374 flow->counter, NULL))->action; 10375 sample_actions[sample_act->actions_num++] = 10376 sample_act->dr_cnt_action; 10377 action_flags |= MLX5_FLOW_ACTION_COUNT; 10378 break; 10379 } 10380 case RTE_FLOW_ACTION_TYPE_PORT_ID: 10381 { 10382 struct mlx5_flow_dv_port_id_action_resource 10383 port_id_resource; 10384 uint32_t port_id = 0; 10385 10386 memset(&port_id_resource, 0, sizeof(port_id_resource)); 10387 /* Save the port id resource before sample */ 10388 pre_rix = dev_flow->handle->rix_port_id_action; 10389 pre_r = dev_flow->dv.port_id_action; 10390 if (flow_dv_translate_action_port_id(dev, sub_actions, 10391 &port_id, error)) 10392 return -rte_errno; 10393 port_id_resource.port_id = port_id; 10394 if (flow_dv_port_id_action_resource_register 10395 (dev, &port_id_resource, dev_flow, error)) 10396 return -rte_errno; 10397 sample_act->dr_port_id_action = 10398 dev_flow->dv.port_id_action->action; 10399 sample_idx->rix_port_id_action = 10400 dev_flow->handle->rix_port_id_action; 10401 sample_actions[sample_act->actions_num++] = 10402 sample_act->dr_port_id_action; 10403 /* Recover the port id resource after sample */ 10404 dev_flow->dv.port_id_action = pre_r; 10405 dev_flow->handle->rix_port_id_action = pre_rix; 10406 (*num_of_dest)++; 10407 action_flags |= MLX5_FLOW_ACTION_PORT_ID; 10408 break; 10409 } 10410 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 10411 /* Save the encap resource before sample */ 10412 pre_rix = dev_flow->handle->dvh.rix_encap_decap; 10413 pre_r = dev_flow->dv.encap_decap; 10414 if (flow_dv_create_action_l2_encap(dev, sub_actions, 10415 dev_flow, 10416 attr->transfer, 10417 error)) 10418 return -rte_errno; 10419 sample_act->dr_encap_action = 10420 dev_flow->dv.encap_decap->action; 10421 sample_idx->rix_encap_decap = 10422 dev_flow->handle->dvh.rix_encap_decap; 10423 sample_actions[sample_act->actions_num++] = 10424 sample_act->dr_encap_action; 10425 /* Recover the encap resource after sample */ 10426 dev_flow->dv.encap_decap = pre_r; 10427 dev_flow->handle->dvh.rix_encap_decap = pre_rix; 10428 action_flags |= MLX5_FLOW_ACTION_ENCAP; 10429 break; 10430 default: 10431 return rte_flow_error_set(error, EINVAL, 10432 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 10433 NULL, 10434 "Not support for sampler action"); 10435 } 10436 } 10437 sample_act->action_flags = action_flags; 10438 res->ft_id = dev_flow->dv.group; 10439 if (attr->transfer) { 10440 union { 10441 uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)]; 10442 uint64_t set_action; 10443 } action_ctx = { .set_action = 0 }; 10444 10445 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 10446 MLX5_SET(set_action_in, action_ctx.action_in, action_type, 10447 MLX5_MODIFICATION_TYPE_SET); 10448 MLX5_SET(set_action_in, action_ctx.action_in, field, 10449 MLX5_MODI_META_REG_C_0); 10450 MLX5_SET(set_action_in, action_ctx.action_in, data, 10451 priv->vport_meta_tag); 10452 res->set_action = action_ctx.set_action; 10453 } else if (attr->ingress) { 10454 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 10455 } else { 10456 res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX; 10457 } 10458 return 0; 10459 } 10460 10461 /** 10462 * Convert Sample action to DV specification. 10463 * 10464 * @param[in] dev 10465 * Pointer to rte_eth_dev structure. 10466 * @param[in, out] dev_flow 10467 * Pointer to the mlx5_flow. 10468 * @param[in] num_of_dest 10469 * The num of destination. 10470 * @param[in, out] res 10471 * Pointer to sample resource. 10472 * @param[in, out] mdest_res 10473 * Pointer to destination array resource. 10474 * @param[in] sample_actions 10475 * Pointer to sample path actions list. 10476 * @param[in] action_flags 10477 * Holds the actions detected until now. 10478 * @param[out] error 10479 * Pointer to the error structure. 10480 * 10481 * @return 10482 * 0 on success, a negative errno value otherwise and rte_errno is set. 10483 */ 10484 static int 10485 flow_dv_create_action_sample(struct rte_eth_dev *dev, 10486 struct mlx5_flow *dev_flow, 10487 uint32_t num_of_dest, 10488 struct mlx5_flow_dv_sample_resource *res, 10489 struct mlx5_flow_dv_dest_array_resource *mdest_res, 10490 void **sample_actions, 10491 uint64_t action_flags, 10492 struct rte_flow_error *error) 10493 { 10494 /* update normal path action resource into last index of array */ 10495 uint32_t dest_index = MLX5_MAX_DEST_NUM - 1; 10496 struct mlx5_flow_sub_actions_list *sample_act = 10497 &mdest_res->sample_act[dest_index]; 10498 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 10499 struct mlx5_flow_rss_desc *rss_desc; 10500 uint32_t normal_idx = 0; 10501 struct mlx5_hrxq *hrxq; 10502 uint32_t hrxq_idx; 10503 10504 MLX5_ASSERT(wks); 10505 rss_desc = &wks->rss_desc; 10506 if (num_of_dest > 1) { 10507 if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) { 10508 /* Handle QP action for mirroring */ 10509 hrxq = flow_dv_hrxq_prepare(dev, dev_flow, 10510 rss_desc, &hrxq_idx); 10511 if (!hrxq) 10512 return rte_flow_error_set 10513 (error, rte_errno, 10514 RTE_FLOW_ERROR_TYPE_ACTION, 10515 NULL, 10516 "cannot create rx queue"); 10517 normal_idx++; 10518 mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx; 10519 sample_act->dr_queue_action = hrxq->action; 10520 if (action_flags & MLX5_FLOW_ACTION_MARK) 10521 dev_flow->handle->rix_hrxq = hrxq_idx; 10522 dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 10523 } 10524 if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) { 10525 normal_idx++; 10526 mdest_res->sample_idx[dest_index].rix_encap_decap = 10527 dev_flow->handle->dvh.rix_encap_decap; 10528 sample_act->dr_encap_action = 10529 dev_flow->dv.encap_decap->action; 10530 } 10531 if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) { 10532 normal_idx++; 10533 mdest_res->sample_idx[dest_index].rix_port_id_action = 10534 dev_flow->handle->rix_port_id_action; 10535 sample_act->dr_port_id_action = 10536 dev_flow->dv.port_id_action->action; 10537 } 10538 if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) { 10539 normal_idx++; 10540 mdest_res->sample_idx[dest_index].rix_jump = 10541 dev_flow->handle->rix_jump; 10542 sample_act->dr_jump_action = 10543 dev_flow->dv.jump->action; 10544 dev_flow->handle->rix_jump = 0; 10545 } 10546 sample_act->actions_num = normal_idx; 10547 /* update sample action resource into first index of array */ 10548 mdest_res->ft_type = res->ft_type; 10549 memcpy(&mdest_res->sample_idx[0], &res->sample_idx, 10550 sizeof(struct mlx5_flow_sub_actions_idx)); 10551 memcpy(&mdest_res->sample_act[0], &res->sample_act, 10552 sizeof(struct mlx5_flow_sub_actions_list)); 10553 mdest_res->num_of_dest = num_of_dest; 10554 if (flow_dv_dest_array_resource_register(dev, mdest_res, 10555 dev_flow, error)) 10556 return rte_flow_error_set(error, EINVAL, 10557 RTE_FLOW_ERROR_TYPE_ACTION, 10558 NULL, "can't create sample " 10559 "action"); 10560 } else { 10561 res->sub_actions = sample_actions; 10562 if (flow_dv_sample_resource_register(dev, res, dev_flow, error)) 10563 return rte_flow_error_set(error, EINVAL, 10564 RTE_FLOW_ERROR_TYPE_ACTION, 10565 NULL, 10566 "can't create sample action"); 10567 } 10568 return 0; 10569 } 10570 10571 /** 10572 * Remove an ASO age action from age actions list. 10573 * 10574 * @param[in] dev 10575 * Pointer to the Ethernet device structure. 10576 * @param[in] age 10577 * Pointer to the aso age action handler. 10578 */ 10579 static void 10580 flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev, 10581 struct mlx5_aso_age_action *age) 10582 { 10583 struct mlx5_age_info *age_info; 10584 struct mlx5_age_param *age_param = &age->age_params; 10585 struct mlx5_priv *priv = dev->data->dev_private; 10586 uint16_t expected = AGE_CANDIDATE; 10587 10588 age_info = GET_PORT_AGE_INFO(priv); 10589 if (!__atomic_compare_exchange_n(&age_param->state, &expected, 10590 AGE_FREE, false, __ATOMIC_RELAXED, 10591 __ATOMIC_RELAXED)) { 10592 /** 10593 * We need the lock even it is age timeout, 10594 * since age action may still in process. 10595 */ 10596 rte_spinlock_lock(&age_info->aged_sl); 10597 LIST_REMOVE(age, next); 10598 rte_spinlock_unlock(&age_info->aged_sl); 10599 __atomic_store_n(&age_param->state, AGE_FREE, __ATOMIC_RELAXED); 10600 } 10601 } 10602 10603 /** 10604 * Release an ASO age action. 10605 * 10606 * @param[in] dev 10607 * Pointer to the Ethernet device structure. 10608 * @param[in] age_idx 10609 * Index of ASO age action to release. 10610 * @param[in] flow 10611 * True if the release operation is during flow destroy operation. 10612 * False if the release operation is during action destroy operation. 10613 * 10614 * @return 10615 * 0 when age action was removed, otherwise the number of references. 10616 */ 10617 static int 10618 flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx) 10619 { 10620 struct mlx5_priv *priv = dev->data->dev_private; 10621 struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; 10622 struct mlx5_aso_age_action *age = flow_aso_age_get_by_idx(dev, age_idx); 10623 uint32_t ret = __atomic_sub_fetch(&age->refcnt, 1, __ATOMIC_RELAXED); 10624 10625 if (!ret) { 10626 flow_dv_aso_age_remove_from_age(dev, age); 10627 rte_spinlock_lock(&mng->free_sl); 10628 LIST_INSERT_HEAD(&mng->free, age, next); 10629 rte_spinlock_unlock(&mng->free_sl); 10630 } 10631 return ret; 10632 } 10633 10634 /** 10635 * Resize the ASO age pools array by MLX5_CNT_CONTAINER_RESIZE pools. 10636 * 10637 * @param[in] dev 10638 * Pointer to the Ethernet device structure. 10639 * 10640 * @return 10641 * 0 on success, otherwise negative errno value and rte_errno is set. 10642 */ 10643 static int 10644 flow_dv_aso_age_pools_resize(struct rte_eth_dev *dev) 10645 { 10646 struct mlx5_priv *priv = dev->data->dev_private; 10647 struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; 10648 void *old_pools = mng->pools; 10649 uint32_t resize = mng->n + MLX5_CNT_CONTAINER_RESIZE; 10650 uint32_t mem_size = sizeof(struct mlx5_aso_age_pool *) * resize; 10651 void *pools = mlx5_malloc(MLX5_MEM_ZERO, mem_size, 0, SOCKET_ID_ANY); 10652 10653 if (!pools) { 10654 rte_errno = ENOMEM; 10655 return -ENOMEM; 10656 } 10657 if (old_pools) { 10658 memcpy(pools, old_pools, 10659 mng->n * sizeof(struct mlx5_flow_counter_pool *)); 10660 mlx5_free(old_pools); 10661 } else { 10662 /* First ASO flow hit allocation - starting ASO data-path. */ 10663 int ret = mlx5_aso_queue_start(priv->sh); 10664 10665 if (ret) { 10666 mlx5_free(pools); 10667 return ret; 10668 } 10669 } 10670 mng->n = resize; 10671 mng->pools = pools; 10672 return 0; 10673 } 10674 10675 /** 10676 * Create and initialize a new ASO aging pool. 10677 * 10678 * @param[in] dev 10679 * Pointer to the Ethernet device structure. 10680 * @param[out] age_free 10681 * Where to put the pointer of a new age action. 10682 * 10683 * @return 10684 * The age actions pool pointer and @p age_free is set on success, 10685 * NULL otherwise and rte_errno is set. 10686 */ 10687 static struct mlx5_aso_age_pool * 10688 flow_dv_age_pool_create(struct rte_eth_dev *dev, 10689 struct mlx5_aso_age_action **age_free) 10690 { 10691 struct mlx5_priv *priv = dev->data->dev_private; 10692 struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; 10693 struct mlx5_aso_age_pool *pool = NULL; 10694 struct mlx5_devx_obj *obj = NULL; 10695 uint32_t i; 10696 10697 obj = mlx5_devx_cmd_create_flow_hit_aso_obj(priv->sh->ctx, 10698 priv->sh->pdn); 10699 if (!obj) { 10700 rte_errno = ENODATA; 10701 DRV_LOG(ERR, "Failed to create flow_hit_aso_obj using DevX."); 10702 return NULL; 10703 } 10704 pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY); 10705 if (!pool) { 10706 claim_zero(mlx5_devx_cmd_destroy(obj)); 10707 rte_errno = ENOMEM; 10708 return NULL; 10709 } 10710 pool->flow_hit_aso_obj = obj; 10711 pool->time_of_last_age_check = MLX5_CURR_TIME_SEC; 10712 rte_spinlock_lock(&mng->resize_sl); 10713 pool->index = mng->next; 10714 /* Resize pools array if there is no room for the new pool in it. */ 10715 if (pool->index == mng->n && flow_dv_aso_age_pools_resize(dev)) { 10716 claim_zero(mlx5_devx_cmd_destroy(obj)); 10717 mlx5_free(pool); 10718 rte_spinlock_unlock(&mng->resize_sl); 10719 return NULL; 10720 } 10721 mng->pools[pool->index] = pool; 10722 mng->next++; 10723 rte_spinlock_unlock(&mng->resize_sl); 10724 /* Assign the first action in the new pool, the rest go to free list. */ 10725 *age_free = &pool->actions[0]; 10726 for (i = 1; i < MLX5_ASO_AGE_ACTIONS_PER_POOL; i++) { 10727 pool->actions[i].offset = i; 10728 LIST_INSERT_HEAD(&mng->free, &pool->actions[i], next); 10729 } 10730 return pool; 10731 } 10732 10733 /** 10734 * Allocate a ASO aging bit. 10735 * 10736 * @param[in] dev 10737 * Pointer to the Ethernet device structure. 10738 * @param[out] error 10739 * Pointer to the error structure. 10740 * 10741 * @return 10742 * Index to ASO age action on success, 0 otherwise and rte_errno is set. 10743 */ 10744 static uint32_t 10745 flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error) 10746 { 10747 struct mlx5_priv *priv = dev->data->dev_private; 10748 const struct mlx5_aso_age_pool *pool; 10749 struct mlx5_aso_age_action *age_free = NULL; 10750 struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; 10751 10752 MLX5_ASSERT(mng); 10753 /* Try to get the next free age action bit. */ 10754 rte_spinlock_lock(&mng->free_sl); 10755 age_free = LIST_FIRST(&mng->free); 10756 if (age_free) { 10757 LIST_REMOVE(age_free, next); 10758 } else if (!flow_dv_age_pool_create(dev, &age_free)) { 10759 rte_spinlock_unlock(&mng->free_sl); 10760 rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION, 10761 NULL, "failed to create ASO age pool"); 10762 return 0; /* 0 is an error. */ 10763 } 10764 rte_spinlock_unlock(&mng->free_sl); 10765 pool = container_of 10766 ((const struct mlx5_aso_age_action (*)[MLX5_ASO_AGE_ACTIONS_PER_POOL]) 10767 (age_free - age_free->offset), const struct mlx5_aso_age_pool, 10768 actions); 10769 if (!age_free->dr_action) { 10770 int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0, 10771 error); 10772 10773 if (reg_c < 0) { 10774 rte_flow_error_set(error, rte_errno, 10775 RTE_FLOW_ERROR_TYPE_ACTION, 10776 NULL, "failed to get reg_c " 10777 "for ASO flow hit"); 10778 return 0; /* 0 is an error. */ 10779 } 10780 #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO 10781 age_free->dr_action = mlx5_glue->dv_create_flow_action_aso 10782 (priv->sh->rx_domain, 10783 pool->flow_hit_aso_obj->obj, age_free->offset, 10784 MLX5DV_DR_ACTION_FLAGS_ASO_FIRST_HIT_SET, 10785 (reg_c - REG_C_0)); 10786 #endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */ 10787 if (!age_free->dr_action) { 10788 rte_errno = errno; 10789 rte_spinlock_lock(&mng->free_sl); 10790 LIST_INSERT_HEAD(&mng->free, age_free, next); 10791 rte_spinlock_unlock(&mng->free_sl); 10792 rte_flow_error_set(error, rte_errno, 10793 RTE_FLOW_ERROR_TYPE_ACTION, 10794 NULL, "failed to create ASO " 10795 "flow hit action"); 10796 return 0; /* 0 is an error. */ 10797 } 10798 } 10799 __atomic_store_n(&age_free->refcnt, 1, __ATOMIC_RELAXED); 10800 return pool->index | ((age_free->offset + 1) << 16); 10801 } 10802 10803 /** 10804 * Create a age action using ASO mechanism. 10805 * 10806 * @param[in] dev 10807 * Pointer to rte_eth_dev structure. 10808 * @param[in] age 10809 * Pointer to the aging action configuration. 10810 * @param[out] error 10811 * Pointer to the error structure. 10812 * 10813 * @return 10814 * Index to flow counter on success, 0 otherwise. 10815 */ 10816 static uint32_t 10817 flow_dv_translate_create_aso_age(struct rte_eth_dev *dev, 10818 const struct rte_flow_action_age *age, 10819 struct rte_flow_error *error) 10820 { 10821 uint32_t age_idx = 0; 10822 struct mlx5_aso_age_action *aso_age; 10823 10824 age_idx = flow_dv_aso_age_alloc(dev, error); 10825 if (!age_idx) 10826 return 0; 10827 aso_age = flow_aso_age_get_by_idx(dev, age_idx); 10828 aso_age->age_params.context = age->context; 10829 aso_age->age_params.timeout = age->timeout; 10830 aso_age->age_params.port_id = dev->data->port_id; 10831 __atomic_store_n(&aso_age->age_params.sec_since_last_hit, 0, 10832 __ATOMIC_RELAXED); 10833 __atomic_store_n(&aso_age->age_params.state, AGE_CANDIDATE, 10834 __ATOMIC_RELAXED); 10835 return age_idx; 10836 } 10837 10838 /** 10839 * Fill the flow with DV spec, lock free 10840 * (mutex should be acquired by caller). 10841 * 10842 * @param[in] dev 10843 * Pointer to rte_eth_dev structure. 10844 * @param[in, out] dev_flow 10845 * Pointer to the sub flow. 10846 * @param[in] attr 10847 * Pointer to the flow attributes. 10848 * @param[in] items 10849 * Pointer to the list of items. 10850 * @param[in] actions 10851 * Pointer to the list of actions. 10852 * @param[out] error 10853 * Pointer to the error structure. 10854 * 10855 * @return 10856 * 0 on success, a negative errno value otherwise and rte_errno is set. 10857 */ 10858 static int 10859 flow_dv_translate(struct rte_eth_dev *dev, 10860 struct mlx5_flow *dev_flow, 10861 const struct rte_flow_attr *attr, 10862 const struct rte_flow_item items[], 10863 const struct rte_flow_action actions[], 10864 struct rte_flow_error *error) 10865 { 10866 struct mlx5_priv *priv = dev->data->dev_private; 10867 struct mlx5_dev_config *dev_conf = &priv->config; 10868 struct rte_flow *flow = dev_flow->flow; 10869 struct mlx5_flow_handle *handle = dev_flow->handle; 10870 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 10871 struct mlx5_flow_rss_desc *rss_desc; 10872 uint64_t item_flags = 0; 10873 uint64_t last_item = 0; 10874 uint64_t action_flags = 0; 10875 struct mlx5_flow_dv_matcher matcher = { 10876 .mask = { 10877 .size = sizeof(matcher.mask.buf) - 10878 MLX5_ST_SZ_BYTES(fte_match_set_misc4), 10879 }, 10880 }; 10881 int actions_n = 0; 10882 bool actions_end = false; 10883 union { 10884 struct mlx5_flow_dv_modify_hdr_resource res; 10885 uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) + 10886 sizeof(struct mlx5_modification_cmd) * 10887 (MLX5_MAX_MODIFY_NUM + 1)]; 10888 } mhdr_dummy; 10889 struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res; 10890 const struct rte_flow_action_count *count = NULL; 10891 const struct rte_flow_action_age *age = NULL; 10892 union flow_dv_attr flow_attr = { .attr = 0 }; 10893 uint32_t tag_be; 10894 union mlx5_flow_tbl_key tbl_key; 10895 uint32_t modify_action_position = UINT32_MAX; 10896 void *match_mask = matcher.mask.buf; 10897 void *match_value = dev_flow->dv.value.buf; 10898 uint8_t next_protocol = 0xff; 10899 struct rte_vlan_hdr vlan = { 0 }; 10900 struct mlx5_flow_dv_dest_array_resource mdest_res; 10901 struct mlx5_flow_dv_sample_resource sample_res; 10902 void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0}; 10903 const struct rte_flow_action_sample *sample = NULL; 10904 struct mlx5_flow_sub_actions_list *sample_act; 10905 uint32_t sample_act_pos = UINT32_MAX; 10906 uint32_t num_of_dest = 0; 10907 int tmp_actions_n = 0; 10908 uint32_t table; 10909 int ret = 0; 10910 const struct mlx5_flow_tunnel *tunnel; 10911 struct flow_grp_info grp_info = { 10912 .external = !!dev_flow->external, 10913 .transfer = !!attr->transfer, 10914 .fdb_def_rule = !!priv->fdb_def_rule, 10915 .skip_scale = dev_flow->skip_scale & 10916 (1 << MLX5_SCALE_FLOW_GROUP_BIT), 10917 }; 10918 10919 if (!wks) 10920 return rte_flow_error_set(error, ENOMEM, 10921 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 10922 NULL, 10923 "failed to push flow workspace"); 10924 rss_desc = &wks->rss_desc; 10925 memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource)); 10926 memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource)); 10927 mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX : 10928 MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 10929 /* update normal path action resource into last index of array */ 10930 sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1]; 10931 tunnel = is_flow_tunnel_match_rule(dev, attr, items, actions) ? 10932 flow_items_to_tunnel(items) : 10933 is_flow_tunnel_steer_rule(dev, attr, items, actions) ? 10934 flow_actions_to_tunnel(actions) : 10935 dev_flow->tunnel ? dev_flow->tunnel : NULL; 10936 mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX : 10937 MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 10938 grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate 10939 (dev, tunnel, attr, items, actions); 10940 ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table, 10941 &grp_info, error); 10942 if (ret) 10943 return ret; 10944 dev_flow->dv.group = table; 10945 if (attr->transfer) 10946 mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 10947 /* number of actions must be set to 0 in case of dirty stack. */ 10948 mhdr_res->actions_num = 0; 10949 if (is_flow_tunnel_match_rule(dev, attr, items, actions)) { 10950 /* 10951 * do not add decap action if match rule drops packet 10952 * HW rejects rules with decap & drop 10953 * 10954 * if tunnel match rule was inserted before matching tunnel set 10955 * rule flow table used in the match rule must be registered. 10956 * current implementation handles that in the 10957 * flow_dv_match_register() at the function end. 10958 */ 10959 bool add_decap = true; 10960 const struct rte_flow_action *ptr = actions; 10961 10962 for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) { 10963 if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) { 10964 add_decap = false; 10965 break; 10966 } 10967 } 10968 if (add_decap) { 10969 if (flow_dv_create_action_l2_decap(dev, dev_flow, 10970 attr->transfer, 10971 error)) 10972 return -rte_errno; 10973 dev_flow->dv.actions[actions_n++] = 10974 dev_flow->dv.encap_decap->action; 10975 action_flags |= MLX5_FLOW_ACTION_DECAP; 10976 } 10977 } 10978 for (; !actions_end ; actions++) { 10979 const struct rte_flow_action_queue *queue; 10980 const struct rte_flow_action_rss *rss; 10981 const struct rte_flow_action *action = actions; 10982 const uint8_t *rss_key; 10983 const struct rte_flow_action_meter *mtr; 10984 struct mlx5_flow_tbl_resource *tbl; 10985 struct mlx5_aso_age_action *age_act; 10986 uint32_t port_id = 0; 10987 struct mlx5_flow_dv_port_id_action_resource port_id_resource; 10988 int action_type = actions->type; 10989 const struct rte_flow_action *found_action = NULL; 10990 struct mlx5_flow_meter *fm = NULL; 10991 uint32_t jump_group = 0; 10992 10993 if (!mlx5_flow_os_action_supported(action_type)) 10994 return rte_flow_error_set(error, ENOTSUP, 10995 RTE_FLOW_ERROR_TYPE_ACTION, 10996 actions, 10997 "action not supported"); 10998 switch (action_type) { 10999 case MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET: 11000 action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET; 11001 break; 11002 case RTE_FLOW_ACTION_TYPE_VOID: 11003 break; 11004 case RTE_FLOW_ACTION_TYPE_PORT_ID: 11005 if (flow_dv_translate_action_port_id(dev, action, 11006 &port_id, error)) 11007 return -rte_errno; 11008 port_id_resource.port_id = port_id; 11009 MLX5_ASSERT(!handle->rix_port_id_action); 11010 if (flow_dv_port_id_action_resource_register 11011 (dev, &port_id_resource, dev_flow, error)) 11012 return -rte_errno; 11013 dev_flow->dv.actions[actions_n++] = 11014 dev_flow->dv.port_id_action->action; 11015 action_flags |= MLX5_FLOW_ACTION_PORT_ID; 11016 dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID; 11017 sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID; 11018 num_of_dest++; 11019 break; 11020 case RTE_FLOW_ACTION_TYPE_FLAG: 11021 action_flags |= MLX5_FLOW_ACTION_FLAG; 11022 dev_flow->handle->mark = 1; 11023 if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 11024 struct rte_flow_action_mark mark = { 11025 .id = MLX5_FLOW_MARK_DEFAULT, 11026 }; 11027 11028 if (flow_dv_convert_action_mark(dev, &mark, 11029 mhdr_res, 11030 error)) 11031 return -rte_errno; 11032 action_flags |= MLX5_FLOW_ACTION_MARK_EXT; 11033 break; 11034 } 11035 tag_be = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT); 11036 /* 11037 * Only one FLAG or MARK is supported per device flow 11038 * right now. So the pointer to the tag resource must be 11039 * zero before the register process. 11040 */ 11041 MLX5_ASSERT(!handle->dvh.rix_tag); 11042 if (flow_dv_tag_resource_register(dev, tag_be, 11043 dev_flow, error)) 11044 return -rte_errno; 11045 MLX5_ASSERT(dev_flow->dv.tag_resource); 11046 dev_flow->dv.actions[actions_n++] = 11047 dev_flow->dv.tag_resource->action; 11048 break; 11049 case RTE_FLOW_ACTION_TYPE_MARK: 11050 action_flags |= MLX5_FLOW_ACTION_MARK; 11051 dev_flow->handle->mark = 1; 11052 if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 11053 const struct rte_flow_action_mark *mark = 11054 (const struct rte_flow_action_mark *) 11055 actions->conf; 11056 11057 if (flow_dv_convert_action_mark(dev, mark, 11058 mhdr_res, 11059 error)) 11060 return -rte_errno; 11061 action_flags |= MLX5_FLOW_ACTION_MARK_EXT; 11062 break; 11063 } 11064 /* Fall-through */ 11065 case MLX5_RTE_FLOW_ACTION_TYPE_MARK: 11066 /* Legacy (non-extensive) MARK action. */ 11067 tag_be = mlx5_flow_mark_set 11068 (((const struct rte_flow_action_mark *) 11069 (actions->conf))->id); 11070 MLX5_ASSERT(!handle->dvh.rix_tag); 11071 if (flow_dv_tag_resource_register(dev, tag_be, 11072 dev_flow, error)) 11073 return -rte_errno; 11074 MLX5_ASSERT(dev_flow->dv.tag_resource); 11075 dev_flow->dv.actions[actions_n++] = 11076 dev_flow->dv.tag_resource->action; 11077 break; 11078 case RTE_FLOW_ACTION_TYPE_SET_META: 11079 if (flow_dv_convert_action_set_meta 11080 (dev, mhdr_res, attr, 11081 (const struct rte_flow_action_set_meta *) 11082 actions->conf, error)) 11083 return -rte_errno; 11084 action_flags |= MLX5_FLOW_ACTION_SET_META; 11085 break; 11086 case RTE_FLOW_ACTION_TYPE_SET_TAG: 11087 if (flow_dv_convert_action_set_tag 11088 (dev, mhdr_res, 11089 (const struct rte_flow_action_set_tag *) 11090 actions->conf, error)) 11091 return -rte_errno; 11092 action_flags |= MLX5_FLOW_ACTION_SET_TAG; 11093 break; 11094 case RTE_FLOW_ACTION_TYPE_DROP: 11095 action_flags |= MLX5_FLOW_ACTION_DROP; 11096 dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP; 11097 break; 11098 case RTE_FLOW_ACTION_TYPE_QUEUE: 11099 queue = actions->conf; 11100 rss_desc->queue_num = 1; 11101 rss_desc->queue[0] = queue->index; 11102 action_flags |= MLX5_FLOW_ACTION_QUEUE; 11103 dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 11104 sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE; 11105 num_of_dest++; 11106 break; 11107 case RTE_FLOW_ACTION_TYPE_RSS: 11108 rss = actions->conf; 11109 memcpy(rss_desc->queue, rss->queue, 11110 rss->queue_num * sizeof(uint16_t)); 11111 rss_desc->queue_num = rss->queue_num; 11112 /* NULL RSS key indicates default RSS key. */ 11113 rss_key = !rss->key ? rss_hash_default_key : rss->key; 11114 memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN); 11115 /* 11116 * rss->level and rss.types should be set in advance 11117 * when expanding items for RSS. 11118 */ 11119 action_flags |= MLX5_FLOW_ACTION_RSS; 11120 dev_flow->handle->fate_action = rss_desc->shared_rss ? 11121 MLX5_FLOW_FATE_SHARED_RSS : 11122 MLX5_FLOW_FATE_QUEUE; 11123 break; 11124 case MLX5_RTE_FLOW_ACTION_TYPE_AGE: 11125 flow->age = (uint32_t)(uintptr_t)(action->conf); 11126 age_act = flow_aso_age_get_by_idx(dev, flow->age); 11127 __atomic_fetch_add(&age_act->refcnt, 1, 11128 __ATOMIC_RELAXED); 11129 dev_flow->dv.actions[actions_n++] = age_act->dr_action; 11130 action_flags |= MLX5_FLOW_ACTION_AGE; 11131 break; 11132 case RTE_FLOW_ACTION_TYPE_AGE: 11133 if (priv->sh->flow_hit_aso_en && attr->group) { 11134 /* 11135 * Create one shared age action, to be used 11136 * by all sub-flows. 11137 */ 11138 if (!flow->age) { 11139 flow->age = 11140 flow_dv_translate_create_aso_age 11141 (dev, action->conf, 11142 error); 11143 if (!flow->age) 11144 return rte_flow_error_set 11145 (error, rte_errno, 11146 RTE_FLOW_ERROR_TYPE_ACTION, 11147 NULL, 11148 "can't create ASO age action"); 11149 } 11150 dev_flow->dv.actions[actions_n++] = 11151 (flow_aso_age_get_by_idx 11152 (dev, flow->age))->dr_action; 11153 action_flags |= MLX5_FLOW_ACTION_AGE; 11154 break; 11155 } 11156 /* Fall-through */ 11157 case RTE_FLOW_ACTION_TYPE_COUNT: 11158 if (!dev_conf->devx) { 11159 return rte_flow_error_set 11160 (error, ENOTSUP, 11161 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 11162 NULL, 11163 "count action not supported"); 11164 } 11165 /* Save information first, will apply later. */ 11166 if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT) 11167 count = action->conf; 11168 else 11169 age = action->conf; 11170 action_flags |= MLX5_FLOW_ACTION_COUNT; 11171 break; 11172 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 11173 dev_flow->dv.actions[actions_n++] = 11174 priv->sh->pop_vlan_action; 11175 action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN; 11176 break; 11177 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 11178 if (!(action_flags & 11179 MLX5_FLOW_ACTION_OF_SET_VLAN_VID)) 11180 flow_dev_get_vlan_info_from_items(items, &vlan); 11181 vlan.eth_proto = rte_be_to_cpu_16 11182 ((((const struct rte_flow_action_of_push_vlan *) 11183 actions->conf)->ethertype)); 11184 found_action = mlx5_flow_find_action 11185 (actions + 1, 11186 RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID); 11187 if (found_action) 11188 mlx5_update_vlan_vid_pcp(found_action, &vlan); 11189 found_action = mlx5_flow_find_action 11190 (actions + 1, 11191 RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP); 11192 if (found_action) 11193 mlx5_update_vlan_vid_pcp(found_action, &vlan); 11194 if (flow_dv_create_action_push_vlan 11195 (dev, attr, &vlan, dev_flow, error)) 11196 return -rte_errno; 11197 dev_flow->dv.actions[actions_n++] = 11198 dev_flow->dv.push_vlan_res->action; 11199 action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN; 11200 break; 11201 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 11202 /* of_vlan_push action handled this action */ 11203 MLX5_ASSERT(action_flags & 11204 MLX5_FLOW_ACTION_OF_PUSH_VLAN); 11205 break; 11206 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 11207 if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) 11208 break; 11209 flow_dev_get_vlan_info_from_items(items, &vlan); 11210 mlx5_update_vlan_vid_pcp(actions, &vlan); 11211 /* If no VLAN push - this is a modify header action */ 11212 if (flow_dv_convert_action_modify_vlan_vid 11213 (mhdr_res, actions, error)) 11214 return -rte_errno; 11215 action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID; 11216 break; 11217 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 11218 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 11219 if (flow_dv_create_action_l2_encap(dev, actions, 11220 dev_flow, 11221 attr->transfer, 11222 error)) 11223 return -rte_errno; 11224 dev_flow->dv.actions[actions_n++] = 11225 dev_flow->dv.encap_decap->action; 11226 action_flags |= MLX5_FLOW_ACTION_ENCAP; 11227 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 11228 sample_act->action_flags |= 11229 MLX5_FLOW_ACTION_ENCAP; 11230 break; 11231 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 11232 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 11233 if (flow_dv_create_action_l2_decap(dev, dev_flow, 11234 attr->transfer, 11235 error)) 11236 return -rte_errno; 11237 dev_flow->dv.actions[actions_n++] = 11238 dev_flow->dv.encap_decap->action; 11239 action_flags |= MLX5_FLOW_ACTION_DECAP; 11240 break; 11241 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 11242 /* Handle encap with preceding decap. */ 11243 if (action_flags & MLX5_FLOW_ACTION_DECAP) { 11244 if (flow_dv_create_action_raw_encap 11245 (dev, actions, dev_flow, attr, error)) 11246 return -rte_errno; 11247 dev_flow->dv.actions[actions_n++] = 11248 dev_flow->dv.encap_decap->action; 11249 } else { 11250 /* Handle encap without preceding decap. */ 11251 if (flow_dv_create_action_l2_encap 11252 (dev, actions, dev_flow, attr->transfer, 11253 error)) 11254 return -rte_errno; 11255 dev_flow->dv.actions[actions_n++] = 11256 dev_flow->dv.encap_decap->action; 11257 } 11258 action_flags |= MLX5_FLOW_ACTION_ENCAP; 11259 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) 11260 sample_act->action_flags |= 11261 MLX5_FLOW_ACTION_ENCAP; 11262 break; 11263 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 11264 while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID) 11265 ; 11266 if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { 11267 if (flow_dv_create_action_l2_decap 11268 (dev, dev_flow, attr->transfer, error)) 11269 return -rte_errno; 11270 dev_flow->dv.actions[actions_n++] = 11271 dev_flow->dv.encap_decap->action; 11272 } 11273 /* If decap is followed by encap, handle it at encap. */ 11274 action_flags |= MLX5_FLOW_ACTION_DECAP; 11275 break; 11276 case RTE_FLOW_ACTION_TYPE_JUMP: 11277 jump_group = ((const struct rte_flow_action_jump *) 11278 action->conf)->group; 11279 grp_info.std_tbl_fix = 0; 11280 if (dev_flow->skip_scale & 11281 (1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT)) 11282 grp_info.skip_scale = 1; 11283 else 11284 grp_info.skip_scale = 0; 11285 ret = mlx5_flow_group_to_table(dev, tunnel, 11286 jump_group, 11287 &table, 11288 &grp_info, error); 11289 if (ret) 11290 return ret; 11291 tbl = flow_dv_tbl_resource_get(dev, table, attr->egress, 11292 attr->transfer, 11293 !!dev_flow->external, 11294 tunnel, jump_group, 0, 11295 error); 11296 if (!tbl) 11297 return rte_flow_error_set 11298 (error, errno, 11299 RTE_FLOW_ERROR_TYPE_ACTION, 11300 NULL, 11301 "cannot create jump action."); 11302 if (flow_dv_jump_tbl_resource_register 11303 (dev, tbl, dev_flow, error)) { 11304 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl); 11305 return rte_flow_error_set 11306 (error, errno, 11307 RTE_FLOW_ERROR_TYPE_ACTION, 11308 NULL, 11309 "cannot create jump action."); 11310 } 11311 dev_flow->dv.actions[actions_n++] = 11312 dev_flow->dv.jump->action; 11313 action_flags |= MLX5_FLOW_ACTION_JUMP; 11314 dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP; 11315 sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP; 11316 num_of_dest++; 11317 break; 11318 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: 11319 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: 11320 if (flow_dv_convert_action_modify_mac 11321 (mhdr_res, actions, error)) 11322 return -rte_errno; 11323 action_flags |= actions->type == 11324 RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ? 11325 MLX5_FLOW_ACTION_SET_MAC_SRC : 11326 MLX5_FLOW_ACTION_SET_MAC_DST; 11327 break; 11328 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: 11329 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: 11330 if (flow_dv_convert_action_modify_ipv4 11331 (mhdr_res, actions, error)) 11332 return -rte_errno; 11333 action_flags |= actions->type == 11334 RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ? 11335 MLX5_FLOW_ACTION_SET_IPV4_SRC : 11336 MLX5_FLOW_ACTION_SET_IPV4_DST; 11337 break; 11338 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: 11339 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: 11340 if (flow_dv_convert_action_modify_ipv6 11341 (mhdr_res, actions, error)) 11342 return -rte_errno; 11343 action_flags |= actions->type == 11344 RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ? 11345 MLX5_FLOW_ACTION_SET_IPV6_SRC : 11346 MLX5_FLOW_ACTION_SET_IPV6_DST; 11347 break; 11348 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: 11349 case RTE_FLOW_ACTION_TYPE_SET_TP_DST: 11350 if (flow_dv_convert_action_modify_tp 11351 (mhdr_res, actions, items, 11352 &flow_attr, dev_flow, !!(action_flags & 11353 MLX5_FLOW_ACTION_DECAP), error)) 11354 return -rte_errno; 11355 action_flags |= actions->type == 11356 RTE_FLOW_ACTION_TYPE_SET_TP_SRC ? 11357 MLX5_FLOW_ACTION_SET_TP_SRC : 11358 MLX5_FLOW_ACTION_SET_TP_DST; 11359 break; 11360 case RTE_FLOW_ACTION_TYPE_DEC_TTL: 11361 if (flow_dv_convert_action_modify_dec_ttl 11362 (mhdr_res, items, &flow_attr, dev_flow, 11363 !!(action_flags & 11364 MLX5_FLOW_ACTION_DECAP), error)) 11365 return -rte_errno; 11366 action_flags |= MLX5_FLOW_ACTION_DEC_TTL; 11367 break; 11368 case RTE_FLOW_ACTION_TYPE_SET_TTL: 11369 if (flow_dv_convert_action_modify_ttl 11370 (mhdr_res, actions, items, &flow_attr, 11371 dev_flow, !!(action_flags & 11372 MLX5_FLOW_ACTION_DECAP), error)) 11373 return -rte_errno; 11374 action_flags |= MLX5_FLOW_ACTION_SET_TTL; 11375 break; 11376 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ: 11377 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ: 11378 if (flow_dv_convert_action_modify_tcp_seq 11379 (mhdr_res, actions, error)) 11380 return -rte_errno; 11381 action_flags |= actions->type == 11382 RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ? 11383 MLX5_FLOW_ACTION_INC_TCP_SEQ : 11384 MLX5_FLOW_ACTION_DEC_TCP_SEQ; 11385 break; 11386 11387 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK: 11388 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK: 11389 if (flow_dv_convert_action_modify_tcp_ack 11390 (mhdr_res, actions, error)) 11391 return -rte_errno; 11392 action_flags |= actions->type == 11393 RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ? 11394 MLX5_FLOW_ACTION_INC_TCP_ACK : 11395 MLX5_FLOW_ACTION_DEC_TCP_ACK; 11396 break; 11397 case MLX5_RTE_FLOW_ACTION_TYPE_TAG: 11398 if (flow_dv_convert_action_set_reg 11399 (mhdr_res, actions, error)) 11400 return -rte_errno; 11401 action_flags |= MLX5_FLOW_ACTION_SET_TAG; 11402 break; 11403 case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG: 11404 if (flow_dv_convert_action_copy_mreg 11405 (dev, mhdr_res, actions, error)) 11406 return -rte_errno; 11407 action_flags |= MLX5_FLOW_ACTION_SET_TAG; 11408 break; 11409 case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS: 11410 action_flags |= MLX5_FLOW_ACTION_DEFAULT_MISS; 11411 dev_flow->handle->fate_action = 11412 MLX5_FLOW_FATE_DEFAULT_MISS; 11413 break; 11414 case RTE_FLOW_ACTION_TYPE_METER: 11415 mtr = actions->conf; 11416 if (!flow->meter) { 11417 fm = mlx5_flow_meter_attach(priv, mtr->mtr_id, 11418 attr, error); 11419 if (!fm) 11420 return rte_flow_error_set(error, 11421 rte_errno, 11422 RTE_FLOW_ERROR_TYPE_ACTION, 11423 NULL, 11424 "meter not found " 11425 "or invalid parameters"); 11426 flow->meter = fm->idx; 11427 } 11428 /* Set the meter action. */ 11429 if (!fm) { 11430 fm = mlx5_ipool_get(priv->sh->ipool 11431 [MLX5_IPOOL_MTR], flow->meter); 11432 if (!fm) 11433 return rte_flow_error_set(error, 11434 rte_errno, 11435 RTE_FLOW_ERROR_TYPE_ACTION, 11436 NULL, 11437 "meter not found " 11438 "or invalid parameters"); 11439 } 11440 dev_flow->dv.actions[actions_n++] = 11441 fm->mfts->meter_action; 11442 action_flags |= MLX5_FLOW_ACTION_METER; 11443 break; 11444 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: 11445 if (flow_dv_convert_action_modify_ipv4_dscp(mhdr_res, 11446 actions, error)) 11447 return -rte_errno; 11448 action_flags |= MLX5_FLOW_ACTION_SET_IPV4_DSCP; 11449 break; 11450 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: 11451 if (flow_dv_convert_action_modify_ipv6_dscp(mhdr_res, 11452 actions, error)) 11453 return -rte_errno; 11454 action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP; 11455 break; 11456 case RTE_FLOW_ACTION_TYPE_SAMPLE: 11457 sample_act_pos = actions_n; 11458 sample = (const struct rte_flow_action_sample *) 11459 action->conf; 11460 actions_n++; 11461 action_flags |= MLX5_FLOW_ACTION_SAMPLE; 11462 /* put encap action into group if work with port id */ 11463 if ((action_flags & MLX5_FLOW_ACTION_ENCAP) && 11464 (action_flags & MLX5_FLOW_ACTION_PORT_ID)) 11465 sample_act->action_flags |= 11466 MLX5_FLOW_ACTION_ENCAP; 11467 break; 11468 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD: 11469 if (flow_dv_convert_action_modify_field 11470 (dev, mhdr_res, actions, attr, error)) 11471 return -rte_errno; 11472 action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD; 11473 break; 11474 case RTE_FLOW_ACTION_TYPE_END: 11475 actions_end = true; 11476 if (mhdr_res->actions_num) { 11477 /* create modify action if needed. */ 11478 if (flow_dv_modify_hdr_resource_register 11479 (dev, mhdr_res, dev_flow, error)) 11480 return -rte_errno; 11481 dev_flow->dv.actions[modify_action_position] = 11482 handle->dvh.modify_hdr->action; 11483 } 11484 if (action_flags & MLX5_FLOW_ACTION_COUNT) { 11485 /* 11486 * Create one count action, to be used 11487 * by all sub-flows. 11488 */ 11489 if (!flow->counter) { 11490 flow->counter = 11491 flow_dv_translate_create_counter 11492 (dev, dev_flow, count, 11493 age); 11494 if (!flow->counter) 11495 return rte_flow_error_set 11496 (error, rte_errno, 11497 RTE_FLOW_ERROR_TYPE_ACTION, 11498 NULL, "cannot create counter" 11499 " object."); 11500 } 11501 dev_flow->dv.actions[actions_n] = 11502 (flow_dv_counter_get_by_idx(dev, 11503 flow->counter, NULL))->action; 11504 actions_n++; 11505 } 11506 default: 11507 break; 11508 } 11509 if (mhdr_res->actions_num && 11510 modify_action_position == UINT32_MAX) 11511 modify_action_position = actions_n++; 11512 } 11513 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 11514 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 11515 int item_type = items->type; 11516 11517 if (!mlx5_flow_os_item_supported(item_type)) 11518 return rte_flow_error_set(error, ENOTSUP, 11519 RTE_FLOW_ERROR_TYPE_ITEM, 11520 NULL, "item not supported"); 11521 switch (item_type) { 11522 case RTE_FLOW_ITEM_TYPE_PORT_ID: 11523 flow_dv_translate_item_port_id 11524 (dev, match_mask, match_value, items, attr); 11525 last_item = MLX5_FLOW_ITEM_PORT_ID; 11526 break; 11527 case RTE_FLOW_ITEM_TYPE_ETH: 11528 flow_dv_translate_item_eth(match_mask, match_value, 11529 items, tunnel, 11530 dev_flow->dv.group); 11531 matcher.priority = action_flags & 11532 MLX5_FLOW_ACTION_DEFAULT_MISS && 11533 !dev_flow->external ? 11534 MLX5_PRIORITY_MAP_L3 : 11535 MLX5_PRIORITY_MAP_L2; 11536 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 11537 MLX5_FLOW_LAYER_OUTER_L2; 11538 break; 11539 case RTE_FLOW_ITEM_TYPE_VLAN: 11540 flow_dv_translate_item_vlan(dev_flow, 11541 match_mask, match_value, 11542 items, tunnel, 11543 dev_flow->dv.group); 11544 matcher.priority = MLX5_PRIORITY_MAP_L2; 11545 last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 | 11546 MLX5_FLOW_LAYER_INNER_VLAN) : 11547 (MLX5_FLOW_LAYER_OUTER_L2 | 11548 MLX5_FLOW_LAYER_OUTER_VLAN); 11549 break; 11550 case RTE_FLOW_ITEM_TYPE_IPV4: 11551 mlx5_flow_tunnel_ip_check(items, next_protocol, 11552 &item_flags, &tunnel); 11553 flow_dv_translate_item_ipv4(match_mask, match_value, 11554 items, tunnel, 11555 dev_flow->dv.group); 11556 matcher.priority = MLX5_PRIORITY_MAP_L3; 11557 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 11558 MLX5_FLOW_LAYER_OUTER_L3_IPV4; 11559 if (items->mask != NULL && 11560 ((const struct rte_flow_item_ipv4 *) 11561 items->mask)->hdr.next_proto_id) { 11562 next_protocol = 11563 ((const struct rte_flow_item_ipv4 *) 11564 (items->spec))->hdr.next_proto_id; 11565 next_protocol &= 11566 ((const struct rte_flow_item_ipv4 *) 11567 (items->mask))->hdr.next_proto_id; 11568 } else { 11569 /* Reset for inner layer. */ 11570 next_protocol = 0xff; 11571 } 11572 break; 11573 case RTE_FLOW_ITEM_TYPE_IPV6: 11574 mlx5_flow_tunnel_ip_check(items, next_protocol, 11575 &item_flags, &tunnel); 11576 flow_dv_translate_item_ipv6(match_mask, match_value, 11577 items, tunnel, 11578 dev_flow->dv.group); 11579 matcher.priority = MLX5_PRIORITY_MAP_L3; 11580 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 11581 MLX5_FLOW_LAYER_OUTER_L3_IPV6; 11582 if (items->mask != NULL && 11583 ((const struct rte_flow_item_ipv6 *) 11584 items->mask)->hdr.proto) { 11585 next_protocol = 11586 ((const struct rte_flow_item_ipv6 *) 11587 items->spec)->hdr.proto; 11588 next_protocol &= 11589 ((const struct rte_flow_item_ipv6 *) 11590 items->mask)->hdr.proto; 11591 } else { 11592 /* Reset for inner layer. */ 11593 next_protocol = 0xff; 11594 } 11595 break; 11596 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT: 11597 flow_dv_translate_item_ipv6_frag_ext(match_mask, 11598 match_value, 11599 items, tunnel); 11600 last_item = tunnel ? 11601 MLX5_FLOW_LAYER_INNER_L3_IPV6_FRAG_EXT : 11602 MLX5_FLOW_LAYER_OUTER_L3_IPV6_FRAG_EXT; 11603 if (items->mask != NULL && 11604 ((const struct rte_flow_item_ipv6_frag_ext *) 11605 items->mask)->hdr.next_header) { 11606 next_protocol = 11607 ((const struct rte_flow_item_ipv6_frag_ext *) 11608 items->spec)->hdr.next_header; 11609 next_protocol &= 11610 ((const struct rte_flow_item_ipv6_frag_ext *) 11611 items->mask)->hdr.next_header; 11612 } else { 11613 /* Reset for inner layer. */ 11614 next_protocol = 0xff; 11615 } 11616 break; 11617 case RTE_FLOW_ITEM_TYPE_TCP: 11618 flow_dv_translate_item_tcp(match_mask, match_value, 11619 items, tunnel); 11620 matcher.priority = MLX5_PRIORITY_MAP_L4; 11621 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 11622 MLX5_FLOW_LAYER_OUTER_L4_TCP; 11623 break; 11624 case RTE_FLOW_ITEM_TYPE_UDP: 11625 flow_dv_translate_item_udp(match_mask, match_value, 11626 items, tunnel); 11627 matcher.priority = MLX5_PRIORITY_MAP_L4; 11628 last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 11629 MLX5_FLOW_LAYER_OUTER_L4_UDP; 11630 break; 11631 case RTE_FLOW_ITEM_TYPE_GRE: 11632 flow_dv_translate_item_gre(match_mask, match_value, 11633 items, tunnel); 11634 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11635 last_item = MLX5_FLOW_LAYER_GRE; 11636 break; 11637 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 11638 flow_dv_translate_item_gre_key(match_mask, 11639 match_value, items); 11640 last_item = MLX5_FLOW_LAYER_GRE_KEY; 11641 break; 11642 case RTE_FLOW_ITEM_TYPE_NVGRE: 11643 flow_dv_translate_item_nvgre(match_mask, match_value, 11644 items, tunnel); 11645 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11646 last_item = MLX5_FLOW_LAYER_GRE; 11647 break; 11648 case RTE_FLOW_ITEM_TYPE_VXLAN: 11649 flow_dv_translate_item_vxlan(match_mask, match_value, 11650 items, tunnel); 11651 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11652 last_item = MLX5_FLOW_LAYER_VXLAN; 11653 break; 11654 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 11655 flow_dv_translate_item_vxlan_gpe(match_mask, 11656 match_value, items, 11657 tunnel); 11658 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11659 last_item = MLX5_FLOW_LAYER_VXLAN_GPE; 11660 break; 11661 case RTE_FLOW_ITEM_TYPE_GENEVE: 11662 flow_dv_translate_item_geneve(match_mask, match_value, 11663 items, tunnel); 11664 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11665 last_item = MLX5_FLOW_LAYER_GENEVE; 11666 break; 11667 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 11668 ret = flow_dv_translate_item_geneve_opt(dev, match_mask, 11669 match_value, 11670 items, error); 11671 if (ret) 11672 return rte_flow_error_set(error, -ret, 11673 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 11674 "cannot create GENEVE TLV option"); 11675 flow->geneve_tlv_option = 1; 11676 last_item = MLX5_FLOW_LAYER_GENEVE_OPT; 11677 break; 11678 case RTE_FLOW_ITEM_TYPE_MPLS: 11679 flow_dv_translate_item_mpls(match_mask, match_value, 11680 items, last_item, tunnel); 11681 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11682 last_item = MLX5_FLOW_LAYER_MPLS; 11683 break; 11684 case RTE_FLOW_ITEM_TYPE_MARK: 11685 flow_dv_translate_item_mark(dev, match_mask, 11686 match_value, items); 11687 last_item = MLX5_FLOW_ITEM_MARK; 11688 break; 11689 case RTE_FLOW_ITEM_TYPE_META: 11690 flow_dv_translate_item_meta(dev, match_mask, 11691 match_value, attr, items); 11692 last_item = MLX5_FLOW_ITEM_METADATA; 11693 break; 11694 case RTE_FLOW_ITEM_TYPE_ICMP: 11695 flow_dv_translate_item_icmp(match_mask, match_value, 11696 items, tunnel); 11697 last_item = MLX5_FLOW_LAYER_ICMP; 11698 break; 11699 case RTE_FLOW_ITEM_TYPE_ICMP6: 11700 flow_dv_translate_item_icmp6(match_mask, match_value, 11701 items, tunnel); 11702 last_item = MLX5_FLOW_LAYER_ICMP6; 11703 break; 11704 case RTE_FLOW_ITEM_TYPE_TAG: 11705 flow_dv_translate_item_tag(dev, match_mask, 11706 match_value, items); 11707 last_item = MLX5_FLOW_ITEM_TAG; 11708 break; 11709 case MLX5_RTE_FLOW_ITEM_TYPE_TAG: 11710 flow_dv_translate_mlx5_item_tag(dev, match_mask, 11711 match_value, items); 11712 last_item = MLX5_FLOW_ITEM_TAG; 11713 break; 11714 case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE: 11715 flow_dv_translate_item_tx_queue(dev, match_mask, 11716 match_value, 11717 items); 11718 last_item = MLX5_FLOW_ITEM_TX_QUEUE; 11719 break; 11720 case RTE_FLOW_ITEM_TYPE_GTP: 11721 flow_dv_translate_item_gtp(match_mask, match_value, 11722 items, tunnel); 11723 matcher.priority = MLX5_TUNNEL_PRIO_GET(rss_desc); 11724 last_item = MLX5_FLOW_LAYER_GTP; 11725 break; 11726 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 11727 ret = flow_dv_translate_item_gtp_psc(match_mask, 11728 match_value, 11729 items); 11730 if (ret) 11731 return rte_flow_error_set(error, -ret, 11732 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 11733 "cannot create GTP PSC item"); 11734 last_item = MLX5_FLOW_LAYER_GTP_PSC; 11735 break; 11736 case RTE_FLOW_ITEM_TYPE_ECPRI: 11737 if (!mlx5_flex_parser_ecpri_exist(dev)) { 11738 /* Create it only the first time to be used. */ 11739 ret = mlx5_flex_parser_ecpri_alloc(dev); 11740 if (ret) 11741 return rte_flow_error_set 11742 (error, -ret, 11743 RTE_FLOW_ERROR_TYPE_ITEM, 11744 NULL, 11745 "cannot create eCPRI parser"); 11746 } 11747 /* Adjust the length matcher and device flow value. */ 11748 matcher.mask.size = MLX5_ST_SZ_BYTES(fte_match_param); 11749 dev_flow->dv.value.size = 11750 MLX5_ST_SZ_BYTES(fte_match_param); 11751 flow_dv_translate_item_ecpri(dev, match_mask, 11752 match_value, items); 11753 /* No other protocol should follow eCPRI layer. */ 11754 last_item = MLX5_FLOW_LAYER_ECPRI; 11755 break; 11756 default: 11757 break; 11758 } 11759 item_flags |= last_item; 11760 } 11761 /* 11762 * When E-Switch mode is enabled, we have two cases where we need to 11763 * set the source port manually. 11764 * The first one, is in case of Nic steering rule, and the second is 11765 * E-Switch rule where no port_id item was found. In both cases 11766 * the source port is set according the current port in use. 11767 */ 11768 if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) && 11769 (priv->representor || priv->master)) { 11770 if (flow_dv_translate_item_port_id(dev, match_mask, 11771 match_value, NULL, attr)) 11772 return -rte_errno; 11773 } 11774 #ifdef RTE_LIBRTE_MLX5_DEBUG 11775 MLX5_ASSERT(!flow_dv_check_valid_spec(matcher.mask.buf, 11776 dev_flow->dv.value.buf)); 11777 #endif 11778 /* 11779 * Layers may be already initialized from prefix flow if this dev_flow 11780 * is the suffix flow. 11781 */ 11782 handle->layers |= item_flags; 11783 if (action_flags & MLX5_FLOW_ACTION_RSS) 11784 flow_dv_hashfields_set(dev_flow, rss_desc); 11785 /* If has RSS action in the sample action, the Sample/Mirror resource 11786 * should be registered after the hash filed be update. 11787 */ 11788 if (action_flags & MLX5_FLOW_ACTION_SAMPLE) { 11789 ret = flow_dv_translate_action_sample(dev, 11790 sample, 11791 dev_flow, attr, 11792 &num_of_dest, 11793 sample_actions, 11794 &sample_res, 11795 error); 11796 if (ret < 0) 11797 return ret; 11798 ret = flow_dv_create_action_sample(dev, 11799 dev_flow, 11800 num_of_dest, 11801 &sample_res, 11802 &mdest_res, 11803 sample_actions, 11804 action_flags, 11805 error); 11806 if (ret < 0) 11807 return rte_flow_error_set 11808 (error, rte_errno, 11809 RTE_FLOW_ERROR_TYPE_ACTION, 11810 NULL, 11811 "cannot create sample action"); 11812 if (num_of_dest > 1) { 11813 dev_flow->dv.actions[sample_act_pos] = 11814 dev_flow->dv.dest_array_res->action; 11815 } else { 11816 dev_flow->dv.actions[sample_act_pos] = 11817 dev_flow->dv.sample_res->verbs_action; 11818 } 11819 } 11820 /* 11821 * For multiple destination (sample action with ratio=1), the encap 11822 * action and port id action will be combined into group action. 11823 * So need remove the original these actions in the flow and only 11824 * use the sample action instead of. 11825 */ 11826 if (num_of_dest > 1 && 11827 (sample_act->dr_port_id_action || sample_act->dr_jump_action)) { 11828 int i; 11829 void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0}; 11830 11831 for (i = 0; i < actions_n; i++) { 11832 if ((sample_act->dr_encap_action && 11833 sample_act->dr_encap_action == 11834 dev_flow->dv.actions[i]) || 11835 (sample_act->dr_port_id_action && 11836 sample_act->dr_port_id_action == 11837 dev_flow->dv.actions[i]) || 11838 (sample_act->dr_jump_action && 11839 sample_act->dr_jump_action == 11840 dev_flow->dv.actions[i])) 11841 continue; 11842 temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i]; 11843 } 11844 memcpy((void *)dev_flow->dv.actions, 11845 (void *)temp_actions, 11846 tmp_actions_n * sizeof(void *)); 11847 actions_n = tmp_actions_n; 11848 } 11849 dev_flow->dv.actions_n = actions_n; 11850 dev_flow->act_flags = action_flags; 11851 /* Register matcher. */ 11852 matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf, 11853 matcher.mask.size); 11854 matcher.priority = mlx5_get_matcher_priority(dev, attr, 11855 matcher.priority); 11856 /* reserved field no needs to be set to 0 here. */ 11857 tbl_key.domain = attr->transfer; 11858 tbl_key.direction = attr->egress; 11859 tbl_key.table_id = dev_flow->dv.group; 11860 if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow, 11861 tunnel, attr->group, error)) 11862 return -rte_errno; 11863 return 0; 11864 } 11865 11866 /** 11867 * Set hash RX queue by hash fields (see enum ibv_rx_hash_fields) 11868 * and tunnel. 11869 * 11870 * @param[in, out] action 11871 * Shred RSS action holding hash RX queue objects. 11872 * @param[in] hash_fields 11873 * Defines combination of packet fields to participate in RX hash. 11874 * @param[in] tunnel 11875 * Tunnel type 11876 * @param[in] hrxq_idx 11877 * Hash RX queue index to set. 11878 * 11879 * @return 11880 * 0 on success, otherwise negative errno value. 11881 */ 11882 static int 11883 __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action, 11884 const uint64_t hash_fields, 11885 const int tunnel, 11886 uint32_t hrxq_idx) 11887 { 11888 uint32_t *hrxqs = tunnel ? action->hrxq : action->hrxq_tunnel; 11889 11890 switch (hash_fields & ~IBV_RX_HASH_INNER) { 11891 case MLX5_RSS_HASH_IPV4: 11892 hrxqs[0] = hrxq_idx; 11893 return 0; 11894 case MLX5_RSS_HASH_IPV4_TCP: 11895 hrxqs[1] = hrxq_idx; 11896 return 0; 11897 case MLX5_RSS_HASH_IPV4_UDP: 11898 hrxqs[2] = hrxq_idx; 11899 return 0; 11900 case MLX5_RSS_HASH_IPV6: 11901 hrxqs[3] = hrxq_idx; 11902 return 0; 11903 case MLX5_RSS_HASH_IPV6_TCP: 11904 hrxqs[4] = hrxq_idx; 11905 return 0; 11906 case MLX5_RSS_HASH_IPV6_UDP: 11907 hrxqs[5] = hrxq_idx; 11908 return 0; 11909 case MLX5_RSS_HASH_NONE: 11910 hrxqs[6] = hrxq_idx; 11911 return 0; 11912 default: 11913 return -1; 11914 } 11915 } 11916 11917 /** 11918 * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields) 11919 * and tunnel. 11920 * 11921 * @param[in] dev 11922 * Pointer to the Ethernet device structure. 11923 * @param[in] idx 11924 * Shared RSS action ID holding hash RX queue objects. 11925 * @param[in] hash_fields 11926 * Defines combination of packet fields to participate in RX hash. 11927 * @param[in] tunnel 11928 * Tunnel type 11929 * 11930 * @return 11931 * Valid hash RX queue index, otherwise 0. 11932 */ 11933 static uint32_t 11934 __flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx, 11935 const uint64_t hash_fields, 11936 const int tunnel) 11937 { 11938 struct mlx5_priv *priv = dev->data->dev_private; 11939 struct mlx5_shared_action_rss *shared_rss = 11940 mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx); 11941 const uint32_t *hrxqs = tunnel ? shared_rss->hrxq : 11942 shared_rss->hrxq_tunnel; 11943 11944 switch (hash_fields & ~IBV_RX_HASH_INNER) { 11945 case MLX5_RSS_HASH_IPV4: 11946 return hrxqs[0]; 11947 case MLX5_RSS_HASH_IPV4_TCP: 11948 return hrxqs[1]; 11949 case MLX5_RSS_HASH_IPV4_UDP: 11950 return hrxqs[2]; 11951 case MLX5_RSS_HASH_IPV6: 11952 return hrxqs[3]; 11953 case MLX5_RSS_HASH_IPV6_TCP: 11954 return hrxqs[4]; 11955 case MLX5_RSS_HASH_IPV6_UDP: 11956 return hrxqs[5]; 11957 case MLX5_RSS_HASH_NONE: 11958 return hrxqs[6]; 11959 default: 11960 return 0; 11961 } 11962 } 11963 11964 /** 11965 * Apply the flow to the NIC, lock free, 11966 * (mutex should be acquired by caller). 11967 * 11968 * @param[in] dev 11969 * Pointer to the Ethernet device structure. 11970 * @param[in, out] flow 11971 * Pointer to flow structure. 11972 * @param[out] error 11973 * Pointer to error structure. 11974 * 11975 * @return 11976 * 0 on success, a negative errno value otherwise and rte_errno is set. 11977 */ 11978 static int 11979 flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, 11980 struct rte_flow_error *error) 11981 { 11982 struct mlx5_flow_dv_workspace *dv; 11983 struct mlx5_flow_handle *dh; 11984 struct mlx5_flow_handle_dv *dv_h; 11985 struct mlx5_flow *dev_flow; 11986 struct mlx5_priv *priv = dev->data->dev_private; 11987 uint32_t handle_idx; 11988 int n; 11989 int err; 11990 int idx; 11991 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 11992 struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc; 11993 11994 MLX5_ASSERT(wks); 11995 for (idx = wks->flow_idx - 1; idx >= 0; idx--) { 11996 dev_flow = &wks->flows[idx]; 11997 dv = &dev_flow->dv; 11998 dh = dev_flow->handle; 11999 dv_h = &dh->dvh; 12000 n = dv->actions_n; 12001 if (dh->fate_action == MLX5_FLOW_FATE_DROP) { 12002 if (dv->transfer) { 12003 dv->actions[n++] = priv->sh->esw_drop_action; 12004 } else { 12005 MLX5_ASSERT(priv->drop_queue.hrxq); 12006 dv->actions[n++] = 12007 priv->drop_queue.hrxq->action; 12008 } 12009 } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE && 12010 !dv_h->rix_sample && !dv_h->rix_dest_array)) { 12011 struct mlx5_hrxq *hrxq; 12012 uint32_t hrxq_idx; 12013 12014 hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc, 12015 &hrxq_idx); 12016 if (!hrxq) { 12017 rte_flow_error_set 12018 (error, rte_errno, 12019 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12020 "cannot get hash queue"); 12021 goto error; 12022 } 12023 dh->rix_hrxq = hrxq_idx; 12024 dv->actions[n++] = hrxq->action; 12025 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) { 12026 struct mlx5_hrxq *hrxq = NULL; 12027 uint32_t hrxq_idx; 12028 12029 hrxq_idx = __flow_dv_action_rss_hrxq_lookup(dev, 12030 rss_desc->shared_rss, 12031 dev_flow->hash_fields, 12032 !!(dh->layers & 12033 MLX5_FLOW_LAYER_TUNNEL)); 12034 if (hrxq_idx) 12035 hrxq = mlx5_ipool_get 12036 (priv->sh->ipool[MLX5_IPOOL_HRXQ], 12037 hrxq_idx); 12038 if (!hrxq) { 12039 rte_flow_error_set 12040 (error, rte_errno, 12041 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12042 "cannot get hash queue"); 12043 goto error; 12044 } 12045 dh->rix_srss = rss_desc->shared_rss; 12046 dv->actions[n++] = hrxq->action; 12047 } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) { 12048 if (!priv->sh->default_miss_action) { 12049 rte_flow_error_set 12050 (error, rte_errno, 12051 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12052 "default miss action not be created."); 12053 goto error; 12054 } 12055 dv->actions[n++] = priv->sh->default_miss_action; 12056 } 12057 err = mlx5_flow_os_create_flow(dv_h->matcher->matcher_object, 12058 (void *)&dv->value, n, 12059 dv->actions, &dh->drv_flow); 12060 if (err) { 12061 rte_flow_error_set(error, errno, 12062 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 12063 NULL, 12064 "hardware refuses to create flow"); 12065 goto error; 12066 } 12067 if (priv->vmwa_context && 12068 dh->vf_vlan.tag && !dh->vf_vlan.created) { 12069 /* 12070 * The rule contains the VLAN pattern. 12071 * For VF we are going to create VLAN 12072 * interface to make hypervisor set correct 12073 * e-Switch vport context. 12074 */ 12075 mlx5_vlan_vmwa_acquire(dev, &dh->vf_vlan); 12076 } 12077 } 12078 return 0; 12079 error: 12080 err = rte_errno; /* Save rte_errno before cleanup. */ 12081 SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 12082 handle_idx, dh, next) { 12083 /* hrxq is union, don't clear it if the flag is not set. */ 12084 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && dh->rix_hrxq) { 12085 mlx5_hrxq_release(dev, dh->rix_hrxq); 12086 dh->rix_hrxq = 0; 12087 } else if (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS) { 12088 dh->rix_srss = 0; 12089 } 12090 if (dh->vf_vlan.tag && dh->vf_vlan.created) 12091 mlx5_vlan_vmwa_release(dev, &dh->vf_vlan); 12092 } 12093 rte_errno = err; /* Restore rte_errno. */ 12094 return -rte_errno; 12095 } 12096 12097 void 12098 flow_dv_matcher_remove_cb(struct mlx5_cache_list *list __rte_unused, 12099 struct mlx5_cache_entry *entry) 12100 { 12101 struct mlx5_flow_dv_matcher *cache = container_of(entry, typeof(*cache), 12102 entry); 12103 12104 claim_zero(mlx5_flow_os_destroy_flow_matcher(cache->matcher_object)); 12105 mlx5_free(cache); 12106 } 12107 12108 /** 12109 * Release the flow matcher. 12110 * 12111 * @param dev 12112 * Pointer to Ethernet device. 12113 * @param port_id 12114 * Index to port ID action resource. 12115 * 12116 * @return 12117 * 1 while a reference on it exists, 0 when freed. 12118 */ 12119 static int 12120 flow_dv_matcher_release(struct rte_eth_dev *dev, 12121 struct mlx5_flow_handle *handle) 12122 { 12123 struct mlx5_flow_dv_matcher *matcher = handle->dvh.matcher; 12124 struct mlx5_flow_tbl_data_entry *tbl = container_of(matcher->tbl, 12125 typeof(*tbl), tbl); 12126 int ret; 12127 12128 MLX5_ASSERT(matcher->matcher_object); 12129 ret = mlx5_cache_unregister(&tbl->matchers, &matcher->entry); 12130 flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl->tbl); 12131 return ret; 12132 } 12133 12134 /** 12135 * Release encap_decap resource. 12136 * 12137 * @param list 12138 * Pointer to the hash list. 12139 * @param entry 12140 * Pointer to exist resource entry object. 12141 */ 12142 void 12143 flow_dv_encap_decap_remove_cb(struct mlx5_hlist *list, 12144 struct mlx5_hlist_entry *entry) 12145 { 12146 struct mlx5_dev_ctx_shared *sh = list->ctx; 12147 struct mlx5_flow_dv_encap_decap_resource *res = 12148 container_of(entry, typeof(*res), entry); 12149 12150 claim_zero(mlx5_flow_os_destroy_flow_action(res->action)); 12151 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], res->idx); 12152 } 12153 12154 /** 12155 * Release an encap/decap resource. 12156 * 12157 * @param dev 12158 * Pointer to Ethernet device. 12159 * @param encap_decap_idx 12160 * Index of encap decap resource. 12161 * 12162 * @return 12163 * 1 while a reference on it exists, 0 when freed. 12164 */ 12165 static int 12166 flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev, 12167 uint32_t encap_decap_idx) 12168 { 12169 struct mlx5_priv *priv = dev->data->dev_private; 12170 struct mlx5_flow_dv_encap_decap_resource *cache_resource; 12171 12172 cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP], 12173 encap_decap_idx); 12174 if (!cache_resource) 12175 return 0; 12176 MLX5_ASSERT(cache_resource->action); 12177 return mlx5_hlist_unregister(priv->sh->encaps_decaps, 12178 &cache_resource->entry); 12179 } 12180 12181 /** 12182 * Release an jump to table action resource. 12183 * 12184 * @param dev 12185 * Pointer to Ethernet device. 12186 * @param rix_jump 12187 * Index to the jump action resource. 12188 * 12189 * @return 12190 * 1 while a reference on it exists, 0 when freed. 12191 */ 12192 static int 12193 flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev, 12194 uint32_t rix_jump) 12195 { 12196 struct mlx5_priv *priv = dev->data->dev_private; 12197 struct mlx5_flow_tbl_data_entry *tbl_data; 12198 12199 tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP], 12200 rix_jump); 12201 if (!tbl_data) 12202 return 0; 12203 return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl); 12204 } 12205 12206 void 12207 flow_dv_modify_remove_cb(struct mlx5_hlist *list __rte_unused, 12208 struct mlx5_hlist_entry *entry) 12209 { 12210 struct mlx5_flow_dv_modify_hdr_resource *res = 12211 container_of(entry, typeof(*res), entry); 12212 12213 claim_zero(mlx5_flow_os_destroy_flow_action(res->action)); 12214 mlx5_free(entry); 12215 } 12216 12217 /** 12218 * Release a modify-header resource. 12219 * 12220 * @param dev 12221 * Pointer to Ethernet device. 12222 * @param handle 12223 * Pointer to mlx5_flow_handle. 12224 * 12225 * @return 12226 * 1 while a reference on it exists, 0 when freed. 12227 */ 12228 static int 12229 flow_dv_modify_hdr_resource_release(struct rte_eth_dev *dev, 12230 struct mlx5_flow_handle *handle) 12231 { 12232 struct mlx5_priv *priv = dev->data->dev_private; 12233 struct mlx5_flow_dv_modify_hdr_resource *entry = handle->dvh.modify_hdr; 12234 12235 MLX5_ASSERT(entry->action); 12236 return mlx5_hlist_unregister(priv->sh->modify_cmds, &entry->entry); 12237 } 12238 12239 void 12240 flow_dv_port_id_remove_cb(struct mlx5_cache_list *list, 12241 struct mlx5_cache_entry *entry) 12242 { 12243 struct mlx5_dev_ctx_shared *sh = list->ctx; 12244 struct mlx5_flow_dv_port_id_action_resource *cache = 12245 container_of(entry, typeof(*cache), entry); 12246 12247 claim_zero(mlx5_flow_os_destroy_flow_action(cache->action)); 12248 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PORT_ID], cache->idx); 12249 } 12250 12251 /** 12252 * Release port ID action resource. 12253 * 12254 * @param dev 12255 * Pointer to Ethernet device. 12256 * @param handle 12257 * Pointer to mlx5_flow_handle. 12258 * 12259 * @return 12260 * 1 while a reference on it exists, 0 when freed. 12261 */ 12262 static int 12263 flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev, 12264 uint32_t port_id) 12265 { 12266 struct mlx5_priv *priv = dev->data->dev_private; 12267 struct mlx5_flow_dv_port_id_action_resource *cache; 12268 12269 cache = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID], port_id); 12270 if (!cache) 12271 return 0; 12272 MLX5_ASSERT(cache->action); 12273 return mlx5_cache_unregister(&priv->sh->port_id_action_list, 12274 &cache->entry); 12275 } 12276 12277 /** 12278 * Release shared RSS action resource. 12279 * 12280 * @param dev 12281 * Pointer to Ethernet device. 12282 * @param srss 12283 * Shared RSS action index. 12284 */ 12285 static void 12286 flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss) 12287 { 12288 struct mlx5_priv *priv = dev->data->dev_private; 12289 struct mlx5_shared_action_rss *shared_rss; 12290 12291 shared_rss = mlx5_ipool_get 12292 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss); 12293 __atomic_sub_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED); 12294 } 12295 12296 void 12297 flow_dv_push_vlan_remove_cb(struct mlx5_cache_list *list, 12298 struct mlx5_cache_entry *entry) 12299 { 12300 struct mlx5_dev_ctx_shared *sh = list->ctx; 12301 struct mlx5_flow_dv_push_vlan_action_resource *cache = 12302 container_of(entry, typeof(*cache), entry); 12303 12304 claim_zero(mlx5_flow_os_destroy_flow_action(cache->action)); 12305 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_PUSH_VLAN], cache->idx); 12306 } 12307 12308 /** 12309 * Release push vlan action resource. 12310 * 12311 * @param dev 12312 * Pointer to Ethernet device. 12313 * @param handle 12314 * Pointer to mlx5_flow_handle. 12315 * 12316 * @return 12317 * 1 while a reference on it exists, 0 when freed. 12318 */ 12319 static int 12320 flow_dv_push_vlan_action_resource_release(struct rte_eth_dev *dev, 12321 struct mlx5_flow_handle *handle) 12322 { 12323 struct mlx5_priv *priv = dev->data->dev_private; 12324 struct mlx5_flow_dv_push_vlan_action_resource *cache; 12325 uint32_t idx = handle->dvh.rix_push_vlan; 12326 12327 cache = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN], idx); 12328 if (!cache) 12329 return 0; 12330 MLX5_ASSERT(cache->action); 12331 return mlx5_cache_unregister(&priv->sh->push_vlan_action_list, 12332 &cache->entry); 12333 } 12334 12335 /** 12336 * Release the fate resource. 12337 * 12338 * @param dev 12339 * Pointer to Ethernet device. 12340 * @param handle 12341 * Pointer to mlx5_flow_handle. 12342 */ 12343 static void 12344 flow_dv_fate_resource_release(struct rte_eth_dev *dev, 12345 struct mlx5_flow_handle *handle) 12346 { 12347 if (!handle->rix_fate) 12348 return; 12349 switch (handle->fate_action) { 12350 case MLX5_FLOW_FATE_QUEUE: 12351 mlx5_hrxq_release(dev, handle->rix_hrxq); 12352 break; 12353 case MLX5_FLOW_FATE_JUMP: 12354 flow_dv_jump_tbl_resource_release(dev, handle->rix_jump); 12355 break; 12356 case MLX5_FLOW_FATE_PORT_ID: 12357 flow_dv_port_id_action_resource_release(dev, 12358 handle->rix_port_id_action); 12359 break; 12360 default: 12361 DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action); 12362 break; 12363 } 12364 handle->rix_fate = 0; 12365 } 12366 12367 void 12368 flow_dv_sample_remove_cb(struct mlx5_cache_list *list __rte_unused, 12369 struct mlx5_cache_entry *entry) 12370 { 12371 struct mlx5_flow_dv_sample_resource *cache_resource = 12372 container_of(entry, typeof(*cache_resource), entry); 12373 struct rte_eth_dev *dev = cache_resource->dev; 12374 struct mlx5_priv *priv = dev->data->dev_private; 12375 12376 if (cache_resource->verbs_action) 12377 claim_zero(mlx5_flow_os_destroy_flow_action 12378 (cache_resource->verbs_action)); 12379 if (cache_resource->normal_path_tbl) 12380 flow_dv_tbl_resource_release(MLX5_SH(dev), 12381 cache_resource->normal_path_tbl); 12382 flow_dv_sample_sub_actions_release(dev, 12383 &cache_resource->sample_idx); 12384 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], 12385 cache_resource->idx); 12386 DRV_LOG(DEBUG, "sample resource %p: removed", 12387 (void *)cache_resource); 12388 } 12389 12390 /** 12391 * Release an sample resource. 12392 * 12393 * @param dev 12394 * Pointer to Ethernet device. 12395 * @param handle 12396 * Pointer to mlx5_flow_handle. 12397 * 12398 * @return 12399 * 1 while a reference on it exists, 0 when freed. 12400 */ 12401 static int 12402 flow_dv_sample_resource_release(struct rte_eth_dev *dev, 12403 struct mlx5_flow_handle *handle) 12404 { 12405 struct mlx5_priv *priv = dev->data->dev_private; 12406 struct mlx5_flow_dv_sample_resource *cache_resource; 12407 12408 cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE], 12409 handle->dvh.rix_sample); 12410 if (!cache_resource) 12411 return 0; 12412 MLX5_ASSERT(cache_resource->verbs_action); 12413 return mlx5_cache_unregister(&priv->sh->sample_action_list, 12414 &cache_resource->entry); 12415 } 12416 12417 void 12418 flow_dv_dest_array_remove_cb(struct mlx5_cache_list *list __rte_unused, 12419 struct mlx5_cache_entry *entry) 12420 { 12421 struct mlx5_flow_dv_dest_array_resource *cache_resource = 12422 container_of(entry, typeof(*cache_resource), entry); 12423 struct rte_eth_dev *dev = cache_resource->dev; 12424 struct mlx5_priv *priv = dev->data->dev_private; 12425 uint32_t i = 0; 12426 12427 MLX5_ASSERT(cache_resource->action); 12428 if (cache_resource->action) 12429 claim_zero(mlx5_flow_os_destroy_flow_action 12430 (cache_resource->action)); 12431 for (; i < cache_resource->num_of_dest; i++) 12432 flow_dv_sample_sub_actions_release(dev, 12433 &cache_resource->sample_idx[i]); 12434 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], 12435 cache_resource->idx); 12436 DRV_LOG(DEBUG, "destination array resource %p: removed", 12437 (void *)cache_resource); 12438 } 12439 12440 /** 12441 * Release an destination array resource. 12442 * 12443 * @param dev 12444 * Pointer to Ethernet device. 12445 * @param handle 12446 * Pointer to mlx5_flow_handle. 12447 * 12448 * @return 12449 * 1 while a reference on it exists, 0 when freed. 12450 */ 12451 static int 12452 flow_dv_dest_array_resource_release(struct rte_eth_dev *dev, 12453 struct mlx5_flow_handle *handle) 12454 { 12455 struct mlx5_priv *priv = dev->data->dev_private; 12456 struct mlx5_flow_dv_dest_array_resource *cache; 12457 12458 cache = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], 12459 handle->dvh.rix_dest_array); 12460 if (!cache) 12461 return 0; 12462 MLX5_ASSERT(cache->action); 12463 return mlx5_cache_unregister(&priv->sh->dest_array_list, 12464 &cache->entry); 12465 } 12466 12467 static void 12468 flow_dv_geneve_tlv_option_resource_release(struct rte_eth_dev *dev) 12469 { 12470 struct mlx5_priv *priv = dev->data->dev_private; 12471 struct mlx5_dev_ctx_shared *sh = priv->sh; 12472 struct mlx5_geneve_tlv_option_resource *geneve_opt_resource = 12473 sh->geneve_tlv_option_resource; 12474 rte_spinlock_lock(&sh->geneve_tlv_opt_sl); 12475 if (geneve_opt_resource) { 12476 if (!(__atomic_sub_fetch(&geneve_opt_resource->refcnt, 1, 12477 __ATOMIC_RELAXED))) { 12478 claim_zero(mlx5_devx_cmd_destroy 12479 (geneve_opt_resource->obj)); 12480 mlx5_free(sh->geneve_tlv_option_resource); 12481 sh->geneve_tlv_option_resource = NULL; 12482 } 12483 } 12484 rte_spinlock_unlock(&sh->geneve_tlv_opt_sl); 12485 } 12486 12487 /** 12488 * Remove the flow from the NIC but keeps it in memory. 12489 * Lock free, (mutex should be acquired by caller). 12490 * 12491 * @param[in] dev 12492 * Pointer to Ethernet device. 12493 * @param[in, out] flow 12494 * Pointer to flow structure. 12495 */ 12496 static void 12497 flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow) 12498 { 12499 struct mlx5_flow_handle *dh; 12500 uint32_t handle_idx; 12501 struct mlx5_priv *priv = dev->data->dev_private; 12502 12503 if (!flow) 12504 return; 12505 handle_idx = flow->dev_handles; 12506 while (handle_idx) { 12507 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 12508 handle_idx); 12509 if (!dh) 12510 return; 12511 if (dh->drv_flow) { 12512 claim_zero(mlx5_flow_os_destroy_flow(dh->drv_flow)); 12513 dh->drv_flow = NULL; 12514 } 12515 if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) 12516 flow_dv_fate_resource_release(dev, dh); 12517 if (dh->vf_vlan.tag && dh->vf_vlan.created) 12518 mlx5_vlan_vmwa_release(dev, &dh->vf_vlan); 12519 handle_idx = dh->next.next; 12520 } 12521 } 12522 12523 /** 12524 * Remove the flow from the NIC and the memory. 12525 * Lock free, (mutex should be acquired by caller). 12526 * 12527 * @param[in] dev 12528 * Pointer to the Ethernet device structure. 12529 * @param[in, out] flow 12530 * Pointer to flow structure. 12531 */ 12532 static void 12533 flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 12534 { 12535 struct mlx5_flow_handle *dev_handle; 12536 struct mlx5_priv *priv = dev->data->dev_private; 12537 uint32_t srss = 0; 12538 12539 if (!flow) 12540 return; 12541 flow_dv_remove(dev, flow); 12542 if (flow->counter) { 12543 flow_dv_counter_free(dev, flow->counter); 12544 flow->counter = 0; 12545 } 12546 if (flow->meter) { 12547 struct mlx5_flow_meter *fm; 12548 12549 fm = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], 12550 flow->meter); 12551 if (fm) 12552 mlx5_flow_meter_detach(fm); 12553 flow->meter = 0; 12554 } 12555 if (flow->age) 12556 flow_dv_aso_age_release(dev, flow->age); 12557 if (flow->geneve_tlv_option) { 12558 flow_dv_geneve_tlv_option_resource_release(dev); 12559 flow->geneve_tlv_option = 0; 12560 } 12561 while (flow->dev_handles) { 12562 uint32_t tmp_idx = flow->dev_handles; 12563 12564 dev_handle = mlx5_ipool_get(priv->sh->ipool 12565 [MLX5_IPOOL_MLX5_FLOW], tmp_idx); 12566 if (!dev_handle) 12567 return; 12568 flow->dev_handles = dev_handle->next.next; 12569 if (dev_handle->dvh.matcher) 12570 flow_dv_matcher_release(dev, dev_handle); 12571 if (dev_handle->dvh.rix_sample) 12572 flow_dv_sample_resource_release(dev, dev_handle); 12573 if (dev_handle->dvh.rix_dest_array) 12574 flow_dv_dest_array_resource_release(dev, dev_handle); 12575 if (dev_handle->dvh.rix_encap_decap) 12576 flow_dv_encap_decap_resource_release(dev, 12577 dev_handle->dvh.rix_encap_decap); 12578 if (dev_handle->dvh.modify_hdr) 12579 flow_dv_modify_hdr_resource_release(dev, dev_handle); 12580 if (dev_handle->dvh.rix_push_vlan) 12581 flow_dv_push_vlan_action_resource_release(dev, 12582 dev_handle); 12583 if (dev_handle->dvh.rix_tag) 12584 flow_dv_tag_release(dev, 12585 dev_handle->dvh.rix_tag); 12586 if (dev_handle->fate_action != MLX5_FLOW_FATE_SHARED_RSS) 12587 flow_dv_fate_resource_release(dev, dev_handle); 12588 else if (!srss) 12589 srss = dev_handle->rix_srss; 12590 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 12591 tmp_idx); 12592 } 12593 if (srss) 12594 flow_dv_shared_rss_action_release(dev, srss); 12595 } 12596 12597 /** 12598 * Release array of hash RX queue objects. 12599 * Helper function. 12600 * 12601 * @param[in] dev 12602 * Pointer to the Ethernet device structure. 12603 * @param[in, out] hrxqs 12604 * Array of hash RX queue objects. 12605 * 12606 * @return 12607 * Total number of references to hash RX queue objects in *hrxqs* array 12608 * after this operation. 12609 */ 12610 static int 12611 __flow_dv_hrxqs_release(struct rte_eth_dev *dev, 12612 uint32_t (*hrxqs)[MLX5_RSS_HASH_FIELDS_LEN]) 12613 { 12614 size_t i; 12615 int remaining = 0; 12616 12617 for (i = 0; i < RTE_DIM(*hrxqs); i++) { 12618 int ret = mlx5_hrxq_release(dev, (*hrxqs)[i]); 12619 12620 if (!ret) 12621 (*hrxqs)[i] = 0; 12622 remaining += ret; 12623 } 12624 return remaining; 12625 } 12626 12627 /** 12628 * Release all hash RX queue objects representing shared RSS action. 12629 * 12630 * @param[in] dev 12631 * Pointer to the Ethernet device structure. 12632 * @param[in, out] action 12633 * Shared RSS action to remove hash RX queue objects from. 12634 * 12635 * @return 12636 * Total number of references to hash RX queue objects stored in *action* 12637 * after this operation. 12638 * Expected to be 0 if no external references held. 12639 */ 12640 static int 12641 __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev, 12642 struct mlx5_shared_action_rss *shared_rss) 12643 { 12644 return __flow_dv_hrxqs_release(dev, &shared_rss->hrxq) + 12645 __flow_dv_hrxqs_release(dev, &shared_rss->hrxq_tunnel); 12646 } 12647 12648 /** 12649 * Setup shared RSS action. 12650 * Prepare set of hash RX queue objects sufficient to handle all valid 12651 * hash_fields combinations (see enum ibv_rx_hash_fields). 12652 * 12653 * @param[in] dev 12654 * Pointer to the Ethernet device structure. 12655 * @param[in] action_idx 12656 * Shared RSS action ipool index. 12657 * @param[in, out] action 12658 * Partially initialized shared RSS action. 12659 * @param[out] error 12660 * Perform verbose error reporting if not NULL. Initialized in case of 12661 * error only. 12662 * 12663 * @return 12664 * 0 on success, otherwise negative errno value. 12665 */ 12666 static int 12667 __flow_dv_action_rss_setup(struct rte_eth_dev *dev, 12668 uint32_t action_idx, 12669 struct mlx5_shared_action_rss *shared_rss, 12670 struct rte_flow_error *error) 12671 { 12672 struct mlx5_flow_rss_desc rss_desc = { 0 }; 12673 size_t i; 12674 int err; 12675 12676 if (mlx5_ind_table_obj_setup(dev, shared_rss->ind_tbl)) { 12677 return rte_flow_error_set(error, rte_errno, 12678 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12679 "cannot setup indirection table"); 12680 } 12681 memcpy(rss_desc.key, shared_rss->origin.key, MLX5_RSS_HASH_KEY_LEN); 12682 rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN; 12683 rss_desc.const_q = shared_rss->origin.queue; 12684 rss_desc.queue_num = shared_rss->origin.queue_num; 12685 /* Set non-zero value to indicate a shared RSS. */ 12686 rss_desc.shared_rss = action_idx; 12687 rss_desc.ind_tbl = shared_rss->ind_tbl; 12688 for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) { 12689 uint32_t hrxq_idx; 12690 uint64_t hash_fields = mlx5_rss_hash_fields[i]; 12691 int tunnel; 12692 12693 for (tunnel = 0; tunnel < 2; tunnel++) { 12694 rss_desc.tunnel = tunnel; 12695 rss_desc.hash_fields = hash_fields; 12696 hrxq_idx = mlx5_hrxq_get(dev, &rss_desc); 12697 if (!hrxq_idx) { 12698 rte_flow_error_set 12699 (error, rte_errno, 12700 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12701 "cannot get hash queue"); 12702 goto error_hrxq_new; 12703 } 12704 err = __flow_dv_action_rss_hrxq_set 12705 (shared_rss, hash_fields, tunnel, hrxq_idx); 12706 MLX5_ASSERT(!err); 12707 } 12708 } 12709 return 0; 12710 error_hrxq_new: 12711 err = rte_errno; 12712 __flow_dv_action_rss_hrxqs_release(dev, shared_rss); 12713 if (!mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true)) 12714 shared_rss->ind_tbl = NULL; 12715 rte_errno = err; 12716 return -rte_errno; 12717 } 12718 12719 /** 12720 * Create shared RSS action. 12721 * 12722 * @param[in] dev 12723 * Pointer to the Ethernet device structure. 12724 * @param[in] conf 12725 * Shared action configuration. 12726 * @param[in] rss 12727 * RSS action specification used to create shared action. 12728 * @param[out] error 12729 * Perform verbose error reporting if not NULL. Initialized in case of 12730 * error only. 12731 * 12732 * @return 12733 * A valid shared action ID in case of success, 0 otherwise and 12734 * rte_errno is set. 12735 */ 12736 static uint32_t 12737 __flow_dv_action_rss_create(struct rte_eth_dev *dev, 12738 const struct rte_flow_shared_action_conf *conf, 12739 const struct rte_flow_action_rss *rss, 12740 struct rte_flow_error *error) 12741 { 12742 struct mlx5_priv *priv = dev->data->dev_private; 12743 struct mlx5_shared_action_rss *shared_rss = NULL; 12744 void *queue = NULL; 12745 struct rte_flow_action_rss *origin; 12746 const uint8_t *rss_key; 12747 uint32_t queue_size = rss->queue_num * sizeof(uint16_t); 12748 uint32_t idx; 12749 12750 RTE_SET_USED(conf); 12751 queue = mlx5_malloc(0, RTE_ALIGN_CEIL(queue_size, sizeof(void *)), 12752 0, SOCKET_ID_ANY); 12753 shared_rss = mlx5_ipool_zmalloc 12754 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx); 12755 if (!shared_rss || !queue) { 12756 rte_flow_error_set(error, ENOMEM, 12757 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12758 "cannot allocate resource memory"); 12759 goto error_rss_init; 12760 } 12761 if (idx > (1u << MLX5_SHARED_ACTION_TYPE_OFFSET)) { 12762 rte_flow_error_set(error, E2BIG, 12763 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12764 "rss action number out of range"); 12765 goto error_rss_init; 12766 } 12767 shared_rss->ind_tbl = mlx5_malloc(MLX5_MEM_ZERO, 12768 sizeof(*shared_rss->ind_tbl), 12769 0, SOCKET_ID_ANY); 12770 if (!shared_rss->ind_tbl) { 12771 rte_flow_error_set(error, ENOMEM, 12772 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 12773 "cannot allocate resource memory"); 12774 goto error_rss_init; 12775 } 12776 memcpy(queue, rss->queue, queue_size); 12777 shared_rss->ind_tbl->queues = queue; 12778 shared_rss->ind_tbl->queues_n = rss->queue_num; 12779 origin = &shared_rss->origin; 12780 origin->func = rss->func; 12781 origin->level = rss->level; 12782 /* RSS type 0 indicates default RSS type (ETH_RSS_IP). */ 12783 origin->types = !rss->types ? ETH_RSS_IP : rss->types; 12784 /* NULL RSS key indicates default RSS key. */ 12785 rss_key = !rss->key ? rss_hash_default_key : rss->key; 12786 memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN); 12787 origin->key = &shared_rss->key[0]; 12788 origin->key_len = MLX5_RSS_HASH_KEY_LEN; 12789 origin->queue = queue; 12790 origin->queue_num = rss->queue_num; 12791 if (__flow_dv_action_rss_setup(dev, idx, shared_rss, error)) 12792 goto error_rss_init; 12793 rte_spinlock_init(&shared_rss->action_rss_sl); 12794 __atomic_add_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED); 12795 rte_spinlock_lock(&priv->shared_act_sl); 12796 ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 12797 &priv->rss_shared_actions, idx, shared_rss, next); 12798 rte_spinlock_unlock(&priv->shared_act_sl); 12799 return idx; 12800 error_rss_init: 12801 if (shared_rss) { 12802 if (shared_rss->ind_tbl) 12803 mlx5_free(shared_rss->ind_tbl); 12804 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 12805 idx); 12806 } 12807 if (queue) 12808 mlx5_free(queue); 12809 return 0; 12810 } 12811 12812 /** 12813 * Destroy the shared RSS action. 12814 * Release related hash RX queue objects. 12815 * 12816 * @param[in] dev 12817 * Pointer to the Ethernet device structure. 12818 * @param[in] idx 12819 * The shared RSS action object ID to be removed. 12820 * @param[out] error 12821 * Perform verbose error reporting if not NULL. Initialized in case of 12822 * error only. 12823 * 12824 * @return 12825 * 0 on success, otherwise negative errno value. 12826 */ 12827 static int 12828 __flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx, 12829 struct rte_flow_error *error) 12830 { 12831 struct mlx5_priv *priv = dev->data->dev_private; 12832 struct mlx5_shared_action_rss *shared_rss = 12833 mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx); 12834 uint32_t old_refcnt = 1; 12835 int remaining; 12836 uint16_t *queue = NULL; 12837 12838 if (!shared_rss) 12839 return rte_flow_error_set(error, EINVAL, 12840 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 12841 "invalid shared action"); 12842 remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss); 12843 if (remaining) 12844 return rte_flow_error_set(error, EBUSY, 12845 RTE_FLOW_ERROR_TYPE_ACTION, 12846 NULL, 12847 "shared rss hrxq has references"); 12848 if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt, 12849 0, 0, __ATOMIC_ACQUIRE, 12850 __ATOMIC_RELAXED)) 12851 return rte_flow_error_set(error, EBUSY, 12852 RTE_FLOW_ERROR_TYPE_ACTION, 12853 NULL, 12854 "shared rss has references"); 12855 queue = shared_rss->ind_tbl->queues; 12856 remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true); 12857 if (remaining) 12858 return rte_flow_error_set(error, EBUSY, 12859 RTE_FLOW_ERROR_TYPE_ACTION, 12860 NULL, 12861 "shared rss indirection table has" 12862 " references"); 12863 mlx5_free(queue); 12864 rte_spinlock_lock(&priv->shared_act_sl); 12865 ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 12866 &priv->rss_shared_actions, idx, shared_rss, next); 12867 rte_spinlock_unlock(&priv->shared_act_sl); 12868 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 12869 idx); 12870 return 0; 12871 } 12872 12873 /** 12874 * Create shared action, lock free, 12875 * (mutex should be acquired by caller). 12876 * Dispatcher for action type specific call. 12877 * 12878 * @param[in] dev 12879 * Pointer to the Ethernet device structure. 12880 * @param[in] conf 12881 * Shared action configuration. 12882 * @param[in] action 12883 * Action specification used to create shared action. 12884 * @param[out] error 12885 * Perform verbose error reporting if not NULL. Initialized in case of 12886 * error only. 12887 * 12888 * @return 12889 * A valid shared action handle in case of success, NULL otherwise and 12890 * rte_errno is set. 12891 */ 12892 static struct rte_flow_shared_action * 12893 flow_dv_action_create(struct rte_eth_dev *dev, 12894 const struct rte_flow_shared_action_conf *conf, 12895 const struct rte_flow_action *action, 12896 struct rte_flow_error *err) 12897 { 12898 uint32_t idx = 0; 12899 uint32_t ret = 0; 12900 12901 switch (action->type) { 12902 case RTE_FLOW_ACTION_TYPE_RSS: 12903 ret = __flow_dv_action_rss_create(dev, conf, action->conf, err); 12904 idx = (MLX5_SHARED_ACTION_TYPE_RSS << 12905 MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; 12906 break; 12907 case RTE_FLOW_ACTION_TYPE_AGE: 12908 ret = flow_dv_translate_create_aso_age(dev, action->conf, err); 12909 idx = (MLX5_SHARED_ACTION_TYPE_AGE << 12910 MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; 12911 if (ret) { 12912 struct mlx5_aso_age_action *aso_age = 12913 flow_aso_age_get_by_idx(dev, ret); 12914 12915 if (!aso_age->age_params.context) 12916 aso_age->age_params.context = 12917 (void *)(uintptr_t)idx; 12918 } 12919 break; 12920 default: 12921 rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 12922 NULL, "action type not supported"); 12923 break; 12924 } 12925 return ret ? (struct rte_flow_shared_action *)(uintptr_t)idx : NULL; 12926 } 12927 12928 /** 12929 * Destroy the shared action. 12930 * Release action related resources on the NIC and the memory. 12931 * Lock free, (mutex should be acquired by caller). 12932 * Dispatcher for action type specific call. 12933 * 12934 * @param[in] dev 12935 * Pointer to the Ethernet device structure. 12936 * @param[in] action 12937 * The shared action object to be removed. 12938 * @param[out] error 12939 * Perform verbose error reporting if not NULL. Initialized in case of 12940 * error only. 12941 * 12942 * @return 12943 * 0 on success, otherwise negative errno value. 12944 */ 12945 static int 12946 flow_dv_action_destroy(struct rte_eth_dev *dev, 12947 struct rte_flow_shared_action *action, 12948 struct rte_flow_error *error) 12949 { 12950 uint32_t act_idx = (uint32_t)(uintptr_t)action; 12951 uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET; 12952 uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1); 12953 int ret; 12954 12955 switch (type) { 12956 case MLX5_SHARED_ACTION_TYPE_RSS: 12957 return __flow_dv_action_rss_release(dev, idx, error); 12958 case MLX5_SHARED_ACTION_TYPE_AGE: 12959 ret = flow_dv_aso_age_release(dev, idx); 12960 if (ret) 12961 /* 12962 * In this case, the last flow has a reference will 12963 * actually release the age action. 12964 */ 12965 DRV_LOG(DEBUG, "Shared age action %" PRIu32 " was" 12966 " released with references %d.", idx, ret); 12967 return 0; 12968 default: 12969 return rte_flow_error_set(error, ENOTSUP, 12970 RTE_FLOW_ERROR_TYPE_ACTION, 12971 NULL, 12972 "action type not supported"); 12973 } 12974 } 12975 12976 /** 12977 * Updates in place shared RSS action configuration. 12978 * 12979 * @param[in] dev 12980 * Pointer to the Ethernet device structure. 12981 * @param[in] idx 12982 * The shared RSS action object ID to be updated. 12983 * @param[in] action_conf 12984 * RSS action specification used to modify *shared_rss*. 12985 * @param[out] error 12986 * Perform verbose error reporting if not NULL. Initialized in case of 12987 * error only. 12988 * 12989 * @return 12990 * 0 on success, otherwise negative errno value. 12991 * @note: currently only support update of RSS queues. 12992 */ 12993 static int 12994 __flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx, 12995 const struct rte_flow_action_rss *action_conf, 12996 struct rte_flow_error *error) 12997 { 12998 struct mlx5_priv *priv = dev->data->dev_private; 12999 struct mlx5_shared_action_rss *shared_rss = 13000 mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx); 13001 int ret = 0; 13002 void *queue = NULL; 13003 uint16_t *queue_old = NULL; 13004 uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t); 13005 13006 if (!shared_rss) 13007 return rte_flow_error_set(error, EINVAL, 13008 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 13009 "invalid shared action to update"); 13010 if (priv->obj_ops.ind_table_modify == NULL) 13011 return rte_flow_error_set(error, ENOTSUP, 13012 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 13013 "cannot modify indirection table"); 13014 queue = mlx5_malloc(MLX5_MEM_ZERO, 13015 RTE_ALIGN_CEIL(queue_size, sizeof(void *)), 13016 0, SOCKET_ID_ANY); 13017 if (!queue) 13018 return rte_flow_error_set(error, ENOMEM, 13019 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13020 NULL, 13021 "cannot allocate resource memory"); 13022 memcpy(queue, action_conf->queue, queue_size); 13023 MLX5_ASSERT(shared_rss->ind_tbl); 13024 rte_spinlock_lock(&shared_rss->action_rss_sl); 13025 queue_old = shared_rss->ind_tbl->queues; 13026 ret = mlx5_ind_table_obj_modify(dev, shared_rss->ind_tbl, 13027 queue, action_conf->queue_num, true); 13028 if (ret) { 13029 mlx5_free(queue); 13030 ret = rte_flow_error_set(error, rte_errno, 13031 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 13032 "cannot update indirection table"); 13033 } else { 13034 mlx5_free(queue_old); 13035 shared_rss->origin.queue = queue; 13036 shared_rss->origin.queue_num = action_conf->queue_num; 13037 } 13038 rte_spinlock_unlock(&shared_rss->action_rss_sl); 13039 return ret; 13040 } 13041 13042 /** 13043 * Updates in place shared action configuration, lock free, 13044 * (mutex should be acquired by caller). 13045 * 13046 * @param[in] dev 13047 * Pointer to the Ethernet device structure. 13048 * @param[in] action 13049 * The shared action object to be updated. 13050 * @param[in] action_conf 13051 * Action specification used to modify *action*. 13052 * *action_conf* should be of type correlating with type of the *action*, 13053 * otherwise considered as invalid. 13054 * @param[out] error 13055 * Perform verbose error reporting if not NULL. Initialized in case of 13056 * error only. 13057 * 13058 * @return 13059 * 0 on success, otherwise negative errno value. 13060 */ 13061 static int 13062 flow_dv_action_update(struct rte_eth_dev *dev, 13063 struct rte_flow_shared_action *action, 13064 const void *action_conf, 13065 struct rte_flow_error *err) 13066 { 13067 uint32_t act_idx = (uint32_t)(uintptr_t)action; 13068 uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET; 13069 uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1); 13070 13071 switch (type) { 13072 case MLX5_SHARED_ACTION_TYPE_RSS: 13073 return __flow_dv_action_rss_update(dev, idx, action_conf, err); 13074 default: 13075 return rte_flow_error_set(err, ENOTSUP, 13076 RTE_FLOW_ERROR_TYPE_ACTION, 13077 NULL, 13078 "action type update not supported"); 13079 } 13080 } 13081 13082 static int 13083 flow_dv_action_query(struct rte_eth_dev *dev, 13084 const struct rte_flow_shared_action *action, void *data, 13085 struct rte_flow_error *error) 13086 { 13087 struct mlx5_age_param *age_param; 13088 struct rte_flow_query_age *resp; 13089 uint32_t act_idx = (uint32_t)(uintptr_t)action; 13090 uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET; 13091 uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1); 13092 13093 switch (type) { 13094 case MLX5_SHARED_ACTION_TYPE_AGE: 13095 age_param = &flow_aso_age_get_by_idx(dev, idx)->age_params; 13096 resp = data; 13097 resp->aged = __atomic_load_n(&age_param->state, 13098 __ATOMIC_RELAXED) == AGE_TMOUT ? 13099 1 : 0; 13100 resp->sec_since_last_hit_valid = !resp->aged; 13101 if (resp->sec_since_last_hit_valid) 13102 resp->sec_since_last_hit = __atomic_load_n 13103 (&age_param->sec_since_last_hit, __ATOMIC_RELAXED); 13104 return 0; 13105 default: 13106 return rte_flow_error_set(error, ENOTSUP, 13107 RTE_FLOW_ERROR_TYPE_ACTION, 13108 NULL, 13109 "action type query not supported"); 13110 } 13111 } 13112 13113 /** 13114 * Query a dv flow rule for its statistics via devx. 13115 * 13116 * @param[in] dev 13117 * Pointer to Ethernet device. 13118 * @param[in] flow 13119 * Pointer to the sub flow. 13120 * @param[out] data 13121 * data retrieved by the query. 13122 * @param[out] error 13123 * Perform verbose error reporting if not NULL. 13124 * 13125 * @return 13126 * 0 on success, a negative errno value otherwise and rte_errno is set. 13127 */ 13128 static int 13129 flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow, 13130 void *data, struct rte_flow_error *error) 13131 { 13132 struct mlx5_priv *priv = dev->data->dev_private; 13133 struct rte_flow_query_count *qc = data; 13134 13135 if (!priv->config.devx) 13136 return rte_flow_error_set(error, ENOTSUP, 13137 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13138 NULL, 13139 "counters are not supported"); 13140 if (flow->counter) { 13141 uint64_t pkts, bytes; 13142 struct mlx5_flow_counter *cnt; 13143 13144 cnt = flow_dv_counter_get_by_idx(dev, flow->counter, 13145 NULL); 13146 int err = _flow_dv_query_count(dev, flow->counter, &pkts, 13147 &bytes); 13148 13149 if (err) 13150 return rte_flow_error_set(error, -err, 13151 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13152 NULL, "cannot read counters"); 13153 qc->hits_set = 1; 13154 qc->bytes_set = 1; 13155 qc->hits = pkts - cnt->hits; 13156 qc->bytes = bytes - cnt->bytes; 13157 if (qc->reset) { 13158 cnt->hits = pkts; 13159 cnt->bytes = bytes; 13160 } 13161 return 0; 13162 } 13163 return rte_flow_error_set(error, EINVAL, 13164 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13165 NULL, 13166 "counters are not available"); 13167 } 13168 13169 /** 13170 * Query a flow rule AGE action for aging information. 13171 * 13172 * @param[in] dev 13173 * Pointer to Ethernet device. 13174 * @param[in] flow 13175 * Pointer to the sub flow. 13176 * @param[out] data 13177 * data retrieved by the query. 13178 * @param[out] error 13179 * Perform verbose error reporting if not NULL. 13180 * 13181 * @return 13182 * 0 on success, a negative errno value otherwise and rte_errno is set. 13183 */ 13184 static int 13185 flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow, 13186 void *data, struct rte_flow_error *error) 13187 { 13188 struct rte_flow_query_age *resp = data; 13189 struct mlx5_age_param *age_param; 13190 13191 if (flow->age) { 13192 struct mlx5_aso_age_action *act = 13193 flow_aso_age_get_by_idx(dev, flow->age); 13194 13195 age_param = &act->age_params; 13196 } else if (flow->counter) { 13197 age_param = flow_dv_counter_idx_get_age(dev, flow->counter); 13198 13199 if (!age_param || !age_param->timeout) 13200 return rte_flow_error_set 13201 (error, EINVAL, 13202 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13203 NULL, "cannot read age data"); 13204 } else { 13205 return rte_flow_error_set(error, EINVAL, 13206 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13207 NULL, "age data not available"); 13208 } 13209 resp->aged = __atomic_load_n(&age_param->state, __ATOMIC_RELAXED) == 13210 AGE_TMOUT ? 1 : 0; 13211 resp->sec_since_last_hit_valid = !resp->aged; 13212 if (resp->sec_since_last_hit_valid) 13213 resp->sec_since_last_hit = __atomic_load_n 13214 (&age_param->sec_since_last_hit, __ATOMIC_RELAXED); 13215 return 0; 13216 } 13217 13218 /** 13219 * Query a flow. 13220 * 13221 * @see rte_flow_query() 13222 * @see rte_flow_ops 13223 */ 13224 static int 13225 flow_dv_query(struct rte_eth_dev *dev, 13226 struct rte_flow *flow __rte_unused, 13227 const struct rte_flow_action *actions __rte_unused, 13228 void *data __rte_unused, 13229 struct rte_flow_error *error __rte_unused) 13230 { 13231 int ret = -EINVAL; 13232 13233 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 13234 switch (actions->type) { 13235 case RTE_FLOW_ACTION_TYPE_VOID: 13236 break; 13237 case RTE_FLOW_ACTION_TYPE_COUNT: 13238 ret = flow_dv_query_count(dev, flow, data, error); 13239 break; 13240 case RTE_FLOW_ACTION_TYPE_AGE: 13241 ret = flow_dv_query_age(dev, flow, data, error); 13242 break; 13243 default: 13244 return rte_flow_error_set(error, ENOTSUP, 13245 RTE_FLOW_ERROR_TYPE_ACTION, 13246 actions, 13247 "action not supported"); 13248 } 13249 } 13250 return ret; 13251 } 13252 13253 /** 13254 * Destroy the meter table set. 13255 * Lock free, (mutex should be acquired by caller). 13256 * 13257 * @param[in] dev 13258 * Pointer to Ethernet device. 13259 * @param[in] tbl 13260 * Pointer to the meter table set. 13261 * 13262 * @return 13263 * Always 0. 13264 */ 13265 static int 13266 flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev, 13267 struct mlx5_meter_domains_infos *tbl) 13268 { 13269 struct mlx5_priv *priv = dev->data->dev_private; 13270 struct mlx5_meter_domains_infos *mtd = 13271 (struct mlx5_meter_domains_infos *)tbl; 13272 13273 if (!mtd || !priv->config.dv_flow_en) 13274 return 0; 13275 if (mtd->ingress.policer_rules[RTE_MTR_DROPPED]) 13276 claim_zero(mlx5_flow_os_destroy_flow 13277 (mtd->ingress.policer_rules[RTE_MTR_DROPPED])); 13278 if (mtd->egress.policer_rules[RTE_MTR_DROPPED]) 13279 claim_zero(mlx5_flow_os_destroy_flow 13280 (mtd->egress.policer_rules[RTE_MTR_DROPPED])); 13281 if (mtd->transfer.policer_rules[RTE_MTR_DROPPED]) 13282 claim_zero(mlx5_flow_os_destroy_flow 13283 (mtd->transfer.policer_rules[RTE_MTR_DROPPED])); 13284 if (mtd->egress.color_matcher) 13285 claim_zero(mlx5_flow_os_destroy_flow_matcher 13286 (mtd->egress.color_matcher)); 13287 if (mtd->egress.any_matcher) 13288 claim_zero(mlx5_flow_os_destroy_flow_matcher 13289 (mtd->egress.any_matcher)); 13290 if (mtd->egress.tbl) 13291 flow_dv_tbl_resource_release(MLX5_SH(dev), mtd->egress.tbl); 13292 if (mtd->egress.sfx_tbl) 13293 flow_dv_tbl_resource_release(MLX5_SH(dev), mtd->egress.sfx_tbl); 13294 if (mtd->ingress.color_matcher) 13295 claim_zero(mlx5_flow_os_destroy_flow_matcher 13296 (mtd->ingress.color_matcher)); 13297 if (mtd->ingress.any_matcher) 13298 claim_zero(mlx5_flow_os_destroy_flow_matcher 13299 (mtd->ingress.any_matcher)); 13300 if (mtd->ingress.tbl) 13301 flow_dv_tbl_resource_release(MLX5_SH(dev), mtd->ingress.tbl); 13302 if (mtd->ingress.sfx_tbl) 13303 flow_dv_tbl_resource_release(MLX5_SH(dev), 13304 mtd->ingress.sfx_tbl); 13305 if (mtd->transfer.color_matcher) 13306 claim_zero(mlx5_flow_os_destroy_flow_matcher 13307 (mtd->transfer.color_matcher)); 13308 if (mtd->transfer.any_matcher) 13309 claim_zero(mlx5_flow_os_destroy_flow_matcher 13310 (mtd->transfer.any_matcher)); 13311 if (mtd->transfer.tbl) 13312 flow_dv_tbl_resource_release(MLX5_SH(dev), mtd->transfer.tbl); 13313 if (mtd->transfer.sfx_tbl) 13314 flow_dv_tbl_resource_release(MLX5_SH(dev), 13315 mtd->transfer.sfx_tbl); 13316 if (mtd->drop_actn) 13317 claim_zero(mlx5_flow_os_destroy_flow_action(mtd->drop_actn)); 13318 mlx5_free(mtd); 13319 return 0; 13320 } 13321 13322 /* Number of meter flow actions, count and jump or count and drop. */ 13323 #define METER_ACTIONS 2 13324 13325 /** 13326 * Create specify domain meter table and suffix table. 13327 * 13328 * @param[in] dev 13329 * Pointer to Ethernet device. 13330 * @param[in,out] mtb 13331 * Pointer to DV meter table set. 13332 * @param[in] egress 13333 * Table attribute. 13334 * @param[in] transfer 13335 * Table attribute. 13336 * @param[in] color_reg_c_idx 13337 * Reg C index for color match. 13338 * 13339 * @return 13340 * 0 on success, -1 otherwise and rte_errno is set. 13341 */ 13342 static int 13343 flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev, 13344 struct mlx5_meter_domains_infos *mtb, 13345 uint8_t egress, uint8_t transfer, 13346 uint32_t color_reg_c_idx) 13347 { 13348 struct mlx5_priv *priv = dev->data->dev_private; 13349 struct mlx5_dev_ctx_shared *sh = priv->sh; 13350 struct mlx5_flow_dv_match_params mask = { 13351 .size = sizeof(mask.buf), 13352 }; 13353 struct mlx5_flow_dv_match_params value = { 13354 .size = sizeof(value.buf), 13355 }; 13356 struct mlx5dv_flow_matcher_attr dv_attr = { 13357 .type = IBV_FLOW_ATTR_NORMAL, 13358 .priority = 0, 13359 .match_criteria_enable = 0, 13360 .match_mask = (void *)&mask, 13361 }; 13362 void *actions[METER_ACTIONS]; 13363 struct mlx5_meter_domain_info *dtb; 13364 struct rte_flow_error error; 13365 int i = 0; 13366 int ret; 13367 13368 if (transfer) 13369 dtb = &mtb->transfer; 13370 else if (egress) 13371 dtb = &mtb->egress; 13372 else 13373 dtb = &mtb->ingress; 13374 /* Create the meter table with METER level. */ 13375 dtb->tbl = flow_dv_tbl_resource_get(dev, MLX5_FLOW_TABLE_LEVEL_METER, 13376 egress, transfer, false, NULL, 0, 13377 0, &error); 13378 if (!dtb->tbl) { 13379 DRV_LOG(ERR, "Failed to create meter policer table."); 13380 return -1; 13381 } 13382 /* Create the meter suffix table with SUFFIX level. */ 13383 dtb->sfx_tbl = flow_dv_tbl_resource_get(dev, 13384 MLX5_FLOW_TABLE_LEVEL_SUFFIX, 13385 egress, transfer, false, NULL, 0, 13386 0, &error); 13387 if (!dtb->sfx_tbl) { 13388 DRV_LOG(ERR, "Failed to create meter suffix table."); 13389 return -1; 13390 } 13391 /* Create matchers, Any and Color. */ 13392 dv_attr.priority = 3; 13393 dv_attr.match_criteria_enable = 0; 13394 ret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, dtb->tbl->obj, 13395 &dtb->any_matcher); 13396 if (ret) { 13397 DRV_LOG(ERR, "Failed to create meter" 13398 " policer default matcher."); 13399 goto error_exit; 13400 } 13401 dv_attr.priority = 0; 13402 dv_attr.match_criteria_enable = 13403 1 << MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT; 13404 flow_dv_match_meta_reg(mask.buf, value.buf, color_reg_c_idx, 13405 rte_col_2_mlx5_col(RTE_COLORS), UINT8_MAX); 13406 ret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, dtb->tbl->obj, 13407 &dtb->color_matcher); 13408 if (ret) { 13409 DRV_LOG(ERR, "Failed to create meter policer color matcher."); 13410 goto error_exit; 13411 } 13412 if (mtb->count_actns[RTE_MTR_DROPPED]) 13413 actions[i++] = mtb->count_actns[RTE_MTR_DROPPED]; 13414 actions[i++] = mtb->drop_actn; 13415 /* Default rule: lowest priority, match any, actions: drop. */ 13416 ret = mlx5_flow_os_create_flow(dtb->any_matcher, (void *)&value, i, 13417 actions, 13418 &dtb->policer_rules[RTE_MTR_DROPPED]); 13419 if (ret) { 13420 DRV_LOG(ERR, "Failed to create meter policer drop rule."); 13421 goto error_exit; 13422 } 13423 return 0; 13424 error_exit: 13425 return -1; 13426 } 13427 13428 /** 13429 * Create the needed meter and suffix tables. 13430 * Lock free, (mutex should be acquired by caller). 13431 * 13432 * @param[in] dev 13433 * Pointer to Ethernet device. 13434 * @param[in] fm 13435 * Pointer to the flow meter. 13436 * 13437 * @return 13438 * Pointer to table set on success, NULL otherwise and rte_errno is set. 13439 */ 13440 static struct mlx5_meter_domains_infos * 13441 flow_dv_create_mtr_tbl(struct rte_eth_dev *dev, 13442 const struct mlx5_flow_meter *fm) 13443 { 13444 struct mlx5_priv *priv = dev->data->dev_private; 13445 struct mlx5_meter_domains_infos *mtb; 13446 int ret; 13447 int i; 13448 13449 if (!priv->mtr_en) { 13450 rte_errno = ENOTSUP; 13451 return NULL; 13452 } 13453 mtb = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*mtb), 0, SOCKET_ID_ANY); 13454 if (!mtb) { 13455 DRV_LOG(ERR, "Failed to allocate memory for meter."); 13456 return NULL; 13457 } 13458 /* Create meter count actions */ 13459 for (i = 0; i <= RTE_MTR_DROPPED; i++) { 13460 struct mlx5_flow_counter *cnt; 13461 if (!fm->policer_stats.cnt[i]) 13462 continue; 13463 cnt = flow_dv_counter_get_by_idx(dev, 13464 fm->policer_stats.cnt[i], NULL); 13465 mtb->count_actns[i] = cnt->action; 13466 } 13467 /* Create drop action. */ 13468 ret = mlx5_flow_os_create_flow_action_drop(&mtb->drop_actn); 13469 if (ret) { 13470 DRV_LOG(ERR, "Failed to create drop action."); 13471 goto error_exit; 13472 } 13473 /* Egress meter table. */ 13474 ret = flow_dv_prepare_mtr_tables(dev, mtb, 1, 0, priv->mtr_color_reg); 13475 if (ret) { 13476 DRV_LOG(ERR, "Failed to prepare egress meter table."); 13477 goto error_exit; 13478 } 13479 /* Ingress meter table. */ 13480 ret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 0, priv->mtr_color_reg); 13481 if (ret) { 13482 DRV_LOG(ERR, "Failed to prepare ingress meter table."); 13483 goto error_exit; 13484 } 13485 /* FDB meter table. */ 13486 if (priv->config.dv_esw_en) { 13487 ret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 1, 13488 priv->mtr_color_reg); 13489 if (ret) { 13490 DRV_LOG(ERR, "Failed to prepare fdb meter table."); 13491 goto error_exit; 13492 } 13493 } 13494 return mtb; 13495 error_exit: 13496 flow_dv_destroy_mtr_tbl(dev, mtb); 13497 return NULL; 13498 } 13499 13500 /** 13501 * Destroy domain policer rule. 13502 * 13503 * @param[in] dt 13504 * Pointer to domain table. 13505 */ 13506 static void 13507 flow_dv_destroy_domain_policer_rule(struct mlx5_meter_domain_info *dt) 13508 { 13509 int i; 13510 13511 for (i = 0; i < RTE_MTR_DROPPED; i++) { 13512 if (dt->policer_rules[i]) { 13513 claim_zero(mlx5_flow_os_destroy_flow 13514 (dt->policer_rules[i])); 13515 dt->policer_rules[i] = NULL; 13516 } 13517 } 13518 if (dt->jump_actn) { 13519 claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn)); 13520 dt->jump_actn = NULL; 13521 } 13522 } 13523 13524 /** 13525 * Destroy policer rules. 13526 * 13527 * @param[in] dev 13528 * Pointer to Ethernet device. 13529 * @param[in] fm 13530 * Pointer to flow meter structure. 13531 * @param[in] attr 13532 * Pointer to flow attributes. 13533 * 13534 * @return 13535 * Always 0. 13536 */ 13537 static int 13538 flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused, 13539 const struct mlx5_flow_meter *fm, 13540 const struct rte_flow_attr *attr) 13541 { 13542 struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL; 13543 13544 if (!mtb) 13545 return 0; 13546 if (attr->egress) 13547 flow_dv_destroy_domain_policer_rule(&mtb->egress); 13548 if (attr->ingress) 13549 flow_dv_destroy_domain_policer_rule(&mtb->ingress); 13550 if (attr->transfer) 13551 flow_dv_destroy_domain_policer_rule(&mtb->transfer); 13552 return 0; 13553 } 13554 13555 /** 13556 * Create specify domain meter policer rule. 13557 * 13558 * @param[in] fm 13559 * Pointer to flow meter structure. 13560 * @param[in] mtb 13561 * Pointer to DV meter table set. 13562 * @param[in] mtr_reg_c 13563 * Color match REG_C. 13564 * 13565 * @return 13566 * 0 on success, -1 otherwise. 13567 */ 13568 static int 13569 flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm, 13570 struct mlx5_meter_domain_info *dtb, 13571 uint8_t mtr_reg_c) 13572 { 13573 struct mlx5_flow_dv_match_params matcher = { 13574 .size = sizeof(matcher.buf), 13575 }; 13576 struct mlx5_flow_dv_match_params value = { 13577 .size = sizeof(value.buf), 13578 }; 13579 struct mlx5_meter_domains_infos *mtb = fm->mfts; 13580 void *actions[METER_ACTIONS]; 13581 int i; 13582 int ret = 0; 13583 13584 /* Create jump action. */ 13585 if (!dtb->jump_actn) 13586 ret = mlx5_flow_os_create_flow_action_dest_flow_tbl 13587 (dtb->sfx_tbl->obj, &dtb->jump_actn); 13588 if (ret) { 13589 DRV_LOG(ERR, "Failed to create policer jump action."); 13590 goto error; 13591 } 13592 for (i = 0; i < RTE_MTR_DROPPED; i++) { 13593 int j = 0; 13594 13595 flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_reg_c, 13596 rte_col_2_mlx5_col(i), UINT8_MAX); 13597 if (mtb->count_actns[i]) 13598 actions[j++] = mtb->count_actns[i]; 13599 if (fm->action[i] == MTR_POLICER_ACTION_DROP) 13600 actions[j++] = mtb->drop_actn; 13601 else 13602 actions[j++] = dtb->jump_actn; 13603 ret = mlx5_flow_os_create_flow(dtb->color_matcher, 13604 (void *)&value, j, actions, 13605 &dtb->policer_rules[i]); 13606 if (ret) { 13607 DRV_LOG(ERR, "Failed to create policer rule."); 13608 goto error; 13609 } 13610 } 13611 return 0; 13612 error: 13613 rte_errno = errno; 13614 return -1; 13615 } 13616 13617 /** 13618 * Create policer rules. 13619 * 13620 * @param[in] dev 13621 * Pointer to Ethernet device. 13622 * @param[in] fm 13623 * Pointer to flow meter structure. 13624 * @param[in] attr 13625 * Pointer to flow attributes. 13626 * 13627 * @return 13628 * 0 on success, -1 otherwise. 13629 */ 13630 static int 13631 flow_dv_create_policer_rules(struct rte_eth_dev *dev, 13632 struct mlx5_flow_meter *fm, 13633 const struct rte_flow_attr *attr) 13634 { 13635 struct mlx5_priv *priv = dev->data->dev_private; 13636 struct mlx5_meter_domains_infos *mtb = fm->mfts; 13637 int ret; 13638 13639 if (attr->egress) { 13640 ret = flow_dv_create_policer_forward_rule(fm, &mtb->egress, 13641 priv->mtr_color_reg); 13642 if (ret) { 13643 DRV_LOG(ERR, "Failed to create egress policer."); 13644 goto error; 13645 } 13646 } 13647 if (attr->ingress) { 13648 ret = flow_dv_create_policer_forward_rule(fm, &mtb->ingress, 13649 priv->mtr_color_reg); 13650 if (ret) { 13651 DRV_LOG(ERR, "Failed to create ingress policer."); 13652 goto error; 13653 } 13654 } 13655 if (attr->transfer) { 13656 ret = flow_dv_create_policer_forward_rule(fm, &mtb->transfer, 13657 priv->mtr_color_reg); 13658 if (ret) { 13659 DRV_LOG(ERR, "Failed to create transfer policer."); 13660 goto error; 13661 } 13662 } 13663 return 0; 13664 error: 13665 flow_dv_destroy_policer_rules(dev, fm, attr); 13666 return -1; 13667 } 13668 13669 /** 13670 * Validate the batch counter support in root table. 13671 * 13672 * Create a simple flow with invalid counter and drop action on root table to 13673 * validate if batch counter with offset on root table is supported or not. 13674 * 13675 * @param[in] dev 13676 * Pointer to rte_eth_dev structure. 13677 * 13678 * @return 13679 * 0 on success, a negative errno value otherwise and rte_errno is set. 13680 */ 13681 int 13682 mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev) 13683 { 13684 struct mlx5_priv *priv = dev->data->dev_private; 13685 struct mlx5_dev_ctx_shared *sh = priv->sh; 13686 struct mlx5_flow_dv_match_params mask = { 13687 .size = sizeof(mask.buf), 13688 }; 13689 struct mlx5_flow_dv_match_params value = { 13690 .size = sizeof(value.buf), 13691 }; 13692 struct mlx5dv_flow_matcher_attr dv_attr = { 13693 .type = IBV_FLOW_ATTR_NORMAL, 13694 .priority = 0, 13695 .match_criteria_enable = 0, 13696 .match_mask = (void *)&mask, 13697 }; 13698 void *actions[2] = { 0 }; 13699 struct mlx5_flow_tbl_resource *tbl = NULL; 13700 struct mlx5_devx_obj *dcs = NULL; 13701 void *matcher = NULL; 13702 void *flow = NULL; 13703 int ret = -1; 13704 13705 tbl = flow_dv_tbl_resource_get(dev, 0, 0, 0, false, NULL, 0, 0, NULL); 13706 if (!tbl) 13707 goto err; 13708 dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->ctx, 0x4); 13709 if (!dcs) 13710 goto err; 13711 ret = mlx5_flow_os_create_flow_action_count(dcs->obj, UINT16_MAX, 13712 &actions[0]); 13713 if (ret) 13714 goto err; 13715 actions[1] = priv->drop_queue.hrxq->action; 13716 dv_attr.match_criteria_enable = flow_dv_matcher_enable(mask.buf); 13717 ret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, tbl->obj, 13718 &matcher); 13719 if (ret) 13720 goto err; 13721 ret = mlx5_flow_os_create_flow(matcher, (void *)&value, 2, 13722 actions, &flow); 13723 err: 13724 /* 13725 * If batch counter with offset is not supported, the driver will not 13726 * validate the invalid offset value, flow create should success. 13727 * In this case, it means batch counter is not supported in root table. 13728 * 13729 * Otherwise, if flow create is failed, counter offset is supported. 13730 */ 13731 if (flow) { 13732 DRV_LOG(INFO, "Batch counter is not supported in root " 13733 "table. Switch to fallback mode."); 13734 rte_errno = ENOTSUP; 13735 ret = -rte_errno; 13736 claim_zero(mlx5_flow_os_destroy_flow(flow)); 13737 } else { 13738 /* Check matcher to make sure validate fail at flow create. */ 13739 if (!matcher || (matcher && errno != EINVAL)) 13740 DRV_LOG(ERR, "Unexpected error in counter offset " 13741 "support detection"); 13742 ret = 0; 13743 } 13744 if (actions[0]) 13745 claim_zero(mlx5_flow_os_destroy_flow_action(actions[0])); 13746 if (matcher) 13747 claim_zero(mlx5_flow_os_destroy_flow_matcher(matcher)); 13748 if (tbl) 13749 flow_dv_tbl_resource_release(MLX5_SH(dev), tbl); 13750 if (dcs) 13751 claim_zero(mlx5_devx_cmd_destroy(dcs)); 13752 return ret; 13753 } 13754 13755 /** 13756 * Query a devx counter. 13757 * 13758 * @param[in] dev 13759 * Pointer to the Ethernet device structure. 13760 * @param[in] cnt 13761 * Index to the flow counter. 13762 * @param[in] clear 13763 * Set to clear the counter statistics. 13764 * @param[out] pkts 13765 * The statistics value of packets. 13766 * @param[out] bytes 13767 * The statistics value of bytes. 13768 * 13769 * @return 13770 * 0 on success, otherwise return -1. 13771 */ 13772 static int 13773 flow_dv_counter_query(struct rte_eth_dev *dev, uint32_t counter, bool clear, 13774 uint64_t *pkts, uint64_t *bytes) 13775 { 13776 struct mlx5_priv *priv = dev->data->dev_private; 13777 struct mlx5_flow_counter *cnt; 13778 uint64_t inn_pkts, inn_bytes; 13779 int ret; 13780 13781 if (!priv->config.devx) 13782 return -1; 13783 13784 ret = _flow_dv_query_count(dev, counter, &inn_pkts, &inn_bytes); 13785 if (ret) 13786 return -1; 13787 cnt = flow_dv_counter_get_by_idx(dev, counter, NULL); 13788 *pkts = inn_pkts - cnt->hits; 13789 *bytes = inn_bytes - cnt->bytes; 13790 if (clear) { 13791 cnt->hits = inn_pkts; 13792 cnt->bytes = inn_bytes; 13793 } 13794 return 0; 13795 } 13796 13797 /** 13798 * Get aged-out flows. 13799 * 13800 * @param[in] dev 13801 * Pointer to the Ethernet device structure. 13802 * @param[in] context 13803 * The address of an array of pointers to the aged-out flows contexts. 13804 * @param[in] nb_contexts 13805 * The length of context array pointers. 13806 * @param[out] error 13807 * Perform verbose error reporting if not NULL. Initialized in case of 13808 * error only. 13809 * 13810 * @return 13811 * how many contexts get in success, otherwise negative errno value. 13812 * if nb_contexts is 0, return the amount of all aged contexts. 13813 * if nb_contexts is not 0 , return the amount of aged flows reported 13814 * in the context array. 13815 * @note: only stub for now 13816 */ 13817 static int 13818 flow_get_aged_flows(struct rte_eth_dev *dev, 13819 void **context, 13820 uint32_t nb_contexts, 13821 struct rte_flow_error *error) 13822 { 13823 struct mlx5_priv *priv = dev->data->dev_private; 13824 struct mlx5_age_info *age_info; 13825 struct mlx5_age_param *age_param; 13826 struct mlx5_flow_counter *counter; 13827 struct mlx5_aso_age_action *act; 13828 int nb_flows = 0; 13829 13830 if (nb_contexts && !context) 13831 return rte_flow_error_set(error, EINVAL, 13832 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13833 NULL, "empty context"); 13834 age_info = GET_PORT_AGE_INFO(priv); 13835 rte_spinlock_lock(&age_info->aged_sl); 13836 LIST_FOREACH(act, &age_info->aged_aso, next) { 13837 nb_flows++; 13838 if (nb_contexts) { 13839 context[nb_flows - 1] = 13840 act->age_params.context; 13841 if (!(--nb_contexts)) 13842 break; 13843 } 13844 } 13845 TAILQ_FOREACH(counter, &age_info->aged_counters, next) { 13846 nb_flows++; 13847 if (nb_contexts) { 13848 age_param = MLX5_CNT_TO_AGE(counter); 13849 context[nb_flows - 1] = age_param->context; 13850 if (!(--nb_contexts)) 13851 break; 13852 } 13853 } 13854 rte_spinlock_unlock(&age_info->aged_sl); 13855 MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER); 13856 return nb_flows; 13857 } 13858 13859 /* 13860 * Mutex-protected thunk to lock-free flow_dv_counter_alloc(). 13861 */ 13862 static uint32_t 13863 flow_dv_counter_allocate(struct rte_eth_dev *dev) 13864 { 13865 return flow_dv_counter_alloc(dev, 0); 13866 } 13867 13868 /** 13869 * Validate shared action. 13870 * Dispatcher for action type specific validation. 13871 * 13872 * @param[in] dev 13873 * Pointer to the Ethernet device structure. 13874 * @param[in] conf 13875 * Shared action configuration. 13876 * @param[in] action 13877 * The shared action object to validate. 13878 * @param[out] error 13879 * Perform verbose error reporting if not NULL. Initialized in case of 13880 * error only. 13881 * 13882 * @return 13883 * 0 on success, otherwise negative errno value. 13884 */ 13885 static int 13886 flow_dv_action_validate(struct rte_eth_dev *dev, 13887 const struct rte_flow_shared_action_conf *conf, 13888 const struct rte_flow_action *action, 13889 struct rte_flow_error *err) 13890 { 13891 struct mlx5_priv *priv = dev->data->dev_private; 13892 13893 RTE_SET_USED(conf); 13894 switch (action->type) { 13895 case RTE_FLOW_ACTION_TYPE_RSS: 13896 /* 13897 * priv->obj_ops is set according to driver capabilities. 13898 * When DevX capabilities are 13899 * sufficient, it is set to devx_obj_ops. 13900 * Otherwise, it is set to ibv_obj_ops. 13901 * ibv_obj_ops doesn't support ind_table_modify operation. 13902 * In this case the shared RSS action can't be used. 13903 */ 13904 if (priv->obj_ops.ind_table_modify == NULL) 13905 return rte_flow_error_set 13906 (err, ENOTSUP, 13907 RTE_FLOW_ERROR_TYPE_ACTION, 13908 NULL, 13909 "shared RSS action not supported"); 13910 return mlx5_validate_action_rss(dev, action, err); 13911 case RTE_FLOW_ACTION_TYPE_AGE: 13912 if (!priv->sh->aso_age_mng) 13913 return rte_flow_error_set(err, ENOTSUP, 13914 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 13915 NULL, 13916 "shared age action not supported"); 13917 return flow_dv_validate_action_age(0, action, dev, err); 13918 default: 13919 return rte_flow_error_set(err, ENOTSUP, 13920 RTE_FLOW_ERROR_TYPE_ACTION, 13921 NULL, 13922 "action type not supported"); 13923 } 13924 } 13925 13926 static int 13927 flow_dv_sync_domain(struct rte_eth_dev *dev, uint32_t domains, uint32_t flags) 13928 { 13929 struct mlx5_priv *priv = dev->data->dev_private; 13930 int ret = 0; 13931 13932 if ((domains & MLX5_DOMAIN_BIT_NIC_RX) && priv->sh->rx_domain != NULL) { 13933 ret = mlx5_os_flow_dr_sync_domain(priv->sh->rx_domain, 13934 flags); 13935 if (ret != 0) 13936 return ret; 13937 } 13938 if ((domains & MLX5_DOMAIN_BIT_NIC_TX) && priv->sh->tx_domain != NULL) { 13939 ret = mlx5_os_flow_dr_sync_domain(priv->sh->tx_domain, flags); 13940 if (ret != 0) 13941 return ret; 13942 } 13943 if ((domains & MLX5_DOMAIN_BIT_FDB) && priv->sh->fdb_domain != NULL) { 13944 ret = mlx5_os_flow_dr_sync_domain(priv->sh->fdb_domain, flags); 13945 if (ret != 0) 13946 return ret; 13947 } 13948 return 0; 13949 } 13950 13951 const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = { 13952 .validate = flow_dv_validate, 13953 .prepare = flow_dv_prepare, 13954 .translate = flow_dv_translate, 13955 .apply = flow_dv_apply, 13956 .remove = flow_dv_remove, 13957 .destroy = flow_dv_destroy, 13958 .query = flow_dv_query, 13959 .create_mtr_tbls = flow_dv_create_mtr_tbl, 13960 .destroy_mtr_tbls = flow_dv_destroy_mtr_tbl, 13961 .create_policer_rules = flow_dv_create_policer_rules, 13962 .destroy_policer_rules = flow_dv_destroy_policer_rules, 13963 .counter_alloc = flow_dv_counter_allocate, 13964 .counter_free = flow_dv_counter_free, 13965 .counter_query = flow_dv_counter_query, 13966 .get_aged_flows = flow_get_aged_flows, 13967 .action_validate = flow_dv_action_validate, 13968 .action_create = flow_dv_action_create, 13969 .action_destroy = flow_dv_action_destroy, 13970 .action_update = flow_dv_action_update, 13971 .action_query = flow_dv_action_query, 13972 .sync_domain = flow_dv_sync_domain, 13973 }; 13974 13975 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 13976 13977