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