pipeline: improve table entry parsing

Improve the table entry parsing: better code structure, enable parsing
for the key field masks, allow comments and empty lines in the table
entry files.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Venkata Suresh Kumar P <venkata.suresh.kumar.p@intel.com>
Signed-off-by: Churchill Khangar <churchill.khangar@intel.com>
This commit is contained in:
Cristian Dumitrescu 2021-02-16 20:46:43 +00:00 committed by Thomas Monjalon
parent d526f6e2d0
commit cff9a7178e
3 changed files with 141 additions and 59 deletions

View File

@ -1002,14 +1002,19 @@ cmd_pipeline_table_update(char **tokens,
if (file_add)
for (line_id = 1; ; line_id++) {
struct rte_swx_table_entry *entry;
int is_blank_or_comment;
if (fgets(line, 2048, file_add) == NULL)
break;
entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
table_name,
line);
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
snprintf(out, out_size, MSG_FILE_ERR,
file_name_add, line_id);
goto error;
@ -1032,14 +1037,19 @@ cmd_pipeline_table_update(char **tokens,
if (file_delete)
for (line_id = 1; ; line_id++) {
struct rte_swx_table_entry *entry;
int is_blank_or_comment;
if (fgets(line, 2048, file_delete) == NULL)
break;
entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
table_name,
line);
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
snprintf(out, out_size, MSG_FILE_ERR,
file_name_delete, line_id);
goto error;
@ -1061,14 +1071,19 @@ cmd_pipeline_table_update(char **tokens,
if (file_default)
for (line_id = 1; ; line_id++) {
struct rte_swx_table_entry *entry;
int is_blank_or_comment;
if (fgets(line, 2048, file_default) == NULL)
break;
entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
table_name,
line);
line,
&is_blank_or_comment);
if (!entry) {
if (is_blank_or_comment)
continue;
snprintf(out, out_size, MSG_FILE_ERR,
file_name_default, line_id);
goto error;

View File

@ -1339,19 +1339,32 @@ rte_swx_ctl_pipeline_abort(struct rte_swx_ctl_pipeline *ctl)
table_abort(ctl, i);
}
static int
token_is_comment(const char *token)
{
if ((token[0] == '#') ||
(token[0] == ';') ||
((token[0] == '/') && (token[1] == '/')))
return 1; /* TRUE. */
return 0; /* FALSE. */
}
#define RTE_SWX_CTL_ENTRY_TOKENS_MAX 256
struct rte_swx_table_entry *
rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
const char *table_name,
const char *string)
const char *string,
int *is_blank_or_comment)
{
char *tokens[RTE_SWX_CTL_ENTRY_TOKENS_MAX];
char *token_array[RTE_SWX_CTL_ENTRY_TOKENS_MAX], **tokens;
struct table *table;
struct action *action;
struct rte_swx_table_entry *entry = NULL;
char *s0 = NULL, *s;
uint32_t n_tokens = 0, arg_offset = 0, i;
int blank_or_comment = 0;
/* Check input arguments. */
if (!ctl)
@ -1381,37 +1394,66 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
char *token;
token = strtok_r(s, " \f\n\r\t\v", &s);
if (!token)
if (!token || token_is_comment(token))
break;
if (n_tokens >= RTE_SWX_CTL_ENTRY_TOKENS_MAX)
goto error;
tokens[n_tokens] = token;
token_array[n_tokens] = token;
n_tokens++;
}
if ((n_tokens < 3 + table->info.n_match_fields) ||
strcmp(tokens[0], "match") ||
strcmp(tokens[1 + table->info.n_match_fields], "action"))
if (!n_tokens) {
blank_or_comment = 1;
goto error;
}
action = action_find(ctl, tokens[2 + table->info.n_match_fields]);
if (!action)
goto error;
if (n_tokens != 3 + table->info.n_match_fields +
action->info.n_args * 2)
goto error;
tokens = token_array;
/*
* Match.
*/
if (n_tokens && strcmp(tokens[0], "match"))
goto action;
if (n_tokens < 1 + table->info.n_match_fields)
goto error;
for (i = 0; i < table->info.n_match_fields; i++) {
struct rte_swx_ctl_table_match_field_info *mf = &table->mf[i];
char *mf_val = tokens[1 + i];
uint64_t val;
char *mf_val = tokens[1 + i], *mf_mask = NULL;
uint64_t val, mask = UINT64_MAX;
uint32_t offset = (mf->offset - table->mf[0].offset) / 8;
/*
* Mask.
*/
mf_mask = strchr(mf_val, '/');
if (mf_mask) {
*mf_mask = 0;
mf_mask++;
/* Parse. */
mask = strtoull(mf_mask, &mf_mask, 0);
if (mf_mask[0])
goto error;
/* Endianness conversion. */
if (mf->is_header)
mask = field_hton(mask, mf->n_bits);
}
/* Copy to entry. */
if (entry->key_mask)
memcpy(&entry->key_mask[offset],
(uint8_t *)&mask,
mf->n_bits / 8);
/*
* Value.
*/
/* Parse. */
val = strtoull(mf_val, &mf_val, 0);
if (mf_val[0])
goto error;
@ -1420,17 +1462,32 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
if (mf->is_header)
val = field_hton(val, mf->n_bits);
/* Copy key and key_mask to entry. */
memcpy(&entry->key[(mf->offset - table->mf[0].offset) / 8],
/* Copy to entry. */
memcpy(&entry->key[offset],
(uint8_t *)&val,
mf->n_bits / 8);
/* TBD Set entry->key_mask for wildcard and LPM tables. */
}
tokens += 1 + table->info.n_match_fields;
n_tokens -= 1 + table->info.n_match_fields;
/*
* Action.
*/
action:
if (n_tokens && strcmp(tokens[0], "action"))
goto other;
if (n_tokens < 2)
goto error;
action = action_find(ctl, tokens[1]);
if (!action)
goto error;
if (n_tokens < 2 + action->info.n_args * 2)
goto error;
/* action_id. */
entry->action_id = action - ctl->actions;
@ -1441,8 +1498,8 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
uint64_t val;
int is_nbo = 0;
arg_name = tokens[3 + table->info.n_match_fields + i * 2];
arg_val = tokens[3 + table->info.n_match_fields + i * 2 + 1];
arg_name = tokens[2 + i * 2];
arg_val = tokens[2 + i * 2 + 1];
if (strcmp(arg_name, arg->name) ||
(strlen(arg_val) < 4) ||
@ -1473,15 +1530,50 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
arg_offset += arg->n_bits / 8;
}
tokens += 2 + action->info.n_args * 2;
n_tokens -= 2 + action->info.n_args * 2;
other:
if (n_tokens)
goto error;
free(s0);
return entry;
error:
table_entry_free(entry);
free(s0);
if (is_blank_or_comment)
*is_blank_or_comment = blank_or_comment;
return NULL;
}
static void
table_entry_printf(FILE *f,
struct rte_swx_ctl_pipeline *ctl,
struct table *table,
struct rte_swx_table_entry *entry)
{
struct action *action = &ctl->actions[entry->action_id];
uint32_t i;
fprintf(f, "match ");
for (i = 0; i < table->params.key_size; i++)
fprintf(f, "%02x", entry->key[i]);
if (entry->key_mask) {
fprintf(f, "/");
for (i = 0; i < table->params.key_size; i++)
fprintf(f, "%02x", entry->key_mask[i]);
}
fprintf(f, " action %s ", action->info.name);
for (i = 0; i < action->data_size; i++)
fprintf(f, "%02x", entry->action_data[i]);
fprintf(f, "\n");
}
int
rte_swx_ctl_pipeline_table_fprintf(FILE *f,
struct rte_swx_ctl_pipeline *ctl,
@ -1512,47 +1604,17 @@ rte_swx_ctl_pipeline_table_fprintf(FILE *f,
/* Table entries. */
TAILQ_FOREACH(entry, &table->entries, node) {
struct action *action = &ctl->actions[entry->action_id];
fprintf(f, "match ");
for (i = 0; i < table->params.key_size; i++)
fprintf(f, "%02x", entry->key[i]);
fprintf(f, " action %s ", action->info.name);
for (i = 0; i < action->data_size; i++)
fprintf(f, "%02x", entry->action_data[i]);
fprintf(f, "\n");
table_entry_printf(f, ctl, table, entry);
n_entries++;
}
TAILQ_FOREACH(entry, &table->pending_modify0, node) {
struct action *action = &ctl->actions[entry->action_id];
fprintf(f, "match ");
for (i = 0; i < table->params.key_size; i++)
fprintf(f, "%02x", entry->key[i]);
fprintf(f, " action %s ", action->info.name);
for (i = 0; i < action->data_size; i++)
fprintf(f, "%02x", entry->action_data[i]);
fprintf(f, "\n");
table_entry_printf(f, ctl, table, entry);
n_entries++;
}
TAILQ_FOREACH(entry, &table->pending_delete, node) {
struct action *action = &ctl->actions[entry->action_id];
fprintf(f, "match ");
for (i = 0; i < table->params.key_size; i++)
fprintf(f, "%02x", entry->key[i]);
fprintf(f, " action %s ", action->info.name);
for (i = 0; i < action->data_size; i++)
fprintf(f, "%02x", entry->action_data[i]);
fprintf(f, "\n");
table_entry_printf(f, ctl, table, entry);
n_entries++;
}

View File

@ -521,6 +521,10 @@ rte_swx_ctl_pipeline_abort(struct rte_swx_ctl_pipeline *ctl);
* Table name.
* @param[in] string
* String containing the table entry.
* @param[out] is_blank_or_comment
* On error, this argument provides an indication of whether *string* contains
* an invalid table entry (set to zero) or a blank or comment line that should
* typically be ignored (set to a non-zero value).
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument.
@ -529,7 +533,8 @@ __rte_experimental
struct rte_swx_table_entry *
rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
const char *table_name,
const char *string);
const char *string,
int *is_blank_or_comment);
/**
* Pipeline table print to file