1 /* * SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018 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 struct rte_flow { 26 LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ 27 struct dpni_rule_cfg rule; 28 uint8_t key_size; 29 uint8_t tc_id; 30 uint8_t flow_type; 31 uint8_t index; 32 enum rte_flow_action_type action; 33 uint16_t flow_id; 34 }; 35 36 /* Layout for rule compositions for supported patterns */ 37 /* TODO: Current design only supports Ethernet + IPv4 based classification. */ 38 /* So corresponding offset macros are valid only. Rest are placeholder for */ 39 /* now. Once support for other netwrok headers will be added then */ 40 /* corresponding macros will be updated with correct values*/ 41 #define DPAA2_CLS_RULE_OFFSET_ETH 0 /*Start of buffer*/ 42 #define DPAA2_CLS_RULE_OFFSET_VLAN 14 /* DPAA2_CLS_RULE_OFFSET_ETH */ 43 /* + Sizeof Eth fields */ 44 #define DPAA2_CLS_RULE_OFFSET_IPV4 14 /* DPAA2_CLS_RULE_OFFSET_VLAN */ 45 /* + Sizeof VLAN fields */ 46 #define DPAA2_CLS_RULE_OFFSET_IPV6 25 /* DPAA2_CLS_RULE_OFFSET_IPV4 */ 47 /* + Sizeof IPV4 fields */ 48 #define DPAA2_CLS_RULE_OFFSET_ICMP 58 /* DPAA2_CLS_RULE_OFFSET_IPV6 */ 49 /* + Sizeof IPV6 fields */ 50 #define DPAA2_CLS_RULE_OFFSET_UDP 60 /* DPAA2_CLS_RULE_OFFSET_ICMP */ 51 /* + Sizeof ICMP fields */ 52 #define DPAA2_CLS_RULE_OFFSET_TCP 64 /* DPAA2_CLS_RULE_OFFSET_UDP */ 53 /* + Sizeof UDP fields */ 54 #define DPAA2_CLS_RULE_OFFSET_SCTP 68 /* DPAA2_CLS_RULE_OFFSET_TCP */ 55 /* + Sizeof TCP fields */ 56 #define DPAA2_CLS_RULE_OFFSET_GRE 72 /* DPAA2_CLS_RULE_OFFSET_SCTP */ 57 /* + Sizeof SCTP fields */ 58 59 static const 60 enum rte_flow_item_type dpaa2_supported_pattern_type[] = { 61 RTE_FLOW_ITEM_TYPE_END, 62 RTE_FLOW_ITEM_TYPE_ETH, 63 RTE_FLOW_ITEM_TYPE_VLAN, 64 RTE_FLOW_ITEM_TYPE_IPV4, 65 RTE_FLOW_ITEM_TYPE_IPV6, 66 RTE_FLOW_ITEM_TYPE_ICMP, 67 RTE_FLOW_ITEM_TYPE_UDP, 68 RTE_FLOW_ITEM_TYPE_TCP, 69 RTE_FLOW_ITEM_TYPE_SCTP, 70 RTE_FLOW_ITEM_TYPE_GRE, 71 }; 72 73 static const 74 enum rte_flow_action_type dpaa2_supported_action_type[] = { 75 RTE_FLOW_ACTION_TYPE_END, 76 RTE_FLOW_ACTION_TYPE_QUEUE, 77 RTE_FLOW_ACTION_TYPE_RSS 78 }; 79 80 enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE; 81 static const void *default_mask; 82 83 static int 84 dpaa2_configure_flow_eth(struct rte_flow *flow, 85 struct rte_eth_dev *dev, 86 const struct rte_flow_attr *attr, 87 const struct rte_flow_item *pattern, 88 const struct rte_flow_action actions[] __rte_unused, 89 struct rte_flow_error *error __rte_unused) 90 { 91 int index, j = 0; 92 size_t key_iova; 93 size_t mask_iova; 94 int device_configured = 0, entry_found = 0; 95 uint32_t group; 96 const struct rte_flow_item_eth *spec, *mask; 97 98 /* TODO: Currently upper bound of range parameter is not implemented */ 99 const struct rte_flow_item_eth *last __rte_unused; 100 struct dpaa2_dev_priv *priv = dev->data->dev_private; 101 102 group = attr->group; 103 104 /* DPAA2 platform has a limitation that extract parameter can not be */ 105 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 106 /* TODO: pattern is an array of 9 elements where 9th pattern element */ 107 /* is for QoS table and 1-8th pattern element is for FS tables. */ 108 /* It can be changed to macro. */ 109 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 110 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 111 DPKG_MAX_NUM_OF_EXTRACTS); 112 return -ENOTSUP; 113 } 114 115 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 116 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 117 DPKG_MAX_NUM_OF_EXTRACTS); 118 return -ENOTSUP; 119 } 120 121 for (j = 0; j < priv->pattern[8].item_count; j++) { 122 if (priv->pattern[8].pattern_type[j] != pattern->type) { 123 continue; 124 } else { 125 entry_found = 1; 126 break; 127 } 128 } 129 130 if (!entry_found) { 131 priv->pattern[8].pattern_type[j] = pattern->type; 132 priv->pattern[8].item_count++; 133 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 134 } 135 136 entry_found = 0; 137 for (j = 0; j < priv->pattern[group].item_count; j++) { 138 if (priv->pattern[group].pattern_type[j] != pattern->type) { 139 continue; 140 } else { 141 entry_found = 1; 142 break; 143 } 144 } 145 146 if (!entry_found) { 147 priv->pattern[group].pattern_type[j] = pattern->type; 148 priv->pattern[group].item_count++; 149 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 150 } 151 152 /* Get traffic class index and flow id to be configured */ 153 flow->tc_id = group; 154 flow->index = attr->priority; 155 156 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 157 index = priv->extract.qos_key_cfg.num_extracts; 158 priv->extract.qos_key_cfg.extracts[index].type = 159 DPKG_EXTRACT_FROM_HDR; 160 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 161 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 162 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA; 163 index++; 164 165 priv->extract.qos_key_cfg.extracts[index].type = 166 DPKG_EXTRACT_FROM_HDR; 167 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 168 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 169 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA; 170 index++; 171 172 priv->extract.qos_key_cfg.extracts[index].type = 173 DPKG_EXTRACT_FROM_HDR; 174 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 175 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 176 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE; 177 index++; 178 179 priv->extract.qos_key_cfg.num_extracts = index; 180 } 181 182 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 183 index = priv->extract.fs_key_cfg[group].num_extracts; 184 priv->extract.fs_key_cfg[group].extracts[index].type = 185 DPKG_EXTRACT_FROM_HDR; 186 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 187 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 188 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA; 189 index++; 190 191 priv->extract.fs_key_cfg[group].extracts[index].type = 192 DPKG_EXTRACT_FROM_HDR; 193 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 194 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 195 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA; 196 index++; 197 198 priv->extract.fs_key_cfg[group].extracts[index].type = 199 DPKG_EXTRACT_FROM_HDR; 200 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 201 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH; 202 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE; 203 index++; 204 205 priv->extract.fs_key_cfg[group].num_extracts = index; 206 } 207 208 /* Parse pattern list to get the matching parameters */ 209 spec = (const struct rte_flow_item_eth *)pattern->spec; 210 last = (const struct rte_flow_item_eth *)pattern->last; 211 mask = (const struct rte_flow_item_eth *) 212 (pattern->mask ? pattern->mask : default_mask); 213 214 /* Key rule */ 215 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_ETH; 216 memcpy((void *)key_iova, (const void *)(spec->src.addr_bytes), 217 sizeof(struct rte_ether_addr)); 218 key_iova += sizeof(struct rte_ether_addr); 219 memcpy((void *)key_iova, (const void *)(spec->dst.addr_bytes), 220 sizeof(struct rte_ether_addr)); 221 key_iova += sizeof(struct rte_ether_addr); 222 memcpy((void *)key_iova, (const void *)(&spec->type), 223 sizeof(rte_be16_t)); 224 225 /* Key mask */ 226 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_ETH; 227 memcpy((void *)mask_iova, (const void *)(mask->src.addr_bytes), 228 sizeof(struct rte_ether_addr)); 229 mask_iova += sizeof(struct rte_ether_addr); 230 memcpy((void *)mask_iova, (const void *)(mask->dst.addr_bytes), 231 sizeof(struct rte_ether_addr)); 232 mask_iova += sizeof(struct rte_ether_addr); 233 memcpy((void *)mask_iova, (const void *)(&mask->type), 234 sizeof(rte_be16_t)); 235 236 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_ETH + 237 ((2 * sizeof(struct rte_ether_addr)) + 238 sizeof(rte_be16_t))); 239 return device_configured; 240 } 241 242 static int 243 dpaa2_configure_flow_vlan(struct rte_flow *flow, 244 struct rte_eth_dev *dev, 245 const struct rte_flow_attr *attr, 246 const struct rte_flow_item *pattern, 247 const struct rte_flow_action actions[] __rte_unused, 248 struct rte_flow_error *error __rte_unused) 249 { 250 int index, j = 0; 251 size_t key_iova; 252 size_t mask_iova; 253 int device_configured = 0, entry_found = 0; 254 uint32_t group; 255 const struct rte_flow_item_vlan *spec, *mask; 256 257 const struct rte_flow_item_vlan *last __rte_unused; 258 struct dpaa2_dev_priv *priv = dev->data->dev_private; 259 260 group = attr->group; 261 262 /* DPAA2 platform has a limitation that extract parameter can not be */ 263 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 264 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 265 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 266 DPKG_MAX_NUM_OF_EXTRACTS); 267 return -ENOTSUP; 268 } 269 270 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 271 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 272 DPKG_MAX_NUM_OF_EXTRACTS); 273 return -ENOTSUP; 274 } 275 276 for (j = 0; j < priv->pattern[8].item_count; j++) { 277 if (priv->pattern[8].pattern_type[j] != pattern->type) { 278 continue; 279 } else { 280 entry_found = 1; 281 break; 282 } 283 } 284 285 if (!entry_found) { 286 priv->pattern[8].pattern_type[j] = pattern->type; 287 priv->pattern[8].item_count++; 288 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 289 } 290 291 entry_found = 0; 292 for (j = 0; j < priv->pattern[group].item_count; j++) { 293 if (priv->pattern[group].pattern_type[j] != pattern->type) { 294 continue; 295 } else { 296 entry_found = 1; 297 break; 298 } 299 } 300 301 if (!entry_found) { 302 priv->pattern[group].pattern_type[j] = pattern->type; 303 priv->pattern[group].item_count++; 304 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 305 } 306 307 308 /* Get traffic class index and flow id to be configured */ 309 flow->tc_id = group; 310 flow->index = attr->priority; 311 312 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 313 index = priv->extract.qos_key_cfg.num_extracts; 314 priv->extract.qos_key_cfg.extracts[index].type = 315 DPKG_EXTRACT_FROM_HDR; 316 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 317 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_VLAN; 318 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI; 319 priv->extract.qos_key_cfg.num_extracts++; 320 } 321 322 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 323 index = priv->extract.fs_key_cfg[group].num_extracts; 324 priv->extract.fs_key_cfg[group].extracts[index].type = 325 DPKG_EXTRACT_FROM_HDR; 326 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 327 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_VLAN; 328 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI; 329 priv->extract.fs_key_cfg[group].num_extracts++; 330 } 331 332 /* Parse pattern list to get the matching parameters */ 333 spec = (const struct rte_flow_item_vlan *)pattern->spec; 334 last = (const struct rte_flow_item_vlan *)pattern->last; 335 mask = (const struct rte_flow_item_vlan *) 336 (pattern->mask ? pattern->mask : default_mask); 337 338 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_VLAN; 339 memcpy((void *)key_iova, (const void *)(&spec->tci), 340 sizeof(rte_be16_t)); 341 342 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_VLAN; 343 memcpy((void *)mask_iova, (const void *)(&mask->tci), 344 sizeof(rte_be16_t)); 345 346 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_VLAN + sizeof(rte_be16_t)); 347 return device_configured; 348 } 349 350 static int 351 dpaa2_configure_flow_ipv4(struct rte_flow *flow, 352 struct rte_eth_dev *dev, 353 const struct rte_flow_attr *attr, 354 const struct rte_flow_item *pattern, 355 const struct rte_flow_action actions[] __rte_unused, 356 struct rte_flow_error *error __rte_unused) 357 { 358 int index, j = 0; 359 size_t key_iova; 360 size_t mask_iova; 361 int device_configured = 0, entry_found = 0; 362 uint32_t group; 363 const struct rte_flow_item_ipv4 *spec, *mask; 364 365 const struct rte_flow_item_ipv4 *last __rte_unused; 366 struct dpaa2_dev_priv *priv = dev->data->dev_private; 367 368 group = attr->group; 369 370 /* DPAA2 platform has a limitation that extract parameter can not be */ 371 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 372 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 373 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 374 DPKG_MAX_NUM_OF_EXTRACTS); 375 return -ENOTSUP; 376 } 377 378 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 379 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 380 DPKG_MAX_NUM_OF_EXTRACTS); 381 return -ENOTSUP; 382 } 383 384 for (j = 0; j < priv->pattern[8].item_count; j++) { 385 if (priv->pattern[8].pattern_type[j] != pattern->type) { 386 continue; 387 } else { 388 entry_found = 1; 389 break; 390 } 391 } 392 393 if (!entry_found) { 394 priv->pattern[8].pattern_type[j] = pattern->type; 395 priv->pattern[8].item_count++; 396 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 397 } 398 399 entry_found = 0; 400 for (j = 0; j < priv->pattern[group].item_count; j++) { 401 if (priv->pattern[group].pattern_type[j] != pattern->type) { 402 continue; 403 } else { 404 entry_found = 1; 405 break; 406 } 407 } 408 409 if (!entry_found) { 410 priv->pattern[group].pattern_type[j] = pattern->type; 411 priv->pattern[group].item_count++; 412 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 413 } 414 415 /* Get traffic class index and flow id to be configured */ 416 flow->tc_id = group; 417 flow->index = attr->priority; 418 419 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 420 index = priv->extract.qos_key_cfg.num_extracts; 421 priv->extract.qos_key_cfg.extracts[index].type = 422 DPKG_EXTRACT_FROM_HDR; 423 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 424 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 425 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC; 426 index++; 427 428 priv->extract.qos_key_cfg.extracts[index].type = 429 DPKG_EXTRACT_FROM_HDR; 430 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 431 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 432 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST; 433 index++; 434 435 priv->extract.qos_key_cfg.extracts[index].type = 436 DPKG_EXTRACT_FROM_HDR; 437 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 438 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 439 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 440 index++; 441 442 priv->extract.qos_key_cfg.num_extracts = index; 443 } 444 445 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 446 index = priv->extract.fs_key_cfg[group].num_extracts; 447 priv->extract.fs_key_cfg[group].extracts[index].type = 448 DPKG_EXTRACT_FROM_HDR; 449 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 450 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 451 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC; 452 index++; 453 454 priv->extract.fs_key_cfg[group].extracts[index].type = 455 DPKG_EXTRACT_FROM_HDR; 456 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 457 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 458 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST; 459 index++; 460 461 priv->extract.fs_key_cfg[group].extracts[index].type = 462 DPKG_EXTRACT_FROM_HDR; 463 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 464 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 465 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 466 index++; 467 468 priv->extract.fs_key_cfg[group].num_extracts = index; 469 } 470 471 /* Parse pattern list to get the matching parameters */ 472 spec = (const struct rte_flow_item_ipv4 *)pattern->spec; 473 last = (const struct rte_flow_item_ipv4 *)pattern->last; 474 mask = (const struct rte_flow_item_ipv4 *) 475 (pattern->mask ? pattern->mask : default_mask); 476 477 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4; 478 memcpy((void *)key_iova, (const void *)&spec->hdr.src_addr, 479 sizeof(uint32_t)); 480 key_iova += sizeof(uint32_t); 481 memcpy((void *)key_iova, (const void *)&spec->hdr.dst_addr, 482 sizeof(uint32_t)); 483 key_iova += sizeof(uint32_t); 484 memcpy((void *)key_iova, (const void *)&spec->hdr.next_proto_id, 485 sizeof(uint8_t)); 486 487 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_IPV4; 488 memcpy((void *)mask_iova, (const void *)&mask->hdr.src_addr, 489 sizeof(uint32_t)); 490 mask_iova += sizeof(uint32_t); 491 memcpy((void *)mask_iova, (const void *)&mask->hdr.dst_addr, 492 sizeof(uint32_t)); 493 mask_iova += sizeof(uint32_t); 494 memcpy((void *)mask_iova, (const void *)&mask->hdr.next_proto_id, 495 sizeof(uint8_t)); 496 497 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_IPV4 + 498 (2 * sizeof(uint32_t)) + sizeof(uint8_t)); 499 500 return device_configured; 501 } 502 503 static int 504 dpaa2_configure_flow_ipv6(struct rte_flow *flow, 505 struct rte_eth_dev *dev, 506 const struct rte_flow_attr *attr, 507 const struct rte_flow_item *pattern, 508 const struct rte_flow_action actions[] __rte_unused, 509 struct rte_flow_error *error __rte_unused) 510 { 511 int index, j = 0; 512 size_t key_iova; 513 size_t mask_iova; 514 int device_configured = 0, entry_found = 0; 515 uint32_t group; 516 const struct rte_flow_item_ipv6 *spec, *mask; 517 518 const struct rte_flow_item_ipv6 *last __rte_unused; 519 struct dpaa2_dev_priv *priv = dev->data->dev_private; 520 521 group = attr->group; 522 523 /* DPAA2 platform has a limitation that extract parameter can not be */ 524 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 525 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 526 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 527 DPKG_MAX_NUM_OF_EXTRACTS); 528 return -ENOTSUP; 529 } 530 531 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 532 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 533 DPKG_MAX_NUM_OF_EXTRACTS); 534 return -ENOTSUP; 535 } 536 537 for (j = 0; j < priv->pattern[8].item_count; j++) { 538 if (priv->pattern[8].pattern_type[j] != pattern->type) { 539 continue; 540 } else { 541 entry_found = 1; 542 break; 543 } 544 } 545 546 if (!entry_found) { 547 priv->pattern[8].pattern_type[j] = pattern->type; 548 priv->pattern[8].item_count++; 549 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 550 } 551 552 entry_found = 0; 553 for (j = 0; j < priv->pattern[group].item_count; j++) { 554 if (priv->pattern[group].pattern_type[j] != pattern->type) { 555 continue; 556 } else { 557 entry_found = 1; 558 break; 559 } 560 } 561 562 if (!entry_found) { 563 priv->pattern[group].pattern_type[j] = pattern->type; 564 priv->pattern[group].item_count++; 565 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 566 } 567 568 /* Get traffic class index and flow id to be configured */ 569 flow->tc_id = group; 570 flow->index = attr->priority; 571 572 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 573 index = priv->extract.qos_key_cfg.num_extracts; 574 priv->extract.qos_key_cfg.extracts[index].type = 575 DPKG_EXTRACT_FROM_HDR; 576 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 577 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 578 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC; 579 index++; 580 581 priv->extract.qos_key_cfg.extracts[index].type = 582 DPKG_EXTRACT_FROM_HDR; 583 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 584 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 585 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST; 586 index++; 587 588 priv->extract.qos_key_cfg.num_extracts = index; 589 } 590 591 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 592 index = priv->extract.fs_key_cfg[group].num_extracts; 593 priv->extract.fs_key_cfg[group].extracts[index].type = 594 DPKG_EXTRACT_FROM_HDR; 595 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 596 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 597 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC; 598 index++; 599 600 priv->extract.fs_key_cfg[group].extracts[index].type = 601 DPKG_EXTRACT_FROM_HDR; 602 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 603 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 604 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST; 605 index++; 606 607 priv->extract.fs_key_cfg[group].num_extracts = index; 608 } 609 610 /* Parse pattern list to get the matching parameters */ 611 spec = (const struct rte_flow_item_ipv6 *)pattern->spec; 612 last = (const struct rte_flow_item_ipv6 *)pattern->last; 613 mask = (const struct rte_flow_item_ipv6 *) 614 (pattern->mask ? pattern->mask : default_mask); 615 616 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV6; 617 memcpy((void *)key_iova, (const void *)(spec->hdr.src_addr), 618 sizeof(spec->hdr.src_addr)); 619 key_iova += sizeof(spec->hdr.src_addr); 620 memcpy((void *)key_iova, (const void *)(spec->hdr.dst_addr), 621 sizeof(spec->hdr.dst_addr)); 622 623 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_IPV6; 624 memcpy((void *)mask_iova, (const void *)(mask->hdr.src_addr), 625 sizeof(mask->hdr.src_addr)); 626 mask_iova += sizeof(mask->hdr.src_addr); 627 memcpy((void *)mask_iova, (const void *)(mask->hdr.dst_addr), 628 sizeof(mask->hdr.dst_addr)); 629 630 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_IPV6 + 631 sizeof(spec->hdr.src_addr) + 632 sizeof(mask->hdr.dst_addr)); 633 return device_configured; 634 } 635 636 static int 637 dpaa2_configure_flow_icmp(struct rte_flow *flow, 638 struct rte_eth_dev *dev, 639 const struct rte_flow_attr *attr, 640 const struct rte_flow_item *pattern, 641 const struct rte_flow_action actions[] __rte_unused, 642 struct rte_flow_error *error __rte_unused) 643 { 644 int index, j = 0; 645 size_t key_iova; 646 size_t mask_iova; 647 int device_configured = 0, entry_found = 0; 648 uint32_t group; 649 const struct rte_flow_item_icmp *spec, *mask; 650 651 const struct rte_flow_item_icmp *last __rte_unused; 652 struct dpaa2_dev_priv *priv = dev->data->dev_private; 653 654 group = attr->group; 655 656 /* DPAA2 platform has a limitation that extract parameter can not be */ 657 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 658 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 659 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 660 DPKG_MAX_NUM_OF_EXTRACTS); 661 return -ENOTSUP; 662 } 663 664 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 665 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 666 DPKG_MAX_NUM_OF_EXTRACTS); 667 return -ENOTSUP; 668 } 669 670 for (j = 0; j < priv->pattern[8].item_count; j++) { 671 if (priv->pattern[8].pattern_type[j] != pattern->type) { 672 continue; 673 } else { 674 entry_found = 1; 675 break; 676 } 677 } 678 679 if (!entry_found) { 680 priv->pattern[8].pattern_type[j] = pattern->type; 681 priv->pattern[8].item_count++; 682 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 683 } 684 685 entry_found = 0; 686 for (j = 0; j < priv->pattern[group].item_count; j++) { 687 if (priv->pattern[group].pattern_type[j] != pattern->type) { 688 continue; 689 } else { 690 entry_found = 1; 691 break; 692 } 693 } 694 695 if (!entry_found) { 696 priv->pattern[group].pattern_type[j] = pattern->type; 697 priv->pattern[group].item_count++; 698 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 699 } 700 701 /* Get traffic class index and flow id to be configured */ 702 flow->tc_id = group; 703 flow->index = attr->priority; 704 705 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 706 index = priv->extract.qos_key_cfg.num_extracts; 707 priv->extract.qos_key_cfg.extracts[index].type = 708 DPKG_EXTRACT_FROM_HDR; 709 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 710 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP; 711 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE; 712 index++; 713 714 priv->extract.qos_key_cfg.extracts[index].type = 715 DPKG_EXTRACT_FROM_HDR; 716 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 717 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP; 718 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE; 719 index++; 720 721 priv->extract.qos_key_cfg.num_extracts = index; 722 } 723 724 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 725 index = priv->extract.fs_key_cfg[group].num_extracts; 726 priv->extract.fs_key_cfg[group].extracts[index].type = 727 DPKG_EXTRACT_FROM_HDR; 728 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 729 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP; 730 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE; 731 index++; 732 733 priv->extract.fs_key_cfg[group].extracts[index].type = 734 DPKG_EXTRACT_FROM_HDR; 735 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 736 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP; 737 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE; 738 index++; 739 740 priv->extract.fs_key_cfg[group].num_extracts = index; 741 } 742 743 /* Parse pattern list to get the matching parameters */ 744 spec = (const struct rte_flow_item_icmp *)pattern->spec; 745 last = (const struct rte_flow_item_icmp *)pattern->last; 746 mask = (const struct rte_flow_item_icmp *) 747 (pattern->mask ? pattern->mask : default_mask); 748 749 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_ICMP; 750 memcpy((void *)key_iova, (const void *)&spec->hdr.icmp_type, 751 sizeof(uint8_t)); 752 key_iova += sizeof(uint8_t); 753 memcpy((void *)key_iova, (const void *)&spec->hdr.icmp_code, 754 sizeof(uint8_t)); 755 756 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_ICMP; 757 memcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_type, 758 sizeof(uint8_t)); 759 key_iova += sizeof(uint8_t); 760 memcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_code, 761 sizeof(uint8_t)); 762 763 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_ICMP + 764 (2 * sizeof(uint8_t))); 765 766 return device_configured; 767 } 768 769 static int 770 dpaa2_configure_flow_udp(struct rte_flow *flow, 771 struct rte_eth_dev *dev, 772 const struct rte_flow_attr *attr, 773 const struct rte_flow_item *pattern, 774 const struct rte_flow_action actions[] __rte_unused, 775 struct rte_flow_error *error __rte_unused) 776 { 777 int index, j = 0; 778 size_t key_iova; 779 size_t mask_iova; 780 int device_configured = 0, entry_found = 0; 781 uint32_t group; 782 const struct rte_flow_item_udp *spec, *mask; 783 784 const struct rte_flow_item_udp *last __rte_unused; 785 struct dpaa2_dev_priv *priv = dev->data->dev_private; 786 787 group = attr->group; 788 789 /* DPAA2 platform has a limitation that extract parameter can not be */ 790 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 791 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 792 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 793 DPKG_MAX_NUM_OF_EXTRACTS); 794 return -ENOTSUP; 795 } 796 797 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 798 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 799 DPKG_MAX_NUM_OF_EXTRACTS); 800 return -ENOTSUP; 801 } 802 803 for (j = 0; j < priv->pattern[8].item_count; j++) { 804 if (priv->pattern[8].pattern_type[j] != pattern->type) { 805 continue; 806 } else { 807 entry_found = 1; 808 break; 809 } 810 } 811 812 if (!entry_found) { 813 priv->pattern[8].pattern_type[j] = pattern->type; 814 priv->pattern[8].item_count++; 815 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 816 } 817 818 entry_found = 0; 819 for (j = 0; j < priv->pattern[group].item_count; j++) { 820 if (priv->pattern[group].pattern_type[j] != pattern->type) { 821 continue; 822 } else { 823 entry_found = 1; 824 break; 825 } 826 } 827 828 if (!entry_found) { 829 priv->pattern[group].pattern_type[j] = pattern->type; 830 priv->pattern[group].item_count++; 831 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 832 } 833 834 /* Get traffic class index and flow id to be configured */ 835 flow->tc_id = group; 836 flow->index = attr->priority; 837 838 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 839 index = priv->extract.qos_key_cfg.num_extracts; 840 priv->extract.qos_key_cfg.extracts[index].type = 841 DPKG_EXTRACT_FROM_HDR; 842 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 843 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 844 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 845 index++; 846 847 priv->extract.qos_key_cfg.extracts[index].type = 848 DPKG_EXTRACT_FROM_HDR; 849 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 850 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP; 851 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC; 852 index++; 853 854 priv->extract.qos_key_cfg.extracts[index].type = DPKG_EXTRACT_FROM_HDR; 855 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 856 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP; 857 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST; 858 index++; 859 860 priv->extract.qos_key_cfg.num_extracts = index; 861 } 862 863 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 864 index = priv->extract.fs_key_cfg[group].num_extracts; 865 priv->extract.fs_key_cfg[group].extracts[index].type = 866 DPKG_EXTRACT_FROM_HDR; 867 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 868 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 869 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 870 index++; 871 872 priv->extract.fs_key_cfg[group].extracts[index].type = 873 DPKG_EXTRACT_FROM_HDR; 874 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 875 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP; 876 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC; 877 index++; 878 879 priv->extract.fs_key_cfg[group].extracts[index].type = 880 DPKG_EXTRACT_FROM_HDR; 881 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 882 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP; 883 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST; 884 index++; 885 886 priv->extract.fs_key_cfg[group].num_extracts = index; 887 } 888 889 /* Parse pattern list to get the matching parameters */ 890 spec = (const struct rte_flow_item_udp *)pattern->spec; 891 last = (const struct rte_flow_item_udp *)pattern->last; 892 mask = (const struct rte_flow_item_udp *) 893 (pattern->mask ? pattern->mask : default_mask); 894 895 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 + 896 (2 * sizeof(uint32_t)); 897 memset((void *)key_iova, 0x11, sizeof(uint8_t)); 898 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_UDP; 899 memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port), 900 sizeof(uint16_t)); 901 key_iova += sizeof(uint16_t); 902 memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port), 903 sizeof(uint16_t)); 904 905 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_UDP; 906 memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port), 907 sizeof(uint16_t)); 908 mask_iova += sizeof(uint16_t); 909 memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port), 910 sizeof(uint16_t)); 911 912 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_UDP + 913 (2 * sizeof(uint16_t))); 914 915 return device_configured; 916 } 917 918 static int 919 dpaa2_configure_flow_tcp(struct rte_flow *flow, 920 struct rte_eth_dev *dev, 921 const struct rte_flow_attr *attr, 922 const struct rte_flow_item *pattern, 923 const struct rte_flow_action actions[] __rte_unused, 924 struct rte_flow_error *error __rte_unused) 925 { 926 int index, j = 0; 927 size_t key_iova; 928 size_t mask_iova; 929 int device_configured = 0, entry_found = 0; 930 uint32_t group; 931 const struct rte_flow_item_tcp *spec, *mask; 932 933 const struct rte_flow_item_tcp *last __rte_unused; 934 struct dpaa2_dev_priv *priv = dev->data->dev_private; 935 936 group = attr->group; 937 938 /* DPAA2 platform has a limitation that extract parameter can not be */ 939 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/ 940 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 941 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 942 DPKG_MAX_NUM_OF_EXTRACTS); 943 return -ENOTSUP; 944 } 945 946 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 947 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 948 DPKG_MAX_NUM_OF_EXTRACTS); 949 return -ENOTSUP; 950 } 951 952 for (j = 0; j < priv->pattern[8].item_count; j++) { 953 if (priv->pattern[8].pattern_type[j] != pattern->type) { 954 continue; 955 } else { 956 entry_found = 1; 957 break; 958 } 959 } 960 961 if (!entry_found) { 962 priv->pattern[8].pattern_type[j] = pattern->type; 963 priv->pattern[8].item_count++; 964 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 965 } 966 967 entry_found = 0; 968 for (j = 0; j < priv->pattern[group].item_count; j++) { 969 if (priv->pattern[group].pattern_type[j] != pattern->type) { 970 continue; 971 } else { 972 entry_found = 1; 973 break; 974 } 975 } 976 977 if (!entry_found) { 978 priv->pattern[group].pattern_type[j] = pattern->type; 979 priv->pattern[group].item_count++; 980 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 981 } 982 983 /* Get traffic class index and flow id to be configured */ 984 flow->tc_id = group; 985 flow->index = attr->priority; 986 987 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 988 index = priv->extract.qos_key_cfg.num_extracts; 989 priv->extract.qos_key_cfg.extracts[index].type = 990 DPKG_EXTRACT_FROM_HDR; 991 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 992 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 993 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 994 index++; 995 996 priv->extract.qos_key_cfg.extracts[index].type = 997 DPKG_EXTRACT_FROM_HDR; 998 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 999 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP; 1000 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC; 1001 index++; 1002 1003 priv->extract.qos_key_cfg.extracts[index].type = 1004 DPKG_EXTRACT_FROM_HDR; 1005 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1006 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP; 1007 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST; 1008 index++; 1009 1010 priv->extract.qos_key_cfg.num_extracts = index; 1011 } 1012 1013 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 1014 index = priv->extract.fs_key_cfg[group].num_extracts; 1015 priv->extract.fs_key_cfg[group].extracts[index].type = 1016 DPKG_EXTRACT_FROM_HDR; 1017 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1018 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 1019 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 1020 index++; 1021 1022 priv->extract.fs_key_cfg[group].extracts[index].type = 1023 DPKG_EXTRACT_FROM_HDR; 1024 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1025 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP; 1026 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC; 1027 index++; 1028 1029 priv->extract.fs_key_cfg[group].extracts[index].type = 1030 DPKG_EXTRACT_FROM_HDR; 1031 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1032 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP; 1033 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST; 1034 index++; 1035 1036 priv->extract.fs_key_cfg[group].num_extracts = index; 1037 } 1038 1039 /* Parse pattern list to get the matching parameters */ 1040 spec = (const struct rte_flow_item_tcp *)pattern->spec; 1041 last = (const struct rte_flow_item_tcp *)pattern->last; 1042 mask = (const struct rte_flow_item_tcp *) 1043 (pattern->mask ? pattern->mask : default_mask); 1044 1045 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 + 1046 (2 * sizeof(uint32_t)); 1047 memset((void *)key_iova, 0x06, sizeof(uint8_t)); 1048 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_TCP; 1049 memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port), 1050 sizeof(uint16_t)); 1051 key_iova += sizeof(uint16_t); 1052 memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port), 1053 sizeof(uint16_t)); 1054 1055 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_TCP; 1056 memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port), 1057 sizeof(uint16_t)); 1058 mask_iova += sizeof(uint16_t); 1059 memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port), 1060 sizeof(uint16_t)); 1061 1062 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_TCP + 1063 (2 * sizeof(uint16_t))); 1064 1065 return device_configured; 1066 } 1067 1068 static int 1069 dpaa2_configure_flow_sctp(struct rte_flow *flow, 1070 struct rte_eth_dev *dev, 1071 const struct rte_flow_attr *attr, 1072 const struct rte_flow_item *pattern, 1073 const struct rte_flow_action actions[] __rte_unused, 1074 struct rte_flow_error *error __rte_unused) 1075 { 1076 int index, j = 0; 1077 size_t key_iova; 1078 size_t mask_iova; 1079 int device_configured = 0, entry_found = 0; 1080 uint32_t group; 1081 const struct rte_flow_item_sctp *spec, *mask; 1082 1083 const struct rte_flow_item_sctp *last __rte_unused; 1084 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1085 1086 group = attr->group; 1087 1088 /* DPAA2 platform has a limitation that extract parameter can not be */ 1089 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */ 1090 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 1091 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 1092 DPKG_MAX_NUM_OF_EXTRACTS); 1093 return -ENOTSUP; 1094 } 1095 1096 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 1097 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 1098 DPKG_MAX_NUM_OF_EXTRACTS); 1099 return -ENOTSUP; 1100 } 1101 1102 for (j = 0; j < priv->pattern[8].item_count; j++) { 1103 if (priv->pattern[8].pattern_type[j] != pattern->type) { 1104 continue; 1105 } else { 1106 entry_found = 1; 1107 break; 1108 } 1109 } 1110 1111 if (!entry_found) { 1112 priv->pattern[8].pattern_type[j] = pattern->type; 1113 priv->pattern[8].item_count++; 1114 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 1115 } 1116 1117 entry_found = 0; 1118 for (j = 0; j < priv->pattern[group].item_count; j++) { 1119 if (priv->pattern[group].pattern_type[j] != pattern->type) { 1120 continue; 1121 } else { 1122 entry_found = 1; 1123 break; 1124 } 1125 } 1126 1127 if (!entry_found) { 1128 priv->pattern[group].pattern_type[j] = pattern->type; 1129 priv->pattern[group].item_count++; 1130 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 1131 } 1132 1133 /* Get traffic class index and flow id to be configured */ 1134 flow->tc_id = group; 1135 flow->index = attr->priority; 1136 1137 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 1138 index = priv->extract.qos_key_cfg.num_extracts; 1139 priv->extract.qos_key_cfg.extracts[index].type = 1140 DPKG_EXTRACT_FROM_HDR; 1141 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1142 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP; 1143 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 1144 index++; 1145 1146 priv->extract.qos_key_cfg.extracts[index].type = 1147 DPKG_EXTRACT_FROM_HDR; 1148 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1149 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP; 1150 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC; 1151 index++; 1152 1153 priv->extract.qos_key_cfg.extracts[index].type = 1154 DPKG_EXTRACT_FROM_HDR; 1155 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1156 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP; 1157 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST; 1158 index++; 1159 1160 priv->extract.qos_key_cfg.num_extracts = index; 1161 } 1162 1163 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 1164 index = priv->extract.fs_key_cfg[group].num_extracts; 1165 priv->extract.fs_key_cfg[group].extracts[index].type = 1166 DPKG_EXTRACT_FROM_HDR; 1167 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1168 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP; 1169 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO; 1170 index++; 1171 1172 priv->extract.fs_key_cfg[group].extracts[index].type = 1173 DPKG_EXTRACT_FROM_HDR; 1174 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1175 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP; 1176 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC; 1177 index++; 1178 1179 priv->extract.fs_key_cfg[group].extracts[index].type = 1180 DPKG_EXTRACT_FROM_HDR; 1181 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1182 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP; 1183 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST; 1184 index++; 1185 1186 priv->extract.fs_key_cfg[group].num_extracts = index; 1187 } 1188 1189 /* Parse pattern list to get the matching parameters */ 1190 spec = (const struct rte_flow_item_sctp *)pattern->spec; 1191 last = (const struct rte_flow_item_sctp *)pattern->last; 1192 mask = (const struct rte_flow_item_sctp *) 1193 (pattern->mask ? pattern->mask : default_mask); 1194 1195 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_IPV4 + 1196 (2 * sizeof(uint32_t)); 1197 memset((void *)key_iova, 0x84, sizeof(uint8_t)); 1198 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_SCTP; 1199 memcpy((void *)key_iova, (const void *)(&spec->hdr.src_port), 1200 sizeof(uint16_t)); 1201 key_iova += sizeof(uint16_t); 1202 memcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port), 1203 sizeof(uint16_t)); 1204 1205 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_SCTP; 1206 memcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port), 1207 sizeof(uint16_t)); 1208 mask_iova += sizeof(uint16_t); 1209 memcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port), 1210 sizeof(uint16_t)); 1211 1212 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_SCTP + 1213 (2 * sizeof(uint16_t))); 1214 return device_configured; 1215 } 1216 1217 static int 1218 dpaa2_configure_flow_gre(struct rte_flow *flow, 1219 struct rte_eth_dev *dev, 1220 const struct rte_flow_attr *attr, 1221 const struct rte_flow_item *pattern, 1222 const struct rte_flow_action actions[] __rte_unused, 1223 struct rte_flow_error *error __rte_unused) 1224 { 1225 int index, j = 0; 1226 size_t key_iova; 1227 size_t mask_iova; 1228 int device_configured = 0, entry_found = 0; 1229 uint32_t group; 1230 const struct rte_flow_item_gre *spec, *mask; 1231 1232 const struct rte_flow_item_gre *last __rte_unused; 1233 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1234 1235 group = attr->group; 1236 1237 /* DPAA2 platform has a limitation that extract parameter can not be */ 1238 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */ 1239 if (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 1240 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 1241 DPKG_MAX_NUM_OF_EXTRACTS); 1242 return -ENOTSUP; 1243 } 1244 1245 if (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) { 1246 DPAA2_PMD_ERR("Maximum limit for different pattern type = %d\n", 1247 DPKG_MAX_NUM_OF_EXTRACTS); 1248 return -ENOTSUP; 1249 } 1250 1251 for (j = 0; j < priv->pattern[8].item_count; j++) { 1252 if (priv->pattern[8].pattern_type[j] != pattern->type) { 1253 continue; 1254 } else { 1255 entry_found = 1; 1256 break; 1257 } 1258 } 1259 1260 if (!entry_found) { 1261 priv->pattern[8].pattern_type[j] = pattern->type; 1262 priv->pattern[8].item_count++; 1263 device_configured |= DPAA2_QOS_TABLE_RECONFIGURE; 1264 } 1265 1266 entry_found = 0; 1267 for (j = 0; j < priv->pattern[group].item_count; j++) { 1268 if (priv->pattern[group].pattern_type[j] != pattern->type) { 1269 continue; 1270 } else { 1271 entry_found = 1; 1272 break; 1273 } 1274 } 1275 1276 if (!entry_found) { 1277 priv->pattern[group].pattern_type[j] = pattern->type; 1278 priv->pattern[group].item_count++; 1279 device_configured |= DPAA2_FS_TABLE_RECONFIGURE; 1280 } 1281 1282 /* Get traffic class index and flow id to be configured */ 1283 flow->tc_id = group; 1284 flow->index = attr->priority; 1285 1286 if (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 1287 index = priv->extract.qos_key_cfg.num_extracts; 1288 priv->extract.qos_key_cfg.extracts[index].type = 1289 DPKG_EXTRACT_FROM_HDR; 1290 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1291 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_GRE; 1292 priv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE; 1293 index++; 1294 1295 priv->extract.qos_key_cfg.num_extracts = index; 1296 } 1297 1298 if (device_configured & DPAA2_FS_TABLE_RECONFIGURE) { 1299 index = priv->extract.fs_key_cfg[group].num_extracts; 1300 priv->extract.fs_key_cfg[group].extracts[index].type = 1301 DPKG_EXTRACT_FROM_HDR; 1302 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD; 1303 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_GRE; 1304 priv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE; 1305 index++; 1306 1307 priv->extract.fs_key_cfg[group].num_extracts = index; 1308 } 1309 1310 /* Parse pattern list to get the matching parameters */ 1311 spec = (const struct rte_flow_item_gre *)pattern->spec; 1312 last = (const struct rte_flow_item_gre *)pattern->last; 1313 mask = (const struct rte_flow_item_gre *) 1314 (pattern->mask ? pattern->mask : default_mask); 1315 1316 key_iova = flow->rule.key_iova + DPAA2_CLS_RULE_OFFSET_GRE; 1317 memcpy((void *)key_iova, (const void *)(&spec->protocol), 1318 sizeof(rte_be16_t)); 1319 1320 mask_iova = flow->rule.mask_iova + DPAA2_CLS_RULE_OFFSET_GRE; 1321 memcpy((void *)mask_iova, (const void *)(&mask->protocol), 1322 sizeof(rte_be16_t)); 1323 1324 flow->rule.key_size = (DPAA2_CLS_RULE_OFFSET_GRE + sizeof(rte_be16_t)); 1325 1326 return device_configured; 1327 } 1328 1329 static int 1330 dpaa2_generic_flow_set(struct rte_flow *flow, 1331 struct rte_eth_dev *dev, 1332 const struct rte_flow_attr *attr, 1333 const struct rte_flow_item pattern[], 1334 const struct rte_flow_action actions[], 1335 struct rte_flow_error *error) 1336 { 1337 const struct rte_flow_action_queue *dest_queue; 1338 const struct rte_flow_action_rss *rss_conf; 1339 uint16_t index; 1340 int is_keycfg_configured = 0, end_of_list = 0; 1341 int ret = 0, i = 0, j = 0; 1342 struct dpni_attr nic_attr; 1343 struct dpni_rx_tc_dist_cfg tc_cfg; 1344 struct dpni_qos_tbl_cfg qos_cfg; 1345 struct dpkg_profile_cfg key_cfg; 1346 struct dpni_fs_action_cfg action; 1347 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1348 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 1349 size_t param; 1350 struct rte_flow *curr = LIST_FIRST(&priv->flows); 1351 1352 /* Parse pattern list to get the matching parameters */ 1353 while (!end_of_list) { 1354 switch (pattern[i].type) { 1355 case RTE_FLOW_ITEM_TYPE_ETH: 1356 is_keycfg_configured = dpaa2_configure_flow_eth(flow, 1357 dev, 1358 attr, 1359 &pattern[i], 1360 actions, 1361 error); 1362 break; 1363 case RTE_FLOW_ITEM_TYPE_VLAN: 1364 is_keycfg_configured = dpaa2_configure_flow_vlan(flow, 1365 dev, 1366 attr, 1367 &pattern[i], 1368 actions, 1369 error); 1370 break; 1371 case RTE_FLOW_ITEM_TYPE_IPV4: 1372 is_keycfg_configured = dpaa2_configure_flow_ipv4(flow, 1373 dev, 1374 attr, 1375 &pattern[i], 1376 actions, 1377 error); 1378 break; 1379 case RTE_FLOW_ITEM_TYPE_IPV6: 1380 is_keycfg_configured = dpaa2_configure_flow_ipv6(flow, 1381 dev, 1382 attr, 1383 &pattern[i], 1384 actions, 1385 error); 1386 break; 1387 case RTE_FLOW_ITEM_TYPE_ICMP: 1388 is_keycfg_configured = dpaa2_configure_flow_icmp(flow, 1389 dev, 1390 attr, 1391 &pattern[i], 1392 actions, 1393 error); 1394 break; 1395 case RTE_FLOW_ITEM_TYPE_UDP: 1396 is_keycfg_configured = dpaa2_configure_flow_udp(flow, 1397 dev, 1398 attr, 1399 &pattern[i], 1400 actions, 1401 error); 1402 break; 1403 case RTE_FLOW_ITEM_TYPE_TCP: 1404 is_keycfg_configured = dpaa2_configure_flow_tcp(flow, 1405 dev, 1406 attr, 1407 &pattern[i], 1408 actions, 1409 error); 1410 break; 1411 case RTE_FLOW_ITEM_TYPE_SCTP: 1412 is_keycfg_configured = dpaa2_configure_flow_sctp(flow, 1413 dev, attr, 1414 &pattern[i], 1415 actions, 1416 error); 1417 break; 1418 case RTE_FLOW_ITEM_TYPE_GRE: 1419 is_keycfg_configured = dpaa2_configure_flow_gre(flow, 1420 dev, 1421 attr, 1422 &pattern[i], 1423 actions, 1424 error); 1425 break; 1426 case RTE_FLOW_ITEM_TYPE_END: 1427 end_of_list = 1; 1428 break; /*End of List*/ 1429 default: 1430 DPAA2_PMD_ERR("Invalid action type"); 1431 ret = -ENOTSUP; 1432 break; 1433 } 1434 i++; 1435 } 1436 1437 /* Let's parse action on matching traffic */ 1438 end_of_list = 0; 1439 while (!end_of_list) { 1440 switch (actions[j].type) { 1441 case RTE_FLOW_ACTION_TYPE_QUEUE: 1442 dest_queue = (const struct rte_flow_action_queue *)(actions[j].conf); 1443 flow->flow_id = dest_queue->index; 1444 flow->action = RTE_FLOW_ACTION_TYPE_QUEUE; 1445 memset(&action, 0, sizeof(struct dpni_fs_action_cfg)); 1446 action.flow_id = flow->flow_id; 1447 if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) { 1448 if (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg, 1449 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) { 1450 DPAA2_PMD_ERR( 1451 "Unable to prepare extract parameters"); 1452 return -1; 1453 } 1454 1455 memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg)); 1456 qos_cfg.discard_on_miss = true; 1457 qos_cfg.keep_entries = true; 1458 qos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param; 1459 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, 1460 priv->token, &qos_cfg); 1461 if (ret < 0) { 1462 DPAA2_PMD_ERR( 1463 "Distribution cannot be configured.(%d)" 1464 , ret); 1465 return -1; 1466 } 1467 } 1468 if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) { 1469 if (dpkg_prepare_key_cfg(&priv->extract.fs_key_cfg[flow->tc_id], 1470 (uint8_t *)(size_t)priv->extract.fs_extract_param[flow->tc_id]) < 0) { 1471 DPAA2_PMD_ERR( 1472 "Unable to prepare extract parameters"); 1473 return -1; 1474 } 1475 1476 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); 1477 tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc; 1478 tc_cfg.dist_mode = DPNI_DIST_MODE_FS; 1479 tc_cfg.key_cfg_iova = 1480 (uint64_t)priv->extract.fs_extract_param[flow->tc_id]; 1481 tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP; 1482 tc_cfg.fs_cfg.keep_entries = true; 1483 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, 1484 priv->token, 1485 flow->tc_id, &tc_cfg); 1486 if (ret < 0) { 1487 DPAA2_PMD_ERR( 1488 "Distribution cannot be configured.(%d)" 1489 , ret); 1490 return -1; 1491 } 1492 } 1493 /* Configure QoS table first */ 1494 memset(&nic_attr, 0, sizeof(struct dpni_attr)); 1495 ret = dpni_get_attributes(dpni, CMD_PRI_LOW, 1496 priv->token, &nic_attr); 1497 if (ret < 0) { 1498 DPAA2_PMD_ERR( 1499 "Failure to get attribute. dpni@%p err code(%d)\n", 1500 dpni, ret); 1501 return ret; 1502 } 1503 1504 action.flow_id = action.flow_id % nic_attr.num_rx_tcs; 1505 index = flow->index + (flow->tc_id * nic_attr.fs_entries); 1506 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, 1507 priv->token, &flow->rule, 1508 flow->tc_id, index, 1509 0, 0); 1510 if (ret < 0) { 1511 DPAA2_PMD_ERR( 1512 "Error in addnig entry to QoS table(%d)", ret); 1513 return ret; 1514 } 1515 1516 /* Then Configure FS table */ 1517 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token, 1518 flow->tc_id, flow->index, 1519 &flow->rule, &action); 1520 if (ret < 0) { 1521 DPAA2_PMD_ERR( 1522 "Error in adding entry to FS table(%d)", ret); 1523 return ret; 1524 } 1525 break; 1526 case RTE_FLOW_ACTION_TYPE_RSS: 1527 ret = dpni_get_attributes(dpni, CMD_PRI_LOW, 1528 priv->token, &nic_attr); 1529 if (ret < 0) { 1530 DPAA2_PMD_ERR( 1531 "Failure to get attribute. dpni@%p err code(%d)\n", 1532 dpni, ret); 1533 return ret; 1534 } 1535 rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf); 1536 for (i = 0; i < (int)rss_conf->queue_num; i++) { 1537 if (rss_conf->queue[i] < (attr->group * nic_attr.num_queues) || 1538 rss_conf->queue[i] >= ((attr->group + 1) * nic_attr.num_queues)) { 1539 DPAA2_PMD_ERR( 1540 "Queue/Group combination are not supported\n"); 1541 return -ENOTSUP; 1542 } 1543 } 1544 1545 flow->action = RTE_FLOW_ACTION_TYPE_RSS; 1546 ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types, 1547 &key_cfg); 1548 if (ret < 0) { 1549 DPAA2_PMD_ERR( 1550 "unable to set flow distribution.please check queue config\n"); 1551 return ret; 1552 } 1553 1554 /* Allocate DMA'ble memory to write the rules */ 1555 param = (size_t)rte_malloc(NULL, 256, 64); 1556 if (!param) { 1557 DPAA2_PMD_ERR("Memory allocation failure\n"); 1558 return -1; 1559 } 1560 1561 if (dpkg_prepare_key_cfg(&key_cfg, (uint8_t *)param) < 0) { 1562 DPAA2_PMD_ERR( 1563 "Unable to prepare extract parameters"); 1564 rte_free((void *)param); 1565 return -1; 1566 } 1567 1568 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); 1569 tc_cfg.dist_size = rss_conf->queue_num; 1570 tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; 1571 tc_cfg.key_cfg_iova = (size_t)param; 1572 tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP; 1573 1574 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, 1575 priv->token, flow->tc_id, 1576 &tc_cfg); 1577 if (ret < 0) { 1578 DPAA2_PMD_ERR( 1579 "Distribution cannot be configured: %d\n", ret); 1580 rte_free((void *)param); 1581 return -1; 1582 } 1583 1584 rte_free((void *)param); 1585 if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) { 1586 if (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg, 1587 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) { 1588 DPAA2_PMD_ERR( 1589 "Unable to prepare extract parameters"); 1590 return -1; 1591 } 1592 memset(&qos_cfg, 0, 1593 sizeof(struct dpni_qos_tbl_cfg)); 1594 qos_cfg.discard_on_miss = true; 1595 qos_cfg.keep_entries = true; 1596 qos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param; 1597 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, 1598 priv->token, &qos_cfg); 1599 if (ret < 0) { 1600 DPAA2_PMD_ERR( 1601 "Distribution can not be configured(%d)\n", 1602 ret); 1603 return -1; 1604 } 1605 } 1606 1607 /* Add Rule into QoS table */ 1608 index = flow->index + (flow->tc_id * nic_attr.fs_entries); 1609 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token, 1610 &flow->rule, flow->tc_id, 1611 index, 0, 0); 1612 if (ret < 0) { 1613 DPAA2_PMD_ERR( 1614 "Error in entry addition in QoS table(%d)", 1615 ret); 1616 return ret; 1617 } 1618 break; 1619 case RTE_FLOW_ACTION_TYPE_END: 1620 end_of_list = 1; 1621 break; 1622 default: 1623 DPAA2_PMD_ERR("Invalid action type"); 1624 ret = -ENOTSUP; 1625 break; 1626 } 1627 j++; 1628 } 1629 1630 if (!ret) { 1631 /* New rules are inserted. */ 1632 if (!curr) { 1633 LIST_INSERT_HEAD(&priv->flows, flow, next); 1634 } else { 1635 while (LIST_NEXT(curr, next)) 1636 curr = LIST_NEXT(curr, next); 1637 LIST_INSERT_AFTER(curr, flow, next); 1638 } 1639 } 1640 return ret; 1641 } 1642 1643 static inline int 1644 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, 1645 const struct rte_flow_attr *attr) 1646 { 1647 int ret = 0; 1648 1649 if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) { 1650 DPAA2_PMD_ERR("Priority group is out of range\n"); 1651 ret = -ENOTSUP; 1652 } 1653 if (unlikely(attr->priority >= dpni_attr->fs_entries)) { 1654 DPAA2_PMD_ERR("Priority within the group is out of range\n"); 1655 ret = -ENOTSUP; 1656 } 1657 if (unlikely(attr->egress)) { 1658 DPAA2_PMD_ERR( 1659 "Flow configuration is not supported on egress side\n"); 1660 ret = -ENOTSUP; 1661 } 1662 if (unlikely(!attr->ingress)) { 1663 DPAA2_PMD_ERR("Ingress flag must be configured\n"); 1664 ret = -EINVAL; 1665 } 1666 return ret; 1667 } 1668 1669 static inline void 1670 dpaa2_dev_update_default_mask(const struct rte_flow_item *pattern) 1671 { 1672 switch (pattern->type) { 1673 case RTE_FLOW_ITEM_TYPE_ETH: 1674 default_mask = (const void *)&rte_flow_item_eth_mask; 1675 break; 1676 case RTE_FLOW_ITEM_TYPE_VLAN: 1677 default_mask = (const void *)&rte_flow_item_vlan_mask; 1678 break; 1679 case RTE_FLOW_ITEM_TYPE_IPV4: 1680 default_mask = (const void *)&rte_flow_item_ipv4_mask; 1681 break; 1682 case RTE_FLOW_ITEM_TYPE_IPV6: 1683 default_mask = (const void *)&rte_flow_item_ipv6_mask; 1684 break; 1685 case RTE_FLOW_ITEM_TYPE_ICMP: 1686 default_mask = (const void *)&rte_flow_item_icmp_mask; 1687 break; 1688 case RTE_FLOW_ITEM_TYPE_UDP: 1689 default_mask = (const void *)&rte_flow_item_udp_mask; 1690 break; 1691 case RTE_FLOW_ITEM_TYPE_TCP: 1692 default_mask = (const void *)&rte_flow_item_tcp_mask; 1693 break; 1694 case RTE_FLOW_ITEM_TYPE_SCTP: 1695 default_mask = (const void *)&rte_flow_item_sctp_mask; 1696 break; 1697 case RTE_FLOW_ITEM_TYPE_GRE: 1698 default_mask = (const void *)&rte_flow_item_gre_mask; 1699 break; 1700 default: 1701 DPAA2_PMD_ERR("Invalid pattern type"); 1702 } 1703 } 1704 1705 static inline int 1706 dpaa2_dev_verify_patterns(struct dpaa2_dev_priv *dev_priv, 1707 const struct rte_flow_item pattern[]) 1708 { 1709 unsigned int i, j, k, is_found = 0; 1710 int ret = 0; 1711 1712 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { 1713 for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) { 1714 if (dpaa2_supported_pattern_type[i] == pattern[j].type) { 1715 is_found = 1; 1716 break; 1717 } 1718 } 1719 if (!is_found) { 1720 ret = -ENOTSUP; 1721 break; 1722 } 1723 } 1724 /* Lets verify other combinations of given pattern rules */ 1725 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { 1726 if (!pattern[j].spec) { 1727 ret = -EINVAL; 1728 break; 1729 } 1730 if ((pattern[j].last) && (!pattern[j].mask)) 1731 dpaa2_dev_update_default_mask(&pattern[j]); 1732 } 1733 1734 /* DPAA2 platform has a limitation that extract parameter can not be */ 1735 /* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */ 1736 for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) { 1737 for (j = 0; j < MAX_TCS + 1; j++) { 1738 for (k = 0; k < DPKG_MAX_NUM_OF_EXTRACTS; k++) { 1739 if (dev_priv->pattern[j].pattern_type[k] == pattern[i].type) 1740 break; 1741 } 1742 if (dev_priv->pattern[j].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) 1743 ret = -ENOTSUP; 1744 } 1745 } 1746 return ret; 1747 } 1748 1749 static inline int 1750 dpaa2_dev_verify_actions(const struct rte_flow_action actions[]) 1751 { 1752 unsigned int i, j, is_found = 0; 1753 int ret = 0; 1754 1755 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { 1756 for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) { 1757 if (dpaa2_supported_action_type[i] == actions[j].type) { 1758 is_found = 1; 1759 break; 1760 } 1761 } 1762 if (!is_found) { 1763 ret = -ENOTSUP; 1764 break; 1765 } 1766 } 1767 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { 1768 if ((actions[j].type != RTE_FLOW_ACTION_TYPE_DROP) && (!actions[j].conf)) 1769 ret = -EINVAL; 1770 } 1771 return ret; 1772 } 1773 1774 static 1775 int dpaa2_flow_validate(struct rte_eth_dev *dev, 1776 const struct rte_flow_attr *flow_attr, 1777 const struct rte_flow_item pattern[], 1778 const struct rte_flow_action actions[], 1779 struct rte_flow_error *error) 1780 { 1781 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1782 struct dpni_attr dpni_attr; 1783 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 1784 uint16_t token = priv->token; 1785 int ret = 0; 1786 1787 memset(&dpni_attr, 0, sizeof(struct dpni_attr)); 1788 ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr); 1789 if (ret < 0) { 1790 DPAA2_PMD_ERR( 1791 "Failure to get dpni@%p attribute, err code %d\n", 1792 dpni, ret); 1793 rte_flow_error_set(error, EPERM, 1794 RTE_FLOW_ERROR_TYPE_ATTR, 1795 flow_attr, "invalid"); 1796 return ret; 1797 } 1798 1799 /* Verify input attributes */ 1800 ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr); 1801 if (ret < 0) { 1802 DPAA2_PMD_ERR( 1803 "Invalid attributes are given\n"); 1804 rte_flow_error_set(error, EPERM, 1805 RTE_FLOW_ERROR_TYPE_ATTR, 1806 flow_attr, "invalid"); 1807 goto not_valid_params; 1808 } 1809 /* Verify input pattern list */ 1810 ret = dpaa2_dev_verify_patterns(priv, pattern); 1811 if (ret < 0) { 1812 DPAA2_PMD_ERR( 1813 "Invalid pattern list is given\n"); 1814 rte_flow_error_set(error, EPERM, 1815 RTE_FLOW_ERROR_TYPE_ITEM, 1816 pattern, "invalid"); 1817 goto not_valid_params; 1818 } 1819 /* Verify input action list */ 1820 ret = dpaa2_dev_verify_actions(actions); 1821 if (ret < 0) { 1822 DPAA2_PMD_ERR( 1823 "Invalid action list is given\n"); 1824 rte_flow_error_set(error, EPERM, 1825 RTE_FLOW_ERROR_TYPE_ACTION, 1826 actions, "invalid"); 1827 goto not_valid_params; 1828 } 1829 not_valid_params: 1830 return ret; 1831 } 1832 1833 static 1834 struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev, 1835 const struct rte_flow_attr *attr, 1836 const struct rte_flow_item pattern[], 1837 const struct rte_flow_action actions[], 1838 struct rte_flow_error *error) 1839 { 1840 struct rte_flow *flow = NULL; 1841 size_t key_iova = 0, mask_iova = 0; 1842 int ret; 1843 1844 flow = rte_malloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE); 1845 if (!flow) { 1846 DPAA2_PMD_ERR("Failure to allocate memory for flow"); 1847 goto mem_failure; 1848 } 1849 /* Allocate DMA'ble memory to write the rules */ 1850 key_iova = (size_t)rte_malloc(NULL, 256, 64); 1851 if (!key_iova) { 1852 DPAA2_PMD_ERR( 1853 "Memory allocation failure for rule configuration\n"); 1854 goto mem_failure; 1855 } 1856 mask_iova = (size_t)rte_malloc(NULL, 256, 64); 1857 if (!mask_iova) { 1858 DPAA2_PMD_ERR( 1859 "Memory allocation failure for rule configuration\n"); 1860 goto mem_failure; 1861 } 1862 1863 flow->rule.key_iova = key_iova; 1864 flow->rule.mask_iova = mask_iova; 1865 flow->rule.key_size = 0; 1866 1867 switch (dpaa2_filter_type) { 1868 case RTE_ETH_FILTER_GENERIC: 1869 ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, 1870 actions, error); 1871 if (ret < 0) { 1872 if (error->type > RTE_FLOW_ERROR_TYPE_ACTION) 1873 rte_flow_error_set(error, EPERM, 1874 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1875 attr, "unknown"); 1876 DPAA2_PMD_ERR( 1877 "Failure to create flow, return code (%d)", ret); 1878 goto creation_error; 1879 } 1880 break; 1881 default: 1882 DPAA2_PMD_ERR("Filter type (%d) not supported", 1883 dpaa2_filter_type); 1884 break; 1885 } 1886 1887 return flow; 1888 mem_failure: 1889 rte_flow_error_set(error, EPERM, 1890 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1891 NULL, "memory alloc"); 1892 creation_error: 1893 rte_free((void *)flow); 1894 rte_free((void *)key_iova); 1895 rte_free((void *)mask_iova); 1896 1897 return NULL; 1898 } 1899 1900 static 1901 int dpaa2_flow_destroy(struct rte_eth_dev *dev, 1902 struct rte_flow *flow, 1903 struct rte_flow_error *error) 1904 { 1905 int ret = 0; 1906 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1907 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; 1908 1909 switch (flow->action) { 1910 case RTE_FLOW_ACTION_TYPE_QUEUE: 1911 /* Remove entry from QoS table first */ 1912 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token, 1913 &flow->rule); 1914 if (ret < 0) { 1915 DPAA2_PMD_ERR( 1916 "Error in adding entry to QoS table(%d)", ret); 1917 goto error; 1918 } 1919 1920 /* Then remove entry from FS table */ 1921 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, 1922 flow->tc_id, &flow->rule); 1923 if (ret < 0) { 1924 DPAA2_PMD_ERR( 1925 "Error in entry addition in FS table(%d)", ret); 1926 goto error; 1927 } 1928 break; 1929 case RTE_FLOW_ACTION_TYPE_RSS: 1930 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token, 1931 &flow->rule); 1932 if (ret < 0) { 1933 DPAA2_PMD_ERR( 1934 "Error in entry addition in QoS table(%d)", ret); 1935 goto error; 1936 } 1937 break; 1938 default: 1939 DPAA2_PMD_ERR( 1940 "Action type (%d) is not supported", flow->action); 1941 ret = -ENOTSUP; 1942 break; 1943 } 1944 1945 LIST_REMOVE(flow, next); 1946 /* Now free the flow */ 1947 rte_free(flow); 1948 1949 error: 1950 if (ret) 1951 rte_flow_error_set(error, EPERM, 1952 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1953 NULL, "unknown"); 1954 return ret; 1955 } 1956 1957 /** 1958 * Destroy user-configured flow rules. 1959 * 1960 * This function skips internal flows rules. 1961 * 1962 * @see rte_flow_flush() 1963 * @see rte_flow_ops 1964 */ 1965 static int 1966 dpaa2_flow_flush(struct rte_eth_dev *dev, 1967 struct rte_flow_error *error) 1968 { 1969 struct dpaa2_dev_priv *priv = dev->data->dev_private; 1970 struct rte_flow *flow = LIST_FIRST(&priv->flows); 1971 1972 while (flow) { 1973 struct rte_flow *next = LIST_NEXT(flow, next); 1974 1975 dpaa2_flow_destroy(dev, flow, error); 1976 flow = next; 1977 } 1978 return 0; 1979 } 1980 1981 static int 1982 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, 1983 struct rte_flow *flow __rte_unused, 1984 const struct rte_flow_action *actions __rte_unused, 1985 void *data __rte_unused, 1986 struct rte_flow_error *error __rte_unused) 1987 { 1988 return 0; 1989 } 1990 1991 /** 1992 * Clean up all flow rules. 1993 * 1994 * Unlike dpaa2_flow_flush(), this function takes care of all remaining flow 1995 * rules regardless of whether they are internal or user-configured. 1996 * 1997 * @param priv 1998 * Pointer to private structure. 1999 */ 2000 void 2001 dpaa2_flow_clean(struct rte_eth_dev *dev) 2002 { 2003 struct rte_flow *flow; 2004 struct dpaa2_dev_priv *priv = dev->data->dev_private; 2005 2006 while ((flow = LIST_FIRST(&priv->flows))) 2007 dpaa2_flow_destroy(dev, flow, NULL); 2008 } 2009 2010 const struct rte_flow_ops dpaa2_flow_ops = { 2011 .create = dpaa2_flow_create, 2012 .validate = dpaa2_flow_validate, 2013 .destroy = dpaa2_flow_destroy, 2014 .flush = dpaa2_flow_flush, 2015 .query = dpaa2_flow_query, 2016 }; 2017