1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2020 Broadcom
6 #include <rte_malloc.h>
8 #include "bnxt_tf_common.h"
9 #include "ulp_flow_db.h"
10 #include "ulp_utils.h"
11 #include "ulp_template_struct.h"
12 #include "ulp_mapper.h"
14 #define ULP_FLOW_DB_RES_DIR_BIT 31
15 #define ULP_FLOW_DB_RES_DIR_MASK 0x80000000
16 #define ULP_FLOW_DB_RES_FUNC_BITS 28
17 #define ULP_FLOW_DB_RES_FUNC_MASK 0x70000000
18 #define ULP_FLOW_DB_RES_NXT_MASK 0x0FFFFFFF
19 #define ULP_FLOW_DB_RES_FUNC_UPPER 5
20 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80
21 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F
23 /* Macro to copy the nxt_resource_idx */
24 #define ULP_FLOW_DB_RES_NXT_SET(dst, src) {(dst) |= ((src) &\
25 ULP_FLOW_DB_RES_NXT_MASK); }
26 #define ULP_FLOW_DB_RES_NXT_RESET(dst) ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
29 * Helper function to set the bit in the active flow table
30 * No validation is done in this function.
32 * flow_tbl [in] Ptr to flow table
33 * idx [in] The index to bit to be set or reset.
34 * flag [in] 1 to set and 0 to reset.
39 ulp_flow_db_active_flow_set(struct bnxt_ulp_flow_tbl *flow_tbl,
43 uint32_t active_index;
45 active_index = idx / ULP_INDEX_BITMAP_SIZE;
47 ULP_INDEX_BITMAP_SET(flow_tbl->active_flow_tbl[active_index],
50 ULP_INDEX_BITMAP_RESET(flow_tbl->active_flow_tbl[active_index],
55 * Helper function to allocate the flow table and initialize
56 * is set.No validation being done in this function.
58 * flow_tbl [in] Ptr to flow table
59 * idx [in] The index to bit to be set or reset.
61 * returns 1 on set or 0 if not set.
64 ulp_flow_db_active_flow_is_set(struct bnxt_ulp_flow_tbl *flow_tbl,
67 uint32_t active_index;
69 active_index = idx / ULP_INDEX_BITMAP_SIZE;
70 return ULP_INDEX_BITMAP_GET(flow_tbl->active_flow_tbl[active_index],
75 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
79 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
80 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
81 /* The reource func is split into upper and lower */
82 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
83 return (func | res_info->resource_func_lower);
88 * Helper function to copy the resource params to resource info
89 * No validation being done in this function.
91 * resource_info [out] Ptr to resource information
92 * params [in] The input params from the caller
96 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
97 struct ulp_flow_db_res_params *params)
99 uint32_t resource_func;
101 resource_info->nxt_resource_idx |= ((params->direction <<
102 ULP_FLOW_DB_RES_DIR_BIT) &
103 ULP_FLOW_DB_RES_DIR_MASK);
104 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
105 resource_info->nxt_resource_idx |= ((resource_func <<
106 ULP_FLOW_DB_RES_FUNC_BITS) &
107 ULP_FLOW_DB_RES_FUNC_MASK);
109 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
110 /* Break the resource func into two parts */
111 resource_func = (params->resource_func &
112 ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
113 resource_info->resource_func_lower = resource_func;
116 /* Store the handle as 64bit only for EM table entries */
117 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
118 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
119 resource_info->resource_type = params->resource_type;
120 resource_info->resource_sub_type = params->resource_sub_type;
121 resource_info->reserved = params->reserved;
123 resource_info->resource_em_handle = params->resource_hndl;
128 * Helper function to copy the resource params to resource info
129 * No validation being done in this function.
131 * resource_info [in] Ptr to resource information
132 * params [out] The output params to the caller
137 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
138 struct ulp_flow_db_res_params *params)
140 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
141 params->direction = ((resource_info->nxt_resource_idx &
142 ULP_FLOW_DB_RES_DIR_MASK) >>
143 ULP_FLOW_DB_RES_DIR_BIT);
145 /* use the helper function to get the resource func */
146 params->resource_func = ulp_flow_db_resource_func_get(resource_info);
148 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
149 params->resource_hndl = resource_info->resource_em_handle;
150 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
151 params->resource_hndl = resource_info->resource_hndl;
152 params->resource_type = resource_info->resource_type;
153 params->resource_sub_type = resource_info->resource_sub_type;
154 params->reserved = resource_info->reserved;
159 * Helper function to allocate the flow table and initialize
160 * the stack for allocation operations.
162 * flow_db [in] Ptr to flow database structure
163 * tbl_idx [in] The index to table creation.
165 * Returns 0 on success or negative number on failure.
168 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
169 enum bnxt_ulp_flow_db_tables tbl_idx)
172 struct bnxt_ulp_flow_tbl *flow_tbl;
175 flow_tbl = &flow_db->flow_tbl[tbl_idx];
177 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
178 flow_tbl->flow_resources =
179 rte_zmalloc("ulp_fdb_resource_info", size, 0);
181 if (!flow_tbl->flow_resources) {
182 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
185 size = sizeof(uint32_t) * flow_tbl->num_resources;
186 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
187 if (!flow_tbl->flow_tbl_stack) {
188 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
191 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
192 flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
193 if (!flow_tbl->active_flow_tbl) {
194 BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
198 /* Initialize the stack table. */
199 for (idx = 0; idx < flow_tbl->num_resources; idx++)
200 flow_tbl->flow_tbl_stack[idx] = idx;
202 /* Ignore the first element in the list. */
203 flow_tbl->head_index = 1;
204 /* Tail points to the last entry in the list. */
205 flow_tbl->tail_index = flow_tbl->num_resources - 1;
210 * Helper function to deallocate the flow table.
212 * flow_db [in] Ptr to flow database structure
213 * tbl_idx [in] The index to table creation.
218 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
219 enum bnxt_ulp_flow_db_tables tbl_idx)
221 struct bnxt_ulp_flow_tbl *flow_tbl;
223 flow_tbl = &flow_db->flow_tbl[tbl_idx];
225 /* Free all the allocated tables in the flow table. */
226 if (flow_tbl->active_flow_tbl) {
227 rte_free(flow_tbl->active_flow_tbl);
228 flow_tbl->active_flow_tbl = NULL;
231 if (flow_tbl->flow_tbl_stack) {
232 rte_free(flow_tbl->flow_tbl_stack);
233 flow_tbl->flow_tbl_stack = NULL;
236 if (flow_tbl->flow_resources) {
237 rte_free(flow_tbl->flow_resources);
238 flow_tbl->flow_resources = NULL;
243 * Helper function to add function id to the flow table
245 * flow_db [in] Ptr to flow table
246 * flow_id [in] The flow id of the flow
247 * func_id [in] The func_id to be set, for reset pass zero
252 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
256 /* set the function id in the function table */
257 if (flow_id < flow_db->func_id_tbl_size)
258 flow_db->func_id_tbl[flow_id] = func_id;
259 else /* This should never happen */
260 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
264 * Initialize the flow database. Memory is allocated in this
265 * call and assigned to the flow database.
267 * ulp_ctxt [in] Ptr to ulp context
269 * Returns 0 on success or negative number on failure.
271 int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
273 struct bnxt_ulp_device_params *dparms;
274 struct bnxt_ulp_flow_tbl *flow_tbl;
275 struct bnxt_ulp_flow_db *flow_db;
278 /* Get the dev specific number of flows that needed to be supported. */
279 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
280 BNXT_TF_DBG(ERR, "Invalid device id\n");
284 dparms = bnxt_ulp_device_params_get(dev_id);
286 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
290 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
291 sizeof(struct bnxt_ulp_flow_db), 0);
294 "Failed to allocate memory for flow table ptr\n");
298 /* Attach the flow database to the ulp context. */
299 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
301 /* Populate the regular flow table limits. */
302 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
303 flow_tbl->num_flows = dparms->flow_db_num_entries + 1;
304 flow_tbl->num_resources = (flow_tbl->num_flows *
305 dparms->num_resources_per_flow);
307 /* Populate the default flow table limits. */
308 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
309 flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
310 flow_tbl->num_resources = (flow_tbl->num_flows *
311 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
313 /* Allocate the resource for the regular flow table. */
314 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
316 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
319 /* add 1 since we are not using index 0 for flow id */
320 flow_db->func_id_tbl_size = dparms->flow_db_num_entries + 1;
321 /* Allocate the function Id table */
322 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
323 flow_db->func_id_tbl_size *
324 sizeof(uint16_t), 0);
325 if (!flow_db->func_id_tbl) {
327 "Failed to allocate mem for flow table func id\n");
330 /* All good so return. */
333 ulp_flow_db_deinit(ulp_ctxt);
338 * Deinitialize the flow database. Memory is deallocated in
339 * this call and all flows should have been purged before this
342 * ulp_ctxt [in] Ptr to ulp context
344 * Returns 0 on success.
346 int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
348 struct bnxt_ulp_flow_db *flow_db;
350 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
352 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
356 /* Detach the flow database from the ulp context. */
357 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
359 /* Free up all the memory. */
360 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
361 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
362 rte_free(flow_db->func_id_tbl);
369 * Allocate the flow database entry
371 * ulp_ctxt [in] Ptr to ulp_context
372 * tbl_idx [in] Specify it is regular or default flow
373 * fid [out] The index to the flow entry
375 * returns 0 on success and negative on failure.
377 int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
378 enum bnxt_ulp_flow_db_tables tbl_idx,
382 struct bnxt_ulp_flow_db *flow_db;
383 struct bnxt_ulp_flow_tbl *flow_tbl;
385 *fid = 0; /* Initialize fid to invalid value */
386 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
388 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
392 flow_tbl = &flow_db->flow_tbl[tbl_idx];
393 /* check for max flows */
394 if (flow_tbl->num_flows <= flow_tbl->head_index) {
395 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
398 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
399 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
402 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
403 flow_tbl->head_index++;
404 ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
406 /* The function id update is only valid for regular flow table */
407 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
408 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
410 /* all good, return success */
415 * Allocate the flow database entry.
416 * The params->critical_resource has to be set to 0 to allocate a new resource.
418 * ulp_ctxt [in] Ptr to ulp_context
419 * tbl_idx [in] Specify it is regular or default flow
420 * fid [in] The index to the flow entry
421 * params [in] The contents to be copied into resource
423 * returns 0 on success and negative on failure.
425 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
426 enum bnxt_ulp_flow_db_tables tbl_idx,
428 struct ulp_flow_db_res_params *params)
430 struct bnxt_ulp_flow_db *flow_db;
431 struct bnxt_ulp_flow_tbl *flow_tbl;
432 struct ulp_fdb_resource_info *resource, *fid_resource;
435 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
437 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
441 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
442 BNXT_TF_DBG(ERR, "Invalid table index\n");
445 flow_tbl = &flow_db->flow_tbl[tbl_idx];
447 /* check for max flows */
448 if (fid >= flow_tbl->num_flows || !fid) {
449 BNXT_TF_DBG(ERR, "Invalid flow index\n");
453 /* check if the flow is active or not */
454 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
455 BNXT_TF_DBG(ERR, "flow does not exist\n");
459 /* check for max resource */
460 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
461 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
464 fid_resource = &flow_tbl->flow_resources[fid];
466 if (!params->critical_resource) {
467 /* Not the critical_resource so allocate a resource */
468 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
469 resource = &flow_tbl->flow_resources[idx];
470 flow_tbl->tail_index--;
472 /* Update the chain list of resource*/
473 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
474 fid_resource->nxt_resource_idx);
475 /* update the contents */
476 ulp_flow_db_res_params_to_info(resource, params);
477 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
478 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
481 /* critical resource. Just update the fid resource */
482 ulp_flow_db_res_params_to_info(fid_resource, params);
485 /* all good, return success */
490 * Free the flow database entry.
491 * The params->critical_resource has to be set to 1 to free the first resource.
493 * ulp_ctxt [in] Ptr to ulp_context
494 * tbl_idx [in] Specify it is regular or default flow
495 * fid [in] The index to the flow entry
496 * params [in/out] The contents to be copied into params.
497 * Onlythe critical_resource needs to be set by the caller.
499 * Returns 0 on success and negative on failure.
501 int32_t ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
502 enum bnxt_ulp_flow_db_tables tbl_idx,
504 struct ulp_flow_db_res_params *params)
506 struct bnxt_ulp_flow_db *flow_db;
507 struct bnxt_ulp_flow_tbl *flow_tbl;
508 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
509 uint32_t nxt_idx = 0;
511 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
513 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
517 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
518 BNXT_TF_DBG(ERR, "Invalid table index\n");
521 flow_tbl = &flow_db->flow_tbl[tbl_idx];
523 /* check for max flows */
524 if (fid >= flow_tbl->num_flows || !fid) {
525 BNXT_TF_DBG(ERR, "Invalid flow index\n");
529 /* check if the flow is active or not */
530 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
531 BNXT_TF_DBG(ERR, "flow does not exist\n");
535 fid_resource = &flow_tbl->flow_resources[fid];
536 if (!params->critical_resource) {
537 /* Not the critical resource so free the resource */
538 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
539 fid_resource->nxt_resource_idx);
541 /* reached end of resources */
544 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
546 /* connect the fid resource to the next resource */
547 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
548 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
549 nxt_resource->nxt_resource_idx);
551 /* update the contents to be given to caller */
552 ulp_flow_db_res_info_to_params(nxt_resource, params);
554 /* Delete the nxt_resource */
555 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
557 /* add it to the free list */
558 flow_tbl->tail_index++;
559 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
560 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
563 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
566 /* Critical resource. copy the contents and exit */
567 ulp_flow_db_res_info_to_params(fid_resource, params);
568 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
569 fid_resource->nxt_resource_idx);
570 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
571 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
575 /* all good, return success */
580 * Free the flow database entry
582 * ulp_ctxt [in] Ptr to ulp_context
583 * tbl_idx [in] Specify it is regular or default flow
584 * fid [in] The index to the flow entry
586 * returns 0 on success and negative on failure.
588 int32_t ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
589 enum bnxt_ulp_flow_db_tables tbl_idx,
592 struct bnxt_ulp_flow_db *flow_db;
593 struct bnxt_ulp_flow_tbl *flow_tbl;
595 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
597 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
601 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
602 BNXT_TF_DBG(ERR, "Invalid table index\n");
606 flow_tbl = &flow_db->flow_tbl[tbl_idx];
608 /* check for limits of fid */
609 if (fid >= flow_tbl->num_flows || !fid) {
610 BNXT_TF_DBG(ERR, "Invalid flow index\n");
614 /* check if the flow is active or not */
615 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
616 BNXT_TF_DBG(ERR, "flow does not exist\n");
619 flow_tbl->head_index--;
620 if (!flow_tbl->head_index) {
621 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
624 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
625 ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
626 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
627 ulp_flow_db_func_id_set(flow_db, fid, 0);
629 /* all good, return success */
634 * Get the flow database entry details
636 * ulp_ctxt [in] Ptr to ulp_context
637 * tbl_idx [in] Specify it is regular or default flow
638 * fid [in] The index to the flow entry
639 * nxt_idx [in/out] the index to the next entry
640 * params [out] The contents to be copied into params.
642 * returns 0 on success and negative on failure.
644 int32_t ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
645 enum bnxt_ulp_flow_db_tables tbl_idx,
648 struct ulp_flow_db_res_params *params)
650 struct bnxt_ulp_flow_db *flow_db;
651 struct bnxt_ulp_flow_tbl *flow_tbl;
652 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
654 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
656 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
660 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
661 BNXT_TF_DBG(ERR, "Invalid table index\n");
665 flow_tbl = &flow_db->flow_tbl[tbl_idx];
667 /* check for limits of fid */
668 if (fid >= flow_tbl->num_flows || !fid) {
669 BNXT_TF_DBG(ERR, "Invalid flow index\n");
673 /* check if the flow is active or not */
674 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
675 BNXT_TF_DBG(ERR, "flow does not exist\n");
680 fid_resource = &flow_tbl->flow_resources[fid];
681 ulp_flow_db_res_info_to_params(fid_resource, params);
682 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
683 fid_resource->nxt_resource_idx);
685 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
686 ulp_flow_db_res_info_to_params(nxt_resource, params);
688 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
689 nxt_resource->nxt_resource_idx);
692 /* all good, return success */
697 * Get the flow database entry iteratively
699 * flow_tbl [in] Ptr to flow table
700 * fid [in/out] The index to the flow entry
702 * returns 0 on success and negative on failure.
705 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl *flowtbl,
708 uint32_t lfid = *fid;
709 uint32_t idx, s_idx, mod_fid;
713 /* increment the flow id to find the next valid flow id */
715 if (lfid >= flowtbl->num_flows)
717 idx = lfid / ULP_INDEX_BITMAP_SIZE;
718 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
720 while (!(bs = flowtbl->active_flow_tbl[idx])) {
722 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
726 * remove the previous bits in the bitset bs to find the
727 * next non zero bit in the bitset. This needs to be done
728 * only if the idx is same as he one you started.
731 bs &= (-1UL >> mod_fid);
732 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
734 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
737 } while (!ulp_flow_db_active_flow_is_set(flowtbl, lfid));
739 /* all good, return success */
745 * Flush all flows in the flow database.
747 * ulp_ctxt [in] Ptr to ulp context
748 * tbl_idx [in] The index to table
750 * returns 0 on success or negative number on failure
752 int32_t ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
756 struct bnxt_ulp_flow_db *flow_db;
757 struct bnxt_ulp_flow_tbl *flow_tbl;
760 BNXT_TF_DBG(ERR, "Invalid Argument\n");
764 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
766 BNXT_TF_DBG(ERR, "Flow database not found\n");
769 flow_tbl = &flow_db->flow_tbl[idx];
770 while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
771 ulp_mapper_resources_free(ulp_ctx, fid, idx);
777 * Flush all flows in the flow database that belong to a device function.
779 * ulp_ctxt [in] Ptr to ulp context
780 * tbl_idx [in] The index to table
782 * returns 0 on success or negative number on failure
785 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
788 uint32_t flow_id = 0;
789 struct bnxt_ulp_flow_db *flow_db;
790 struct bnxt_ulp_flow_tbl *flow_tbl;
792 if (!ulp_ctx || !func_id) {
793 BNXT_TF_DBG(ERR, "Invalid Argument\n");
797 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
799 BNXT_TF_DBG(ERR, "Flow database not found\n");
802 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
803 while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
804 if (flow_db->func_id_tbl[flow_id] == func_id)
805 ulp_mapper_resources_free(ulp_ctx, flow_id,
806 BNXT_ULP_REGULAR_FLOW_TABLE);
813 * Flush all flows in the flow database that are associated with the session.
815 * ulp_ctxt [in] Ptr to ulp context
817 * returns 0 on success or negative number on failure
820 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
823 * TBD: Tf core implementation of FW session flush shall change this
826 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
830 * Check that flow id matches the function id or not
832 * ulp_ctxt [in] Ptr to ulp context
833 * flow_db [in] Ptr to flow table
834 * func_id [in] The func_id to be set, for reset pass zero.
836 * returns true on success or false on failure
839 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
843 struct bnxt_ulp_flow_db *flow_db;
845 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
847 BNXT_TF_DBG(ERR, "Flow database not found\n");
851 /* set the function id in the function table */
852 if (flow_id < flow_db->func_id_tbl_size && func_id &&
853 flow_db->func_id_tbl[flow_id] == func_id)
860 * Internal api to traverse the resource list within a flow
861 * and match a resource based on resource func and resource
862 * sub type. This api should be used only for resources that
863 * are unique and do not have multiple instances of resource
864 * func and sub type combination since it will return only
868 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
869 enum bnxt_ulp_flow_db_tables tbl_idx,
871 uint32_t resource_func,
872 uint32_t res_subtype,
875 struct bnxt_ulp_flow_db *flow_db;
876 struct bnxt_ulp_flow_tbl *flow_tbl;
877 struct ulp_fdb_resource_info *fid_res;
880 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
882 BNXT_TF_DBG(ERR, "Flow database not found\n");
886 flow_tbl = &flow_db->flow_tbl[tbl_idx];
888 /* check for limits of fid */
889 if (flow_id >= flow_tbl->num_flows || !flow_id) {
890 BNXT_TF_DBG(ERR, "Invalid flow index\n");
894 /* check if the flow is active or not */
895 if (!ulp_flow_db_active_flow_is_set(flow_tbl, flow_id)) {
896 BNXT_TF_DBG(ERR, "flow does not exist\n");
899 /* Iterate the resource to get the resource handle */
902 fid_res = &flow_tbl->flow_resources[res_id];
903 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
904 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
905 if (res_subtype == fid_res->resource_sub_type) {
906 *res_hndl = fid_res->resource_hndl;
910 } else if (resource_func ==
911 BNXT_ULP_RESOURCE_FUNC_EM_TABLE){
912 *res_hndl = fid_res->resource_em_handle;
917 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
923 * Api to get the cfa action pointer from a flow.
925 * ulp_ctxt [in] Ptr to ulp context
926 * flow_id [in] flow id
927 * cfa_action [out] The resource handle stored in the flow database
929 * returns 0 on success
932 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
934 uint32_t *cfa_action)
936 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_ACT_IDX;
940 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
941 BNXT_ULP_DEFAULT_FLOW_TABLE,
943 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
946 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
954 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
956 * Dump the entry details
958 * ulp_ctxt [in] Ptr to ulp_context
962 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
965 uint8_t res_func = ulp_flow_db_resource_func_get(r);
967 BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
968 res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
969 if (res_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE)
970 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
971 r->resource_em_handle);
973 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
976 ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
977 r->nxt_resource_idx);
981 * Dump the flow database entry details
983 * ulp_ctxt [in] Ptr to ulp_context
987 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt)
989 struct bnxt_ulp_flow_db *flow_db;
990 struct bnxt_ulp_flow_tbl *flow_tbl;
991 struct ulp_fdb_resource_info *r;
992 uint32_t nxt_res = 0;
993 enum bnxt_ulp_flow_db_tables tbl_idx;
996 if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
997 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1000 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1002 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1006 for (tbl_idx = 0; tbl_idx < BNXT_ULP_FLOW_TABLE_MAX; tbl_idx++) {
1007 flow_tbl = &flow_db->flow_tbl[tbl_idx];
1008 BNXT_TF_DBG(DEBUG, "Dump Tbl index = %u, flows = %u:%u\n",
1009 tbl_idx, flow_tbl->num_flows,
1010 flow_tbl->num_resources);
1011 BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1012 flow_tbl->head_index, flow_tbl->tail_index);
1013 for (fid = 0; fid < flow_tbl->num_flows; fid++) {
1014 if (ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
1015 BNXT_TF_DBG(DEBUG, "fid = %u\n", fid);
1016 /* iterate the resource */
1019 r = &flow_tbl->flow_resources[nxt_res];
1020 ulp_flow_db_res_dump(r, &nxt_res);
1024 BNXT_TF_DBG(DEBUG, "Done.\n");