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