1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_malloc.h> 7 #include "bnxt.h" 8 #include "bnxt_tf_common.h" 9 #include "ulp_utils.h" 10 #include "ulp_template_struct.h" 11 #include "ulp_mapper.h" 12 #include "ulp_flow_db.h" 13 #include "ulp_fc_mgr.h" 14 #include "ulp_tun.h" 15 16 #define ULP_FLOW_DB_RES_DIR_BIT 31 17 #define ULP_FLOW_DB_RES_DIR_MASK 0x80000000 18 #define ULP_FLOW_DB_RES_FUNC_BITS 28 19 #define ULP_FLOW_DB_RES_FUNC_MASK 0x70000000 20 #define ULP_FLOW_DB_RES_NXT_MASK 0x0FFFFFFF 21 #define ULP_FLOW_DB_RES_FUNC_UPPER 5 22 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80 23 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F 24 25 /* Macro to copy the nxt_resource_idx */ 26 #define ULP_FLOW_DB_RES_NXT_SET(dst, src) {(dst) |= ((src) &\ 27 ULP_FLOW_DB_RES_NXT_MASK); } 28 #define ULP_FLOW_DB_RES_NXT_RESET(dst) ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK)) 29 30 /* 31 * Helper function to set the bit in the active flows 32 * No validation is done in this function. 33 * 34 * flow_db [in] Ptr to flow database 35 * flow_type [in] - specify default or regular 36 * idx [in] The index to bit to be set or reset. 37 * flag [in] 1 to set and 0 to reset. 38 * 39 * returns none 40 */ 41 static void 42 ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db, 43 enum bnxt_ulp_fdb_type flow_type, 44 uint32_t idx, 45 uint32_t flag) 46 { 47 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl; 48 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE; 49 50 if (flag) { 51 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type == 52 BNXT_ULP_FDB_TYPE_RID) 53 ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx], 54 idx); 55 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type == 56 BNXT_ULP_FDB_TYPE_RID) 57 ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx], 58 idx); 59 } else { 60 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type == 61 BNXT_ULP_FDB_TYPE_RID) 62 ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx], 63 idx); 64 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type == 65 BNXT_ULP_FDB_TYPE_RID) 66 ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx], 67 idx); 68 } 69 } 70 71 /* 72 * Helper function to check if given fid is active flow. 73 * No validation being done in this function. 74 * 75 * flow_db [in] Ptr to flow database 76 * flow_type [in] - specify default or regular 77 * idx [in] The index to bit to be set or reset. 78 * 79 * returns 1 on set or 0 if not set. 80 */ 81 static int32_t 82 ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db, 83 enum bnxt_ulp_fdb_type flow_type, 84 uint32_t idx) 85 { 86 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl; 87 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE; 88 uint32_t reg, dflt; 89 90 reg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx); 91 dflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx); 92 93 switch (flow_type) { 94 case BNXT_ULP_FDB_TYPE_REGULAR: 95 return (reg && !dflt); 96 case BNXT_ULP_FDB_TYPE_DEFAULT: 97 return (!reg && dflt); 98 case BNXT_ULP_FDB_TYPE_RID: 99 return (reg && dflt); 100 default: 101 return 0; 102 } 103 } 104 105 static inline enum tf_dir 106 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info) 107 { 108 return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >> 109 ULP_FLOW_DB_RES_DIR_BIT); 110 } 111 112 static uint8_t 113 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info) 114 { 115 uint8_t func; 116 117 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >> 118 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER); 119 /* The resource func is split into upper and lower */ 120 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) 121 return (func | res_info->resource_func_lower); 122 return func; 123 } 124 125 /* 126 * Helper function to copy the resource params to resource info 127 * No validation being done in this function. 128 * 129 * resource_info [out] Ptr to resource information 130 * params [in] The input params from the caller 131 * returns none 132 */ 133 static void 134 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info, 135 struct ulp_flow_db_res_params *params) 136 { 137 uint32_t resource_func; 138 139 resource_info->nxt_resource_idx |= ((params->direction << 140 ULP_FLOW_DB_RES_DIR_BIT) & 141 ULP_FLOW_DB_RES_DIR_MASK); 142 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER); 143 resource_info->nxt_resource_idx |= ((resource_func << 144 ULP_FLOW_DB_RES_FUNC_BITS) & 145 ULP_FLOW_DB_RES_FUNC_MASK); 146 147 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) { 148 /* Break the resource func into two parts */ 149 resource_func = (params->resource_func & 150 ULP_FLOW_DB_RES_FUNC_LOWER_MASK); 151 resource_info->resource_func_lower = resource_func; 152 } 153 154 /* Store the handle as 64bit only for EM table entries */ 155 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) { 156 resource_info->resource_hndl = (uint32_t)params->resource_hndl; 157 resource_info->resource_type = params->resource_type; 158 resource_info->resource_sub_type = params->resource_sub_type; 159 resource_info->fdb_flags = params->fdb_flags; 160 } else { 161 resource_info->resource_em_handle = params->resource_hndl; 162 } 163 } 164 165 /* 166 * Helper function to copy the resource params to resource info 167 * No validation being done in this function. 168 * 169 * resource_info [in] Ptr to resource information 170 * params [out] The output params to the caller 171 * 172 * returns none 173 */ 174 static void 175 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info, 176 struct ulp_flow_db_res_params *params) 177 { 178 memset(params, 0, sizeof(struct ulp_flow_db_res_params)); 179 180 /* use the helper function to get the resource func */ 181 params->direction = ulp_flow_db_resource_dir_get(resource_info); 182 params->resource_func = ulp_flow_db_resource_func_get(resource_info); 183 184 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE) { 185 params->resource_hndl = resource_info->resource_em_handle; 186 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) { 187 params->resource_hndl = resource_info->resource_hndl; 188 params->resource_type = resource_info->resource_type; 189 params->resource_sub_type = resource_info->resource_sub_type; 190 params->fdb_flags = resource_info->fdb_flags; 191 } 192 } 193 194 /* 195 * Helper function to allocate the flow table and initialize 196 * the stack for allocation operations. 197 * 198 * flow_db [in] Ptr to flow database structure 199 * 200 * Returns 0 on success or negative number on failure. 201 */ 202 static int32_t 203 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db) 204 { 205 uint32_t idx = 0; 206 struct bnxt_ulp_flow_tbl *flow_tbl; 207 uint32_t size; 208 209 flow_tbl = &flow_db->flow_tbl; 210 211 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources; 212 flow_tbl->flow_resources = 213 rte_zmalloc("ulp_fdb_resource_info", size, 0); 214 215 if (!flow_tbl->flow_resources) { 216 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n"); 217 return -ENOMEM; 218 } 219 size = sizeof(uint32_t) * flow_tbl->num_resources; 220 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0); 221 if (!flow_tbl->flow_tbl_stack) { 222 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n"); 223 return -ENOMEM; 224 } 225 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1; 226 size = ULP_BYTE_ROUND_OFF_8(size); 227 flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size, 228 ULP_BUFFER_ALIGN_64_BYTE); 229 if (!flow_tbl->active_reg_flows) { 230 BNXT_TF_DBG(ERR, "Failed to alloc memory active reg flows\n"); 231 return -ENOMEM; 232 } 233 234 flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size, 235 ULP_BUFFER_ALIGN_64_BYTE); 236 if (!flow_tbl->active_dflt_flows) { 237 BNXT_TF_DBG(ERR, "Failed to alloc memory active dflt flows\n"); 238 return -ENOMEM; 239 } 240 241 /* Initialize the stack table. */ 242 for (idx = 0; idx < flow_tbl->num_resources; idx++) 243 flow_tbl->flow_tbl_stack[idx] = idx; 244 245 /* Ignore the first element in the list. */ 246 flow_tbl->head_index = 1; 247 /* Tail points to the last entry in the list. */ 248 flow_tbl->tail_index = flow_tbl->num_resources - 1; 249 return 0; 250 } 251 252 /* 253 * Helper function to deallocate the flow table. 254 * 255 * flow_db [in] Ptr to flow database structure 256 * 257 * Returns none. 258 */ 259 static void 260 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db) 261 { 262 struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl; 263 264 /* Free all the allocated tables in the flow table. */ 265 if (flow_tbl->active_reg_flows) { 266 rte_free(flow_tbl->active_reg_flows); 267 flow_tbl->active_reg_flows = NULL; 268 } 269 if (flow_tbl->active_dflt_flows) { 270 rte_free(flow_tbl->active_dflt_flows); 271 flow_tbl->active_dflt_flows = NULL; 272 } 273 274 if (flow_tbl->flow_tbl_stack) { 275 rte_free(flow_tbl->flow_tbl_stack); 276 flow_tbl->flow_tbl_stack = NULL; 277 } 278 279 if (flow_tbl->flow_resources) { 280 rte_free(flow_tbl->flow_resources); 281 flow_tbl->flow_resources = NULL; 282 } 283 } 284 285 /* 286 * Helper function to add function id to the flow table 287 * 288 * flow_db [in] Ptr to flow table 289 * flow_id [in] The flow id of the flow 290 * func_id [in] The func_id to be set, for reset pass zero 291 * 292 * returns none 293 */ 294 static void 295 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db, 296 uint32_t flow_id, 297 uint32_t func_id) 298 { 299 /* set the function id in the function table */ 300 if (flow_id < flow_db->func_id_tbl_size) 301 flow_db->func_id_tbl[flow_id] = func_id; 302 else /* This should never happen */ 303 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n"); 304 } 305 306 /* 307 * Initialize the parent-child database. Memory is allocated in this 308 * call and assigned to the database 309 * 310 * flow_db [in] Ptr to flow table 311 * num_entries[in] - number of entries to allocate 312 * 313 * Returns 0 on success or negative number on failure. 314 */ 315 static int32_t 316 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db, 317 uint32_t num_entries) 318 { 319 struct ulp_fdb_parent_child_db *p_db; 320 uint32_t size, idx; 321 322 if (!num_entries) 323 return 0; 324 325 /* update the sizes for the allocation */ 326 p_db = &flow_db->parent_child_db; 327 p_db->child_bitset_size = (flow_db->flow_tbl.num_flows / 328 sizeof(uint64_t)) + 1; /* size in bytes */ 329 p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size); 330 p_db->entries_count = num_entries; 331 332 /* allocate the memory */ 333 p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl", 334 sizeof(struct ulp_fdb_parent_info) * 335 p_db->entries_count, 0); 336 if (!p_db->parent_flow_tbl) { 337 BNXT_TF_DBG(ERR, 338 "Failed to allocate memory fdb parent flow tbl\n"); 339 return -ENOMEM; 340 } 341 size = p_db->child_bitset_size * p_db->entries_count; 342 343 /* 344 * allocate the big chunk of memory to be statically carved into 345 * child_fid_bitset pointer. 346 */ 347 p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem", 348 size, 349 ULP_BUFFER_ALIGN_64_BYTE); 350 if (!p_db->parent_flow_tbl_mem) { 351 BNXT_TF_DBG(ERR, 352 "Failed to allocate memory fdb parent flow mem\n"); 353 return -ENOMEM; 354 } 355 356 /* set the pointers in parent table to their offsets */ 357 for (idx = 0 ; idx < p_db->entries_count; idx++) { 358 p_db->parent_flow_tbl[idx].child_fid_bitset = 359 (uint64_t *)&p_db->parent_flow_tbl_mem[idx * 360 p_db->child_bitset_size]; 361 } 362 /* success */ 363 return 0; 364 } 365 366 /* 367 * Deinitialize the parent-child database. Memory is deallocated in 368 * this call and all flows should have been purged before this 369 * call. 370 * 371 * flow_db [in] Ptr to flow table 372 * 373 * Returns none 374 */ 375 static void 376 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db) 377 { 378 /* free the memory related to parent child database */ 379 if (flow_db->parent_child_db.parent_flow_tbl_mem) { 380 rte_free(flow_db->parent_child_db.parent_flow_tbl_mem); 381 flow_db->parent_child_db.parent_flow_tbl_mem = NULL; 382 } 383 if (flow_db->parent_child_db.parent_flow_tbl) { 384 rte_free(flow_db->parent_child_db.parent_flow_tbl); 385 flow_db->parent_child_db.parent_flow_tbl = NULL; 386 } 387 } 388 389 /* internal validation function for parent flow tbl */ 390 static struct bnxt_ulp_flow_db * 391 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt, 392 uint32_t fid) 393 { 394 struct bnxt_ulp_flow_db *flow_db; 395 396 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 397 if (!flow_db) { 398 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 399 return NULL; 400 } 401 402 /* check for max flows */ 403 if (fid >= flow_db->flow_tbl.num_flows || !fid) { 404 BNXT_TF_DBG(ERR, "Invalid flow index\n"); 405 return NULL; 406 } 407 408 /* No support for parent child db then just exit */ 409 if (!flow_db->parent_child_db.entries_count) { 410 BNXT_TF_DBG(ERR, "parent child db not supported\n"); 411 return NULL; 412 } 413 414 return flow_db; 415 } 416 417 /* 418 * Set the tunnel index in the parent flow 419 * 420 * ulp_ctxt [in] Ptr to ulp_context 421 * parent_idx [in] The parent index of the parent flow entry 422 * 423 * returns index on success and negative on failure. 424 */ 425 static int32_t 426 ulp_flow_db_parent_tun_idx_set(struct bnxt_ulp_context *ulp_ctxt, 427 uint32_t parent_idx, uint8_t tun_idx) 428 { 429 struct bnxt_ulp_flow_db *flow_db; 430 struct ulp_fdb_parent_child_db *p_pdb; 431 432 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 433 if (!flow_db) { 434 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 435 return -EINVAL; 436 } 437 438 /* check for parent idx validity */ 439 p_pdb = &flow_db->parent_child_db; 440 if (parent_idx >= p_pdb->entries_count || 441 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) { 442 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx); 443 return -EINVAL; 444 } 445 446 p_pdb->parent_flow_tbl[parent_idx].tun_idx = tun_idx; 447 return 0; 448 } 449 450 /* 451 * Get the tunnel index from the parent flow 452 * 453 * ulp_ctxt [in] Ptr to ulp_context 454 * parent_fid [in] The flow id of the parent flow entry 455 * 456 * returns 0 if counter accum is set else -1. 457 */ 458 static int32_t 459 ulp_flow_db_parent_tun_idx_get(struct bnxt_ulp_context *ulp_ctxt, 460 uint32_t parent_fid, uint8_t *tun_idx) 461 { 462 struct bnxt_ulp_flow_db *flow_db; 463 struct ulp_fdb_parent_child_db *p_pdb; 464 uint32_t idx; 465 466 /* validate the arguments */ 467 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 468 if (!flow_db) { 469 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 470 return -EINVAL; 471 } 472 473 p_pdb = &flow_db->parent_child_db; 474 for (idx = 0; idx < p_pdb->entries_count; idx++) { 475 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 476 *tun_idx = p_pdb->parent_flow_tbl[idx].tun_idx; 477 return 0; 478 } 479 } 480 481 return -EINVAL; 482 } 483 484 /* 485 * Initialize the flow database. Memory is allocated in this 486 * call and assigned to the flow database. 487 * 488 * ulp_ctxt [in] Ptr to ulp context 489 * 490 * Returns 0 on success or negative number on failure. 491 */ 492 int32_t 493 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt) 494 { 495 struct bnxt_ulp_device_params *dparms; 496 struct bnxt_ulp_flow_tbl *flow_tbl; 497 struct bnxt_ulp_flow_db *flow_db; 498 uint32_t dev_id, num_flows; 499 enum bnxt_ulp_flow_mem_type mtype; 500 501 /* Get the dev specific number of flows that needed to be supported. */ 502 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) { 503 BNXT_TF_DBG(ERR, "Invalid device id\n"); 504 return -EINVAL; 505 } 506 507 dparms = bnxt_ulp_device_params_get(dev_id); 508 if (!dparms) { 509 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 510 return -ENODEV; 511 } 512 513 flow_db = rte_zmalloc("bnxt_ulp_flow_db", 514 sizeof(struct bnxt_ulp_flow_db), 0); 515 if (!flow_db) { 516 BNXT_TF_DBG(ERR, 517 "Failed to allocate memory for flow table ptr\n"); 518 return -ENOMEM; 519 } 520 521 /* Attach the flow database to the ulp context. */ 522 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db); 523 524 /* Determine the number of flows based on EM type */ 525 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype)) 526 goto error_free; 527 528 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) 529 num_flows = dparms->int_flow_db_num_entries; 530 else 531 num_flows = dparms->ext_flow_db_num_entries; 532 533 /* Populate the regular flow table limits. */ 534 flow_tbl = &flow_db->flow_tbl; 535 flow_tbl->num_flows = num_flows + 1; 536 flow_tbl->num_resources = ((num_flows + 1) * 537 dparms->num_resources_per_flow); 538 539 /* Include the default flow table limits. */ 540 flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1); 541 flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) * 542 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES); 543 544 /* Allocate the resource for the flow table. */ 545 if (ulp_flow_db_alloc_resource(flow_db)) 546 goto error_free; 547 548 /* add 1 since we are not using index 0 for flow id */ 549 flow_db->func_id_tbl_size = flow_tbl->num_flows + 1; 550 /* Allocate the function Id table */ 551 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table", 552 flow_db->func_id_tbl_size * 553 sizeof(uint16_t), 0); 554 if (!flow_db->func_id_tbl) { 555 BNXT_TF_DBG(ERR, 556 "Failed to allocate mem for flow table func id\n"); 557 goto error_free; 558 } 559 /* initialize the parent child database */ 560 if (ulp_flow_db_parent_tbl_init(flow_db, 561 dparms->fdb_parent_flow_entries)) { 562 BNXT_TF_DBG(ERR, 563 "Failed to allocate mem for parent child db\n"); 564 goto error_free; 565 } 566 567 /* All good so return. */ 568 BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n", 569 flow_tbl->num_flows); 570 return 0; 571 error_free: 572 ulp_flow_db_deinit(ulp_ctxt); 573 return -ENOMEM; 574 } 575 576 /* 577 * Deinitialize the flow database. Memory is deallocated in 578 * this call and all flows should have been purged before this 579 * call. 580 * 581 * ulp_ctxt [in] Ptr to ulp context 582 * 583 * Returns 0 on success. 584 */ 585 int32_t 586 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt) 587 { 588 struct bnxt_ulp_flow_db *flow_db; 589 590 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 591 if (!flow_db) 592 return -EINVAL; 593 594 /* Detach the flow database from the ulp context. */ 595 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL); 596 597 /* Free up all the memory. */ 598 ulp_flow_db_parent_tbl_deinit(flow_db); 599 ulp_flow_db_dealloc_resource(flow_db); 600 rte_free(flow_db->func_id_tbl); 601 rte_free(flow_db); 602 603 return 0; 604 } 605 606 /* 607 * Allocate the flow database entry 608 * 609 * ulp_ctxt [in] Ptr to ulp_context 610 * flow_type [in] - specify default or regular 611 * func_id [in].function id of the ingress port 612 * fid [out] The index to the flow entry 613 * 614 * returns 0 on success and negative on failure. 615 */ 616 int32_t 617 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt, 618 enum bnxt_ulp_fdb_type flow_type, 619 uint16_t func_id, 620 uint32_t *fid) 621 { 622 struct bnxt_ulp_flow_db *flow_db; 623 struct bnxt_ulp_flow_tbl *flow_tbl; 624 625 *fid = 0; /* Initialize fid to invalid value */ 626 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 627 if (!flow_db) { 628 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 629 return -EINVAL; 630 } 631 632 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 633 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 634 return -EINVAL; 635 } 636 637 flow_tbl = &flow_db->flow_tbl; 638 /* check for max flows */ 639 if (flow_tbl->num_flows <= flow_tbl->head_index) { 640 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n"); 641 return -ENOMEM; 642 } 643 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) { 644 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n"); 645 return -ENOMEM; 646 } 647 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index]; 648 flow_tbl->head_index++; 649 650 /* Set the flow type */ 651 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1); 652 653 /* function id update is only valid for regular flow table */ 654 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) 655 ulp_flow_db_func_id_set(flow_db, *fid, func_id); 656 657 /* return success */ 658 return 0; 659 } 660 661 /* 662 * Allocate the flow database entry. 663 * The params->critical_resource has to be set to 0 to allocate a new resource. 664 * 665 * ulp_ctxt [in] Ptr to ulp_context 666 * flow_type [in] Specify it is regular or default flow 667 * fid [in] The index to the flow entry 668 * params [in] The contents to be copied into resource 669 * 670 * returns 0 on success and negative on failure. 671 */ 672 int32_t 673 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt, 674 enum bnxt_ulp_fdb_type flow_type, 675 uint32_t fid, 676 struct ulp_flow_db_res_params *params) 677 { 678 struct bnxt_ulp_flow_db *flow_db; 679 struct bnxt_ulp_flow_tbl *flow_tbl; 680 struct ulp_fdb_resource_info *resource, *fid_resource; 681 struct bnxt_ulp_fc_info *ulp_fc_info; 682 uint32_t idx; 683 684 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 685 if (!flow_db) { 686 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 687 return -EINVAL; 688 } 689 690 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 691 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 692 return -EINVAL; 693 } 694 695 flow_tbl = &flow_db->flow_tbl; 696 /* check for max flows */ 697 if (fid >= flow_tbl->num_flows || !fid) { 698 BNXT_TF_DBG(ERR, "Invalid flow index\n"); 699 return -EINVAL; 700 } 701 702 /* check if the flow is active or not */ 703 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 704 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid); 705 return -EINVAL; 706 } 707 708 /* check for max resource */ 709 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) { 710 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n"); 711 return -ENOMEM; 712 } 713 fid_resource = &flow_tbl->flow_resources[fid]; 714 715 if (params->critical_resource && fid_resource->resource_em_handle) { 716 BNXT_TF_DBG(DEBUG, "Ignore multiple critical resources\n"); 717 /* Ignore the multiple critical resources */ 718 params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 719 } 720 721 if (!params->critical_resource) { 722 /* Not the critical_resource so allocate a resource */ 723 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index]; 724 resource = &flow_tbl->flow_resources[idx]; 725 flow_tbl->tail_index--; 726 727 /* Update the chain list of resource*/ 728 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx, 729 fid_resource->nxt_resource_idx); 730 /* update the contents */ 731 ulp_flow_db_res_params_to_info(resource, params); 732 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx); 733 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 734 idx); 735 } else { 736 /* critical resource. Just update the fid resource */ 737 ulp_flow_db_res_params_to_info(fid_resource, params); 738 } 739 740 ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt); 741 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 && 742 params->resource_sub_type == 743 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT && 744 ulp_fc_info && ulp_fc_info->num_counters) { 745 /* Store the first HW counter ID for this table */ 746 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction)) 747 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction, 748 params->resource_hndl); 749 750 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction, 751 params->resource_hndl); 752 753 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt)) 754 ulp_fc_mgr_thread_start(ulp_ctxt); 755 } 756 757 /* all good, return success */ 758 return 0; 759 } 760 761 /* 762 * Free the flow database entry. 763 * The params->critical_resource has to be set to 1 to free the first resource. 764 * 765 * ulp_ctxt [in] Ptr to ulp_context 766 * flow_type [in] Specify it is regular or default flow 767 * fid [in] The index to the flow entry 768 * params [in/out] The contents to be copied into params. 769 * Only the critical_resource needs to be set by the caller. 770 * 771 * Returns 0 on success and negative on failure. 772 */ 773 int32_t 774 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt, 775 enum bnxt_ulp_fdb_type flow_type, 776 uint32_t fid, 777 struct ulp_flow_db_res_params *params) 778 { 779 struct bnxt_ulp_flow_db *flow_db; 780 struct bnxt_ulp_flow_tbl *flow_tbl; 781 struct ulp_fdb_resource_info *nxt_resource, *fid_resource; 782 uint32_t nxt_idx = 0; 783 struct bnxt_tun_cache_entry *tun_tbl; 784 uint8_t tun_idx = 0; 785 int rc; 786 787 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 788 if (!flow_db) { 789 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 790 return -EINVAL; 791 } 792 793 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 794 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 795 return -EINVAL; 796 } 797 798 flow_tbl = &flow_db->flow_tbl; 799 /* check for max flows */ 800 if (fid >= flow_tbl->num_flows || !fid) { 801 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid); 802 return -EINVAL; 803 } 804 805 /* check if the flow is active or not */ 806 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 807 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid); 808 return -EINVAL; 809 } 810 811 fid_resource = &flow_tbl->flow_resources[fid]; 812 if (!params->critical_resource) { 813 /* Not the critical resource so free the resource */ 814 ULP_FLOW_DB_RES_NXT_SET(nxt_idx, 815 fid_resource->nxt_resource_idx); 816 if (!nxt_idx) { 817 /* reached end of resources */ 818 return -ENOENT; 819 } 820 nxt_resource = &flow_tbl->flow_resources[nxt_idx]; 821 822 /* connect the fid resource to the next resource */ 823 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx); 824 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 825 nxt_resource->nxt_resource_idx); 826 827 /* update the contents to be given to caller */ 828 ulp_flow_db_res_info_to_params(nxt_resource, params); 829 830 /* Delete the nxt_resource */ 831 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info)); 832 833 /* add it to the free list */ 834 flow_tbl->tail_index++; 835 if (flow_tbl->tail_index >= flow_tbl->num_resources) { 836 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n"); 837 return -ENOENT; 838 } 839 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx; 840 841 } else { 842 /* Critical resource. copy the contents and exit */ 843 ulp_flow_db_res_info_to_params(fid_resource, params); 844 ULP_FLOW_DB_RES_NXT_SET(nxt_idx, 845 fid_resource->nxt_resource_idx); 846 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info)); 847 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx, 848 nxt_idx); 849 } 850 851 /* Now that the HW Flow counter resource is deleted, reset it's 852 * corresponding slot in the SW accumulation table in the Flow Counter 853 * manager 854 */ 855 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 && 856 params->resource_sub_type == 857 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) { 858 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction, 859 params->resource_hndl); 860 } 861 862 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW) { 863 tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt); 864 if (!tun_tbl) 865 return -EINVAL; 866 867 rc = ulp_flow_db_parent_tun_idx_get(ulp_ctxt, fid, &tun_idx); 868 if (rc) 869 return rc; 870 871 ulp_clear_tun_entry(tun_tbl, tun_idx); 872 } 873 874 /* all good, return success */ 875 return 0; 876 } 877 878 /* 879 * Free the flow database entry 880 * 881 * ulp_ctxt [in] Ptr to ulp_context 882 * flow_type [in] - specify default or regular 883 * fid [in] The index to the flow entry 884 * 885 * returns 0 on success and negative on failure. 886 */ 887 int32_t 888 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt, 889 enum bnxt_ulp_fdb_type flow_type, 890 uint32_t fid) 891 { 892 struct bnxt_tun_cache_entry *tun_tbl; 893 struct bnxt_ulp_flow_tbl *flow_tbl; 894 struct bnxt_ulp_flow_db *flow_db; 895 896 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 897 if (!flow_db) { 898 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 899 return -EINVAL; 900 } 901 902 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 903 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 904 return -EINVAL; 905 } 906 907 flow_tbl = &flow_db->flow_tbl; 908 909 /* check for limits of fid */ 910 if (fid >= flow_tbl->num_flows || !fid) { 911 BNXT_TF_DBG(ERR, "Invalid flow index\n"); 912 return -EINVAL; 913 } 914 915 /* check if the flow is active or not */ 916 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 917 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid); 918 return -EINVAL; 919 } 920 flow_tbl->head_index--; 921 if (!flow_tbl->head_index) { 922 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n"); 923 return -ENOENT; 924 } 925 926 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid; 927 928 /* Clear the flows bitmap */ 929 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0); 930 931 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) 932 ulp_flow_db_func_id_set(flow_db, fid, 0); 933 934 tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt); 935 if (!tun_tbl) 936 return -EINVAL; 937 938 ulp_clear_tun_inner_entry(tun_tbl, fid); 939 940 /* all good, return success */ 941 return 0; 942 } 943 944 /* 945 *Get the flow database entry details 946 * 947 * ulp_ctxt [in] Ptr to ulp_context 948 * flow_type [in] - specify default or regular 949 * fid [in] The index to the flow entry 950 * nxt_idx [in/out] the index to the next entry 951 * params [out] The contents to be copied into params. 952 * 953 * returns 0 on success and negative on failure. 954 */ 955 int32_t 956 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt, 957 enum bnxt_ulp_fdb_type flow_type, 958 uint32_t fid, 959 uint32_t *nxt_idx, 960 struct ulp_flow_db_res_params *params) 961 { 962 struct bnxt_ulp_flow_db *flow_db; 963 struct bnxt_ulp_flow_tbl *flow_tbl; 964 struct ulp_fdb_resource_info *nxt_resource, *fid_resource; 965 966 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 967 if (!flow_db) { 968 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 969 return -EINVAL; 970 } 971 972 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 973 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 974 return -EINVAL; 975 } 976 977 flow_tbl = &flow_db->flow_tbl; 978 979 /* check for limits of fid */ 980 if (fid >= flow_tbl->num_flows || !fid) { 981 BNXT_TF_DBG(ERR, "Invalid flow index\n"); 982 return -EINVAL; 983 } 984 985 /* check if the flow is active or not */ 986 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 987 BNXT_TF_DBG(ERR, "flow does not exist\n"); 988 return -EINVAL; 989 } 990 991 if (!*nxt_idx) { 992 fid_resource = &flow_tbl->flow_resources[fid]; 993 ulp_flow_db_res_info_to_params(fid_resource, params); 994 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx, 995 fid_resource->nxt_resource_idx); 996 } else { 997 nxt_resource = &flow_tbl->flow_resources[*nxt_idx]; 998 ulp_flow_db_res_info_to_params(nxt_resource, params); 999 *nxt_idx = 0; 1000 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx, 1001 nxt_resource->nxt_resource_idx); 1002 } 1003 1004 /* all good, return success */ 1005 return 0; 1006 } 1007 1008 /* 1009 * Get the flow database entry iteratively 1010 * 1011 * flow_tbl [in] Ptr to flow table 1012 * flow_type [in] - specify default or regular 1013 * fid [in/out] The index to the flow entry 1014 * 1015 * returns 0 on success and negative on failure. 1016 */ 1017 static int32_t 1018 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db, 1019 enum bnxt_ulp_fdb_type flow_type, 1020 uint32_t *fid) 1021 { 1022 uint32_t lfid = *fid; 1023 uint32_t idx, s_idx, mod_fid; 1024 uint64_t bs; 1025 uint64_t *active_flows; 1026 struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl; 1027 1028 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) { 1029 active_flows = flowtbl->active_reg_flows; 1030 } else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) { 1031 active_flows = flowtbl->active_dflt_flows; 1032 } else { 1033 BNXT_TF_DBG(ERR, "Invalid flow type %x\n", flow_type); 1034 return -EINVAL; 1035 } 1036 1037 do { 1038 /* increment the flow id to find the next valid flow id */ 1039 lfid++; 1040 if (lfid >= flowtbl->num_flows) 1041 return -ENOENT; 1042 idx = lfid / ULP_INDEX_BITMAP_SIZE; 1043 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE; 1044 s_idx = idx; 1045 while (!(bs = active_flows[idx])) { 1046 idx++; 1047 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows) 1048 return -ENOENT; 1049 } 1050 /* 1051 * remove the previous bits in the bitset bs to find the 1052 * next non zero bit in the bitset. This needs to be done 1053 * only if the idx is same as he one you started. 1054 */ 1055 if (s_idx == idx) 1056 bs &= (-1UL >> mod_fid); 1057 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs); 1058 if (*fid >= lfid) { 1059 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n"); 1060 return -ENOENT; 1061 } 1062 } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, 1063 lfid)); 1064 1065 /* all good, return success */ 1066 *fid = lfid; 1067 return 0; 1068 } 1069 1070 /* 1071 * Flush all flows in the flow database. 1072 * 1073 * ulp_ctxt [in] Ptr to ulp context 1074 * flow_type [in] - specify default or regular 1075 * 1076 * returns 0 on success or negative number on failure 1077 */ 1078 int32_t 1079 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx, 1080 enum bnxt_ulp_fdb_type flow_type) 1081 { 1082 uint32_t fid = 0; 1083 struct bnxt_ulp_flow_db *flow_db; 1084 1085 if (!ulp_ctx) { 1086 BNXT_TF_DBG(ERR, "Invalid Argument\n"); 1087 return -EINVAL; 1088 } 1089 1090 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1091 if (!flow_db) { 1092 BNXT_TF_DBG(ERR, "Flow database not found\n"); 1093 return -EINVAL; 1094 } 1095 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 1096 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n"); 1097 return -EINVAL; 1098 } 1099 1100 while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid)) 1101 ulp_mapper_resources_free(ulp_ctx, flow_type, fid); 1102 1103 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 1104 1105 return 0; 1106 } 1107 1108 /* 1109 * Flush all flows in the flow database that belong to a device function. 1110 * 1111 * ulp_ctxt [in] Ptr to ulp context 1112 * func_id [in] - The port function id 1113 * 1114 * returns 0 on success or negative number on failure 1115 */ 1116 int32_t 1117 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx, 1118 uint16_t func_id) 1119 { 1120 uint32_t flow_id = 0; 1121 struct bnxt_ulp_flow_db *flow_db; 1122 1123 if (!ulp_ctx || !func_id) { 1124 BNXT_TF_DBG(ERR, "Invalid Argument\n"); 1125 return -EINVAL; 1126 } 1127 1128 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1129 if (!flow_db) { 1130 BNXT_TF_DBG(ERR, "Flow database not found\n"); 1131 return -EINVAL; 1132 } 1133 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 1134 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n"); 1135 return -EINVAL; 1136 } 1137 1138 while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR, 1139 &flow_id)) { 1140 if (flow_db->func_id_tbl[flow_id] == func_id) 1141 ulp_mapper_resources_free(ulp_ctx, 1142 BNXT_ULP_FDB_TYPE_REGULAR, 1143 flow_id); 1144 } 1145 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 1146 return 0; 1147 } 1148 1149 /* 1150 * Flush all flows in the flow database that are associated with the session. 1151 * 1152 * ulp_ctxt [in] Ptr to ulp context 1153 * 1154 * returns 0 on success or negative number on failure 1155 */ 1156 int32_t 1157 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx) 1158 { 1159 /* 1160 * TBD: Tf core implementation of FW session flush shall change this 1161 * implementation. 1162 */ 1163 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 1164 } 1165 1166 /* 1167 * Check that flow id matches the function id or not 1168 * 1169 * ulp_ctxt [in] Ptr to ulp context 1170 * flow_db [in] Ptr to flow table 1171 * func_id [in] The func_id to be set, for reset pass zero. 1172 * 1173 * returns true on success or false on failure 1174 */ 1175 bool 1176 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx, 1177 uint32_t flow_id, 1178 uint32_t func_id) 1179 { 1180 struct bnxt_ulp_flow_db *flow_db; 1181 1182 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1183 if (!flow_db) { 1184 BNXT_TF_DBG(ERR, "Flow database not found\n"); 1185 return false; 1186 } 1187 1188 /* set the function id in the function table */ 1189 if (flow_id < flow_db->func_id_tbl_size && func_id && 1190 flow_db->func_id_tbl[flow_id] == func_id) 1191 return true; 1192 1193 return false; 1194 } 1195 1196 /* 1197 * Internal api to traverse the resource list within a flow 1198 * and match a resource based on resource func and resource 1199 * sub type. This api should be used only for resources that 1200 * are unique and do not have multiple instances of resource 1201 * func and sub type combination since it will return only 1202 * the first match. 1203 */ 1204 static int32_t 1205 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx, 1206 enum bnxt_ulp_fdb_type flow_type, 1207 uint32_t flow_id, 1208 uint32_t resource_func, 1209 uint32_t res_subtype, 1210 struct ulp_flow_db_res_params *params) 1211 { 1212 struct bnxt_ulp_flow_db *flow_db; 1213 struct bnxt_ulp_flow_tbl *flow_tbl; 1214 struct ulp_fdb_resource_info *fid_res; 1215 uint32_t res_id; 1216 1217 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx); 1218 if (!flow_db) { 1219 BNXT_TF_DBG(ERR, "Flow database not found\n"); 1220 return -EINVAL; 1221 } 1222 1223 if (!params) { 1224 BNXT_TF_DBG(ERR, "invalid argument\n"); 1225 return -EINVAL; 1226 } 1227 1228 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 1229 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 1230 return -EINVAL; 1231 } 1232 1233 flow_tbl = &flow_db->flow_tbl; 1234 1235 /* check for limits of fid */ 1236 if (flow_id >= flow_tbl->num_flows || !flow_id) { 1237 BNXT_TF_DBG(ERR, "Invalid flow index\n"); 1238 return -EINVAL; 1239 } 1240 1241 /* check if the flow is active or not */ 1242 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) { 1243 BNXT_TF_DBG(ERR, "flow does not exist\n"); 1244 return -EINVAL; 1245 } 1246 /* Iterate the resource to get the resource handle */ 1247 res_id = flow_id; 1248 memset(params, 0, sizeof(struct ulp_flow_db_res_params)); 1249 while (res_id) { 1250 fid_res = &flow_tbl->flow_resources[res_id]; 1251 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) { 1252 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) { 1253 if (res_subtype == fid_res->resource_sub_type) { 1254 ulp_flow_db_res_info_to_params(fid_res, 1255 params); 1256 return 0; 1257 } 1258 1259 } else if (resource_func == 1260 BNXT_ULP_RESOURCE_FUNC_EM_TABLE) { 1261 ulp_flow_db_res_info_to_params(fid_res, 1262 params); 1263 return 0; 1264 } 1265 } 1266 res_id = 0; 1267 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx); 1268 } 1269 return -ENOENT; 1270 } 1271 1272 /* 1273 * Api to get the cfa action pointer from a flow. 1274 * 1275 * ulp_ctxt [in] Ptr to ulp context 1276 * flow_id [in] flow id 1277 * cfa_action [out] The resource handle stored in the flow database 1278 * 1279 * returns 0 on success 1280 */ 1281 int32_t 1282 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx, 1283 uint32_t flow_id, 1284 uint16_t *cfa_action) 1285 { 1286 uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION; 1287 struct ulp_flow_db_res_params params; 1288 int32_t rc; 1289 1290 rc = ulp_flow_db_resource_params_get(ulp_ctx, 1291 BNXT_ULP_FDB_TYPE_DEFAULT, 1292 flow_id, 1293 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE, 1294 sub_typ, ¶ms); 1295 if (rc) { 1296 BNXT_TF_DBG(INFO, "CFA Action ptr not found for flow id %u\n", 1297 flow_id); 1298 return -ENOENT; 1299 } 1300 *cfa_action = params.resource_hndl; 1301 return 0; 1302 } 1303 1304 /* 1305 * Allocate the entry in the parent-child database 1306 * 1307 * ulp_ctxt [in] Ptr to ulp_context 1308 * fid [in] The flow id to the flow entry 1309 * 1310 * returns index on success and negative on failure. 1311 */ 1312 int32_t 1313 ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt, 1314 uint32_t fid) 1315 { 1316 struct bnxt_ulp_flow_db *flow_db; 1317 struct ulp_fdb_parent_child_db *p_pdb; 1318 uint32_t idx, free_idx = 0; 1319 1320 /* validate the arguments */ 1321 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid); 1322 if (!flow_db) { 1323 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1324 return -EINVAL; 1325 } 1326 1327 p_pdb = &flow_db->parent_child_db; 1328 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1329 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) { 1330 BNXT_TF_DBG(ERR, "fid is already allocated\n"); 1331 return -EINVAL; 1332 } 1333 if (!p_pdb->parent_flow_tbl[idx].parent_fid && !free_idx) 1334 free_idx = idx + 1; 1335 } 1336 /* no free slots */ 1337 if (!free_idx) { 1338 BNXT_TF_DBG(ERR, "parent child db is full\n"); 1339 return -ENOMEM; 1340 } 1341 1342 free_idx -= 1; 1343 /* set the Fid in the parent child */ 1344 p_pdb->parent_flow_tbl[free_idx].parent_fid = fid; 1345 return free_idx; 1346 } 1347 1348 /* 1349 * Free the entry in the parent-child database 1350 * 1351 * ulp_ctxt [in] Ptr to ulp_context 1352 * fid [in] The flow id to the flow entry 1353 * 1354 * returns 0 on success and negative on failure. 1355 */ 1356 int32_t 1357 ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt, 1358 uint32_t fid) 1359 { 1360 struct bnxt_ulp_flow_db *flow_db; 1361 struct ulp_fdb_parent_child_db *p_pdb; 1362 uint32_t idx; 1363 1364 /* validate the arguments */ 1365 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid); 1366 if (!flow_db) { 1367 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1368 return -EINVAL; 1369 } 1370 1371 p_pdb = &flow_db->parent_child_db; 1372 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1373 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) { 1374 /* free the contents */ 1375 p_pdb->parent_flow_tbl[idx].parent_fid = 0; 1376 memset(p_pdb->parent_flow_tbl[idx].child_fid_bitset, 1377 0, p_pdb->child_bitset_size); 1378 return 0; 1379 } 1380 } 1381 BNXT_TF_DBG(ERR, "parent entry not found = %x\n", fid); 1382 return -EINVAL; 1383 } 1384 1385 /* 1386 * Set or reset the child flow in the parent-child database 1387 * 1388 * ulp_ctxt [in] Ptr to ulp_context 1389 * parent_fid [in] The flow id of the parent flow entry 1390 * child_fid [in] The flow id of the child flow entry 1391 * set_flag [in] Use 1 for setting child, 0 to reset 1392 * 1393 * returns zero on success and negative on failure. 1394 */ 1395 int32_t 1396 ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt, 1397 uint32_t parent_fid, 1398 uint32_t child_fid, 1399 uint32_t set_flag) 1400 { 1401 struct bnxt_ulp_flow_db *flow_db; 1402 struct ulp_fdb_parent_child_db *p_pdb; 1403 uint32_t idx, a_idx; 1404 uint64_t *t; 1405 1406 /* validate the arguments */ 1407 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 1408 if (!flow_db) { 1409 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1410 return -EINVAL; 1411 } 1412 1413 /* check for fid validity */ 1414 if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) { 1415 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid); 1416 return -EINVAL; 1417 } 1418 1419 p_pdb = &flow_db->parent_child_db; 1420 a_idx = child_fid / ULP_INDEX_BITMAP_SIZE; 1421 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1422 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 1423 t = p_pdb->parent_flow_tbl[idx].child_fid_bitset; 1424 if (set_flag) 1425 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid); 1426 else 1427 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid); 1428 return 0; 1429 } 1430 } 1431 BNXT_TF_DBG(ERR, "Unable to set the parent-child flow %x:%x\n", 1432 parent_fid, child_fid); 1433 return -1; 1434 } 1435 1436 /* 1437 * Get the parent index from the parent-child database 1438 * 1439 * ulp_ctxt [in] Ptr to ulp_context 1440 * parent_fid [in] The flow id of the parent flow entry 1441 * parent_idx [out] The parent index of parent flow entry 1442 * 1443 * returns zero on success and negative on failure. 1444 */ 1445 int32_t 1446 ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt, 1447 uint32_t parent_fid, 1448 uint32_t *parent_idx) 1449 { 1450 struct bnxt_ulp_flow_db *flow_db; 1451 struct ulp_fdb_parent_child_db *p_pdb; 1452 uint32_t idx; 1453 1454 /* validate the arguments */ 1455 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 1456 if (!flow_db) { 1457 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1458 return -EINVAL; 1459 } 1460 1461 p_pdb = &flow_db->parent_child_db; 1462 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1463 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 1464 *parent_idx = idx; 1465 return 0; 1466 } 1467 } 1468 BNXT_TF_DBG(ERR, "Unable to get the parent flow %x\n", parent_fid); 1469 return -1; 1470 } 1471 1472 /* 1473 * Get the next child flow in the parent-child database 1474 * 1475 * ulp_ctxt [in] Ptr to ulp_context 1476 * parent_fid [in] The flow id of the parent flow entry 1477 * child_fid [in/out] The flow id of the child flow entry 1478 * 1479 * returns zero on success and negative on failure. 1480 * Pass child_fid as zero for first entry. 1481 */ 1482 int32_t 1483 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db, 1484 uint32_t parent_idx, 1485 uint32_t *child_fid) 1486 { 1487 struct ulp_fdb_parent_child_db *p_pdb; 1488 uint32_t idx, s_idx, mod_fid; 1489 uint32_t next_fid = *child_fid; 1490 uint64_t *child_bitset; 1491 uint64_t bs; 1492 1493 /* check for fid validity */ 1494 p_pdb = &flow_db->parent_child_db; 1495 if (parent_idx >= p_pdb->entries_count || 1496 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) { 1497 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx); 1498 return -EINVAL; 1499 } 1500 1501 child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset; 1502 do { 1503 /* increment the flow id to find the next valid flow id */ 1504 next_fid++; 1505 if (next_fid >= flow_db->flow_tbl.num_flows) 1506 return -ENOENT; 1507 idx = next_fid / ULP_INDEX_BITMAP_SIZE; 1508 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE; 1509 s_idx = idx; 1510 while (!(bs = child_bitset[idx])) { 1511 idx++; 1512 if ((idx * ULP_INDEX_BITMAP_SIZE) >= 1513 flow_db->flow_tbl.num_flows) 1514 return -ENOENT; 1515 } 1516 /* 1517 * remove the previous bits in the bitset bs to find the 1518 * next non zero bit in the bitset. This needs to be done 1519 * only if the idx is same as he one you started. 1520 */ 1521 if (s_idx == idx) 1522 bs &= (-1UL >> mod_fid); 1523 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs); 1524 if (*child_fid >= next_fid) { 1525 BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n"); 1526 return -ENOENT; 1527 } 1528 idx = next_fid / ULP_INDEX_BITMAP_SIZE; 1529 } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid)); 1530 *child_fid = next_fid; 1531 return 0; 1532 } 1533 1534 /* 1535 * Set the counter accumulation in the parent flow 1536 * 1537 * ulp_ctxt [in] Ptr to ulp_context 1538 * parent_idx [in] The parent index of the parent flow entry 1539 * 1540 * returns index on success and negative on failure. 1541 */ 1542 static int32_t 1543 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt, 1544 uint32_t parent_idx) 1545 { 1546 struct bnxt_ulp_flow_db *flow_db; 1547 struct ulp_fdb_parent_child_db *p_pdb; 1548 1549 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1550 if (!flow_db) { 1551 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 1552 return -EINVAL; 1553 } 1554 1555 /* check for parent idx validity */ 1556 p_pdb = &flow_db->parent_child_db; 1557 if (parent_idx >= p_pdb->entries_count || 1558 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) { 1559 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx); 1560 return -EINVAL; 1561 } 1562 1563 p_pdb->parent_flow_tbl[parent_idx].counter_acc = 1; 1564 return 0; 1565 } 1566 1567 /* 1568 * Get the counter accumulation in the parent flow 1569 * 1570 * ulp_ctxt [in] Ptr to ulp_context 1571 * parent_fid [in] The flow id of the parent flow entry 1572 * 1573 * returns 0 if counter accum is set else -1. 1574 */ 1575 static int32_t 1576 ulp_flow_db_parent_flow_count_accum_get(struct bnxt_ulp_context *ulp_ctxt, 1577 uint32_t parent_fid) 1578 { 1579 struct bnxt_ulp_flow_db *flow_db; 1580 struct ulp_fdb_parent_child_db *p_pdb; 1581 uint32_t idx; 1582 1583 /* validate the arguments */ 1584 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 1585 if (!flow_db) { 1586 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1587 return -EINVAL; 1588 } 1589 1590 p_pdb = &flow_db->parent_child_db; 1591 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1592 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 1593 if (p_pdb->parent_flow_tbl[idx].counter_acc) 1594 return 0; 1595 break; 1596 } 1597 } 1598 return -1; 1599 } 1600 1601 /* 1602 * Orphan the child flow entry 1603 * This is called only for child flows that have 1604 * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource 1605 * 1606 * ulp_ctxt [in] Ptr to ulp_context 1607 * flow_type [in] Specify it is regular or default flow 1608 * fid [in] The index to the flow entry 1609 * 1610 * Returns 0 on success and negative on failure. 1611 */ 1612 int32_t 1613 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt, 1614 enum bnxt_ulp_fdb_type flow_type, 1615 uint32_t fid) 1616 { 1617 struct bnxt_ulp_flow_db *flow_db; 1618 struct bnxt_ulp_flow_tbl *flow_tbl; 1619 struct ulp_fdb_resource_info *fid_res; 1620 uint32_t res_id = 0; 1621 1622 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); 1623 if (!flow_db) { 1624 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 1625 return -EINVAL; 1626 } 1627 1628 if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) { 1629 BNXT_TF_DBG(ERR, "Invalid flow type\n"); 1630 return -EINVAL; 1631 } 1632 1633 flow_tbl = &flow_db->flow_tbl; 1634 /* check for max flows */ 1635 if (fid >= flow_tbl->num_flows || !fid) { 1636 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid); 1637 return -EINVAL; 1638 } 1639 1640 /* check if the flow is active or not */ 1641 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { 1642 BNXT_TF_DBG(ERR, "flow does not exist\n"); 1643 return -EINVAL; 1644 } 1645 1646 /* Iterate the resource to get the resource handle */ 1647 res_id = fid; 1648 while (res_id) { 1649 fid_res = &flow_tbl->flow_resources[res_id]; 1650 if (ulp_flow_db_resource_func_get(fid_res) == 1651 BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) { 1652 /* invalidate the resource details */ 1653 fid_res->resource_hndl = 0; 1654 return 0; 1655 } 1656 res_id = 0; 1657 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx); 1658 } 1659 /* failed */ 1660 return -1; 1661 } 1662 1663 /* 1664 * Create parent flow in the parent flow tbl 1665 * 1666 * parms [in] Ptr to mapper params 1667 * 1668 * Returns 0 on success and negative on failure. 1669 */ 1670 int32_t 1671 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms) 1672 { 1673 struct ulp_flow_db_res_params fid_parms; 1674 uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT_ACC; 1675 struct ulp_flow_db_res_params res_params; 1676 int32_t fid_idx, rc; 1677 1678 /* create the child flow entry in parent flow table */ 1679 fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid); 1680 if (fid_idx < 0) { 1681 BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n", 1682 parms->fid); 1683 return -1; 1684 } 1685 1686 /* Add the parent details in the resource list of the flow */ 1687 memset(&fid_parms, 0, sizeof(fid_parms)); 1688 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW; 1689 fid_parms.resource_hndl = fid_idx; 1690 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1691 if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, 1692 parms->fid, &fid_parms)) { 1693 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n", 1694 parms->fid); 1695 return -1; 1696 } 1697 1698 /* check of the flow has internal counter accumulation enabled */ 1699 if (!ulp_flow_db_resource_params_get(parms->ulp_ctx, 1700 BNXT_ULP_FDB_TYPE_REGULAR, 1701 parms->fid, 1702 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE, 1703 sub_typ, 1704 &res_params)) { 1705 /* Enable the counter accumulation in parent entry */ 1706 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx, 1707 fid_idx)) { 1708 BNXT_TF_DBG(ERR, "Error in setting counter acc %x\n", 1709 parms->fid); 1710 return -1; 1711 } 1712 } 1713 1714 rc = ulp_flow_db_parent_tun_idx_set(parms->ulp_ctx, fid_idx, 1715 parms->tun_idx); 1716 if (rc) { 1717 BNXT_TF_DBG(ERR, "Error setting tun_idx in the parent flow\n"); 1718 return rc; 1719 } 1720 1721 return 0; 1722 } 1723 1724 /* 1725 * Create child flow in the parent flow tbl 1726 * 1727 * parms [in] Ptr to mapper params 1728 * 1729 * Returns 0 on success and negative on failure. 1730 */ 1731 int32_t 1732 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms) 1733 { 1734 struct ulp_flow_db_res_params fid_parms; 1735 uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT; 1736 enum bnxt_ulp_resource_func res_fun; 1737 struct ulp_flow_db_res_params res_p; 1738 uint32_t parent_fid = parms->parent_fid; 1739 int32_t rc; 1740 1741 /* create the parent flow entry in parent flow table */ 1742 rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx, 1743 parms->parent_fid, 1744 parms->fid, 1); 1745 if (rc) { 1746 BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid); 1747 return rc; 1748 } 1749 1750 /* Add the parent details in the resource list of the flow */ 1751 memset(&fid_parms, 0, sizeof(fid_parms)); 1752 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW; 1753 fid_parms.resource_hndl = parms->parent_fid; 1754 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1755 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1756 BNXT_ULP_FDB_TYPE_REGULAR, 1757 parms->fid, &fid_parms); 1758 if (rc) { 1759 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n", 1760 parms->fid); 1761 return rc; 1762 } 1763 1764 /* check if accumulation count is set for parent flow */ 1765 rc = ulp_flow_db_parent_flow_count_accum_get(parms->ulp_ctx, 1766 parms->parent_fid); 1767 if (!rc) { 1768 /* check if internal count action included for this flow.*/ 1769 res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE; 1770 rc = ulp_flow_db_resource_params_get(parms->ulp_ctx, 1771 BNXT_ULP_FDB_TYPE_REGULAR, 1772 parms->fid, 1773 res_fun, 1774 sub_type, 1775 &res_p); 1776 if (!rc) { 1777 /* update the counter manager to include parent fid */ 1778 if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx, 1779 res_p.direction, 1780 res_p.resource_hndl, 1781 parent_fid)) { 1782 BNXT_TF_DBG(ERR, "Error in setting child %x\n", 1783 parms->fid); 1784 return -1; 1785 } 1786 } 1787 } 1788 /* return success */ 1789 return 0; 1790 } 1791 1792 /* 1793 * Update the parent counters 1794 * 1795 * ulp_ctxt [in] Ptr to ulp_context 1796 * parent_fid [in] The flow id of the parent flow entry 1797 * packet_count [in] - packet count 1798 * byte_count [in] - byte count 1799 * 1800 * returns 0 on success 1801 */ 1802 int32_t 1803 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt, 1804 uint32_t parent_fid, 1805 uint64_t packet_count, 1806 uint64_t byte_count) 1807 { 1808 struct bnxt_ulp_flow_db *flow_db; 1809 struct ulp_fdb_parent_child_db *p_pdb; 1810 uint32_t idx; 1811 1812 /* validate the arguments */ 1813 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 1814 if (!flow_db) { 1815 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1816 return -EINVAL; 1817 } 1818 1819 p_pdb = &flow_db->parent_child_db; 1820 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1821 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 1822 if (p_pdb->parent_flow_tbl[idx].counter_acc) { 1823 p_pdb->parent_flow_tbl[idx].pkt_count += 1824 packet_count; 1825 p_pdb->parent_flow_tbl[idx].byte_count += 1826 byte_count; 1827 } 1828 return 0; 1829 } 1830 } 1831 return -ENOENT; 1832 } 1833 1834 /* 1835 * Get the parent accumulation counters 1836 * 1837 * ulp_ctxt [in] Ptr to ulp_context 1838 * parent_fid [in] The flow id of the parent flow entry 1839 * packet_count [out] - packet count 1840 * byte_count [out] - byte count 1841 * 1842 * returns 0 on success 1843 */ 1844 int32_t 1845 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt, 1846 uint32_t parent_fid, uint64_t *packet_count, 1847 uint64_t *byte_count, uint8_t count_reset) 1848 { 1849 struct bnxt_ulp_flow_db *flow_db; 1850 struct ulp_fdb_parent_child_db *p_pdb; 1851 uint32_t idx; 1852 1853 /* validate the arguments */ 1854 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid); 1855 if (!flow_db) { 1856 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1857 return -EINVAL; 1858 } 1859 1860 p_pdb = &flow_db->parent_child_db; 1861 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1862 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { 1863 if (p_pdb->parent_flow_tbl[idx].counter_acc) { 1864 *packet_count = 1865 p_pdb->parent_flow_tbl[idx].pkt_count; 1866 *byte_count = 1867 p_pdb->parent_flow_tbl[idx].byte_count; 1868 if (count_reset) { 1869 p_pdb->parent_flow_tbl[idx].pkt_count = 0; 1870 p_pdb->parent_flow_tbl[idx].byte_count = 0; 1871 } 1872 } 1873 return 0; 1874 } 1875 } 1876 return -ENOENT; 1877 } 1878 1879 /* 1880 * reset the parent accumulation counters 1881 * 1882 * ulp_ctxt [in] Ptr to ulp_context 1883 * 1884 * returns none 1885 */ 1886 void 1887 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt) 1888 { 1889 struct bnxt_ulp_flow_db *flow_db; 1890 struct ulp_fdb_parent_child_db *p_pdb; 1891 uint32_t idx; 1892 1893 /* validate the arguments */ 1894 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, 1); 1895 if (!flow_db) { 1896 BNXT_TF_DBG(ERR, "parent child db validation failed\n"); 1897 return; 1898 } 1899 1900 p_pdb = &flow_db->parent_child_db; 1901 for (idx = 0; idx < p_pdb->entries_count; idx++) { 1902 if (p_pdb->parent_flow_tbl[idx].parent_fid && 1903 p_pdb->parent_flow_tbl[idx].counter_acc) { 1904 p_pdb->parent_flow_tbl[idx].pkt_count = 0; 1905 p_pdb->parent_flow_tbl[idx].byte_count = 0; 1906 } 1907 } 1908 } 1909 1910 /* 1911 * Set the shared bit for the flow db entry 1912 * 1913 * res [in] Ptr to fdb entry 1914 * shared [in] shared flag 1915 * 1916 * returns none 1917 */ 1918 void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res, 1919 enum bnxt_ulp_shared_session shared) 1920 { 1921 if (res && (shared & BNXT_ULP_SHARED_SESSION_YES)) 1922 res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION; 1923 } 1924