From 739e045bf2567142cb398888437e459db45fc7b4 Mon Sep 17 00:00:00 2001 From: Xiaoyu Min Date: Mon, 16 Sep 2019 17:21:02 +0800 Subject: [PATCH] app/testpmd: support multiple raw encap/decap MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In some scenarios, the raw_encap/raw_decap actions could be multiple in one single flow (e,g. hirepin flow): ... actions raw_decap / raw_encap / raw_decap / raw_encap / ... This requires the testpmd supports multiple raw_encap/raw_decap data settings as well. With the multiple raw_encap/raw_decap settings, the testpmd commands – set raw_encap / set raw_decap will become: set raw_encap set raw_decap And the actions – raw_encap/raw_decap also could optionally choose which global raw_encap/raw_decap confs to be used by index: ... actions raw_decap index 1 / raw_encap index 2 / ... If there is no `index` specified, the default index is 0: set raw_encap ... actions raw_decap / raw_encap / ... which will use raw_encap index 0. In addition to the set raw_encap/raw_decap commands, show show all are also introduced into in order to check which index is set and to what. Signed-off-by: Xiaoyu Min Acked-by: Ori Kam --- app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 310 ++++++++++++++++++-- app/test-pmd/testpmd.h | 2 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 57 +++- 4 files changed, 331 insertions(+), 40 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 85514d1e64..4478069911 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -19205,6 +19205,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_config_tx_metadata_specific, (cmdline_parse_inst_t *)&cmd_show_tx_metadata, (cmdline_parse_inst_t *)&cmd_set_raw, + (cmdline_parse_inst_t *)&cmd_show_set_raw, + (cmdline_parse_inst_t *)&cmd_show_set_raw_all, NULL, }; diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index b2c16e6e45..0d0bc0a5b2 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -19,7 +19,10 @@ #include #include #include +#include +#include #include +#include #include "testpmd.h" @@ -51,6 +54,7 @@ enum index { /* Sub-leve commands. */ SET_RAW_ENCAP, SET_RAW_DECAP, + SET_RAW_INDEX, /* Top-level command. */ FLOW, @@ -308,6 +312,10 @@ enum index { ACTION_DEC_TCP_ACK_VALUE, ACTION_RAW_ENCAP, ACTION_RAW_DECAP, + ACTION_RAW_ENCAP_INDEX, + ACTION_RAW_ENCAP_INDEX_VALUE, + ACTION_RAW_DECAP_INDEX, + ACTION_RAW_DECAP_INDEX_VALUE, }; /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -329,6 +337,7 @@ struct action_rss_data { /** Maximum data size in struct rte_flow_action_raw_encap. */ #define ACTION_RAW_ENCAP_MAX_DATA 128 +#define RAW_ENCAP_CONFS_MAX_NUM 8 /** Storage for struct rte_flow_action_raw_encap. */ struct raw_encap_conf { @@ -337,13 +346,14 @@ struct raw_encap_conf { size_t size; }; -struct raw_encap_conf raw_encap_conf = {.size = 0}; +struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM]; /** Storage for struct rte_flow_action_raw_encap including external data. */ struct action_raw_encap_data { struct rte_flow_action_raw_encap conf; uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; + uint16_t idx; }; /** Storage for struct rte_flow_action_raw_decap. */ @@ -352,12 +362,13 @@ struct raw_decap_conf { size_t size; }; -struct raw_decap_conf raw_decap_conf = {.size = 0}; +struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM]; /** Storage for struct rte_flow_action_raw_decap including external data. */ struct action_raw_decap_data { struct rte_flow_action_raw_decap conf; uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; + uint16_t idx; }; struct vxlan_encap_conf vxlan_encap_conf = { @@ -995,6 +1006,12 @@ static const enum index item_higig2[] = { ZERO, }; +static const enum index next_set_raw[] = { + SET_RAW_INDEX, + ITEM_ETH, + ZERO, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -1236,6 +1253,18 @@ static const enum index action_dec_tcp_ack[] = { ZERO, }; +static const enum index action_raw_encap[] = { + ACTION_RAW_ENCAP_INDEX, + ACTION_NEXT, + ZERO, +}; + +static const enum index action_raw_decap[] = { + ACTION_RAW_DECAP_INDEX, + ACTION_NEXT, + ZERO, +}; + static int parse_set_raw_encap_decap(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1294,6 +1323,12 @@ static int parse_vc_action_raw_encap(struct context *, static int parse_vc_action_raw_decap(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_action_raw_encap_index(struct context *, + const struct token *, const char *, + unsigned int, void *, unsigned int); +static int parse_vc_action_raw_decap_index(struct context *, + const struct token *, const char *, + unsigned int, void *, unsigned int); static int parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1353,6 +1388,8 @@ static int comp_vc_action_rss_type(struct context *, const struct token *, unsigned int, char *, unsigned int); 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); /** Token definitions. */ static const struct token token_list[] = { @@ -3266,23 +3303,49 @@ static const struct token token_list[] = { .name = "raw_encap", .help = "encapsulation data, defined by set raw_encap", .priv = PRIV_ACTION(RAW_ENCAP, - sizeof(struct rte_flow_action_raw_encap)), - .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + sizeof(struct action_raw_encap_data)), + .next = NEXT(action_raw_encap), .call = parse_vc_action_raw_encap, }, + [ACTION_RAW_ENCAP_INDEX] = { + .name = "index", + .help = "the index of raw_encap_confs", + .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)), + }, + [ACTION_RAW_ENCAP_INDEX_VALUE] = { + .name = "{index}", + .type = "UNSIGNED", + .help = "unsigned integer value", + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc_action_raw_encap_index, + .comp = comp_set_raw_index, + }, [ACTION_RAW_DECAP] = { .name = "raw_decap", .help = "decapsulation data, defined by set raw_encap", .priv = PRIV_ACTION(RAW_DECAP, - sizeof(struct rte_flow_action_raw_decap)), - .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + sizeof(struct action_raw_decap_data)), + .next = NEXT(action_raw_decap), .call = parse_vc_action_raw_decap, }, + [ACTION_RAW_DECAP_INDEX] = { + .name = "index", + .help = "the index of raw_encap_confs", + .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)), + }, + [ACTION_RAW_DECAP_INDEX_VALUE] = { + .name = "{index}", + .type = "UNSIGNED", + .help = "unsigned integer value", + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc_action_raw_decap_index, + .comp = comp_set_raw_index, + }, /* Top level command. */ [SET] = { .name = "set", .help = "set raw encap/decap data", - .type = "set raw_encap|raw_decap ", + .type = "set raw_encap|raw_decap ", .next = NEXT(NEXT_ENTRY (SET_RAW_ENCAP, SET_RAW_DECAP)), @@ -3292,14 +3355,29 @@ static const struct token token_list[] = { [SET_RAW_ENCAP] = { .name = "raw_encap", .help = "set raw encap data", - .next = NEXT(next_item), + .next = NEXT(next_set_raw), + .args = ARGS(ARGS_ENTRY_ARB_BOUNDED + (offsetof(struct buffer, port), + sizeof(((struct buffer *)0)->port), + 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), .call = parse_set_raw_encap_decap, }, [SET_RAW_DECAP] = { .name = "raw_decap", .help = "set raw decap data", - .next = NEXT(next_item), + .next = NEXT(next_set_raw), + .args = ARGS(ARGS_ENTRY_ARB_BOUNDED + (offsetof(struct buffer, port), + sizeof(((struct buffer *)0)->port), + 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), .call = parse_set_raw_encap_decap, + }, + [SET_RAW_INDEX] = { + .name = "{index}", + .type = "UNSIGNED", + .help = "index of raw_encap/raw_decap data", + .next = NEXT(next_item), + .call = parse_port, } }; @@ -4601,6 +4679,84 @@ parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, return ret; } +static int +parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, + const char *str, unsigned int len, void *buf, + unsigned int size) +{ + struct action_raw_decap_data *action_raw_decap_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); + arg = ARGS_ENTRY_ARB_BOUNDED + (offsetof(struct action_raw_decap_data, idx), + sizeof(((struct action_raw_decap_data *)0)->idx), + 0, RAW_ENCAP_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_raw_decap_data = ctx->object; + idx = action_raw_decap_data->idx; + action_raw_decap_data->conf.data = raw_decap_confs[idx].data; + action_raw_decap_data->conf.size = raw_decap_confs[idx].size; + action->conf = &action_raw_decap_data->conf; + return len; +} + + +static int +parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, + const char *str, unsigned int len, void *buf, + unsigned int size) +{ + struct action_raw_encap_data *action_raw_encap_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_RAW_ENCAP_INDEX_VALUE) + return -1; + arg = ARGS_ENTRY_ARB_BOUNDED + (offsetof(struct action_raw_encap_data, idx), + sizeof(((struct action_raw_encap_data *)0)->idx), + 0, RAW_ENCAP_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_raw_encap_data = ctx->object; + idx = action_raw_encap_data->idx; + action_raw_encap_data->conf.data = raw_encap_confs[idx].data; + action_raw_encap_data->conf.size = raw_encap_confs[idx].size; + action_raw_encap_data->conf.preserve = NULL; + action->conf = &action_raw_encap_data->conf; + return len; +} + static int parse_vc_action_raw_encap(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, @@ -4608,8 +4764,7 @@ parse_vc_action_raw_encap(struct context *ctx, const struct token *token, { struct buffer *out = buf; struct rte_flow_action *action; - struct rte_flow_action_raw_encap *action_raw_encap_conf = NULL; - uint8_t *data = NULL; + struct action_raw_encap_data *action_raw_encap_data = NULL; int ret; ret = parse_vc(ctx, token, str, len, buf, size); @@ -4625,14 +4780,11 @@ parse_vc_action_raw_encap(struct context *ctx, const struct token *token, ctx->object = out->args.vc.data; ctx->objmask = NULL; /* Copy the headers to the buffer. */ - action_raw_encap_conf = ctx->object; - /* data stored from tail of data buffer */ - data = (uint8_t *)&(raw_encap_conf.data) + - ACTION_RAW_ENCAP_MAX_DATA - raw_encap_conf.size; - action_raw_encap_conf->data = data; - action_raw_encap_conf->preserve = NULL; - action_raw_encap_conf->size = raw_encap_conf.size; - action->conf = action_raw_encap_conf; + action_raw_encap_data = ctx->object; + action_raw_encap_data->conf.data = raw_encap_confs[0].data; + action_raw_encap_data->conf.preserve = NULL; + action_raw_encap_data->conf.size = raw_encap_confs[0].size; + action->conf = &action_raw_encap_data->conf; return ret; } @@ -4643,8 +4795,7 @@ parse_vc_action_raw_decap(struct context *ctx, const struct token *token, { struct buffer *out = buf; struct rte_flow_action *action; - struct rte_flow_action_raw_decap *action_raw_decap_conf = NULL; - uint8_t *data = NULL; + struct action_raw_decap_data *action_raw_decap_data = NULL; int ret; ret = parse_vc(ctx, token, str, len, buf, size); @@ -4660,13 +4811,10 @@ parse_vc_action_raw_decap(struct context *ctx, const struct token *token, ctx->object = out->args.vc.data; ctx->objmask = NULL; /* Copy the headers to the buffer. */ - action_raw_decap_conf = ctx->object; - /* data stored from tail of data buffer */ - data = (uint8_t *)&(raw_decap_conf.data) + - ACTION_RAW_ENCAP_MAX_DATA - raw_decap_conf.size; - action_raw_decap_conf->data = data; - action_raw_decap_conf->size = raw_decap_conf.size; - action->conf = action_raw_decap_conf; + action_raw_decap_data = ctx->object; + action_raw_decap_data->conf.data = raw_decap_confs[0].data; + action_raw_decap_data->conf.size = raw_decap_confs[0].size; + action->conf = &action_raw_decap_data->conf; return ret; } @@ -5345,6 +5493,7 @@ parse_set_raw_encap_decap(struct context *ctx, const struct token *token, return -1; ctx->objdata = 0; ctx->objmask = NULL; + ctx->object = out; if (!out->command) return -1; out->command = ctx->curr; @@ -5521,6 +5670,24 @@ comp_vc_action_rss_queue(struct context *ctx, const struct token *token, return -1; } +/** Complete index number for set raw_encap/raw_decap commands. */ +static int +comp_set_raw_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_ENCAP_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; @@ -5960,15 +6127,16 @@ cmd_set_raw_parsed(const struct buffer *in) size_t *total_size = NULL; uint16_t upper_layer = 0; uint16_t proto = 0; + uint16_t idx = in->port; /* We borrow port field as index */ RTE_ASSERT(in->command == SET_RAW_ENCAP || in->command == SET_RAW_DECAP); if (in->command == SET_RAW_ENCAP) { - total_size = &raw_encap_conf.size; - data = (uint8_t *)&raw_encap_conf.data; + total_size = &raw_encap_confs[idx].size; + data = (uint8_t *)&raw_encap_confs[idx].data; } else { - total_size = &raw_decap_conf.size; - data = (uint8_t *)&raw_decap_conf.data; + total_size = &raw_decap_confs[idx].size; + data = (uint8_t *)&raw_decap_confs[idx].data; } *total_size = 0; memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); @@ -6041,6 +6209,7 @@ cmd_set_raw_parsed(const struct buffer *in) if (verbose_level & 0x1) printf("total data size is %zu\n", (*total_size)); RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); + memmove(data, (data_tail - (*total_size)), *total_size); } /** Populate help strings for current token (cmdline API). */ @@ -6125,3 +6294,80 @@ cmdline_parse_inst_t cmd_set_raw = { NULL, }, /**< Tokens are returned by cmd_flow_tok(). */ }; + +/* *** display raw_encap/raw_decap buf */ +struct cmd_show_set_raw_result { + cmdline_fixed_string_t cmd_show; + cmdline_fixed_string_t cmd_what; + cmdline_fixed_string_t cmd_all; + uint16_t cmd_index; +}; + +static void +cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) +{ + struct cmd_show_set_raw_result *res = parsed_result; + uint16_t index = res->cmd_index; + uint8_t all = 0; + uint8_t *raw_data = NULL; + size_t raw_size = 0; + char title[16] = {0}; + + RTE_SET_USED(cl); + RTE_SET_USED(data); + if (!strcmp(res->cmd_all, "all")) { + all = 1; + index = 0; + } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { + printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1); + return; + } + do { + if (!strcmp(res->cmd_what, "raw_encap")) { + raw_data = (uint8_t *)&raw_encap_confs[index].data; + raw_size = raw_encap_confs[index].size; + snprintf(title, 16, "\nindex: %u", index); + rte_hexdump(stdout, title, raw_data, raw_size); + } else { + raw_data = (uint8_t *)&raw_decap_confs[index].data; + raw_size = raw_decap_confs[index].size; + snprintf(title, 16, "\nindex: %u", index); + rte_hexdump(stdout, title, raw_data, raw_size); + } + } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); +} + +cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = + TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, + cmd_show, "show"); +cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = + TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, + cmd_what, "raw_encap#raw_decap"); +cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = + TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, + cmd_index, UINT16); +cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = + TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, + cmd_all, "all"); +cmdline_parse_inst_t cmd_show_set_raw = { + .f = cmd_show_set_raw_parsed, + .data = NULL, + .help_str = "show ", + .tokens = { + (void *)&cmd_show_set_raw_cmd_show, + (void *)&cmd_show_set_raw_cmd_what, + (void *)&cmd_show_set_raw_cmd_index, + NULL, + }, +}; +cmdline_parse_inst_t cmd_show_set_raw_all = { + .f = cmd_show_set_raw_parsed, + .data = NULL, + .help_str = "show all", + .tokens = { + (void *)&cmd_show_set_raw_cmd_show, + (void *)&cmd_show_set_raw_cmd_what, + (void *)&cmd_show_set_raw_cmd_all, + NULL, + }, +}; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index ce79f41950..ec10a1a35a 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -265,6 +265,8 @@ extern struct fwd_engine ieee1588_fwd_engine; extern struct fwd_engine * fwd_engines[]; /**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw; +extern cmdline_parse_inst_t cmd_show_set_raw; +extern cmdline_parse_inst_t cmd_show_set_raw_all; extern uint16_t mempool_flags; diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 1da60faffe..c68a742ebd 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -545,6 +545,25 @@ Dumps the log level for all the dpdk modules:: testpmd> dump_log_types +show (raw_encap|raw_decap) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Display content of raw_encap/raw_decap buffers in hex:: + + testpmd> show + testpmd> show all + +For example:: + + testpmd> show raw_encap 6 + + index: 6 at [0x1c565b0], len=50 + 00000000: 00 00 00 00 00 00 16 26 36 46 56 66 08 00 45 00 | .......&6FVf..E. + 00000010: 00 00 00 00 00 00 00 11 00 00 C0 A8 01 06 C0 A8 | ................ + 00000020: 03 06 00 00 00 FA 00 00 00 00 08 00 00 00 00 00 | ................ + 00000030: 06 00 | .. + + Configuration Functions ----------------------- @@ -1834,12 +1853,22 @@ Config Raw Encapsulation Configure the raw data to be used when encapsulating a packet by rte_flow_action_raw_encap:: + set raw_encap {index} {item} [/ {item} [...]] / end_set + +There are multiple global buffers for ``raw_encap``, this command will set one +internal buffer index by ``{index}``. +If there is no ``{index}`` specified:: + set raw_encap {item} [/ {item} [...]] / end_set -This command will set an internal buffer inside testpmd, any following flow rule -using the action raw_encap will use the last configuration set. -To have a different encapsulation header, this command must be called before the -flow rule creation. +the default index ``0`` is used. +In order to use different encapsulating header, ``index`` must be specified +during the flow rule creation:: + + testpmd> flow create 0 egress pattern eth / ipv4 / end actions + raw_encap index 2 / end + +Otherwise the default index ``0`` is used. Config Raw Decapsulation ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1847,10 +1876,22 @@ Config Raw Decapsulation Configure the raw data to be used when decapsulating a packet by rte_flow_action_raw_decap:: + set raw_decap {index} {item} [/ {item} [...]] / end_set + +There are multiple global buffers for ``raw_decap``, this command will set +one internal buffer index by ``{index}``. +If there is no ``{index}`` specified:: + set raw_decap {item} [/ {item} [...]] / end_set -This command will set an internal buffer inside testpmd, any following flow rule -using the action raw_decap will use the last configuration set. +the default index ``0`` is used. +In order to use different decapsulating header, ``index`` must be specified +during the flow rule creation:: + + testpmd> flow create 0 egress pattern eth / ipv4 / end actions + raw_encap index 3 / end + +Otherwise the default index ``0`` is used. Port Functions -------------- @@ -4670,11 +4711,11 @@ Raw encapsulation configuration can be set by the following commands Eecapsulating VxLAN:: - testpmd> set raw_encap eth src is 10:11:22:33:44:55 / vlan tci is 1 + testpmd> set raw_encap 4 eth src is 10:11:22:33:44:55 / vlan tci is 1 inner_type is 0x0800 / ipv4 / udp dst is 4789 / vxlan vni is 2 / end_set testpmd> flow create 0 egress pattern eth / ipv4 / end actions - raw_encap / end + raw_encap index 4 / end Sample Raw decapsulation rule ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- 2.20.1