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