From patchwork Tue Feb 16 20:46:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 87956 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 55D8CA054D; Tue, 16 Feb 2021 21:46:56 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6266D1607F3; Tue, 16 Feb 2021 21:46:52 +0100 (CET) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mails.dpdk.org (Postfix) with ESMTP id 79C311607C0 for ; Tue, 16 Feb 2021 21:46:50 +0100 (CET) IronPort-SDR: 3/a0onrBQxXpaHN8JaY/2vm7TNLhMs2C8b34LumUKuBiTUU4huy6VbeqYCLC54ICTavFUFbmzz 4cPtnJSGpR3w== X-IronPort-AV: E=McAfee;i="6000,8403,9897"; a="247078499" X-IronPort-AV: E=Sophos;i="5.81,184,1610438400"; d="scan'208";a="247078499" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Feb 2021 12:46:48 -0800 IronPort-SDR: rq2aluMuwmw54sj7iOpKcssz2R0/fgpPwqm7yNriX0zTQDFYoXsf6h4i9CCxi/kLWO8bYCZqOt Hh7J7EJIsyKg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,184,1610438400"; d="scan'208";a="493443107" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by fmsmga001.fm.intel.com with ESMTP; 16 Feb 2021 12:46:47 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Venkata Suresh Kumar P , Churchill Khangar Date: Tue, 16 Feb 2021 20:46:43 +0000 Message-Id: <20210216204646.24196-2-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210216204646.24196-1-cristian.dumitrescu@intel.com> References: <20210216202127.22803-1-cristian.dumitrescu@intel.com> <20210216204646.24196-1-cristian.dumitrescu@intel.com> Subject: [dpdk-dev] [PATCH v3 2/5] pipeline: improve table entry parsing X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 Signed-off-by: Venkata Suresh Kumar P Signed-off-by: Churchill Khangar --- examples/pipeline/cli.c | 21 +++- lib/librte_pipeline/rte_swx_ctl.c | 172 ++++++++++++++++++++---------- lib/librte_pipeline/rte_swx_ctl.h | 7 +- 3 files changed, 141 insertions(+), 59 deletions(-) diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c index e97e12060..30c2dd34d 100644 --- a/examples/pipeline/cli.c +++ b/examples/pipeline/cli.c @@ -881,14 +881,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; @@ -911,14 +916,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; @@ -940,14 +950,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; diff --git a/lib/librte_pipeline/rte_swx_ctl.c b/lib/librte_pipeline/rte_swx_ctl.c index af653d7f4..4a416bc71 100644 --- a/lib/librte_pipeline/rte_swx_ctl.c +++ b/lib/librte_pipeline/rte_swx_ctl.c @@ -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")) - goto error; - - action = action_find(ctl, tokens[2 + table->info.n_match_fields]); - if (!action) + if (!n_tokens) { + blank_or_comment = 1; 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++; } diff --git a/lib/librte_pipeline/rte_swx_ctl.h b/lib/librte_pipeline/rte_swx_ctl.h index 32815b69e..530671db1 100644 --- a/lib/librte_pipeline/rte_swx_ctl.h +++ b/lib/librte_pipeline/rte_swx_ctl.h @@ -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