From: Danylo Vodopianov <dvo-...@napatech.com>

Flow action update was implemented.

Signed-off-by: Danylo Vodopianov <dvo-...@napatech.com>
---
 .../profile_inline/flow_api_profile_inline.c  | 165 ++++++++++++++++++
 1 file changed, 165 insertions(+)

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 88b716d836..98bfc01539 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
@@ -15,6 +15,7 @@
 #include "flow_api_hw_db_inline.h"
 #include "flow_api_profile_inline_config.h"
 #include "flow_id_table.h"
+#include "rte_flow.h"
 #include "stream_binary_flow_api.h"
 
 #include "flow_api_profile_inline.h"
@@ -36,6 +37,7 @@
 #define NT_FLM_UNHANDLED_FLOW_TYPE 1
 #define NT_FLM_OP_UNLEARN 0
 #define NT_FLM_OP_LEARN 1
+#define NT_FLM_OP_RELEARN 2
 
 #define NT_FLM_VIOLATING_MBR_FLOW_TYPE 15
 #define NT_VIOLATING_MBR_CFN 0
@@ -4385,6 +4387,168 @@ int flow_flush_profile_inline(struct flow_eth_dev *dev,
        return err;
 }
 
+int flow_actions_update_profile_inline(struct flow_eth_dev *dev,
+       struct flow_handle *flow,
+       const struct rte_flow_action action[],
+       struct rte_flow_error *error)
+{
+       assert(dev);
+       assert(flow);
+
+       uint32_t num_dest_port = 0;
+       uint32_t num_queues = 0;
+
+       int group = (int)flow->flm_kid - 2;
+
+       flow_nic_set_error(ERR_SUCCESS, error);
+
+       if (flow->type != FLOW_HANDLE_TYPE_FLM) {
+               NT_LOG(ERR, FILTER,
+                       "Flow actions update not supported for group 0 or 
default flows");
+               flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM, 
error);
+               return -1;
+       }
+
+       struct nic_flow_def *fd = allocate_nic_flow_def();
+
+       if (fd == NULL) {
+               error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+               error->message = "Failed to allocate nic_flow_def";
+               return -1;
+       }
+
+       fd->non_empty = 1;
+
+       int res =
+               interpret_flow_actions(dev, action, NULL, fd, error, 
&num_dest_port, &num_queues);
+
+       if (res) {
+               free(fd);
+               return -1;
+       }
+
+       pthread_mutex_lock(&dev->ndev->mtx);
+
+       /* Setup new actions */
+       uint32_t local_idx_counter = 0;
+       uint32_t local_idxs[RES_COUNT];
+       memset(local_idxs, 0x0, sizeof(uint32_t) * RES_COUNT);
+
+       struct hw_db_inline_qsl_data qsl_data;
+       setup_db_qsl_data(fd, &qsl_data, num_dest_port, num_queues);
+
+       struct hw_db_inline_hsh_data hsh_data;
+       setup_db_hsh_data(fd, &hsh_data);
+
+       {
+               uint32_t flm_ft = 0;
+               uint32_t flm_scrub = 0;
+
+               /* Setup FLM RCP */
+               const struct hw_db_inline_flm_rcp_data *flm_data =
+                       hw_db_inline_find_data(dev->ndev, 
dev->ndev->hw_db_handle,
+                               HW_DB_IDX_TYPE_FLM_RCP,
+                               (struct hw_db_idx *)flow->flm_db_idxs,
+                               flow->flm_db_idx_counter);
+
+               if (flm_data == NULL) {
+                       NT_LOG(ERR, FILTER, "Could not retrieve FLM RPC 
resource");
+                       
flow_nic_set_error(ERR_MATCH_INVALID_OR_UNSUPPORTED_ELEM, error);
+                       goto error_out;
+               }
+
+               struct hw_db_flm_idx flm_idx =
+                       hw_db_inline_flm_add(dev->ndev, 
dev->ndev->hw_db_handle, flm_data, group);
+
+               local_idxs[local_idx_counter++] = flm_idx.raw;
+
+               if (flm_idx.error) {
+                       NT_LOG(ERR, FILTER, "Could not reference FLM RPC 
resource");
+                       flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, 
error);
+                       goto error_out;
+               }
+
+               if (setup_flow_flm_actions(dev, fd, &qsl_data, &hsh_data, 
group, local_idxs,
+                               &local_idx_counter, &flow->flm_rpl_ext_ptr, 
&flm_ft,
+                               &flm_scrub, error)) {
+                       goto error_out;
+               }
+
+               /* Update flow_handle */
+               for (int i = 0; i < MAX_FLM_MTRS_SUPPORTED; ++i) {
+                       struct flm_flow_mtr_handle_s *handle = 
dev->ndev->flm_mtr_handle;
+                       struct flm_mtr_stat_s *mtr_stat =
+                                       
handle->port_stats[flow->caller_id]->stats;
+                       flow->flm_mtr_ids[i] =
+                               fd->mtr_ids[i] == UINT32_MAX ? 0 : 
mtr_stat[fd->mtr_ids[i]].flm_id;
+               }
+
+               for (unsigned int i = 0; i < fd->modify_field_count; ++i) {
+                       switch (fd->modify_field[i].select) {
+                       case CPY_SELECT_DSCP_IPV4:
+
+                       /* fallthrough */
+                       case CPY_SELECT_DSCP_IPV6:
+                               flow->flm_dscp = fd->modify_field[i].value8[0];
+                               break;
+
+                       case CPY_SELECT_RQI_QFI:
+                               flow->flm_rqi = (fd->modify_field[i].value8[0] 
>> 6) & 0x1;
+                               flow->flm_qfi = fd->modify_field[i].value8[0] & 
0x3f;
+                               break;
+
+                       case CPY_SELECT_IPV4:
+                               flow->flm_nat_ipv4 = 
ntohl(fd->modify_field[i].value32[0]);
+                               break;
+
+                       case CPY_SELECT_PORT:
+                               flow->flm_nat_port = 
ntohs(fd->modify_field[i].value16[0]);
+                               break;
+
+                       case CPY_SELECT_TEID:
+                               flow->flm_teid = 
ntohl(fd->modify_field[i].value32[0]);
+                               break;
+
+                       default:
+                               NT_LOG(DBG, FILTER, "Unknown modify field: %d",
+                                       fd->modify_field[i].select);
+                               break;
+                       }
+               }
+
+               flow->flm_ft = (uint8_t)flm_ft;
+               flow->flm_scrub_prof = (uint8_t)flm_scrub;
+               flow->context = fd->age.context;
+
+               /* Program flow */
+               flm_flow_programming(flow, NT_FLM_OP_RELEARN);
+
+               hw_db_inline_deref_idxs(dev->ndev, dev->ndev->hw_db_handle,
+                       (struct hw_db_idx *)flow->flm_db_idxs,
+                       flow->flm_db_idx_counter);
+               memset(flow->flm_db_idxs, 0x0, sizeof(struct hw_db_idx) * 
RES_COUNT);
+
+               flow->flm_db_idx_counter = local_idx_counter;
+
+               for (int i = 0; i < RES_COUNT; ++i)
+                       flow->flm_db_idxs[i] = local_idxs[i];
+       }
+
+       pthread_mutex_unlock(&dev->ndev->mtx);
+
+       free(fd);
+       return 0;
+
+error_out:
+       hw_db_inline_deref_idxs(dev->ndev, dev->ndev->hw_db_handle, (struct 
hw_db_idx *)local_idxs,
+               local_idx_counter);
+
+       pthread_mutex_unlock(&dev->ndev->mtx);
+
+       free(fd);
+       return -1;
+}
+
 static __rte_always_inline bool all_bits_enabled(uint64_t hash_mask, uint64_t 
hash_bits)
 {
        return (hash_mask & hash_bits) == hash_bits;
@@ -5328,6 +5492,7 @@ static const struct profile_inline_ops ops = {
        .flow_create_profile_inline = flow_create_profile_inline,
        .flow_destroy_profile_inline = flow_destroy_profile_inline,
        .flow_flush_profile_inline = flow_flush_profile_inline,
+       .flow_actions_update_profile_inline = 
flow_actions_update_profile_inline,
        .flow_nic_set_hasher_fields_inline = flow_nic_set_hasher_fields_inline,
        .flow_get_aged_flows_profile_inline = 
flow_get_aged_flows_profile_inline,
        /*
-- 
2.45.0

Reply via email to