1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include "bnxt_tf_common.h" 7 #include "bnxt_ulp_utils.h" 8 #include "ulp_template_struct.h" 9 #include "ulp_template_db_enum.h" 10 #include "ulp_template_db_field.h" 11 #include "ulp_utils.h" 12 #include "ulp_port_db.h" 13 #include "ulp_flow_db.h" 14 #include "ulp_mapper.h" 15 #include "ulp_rte_parser.h" 16 static void 17 ulp_l2_custom_tunnel_id_update(struct bnxt *bp, 18 struct bnxt_ulp_mapper_parms *params); 19 20 struct bnxt_ulp_def_param_handler { 21 int32_t (*vfr_func)(struct bnxt_ulp_context *ulp_ctx, 22 struct ulp_tlv_param *param, 23 struct bnxt_ulp_mapper_parms *mapper_params); 24 }; 25 26 static int32_t 27 ulp_set_svif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, 28 uint32_t ifindex, uint8_t svif_type, 29 struct bnxt_ulp_mapper_parms *mapper_params) 30 { 31 uint16_t svif; 32 uint8_t idx; 33 int rc; 34 35 rc = ulp_port_db_svif_get(ulp_ctx, ifindex, svif_type, &svif); 36 if (rc) 37 return rc; 38 39 if (svif_type == BNXT_ULP_PHY_PORT_SVIF) 40 idx = BNXT_ULP_CF_IDX_PHY_PORT_SVIF; 41 else if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) 42 idx = BNXT_ULP_CF_IDX_DRV_FUNC_SVIF; 43 else 44 idx = BNXT_ULP_CF_IDX_VF_FUNC_SVIF; 45 46 ULP_COMP_FLD_IDX_WR(mapper_params, idx, svif); 47 48 return 0; 49 } 50 51 static int32_t 52 ulp_set_spif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, 53 uint32_t ifindex, uint8_t spif_type, 54 struct bnxt_ulp_mapper_parms *mapper_params) 55 { 56 uint16_t spif; 57 uint8_t idx; 58 int rc; 59 60 rc = ulp_port_db_spif_get(ulp_ctx, ifindex, spif_type, &spif); 61 if (rc) 62 return rc; 63 64 if (spif_type == BNXT_ULP_PHY_PORT_SPIF) 65 idx = BNXT_ULP_CF_IDX_PHY_PORT_SPIF; 66 else if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) 67 idx = BNXT_ULP_CF_IDX_DRV_FUNC_SPIF; 68 else 69 idx = BNXT_ULP_CF_IDX_VF_FUNC_SPIF; 70 71 ULP_COMP_FLD_IDX_WR(mapper_params, idx, spif); 72 73 return 0; 74 } 75 76 static int32_t 77 ulp_set_parif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, 78 uint32_t ifindex, uint8_t parif_type, 79 struct bnxt_ulp_mapper_parms *mapper_params) 80 { 81 uint16_t parif; 82 uint8_t idx; 83 int rc; 84 85 rc = ulp_port_db_parif_get(ulp_ctx, ifindex, parif_type, &parif); 86 if (rc) 87 return rc; 88 89 if (parif_type == BNXT_ULP_PHY_PORT_PARIF) 90 idx = BNXT_ULP_CF_IDX_PHY_PORT_PARIF; 91 else if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) 92 idx = BNXT_ULP_CF_IDX_DRV_FUNC_PARIF; 93 else 94 idx = BNXT_ULP_CF_IDX_VF_FUNC_PARIF; 95 96 ULP_COMP_FLD_IDX_WR(mapper_params, idx, parif); 97 98 return 0; 99 } 100 101 static int32_t 102 ulp_set_vport_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, uint32_t ifindex, 103 struct bnxt_ulp_mapper_parms *mapper_params) 104 { 105 uint16_t vport; 106 int rc; 107 108 rc = ulp_port_db_vport_get(ulp_ctx, ifindex, &vport); 109 if (rc) 110 return rc; 111 112 ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_PHY_PORT_VPORT, 113 vport); 114 return 0; 115 } 116 117 static int32_t 118 ulp_set_vnic_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, 119 uint32_t ifindex, uint8_t vnic_type, 120 struct bnxt_ulp_mapper_parms *mapper_params) 121 { 122 uint16_t vnic; 123 uint8_t idx; 124 int rc; 125 126 rc = ulp_port_db_default_vnic_get(ulp_ctx, ifindex, vnic_type, &vnic); 127 if (rc) 128 return rc; 129 130 if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) 131 idx = BNXT_ULP_CF_IDX_DRV_FUNC_VNIC; 132 else 133 idx = BNXT_ULP_CF_IDX_VF_FUNC_VNIC; 134 135 ULP_COMP_FLD_IDX_WR(mapper_params, idx, vnic); 136 137 return 0; 138 } 139 140 static int32_t 141 ulp_set_vlan_in_act_prop(uint16_t port_id, 142 struct bnxt_ulp_mapper_parms *mapper_params) 143 { 144 struct ulp_rte_act_prop *act_prop = mapper_params->act_prop; 145 146 if (ULP_BITMAP_ISSET(mapper_params->act_bitmap->bits, 147 BNXT_ULP_ACT_BIT_SET_VLAN_VID)) { 148 BNXT_DRV_DBG(ERR, 149 "VLAN already set, multiple VLANs unsupported\n"); 150 return BNXT_TF_RC_ERROR; 151 } 152 153 port_id = rte_cpu_to_be_16(port_id); 154 155 ULP_BITMAP_SET(mapper_params->act_bitmap->bits, 156 BNXT_ULP_ACT_BIT_SET_VLAN_VID); 157 158 memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_ENCAP_VTAG], 159 &port_id, sizeof(port_id)); 160 161 return 0; 162 } 163 164 static int32_t 165 ulp_set_mark_in_act_prop(uint16_t port_id, 166 struct bnxt_ulp_mapper_parms *mapper_params) 167 { 168 if (ULP_BITMAP_ISSET(mapper_params->act_bitmap->bits, 169 BNXT_ULP_ACT_BIT_MARK)) { 170 BNXT_DRV_DBG(ERR, 171 "MARK already set, multiple MARKs unsupported\n"); 172 return BNXT_TF_RC_ERROR; 173 } 174 175 ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_DEV_PORT_ID, 176 port_id); 177 178 return 0; 179 } 180 181 static int32_t 182 ulp_df_dev_port_handler(struct bnxt_ulp_context *ulp_ctx, 183 struct ulp_tlv_param *param, 184 struct bnxt_ulp_mapper_parms *mapper_params) 185 { 186 uint16_t port_id; 187 uint16_t parif; 188 uint32_t ifindex; 189 int rc; 190 191 port_id = param->value[0] | param->value[1]; 192 193 rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctx, port_id, &ifindex); 194 if (rc) { 195 BNXT_DRV_DBG(ERR, "Invalid port id\n"); 196 return BNXT_TF_RC_ERROR; 197 } 198 199 /* Set port SVIF */ 200 rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_PHY_PORT_SVIF, 201 mapper_params); 202 if (rc) 203 return rc; 204 205 /* Set DRV Func SVIF */ 206 rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SVIF, 207 mapper_params); 208 if (rc) 209 return rc; 210 211 /* Set VF Func SVIF */ 212 rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_VF_FUNC_SVIF, 213 mapper_params); 214 if (rc) 215 return rc; 216 217 /* Set port SPIF */ 218 rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_PHY_PORT_SPIF, 219 mapper_params); 220 if (rc) 221 return rc; 222 223 /* Set DRV Func SPIF */ 224 rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SPIF, 225 mapper_params); 226 if (rc) 227 return rc; 228 229 /* Set VF Func SPIF */ 230 rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SPIF, 231 mapper_params); 232 if (rc) 233 return rc; 234 235 /* Set port PARIF */ 236 rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex, 237 BNXT_ULP_PHY_PORT_PARIF, mapper_params); 238 if (rc) 239 return rc; 240 241 /* Set DRV Func PARIF */ 242 rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex, 243 BNXT_ULP_DRV_FUNC_PARIF, mapper_params); 244 if (rc) 245 return rc; 246 247 /* Note: 248 * We save the drv_func_parif into CF_IDX of phy_port_parif, 249 * since that index is currently referenced by ingress templates 250 * for datapath flows. If in the future we change the parser to 251 * save it in the CF_IDX of drv_func_parif we also need to update 252 * the template. 253 * WARNING: Two VFs on same parent PF will not work, as the parif is 254 * based on fw fid of the parent PF. 255 */ 256 parif = ULP_COMP_FLD_IDX_RD(mapper_params, BNXT_ULP_CF_IDX_DRV_FUNC_PARIF); 257 ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_PHY_PORT_PARIF, parif); 258 259 /* Set VF Func PARIF */ 260 rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_VF_FUNC_PARIF, 261 mapper_params); 262 if (rc) 263 return rc; 264 265 /* Set uplink VNIC */ 266 rc = ulp_set_vnic_in_comp_fld(ulp_ctx, ifindex, true, mapper_params); 267 if (rc) 268 return rc; 269 270 /* Set VF VNIC */ 271 rc = ulp_set_vnic_in_comp_fld(ulp_ctx, ifindex, false, mapper_params); 272 if (rc) 273 return rc; 274 275 /* Set VPORT */ 276 rc = ulp_set_vport_in_comp_fld(ulp_ctx, ifindex, mapper_params); 277 if (rc) 278 return rc; 279 280 /* Set VLAN */ 281 rc = ulp_set_vlan_in_act_prop(port_id, mapper_params); 282 if (rc) 283 return rc; 284 285 /* Set MARK */ 286 rc = ulp_set_mark_in_act_prop(port_id, mapper_params); 287 if (rc) 288 return rc; 289 290 return 0; 291 } 292 293 struct bnxt_ulp_def_param_handler ulp_def_handler_tbl[] = { 294 [BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID] = { 295 .vfr_func = ulp_df_dev_port_handler } 296 }; 297 298 /* 299 * Function to create default rules for the following paths 300 * 1) Device PORT to DPDK App 301 * 2) DPDK App to Device PORT 302 * 3) VF Representor to VF 303 * 4) VF to VF Representor 304 * 305 * eth_dev [in] Ptr to rte eth device. 306 * param_list [in] Ptr to a list of parameters (Currently, only DPDK port_id). 307 * ulp_class_tid [in] Class template ID number. 308 * flow_id [out] Ptr to flow identifier. 309 * 310 * Returns 0 on success or negative number on failure. 311 */ 312 int32_t 313 ulp_default_flow_create(struct rte_eth_dev *eth_dev, 314 struct ulp_tlv_param *param_list, 315 uint32_t ulp_class_tid, 316 uint16_t port_id, 317 uint32_t *flow_id) 318 { 319 struct ulp_rte_hdr_field hdr_field[BNXT_ULP_PROTO_HDR_MAX]; 320 uint64_t comp_fld[BNXT_ULP_CF_IDX_LAST]; 321 struct bnxt_ulp_mapper_parms mapper_params = { 0 }; 322 struct ulp_rte_act_prop act_prop; 323 struct ulp_rte_act_bitmap act = { 0 }; 324 struct bnxt_ulp_context *ulp_ctx; 325 uint32_t type, ulp_flags = 0, fid; 326 struct bnxt *bp = eth_dev->data->dev_private; 327 uint16_t static_port = 0; 328 int rc = 0; 329 330 memset(&mapper_params, 0, sizeof(mapper_params)); 331 memset(hdr_field, 0, sizeof(hdr_field)); 332 memset(comp_fld, 0, sizeof(comp_fld)); 333 memset(&act_prop, 0, sizeof(act_prop)); 334 335 mapper_params.hdr_field = hdr_field; 336 mapper_params.act_bitmap = &act; 337 mapper_params.act_prop = &act_prop; 338 mapper_params.comp_fld = comp_fld; 339 mapper_params.class_tid = ulp_class_tid; 340 mapper_params.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT; 341 mapper_params.port_id = eth_dev->data->port_id; 342 343 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); 344 if (!ulp_ctx) { 345 BNXT_DRV_DBG(ERR, 346 "ULP is not init'ed. Fail to create dflt flow.\n"); 347 return -EINVAL; 348 } 349 350 /* update the vf rep flag */ 351 if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(ulp_ctx, &ulp_flags)) { 352 BNXT_DRV_DBG(ERR, "Error in getting ULP context flags\n"); 353 return -EINVAL; 354 } 355 if (ULP_VF_REP_IS_ENABLED(ulp_flags)) 356 ULP_COMP_FLD_IDX_WR(&mapper_params, 357 BNXT_ULP_CF_IDX_VFR_MODE, 1); 358 359 type = param_list->type; 360 while (type != BNXT_ULP_DF_PARAM_TYPE_LAST) { 361 if (ulp_def_handler_tbl[type].vfr_func) { 362 rc = ulp_def_handler_tbl[type].vfr_func(ulp_ctx, 363 param_list, 364 &mapper_params); 365 if (rc) { 366 BNXT_DRV_DBG(ERR, 367 "Failed to create default flow.\n"); 368 return rc; 369 } 370 } 371 372 param_list++; 373 type = param_list->type; 374 } 375 376 /* Get the function id */ 377 if (ulp_port_db_port_func_id_get(ulp_ctx, 378 port_id, 379 &mapper_params.func_id)) { 380 BNXT_DRV_DBG(ERR, "conversion of port to func id failed\n"); 381 goto err1; 382 } 383 384 /* update the VF meta function id */ 385 ULP_COMP_FLD_IDX_WR(&mapper_params, BNXT_ULP_CF_IDX_VF_META_FID, 386 BNXT_ULP_META_VF_FLAG | mapper_params.func_id); 387 388 /* update the upar id */ 389 ulp_l2_custom_tunnel_id_update(bp, &mapper_params); 390 391 /* update the vxlan port */ 392 if (ULP_APP_STATIC_VXLAN_PORT_EN(ulp_ctx)) { 393 static_port = bnxt_ulp_cntxt_vxlan_port_get(ulp_ctx); 394 if (static_port) { 395 ULP_COMP_FLD_IDX_WR(&mapper_params, 396 BNXT_ULP_CF_IDX_TUNNEL_PORT, 397 static_port); 398 ULP_BITMAP_SET(mapper_params.cf_bitmap, 399 BNXT_ULP_CF_BIT_STATIC_VXLAN_PORT); 400 } else { 401 static_port = bnxt_ulp_cntxt_vxlan_ip_port_get(ulp_ctx); 402 ULP_COMP_FLD_IDX_WR(&mapper_params, 403 BNXT_ULP_CF_IDX_TUNNEL_PORT, 404 static_port); 405 ULP_BITMAP_SET(mapper_params.cf_bitmap, 406 BNXT_ULP_CF_BIT_STATIC_VXLAN_IP_PORT); 407 } 408 } 409 410 BNXT_DRV_DBG(DEBUG, "Creating default flow with template id: %u\n", 411 ulp_class_tid); 412 413 /* Protect flow creation */ 414 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 415 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 416 goto err1; 417 } 418 419 rc = ulp_flow_db_fid_alloc(ulp_ctx, mapper_params.flow_type, 420 mapper_params.func_id, &fid); 421 if (rc) { 422 BNXT_DRV_DBG(ERR, "Unable to allocate flow table entry\n"); 423 goto err2; 424 } 425 426 mapper_params.flow_id = fid; 427 rc = ulp_mapper_flow_create(ulp_ctx, &mapper_params, 428 NULL); 429 if (rc) 430 goto err3; 431 432 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 433 *flow_id = fid; 434 return 0; 435 436 err3: 437 ulp_flow_db_fid_free(ulp_ctx, mapper_params.flow_type, fid); 438 err2: 439 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 440 err1: 441 BNXT_DRV_DBG(ERR, "Failed to create default flow.\n"); 442 return rc; 443 } 444 445 /* 446 * Function to destroy default rules for the following paths 447 * 1) Device PORT to DPDK App 448 * 2) DPDK App to Device PORT 449 * 3) VF Representor to VF 450 * 4) VF to VF Representor 451 * 452 * eth_dev [in] Ptr to rte eth device. 453 * flow_id [in] Flow identifier. 454 * 455 * Returns 0 on success or negative number on failure. 456 */ 457 int32_t 458 ulp_default_flow_destroy(struct rte_eth_dev *eth_dev, uint32_t flow_id) 459 { 460 struct bnxt_ulp_context *ulp_ctx; 461 int rc = 0; 462 463 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev); 464 if (!ulp_ctx) { 465 BNXT_DRV_DBG(ERR, "ULP context is not initialized\n"); 466 return -EINVAL; 467 } 468 469 if (!flow_id) { 470 BNXT_DRV_DBG(DEBUG, "invalid flow id zero\n"); 471 return rc; 472 } 473 474 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 475 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 476 return -EINVAL; 477 } 478 rc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT, 479 flow_id, 480 NULL); 481 if (rc) 482 BNXT_DRV_DBG(ERR, "Failed to destroy flow.\n"); 483 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 484 485 return rc; 486 } 487 488 static void 489 bnxt_ulp_destroy_group_rules(struct bnxt *bp, uint16_t port_id) 490 { 491 struct bnxt_ulp_grp_rule_info *info; 492 struct bnxt_ulp_grp_rule_info *grp_rules; 493 uint16_t idx; 494 495 grp_rules = bp->ulp_ctx->cfg_data->df_rule_info[port_id].grp_df_rule; 496 497 for (idx = 0; idx < BNXT_ULP_MAX_GROUP_CNT; idx++) { 498 info = &grp_rules[idx]; 499 if (!info->valid) 500 continue; 501 ulp_default_flow_destroy(bp->eth_dev, info->flow_id); 502 memset(info, 0, sizeof(struct bnxt_ulp_grp_rule_info)); 503 } 504 } 505 506 void 507 bnxt_ulp_destroy_df_rules(struct bnxt *bp, bool global) 508 { 509 struct bnxt_ulp_df_rule_info *info; 510 uint16_t port_id; 511 512 if (!BNXT_TRUFLOW_EN(bp) || 513 rte_eth_dev_is_repr(bp->eth_dev)) 514 return; 515 516 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 517 return; 518 519 /* Delete default rules per port */ 520 if (!global) { 521 port_id = bp->eth_dev->data->port_id; 522 info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id]; 523 if (!info->valid) 524 return; 525 526 /* Delete the group default rules */ 527 bnxt_ulp_destroy_group_rules(bp, port_id); 528 529 ulp_default_flow_destroy(bp->eth_dev, 530 info->def_port_flow_id); 531 if (info->promisc_flow_id) 532 ulp_default_flow_destroy(bp->eth_dev, 533 info->promisc_flow_id); 534 memset(info, 0, sizeof(struct bnxt_ulp_df_rule_info)); 535 return; 536 } 537 538 /* Delete default rules for all ports */ 539 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { 540 info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id]; 541 if (!info->valid) 542 continue; 543 544 /* Delete the group default rules */ 545 bnxt_ulp_destroy_group_rules(bp, port_id); 546 547 ulp_default_flow_destroy(bp->eth_dev, 548 info->def_port_flow_id); 549 if (info->promisc_flow_id) 550 ulp_default_flow_destroy(bp->eth_dev, 551 info->promisc_flow_id); 552 memset(info, 0, sizeof(struct bnxt_ulp_df_rule_info)); 553 } 554 } 555 556 static int32_t 557 bnxt_create_port_app_df_rule(struct bnxt *bp, uint8_t flow_type, 558 uint32_t *flow_id) 559 { 560 uint16_t port_id = bp->eth_dev->data->port_id; 561 struct ulp_tlv_param param_list[] = { 562 { 563 .type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID, 564 .length = 2, 565 .value = {(port_id >> 8) & 0xff, port_id & 0xff} 566 }, 567 { 568 .type = BNXT_ULP_DF_PARAM_TYPE_LAST, 569 .length = 0, 570 .value = {0} 571 } 572 }; 573 574 if (!flow_type) { 575 *flow_id = 0; 576 return 0; 577 } 578 return ulp_default_flow_create(bp->eth_dev, param_list, flow_type, 579 port_id, flow_id); 580 } 581 582 int32_t 583 bnxt_ulp_create_df_rules(struct bnxt *bp) 584 { 585 struct rte_eth_dev *dev = bp->eth_dev; 586 struct bnxt_ulp_df_rule_info *info; 587 uint16_t port_id; 588 int rc = 0; 589 590 if (!BNXT_TRUFLOW_EN(bp) || 591 rte_eth_dev_is_repr(bp->eth_dev) || !bp->ulp_ctx) 592 return 0; 593 594 port_id = bp->eth_dev->data->port_id; 595 info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id]; 596 rc = bnxt_create_port_app_df_rule(bp, 597 BNXT_ULP_DF_TPL_DEFAULT_UPLINK_PORT, 598 &info->def_port_flow_id); 599 if (rc) { 600 BNXT_DRV_DBG(ERR, 601 "Failed to create port to app default rule\n"); 602 return rc; 603 } 604 605 /* If the template already set the bd_action, skip this */ 606 if (!bp->tx_cfa_action) { 607 rc = ulp_default_flow_db_cfa_action_get(bp->ulp_ctx, 608 info->def_port_flow_id, 609 &bp->tx_cfa_action); 610 } 611 612 if (rc || BNXT_TESTPMD_EN(bp)) 613 bp->tx_cfa_action = 0; 614 615 /* set or reset the promiscuous rule */ 616 bnxt_ulp_promisc_mode_set(bp, dev->data->promiscuous); 617 618 info->valid = true; 619 return 0; 620 } 621 622 static int32_t 623 bnxt_create_port_vfr_default_rule(struct bnxt *bp, 624 uint8_t flow_type, 625 uint16_t vfr_port_id, 626 uint32_t *flow_id) 627 { 628 struct ulp_tlv_param param_list[] = { 629 { 630 .type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID, 631 .length = 2, 632 .value = {(vfr_port_id >> 8) & 0xff, vfr_port_id & 0xff} 633 }, 634 { 635 .type = BNXT_ULP_DF_PARAM_TYPE_LAST, 636 .length = 0, 637 .value = {0} 638 } 639 }; 640 return ulp_default_flow_create(bp->eth_dev, param_list, flow_type, 641 vfr_port_id, 642 flow_id); 643 } 644 645 int32_t 646 bnxt_ulp_create_vfr_default_rules(struct rte_eth_dev *vfr_ethdev) 647 { 648 struct bnxt_ulp_vfr_rule_info *info; 649 struct bnxt_representor *vfr = vfr_ethdev->data->dev_private; 650 struct rte_eth_dev *parent_dev = vfr->parent_dev; 651 struct bnxt *bp = parent_dev->data->dev_private; 652 uint16_t vfr_port_id = vfr_ethdev->data->port_id; 653 uint16_t port_id; 654 int rc; 655 656 if (!bp || !BNXT_TRUFLOW_EN(bp)) 657 return 0; 658 659 port_id = vfr_ethdev->data->port_id; 660 info = bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(bp->ulp_ctx, port_id); 661 662 if (!info) { 663 BNXT_DRV_DBG(ERR, "Failed to get vfr ulp context\n"); 664 return -EINVAL; 665 } 666 667 if (info->valid) { 668 BNXT_DRV_DBG(ERR, "VFR already allocated\n"); 669 return -EINVAL; 670 } 671 672 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info)); 673 rc = bnxt_create_port_vfr_default_rule(bp, BNXT_ULP_DF_TPL_DEFAULT_VFR, 674 vfr_port_id, 675 &info->vfr_flow_id); 676 if (rc) { 677 BNXT_DRV_DBG(ERR, "Failed to create VFR default rule\n"); 678 goto error; 679 } 680 681 /* If the template already set the bd action, skip this */ 682 if (!vfr->vfr_tx_cfa_action) { 683 rc = ulp_default_flow_db_cfa_action_get(bp->ulp_ctx, 684 info->vfr_flow_id, 685 &vfr->vfr_tx_cfa_action); 686 if (rc) { 687 BNXT_DRV_DBG(ERR, "Failed to get the tx cfa action\n"); 688 goto error; 689 } 690 } 691 692 /* Update the other details */ 693 info->valid = true; 694 info->parent_port_id = bp->eth_dev->data->port_id; 695 return 0; 696 697 error: 698 if (info->vfr_flow_id) 699 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id); 700 return rc; 701 } 702 703 int32_t 704 bnxt_ulp_delete_vfr_default_rules(struct bnxt_representor *vfr) 705 { 706 struct bnxt_ulp_vfr_rule_info *info; 707 struct rte_eth_dev *parent_dev = vfr->parent_dev; 708 struct bnxt *bp = parent_dev->data->dev_private; 709 710 if (!bp || !BNXT_TRUFLOW_EN(bp)) 711 return 0; 712 info = bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(bp->ulp_ctx, 713 vfr->dpdk_port_id); 714 if (!info) { 715 BNXT_DRV_DBG(ERR, "Failed to get vfr ulp context\n"); 716 return -EINVAL; 717 } 718 719 if (!info->valid) { 720 BNXT_DRV_DBG(ERR, "VFR already freed\n"); 721 return -EINVAL; 722 } 723 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id); 724 vfr->vfr_tx_cfa_action = 0; 725 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info)); 726 return 0; 727 } 728 729 static void 730 ulp_l2_custom_tunnel_id_update(struct bnxt *bp, 731 struct bnxt_ulp_mapper_parms *params) 732 { 733 if (!bp->l2_etype_tunnel_cnt) 734 return; 735 736 if (bp->l2_etype_upar_in_use & 737 HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR0) { 738 ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L2_CUSTOM_UPAR_ID, 739 ULP_WP_SYM_TUN_HDR_TYPE_UPAR1); 740 } else if (bp->l2_etype_upar_in_use & 741 HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR1) { 742 ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L2_CUSTOM_UPAR_ID, 743 ULP_WP_SYM_TUN_HDR_TYPE_UPAR2); 744 } 745 } 746 747 /* 748 * Function to execute a specific template, this does not create flow id 749 * 750 * bp [in] Ptr to bnxt 751 * param_list [in] Ptr to a list of parameters (Currently, only DPDK port_id). 752 * ulp_class_tid [in] Class template ID number. 753 * 754 * Returns 0 on success or negative number on failure. 755 */ 756 static int32_t 757 ulp_flow_template_process(struct bnxt *bp, 758 struct ulp_tlv_param *param_list, 759 uint32_t ulp_class_tid, 760 uint16_t port_id, 761 uint32_t flow_id) 762 { 763 struct ulp_rte_hdr_field hdr_field[BNXT_ULP_PROTO_HDR_MAX]; 764 uint64_t comp_fld[BNXT_ULP_CF_IDX_LAST]; 765 struct bnxt_ulp_mapper_parms mapper_params = { 0 }; 766 struct ulp_rte_act_prop act_prop; 767 struct ulp_rte_act_bitmap act = { 0 }; 768 struct bnxt_ulp_context *ulp_ctx; 769 uint32_t type; 770 int rc = 0; 771 772 memset(&mapper_params, 0, sizeof(mapper_params)); 773 memset(hdr_field, 0, sizeof(hdr_field)); 774 memset(comp_fld, 0, sizeof(comp_fld)); 775 memset(&act_prop, 0, sizeof(act_prop)); 776 777 mapper_params.hdr_field = hdr_field; 778 mapper_params.act_bitmap = &act; 779 mapper_params.act_prop = &act_prop; 780 mapper_params.comp_fld = comp_fld; 781 mapper_params.class_tid = ulp_class_tid; 782 mapper_params.port_id = port_id; 783 784 ulp_ctx = bp->ulp_ctx; 785 if (!ulp_ctx) { 786 BNXT_DRV_DBG(ERR, 787 "ULP is not init'ed. Fail to create dflt flow.\n"); 788 return -EINVAL; 789 } 790 791 type = param_list->type; 792 while (type != BNXT_ULP_DF_PARAM_TYPE_LAST) { 793 if (ulp_def_handler_tbl[type].vfr_func) { 794 rc = ulp_def_handler_tbl[type].vfr_func(ulp_ctx, 795 param_list, 796 &mapper_params); 797 if (rc) { 798 BNXT_DRV_DBG(ERR, 799 "Failed to create default flow\n"); 800 return rc; 801 } 802 } 803 804 param_list++; 805 type = param_list->type; 806 } 807 /* Protect flow creation */ 808 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 809 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 810 return -EINVAL; 811 } 812 813 mapper_params.flow_id = flow_id; 814 rc = ulp_mapper_flow_create(ulp_ctx, &mapper_params, 815 NULL); 816 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 817 return rc; 818 } 819 820 int32_t 821 bnxt_ulp_promisc_mode_set(struct bnxt *bp, uint8_t enable) 822 { 823 uint32_t flow_type; 824 struct bnxt_ulp_df_rule_info *info; 825 uint16_t port_id; 826 int rc = 0; 827 828 if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev) || 829 !bp->ulp_ctx) 830 return rc; 831 832 if (!BNXT_CHIP_P5(bp)) 833 return rc; 834 835 port_id = bp->eth_dev->data->port_id; 836 info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id]; 837 838 /* create the promiscuous rule */ 839 if (enable && !info->promisc_flow_id) { 840 flow_type = BNXT_ULP_TEMPLATE_PROMISCUOUS_ENABLE; 841 rc = bnxt_create_port_app_df_rule(bp, flow_type, 842 &info->promisc_flow_id); 843 BNXT_DRV_DBG(DEBUG, "enable ulp promisc mode on port %u:%u\n", 844 port_id, info->promisc_flow_id); 845 } else if (!enable && info->promisc_flow_id) { 846 struct ulp_tlv_param param_list[] = { 847 { 848 .type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID, 849 .length = 2, 850 .value = {(port_id >> 8) & 0xff, port_id & 0xff} 851 }, 852 { 853 .type = BNXT_ULP_DF_PARAM_TYPE_LAST, 854 .length = 0, 855 .value = {0} 856 } 857 }; 858 859 flow_type = BNXT_ULP_TEMPLATE_PROMISCUOUS_DISABLE; 860 if (ulp_flow_template_process(bp, param_list, flow_type, 861 port_id, 0)) 862 return -EIO; 863 864 rc = ulp_default_flow_destroy(bp->eth_dev, 865 info->promisc_flow_id); 866 BNXT_DRV_DBG(DEBUG, "disable ulp promisc mode on port %u:%u\n", 867 port_id, info->promisc_flow_id); 868 info->promisc_flow_id = 0; 869 } 870 return rc; 871 } 872 873 /* Function to create the rte flow for miss action. */ 874 int32_t 875 bnxt_ulp_grp_miss_act_set(struct rte_eth_dev *dev, 876 const struct rte_flow_attr *attr, 877 const struct rte_flow_action actions[], 878 uint32_t *flow_id) 879 { 880 struct bnxt_ulp_mapper_parms mparms = { 0 }; 881 struct ulp_rte_parser_params params; 882 struct bnxt_ulp_context *ulp_ctx; 883 int ret = BNXT_TF_RC_ERROR; 884 uint16_t func_id; 885 uint32_t fid; 886 uint32_t group_id; 887 888 ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev); 889 if (unlikely(!ulp_ctx)) { 890 BNXT_DRV_DBG(ERR, "ULP context is not initialized\n"); 891 goto flow_error; 892 } 893 894 /* Initialize the parser params */ 895 memset(¶ms, 0, sizeof(struct ulp_rte_parser_params)); 896 params.ulp_ctx = ulp_ctx; 897 params.port_id = dev->data->port_id; 898 /* classid is the group action template*/ 899 params.class_id = BNXT_ULP_TEMPLATE_GROUP_MISS_ACTION; 900 901 if (unlikely(bnxt_ulp_cntxt_app_id_get(params.ulp_ctx, ¶ms.app_id))) { 902 BNXT_DRV_DBG(ERR, "failed to get the app id\n"); 903 goto flow_error; 904 } 905 906 /* Set the flow attributes */ 907 bnxt_ulp_set_dir_attributes(¶ms, attr); 908 909 if (unlikely(bnxt_ulp_set_prio_attribute(¶ms, attr))) 910 goto flow_error; 911 912 bnxt_ulp_init_parser_cf_defaults(¶ms, params.port_id); 913 914 /* Get the function id */ 915 if (unlikely(ulp_port_db_port_func_id_get(ulp_ctx, 916 params.port_id, 917 &func_id))) { 918 BNXT_DRV_DBG(ERR, "conversion of port to func id failed\n"); 919 goto flow_error; 920 } 921 922 /* Protect flow creation */ 923 if (unlikely(bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx))) { 924 BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n"); 925 goto flow_error; 926 } 927 928 /* Allocate a Flow ID for attaching all resources for the flow to. 929 * Once allocated, all errors have to walk the list of resources and 930 * free each of them. 931 */ 932 ret = ulp_flow_db_fid_alloc(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT, 933 func_id, &fid); 934 if (unlikely(ret)) { 935 BNXT_DRV_DBG(ERR, "Unable to allocate flow table entry\n"); 936 goto release_lock; 937 } 938 939 /* Update the implied SVIF */ 940 ulp_rte_parser_implicit_match_port_process(¶ms); 941 942 /* Parse the rte flow action */ 943 ret = bnxt_ulp_rte_parser_act_parse(actions, ¶ms); 944 if (unlikely(ret != BNXT_TF_RC_SUCCESS)) 945 goto free_fid; 946 947 /* Verify the jump target group id */ 948 if (ULP_BITMAP_ISSET(params.act_bitmap.bits, BNXT_ULP_ACT_BIT_JUMP)) { 949 memcpy(&group_id, 950 ¶ms.act_prop.act_details[BNXT_ULP_ACT_PROP_IDX_JUMP], 951 BNXT_ULP_ACT_PROP_SZ_JUMP); 952 if (rte_cpu_to_be_32(group_id) == attr->group) { 953 BNXT_DRV_DBG(ERR, "Jump action cannot jump to its own group.\n"); 954 ret = BNXT_TF_RC_ERROR; 955 goto free_fid; 956 } 957 } 958 959 mparms.flow_id = fid; 960 mparms.func_id = func_id; 961 mparms.port_id = params.port_id; 962 963 /* Perform the rte flow post process */ 964 bnxt_ulp_rte_parser_post_process(¶ms); 965 966 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 967 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_PARSER 968 /* Dump the rte flow action */ 969 ulp_parser_act_info_dump(¶ms); 970 #endif 971 #endif 972 973 ret = ulp_matcher_action_match(¶ms, ¶ms.act_tmpl); 974 if (unlikely(ret != BNXT_TF_RC_SUCCESS)) 975 goto free_fid; 976 977 bnxt_ulp_init_mapper_params(&mparms, ¶ms, 978 BNXT_ULP_FDB_TYPE_DEFAULT); 979 /* Call the ulp mapper to create the flow in the hardware. */ 980 ret = ulp_mapper_flow_create(ulp_ctx, &mparms, NULL); 981 if (unlikely(ret)) 982 goto free_fid; 983 984 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 985 986 *flow_id = fid; 987 return 0; 988 989 free_fid: 990 ulp_flow_db_fid_free(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT, fid); 991 release_lock: 992 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 993 flow_error: 994 return ret; 995 } 996