@@ -58,6 +58,7 @@ sources = files(
'nthw/flow_api/flow_group.c',
'nthw/flow_api/flow_id_table.c',
'nthw/flow_api/hw_mod/hw_mod_backend.c',
+ 'nthw/flow_api/profile_inline/flm_age_queue.c',
'nthw/flow_api/profile_inline/flm_lrn_queue.c',
'nthw/flow_api/profile_inline/flm_evt_queue.c',
'nthw/flow_api/profile_inline/flow_api_profile_inline.c',
new file mode 100644
@@ -0,0 +1,49 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#include <rte_ring.h>
+
+#include "ntlog.h"
+#include "flm_age_queue.h"
+
+/* Queues for flm aged events */
+static struct rte_ring *age_queue[MAX_EVT_AGE_QUEUES];
+
+int flm_age_queue_get(uint16_t caller_id, struct flm_age_event_s *obj)
+{
+ int ret;
+
+ /* If queues is not created, then ignore and return */
+ if (caller_id < MAX_EVT_AGE_QUEUES && age_queue[caller_id] != NULL) {
+ ret = rte_ring_sc_dequeue_elem(age_queue[caller_id], obj, FLM_AGE_ELEM_SIZE);
+
+ if (ret != 0)
+ NT_LOG(DBG, FILTER, "FLM aged event queue empty");
+
+ return ret;
+ }
+
+ return -ENOENT;
+}
+
+unsigned int flm_age_queue_count(uint16_t caller_id)
+{
+ unsigned int ret = 0;
+
+ if (caller_id < MAX_EVT_AGE_QUEUES && age_queue[caller_id] != NULL)
+ ret = rte_ring_count(age_queue[caller_id]);
+
+ return ret;
+}
+
+unsigned int flm_age_queue_get_size(uint16_t caller_id)
+{
+ unsigned int ret = 0;
+
+ if (caller_id < MAX_EVT_AGE_QUEUES && age_queue[caller_id] != NULL)
+ ret = rte_ring_get_size(age_queue[caller_id]);
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#ifndef _FLM_AGE_QUEUE_H_
+#define _FLM_AGE_QUEUE_H_
+
+#include "stdint.h"
+
+struct flm_age_event_s {
+ void *context;
+};
+
+/* Max number of event queues */
+#define MAX_EVT_AGE_QUEUES 256
+
+#define FLM_AGE_ELEM_SIZE sizeof(struct flm_age_event_s)
+
+int flm_age_queue_get(uint16_t caller_id, struct flm_age_event_s *obj);
+unsigned int flm_age_queue_count(uint16_t caller_id);
+unsigned int flm_age_queue_get_size(uint16_t caller_id);
+
+#endif /* _FLM_AGE_QUEUE_H_ */
@@ -7,6 +7,7 @@
#include "nt_util.h"
#include "hw_mod_backend.h"
+#include "flm_age_queue.h"
#include "flm_lrn_queue.h"
#include "flow_api.h"
#include "flow_api_engine.h"
@@ -4390,6 +4391,55 @@ static void dump_flm_data(const uint32_t *data, FILE *file)
}
}
+int flow_get_aged_flows_profile_inline(struct flow_eth_dev *dev,
+ uint16_t caller_id,
+ void **context,
+ uint32_t nb_contexts,
+ struct rte_flow_error *error)
+{
+ (void)dev;
+ flow_nic_set_error(ERR_SUCCESS, error);
+
+ unsigned int queue_size = flm_age_queue_get_size(caller_id);
+
+ if (queue_size == 0) {
+ error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Aged queue size is not configured";
+ return -1;
+ }
+
+ unsigned int queue_count = flm_age_queue_count(caller_id);
+
+ if (context == NULL)
+ return queue_count;
+
+ if (queue_count < nb_contexts) {
+ error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Aged queue size contains fewer records than the expected output";
+ return -1;
+ }
+
+ if (queue_size < nb_contexts) {
+ error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Defined aged queue size is smaller than the expected output";
+ return -1;
+ }
+
+ uint32_t idx;
+
+ for (idx = 0; idx < nb_contexts; ++idx) {
+ struct flm_age_event_s obj;
+ int ret = flm_age_queue_get(caller_id, &obj);
+
+ if (ret != 0)
+ break;
+
+ context[idx] = obj.context;
+ }
+
+ return idx;
+}
+
int flow_dev_dump_profile_inline(struct flow_eth_dev *dev,
struct flow_handle *flow,
uint16_t caller_id,
@@ -4520,6 +4570,7 @@ static const struct profile_inline_ops ops = {
.flow_destroy_profile_inline = flow_destroy_profile_inline,
.flow_flush_profile_inline = flow_flush_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,
/*
* Stats
*/
@@ -48,6 +48,12 @@ int flow_dev_dump_profile_inline(struct flow_eth_dev *dev,
FILE *file,
struct rte_flow_error *error);
+int flow_get_aged_flows_profile_inline(struct flow_eth_dev *dev,
+ uint16_t caller_id,
+ void **context,
+ uint32_t nb_contexts,
+ struct rte_flow_error *error);
+
int flow_nic_set_hasher_fields_inline(struct flow_nic_dev *ndev,
int hsh_idx,
struct nt_eth_rss_conf rss_conf);