endif
ifeq ($(CONFIG_RTE_LIBRTE_BNXT_PMD), y)
-CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/tf_core
+CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/tf_core -I$(SRCDIR)/tf_ulp
endif
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_core.c
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_tbl.c
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tfp.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_ulp/bnxt_ulp.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_ulp/ulp_mark_mgr.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_ulp/ulp_flow_db.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_ulp/ulp_template_db.c
#
# Export include files
#
#include "bnxt_util.h"
#include "tf_core.h"
+#include "bnxt_ulp.h"
/* Vendor ID */
#define PCI_VENDOR_ID_BROADCOM 0x14E4
uint16_t port_svif;
struct tf tfp;
+ struct bnxt_ulp_context ulp_ctx;
uint8_t truflow;
};
#define PMD_DRV_LOG(level, fmt, args...) \
PMD_DRV_LOG_RAW(level, fmt, ## args)
+int32_t bnxt_ulp_init(struct bnxt *bp);
+void bnxt_ulp_deinit(struct bnxt *bp);
+
uint16_t bnxt_get_vnic_id(uint16_t port);
uint16_t bnxt_get_svif(uint16_t port_id, bool func_svif);
pthread_mutex_lock(&bp->def_cp_lock);
bnxt_schedule_fw_health_check(bp);
pthread_mutex_unlock(&bp->def_cp_lock);
+
+ if (bp->truflow)
+ bnxt_ulp_init(bp);
+
return 0;
error:
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _BNXT_TF_COMMON_H_
+#define _BNXT_TF_COMMON_H_
+
+#define BNXT_TF_DBG(lvl, fmt, args...) PMD_DRV_LOG(lvl, fmt, ## args)
+
+#define BNXT_ULP_EM_FLOWS 8192
+#define BNXT_ULP_1M_FLOWS 1000000
+#define BNXT_EEM_RX_GLOBAL_ID_MASK (BNXT_ULP_1M_FLOWS - 1)
+#define BNXT_EEM_TX_GLOBAL_ID_MASK (BNXT_ULP_1M_FLOWS - 1)
+#define BNXT_EEM_HASH_KEY2_USED 0x8000000
+#define BNXT_EEM_RX_HW_HASH_KEY2_BIT BNXT_ULP_1M_FLOWS
+#define BNXT_ULP_DFLT_RX_MAX_KEY 512
+#define BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY 256
+#define BNXT_ULP_DFLT_RX_MEM 0
+#define BNXT_ULP_RX_NUM_FLOWS 32
+#define BNXT_ULP_RX_TBL_IF_ID 0
+#define BNXT_ULP_DFLT_TX_MAX_KEY 512
+#define BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY 256
+#define BNXT_ULP_DFLT_TX_MEM 0
+#define BNXT_ULP_TX_NUM_FLOWS 32
+#define BNXT_ULP_TX_TBL_IF_ID 0
+
+struct bnxt_ulp_mark_tbl *
+bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx);
+
+int32_t
+bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_mark_tbl *mark_tbl);
+
+#endif /* _BNXT_TF_COMMON_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_flow.h>
+#include <rte_flow_driver.h>
+#include <rte_tailq.h>
+
+#include "bnxt_ulp.h"
+#include "bnxt_tf_common.h"
+#include "bnxt.h"
+#include "tf_core.h"
+#include "tf_ext_flow_handle.h"
+
+#include "ulp_template_db.h"
+#include "ulp_template_struct.h"
+#include "ulp_mark_mgr.h"
+#include "ulp_flow_db.h"
+
+/* Linked list of all TF sessions. */
+STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
+ STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
+
+/* Mutex to synchronize bnxt_ulp_session_list operations. */
+static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Initialize an ULP session.
+ * An ULP session will contain all the resources needed to support rte flow
+ * offloads. A session is initialized as part of rte_eth_device start.
+ * A single vswitch instance can have multiple uplinks which means
+ * rte_eth_device start will be called for each of these devices.
+ * ULP session manager will make sure that a single ULP session is only
+ * initialized once. Apart from this, it also initializes MARK database,
+ * EEM table & flow database. ULP session manager also manages a list of
+ * all opened ULP sessions.
+ */
+static int32_t
+ulp_ctx_session_open(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ struct rte_eth_dev *ethdev = bp->eth_dev;
+ int32_t rc = 0;
+ struct tf_open_session_parms params;
+
+ memset(¶ms, 0, sizeof(params));
+
+ rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
+ params.ctrl_chan_name);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
+ ethdev->data->port_id, rc);
+ return rc;
+ }
+
+ rc = tf_open_session(&bp->tfp, ¶ms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
+ params.ctrl_chan_name, rc);
+ return -EINVAL;
+ }
+ session->session_opened = 1;
+ session->g_tfp = &bp->tfp;
+ return rc;
+}
+
+static void
+bnxt_init_tbl_scope_parms(struct bnxt *bp,
+ struct tf_alloc_tbl_scope_parms *params)
+{
+ struct bnxt_ulp_device_params *dparms;
+ uint32_t dev_id;
+ int rc;
+
+ rc = bnxt_ulp_cntxt_dev_id_get(&bp->ulp_ctx, &dev_id);
+ if (rc)
+ /* TBD: For now, just use default. */
+ dparms = 0;
+ else
+ dparms = bnxt_ulp_device_params_get(dev_id);
+
+ if (!dparms) {
+ params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
+ params->rx_max_action_entry_sz_in_bits =
+ BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
+ params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
+ params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
+ params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
+
+ params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
+ params->tx_max_action_entry_sz_in_bits =
+ BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
+ params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
+ params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
+ params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
+ } else {
+ params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
+ params->rx_max_action_entry_sz_in_bits =
+ BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
+ params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
+ params->rx_num_flows_in_k = dparms->num_flows / (1024);
+ params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
+
+ params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
+ params->tx_max_action_entry_sz_in_bits =
+ BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
+ params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
+ params->tx_num_flows_in_k = dparms->num_flows / (1024);
+ params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
+ }
+}
+
+/* Initialize Extended Exact Match host memory. */
+static int32_t
+ulp_eem_tbl_scope_init(struct bnxt *bp)
+{
+ struct tf_alloc_tbl_scope_parms params = {0};
+ int rc;
+
+ bnxt_init_tbl_scope_parms(bp, ¶ms);
+
+ rc = tf_alloc_tbl_scope(&bp->tfp, ¶ms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
+ rc);
+ return rc;
+ }
+
+ rc = bnxt_ulp_cntxt_tbl_scope_id_set(&bp->ulp_ctx, params.tbl_scope_id);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+/* The function to free and deinit the ulp context data. */
+static int32_t
+ulp_ctx_deinit(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ if (!session || !bp) {
+ BNXT_TF_DBG(ERR, "Invalid Arguments\n");
+ return -EINVAL;
+ }
+
+ /* Free the contents */
+ if (session->cfg_data) {
+ rte_free(session->cfg_data);
+ bp->ulp_ctx.cfg_data = NULL;
+ session->cfg_data = NULL;
+ }
+ return 0;
+}
+
+/* The function to allocate and initialize the ulp context data. */
+static int32_t
+ulp_ctx_init(struct bnxt *bp,
+ struct bnxt_ulp_session_state *session)
+{
+ struct bnxt_ulp_data *ulp_data;
+ int32_t rc = 0;
+
+ if (!session || !bp) {
+ BNXT_TF_DBG(ERR, "Invalid Arguments\n");
+ return -EINVAL;
+ }
+
+ /* Allocate memory to hold ulp context data. */
+ ulp_data = rte_zmalloc("bnxt_ulp_data",
+ sizeof(struct bnxt_ulp_data), 0);
+ if (!ulp_data) {
+ BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
+ return -ENOMEM;
+ }
+
+ /* Increment the ulp context data reference count usage. */
+ bp->ulp_ctx.cfg_data = ulp_data;
+ session->cfg_data = ulp_data;
+ ulp_data->ref_cnt++;
+
+ /* Open the ulp session. */
+ rc = ulp_ctx_session_open(bp, session);
+ if (rc) {
+ (void)ulp_ctx_deinit(bp, session);
+ return rc;
+ }
+ bnxt_ulp_cntxt_tfp_set(&bp->ulp_ctx, session->g_tfp);
+ return rc;
+}
+
+static int32_t
+ulp_ctx_attach(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_session_state *session)
+{
+ if (!ulp_ctx || !session) {
+ BNXT_TF_DBG(ERR, "Invalid Arguments\n");
+ return -EINVAL;
+ }
+
+ /* Increment the ulp context data reference count usage. */
+ ulp_ctx->cfg_data = session->cfg_data;
+ ulp_ctx->cfg_data->ref_cnt++;
+
+ /* TBD call TF_session_attach. */
+ ulp_ctx->g_tfp = session->g_tfp;
+ return 0;
+}
+
+/*
+ * Initialize the state of an ULP session.
+ * If the state of an ULP session is not initialized, set it's state to
+ * initialized. If the state is already initialized, do nothing.
+ */
+static void
+ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
+{
+ pthread_mutex_lock(&session->bnxt_ulp_mutex);
+
+ if (!session->bnxt_ulp_init) {
+ session->bnxt_ulp_init = true;
+ *init = false;
+ } else {
+ *init = true;
+ }
+
+ pthread_mutex_unlock(&session->bnxt_ulp_mutex);
+}
+
+/*
+ * Check if an ULP session is already allocated for a specific PCI
+ * domain & bus. If it is already allocated simply return the session
+ * pointer, otherwise allocate a new session.
+ */
+static struct bnxt_ulp_session_state *
+ulp_get_session(struct rte_pci_addr *pci_addr)
+{
+ struct bnxt_ulp_session_state *session;
+
+ STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
+ if (session->pci_info.domain == pci_addr->domain &&
+ session->pci_info.bus == pci_addr->bus) {
+ return session;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
+ * If it's already initialized simply return the already existing session.
+ */
+static struct bnxt_ulp_session_state *
+ulp_session_init(struct bnxt *bp,
+ bool *init)
+{
+ struct rte_pci_device *pci_dev;
+ struct rte_pci_addr *pci_addr;
+ struct bnxt_ulp_session_state *session;
+
+ if (!bp)
+ return NULL;
+
+ pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
+ pci_addr = &pci_dev->addr;
+
+ pthread_mutex_lock(&bnxt_ulp_global_mutex);
+
+ session = ulp_get_session(pci_addr);
+ if (!session) {
+ /* Not Found the session Allocate a new one */
+ session = rte_zmalloc("bnxt_ulp_session",
+ sizeof(struct bnxt_ulp_session_state),
+ 0);
+ if (!session) {
+ BNXT_TF_DBG(ERR,
+ "Allocation failed for bnxt_ulp_session\n");
+ pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+ return NULL;
+
+ } else {
+ /* Add it to the queue */
+ session->pci_info.domain = pci_addr->domain;
+ session->pci_info.bus = pci_addr->bus;
+ pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
+ STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
+ session, next);
+ }
+ }
+ ulp_context_initialized(session, init);
+ pthread_mutex_unlock(&bnxt_ulp_global_mutex);
+ return session;
+}
+
+/*
+ * When a port is initialized by dpdk. This functions is called
+ * and this function initializes the ULP context and rest of the
+ * infrastructure associated with it.
+ */
+int32_t
+bnxt_ulp_init(struct bnxt *bp)
+{
+ struct bnxt_ulp_session_state *session;
+ bool init;
+ int rc;
+
+ /*
+ * Multiple uplink ports can be associated with a single vswitch.
+ * Make sure only the port that is started first will initialize
+ * the TF session.
+ */
+ session = ulp_session_init(bp, &init);
+ if (!session) {
+ BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
+ return -EINVAL;
+ }
+
+ /*
+ * If ULP is already initialized for a specific domain then simply
+ * assign the ulp context to this rte_eth_dev.
+ */
+ if (init) {
+ rc = ulp_ctx_attach(&bp->ulp_ctx, session);
+ if (rc) {
+ BNXT_TF_DBG(ERR,
+ "Failed to attach the ulp context\n");
+ }
+ return rc;
+ }
+
+ /* Allocate and Initialize the ulp context. */
+ rc = ulp_ctx_init(bp, session);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
+ goto jump_to_error;
+ }
+
+ /* Create the Mark database. */
+ rc = ulp_mark_db_init(&bp->ulp_ctx);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
+ goto jump_to_error;
+ }
+
+ /* Create the flow database. */
+ rc = ulp_flow_db_init(&bp->ulp_ctx);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
+ goto jump_to_error;
+ }
+
+ /* Create the eem table scope. */
+ rc = ulp_eem_tbl_scope_init(bp);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
+ goto jump_to_error;
+ }
+
+ return rc;
+
+jump_to_error:
+ return -ENOMEM;
+}
+
+/* Below are the access functions to access internal data of ulp context. */
+
+/* Function to set the Mark DB into the context. */
+int32_t
+bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_mark_tbl *mark_tbl)
+{
+ if (!ulp_ctx || !ulp_ctx->cfg_data) {
+ BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+ return -EINVAL;
+ }
+
+ ulp_ctx->cfg_data->mark_tbl = mark_tbl;
+
+ return 0;
+}
+
+/* Function to retrieve the Mark DB from the context. */
+struct bnxt_ulp_mark_tbl *
+bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
+{
+ if (!ulp_ctx || !ulp_ctx->cfg_data)
+ return NULL;
+
+ return ulp_ctx->cfg_data->mark_tbl;
+}
+
+/* Function to set the device id of the hardware. */
+int32_t
+bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t dev_id)
+{
+ if (ulp_ctx && ulp_ctx->cfg_data) {
+ ulp_ctx->cfg_data->dev_id = dev_id;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/* Function to get the device id of the hardware. */
+int32_t
+bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t *dev_id)
+{
+ if (ulp_ctx && ulp_ctx->cfg_data) {
+ *dev_id = ulp_ctx->cfg_data->dev_id;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/* Function to get the table scope id of the EEM table. */
+int32_t
+bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t *tbl_scope_id)
+{
+ if (ulp_ctx && ulp_ctx->cfg_data) {
+ *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/* Function to set the table scope id of the EEM table. */
+int32_t
+bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t tbl_scope_id)
+{
+ if (ulp_ctx && ulp_ctx->cfg_data) {
+ ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/* Function to set the tfp session details from the ulp context. */
+int32_t
+bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
+{
+ if (!ulp) {
+ BNXT_TF_DBG(ERR, "Invalid arguments\n");
+ return -EINVAL;
+ }
+
+ /* TBD The tfp should be removed once tf_attach is implemented. */
+ ulp->g_tfp = tfp;
+ return 0;
+}
+
+/* Function to get the tfp session details from the ulp context. */
+struct tf *
+bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp)
+{
+ if (!ulp) {
+ BNXT_TF_DBG(ERR, "Invalid arguments\n");
+ return NULL;
+ }
+ /* TBD The tfp should be removed once tf_attach is implemented. */
+ return ulp->g_tfp;
+}
+
+/*
+ * Get the device table entry based on the device id.
+ *
+ * dev_id [in] The device id of the hardware
+ *
+ * Returns the pointer to the device parameters.
+ */
+struct bnxt_ulp_device_params *
+bnxt_ulp_device_params_get(uint32_t dev_id)
+{
+ if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
+ return &ulp_device_params[dev_id];
+ return NULL;
+}
+
+/* Function to set the flow database to the ulp context. */
+int32_t
+bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_flow_db *flow_db)
+{
+ if (!ulp_ctx || !ulp_ctx->cfg_data) {
+ BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+ return -EINVAL;
+ }
+
+ ulp_ctx->cfg_data->flow_db = flow_db;
+ return 0;
+}
+
+/* Function to get the flow database from the ulp context. */
+struct bnxt_ulp_flow_db *
+bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx)
+{
+ if (!ulp_ctx || !ulp_ctx->cfg_data) {
+ BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+ return NULL;
+ }
+
+ return ulp_ctx->cfg_data->flow_db;
+}
+
+/* Function to get the ulp context from eth device. */
+struct bnxt_ulp_context *
+bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev)
+{
+ struct bnxt *bp;
+
+ bp = (struct bnxt *)dev->data->dev_private;
+ if (!bp) {
+ BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
+ return NULL;
+ }
+ return &bp->ulp_ctx;
+}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019-2020 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _BNXT_ULP_H_
+#define _BNXT_ULP_H_
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/queue.h>
+
+#include "rte_ethdev.h"
+
+struct bnxt_ulp_data {
+ uint32_t tbl_scope_id;
+ struct bnxt_ulp_mark_tbl *mark_tbl;
+ uint32_t dev_id; /* Hardware device id */
+ uint32_t ref_cnt;
+ struct bnxt_ulp_flow_db *flow_db;
+};
+
+struct bnxt_ulp_context {
+ struct bnxt_ulp_data *cfg_data;
+ /* TBD The tfp should be removed once tf_attach is implemented. */
+ struct tf *g_tfp;
+};
+
+struct bnxt_ulp_pci_info {
+ uint32_t domain;
+ uint8_t bus;
+};
+
+struct bnxt_ulp_session_state {
+ STAILQ_ENTRY(bnxt_ulp_session_state) next;
+ bool bnxt_ulp_init;
+ pthread_mutex_t bnxt_ulp_mutex;
+ struct bnxt_ulp_pci_info pci_info;
+ struct bnxt_ulp_data *cfg_data;
+ /* TBD The tfp should be removed once tf_attach is implemented. */
+ struct tf *g_tfp;
+ uint32_t session_opened;
+};
+
+/* ULP flow id structure */
+struct rte_tf_flow {
+ uint32_t flow_id;
+};
+
+/* Function to set the device id of the hardware. */
+int32_t
+bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx, uint32_t dev_id);
+
+/* Function to get the device id of the hardware. */
+int32_t
+bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx, uint32_t *dev_id);
+
+/* Function to set the table scope id of the EEM table. */
+int32_t
+bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t tbl_scope_id);
+
+/* Function to get the table scope id of the EEM table. */
+int32_t
+bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
+ uint32_t *tbl_scope_id);
+
+/* Function to set the tfp session details in the ulp context. */
+int32_t
+bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp);
+
+/* Function to get the tfp session details from ulp context. */
+struct tf *
+bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp);
+
+/* Get the device table entry based on the device id. */
+struct bnxt_ulp_device_params *
+bnxt_ulp_device_params_get(uint32_t dev_id);
+
+int32_t
+bnxt_ulp_ctxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_mark_tbl *mark_tbl);
+
+struct bnxt_ulp_mark_tbl *
+bnxt_ulp_ctxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx);
+
+/* Function to set the flow database to the ulp context. */
+int32_t
+bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
+ struct bnxt_ulp_flow_db *flow_db);
+
+/* Function to get the flow database from the ulp context. */
+struct bnxt_ulp_flow_db *
+bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx);
+
+/* Function to get the ulp context from eth device. */
+struct bnxt_ulp_context *
+bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev);
+
+#endif /* _BNXT_ULP_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2020 Broadcom
+ * All rights reserved.
+ */
+
+#include <rte_malloc.h>
+#include "bnxt.h"
+#include "bnxt_tf_common.h"
+#include "ulp_flow_db.h"
+#include "ulp_template_struct.h"
+
+/*
+ * Helper function to allocate the flow table and initialize
+ * the stack for allocation operations.
+ *
+ * flow_db [in] Ptr to flow database structure
+ * tbl_idx [in] The index to table creation.
+ *
+ * Returns 0 on success or negative number on failure.
+ */
+static int32_t
+ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
+ enum bnxt_ulp_flow_db_tables tbl_idx)
+{
+ uint32_t idx = 0;
+ struct bnxt_ulp_flow_tbl *flow_tbl;
+ uint32_t size;
+
+ flow_tbl = &flow_db->flow_tbl[tbl_idx];
+
+ size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
+ flow_tbl->flow_resources =
+ rte_zmalloc("ulp_fdb_resource_info", size, 0);
+
+ if (!flow_tbl->flow_resources) {
+ BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
+ return -ENOMEM;
+ }
+ size = sizeof(uint32_t) * flow_tbl->num_resources;
+ flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
+ if (!flow_tbl->flow_tbl_stack) {
+ BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
+ return -ENOMEM;
+ }
+ size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
+ flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
+ if (!flow_tbl->active_flow_tbl) {
+ BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the stack table. */
+ for (idx = 0; idx < flow_tbl->num_resources; idx++)
+ flow_tbl->flow_tbl_stack[idx] = idx;
+
+ /* Ignore the first element in the list. */
+ flow_tbl->head_index = 1;
+ /* Tail points to the last entry in the list. */
+ flow_tbl->tail_index = flow_tbl->num_resources - 1;
+ return 0;
+}
+
+/*
+ * Helper function to de allocate the flow table.
+ *
+ * flow_db [in] Ptr to flow database structure
+ * tbl_idx [in] The index to table creation.
+ *
+ * Returns none.
+ */
+static void
+ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
+ enum bnxt_ulp_flow_db_tables tbl_idx)
+{
+ struct bnxt_ulp_flow_tbl *flow_tbl;
+
+ flow_tbl = &flow_db->flow_tbl[tbl_idx];
+
+ /* Free all the allocated tables in the flow table. */
+ if (flow_tbl->active_flow_tbl) {
+ rte_free(flow_tbl->active_flow_tbl);
+ flow_tbl->active_flow_tbl = NULL;
+ }
+
+ if (flow_tbl->flow_tbl_stack) {
+ rte_free(flow_tbl->flow_tbl_stack);
+ flow_tbl->flow_tbl_stack = NULL;
+ }
+
+ if (flow_tbl->flow_resources) {
+ rte_free(flow_tbl->flow_resources);
+ flow_tbl->flow_resources = NULL;
+ }
+}
+
+/*
+ * Initialize the flow database. Memory is allocated in this
+ * call and assigned to the flow database.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * Returns 0 on success or negative number on failure.
+ */
+int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
+{
+ struct bnxt_ulp_device_params *dparms;
+ struct bnxt_ulp_flow_tbl *flow_tbl;
+ struct bnxt_ulp_flow_db *flow_db;
+ uint32_t dev_id;
+
+ /* Get the dev specific number of flows that needed to be supported. */
+ if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
+ BNXT_TF_DBG(ERR, "Invalid device id\n");
+ return -EINVAL;
+ }
+
+ dparms = bnxt_ulp_device_params_get(dev_id);
+ if (!dparms) {
+ BNXT_TF_DBG(ERR, "could not fetch the device params\n");
+ return -ENODEV;
+ }
+
+ flow_db = rte_zmalloc("bnxt_ulp_flow_db",
+ sizeof(struct bnxt_ulp_flow_db), 0);
+ if (!flow_db) {
+ BNXT_TF_DBG(ERR,
+ "Failed to allocate memory for flow table ptr\n");
+ goto error_free;
+ }
+
+ /* Attach the flow database to the ulp context. */
+ bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
+
+ /* Populate the regular flow table limits. */
+ flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
+ flow_tbl->num_flows = dparms->num_flows + 1;
+ flow_tbl->num_resources = (flow_tbl->num_flows *
+ dparms->num_resources_per_flow);
+
+ /* Populate the default flow table limits. */
+ flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
+ flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
+ flow_tbl->num_resources = (flow_tbl->num_flows *
+ BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
+
+ /* Allocate the resource for the regular flow table. */
+ if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
+ goto error_free;
+ if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
+ goto error_free;
+
+ /* All good so return. */
+ return 0;
+error_free:
+ ulp_flow_db_deinit(ulp_ctxt);
+ return -ENOMEM;
+}
+
+/*
+ * Deinitialize the flow database. Memory is deallocated in
+ * this call and all flows should have been purged before this
+ * call.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * Returns 0 on success.
+ */
+int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
+{
+ struct bnxt_ulp_flow_db *flow_db;
+
+ flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
+ if (!flow_db) {
+ BNXT_TF_DBG(ERR, "Invalid Arguments\n");
+ return -EINVAL;
+ }
+
+ /* Detach the flow database from the ulp context. */
+ bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
+
+ /* Free up all the memory. */
+ ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
+ ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
+ rte_free(flow_db);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _ULP_FLOW_DB_H_
+#define _ULP_FLOW_DB_H_
+
+#include "bnxt_ulp.h"
+#include "ulp_template_db.h"
+
+#define BNXT_FLOW_DB_DEFAULT_NUM_FLOWS 128
+#define BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES 5
+
+/* Structure for the flow database resource information. */
+struct ulp_fdb_resource_info {
+ /* Points to next resource in the chained list. */
+ uint32_t nxt_resource_idx;
+ union {
+ uint64_t resource_em_handle;
+ struct {
+ uint32_t resource_type;
+ uint32_t resource_hndl;
+ };
+ };
+};
+
+/* Structure for the flow database resource information. */
+struct bnxt_ulp_flow_tbl {
+ /* Flow tbl is the resource object list for each flow id. */
+ struct ulp_fdb_resource_info *flow_resources;
+
+ /* Flow table stack to track free list of resources. */
+ uint32_t *flow_tbl_stack;
+ uint32_t head_index;
+ uint32_t tail_index;
+
+ /* Table to track the active flows. */
+ uint64_t *active_flow_tbl;
+ uint32_t num_flows;
+ uint32_t num_resources;
+};
+
+/* Flow database supports two tables. */
+enum bnxt_ulp_flow_db_tables {
+ BNXT_ULP_REGULAR_FLOW_TABLE,
+ BNXT_ULP_DEFAULT_FLOW_TABLE,
+ BNXT_ULP_FLOW_TABLE_MAX
+};
+
+/* Structure for the flow database resource information. */
+struct bnxt_ulp_flow_db {
+ struct bnxt_ulp_flow_tbl flow_tbl[BNXT_ULP_FLOW_TABLE_MAX];
+};
+
+/*
+ * Initialize the flow database. Memory is allocated in this
+ * call and assigned to the flow database.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * Returns 0 on success or negative number on failure.
+ */
+int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt);
+
+/*
+ * Deinitialize the flow database. Memory is deallocated in
+ * this call and all flows should have been purged before this
+ * call.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * Returns 0 on success.
+ */
+int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt);
+
+#endif /* _ULP_FLOW_DB_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2020 Broadcom
+ * All rights reserved.
+ */
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+#include "bnxt_ulp.h"
+#include "tf_ext_flow_handle.h"
+#include "ulp_mark_mgr.h"
+#include "bnxt_tf_common.h"
+#include "../bnxt.h"
+#include "ulp_template_db.h"
+#include "ulp_template_struct.h"
+
+/*
+ * Allocate and Initialize all Mark Manager resources for this ulp context.
+ *
+ * ctxt [in] The ulp context for the mark manager.
+ *
+ */
+int32_t
+ulp_mark_db_init(struct bnxt_ulp_context *ctxt)
+{
+ struct bnxt_ulp_device_params *dparms;
+ struct bnxt_ulp_mark_tbl *mark_tbl = NULL;
+ uint32_t dev_id;
+
+ if (!ctxt) {
+ BNXT_TF_DBG(DEBUG, "Invalid ULP CTXT\n");
+ return -EINVAL;
+ }
+
+ if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
+ BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
+ return -EINVAL;
+ }
+
+ dparms = bnxt_ulp_device_params_get(dev_id);
+ if (!dparms) {
+ BNXT_TF_DBG(DEBUG, "Failed to device parms\n");
+ return -EINVAL;
+ }
+
+ mark_tbl = rte_zmalloc("ulp_rx_mark_tbl_ptr",
+ sizeof(struct bnxt_ulp_mark_tbl), 0);
+ if (!mark_tbl)
+ goto mem_error;
+
+ /* Need to allocate 2 * Num flows to account for hash type bit. */
+ mark_tbl->lfid_tbl = rte_zmalloc("ulp_rx_em_flow_mark_table",
+ dparms->lfid_entries *
+ sizeof(struct bnxt_lfid_mark_info),
+ 0);
+
+ if (!mark_tbl->lfid_tbl)
+ goto mem_error;
+
+ /* Need to allocate 2 * Num flows to account for hash type bit. */
+ mark_tbl->gfid_tbl = rte_zmalloc("ulp_rx_eem_flow_mark_table",
+ 2 * dparms->num_flows *
+ sizeof(struct bnxt_gfid_mark_info),
+ 0);
+ if (!mark_tbl->gfid_tbl)
+ goto mem_error;
+
+ /*
+ * TBD: This needs to be generalized for better mark handling
+ * These values are used to compress the FID to the allowable index
+ * space. The FID from hw may be the full hash.
+ */
+ mark_tbl->gfid_max = dparms->gfid_entries - 1;
+ mark_tbl->gfid_mask = (dparms->gfid_entries / 2) - 1;
+ mark_tbl->gfid_type_bit = (dparms->gfid_entries / 2);
+
+ BNXT_TF_DBG(DEBUG, "GFID Max = 0x%08x\nGFID MASK = 0x%08x\n",
+ mark_tbl->gfid_max,
+ mark_tbl->gfid_mask);
+
+ /* Add the mart tbl to the ulp context. */
+ bnxt_ulp_cntxt_ptr2_mark_db_set(ctxt, mark_tbl);
+
+ return 0;
+
+mem_error:
+ rte_free(mark_tbl->gfid_tbl);
+ rte_free(mark_tbl->lfid_tbl);
+ rte_free(mark_tbl);
+ BNXT_TF_DBG(DEBUG,
+ "Failed to allocate memory for mark mgr\n");
+
+ return -ENOMEM;
+}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _ULP_MARK_MGR_H_
+#define _ULP_MARK_MGR_H_
+
+#include "bnxt_ulp.h"
+
+#define ULP_MARK_INVALID (0)
+struct bnxt_lfid_mark_info {
+ uint16_t mark_id;
+ bool valid;
+};
+
+struct bnxt_gfid_mark_info {
+ uint32_t mark_id;
+ bool valid;
+};
+
+struct bnxt_ulp_mark_tbl {
+ struct bnxt_lfid_mark_info *lfid_tbl;
+ struct bnxt_gfid_mark_info *gfid_tbl;
+ uint32_t gfid_mask;
+ uint32_t gfid_type_bit;
+ uint32_t gfid_max;
+};
+
+/*
+ * Allocate and Initialize all Mark Manager resources for this ulp context.
+ *
+ * Initialize MARK database for GFID & LFID tables
+ * GFID: Global flow id which is based on EEM hash id.
+ * LFID: Local flow id which is the CFA action pointer.
+ * GFID is used for EEM flows, LFID is used for EM flows.
+ *
+ * Flow mapper modules adds mark_id in the MARK database.
+ *
+ * BNXT PMD receive handler extracts the hardware flow id from the
+ * received completion record. Fetches mark_id from the MARK
+ * database using the flow id. Injects mark_id into the packet's mbuf.
+ *
+ * ctxt [in] The ulp context for the mark manager.
+ */
+int32_t
+ulp_mark_db_init(struct bnxt_ulp_context *ctxt);
+
+#endif /* _ULP_MARK_MGR_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+/*
+ * date: Mon Mar 9 02:37:53 2020
+ * version: 0.0
+ */
+
+#include "ulp_template_db.h"
+#include "ulp_template_struct.h"
+
+struct bnxt_ulp_device_params ulp_device_params[] = {
+ [BNXT_ULP_DEVICE_ID_WH_PLUS] = {
+ .global_fid_enable = BNXT_ULP_SYM_YES,
+ .byte_order = (enum bnxt_ulp_byte_order)
+ BNXT_ULP_SYM_LITTLE_ENDIAN,
+ .encap_byte_swap = 1,
+ .lfid_entries = 16384,
+ .lfid_entry_size = 4,
+ .gfid_entries = 65536,
+ .gfid_entry_size = 4,
+ .num_flows = 32768,
+ .num_resources_per_flow = 8
+ }
+};
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+/*
+ * date: Mon Mar 9 02:37:53 2020
+ * version: 0.0
+ */
+
+#ifndef ULP_TEMPLATE_DB_H_
+#define ULP_TEMPLATE_DB_H_
+
+#define BNXT_ULP_MAX_NUM_DEVICES 4
+
+enum bnxt_ulp_byte_order {
+ BNXT_ULP_BYTE_ORDER_BE,
+ BNXT_ULP_BYTE_ORDER_LE,
+ BNXT_ULP_BYTE_ORDER_LAST
+};
+
+enum bnxt_ulp_device_id {
+ BNXT_ULP_DEVICE_ID_WH_PLUS,
+ BNXT_ULP_DEVICE_ID_THOR,
+ BNXT_ULP_DEVICE_ID_STINGRAY,
+ BNXT_ULP_DEVICE_ID_STINGRAY2,
+ BNXT_ULP_DEVICE_ID_LAST
+};
+
+enum bnxt_ulp_sym {
+ BNXT_ULP_SYM_LITTLE_ENDIAN = 1,
+ BNXT_ULP_SYM_YES = 1
+};
+
+#endif /* _ULP_TEMPLATE_DB_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2019 Broadcom
+ * All rights reserved.
+ */
+
+#ifndef _ULP_TEMPLATE_STRUCT_H_
+#define _ULP_TEMPLATE_STRUCT_H_
+
+#include <stdint.h>
+#include "rte_ether.h"
+#include "rte_icmp.h"
+#include "rte_ip.h"
+#include "rte_tcp.h"
+#include "rte_udp.h"
+#include "rte_esp.h"
+#include "rte_sctp.h"
+#include "rte_flow.h"
+#include "tf_core.h"
+
+/* Device specific parameters. */
+struct bnxt_ulp_device_params {
+ uint8_t description[16];
+ uint32_t global_fid_enable;
+ enum bnxt_ulp_byte_order byte_order;
+ uint8_t encap_byte_swap;
+ uint32_t lfid_entries;
+ uint32_t lfid_entry_size;
+ uint64_t gfid_entries;
+ uint32_t gfid_entry_size;
+ uint64_t num_flows;
+ uint32_t num_resources_per_flow;
+};
+
+/*
+ * The ulp_device_params is indexed by the dev_id.
+ * This table maintains the device specific parameters.
+ */
+extern struct bnxt_ulp_device_params ulp_device_params[];
+
+#endif /* _ULP_TEMPLATE_STRUCT_H_ */