net/bnxt: support ULP session manager init

A 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 DPDK application can have multiple interfaces 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.

Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Signed-off-by: Mike Baucom <michael.baucom@broadcom.com>
Reviewed-by: Lance Richardson <lance.richardson@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
Venkat Duvvuru 2020-04-15 13:48:53 +05:30 committed by Ferruh Yigit
parent 7b09406537
commit 313ac35ac7
13 changed files with 1185 additions and 1 deletions

View File

@ -44,7 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_rxtx_vec_sse.c
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
@ -57,6 +57,10 @@ SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_rm.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
#

View File

@ -22,6 +22,7 @@
#include "bnxt_util.h"
#include "tf_core.h"
#include "bnxt_ulp.h"
/* Vendor ID */
#define PCI_VENDOR_ID_BROADCOM 0x14E4
@ -687,6 +688,7 @@ struct bnxt {
uint16_t port_svif;
struct tf tfp;
struct bnxt_ulp_context ulp_ctx;
uint8_t truflow;
};
@ -729,6 +731,9 @@ extern int bnxt_logtype_driver;
#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);

View File

@ -904,6 +904,10 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
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:

View File

@ -0,0 +1,35 @@
/* 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_ */

View File

@ -0,0 +1,527 @@
/* 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(&params, 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, &params);
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, &params);
rc = tf_alloc_tbl_scope(&bp->tfp, &params);
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;
}

View File

@ -0,0 +1,100 @@
/* 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_ */

View File

@ -0,0 +1,187 @@
/* 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;
}

View File

@ -0,0 +1,77 @@
/* 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_ */

View File

@ -0,0 +1,94 @@
/* 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;
}

View File

@ -0,0 +1,49 @@
/* 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_ */

View File

@ -0,0 +1,27 @@
/* 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
}
};

View File

@ -0,0 +1,35 @@
/* 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_ */

View File

@ -0,0 +1,40 @@
/* 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_ */