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