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