pipeline: improve learner table timers
Enable the pipeline to use the improved learner table timer operation through the new "rearm" instruction. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
8186c0bbc9
commit
e2ecc53582
@ -548,6 +548,9 @@ struct rte_swx_ctl_learner_info {
|
||||
|
||||
/** Learner table size parameter. */
|
||||
uint32_t size;
|
||||
|
||||
/** Number of possible key timeout values. */
|
||||
uint32_t n_key_timeouts;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -615,6 +618,50 @@ rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
|
||||
uint32_t learner_action_id,
|
||||
struct rte_swx_ctl_table_action_info *learner_action);
|
||||
|
||||
/**
|
||||
* Learner table timeout get
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] learner_id
|
||||
* Learner table ID (0 .. *n_learners* - 1).
|
||||
* @param[in] timeout_id
|
||||
* Timeout ID.
|
||||
* @param[out] timeout
|
||||
* Timeout value measured in seconds. Must be non-NULL.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
|
||||
uint32_t learner_id,
|
||||
uint32_t timeout_id,
|
||||
uint32_t *timeout);
|
||||
|
||||
/**
|
||||
* Learner table timeout set
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] learner_id
|
||||
* Learner table ID (0 .. *n_learners* - 1).
|
||||
* @param[in] timeout_id
|
||||
* Timeout ID.
|
||||
* @param[in] timeout
|
||||
* Timeout value measured in seconds.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
|
||||
uint32_t learner_id,
|
||||
uint32_t timeout_id,
|
||||
uint32_t timeout);
|
||||
|
||||
/** Learner table statistics. */
|
||||
struct rte_swx_learner_stats {
|
||||
/** Number of packets with lookup hit. */
|
||||
@ -629,6 +676,9 @@ struct rte_swx_learner_stats {
|
||||
/** Number of packets with learning error. */
|
||||
uint64_t n_pkts_learn_err;
|
||||
|
||||
/** Number of packets with rearm event. */
|
||||
uint64_t n_pkts_rearm;
|
||||
|
||||
/** Number of packets with forget event. */
|
||||
uint64_t n_pkts_forget;
|
||||
|
||||
|
@ -2556,7 +2556,7 @@ instr_learner_af_exec(struct rte_swx_pipeline *p)
|
||||
stats->n_pkts_action[action_id] = n_pkts_action + 1;
|
||||
|
||||
/* Thread. */
|
||||
thread_ip_action_call(p, t, action_id);
|
||||
thread_ip_inc(p);
|
||||
|
||||
/* Action */
|
||||
action_func(p);
|
||||
@ -2583,31 +2583,38 @@ instr_learn_translate(struct rte_swx_pipeline *p,
|
||||
struct instruction_data *data __rte_unused)
|
||||
{
|
||||
struct action *a;
|
||||
const char *mf_name;
|
||||
uint32_t mf_offset = 0;
|
||||
struct field *mf_first_arg = NULL, *mf_timeout_id = NULL;
|
||||
const char *mf_first_arg_name, *mf_timeout_id_name;
|
||||
|
||||
CHECK(action, EINVAL);
|
||||
CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
|
||||
CHECK((n_tokens == 3) || (n_tokens == 4), EINVAL);
|
||||
|
||||
/* Action. */
|
||||
a = action_find(p, tokens[1]);
|
||||
CHECK(a, EINVAL);
|
||||
CHECK(!action_has_nbo_args(a), EINVAL);
|
||||
|
||||
mf_name = (n_tokens > 2) ? tokens[2] : NULL;
|
||||
CHECK(!learner_action_args_check(p, a, mf_name), EINVAL);
|
||||
/* Action first argument. */
|
||||
mf_first_arg_name = (n_tokens == 4) ? tokens[2] : NULL;
|
||||
CHECK(!learner_action_args_check(p, a, mf_first_arg_name), EINVAL);
|
||||
|
||||
if (mf_name) {
|
||||
struct field *mf;
|
||||
|
||||
mf = metadata_field_parse(p, mf_name);
|
||||
CHECK(mf, EINVAL);
|
||||
|
||||
mf_offset = mf->offset / 8;
|
||||
if (mf_first_arg_name) {
|
||||
mf_first_arg = metadata_field_parse(p, mf_first_arg_name);
|
||||
CHECK(mf_first_arg, EINVAL);
|
||||
}
|
||||
|
||||
/* Timeout ID. */
|
||||
mf_timeout_id_name = (n_tokens == 4) ? tokens[3] : tokens[2];
|
||||
CHECK_NAME(mf_timeout_id_name, EINVAL);
|
||||
mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
|
||||
CHECK(mf_timeout_id, EINVAL);
|
||||
|
||||
/* Instruction. */
|
||||
instr->type = INSTR_LEARNER_LEARN;
|
||||
instr->learn.action_id = a->id;
|
||||
instr->learn.mf_offset = mf_offset;
|
||||
instr->learn.mf_first_arg_offset = mf_first_arg ? (mf_first_arg->offset / 8) : 0;
|
||||
instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
|
||||
instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2624,6 +2631,66 @@ instr_learn_exec(struct rte_swx_pipeline *p)
|
||||
thread_ip_inc(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* rearm.
|
||||
*/
|
||||
static int
|
||||
instr_rearm_translate(struct rte_swx_pipeline *p,
|
||||
struct action *action,
|
||||
char **tokens,
|
||||
int n_tokens,
|
||||
struct instruction *instr,
|
||||
struct instruction_data *data __rte_unused)
|
||||
{
|
||||
struct field *mf_timeout_id;
|
||||
const char *mf_timeout_id_name;
|
||||
|
||||
CHECK(action, EINVAL);
|
||||
CHECK((n_tokens == 1) || (n_tokens == 2), EINVAL);
|
||||
|
||||
/* INSTR_LEARNER_REARM. */
|
||||
if (n_tokens == 1) {
|
||||
instr->type = INSTR_LEARNER_REARM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* INSTR_LEARNER_REARM_NEW. */
|
||||
mf_timeout_id_name = tokens[1];
|
||||
CHECK_NAME(mf_timeout_id_name, EINVAL);
|
||||
mf_timeout_id = metadata_field_parse(p, mf_timeout_id_name);
|
||||
CHECK(mf_timeout_id, EINVAL);
|
||||
|
||||
instr->type = INSTR_LEARNER_REARM_NEW;
|
||||
instr->learn.mf_timeout_id_offset = mf_timeout_id->offset / 8;
|
||||
instr->learn.mf_timeout_id_n_bits = mf_timeout_id->n_bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_rearm_exec(struct rte_swx_pipeline *p)
|
||||
{
|
||||
struct thread *t = &p->threads[p->thread_id];
|
||||
struct instruction *ip = t->ip;
|
||||
|
||||
__instr_rearm_exec(p, t, ip);
|
||||
|
||||
/* Thread. */
|
||||
thread_ip_inc(p);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_rearm_new_exec(struct rte_swx_pipeline *p)
|
||||
{
|
||||
struct thread *t = &p->threads[p->thread_id];
|
||||
struct instruction *ip = t->ip;
|
||||
|
||||
__instr_rearm_new_exec(p, t, ip);
|
||||
|
||||
/* Thread. */
|
||||
thread_ip_inc(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* forget.
|
||||
*/
|
||||
@ -6051,6 +6118,13 @@ instr_translate(struct rte_swx_pipeline *p,
|
||||
n_tokens - tpos,
|
||||
instr,
|
||||
data);
|
||||
if (!strcmp(tokens[tpos], "rearm"))
|
||||
return instr_rearm_translate(p,
|
||||
action,
|
||||
&tokens[tpos],
|
||||
n_tokens - tpos,
|
||||
instr,
|
||||
data);
|
||||
|
||||
if (!strcmp(tokens[tpos], "forget"))
|
||||
return instr_forget_translate(p,
|
||||
@ -7040,6 +7114,8 @@ static instr_exec_t instruction_table[] = {
|
||||
[INSTR_LEARNER] = instr_learner_exec,
|
||||
[INSTR_LEARNER_AF] = instr_learner_af_exec,
|
||||
[INSTR_LEARNER_LEARN] = instr_learn_exec,
|
||||
[INSTR_LEARNER_REARM] = instr_rearm_exec,
|
||||
[INSTR_LEARNER_REARM_NEW] = instr_rearm_new_exec,
|
||||
[INSTR_LEARNER_FORGET] = instr_forget_exec,
|
||||
[INSTR_EXTERN_OBJ] = instr_extern_obj_exec,
|
||||
[INSTR_EXTERN_FUNC] = instr_extern_func_exec,
|
||||
@ -8546,7 +8622,8 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
struct rte_swx_pipeline_learner_params *params,
|
||||
uint32_t size,
|
||||
uint32_t timeout)
|
||||
uint32_t *timeout,
|
||||
uint32_t n_timeouts)
|
||||
{
|
||||
struct learner *l = NULL;
|
||||
struct action *default_action;
|
||||
@ -8616,6 +8693,7 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
/* Any other checks. */
|
||||
CHECK(size, EINVAL);
|
||||
CHECK(timeout, EINVAL);
|
||||
CHECK(n_timeouts && (n_timeouts < RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX), EINVAL);
|
||||
|
||||
/* Memory allocation. */
|
||||
l = calloc(1, sizeof(struct learner));
|
||||
@ -8702,7 +8780,10 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
|
||||
l->size = size;
|
||||
|
||||
l->timeout = timeout;
|
||||
for (i = 0; i < n_timeouts; i++)
|
||||
l->timeout[i] = timeout[i];
|
||||
|
||||
l->n_timeouts = n_timeouts;
|
||||
|
||||
l->id = p->n_learners;
|
||||
|
||||
@ -8734,6 +8815,8 @@ learner_params_free(struct rte_swx_table_learner_params *params)
|
||||
|
||||
free(params->key_mask0);
|
||||
|
||||
free(params->key_timeout);
|
||||
|
||||
free(params);
|
||||
}
|
||||
|
||||
@ -8787,9 +8870,16 @@ learner_params_get(struct learner *l)
|
||||
/* Maximum number of keys. */
|
||||
params->n_keys_max = l->size;
|
||||
|
||||
/* Memory allocation. */
|
||||
params->key_timeout = calloc(l->n_timeouts, sizeof(uint32_t));
|
||||
if (!params->key_timeout)
|
||||
goto error;
|
||||
|
||||
/* Timeout. */
|
||||
params->key_timeout[0] = l->timeout;
|
||||
params->n_key_timeouts = 1;
|
||||
for (i = 0; i < l->n_timeouts; i++)
|
||||
params->key_timeout[i] = l->timeout[i];
|
||||
|
||||
params->n_key_timeouts = l->n_timeouts;
|
||||
|
||||
return params;
|
||||
|
||||
@ -9984,6 +10074,7 @@ rte_swx_ctl_learner_info_get(struct rte_swx_pipeline *p,
|
||||
learner->n_actions = l->n_actions;
|
||||
learner->default_action_is_const = l->default_action_is_const;
|
||||
learner->size = l->size;
|
||||
learner->n_key_timeouts = l->n_timeouts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -10039,6 +10130,56 @@ rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_ctl_pipeline_learner_timeout_get(struct rte_swx_pipeline *p,
|
||||
uint32_t learner_id,
|
||||
uint32_t timeout_id,
|
||||
uint32_t *timeout)
|
||||
{
|
||||
struct learner *l;
|
||||
|
||||
if (!p || (learner_id >= p->n_learners) || !timeout)
|
||||
return -EINVAL;
|
||||
|
||||
l = learner_find_by_id(p, learner_id);
|
||||
if (!l || (timeout_id >= l->n_timeouts))
|
||||
return -EINVAL;
|
||||
|
||||
*timeout = l->timeout[timeout_id];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_ctl_pipeline_learner_timeout_set(struct rte_swx_pipeline *p,
|
||||
uint32_t learner_id,
|
||||
uint32_t timeout_id,
|
||||
uint32_t timeout)
|
||||
{
|
||||
struct learner *l;
|
||||
struct rte_swx_table_state *ts;
|
||||
int status;
|
||||
|
||||
if (!p || (learner_id >= p->n_learners) || !timeout)
|
||||
return -EINVAL;
|
||||
|
||||
l = learner_find_by_id(p, learner_id);
|
||||
if (!l || (timeout_id >= l->n_timeouts))
|
||||
return -EINVAL;
|
||||
|
||||
if (!p->build_done)
|
||||
return -EINVAL;
|
||||
|
||||
ts = &p->table_state[p->n_tables + p->n_selectors + l->id];
|
||||
|
||||
status = rte_swx_table_learner_timeout_update(ts->obj, timeout_id, timeout);
|
||||
if (status)
|
||||
return -EINVAL;
|
||||
|
||||
l->timeout[timeout_id] = timeout;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p,
|
||||
struct rte_swx_table_state **table_state)
|
||||
@ -10170,6 +10311,7 @@ rte_swx_ctl_pipeline_learner_stats_read(struct rte_swx_pipeline *p,
|
||||
stats->n_pkts_learn_ok = learner_stats->n_pkts_learn[0];
|
||||
stats->n_pkts_learn_err = learner_stats->n_pkts_learn[1];
|
||||
|
||||
stats->n_pkts_rearm = learner_stats->n_pkts_rearm;
|
||||
stats->n_pkts_forget = learner_stats->n_pkts_forget;
|
||||
|
||||
return 0;
|
||||
@ -10583,6 +10725,8 @@ instr_type_to_name(struct instruction *instr)
|
||||
case INSTR_LEARNER_AF: return "INSTR_LEARNER_AF";
|
||||
|
||||
case INSTR_LEARNER_LEARN: return "INSTR_LEARNER_LEARN";
|
||||
case INSTR_LEARNER_REARM: return "INSTR_LEARNER_REARM";
|
||||
case INSTR_LEARNER_REARM_NEW: return "INSTR_LEARNER_REARM_NEW";
|
||||
case INSTR_LEARNER_FORGET: return "INSTR_LEARNER_FORGET";
|
||||
|
||||
case INSTR_EXTERN_OBJ: return "INSTR_EXTERN_OBJ";
|
||||
@ -11207,11 +11351,40 @@ instr_learn_export(struct instruction *instr, FILE *f)
|
||||
"\t{\n"
|
||||
"\t\t.type = %s,\n"
|
||||
"\t\t.learn = {\n"
|
||||
"\t\t\t\t.action_id = %u,\n"
|
||||
"\t\t\t.action_id = %u,\n"
|
||||
"\t\t\t.mf_first_arg_offset = %u,\n"
|
||||
"\t\t\t.mf_timeout_id_offset = %u,\n"
|
||||
"\t\t\t.mf_timeout_id_n_bits = %u,\n"
|
||||
"\t\t},\n"
|
||||
"\t},\n",
|
||||
instr_type_to_name(instr),
|
||||
instr->learn.action_id);
|
||||
instr->learn.action_id,
|
||||
instr->learn.mf_first_arg_offset,
|
||||
instr->learn.mf_timeout_id_offset,
|
||||
instr->learn.mf_timeout_id_n_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
instr_rearm_export(struct instruction *instr, FILE *f)
|
||||
{
|
||||
if (instr->type == INSTR_LEARNER_REARM)
|
||||
fprintf(f,
|
||||
"\t{\n"
|
||||
"\t\t.type = %s,\n"
|
||||
"\t},\n",
|
||||
instr_type_to_name(instr));
|
||||
else
|
||||
fprintf(f,
|
||||
"\t{\n"
|
||||
"\t\t.type = %s,\n"
|
||||
"\t\t.learn = {\n"
|
||||
"\t\t\t.mf_timeout_id_offset = %u,\n"
|
||||
"\t\t\t.mf_timeout_id_n_bits = %u,\n"
|
||||
"\t\t},\n"
|
||||
"\t},\n",
|
||||
instr_type_to_name(instr),
|
||||
instr->learn.mf_timeout_id_offset,
|
||||
instr->learn.mf_timeout_id_n_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -11509,6 +11682,8 @@ static instruction_export_t export_table[] = {
|
||||
[INSTR_LEARNER_AF] = instr_table_export,
|
||||
|
||||
[INSTR_LEARNER_LEARN] = instr_learn_export,
|
||||
[INSTR_LEARNER_REARM] = instr_rearm_export,
|
||||
[INSTR_LEARNER_REARM_NEW] = instr_rearm_export,
|
||||
[INSTR_LEARNER_FORGET] = instr_forget_export,
|
||||
|
||||
[INSTR_EXTERN_OBJ] = instr_extern_export,
|
||||
@ -11730,6 +11905,8 @@ instr_type_to_func(struct instruction *instr)
|
||||
case INSTR_LEARNER_AF: return NULL;
|
||||
|
||||
case INSTR_LEARNER_LEARN: return "__instr_learn_exec";
|
||||
case INSTR_LEARNER_REARM: return "__instr_rearm_exec";
|
||||
case INSTR_LEARNER_REARM_NEW: return "__instr_rearm_new_exec";
|
||||
case INSTR_LEARNER_FORGET: return "__instr_forget_exec";
|
||||
|
||||
case INSTR_EXTERN_OBJ: return NULL;
|
||||
|
@ -786,7 +786,9 @@ struct rte_swx_pipeline_learner_params {
|
||||
* @param[in] size
|
||||
* The maximum number of table entries. Must be non-zero.
|
||||
* @param[in] timeout
|
||||
* Table entry timeout in seconds. Must be non-zero.
|
||||
* Array of possible table entry timeouts in seconds. Must be non-NULL.
|
||||
* @param[in] n_timeouts
|
||||
* Number of elements in the *timeout* array.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
@ -800,7 +802,8 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
struct rte_swx_pipeline_learner_params *params,
|
||||
uint32_t size,
|
||||
uint32_t timeout);
|
||||
uint32_t *timeout,
|
||||
uint32_t n_timeouts);
|
||||
|
||||
/**
|
||||
* Pipeline register array configure
|
||||
|
@ -476,9 +476,13 @@ enum instruction_type {
|
||||
INSTR_LEARNER,
|
||||
INSTR_LEARNER_AF,
|
||||
|
||||
/* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
|
||||
/* learn ACTION_NAME [ m.action_first_arg ] m.timeout_id */
|
||||
INSTR_LEARNER_LEARN,
|
||||
|
||||
/* rearm [ m.timeout_id ] */
|
||||
INSTR_LEARNER_REARM,
|
||||
INSTR_LEARNER_REARM_NEW,
|
||||
|
||||
/* forget */
|
||||
INSTR_LEARNER_FORGET,
|
||||
|
||||
@ -611,7 +615,9 @@ struct instr_table {
|
||||
|
||||
struct instr_learn {
|
||||
uint8_t action_id;
|
||||
uint8_t mf_offset;
|
||||
uint8_t mf_first_arg_offset;
|
||||
uint8_t mf_timeout_id_offset;
|
||||
uint8_t mf_timeout_id_n_bits;
|
||||
};
|
||||
|
||||
struct instr_extern_obj {
|
||||
@ -850,7 +856,8 @@ struct learner {
|
||||
int *action_is_for_default_entry;
|
||||
|
||||
uint32_t size;
|
||||
uint32_t timeout;
|
||||
uint32_t timeout[RTE_SWX_TABLE_LEARNER_N_KEY_TIMEOUTS_MAX];
|
||||
uint32_t n_timeouts;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
@ -864,6 +871,7 @@ struct learner_runtime {
|
||||
struct learner_statistics {
|
||||
uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
|
||||
uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
|
||||
uint64_t n_pkts_rearm;
|
||||
uint64_t n_pkts_forget;
|
||||
uint64_t *n_pkts_action;
|
||||
};
|
||||
@ -2208,7 +2216,9 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
|
||||
const struct instruction *ip)
|
||||
{
|
||||
uint64_t action_id = ip->learn.action_id;
|
||||
uint32_t mf_offset = ip->learn.mf_offset;
|
||||
uint32_t mf_first_arg_offset = ip->learn.mf_first_arg_offset;
|
||||
uint32_t timeout_id = METADATA_READ(t, ip->learn.mf_timeout_id_offset,
|
||||
ip->learn.mf_timeout_id_n_bits);
|
||||
uint32_t learner_id = t->learner_id;
|
||||
struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
|
||||
p->n_selectors + learner_id];
|
||||
@ -2221,8 +2231,8 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
|
||||
l->mailbox,
|
||||
t->time,
|
||||
action_id,
|
||||
&t->metadata[mf_offset],
|
||||
0);
|
||||
&t->metadata[mf_first_arg_offset],
|
||||
timeout_id);
|
||||
|
||||
TRACE("[Thread %2u] learner %u learn %s\n",
|
||||
p->thread_id,
|
||||
@ -2232,6 +2242,54 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
|
||||
stats->n_pkts_learn[status] += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* rearm.
|
||||
*/
|
||||
static inline void
|
||||
__instr_rearm_exec(struct rte_swx_pipeline *p,
|
||||
struct thread *t,
|
||||
const struct instruction *ip __rte_unused)
|
||||
{
|
||||
uint32_t learner_id = t->learner_id;
|
||||
struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
|
||||
p->n_selectors + learner_id];
|
||||
struct learner_runtime *l = &t->learners[learner_id];
|
||||
struct learner_statistics *stats = &p->learner_stats[learner_id];
|
||||
|
||||
/* Table. */
|
||||
rte_swx_table_learner_rearm(ts->obj, l->mailbox, t->time);
|
||||
|
||||
TRACE("[Thread %2u] learner %u rearm\n",
|
||||
p->thread_id,
|
||||
learner_id);
|
||||
|
||||
stats->n_pkts_rearm += 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__instr_rearm_new_exec(struct rte_swx_pipeline *p,
|
||||
struct thread *t,
|
||||
const struct instruction *ip)
|
||||
{
|
||||
uint32_t timeout_id = METADATA_READ(t, ip->learn.mf_timeout_id_offset,
|
||||
ip->learn.mf_timeout_id_n_bits);
|
||||
uint32_t learner_id = t->learner_id;
|
||||
struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
|
||||
p->n_selectors + learner_id];
|
||||
struct learner_runtime *l = &t->learners[learner_id];
|
||||
struct learner_statistics *stats = &p->learner_stats[learner_id];
|
||||
|
||||
/* Table. */
|
||||
rte_swx_table_learner_rearm_new(ts->obj, l->mailbox, t->time, timeout_id);
|
||||
|
||||
TRACE("[Thread %2u] learner %u rearm with timeout ID %u\n",
|
||||
p->thread_id,
|
||||
learner_id,
|
||||
timeout_id);
|
||||
|
||||
stats->n_pkts_rearm += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* forget.
|
||||
*/
|
||||
|
@ -29,7 +29,8 @@
|
||||
#define LEARNER_BLOCK 7
|
||||
#define LEARNER_KEY_BLOCK 8
|
||||
#define LEARNER_ACTIONS_BLOCK 9
|
||||
#define APPLY_BLOCK 10
|
||||
#define LEARNER_TIMEOUT_BLOCK 10
|
||||
#define APPLY_BLOCK 11
|
||||
|
||||
/*
|
||||
* extobj.
|
||||
@ -1395,14 +1396,18 @@ selector_block_parse(struct selector_spec *s,
|
||||
* }
|
||||
* default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
|
||||
* size SIZE
|
||||
* timeout TIMEOUT_IN_SECONDS
|
||||
* timeout {
|
||||
* TIMEOUT_IN_SECONDS
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
struct learner_spec {
|
||||
char *name;
|
||||
struct rte_swx_pipeline_learner_params params;
|
||||
uint32_t size;
|
||||
uint32_t timeout;
|
||||
uint32_t *timeout;
|
||||
uint32_t n_timeouts;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1457,7 +1462,10 @@ learner_spec_free(struct learner_spec *s)
|
||||
|
||||
s->size = 0;
|
||||
|
||||
s->timeout = 0;
|
||||
free(s->timeout);
|
||||
s->timeout = NULL;
|
||||
|
||||
s->n_timeouts = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1719,6 +1727,95 @@ learner_default_action_statement_parse(struct learner_spec *s,
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
learner_timeout_statement_parse(uint32_t *block_mask,
|
||||
char **tokens,
|
||||
uint32_t n_tokens,
|
||||
uint32_t n_lines,
|
||||
uint32_t *err_line,
|
||||
const char **err_msg)
|
||||
{
|
||||
/* Check format. */
|
||||
if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Invalid timeout statement.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* block_mask. */
|
||||
*block_mask |= 1 << LEARNER_TIMEOUT_BLOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
learner_timeout_block_parse(struct learner_spec *s,
|
||||
uint32_t *block_mask,
|
||||
char **tokens,
|
||||
uint32_t n_tokens,
|
||||
uint32_t n_lines,
|
||||
uint32_t *err_line,
|
||||
const char **err_msg)
|
||||
{
|
||||
uint32_t *new_timeout = NULL;
|
||||
char *str;
|
||||
uint32_t val;
|
||||
int status = 0;
|
||||
|
||||
/* Handle end of block. */
|
||||
if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
|
||||
*block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check input arguments. */
|
||||
if (n_tokens != 1) {
|
||||
status = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
str = tokens[0];
|
||||
val = strtoul(str, &str, 0);
|
||||
if (str[0]) {
|
||||
status = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t));
|
||||
if (!new_timeout) {
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
s->timeout = new_timeout;
|
||||
s->timeout[s->n_timeouts] = val;
|
||||
s->n_timeouts++;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(new_timeout);
|
||||
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
|
||||
if (err_msg)
|
||||
switch (status) {
|
||||
case -ENOMEM:
|
||||
*err_msg = "Memory allocation failed.";
|
||||
break;
|
||||
|
||||
default:
|
||||
*err_msg = "Invalid timeout value statement.";
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
learner_statement_parse(struct learner_spec *s,
|
||||
uint32_t *block_mask,
|
||||
@ -1780,6 +1877,15 @@ learner_block_parse(struct learner_spec *s,
|
||||
err_line,
|
||||
err_msg);
|
||||
|
||||
if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK))
|
||||
return learner_timeout_block_parse(s,
|
||||
block_mask,
|
||||
tokens,
|
||||
n_tokens,
|
||||
n_lines,
|
||||
err_line,
|
||||
err_msg);
|
||||
|
||||
/* Handle end of block. */
|
||||
if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
|
||||
*block_mask &= ~(1 << LEARNER_BLOCK);
|
||||
@ -1833,28 +1939,13 @@ learner_block_parse(struct learner_spec *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[0], "timeout")) {
|
||||
char *p = tokens[1];
|
||||
|
||||
if (n_tokens != 2) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Invalid timeout statement.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s->timeout = strtoul(p, &p, 0);
|
||||
if (p[0]) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
*err_msg = "Invalid timeout argument.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(tokens[0], "timeout"))
|
||||
return learner_timeout_statement_parse(block_mask,
|
||||
tokens,
|
||||
n_tokens,
|
||||
n_lines,
|
||||
err_line,
|
||||
err_msg);
|
||||
|
||||
/* Anything else. */
|
||||
if (err_line)
|
||||
@ -2365,7 +2456,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
|
||||
learner_spec.name,
|
||||
&learner_spec.params,
|
||||
learner_spec.size,
|
||||
learner_spec.timeout);
|
||||
learner_spec.timeout,
|
||||
learner_spec.n_timeouts);
|
||||
if (status) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
|
@ -140,4 +140,8 @@ EXPERIMENTAL {
|
||||
rte_swx_ctl_learner_info_get;
|
||||
rte_swx_ctl_learner_match_field_info_get;
|
||||
rte_swx_pipeline_learner_config;
|
||||
|
||||
#added in 22.07
|
||||
rte_swx_ctl_pipeline_learner_timeout_get;
|
||||
rte_swx_ctl_pipeline_learner_timeout_set;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user