1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018-2021 NXP 3 */ 4 5 #include <sys/queue.h> 6 #include <stdio.h> 7 #include <errno.h> 8 #include <stdint.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <stdarg.h> 12 13 #include <rte_ethdev.h> 14 #include <rte_log.h> 15 #include <rte_malloc.h> 16 #include <rte_flow_driver.h> 17 #include <rte_tailq.h> 18 19 #include <fsl_dpni.h> 20 #include <fsl_dpkg.h> 21 22 #include <dpaa2_ethdev.h> 23 #include <dpaa2_pmd_logs.h> 24 25 /* Workaround to discriminate the UDP/TCP/SCTP 26 * with next protocol of l3. 27 * MC/WRIOP are not able to identify 28 * the l4 protocol with l4 ports. 29 */ 30 int mc_l4_port_identification; 31 32 static char *dpaa2_flow_control_log; 33 static uint16_t dpaa2_flow_miss_flow_id = 34 DPNI_FS_MISS_DROP; 35 36 #define FIXED_ENTRY_SIZE DPNI_MAX_KEY_SIZE 37 38 enum flow_rule_ipaddr_type { 39 FLOW_NONE_IPADDR, 40 FLOW_IPV4_ADDR, 41 FLOW_IPV6_ADDR 42 }; 43 44 struct flow_rule_ipaddr { 45 enum flow_rule_ipaddr_type ipaddr_type; 46 int qos_ipsrc_offset; 47 int qos_ipdst_offset; 48 int fs_ipsrc_offset; 49 int fs_ipdst_offset; 50 }; 51 52 struct rte_flow { 53 LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ 54 struct dpni_rule_cfg qos_rule; 55 struct dpni_rule_cfg fs_rule; 56 uint8_t qos_real_key_size; 57 uint8_t fs_real_key_size; 58 uint8_t tc_id; /** Traffic Class ID. */ 59 uint8_t tc_index; /** index within this Traffic Class. */ 60 enum rte_flow_action_type action; 61 /* Special for IP address to specify the offset 62 * in key/mask. 63 */ 64 struct flow_rule_ipaddr ipaddr_rule; 65 struct dpni_fs_action_cfg action_cfg; 66 }; 67 68 static const 69 enum rte_flow_item_type dpaa2_supported_pattern_type[] = { 70 RTE_FLOW_ITEM_TYPE_END, 71 RTE_FLOW_ITEM_TYPE_ETH, 72 RTE_FLOW_ITEM_TYPE_VLAN, 73 RTE_FLOW_ITEM_TYPE_IPV4, 74 RTE_FLOW_ITEM_TYPE_IPV6, 75 RTE_FLOW_ITEM_TYPE_ICMP, 76 RTE_FLOW_ITEM_TYPE_UDP, 77 RTE_FLOW_ITEM_TYPE_TCP, 78 RTE_FLOW_ITEM_TYPE_SCTP, 79 RTE_FLOW_ITEM_TYPE_GRE, 80 }; 81 82 static const 83 enum rte_flow_action_type dpaa2_supported_action_type[] = { 84 RTE_FLOW_ACTION_TYPE_END, 85 RTE_FLOW_ACTION_TYPE_QUEUE, 86 RTE_FLOW_ACTION_TYPE_PHY_PORT, 87 RTE_FLOW_ACTION_TYPE_PORT_ID, 88 RTE_FLOW_ACTION_TYPE_RSS 89 }; 90 91 static const 92 enum rte_flow_action_type dpaa2_supported_fs_action_type[] = { 93 RTE_FLOW_ACTION_TYPE_QUEUE, 94 RTE_FLOW_ACTION_TYPE_PHY_PORT, 95 RTE_FLOW_ACTION_TYPE_PORT_ID 96 }; 97 98 /* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/ 99 #define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1) 100 101 #ifndef __cplusplus 102 static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = { 103 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 104 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", 105 .type = RTE_BE16(0xffff), 106 }; 107 108 static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = { 109 .tci = RTE_BE16(0xffff), 110 }; 111 112 static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = { 113 .hdr.src_addr = RTE_BE32(0xffffffff), 114 .hdr.dst_addr = RTE_BE32(0xffffffff), 115 .hdr.next_proto_id = 0xff, 116 }; 117 118 static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = { 119 .hdr = { 120 .src_addr = 121 "\xff\xff\xff\xff\xff\xff\xff\xff" 122 "\xff\xff\xff\xff\xff\xff\xff\xff", 123 .dst_addr = 124 "\xff\xff\xff\xff\xff\xff\xff\xff" 125 "\xff\xff\xff\xff\xff\xff\xff\xff", 126 .proto = 0xff 127 }, 128 }; 129 130 static const struct rte_flow_item_icmp dpaa2_flow_item_icmp_mask = { 131 .hdr.icmp_type = 0xff, 132 .hdr.icmp_code = 0xff, 133 }; 134 135 static const struct rte_flow_item_udp dpaa2_flow_item_udp_mask = { 136 .hdr = { 137 .src_port = RTE_BE16(0xffff), 138 .dst_port = RTE_BE16(0xffff), 139 }, 140 }; 141 142 static const struct rte_flow_item_tcp dpaa2_flow_item_tcp_mask = { 143 .hdr = { 144 .src_port = RTE_BE16(0xffff), 145 .dst_port = RTE_BE16(0xffff), 146 }, 147 }; 148 149 static const struct rte_flow_item_sctp dpaa2_flow_item_sctp_mask = { 150 .hdr = { 151 .src_port = RTE_BE16(0xffff), 152 .dst_port = RTE_BE16(0xffff), 153 }, 154 }; 155 156 static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { 157 .protocol = RTE_BE16(0xffff), 158 }; 159 160 #endif 161 162 static inline void dpaa2_prot_field_string( 163 enum net_prot prot, uint32_t field, 164 char *string) 165 { 166 if (!dpaa2_flow_control_log) 167 return; 168 169 if (prot == NET_PROT_ETH) { 170 strcpy(string, "eth"); 171 if (field == NH_FLD_ETH_DA) 172 strcat(string, ".dst"); 173 else if (field == NH_FLD_ETH_SA) 174 strcat(string, ".src"); 175 else if (field == NH_FLD_ETH_TYPE) 176 strcat(string, ".type"); 177 else 178 strcat(string, ".unknown field"); 179 } else if (prot == NET_PROT_VLAN) { 180 strcpy(string, "vlan"); 181 if (field == NH_FLD_VLAN_TCI) 182 strcat(string, ".tci"); 183 else 184 strcat(string, ".unknown field"); 185 } else if (prot == NET_PROT_IP) { 186 strcpy(string, "ip"); 187 if (field == NH_FLD_IP_SRC) 188 strcat(string, ".src"); 189 else if (field == NH_FLD_IP_DST) 190 strcat(string, ".dst"); 191 else if (field == NH_FLD_IP_PROTO) 192 strcat(string, ".proto"); 193 else 194 strcat(string, ".unknown field"); 195 } else if (prot == NET_PROT_TCP) { 196 strcpy(string, "tcp"); 197 if (field == NH_FLD_TCP_PORT_SRC) 198 strcat(string, ".src"); 199 else if (field == NH_FLD_TCP_PORT_DST) 200 strcat(string, ".dst"); 201 else 202 strcat(string, ".unknown field"); 203 } else if (prot == NET_PROT_UDP) { 204 strcpy(string, "udp"); 205 if (field == NH_FLD_UDP_PORT_SRC) 206 strcat(string, ".src"); 207 else if (field == NH_FLD_UDP_PORT_DST) 208 strcat(string, ".dst"); 209 else 210 strcat(string, ".unknown field"); 211 } else if (prot == NET_PROT_ICMP) { 212 strcpy(string, "icmp"); 213 if (field == NH_FLD_ICMP_TYPE) 214 strcat(string, ".type"); 215 else if (field == NH_FLD_ICMP_CODE) 216 strcat(string, ".code"); 217 else 218 strcat(string, ".unknown field"); 219 } else if (prot == NET_PROT_SCTP) { 220 strcpy(string, "sctp"); 221 if (field == NH_FLD_SCTP_PORT_SRC) 222 strcat(string, ".src"); 223 else if (field == NH_FLD_SCTP_PORT_DST) 224 strcat(string, ".dst"); 225 else 226 strcat(string, ".unknown field"); 227 } else if (prot == NET_PROT_GRE) { 228 strcpy(string, "gre"); 229 if (field == NH_FLD_GRE_TYPE) 230 strcat(string, ".type"); 231 else 232 strcat(string, ".unknown field"); 233 } else { 234 strcpy(string, "unknown protocol"); 235 } 236 } 237 238 static inline void dpaa2_flow_qos_table_extracts_log( 239 const struct dpaa2_dev_priv *priv) 240 { 241 int idx; 242 char string[32]; 243 244 if (!dpaa2_flow_control_log) 245 return; 246 247 printf("Setup QoS table: number of extracts: %d\r\n", 248 priv->extract.qos_key_extract.dpkg.num_extracts); 249 for (idx = 0; idx < priv->extract.qos_key_extract.dpkg.num_extracts; 250 idx++) { 251 dpaa2_prot_field_string(priv->extract.qos_key_extract.dpkg 252 .extracts[idx].extract.from_hdr.prot, 253 priv->extract.qos_key_extract.dpkg.extracts[idx] 254 .extract.from_hdr.field, 255 string); 256 printf("%s", string); 257 if ((idx + 1) < priv->extract.qos_key_extract.dpkg.num_extracts) 258 printf(" / "); 259 } 260 printf("\r\n"); 261 } 262 263 static inline void dpaa2_flow_fs_table_extracts_log( 264 const struct dpaa2_dev_priv *priv, int tc_id) 265 { 266 int idx; 267 char string[32]; 268 269 if (!dpaa2_flow_control_log) 270 return; 271 272 printf("Setup FS table: number of extracts of TC[%d]: %d\r\n", 273 tc_id, priv->extract.tc_key_extract[tc_id] 274 .dpkg.num_extracts); 275 for (idx = 0; idx < priv->extract.tc_key_extract[tc_id] 276 .dpkg.num_extracts; idx++) { 277 dpaa2_prot_field_string(priv->extract.tc_key_extract[tc_id] 278 .dpkg.extracts[idx].extract.from_hdr.prot, 279 priv->extract.tc_key_extract[tc_id].dpkg.extracts[idx] 280 .extract.from_hdr.field, 281 string); 282 printf("%s", string); 283 if ((idx + 1) < priv->extract.tc_key_extract[tc_id] 284 .dpkg.num_extracts) 285 printf(" / "); 286 } 287 printf("\r\n"); 288 } 289 290 static inline void dpaa2_flow_qos_entry_log( 291 const char *log_info, const struct rte_flow *flow, int qos_index) 292 { 293 int idx; 294 uint8_t *key, *mask; 295 296 if (!dpaa2_flow_control_log) 297 return; 298 299 printf("\r\n%s QoS entry[%d] for TC[%d], extracts size is %d\r\n", 300 log_info, qos_index, flow->tc_id, flow->qos_real_key_size); 301 302 key = (uint8_t *)(size_t)flow->qos_rule.key_iova; 303 mask = (uint8_t *)(size_t)flow->qos_rule.mask_iova; 304 305 printf("key:\r\n"); 306 for (idx = 0; idx < flow->qos_real_key_size; idx++) 307 printf("%02x ", key[idx]); 308 309 printf("\r\nmask:\r\n"); 310 for (idx = 0; idx < flow->qos_real_key_size; idx++) 311 printf("%02x ", mask[idx]); 312 313 printf("\r\n%s QoS ipsrc: %d, ipdst: %d\r\n", log_info, 314 flow->ipaddr_rule.qos_ipsrc_offset, 315 flow->ipaddr_rule.qos_ipdst_offset); 316 } 317 318 static inline void dpaa2_flow_fs_entry_log( 319 const char *log_info, const struct rte_flow *flow) 320 { 321 int idx; 322 uint8_t *key, *mask; 323 324 if (!dpaa2_flow_control_log) 325 return; 326 327 printf("\r\n%s FS/TC entry[%d] of TC[%d], extracts size is %d\r\n", 328 log_info, flow->tc_index, flow->tc_id, flow->fs_real_key_size); 329 330 key = (uint8_t *)(size_t)flow->fs_rule.key_iova; 331 mask = (uint8_t *)(size_t)flow->fs_rule.mask_iova; 332 333 printf("key:\r\n"); 334 for (idx = 0; idx < flow->fs_real_key_size; idx++) 335 printf("%02x ", key[idx]); 336 337 printf("\r\nmask:\r\n"); 338 for (idx = 0; idx < flow->fs_real_key_size; idx++) 339 printf("%02x ", mask[idx]); 340 341 printf("\r\n%s FS ipsrc: %d, ipdst: %d\r\n", log_info, 342 flow->ipaddr_rule.fs_ipsrc_offset, 343 flow->ipaddr_rule.fs_ipdst_offset); 344 } 345 346 static inline void dpaa2_flow_extract_key_set( 347 struct dpaa2_key_info *key_info, int index, uint8_t size) 348 { 349 key_info->key_size[index] = size; 350 if (index > 0) { 351 key_info->key_offset[index] = 352 key_info->key_offset[index - 1] + 353 key_info->key_size[index - 1]; 354 } else { 355 key_info->key_offset[index] = 0; 356 } 357 key_info->key_total_size += size; 358 } 359 360 static int dpaa2_flow_extract_add( 361 struct dpaa2_key_extract *key_extract, 362 enum net_prot prot, 363 uint32_t field, uint8_t field_size) 364 { 365 int index, ip_src = -1, ip_dst = -1; 366 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg; 367 struct dpaa2_key_info *key_info = &key_extract->key_info; 368 369 if (dpkg->num_extracts >= 370 DPKG_MAX_NUM_OF_EXTRACTS) { 371 DPAA2_PMD_WARN("Number of extracts overflows"); 372 return -1; 373 } 374 /* Before reorder, the IP SRC and IP DST are already last 375 * extract(s). 376 */ 377 for (index = 0; index < dpkg->num_extracts; index++) { 378 if (dpkg->extracts[index].extract.from_hdr.prot == 379 NET_PROT_IP) { 380 if (dpkg->extracts[index].extract.from_hdr.field == 381 NH_FLD_IP_SRC) { 382 ip_src = index; 383 } 384 if (dpkg->extracts[index].extract.from_hdr.field == 385 NH_FLD_IP_DST) { 386 ip_dst = index; 387 } 388 } 389 } 390 391 if (ip_src >= 0) 392 RTE_ASSERT((ip_src + 2) >= dpkg->num_extracts); 393 394 if (ip_dst >= 0) 395 RTE_ASSERT((ip_dst + 2) >= dpkg->num_extracts); 396 397 if (prot == NET_PROT_IP && 398 (field == NH_FLD_IP_SRC || 399 field == NH_FLD_IP_DST)) { 400 index = dpkg->num_extracts; 401 } else { 402 if (ip_src >= 0 && ip_dst >= 0) 403 index = dpkg->num_extracts - 2; 404 else if (ip_src >= 0 || ip_dst >= 0) 405 index = dpkg->num_extracts - 1; 406 else 407 index = dpkg->num_extracts; 408 } 409 410 dpkg->extracts[index].type = DPKG_EXTRACT_FROM_HDR; 411 dpkg->extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 412 dpkg->extracts[index].extract.from_hdr.prot = prot; 413 dpkg->extracts[index].extract.from_hdr.field = field; 414 if (prot == NET_PROT_IP && 415 (field == NH_FLD_IP_SRC || 416 field == NH_FLD_IP_DST)) { 417 dpaa2_flow_extract_key_set(key_info, index, 0); 418 } else { 419 dpaa2_flow_extract_key_set(key_info, index, field_size); 420 } 421 422 if (prot == NET_PROT_IP) { 423 if (field == NH_FLD_IP_SRC) { 424 if (key_info->ipv4_dst_offset >= 0) { 425 key_info->ipv4_src_offset = 426 key_info->ipv4_dst_offset + 427 NH_FLD_IPV4_ADDR_SIZE; 428 } else { 429 key_info->ipv4_src_offset = 430 key_info->key_offset[index - 1] + 431 key_info->key_size[index - 1]; 432 } 433 if (key_info->ipv6_dst_offset >= 0) { 434 key_info->ipv6_src_offset = 435 key_info->ipv6_dst_offset + 436 NH_FLD_IPV6_ADDR_SIZE; 437 } else { 438 key_info->ipv6_src_offset = 439 key_info->key_offset[index - 1] + 440 key_info->key_size[index - 1]; 441 } 442 } else if (field == NH_FLD_IP_DST) { 443 if (key_info->ipv4_src_offset >= 0) { 444 key_info->ipv4_dst_offset = 445 key_info->ipv4_src_offset + 446 NH_FLD_IPV4_ADDR_SIZE; 447 } else { 448 key_info->ipv4_dst_offset = 449 key_info->key_offset[index - 1] + 450 key_info->key_size[index - 1]; 451 } 452 if (key_info->ipv6_src_offset >= 0) { 453 key_info->ipv6_dst_offset = 454 key_info->ipv6_src_offset + 455 NH_FLD_IPV6_ADDR_SIZE; 456 } else { 457 key_info->ipv6_dst_offset = 458 key_info->key_offset[index - 1] + 459 key_info->key_size[index - 1]; 460 } 461 } 462 } 463 464 if (index == dpkg->num_extracts) { 465 dpkg->num_extracts++; 466 return 0; 467 } 468 469 if (ip_src >= 0) { 470 ip_src++; 471 dpkg->extracts[ip_src].type = 472 DPKG_EXTRACT_FROM_HDR; 473 dpkg->extracts[ip_src].extract.from_hdr.type = 474 DPKG_FULL_FIELD; 475 dpkg->extracts[ip_src].extract.from_hdr.prot = 476 NET_PROT_IP; 477 dpkg->extracts[ip_src].extract.from_hdr.field = 478 NH_FLD_IP_SRC; 479 dpaa2_flow_extract_key_set(key_info, ip_src, 0); 480 key_info->ipv4_src_offset += field_size; 481 key_info->ipv6_src_offset += field_size; 482 } 483 if (ip_dst >= 0) { 484 ip_dst++; 485 dpkg->extracts[ip_dst].type = 486 DPKG_EXTRACT_FROM_HDR; 487 dpkg->extracts[ip_dst].extract.from_hdr.type = 488 DPKG_FULL_FIELD; 489 dpkg->extracts[ip_dst].extract.from_hdr.prot = 490 NET_PROT_IP; 491 dpkg->extracts[ip_dst].extract.from_hdr.field = 492 NH_FLD_IP_DST; 493 dpaa2_flow_extract_key_set(key_info, ip_dst, 0); 494 key_info->ipv4_dst_offset += field_size; 495 key_info->ipv6_dst_offset += field_size; 496 } 497 498 dpkg->num_extracts++; 499 500 return 0; 501 } 502 503 static int dpaa2_flow_extract_add_raw(struct dpaa2_key_extract *key_extract, 504 int size) 505 { 506 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg; 507 struct dpaa2_key_info *key_info = &key_extract->key_info; 508 int last_extract_size, index; 509 510 if (dpkg->num_extracts != 0 && dpkg->extracts[0].type != 511 DPKG_EXTRACT_FROM_DATA) { 512 DPAA2_PMD_WARN("RAW extract cannot be combined with others"); 513 return -1; 514 } 515 516 last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE); 517 dpkg->num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE); 518 if (last_extract_size) 519 dpkg->num_extracts++; 520 else 521 last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; 522 523 for (index = 0; index < dpkg->num_extracts; index++) { 524 dpkg->extracts[index].type = DPKG_EXTRACT_FROM_DATA; 525 if (index == dpkg->num_extracts - 1) 526 dpkg->extracts[index].extract.from_data.size = 527 last_extract_size; 528 else 529 dpkg->extracts[index].extract.from_data.size = 530 DPAA2_FLOW_MAX_KEY_SIZE; 531 dpkg->extracts[index].extract.from_data.offset = 532 DPAA2_FLOW_MAX_KEY_SIZE * index; 533 } 534 535 key_info->key_total_size = size; 536 return 0; 537 } 538 539 /* Protocol discrimination. 540 * Discriminate IPv4/IPv6/vLan by Eth type. 541 * Discriminate UDP/TCP/ICMP by next proto of IP. 542 */ 543 static inline int 544 dpaa2_flow_proto_discrimination_extract( 545 struct dpaa2_key_extract *key_extract, 546 enum rte_flow_item_type type) 547 { 548 if (type == RTE_FLOW_ITEM_TYPE_ETH) { 549 return dpaa2_flow_extract_add( 550 key_extract, NET_PROT_ETH, 551 NH_FLD_ETH_TYPE, 552 sizeof(rte_be16_t)); 553 } else if (type == (enum rte_flow_item_type) 554 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) { 555 return dpaa2_flow_extract_add( 556 key_extract, NET_PROT_IP, 557 NH_FLD_IP_PROTO, 558 NH_FLD_IP_PROTO_SIZE); 559 } 560 561 return -1; 562 } 563 564 static inline int dpaa2_flow_extract_search( 565 struct dpkg_profile_cfg *dpkg, 566 enum net_prot prot, uint32_t field) 567 { 568 int i; 569 570 for (i = 0; i < dpkg->num_extracts; i++) { 571 if (dpkg->extracts[i].extract.from_hdr.prot == prot && 572 dpkg->extracts[i].extract.from_hdr.field == field) { 573 return i; 574 } 575 } 576 577 return -1; 578 } 579 580 static inline int dpaa2_flow_extract_key_offset( 581 struct dpaa2_key_extract *key_extract, 582 enum net_prot prot, uint32_t field) 583 { 584 int i; 585 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg; 586 struct dpaa2_key_info *key_info = &key_extract->key_info; 587 588 if (prot == NET_PROT_IPV4 || 589 prot == NET_PROT_IPV6) 590 i = dpaa2_flow_extract_search(dpkg, NET_PROT_IP, field); 591 else 592 i = dpaa2_flow_extract_search(dpkg, prot, field); 593 594 if (i >= 0) { 595 if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_SRC) 596 return key_info->ipv4_src_offset; 597 else if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_DST) 598 return key_info->ipv4_dst_offset; 599 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_SRC) 600 return key_info->ipv6_src_offset; 601 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_DST) 602 return key_info->ipv6_dst_offset; 603 else 604 return key_info->key_offset[i]; 605 } else { 606 return -1; 607 } 608 } 609 610 struct proto_discrimination { 611 enum rte_flow_item_type type; 612 union { 613 rte_be16_t eth_type; 614 uint8_t ip_proto; 615 }; 616 }; 617 618 static int 619 dpaa2_flow_proto_discrimination_rule( 620 struct dpaa2_dev_priv *priv, struct rte_flow *flow, 621 struct proto_discrimination proto, int group) 622 { 623 enum net_prot prot; 624 uint32_t field; 625 int offset; 626 size_t key_iova; 627 size_t mask_iova; 628 rte_be16_t eth_type; 629 uint8_t ip_proto; 630 631 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) { 632 prot = NET_PROT_ETH; 633 field = NH_FLD_ETH_TYPE; 634 } else if (proto.type == DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) { 635 prot = NET_PROT_IP; 636 field = NH_FLD_IP_PROTO; 637 } else { 638 DPAA2_PMD_ERR( 639 "Only Eth and IP support to discriminate next proto."); 640 return -1; 641 } 642 643 offset = dpaa2_flow_extract_key_offset(&priv->extract.qos_key_extract, 644 prot, field); 645 if (offset < 0) { 646 DPAA2_PMD_ERR("QoS prot %d field %d extract failed", 647 prot, field); 648 return -1; 649 } 650 key_iova = flow->qos_rule.key_iova + offset; 651 mask_iova = flow->qos_rule.mask_iova + offset; 652 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) { 653 eth_type = proto.eth_type; 654 memcpy((void *)key_iova, (const void *)(ð_type), 655 sizeof(rte_be16_t)); 656 eth_type = 0xffff; 657 memcpy((void *)mask_iova, (const void *)(ð_type), 658 sizeof(rte_be16_t)); 659 } else { 660 ip_proto = proto.ip_proto; 661 memcpy((void *)key_iova, (const void *)(&ip_proto), 662 sizeof(uint8_t)); 663 ip_proto = 0xff; 664 memcpy((void *)mask_iova, (const void *)(&ip_proto), 665 sizeof(uint8_t)); 666 } 667 668 offset = dpaa2_flow_extract_key_offset( 669 &priv->extract.tc_key_extract[group], 670 prot, field); 671 if (offset < 0) { 672 DPAA2_PMD_ERR("FS prot %d field %d extract failed", 673 prot, field); 674 return -1; 675 } 676 key_iova = flow->fs_rule.key_iova + offset; 677 mask_iova = flow->fs_rule.mask_iova + offset; 678 679 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) { 680 eth_type = proto.eth_type; 681 memcpy((void *)key_iova, (const void *)(ð_type), 682 sizeof(rte_be16_t)); 683 eth_type = 0xffff; 684 memcpy((void *)mask_iova, (const void *)(ð_type), 685 sizeof(rte_be16_t)); 686 } else { 687 ip_proto = proto.ip_proto; 688 memcpy((void *)key_iova, (const void *)(&ip_proto), 689 sizeof(uint8_t)); 690 ip_proto = 0xff; 691 memcpy((void *)mask_iova, (const void *)(&ip_proto), 692 sizeof(uint8_t)); 693 } 694 695 return 0; 696 } 697 698 static inline int 699 dpaa2_flow_rule_data_set( 700 struct dpaa2_key_extract *key_extract, 701 struct dpni_rule_cfg *rule, 702 enum net_prot prot, uint32_t field, 703 const void *key, const void *mask, int size) 704 { 705 int offset = dpaa2_flow_extract_key_offset(key_extract, 706 prot, field); 707 708 if (offset < 0) { 709 DPAA2_PMD_ERR("prot %d, field %d extract failed", 710 prot, field); 711 return -1; 712 } 713 714 memcpy((void *)(size_t)(rule->key_iova + offset), key, size); 715 memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size); 716 717 return 0; 718 } 719 720 static inline int 721 dpaa2_flow_rule_data_set_raw(struct dpni_rule_cfg *rule, 722 const void *key, const void *mask, int size) 723 { 724 int offset = 0; 725 726 memcpy((void *)(size_t)(rule->key_iova + offset), key, size); 727 memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size); 728 729 return 0; 730 } 731 732 static inline int 733 _dpaa2_flow_rule_move_ipaddr_tail( 734 struct dpaa2_key_extract *key_extract, 735 struct dpni_rule_cfg *rule, int src_offset, 736 uint32_t field, bool ipv4) 737 { 738 size_t key_src; 739 size_t mask_src; 740 size_t key_dst; 741 size_t mask_dst; 742 int dst_offset, len; 743 enum net_prot prot; 744 char tmp[NH_FLD_IPV6_ADDR_SIZE]; 745 746 if (field != NH_FLD_IP_SRC && 747 field != NH_FLD_IP_DST) { 748 DPAA2_PMD_ERR("Field of IP addr reorder must be IP SRC/DST"); 749 return -1; 750 } 751 if (ipv4) 752 prot = NET_PROT_IPV4; 753 else 754 prot = NET_PROT_IPV6; 755 dst_offset = dpaa2_flow_extract_key_offset(key_extract, 756 prot, field); 757 if (dst_offset < 0) { 758 DPAA2_PMD_ERR("Field %d reorder extract failed", field); 759 return -1; 760 } 761 key_src = rule->key_iova + src_offset; 762 mask_src = rule->mask_iova + src_offset; 763 key_dst = rule->key_iova + dst_offset; 764 mask_dst = rule->mask_iova + dst_offset; 765 if (ipv4) 766 len = sizeof(rte_be32_t); 767 else 768 len = NH_FLD_IPV6_ADDR_SIZE; 769 770 memcpy(tmp, (char *)key_src, len); 771 memset((char *)key_src, 0, len); 772 memcpy((char *)key_dst, tmp, len); 773 774 memcpy(tmp, (char *)mask_src, len); 775 memset((char *)mask_src, 0, len); 776 memcpy((char *)mask_dst, tmp, len); 777 778 return 0; 779 } 780 781 static inline int 782 dpaa2_flow_rule_move_ipaddr_tail( 783 struct rte_flow *flow, struct dpaa2_dev_priv *priv, 784 int fs_group) 785 { 786 int ret; 787 enum net_prot prot; 788 789 if (flow->ipaddr_rule.ipaddr_type == FLOW_NONE_IPADDR) 790 return 0; 791 792 if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) 793 prot = NET_PROT_IPV4; 794 else 795 prot = NET_PROT_IPV6; 796 797 if (flow->ipaddr_rule.qos_ipsrc_offset >= 0) { 798 ret = _dpaa2_flow_rule_move_ipaddr_tail( 799 &priv->extract.qos_key_extract, 800 &flow->qos_rule, 801 flow->ipaddr_rule.qos_ipsrc_offset, 802 NH_FLD_IP_SRC, prot == NET_PROT_IPV4); 803 if (ret) { 804 DPAA2_PMD_ERR("QoS src address reorder failed"); 805 return -1; 806 } 807 flow->ipaddr_rule.qos_ipsrc_offset = 808 dpaa2_flow_extract_key_offset( 809 &priv->extract.qos_key_extract, 810 prot, NH_FLD_IP_SRC); 811 } 812 813 if (flow->ipaddr_rule.qos_ipdst_offset >= 0) { 814 ret = _dpaa2_flow_rule_move_ipaddr_tail( 815 &priv->extract.qos_key_extract, 816 &flow->qos_rule, 817 flow->ipaddr_rule.qos_ipdst_offset, 818 NH_FLD_IP_DST, prot == NET_PROT_IPV4); 819 if (ret) { 820 DPAA2_PMD_ERR("QoS dst address reorder failed"); 821 return -1; 822 } 823 flow->ipaddr_rule.qos_ipdst_offset = 824 dpaa2_flow_extract_key_offset( 825 &priv->extract.qos_key_extract, 826 prot, NH_FLD_IP_DST); 827 } 828 829 if (flow->ipaddr_rule.fs_ipsrc_offset >= 0) { 830 ret = _dpaa2_flow_rule_move_ipaddr_tail( 831 &priv->extract.tc_key_extract[fs_group], 832 &flow->fs_rule, 833 flow->ipaddr_rule.fs_ipsrc_offset, 834 NH_FLD_IP_SRC, prot == NET_PROT_IPV4); 835 if (ret) { 836 DPAA2_PMD_ERR("FS src address reorder failed"); 837 return -1; 838 } 839 flow->ipaddr_rule.fs_ipsrc_offset = 840 dpaa2_flow_extract_key_offset( 841 &priv->extract.tc_key_extract[fs_group], 842 prot, NH_FLD_IP_SRC); 843 } 844 if (flow->ipaddr_rule.fs_ipdst_offset >= 0) { 845 ret = _dpaa2_flow_rule_move_ipaddr_tail( 846 &priv->extract.tc_key_extract[fs_group], 847 &flow->fs_rule, 848 flow->ipaddr_rule.fs_ipdst_offset, 849 NH_FLD_IP_DST, prot == NET_PROT_IPV4); 850 if (ret) { 851 DPAA2_PMD_ERR("FS dst address reorder failed"); 852 return -1; 853 } 854 flow->ipaddr_rule.fs_ipdst_offset = 855 dpaa2_flow_extract_key_offset( 856 &priv->extract.tc_key_extract[fs_group], 857 prot, NH_FLD_IP_DST); 858 } 859 860 return 0; 861 } 862 863 static int 864 dpaa2_flow_extract_support( 865 const uint8_t *mask_src, 866 enum rte_flow_item_type type) 867 { 868 char mask[64]; 869 int i, size = 0; 870 const char *mask_support = 0; 871 872 switch (type) { 873 case RTE_FLOW_ITEM_TYPE_ETH: 874 mask_support = (const char *)&dpaa2_flow_item_eth_mask; 875 size = sizeof(struct rte_flow_item_eth); 876 break; 877 case RTE_FLOW_ITEM_TYPE_VLAN: 878 mask_support = (const char *)&dpaa2_flow_item_vlan_mask; 879 size = sizeof(struct rte_flow_item_vlan); 880 break; 881 case RTE_FLOW_ITEM_TYPE_IPV4: 882 mask_support = (const char *)&dpaa2_flow_item_ipv4_mask; 883 size = sizeof(struct rte_flow_item_ipv4); 884 break; 885 case RTE_FLOW_ITEM_TYPE_IPV6: 886 mask_support = (const char *)&dpaa2_flow_item_ipv6_mask; 887 size = sizeof(struct rte_flow_item_ipv6); 888 break; 889 case RTE_FLOW_ITEM_TYPE_ICMP: 890 mask_support = (const char *)&dpaa2_flow_item_icmp_mask; 891 size = sizeof(struct rte_flow_item_icmp); 892 break; 893 case RTE_FLOW_ITEM_TYPE_UDP: 894 mask_support = (const char *)&dpaa2_flow_item_udp_mask; 895 size = sizeof(struct rte_flow_item_udp); 896 break; 897 case RTE_FLOW_ITEM_TYPE_TCP: 898 mask_support = (const char *)&dpaa2_flow_item_tcp_mask; 899 size = sizeof(struct rte_flow_item_tcp); 900 break; 901 case RTE_FLOW_ITEM_TYPE_SCTP: 902 mask_support = (const char *)&dpaa2_flow_item_sctp_mask; 903 size = sizeof(struct rte_flow_item_sctp); 904 break; 905 case RTE_FLOW_ITEM_TYPE_GRE: 906 mask_support = (const char *)&dpaa2_flow_item_gre_mask; 907 size = sizeof(struct rte_flow_item_gre); 908 break; 909 default: 910 return -1; 911 } 912 913 memcpy(mask, mask_support, size); 914 915 for (i = 0; i < size; i++) 916 mask[i] = (mask[i] | mask_src[i]); 917 918 if (memcmp(mask, mask_support, size)) 919 return -1; 920 921 return 0; 922 } 923 924 static int 925 dpaa2_configure_flow_eth(struct rte_flow *flow, 926 struct rte_eth_dev *dev, 927 const struct rte_flow_attr *attr, 928 const struct rte_flow_item *pattern, 929 const struct rte_flow_action actions[] __rte_unused, 930 struct rte_flow_error *error __rte_unused, 931 int *device_configured) 932 { 933 int index, ret; 934 int local_cfg = 0; 935 uint32_t group; 936 const struct rte_flow_item_eth *spec, *mask; 937 938 /* TODO: Currently upper bound of range parameter is not implemented */ 939 const struct rte_flow_item_eth *last __rte_unused; 940 struct dpaa2_dev_priv *priv = dev->data->dev_private; 941 const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; 942 943 group = attr->group; 944 945 /* Parse pattern list to get the matching parameters */ 946 spec = (const struct rte_flow_item_eth *)pattern->spec; 947 last = (const struct rte_flow_item_eth *)pattern->last; 948 mask = (const struct rte_flow_item_eth *) 949 (pattern->mask ? pattern->mask : &dpaa2_flow_item_eth_mask); 950 if (!spec) { 951 /* Don't care any field of eth header, 952 * only care eth protocol. 953 */ 954 DPAA2_PMD_WARN("No pattern spec for Eth flow, just skip"); 955 return 0; 956 } 957 958 /* Get traffic class index and flow id to be configured */ 959 flow->tc_id = group; 960 flow->tc_index = attr->priority; 961 962 if (dpaa2_flow_extract_support((const uint8_t *)mask, 963 RTE_FLOW_ITEM_TYPE_ETH)) { 964 DPAA2_PMD_WARN("Extract field(s) of ethernet not support."); 965 966 return -1; 967 } 968 969 if (memcmp((const char *)&mask->src, zero_cmp, RTE_ETHER_ADDR_LEN)) { 970 index = dpaa2_flow_extract_search( 971 &priv->extract.qos_key_extract.dpkg, 972 NET_PROT_ETH, NH_FLD_ETH_SA); 973 if (index < 0) { 974 ret = dpaa2_flow_extract_add( 975 &priv->extract.qos_key_extract, 976 NET_PROT_ETH, NH_FLD_ETH_SA, 977 RTE_ETHER_ADDR_LEN); 978 if (ret) { 979 DPAA2_PMD_ERR("QoS Extract add ETH_SA failed."); 980 981 return -1; 982 } 983 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 984 } 985 index = dpaa2_flow_extract_search( 986 &priv->extract.tc_key_extract[group].dpkg, 987 NET_PROT_ETH, NH_FLD_ETH_SA); 988 if (index < 0) { 989 ret = dpaa2_flow_extract_add( 990 &priv->extract.tc_key_extract[group], 991 NET_PROT_ETH, NH_FLD_ETH_SA, 992 RTE_ETHER_ADDR_LEN); 993 if (ret) { 994 DPAA2_PMD_ERR("FS Extract add ETH_SA failed."); 995 return -1; 996 } 997 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 998 } 999 1000 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1001 if (ret) { 1002 DPAA2_PMD_ERR( 1003 "Move ipaddr before ETH_SA rule set failed"); 1004 return -1; 1005 } 1006 1007 ret = dpaa2_flow_rule_data_set( 1008 &priv->extract.qos_key_extract, 1009 &flow->qos_rule, 1010 NET_PROT_ETH, 1011 NH_FLD_ETH_SA, 1012 &spec->src.addr_bytes, 1013 &mask->src.addr_bytes, 1014 sizeof(struct rte_ether_addr)); 1015 if (ret) { 1016 DPAA2_PMD_ERR("QoS NH_FLD_ETH_SA rule data set failed"); 1017 return -1; 1018 } 1019 1020 ret = dpaa2_flow_rule_data_set( 1021 &priv->extract.tc_key_extract[group], 1022 &flow->fs_rule, 1023 NET_PROT_ETH, 1024 NH_FLD_ETH_SA, 1025 &spec->src.addr_bytes, 1026 &mask->src.addr_bytes, 1027 sizeof(struct rte_ether_addr)); 1028 if (ret) { 1029 DPAA2_PMD_ERR("FS NH_FLD_ETH_SA rule data set failed"); 1030 return -1; 1031 } 1032 } 1033 1034 if (memcmp((const char *)&mask->dst, zero_cmp, RTE_ETHER_ADDR_LEN)) { 1035 index = dpaa2_flow_extract_search( 1036 &priv->extract.qos_key_extract.dpkg, 1037 NET_PROT_ETH, NH_FLD_ETH_DA); 1038 if (index < 0) { 1039 ret = dpaa2_flow_extract_add( 1040 &priv->extract.qos_key_extract, 1041 NET_PROT_ETH, NH_FLD_ETH_DA, 1042 RTE_ETHER_ADDR_LEN); 1043 if (ret) { 1044 DPAA2_PMD_ERR("QoS Extract add ETH_DA failed."); 1045 1046 return -1; 1047 } 1048 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1049 } 1050 1051 index = dpaa2_flow_extract_search( 1052 &priv->extract.tc_key_extract[group].dpkg, 1053 NET_PROT_ETH, NH_FLD_ETH_DA); 1054 if (index < 0) { 1055 ret = dpaa2_flow_extract_add( 1056 &priv->extract.tc_key_extract[group], 1057 NET_PROT_ETH, NH_FLD_ETH_DA, 1058 RTE_ETHER_ADDR_LEN); 1059 if (ret) { 1060 DPAA2_PMD_ERR("FS Extract add ETH_DA failed."); 1061 1062 return -1; 1063 } 1064 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1065 } 1066 1067 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1068 if (ret) { 1069 DPAA2_PMD_ERR( 1070 "Move ipaddr before ETH DA rule set failed"); 1071 return -1; 1072 } 1073 1074 ret = dpaa2_flow_rule_data_set( 1075 &priv->extract.qos_key_extract, 1076 &flow->qos_rule, 1077 NET_PROT_ETH, 1078 NH_FLD_ETH_DA, 1079 &spec->dst.addr_bytes, 1080 &mask->dst.addr_bytes, 1081 sizeof(struct rte_ether_addr)); 1082 if (ret) { 1083 DPAA2_PMD_ERR("QoS NH_FLD_ETH_DA rule data set failed"); 1084 return -1; 1085 } 1086 1087 ret = dpaa2_flow_rule_data_set( 1088 &priv->extract.tc_key_extract[group], 1089 &flow->fs_rule, 1090 NET_PROT_ETH, 1091 NH_FLD_ETH_DA, 1092 &spec->dst.addr_bytes, 1093 &mask->dst.addr_bytes, 1094 sizeof(struct rte_ether_addr)); 1095 if (ret) { 1096 DPAA2_PMD_ERR("FS NH_FLD_ETH_DA rule data set failed"); 1097 return -1; 1098 } 1099 } 1100 1101 if (memcmp((const char *)&mask->type, zero_cmp, sizeof(rte_be16_t))) { 1102 index = dpaa2_flow_extract_search( 1103 &priv->extract.qos_key_extract.dpkg, 1104 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1105 if (index < 0) { 1106 ret = dpaa2_flow_extract_add( 1107 &priv->extract.qos_key_extract, 1108 NET_PROT_ETH, NH_FLD_ETH_TYPE, 1109 RTE_ETHER_TYPE_LEN); 1110 if (ret) { 1111 DPAA2_PMD_ERR("QoS Extract add ETH_TYPE failed."); 1112 1113 return -1; 1114 } 1115 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1116 } 1117 index = dpaa2_flow_extract_search( 1118 &priv->extract.tc_key_extract[group].dpkg, 1119 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1120 if (index < 0) { 1121 ret = dpaa2_flow_extract_add( 1122 &priv->extract.tc_key_extract[group], 1123 NET_PROT_ETH, NH_FLD_ETH_TYPE, 1124 RTE_ETHER_TYPE_LEN); 1125 if (ret) { 1126 DPAA2_PMD_ERR("FS Extract add ETH_TYPE failed."); 1127 1128 return -1; 1129 } 1130 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1131 } 1132 1133 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1134 if (ret) { 1135 DPAA2_PMD_ERR( 1136 "Move ipaddr before ETH TYPE rule set failed"); 1137 return -1; 1138 } 1139 1140 ret = dpaa2_flow_rule_data_set( 1141 &priv->extract.qos_key_extract, 1142 &flow->qos_rule, 1143 NET_PROT_ETH, 1144 NH_FLD_ETH_TYPE, 1145 &spec->type, 1146 &mask->type, 1147 sizeof(rte_be16_t)); 1148 if (ret) { 1149 DPAA2_PMD_ERR("QoS NH_FLD_ETH_TYPE rule data set failed"); 1150 return -1; 1151 } 1152 1153 ret = dpaa2_flow_rule_data_set( 1154 &priv->extract.tc_key_extract[group], 1155 &flow->fs_rule, 1156 NET_PROT_ETH, 1157 NH_FLD_ETH_TYPE, 1158 &spec->type, 1159 &mask->type, 1160 sizeof(rte_be16_t)); 1161 if (ret) { 1162 DPAA2_PMD_ERR("FS NH_FLD_ETH_TYPE rule data set failed"); 1163 return -1; 1164 } 1165 } 1166 1167 (*device_configured) |= local_cfg; 1168 1169 return 0; 1170 } 1171 1172 static int 1173 dpaa2_configure_flow_vlan(struct rte_flow *flow, 1174 struct rte_eth_dev *dev, 1175 const struct rte_flow_attr *attr, 1176 const struct rte_flow_item *pattern, 1177 const struct rte_flow_action actions[] __rte_unused, 1178 struct rte_flow_error *error __rte_unused, 1179 int *device_configured) 1180 { 1181 int index, ret; 1182 int local_cfg = 0; 1183 uint32_t group; 1184 const struct rte_flow_item_vlan *spec, *mask; 1185 1186 const struct rte_flow_item_vlan *last __rte_unused; 1187 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1188 1189 group = attr->group; 1190 1191 /* Parse pattern list to get the matching parameters */ 1192 spec = (const struct rte_flow_item_vlan *)pattern->spec; 1193 last = (const struct rte_flow_item_vlan *)pattern->last; 1194 mask = (const struct rte_flow_item_vlan *) 1195 (pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask); 1196 1197 /* Get traffic class index and flow id to be configured */ 1198 flow->tc_id = group; 1199 flow->tc_index = attr->priority; 1200 1201 if (!spec) { 1202 /* Don't care any field of vlan header, 1203 * only care vlan protocol. 1204 */ 1205 /* Eth type is actually used for vLan classification. 1206 */ 1207 struct proto_discrimination proto; 1208 1209 index = dpaa2_flow_extract_search( 1210 &priv->extract.qos_key_extract.dpkg, 1211 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1212 if (index < 0) { 1213 ret = dpaa2_flow_proto_discrimination_extract( 1214 &priv->extract.qos_key_extract, 1215 RTE_FLOW_ITEM_TYPE_ETH); 1216 if (ret) { 1217 DPAA2_PMD_ERR( 1218 "QoS Ext ETH_TYPE to discriminate vLan failed"); 1219 1220 return -1; 1221 } 1222 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1223 } 1224 1225 index = dpaa2_flow_extract_search( 1226 &priv->extract.tc_key_extract[group].dpkg, 1227 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1228 if (index < 0) { 1229 ret = dpaa2_flow_proto_discrimination_extract( 1230 &priv->extract.tc_key_extract[group], 1231 RTE_FLOW_ITEM_TYPE_ETH); 1232 if (ret) { 1233 DPAA2_PMD_ERR( 1234 "FS Ext ETH_TYPE to discriminate vLan failed."); 1235 1236 return -1; 1237 } 1238 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1239 } 1240 1241 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1242 if (ret) { 1243 DPAA2_PMD_ERR( 1244 "Move ipaddr before vLan discrimination set failed"); 1245 return -1; 1246 } 1247 1248 proto.type = RTE_FLOW_ITEM_TYPE_ETH; 1249 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 1250 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 1251 proto, group); 1252 if (ret) { 1253 DPAA2_PMD_ERR("vLan discrimination rule set failed"); 1254 return -1; 1255 } 1256 1257 (*device_configured) |= local_cfg; 1258 1259 return 0; 1260 } 1261 1262 if (dpaa2_flow_extract_support((const uint8_t *)mask, 1263 RTE_FLOW_ITEM_TYPE_VLAN)) { 1264 DPAA2_PMD_WARN("Extract field(s) of vlan not support."); 1265 1266 return -1; 1267 } 1268 1269 if (!mask->tci) 1270 return 0; 1271 1272 index = dpaa2_flow_extract_search( 1273 &priv->extract.qos_key_extract.dpkg, 1274 NET_PROT_VLAN, NH_FLD_VLAN_TCI); 1275 if (index < 0) { 1276 ret = dpaa2_flow_extract_add( 1277 &priv->extract.qos_key_extract, 1278 NET_PROT_VLAN, 1279 NH_FLD_VLAN_TCI, 1280 sizeof(rte_be16_t)); 1281 if (ret) { 1282 DPAA2_PMD_ERR("QoS Extract add VLAN_TCI failed."); 1283 1284 return -1; 1285 } 1286 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1287 } 1288 1289 index = dpaa2_flow_extract_search( 1290 &priv->extract.tc_key_extract[group].dpkg, 1291 NET_PROT_VLAN, NH_FLD_VLAN_TCI); 1292 if (index < 0) { 1293 ret = dpaa2_flow_extract_add( 1294 &priv->extract.tc_key_extract[group], 1295 NET_PROT_VLAN, 1296 NH_FLD_VLAN_TCI, 1297 sizeof(rte_be16_t)); 1298 if (ret) { 1299 DPAA2_PMD_ERR("FS Extract add VLAN_TCI failed."); 1300 1301 return -1; 1302 } 1303 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1304 } 1305 1306 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1307 if (ret) { 1308 DPAA2_PMD_ERR( 1309 "Move ipaddr before VLAN TCI rule set failed"); 1310 return -1; 1311 } 1312 1313 ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract, 1314 &flow->qos_rule, 1315 NET_PROT_VLAN, 1316 NH_FLD_VLAN_TCI, 1317 &spec->tci, 1318 &mask->tci, 1319 sizeof(rte_be16_t)); 1320 if (ret) { 1321 DPAA2_PMD_ERR("QoS NH_FLD_VLAN_TCI rule data set failed"); 1322 return -1; 1323 } 1324 1325 ret = dpaa2_flow_rule_data_set( 1326 &priv->extract.tc_key_extract[group], 1327 &flow->fs_rule, 1328 NET_PROT_VLAN, 1329 NH_FLD_VLAN_TCI, 1330 &spec->tci, 1331 &mask->tci, 1332 sizeof(rte_be16_t)); 1333 if (ret) { 1334 DPAA2_PMD_ERR("FS NH_FLD_VLAN_TCI rule data set failed"); 1335 return -1; 1336 } 1337 1338 (*device_configured) |= local_cfg; 1339 1340 return 0; 1341 } 1342 1343 static int 1344 dpaa2_configure_flow_ip_discrimation( 1345 struct dpaa2_dev_priv *priv, struct rte_flow *flow, 1346 const struct rte_flow_item *pattern, 1347 int *local_cfg, int *device_configured, 1348 uint32_t group) 1349 { 1350 int index, ret; 1351 struct proto_discrimination proto; 1352 1353 index = dpaa2_flow_extract_search( 1354 &priv->extract.qos_key_extract.dpkg, 1355 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1356 if (index < 0) { 1357 ret = dpaa2_flow_proto_discrimination_extract( 1358 &priv->extract.qos_key_extract, 1359 RTE_FLOW_ITEM_TYPE_ETH); 1360 if (ret) { 1361 DPAA2_PMD_ERR( 1362 "QoS Extract ETH_TYPE to discriminate IP failed."); 1363 return -1; 1364 } 1365 (*local_cfg) |= DPAA2_QOS_TABLE_RECONFIGURE; 1366 } 1367 1368 index = dpaa2_flow_extract_search( 1369 &priv->extract.tc_key_extract[group].dpkg, 1370 NET_PROT_ETH, NH_FLD_ETH_TYPE); 1371 if (index < 0) { 1372 ret = dpaa2_flow_proto_discrimination_extract( 1373 &priv->extract.tc_key_extract[group], 1374 RTE_FLOW_ITEM_TYPE_ETH); 1375 if (ret) { 1376 DPAA2_PMD_ERR( 1377 "FS Extract ETH_TYPE to discriminate IP failed."); 1378 return -1; 1379 } 1380 (*local_cfg) |= DPAA2_FS_TABLE_RECONFIGURE; 1381 } 1382 1383 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1384 if (ret) { 1385 DPAA2_PMD_ERR( 1386 "Move ipaddr before IP discrimination set failed"); 1387 return -1; 1388 } 1389 1390 proto.type = RTE_FLOW_ITEM_TYPE_ETH; 1391 if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) 1392 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 1393 else 1394 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 1395 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, proto, group); 1396 if (ret) { 1397 DPAA2_PMD_ERR("IP discrimination rule set failed"); 1398 return -1; 1399 } 1400 1401 (*device_configured) |= (*local_cfg); 1402 1403 return 0; 1404 } 1405 1406 1407 static int 1408 dpaa2_configure_flow_generic_ip( 1409 struct rte_flow *flow, 1410 struct rte_eth_dev *dev, 1411 const struct rte_flow_attr *attr, 1412 const struct rte_flow_item *pattern, 1413 const struct rte_flow_action actions[] __rte_unused, 1414 struct rte_flow_error *error __rte_unused, 1415 int *device_configured) 1416 { 1417 int index, ret; 1418 int local_cfg = 0; 1419 uint32_t group; 1420 const struct rte_flow_item_ipv4 *spec_ipv4 = 0, 1421 *mask_ipv4 = 0; 1422 const struct rte_flow_item_ipv6 *spec_ipv6 = 0, 1423 *mask_ipv6 = 0; 1424 const void *key, *mask; 1425 enum net_prot prot; 1426 1427 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1428 const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0}; 1429 int size; 1430 1431 group = attr->group; 1432 1433 /* Parse pattern list to get the matching parameters */ 1434 if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) { 1435 spec_ipv4 = (const struct rte_flow_item_ipv4 *)pattern->spec; 1436 mask_ipv4 = (const struct rte_flow_item_ipv4 *) 1437 (pattern->mask ? pattern->mask : 1438 &dpaa2_flow_item_ipv4_mask); 1439 } else { 1440 spec_ipv6 = (const struct rte_flow_item_ipv6 *)pattern->spec; 1441 mask_ipv6 = (const struct rte_flow_item_ipv6 *) 1442 (pattern->mask ? pattern->mask : 1443 &dpaa2_flow_item_ipv6_mask); 1444 } 1445 1446 /* Get traffic class index and flow id to be configured */ 1447 flow->tc_id = group; 1448 flow->tc_index = attr->priority; 1449 1450 ret = dpaa2_configure_flow_ip_discrimation(priv, 1451 flow, pattern, &local_cfg, 1452 device_configured, group); 1453 if (ret) { 1454 DPAA2_PMD_ERR("IP discrimation failed!"); 1455 return -1; 1456 } 1457 1458 if (!spec_ipv4 && !spec_ipv6) 1459 return 0; 1460 1461 if (mask_ipv4) { 1462 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv4, 1463 RTE_FLOW_ITEM_TYPE_IPV4)) { 1464 DPAA2_PMD_WARN("Extract field(s) of IPv4 not support."); 1465 1466 return -1; 1467 } 1468 } 1469 1470 if (mask_ipv6) { 1471 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv6, 1472 RTE_FLOW_ITEM_TYPE_IPV6)) { 1473 DPAA2_PMD_WARN("Extract field(s) of IPv6 not support."); 1474 1475 return -1; 1476 } 1477 } 1478 1479 if (mask_ipv4 && (mask_ipv4->hdr.src_addr || 1480 mask_ipv4->hdr.dst_addr)) { 1481 flow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR; 1482 } else if (mask_ipv6 && 1483 (memcmp((const char *)mask_ipv6->hdr.src_addr, 1484 zero_cmp, NH_FLD_IPV6_ADDR_SIZE) || 1485 memcmp((const char *)mask_ipv6->hdr.dst_addr, 1486 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) { 1487 flow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR; 1488 } 1489 1490 if ((mask_ipv4 && mask_ipv4->hdr.src_addr) || 1491 (mask_ipv6 && 1492 memcmp((const char *)mask_ipv6->hdr.src_addr, 1493 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) { 1494 index = dpaa2_flow_extract_search( 1495 &priv->extract.qos_key_extract.dpkg, 1496 NET_PROT_IP, NH_FLD_IP_SRC); 1497 if (index < 0) { 1498 ret = dpaa2_flow_extract_add( 1499 &priv->extract.qos_key_extract, 1500 NET_PROT_IP, 1501 NH_FLD_IP_SRC, 1502 0); 1503 if (ret) { 1504 DPAA2_PMD_ERR("QoS Extract add IP_SRC failed."); 1505 1506 return -1; 1507 } 1508 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1509 } 1510 1511 index = dpaa2_flow_extract_search( 1512 &priv->extract.tc_key_extract[group].dpkg, 1513 NET_PROT_IP, NH_FLD_IP_SRC); 1514 if (index < 0) { 1515 ret = dpaa2_flow_extract_add( 1516 &priv->extract.tc_key_extract[group], 1517 NET_PROT_IP, 1518 NH_FLD_IP_SRC, 1519 0); 1520 if (ret) { 1521 DPAA2_PMD_ERR("FS Extract add IP_SRC failed."); 1522 1523 return -1; 1524 } 1525 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1526 } 1527 1528 if (spec_ipv4) 1529 key = &spec_ipv4->hdr.src_addr; 1530 else 1531 key = &spec_ipv6->hdr.src_addr[0]; 1532 if (mask_ipv4) { 1533 mask = &mask_ipv4->hdr.src_addr; 1534 size = NH_FLD_IPV4_ADDR_SIZE; 1535 prot = NET_PROT_IPV4; 1536 } else { 1537 mask = &mask_ipv6->hdr.src_addr[0]; 1538 size = NH_FLD_IPV6_ADDR_SIZE; 1539 prot = NET_PROT_IPV6; 1540 } 1541 1542 ret = dpaa2_flow_rule_data_set( 1543 &priv->extract.qos_key_extract, 1544 &flow->qos_rule, 1545 prot, NH_FLD_IP_SRC, 1546 key, mask, size); 1547 if (ret) { 1548 DPAA2_PMD_ERR("QoS NH_FLD_IP_SRC rule data set failed"); 1549 return -1; 1550 } 1551 1552 ret = dpaa2_flow_rule_data_set( 1553 &priv->extract.tc_key_extract[group], 1554 &flow->fs_rule, 1555 prot, NH_FLD_IP_SRC, 1556 key, mask, size); 1557 if (ret) { 1558 DPAA2_PMD_ERR("FS NH_FLD_IP_SRC rule data set failed"); 1559 return -1; 1560 } 1561 1562 flow->ipaddr_rule.qos_ipsrc_offset = 1563 dpaa2_flow_extract_key_offset( 1564 &priv->extract.qos_key_extract, 1565 prot, NH_FLD_IP_SRC); 1566 flow->ipaddr_rule.fs_ipsrc_offset = 1567 dpaa2_flow_extract_key_offset( 1568 &priv->extract.tc_key_extract[group], 1569 prot, NH_FLD_IP_SRC); 1570 } 1571 1572 if ((mask_ipv4 && mask_ipv4->hdr.dst_addr) || 1573 (mask_ipv6 && 1574 memcmp((const char *)mask_ipv6->hdr.dst_addr, 1575 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) { 1576 index = dpaa2_flow_extract_search( 1577 &priv->extract.qos_key_extract.dpkg, 1578 NET_PROT_IP, NH_FLD_IP_DST); 1579 if (index < 0) { 1580 if (mask_ipv4) 1581 size = NH_FLD_IPV4_ADDR_SIZE; 1582 else 1583 size = NH_FLD_IPV6_ADDR_SIZE; 1584 ret = dpaa2_flow_extract_add( 1585 &priv->extract.qos_key_extract, 1586 NET_PROT_IP, 1587 NH_FLD_IP_DST, 1588 size); 1589 if (ret) { 1590 DPAA2_PMD_ERR("QoS Extract add IP_DST failed."); 1591 1592 return -1; 1593 } 1594 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1595 } 1596 1597 index = dpaa2_flow_extract_search( 1598 &priv->extract.tc_key_extract[group].dpkg, 1599 NET_PROT_IP, NH_FLD_IP_DST); 1600 if (index < 0) { 1601 if (mask_ipv4) 1602 size = NH_FLD_IPV4_ADDR_SIZE; 1603 else 1604 size = NH_FLD_IPV6_ADDR_SIZE; 1605 ret = dpaa2_flow_extract_add( 1606 &priv->extract.tc_key_extract[group], 1607 NET_PROT_IP, 1608 NH_FLD_IP_DST, 1609 size); 1610 if (ret) { 1611 DPAA2_PMD_ERR("FS Extract add IP_DST failed."); 1612 1613 return -1; 1614 } 1615 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1616 } 1617 1618 if (spec_ipv4) 1619 key = &spec_ipv4->hdr.dst_addr; 1620 else 1621 key = spec_ipv6->hdr.dst_addr; 1622 if (mask_ipv4) { 1623 mask = &mask_ipv4->hdr.dst_addr; 1624 size = NH_FLD_IPV4_ADDR_SIZE; 1625 prot = NET_PROT_IPV4; 1626 } else { 1627 mask = &mask_ipv6->hdr.dst_addr[0]; 1628 size = NH_FLD_IPV6_ADDR_SIZE; 1629 prot = NET_PROT_IPV6; 1630 } 1631 1632 ret = dpaa2_flow_rule_data_set( 1633 &priv->extract.qos_key_extract, 1634 &flow->qos_rule, 1635 prot, NH_FLD_IP_DST, 1636 key, mask, size); 1637 if (ret) { 1638 DPAA2_PMD_ERR("QoS NH_FLD_IP_DST rule data set failed"); 1639 return -1; 1640 } 1641 1642 ret = dpaa2_flow_rule_data_set( 1643 &priv->extract.tc_key_extract[group], 1644 &flow->fs_rule, 1645 prot, NH_FLD_IP_DST, 1646 key, mask, size); 1647 if (ret) { 1648 DPAA2_PMD_ERR("FS NH_FLD_IP_DST rule data set failed"); 1649 return -1; 1650 } 1651 flow->ipaddr_rule.qos_ipdst_offset = 1652 dpaa2_flow_extract_key_offset( 1653 &priv->extract.qos_key_extract, 1654 prot, NH_FLD_IP_DST); 1655 flow->ipaddr_rule.fs_ipdst_offset = 1656 dpaa2_flow_extract_key_offset( 1657 &priv->extract.tc_key_extract[group], 1658 prot, NH_FLD_IP_DST); 1659 } 1660 1661 if ((mask_ipv4 && mask_ipv4->hdr.next_proto_id) || 1662 (mask_ipv6 && mask_ipv6->hdr.proto)) { 1663 index = dpaa2_flow_extract_search( 1664 &priv->extract.qos_key_extract.dpkg, 1665 NET_PROT_IP, NH_FLD_IP_PROTO); 1666 if (index < 0) { 1667 ret = dpaa2_flow_extract_add( 1668 &priv->extract.qos_key_extract, 1669 NET_PROT_IP, 1670 NH_FLD_IP_PROTO, 1671 NH_FLD_IP_PROTO_SIZE); 1672 if (ret) { 1673 DPAA2_PMD_ERR("QoS Extract add IP_DST failed."); 1674 1675 return -1; 1676 } 1677 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1678 } 1679 1680 index = dpaa2_flow_extract_search( 1681 &priv->extract.tc_key_extract[group].dpkg, 1682 NET_PROT_IP, NH_FLD_IP_PROTO); 1683 if (index < 0) { 1684 ret = dpaa2_flow_extract_add( 1685 &priv->extract.tc_key_extract[group], 1686 NET_PROT_IP, 1687 NH_FLD_IP_PROTO, 1688 NH_FLD_IP_PROTO_SIZE); 1689 if (ret) { 1690 DPAA2_PMD_ERR("FS Extract add IP_DST failed."); 1691 1692 return -1; 1693 } 1694 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1695 } 1696 1697 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1698 if (ret) { 1699 DPAA2_PMD_ERR( 1700 "Move ipaddr after NH_FLD_IP_PROTO rule set failed"); 1701 return -1; 1702 } 1703 1704 if (spec_ipv4) 1705 key = &spec_ipv4->hdr.next_proto_id; 1706 else 1707 key = &spec_ipv6->hdr.proto; 1708 if (mask_ipv4) 1709 mask = &mask_ipv4->hdr.next_proto_id; 1710 else 1711 mask = &mask_ipv6->hdr.proto; 1712 1713 ret = dpaa2_flow_rule_data_set( 1714 &priv->extract.qos_key_extract, 1715 &flow->qos_rule, 1716 NET_PROT_IP, 1717 NH_FLD_IP_PROTO, 1718 key, mask, NH_FLD_IP_PROTO_SIZE); 1719 if (ret) { 1720 DPAA2_PMD_ERR("QoS NH_FLD_IP_PROTO rule data set failed"); 1721 return -1; 1722 } 1723 1724 ret = dpaa2_flow_rule_data_set( 1725 &priv->extract.tc_key_extract[group], 1726 &flow->fs_rule, 1727 NET_PROT_IP, 1728 NH_FLD_IP_PROTO, 1729 key, mask, NH_FLD_IP_PROTO_SIZE); 1730 if (ret) { 1731 DPAA2_PMD_ERR("FS NH_FLD_IP_PROTO rule data set failed"); 1732 return -1; 1733 } 1734 } 1735 1736 (*device_configured) |= local_cfg; 1737 1738 return 0; 1739 } 1740 1741 static int 1742 dpaa2_configure_flow_icmp(struct rte_flow *flow, 1743 struct rte_eth_dev *dev, 1744 const struct rte_flow_attr *attr, 1745 const struct rte_flow_item *pattern, 1746 const struct rte_flow_action actions[] __rte_unused, 1747 struct rte_flow_error *error __rte_unused, 1748 int *device_configured) 1749 { 1750 int index, ret; 1751 int local_cfg = 0; 1752 uint32_t group; 1753 const struct rte_flow_item_icmp *spec, *mask; 1754 1755 const struct rte_flow_item_icmp *last __rte_unused; 1756 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1757 1758 group = attr->group; 1759 1760 /* Parse pattern list to get the matching parameters */ 1761 spec = (const struct rte_flow_item_icmp *)pattern->spec; 1762 last = (const struct rte_flow_item_icmp *)pattern->last; 1763 mask = (const struct rte_flow_item_icmp *) 1764 (pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask); 1765 1766 /* Get traffic class index and flow id to be configured */ 1767 flow->tc_id = group; 1768 flow->tc_index = attr->priority; 1769 1770 if (!spec) { 1771 /* Don't care any field of ICMP header, 1772 * only care ICMP protocol. 1773 * Example: flow create 0 ingress pattern icmp / 1774 */ 1775 /* Next proto of Generical IP is actually used 1776 * for ICMP identification. 1777 */ 1778 struct proto_discrimination proto; 1779 1780 index = dpaa2_flow_extract_search( 1781 &priv->extract.qos_key_extract.dpkg, 1782 NET_PROT_IP, NH_FLD_IP_PROTO); 1783 if (index < 0) { 1784 ret = dpaa2_flow_proto_discrimination_extract( 1785 &priv->extract.qos_key_extract, 1786 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 1787 if (ret) { 1788 DPAA2_PMD_ERR( 1789 "QoS Extract IP protocol to discriminate ICMP failed."); 1790 1791 return -1; 1792 } 1793 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1794 } 1795 1796 index = dpaa2_flow_extract_search( 1797 &priv->extract.tc_key_extract[group].dpkg, 1798 NET_PROT_IP, NH_FLD_IP_PROTO); 1799 if (index < 0) { 1800 ret = dpaa2_flow_proto_discrimination_extract( 1801 &priv->extract.tc_key_extract[group], 1802 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 1803 if (ret) { 1804 DPAA2_PMD_ERR( 1805 "FS Extract IP protocol to discriminate ICMP failed."); 1806 1807 return -1; 1808 } 1809 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1810 } 1811 1812 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1813 if (ret) { 1814 DPAA2_PMD_ERR( 1815 "Move IP addr before ICMP discrimination set failed"); 1816 return -1; 1817 } 1818 1819 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP; 1820 proto.ip_proto = IPPROTO_ICMP; 1821 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 1822 proto, group); 1823 if (ret) { 1824 DPAA2_PMD_ERR("ICMP discrimination rule set failed"); 1825 return -1; 1826 } 1827 1828 (*device_configured) |= local_cfg; 1829 1830 return 0; 1831 } 1832 1833 if (dpaa2_flow_extract_support((const uint8_t *)mask, 1834 RTE_FLOW_ITEM_TYPE_ICMP)) { 1835 DPAA2_PMD_WARN("Extract field(s) of ICMP not support."); 1836 1837 return -1; 1838 } 1839 1840 if (mask->hdr.icmp_type) { 1841 index = dpaa2_flow_extract_search( 1842 &priv->extract.qos_key_extract.dpkg, 1843 NET_PROT_ICMP, NH_FLD_ICMP_TYPE); 1844 if (index < 0) { 1845 ret = dpaa2_flow_extract_add( 1846 &priv->extract.qos_key_extract, 1847 NET_PROT_ICMP, 1848 NH_FLD_ICMP_TYPE, 1849 NH_FLD_ICMP_TYPE_SIZE); 1850 if (ret) { 1851 DPAA2_PMD_ERR("QoS Extract add ICMP_TYPE failed."); 1852 1853 return -1; 1854 } 1855 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1856 } 1857 1858 index = dpaa2_flow_extract_search( 1859 &priv->extract.tc_key_extract[group].dpkg, 1860 NET_PROT_ICMP, NH_FLD_ICMP_TYPE); 1861 if (index < 0) { 1862 ret = dpaa2_flow_extract_add( 1863 &priv->extract.tc_key_extract[group], 1864 NET_PROT_ICMP, 1865 NH_FLD_ICMP_TYPE, 1866 NH_FLD_ICMP_TYPE_SIZE); 1867 if (ret) { 1868 DPAA2_PMD_ERR("FS Extract add ICMP_TYPE failed."); 1869 1870 return -1; 1871 } 1872 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1873 } 1874 1875 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1876 if (ret) { 1877 DPAA2_PMD_ERR( 1878 "Move ipaddr before ICMP TYPE set failed"); 1879 return -1; 1880 } 1881 1882 ret = dpaa2_flow_rule_data_set( 1883 &priv->extract.qos_key_extract, 1884 &flow->qos_rule, 1885 NET_PROT_ICMP, 1886 NH_FLD_ICMP_TYPE, 1887 &spec->hdr.icmp_type, 1888 &mask->hdr.icmp_type, 1889 NH_FLD_ICMP_TYPE_SIZE); 1890 if (ret) { 1891 DPAA2_PMD_ERR("QoS NH_FLD_ICMP_TYPE rule data set failed"); 1892 return -1; 1893 } 1894 1895 ret = dpaa2_flow_rule_data_set( 1896 &priv->extract.tc_key_extract[group], 1897 &flow->fs_rule, 1898 NET_PROT_ICMP, 1899 NH_FLD_ICMP_TYPE, 1900 &spec->hdr.icmp_type, 1901 &mask->hdr.icmp_type, 1902 NH_FLD_ICMP_TYPE_SIZE); 1903 if (ret) { 1904 DPAA2_PMD_ERR("FS NH_FLD_ICMP_TYPE rule data set failed"); 1905 return -1; 1906 } 1907 } 1908 1909 if (mask->hdr.icmp_code) { 1910 index = dpaa2_flow_extract_search( 1911 &priv->extract.qos_key_extract.dpkg, 1912 NET_PROT_ICMP, NH_FLD_ICMP_CODE); 1913 if (index < 0) { 1914 ret = dpaa2_flow_extract_add( 1915 &priv->extract.qos_key_extract, 1916 NET_PROT_ICMP, 1917 NH_FLD_ICMP_CODE, 1918 NH_FLD_ICMP_CODE_SIZE); 1919 if (ret) { 1920 DPAA2_PMD_ERR("QoS Extract add ICMP_CODE failed."); 1921 1922 return -1; 1923 } 1924 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 1925 } 1926 1927 index = dpaa2_flow_extract_search( 1928 &priv->extract.tc_key_extract[group].dpkg, 1929 NET_PROT_ICMP, NH_FLD_ICMP_CODE); 1930 if (index < 0) { 1931 ret = dpaa2_flow_extract_add( 1932 &priv->extract.tc_key_extract[group], 1933 NET_PROT_ICMP, 1934 NH_FLD_ICMP_CODE, 1935 NH_FLD_ICMP_CODE_SIZE); 1936 if (ret) { 1937 DPAA2_PMD_ERR("FS Extract add ICMP_CODE failed."); 1938 1939 return -1; 1940 } 1941 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 1942 } 1943 1944 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 1945 if (ret) { 1946 DPAA2_PMD_ERR( 1947 "Move ipaddr after ICMP CODE set failed"); 1948 return -1; 1949 } 1950 1951 ret = dpaa2_flow_rule_data_set( 1952 &priv->extract.qos_key_extract, 1953 &flow->qos_rule, 1954 NET_PROT_ICMP, 1955 NH_FLD_ICMP_CODE, 1956 &spec->hdr.icmp_code, 1957 &mask->hdr.icmp_code, 1958 NH_FLD_ICMP_CODE_SIZE); 1959 if (ret) { 1960 DPAA2_PMD_ERR("QoS NH_FLD_ICMP_CODE rule data set failed"); 1961 return -1; 1962 } 1963 1964 ret = dpaa2_flow_rule_data_set( 1965 &priv->extract.tc_key_extract[group], 1966 &flow->fs_rule, 1967 NET_PROT_ICMP, 1968 NH_FLD_ICMP_CODE, 1969 &spec->hdr.icmp_code, 1970 &mask->hdr.icmp_code, 1971 NH_FLD_ICMP_CODE_SIZE); 1972 if (ret) { 1973 DPAA2_PMD_ERR("FS NH_FLD_ICMP_CODE rule data set failed"); 1974 return -1; 1975 } 1976 } 1977 1978 (*device_configured) |= local_cfg; 1979 1980 return 0; 1981 } 1982 1983 static int 1984 dpaa2_configure_flow_udp(struct rte_flow *flow, 1985 struct rte_eth_dev *dev, 1986 const struct rte_flow_attr *attr, 1987 const struct rte_flow_item *pattern, 1988 const struct rte_flow_action actions[] __rte_unused, 1989 struct rte_flow_error *error __rte_unused, 1990 int *device_configured) 1991 { 1992 int index, ret; 1993 int local_cfg = 0; 1994 uint32_t group; 1995 const struct rte_flow_item_udp *spec, *mask; 1996 1997 const struct rte_flow_item_udp *last __rte_unused; 1998 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1999 2000 group = attr->group; 2001 2002 /* Parse pattern list to get the matching parameters */ 2003 spec = (const struct rte_flow_item_udp *)pattern->spec; 2004 last = (const struct rte_flow_item_udp *)pattern->last; 2005 mask = (const struct rte_flow_item_udp *) 2006 (pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask); 2007 2008 /* Get traffic class index and flow id to be configured */ 2009 flow->tc_id = group; 2010 flow->tc_index = attr->priority; 2011 2012 if (!spec || !mc_l4_port_identification) { 2013 struct proto_discrimination proto; 2014 2015 index = dpaa2_flow_extract_search( 2016 &priv->extract.qos_key_extract.dpkg, 2017 NET_PROT_IP, NH_FLD_IP_PROTO); 2018 if (index < 0) { 2019 ret = dpaa2_flow_proto_discrimination_extract( 2020 &priv->extract.qos_key_extract, 2021 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2022 if (ret) { 2023 DPAA2_PMD_ERR( 2024 "QoS Extract IP protocol to discriminate UDP failed."); 2025 2026 return -1; 2027 } 2028 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2029 } 2030 2031 index = dpaa2_flow_extract_search( 2032 &priv->extract.tc_key_extract[group].dpkg, 2033 NET_PROT_IP, NH_FLD_IP_PROTO); 2034 if (index < 0) { 2035 ret = dpaa2_flow_proto_discrimination_extract( 2036 &priv->extract.tc_key_extract[group], 2037 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2038 if (ret) { 2039 DPAA2_PMD_ERR( 2040 "FS Extract IP protocol to discriminate UDP failed."); 2041 2042 return -1; 2043 } 2044 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2045 } 2046 2047 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2048 if (ret) { 2049 DPAA2_PMD_ERR( 2050 "Move IP addr before UDP discrimination set failed"); 2051 return -1; 2052 } 2053 2054 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP; 2055 proto.ip_proto = IPPROTO_UDP; 2056 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 2057 proto, group); 2058 if (ret) { 2059 DPAA2_PMD_ERR("UDP discrimination rule set failed"); 2060 return -1; 2061 } 2062 2063 (*device_configured) |= local_cfg; 2064 2065 if (!spec) 2066 return 0; 2067 } 2068 2069 if (dpaa2_flow_extract_support((const uint8_t *)mask, 2070 RTE_FLOW_ITEM_TYPE_UDP)) { 2071 DPAA2_PMD_WARN("Extract field(s) of UDP not support."); 2072 2073 return -1; 2074 } 2075 2076 if (mask->hdr.src_port) { 2077 index = dpaa2_flow_extract_search( 2078 &priv->extract.qos_key_extract.dpkg, 2079 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC); 2080 if (index < 0) { 2081 ret = dpaa2_flow_extract_add( 2082 &priv->extract.qos_key_extract, 2083 NET_PROT_UDP, 2084 NH_FLD_UDP_PORT_SRC, 2085 NH_FLD_UDP_PORT_SIZE); 2086 if (ret) { 2087 DPAA2_PMD_ERR("QoS Extract add UDP_SRC failed."); 2088 2089 return -1; 2090 } 2091 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2092 } 2093 2094 index = dpaa2_flow_extract_search( 2095 &priv->extract.tc_key_extract[group].dpkg, 2096 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC); 2097 if (index < 0) { 2098 ret = dpaa2_flow_extract_add( 2099 &priv->extract.tc_key_extract[group], 2100 NET_PROT_UDP, 2101 NH_FLD_UDP_PORT_SRC, 2102 NH_FLD_UDP_PORT_SIZE); 2103 if (ret) { 2104 DPAA2_PMD_ERR("FS Extract add UDP_SRC failed."); 2105 2106 return -1; 2107 } 2108 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2109 } 2110 2111 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2112 if (ret) { 2113 DPAA2_PMD_ERR( 2114 "Move ipaddr before UDP_PORT_SRC set failed"); 2115 return -1; 2116 } 2117 2118 ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract, 2119 &flow->qos_rule, 2120 NET_PROT_UDP, 2121 NH_FLD_UDP_PORT_SRC, 2122 &spec->hdr.src_port, 2123 &mask->hdr.src_port, 2124 NH_FLD_UDP_PORT_SIZE); 2125 if (ret) { 2126 DPAA2_PMD_ERR( 2127 "QoS NH_FLD_UDP_PORT_SRC rule data set failed"); 2128 return -1; 2129 } 2130 2131 ret = dpaa2_flow_rule_data_set( 2132 &priv->extract.tc_key_extract[group], 2133 &flow->fs_rule, 2134 NET_PROT_UDP, 2135 NH_FLD_UDP_PORT_SRC, 2136 &spec->hdr.src_port, 2137 &mask->hdr.src_port, 2138 NH_FLD_UDP_PORT_SIZE); 2139 if (ret) { 2140 DPAA2_PMD_ERR( 2141 "FS NH_FLD_UDP_PORT_SRC rule data set failed"); 2142 return -1; 2143 } 2144 } 2145 2146 if (mask->hdr.dst_port) { 2147 index = dpaa2_flow_extract_search( 2148 &priv->extract.qos_key_extract.dpkg, 2149 NET_PROT_UDP, NH_FLD_UDP_PORT_DST); 2150 if (index < 0) { 2151 ret = dpaa2_flow_extract_add( 2152 &priv->extract.qos_key_extract, 2153 NET_PROT_UDP, 2154 NH_FLD_UDP_PORT_DST, 2155 NH_FLD_UDP_PORT_SIZE); 2156 if (ret) { 2157 DPAA2_PMD_ERR("QoS Extract add UDP_DST failed."); 2158 2159 return -1; 2160 } 2161 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2162 } 2163 2164 index = dpaa2_flow_extract_search( 2165 &priv->extract.tc_key_extract[group].dpkg, 2166 NET_PROT_UDP, NH_FLD_UDP_PORT_DST); 2167 if (index < 0) { 2168 ret = dpaa2_flow_extract_add( 2169 &priv->extract.tc_key_extract[group], 2170 NET_PROT_UDP, 2171 NH_FLD_UDP_PORT_DST, 2172 NH_FLD_UDP_PORT_SIZE); 2173 if (ret) { 2174 DPAA2_PMD_ERR("FS Extract add UDP_DST failed."); 2175 2176 return -1; 2177 } 2178 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2179 } 2180 2181 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2182 if (ret) { 2183 DPAA2_PMD_ERR( 2184 "Move ipaddr before UDP_PORT_DST set failed"); 2185 return -1; 2186 } 2187 2188 ret = dpaa2_flow_rule_data_set( 2189 &priv->extract.qos_key_extract, 2190 &flow->qos_rule, 2191 NET_PROT_UDP, 2192 NH_FLD_UDP_PORT_DST, 2193 &spec->hdr.dst_port, 2194 &mask->hdr.dst_port, 2195 NH_FLD_UDP_PORT_SIZE); 2196 if (ret) { 2197 DPAA2_PMD_ERR( 2198 "QoS NH_FLD_UDP_PORT_DST rule data set failed"); 2199 return -1; 2200 } 2201 2202 ret = dpaa2_flow_rule_data_set( 2203 &priv->extract.tc_key_extract[group], 2204 &flow->fs_rule, 2205 NET_PROT_UDP, 2206 NH_FLD_UDP_PORT_DST, 2207 &spec->hdr.dst_port, 2208 &mask->hdr.dst_port, 2209 NH_FLD_UDP_PORT_SIZE); 2210 if (ret) { 2211 DPAA2_PMD_ERR( 2212 "FS NH_FLD_UDP_PORT_DST rule data set failed"); 2213 return -1; 2214 } 2215 } 2216 2217 (*device_configured) |= local_cfg; 2218 2219 return 0; 2220 } 2221 2222 static int 2223 dpaa2_configure_flow_tcp(struct rte_flow *flow, 2224 struct rte_eth_dev *dev, 2225 const struct rte_flow_attr *attr, 2226 const struct rte_flow_item *pattern, 2227 const struct rte_flow_action actions[] __rte_unused, 2228 struct rte_flow_error *error __rte_unused, 2229 int *device_configured) 2230 { 2231 int index, ret; 2232 int local_cfg = 0; 2233 uint32_t group; 2234 const struct rte_flow_item_tcp *spec, *mask; 2235 2236 const struct rte_flow_item_tcp *last __rte_unused; 2237 struct dpaa2_dev_priv *priv = dev->data->dev_private; 2238 2239 group = attr->group; 2240 2241 /* Parse pattern list to get the matching parameters */ 2242 spec = (const struct rte_flow_item_tcp *)pattern->spec; 2243 last = (const struct rte_flow_item_tcp *)pattern->last; 2244 mask = (const struct rte_flow_item_tcp *) 2245 (pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask); 2246 2247 /* Get traffic class index and flow id to be configured */ 2248 flow->tc_id = group; 2249 flow->tc_index = attr->priority; 2250 2251 if (!spec || !mc_l4_port_identification) { 2252 struct proto_discrimination proto; 2253 2254 index = dpaa2_flow_extract_search( 2255 &priv->extract.qos_key_extract.dpkg, 2256 NET_PROT_IP, NH_FLD_IP_PROTO); 2257 if (index < 0) { 2258 ret = dpaa2_flow_proto_discrimination_extract( 2259 &priv->extract.qos_key_extract, 2260 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2261 if (ret) { 2262 DPAA2_PMD_ERR( 2263 "QoS Extract IP protocol to discriminate TCP failed."); 2264 2265 return -1; 2266 } 2267 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2268 } 2269 2270 index = dpaa2_flow_extract_search( 2271 &priv->extract.tc_key_extract[group].dpkg, 2272 NET_PROT_IP, NH_FLD_IP_PROTO); 2273 if (index < 0) { 2274 ret = dpaa2_flow_proto_discrimination_extract( 2275 &priv->extract.tc_key_extract[group], 2276 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2277 if (ret) { 2278 DPAA2_PMD_ERR( 2279 "FS Extract IP protocol to discriminate TCP failed."); 2280 2281 return -1; 2282 } 2283 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2284 } 2285 2286 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2287 if (ret) { 2288 DPAA2_PMD_ERR( 2289 "Move IP addr before TCP discrimination set failed"); 2290 return -1; 2291 } 2292 2293 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP; 2294 proto.ip_proto = IPPROTO_TCP; 2295 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 2296 proto, group); 2297 if (ret) { 2298 DPAA2_PMD_ERR("TCP discrimination rule set failed"); 2299 return -1; 2300 } 2301 2302 (*device_configured) |= local_cfg; 2303 2304 if (!spec) 2305 return 0; 2306 } 2307 2308 if (dpaa2_flow_extract_support((const uint8_t *)mask, 2309 RTE_FLOW_ITEM_TYPE_TCP)) { 2310 DPAA2_PMD_WARN("Extract field(s) of TCP not support."); 2311 2312 return -1; 2313 } 2314 2315 if (mask->hdr.src_port) { 2316 index = dpaa2_flow_extract_search( 2317 &priv->extract.qos_key_extract.dpkg, 2318 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC); 2319 if (index < 0) { 2320 ret = dpaa2_flow_extract_add( 2321 &priv->extract.qos_key_extract, 2322 NET_PROT_TCP, 2323 NH_FLD_TCP_PORT_SRC, 2324 NH_FLD_TCP_PORT_SIZE); 2325 if (ret) { 2326 DPAA2_PMD_ERR("QoS Extract add TCP_SRC failed."); 2327 2328 return -1; 2329 } 2330 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2331 } 2332 2333 index = dpaa2_flow_extract_search( 2334 &priv->extract.tc_key_extract[group].dpkg, 2335 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC); 2336 if (index < 0) { 2337 ret = dpaa2_flow_extract_add( 2338 &priv->extract.tc_key_extract[group], 2339 NET_PROT_TCP, 2340 NH_FLD_TCP_PORT_SRC, 2341 NH_FLD_TCP_PORT_SIZE); 2342 if (ret) { 2343 DPAA2_PMD_ERR("FS Extract add TCP_SRC failed."); 2344 2345 return -1; 2346 } 2347 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2348 } 2349 2350 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2351 if (ret) { 2352 DPAA2_PMD_ERR( 2353 "Move ipaddr before TCP_PORT_SRC set failed"); 2354 return -1; 2355 } 2356 2357 ret = dpaa2_flow_rule_data_set( 2358 &priv->extract.qos_key_extract, 2359 &flow->qos_rule, 2360 NET_PROT_TCP, 2361 NH_FLD_TCP_PORT_SRC, 2362 &spec->hdr.src_port, 2363 &mask->hdr.src_port, 2364 NH_FLD_TCP_PORT_SIZE); 2365 if (ret) { 2366 DPAA2_PMD_ERR( 2367 "QoS NH_FLD_TCP_PORT_SRC rule data set failed"); 2368 return -1; 2369 } 2370 2371 ret = dpaa2_flow_rule_data_set( 2372 &priv->extract.tc_key_extract[group], 2373 &flow->fs_rule, 2374 NET_PROT_TCP, 2375 NH_FLD_TCP_PORT_SRC, 2376 &spec->hdr.src_port, 2377 &mask->hdr.src_port, 2378 NH_FLD_TCP_PORT_SIZE); 2379 if (ret) { 2380 DPAA2_PMD_ERR( 2381 "FS NH_FLD_TCP_PORT_SRC rule data set failed"); 2382 return -1; 2383 } 2384 } 2385 2386 if (mask->hdr.dst_port) { 2387 index = dpaa2_flow_extract_search( 2388 &priv->extract.qos_key_extract.dpkg, 2389 NET_PROT_TCP, NH_FLD_TCP_PORT_DST); 2390 if (index < 0) { 2391 ret = dpaa2_flow_extract_add( 2392 &priv->extract.qos_key_extract, 2393 NET_PROT_TCP, 2394 NH_FLD_TCP_PORT_DST, 2395 NH_FLD_TCP_PORT_SIZE); 2396 if (ret) { 2397 DPAA2_PMD_ERR("QoS Extract add TCP_DST failed."); 2398 2399 return -1; 2400 } 2401 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2402 } 2403 2404 index = dpaa2_flow_extract_search( 2405 &priv->extract.tc_key_extract[group].dpkg, 2406 NET_PROT_TCP, NH_FLD_TCP_PORT_DST); 2407 if (index < 0) { 2408 ret = dpaa2_flow_extract_add( 2409 &priv->extract.tc_key_extract[group], 2410 NET_PROT_TCP, 2411 NH_FLD_TCP_PORT_DST, 2412 NH_FLD_TCP_PORT_SIZE); 2413 if (ret) { 2414 DPAA2_PMD_ERR("FS Extract add TCP_DST failed."); 2415 2416 return -1; 2417 } 2418 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2419 } 2420 2421 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2422 if (ret) { 2423 DPAA2_PMD_ERR( 2424 "Move ipaddr before TCP_PORT_DST set failed"); 2425 return -1; 2426 } 2427 2428 ret = dpaa2_flow_rule_data_set( 2429 &priv->extract.qos_key_extract, 2430 &flow->qos_rule, 2431 NET_PROT_TCP, 2432 NH_FLD_TCP_PORT_DST, 2433 &spec->hdr.dst_port, 2434 &mask->hdr.dst_port, 2435 NH_FLD_TCP_PORT_SIZE); 2436 if (ret) { 2437 DPAA2_PMD_ERR( 2438 "QoS NH_FLD_TCP_PORT_DST rule data set failed"); 2439 return -1; 2440 } 2441 2442 ret = dpaa2_flow_rule_data_set( 2443 &priv->extract.tc_key_extract[group], 2444 &flow->fs_rule, 2445 NET_PROT_TCP, 2446 NH_FLD_TCP_PORT_DST, 2447 &spec->hdr.dst_port, 2448 &mask->hdr.dst_port, 2449 NH_FLD_TCP_PORT_SIZE); 2450 if (ret) { 2451 DPAA2_PMD_ERR( 2452 "FS NH_FLD_TCP_PORT_DST rule data set failed"); 2453 return -1; 2454 } 2455 } 2456 2457 (*device_configured) |= local_cfg; 2458 2459 return 0; 2460 } 2461 2462 static int 2463 dpaa2_configure_flow_sctp(struct rte_flow *flow, 2464 struct rte_eth_dev *dev, 2465 const struct rte_flow_attr *attr, 2466 const struct rte_flow_item *pattern, 2467 const struct rte_flow_action actions[] __rte_unused, 2468 struct rte_flow_error *error __rte_unused, 2469 int *device_configured) 2470 { 2471 int index, ret; 2472 int local_cfg = 0; 2473 uint32_t group; 2474 const struct rte_flow_item_sctp *spec, *mask; 2475 2476 const struct rte_flow_item_sctp *last __rte_unused; 2477 struct dpaa2_dev_priv *priv = dev->data->dev_private; 2478 2479 group = attr->group; 2480 2481 /* Parse pattern list to get the matching parameters */ 2482 spec = (const struct rte_flow_item_sctp *)pattern->spec; 2483 last = (const struct rte_flow_item_sctp *)pattern->last; 2484 mask = (const struct rte_flow_item_sctp *) 2485 (pattern->mask ? pattern->mask : 2486 &dpaa2_flow_item_sctp_mask); 2487 2488 /* Get traffic class index and flow id to be configured */ 2489 flow->tc_id = group; 2490 flow->tc_index = attr->priority; 2491 2492 if (!spec || !mc_l4_port_identification) { 2493 struct proto_discrimination proto; 2494 2495 index = dpaa2_flow_extract_search( 2496 &priv->extract.qos_key_extract.dpkg, 2497 NET_PROT_IP, NH_FLD_IP_PROTO); 2498 if (index < 0) { 2499 ret = dpaa2_flow_proto_discrimination_extract( 2500 &priv->extract.qos_key_extract, 2501 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2502 if (ret) { 2503 DPAA2_PMD_ERR( 2504 "QoS Extract IP protocol to discriminate SCTP failed."); 2505 2506 return -1; 2507 } 2508 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2509 } 2510 2511 index = dpaa2_flow_extract_search( 2512 &priv->extract.tc_key_extract[group].dpkg, 2513 NET_PROT_IP, NH_FLD_IP_PROTO); 2514 if (index < 0) { 2515 ret = dpaa2_flow_proto_discrimination_extract( 2516 &priv->extract.tc_key_extract[group], 2517 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2518 if (ret) { 2519 DPAA2_PMD_ERR( 2520 "FS Extract IP protocol to discriminate SCTP failed."); 2521 2522 return -1; 2523 } 2524 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2525 } 2526 2527 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2528 if (ret) { 2529 DPAA2_PMD_ERR( 2530 "Move ipaddr before SCTP discrimination set failed"); 2531 return -1; 2532 } 2533 2534 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP; 2535 proto.ip_proto = IPPROTO_SCTP; 2536 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 2537 proto, group); 2538 if (ret) { 2539 DPAA2_PMD_ERR("SCTP discrimination rule set failed"); 2540 return -1; 2541 } 2542 2543 (*device_configured) |= local_cfg; 2544 2545 if (!spec) 2546 return 0; 2547 } 2548 2549 if (dpaa2_flow_extract_support((const uint8_t *)mask, 2550 RTE_FLOW_ITEM_TYPE_SCTP)) { 2551 DPAA2_PMD_WARN("Extract field(s) of SCTP not support."); 2552 2553 return -1; 2554 } 2555 2556 if (mask->hdr.src_port) { 2557 index = dpaa2_flow_extract_search( 2558 &priv->extract.qos_key_extract.dpkg, 2559 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC); 2560 if (index < 0) { 2561 ret = dpaa2_flow_extract_add( 2562 &priv->extract.qos_key_extract, 2563 NET_PROT_SCTP, 2564 NH_FLD_SCTP_PORT_SRC, 2565 NH_FLD_SCTP_PORT_SIZE); 2566 if (ret) { 2567 DPAA2_PMD_ERR("QoS Extract add SCTP_SRC failed."); 2568 2569 return -1; 2570 } 2571 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2572 } 2573 2574 index = dpaa2_flow_extract_search( 2575 &priv->extract.tc_key_extract[group].dpkg, 2576 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC); 2577 if (index < 0) { 2578 ret = dpaa2_flow_extract_add( 2579 &priv->extract.tc_key_extract[group], 2580 NET_PROT_SCTP, 2581 NH_FLD_SCTP_PORT_SRC, 2582 NH_FLD_SCTP_PORT_SIZE); 2583 if (ret) { 2584 DPAA2_PMD_ERR("FS Extract add SCTP_SRC failed."); 2585 2586 return -1; 2587 } 2588 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2589 } 2590 2591 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2592 if (ret) { 2593 DPAA2_PMD_ERR( 2594 "Move ipaddr before SCTP_PORT_SRC set failed"); 2595 return -1; 2596 } 2597 2598 ret = dpaa2_flow_rule_data_set( 2599 &priv->extract.qos_key_extract, 2600 &flow->qos_rule, 2601 NET_PROT_SCTP, 2602 NH_FLD_SCTP_PORT_SRC, 2603 &spec->hdr.src_port, 2604 &mask->hdr.src_port, 2605 NH_FLD_SCTP_PORT_SIZE); 2606 if (ret) { 2607 DPAA2_PMD_ERR( 2608 "QoS NH_FLD_SCTP_PORT_SRC rule data set failed"); 2609 return -1; 2610 } 2611 2612 ret = dpaa2_flow_rule_data_set( 2613 &priv->extract.tc_key_extract[group], 2614 &flow->fs_rule, 2615 NET_PROT_SCTP, 2616 NH_FLD_SCTP_PORT_SRC, 2617 &spec->hdr.src_port, 2618 &mask->hdr.src_port, 2619 NH_FLD_SCTP_PORT_SIZE); 2620 if (ret) { 2621 DPAA2_PMD_ERR( 2622 "FS NH_FLD_SCTP_PORT_SRC rule data set failed"); 2623 return -1; 2624 } 2625 } 2626 2627 if (mask->hdr.dst_port) { 2628 index = dpaa2_flow_extract_search( 2629 &priv->extract.qos_key_extract.dpkg, 2630 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST); 2631 if (index < 0) { 2632 ret = dpaa2_flow_extract_add( 2633 &priv->extract.qos_key_extract, 2634 NET_PROT_SCTP, 2635 NH_FLD_SCTP_PORT_DST, 2636 NH_FLD_SCTP_PORT_SIZE); 2637 if (ret) { 2638 DPAA2_PMD_ERR("QoS Extract add SCTP_DST failed."); 2639 2640 return -1; 2641 } 2642 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2643 } 2644 2645 index = dpaa2_flow_extract_search( 2646 &priv->extract.tc_key_extract[group].dpkg, 2647 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST); 2648 if (index < 0) { 2649 ret = dpaa2_flow_extract_add( 2650 &priv->extract.tc_key_extract[group], 2651 NET_PROT_SCTP, 2652 NH_FLD_SCTP_PORT_DST, 2653 NH_FLD_SCTP_PORT_SIZE); 2654 if (ret) { 2655 DPAA2_PMD_ERR("FS Extract add SCTP_DST failed."); 2656 2657 return -1; 2658 } 2659 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2660 } 2661 2662 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2663 if (ret) { 2664 DPAA2_PMD_ERR( 2665 "Move ipaddr before SCTP_PORT_DST set failed"); 2666 return -1; 2667 } 2668 2669 ret = dpaa2_flow_rule_data_set( 2670 &priv->extract.qos_key_extract, 2671 &flow->qos_rule, 2672 NET_PROT_SCTP, 2673 NH_FLD_SCTP_PORT_DST, 2674 &spec->hdr.dst_port, 2675 &mask->hdr.dst_port, 2676 NH_FLD_SCTP_PORT_SIZE); 2677 if (ret) { 2678 DPAA2_PMD_ERR( 2679 "QoS NH_FLD_SCTP_PORT_DST rule data set failed"); 2680 return -1; 2681 } 2682 2683 ret = dpaa2_flow_rule_data_set( 2684 &priv->extract.tc_key_extract[group], 2685 &flow->fs_rule, 2686 NET_PROT_SCTP, 2687 NH_FLD_SCTP_PORT_DST, 2688 &spec->hdr.dst_port, 2689 &mask->hdr.dst_port, 2690 NH_FLD_SCTP_PORT_SIZE); 2691 if (ret) { 2692 DPAA2_PMD_ERR( 2693 "FS NH_FLD_SCTP_PORT_DST rule data set failed"); 2694 return -1; 2695 } 2696 } 2697 2698 (*device_configured) |= local_cfg; 2699 2700 return 0; 2701 } 2702 2703 static int 2704 dpaa2_configure_flow_gre(struct rte_flow *flow, 2705 struct rte_eth_dev *dev, 2706 const struct rte_flow_attr *attr, 2707 const struct rte_flow_item *pattern, 2708 const struct rte_flow_action actions[] __rte_unused, 2709 struct rte_flow_error *error __rte_unused, 2710 int *device_configured) 2711 { 2712 int index, ret; 2713 int local_cfg = 0; 2714 uint32_t group; 2715 const struct rte_flow_item_gre *spec, *mask; 2716 2717 const struct rte_flow_item_gre *last __rte_unused; 2718 struct dpaa2_dev_priv *priv = dev->data->dev_private; 2719 2720 group = attr->group; 2721 2722 /* Parse pattern list to get the matching parameters */ 2723 spec = (const struct rte_flow_item_gre *)pattern->spec; 2724 last = (const struct rte_flow_item_gre *)pattern->last; 2725 mask = (const struct rte_flow_item_gre *) 2726 (pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask); 2727 2728 /* Get traffic class index and flow id to be configured */ 2729 flow->tc_id = group; 2730 flow->tc_index = attr->priority; 2731 2732 if (!spec) { 2733 struct proto_discrimination proto; 2734 2735 index = dpaa2_flow_extract_search( 2736 &priv->extract.qos_key_extract.dpkg, 2737 NET_PROT_IP, NH_FLD_IP_PROTO); 2738 if (index < 0) { 2739 ret = dpaa2_flow_proto_discrimination_extract( 2740 &priv->extract.qos_key_extract, 2741 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2742 if (ret) { 2743 DPAA2_PMD_ERR( 2744 "QoS Extract IP protocol to discriminate GRE failed."); 2745 2746 return -1; 2747 } 2748 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2749 } 2750 2751 index = dpaa2_flow_extract_search( 2752 &priv->extract.tc_key_extract[group].dpkg, 2753 NET_PROT_IP, NH_FLD_IP_PROTO); 2754 if (index < 0) { 2755 ret = dpaa2_flow_proto_discrimination_extract( 2756 &priv->extract.tc_key_extract[group], 2757 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP); 2758 if (ret) { 2759 DPAA2_PMD_ERR( 2760 "FS Extract IP protocol to discriminate GRE failed."); 2761 2762 return -1; 2763 } 2764 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2765 } 2766 2767 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2768 if (ret) { 2769 DPAA2_PMD_ERR( 2770 "Move IP addr before GRE discrimination set failed"); 2771 return -1; 2772 } 2773 2774 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP; 2775 proto.ip_proto = IPPROTO_GRE; 2776 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, 2777 proto, group); 2778 if (ret) { 2779 DPAA2_PMD_ERR("GRE discrimination rule set failed"); 2780 return -1; 2781 } 2782 2783 (*device_configured) |= local_cfg; 2784 2785 return 0; 2786 } 2787 2788 if (dpaa2_flow_extract_support((const uint8_t *)mask, 2789 RTE_FLOW_ITEM_TYPE_GRE)) { 2790 DPAA2_PMD_WARN("Extract field(s) of GRE not support."); 2791 2792 return -1; 2793 } 2794 2795 if (!mask->protocol) 2796 return 0; 2797 2798 index = dpaa2_flow_extract_search( 2799 &priv->extract.qos_key_extract.dpkg, 2800 NET_PROT_GRE, NH_FLD_GRE_TYPE); 2801 if (index < 0) { 2802 ret = dpaa2_flow_extract_add( 2803 &priv->extract.qos_key_extract, 2804 NET_PROT_GRE, 2805 NH_FLD_GRE_TYPE, 2806 sizeof(rte_be16_t)); 2807 if (ret) { 2808 DPAA2_PMD_ERR("QoS Extract add GRE_TYPE failed."); 2809 2810 return -1; 2811 } 2812 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2813 } 2814 2815 index = dpaa2_flow_extract_search( 2816 &priv->extract.tc_key_extract[group].dpkg, 2817 NET_PROT_GRE, NH_FLD_GRE_TYPE); 2818 if (index < 0) { 2819 ret = dpaa2_flow_extract_add( 2820 &priv->extract.tc_key_extract[group], 2821 NET_PROT_GRE, 2822 NH_FLD_GRE_TYPE, 2823 sizeof(rte_be16_t)); 2824 if (ret) { 2825 DPAA2_PMD_ERR("FS Extract add GRE_TYPE failed."); 2826 2827 return -1; 2828 } 2829 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2830 } 2831 2832 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group); 2833 if (ret) { 2834 DPAA2_PMD_ERR( 2835 "Move ipaddr before GRE_TYPE set failed"); 2836 return -1; 2837 } 2838 2839 ret = dpaa2_flow_rule_data_set( 2840 &priv->extract.qos_key_extract, 2841 &flow->qos_rule, 2842 NET_PROT_GRE, 2843 NH_FLD_GRE_TYPE, 2844 &spec->protocol, 2845 &mask->protocol, 2846 sizeof(rte_be16_t)); 2847 if (ret) { 2848 DPAA2_PMD_ERR( 2849 "QoS NH_FLD_GRE_TYPE rule data set failed"); 2850 return -1; 2851 } 2852 2853 ret = dpaa2_flow_rule_data_set( 2854 &priv->extract.tc_key_extract[group], 2855 &flow->fs_rule, 2856 NET_PROT_GRE, 2857 NH_FLD_GRE_TYPE, 2858 &spec->protocol, 2859 &mask->protocol, 2860 sizeof(rte_be16_t)); 2861 if (ret) { 2862 DPAA2_PMD_ERR( 2863 "FS NH_FLD_GRE_TYPE rule data set failed"); 2864 return -1; 2865 } 2866 2867 (*device_configured) |= local_cfg; 2868 2869 return 0; 2870 } 2871 2872 static int 2873 dpaa2_configure_flow_raw(struct rte_flow *flow, 2874 struct rte_eth_dev *dev, 2875 const struct rte_flow_attr *attr, 2876 const struct rte_flow_item *pattern, 2877 const struct rte_flow_action actions[] __rte_unused, 2878 struct rte_flow_error *error __rte_unused, 2879 int *device_configured) 2880 { 2881 struct dpaa2_dev_priv *priv = dev->data->dev_private; 2882 const struct rte_flow_item_raw *spec = pattern->spec; 2883 const struct rte_flow_item_raw *mask = pattern->mask; 2884 int prev_key_size = 2885 priv->extract.qos_key_extract.key_info.key_total_size; 2886 int local_cfg = 0, ret; 2887 uint32_t group; 2888 2889 /* Need both spec and mask */ 2890 if (!spec || !mask) { 2891 DPAA2_PMD_ERR("spec or mask not present."); 2892 return -EINVAL; 2893 } 2894 /* Only supports non-relative with offset 0 */ 2895 if (spec->relative || spec->offset != 0 || 2896 spec->search || spec->limit) { 2897 DPAA2_PMD_ERR("relative and non zero offset not supported."); 2898 return -EINVAL; 2899 } 2900 /* Spec len and mask len should be same */ 2901 if (spec->length != mask->length) { 2902 DPAA2_PMD_ERR("Spec len and mask len mismatch."); 2903 return -EINVAL; 2904 } 2905 2906 /* Get traffic class index and flow id to be configured */ 2907 group = attr->group; 2908 flow->tc_id = group; 2909 flow->tc_index = attr->priority; 2910 2911 if (prev_key_size <= spec->length) { 2912 ret = dpaa2_flow_extract_add_raw(&priv->extract.qos_key_extract, 2913 spec->length); 2914 if (ret) { 2915 DPAA2_PMD_ERR("QoS Extract RAW add failed."); 2916 return -1; 2917 } 2918 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE; 2919 2920 ret = dpaa2_flow_extract_add_raw( 2921 &priv->extract.tc_key_extract[group], 2922 spec->length); 2923 if (ret) { 2924 DPAA2_PMD_ERR("FS Extract RAW add failed."); 2925 return -1; 2926 } 2927 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE; 2928 } 2929 2930 ret = dpaa2_flow_rule_data_set_raw(&flow->qos_rule, spec->pattern, 2931 mask->pattern, spec->length); 2932 if (ret) { 2933 DPAA2_PMD_ERR("QoS RAW rule data set failed"); 2934 return -1; 2935 } 2936 2937 ret = dpaa2_flow_rule_data_set_raw(&flow->fs_rule, spec->pattern, 2938 mask->pattern, spec->length); 2939 if (ret) { 2940 DPAA2_PMD_ERR("FS RAW rule data set failed"); 2941 return -1; 2942 } 2943 2944 (*device_configured) |= local_cfg; 2945 2946 return 0; 2947 } 2948 2949 static inline int 2950 dpaa2_fs_action_supported(enum rte_flow_action_type action) 2951 { 2952 int i; 2953 2954 for (i = 0; i < (int)(sizeof(dpaa2_supported_fs_action_type) / 2955 sizeof(enum rte_flow_action_type)); i++) { 2956 if (action == dpaa2_supported_fs_action_type[i]) 2957 return 1; 2958 } 2959 2960 return 0; 2961 } 2962 /* The existing QoS/FS entry with IP address(es) 2963 * needs update after 2964 * new extract(s) are inserted before IP 2965 * address(es) extract(s). 2966 */ 2967 static int 2968 dpaa2_flow_entry_update( 2969 struct dpaa2_dev_priv *priv, uint8_t tc_id) 2970 { 2971 struct rte_flow *curr = LIST_FIRST(&priv->flows); 2972 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 2973 int ret; 2974 int qos_ipsrc_offset = -1, qos_ipdst_offset = -1; 2975 int fs_ipsrc_offset = -1, fs_ipdst_offset = -1; 2976 struct dpaa2_key_extract *qos_key_extract = 2977 &priv->extract.qos_key_extract; 2978 struct dpaa2_key_extract *tc_key_extract = 2979 &priv->extract.tc_key_extract[tc_id]; 2980 char ipsrc_key[NH_FLD_IPV6_ADDR_SIZE]; 2981 char ipdst_key[NH_FLD_IPV6_ADDR_SIZE]; 2982 char ipsrc_mask[NH_FLD_IPV6_ADDR_SIZE]; 2983 char ipdst_mask[NH_FLD_IPV6_ADDR_SIZE]; 2984 int extend = -1, extend1, size = -1; 2985 uint16_t qos_index; 2986 2987 while (curr) { 2988 if (curr->ipaddr_rule.ipaddr_type == 2989 FLOW_NONE_IPADDR) { 2990 curr = LIST_NEXT(curr, next); 2991 continue; 2992 } 2993 2994 if (curr->ipaddr_rule.ipaddr_type == 2995 FLOW_IPV4_ADDR) { 2996 qos_ipsrc_offset = 2997 qos_key_extract->key_info.ipv4_src_offset; 2998 qos_ipdst_offset = 2999 qos_key_extract->key_info.ipv4_dst_offset; 3000 fs_ipsrc_offset = 3001 tc_key_extract->key_info.ipv4_src_offset; 3002 fs_ipdst_offset = 3003 tc_key_extract->key_info.ipv4_dst_offset; 3004 size = NH_FLD_IPV4_ADDR_SIZE; 3005 } else { 3006 qos_ipsrc_offset = 3007 qos_key_extract->key_info.ipv6_src_offset; 3008 qos_ipdst_offset = 3009 qos_key_extract->key_info.ipv6_dst_offset; 3010 fs_ipsrc_offset = 3011 tc_key_extract->key_info.ipv6_src_offset; 3012 fs_ipdst_offset = 3013 tc_key_extract->key_info.ipv6_dst_offset; 3014 size = NH_FLD_IPV6_ADDR_SIZE; 3015 } 3016 3017 qos_index = curr->tc_id * priv->fs_entries + 3018 curr->tc_index; 3019 3020 dpaa2_flow_qos_entry_log("Before update", curr, qos_index); 3021 3022 if (priv->num_rx_tc > 1) { 3023 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, 3024 priv->token, &curr->qos_rule); 3025 if (ret) { 3026 DPAA2_PMD_ERR("Qos entry remove failed."); 3027 return -1; 3028 } 3029 } 3030 3031 extend = -1; 3032 3033 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) { 3034 RTE_ASSERT(qos_ipsrc_offset >= 3035 curr->ipaddr_rule.qos_ipsrc_offset); 3036 extend1 = qos_ipsrc_offset - 3037 curr->ipaddr_rule.qos_ipsrc_offset; 3038 if (extend >= 0) 3039 RTE_ASSERT(extend == extend1); 3040 else 3041 extend = extend1; 3042 3043 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) || 3044 (size == NH_FLD_IPV6_ADDR_SIZE)); 3045 3046 memcpy(ipsrc_key, 3047 (char *)(size_t)curr->qos_rule.key_iova + 3048 curr->ipaddr_rule.qos_ipsrc_offset, 3049 size); 3050 memset((char *)(size_t)curr->qos_rule.key_iova + 3051 curr->ipaddr_rule.qos_ipsrc_offset, 3052 0, size); 3053 3054 memcpy(ipsrc_mask, 3055 (char *)(size_t)curr->qos_rule.mask_iova + 3056 curr->ipaddr_rule.qos_ipsrc_offset, 3057 size); 3058 memset((char *)(size_t)curr->qos_rule.mask_iova + 3059 curr->ipaddr_rule.qos_ipsrc_offset, 3060 0, size); 3061 3062 curr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset; 3063 } 3064 3065 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) { 3066 RTE_ASSERT(qos_ipdst_offset >= 3067 curr->ipaddr_rule.qos_ipdst_offset); 3068 extend1 = qos_ipdst_offset - 3069 curr->ipaddr_rule.qos_ipdst_offset; 3070 if (extend >= 0) 3071 RTE_ASSERT(extend == extend1); 3072 else 3073 extend = extend1; 3074 3075 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) || 3076 (size == NH_FLD_IPV6_ADDR_SIZE)); 3077 3078 memcpy(ipdst_key, 3079 (char *)(size_t)curr->qos_rule.key_iova + 3080 curr->ipaddr_rule.qos_ipdst_offset, 3081 size); 3082 memset((char *)(size_t)curr->qos_rule.key_iova + 3083 curr->ipaddr_rule.qos_ipdst_offset, 3084 0, size); 3085 3086 memcpy(ipdst_mask, 3087 (char *)(size_t)curr->qos_rule.mask_iova + 3088 curr->ipaddr_rule.qos_ipdst_offset, 3089 size); 3090 memset((char *)(size_t)curr->qos_rule.mask_iova + 3091 curr->ipaddr_rule.qos_ipdst_offset, 3092 0, size); 3093 3094 curr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset; 3095 } 3096 3097 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) { 3098 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) || 3099 (size == NH_FLD_IPV6_ADDR_SIZE)); 3100 memcpy((char *)(size_t)curr->qos_rule.key_iova + 3101 curr->ipaddr_rule.qos_ipsrc_offset, 3102 ipsrc_key, 3103 size); 3104 memcpy((char *)(size_t)curr->qos_rule.mask_iova + 3105 curr->ipaddr_rule.qos_ipsrc_offset, 3106 ipsrc_mask, 3107 size); 3108 } 3109 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) { 3110 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) || 3111 (size == NH_FLD_IPV6_ADDR_SIZE)); 3112 memcpy((char *)(size_t)curr->qos_rule.key_iova + 3113 curr->ipaddr_rule.qos_ipdst_offset, 3114 ipdst_key, 3115 size); 3116 memcpy((char *)(size_t)curr->qos_rule.mask_iova + 3117 curr->ipaddr_rule.qos_ipdst_offset, 3118 ipdst_mask, 3119 size); 3120 } 3121 3122 if (extend >= 0) 3123 curr->qos_real_key_size += extend; 3124 3125 curr->qos_rule.key_size = FIXED_ENTRY_SIZE; 3126 3127 dpaa2_flow_qos_entry_log("Start update", curr, qos_index); 3128 3129 if (priv->num_rx_tc > 1) { 3130 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, 3131 priv->token, &curr->qos_rule, 3132 curr->tc_id, qos_index, 3133 0, 0); 3134 if (ret) { 3135 DPAA2_PMD_ERR("Qos entry update failed."); 3136 return -1; 3137 } 3138 } 3139 3140 if (!dpaa2_fs_action_supported(curr->action)) { 3141 curr = LIST_NEXT(curr, next); 3142 continue; 3143 } 3144 3145 dpaa2_flow_fs_entry_log("Before update", curr); 3146 extend = -1; 3147 3148 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, 3149 priv->token, curr->tc_id, &curr->fs_rule); 3150 if (ret) { 3151 DPAA2_PMD_ERR("FS entry remove failed."); 3152 return -1; 3153 } 3154 3155 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0 && 3156 tc_id == curr->tc_id) { 3157 RTE_ASSERT(fs_ipsrc_offset >= 3158 curr->ipaddr_rule.fs_ipsrc_offset); 3159 extend1 = fs_ipsrc_offset - 3160 curr->ipaddr_rule.fs_ipsrc_offset; 3161 if (extend >= 0) 3162 RTE_ASSERT(extend == extend1); 3163 else 3164 extend = extend1; 3165 3166 memcpy(ipsrc_key, 3167 (char *)(size_t)curr->fs_rule.key_iova + 3168 curr->ipaddr_rule.fs_ipsrc_offset, 3169 size); 3170 memset((char *)(size_t)curr->fs_rule.key_iova + 3171 curr->ipaddr_rule.fs_ipsrc_offset, 3172 0, size); 3173 3174 memcpy(ipsrc_mask, 3175 (char *)(size_t)curr->fs_rule.mask_iova + 3176 curr->ipaddr_rule.fs_ipsrc_offset, 3177 size); 3178 memset((char *)(size_t)curr->fs_rule.mask_iova + 3179 curr->ipaddr_rule.fs_ipsrc_offset, 3180 0, size); 3181 3182 curr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset; 3183 } 3184 3185 if (curr->ipaddr_rule.fs_ipdst_offset >= 0 && 3186 tc_id == curr->tc_id) { 3187 RTE_ASSERT(fs_ipdst_offset >= 3188 curr->ipaddr_rule.fs_ipdst_offset); 3189 extend1 = fs_ipdst_offset - 3190 curr->ipaddr_rule.fs_ipdst_offset; 3191 if (extend >= 0) 3192 RTE_ASSERT(extend == extend1); 3193 else 3194 extend = extend1; 3195 3196 memcpy(ipdst_key, 3197 (char *)(size_t)curr->fs_rule.key_iova + 3198 curr->ipaddr_rule.fs_ipdst_offset, 3199 size); 3200 memset((char *)(size_t)curr->fs_rule.key_iova + 3201 curr->ipaddr_rule.fs_ipdst_offset, 3202 0, size); 3203 3204 memcpy(ipdst_mask, 3205 (char *)(size_t)curr->fs_rule.mask_iova + 3206 curr->ipaddr_rule.fs_ipdst_offset, 3207 size); 3208 memset((char *)(size_t)curr->fs_rule.mask_iova + 3209 curr->ipaddr_rule.fs_ipdst_offset, 3210 0, size); 3211 3212 curr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset; 3213 } 3214 3215 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0) { 3216 memcpy((char *)(size_t)curr->fs_rule.key_iova + 3217 curr->ipaddr_rule.fs_ipsrc_offset, 3218 ipsrc_key, 3219 size); 3220 memcpy((char *)(size_t)curr->fs_rule.mask_iova + 3221 curr->ipaddr_rule.fs_ipsrc_offset, 3222 ipsrc_mask, 3223 size); 3224 } 3225 if (curr->ipaddr_rule.fs_ipdst_offset >= 0) { 3226 memcpy((char *)(size_t)curr->fs_rule.key_iova + 3227 curr->ipaddr_rule.fs_ipdst_offset, 3228 ipdst_key, 3229 size); 3230 memcpy((char *)(size_t)curr->fs_rule.mask_iova + 3231 curr->ipaddr_rule.fs_ipdst_offset, 3232 ipdst_mask, 3233 size); 3234 } 3235 3236 if (extend >= 0) 3237 curr->fs_real_key_size += extend; 3238 curr->fs_rule.key_size = FIXED_ENTRY_SIZE; 3239 3240 dpaa2_flow_fs_entry_log("Start update", curr); 3241 3242 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, 3243 priv->token, curr->tc_id, curr->tc_index, 3244 &curr->fs_rule, &curr->action_cfg); 3245 if (ret) { 3246 DPAA2_PMD_ERR("FS entry update failed."); 3247 return -1; 3248 } 3249 3250 curr = LIST_NEXT(curr, next); 3251 } 3252 3253 return 0; 3254 } 3255 3256 static inline int 3257 dpaa2_flow_verify_attr( 3258 struct dpaa2_dev_priv *priv, 3259 const struct rte_flow_attr *attr) 3260 { 3261 struct rte_flow *curr = LIST_FIRST(&priv->flows); 3262 3263 while (curr) { 3264 if (curr->tc_id == attr->group && 3265 curr->tc_index == attr->priority) { 3266 DPAA2_PMD_ERR( 3267 "Flow with group %d and priority %d already exists.", 3268 attr->group, attr->priority); 3269 3270 return -1; 3271 } 3272 curr = LIST_NEXT(curr, next); 3273 } 3274 3275 return 0; 3276 } 3277 3278 static inline struct rte_eth_dev * 3279 dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv, 3280 const struct rte_flow_action *action) 3281 { 3282 const struct rte_flow_action_phy_port *phy_port; 3283 const struct rte_flow_action_port_id *port_id; 3284 int idx = -1; 3285 struct rte_eth_dev *dest_dev; 3286 3287 if (action->type == RTE_FLOW_ACTION_TYPE_PHY_PORT) { 3288 phy_port = (const struct rte_flow_action_phy_port *) 3289 action->conf; 3290 if (!phy_port->original) 3291 idx = phy_port->index; 3292 } else if (action->type == RTE_FLOW_ACTION_TYPE_PORT_ID) { 3293 port_id = (const struct rte_flow_action_port_id *) 3294 action->conf; 3295 if (!port_id->original) 3296 idx = port_id->id; 3297 } else { 3298 return NULL; 3299 } 3300 3301 if (idx >= 0) { 3302 if (!rte_eth_dev_is_valid_port(idx)) 3303 return NULL; 3304 dest_dev = &rte_eth_devices[idx]; 3305 } else { 3306 dest_dev = priv->eth_dev; 3307 } 3308 3309 if (!dpaa2_dev_is_dpaa2(dest_dev)) 3310 return NULL; 3311 3312 return dest_dev; 3313 } 3314 3315 static inline int 3316 dpaa2_flow_verify_action( 3317 struct dpaa2_dev_priv *priv, 3318 const struct rte_flow_attr *attr, 3319 const struct rte_flow_action actions[]) 3320 { 3321 int end_of_list = 0, i, j = 0; 3322 const struct rte_flow_action_queue *dest_queue; 3323 const struct rte_flow_action_rss *rss_conf; 3324 struct dpaa2_queue *rxq; 3325 3326 while (!end_of_list) { 3327 switch (actions[j].type) { 3328 case RTE_FLOW_ACTION_TYPE_QUEUE: 3329 dest_queue = (const struct rte_flow_action_queue *) 3330 (actions[j].conf); 3331 rxq = priv->rx_vq[dest_queue->index]; 3332 if (attr->group != rxq->tc_index) { 3333 DPAA2_PMD_ERR( 3334 "RXQ[%d] does not belong to the group %d", 3335 dest_queue->index, attr->group); 3336 3337 return -1; 3338 } 3339 break; 3340 case RTE_FLOW_ACTION_TYPE_PHY_PORT: 3341 case RTE_FLOW_ACTION_TYPE_PORT_ID: 3342 if (!dpaa2_flow_redirect_dev(priv, &actions[j])) { 3343 DPAA2_PMD_ERR("Invalid port id of action"); 3344 return -ENOTSUP; 3345 } 3346 break; 3347 case RTE_FLOW_ACTION_TYPE_RSS: 3348 rss_conf = (const struct rte_flow_action_rss *) 3349 (actions[j].conf); 3350 if (rss_conf->queue_num > priv->dist_queues) { 3351 DPAA2_PMD_ERR( 3352 "RSS number exceeds the distrbution size"); 3353 return -ENOTSUP; 3354 } 3355 for (i = 0; i < (int)rss_conf->queue_num; i++) { 3356 if (rss_conf->queue[i] >= priv->nb_rx_queues) { 3357 DPAA2_PMD_ERR( 3358 "RSS queue index exceeds the number of RXQs"); 3359 return -ENOTSUP; 3360 } 3361 rxq = priv->rx_vq[rss_conf->queue[i]]; 3362 if (rxq->tc_index != attr->group) { 3363 DPAA2_PMD_ERR( 3364 "Queue/Group combination are not supported\n"); 3365 return -ENOTSUP; 3366 } 3367 } 3368 3369 break; 3370 case RTE_FLOW_ACTION_TYPE_END: 3371 end_of_list = 1; 3372 break; 3373 default: 3374 DPAA2_PMD_ERR("Invalid action type"); 3375 return -ENOTSUP; 3376 } 3377 j++; 3378 } 3379 3380 return 0; 3381 } 3382 3383 static int 3384 dpaa2_generic_flow_set(struct rte_flow *flow, 3385 struct rte_eth_dev *dev, 3386 const struct rte_flow_attr *attr, 3387 const struct rte_flow_item pattern[], 3388 const struct rte_flow_action actions[], 3389 struct rte_flow_error *error) 3390 { 3391 const struct rte_flow_action_queue *dest_queue; 3392 const struct rte_flow_action_rss *rss_conf; 3393 int is_keycfg_configured = 0, end_of_list = 0; 3394 int ret = 0, i = 0, j = 0; 3395 struct dpni_rx_dist_cfg tc_cfg; 3396 struct dpni_qos_tbl_cfg qos_cfg; 3397 struct dpni_fs_action_cfg action; 3398 struct dpaa2_dev_priv *priv = dev->data->dev_private; 3399 struct dpaa2_queue *dest_q; 3400 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 3401 size_t param; 3402 struct rte_flow *curr = LIST_FIRST(&priv->flows); 3403 uint16_t qos_index; 3404 struct rte_eth_dev *dest_dev; 3405 struct dpaa2_dev_priv *dest_priv; 3406 3407 ret = dpaa2_flow_verify_attr(priv, attr); 3408 if (ret) 3409 return ret; 3410 3411 ret = dpaa2_flow_verify_action(priv, attr, actions); 3412 if (ret) 3413 return ret; 3414 3415 /* Parse pattern list to get the matching parameters */ 3416 while (!end_of_list) { 3417 switch (pattern[i].type) { 3418 case RTE_FLOW_ITEM_TYPE_ETH: 3419 ret = dpaa2_configure_flow_eth(flow, 3420 dev, attr, &pattern[i], actions, error, 3421 &is_keycfg_configured); 3422 if (ret) { 3423 DPAA2_PMD_ERR("ETH flow configuration failed!"); 3424 return ret; 3425 } 3426 break; 3427 case RTE_FLOW_ITEM_TYPE_VLAN: 3428 ret = dpaa2_configure_flow_vlan(flow, 3429 dev, attr, &pattern[i], actions, error, 3430 &is_keycfg_configured); 3431 if (ret) { 3432 DPAA2_PMD_ERR("vLan flow configuration failed!"); 3433 return ret; 3434 } 3435 break; 3436 case RTE_FLOW_ITEM_TYPE_IPV4: 3437 case RTE_FLOW_ITEM_TYPE_IPV6: 3438 ret = dpaa2_configure_flow_generic_ip(flow, 3439 dev, attr, &pattern[i], actions, error, 3440 &is_keycfg_configured); 3441 if (ret) { 3442 DPAA2_PMD_ERR("IP flow configuration failed!"); 3443 return ret; 3444 } 3445 break; 3446 case RTE_FLOW_ITEM_TYPE_ICMP: 3447 ret = dpaa2_configure_flow_icmp(flow, 3448 dev, attr, &pattern[i], actions, error, 3449 &is_keycfg_configured); 3450 if (ret) { 3451 DPAA2_PMD_ERR("ICMP flow configuration failed!"); 3452 return ret; 3453 } 3454 break; 3455 case RTE_FLOW_ITEM_TYPE_UDP: 3456 ret = dpaa2_configure_flow_udp(flow, 3457 dev, attr, &pattern[i], actions, error, 3458 &is_keycfg_configured); 3459 if (ret) { 3460 DPAA2_PMD_ERR("UDP flow configuration failed!"); 3461 return ret; 3462 } 3463 break; 3464 case RTE_FLOW_ITEM_TYPE_TCP: 3465 ret = dpaa2_configure_flow_tcp(flow, 3466 dev, attr, &pattern[i], actions, error, 3467 &is_keycfg_configured); 3468 if (ret) { 3469 DPAA2_PMD_ERR("TCP flow configuration failed!"); 3470 return ret; 3471 } 3472 break; 3473 case RTE_FLOW_ITEM_TYPE_SCTP: 3474 ret = dpaa2_configure_flow_sctp(flow, 3475 dev, attr, &pattern[i], actions, error, 3476 &is_keycfg_configured); 3477 if (ret) { 3478 DPAA2_PMD_ERR("SCTP flow configuration failed!"); 3479 return ret; 3480 } 3481 break; 3482 case RTE_FLOW_ITEM_TYPE_GRE: 3483 ret = dpaa2_configure_flow_gre(flow, 3484 dev, attr, &pattern[i], actions, error, 3485 &is_keycfg_configured); 3486 if (ret) { 3487 DPAA2_PMD_ERR("GRE flow configuration failed!"); 3488 return ret; 3489 } 3490 break; 3491 case RTE_FLOW_ITEM_TYPE_RAW: 3492 ret = dpaa2_configure_flow_raw(flow, 3493 dev, attr, &pattern[i], 3494 actions, error, 3495 &is_keycfg_configured); 3496 if (ret) { 3497 DPAA2_PMD_ERR("RAW flow configuration failed!"); 3498 return ret; 3499 } 3500 break; 3501 case RTE_FLOW_ITEM_TYPE_END: 3502 end_of_list = 1; 3503 break; /*End of List*/ 3504 default: 3505 DPAA2_PMD_ERR("Invalid action type"); 3506 ret = -ENOTSUP; 3507 break; 3508 } 3509 i++; 3510 } 3511 3512 /* Let's parse action on matching traffic */ 3513 end_of_list = 0; 3514 while (!end_of_list) { 3515 switch (actions[j].type) { 3516 case RTE_FLOW_ACTION_TYPE_QUEUE: 3517 case RTE_FLOW_ACTION_TYPE_PHY_PORT: 3518 case RTE_FLOW_ACTION_TYPE_PORT_ID: 3519 memset(&action, 0, sizeof(struct dpni_fs_action_cfg)); 3520 flow->action = actions[j].type; 3521 3522 if (actions[j].type == RTE_FLOW_ACTION_TYPE_QUEUE) { 3523 dest_queue = (const struct rte_flow_action_queue *) 3524 (actions[j].conf); 3525 dest_q = priv->rx_vq[dest_queue->index]; 3526 action.flow_id = dest_q->flow_id; 3527 } else { 3528 dest_dev = dpaa2_flow_redirect_dev(priv, 3529 &actions[j]); 3530 if (!dest_dev) { 3531 DPAA2_PMD_ERR("Invalid destination device to redirect!"); 3532 return -1; 3533 } 3534 3535 dest_priv = dest_dev->data->dev_private; 3536 dest_q = dest_priv->tx_vq[0]; 3537 action.options = 3538 DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; 3539 action.redirect_obj_token = dest_priv->token; 3540 action.flow_id = dest_q->flow_id; 3541 } 3542 3543 /* Configure FS table first*/ 3544 if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) { 3545 dpaa2_flow_fs_table_extracts_log(priv, flow->tc_id); 3546 if (dpkg_prepare_key_cfg( 3547 &priv->extract.tc_key_extract[flow->tc_id].dpkg, 3548 (uint8_t *)(size_t)priv->extract 3549 .tc_extract_param[flow->tc_id]) < 0) { 3550 DPAA2_PMD_ERR( 3551 "Unable to prepare extract parameters"); 3552 return -1; 3553 } 3554 3555 memset(&tc_cfg, 0, 3556 sizeof(struct dpni_rx_dist_cfg)); 3557 tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc; 3558 tc_cfg.key_cfg_iova = 3559 (uint64_t)priv->extract.tc_extract_param[flow->tc_id]; 3560 tc_cfg.tc = flow->tc_id; 3561 tc_cfg.enable = false; 3562 ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, 3563 priv->token, &tc_cfg); 3564 if (ret < 0) { 3565 DPAA2_PMD_ERR( 3566 "TC hash cannot be disabled.(%d)", 3567 ret); 3568 return -1; 3569 } 3570 tc_cfg.enable = true; 3571 tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; 3572 ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, 3573 priv->token, &tc_cfg); 3574 if (ret < 0) { 3575 DPAA2_PMD_ERR( 3576 "TC distribution cannot be configured.(%d)", 3577 ret); 3578 return -1; 3579 } 3580 } 3581 3582 /* Configure QoS table then.*/ 3583 if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 3584 dpaa2_flow_qos_table_extracts_log(priv); 3585 if (dpkg_prepare_key_cfg( 3586 &priv->extract.qos_key_extract.dpkg, 3587 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) { 3588 DPAA2_PMD_ERR( 3589 "Unable to prepare extract parameters"); 3590 return -1; 3591 } 3592 3593 memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg)); 3594 qos_cfg.discard_on_miss = false; 3595 qos_cfg.default_tc = 0; 3596 qos_cfg.keep_entries = true; 3597 qos_cfg.key_cfg_iova = 3598 (size_t)priv->extract.qos_extract_param; 3599 /* QoS table is effecitive for multiple TCs.*/ 3600 if (priv->num_rx_tc > 1) { 3601 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, 3602 priv->token, &qos_cfg); 3603 if (ret < 0) { 3604 DPAA2_PMD_ERR( 3605 "RSS QoS table can not be configured(%d)\n", 3606 ret); 3607 return -1; 3608 } 3609 } 3610 } 3611 3612 flow->qos_real_key_size = priv->extract 3613 .qos_key_extract.key_info.key_total_size; 3614 if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) { 3615 if (flow->ipaddr_rule.qos_ipdst_offset >= 3616 flow->ipaddr_rule.qos_ipsrc_offset) { 3617 flow->qos_real_key_size = 3618 flow->ipaddr_rule.qos_ipdst_offset + 3619 NH_FLD_IPV4_ADDR_SIZE; 3620 } else { 3621 flow->qos_real_key_size = 3622 flow->ipaddr_rule.qos_ipsrc_offset + 3623 NH_FLD_IPV4_ADDR_SIZE; 3624 } 3625 } else if (flow->ipaddr_rule.ipaddr_type == 3626 FLOW_IPV6_ADDR) { 3627 if (flow->ipaddr_rule.qos_ipdst_offset >= 3628 flow->ipaddr_rule.qos_ipsrc_offset) { 3629 flow->qos_real_key_size = 3630 flow->ipaddr_rule.qos_ipdst_offset + 3631 NH_FLD_IPV6_ADDR_SIZE; 3632 } else { 3633 flow->qos_real_key_size = 3634 flow->ipaddr_rule.qos_ipsrc_offset + 3635 NH_FLD_IPV6_ADDR_SIZE; 3636 } 3637 } 3638 3639 /* QoS entry added is only effective for multiple TCs.*/ 3640 if (priv->num_rx_tc > 1) { 3641 qos_index = flow->tc_id * priv->fs_entries + 3642 flow->tc_index; 3643 if (qos_index >= priv->qos_entries) { 3644 DPAA2_PMD_ERR("QoS table with %d entries full", 3645 priv->qos_entries); 3646 return -1; 3647 } 3648 flow->qos_rule.key_size = FIXED_ENTRY_SIZE; 3649 3650 dpaa2_flow_qos_entry_log("Start add", flow, qos_index); 3651 3652 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, 3653 priv->token, &flow->qos_rule, 3654 flow->tc_id, qos_index, 3655 0, 0); 3656 if (ret < 0) { 3657 DPAA2_PMD_ERR( 3658 "Error in addnig entry to QoS table(%d)", ret); 3659 return ret; 3660 } 3661 } 3662 3663 if (flow->tc_index >= priv->fs_entries) { 3664 DPAA2_PMD_ERR("FS table with %d entries full", 3665 priv->fs_entries); 3666 return -1; 3667 } 3668 3669 flow->fs_real_key_size = 3670 priv->extract.tc_key_extract[flow->tc_id] 3671 .key_info.key_total_size; 3672 3673 if (flow->ipaddr_rule.ipaddr_type == 3674 FLOW_IPV4_ADDR) { 3675 if (flow->ipaddr_rule.fs_ipdst_offset >= 3676 flow->ipaddr_rule.fs_ipsrc_offset) { 3677 flow->fs_real_key_size = 3678 flow->ipaddr_rule.fs_ipdst_offset + 3679 NH_FLD_IPV4_ADDR_SIZE; 3680 } else { 3681 flow->fs_real_key_size = 3682 flow->ipaddr_rule.fs_ipsrc_offset + 3683 NH_FLD_IPV4_ADDR_SIZE; 3684 } 3685 } else if (flow->ipaddr_rule.ipaddr_type == 3686 FLOW_IPV6_ADDR) { 3687 if (flow->ipaddr_rule.fs_ipdst_offset >= 3688 flow->ipaddr_rule.fs_ipsrc_offset) { 3689 flow->fs_real_key_size = 3690 flow->ipaddr_rule.fs_ipdst_offset + 3691 NH_FLD_IPV6_ADDR_SIZE; 3692 } else { 3693 flow->fs_real_key_size = 3694 flow->ipaddr_rule.fs_ipsrc_offset + 3695 NH_FLD_IPV6_ADDR_SIZE; 3696 } 3697 } 3698 3699 flow->fs_rule.key_size = FIXED_ENTRY_SIZE; 3700 3701 dpaa2_flow_fs_entry_log("Start add", flow); 3702 3703 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token, 3704 flow->tc_id, flow->tc_index, 3705 &flow->fs_rule, &action); 3706 if (ret < 0) { 3707 DPAA2_PMD_ERR( 3708 "Error in adding entry to FS table(%d)", ret); 3709 return ret; 3710 } 3711 memcpy(&flow->action_cfg, &action, 3712 sizeof(struct dpni_fs_action_cfg)); 3713 break; 3714 case RTE_FLOW_ACTION_TYPE_RSS: 3715 rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf); 3716 3717 flow->action = RTE_FLOW_ACTION_TYPE_RSS; 3718 ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types, 3719 &priv->extract.tc_key_extract[flow->tc_id].dpkg); 3720 if (ret < 0) { 3721 DPAA2_PMD_ERR( 3722 "unable to set flow distribution.please check queue config\n"); 3723 return ret; 3724 } 3725 3726 /* Allocate DMA'ble memory to write the rules */ 3727 param = (size_t)rte_malloc(NULL, 256, 64); 3728 if (!param) { 3729 DPAA2_PMD_ERR("Memory allocation failure\n"); 3730 return -1; 3731 } 3732 3733 if (dpkg_prepare_key_cfg( 3734 &priv->extract.tc_key_extract[flow->tc_id].dpkg, 3735 (uint8_t *)param) < 0) { 3736 DPAA2_PMD_ERR( 3737 "Unable to prepare extract parameters"); 3738 rte_free((void *)param); 3739 return -1; 3740 } 3741 3742 memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); 3743 tc_cfg.dist_size = rss_conf->queue_num; 3744 tc_cfg.key_cfg_iova = (size_t)param; 3745 tc_cfg.enable = true; 3746 tc_cfg.tc = flow->tc_id; 3747 ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, 3748 priv->token, &tc_cfg); 3749 if (ret < 0) { 3750 DPAA2_PMD_ERR( 3751 "RSS TC table cannot be configured: %d\n", 3752 ret); 3753 rte_free((void *)param); 3754 return -1; 3755 } 3756 3757 rte_free((void *)param); 3758 if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 3759 if (dpkg_prepare_key_cfg( 3760 &priv->extract.qos_key_extract.dpkg, 3761 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) { 3762 DPAA2_PMD_ERR( 3763 "Unable to prepare extract parameters"); 3764 return -1; 3765 } 3766 memset(&qos_cfg, 0, 3767 sizeof(struct dpni_qos_tbl_cfg)); 3768 qos_cfg.discard_on_miss = true; 3769 qos_cfg.keep_entries = true; 3770 qos_cfg.key_cfg_iova = 3771 (size_t)priv->extract.qos_extract_param; 3772 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, 3773 priv->token, &qos_cfg); 3774 if (ret < 0) { 3775 DPAA2_PMD_ERR( 3776 "RSS QoS dist can't be configured-%d\n", 3777 ret); 3778 return -1; 3779 } 3780 } 3781 3782 /* Add Rule into QoS table */ 3783 qos_index = flow->tc_id * priv->fs_entries + 3784 flow->tc_index; 3785 if (qos_index >= priv->qos_entries) { 3786 DPAA2_PMD_ERR("QoS table with %d entries full", 3787 priv->qos_entries); 3788 return -1; 3789 } 3790 3791 flow->qos_real_key_size = 3792 priv->extract.qos_key_extract.key_info.key_total_size; 3793 flow->qos_rule.key_size = FIXED_ENTRY_SIZE; 3794 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token, 3795 &flow->qos_rule, flow->tc_id, 3796 qos_index, 0, 0); 3797 if (ret < 0) { 3798 DPAA2_PMD_ERR( 3799 "Error in entry addition in QoS table(%d)", 3800 ret); 3801 return ret; 3802 } 3803 break; 3804 case RTE_FLOW_ACTION_TYPE_END: 3805 end_of_list = 1; 3806 break; 3807 default: 3808 DPAA2_PMD_ERR("Invalid action type"); 3809 ret = -ENOTSUP; 3810 break; 3811 } 3812 j++; 3813 } 3814 3815 if (!ret) { 3816 if (is_keycfg_configured & 3817 (DPAA2_QOS_TABLE_RECONFIGURE | 3818 DPAA2_FS_TABLE_RECONFIGURE)) { 3819 ret = dpaa2_flow_entry_update(priv, flow->tc_id); 3820 if (ret) { 3821 DPAA2_PMD_ERR("Flow entry update failed."); 3822 3823 return -1; 3824 } 3825 } 3826 /* New rules are inserted. */ 3827 if (!curr) { 3828 LIST_INSERT_HEAD(&priv->flows, flow, next); 3829 } else { 3830 while (LIST_NEXT(curr, next)) 3831 curr = LIST_NEXT(curr, next); 3832 LIST_INSERT_AFTER(curr, flow, next); 3833 } 3834 } 3835 return ret; 3836 } 3837 3838 static inline int 3839 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, 3840 const struct rte_flow_attr *attr) 3841 { 3842 int ret = 0; 3843 3844 if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) { 3845 DPAA2_PMD_ERR("Priority group is out of range\n"); 3846 ret = -ENOTSUP; 3847 } 3848 if (unlikely(attr->priority >= dpni_attr->fs_entries)) { 3849 DPAA2_PMD_ERR("Priority within the group is out of range\n"); 3850 ret = -ENOTSUP; 3851 } 3852 if (unlikely(attr->egress)) { 3853 DPAA2_PMD_ERR( 3854 "Flow configuration is not supported on egress side\n"); 3855 ret = -ENOTSUP; 3856 } 3857 if (unlikely(!attr->ingress)) { 3858 DPAA2_PMD_ERR("Ingress flag must be configured\n"); 3859 ret = -EINVAL; 3860 } 3861 return ret; 3862 } 3863 3864 static inline int 3865 dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) 3866 { 3867 unsigned int i, j, is_found = 0; 3868 int ret = 0; 3869 3870 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { 3871 for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) { 3872 if (dpaa2_supported_pattern_type[i] 3873 == pattern[j].type) { 3874 is_found = 1; 3875 break; 3876 } 3877 } 3878 if (!is_found) { 3879 ret = -ENOTSUP; 3880 break; 3881 } 3882 } 3883 /* Lets verify other combinations of given pattern rules */ 3884 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { 3885 if (!pattern[j].spec) { 3886 ret = -EINVAL; 3887 break; 3888 } 3889 } 3890 3891 return ret; 3892 } 3893 3894 static inline int 3895 dpaa2_dev_verify_actions(const struct rte_flow_action actions[]) 3896 { 3897 unsigned int i, j, is_found = 0; 3898 int ret = 0; 3899 3900 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { 3901 for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) { 3902 if (dpaa2_supported_action_type[i] == actions[j].type) { 3903 is_found = 1; 3904 break; 3905 } 3906 } 3907 if (!is_found) { 3908 ret = -ENOTSUP; 3909 break; 3910 } 3911 } 3912 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { 3913 if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP && 3914 !actions[j].conf) 3915 ret = -EINVAL; 3916 } 3917 return ret; 3918 } 3919 3920 static 3921 int dpaa2_flow_validate(struct rte_eth_dev *dev, 3922 const struct rte_flow_attr *flow_attr, 3923 const struct rte_flow_item pattern[], 3924 const struct rte_flow_action actions[], 3925 struct rte_flow_error *error) 3926 { 3927 struct dpaa2_dev_priv *priv = dev->data->dev_private; 3928 struct dpni_attr dpni_attr; 3929 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 3930 uint16_t token = priv->token; 3931 int ret = 0; 3932 3933 memset(&dpni_attr, 0, sizeof(struct dpni_attr)); 3934 ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr); 3935 if (ret < 0) { 3936 DPAA2_PMD_ERR( 3937 "Failure to get dpni@%p attribute, err code %d\n", 3938 dpni, ret); 3939 rte_flow_error_set(error, EPERM, 3940 RTE_FLOW_ERROR_TYPE_ATTR, 3941 flow_attr, "invalid"); 3942 return ret; 3943 } 3944 3945 /* Verify input attributes */ 3946 ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr); 3947 if (ret < 0) { 3948 DPAA2_PMD_ERR( 3949 "Invalid attributes are given\n"); 3950 rte_flow_error_set(error, EPERM, 3951 RTE_FLOW_ERROR_TYPE_ATTR, 3952 flow_attr, "invalid"); 3953 goto not_valid_params; 3954 } 3955 /* Verify input pattern list */ 3956 ret = dpaa2_dev_verify_patterns(pattern); 3957 if (ret < 0) { 3958 DPAA2_PMD_ERR( 3959 "Invalid pattern list is given\n"); 3960 rte_flow_error_set(error, EPERM, 3961 RTE_FLOW_ERROR_TYPE_ITEM, 3962 pattern, "invalid"); 3963 goto not_valid_params; 3964 } 3965 /* Verify input action list */ 3966 ret = dpaa2_dev_verify_actions(actions); 3967 if (ret < 0) { 3968 DPAA2_PMD_ERR( 3969 "Invalid action list is given\n"); 3970 rte_flow_error_set(error, EPERM, 3971 RTE_FLOW_ERROR_TYPE_ACTION, 3972 actions, "invalid"); 3973 goto not_valid_params; 3974 } 3975 not_valid_params: 3976 return ret; 3977 } 3978 3979 static 3980 struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev, 3981 const struct rte_flow_attr *attr, 3982 const struct rte_flow_item pattern[], 3983 const struct rte_flow_action actions[], 3984 struct rte_flow_error *error) 3985 { 3986 struct rte_flow *flow = NULL; 3987 size_t key_iova = 0, mask_iova = 0; 3988 int ret; 3989 3990 dpaa2_flow_control_log = 3991 getenv("DPAA2_FLOW_CONTROL_LOG"); 3992 3993 if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { 3994 struct dpaa2_dev_priv *priv = dev->data->dev_private; 3995 3996 dpaa2_flow_miss_flow_id = 3997 atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); 3998 if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { 3999 DPAA2_PMD_ERR( 4000 "The missed flow ID %d exceeds the max flow ID %d", 4001 dpaa2_flow_miss_flow_id, 4002 priv->dist_queues - 1); 4003 return NULL; 4004 } 4005 } 4006 4007 flow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE); 4008 if (!flow) { 4009 DPAA2_PMD_ERR("Failure to allocate memory for flow"); 4010 goto mem_failure; 4011 } 4012 /* Allocate DMA'ble memory to write the rules */ 4013 key_iova = (size_t)rte_zmalloc(NULL, 256, 64); 4014 if (!key_iova) { 4015 DPAA2_PMD_ERR( 4016 "Memory allocation failure for rule configuration\n"); 4017 goto mem_failure; 4018 } 4019 mask_iova = (size_t)rte_zmalloc(NULL, 256, 64); 4020 if (!mask_iova) { 4021 DPAA2_PMD_ERR( 4022 "Memory allocation failure for rule configuration\n"); 4023 goto mem_failure; 4024 } 4025 4026 flow->qos_rule.key_iova = key_iova; 4027 flow->qos_rule.mask_iova = mask_iova; 4028 4029 /* Allocate DMA'ble memory to write the rules */ 4030 key_iova = (size_t)rte_zmalloc(NULL, 256, 64); 4031 if (!key_iova) { 4032 DPAA2_PMD_ERR( 4033 "Memory allocation failure for rule configuration\n"); 4034 goto mem_failure; 4035 } 4036 mask_iova = (size_t)rte_zmalloc(NULL, 256, 64); 4037 if (!mask_iova) { 4038 DPAA2_PMD_ERR( 4039 "Memory allocation failure for rule configuration\n"); 4040 goto mem_failure; 4041 } 4042 4043 flow->fs_rule.key_iova = key_iova; 4044 flow->fs_rule.mask_iova = mask_iova; 4045 4046 flow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR; 4047 flow->ipaddr_rule.qos_ipsrc_offset = 4048 IP_ADDRESS_OFFSET_INVALID; 4049 flow->ipaddr_rule.qos_ipdst_offset = 4050 IP_ADDRESS_OFFSET_INVALID; 4051 flow->ipaddr_rule.fs_ipsrc_offset = 4052 IP_ADDRESS_OFFSET_INVALID; 4053 flow->ipaddr_rule.fs_ipdst_offset = 4054 IP_ADDRESS_OFFSET_INVALID; 4055 4056 ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, 4057 actions, error); 4058 if (ret < 0) { 4059 if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) 4060 rte_flow_error_set(error, EPERM, 4061 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4062 attr, "unknown"); 4063 DPAA2_PMD_ERR("Failure to create flow, return code (%d)", ret); 4064 goto creation_error; 4065 } 4066 4067 return flow; 4068 mem_failure: 4069 rte_flow_error_set(error, EPERM, 4070 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4071 NULL, "memory alloc"); 4072 creation_error: 4073 rte_free((void *)flow); 4074 rte_free((void *)key_iova); 4075 rte_free((void *)mask_iova); 4076 4077 return NULL; 4078 } 4079 4080 static 4081 int dpaa2_flow_destroy(struct rte_eth_dev *dev, 4082 struct rte_flow *flow, 4083 struct rte_flow_error *error) 4084 { 4085 int ret = 0; 4086 struct dpaa2_dev_priv *priv = dev->data->dev_private; 4087 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 4088 4089 switch (flow->action) { 4090 case RTE_FLOW_ACTION_TYPE_QUEUE: 4091 case RTE_FLOW_ACTION_TYPE_PHY_PORT: 4092 case RTE_FLOW_ACTION_TYPE_PORT_ID: 4093 if (priv->num_rx_tc > 1) { 4094 /* Remove entry from QoS table first */ 4095 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token, 4096 &flow->qos_rule); 4097 if (ret < 0) { 4098 DPAA2_PMD_ERR( 4099 "Error in removing entry from QoS table(%d)", ret); 4100 goto error; 4101 } 4102 } 4103 4104 /* Then remove entry from FS table */ 4105 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, 4106 flow->tc_id, &flow->fs_rule); 4107 if (ret < 0) { 4108 DPAA2_PMD_ERR( 4109 "Error in removing entry from FS table(%d)", ret); 4110 goto error; 4111 } 4112 break; 4113 case RTE_FLOW_ACTION_TYPE_RSS: 4114 if (priv->num_rx_tc > 1) { 4115 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token, 4116 &flow->qos_rule); 4117 if (ret < 0) { 4118 DPAA2_PMD_ERR( 4119 "Error in entry addition in QoS table(%d)", ret); 4120 goto error; 4121 } 4122 } 4123 break; 4124 default: 4125 DPAA2_PMD_ERR( 4126 "Action type (%d) is not supported", flow->action); 4127 ret = -ENOTSUP; 4128 break; 4129 } 4130 4131 LIST_REMOVE(flow, next); 4132 rte_free((void *)(size_t)flow->qos_rule.key_iova); 4133 rte_free((void *)(size_t)flow->qos_rule.mask_iova); 4134 rte_free((void *)(size_t)flow->fs_rule.key_iova); 4135 rte_free((void *)(size_t)flow->fs_rule.mask_iova); 4136 /* Now free the flow */ 4137 rte_free(flow); 4138 4139 error: 4140 if (ret) 4141 rte_flow_error_set(error, EPERM, 4142 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4143 NULL, "unknown"); 4144 return ret; 4145 } 4146 4147 /** 4148 * Destroy user-configured flow rules. 4149 * 4150 * This function skips internal flows rules. 4151 * 4152 * @see rte_flow_flush() 4153 * @see rte_flow_ops 4154 */ 4155 static int 4156 dpaa2_flow_flush(struct rte_eth_dev *dev, 4157 struct rte_flow_error *error) 4158 { 4159 struct dpaa2_dev_priv *priv = dev->data->dev_private; 4160 struct rte_flow *flow = LIST_FIRST(&priv->flows); 4161 4162 while (flow) { 4163 struct rte_flow *next = LIST_NEXT(flow, next); 4164 4165 dpaa2_flow_destroy(dev, flow, error); 4166 flow = next; 4167 } 4168 return 0; 4169 } 4170 4171 static int 4172 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, 4173 struct rte_flow *flow __rte_unused, 4174 const struct rte_flow_action *actions __rte_unused, 4175 void *data __rte_unused, 4176 struct rte_flow_error *error __rte_unused) 4177 { 4178 return 0; 4179 } 4180 4181 /** 4182 * Clean up all flow rules. 4183 * 4184 * Unlike dpaa2_flow_flush(), this function takes care of all remaining flow 4185 * rules regardless of whether they are internal or user-configured. 4186 * 4187 * @param priv 4188 * Pointer to private structure. 4189 */ 4190 void 4191 dpaa2_flow_clean(struct rte_eth_dev *dev) 4192 { 4193 struct rte_flow *flow; 4194 struct dpaa2_dev_priv *priv = dev->data->dev_private; 4195 4196 while ((flow = LIST_FIRST(&priv->flows))) 4197 dpaa2_flow_destroy(dev, flow, NULL); 4198 } 4199 4200 const struct rte_flow_ops dpaa2_flow_ops = { 4201 .create = dpaa2_flow_create, 4202 .validate = dpaa2_flow_validate, 4203 .destroy = dpaa2_flow_destroy, 4204 .flush = dpaa2_flow_flush, 4205 .query = dpaa2_flow_query, 4206 }; 4207