[8/8] app/testpmd: add testpmd command for sample action
Checks
Commit Message
Add a new testpmd command 'set sample_actions' that supports the multiple
sample actions list configuration by using the index:
set sample_actions <index> <actions list>
The examples for the sample flow use case and result as below:
1. set sample_actions 0 mark id 0x8 / queue index 2 / end
.. pattern eth / end actions sample ratio 2 index 0 / jump group 2 ...
This flow will result in all the matched ingress packets will be
jumped to next flow table, and the each second packet will be
marked and sent to queue 2 of the control application.
2. ...pattern eth / end actions sample ratio 2 / port_id id 2 ...
The flow will result in all the matched ingress packets will be sent to
port 2, and the each second packet will also be sent to e-switch
manager vport.
Signed-off-by: Jiawei Wang <jiaweiw@mellanox.com>
---
app/test-pmd/cmdline_flow.c | 285 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 276 insertions(+), 9 deletions(-)
Comments
> -----Original Message-----
> From: Jiawei Wang <jiaweiw@mellanox.com>
> Sent: Thursday, June 25, 2020 7:26 PM
> To: Ori Kam <orika@mellanox.com>; Slava Ovsiienko
> <viacheslavo@mellanox.com>; Matan Azrad <matan@mellanox.com>
> Cc: dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>; Raslan
> Darawsheh <rasland@mellanox.com>; ian.stokes@intel.com; fbl@redhat.com;
> Jiawei(Jonny) Wang <jiaweiw@mellanox.com>
> Subject: [PATCH 8/8] app/testpmd: add testpmd command for sample action
>
> Add a new testpmd command 'set sample_actions' that supports the multiple
> sample actions list configuration by using the index:
> set sample_actions <index> <actions list>
>
> The examples for the sample flow use case and result as below:
>
> 1. set sample_actions 0 mark id 0x8 / queue index 2 / end
> .. pattern eth / end actions sample ratio 2 index 0 / jump group 2 ...
>
> This flow will result in all the matched ingress packets will be
> jumped to next flow table, and the each second packet will be
> marked and sent to queue 2 of the control application.
>
> 2. ...pattern eth / end actions sample ratio 2 / port_id id 2 ...
>
> The flow will result in all the matched ingress packets will be sent to
> port 2, and the each second packet will also be sent to e-switch
> manager vport.
>
> Signed-off-by: Jiawei Wang <jiaweiw@mellanox.com>
> ---
> app/test-pmd/cmdline_flow.c | 285
> ++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 276 insertions(+), 9 deletions(-)
>
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 4e2006c..6b1e515 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -56,6 +56,8 @@ enum index {
> SET_RAW_ENCAP,
> SET_RAW_DECAP,
> SET_RAW_INDEX,
> + SET_SAMPLE_ACTIONS,
> + SET_SAMPLE_INDEX,
>
> /* Top-level command. */
> FLOW,
> @@ -349,6 +351,10 @@ enum index {
> ACTION_SET_IPV6_DSCP_VALUE,
> ACTION_AGE,
> ACTION_AGE_TIMEOUT,
> + ACTION_SAMPLE,
> + ACTION_SAMPLE_RATIO,
> + ACTION_SAMPLE_INDEX,
> + ACTION_SAMPLE_INDEX_VALUE,
> };
>
> /** Maximum size for pattern in struct rte_flow_item_raw. */
> @@ -484,6 +490,22 @@ struct action_nvgre_encap_data {
>
> struct mplsoudp_decap_conf mplsoudp_decap_conf;
>
> +#define ACTION_SAMPLE_ACTIONS_NUM 10
> +#define RAW_SAMPLE_CONFS_MAX_NUM 8
> +/** Storage for struct rte_flow_action_sample including external data. */
> +struct action_sample_data {
> + struct rte_flow_action_sample conf;
> + uint32_t idx;
> +};
> +/** Storage for struct rte_flow_action_sample. */
> +struct raw_sample_conf {
> + struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
> +};
> +struct raw_sample_conf
> raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
> +struct rte_flow_action_mark
> sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
> +struct rte_flow_action_queue
> sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
> +struct rte_flow_action_count
> sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
> +
> /** Maximum number of subsequent tokens and arguments on the stack. */
> #define CTX_STACK_SIZE 16
>
> @@ -1161,6 +1183,7 @@ struct parse_action_priv {
> ACTION_SET_IPV4_DSCP,
> ACTION_SET_IPV6_DSCP,
> ACTION_AGE,
> + ACTION_SAMPLE,
> ZERO,
> };
>
> @@ -1393,9 +1416,28 @@ struct parse_action_priv {
> ZERO,
> };
>
> +static const enum index action_sample[] = {
> + ACTION_SAMPLE,
> + ACTION_SAMPLE_RATIO,
> + ACTION_SAMPLE_INDEX,
> + ACTION_NEXT,
> + ZERO,
> +};
> +
> +static const enum index next_action_sample[] = {
> + ACTION_QUEUE,
> + ACTION_MARK,
> + ACTION_COUNT,
> + ACTION_NEXT,
> + ZERO,
> +};
> +
> static int parse_set_raw_encap_decap(struct context *, const struct token *,
> const char *, unsigned int,
> void *, unsigned int);
> +static int parse_set_sample_action(struct context *, const struct token *,
> + const char *, unsigned int,
> + void *, unsigned int);
> static int parse_set_init(struct context *, const struct token *,
> const char *, unsigned int,
> void *, unsigned int);
> @@ -1460,7 +1502,15 @@ static int parse_vc_action_raw_decap_index(struct
> context *,
> static int parse_vc_action_set_meta(struct context *ctx,
> const struct token *token, const char *str,
> unsigned int len, void *buf,
> + unsigned int size);
> +static int parse_vc_action_sample(struct context *ctx,
> + const struct token *token, const char *str,
> + unsigned int len, void *buf,
> unsigned int size);
> +static int
> +parse_vc_action_sample_index(struct context *ctx, const struct token *token,
> + const char *str, unsigned int len, void *buf,
> + unsigned int size);
> static int parse_destroy(struct context *, const struct token *,
> const char *, unsigned int,
> void *, unsigned int);
> @@ -1531,6 +1581,8 @@ static int comp_vc_action_rss_queue(struct context
> *, const struct token *,
> unsigned int, char *, unsigned int);
> static int comp_set_raw_index(struct context *, const struct token *,
> unsigned int, char *, unsigned int);
> +static int comp_set_sample_index(struct context *, const struct token *,
> + unsigned int, char *, unsigned int);
>
> /** Token definitions. */
> static const struct token token_list[] = {
> @@ -3612,11 +3664,13 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> /* Top level command. */
> [SET] = {
> .name = "set",
> - .help = "set raw encap/decap data",
> - .type = "set raw_encap|raw_decap <index> <pattern>",
> + .help = "set raw encap/decap/sample data",
> + .type = "set raw_encap|raw_decap <index> <pattern>"
> + " or set sample_actions <index> <action>",
> .next = NEXT(NEXT_ENTRY
> (SET_RAW_ENCAP,
> - SET_RAW_DECAP)),
> + SET_RAW_DECAP,
> + SET_SAMPLE_ACTIONS)),
> .call = parse_set_init,
> },
> /* Sub-level commands. */
> @@ -3647,6 +3701,23 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> .next = NEXT(next_item),
> .call = parse_port,
> },
> + [SET_SAMPLE_INDEX] = {
> + .name = "{index}",
> + .type = "UNSIGNED",
> + .help = "index of sample actions",
> + .next = NEXT(next_action_sample),
> + .call = parse_port,
> + },
> + [SET_SAMPLE_ACTIONS] = {
> + .name = "sample_actions",
> + .help = "set sample actions list",
> + .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
> + .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
> + (offsetof(struct buffer, port),
> + sizeof(((struct buffer *)0)->port),
> + 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
> + .call = parse_set_sample_action,
> + },
> [ACTION_SET_TAG] = {
> .name = "set_tag",
> .help = "set tag",
> @@ -3750,6 +3821,37 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> .next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
> .call = parse_vc_conf,
> },
> + [ACTION_SAMPLE] = {
> + .name = "sample",
> + .help = "set a sample action",
> + .next = NEXT(action_sample),
> + .priv = PRIV_ACTION(SAMPLE,
> + sizeof(struct action_sample_data)),
> + .call = parse_vc_action_sample,
> + },
> + [ACTION_SAMPLE_RATIO] = {
> + .name = "ratio",
> + .help = "flow sample ratio value",
> + .next = NEXT(action_sample, NEXT_ENTRY(UNSIGNED)),
> + .args = ARGS(ARGS_ENTRY_ARB
> + (offsetof(struct action_sample_data, conf) +
> + offsetof(struct rte_flow_action_sample, ratio),
> + sizeof(((struct rte_flow_action_sample *)0)->
> + ratio))),
> + },
> + [ACTION_SAMPLE_INDEX] = {
> + .name = "index",
> + .help = "the index of sample actions list",
> + .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
> + },
> + [ACTION_SAMPLE_INDEX_VALUE] = {
> + .name = "{index}",
> + .type = "UNSIGNED",
> + .help = "unsigned integer value",
> + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> + .call = parse_vc_action_sample_index,
> + .comp = comp_set_sample_index,
> + },
> };
>
> /** Remove and return last entry from argument stack. */
> @@ -5207,6 +5309,76 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> return len;
> }
>
> +static int
> +parse_vc_action_sample(struct context *ctx, const struct token *token,
> + const char *str, unsigned int len, void *buf,
> + unsigned int size)
> +{
> + struct buffer *out = buf;
> + struct rte_flow_action *action;
> + struct action_sample_data *action_sample_data = NULL;
> + static struct rte_flow_action end_action = {
> + RTE_FLOW_ACTION_TYPE_END, 0
> + };
> + int ret;
> +
> + ret = parse_vc(ctx, token, str, len, buf, size);
> + if (ret < 0)
> + return ret;
> + /* Nothing else to do if there is no buffer. */
> + if (!out)
> + return ret;
> + if (!out->args.vc.actions_n)
> + return -1;
> + action = &out->args.vc.actions[out->args.vc.actions_n - 1];
> + /* Point to selected object. */
> + ctx->object = out->args.vc.data;
> + ctx->objmask = NULL;
> + /* Copy the headers to the buffer. */
> + action_sample_data = ctx->object;
> + action_sample_data->conf.actions = &end_action;
> + action->conf = &action_sample_data->conf;
> + return ret;
> +}
> +
> +static int
> +parse_vc_action_sample_index(struct context *ctx, const struct token *token,
> + const char *str, unsigned int len, void *buf,
> + unsigned int size)
> +{
> + struct action_sample_data *action_sample_data;
> + struct rte_flow_action *action;
> + const struct arg *arg;
> + struct buffer *out = buf;
> + int ret;
> + uint16_t idx;
> +
> + RTE_SET_USED(token);
> + RTE_SET_USED(buf);
> + RTE_SET_USED(size);
> + if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
> + return -1;
> + arg = ARGS_ENTRY_ARB_BOUNDED
> + (offsetof(struct action_sample_data, idx),
> + sizeof(((struct action_sample_data *)0)->idx),
> + 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
> + if (push_args(ctx, arg))
> + return -1;
> + ret = parse_int(ctx, token, str, len, NULL, 0);
> + if (ret < 0) {
> + pop_args(ctx);
> + return -1;
> + }
> + if (!ctx->object)
> + return len;
> + action = &out->args.vc.actions[out->args.vc.actions_n - 1];
> + action_sample_data = ctx->object;
> + idx = action_sample_data->idx;
> + action_sample_data->conf.actions = raw_sample_confs[idx].data;
> + action->conf = &action_sample_data->conf;
> + return len;
> +}
> +
> /** Parse tokens for destroy command. */
> static int
> parse_destroy(struct context *ctx, const struct token *token,
> @@ -5971,6 +6143,38 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> if (!out->command)
> return -1;
> out->command = ctx->curr;
> + /* For encap/decap we need is pattern */
> + out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> + sizeof(double));
> + return len;
> +}
> +
> +/** Parse set command, initialize output buffer for subsequent tokens. */
> +static int
> +parse_set_sample_action(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)
> + return -1;
> + /* Nothing else to do if there is no buffer. */
> + if (!out)
> + return len;
> + /* Make sure buffer is large enough. */
> + if (size < sizeof(*out))
> + return -1;
> + ctx->objdata = 0;
> + ctx->objmask = NULL;
> + ctx->object = out;
> + if (!out->command)
> + return -1;
> + out->command = ctx->curr;
> + /* For sampler we need is actions */
> + out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> + sizeof(double));
> return len;
> }
>
> @@ -6007,11 +6211,8 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> return -1;
> out->command = ctx->curr;
> out->args.vc.data = (uint8_t *)out + size;
> - /* All we need is pattern */
> - out->args.vc.pattern =
> - (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> - sizeof(double));
> - ctx->object = out->args.vc.pattern;
> + ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> + sizeof(double));
> }
> return len;
> }
> @@ -6162,6 +6363,24 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> return nb;
> }
>
> +/** Complete index number for set raw_encap/raw_decap commands. */
> +static int
> +comp_set_sample_index(struct context *ctx, const struct token *token,
> + unsigned int ent, char *buf, unsigned int size)
> +{
> + uint16_t idx = 0;
> + uint16_t nb = 0;
> +
> + RTE_SET_USED(ctx);
> + RTE_SET_USED(token);
> + for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
> + if (buf && idx == ent)
> + return snprintf(buf, size, "%u", idx);
> + ++nb;
> + }
> + return nb;
> +}
> +
> /** Internal context. */
> static struct context cmd_flow_context;
>
> @@ -6607,7 +6826,53 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> return mask;
> }
>
> -
> +/** Dispatch parsed buffer to function calls. */
> +static void
> +cmd_set_raw_parsed_sample(const struct buffer *in)
> +{
> + uint32_t n = in->args.vc.actions_n;
> + uint32_t i = 0;
> + struct rte_flow_action *action = NULL;
> + struct rte_flow_action *data = NULL;
> + size_t size = 0;
> + uint16_t idx = in->port; /* We borrow port field as index */
> + uint32_t max_size = sizeof(struct rte_flow_action) *
> +
> ACTION_SAMPLE_ACTIONS_NUM;
> +
> + RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
> + data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
> + memset(data, 0x00, max_size);
> + for (; i <= n - 1; i++) {
> + action = in->args.vc.actions + i;
> + if (action->type == RTE_FLOW_ACTION_TYPE_END)
> + break;
> + switch (action->type) {
> + case RTE_FLOW_ACTION_TYPE_MARK:
> + size = sizeof(struct rte_flow_action_mark);
> + rte_memcpy(&sample_mark[idx],
> + (const void *)action->conf, size);
> + action->conf = &sample_mark[idx];
> + break;
> + case RTE_FLOW_ACTION_TYPE_COUNT:
> + size = sizeof(struct rte_flow_action_count);
> + rte_memcpy(&sample_count[idx],
> + (const void *)action->conf, size);
> + action->conf = &sample_count[idx];
> + break;
> + case RTE_FLOW_ACTION_TYPE_QUEUE:
> + size = sizeof(struct rte_flow_action_queue);
> + rte_memcpy(&sample_queue[idx],
> + (const void *)action->conf, size);
> + action->conf = &sample_queue[idx];
> + break;
> + default:
> + printf("Error - Not supported action\n");
> + return;
> + }
> + rte_memcpy(data, action, sizeof(struct rte_flow_action));
> + data++;
> + }
> +}
>
> /** Dispatch parsed buffer to function calls. */
> static void
> @@ -6624,6 +6889,8 @@ static int comp_set_raw_index(struct context *,
> const struct token *,
> uint16_t proto = 0;
> uint16_t idx = in->port; /* We borrow port field as index */
>
> + if (in->command == SET_SAMPLE_ACTIONS)
> + return cmd_set_raw_parsed_sample(in);
> RTE_ASSERT(in->command == SET_RAW_ENCAP ||
> in->command == SET_RAW_DECAP);
> if (in->command == SET_RAW_ENCAP) {
> --
> 1.8.3.1
Acked-by: Ori Kam <orika@mellanox.com>
Thanks,
Ori
@@ -56,6 +56,8 @@ enum index {
SET_RAW_ENCAP,
SET_RAW_DECAP,
SET_RAW_INDEX,
+ SET_SAMPLE_ACTIONS,
+ SET_SAMPLE_INDEX,
/* Top-level command. */
FLOW,
@@ -349,6 +351,10 @@ enum index {
ACTION_SET_IPV6_DSCP_VALUE,
ACTION_AGE,
ACTION_AGE_TIMEOUT,
+ ACTION_SAMPLE,
+ ACTION_SAMPLE_RATIO,
+ ACTION_SAMPLE_INDEX,
+ ACTION_SAMPLE_INDEX_VALUE,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -484,6 +490,22 @@ struct action_nvgre_encap_data {
struct mplsoudp_decap_conf mplsoudp_decap_conf;
+#define ACTION_SAMPLE_ACTIONS_NUM 10
+#define RAW_SAMPLE_CONFS_MAX_NUM 8
+/** Storage for struct rte_flow_action_sample including external data. */
+struct action_sample_data {
+ struct rte_flow_action_sample conf;
+ uint32_t idx;
+};
+/** Storage for struct rte_flow_action_sample. */
+struct raw_sample_conf {
+ struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
+};
+struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
+struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
+struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
+struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
+
/** Maximum number of subsequent tokens and arguments on the stack. */
#define CTX_STACK_SIZE 16
@@ -1161,6 +1183,7 @@ struct parse_action_priv {
ACTION_SET_IPV4_DSCP,
ACTION_SET_IPV6_DSCP,
ACTION_AGE,
+ ACTION_SAMPLE,
ZERO,
};
@@ -1393,9 +1416,28 @@ struct parse_action_priv {
ZERO,
};
+static const enum index action_sample[] = {
+ ACTION_SAMPLE,
+ ACTION_SAMPLE_RATIO,
+ ACTION_SAMPLE_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index next_action_sample[] = {
+ ACTION_QUEUE,
+ ACTION_MARK,
+ ACTION_COUNT,
+ ACTION_NEXT,
+ ZERO,
+};
+
static int parse_set_raw_encap_decap(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_set_sample_action(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
static int parse_set_init(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
@@ -1460,7 +1502,15 @@ static int parse_vc_action_raw_decap_index(struct context *,
static int parse_vc_action_set_meta(struct context *ctx,
const struct token *token, const char *str,
unsigned int len, void *buf,
+ unsigned int size);
+static int parse_vc_action_sample(struct context *ctx,
+ const struct token *token, const char *str,
+ unsigned int len, void *buf,
unsigned int size);
+static int
+parse_vc_action_sample_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
static int parse_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
@@ -1531,6 +1581,8 @@ static int comp_vc_action_rss_queue(struct context *, const struct token *,
unsigned int, char *, unsigned int);
static int comp_set_raw_index(struct context *, const struct token *,
unsigned int, char *, unsigned int);
+static int comp_set_sample_index(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
/** Token definitions. */
static const struct token token_list[] = {
@@ -3612,11 +3664,13 @@ static int comp_set_raw_index(struct context *, const struct token *,
/* Top level command. */
[SET] = {
.name = "set",
- .help = "set raw encap/decap data",
- .type = "set raw_encap|raw_decap <index> <pattern>",
+ .help = "set raw encap/decap/sample data",
+ .type = "set raw_encap|raw_decap <index> <pattern>"
+ " or set sample_actions <index> <action>",
.next = NEXT(NEXT_ENTRY
(SET_RAW_ENCAP,
- SET_RAW_DECAP)),
+ SET_RAW_DECAP,
+ SET_SAMPLE_ACTIONS)),
.call = parse_set_init,
},
/* Sub-level commands. */
@@ -3647,6 +3701,23 @@ static int comp_set_raw_index(struct context *, const struct token *,
.next = NEXT(next_item),
.call = parse_port,
},
+ [SET_SAMPLE_INDEX] = {
+ .name = "{index}",
+ .type = "UNSIGNED",
+ .help = "index of sample actions",
+ .next = NEXT(next_action_sample),
+ .call = parse_port,
+ },
+ [SET_SAMPLE_ACTIONS] = {
+ .name = "sample_actions",
+ .help = "set sample actions list",
+ .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
+ .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct buffer, port),
+ sizeof(((struct buffer *)0)->port),
+ 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
+ .call = parse_set_sample_action,
+ },
[ACTION_SET_TAG] = {
.name = "set_tag",
.help = "set tag",
@@ -3750,6 +3821,37 @@ static int comp_set_raw_index(struct context *, const struct token *,
.next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
.call = parse_vc_conf,
},
+ [ACTION_SAMPLE] = {
+ .name = "sample",
+ .help = "set a sample action",
+ .next = NEXT(action_sample),
+ .priv = PRIV_ACTION(SAMPLE,
+ sizeof(struct action_sample_data)),
+ .call = parse_vc_action_sample,
+ },
+ [ACTION_SAMPLE_RATIO] = {
+ .name = "ratio",
+ .help = "flow sample ratio value",
+ .next = NEXT(action_sample, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_ARB
+ (offsetof(struct action_sample_data, conf) +
+ offsetof(struct rte_flow_action_sample, ratio),
+ sizeof(((struct rte_flow_action_sample *)0)->
+ ratio))),
+ },
+ [ACTION_SAMPLE_INDEX] = {
+ .name = "index",
+ .help = "the index of sample actions list",
+ .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
+ },
+ [ACTION_SAMPLE_INDEX_VALUE] = {
+ .name = "{index}",
+ .type = "UNSIGNED",
+ .help = "unsigned integer value",
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_sample_index,
+ .comp = comp_set_sample_index,
+ },
};
/** Remove and return last entry from argument stack. */
@@ -5207,6 +5309,76 @@ static int comp_set_raw_index(struct context *, const struct token *,
return len;
}
+static int
+parse_vc_action_sample(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_sample_data *action_sample_data = NULL;
+ static struct rte_flow_action end_action = {
+ RTE_FLOW_ACTION_TYPE_END, 0
+ };
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_sample_data = ctx->object;
+ action_sample_data->conf.actions = &end_action;
+ action->conf = &action_sample_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_sample_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_sample_data *action_sample_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
+ return -1;
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_sample_data, idx),
+ sizeof(((struct action_sample_data *)0)->idx),
+ 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_sample_data = ctx->object;
+ idx = action_sample_data->idx;
+ action_sample_data->conf.actions = raw_sample_confs[idx].data;
+ action->conf = &action_sample_data->conf;
+ return len;
+}
+
/** Parse tokens for destroy command. */
static int
parse_destroy(struct context *ctx, const struct token *token,
@@ -5971,6 +6143,38 @@ static int comp_set_raw_index(struct context *, const struct token *,
if (!out->command)
return -1;
out->command = ctx->curr;
+ /* For encap/decap we need is pattern */
+ out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+}
+
+/** Parse set command, initialize output buffer for subsequent tokens. */
+static int
+parse_set_sample_action(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)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Make sure buffer is large enough. */
+ if (size < sizeof(*out))
+ return -1;
+ ctx->objdata = 0;
+ ctx->objmask = NULL;
+ ctx->object = out;
+ if (!out->command)
+ return -1;
+ out->command = ctx->curr;
+ /* For sampler we need is actions */
+ out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
return len;
}
@@ -6007,11 +6211,8 @@ static int comp_set_raw_index(struct context *, const struct token *,
return -1;
out->command = ctx->curr;
out->args.vc.data = (uint8_t *)out + size;
- /* All we need is pattern */
- out->args.vc.pattern =
- (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
- sizeof(double));
- ctx->object = out->args.vc.pattern;
+ ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
}
return len;
}
@@ -6162,6 +6363,24 @@ static int comp_set_raw_index(struct context *, const struct token *,
return nb;
}
+/** Complete index number for set raw_encap/raw_decap commands. */
+static int
+comp_set_sample_index(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ uint16_t idx = 0;
+ uint16_t nb = 0;
+
+ RTE_SET_USED(ctx);
+ RTE_SET_USED(token);
+ for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
+ if (buf && idx == ent)
+ return snprintf(buf, size, "%u", idx);
+ ++nb;
+ }
+ return nb;
+}
+
/** Internal context. */
static struct context cmd_flow_context;
@@ -6607,7 +6826,53 @@ static int comp_set_raw_index(struct context *, const struct token *,
return mask;
}
-
+/** Dispatch parsed buffer to function calls. */
+static void
+cmd_set_raw_parsed_sample(const struct buffer *in)
+{
+ uint32_t n = in->args.vc.actions_n;
+ uint32_t i = 0;
+ struct rte_flow_action *action = NULL;
+ struct rte_flow_action *data = NULL;
+ size_t size = 0;
+ uint16_t idx = in->port; /* We borrow port field as index */
+ uint32_t max_size = sizeof(struct rte_flow_action) *
+ ACTION_SAMPLE_ACTIONS_NUM;
+
+ RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
+ data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
+ memset(data, 0x00, max_size);
+ for (; i <= n - 1; i++) {
+ action = in->args.vc.actions + i;
+ if (action->type == RTE_FLOW_ACTION_TYPE_END)
+ break;
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ size = sizeof(struct rte_flow_action_mark);
+ rte_memcpy(&sample_mark[idx],
+ (const void *)action->conf, size);
+ action->conf = &sample_mark[idx];
+ break;
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ size = sizeof(struct rte_flow_action_count);
+ rte_memcpy(&sample_count[idx],
+ (const void *)action->conf, size);
+ action->conf = &sample_count[idx];
+ break;
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ size = sizeof(struct rte_flow_action_queue);
+ rte_memcpy(&sample_queue[idx],
+ (const void *)action->conf, size);
+ action->conf = &sample_queue[idx];
+ break;
+ default:
+ printf("Error - Not supported action\n");
+ return;
+ }
+ rte_memcpy(data, action, sizeof(struct rte_flow_action));
+ data++;
+ }
+}
/** Dispatch parsed buffer to function calls. */
static void
@@ -6624,6 +6889,8 @@ static int comp_set_raw_index(struct context *, const struct token *,
uint16_t proto = 0;
uint16_t idx = in->port; /* We borrow port field as index */
+ if (in->command == SET_SAMPLE_ACTIONS)
+ return cmd_set_raw_parsed_sample(in);
RTE_ASSERT(in->command == SET_RAW_ENCAP ||
in->command == SET_RAW_DECAP);
if (in->command == SET_RAW_ENCAP) {