DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 1/3] table: improve learner table timers
@ 2022-04-21 15:59 Cristian Dumitrescu
  2022-04-21 15:59 ` [PATCH 2/3] pipeline: " Cristian Dumitrescu
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Cristian Dumitrescu @ 2022-04-21 15:59 UTC (permalink / raw)
  To: dev

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/pipeline/rte_swx_pipeline.c          |   3 +-
 lib/pipeline/rte_swx_pipeline_internal.h |   3 +-
 lib/table/rte_swx_table_learner.c        | 109 ++++++++++++++++++++---
 lib/table/rte_swx_table_learner.h        |  90 +++++++++++++++++--
 lib/table/version.map                    |   4 +
 5 files changed, 189 insertions(+), 20 deletions(-)

diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index dfbac929c7..17be31d5a4 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -8788,7 +8788,8 @@ learner_params_get(struct learner *l)
 	params->n_keys_max = l->size;
 
 	/* Timeout. */
-	params->key_timeout = l->timeout;
+	params->key_timeout[0] = l->timeout;
+	params->n_key_timeouts = 1;
 
 	return params;
 
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index 381a35c6e0..51bb464f5f 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -2215,7 +2215,8 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
 					   l->mailbox,
 					   t->time,
 					   action_id,
-					   &t->metadata[mf_offset]);
+					   &t->metadata[mf_offset],
+					   0);
 
 	TRACE("[Thread %2u] learner %u learn %s\n",
 	      p->thread_id,
diff --git a/lib/table/rte_swx_table_learner.c b/lib/table/rte_swx_table_learner.c
index 15576c2aa3..02f7613c22 100644
--- a/lib/table/rte_swx_table_learner.c
+++ b/lib/table/rte_swx_table_learner.c
@@ -231,11 +231,14 @@ table_keycmp(void *a, void *b, void *b_mask, uint32_t n_bytes)
 #define TABLE_KEYS_PER_BUCKET 4
 
 #define TABLE_BUCKET_PAD_SIZE \
-	(RTE_CACHE_LINE_SIZE - TABLE_KEYS_PER_BUCKET * (sizeof(uint32_t) + sizeof(uint32_t)))
+	(RTE_CACHE_LINE_SIZE - TABLE_KEYS_PER_BUCKET * (sizeof(uint32_t) + \
+	                                                sizeof(uint32_t) + \
+	                                                sizeof(uint8_t)))
 
 struct table_bucket {
 	uint32_t time[TABLE_KEYS_PER_BUCKET];
 	uint32_t sig[TABLE_KEYS_PER_BUCKET];
+	uint8_t key_timeout_id[TABLE_KEYS_PER_BUCKET];
 	uint8_t pad[TABLE_BUCKET_PAD_SIZE];
 	uint8_t key[0];
 };
@@ -284,8 +287,11 @@ struct table_params {
 	/* log2(bucket_size). Purpose: avoid multiplication with non-power of 2 numbers. */
 	size_t bucket_size_log2;
 
-	/* Timeout in CPU clock cycles. */
-	uint64_t key_timeout;
+	/* Set of all possible key timeout values measured in CPU clock cycles. */
+	uint64_t key_timeout[RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX];
+
+	/* Number of key timeout values. */
+	uint32_t n_key_timeouts;
 
 	/* Total memory size. */
 	size_t total_size;
@@ -305,15 +311,23 @@ struct table {
 static int
 table_params_get(struct table_params *p, struct rte_swx_table_learner_params *params)
 {
+	uint32_t i;
+
 	/* Check input parameters. */
 	if (!params ||
 	    !params->key_size ||
 	    (params->key_size > 64) ||
 	    !params->n_keys_max ||
 	    (params->n_keys_max > 1U << 31) ||
-	    !params->key_timeout)
+	    !params->key_timeout ||
+	    !params->n_key_timeouts ||
+	    (params->n_key_timeouts > RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX))
 		return -EINVAL;
 
+	for (i = 0; i < params->n_key_timeouts; i++)
+		if (!params->key_timeout[i])
+			return -EINVAL;
+
 	/* Key. */
 	p->key_size = params->key_size;
 
@@ -346,7 +360,17 @@ table_params_get(struct table_params *p, struct rte_swx_table_learner_params *pa
 	p->bucket_size_log2 = __builtin_ctzll(p->bucket_size);
 
 	/* Timeout. */
-	p->key_timeout = params->key_timeout * rte_get_tsc_hz();
+	for (i = 0; i < params->n_key_timeouts; i++) {
+		p->key_timeout[i] = params->key_timeout[i] * rte_get_tsc_hz();
+
+		if (!(p->key_timeout[i] >> 32))
+			p->key_timeout[i] = 1LLU << 32;
+	}
+
+	p->n_key_timeouts = rte_align32pow2(params->n_key_timeouts);
+
+	for ( ; i < p->n_key_timeouts; i++)
+		p->key_timeout[i] = p->key_timeout[0];
 
 	/* Total size. */
 	p->total_size = sizeof(struct table) + p->n_buckets * p->bucket_size;
@@ -505,8 +529,6 @@ rte_swx_table_learner_lookup(void *table,
 				/* Hit. */
 				rte_prefetch0(data);
 
-				b->time[i] = (input_time + t->params.key_timeout) >> 32;
-
 				m->hit = 1;
 				m->bucket_key_pos = i;
 				m->state = 0;
@@ -536,23 +558,83 @@ rte_swx_table_learner_lookup(void *table,
 	}
 }
 
+void
+rte_swx_table_learner_rearm(void *table,
+			    void *mailbox,
+			    uint64_t input_time)
+{
+	struct table *t = table;
+	struct mailbox *m = mailbox;
+	struct table_bucket *b;
+	size_t bucket_key_pos;
+	uint64_t key_timeout;
+	uint32_t key_timeout_id;
+
+	if (!m->hit)
+		return;
+
+	b = m->bucket;
+	bucket_key_pos = m->bucket_key_pos;
+
+	key_timeout_id = b->key_timeout_id[bucket_key_pos];
+	key_timeout = t->params.key_timeout[key_timeout_id];
+	b->time[bucket_key_pos] = (input_time + key_timeout) >> 32;
+}
+
+void
+rte_swx_table_learner_rearm_new(void *table,
+				void *mailbox,
+				uint64_t input_time,
+				uint32_t key_timeout_id)
+{
+	struct table *t = table;
+	struct mailbox *m = mailbox;
+	struct table_bucket *b;
+	size_t bucket_key_pos;
+	uint64_t key_timeout;
+
+	if (!m->hit)
+		return;
+
+	b = m->bucket;
+	bucket_key_pos = m->bucket_key_pos;
+
+	key_timeout_id &= t->params.n_key_timeouts - 1;
+	key_timeout = t->params.key_timeout[key_timeout_id];
+	b->time[bucket_key_pos] = (input_time + key_timeout) >> 32;
+	b->key_timeout_id[bucket_key_pos] = (uint8_t)key_timeout_id;
+}
+
 uint32_t
 rte_swx_table_learner_add(void *table,
 			  void *mailbox,
 			  uint64_t input_time,
 			  uint64_t action_id,
-			  uint8_t *action_data)
+			  uint8_t *action_data,
+			  uint32_t key_timeout_id)
 {
 	struct table *t = table;
 	struct mailbox *m = mailbox;
 	struct table_bucket *b = m->bucket;
+	uint64_t key_timeout;
 	uint32_t i;
 
-	/* Lookup hit: The key, key signature and key time are already properly configured (the key
-	 * time was bumped by lookup), only the key data need to be updated.
+	/* Adjust the key timeout ID to fit the valid range. */
+	key_timeout_id &= t->params.n_key_timeouts - 1;
+	key_timeout = t->params.key_timeout[key_timeout_id];
+
+	/* Lookup hit: The following bucket fields need to be updated:
+	 * - key (key, sig): NO (already correctly set).
+	 * - key timeout (key_timeout_id, time): YES.
+	 * - key data (data): YES.
 	 */
 	if (m->hit) {
-		uint64_t *data = table_bucket_data_get(t, b, m->bucket_key_pos);
+		size_t bucket_key_pos = m->bucket_key_pos;
+		uint64_t *data = table_bucket_data_get(t, b, bucket_key_pos);
+
+		/* Install the key timeout. */
+		b->time[bucket_key_pos] = (input_time + key_timeout) >> 32;
+		b->key_timeout_id[bucket_key_pos] = (uint8_t)key_timeout_id;
 
 		/* Install the key data. */
 		data[0] = action_id;
@@ -576,9 +658,10 @@ rte_swx_table_learner_add(void *table,
 			uint8_t *key = table_bucket_key_get(t, b, i);
 			uint64_t *data = table_bucket_data_get(t, b, i);
 
-			/* Install the key. */
-			b->time[i] = (input_time + t->params.key_timeout) >> 32;
+			/* Install the key and the key timeout. */
+			b->time[i] = (input_time + key_timeout) >> 32;
 			b->sig[i] = m->input_sig;
+			b->key_timeout_id[i] = (uint8_t)key_timeout_id;
 			memcpy(key, m->input_key, t->params.key_size);
 
 			/* Install the key data. */
diff --git a/lib/table/rte_swx_table_learner.h b/lib/table/rte_swx_table_learner.h
index eb9d7689fd..8b3128ec5d 100644
--- a/lib/table/rte_swx_table_learner.h
+++ b/lib/table/rte_swx_table_learner.h
@@ -18,13 +18,43 @@ extern "C" {
  * implementation of the "add on miss" scenario: whenever the lookup key is not found in the table
  * (lookup miss), the data plane can decide to add this key to the table with a given action with no
  * control plane intervention. Likewise, the table keys expire based on a configurable timeout and
- * are automatically deleted from the table with no control plane intervention.
+ * are thus automatically removed from the table with no control plane intervention.
+ *
+ * The keys are not automatically rearmed on lookup hit. To delay the key expiration, the key timer
+ * has to be explicitly reinitialized on lookup hit. The key will be kept in the table as long as it
+ * is frequently hit and explicitly rearmed on every hit.
+ *
+ * Operation overview:
+ * 1) Lookup miss:
+ *      a) add: Add the current input key (the key that missed the lookup) to the table with given
+ *              action, action parameters and expiration timeout. This is the way to populate the
+ *              table (which is empty initially). Data plane operation.
+ *      b) Do nothing: Keep the current input key out of the table.
+ * 2) Lookup hit:
+ *      a) add: Update the action, action parameters and/or the expiration timeout for the current
+ *              input key, which is already in the table. The expiration timer of the key is
+ *              automatically rearmed. Data plane operation.
+ *      b) rearm: Rearm the expiration timer for the current input key, which is already in the
+ *              table. The timeout value used for the expiration timer is either the same as the one
+ *              currently associated with the key or a new one can be provided as input. Data plane
+ *              operation.
+ *      c) delete: Delete the current input key from the table. The purpose of this operation is to
+ *              force the deletion of the key from the table before the key expires on timeout due
+ *              to inactivity. Data plane operation.
+ *      d) Do nothing: Keep the expiration timer of the current input key running down. This key
+ *              will thus expire naturally, unless it is hit again as part of a subsequent lookup
+ *              operation, when the key timer can be rearmed or re-added to prolong its life.
  */
 
 #include <stdint.h>
 
 #include <rte_compat.h>
 
+/** Maximum number of key timeout values per learner table. */
+#ifndef RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX
+#define RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX 16
+#endif
+
 /** Learner table creation parameters. */
 struct rte_swx_table_learner_params {
 	/** Key size in bytes. Must be non-zero. */
@@ -50,10 +80,16 @@ struct rte_swx_table_learner_params {
 	/** Maximum number of keys to be stored in the table together with their associated data. */
 	uint32_t n_keys_max;
 
-	/** Key timeout in seconds. Must be non-zero. Each table key expires and is automatically
-	 * deleted from the table after this many seconds.
+	/** The set of all possible key timeout values measured in seconds. Each value must be
+	 * non-zero. Each table key expires and is automatically deleted from the table after
+	 * this many seconds.
 	 */
-	uint32_t key_timeout;
+	uint32_t *key_timeout;
+
+	/** Number of possible key timeout values present in the *key_timeout* set. It must be less
+	 * than or equal to *RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX*.
+	 */
+	uint32_t n_key_timeouts;
 };
 
 /**
@@ -160,6 +196,8 @@ rte_swx_table_learner_lookup(void *table,
  *   ID of the action associated with the key.
  * @param[out] action_data
  *   Action data for the *action_id* action.
+ * @param[in] key_timeout_id
+ *   Key timeout ID.
  * @return
  *   0 on success, 1 or error (table full).
  */
@@ -169,7 +207,49 @@ rte_swx_table_learner_add(void *table,
 			  void *mailbox,
 			  uint64_t time,
 			  uint64_t action_id,
-			  uint8_t *action_data);
+			  uint8_t *action_data,
+			  uint32_t key_timeout_id);
+
+/**
+ * Learner table key rearm with same timeout value
+ *
+ * This operation takes the latest key that was looked up in the table and, in case of lookup hit,
+ * it rearms its expiration timer using the same timeout value currently associated with the key.
+ *
+ * @param[in] table
+ *   Table handle.
+ * @param[in] mailbox
+ *   Mailbox for the current operation.
+ * @param[in] time
+ *   Current time measured in CPU clock cycles.
+ */
+__rte_experimental
+void
+rte_swx_table_learner_rearm(void *table,
+			    void *mailbox,
+			    uint64_t time);
+
+/**
+ * Learner table key rearm with given timeout value
+ *
+ * This operation takes the latest key that was looked up in the table and, in case of lookup hit,
+ * it rearms its expiration timer using the given timeout value.
+ *
+ * @param[in] table
+ *   Table handle.
+ * @param[in] mailbox
+ *   Mailbox for the current operation.
+ * @param[in] time
+ *   Current time measured in CPU clock cycles.
+ * @param[in] key_timeout_id
+ *   Key timeout ID.
+ */
+__rte_experimental
+void
+rte_swx_table_learner_rearm_new(void *table,
+				void *mailbox,
+				uint64_t time,
+				uint32_t key_timeout_id);
 
 /**
  * Learner table key delete
diff --git a/lib/table/version.map b/lib/table/version.map
index efe5f6e52c..d27d649332 100644
--- a/lib/table/version.map
+++ b/lib/table/version.map
@@ -45,4 +45,8 @@ EXPERIMENTAL {
 	rte_swx_table_learner_free;
 	rte_swx_table_learner_lookup;
 	rte_swx_table_learner_mailbox_size_get;
+
+	#added in 22.07
+	rte_swx_table_learner_rearm;
+	rte_swx_table_learner_rearm_new;
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-06-01 13:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-21 15:59 [PATCH 1/3] table: improve learner table timers Cristian Dumitrescu
2022-04-21 15:59 ` [PATCH 2/3] pipeline: " Cristian Dumitrescu
2022-04-21 15:59 ` [PATCH 3/3] examples/pipeline: " Cristian Dumitrescu
2022-04-22 13:03 ` [PATCH V2 1/3] table: " Cristian Dumitrescu
2022-04-22 13:03   ` [PATCH V2 2/3] pipeline: " Cristian Dumitrescu
2022-04-22 13:03   ` [PATCH V2 3/3] examples/pipeline: " Cristian Dumitrescu
2022-05-20 22:12   ` [PATCH V3 1/3] table: " Cristian Dumitrescu
2022-05-20 22:12     ` [PATCH V3 2/3] pipeline: " Cristian Dumitrescu
2022-05-20 22:12     ` [PATCH V3 3/3] examples/pipeline: " Cristian Dumitrescu
2022-06-01 13:57     ` [PATCH V3 1/3] table: " Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).