From: Danylo Vodopianov <dvo-...@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-...@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  |  37 ++++++-
 5 files changed, 257 insertions(+), 5 deletions(-)

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 addd5f288f..b17bce3745 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
@@ -20,7 +20,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 {
@@ -55,6 +61,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));
 
@@ -72,6 +86,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);
@@ -95,6 +110,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;
                }
@@ -235,6 +255,90 @@ void hw_db_inline_cot_deref(struct flow_nic_dev *ndev 
__rte_unused, void *db_han
        }
 }
 
+/******************************************************************************/
+/* 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 5176464054..73fab083de 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
@@ -2277,18 +2277,38 @@ static int convert_fh_to_fh_flm(struct flow_handle *fh, 
const uint32_t *packet_d
        return 0;
 }
 
-static int setup_flow_flm_actions(struct flow_eth_dev *dev __rte_unused,
-       const struct nic_flow_def *fd __rte_unused,
+static int setup_flow_flm_actions(struct flow_eth_dev *dev,
+       const struct nic_flow_def *fd,
        const struct hw_db_inline_qsl_data *qsl_data __rte_unused,
        const struct hw_db_inline_hsh_data *hsh_data __rte_unused,
        uint32_t group __rte_unused,
-       uint32_t local_idxs[] __rte_unused,
-       uint32_t *local_idx_counter __rte_unused,
+       uint32_t local_idxs[],
+       uint32_t *local_idx_counter,
        uint16_t *flm_rpl_ext_ptr __rte_unused,
        uint32_t *flm_ft __rte_unused,
        uint32_t *flm_scrub __rte_unused,
-       struct rte_flow_error *error __rte_unused)
+       struct rte_flow_error *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;
 }
 
@@ -2450,6 +2470,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);
 
@@ -2498,6 +2521,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

Reply via email to