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