[PATCH v1 27/73] net/ntnic: add SLC LR module
Serhii Iliushyk
sil-plv at napatech.com
Mon Oct 21 23:04:29 CEST 2024
From: Danylo Vodopianov <dvo-plv at napatech.com>
The Slicer for Local Retransmit module can cut of the head a packet
before the packet leaves the FPGA RX pipeline.
This is used when the TX pipeline is configured
to add a new head in the packet.
Signed-off-by: Danylo Vodopianov <dvo-plv at napatech.com>
---
drivers/net/ntnic/include/hw_mod_backend.h | 2 +
.../nthw/flow_api/hw_mod/hw_mod_slc_lr.c | 100 +++++++++++++++++
.../profile_inline/flow_api_hw_db_inline.c | 104 ++++++++++++++++++
.../profile_inline/flow_api_hw_db_inline.h | 19 ++++
.../profile_inline/flow_api_profile_inline.c | 27 +++++
5 files changed, 252 insertions(+)
diff --git a/drivers/net/ntnic/include/hw_mod_backend.h b/drivers/net/ntnic/include/hw_mod_backend.h
index 87fc16ecb4..2711f44083 100644
--- a/drivers/net/ntnic/include/hw_mod_backend.h
+++ b/drivers/net/ntnic/include/hw_mod_backend.h
@@ -697,6 +697,8 @@ int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be);
void hw_mod_slc_lr_free(struct flow_api_backend_s *be);
int hw_mod_slc_lr_reset(struct flow_api_backend_s *be);
int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count);
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, uint32_t index,
+ uint32_t value);
struct pdb_func_s {
COMMON_FUNC_INFO_S;
diff --git a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
index 1d878f3f96..30e5e38690 100644
--- a/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
+++ b/drivers/net/ntnic/nthw/flow_api/hw_mod/hw_mod_slc_lr.c
@@ -66,3 +66,103 @@ int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, int co
return be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx, count);
}
+
+static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value, int get)
+{
+ if (index >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_SLC_LR_RCP_PRESET_ALL:
+ if (get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ memset(&be->slc_lr.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_lr_v2_s));
+ break;
+
+ case HW_SLC_LR_RCP_FIND:
+ if (!get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ if (*value >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ FIND_EQUAL_INDEX(be->slc_lr.v2.rcp, struct hw_mod_slc_lr_v2_s, index,
+ *value, be->max_categories);
+ break;
+
+ case HW_SLC_LR_RCP_COMPARE:
+ if (!get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ if (*value >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ DO_COMPARE_INDEXS(be->slc_lr.v2.rcp, struct hw_mod_slc_lr_v2_s, index,
+ *value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_SLC_EN:
+ GET_SET(be->slc_lr.v2.rcp[index].head_slc_en, value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_DYN:
+ GET_SET(be->slc_lr.v2.rcp[index].head_dyn, value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_OFS:
+ GET_SET_SIGNED(be->slc_lr.v2.rcp[index].head_ofs, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_SLC_EN:
+ GET_SET(be->slc_lr.v2.rcp[index].tail_slc_en, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_DYN:
+ GET_SET(be->slc_lr.v2.rcp[index].tail_dyn, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_OFS:
+ GET_SET_SIGNED(be->slc_lr.v2.rcp[index].tail_ofs, value);
+ break;
+
+ case HW_SLC_LR_RCP_PCAP:
+ GET_SET(be->slc_lr.v2.rcp[index].pcap, value);
+ break;
+
+ default:
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ break;
+
+ default:
+ UNSUP_VER_LOG;
+ return UNSUP_VER;
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, uint32_t index,
+ uint32_t value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0);
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
index 4d5bcbef49..35edd2d1a3 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
@@ -19,7 +19,13 @@ struct hw_db_inline_resource_db {
int ref;
} *cot;
+ struct hw_db_inline_resource_db_slc_lr {
+ struct hw_db_inline_slc_lr_data data;
+ int ref;
+ } *slc_lr;
+
uint32_t nb_cot;
+ uint32_t nb_slc_lr;
/* Items */
struct hw_db_inline_resource_db_cat {
@@ -54,6 +60,14 @@ int hw_db_inline_create(struct flow_nic_dev *ndev, void **db_handle)
return -1;
}
+ db->nb_slc_lr = ndev->be.max_categories;
+ db->slc_lr = calloc(db->nb_slc_lr, sizeof(struct hw_db_inline_resource_db_slc_lr));
+
+ if (db->slc_lr == NULL) {
+ hw_db_inline_destroy(db);
+ return -1;
+ }
+
db->nb_cat = ndev->be.cat.nb_cat_funcs;
db->cat = calloc(db->nb_cat, sizeof(struct hw_db_inline_resource_db_cat));
@@ -71,6 +85,7 @@ void hw_db_inline_destroy(void *db_handle)
struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
free(db->cot);
+ free(db->slc_lr);
free(db->cat);
free(db->cfn);
@@ -94,6 +109,11 @@ void hw_db_inline_deref_idxs(struct flow_nic_dev *ndev, void *db_handle, struct
hw_db_inline_cot_deref(ndev, db_handle, *(struct hw_db_cot_idx *)&idxs[i]);
break;
+ case HW_DB_IDX_TYPE_SLC_LR:
+ hw_db_inline_slc_lr_deref(ndev, db_handle,
+ *(struct hw_db_slc_lr_idx *)&idxs[i]);
+ break;
+
default:
break;
}
@@ -234,6 +254,90 @@ void hw_db_inline_cot_deref(struct flow_nic_dev *ndev, void *db_handle, struct h
}
}
+/******************************************************************************/
+/* SLC_LR */
+/******************************************************************************/
+
+static int hw_db_inline_slc_lr_compare(const struct hw_db_inline_slc_lr_data *data1,
+ const struct hw_db_inline_slc_lr_data *data2)
+{
+ if (!data1->head_slice_en)
+ return data1->head_slice_en == data2->head_slice_en;
+
+ return data1->head_slice_en == data2->head_slice_en &&
+ data1->head_slice_dyn == data2->head_slice_dyn &&
+ data1->head_slice_ofs == data2->head_slice_ofs;
+}
+
+struct hw_db_slc_lr_idx hw_db_inline_slc_lr_add(struct flow_nic_dev *ndev, void *db_handle,
+ const struct hw_db_inline_slc_lr_data *data)
+{
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+ struct hw_db_slc_lr_idx idx = { .raw = 0 };
+ int found = 0;
+
+ idx.type = HW_DB_IDX_TYPE_SLC_LR;
+
+ for (uint32_t i = 1; i < db->nb_slc_lr; ++i) {
+ int ref = db->slc_lr[i].ref;
+
+ if (ref > 0 && hw_db_inline_slc_lr_compare(data, &db->slc_lr[i].data)) {
+ idx.ids = i;
+ hw_db_inline_slc_lr_ref(ndev, db, idx);
+ return idx;
+ }
+
+ if (!found && ref <= 0) {
+ found = 1;
+ idx.ids = i;
+ }
+ }
+
+ if (!found) {
+ idx.error = 1;
+ return idx;
+ }
+
+ db->slc_lr[idx.ids].ref = 1;
+ memcpy(&db->slc_lr[idx.ids].data, data, sizeof(struct hw_db_inline_slc_lr_data));
+
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_SLC_EN, idx.ids, data->head_slice_en);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_DYN, idx.ids, data->head_slice_dyn);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_OFS, idx.ids, data->head_slice_ofs);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, idx.ids, 1);
+
+ return idx;
+}
+
+void hw_db_inline_slc_lr_ref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx)
+{
+ (void)ndev;
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+
+ if (!idx.error)
+ db->slc_lr[idx.ids].ref += 1;
+}
+
+void hw_db_inline_slc_lr_deref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx)
+{
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+
+ if (idx.error)
+ return;
+
+ db->slc_lr[idx.ids].ref -= 1;
+
+ if (db->slc_lr[idx.ids].ref <= 0) {
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_PRESET_ALL, idx.ids, 0x0);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, idx.ids, 1);
+
+ memset(&db->slc_lr[idx.ids].data, 0x0, sizeof(struct hw_db_inline_slc_lr_data));
+ db->slc_lr[idx.ids].ref = 0;
+ }
+}
+
/******************************************************************************/
/* CAT */
/******************************************************************************/
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h
index 38502ac1ec..ef63336b1c 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h
@@ -40,10 +40,15 @@ struct hw_db_cat_idx {
HW_DB_IDX;
};
+struct hw_db_slc_lr_idx {
+ HW_DB_IDX;
+};
+
enum hw_db_idx_type {
HW_DB_IDX_TYPE_NONE = 0,
HW_DB_IDX_TYPE_COT,
HW_DB_IDX_TYPE_CAT,
+ HW_DB_IDX_TYPE_SLC_LR,
};
/* Functionality data types */
@@ -89,6 +94,13 @@ struct hw_db_inline_cot_data {
uint32_t padding : 24;
};
+struct hw_db_inline_slc_lr_data {
+ uint32_t head_slice_en : 1;
+ uint32_t head_slice_dyn : 5;
+ uint32_t head_slice_ofs : 8;
+ uint32_t padding : 18;
+};
+
struct hw_db_inline_hsh_data {
uint32_t func;
uint64_t hash_mask;
@@ -119,6 +131,13 @@ struct hw_db_cot_idx hw_db_inline_cot_add(struct flow_nic_dev *ndev, void *db_ha
void hw_db_inline_cot_ref(struct flow_nic_dev *ndev, void *db_handle, struct hw_db_cot_idx idx);
void hw_db_inline_cot_deref(struct flow_nic_dev *ndev, void *db_handle, struct hw_db_cot_idx idx);
+struct hw_db_slc_lr_idx hw_db_inline_slc_lr_add(struct flow_nic_dev *ndev, void *db_handle,
+ const struct hw_db_inline_slc_lr_data *data);
+void hw_db_inline_slc_lr_ref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx);
+void hw_db_inline_slc_lr_deref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx);
+
/**/
struct hw_db_cat_idx hw_db_inline_cat_add(struct flow_nic_dev *ndev, void *db_handle,
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index f7babec3b4..c2a0273aa2 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -2302,6 +2302,26 @@ static int setup_flow_flm_actions(struct flow_eth_dev *dev,
(void)hsh_data;
(void)error;
+ /* Setup SLC LR */
+ struct hw_db_slc_lr_idx slc_lr_idx = { .raw = 0 };
+
+ if (fd->header_strip_end_dyn != 0 || fd->header_strip_end_ofs != 0) {
+ struct hw_db_inline_slc_lr_data slc_lr_data = {
+ .head_slice_en = 1,
+ .head_slice_dyn = fd->header_strip_end_dyn,
+ .head_slice_ofs = fd->header_strip_end_ofs,
+ };
+ slc_lr_idx =
+ hw_db_inline_slc_lr_add(dev->ndev, dev->ndev->hw_db_handle, &slc_lr_data);
+ local_idxs[(*local_idx_counter)++] = slc_lr_idx.raw;
+
+ if (slc_lr_idx.error) {
+ NT_LOG(ERR, FILTER, "Could not reference SLC LR resource");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return -1;
+ }
+ }
+
return 0;
}
@@ -2469,6 +2489,9 @@ int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
if (hw_mod_cat_cot_flush(&ndev->be, 0, 1) < 0)
goto err_exit0;
+ /* SLC LR index 0 is reserved */
+ flow_nic_mark_resource_used(ndev, RES_SLC_LR_RCP, 0);
+
/* Setup filter using matching all packets violating traffic policing parameters */
flow_nic_mark_resource_used(ndev, RES_CAT_CFN, NT_VIOLATING_MBR_CFN);
@@ -2517,6 +2540,10 @@ int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
hw_mod_cat_cot_flush(&ndev->be, 0, 1);
flow_nic_free_resource(ndev, RES_CAT_CFN, 0);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_PRESET_ALL, 0, 0);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_SLC_LR_RCP, 0);
+
hw_mod_tpe_reset(&ndev->be);
flow_nic_free_resource(ndev, RES_TPE_RCP, 0);
flow_nic_free_resource(ndev, RES_TPE_EXT, 0);
--
2.45.0
More information about the dev
mailing list