[v4,76/86] net/ntnic: flow update was added

Message ID 20241029164243.1648775-77-sil-plv@napatech.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series Provide flow filter API and statistics |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Serhii Iliushyk Oct. 29, 2024, 4:42 p.m. UTC
From: Danylo Vodopianov <dvo-plv@napatech.com>

Flow action update was implemented.

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

Patch

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,
 	/*