#include "ulp_mark_mgr.h"
#include "ulp_flow_db.h"
#include "ulp_mapper.h"
+#include "tf_util.h"
static struct bnxt_ulp_glb_resource_info *
ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
{
if (!num_entries)
return NULL;
- *num_entries = BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
+ *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
return ulp_glb_resource_tbl;
}
tf_free_identifier(tfp, &fparms);
return rc;
}
-#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
- BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n",
- (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
- glb_res->glb_regfile_index, iparms.ident_type, iparms.id);
-#endif
return rc;
}
tf_free_tbl_entry(tfp, &free_parms);
return rc;
}
-#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
- BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n",
- (aparms.dir == TF_DIR_RX) ? "RX" : "TX",
- glb_res->glb_regfile_index, aparms.type, aparms.idx);
-#endif
return rc;
}
};
/*
- * Just set the table scope, it will be ignored if not necessary
+ * Just get the table scope, it will be ignored if not necessary
* by the tf_free_tbl_entry
*/
- bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
+ (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
return tf_free_tbl_entry(tfp, &fparms);
}
return rc;
}
+/*
+ * Process the identifier instruction and extract it from result blob.
+ * Increment the identifier reference count and store it in the flow database.
+ */
+static int32_t
+ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ struct bnxt_ulp_mapper_ident_info *ident,
+ struct ulp_blob *res_blob)
+{
+ struct ulp_flow_db_res_params fid_parms;
+ uint64_t id = 0;
+ uint32_t idx = 0;
+ struct tf_search_identifier_parms sparms = { 0 };
+ struct tf_free_identifier_parms free_parms = { 0 };
+ struct tf *tfp;
+ int rc;
+
+ /* Get the tfp from ulp context */
+ tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
+ if (!tfp) {
+ BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
+ return -EINVAL;
+ }
+
+ /* Extract the index from the result blob */
+ rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
+ ident->ident_bit_pos, ident->ident_bit_size);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
+ return -EIO;
+ }
+
+ /* populate the search params and search identifier shadow table */
+ sparms.ident_type = ident->ident_type;
+ sparms.dir = tbl->direction;
+ /* convert the idx into cpu format */
+ sparms.search_id = tfp_be_to_cpu_32(idx);
+
+ /* Search identifier also increase the reference count */
+ rc = tf_search_identifier(tfp, &sparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Search ident %s:%x failed.\n",
+ tf_dir_2_str(sparms.dir),
+ sparms.search_id);
+ return rc;
+ }
+ BNXT_TF_DBG(INFO, "Search ident %s:%x.success.\n",
+ tf_dir_2_str(sparms.dir),
+ sparms.search_id);
+
+ /* Write it to the regfile */
+ id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
+ if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
+ BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
+ rc = -EINVAL;
+ /* Need to free the identifier, so goto error */
+ goto error;
+ }
+
+ /* Link the resource to the flow in the flow db */
+ memset(&fid_parms, 0, sizeof(fid_parms));
+ fid_parms.direction = tbl->direction;
+ fid_parms.resource_func = ident->resource_func;
+ fid_parms.resource_type = ident->ident_type;
+ fid_parms.resource_hndl = sparms.search_id;
+ fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
+ rc = ulp_flow_db_resource_add(parms->ulp_ctx,
+ parms->tbl_idx,
+ parms->fid,
+ &fid_parms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
+ rc);
+ /* Need to free the identifier, so goto error */
+ goto error;
+ }
+
+ return 0;
+
+error:
+ /* Need to free the identifier */
+ free_parms.dir = tbl->direction;
+ free_parms.ident_type = ident->ident_type;
+ free_parms.id = sparms.search_id;
+ (void)tf_free_identifier(tfp, &free_parms);
+ BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
+ ident->description,
+ tf_dir_2_str(tbl->direction), sparms.search_id);
+ return rc;
+}
+
static int32_t
ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
enum tf_dir dir,
return -EINVAL;
}
+ break;
+ case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST:
+ if (!ulp_operand_read(fld->result_operand,
+ (uint8_t *)&act_bit, sizeof(uint64_t))) {
+ BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
+ return -EINVAL;
+ }
+ act_bit = tfp_be_to_cpu_64(act_bit);
+ if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
+ /* Action bit is set so consider operand_true */
+ if (!ulp_operand_read(fld->result_operand_true,
+ (uint8_t *)&idx,
+ sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "%s operand read failed\n",
+ name);
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n",
+ name, idx);
+ return -EINVAL;
+ }
+ val = &parms->act_prop->act_details[idx];
+ field_size = ulp_mapper_act_prop_size_get(idx);
+ if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
+ field_size = field_size -
+ ((fld->field_bit_size + 7) / 8);
+ val += field_size;
+ }
+ if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
+ BNXT_TF_DBG(ERR, "%s push field failed\n",
+ name);
+ return -EINVAL;
+ }
+ } else {
+ /* action bit is not set, use the operand false */
+ val = fld->result_operand_false;
+ if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
+ BNXT_TF_DBG(ERR, "%s failed to add field\n",
+ name);
+ return -EINVAL;
+ }
+ }
+ break;
+ case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST:
+ if (!ulp_operand_read(fld->result_operand,
+ (uint8_t *)&act_bit, sizeof(uint64_t))) {
+ BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
+ return -EINVAL;
+ }
+ act_bit = tfp_be_to_cpu_64(act_bit);
+ if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
+ /* Action bit is set so consider operand_true */
+ val = fld->result_operand_true;
+ } else {
+ /* action bit is not set, use the operand false */
+ val = fld->result_operand_false;
+ }
+ if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
+ BNXT_TF_DBG(ERR, "%s failed to add field\n",
+ name);
+ return -EINVAL;
+ }
+ break;
+ case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF:
+ if (!ulp_operand_read(fld->result_operand,
+ (uint8_t *)&idx,
+ sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (idx >= BNXT_ULP_CF_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
+ return -EINVAL;
+ }
+ /* check if the computed field is set */
+ if (ULP_COMP_FLD_IDX_RD(parms, idx))
+ val = fld->result_operand_true;
+ else
+ val = fld->result_operand_false;
+
+ /* read the appropriate computed field */
+ if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "%s val operand read failed\n", name);
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (idx >= BNXT_ULP_CF_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
+ return -EINVAL;
+ }
+ val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
+ fld->field_bit_size);
+ if (!val) {
+ BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
+ return -EINVAL;
+ }
break;
default:
+ BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x\n",
+ fld->result_opcode);
return -EINVAL;
}
return 0;
}
break;
default:
+ BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n",
+ opcode);
+ return -EINVAL;
break;
}
struct tf *tfp;
int32_t rc, trc;
struct tf_alloc_tcam_entry_parms aparms = { 0 };
+ struct tf_search_tcam_entry_parms searchparms = { 0 };
struct tf_set_tcam_entry_parms sparms = { 0 };
struct ulp_flow_db_res_params fid_parms = { 0 };
struct tf_free_tcam_entry_parms free_parms = { 0 };
uint32_t hit = 0;
uint16_t tmplen = 0;
+ uint16_t idx;
/* Skip this if was handled by the cache. */
if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
}
}
- aparms.dir = tbl->direction;
- aparms.tcam_tbl_type = tbl->resource_type;
- aparms.search_enable = tbl->srch_b4_alloc;
- aparms.key_sz_in_bits = tbl->key_bit_size;
- aparms.key = ulp_blob_data_get(&key, &tmplen);
- if (tbl->key_bit_size != tmplen) {
- BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
- tmplen, tbl->key_bit_size);
- return -EINVAL;
- }
+ if (!tbl->srch_b4_alloc) {
+ /*
+ * No search for re-use is requested, so simply allocate the
+ * tcam index.
+ */
+ aparms.dir = tbl->direction;
+ aparms.tcam_tbl_type = tbl->resource_type;
+ aparms.search_enable = tbl->srch_b4_alloc;
+ aparms.key_sz_in_bits = tbl->key_bit_size;
+ aparms.key = ulp_blob_data_get(&key, &tmplen);
+ if (tbl->key_bit_size != tmplen) {
+ BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
+ tmplen, tbl->key_bit_size);
+ return -EINVAL;
+ }
- aparms.mask = ulp_blob_data_get(&mask, &tmplen);
- if (tbl->key_bit_size != tmplen) {
- BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
- tmplen, tbl->key_bit_size);
- return -EINVAL;
- }
+ aparms.mask = ulp_blob_data_get(&mask, &tmplen);
+ if (tbl->key_bit_size != tmplen) {
+ BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
+ tmplen, tbl->key_bit_size);
+ return -EINVAL;
+ }
- aparms.priority = tbl->priority;
+ aparms.priority = tbl->priority;
- /*
- * All failures after this succeeds require the entry to be freed.
- * cannot return directly on failure, but needs to goto error
- */
- rc = tf_alloc_tcam_entry(tfp, &aparms);
- if (rc) {
- BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
- return rc;
- }
+ /*
+ * All failures after this succeeds require the entry to be
+ * freed. cannot return directly on failure, but needs to goto
+ * error.
+ */
+ rc = tf_alloc_tcam_entry(tfp, &aparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
+ return rc;
+ }
+ idx = aparms.idx;
+ hit = aparms.hit;
+ } else {
+ /*
+ * Searching before allocation to see if we already have an
+ * entry. This allows re-use of a constrained resource.
+ */
+ searchparms.dir = tbl->direction;
+ searchparms.tcam_tbl_type = tbl->resource_type;
+ searchparms.key = ulp_blob_data_get(&key, &tmplen);
+ searchparms.key_sz_in_bits = tbl->key_bit_size;
+ searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
+ searchparms.priority = tbl->priority;
+ searchparms.alloc = 1;
+ searchparms.result = ulp_blob_data_get(&data, &tmplen);
+ searchparms.result_sz_in_bits = tbl->result_bit_size;
+
+ rc = tf_search_tcam_entry(tfp, &searchparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
+ return rc;
+ }
- hit = aparms.hit;
+ /* Successful search, check the result */
+ if (searchparms.search_status == REJECT) {
+ BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
+ return -ENOMEM;
+ }
+ idx = searchparms.idx;
+ hit = searchparms.hit;
+ }
/* Build the result */
if (!tbl->srch_b4_alloc || !hit) {
}
}
- sparms.dir = aparms.dir;
- sparms.tcam_tbl_type = aparms.tcam_tbl_type;
- sparms.idx = aparms.idx;
+ sparms.dir = tbl->direction;
+ sparms.tcam_tbl_type = tbl->resource_type;
+ sparms.idx = idx;
/* Already verified the key/mask lengths */
sparms.key = ulp_blob_data_get(&key, &tmplen);
sparms.mask = ulp_blob_data_get(&mask, &tmplen);
rc = -EINVAL;
goto error;
}
- parms->cache_ptr->tcam_idx = aparms.idx;
+ parms->cache_ptr->tcam_idx = idx;
}
/* Mark action */
goto error;
} else {
- BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
- rc = -EINVAL;
- goto error;
+ struct bnxt_ulp_mapper_ident_info *idents;
+ uint32_t num_idents;
+
+ /*
+ * Extract the listed identifiers from the result field,
+ * no need to allocate them.
+ */
+ idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
+ for (i = 0; i < num_idents; i++) {
+ rc = ulp_mapper_ident_extract(parms, tbl,
+ &idents[i], &data);
+ if (rc) {
+ BNXT_TF_DBG(ERR,
+ "Error in ident extraction\n");
+ goto error;
+ }
+ }
}
/*
fid_parms.resource_func = tbl->resource_func;
fid_parms.resource_type = tbl->resource_type;
fid_parms.critical_resource = tbl->critical_resource;
- fid_parms.resource_hndl = aparms.idx;
+ fid_parms.resource_hndl = idx;
rc = ulp_flow_db_resource_add(parms->ulp_ctx,
parms->tbl_idx,
parms->fid,
return rc;
}
}
-#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
- ulp_mapper_result_dump("EEM Result", tbl, &data);
-#endif
/* do the transpose for the internal EM keys */
if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
/* if encap bit swap is enabled perform the bit swap */
if (parms->device_params->encap_byte_swap && encap_flds) {
ulp_blob_perform_encap_swap(&data);
-#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
- BNXT_TF_DBG(INFO, "Dump after encap swap\n");
- ulp_mapper_blob_dump(&data);
-#endif
}
/*
}
/* Get the index details from computed field */
- if (tbl->index_opcode != BNXT_ULP_INDEX_OPCODE_COMP_FIELD) {
+ if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) {
+ idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand);
+ } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) {
+ idx = tbl->index_operand;
+ } else {
BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
return -EINVAL;
}
- idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand);
/* Perform the tf table set by filling the set params */
iftbl_params.dir = tbl->direction;
return rc;
}
+/*
+ * Function to process the conditional opcode of the mapper table.
+ * returns 1 to skip the table.
+ * return 0 to continue processing the table.
+ */
+static int32_t
+ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ int32_t rc = 1;
+
+ switch (tbl->cond_opcode) {
+ case BNXT_ULP_COND_OPCODE_NOP:
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET:
+ if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
+ ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET:
+ if (ULP_BITMAP_ISSET(parms->act_bitmap->bits,
+ tbl->cond_operand))
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET:
+ if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
+ tbl->cond_operand))
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET:
+ if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
+ !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET:
+ if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits,
+ tbl->cond_operand))
+ rc = 0;
+ break;
+ case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET:
+ if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
+ tbl->cond_operand))
+ rc = 0;
+ break;
+ default:
+ BNXT_TF_DBG(ERR,
+ "Invalid arg in mapper tbl for cond opcode\n");
+ break;
+ }
+ return rc;
+}
+
/*
* Function to process the action template. Iterate through the list
* action info templates and process it.
for (i = 0; i < parms->num_atbls; i++) {
tbl = &parms->atbls[i];
+ if (ulp_mapper_tbl_cond_opcode_process(parms, tbl))
+ continue;
+
switch (tbl->resource_func) {
case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
rc = ulp_mapper_index_tbl_process(parms, tbl, false);
for (i = 0; i < parms->num_ctbls; i++) {
struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i];
+ if (ulp_mapper_tbl_cond_opcode_process(parms, tbl))
+ continue;
+
switch (tbl->resource_func) {
case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
rc = ulp_mapper_tcam_tbl_process(parms, tbl);
/* Iterate the global resources and process each one */
for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
- for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ;
+ for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
idx++) {
ent = &mapper_data->glb_res_tbl[dir][idx];
if (ent->resource_func ==
}
int32_t
-ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid)
+ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid,
+ enum bnxt_ulp_flow_db_tables flow_tbl_type)
{
if (!ulp_ctx) {
BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
return -EINVAL;
}
- return ulp_mapper_resources_free(ulp_ctx,
- fid,
- BNXT_ULP_REGULAR_FLOW_TABLE);
+ return ulp_mapper_resources_free(ulp_ctx, fid, flow_tbl_type);
}
/* Function to handle the default global templates that are allocated during
memset(&parms, 0, sizeof(parms));
parms.act_prop = cparms->act_prop;
parms.act_bitmap = cparms->act;
+ parms.hdr_bitmap = cparms->hdr_bitmap;
parms.regfile = ®file;
parms.hdr_field = cparms->hdr_field;
parms.comp_fld = cparms->comp_fld;
flow_error:
/* Free all resources that were allocated during flow creation */
- trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid);
+ trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid,
+ BNXT_ULP_REGULAR_FLOW_TABLE);
if (trc)
BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);