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