From: Somnath Kotur <somnath.kotur@broadcom.com>
To: dev@dpdk.org
Cc: ferruh.yigit@intel.com
Subject: [dpdk-dev] [PATCH v2 01/20] net/bnxt: add shadow tcam capability with search
Date: Thu, 23 Jul 2020 17:26:20 +0530 [thread overview]
Message-ID: <20200723115639.22357-2-somnath.kotur@broadcom.com> (raw)
In-Reply-To: <20200723115639.22357-1-somnath.kotur@broadcom.com>
From: Mike Baucom <michael.baucom@broadcom.com>
- Add TCAM shadow tables for searching
- Add Search API to allow reuse of TCAM entries
Signed-off-by: Mike Baucom <michael.baucom@broadcom.com>
Reviewed-by: Randy Schacher <stuart.schacher@broadcom.com>
---
drivers/net/bnxt/tf_core/tf_core.c | 73 +++
drivers/net/bnxt/tf_core/tf_core.h | 101 ++++
drivers/net/bnxt/tf_core/tf_device_p4.c | 2 +-
drivers/net/bnxt/tf_core/tf_shadow_tcam.c | 885 +++++++++++++++++++++++++++++-
drivers/net/bnxt/tf_core/tf_shadow_tcam.h | 258 ++++-----
drivers/net/bnxt/tf_core/tf_tcam.c | 300 +++++++++-
drivers/net/bnxt/tf_core/tf_tcam.h | 31 +-
7 files changed, 1449 insertions(+), 201 deletions(-)
diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c
index 97e7952..ca3280b 100644
--- a/drivers/net/bnxt/tf_core/tf_core.c
+++ b/drivers/net/bnxt/tf_core/tf_core.c
@@ -608,6 +608,79 @@ tf_search_identifier(struct tf *tfp,
}
int
+tf_search_tcam_entry(struct tf *tfp,
+ struct tf_search_tcam_entry_parms *parms)
+{
+ int rc;
+ struct tf_session *tfs;
+ struct tf_dev_info *dev;
+ struct tf_tcam_alloc_search_parms sparms;
+
+ TF_CHECK_PARMS2(tfp, parms);
+
+ memset(&sparms, 0, sizeof(struct tf_tcam_alloc_search_parms));
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session(tfp, &tfs);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Failed to lookup session, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Retrieve the device information */
+ rc = tf_session_get_device(tfs, &dev);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Failed to lookup device, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ if (dev->ops->tf_dev_alloc_search_tcam == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ sparms.dir = parms->dir;
+ sparms.type = parms->tcam_tbl_type;
+ sparms.key = parms->key;
+ sparms.key_size = TF_BITS2BYTES_WORD_ALIGN(parms->key_sz_in_bits);
+ sparms.mask = parms->mask;
+ sparms.priority = parms->priority;
+ sparms.alloc = parms->alloc;
+
+ /* Result is an in/out and so no need to copy during outputs */
+ sparms.result = parms->result;
+ sparms.result_size =
+ TF_BITS2BYTES_WORD_ALIGN(parms->result_sz_in_bits);
+
+ rc = dev->ops->tf_dev_alloc_search_tcam(tfp, &sparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: TCAM allocation failed, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Copy the outputs */
+ parms->hit = sparms.hit;
+ parms->search_status = sparms.search_status;
+ parms->ref_cnt = sparms.ref_cnt;
+ parms->idx = sparms.idx;
+
+ return 0;
+}
+
+int
tf_alloc_tcam_entry(struct tf *tfp,
struct tf_alloc_tcam_entry_parms *parms)
{
diff --git a/drivers/net/bnxt/tf_core/tf_core.h b/drivers/net/bnxt/tf_core/tf_core.h
index 67415ad..349a1f1 100644
--- a/drivers/net/bnxt/tf_core/tf_core.h
+++ b/drivers/net/bnxt/tf_core/tf_core.h
@@ -291,6 +291,18 @@ enum tf_tcam_tbl_type {
};
/**
+ * TCAM SEARCH STATUS
+ */
+enum tf_tcam_search_status {
+ /** The entry was not found, but an idx was allocated if requested. */
+ MISS,
+ /** The entry was found, and the result/idx are valid */
+ HIT,
+ /** The entry was not found and the table is full */
+ REJECT
+};
+
+/**
* EM Resources
* These defines are provisioned during
* tf_open_session()
@@ -949,6 +961,8 @@ int tf_free_tbl_scope(struct tf *tfp,
/**
* @page tcam TCAM Access
*
+ * @ref tf_search_tcam_entry
+ *
* @ref tf_alloc_tcam_entry
*
* @ref tf_set_tcam_entry
@@ -958,6 +972,93 @@ int tf_free_tbl_scope(struct tf *tfp,
* @ref tf_free_tcam_entry
*/
+/**
+ * tf_search_tcam_entry parameter definition (experimental)
+ */
+struct tf_search_tcam_entry_parms {
+ /**
+ * [in] receive or transmit direction
+ */
+ enum tf_dir dir;
+ /**
+ * [in] TCAM table type
+ */
+ enum tf_tcam_tbl_type tcam_tbl_type;
+ /**
+ * [in] Key data to match on
+ */
+ uint8_t *key;
+ /**
+ * [in] key size in bits
+ */
+ uint16_t key_sz_in_bits;
+ /**
+ * [in] Mask data to match on
+ */
+ uint8_t *mask;
+ /**
+ * [in] Priority of entry requested (definition TBD)
+ */
+ uint32_t priority;
+ /**
+ * [in] Allocate on miss.
+ */
+ uint8_t alloc;
+ /**
+ * [out] Set if matching entry found
+ */
+ uint8_t hit;
+ /**
+ * [out] Search result status (hit, miss, reject)
+ */
+ enum tf_tcam_search_status search_status;
+ /**
+ * [out] Current refcnt after allocation
+ */
+ uint16_t ref_cnt;
+ /**
+ * [in out] The result data from the search is copied here
+ */
+ uint8_t *result;
+ /**
+ * [in out] result size in bits for the result data
+ */
+ uint16_t result_sz_in_bits;
+ /**
+ * [out] Index found
+ */
+ uint16_t idx;
+};
+
+/**
+ * search TCAM entry (experimental)
+ *
+ * Search for a TCAM entry
+ *
+ * This function searches the shadow copy of the TCAM table for a matching
+ * entry. Key and mask must match for hit to be set. Only TruFlow core data
+ * is accessed. If shadow_copy is not enabled, an error is returned.
+ *
+ * Implementation:
+ *
+ * A hash is performed on the key/mask data and mapped to a shadow copy entry
+ * where the full key/mask is populated. If the full key/mask matches the
+ * entry, hit is set, ref_cnt is incremented, and search_status indicates what
+ * action the caller can take regarding setting the entry.
+ *
+ * search_status should be used as follows:
+ * - On Miss, the caller should create a result and call tf_set_tcam_entry with
+ * returned index.
+ *
+ * - On Reject, the hash table is full and the entry cannot be added.
+ *
+ * - On Hit, the result data is returned to the caller. Additionally, the
+ * ref_cnt is updated.
+ *
+ * Also returns success or failure code.
+ */
+int tf_search_tcam_entry(struct tf *tfp,
+ struct tf_search_tcam_entry_parms *parms);
/**
* tf_alloc_tcam_entry parameter definition
diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c
index f38c38e..afb6098 100644
--- a/drivers/net/bnxt/tf_core/tf_device_p4.c
+++ b/drivers/net/bnxt/tf_core/tf_device_p4.c
@@ -133,7 +133,7 @@ const struct tf_dev_ops tf_dev_ops_p4 = {
.tf_dev_get_bulk_tbl = tf_tbl_bulk_get,
.tf_dev_alloc_tcam = tf_tcam_alloc,
.tf_dev_free_tcam = tf_tcam_free,
- .tf_dev_alloc_search_tcam = NULL,
+ .tf_dev_alloc_search_tcam = tf_tcam_alloc_search,
.tf_dev_set_tcam = tf_tcam_set,
.tf_dev_get_tcam = NULL,
.tf_dev_insert_int_em_entry = tf_em_insert_int_entry,
diff --git a/drivers/net/bnxt/tf_core/tf_shadow_tcam.c b/drivers/net/bnxt/tf_core/tf_shadow_tcam.c
index c61b833..51aae4f 100644
--- a/drivers/net/bnxt/tf_core/tf_shadow_tcam.c
+++ b/drivers/net/bnxt/tf_core/tf_shadow_tcam.c
@@ -3,61 +3,902 @@
* All rights reserved.
*/
-#include <rte_common.h>
-
+#include "tf_common.h"
+#include "tf_util.h"
+#include "tfp.h"
#include "tf_shadow_tcam.h"
/**
- * Shadow tcam DB element
+ * The implementation includes 3 tables per tcam table type.
+ * - hash table
+ * - sized so that a minimum of 4 slots per shadow entry are available to
+ * minimize the likelihood of collisions.
+ * - shadow key table
+ * - sized to the number of entries requested and is directly indexed
+ * - the index is zero based and is the tcam index - the base address
+ * - the key and mask are stored in the key table.
+ * - The stored key is the AND of the key/mask in order to eliminate the need
+ * to compare both the key and mask.
+ * - shadow result table
+ * - the result table is stored separately since it only needs to be accessed
+ * when the key matches.
+ * - the result has a back pointer to the hash table via the hb handle. The
+ * hb handle is a 32 bit represention of the hash with a valid bit, bucket
+ * element index, and the hash index. It is necessary to store the hb handle
+ * with the result since subsequent removes only provide the tcam index.
+ *
+ * - Max entries is limited in the current implementation since bit 15 is the
+ * valid bit in the hash table.
+ * - A 16bit hash is calculated and masked based on the number of entries
+ * - 64b wide bucket is used and broken into 4x16bit elements.
+ * This decision is based on quicker bucket scanning to determine if any
+ * elements are in use.
+ * - bit 15 of each bucket element is the valid, this is done to prevent having
+ * to read the larger key/result data for determining VALID. It also aids
+ * in the more efficient scanning of the bucket for slot usage.
*/
-struct tf_shadow_tcam_element {
- /**
- * Hash table
- */
- void *hash;
- /**
- * Reference count, array of number of tcam entries
- */
- uint16_t *ref_count;
+/*
+ * The maximum number of shadow entries supported. The value also doubles as
+ * the maximum number of hash buckets. There are only 15 bits of data per
+ * bucket to point to the shadow tables.
+ */
+#define TF_SHADOW_TCAM_ENTRIES_MAX (1 << 15)
+
+/* The number of elements(BE) per hash bucket (HB) */
+#define TF_SHADOW_TCAM_HB_NUM_ELEM (4)
+#define TF_SHADOW_TCAM_BE_VALID (1 << 15)
+#define TF_SHADOW_TCAM_BE_IS_VALID(be) (((be) & TF_SHADOW_TCAM_BE_VALID) != 0)
+
+/**
+ * The hash bucket handle is 32b
+ * - bit 31, the Valid bit
+ * - bit 29-30, the element
+ * - bits 0-15, the hash idx (is masked based on the allocated size)
+ */
+#define TF_SHADOW_TCAM_HB_HANDLE_IS_VALID(hndl) (((hndl) & (1 << 31)) != 0)
+#define TF_SHADOW_TCAM_HB_HANDLE_CREATE(idx, be) ((1 << 31) | \
+ ((be) << 29) | (idx))
+
+#define TF_SHADOW_TCAM_HB_HANDLE_BE_GET(hdl) (((hdl) >> 29) & \
+ (TF_SHADOW_TCAM_HB_NUM_ELEM - 1))
+
+#define TF_SHADOW_TCAM_HB_HANDLE_HASH_GET(ctxt, hdl)((hdl) & \
+ (ctxt)->hash_ctxt.hid_mask)
+
+/**
+ * The idx provided by the caller is within a region, so currently the base is
+ * either added or subtracted from the idx to ensure it can be used as a
+ * compressed index
+ */
+
+/* Convert the tcam index to a shadow index */
+#define TF_SHADOW_TCAM_IDX_TO_SHIDX(ctxt, idx) ((idx) - \
+ (ctxt)->shadow_ctxt.base_addr)
+
+/* Convert the shadow index to a tcam index */
+#define TF_SHADOW_TCAM_SHIDX_TO_IDX(ctxt, idx) ((idx) + \
+ (ctxt)->shadow_ctxt.base_addr)
+
+/* Simple helper masks for clearing en element from the bucket */
+#define TF_SHADOW_TCAM_BE0_MASK_CLEAR(hb) ((hb) & 0xffffffffffff0000ull)
+#define TF_SHADOW_TCAM_BE1_MASK_CLEAR(hb) ((hb) & 0xffffffff0000ffffull)
+#define TF_SHADOW_TCAM_BE2_MASK_CLEAR(hb) ((hb) & 0xffff0000ffffffffull)
+#define TF_SHADOW_TCAM_BE3_MASK_CLEAR(hb) ((hb) & 0x0000ffffffffffffull)
+
+/**
+ * This should be coming from external, but for now it is assumed that no key
+ * is greater than 1K bits and no result is bigger than 128 bits. This makes
+ * allocation of the hash table easier without having to allocate on the fly.
+ */
+#define TF_SHADOW_TCAM_MAX_KEY_SZ 128
+#define TF_SHADOW_TCAM_MAX_RESULT_SZ 16
+
+/*
+ * Local only defines for the internal data.
+ */
+
+/**
+ * tf_shadow_tcam_shadow_key_entry is the key/mask entry of the key table.
+ * The key stored in the table is the masked version of the key. This is done
+ * to eliminate the need of comparing both the key and mask.
+ */
+struct tf_shadow_tcam_shadow_key_entry {
+ uint8_t key[TF_SHADOW_TCAM_MAX_KEY_SZ];
+ uint8_t mask[TF_SHADOW_TCAM_MAX_KEY_SZ];
};
/**
- * Shadow tcam DB definition
+ * tf_shadow_tcam_shadow_result_entry is the result table entry.
+ * The result table writes are broken into two phases:
+ * - The search phase, which stores the hb_handle and key size and
+ * - The set phase, which writes the result, refcnt, and result size
+ */
+struct tf_shadow_tcam_shadow_result_entry {
+ uint8_t result[TF_SHADOW_TCAM_MAX_RESULT_SZ];
+ uint16_t result_size;
+ uint16_t key_size;
+ uint32_t refcnt;
+ uint32_t hb_handle;
+};
+
+/**
+ * tf_shadow_tcam_shadow_ctxt holds all information for accessing the key and
+ * result tables.
+ */
+struct tf_shadow_tcam_shadow_ctxt {
+ struct tf_shadow_tcam_shadow_key_entry *sh_key_tbl;
+ struct tf_shadow_tcam_shadow_result_entry *sh_res_tbl;
+ uint32_t base_addr;
+ uint16_t num_entries;
+ uint16_t alloc_idx;
+};
+
+/**
+ * tf_shadow_tcam_hash_ctxt holds all information related to accessing the hash
+ * table.
+ */
+struct tf_shadow_tcam_hash_ctxt {
+ uint64_t *hashtbl;
+ uint16_t hid_mask;
+ uint16_t hash_entries;
+};
+
+/**
+ * tf_shadow_tcam_ctxt holds the hash and shadow tables for the current shadow
+ * tcam db. This structure is per tcam table type as each tcam table has it's
+ * own shadow and hash table.
+ */
+struct tf_shadow_tcam_ctxt {
+ struct tf_shadow_tcam_shadow_ctxt shadow_ctxt;
+ struct tf_shadow_tcam_hash_ctxt hash_ctxt;
+};
+
+/**
+ * tf_shadow_tcam_db is the allocated db structure returned as an opaque
+ * void * pointer to the caller during create db. It holds the pointers for
+ * each tcam associated with the db.
*/
struct tf_shadow_tcam_db {
- /**
- * The DB consists of an array of elements
- */
- struct tf_shadow_tcam_element *db;
+ /* Each context holds the shadow and hash table information */
+ struct tf_shadow_tcam_ctxt *ctxt[TF_TCAM_TBL_TYPE_MAX];
+};
+
+/* CRC polynomial 0xedb88320 */
+static const uint32_t tf_shadow_tcam_crc32tbl[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
+/**
+ * Returns the number of entries in the contexts shadow table.
+ */
+static inline uint16_t
+tf_shadow_tcam_sh_num_entries_get(struct tf_shadow_tcam_ctxt *ctxt)
+{
+ return ctxt->shadow_ctxt.num_entries;
+}
+
+/**
+ * Compare the give key with the key in the shadow table.
+ *
+ * Returns 0 if the keys match
+ */
+static int
+tf_shadow_tcam_key_cmp(struct tf_shadow_tcam_ctxt *ctxt,
+ uint8_t *key,
+ uint8_t *mask,
+ uint16_t sh_idx,
+ uint16_t size)
+{
+ if (size != ctxt->shadow_ctxt.sh_res_tbl[sh_idx].key_size ||
+ sh_idx >= tf_shadow_tcam_sh_num_entries_get(ctxt) || !key || !mask)
+ return -1;
+
+ return memcmp(key, ctxt->shadow_ctxt.sh_key_tbl[sh_idx].key, size);
+}
+
+/**
+ * Copies the shadow result to the result.
+ *
+ * Returns 0 on failure
+ */
+static void *
+tf_shadow_tcam_res_cpy(struct tf_shadow_tcam_ctxt *ctxt,
+ uint8_t *result,
+ uint16_t sh_idx,
+ uint16_t size)
+{
+ if (sh_idx >= tf_shadow_tcam_sh_num_entries_get(ctxt) || !result)
+ return 0;
+
+ if (ctxt->shadow_ctxt.sh_res_tbl[sh_idx].result_size != size)
+ return 0;
+
+ return memcpy(result,
+ ctxt->shadow_ctxt.sh_res_tbl[sh_idx].result,
+ size);
+}
+
+/**
+ * Using a software based CRC function for now, but will look into using hw
+ * assisted in the future.
+ */
+static uint32_t
+tf_shadow_tcam_crc32_calc(uint8_t *key, uint32_t len)
+{
+ uint32_t crc = ~0U;
+
+ while (len--)
+ crc = tf_shadow_tcam_crc32tbl[(crc ^ key[len]) & 0xff] ^
+ (crc >> 8);
+
+ return ~crc;
+}
+
+/**
+ * Free the memory associated with the context.
+ */
+static void
+tf_shadow_tcam_ctxt_delete(struct tf_shadow_tcam_ctxt *ctxt)
+{
+ if (!ctxt)
+ return;
+
+ tfp_free(ctxt->hash_ctxt.hashtbl);
+ tfp_free(ctxt->shadow_ctxt.sh_key_tbl);
+ tfp_free(ctxt->shadow_ctxt.sh_res_tbl);
+}
+
+/**
+ * The TF Shadow TCAM context is per TCAM and holds all information relating to
+ * managing the shadow and search capability. This routine allocated data that
+ * needs to be deallocated by the tf_shadow_tcam_ctxt_delete prior when deleting
+ * the shadow db.
+ */
+static int
+tf_shadow_tcam_ctxt_create(struct tf_shadow_tcam_ctxt *ctxt,
+ uint16_t num_entries,
+ uint16_t base_addr)
+{
+ struct tfp_calloc_parms cparms;
+ uint16_t hash_size = 1;
+ uint16_t hash_mask;
+ int rc;
+
+ /* Hash table is a power of two that holds the number of entries */
+ if (num_entries > TF_SHADOW_TCAM_ENTRIES_MAX) {
+ TFP_DRV_LOG(ERR, "Too many entries for shadow %d > %d\n",
+ num_entries,
+ TF_SHADOW_TCAM_ENTRIES_MAX);
+ return -ENOMEM;
+ }
+
+ while (hash_size < num_entries)
+ hash_size = hash_size << 1;
+
+ hash_mask = hash_size - 1;
+
+ /* Allocate the hash table */
+ cparms.nitems = hash_size;
+ cparms.size = sizeof(uint64_t);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ goto error;
+ ctxt->hash_ctxt.hashtbl = cparms.mem_va;
+ ctxt->hash_ctxt.hid_mask = hash_mask;
+ ctxt->hash_ctxt.hash_entries = hash_size;
+
+ /* allocate the shadow tables */
+ /* allocate the shadow key table */
+ cparms.nitems = num_entries;
+ cparms.size = sizeof(struct tf_shadow_tcam_shadow_key_entry);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ goto error;
+ ctxt->shadow_ctxt.sh_key_tbl = cparms.mem_va;
+
+ /* allocate the shadow result table */
+ cparms.nitems = num_entries;
+ cparms.size = sizeof(struct tf_shadow_tcam_shadow_result_entry);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ goto error;
+ ctxt->shadow_ctxt.sh_res_tbl = cparms.mem_va;
+
+ ctxt->shadow_ctxt.num_entries = num_entries;
+ ctxt->shadow_ctxt.base_addr = base_addr;
+
+ return 0;
+error:
+ tf_shadow_tcam_ctxt_delete(ctxt);
+
+ return -ENOMEM;
+}
+
+/**
+ * Get a shadow TCAM context given the db and the TCAM type
+ */
+static struct tf_shadow_tcam_ctxt *
+tf_shadow_tcam_ctxt_get(struct tf_shadow_tcam_db *shadow_db,
+ enum tf_tcam_tbl_type type)
+{
+ if (type >= TF_TCAM_TBL_TYPE_MAX ||
+ !shadow_db ||
+ !shadow_db->ctxt[type])
+ return NULL;
+
+ return shadow_db->ctxt[type];
+}
+
+/**
+ * Sets the hash entry into the table given the TCAM context, hash bucket
+ * handle, and shadow index.
+ */
+static inline int
+tf_shadow_tcam_set_hash_entry(struct tf_shadow_tcam_ctxt *ctxt,
+ uint32_t hb_handle,
+ uint16_t sh_idx)
+{
+ uint16_t hid = TF_SHADOW_TCAM_HB_HANDLE_HASH_GET(ctxt, hb_handle);
+ uint16_t be = TF_SHADOW_TCAM_HB_HANDLE_BE_GET(hb_handle);
+ uint64_t entry = sh_idx | TF_SHADOW_TCAM_BE_VALID;
+
+ if (hid >= ctxt->hash_ctxt.hash_entries)
+ return -EINVAL;
+
+ ctxt->hash_ctxt.hashtbl[hid] |= entry << (be * 16);
+ return 0;
+}
+
+/**
+ * Clears the hash entry given the TCAM context and hash bucket handle.
+ */
+static inline void
+tf_shadow_tcam_clear_hash_entry(struct tf_shadow_tcam_ctxt *ctxt,
+ uint32_t hb_handle)
+{
+ uint16_t hid, be;
+ uint64_t *bucket;
+
+ if (!TF_SHADOW_TCAM_HB_HANDLE_IS_VALID(hb_handle))
+ return;
+
+ hid = TF_SHADOW_TCAM_HB_HANDLE_HASH_GET(ctxt, hb_handle);
+ be = TF_SHADOW_TCAM_HB_HANDLE_BE_GET(hb_handle);
+ bucket = &ctxt->hash_ctxt.hashtbl[hid];
+
+ switch (be) {
+ case 0:
+ *bucket = TF_SHADOW_TCAM_BE0_MASK_CLEAR(*bucket);
+ break;
+ case 1:
+ *bucket = TF_SHADOW_TCAM_BE1_MASK_CLEAR(*bucket);
+ break;
+ case 2:
+ *bucket = TF_SHADOW_TCAM_BE2_MASK_CLEAR(*bucket);
+ break;
+ case 3:
+ *bucket = TF_SHADOW_TCAM_BE2_MASK_CLEAR(*bucket);
+ break;
+ }
+}
+
+/**
+ * Clears the shadow key and result entries given the TCAM context and
+ * shadow index.
+ */
+static void
+tf_shadow_tcam_clear_sh_entry(struct tf_shadow_tcam_ctxt *ctxt,
+ uint16_t sh_idx)
+{
+ struct tf_shadow_tcam_shadow_key_entry *sk_entry;
+ struct tf_shadow_tcam_shadow_result_entry *sr_entry;
+
+ if (sh_idx >= tf_shadow_tcam_sh_num_entries_get(ctxt))
+ return;
+
+ sk_entry = &ctxt->shadow_ctxt.sh_key_tbl[sh_idx];
+ sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[sh_idx];
+
+ /*
+ * memset key/result to zero for now, possibly leave the data alone
+ * in the future and rely on the valid bit in the hash table.
+ */
+ memset(sk_entry, 0, sizeof(struct tf_shadow_tcam_shadow_key_entry));
+ memset(sr_entry, 0, sizeof(struct tf_shadow_tcam_shadow_result_entry));
+}
+
+/**
+ * Binds the allocated tcam index with the hash and shadow tables.
+ * The entry will be incomplete until the set has happened with the result
+ * data.
+ */
int
-tf_shadow_tcam_create_db(struct tf_shadow_tcam_create_db_parms *parms __rte_unused)
+tf_shadow_tcam_bind_index(struct tf_shadow_tcam_bind_index_parms *parms)
{
+ int rc;
+ int i;
+ uint16_t idx, klen;
+ struct tf_shadow_tcam_ctxt *ctxt;
+ struct tf_shadow_tcam_db *shadow_db;
+ struct tf_shadow_tcam_shadow_key_entry *sk_entry;
+ struct tf_shadow_tcam_shadow_result_entry *sr_entry;
+ uint8_t tkey[TF_SHADOW_TCAM_MAX_KEY_SZ];
+
+ if (!parms || !TF_SHADOW_TCAM_HB_HANDLE_IS_VALID(parms->hb_handle) ||
+ !parms->key || !parms->mask) {
+ TFP_DRV_LOG(ERR, "Invalid parms\n");
+ return -EINVAL;
+ }
+
+ shadow_db = (struct tf_shadow_tcam_db *)parms->shadow_db;
+ ctxt = tf_shadow_tcam_ctxt_get(shadow_db, parms->type);
+ if (!ctxt) {
+ TFP_DRV_LOG(DEBUG, "%s no ctxt for table\n",
+ tf_tcam_tbl_2_str(parms->type));
+ return -EINVAL;
+ }
+
+ memset(tkey, 0, sizeof(tkey));
+ idx = TF_SHADOW_TCAM_IDX_TO_SHIDX(ctxt, parms->idx);
+ klen = parms->key_size;
+ if (idx >= tf_shadow_tcam_sh_num_entries_get(ctxt) ||
+ klen > TF_SHADOW_TCAM_MAX_KEY_SZ) {
+ TFP_DRV_LOG(ERR, "%s:%s Invalid len (%d) > %d || oob idx %d\n",
+ tf_dir_2_str(parms->dir),
+ tf_tcam_tbl_2_str(parms->type),
+ klen,
+ TF_SHADOW_TCAM_MAX_KEY_SZ, idx);
+
+ return -EINVAL;
+ }
+
+ rc = tf_shadow_tcam_set_hash_entry(ctxt, parms->hb_handle, idx);
+ if (rc)
+ return -EINVAL;
+
+ sk_entry = &ctxt->shadow_ctxt.sh_key_tbl[idx];
+ sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
+
+ /*
+ * Write the masked key to the table for more efficient comparisons
+ * later.
+ */
+ for (i = 0; i < klen; i++)
+ tkey[i] = parms->key[i] & parms->mask[i];
+
+ memcpy(sk_entry->key, tkey, klen);
+ memcpy(sk_entry->mask, parms->mask, klen);
+
+ /* Write the result table */
+ sr_entry->key_size = parms->key_size;
+ sr_entry->hb_handle = parms->hb_handle;
+
return 0;
}
+/**
+ * Deletes hash/shadow information if no more references.
+ *
+ * Returns 0 - The caller should delete the tcam entry in hardware.
+ * Returns non-zero - The number of references to the entry
+ */
int
-tf_shadow_tcam_free_db(struct tf_shadow_tcam_free_db_parms *parms __rte_unused)
+tf_shadow_tcam_remove(struct tf_shadow_tcam_remove_parms *parms)
{
+ uint16_t idx;
+ uint32_t hb_handle;
+ struct tf_shadow_tcam_ctxt *ctxt;
+ struct tf_shadow_tcam_db *shadow_db;
+ struct tf_tcam_free_parms *fparms;
+ struct tf_shadow_tcam_shadow_result_entry *sr_entry;
+
+ if (!parms || !parms->fparms) {
+ TFP_DRV_LOG(ERR, "Invalid parms\n");
+ return -EINVAL;
+ }
+
+ fparms = parms->fparms;
+
+ /*
+ * Initialize the reference count to zero. It will only be changed if
+ * non-zero.
+ */
+ fparms->ref_cnt = 0;
+
+ shadow_db = (struct tf_shadow_tcam_db *)parms->shadow_db;
+ ctxt = tf_shadow_tcam_ctxt_get(shadow_db, fparms->type);
+ if (!ctxt) {
+ TFP_DRV_LOG(DEBUG, "%s no ctxt for table\n",
+ tf_tcam_tbl_2_str(fparms->type));
+ return 0;
+ }
+
+ idx = TF_SHADOW_TCAM_IDX_TO_SHIDX(ctxt, fparms->idx);
+ if (idx >= tf_shadow_tcam_sh_num_entries_get(ctxt)) {
+ TFP_DRV_LOG(DEBUG, "%s %d >= %d\n",
+ tf_tcam_tbl_2_str(fparms->type),
+ fparms->idx,
+ tf_shadow_tcam_sh_num_entries_get(ctxt));
+ return 0;
+ }
+
+ sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
+ if (sr_entry->refcnt <= 1) {
+ hb_handle = sr_entry->hb_handle;
+ tf_shadow_tcam_clear_hash_entry(ctxt, hb_handle);
+ tf_shadow_tcam_clear_sh_entry(ctxt, idx);
+ } else {
+ sr_entry->refcnt--;
+ fparms->ref_cnt = sr_entry->refcnt;
+ }
+
return 0;
}
int
-tf_shadow_tcam_search(struct tf_shadow_tcam_search_parms *parms __rte_unused)
+tf_shadow_tcam_search(struct tf_shadow_tcam_search_parms *parms)
{
+ uint16_t len;
+ uint8_t rcopy;
+ uint64_t bucket;
+ uint32_t i, hid32;
+ struct tf_shadow_tcam_ctxt *ctxt;
+ struct tf_shadow_tcam_db *shadow_db;
+ uint16_t hid16, hb_idx, hid_mask, shtbl_idx, shtbl_key, be_valid;
+ struct tf_tcam_alloc_search_parms *sparms;
+ uint8_t tkey[TF_SHADOW_TCAM_MAX_KEY_SZ];
+ uint32_t be_avail = TF_SHADOW_TCAM_HB_NUM_ELEM;
+
+ if (!parms || !parms->sparms) {
+ TFP_DRV_LOG(ERR, "tcam search with invalid parms\n");
+ return -EINVAL;
+ }
+
+ memset(tkey, 0, sizeof(tkey));
+ sparms = parms->sparms;
+
+ /* Initialize return values to invalid */
+ sparms->hit = 0;
+ sparms->search_status = REJECT;
+ parms->hb_handle = 0;
+ sparms->ref_cnt = 0;
+ /* see if caller wanted the result */
+ rcopy = sparms->result && sparms->result_size;
+
+ shadow_db = (struct tf_shadow_tcam_db *)parms->shadow_db;
+ ctxt = tf_shadow_tcam_ctxt_get(shadow_db, sparms->type);
+ if (!ctxt) {
+ TFP_DRV_LOG(ERR, "%s Unable to get tcam mgr context\n",
+ tf_tcam_tbl_2_str(sparms->type));
+ return -EINVAL;
+ }
+
+ hid_mask = ctxt->hash_ctxt.hid_mask;
+
+ len = sparms->key_size;
+
+ if (len > TF_SHADOW_TCAM_MAX_KEY_SZ ||
+ !sparms->key || !sparms->mask || !len) {
+ TFP_DRV_LOG(ERR, "%s:%s Invalid parms %d : %p : %p\n",
+ tf_dir_2_str(sparms->dir),
+ tf_tcam_tbl_2_str(sparms->type),
+ len,
+ sparms->key,
+ sparms->mask);
+ return -EINVAL;
+ }
+
+ /* Combine the key and mask */
+ for (i = 0; i < len; i++)
+ tkey[i] = sparms->key[i] & sparms->mask[i];
+
+ /*
+ * Calculate the crc32
+ * Fold it to create a 16b value
+ * Reduce it to fit the table
+ */
+ hid32 = tf_shadow_tcam_crc32_calc(tkey, len);
+ hid16 = (uint16_t)(((hid32 >> 16) & 0xffff) ^ (hid32 & 0xffff));
+ hb_idx = hid16 & hid_mask;
+
+ bucket = ctxt->hash_ctxt.hashtbl[hb_idx];
+
+ if (!bucket) {
+ /* empty bucket means a miss and available entry */
+ sparms->search_status = MISS;
+ parms->hb_handle = TF_SHADOW_TCAM_HB_HANDLE_CREATE(hb_idx, 0);
+ sparms->idx = 0;
+ return 0;
+ }
+
+ /* Set the avail to max so we can detect when there is an avail entry */
+ be_avail = TF_SHADOW_TCAM_HB_NUM_ELEM;
+ for (i = 0; i < TF_SHADOW_TCAM_HB_NUM_ELEM; i++) {
+ shtbl_idx = (uint16_t)((bucket >> (i * 16)) & 0xffff);
+ be_valid = TF_SHADOW_TCAM_BE_IS_VALID(shtbl_idx);
+ if (!be_valid) {
+ /* The element is avail, keep going */
+ be_avail = i;
+ continue;
+ }
+ /* There is a valid entry, compare it */
+ shtbl_key = shtbl_idx & ~TF_SHADOW_TCAM_BE_VALID;
+ if (!tf_shadow_tcam_key_cmp(ctxt,
+ sparms->key,
+ sparms->mask,
+ shtbl_key,
+ sparms->key_size)) {
+ /*
+ * It matches, increment the ref count if the caller
+ * requested allocation and return the info
+ */
+ if (sparms->alloc)
+ ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt =
+ ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt + 1;
+
+ sparms->hit = 1;
+ sparms->search_status = HIT;
+ parms->hb_handle =
+ TF_SHADOW_TCAM_HB_HANDLE_CREATE(hb_idx, i);
+ sparms->idx = TF_SHADOW_TCAM_SHIDX_TO_IDX(ctxt,
+ shtbl_key);
+ sparms->ref_cnt =
+ ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt;
+
+ /* copy the result, if caller wanted it. */
+ if (rcopy &&
+ !tf_shadow_tcam_res_cpy(ctxt,
+ sparms->result,
+ shtbl_key,
+ sparms->result_size)) {
+ /*
+ * Should never get here, possible memory
+ * corruption or something unexpected.
+ */
+ TFP_DRV_LOG(ERR, "Error copying result\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+ }
+
+ /* No hits, return avail entry if exists */
+ if (be_avail < TF_SHADOW_TCAM_HB_NUM_ELEM) {
+ parms->hb_handle =
+ TF_SHADOW_TCAM_HB_HANDLE_CREATE(hb_idx, be_avail);
+ sparms->search_status = MISS;
+ sparms->hit = 0;
+ sparms->idx = 0;
+ } else {
+ sparms->search_status = REJECT;
+ }
+
return 0;
}
int
-tf_shadow_tcam_insert(struct tf_shadow_tcam_insert_parms *parms __rte_unused)
+tf_shadow_tcam_insert(struct tf_shadow_tcam_insert_parms *parms)
{
+ uint16_t idx;
+ struct tf_shadow_tcam_ctxt *ctxt;
+ struct tf_tcam_set_parms *sparms;
+ struct tf_shadow_tcam_db *shadow_db;
+ struct tf_shadow_tcam_shadow_result_entry *sr_entry;
+
+ if (!parms || !parms->sparms) {
+ TFP_DRV_LOG(ERR, "Null parms\n");
+ return -EINVAL;
+ }
+
+ sparms = parms->sparms;
+ if (!sparms->result || !sparms->result_size) {
+ TFP_DRV_LOG(ERR, "%s:%s No result to set.\n",
+ tf_dir_2_str(sparms->dir),
+ tf_tcam_tbl_2_str(sparms->type));
+ return -EINVAL;
+ }
+
+ shadow_db = (struct tf_shadow_tcam_db *)parms->shadow_db;
+ ctxt = tf_shadow_tcam_ctxt_get(shadow_db, sparms->type);
+ if (!ctxt) {
+ /* We aren't tracking this table, so return success */
+ TFP_DRV_LOG(DEBUG, "%s Unable to get tcam mgr context\n",
+ tf_tcam_tbl_2_str(sparms->type));
+ return 0;
+ }
+
+ idx = TF_SHADOW_TCAM_IDX_TO_SHIDX(ctxt, sparms->idx);
+ if (idx >= tf_shadow_tcam_sh_num_entries_get(ctxt)) {
+ TFP_DRV_LOG(ERR, "%s:%s Invalid idx(0x%x)\n",
+ tf_dir_2_str(sparms->dir),
+ tf_tcam_tbl_2_str(sparms->type),
+ sparms->idx);
+ return -EINVAL;
+ }
+
+ /* Write the result table, the key/hash has been written already */
+ sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
+
+ /*
+ * If the handle is not valid, the bind was never called. We aren't
+ * tracking this entry.
+ */
+ if (!TF_SHADOW_TCAM_HB_HANDLE_IS_VALID(sr_entry->hb_handle))
+ return 0;
+
+ if (sparms->result_size > TF_SHADOW_TCAM_MAX_RESULT_SZ) {
+ TFP_DRV_LOG(ERR, "%s:%s Result length %d > %d\n",
+ tf_dir_2_str(sparms->dir),
+ tf_tcam_tbl_2_str(sparms->type),
+ sparms->result_size,
+ TF_SHADOW_TCAM_MAX_RESULT_SZ);
+ return -EINVAL;
+ }
+
+ memcpy(sr_entry->result, sparms->result, sparms->result_size);
+ sr_entry->result_size = sparms->result_size;
+ sr_entry->refcnt = 1;
+
return 0;
}
int
-tf_shadow_tcam_remove(struct tf_shadow_tcam_remove_parms *parms __rte_unused)
+tf_shadow_tcam_free_db(struct tf_shadow_tcam_free_db_parms *parms)
+{
+ struct tf_shadow_tcam_db *shadow_db;
+ int i;
+
+ TF_CHECK_PARMS1(parms);
+
+ shadow_db = (struct tf_shadow_tcam_db *)parms->shadow_db;
+ if (!shadow_db) {
+ TFP_DRV_LOG(DEBUG, "Shadow db is NULL cannot be freed\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
+ if (shadow_db->ctxt[i]) {
+ tf_shadow_tcam_ctxt_delete(shadow_db->ctxt[i]);
+ tfp_free(shadow_db->ctxt[i]);
+ }
+ }
+
+ tfp_free(shadow_db);
+
+ return 0;
+}
+
+/**
+ * Allocate the TCAM resources for search and allocate
+ *
+ */
+int tf_shadow_tcam_create_db(struct tf_shadow_tcam_create_db_parms *parms)
{
+ int rc;
+ int i;
+ uint16_t base;
+ struct tfp_calloc_parms cparms;
+ struct tf_shadow_tcam_db *shadow_db = NULL;
+
+ TF_CHECK_PARMS1(parms);
+
+ /* Build the shadow DB per the request */
+ cparms.nitems = 1;
+ cparms.size = sizeof(struct tf_shadow_tcam_db);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ return rc;
+ shadow_db = (void *)cparms.mem_va;
+
+ for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
+ /* If the element didn't request an allocation no need
+ * to create a pool nor verify if we got a reservation.
+ */
+ if (!parms->cfg->alloc_cnt[i]) {
+ shadow_db->ctxt[i] = NULL;
+ continue;
+ }
+
+ cparms.nitems = 1;
+ cparms.size = sizeof(struct tf_shadow_tcam_ctxt);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ goto error;
+
+ shadow_db->ctxt[i] = cparms.mem_va;
+ base = parms->cfg->base_addr[i];
+ rc = tf_shadow_tcam_ctxt_create(shadow_db->ctxt[i],
+ parms->cfg->alloc_cnt[i],
+ base);
+ if (rc)
+ goto error;
+ }
+
+ *parms->shadow_db = (void *)shadow_db;
+
+ TFP_DRV_LOG(INFO,
+ "TF SHADOW TCAM - initialized\n");
+
return 0;
+error:
+ for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
+ if (shadow_db->ctxt[i]) {
+ tf_shadow_tcam_ctxt_delete(shadow_db->ctxt[i]);
+ tfp_free(shadow_db->ctxt[i]);
+ }
+ }
+
+ tfp_free(shadow_db);
+
+ return -ENOMEM;
}
diff --git a/drivers/net/bnxt/tf_core/tf_shadow_tcam.h b/drivers/net/bnxt/tf_core/tf_shadow_tcam.h
index e2c4e06..75c146a 100644
--- a/drivers/net/bnxt/tf_core/tf_shadow_tcam.h
+++ b/drivers/net/bnxt/tf_core/tf_shadow_tcam.h
@@ -8,232 +8,188 @@
#include "tf_core.h"
-struct tf;
-
-/**
- * The Shadow tcam module provides shadow DB handling for tcam based
- * TF types. A shadow DB provides the capability that allows for reuse
- * of TF resources.
- *
- * A Shadow tcam DB is intended to be used by the Tcam module only.
- */
-
/**
- * Shadow DB configuration information for a single tcam type.
- *
- * During Device initialization the HCAPI device specifics are learned
- * and as well as the RM DB creation. From that those initial steps
- * this structure can be populated.
+ * Shadow DB configuration information
*
- * NOTE:
- * If used in an array of tcam types then such array must be ordered
- * by the TF type is represents.
+ * The shadow configuration is for all tcam table types for a direction
*/
struct tf_shadow_tcam_cfg_parms {
/**
- * TF tcam type
+ * [in] The number of elements in the alloc_cnt and base_addr
+ * For now, it should always be equal to TF_TCAM_TBL_TYPE_MAX
*/
- enum tf_tcam_tbl_type type;
-
+ int num_entries;
/**
- * Number of entries the Shadow DB needs to hold
+ * [in] Resource allocation count array
+ * This array content originates from the tf_session_resources
+ * that is passed in on session open
+ * Array size is TF_TCAM_TBL_TYPE_MAX
*/
- int num_entries;
-
+ uint16_t *alloc_cnt;
/**
- * Element width for this table type
+ * [in] The base index for each tcam table
*/
- int element_width;
+ uint16_t base_addr[TF_TCAM_TBL_TYPE_MAX];
};
/**
- * Shadow tcam DB creation parameters
+ * Shadow TCAM DB creation parameters. The shadow db for this direction
+ * is returned
*/
struct tf_shadow_tcam_create_db_parms {
/**
- * [in] Configuration information for the shadow db
+ * [in] Receive or transmit direction
*/
- struct tf_shadow_tcam_cfg_parms *cfg;
+ enum tf_dir dir;
/**
- * [in] Number of elements in the parms structure
+ * [in] Configuration information for the shadow db
*/
- uint16_t num_elements;
+ struct tf_shadow_tcam_cfg_parms *cfg;
/**
* [out] Shadow tcam DB handle
*/
- void *tf_shadow_tcam_db;
+ void **shadow_db;
};
/**
- * Shadow tcam DB free parameters
+ * Create the shadow db for a single direction
+ *
+ * The returned shadow db must be free using the free db API when no longer
+ * needed
*/
-struct tf_shadow_tcam_free_db_parms {
- /**
- * Shadow tcam DB handle
- */
- void *tf_shadow_tcam_db;
-};
+int
+tf_shadow_tcam_create_db(struct tf_shadow_tcam_create_db_parms *parms);
/**
- * Shadow tcam search parameters
+ * Shadow TCAM free parameters
*/
-struct tf_shadow_tcam_search_parms {
+struct tf_shadow_tcam_free_db_parms {
/**
* [in] Shadow tcam DB handle
*/
- void *tf_shadow_tcam_db;
- /**
- * [in] TCAM tbl type
- */
- enum tf_tcam_tbl_type type;
- /**
- * [in] Pointer to entry blob value in remap table to match
- */
- uint8_t *entry;
- /**
- * [in] Size of the entry blob passed in bytes
- */
- uint16_t entry_sz;
- /**
- * [out] Index of the found element returned if hit
- */
- uint16_t *index;
- /**
- * [out] Reference count incremented if hit
- */
- uint16_t *ref_cnt;
+ void *shadow_db;
};
/**
- * Shadow tcam insert parameters
+ * Free all resources associated with the shadow db
+ */
+int
+tf_shadow_tcam_free_db(struct tf_shadow_tcam_free_db_parms *parms);
+
+/**
+ * Shadow TCAM bind index parameters
*/
-struct tf_shadow_tcam_insert_parms {
+struct tf_shadow_tcam_bind_index_parms {
/**
* [in] Shadow tcam DB handle
*/
- void *tf_shadow_tcam_db;
+ void *shadow_db;
/**
- * [in] TCAM tbl type
+ * [in] receive or transmit direction
+ */
+ enum tf_dir dir;
+ /**
+ * [in] TCAM table type
*/
enum tf_tcam_tbl_type type;
/**
- * [in] Pointer to entry blob value in remap table to match
+ * [in] index of the entry to program
*/
- uint8_t *entry;
+ uint16_t idx;
/**
- * [in] Size of the entry blob passed in bytes
+ * [in] struct containing key
*/
- uint16_t entry_sz;
+ uint8_t *key;
/**
- * [in] Entry to update
+ * [in] struct containing mask fields
*/
- uint16_t index;
+ uint8_t *mask;
/**
- * [out] Reference count after insert
+ * [in] key size in bits (if search)
*/
- uint16_t *ref_cnt;
+ uint16_t key_size;
+ /**
+ * [in] The hash bucket handled returned from the search
+ */
+ uint32_t hb_handle;
};
/**
- * Shadow tcam remove parameters
+ * Binds the allocated tcam index with the hash and shadow tables
*/
-struct tf_shadow_tcam_remove_parms {
+int
+tf_shadow_tcam_bind_index(struct tf_shadow_tcam_bind_index_parms *parms);
+
+/**
+ * Shadow TCAM insert parameters
+ */
+struct tf_shadow_tcam_insert_parms {
/**
* [in] Shadow tcam DB handle
*/
- void *tf_shadow_tcam_db;
- /**
- * [in] TCAM tbl type
- */
- enum tf_tcam_tbl_type type;
- /**
- * [in] Entry to update
- */
- uint16_t index;
+ void *shadow_db;
/**
- * [out] Reference count after removal
+ * [in] The set parms from tf core
*/
- uint16_t *ref_cnt;
+ struct tf_tcam_set_parms *sparms;
};
/**
- * @page shadow_tcam Shadow tcam DB
- *
- * @ref tf_shadow_tcam_create_db
- *
- * @ref tf_shadow_tcam_free_db
- *
- * @reg tf_shadow_tcam_search
- *
- * @reg tf_shadow_tcam_insert
- *
- * @reg tf_shadow_tcam_remove
- */
-
-/**
- * Creates and fills a Shadow tcam DB. The DB is indexed per the
- * parms structure.
- *
- * [in] parms
- * Pointer to create db parameters
+ * Set the entry into the tcam manager hash and shadow tables
*
- * Returns
- * - (0) if successful.
- * - (-EINVAL) on failure.
+ * The search must have been used prior to setting the entry so that the
+ * hash has been calculated and duplicate entries will not be added
*/
-int tf_shadow_tcam_create_db(struct tf_shadow_tcam_create_db_parms *parms);
+int
+tf_shadow_tcam_insert(struct tf_shadow_tcam_insert_parms *parms);
/**
- * Closes the Shadow tcam DB and frees all allocated
- * resources per the associated database.
- *
- * [in] parms
- * Pointer to the free DB parameters
- *
- * Returns
- * - (0) if successful.
- * - (-EINVAL) on failure.
+ * Shadow TCAM remove parameters
*/
-int tf_shadow_tcam_free_db(struct tf_shadow_tcam_free_db_parms *parms);
+struct tf_shadow_tcam_remove_parms {
+ /**
+ * [in] Shadow tcam DB handle
+ */
+ void *shadow_db;
+ /**
+ * [inout] The set parms from tf core
+ */
+ struct tf_tcam_free_parms *fparms;
+};
/**
- * Search Shadow tcam db for matching result
- *
- * [in] parms
- * Pointer to the search parameters
+ * Remove the entry from the tcam hash and shadow tables
*
- * Returns
- * - (0) if successful, element was found.
- * - (-EINVAL) on failure.
+ * The search must have been used prior to setting the entry so that the
+ * hash has been calculated and duplicate entries will not be added
*/
-int tf_shadow_tcam_search(struct tf_shadow_tcam_search_parms *parms);
+int
+tf_shadow_tcam_remove(struct tf_shadow_tcam_remove_parms *parms);
/**
- * Inserts an element into the Shadow tcam DB. Will fail if the
- * elements ref_count is different from 0. Ref_count after insert will
- * be incremented.
- *
- * [in] parms
- * Pointer to insert parameters
- *
- * Returns
- * - (0) if successful.
- * - (-EINVAL) on failure.
+ * Shadow TCAM search parameters
*/
-int tf_shadow_tcam_insert(struct tf_shadow_tcam_insert_parms *parms);
+struct tf_shadow_tcam_search_parms {
+ /**
+ * [in] Shadow tcam DB handle
+ */
+ void *shadow_db;
+ /**
+ * [inout] The search parameters from tf core
+ */
+ struct tf_tcam_alloc_search_parms *sparms;
+ /**
+ * [out] The hash handle to use for the set
+ */
+ uint32_t hb_handle;
+};
/**
- * Removes an element from the Shadow tcam DB. Will fail if the
- * elements ref_count is 0. Ref_count after removal will be
- * decremented.
+ * Search for an entry in the tcam hash/shadow tables
*
- * [in] parms
- * Pointer to remove parameter
- *
- * Returns
- * - (0) if successful.
- * - (-EINVAL) on failure.
+ * If there is a miss, but there is room for insertion, the hb_handle returned
+ * is used for insertion during the bind index API
*/
-int tf_shadow_tcam_remove(struct tf_shadow_tcam_remove_parms *parms);
-
-#endif /* _TF_SHADOW_TCAM_H_ */
+int
+tf_shadow_tcam_search(struct tf_shadow_tcam_search_parms *parms);
+#endif
diff --git a/drivers/net/bnxt/tf_core/tf_tcam.c b/drivers/net/bnxt/tf_core/tf_tcam.c
index cbfaa94..7679d09 100644
--- a/drivers/net/bnxt/tf_core/tf_tcam.c
+++ b/drivers/net/bnxt/tf_core/tf_tcam.c
@@ -14,6 +14,7 @@
#include "tfp.h"
#include "tf_session.h"
#include "tf_msg.h"
+#include "tf_shadow_tcam.h"
struct tf;
@@ -25,7 +26,7 @@ static void *tcam_db[TF_DIR_MAX];
/**
* TCAM Shadow DBs
*/
-/* static void *shadow_tcam_db[TF_DIR_MAX]; */
+static void *shadow_tcam_db[TF_DIR_MAX];
/**
* Init flag, set on bind and cleared on unbind
@@ -35,16 +36,22 @@ static uint8_t init;
/**
* Shadow init flag, set on bind and cleared on unbind
*/
-/* static uint8_t shadow_init; */
+static uint8_t shadow_init;
int
tf_tcam_bind(struct tf *tfp,
struct tf_tcam_cfg_parms *parms)
{
int rc;
- int i;
+ int i, d;
+ struct tf_rm_alloc_info info;
+ struct tf_rm_free_db_parms fparms;
+ struct tf_rm_create_db_parms db_cfg;
struct tf_tcam_resources *tcam_cnt;
- struct tf_rm_create_db_parms db_cfg = { 0 };
+ struct tf_shadow_tcam_free_db_parms fshadow;
+ struct tf_rm_get_alloc_info_parms ainfo;
+ struct tf_shadow_tcam_cfg_parms shadow_cfg;
+ struct tf_shadow_tcam_create_db_parms shadow_cdb;
TF_CHECK_PARMS2(tfp, parms);
@@ -62,29 +69,91 @@ tf_tcam_bind(struct tf *tfp,
return -EINVAL;
}
+ memset(&db_cfg, 0, sizeof(db_cfg));
+
db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM;
db_cfg.num_elements = parms->num_elements;
db_cfg.cfg = parms->cfg;
- for (i = 0; i < TF_DIR_MAX; i++) {
- db_cfg.dir = i;
- db_cfg.alloc_cnt = parms->resources->tcam_cnt[i].cnt;
- db_cfg.rm_db = &tcam_db[i];
+ for (d = 0; d < TF_DIR_MAX; d++) {
+ db_cfg.dir = d;
+ db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt;
+ db_cfg.rm_db = &tcam_db[d];
rc = tf_rm_create_db(tfp, &db_cfg);
if (rc) {
TFP_DRV_LOG(ERR,
"%s: TCAM DB creation failed\n",
- tf_dir_2_str(i));
+ tf_dir_2_str(d));
return rc;
}
}
+ /* Initialize the TCAM manager. */
+ if (parms->shadow_copy) {
+ for (d = 0; d < TF_DIR_MAX; d++) {
+ memset(&shadow_cfg, 0, sizeof(shadow_cfg));
+ memset(&shadow_cdb, 0, sizeof(shadow_cdb));
+ /* Get the base addresses of the tcams for tcam mgr */
+ for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
+ memset(&info, 0, sizeof(info));
+
+ if (!parms->resources->tcam_cnt[d].cnt[i])
+ continue;
+ ainfo.rm_db = tcam_db[d];
+ ainfo.db_index = i;
+ ainfo.info = &info;
+ rc = tf_rm_get_info(&ainfo);
+ if (rc)
+ goto error;
+
+ shadow_cfg.base_addr[i] = info.entry.start;
+ }
+
+ /* Create the shadow db */
+ shadow_cfg.alloc_cnt =
+ parms->resources->tcam_cnt[d].cnt;
+ shadow_cfg.num_entries = parms->num_elements;
+
+ shadow_cdb.shadow_db = &shadow_tcam_db[d];
+ shadow_cdb.cfg = &shadow_cfg;
+ rc = tf_shadow_tcam_create_db(&shadow_cdb);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "TCAM MGR DB creation failed "
+ "rc=%d\n", rc);
+ goto error;
+ }
+ }
+ shadow_init = 1;
+ }
+
init = 1;
TFP_DRV_LOG(INFO,
"TCAM - initialized\n");
return 0;
+error:
+ for (i = 0; i < TF_DIR_MAX; i++) {
+ memset(&fparms, 0, sizeof(fparms));
+ fparms.dir = i;
+ fparms.rm_db = tcam_db[i];
+ /* Ignoring return here since we are in the error case */
+ (void)tf_rm_free_db(tfp, &fparms);
+
+ if (parms->shadow_copy) {
+ fshadow.shadow_db = shadow_tcam_db[i];
+ tf_shadow_tcam_free_db(&fshadow);
+ shadow_tcam_db[i] = NULL;
+ }
+
+ tcam_db[i] = NULL;
+ }
+
+ shadow_init = 0;
+ init = 0;
+
+ return rc;
}
int
@@ -92,7 +161,8 @@ tf_tcam_unbind(struct tf *tfp)
{
int rc;
int i;
- struct tf_rm_free_db_parms fparms = { 0 };
+ struct tf_rm_free_db_parms fparms;
+ struct tf_shadow_tcam_free_db_parms fshadow;
TF_CHECK_PARMS1(tfp);
@@ -104,6 +174,7 @@ tf_tcam_unbind(struct tf *tfp)
}
for (i = 0; i < TF_DIR_MAX; i++) {
+ memset(&fparms, 0, sizeof(fparms));
fparms.dir = i;
fparms.rm_db = tcam_db[i];
rc = tf_rm_free_db(tfp, &fparms);
@@ -111,8 +182,17 @@ tf_tcam_unbind(struct tf *tfp)
return rc;
tcam_db[i] = NULL;
+
+ if (shadow_init) {
+ memset(&fshadow, 0, sizeof(fshadow));
+
+ fshadow.shadow_db = shadow_tcam_db[i];
+ tf_shadow_tcam_free_db(&fshadow);
+ shadow_tcam_db[i] = NULL;
+ }
}
+ shadow_init = 0;
init = 0;
return 0;
@@ -125,7 +205,7 @@ tf_tcam_alloc(struct tf *tfp,
int rc;
struct tf_session *tfs;
struct tf_dev_info *dev;
- struct tf_rm_allocate_parms aparms = { 0 };
+ struct tf_rm_allocate_parms aparms;
uint16_t num_slice_per_row = 1;
TF_CHECK_PARMS2(tfp, parms);
@@ -165,6 +245,8 @@ tf_tcam_alloc(struct tf *tfp,
return rc;
/* Allocate requested element */
+ memset(&aparms, 0, sizeof(aparms));
+
aparms.rm_db = tcam_db[parms->dir];
aparms.db_index = parms->type;
aparms.priority = parms->priority;
@@ -202,11 +284,12 @@ tf_tcam_free(struct tf *tfp,
int rc;
struct tf_session *tfs;
struct tf_dev_info *dev;
- struct tf_rm_is_allocated_parms aparms = { 0 };
- struct tf_rm_free_parms fparms = { 0 };
- struct tf_rm_get_hcapi_parms hparms = { 0 };
+ struct tf_rm_is_allocated_parms aparms;
+ struct tf_rm_free_parms fparms;
+ struct tf_rm_get_hcapi_parms hparms;
uint16_t num_slice_per_row = 1;
int allocated = 0;
+ struct tf_shadow_tcam_remove_parms shparms;
TF_CHECK_PARMS2(tfp, parms);
@@ -245,6 +328,8 @@ tf_tcam_free(struct tf *tfp,
return rc;
/* Check if element is in use */
+ memset(&aparms, 0, sizeof(aparms));
+
aparms.rm_db = tcam_db[parms->dir];
aparms.db_index = parms->type;
aparms.index = parms->idx / num_slice_per_row;
@@ -262,7 +347,37 @@ tf_tcam_free(struct tf *tfp,
return -EINVAL;
}
+ /*
+ * The Shadow mgmt, if enabled, determines if the entry needs
+ * to be deleted.
+ */
+ if (shadow_init) {
+ shparms.shadow_db = shadow_tcam_db[parms->dir];
+ shparms.fparms = parms;
+ rc = tf_shadow_tcam_remove(&shparms);
+ if (rc) {
+ /*
+ * Should not get here, log it and let the entry be
+ * deleted.
+ */
+ TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
+ "type:%d index:%d deleting the entry.\n",
+ tf_dir_2_str(parms->dir),
+ parms->type,
+ parms->idx);
+ } else {
+ /*
+ * If the entry still has references, just return the
+ * ref count to the caller. No need to remove entry
+ * from rm or hw
+ */
+ if (parms->ref_cnt >= 1)
+ return rc;
+ }
+ }
+
/* Free requested element */
+ memset(&fparms, 0, sizeof(fparms));
fparms.rm_db = tcam_db[parms->dir];
fparms.db_index = parms->type;
fparms.index = parms->idx / num_slice_per_row;
@@ -291,7 +406,8 @@ tf_tcam_free(struct tf *tfp,
rc = tf_rm_free(&fparms);
if (rc) {
TFP_DRV_LOG(ERR,
- "%s: Free failed, type:%d, index:%d\n",
+ "%s: Free failed, type:%d, "
+ "index:%d\n",
tf_dir_2_str(parms->dir),
parms->type,
fparms.index);
@@ -302,6 +418,8 @@ tf_tcam_free(struct tf *tfp,
}
/* Convert TF type to HCAPI RM type */
+ memset(&hparms, 0, sizeof(hparms));
+
hparms.rm_db = tcam_db[parms->dir];
hparms.db_index = parms->type;
hparms.hcapi_type = &parms->hcapi_type;
@@ -326,9 +444,131 @@ tf_tcam_free(struct tf *tfp,
}
int
-tf_tcam_alloc_search(struct tf *tfp __rte_unused,
- struct tf_tcam_alloc_search_parms *parms __rte_unused)
+tf_tcam_alloc_search(struct tf *tfp,
+ struct tf_tcam_alloc_search_parms *parms)
{
+ struct tf_shadow_tcam_search_parms sparms;
+ struct tf_shadow_tcam_bind_index_parms bparms;
+ struct tf_tcam_alloc_parms aparms;
+ struct tf_tcam_free_parms fparms;
+ uint16_t num_slice_per_row = 1;
+ struct tf_session *tfs;
+ struct tf_dev_info *dev;
+ int rc;
+
+ TF_CHECK_PARMS2(tfp, parms);
+
+ if (!init) {
+ TFP_DRV_LOG(ERR,
+ "%s: No TCAM DBs created\n",
+ tf_dir_2_str(parms->dir));
+ return -EINVAL;
+ }
+
+ if (!shadow_init || !shadow_tcam_db[parms->dir]) {
+ TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n",
+ tf_dir_2_str(parms->dir),
+ tf_tcam_tbl_2_str(parms->type));
+ return -EINVAL;
+ }
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ /* Retrieve the device information */
+ rc = tf_session_get_device(tfs, &dev);
+ if (rc)
+ return rc;
+
+ if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Need to retrieve row size etc */
+ rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
+ parms->type,
+ parms->key_size,
+ &num_slice_per_row);
+ if (rc)
+ return rc;
+
+ /*
+ * Prep the shadow search, reusing the parms from original search
+ * instead of copying them. Shadow will update output in there.
+ */
+ memset(&sparms, 0, sizeof(sparms));
+ sparms.sparms = parms;
+ sparms.shadow_db = shadow_tcam_db[parms->dir];
+
+ rc = tf_shadow_tcam_search(&sparms);
+ if (rc)
+ return rc;
+
+ /*
+ * The app didn't request us to alloc the entry, so return now.
+ * The hit should have been updated in the original search parm.
+ */
+ if (!parms->alloc || parms->search_status != MISS)
+ return rc;
+
+ /* Caller desires an allocate on miss */
+ if (dev->ops->tf_dev_alloc_tcam == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+ memset(&aparms, 0, sizeof(aparms));
+ aparms.dir = parms->dir;
+ aparms.type = parms->type;
+ aparms.key_size = parms->key_size;
+ aparms.priority = parms->priority;
+ rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms);
+ if (rc)
+ return rc;
+
+ /* Successful allocation, attempt to add it to the shadow */
+ memset(&bparms, 0, sizeof(bparms));
+ bparms.dir = parms->dir;
+ bparms.shadow_db = shadow_tcam_db[parms->dir];
+ bparms.type = parms->type;
+ bparms.key = parms->key;
+ bparms.mask = parms->mask;
+ bparms.key_size = parms->key_size;
+ bparms.idx = aparms.idx;
+ bparms.hb_handle = sparms.hb_handle;
+ rc = tf_shadow_tcam_bind_index(&bparms);
+ if (rc) {
+ /* Error binding entry, need to free the allocated idx */
+ if (dev->ops->tf_dev_free_tcam == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ fparms.dir = parms->dir;
+ fparms.type = parms->type;
+ fparms.idx = aparms.idx;
+ rc = dev->ops->tf_dev_free_tcam(tfp, &fparms);
+ if (rc)
+ return rc;
+ }
+
+ /* Add the allocated index to output and done */
+ parms->idx = aparms.idx;
+
return 0;
}
@@ -339,8 +579,9 @@ tf_tcam_set(struct tf *tfp __rte_unused,
int rc;
struct tf_session *tfs;
struct tf_dev_info *dev;
- struct tf_rm_is_allocated_parms aparms = { 0 };
- struct tf_rm_get_hcapi_parms hparms = { 0 };
+ struct tf_rm_is_allocated_parms aparms;
+ struct tf_rm_get_hcapi_parms hparms;
+ struct tf_shadow_tcam_insert_parms iparms;
uint16_t num_slice_per_row = 1;
int allocated = 0;
@@ -381,6 +622,8 @@ tf_tcam_set(struct tf *tfp __rte_unused,
return rc;
/* Check if element is in use */
+ memset(&aparms, 0, sizeof(aparms));
+
aparms.rm_db = tcam_db[parms->dir];
aparms.db_index = parms->type;
aparms.index = parms->idx / num_slice_per_row;
@@ -399,6 +642,8 @@ tf_tcam_set(struct tf *tfp __rte_unused,
}
/* Convert TF type to HCAPI RM type */
+ memset(&hparms, 0, sizeof(hparms));
+
hparms.rm_db = tcam_db[parms->dir];
hparms.db_index = parms->type;
hparms.hcapi_type = &parms->hcapi_type;
@@ -419,6 +664,23 @@ tf_tcam_set(struct tf *tfp __rte_unused,
return rc;
}
+ /* Successfully added to hw, now for shadow if enabled. */
+ if (!shadow_init || !shadow_tcam_db[parms->dir])
+ return 0;
+
+ iparms.shadow_db = shadow_tcam_db[parms->dir];
+ iparms.sparms = parms;
+ rc = tf_shadow_tcam_insert(&iparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: %s: Entry %d set failed, rc:%s",
+ tf_dir_2_str(parms->dir),
+ tf_tcam_tbl_2_str(parms->type),
+ parms->idx,
+ strerror(-rc));
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/net/bnxt/tf_core/tf_tcam.h b/drivers/net/bnxt/tf_core/tf_tcam.h
index ee5bacc..4722ce0 100644
--- a/drivers/net/bnxt/tf_core/tf_tcam.h
+++ b/drivers/net/bnxt/tf_core/tf_tcam.h
@@ -104,19 +104,19 @@ struct tf_tcam_alloc_search_parms {
*/
enum tf_tcam_tbl_type type;
/**
- * [in] Enable search for matching entry
+ * [in] Type of HCAPI
*/
- uint8_t search_enable;
+ uint16_t hcapi_type;
/**
- * [in] Key data to match on (if search)
+ * [in] Key data to match on
*/
uint8_t *key;
/**
- * [in] key size (if search)
+ * [in] key size in bits
*/
uint16_t key_size;
/**
- * [in] Mask data to match on (if search)
+ * [in] Mask data to match on
*/
uint8_t *mask;
/**
@@ -124,16 +124,31 @@ struct tf_tcam_alloc_search_parms {
*/
uint32_t priority;
/**
- * [out] If search, set if matching entry found
+ * [in] Allocate on miss.
+ */
+ uint8_t alloc;
+ /**
+ * [out] Set if matching entry found
*/
uint8_t hit;
/**
+ * [out] Search result status (hit, miss, reject)
+ */
+ enum tf_tcam_search_status search_status;
+ /**
* [out] Current refcnt after allocation
*/
uint16_t ref_cnt;
/**
- * [out] Idx allocated
- *
+ * [inout] The result data from the search is copied here
+ */
+ uint8_t *result;
+ /**
+ * [inout] result size in bits for the result data
+ */
+ uint16_t result_size;
+ /**
+ * [out] Index found
*/
uint16_t idx;
};
--
2.7.4
next prev parent reply other threads:[~2020-07-23 12:02 UTC|newest]
Thread overview: 102+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-23 11:13 [dpdk-dev] [PATCH 00/20] bnxt patches Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 01/20] net/bnxt: add shadow tcam capability with search Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 02/20] net/bnxt: nat global registers support Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 03/20] net/bnxt: parif for offload miss rules Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 04/20] net/bnxt: ulp mapper changes to use tcam search Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 05/20] net/bnxt: add tf hash API Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 06/20] net/bnxt: skip mark id injection into mbuf Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 07/20] net/bnxt: nat template changes Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 08/20] net/bnxt: configure parif for the egress rules Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 09/20] net/bnxt: ignore VLAN priority mask Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 10/20] net/bnxt: add egress template with VLAN tag match Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 11/20] net/bnxt: modify tf shadow tcam to use common tf hash Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 12/20] net/bnxt: added shadow table capability with search Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 13/20] net/bnxt: ulp mapper changes to use tbl search Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 14/20] net/bnxt: fix port default rule create and destroy Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 15/20] net/bnxt: delete VF FW rules when a representor is created Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 16/20] net/bnxt: shadow tcam and tbl reference count modification Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 17/20] net/bnxt: tcam table processing support for search and alloc Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 18/20] net/bnxt: added templates for search before alloc Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 19/20] net/bnxt: enabled shadow tables during session open Somnath Kotur
2020-07-23 11:13 ` [dpdk-dev] [PATCH 20/20] net/bnxt: cleanup of VF-representor dev ops Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 00/20] bnxt patches Somnath Kotur
2020-07-23 11:56 ` Somnath Kotur [this message]
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 02/20] net/bnxt: nat global registers support Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 03/20] net/bnxt: parif for offload miss rules Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 04/20] net/bnxt: ulp mapper changes to use tcam search Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 05/20] net/bnxt: add tf hash API Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 06/20] net/bnxt: skip mark id injection into mbuf Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 07/20] net/bnxt: nat template changes Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 08/20] net/bnxt: configure parif for the egress rules Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 09/20] net/bnxt: ignore VLAN priority mask Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 10/20] net/bnxt: add egress template with VLAN tag match Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 11/20] net/bnxt: modify tf shadow tcam to use common tf hash Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 12/20] net/bnxt: added shadow table capability with search Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 13/20] net/bnxt: ulp mapper changes to use tbl search Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 14/20] net/bnxt: fix port default rule create and destroy Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 15/20] net/bnxt: delete VF FW rules when a representor is created Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 16/20] net/bnxt: shadow tcam and tbl reference count modification Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 17/20] net/bnxt: tcam table processing support for search and alloc Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 18/20] net/bnxt: added templates for search before alloc Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 19/20] net/bnxt: enabled shadow tables during session open Somnath Kotur
2020-07-23 11:56 ` [dpdk-dev] [PATCH v2 20/20] net/bnxt: cleanup of VF-representor dev ops Somnath Kotur
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 00/22] bnxt patches Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 01/22] net/bnxt: add shadow and search capability to tcam Ajit Khaparde
2020-07-24 18:04 ` Stephen Hemminger
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 02/22] net/bnxt: add access to nat global register Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 03/22] net/bnxt: configure parif for offload miss rules Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 04/22] net/bnxt: modify ulp mapper to use tcam search Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 05/22] net/bnxt: add tf hash API Ajit Khaparde
2020-07-27 10:32 ` Ferruh Yigit
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 06/22] net/bnxt: skip mark id injection into mbuf Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 07/22] net/bnxt: update nat template Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 08/22] net/bnxt: configure parif for the egress rules Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 09/22] net/bnxt: ignore VLAN priority mask Ajit Khaparde
2020-07-27 10:30 ` Ferruh Yigit
2020-07-28 5:22 ` Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 10/22] net/bnxt: add egress template with VLAN tag match Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 11/22] net/bnxt: modify tf shadow tcam to use tf hash Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 12/22] net/bnxt: add shadow table capability with search Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 13/22] net/bnxt: modify ulp mapper to use tbl search Ajit Khaparde
2020-07-27 10:36 ` Ferruh Yigit
2020-07-27 10:50 ` Somnath Kotur
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 14/22] net/bnxt: fix port default rule create and destroy Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 15/22] net/bnxt: delete VF FW rules on representor create Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 16/22] net/bnxt: modify shadow tcam and tbl reference count logic Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 17/22] net/bnxt: add tcam table processing for search and alloc Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 18/22] net/bnxt: add templates for search before alloc Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 19/22] net/bnxt: enable shadow tables during session open Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 20/22] net/bnxt: cleanup VF-representor dev ops Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 21/22] net/bnxt: fix if condition Ajit Khaparde
2020-07-24 5:32 ` [dpdk-dev] [PATCH v3 22/22] net/bnxt: fix build error with extra cflags Ajit Khaparde
2020-07-24 16:48 ` [dpdk-dev] [PATCH v3 00/22] bnxt patches Ajit Khaparde
2020-07-27 10:42 ` Ferruh Yigit
2020-07-28 5:20 ` Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 " Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 01/22] net/bnxt: add shadow and search capability to tcam Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 02/22] net/bnxt: add access to nat global register Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 03/22] net/bnxt: configure parif for offload miss rules Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 04/22] net/bnxt: modify ulp mapper to use tcam search Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 05/22] net/bnxt: add TruFlow hash API Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 06/22] net/bnxt: fix mark id update to mbuf Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 07/22] net/bnxt: fix nat template Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 08/22] net/bnxt: configure parif for the egress rules Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 09/22] net/bnxt: ignore VLAN priority mask Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 10/22] net/bnxt: add egress template with VLAN tag match Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 11/22] net/bnxt: update shadow tcam to use TruFlow hash Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 12/22] net/bnxt: add shadow table capability with search Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 13/22] net/bnxt: modify ulp mapper to use tbl search Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 14/22] net/bnxt: fix port default rule create and destroy Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 15/22] net/bnxt: fix FW rule deletion on representor create Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 16/22] net/bnxt: fix table reference count for shadow tcam Ajit Khaparde
2020-07-28 17:00 ` Ferruh Yigit
2020-07-28 17:33 ` Ajit Khaparde
2020-07-28 17:38 ` Ferruh Yigit
2020-07-28 18:06 ` Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 17/22] net/bnxt: add tcam table processing for search and alloc Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 18/22] net/bnxt: add templates for search before alloc Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 19/22] net/bnxt: enable shadow tables during session open Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 20/22] net/bnxt: cleanup VF-representor dev ops Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 21/22] net/bnxt: fix if condition Ajit Khaparde
2020-07-28 6:34 ` [dpdk-dev] [PATCH v4 22/22] net/bnxt: fix build error with extra cflags Ajit Khaparde
2020-07-28 14:20 ` [dpdk-dev] [PATCH v4 00/22] bnxt patches Ajit Khaparde
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200723115639.22357-2-somnath.kotur@broadcom.com \
--to=somnath.kotur@broadcom.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).