From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by dpdk.org (Postfix) with ESMTP id C2399A84C for ; Fri, 12 Jan 2018 22:02:46 +0100 (CET) Received: by mail-wm0-f68.google.com with SMTP id i11so14179087wmf.4 for ; Fri, 12 Jan 2018 13:02:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=CGYjFABqF9k9WODBrTyTD227XICV+7EHb/tWtgoFrxo=; b=AF7aqQPxHnYHVYSjPrdxSaO6ZueMhR74KgXBKG4TkqZG1103+P2TRJf+iEI/uQ240x IvfvHf51oB5Z1ltxjI6VTxVcC+zvrZOr8UzRwvGZubZq/+WhXyW/aUOo00hzR1FsER9L 1v/B8YWhKhNpa1a8uVfX3ZREYWLp3plD03fo8CjcZCPxdqnigoKVis4L+6WkkIbQSqdU wj2PCsoHD9GY8w3PiNh2nlk4MT02cGZzs3+o+tWWE1xIzJKobT1GEQpOwBHVKoveWo6H axOeWBXjJvMImRQE2RI5Ale4yn1T1oD/x7aOLNpQYbpVRxah+up9uuWto2XwF4M2Dj83 Qr1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=CGYjFABqF9k9WODBrTyTD227XICV+7EHb/tWtgoFrxo=; b=OE8VdrsVkDzOJfxcQa2fknPhAqj2dO6gEFgG8x6KRSyNkJ/eQMNzuYPPOShPV+cS1i ksX4Y0FBh1nVkhGwZnU8aFuiXXZg3xWqsx2ebGgEH0bmuO4paSxI6LvDNItM/dTXh+UZ O7NespkmwMz8whxP705PNRnPB4kvFuMyywrwVgzh0SF+ih+WHLRPFBrDm8uROSCIhNKa YdcpkuJjgxYc7nMa4nGzfjqGgNmI6mS/NlZDijGBCDCF1qnFSsKQ5xTVEVYavXUFXtQx AFX6W+TLZNjZHt0E0SNVoziJMNeddZvKr2eY1vIbrY5JMXI63u2c+LiS/+ev5MANmvHX Ju/Q== X-Gm-Message-State: AKwxytcddIa7pKNdJVkOtX1Ft8CULH0/HXvyGiFDvKdIBO1zUuz7fFTf rT1wChnpKCgR+TfkQ7iJqUM= X-Google-Smtp-Source: ACJfBos4bgSqaXvAG1bou3ON+zSca2/7Iqr5NcivGT+IRqQB5kX6yerCIgzsDJpyJx0K7o53d19pAw== X-Received: by 10.80.165.180 with SMTP id a49mr14296879edc.79.1515790964948; Fri, 12 Jan 2018 13:02:44 -0800 (PST) Received: from nslrack08.ssvl.kth.se ([2001:6b0:32:13:eef4:bbff:fed5:fe0d]) by smtp.gmail.com with ESMTPSA id k11sm5769559eda.22.2018.01.12.13.02.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 12 Jan 2018 13:02:44 -0800 (PST) From: Georgios Katsikas To: olivier.matz@6wind.com Cc: dev@dpdk.org, Georgios Katsikas Date: Fri, 12 Jan 2018 22:01:27 +0100 Message-Id: <1515790887-64502-3-git-send-email-george.dit@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515790887-64502-1-git-send-email-george.dit@gmail.com> References: <1515790887-64502-1-git-send-email-george.dit@gmail.com> Subject: [dpdk-dev] [PATCH 3/3] lib/cmdline: Cross platform fixes for cmdline_flow X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jan 2018 21:02:47 -0000 Signed-off-by: Georgios Katsikas --- app/test-pmd/Makefile | 2 + app/test-pmd/cmdline.c | 4 + app/test-pmd/testpmd.h | 14 - lib/librte_cmdline/Makefile | 3 + lib/librte_cmdline/cmdline_flow.c | 555 ++++++-------------------------- lib/librte_cmdline/cmdline_flow.h | 653 +++++++++++++++++++++++++++++++------- lib/librte_ether/rte_flow.c | 4 +- lib/librte_ether/rte_flow.h | 10 - 8 files changed, 640 insertions(+), 605 deletions(-) diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index ec48773..26de9f3 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -38,6 +38,8 @@ endif ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) +LDLIBS += -lrte_cmdline + ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y) LDLIBS += -lrte_pmd_bond endif diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 5b2e2ef..d1c6428 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -10921,7 +10921,11 @@ cmdline_parse_inst_t cmd_set_flow_director_flex_payload = { }; /* Generic flow interface command. */ +#ifdef RTE_BUILD_SHARED_LIB +cmdline_parse_inst_t cmd_flow; +#else extern cmdline_parse_inst_t cmd_flow; +#endif /* *** Classification Filters Control *** */ /* *** Get symmetric hash enable per port *** */ diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 303a9ec..71da7ef 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -498,20 +498,6 @@ void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value); void port_reg_display(portid_t port_id, uint32_t reg_off); void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value); -int port_flow_validate(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions); -int port_flow_create(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions); -int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule); -int port_flow_flush(portid_t port_id); -int port_flow_query(portid_t port_id, uint32_t rule, - enum rte_flow_action_type action); -void port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group); -int port_flow_isolate(portid_t port_id, int set); void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id); void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id); diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile index cf46b22..475b1f7 100644 --- a/lib/librte_cmdline/Makefile +++ b/lib/librte_cmdline/Makefile @@ -28,6 +28,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c CFLAGS += -D_GNU_SOURCE LDLIBS += -lrte_eal +ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) +LDLIBS += -lrte_ethdev +endif # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h diff --git a/lib/librte_cmdline/cmdline_flow.c b/lib/librte_cmdline/cmdline_flow.c index b43c10f..e4a8230 100644 --- a/lib/librte_cmdline/cmdline_flow.c +++ b/lib/librte_cmdline/cmdline_flow.c @@ -43,21 +43,6 @@ #include "cmdline_flow.h" -int -port_id_is_invalid(portid_t port_id, enum print_warning warning) -{ - if (port_id == (portid_t)RTE_PORT_ALL) - return 0; - - if (rte_eth_dev_is_valid_port(port_id)) - return 0; - - if (warning == ENABLED_WARN) - printf("Invalid port %d\n", port_id); - - return 1; -} - /** Remove and return last entry from argument stack. */ const struct arg * pop_args(struct context *ctx) @@ -134,7 +119,7 @@ strcmp_partial(const char *full, const char *partial, size_t partial_len) * location and whether the result must use network byte ordering. */ int -parse_prefix(struct context *ctx, const struct token *token, +cmd_parse_prefix(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -202,7 +187,7 @@ parse_prefix(struct context *ctx, const struct token *token, /** Default parsing function for token name matching. */ int -parse_default(struct context *ctx, const struct token *token, +cmd_parse_default(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -216,14 +201,14 @@ parse_default(struct context *ctx, const struct token *token, /** Parse flow command, initialize output buffer for subsequent tokens. */ int -parse_init(struct context *ctx, const struct token *token, +cmd_parse_init(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -242,7 +227,7 @@ parse_init(struct context *ctx, const struct token *token, /** Parse tokens for validate/create commands. */ int -parse_vc(struct context *ctx, const struct token *token, +cmd_parse_vc(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -251,7 +236,7 @@ parse_vc(struct context *ctx, const struct token *token, uint32_t data_size; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -345,7 +330,7 @@ parse_vc(struct context *ctx, const struct token *token, /** Parse pattern item parameter type. */ int -parse_vc_spec(struct context *ctx, const struct token *token, +cmd_parse_vc_spec(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -357,7 +342,7 @@ parse_vc_spec(struct context *ctx, const struct token *token, (void)size; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Parse parameter types. */ switch (ctx->curr) { @@ -407,7 +392,7 @@ parse_vc_spec(struct context *ctx, const struct token *token, /** Parse action configuration field. */ int -parse_vc_conf(struct context *ctx, const struct token *token, +cmd_parse_vc_conf(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -416,7 +401,7 @@ parse_vc_conf(struct context *ctx, const struct token *token, (void)size; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -438,7 +423,7 @@ parse_vc_conf(struct context *ctx, const struct token *token, * Valid tokens are queue indices and the "end" token. */ int -parse_vc_action_rss_queue(struct context *ctx, const struct token *token, +cmd_parse_vc_action_rss_queue(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -460,7 +445,7 @@ parse_vc_action_rss_queue(struct context *ctx, const struct token *token, return -1; if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss, queue[i]))) return -1; - ret = parse_int(ctx, token, str, len, NULL, 0); + ret = cmd_parse_int(ctx, token, str, len, NULL, 0); if (ret < 0) { pop_args(ctx); return -1; @@ -479,14 +464,14 @@ parse_vc_action_rss_queue(struct context *ctx, const struct token *token, /** Parse tokens for destroy command. */ int -parse_destroy(struct context *ctx, const struct token *token, +cmd_parse_destroy(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -516,14 +501,14 @@ parse_destroy(struct context *ctx, const struct token *token, /** Parse tokens for flush command. */ int -parse_flush(struct context *ctx, const struct token *token, +cmd_parse_flush(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -543,14 +528,14 @@ parse_flush(struct context *ctx, const struct token *token, /** Parse tokens for query command. */ int -parse_query(struct context *ctx, const struct token *token, +cmd_parse_query(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -570,7 +555,7 @@ parse_query(struct context *ctx, const struct token *token, /** Parse action names. */ int -parse_action(struct context *ctx, const struct token *token, +cmd_parse_action(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -605,14 +590,14 @@ parse_action(struct context *ctx, const struct token *token, /** Parse tokens for list command. */ int -parse_list(struct context *ctx, const struct token *token, +cmd_parse_list(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -642,14 +627,14 @@ parse_list(struct context *ctx, const struct token *token, /** Parse tokens for isolate command. */ int -parse_isolate(struct context *ctx, const struct token *token, +cmd_parse_isolate(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { struct buffer *out = buf; /* Token name must match. */ - if (parse_default(ctx, token, str, len, NULL, 0) < 0) + if (cmd_parse_default(ctx, token, str, len, NULL, 0) < 0) return -1; /* Nothing else to do if there is no buffer. */ if (!out) @@ -674,7 +659,7 @@ parse_isolate(struct context *ctx, const struct token *token, * storage location. */ int -parse_int(struct context *ctx, const struct token *token, +cmd_parse_int(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -750,7 +735,7 @@ parse_int(struct context *ctx, const struct token *token, * its length (in that order). */ int -parse_string(struct context *ctx, const struct token *token, +cmd_parse_string(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -772,12 +757,12 @@ parse_string(struct context *ctx, const struct token *token, goto error; if (!ctx->object) return len; - /* Let parse_int() fill length information first. */ + /* Let cmd_parse_int() fill length information first. */ ret = snprintf(tmp, sizeof(tmp), "%u", len); if (ret < 0) goto error; push_args(ctx, arg_len); - ret = parse_int(ctx, token, tmp, ret, NULL, 0); + ret = cmd_parse_int(ctx, token, tmp, ret, NULL, 0); if (ret < 0) { pop_args(ctx); goto error; @@ -802,7 +787,7 @@ parse_string(struct context *ctx, const struct token *token, * location. */ int -parse_mac_addr(struct context *ctx, const struct token *token, +cmd_parse_mac_addr(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -843,7 +828,7 @@ parse_mac_addr(struct context *ctx, const struct token *token, * location. */ int -parse_ipv4_addr(struct context *ctx, const struct token *token, +cmd_parse_ipv4_addr(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -868,7 +853,7 @@ parse_ipv4_addr(struct context *ctx, const struct token *token, if (ret != 1) { /* Attempt integer parsing. */ push_args(ctx, arg); - return parse_int(ctx, token, str, len, buf, size); + return cmd_parse_int(ctx, token, str, len, buf, size); } if (!ctx->object) return len; @@ -889,7 +874,7 @@ parse_ipv4_addr(struct context *ctx, const struct token *token, * location. */ int -parse_ipv6_addr(struct context *ctx, const struct token *token, +cmd_parse_ipv6_addr(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -942,7 +927,7 @@ static const char *const boolean_name[] = { * location. */ int -parse_boolean(struct context *ctx, const struct token *token, +cmd_parse_boolean(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -960,13 +945,13 @@ parse_boolean(struct context *ctx, const struct token *token, if (boolean_name[i]) str = i & 1 ? "1" : "0"; push_args(ctx, arg); - ret = parse_int(ctx, token, str, strlen(str), buf, size); + ret = cmd_parse_int(ctx, token, str, strlen(str), buf, size); return ret > 0 ? (int)len : ret; } /** Parse port and update context. */ int -parse_port(struct context *ctx, const struct token *token, +cmd_parse_port(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size) { @@ -981,7 +966,7 @@ parse_port(struct context *ctx, const struct token *token, ctx->objmask = NULL; size = sizeof(*out); } - ret = parse_int(ctx, token, str, len, out, size); + ret = cmd_parse_int(ctx, token, str, len, out, size); if (ret >= 0) ctx->port = out->port; if (!buf) @@ -1102,9 +1087,6 @@ comp_vc_action_rss_queue(struct context *ctx, const struct token *token, /** Internal context. */ static struct context cmd_flow_context; -/** Global parser instance (cmdline API). */ -cmdline_parse_inst_t cmd_flow; - /** Initialize context. */ void cmd_flow_context_init(struct context *ctx) @@ -1173,7 +1155,7 @@ cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, if (next->call) tmp = next->call(ctx, next, src, len, result, size); else - tmp = parse_default(ctx, next, src, len, result, size); + tmp = cmd_parse_default(ctx, next, src, len, result, size); if (tmp == -1 || tmp != len) continue; token = next; @@ -1328,6 +1310,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, *hdr = &cmd_flow_token_hdr; } +/* Generic flow management functions. */ + +/** Compute storage space needed by item specification. */ +void +flow_item_spec_size(const struct rte_flow_item *item, + size_t *size, size_t *pad) +{ + if (!item->spec) { + *size = 0; + goto empty; + } + switch (item->type) { + union { + const struct rte_flow_item_raw *raw; + } spec; + + /* Not a fall-through */ + case RTE_FLOW_ITEM_TYPE_RAW: + spec.raw = item->spec; + *size = offsetof(struct rte_flow_item_raw, pattern) + + spec.raw->length * sizeof(*spec.raw->pattern); + break; + default: + *size = flow_item[item->type].size; + break; + } +empty: + *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; +} + +/** Compute storage space needed by action configuration. */ +void +flow_action_conf_size(const struct rte_flow_action *action, + size_t *size, size_t *pad) +{ + if (!action->conf) { + *size = 0; + goto empty; + } + switch (action->type) { + union { + const struct rte_flow_action_rss *rss; + } conf; + + /* Not a fall-through. */ + case RTE_FLOW_ACTION_TYPE_RSS: + conf.rss = action->conf; + *size = offsetof(struct rte_flow_action_rss, queue) + + conf.rss->num * sizeof(*conf.rss->queue); + break; + default: + *size = flow_action[action->type].size; + break; + } +empty: + *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; +} + /** Dispatch parsed buffer to function calls. */ void cmd_flow_parsed(const struct buffer *in) @@ -1374,7 +1414,7 @@ cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) cmd_flow_parsed(arg0); } -/** Global parser instance (cmdline API). */ +/** Global parser instance (properly initialized). */ cmdline_parse_inst_t cmd_flow = { .f = cmd_flow_cb, .data = NULL, /**< Unused. */ @@ -1383,408 +1423,3 @@ cmdline_parse_inst_t cmd_flow = { NULL, }, /**< Tokens are returned by cmd_flow_tok(). */ }; - -/* Generic flow management functions. */ - -/** Generate a port_flow entry from attributes/pattern/actions. */ -static struct port_flow * -port_flow_new(const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions) -{ - const struct rte_flow_item *item; - const struct rte_flow_action *action; - struct port_flow *pf = NULL; - size_t tmp; - size_t pad; - size_t off1 = 0; - size_t off2 = 0; - int err = ENOTSUP; - -store: - item = pattern; - if (pf) - pf->pattern = (void *)&pf->data[off1]; - do { - struct rte_flow_item *dst = NULL; - - if ((unsigned int)item->type >= RTE_DIM(flow_item) || - !flow_item[item->type].name) - goto notsup; - if (pf) - dst = memcpy(pf->data + off1, item, sizeof(*item)); - off1 += sizeof(*item); - flow_item_spec_size(item, &tmp, &pad); - if (item->spec) { - if (pf) - dst->spec = memcpy(pf->data + off2, - item->spec, tmp); - off2 += tmp + pad; - } - if (item->last) { - if (pf) - dst->last = memcpy(pf->data + off2, - item->last, tmp); - off2 += tmp + pad; - } - if (item->mask) { - if (pf) - dst->mask = memcpy(pf->data + off2, - item->mask, tmp); - off2 += tmp + pad; - } - off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); - } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END); - off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); - action = actions; - if (pf) - pf->actions = (void *)&pf->data[off1]; - do { - struct rte_flow_action *dst = NULL; - - if ((unsigned int)action->type >= RTE_DIM(flow_action) || - !flow_action[action->type].name) - goto notsup; - if (pf) - dst = memcpy(pf->data + off1, action, sizeof(*action)); - off1 += sizeof(*action); - flow_action_conf_size(action, &tmp, &pad); - if (action->conf) { - if (pf) - dst->conf = memcpy(pf->data + off2, - action->conf, tmp); - off2 += tmp + pad; - } - off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); - } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END); - if (pf != NULL) - return pf; - off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); - tmp = RTE_ALIGN_CEIL(offsetof(struct port_flow, data), sizeof(double)); - pf = calloc(1, tmp + off1 + off2); - if (pf == NULL) - err = errno; - else { - *pf = (const struct port_flow){ - .size = tmp + off1 + off2, - .attr = *attr, - }; - tmp -= offsetof(struct port_flow, data); - off2 = tmp + off1; - off1 = tmp; - goto store; - } -notsup: - rte_errno = err; - return NULL; -} - -/** Print a message out of a flow error. */ -static int -port_flow_complain(struct rte_flow_error *error) -{ - static const char *const errstrlist[] = { - [RTE_FLOW_ERROR_TYPE_NONE] = "no error", - [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", - [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", - [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", - [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", - [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", - [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", - [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", - [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", - [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", - [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", - [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", - }; - const char *errstr; - char buf[32]; - int err = rte_errno; - - if ((unsigned int)error->type >= RTE_DIM(errstrlist) || - !errstrlist[error->type]) - errstr = "unknown type"; - else - errstr = errstrlist[error->type]; - printf("Caught error type %d (%s): %s%s\n", - error->type, errstr, - error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", - error->cause), buf) : "", - error->message ? error->message : "(no stated reason)"); - return -err; -} - -/** Validate flow rule. */ -int -port_flow_validate(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions) -{ - struct rte_flow_error error; - - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x11, sizeof(error)); - if (rte_flow_validate(port_id, attr, pattern, actions, &error)) - return port_flow_complain(&error); - printf("Flow rule validated\n"); - return 0; -} - -/** Create flow rule. */ -int -port_flow_create(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions) -{ - struct rte_flow *flow; - struct rte_port *port; - struct port_flow *pf; - uint32_t id; - struct rte_flow_error error; - - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x22, sizeof(error)); - flow = rte_flow_create(port_id, attr, pattern, actions, &error); - if (!flow) - return port_flow_complain(&error); - port = &ports[port_id]; - if (port->flow_list) { - if (port->flow_list->id == UINT32_MAX) { - printf("Highest rule ID is already assigned, delete" - " it first"); - rte_flow_destroy(port_id, flow, NULL); - return -ENOMEM; - } - id = port->flow_list->id + 1; - } else - id = 0; - pf = port_flow_new(attr, pattern, actions); - if (!pf) { - int err = rte_errno; - - printf("Cannot allocate flow: %s\n", rte_strerror(err)); - rte_flow_destroy(port_id, flow, NULL); - return -err; - } - pf->next = port->flow_list; - pf->id = id; - pf->flow = flow; - port->flow_list = pf; - printf("Flow rule #%u created\n", pf->id); - return 0; -} - -/** Destroy a number of flow rules. */ -int -port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule) -{ - struct rte_port *port; - struct port_flow **tmp; - uint32_t c = 0; - int ret = 0; - - if (port_id_is_invalid(port_id, ENABLED_WARN) || - port_id == (portid_t)RTE_PORT_ALL) - return -EINVAL; - port = &ports[port_id]; - tmp = &port->flow_list; - while (*tmp) { - uint32_t i; - - for (i = 0; i != n; ++i) { - struct rte_flow_error error; - struct port_flow *pf = *tmp; - - if (rule[i] != pf->id) - continue; - /* - * Poisoning to make sure PMDs update it in case - * of error. - */ - memset(&error, 0x33, sizeof(error)); - if (rte_flow_destroy(port_id, pf->flow, &error)) { - ret = port_flow_complain(&error); - continue; - } - printf("Flow rule #%u destroyed\n", pf->id); - *tmp = pf->next; - free(pf); - break; - } - if (i == n) - tmp = &(*tmp)->next; - ++c; - } - return ret; -} - -/** Remove all flow rules. */ -int -port_flow_flush(portid_t port_id) -{ - struct rte_flow_error error; - struct rte_port *port; - int ret = 0; - - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x44, sizeof(error)); - if (rte_flow_flush(port_id, &error)) { - ret = port_flow_complain(&error); - if (port_id_is_invalid(port_id, DISABLED_WARN) || - port_id == (portid_t)RTE_PORT_ALL) - return ret; - } - port = &ports[port_id]; - while (port->flow_list) { - struct port_flow *pf = port->flow_list->next; - - free(port->flow_list); - port->flow_list = pf; - } - return ret; -} - -/** Query a flow rule. */ -int -port_flow_query(portid_t port_id, uint32_t rule, - enum rte_flow_action_type action) -{ - struct rte_flow_error error; - struct rte_port *port; - struct port_flow *pf; - const char *name; - union { - struct rte_flow_query_count count; - } query; - - if (port_id_is_invalid(port_id, ENABLED_WARN) || - port_id == (portid_t)RTE_PORT_ALL) - return -EINVAL; - port = &ports[port_id]; - for (pf = port->flow_list; pf; pf = pf->next) - if (pf->id == rule) - break; - if (!pf) { - printf("Flow rule #%u not found\n", rule); - return -ENOENT; - } - if ((unsigned int)action >= RTE_DIM(flow_action) || - !flow_action[action].name) - name = "unknown"; - else - name = flow_action[action].name; - switch (action) { - case RTE_FLOW_ACTION_TYPE_COUNT: - break; - default: - printf("Cannot query action type %d (%s)\n", action, name); - return -ENOTSUP; - } - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x55, sizeof(error)); - memset(&query, 0, sizeof(query)); - if (rte_flow_query(port_id, pf->flow, action, &query, &error)) - return port_flow_complain(&error); - switch (action) { - case RTE_FLOW_ACTION_TYPE_COUNT: - printf("%s:\n" - " hits_set: %u\n" - " bytes_set: %u\n" - " hits: %" PRIu64 "\n" - " bytes: %" PRIu64 "\n", - name, - query.count.hits_set, - query.count.bytes_set, - query.count.hits, - query.count.bytes); - break; - default: - printf("Cannot display result for action type %d (%s)\n", - action, name); - break; - } - return 0; -} - -/** List flow rules. */ -void -port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n]) -{ - struct rte_port *port; - struct port_flow *pf; - struct port_flow *list = NULL; - uint32_t i; - - if (port_id_is_invalid(port_id, ENABLED_WARN) || - port_id == (portid_t)RTE_PORT_ALL) - return; - port = &ports[port_id]; - if (!port->flow_list) - return; - /* Sort flows by group, priority and ID. */ - for (pf = port->flow_list; pf != NULL; pf = pf->next) { - struct port_flow **tmp; - - if (n) { - /* Filter out unwanted groups. */ - for (i = 0; i != n; ++i) - if (pf->attr.group == group[i]) - break; - if (i == n) - continue; - } - tmp = &list; - while (*tmp && - (pf->attr.group > (*tmp)->attr.group || - (pf->attr.group == (*tmp)->attr.group && - pf->attr.priority > (*tmp)->attr.priority) || - (pf->attr.group == (*tmp)->attr.group && - pf->attr.priority == (*tmp)->attr.priority && - pf->id > (*tmp)->id))) - tmp = &(*tmp)->tmp; - pf->tmp = *tmp; - *tmp = pf; - } - printf("ID\tGroup\tPrio\tAttr\tRule\n"); - for (pf = list; pf != NULL; pf = pf->tmp) { - const struct rte_flow_item *item = pf->pattern; - const struct rte_flow_action *action = pf->actions; - - printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c\t", - pf->id, - pf->attr.group, - pf->attr.priority, - pf->attr.ingress ? 'i' : '-', - pf->attr.egress ? 'e' : '-'); - while (item->type != RTE_FLOW_ITEM_TYPE_END) { - if (item->type != RTE_FLOW_ITEM_TYPE_VOID) - printf("%s ", flow_item[item->type].name); - ++item; - } - printf("=>"); - while (action->type != RTE_FLOW_ACTION_TYPE_END) { - if (action->type != RTE_FLOW_ACTION_TYPE_VOID) - printf(" %s", flow_action[action->type].name); - ++action; - } - printf("\n"); - } -} - -/** Restrict ingress traffic to the defined flow rules. */ -int -port_flow_isolate(portid_t port_id, int set) -{ - struct rte_flow_error error; - - /* Poisoning to make sure PMDs update it in case of error. */ - memset(&error, 0x66, sizeof(error)); - if (rte_flow_isolate(port_id, set, &error)) - return port_flow_complain(&error); - printf("Ingress traffic on port %u is %s to the defined flow rules\n", - port_id, - set ? "now restricted" : "not restricted anymore"); - return 0; -} diff --git a/lib/librte_cmdline/cmdline_flow.h b/lib/librte_cmdline/cmdline_flow.h index 7066254..9cb8045 100644 --- a/lib/librte_cmdline/cmdline_flow.h +++ b/lib/librte_cmdline/cmdline_flow.h @@ -814,8 +814,21 @@ static const struct { }; /** Helper functions for parsing. */ -int port_id_is_invalid(portid_t port_id, - enum print_warning warning); +inline int +port_id_is_invalid(portid_t port_id, enum print_warning warning) +{ + if (port_id == (portid_t)RTE_PORT_ALL) + return 0; + + if (rte_eth_dev_is_valid_port(port_id)) + return 0; + + if (warning == ENABLED_WARN) + printf("Invalid port %d\n", port_id); + + return 1; +} + const struct arg *pop_args(struct context *ctx); int push_args(struct context *ctx, const struct arg *arg); @@ -823,68 +836,75 @@ size_t arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg); int strcmp_partial(const char *full, const char *partial, size_t partial_len); +/** Compute storage space needed by item specification. */ +void flow_item_spec_size(const struct rte_flow_item *item, + size_t *size, size_t *pad); + +/** Compute storage space needed by action configuration. */ +void flow_action_conf_size(const struct rte_flow_action *action, + size_t *size, size_t *pad); /** Parsing functions. */ -int parse_prefix(struct context *, const struct token *, +int cmd_parse_prefix(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_default(struct context *ctx, +int cmd_parse_default(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size); -int parse_init(struct context *, const struct token *, +int cmd_parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_vc(struct context *, const struct token *, +int cmd_parse_vc(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_vc_spec(struct context *, const struct token *, +int cmd_parse_vc_spec(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_vc_conf(struct context *, const struct token *, +int cmd_parse_vc_conf(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_vc_action_rss_queue(struct context *, +int cmd_parse_vc_action_rss_queue(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_destroy(struct context *, const struct token *, +int cmd_parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_flush(struct context *, const struct token *, +int cmd_parse_flush(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_query(struct context *, const struct token *, +int cmd_parse_query(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_action(struct context *, const struct token *, +int cmd_parse_action(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_list(struct context *, const struct token *, +int cmd_parse_list(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_isolate(struct context *, const struct token *, +int cmd_parse_isolate(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_int(struct context *, const struct token *, +int cmd_parse_int(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_string(struct context *, const struct token *, +int cmd_parse_string(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_mac_addr(struct context *, const struct token *, +int cmd_parse_mac_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_ipv4_addr(struct context *, const struct token *, +int cmd_parse_ipv4_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_ipv6_addr(struct context *, const struct token *, +int cmd_parse_ipv6_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_boolean(struct context *, const struct token *, +int cmd_parse_boolean(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); -int parse_port(struct context *, const struct token *, +int cmd_parse_port(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -920,23 +940,418 @@ void cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, void cmd_flow_parsed(const struct buffer *in); void cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2); -/** Generic flow management functions. */ -int port_flow_validate(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions); -int port_flow_create(portid_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions); -int port_flow_destroy(portid_t port_id, uint32_t n, - const uint32_t *rule); -int port_flow_flush(portid_t port_id); -int port_flow_query(portid_t port_id, uint32_t rule, - enum rte_flow_action_type action); -void port_flow_list(portid_t port_id, uint32_t n, - const uint32_t *group); -int port_flow_isolate(portid_t port_id, int set); +/** + * Generic flow management functions. + * + * Allow the creation, validation, insertion, query, + * list, and deletion of a NIC's flows. + */ + +/** Generate a port_flow entry from attributes/pattern/actions. */ +static inline struct port_flow * +port_flow_new(const struct rte_flow_attr *attr, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions) +{ + const struct rte_flow_item *item; + const struct rte_flow_action *action; + struct port_flow *pf = NULL; + size_t tmp; + size_t pad; + size_t off1 = 0; + size_t off2 = 0; + int err = ENOTSUP; + +store: + item = pattern; + if (pf) + pf->pattern = (void *)&pf->data[off1]; + do { + struct rte_flow_item *dst = NULL; + + if ((unsigned int)item->type >= RTE_DIM(flow_item) || + !flow_item[item->type].name) + goto notsup; + if (pf) + dst = memcpy(pf->data + off1, item, sizeof(*item)); + off1 += sizeof(*item); + flow_item_spec_size(item, &tmp, &pad); + if (item->spec) { + if (pf) + dst->spec = memcpy(pf->data + off2, + item->spec, tmp); + off2 += tmp + pad; + } + if (item->last) { + if (pf) + dst->last = memcpy(pf->data + off2, + item->last, tmp); + off2 += tmp + pad; + } + if (item->mask) { + if (pf) + dst->mask = memcpy(pf->data + off2, + item->mask, tmp); + off2 += tmp + pad; + } + off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); + } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END); + off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); + action = actions; + if (pf) + pf->actions = (void *)&pf->data[off1]; + do { + struct rte_flow_action *dst = NULL; + + if ((unsigned int)action->type >= RTE_DIM(flow_action) || + !flow_action[action->type].name) + goto notsup; + if (pf) + dst = memcpy(pf->data + off1, action, sizeof(*action)); + off1 += sizeof(*action); + flow_action_conf_size(action, &tmp, &pad); + if (action->conf) { + if (pf) + dst->conf = memcpy(pf->data + off2, + action->conf, tmp); + off2 += tmp + pad; + } + off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); + } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END); + if (pf != NULL) + return pf; + off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); + tmp = RTE_ALIGN_CEIL(offsetof(struct port_flow, data), sizeof(double)); + pf = calloc(1, tmp + off1 + off2); + if (pf == NULL) + err = errno; + else { + *pf = (const struct port_flow){ + .size = tmp + off1 + off2, + .attr = *attr, + }; + tmp -= offsetof(struct port_flow, data); + off2 = tmp + off1; + off1 = tmp; + goto store; + } +notsup: + rte_errno = err; + return NULL; +} + +/** Print a message out of a flow error. */ +inline int +port_flow_complain(struct rte_flow_error *error) +{ + static const char *const errstrlist[] = { + [RTE_FLOW_ERROR_TYPE_NONE] = "no error", + [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", + [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", + [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", + [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", + [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", + [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", + [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", + [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", + [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", + [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", + [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", + }; + const char *errstr; + char buf[32]; + int err = rte_errno; + + if ((unsigned int)error->type >= RTE_DIM(errstrlist) || + !errstrlist[error->type]) + errstr = "unknown type"; + else + errstr = errstrlist[error->type]; + printf("Caught error type %d (%s): %s%s\n", + error->type, errstr, + error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", + error->cause), buf) : "", + error->message ? error->message : "(no stated reason)"); + return -err; +} + +/** Validate flow rule. */ +inline int +port_flow_validate(portid_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions) +{ + struct rte_flow_error error; + + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x11, sizeof(error)); + if (rte_flow_validate(port_id, attr, pattern, actions, &error)) + return port_flow_complain(&error); + printf("Flow rule validated\n"); + return 0; +} + +/** Create flow rule. */ +static inline int +port_flow_create(portid_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions) +{ + struct rte_flow *flow; + struct rte_port *port; + struct port_flow *pf; + uint32_t id; + struct rte_flow_error error; + + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + flow = rte_flow_create(port_id, attr, pattern, actions, &error); + if (!flow) + return port_flow_complain(&error); + port = &ports[port_id]; + if (port->flow_list) { + if (port->flow_list->id == UINT32_MAX) { + printf("Highest rule ID is already assigned, delete" + " it first"); + rte_flow_destroy(port_id, flow, NULL); + return -ENOMEM; + } + id = port->flow_list->id + 1; + } else + id = 0; + pf = port_flow_new(attr, pattern, actions); + if (!pf) { + int err = rte_errno; + + printf("Cannot allocate flow: %s\n", rte_strerror(err)); + rte_flow_destroy(port_id, flow, NULL); + return -err; + } + pf->next = port->flow_list; + pf->id = id; + pf->flow = flow; + port->flow_list = pf; + printf("Flow rule #%u created\n", pf->id); + return 0; +} + +/** Destroy a number of flow rules. */ +inline int +port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule) +{ + struct rte_port *port; + struct port_flow **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->flow_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_flow *pf = *tmp; + + if (rule[i] != pf->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + if (rte_flow_destroy(port_id, pf->flow, &error)) { + ret = port_flow_complain(&error); + continue; + } + printf("Flow rule #%u destroyed\n", pf->id); + *tmp = pf->next; + free(pf); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + +/** Remove all flow rules. */ +inline int +port_flow_flush(portid_t port_id) +{ + struct rte_flow_error error; + struct rte_port *port; + int ret = 0; + + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x44, sizeof(error)); + if (rte_flow_flush(port_id, &error)) { + ret = port_flow_complain(&error); + if (port_id_is_invalid(port_id, DISABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return ret; + } + port = &ports[port_id]; + while (port->flow_list) { + struct port_flow *pf = port->flow_list->next; + + free(port->flow_list); + port->flow_list = pf; + } + return ret; +} + +/** Query a flow rule. */ +static inline int +port_flow_query(portid_t port_id, uint32_t rule, + enum rte_flow_action_type action) +{ + struct rte_flow_error error; + struct rte_port *port; + struct port_flow *pf; + const char *name; + union { + struct rte_flow_query_count count; + } query; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + for (pf = port->flow_list; pf; pf = pf->next) + if (pf->id == rule) + break; + if (!pf) { + printf("Flow rule #%u not found\n", rule); + return -ENOENT; + } + if ((unsigned int)action >= RTE_DIM(flow_action) || + !flow_action[action].name) + name = "unknown"; + else + name = flow_action[action].name; + switch (action) { + case RTE_FLOW_ACTION_TYPE_COUNT: + break; + default: + printf("Cannot query action type %d (%s)\n", action, name); + return -ENOTSUP; + } + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x55, sizeof(error)); + memset(&query, 0, sizeof(query)); + if (rte_flow_query(port_id, pf->flow, action, &query, &error)) + return port_flow_complain(&error); + switch (action) { + case RTE_FLOW_ACTION_TYPE_COUNT: + printf("%s:\n" + " hits_set: %u\n" + " bytes_set: %u\n" + " hits: %" PRIu64 "\n" + " bytes: %" PRIu64 "\n", + name, + query.count.hits_set, + query.count.bytes_set, + query.count.hits, + query.count.bytes); + break; + default: + printf("Cannot display result for action type %d (%s)\n", + action, name); + break; + } + return 0; +} + +/** List flow rules. */ +static inline void +port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n]) +{ + struct rte_port *port; + struct port_flow *pf; + struct port_flow *list = NULL; + uint32_t i; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return; + port = &ports[port_id]; + if (!port->flow_list) + return; + /* Sort flows by group, priority and ID. */ + for (pf = port->flow_list; pf != NULL; pf = pf->next) { + struct port_flow **tmp; + + if (n) { + /* Filter out unwanted groups. */ + for (i = 0; i != n; ++i) + if (pf->attr.group == group[i]) + break; + if (i == n) + continue; + } + tmp = &list; + while (*tmp && + (pf->attr.group > (*tmp)->attr.group || + (pf->attr.group == (*tmp)->attr.group && + pf->attr.priority > (*tmp)->attr.priority) || + (pf->attr.group == (*tmp)->attr.group && + pf->attr.priority == (*tmp)->attr.priority && + pf->id > (*tmp)->id))) + tmp = &(*tmp)->tmp; + pf->tmp = *tmp; + *tmp = pf; + } + printf("ID\tGroup\tPrio\tAttr\tRule\n"); + for (pf = list; pf != NULL; pf = pf->tmp) { + const struct rte_flow_item *item = pf->pattern; + const struct rte_flow_action *action = pf->actions; + + printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c\t", + pf->id, + pf->attr.group, + pf->attr.priority, + pf->attr.ingress ? 'i' : '-', + pf->attr.egress ? 'e' : '-'); + while (item->type != RTE_FLOW_ITEM_TYPE_END) { + if (item->type != RTE_FLOW_ITEM_TYPE_VOID) + printf("%s ", flow_item[item->type].name); + ++item; + } + printf("=>"); + while (action->type != RTE_FLOW_ACTION_TYPE_END) { + if (action->type != RTE_FLOW_ACTION_TYPE_VOID) + printf(" %s", flow_action[action->type].name); + ++action; + } + printf("\n"); + } +} + +/** Restrict ingress traffic to the defined flow rules. */ +inline int +port_flow_isolate(portid_t port_id, int set) +{ + struct rte_flow_error error; + + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x66, sizeof(error)); + if (rte_flow_isolate(port_id, set, &error)) + return port_flow_complain(&error); + printf("Ingress traffic on port %u is %s to the defined flow rules\n", + port_id, + set ? "now restricted" : "not restricted anymore"); + return 0; +} + +/** Global parser instance (cmdline API). */ +extern cmdline_parse_inst_t cmd_flow; /** Token definitions. */ static const struct token token_list[] = { @@ -956,84 +1371,84 @@ static const struct token token_list[] = { .name = "{int}", .type = "INTEGER", .help = "integer value", - .call = parse_int, + .call = cmd_parse_int, .comp = comp_none, }, [UNSIGNED] = { .name = "{unsigned}", .type = "UNSIGNED", .help = "unsigned integer value", - .call = parse_int, + .call = cmd_parse_int, .comp = comp_none, }, [PREFIX] = { .name = "{prefix}", .type = "PREFIX", .help = "prefix length for bit-mask", - .call = parse_prefix, + .call = cmd_parse_prefix, .comp = comp_none, }, [BOOLEAN] = { .name = "{boolean}", .type = "BOOLEAN", .help = "any boolean value", - .call = parse_boolean, + .call = cmd_parse_boolean, .comp = comp_boolean, }, [STRING] = { .name = "{string}", .type = "STRING", .help = "fixed string", - .call = parse_string, + .call = cmd_parse_string, .comp = comp_none, }, [MAC_ADDR] = { .name = "{MAC address}", .type = "MAC-48", .help = "standard MAC address notation", - .call = parse_mac_addr, + .call = cmd_parse_mac_addr, .comp = comp_none, }, [IPV4_ADDR] = { .name = "{IPv4 address}", .type = "IPV4 ADDRESS", .help = "standard IPv4 address notation", - .call = parse_ipv4_addr, + .call = cmd_parse_ipv4_addr, .comp = comp_none, }, [IPV6_ADDR] = { .name = "{IPv6 address}", .type = "IPV6 ADDRESS", .help = "standard IPv6 address notation", - .call = parse_ipv6_addr, + .call = cmd_parse_ipv6_addr, .comp = comp_none, }, [RULE_ID] = { .name = "{rule id}", .type = "RULE ID", .help = "rule identifier", - .call = parse_int, + .call = cmd_parse_int, .comp = comp_rule_id, }, [PORT_ID] = { .name = "{port_id}", .type = "PORT ID", .help = "port identifier", - .call = parse_port, + .call = cmd_parse_port, .comp = comp_port, }, [GROUP_ID] = { .name = "{group_id}", .type = "GROUP ID", .help = "group identifier", - .call = parse_int, + .call = cmd_parse_int, .comp = comp_none, }, [PRIORITY_LEVEL] = { .name = "{level}", .type = "PRIORITY", .help = "priority level", - .call = parse_int, + .call = cmd_parse_int, .comp = comp_none, }, /* Top-level command. */ @@ -1049,7 +1464,7 @@ static const struct token token_list[] = { LIST, QUERY, ISOLATE)), - .call = parse_init, + .call = cmd_parse_init, }, /* Sub-level commands. */ [VALIDATE] = { @@ -1057,28 +1472,28 @@ static const struct token token_list[] = { .help = "check whether a flow rule can be created", .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, port)), - .call = parse_vc, + .call = cmd_parse_vc, }, [CREATE] = { .name = "create", .help = "create a flow rule", .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, port)), - .call = parse_vc, + .call = cmd_parse_vc, }, [DESTROY] = { .name = "destroy", .help = "destroy specific flow rules", .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, port)), - .call = parse_destroy, + .call = cmd_parse_destroy, }, [FLUSH] = { .name = "flush", .help = "destroy all flow rules", .next = NEXT(NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, port)), - .call = parse_flush, + .call = cmd_parse_flush, }, [QUERY] = { .name = "query", @@ -1089,14 +1504,14 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action), ARGS_ENTRY(struct buffer, args.query.rule), ARGS_ENTRY(struct buffer, port)), - .call = parse_query, + .call = cmd_parse_query, }, [LIST] = { .name = "list", .help = "list existing flow rules", .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, port)), - .call = parse_list, + .call = cmd_parse_list, }, [ISOLATE] = { .name = "isolate", @@ -1105,7 +1520,7 @@ static const struct token token_list[] = { NEXT_ENTRY(PORT_ID)), .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set), ARGS_ENTRY(struct buffer, port)), - .call = parse_isolate, + .call = cmd_parse_isolate, }, /* Destroy arguments. */ [DESTROY_RULE] = { @@ -1113,14 +1528,14 @@ static const struct token token_list[] = { .help = "specify a rule identifier", .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)), .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), - .call = parse_destroy, + .call = cmd_parse_destroy, }, /* Query arguments. */ [QUERY_ACTION] = { .name = "{action}", .type = "ACTION", .help = "action to query, must be part of the rule", - .call = parse_action, + .call = cmd_parse_action, .comp = comp_action, }, /* List arguments. */ @@ -1129,7 +1544,7 @@ static const struct token token_list[] = { .help = "specify a group", .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)), .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), - .call = parse_list, + .call = cmd_parse_list, }, /* Validate/create attributes. */ [GROUP] = { @@ -1137,58 +1552,58 @@ static const struct token token_list[] = { .help = "specify a group", .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)), .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)), - .call = parse_vc, + .call = cmd_parse_vc, }, [PRIORITY] = { .name = "priority", .help = "specify a priority level", .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)), .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)), - .call = parse_vc, + .call = cmd_parse_vc, }, [INGRESS] = { .name = "ingress", .help = "affect rule to ingress", .next = NEXT(next_vc_attr), - .call = parse_vc, + .call = cmd_parse_vc, }, [EGRESS] = { .name = "egress", .help = "affect rule to egress", .next = NEXT(next_vc_attr), - .call = parse_vc, + .call = cmd_parse_vc, }, /* Validate/create pattern. */ [PATTERN] = { .name = "pattern", .help = "submit a list of pattern items", .next = NEXT(next_item), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_PARAM_IS] = { .name = "is", .help = "match value perfectly (with full bit-mask)", - .call = parse_vc_spec, + .call = cmd_parse_vc_spec, }, [ITEM_PARAM_SPEC] = { .name = "spec", .help = "match value according to configured bit-mask", - .call = parse_vc_spec, + .call = cmd_parse_vc_spec, }, [ITEM_PARAM_LAST] = { .name = "last", .help = "specify upper bound to establish a range", - .call = parse_vc_spec, + .call = cmd_parse_vc_spec, }, [ITEM_PARAM_MASK] = { .name = "mask", .help = "specify bit-mask with relevant bits set to one", - .call = parse_vc_spec, + .call = cmd_parse_vc_spec, }, [ITEM_PARAM_PREFIX] = { .name = "prefix", .help = "generate bit-mask from a prefix length", - .call = parse_vc_spec, + .call = cmd_parse_vc_spec, }, [ITEM_NEXT] = { .name = "/", @@ -1200,28 +1615,28 @@ static const struct token token_list[] = { .help = "end list of pattern items", .priv = PRIV_ITEM(END, 0), .next = NEXT(NEXT_ENTRY(ACTIONS)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_VOID] = { .name = "void", .help = "no-op pattern item", .priv = PRIV_ITEM(VOID, 0), .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_INVERT] = { .name = "invert", .help = "perform actions when pattern does not match", .priv = PRIV_ITEM(INVERT, 0), .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_ANY] = { .name = "any", .help = "match any protocol for the current layer", .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), .next = NEXT(item_any), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_ANY_NUM] = { .name = "num", @@ -1234,14 +1649,14 @@ static const struct token token_list[] = { .help = "match packets addressed to the physical function", .priv = PRIV_ITEM(PF, 0), .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_VF] = { .name = "vf", .help = "match packets addressed to a virtual function ID", .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)), .next = NEXT(item_vf), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_VF_ID] = { .name = "id", @@ -1254,7 +1669,7 @@ static const struct token token_list[] = { .help = "device-specific physical port index to use", .priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)), .next = NEXT(item_port), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_PORT_INDEX] = { .name = "index", @@ -1267,7 +1682,7 @@ static const struct token token_list[] = { .help = "match an arbitrary byte string", .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), .next = NEXT(item_raw), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_RAW_RELATIVE] = { .name = "relative", @@ -1313,7 +1728,7 @@ static const struct token token_list[] = { .help = "match Ethernet header", .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), .next = NEXT(item_eth), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_ETH_DST] = { .name = "dst", @@ -1338,7 +1753,7 @@ static const struct token token_list[] = { .help = "match 802.1Q/ad VLAN tag", .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), .next = NEXT(item_vlan), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_VLAN_TPID] = { .name = "tpid", @@ -1378,7 +1793,7 @@ static const struct token token_list[] = { .help = "match IPv4 header", .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), .next = NEXT(item_ipv4), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_IPV4_TOS] = { .name = "tos", @@ -1420,7 +1835,7 @@ static const struct token token_list[] = { .help = "match IPv6 header", .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), .next = NEXT(item_ipv6), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_IPV6_TC] = { .name = "tc", @@ -1471,7 +1886,7 @@ static const struct token token_list[] = { .help = "match ICMP header", .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), .next = NEXT(item_icmp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_ICMP_TYPE] = { .name = "type", @@ -1492,7 +1907,7 @@ static const struct token token_list[] = { .help = "match UDP header", .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), .next = NEXT(item_udp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_UDP_SRC] = { .name = "src", @@ -1513,7 +1928,7 @@ static const struct token token_list[] = { .help = "match TCP header", .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), .next = NEXT(item_tcp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_TCP_SRC] = { .name = "src", @@ -1541,7 +1956,7 @@ static const struct token token_list[] = { .help = "match SCTP header", .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), .next = NEXT(item_sctp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_SCTP_SRC] = { .name = "src", @@ -1576,7 +1991,7 @@ static const struct token token_list[] = { .help = "match VXLAN header", .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), .next = NEXT(item_vxlan), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_VXLAN_VNI] = { .name = "vni", @@ -1589,7 +2004,7 @@ static const struct token token_list[] = { .help = "match E-Tag header", .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)), .next = NEXT(item_e_tag), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_E_TAG_GRP_ECID_B] = { .name = "grp_ecid_b", @@ -1604,7 +2019,7 @@ static const struct token token_list[] = { .help = "match NVGRE header", .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)), .next = NEXT(item_nvgre), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_NVGRE_TNI] = { .name = "tni", @@ -1617,7 +2032,7 @@ static const struct token token_list[] = { .help = "match MPLS header", .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), .next = NEXT(item_mpls), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_MPLS_LABEL] = { .name = "label", @@ -1632,7 +2047,7 @@ static const struct token token_list[] = { .help = "match GRE header", .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)), .next = NEXT(item_gre), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_GRE_PROTO] = { .name = "protocol", @@ -1647,7 +2062,7 @@ static const struct token token_list[] = { .priv = PRIV_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)), .next = NEXT(item_fuzzy), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_FUZZY_THRESH] = { .name = "thresh", @@ -1661,7 +2076,7 @@ static const struct token token_list[] = { .help = "match GTP header", .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)), .next = NEXT(item_gtp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_GTP_TEID] = { .name = "teid", @@ -1674,14 +2089,14 @@ static const struct token token_list[] = { .help = "match GTP header", .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)), .next = NEXT(item_gtp), - .call = parse_vc, + .call = cmd_parse_vc, }, [ITEM_GTPU] = { .name = "gtpu", .help = "match GTP header", .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)), .next = NEXT(item_gtp), - .call = parse_vc, + .call = cmd_parse_vc, }, /* Validate/create actions. */ @@ -1689,7 +2104,7 @@ static const struct token token_list[] = { .name = "actions", .help = "submit a list of associated actions", .next = NEXT(next_action), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_NEXT] = { .name = "/", @@ -1700,42 +2115,42 @@ static const struct token token_list[] = { .name = "end", .help = "end list of actions", .priv = PRIV_ACTION(END, 0), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_VOID] = { .name = "void", .help = "no-op action", .priv = PRIV_ACTION(VOID, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_PASSTHRU] = { .name = "passthru", .help = "let subsequent rule process matched packets", .priv = PRIV_ACTION(PASSTHRU, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_MARK] = { .name = "mark", .help = "attach 32 bit value to packets", .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), .next = NEXT(action_mark), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_MARK_ID] = { .name = "id", .help = "32 bit value to return with packets", .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)), .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_FLAG] = { .name = "flag", .help = "flag packets", .priv = PRIV_ACTION(FLAG, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_QUEUE] = { .name = "queue", @@ -1743,60 +2158,60 @@ static const struct token token_list[] = { .priv = PRIV_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)), .next = NEXT(action_queue), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_QUEUE_INDEX] = { .name = "index", .help = "queue index to use", .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)), .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_DROP] = { .name = "drop", .help = "drop packets (note: passthru has priority)", .priv = PRIV_ACTION(DROP, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_COUNT] = { .name = "count", .help = "enable counters for this rule", .priv = PRIV_ACTION(COUNT, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_DUP] = { .name = "dup", .help = "duplicate packets to a given queue index", .priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)), .next = NEXT(action_dup), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_DUP_INDEX] = { .name = "index", .help = "queue index to duplicate packets to", .next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)), .args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_RSS] = { .name = "rss", .help = "spread packets among several queues", .priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE), .next = NEXT(action_rss), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_RSS_QUEUES] = { .name = "queues", .help = "queue indices to use", .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_RSS_QUEUE] = { .name = "{queue}", .help = "queue index", - .call = parse_vc_action_rss_queue, + .call = cmd_parse_vc_action_rss_queue, .comp = comp_vc_action_rss_queue, }, [ACTION_PF] = { @@ -1804,14 +2219,14 @@ static const struct token token_list[] = { .help = "redirect packets to physical device function", .priv = PRIV_ACTION(PF, 0), .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_VF] = { .name = "vf", .help = "redirect packets to virtual device function", .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), .next = NEXT(action_vf), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_VF_ORIGINAL] = { .name = "original", @@ -1819,14 +2234,14 @@ static const struct token token_list[] = { .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)), .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, original, 1)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_VF_ID] = { .name = "id", .help = "VF ID to redirect packets to", .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)), .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, [ACTION_METER] = { .name = "meter", @@ -1834,14 +2249,14 @@ static const struct token token_list[] = { .priv = PRIV_ACTION(METER, sizeof(struct rte_flow_action_meter)), .next = NEXT(action_meter), - .call = parse_vc, + .call = cmd_parse_vc, }, [ACTION_METER_ID] = { .name = "mtr_id", .help = "meter id to use", .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)), .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)), - .call = parse_vc_conf, + .call = cmd_parse_vc_conf, }, }; diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c index 3302208..e437d03 100644 --- a/lib/librte_ether/rte_flow.c +++ b/lib/librte_ether/rte_flow.c @@ -249,7 +249,7 @@ rte_flow_error_set(struct rte_flow_error *error, } /** Compute storage space needed by item specification. */ -void +static void flow_item_spec_size(const struct rte_flow_item *item, size_t *size, size_t *pad) { @@ -277,7 +277,7 @@ flow_item_spec_size(const struct rte_flow_item *item, } /** Compute storage space needed by action configuration. */ -void +static void flow_action_conf_size(const struct rte_flow_action *action, size_t *size, size_t *pad) { diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h index c2184b6..4178203 100644 --- a/lib/librte_ether/rte_flow.h +++ b/lib/librte_ether/rte_flow.h @@ -1180,16 +1180,6 @@ struct rte_flow_action { */ struct rte_flow; -/** Compute storage space needed by item specification. */ -void -flow_item_spec_size(const struct rte_flow_item *item, - size_t *size, size_t *pad); - -/** Compute storage space needed by action configuration. */ -void -flow_action_conf_size(const struct rte_flow_action *action, - size_t *size, size_t *pad); - /** * Verbose error types. * -- 2.7.4