From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
To: dev@dpdk.org
Subject: [PATCH 1/3] table: improve learner table timers
Date: Thu, 21 Apr 2022 16:59:49 +0100 [thread overview]
Message-ID: <20220421155951.31811-1-cristian.dumitrescu@intel.com> (raw)
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
next reply other threads:[~2022-04-21 15:59 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-21 15:59 Cristian Dumitrescu [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220421155951.31811-1-cristian.dumitrescu@intel.com \
--to=cristian.dumitrescu@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).