* [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow @ 2018-05-09 16:56 Mohammad Abdul Awal 2018-05-10 12:47 ` Iremonger, Bernard 0 siblings, 1 reply; 3+ messages in thread From: Mohammad Abdul Awal @ 2018-05-09 16:56 UTC (permalink / raw) To: dev; +Cc: Mohammad Abdul Awal Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com> --- app/test-pmd/cmdline_flow.c | 872 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 5754e78..7d80f2a 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -237,6 +237,44 @@ enum index { ACTION_OF_POP_MPLS_ETHERTYPE, ACTION_OF_PUSH_MPLS, ACTION_OF_PUSH_MPLS_ETHERTYPE, + ACTION_VXLAN_ENCAP, + ACTION_VXLAN_ENCAP_ETH_DST, + ACTION_VXLAN_ENCAP_ETH_DST_VALUE, + ACTION_VXLAN_ENCAP_ETH_SRC, + ACTION_VXLAN_ENCAP_ETH_SRC_VALUE, + ACTION_VXLAN_ENCAP_ETH_TYPE, + ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE, + ACTION_VXLAN_ENCAP_IPV4_DST, + ACTION_VXLAN_ENCAP_IPV4_DST_VALUE, + ACTION_VXLAN_ENCAP_IPV4_SRC, + ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE, + ACTION_VXLAN_ENCAP_IPV4_PROTO, + ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE, + ACTION_VXLAN_ENCAP_UDP_SRC, + ACTION_VXLAN_ENCAP_UDP_SRC_VALUE, + ACTION_VXLAN_ENCAP_UDP_DST, + ACTION_VXLAN_ENCAP_UDP_DST_VALUE, + ACTION_VXLAN_ENCAP_VXLAN_VNI, + ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE, + ACTION_VXLAN_ENCAP_END, + ACTION_VXLAN_DECAP, + ACTION_NVGRE_ENCAP, + ACTION_NVGRE_ENCAP_ETH_DST, + ACTION_NVGRE_ENCAP_ETH_DST_VALUE, + ACTION_NVGRE_ENCAP_ETH_SRC, + ACTION_NVGRE_ENCAP_ETH_SRC_VALUE, + ACTION_NVGRE_ENCAP_ETH_TYPE, + ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE, + ACTION_NVGRE_ENCAP_IPV4_DST, + ACTION_NVGRE_ENCAP_IPV4_DST_VALUE, + ACTION_NVGRE_ENCAP_IPV4_SRC, + ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE, + ACTION_NVGRE_ENCAP_IPV4_PROTO, + ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE, + ACTION_NVGRE_ENCAP_NVGRE_VSNI, + ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE, + ACTION_NVGRE_ENCAP_END, + ACTION_NVGRE_DECAP, }; /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -256,6 +294,28 @@ struct action_rss_data { uint16_t queue[ACTION_RSS_QUEUE_NUM]; }; +#define ACTION_VXLAN_ENCAP_MAX_PATTERN 5 +#define ACTION_NVGRE_ENCAP_MAX_PATTERN 4 + +struct action_vxlan_encap_data { + struct rte_flow_action_vxlan_encap conf; + struct rte_flow_item pattern[ACTION_VXLAN_ENCAP_MAX_PATTERN]; + struct rte_flow_item_eth eth; + struct rte_flow_item_ipv4 ipv4; + struct rte_flow_item_udp udp; + struct rte_flow_item_vxlan vxlan; + uint32_t hdr_flags; +}; + +struct action_nvgre_encap_data { + struct rte_flow_action_nvgre_encap conf; + struct rte_flow_item pattern[ACTION_NVGRE_ENCAP_MAX_PATTERN]; + struct rte_flow_item_eth eth; + struct rte_flow_item_ipv4 ipv4; + struct rte_flow_item_nvgre nvgre; + uint32_t hdr_flags; +}; + /** Maximum number of subsequent tokens and arguments on the stack. */ #define CTX_STACK_SIZE 16 @@ -383,6 +443,13 @@ struct token { .size = (s), \ }) +#define ARGS_ENTRY_ARB_HTON(o, s) \ + (&(const struct arg){ \ + .hton = 1, \ + .offset = (o), \ + .size = (s), \ + }) + /** Same as ARGS_ENTRY_ARB() with bounded values. */ #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ (&(const struct arg){ \ @@ -773,6 +840,10 @@ static const enum index next_action[] = { ACTION_OF_SET_VLAN_PCP, ACTION_OF_POP_MPLS, ACTION_OF_PUSH_MPLS, + ACTION_VXLAN_ENCAP, + ACTION_VXLAN_DECAP, + ACTION_NVGRE_ENCAP, + ACTION_NVGRE_DECAP, ZERO, }; @@ -874,6 +945,44 @@ static const enum index action_jump[] = { ZERO, }; +static const enum index action_vxlan_encap[] = { + ACTION_VXLAN_ENCAP_ETH_DST, + ACTION_VXLAN_ENCAP_ETH_SRC, + ACTION_VXLAN_ENCAP_ETH_TYPE, + ACTION_VXLAN_ENCAP_IPV4_DST, + ACTION_VXLAN_ENCAP_IPV4_SRC, + ACTION_VXLAN_ENCAP_IPV4_PROTO, + ACTION_VXLAN_ENCAP_UDP_DST, + ACTION_VXLAN_ENCAP_UDP_SRC, + ACTION_VXLAN_ENCAP_VXLAN_VNI, + ACTION_VXLAN_ENCAP_END, + ACTION_NEXT, + ZERO, +}; + +static const enum index action_vxlan_decap[] = { + ACTION_NEXT, + ZERO, +}; + +static const enum index action_nvgre_encap[] = { + ACTION_NVGRE_ENCAP_ETH_DST, + ACTION_NVGRE_ENCAP_ETH_SRC, + ACTION_NVGRE_ENCAP_ETH_TYPE, + ACTION_NVGRE_ENCAP_IPV4_DST, + ACTION_NVGRE_ENCAP_IPV4_SRC, + ACTION_NVGRE_ENCAP_IPV4_PROTO, + ACTION_NVGRE_ENCAP_NVGRE_VSNI, + ACTION_NVGRE_ENCAP_END, + ACTION_NEXT, + ZERO, +}; + +static const enum index action_nvgre_decap[] = { + ACTION_NEXT, + ZERO, +}; + static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -896,6 +1005,42 @@ static int parse_vc_action_rss_type(struct context *, const struct token *, static int parse_vc_action_rss_queue(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_action_vxlan_encap(struct context *, const struct token *, + const char *, unsigned int, void *, + unsigned int); +static int parse_vc_action_vxlan_decap(struct context *, const struct token *, + const char *, unsigned int, void *, + unsigned int); +static int parse_vc_action_vxlan_encap_fields(struct context *, + const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_vc_action_vxlan_encap_fields_value(struct context *, + const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_vc_action_vxlan_encap_end(struct context *, + const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_vc_action_nvgre_encap(struct context *, const struct token *, + const char *, unsigned int, void *, + unsigned int); +static int parse_vc_action_nvgre_decap(struct context *, const struct token *, + const char *, unsigned int, void *, + unsigned int); +static int parse_vc_action_nvgre_encap_fields(struct context *, + const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_vc_action_nvgre_encap_fields_value(struct context *, + const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_vc_action_nvgre_encap_end(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); @@ -2362,6 +2507,256 @@ static const struct token token_list[] = { ethertype)), .call = parse_vc_conf, }, + [ACTION_VXLAN_ENCAP] = { + .name = "vxlan_encap", + .help = "encap flow with vxlan tunnel definition", + .priv = PRIV_ACTION(VXLAN_ENCAP, + sizeof(struct action_vxlan_encap_data)), + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST, + ACTION_VXLAN_ENCAP_ETH_SRC, + ACTION_VXLAN_ENCAP_ETH_TYPE, + ACTION_VXLAN_ENCAP_IPV4_DST, + ACTION_VXLAN_ENCAP_IPV4_SRC, + ACTION_VXLAN_ENCAP_IPV4_PROTO, + ACTION_VXLAN_ENCAP_UDP_DST, + ACTION_VXLAN_ENCAP_UDP_SRC, + ACTION_VXLAN_ENCAP_VXLAN_VNI, + ACTION_VXLAN_ENCAP_END)), + .call = parse_vc_action_vxlan_encap, + }, + [ACTION_VXLAN_DECAP] = { + .name = "vxlan_decap", + .help = "decap flow with vxlan tunnel definition", + .priv = PRIV_ACTION(VXLAN_DECAP, 0), + .next = NEXT(action_vxlan_decap), + .call = parse_vc_action_vxlan_decap, + }, + [ACTION_VXLAN_ENCAP_ETH_DST] = { + .name = "eth_dst", + .help = "destination MAC for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_ETH_DST_VALUE] = { + .name = "eth_dst_value", + .help = "destination MAC for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_ETH_SRC] = { + .name = "eth_src", + .help = "source MAC for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] = { + .name = "eth_src_value", + .help = "source MAC for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_ETH_TYPE] = { + .name = "eth_type", + .help = "eth type for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] = { + .name = "eth_type_value", + .help = "eth type for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_IPV4_DST] = { + .name = "ipv4_dst", + .help = "destination ipv4 IP for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] = { + .name = "ipv4_dst_value", + .help = "destination ipv4 IP for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_IPV4_SRC] = { + .name = "ipv4_src", + .help = "source ipv4 IP for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] = { + .name = "ipv4_src_value", + .help = "source ipv4 IP for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_IPV4_PROTO] = { + .name = "ipv4_proto", + .help = "ipv4 proto for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] = { + .name = "ipv4_proto_value", + .help = "ipv4 proto for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_UDP_DST] = { + .name = "udp_dst", + .help = "udp destination port for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_UDP_DST_VALUE] = { + .name = "udp_dst_value", + .help = "udp destination port for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_UDP_SRC] = { + .name = "udp_src", + .help = "udp source port for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] = { + .name = "udp_src_value", + .help = "udp source port for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_VXLAN_VNI] = { + .name = "vxlan_vni", + .help = "vxlan vni for vxlan tunnel", + .next = NEXT(action_vxlan_encap, + NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)), + .call = parse_vc_action_vxlan_encap_fields, + }, + [ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] = { + .name = "vxlan_vni_value", + .help = "vxlan vni for vxlan tunnel", + .call = parse_vc_action_vxlan_encap_fields_value, + }, + [ACTION_VXLAN_ENCAP_END] = { + .name = "end", + .help = "end of the pattern for vxlan encap", + .call = parse_vc_action_vxlan_encap_end, + }, + [ACTION_NVGRE_ENCAP] = { + .name = "nvgre_encap", + .help = "encap flow with nvgre tunnel definition", + .priv = PRIV_ACTION(NVGRE_ENCAP, + sizeof(struct action_nvgre_encap_data)), + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST, + ACTION_NVGRE_ENCAP_ETH_SRC, + ACTION_NVGRE_ENCAP_ETH_TYPE, + ACTION_NVGRE_ENCAP_IPV4_DST, + ACTION_NVGRE_ENCAP_IPV4_SRC, + ACTION_NVGRE_ENCAP_IPV4_PROTO, + ACTION_NVGRE_ENCAP_NVGRE_VSNI, + ACTION_NVGRE_ENCAP_END)), + .call = parse_vc_action_nvgre_encap, + }, + [ACTION_NVGRE_DECAP] = { + .name = "nvgre_decap", + .help = "decap flow with nvgre tunnel definition", + .priv = PRIV_ACTION(NVGRE_DECAP, 0), + .next = NEXT(action_nvgre_decap), + .call = parse_vc_action_nvgre_decap, + }, + [ACTION_NVGRE_ENCAP_ETH_DST] = { + .name = "eth_dst", + .help = "destination MAC for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_ETH_DST_VALUE] = { + .name = "eth_dst_value", + .help = "destination MAC for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_ETH_SRC] = { + .name = "eth_src", + .help = "source MAC for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] = { + .name = "eth_src_value", + .help = "source MAC for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_ETH_TYPE] = { + .name = "eth_type", + .help = "eth type for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] = { + .name = "eth_type_value", + .help = "eth type for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_IPV4_DST] = { + .name = "ipv4_dst", + .help = "destination ipv4 IP for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] = { + .name = "ipv4_dst_value", + .help = "destination ipv4 IP for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_IPV4_SRC] = { + .name = "ipv4_src", + .help = "source ipv4 IP for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] = { + .name = "ipv4_src_value", + .help = "source ipv4 IP for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_IPV4_PROTO] = { + .name = "ipv4_proto", + .help = "ipv4 proto for nvgre tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] = { + .name = "ipv4_proto_value", + .help = "ipv4 proto for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_NVGRE_VSNI] = { + .name = "nvgre_vsni", + .help = "nvgre vsni for NVGRE tunnel", + .next = NEXT(action_nvgre_encap, + NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)), + .call = parse_vc_action_nvgre_encap_fields, + }, + [ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] = { + .name = "nvgre_vsni_value", + .help = "nvgre vsni for nvgre tunnel", + .call = parse_vc_action_nvgre_encap_fields_value, + }, + [ACTION_NVGRE_ENCAP_END] = { + .name = "end", + .help = "end of the pattern for nvgre encap", + .call = parse_vc_action_nvgre_encap_end, + }, }; /** Remove and return last entry from argument stack. */ @@ -2924,6 +3319,482 @@ parse_vc_action_rss_queue(struct context *ctx, const struct token *token, return len; } +/** Parse VXLAN_ENCAP action. */ +static int +parse_vc_action_vxlan_encap(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_vxlan_encap_data *data; + 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; + /* Set up default configuration. */ + data = ctx->object; + data->conf.definition = data->pattern; + action->conf = &data->conf; + + return ret; +} + +/** Parse VXLAN_DECAP action. */ +static int +parse_vc_action_vxlan_decap(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + 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; + /* Point to selected object. */ + ctx->object = out->args.vc.data; + ctx->objmask = NULL; + return ret; +} + +static uint32_t get_proto_index_using_flag(uint32_t flag) +{ + uint32_t c = 0, i = 0; + uint32_t supported_ptypes[] = { + RTE_PTYPE_L2_ETHER, + RTE_PTYPE_L2_ETHER_VLAN, + RTE_PTYPE_L3_IPV4, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_TUNNEL_VXLAN, + RTE_PTYPE_TUNNEL_NVGRE + }; + + for (i = 0; i != RTE_DIM(supported_ptypes); i++) { + if (supported_ptypes[i] & flag) + c++; + } + c = (c > 0) ? (c - 1) : 0; + + return c; +} + +/** Parse VXLAN_ENCAP action pattern fields. */ +static int +parse_vc_action_vxlan_encap_fields(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_vxlan_encap_data *data; + uint32_t p_index; + + (void)buf; + (void)size; + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + if (!ctx->object) + return len; + switch (ctx->curr) { + case ACTION_VXLAN_ENCAP_ETH_DST: + case ACTION_VXLAN_ENCAP_ETH_SRC: + case ACTION_VXLAN_ENCAP_ETH_TYPE: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_L2_ETHER; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->eth; + data->pattern[p_index].mask = &rte_flow_item_eth_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; + break; + case ACTION_VXLAN_ENCAP_IPV4_DST: + case ACTION_VXLAN_ENCAP_IPV4_SRC: + case ACTION_VXLAN_ENCAP_IPV4_PROTO: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_L3_IPV4; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->ipv4; + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; + break; + case ACTION_VXLAN_ENCAP_UDP_DST: + case ACTION_VXLAN_ENCAP_UDP_SRC: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_L4_UDP; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->udp; + data->pattern[p_index].mask = &rte_flow_item_udp_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_UDP; + break; + case ACTION_VXLAN_ENCAP_VXLAN_VNI: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_TUNNEL_VXLAN; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->vxlan; + data->pattern[p_index].mask = &rte_flow_item_vxlan_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VXLAN; + break; + default: + return -1; + } + + return len; +} + +/** Parse VXLAN_ENCAP action pattern fields value. */ +static int +parse_vc_action_vxlan_encap_fields_value(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_vxlan_encap_data *data; + struct ether_addr mac; + char str2[len + 1]; + struct in_addr ip4; + uint16_t val1; + uint32_t val2; + int ret; + + (void)token; + (void)buf; + if (!ctx->object) + return len; + data = ctx->object; + switch (ctx->curr) { + case ACTION_VXLAN_ENCAP_ETH_DST_VALUE: + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); + if (ret < 0 || (unsigned int)ret != len) + return -1; + memcpy(&data->eth.dst, &mac, sizeof(mac)); + break; + case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE: + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); + if (ret < 0 || (unsigned int)ret != len) + return -1; + memcpy(&data->eth.src, &mac, sizeof(mac)); + break; + case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->eth.type = htons(val1); + break; + case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + ret = inet_pton(AF_INET, str2, &ip4); + if (ret != 1) + return -1; + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); + break; + case ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + ret = inet_pton(AF_INET, str2, &ip4); + if (ret != 1) + return -1; + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); + break; + case ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->ipv4.hdr.next_proto_id = val1; + break; + case ACTION_VXLAN_ENCAP_UDP_DST_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->udp.hdr.dst_port = htons(val1); + break; + case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->udp.hdr.src_port = htons(val1); + break; + case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val2 = strtoul(str2, NULL, 0); + if (val2 == 0) + return -1; + data->vxlan.vni[0] = (uint8_t)((val2 >> 16) & 0xff); + data->vxlan.vni[1] = (uint8_t)((val2 >> 8) & 0xff); + data->vxlan.vni[2] = (uint8_t)(val2 & 0xff); + break; + default: + return -1; + } + + return len; +} + +/** Parse VXLAN_ENCAP action pattern end. */ +static int +parse_vc_action_vxlan_encap_end(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_vxlan_encap_data *data; + uint32_t p_index; + + (void)buf; + (void)size; + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + if (ctx->curr != ACTION_VXLAN_ENCAP_END) + return -1; + if (!ctx->object) + return len; + data = ctx->object; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; + + return len; +} + +/** Parse NVGRE_ENCAP action. */ +static int +parse_vc_action_nvgre_encap(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_nvgre_encap_data *data; + 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; + /* Set up default configuration. */ + data = ctx->object; + data->conf.definition = data->pattern; + action->conf = &data->conf; + + return ret; +} + +/** Parse NVGRE_DECAP action. */ +static int +parse_vc_action_nvgre_decap(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + 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; + /* Point to selected object. */ + ctx->object = out->args.vc.data; + ctx->objmask = NULL; + return ret; +} + +/** Parse NVGRE_ENCAP action pattern fields. */ +static int +parse_vc_action_nvgre_encap_fields(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_nvgre_encap_data *data; + uint32_t p_index; + + (void)buf; + (void)size; + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + if (!ctx->object) + return len; + switch (ctx->curr) { + case ACTION_NVGRE_ENCAP_ETH_DST: + case ACTION_NVGRE_ENCAP_ETH_SRC: + case ACTION_NVGRE_ENCAP_ETH_TYPE: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_L2_ETHER; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->eth; + data->pattern[p_index].mask = &rte_flow_item_eth_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; + break; + case ACTION_NVGRE_ENCAP_IPV4_DST: + case ACTION_NVGRE_ENCAP_IPV4_SRC: + case ACTION_NVGRE_ENCAP_IPV4_PROTO: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_L3_IPV4; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->ipv4; + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; + break; + case ACTION_NVGRE_ENCAP_NVGRE_VSNI: + data = ctx->object; + data->hdr_flags |= RTE_PTYPE_TUNNEL_NVGRE; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index].spec = &data->nvgre; + data->pattern[p_index].mask = &rte_flow_item_nvgre_mask; + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_NVGRE; + break; + default: + return -1; + } + + return len; +} + +/** Parse NVGRE_ENCAP action pattern fields value. */ +static int +parse_vc_action_nvgre_encap_fields_value(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_nvgre_encap_data *data; + struct ether_addr mac; + char str2[len + 1]; + struct in_addr ip4; + uint16_t val1; + uint32_t val2; + int ret; + + (void)token; + (void)buf; + if (!ctx->object) + return len; + data = ctx->object; + switch (ctx->curr) { + case ACTION_NVGRE_ENCAP_ETH_DST_VALUE: + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); + if (ret < 0 || (unsigned int)ret != len) + return -1; + memcpy(&data->eth.dst, &mac, sizeof(mac)); + break; + case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE: + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); + if (ret < 0 || (unsigned int)ret != len) + return -1; + memcpy(&data->eth.src, &mac, sizeof(mac)); + break; + case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->eth.type = htons(val1); + break; + case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + ret = inet_pton(AF_INET, str2, &ip4); + if (ret != 1) + return -1; + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); + break; + case ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + ret = inet_pton(AF_INET, str2, &ip4); + if (ret != 1) + return -1; + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); + break; + case ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val1 = strtoul(str2, NULL, 0); + if (val1 == 0) + return -1; + data->ipv4.hdr.next_proto_id = val1; + break; + case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE: + memcpy(str2, str, len); + str2[len] = '\0'; + val2 = strtoul(str2, NULL, 0); + if (val2 == 0) + return -1; + data->nvgre.tni[0] = (uint8_t)((val2 >> 16) & 0xff); + data->nvgre.tni[1] = (uint8_t)((val2 >> 8) & 0xff); + data->nvgre.tni[2] = (uint8_t)(val2 & 0xff); + break; + default: + return -1; + } + + return len; +} + +/** Parse NVGRE_ENCAP action pattern end. */ +static int +parse_vc_action_nvgre_encap_end(struct context *ctx, + const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct action_nvgre_encap_data *data; + uint32_t p_index; + + (void)buf; + (void)size; + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + if (ctx->curr != ACTION_NVGRE_ENCAP_END) + return -1; + if (!ctx->object) + return len; + data = ctx->object; + p_index = get_proto_index_using_flag(data->hdr_flags); + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; + + return len; +} + /** Parse tokens for destroy command. */ static int parse_destroy(struct context *ctx, const struct token *token, @@ -2961,6 +3832,7 @@ parse_destroy(struct context *ctx, const struct token *token, return len; } + /** Parse tokens for flush command. */ static int parse_flush(struct context *ctx, const struct token *token, -- 2.7.4 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow 2018-05-09 16:56 [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow Mohammad Abdul Awal @ 2018-05-10 12:47 ` Iremonger, Bernard 2018-05-11 10:45 ` Mohammad Abdul Awal 0 siblings, 1 reply; 3+ messages in thread From: Iremonger, Bernard @ 2018-05-10 12:47 UTC (permalink / raw) To: Awal, Mohammad Abdul, dev, Adrien Mazarguil; +Cc: Awal, Mohammad Abdul Hi Awal, > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mohammad Abdul > Awal > Sent: Wednesday, May 9, 2018 5:57 PM > To: dev@dpdk.org > Cc: Awal, Mohammad Abdul <mohammad.abdul.awal@intel.com> > Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap > support for rte_flow The commit message should not be empty, it should contain a description of the changes > > Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com> > --- > app/test-pmd/cmdline_flow.c | 872 > ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 872 insertions(+) > > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index > 5754e78..7d80f2a 100644 > --- a/app/test-pmd/cmdline_flow.c > +++ b/app/test-pmd/cmdline_flow.c > @@ -237,6 +237,44 @@ enum index { > ACTION_OF_POP_MPLS_ETHERTYPE, > ACTION_OF_PUSH_MPLS, > ACTION_OF_PUSH_MPLS_ETHERTYPE, > + ACTION_VXLAN_ENCAP, > + ACTION_VXLAN_ENCAP_ETH_DST, > + ACTION_VXLAN_ENCAP_ETH_DST_VALUE, > + ACTION_VXLAN_ENCAP_ETH_SRC, > + ACTION_VXLAN_ENCAP_ETH_SRC_VALUE, > + ACTION_VXLAN_ENCAP_ETH_TYPE, > + ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE, > + ACTION_VXLAN_ENCAP_IPV4_DST, > + ACTION_VXLAN_ENCAP_IPV4_DST_VALUE, > + ACTION_VXLAN_ENCAP_IPV4_SRC, > + ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE, > + ACTION_VXLAN_ENCAP_IPV4_PROTO, > + ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE, > + ACTION_VXLAN_ENCAP_UDP_SRC, > + ACTION_VXLAN_ENCAP_UDP_SRC_VALUE, > + ACTION_VXLAN_ENCAP_UDP_DST, > + ACTION_VXLAN_ENCAP_UDP_DST_VALUE, > + ACTION_VXLAN_ENCAP_VXLAN_VNI, > + ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE, > + ACTION_VXLAN_ENCAP_END, Is ACTION_VXLAN_ENCAP_END necessary, could ACTION_END be used instead? > + ACTION_VXLAN_DECAP, > + ACTION_NVGRE_ENCAP, > + ACTION_NVGRE_ENCAP_ETH_DST, > + ACTION_NVGRE_ENCAP_ETH_DST_VALUE, > + ACTION_NVGRE_ENCAP_ETH_SRC, > + ACTION_NVGRE_ENCAP_ETH_SRC_VALUE, > + ACTION_NVGRE_ENCAP_ETH_TYPE, > + ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE, > + ACTION_NVGRE_ENCAP_IPV4_DST, > + ACTION_NVGRE_ENCAP_IPV4_DST_VALUE, > + ACTION_NVGRE_ENCAP_IPV4_SRC, > + ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE, > + ACTION_NVGRE_ENCAP_IPV4_PROTO, > + ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE, > + ACTION_NVGRE_ENCAP_NVGRE_VSNI, > + ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE, > + ACTION_NVGRE_ENCAP_END, Is ACTION_NVGRE_ENCAP_END necessary, could ACTION_END be used instead? > + ACTION_NVGRE_DECAP, > }; > > /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -256,6 > +294,28 @@ struct action_rss_data { > uint16_t queue[ACTION_RSS_QUEUE_NUM]; > }; > > +#define ACTION_VXLAN_ENCAP_MAX_PATTERN 5 #define > +ACTION_NVGRE_ENCAP_MAX_PATTERN 4 > + > +struct action_vxlan_encap_data { > + struct rte_flow_action_vxlan_encap conf; > + struct rte_flow_item pattern[ACTION_VXLAN_ENCAP_MAX_PATTERN]; > + struct rte_flow_item_eth eth; > + struct rte_flow_item_ipv4 ipv4; > + struct rte_flow_item_udp udp; > + struct rte_flow_item_vxlan vxlan; > + uint32_t hdr_flags; > +}; > + > +struct action_nvgre_encap_data { > + struct rte_flow_action_nvgre_encap conf; > + struct rte_flow_item pattern[ACTION_NVGRE_ENCAP_MAX_PATTERN]; > + struct rte_flow_item_eth eth; > + struct rte_flow_item_ipv4 ipv4; > + struct rte_flow_item_nvgre nvgre; > + uint32_t hdr_flags; > +}; > + > /** Maximum number of subsequent tokens and arguments on the stack. */ > #define CTX_STACK_SIZE 16 > > @@ -383,6 +443,13 @@ struct token { > .size = (s), \ > }) > > +#define ARGS_ENTRY_ARB_HTON(o, s) \ > + (&(const struct arg){ \ > + .hton = 1, \ > + .offset = (o), \ > + .size = (s), \ > + }) > + > /** Same as ARGS_ENTRY_ARB() with bounded values. */ #define > ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ > (&(const struct arg){ \ > @@ -773,6 +840,10 @@ static const enum index next_action[] = { > ACTION_OF_SET_VLAN_PCP, > ACTION_OF_POP_MPLS, > ACTION_OF_PUSH_MPLS, > + ACTION_VXLAN_ENCAP, > + ACTION_VXLAN_DECAP, > + ACTION_NVGRE_ENCAP, > + ACTION_NVGRE_DECAP, > ZERO, > }; > > @@ -874,6 +945,44 @@ static const enum index action_jump[] = { > ZERO, > }; > > +static const enum index action_vxlan_encap[] = { > + ACTION_VXLAN_ENCAP_ETH_DST, > + ACTION_VXLAN_ENCAP_ETH_SRC, > + ACTION_VXLAN_ENCAP_ETH_TYPE, > + ACTION_VXLAN_ENCAP_IPV4_DST, > + ACTION_VXLAN_ENCAP_IPV4_SRC, > + ACTION_VXLAN_ENCAP_IPV4_PROTO, > + ACTION_VXLAN_ENCAP_UDP_DST, > + ACTION_VXLAN_ENCAP_UDP_SRC, > + ACTION_VXLAN_ENCAP_VXLAN_VNI, > + ACTION_VXLAN_ENCAP_END, > + ACTION_NEXT, > + ZERO, > +}; > + > +static const enum index action_vxlan_decap[] = { > + ACTION_NEXT, > + ZERO, > +}; > + > +static const enum index action_nvgre_encap[] = { > + ACTION_NVGRE_ENCAP_ETH_DST, > + ACTION_NVGRE_ENCAP_ETH_SRC, > + ACTION_NVGRE_ENCAP_ETH_TYPE, > + ACTION_NVGRE_ENCAP_IPV4_DST, > + ACTION_NVGRE_ENCAP_IPV4_SRC, > + ACTION_NVGRE_ENCAP_IPV4_PROTO, > + ACTION_NVGRE_ENCAP_NVGRE_VSNI, > + ACTION_NVGRE_ENCAP_END, > + ACTION_NEXT, > + ZERO, > +}; > + > +static const enum index action_nvgre_decap[] = { > + ACTION_NEXT, > + ZERO, > +}; > + > static int parse_init(struct context *, const struct token *, > const char *, unsigned int, > void *, unsigned int); > @@ -896,6 +1005,42 @@ static int parse_vc_action_rss_type(struct context *, > const struct token *, static int parse_vc_action_rss_queue(struct context *, > const struct token *, > const char *, unsigned int, void *, > unsigned int); > +static int parse_vc_action_vxlan_encap(struct context *, const struct token *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_vxlan_decap(struct context *, const struct token *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_vxlan_encap_fields(struct context *, > + const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > +static int parse_vc_action_vxlan_encap_fields_value(struct context *, > + const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > +static int parse_vc_action_vxlan_encap_end(struct context *, > + const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > +static int parse_vc_action_nvgre_encap(struct context *, const struct token *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_nvgre_decap(struct context *, const struct token *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_nvgre_encap_fields(struct context *, > + const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > +static int parse_vc_action_nvgre_encap_fields_value(struct context *, > + const struct token *, > + const char *, unsigned int, > + void *, unsigned int); > +static int parse_vc_action_nvgre_encap_end(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); > @@ -2362,6 +2507,256 @@ static const struct token token_list[] = { > ethertype)), > .call = parse_vc_conf, > }, > + [ACTION_VXLAN_ENCAP] = { > + .name = "vxlan_encap", > + .help = "encap flow with vxlan tunnel definition", > + .priv = PRIV_ACTION(VXLAN_ENCAP, > + sizeof(struct action_vxlan_encap_data)), > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST, > + ACTION_VXLAN_ENCAP_ETH_SRC, > + ACTION_VXLAN_ENCAP_ETH_TYPE, > + ACTION_VXLAN_ENCAP_IPV4_DST, > + ACTION_VXLAN_ENCAP_IPV4_SRC, > + ACTION_VXLAN_ENCAP_IPV4_PROTO, > + ACTION_VXLAN_ENCAP_UDP_DST, > + ACTION_VXLAN_ENCAP_UDP_SRC, > + ACTION_VXLAN_ENCAP_VXLAN_VNI, > + ACTION_VXLAN_ENCAP_END)), > + .call = parse_vc_action_vxlan_encap, > + }, > + [ACTION_VXLAN_DECAP] = { > + .name = "vxlan_decap", > + .help = "decap flow with vxlan tunnel definition", > + .priv = PRIV_ACTION(VXLAN_DECAP, 0), > + .next = NEXT(action_vxlan_decap), > + .call = parse_vc_action_vxlan_decap, > + }, > + [ACTION_VXLAN_ENCAP_ETH_DST] = { > + .name = "eth_dst", > + .help = "destination MAC for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_DST_VALUE] = { > + .name = "eth_dst_value", > + .help = "destination MAC for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_ETH_SRC] = { > + .name = "eth_src", > + .help = "source MAC for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] = { > + .name = "eth_src_value", > + .help = "source MAC for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_ETH_TYPE] = { > + .name = "eth_type", > + .help = "eth type for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] = { > + .name = "eth_type_value", > + .help = "eth type for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_DST] = { > + .name = "ipv4_dst", > + .help = "destination ipv4 IP for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] = { > + .name = "ipv4_dst_value", > + .help = "destination ipv4 IP for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_SRC] = { > + .name = "ipv4_src", > + .help = "source ipv4 IP for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] = { > + .name = "ipv4_src_value", > + .help = "source ipv4 IP for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_PROTO] = { > + .name = "ipv4_proto", > + .help = "ipv4 proto for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] = { > + .name = "ipv4_proto_value", > + .help = "ipv4 proto for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_UDP_DST] = { > + .name = "udp_dst", > + .help = "udp destination port for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_UDP_DST_VALUE] = { > + .name = "udp_dst_value", > + .help = "udp destination port for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_UDP_SRC] = { > + .name = "udp_src", > + .help = "udp source port for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] = { > + .name = "udp_src_value", > + .help = "udp source port for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_VXLAN_VNI] = { > + .name = "vxlan_vni", > + .help = "vxlan vni for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] = { > + .name = "vxlan_vni_value", > + .help = "vxlan vni for vxlan tunnel", > + .call = parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_END] = { > + .name = "end", > + .help = "end of the pattern for vxlan encap", > + .call = parse_vc_action_vxlan_encap_end, "end" only is being parsed, could ACTION_END be used instead? > + }, > + [ACTION_NVGRE_ENCAP] = { > + .name = "nvgre_encap", > + .help = "encap flow with nvgre tunnel definition", > + .priv = PRIV_ACTION(NVGRE_ENCAP, > + sizeof(struct action_nvgre_encap_data)), > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST, > + ACTION_NVGRE_ENCAP_ETH_SRC, > + ACTION_NVGRE_ENCAP_ETH_TYPE, > + ACTION_NVGRE_ENCAP_IPV4_DST, > + ACTION_NVGRE_ENCAP_IPV4_SRC, > + ACTION_NVGRE_ENCAP_IPV4_PROTO, > + ACTION_NVGRE_ENCAP_NVGRE_VSNI, > + ACTION_NVGRE_ENCAP_END)), > + .call = parse_vc_action_nvgre_encap, > + }, > + [ACTION_NVGRE_DECAP] = { > + .name = "nvgre_decap", > + .help = "decap flow with nvgre tunnel definition", > + .priv = PRIV_ACTION(NVGRE_DECAP, 0), > + .next = NEXT(action_nvgre_decap), > + .call = parse_vc_action_nvgre_decap, > + }, > + [ACTION_NVGRE_ENCAP_ETH_DST] = { > + .name = "eth_dst", > + .help = "destination MAC for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_DST_VALUE] = { > + .name = "eth_dst_value", > + .help = "destination MAC for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_ETH_SRC] = { > + .name = "eth_src", > + .help = "source MAC for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] = { > + .name = "eth_src_value", > + .help = "source MAC for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_ETH_TYPE] = { > + .name = "eth_type", > + .help = "eth type for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] = { > + .name = "eth_type_value", > + .help = "eth type for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_DST] = { > + .name = "ipv4_dst", > + .help = "destination ipv4 IP for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] = { > + .name = "ipv4_dst_value", > + .help = "destination ipv4 IP for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_SRC] = { > + .name = "ipv4_src", > + .help = "source ipv4 IP for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] = { > + .name = "ipv4_src_value", > + .help = "source ipv4 IP for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_PROTO] = { > + .name = "ipv4_proto", > + .help = "ipv4 proto for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] = { > + .name = "ipv4_proto_value", > + .help = "ipv4 proto for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_NVGRE_VSNI] = { > + .name = "nvgre_vsni", > + .help = "nvgre vsni for NVGRE tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] = { > + .name = "nvgre_vsni_value", > + .help = "nvgre vsni for nvgre tunnel", > + .call = parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_END] = { > + .name = "end", > + .help = "end of the pattern for nvgre encap", > + .call = parse_vc_action_nvgre_encap_end, "end" only is being parsed, could ACTION_END be used instead? > + }, > }; > > /** Remove and return last entry from argument stack. */ @@ -2924,6 > +3319,482 @@ parse_vc_action_rss_queue(struct context *ctx, const struct > token *token, > return len; > } > > +/** Parse VXLAN_ENCAP action. */ > +static int > +parse_vc_action_vxlan_encap(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_vxlan_encap_data *data; > + 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; > + /* Set up default configuration. */ > + data = ctx->object; > + data->conf.definition = data->pattern; > + action->conf = &data->conf; > + > + return ret; > +} > + > +/** Parse VXLAN_DECAP action. */ > +static int > +parse_vc_action_vxlan_decap(struct context *ctx, const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out = buf; > + 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; > + /* Point to selected object. */ > + ctx->object = out->args.vc.data; > + ctx->objmask = NULL; > + return ret; > +} > + > +static uint32_t get_proto_index_using_flag(uint32_t flag) { > + uint32_t c = 0, i = 0; > + uint32_t supported_ptypes[] = { > + RTE_PTYPE_L2_ETHER, > + RTE_PTYPE_L2_ETHER_VLAN, > + RTE_PTYPE_L3_IPV4, > + RTE_PTYPE_L4_UDP, > + RTE_PTYPE_TUNNEL_VXLAN, > + RTE_PTYPE_TUNNEL_NVGRE > + }; > + > + for (i = 0; i != RTE_DIM(supported_ptypes); i++) { > + if (supported_ptypes[i] & flag) > + c++; > + } > + c = (c > 0) ? (c - 1) : 0; > + > + return c; > +} > + > +/** Parse VXLAN_ENCAP action pattern fields. */ static int > +parse_vc_action_vxlan_encap_fields(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct action_vxlan_encap_data *data; > + uint32_t p_index; > + > + (void)buf; > + (void)size; > + /* Token name must match. */ > + if (parse_default(ctx, token, str, len, NULL, 0) < 0) > + return -1; > + if (!ctx->object) > + return len; > + switch (ctx->curr) { > + case ACTION_VXLAN_ENCAP_ETH_DST: > + case ACTION_VXLAN_ENCAP_ETH_SRC: > + case ACTION_VXLAN_ENCAP_ETH_TYPE: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L2_ETHER; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->eth; > + data->pattern[p_index].mask = &rte_flow_item_eth_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; > + break; > + case ACTION_VXLAN_ENCAP_IPV4_DST: > + case ACTION_VXLAN_ENCAP_IPV4_SRC: > + case ACTION_VXLAN_ENCAP_IPV4_PROTO: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L3_IPV4; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->ipv4; > + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; > + break; > + case ACTION_VXLAN_ENCAP_UDP_DST: > + case ACTION_VXLAN_ENCAP_UDP_SRC: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L4_UDP; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->udp; > + data->pattern[p_index].mask = &rte_flow_item_udp_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_UDP; > + break; > + case ACTION_VXLAN_ENCAP_VXLAN_VNI: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_TUNNEL_VXLAN; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->vxlan; > + data->pattern[p_index].mask = &rte_flow_item_vxlan_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VXLAN; > + break; > + default: > + return -1; > + } > + > + return len; > +} > + > +/** Parse VXLAN_ENCAP action pattern fields value. */ static int > +parse_vc_action_vxlan_encap_fields_value(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct action_vxlan_encap_data *data; > + struct ether_addr mac; > + char str2[len + 1]; > + struct in_addr ip4; > + uint16_t val1; > + uint32_t val2; > + int ret; > + > + (void)token; > + (void)buf; > + if (!ctx->object) > + return len; > + data = ctx->object; > + switch (ctx->curr) { > + case ACTION_VXLAN_ENCAP_ETH_DST_VALUE: > + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret != len) > + return -1; > + memcpy(&data->eth.dst, &mac, sizeof(mac)); > + break; > + case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE: > + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret != len) > + return -1; > + memcpy(&data->eth.src, &mac, sizeof(mac)); > + break; > + case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->eth.type = htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + ret = inet_pton(AF_INET, str2, &ip4); > + if (ret != 1) > + return -1; > + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); > + break; > + case ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + ret = inet_pton(AF_INET, str2, &ip4); > + if (ret != 1) > + return -1; > + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); > + break; > + case ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->ipv4.hdr.next_proto_id = val1; > + break; > + case ACTION_VXLAN_ENCAP_UDP_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->udp.hdr.dst_port = htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->udp.hdr.src_port = htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val2 = strtoul(str2, NULL, 0); > + if (val2 == 0) > + return -1; > + data->vxlan.vni[0] = (uint8_t)((val2 >> 16) & 0xff); > + data->vxlan.vni[1] = (uint8_t)((val2 >> 8) & 0xff); > + data->vxlan.vni[2] = (uint8_t)(val2 & 0xff); > + break; > + default: > + return -1; > + } > + > + return len; > +} > + > +/** Parse VXLAN_ENCAP action pattern end. */ static int > +parse_vc_action_vxlan_encap_end(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ This function should not be necessary if ACTION_END be used instead? > + struct action_vxlan_encap_data *data; > + uint32_t p_index; > + > + (void)buf; > + (void)size; > + /* Token name must match. */ > + if (parse_default(ctx, token, str, len, NULL, 0) < 0) > + return -1; > + if (ctx->curr != ACTION_VXLAN_ENCAP_END) > + return -1; > + if (!ctx->object) > + return len; > + data = ctx->object; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; > + > + return len; > +} > + > +/** Parse NVGRE_ENCAP action. */ > +static int > +parse_vc_action_nvgre_encap(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_nvgre_encap_data *data; > + 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; > + /* Set up default configuration. */ > + data = ctx->object; > + data->conf.definition = data->pattern; > + action->conf = &data->conf; > + > + return ret; > +} > + > +/** Parse NVGRE_DECAP action. */ > +static int > +parse_vc_action_nvgre_decap(struct context *ctx, const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out = buf; > + 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; > + /* Point to selected object. */ > + ctx->object = out->args.vc.data; > + ctx->objmask = NULL; > + return ret; > +} > + > +/** Parse NVGRE_ENCAP action pattern fields. */ static int > +parse_vc_action_nvgre_encap_fields(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct action_nvgre_encap_data *data; > + uint32_t p_index; > + > + (void)buf; > + (void)size; > + /* Token name must match. */ > + if (parse_default(ctx, token, str, len, NULL, 0) < 0) > + return -1; > + if (!ctx->object) > + return len; > + switch (ctx->curr) { > + case ACTION_NVGRE_ENCAP_ETH_DST: > + case ACTION_NVGRE_ENCAP_ETH_SRC: > + case ACTION_NVGRE_ENCAP_ETH_TYPE: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L2_ETHER; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->eth; > + data->pattern[p_index].mask = &rte_flow_item_eth_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; > + break; > + case ACTION_NVGRE_ENCAP_IPV4_DST: > + case ACTION_NVGRE_ENCAP_IPV4_SRC: > + case ACTION_NVGRE_ENCAP_IPV4_PROTO: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L3_IPV4; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->ipv4; > + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; > + break; > + case ACTION_NVGRE_ENCAP_NVGRE_VSNI: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_TUNNEL_NVGRE; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->nvgre; > + data->pattern[p_index].mask = &rte_flow_item_nvgre_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_NVGRE; > + break; > + default: > + return -1; > + } > + > + return len; > +} > + > +/** Parse NVGRE_ENCAP action pattern fields value. */ static int > +parse_vc_action_nvgre_encap_fields_value(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct action_nvgre_encap_data *data; > + struct ether_addr mac; > + char str2[len + 1]; > + struct in_addr ip4; > + uint16_t val1; > + uint32_t val2; > + int ret; > + > + (void)token; > + (void)buf; > + if (!ctx->object) > + return len; > + data = ctx->object; > + switch (ctx->curr) { > + case ACTION_NVGRE_ENCAP_ETH_DST_VALUE: > + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret != len) > + return -1; > + memcpy(&data->eth.dst, &mac, sizeof(mac)); > + break; > + case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE: > + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret != len) > + return -1; > + memcpy(&data->eth.src, &mac, sizeof(mac)); > + break; > + case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->eth.type = htons(val1); > + break; > + case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + ret = inet_pton(AF_INET, str2, &ip4); > + if (ret != 1) > + return -1; > + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); > + break; > + case ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + ret = inet_pton(AF_INET, str2, &ip4); > + if (ret != 1) > + return -1; > + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); > + break; > + case ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->ipv4.hdr.next_proto_id = val1; > + break; > + case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val2 = strtoul(str2, NULL, 0); > + if (val2 == 0) > + return -1; > + data->nvgre.tni[0] = (uint8_t)((val2 >> 16) & 0xff); > + data->nvgre.tni[1] = (uint8_t)((val2 >> 8) & 0xff); > + data->nvgre.tni[2] = (uint8_t)(val2 & 0xff); > + break; > + default: > + return -1; > + } > + > + return len; > +} > + > +/** Parse NVGRE_ENCAP action pattern end. */ static int > +parse_vc_action_nvgre_encap_end(struct context *ctx, > + const struct token *token, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ This function should not be necessary if ACTION_END be used instead? > + struct action_nvgre_encap_data *data; > + uint32_t p_index; > + > + (void)buf; > + (void)size; > + /* Token name must match. */ > + if (parse_default(ctx, token, str, len, NULL, 0) < 0) > + return -1; > + if (ctx->curr != ACTION_NVGRE_ENCAP_END) > + return -1; > + if (!ctx->object) > + return len; > + data = ctx->object; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; > + > + return len; > +} > + > /** Parse tokens for destroy command. */ static int parse_destroy(struct > context *ctx, const struct token *token, @@ -2961,6 +3832,7 @@ > parse_destroy(struct context *ctx, const struct token *token, > return len; > } > > + Extra blank line should be removed. > /** Parse tokens for flush command. */ > static int > parse_flush(struct context *ctx, const struct token *token, > -- > 2.7.4 In the Testpmd Application/User Guide, there is section 4.12. Flow rules management. dpdk/build/doc/html/guides/testpmd_app_ug/index.html As the encap and decap flows are fairly complex, It might be worth adding sections on Sample Encap flow rules and Sample Decap flow rules. Regards, Bernard. ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow 2018-05-10 12:47 ` Iremonger, Bernard @ 2018-05-11 10:45 ` Mohammad Abdul Awal 0 siblings, 0 replies; 3+ messages in thread From: Mohammad Abdul Awal @ 2018-05-11 10:45 UTC (permalink / raw) To: Iremonger, Bernard, dev, Adrien Mazarguil Hi Bernard, On 10/05/2018 13:47, Iremonger, Bernard wrote: > Hi Awal, > >> -----Original Message----- >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mohammad Abdul >> Awal >> Sent: Wednesday, May 9, 2018 5:57 PM >> To: dev@dpdk.org >> Cc: Awal, Mohammad Abdul <mohammad.abdul.awal@intel.com> >> Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap >> support for rte_flow > The commit message should not be empty, it should contain a description of the changes I will add some message here. > >> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com> >> --- >> app/test-pmd/cmdline_flow.c | 872 >> ++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 872 insertions(+) >> >> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index >> 5754e78..7d80f2a 100644 >> --- a/app/test-pmd/cmdline_flow.c >> +++ b/app/test-pmd/cmdline_flow.c >> @@ -237,6 +237,44 @@ enum index { >> ACTION_OF_POP_MPLS_ETHERTYPE, >> ACTION_OF_PUSH_MPLS, >> ACTION_OF_PUSH_MPLS_ETHERTYPE, >> + ACTION_VXLAN_ENCAP, >> + ACTION_VXLAN_ENCAP_ETH_DST, >> + ACTION_VXLAN_ENCAP_ETH_DST_VALUE, >> + ACTION_VXLAN_ENCAP_ETH_SRC, >> + ACTION_VXLAN_ENCAP_ETH_SRC_VALUE, >> + ACTION_VXLAN_ENCAP_ETH_TYPE, >> + ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE, >> + ACTION_VXLAN_ENCAP_IPV4_DST, >> + ACTION_VXLAN_ENCAP_IPV4_DST_VALUE, >> + ACTION_VXLAN_ENCAP_IPV4_SRC, >> + ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE, >> + ACTION_VXLAN_ENCAP_IPV4_PROTO, >> + ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE, >> + ACTION_VXLAN_ENCAP_UDP_SRC, >> + ACTION_VXLAN_ENCAP_UDP_SRC_VALUE, >> + ACTION_VXLAN_ENCAP_UDP_DST, >> + ACTION_VXLAN_ENCAP_UDP_DST_VALUE, >> + ACTION_VXLAN_ENCAP_VXLAN_VNI, >> + ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE, >> + ACTION_VXLAN_ENCAP_END, > Is ACTION_VXLAN_ENCAP_END necessary, could ACTION_END be used instead? Actually, ACTION_VXLAN_ENCAP_END is different than ACTION_END. ACTION_END creates the RTE_FLOW_ACTION_TYPE_END. On the other hand, ACTION_VXLAN_ENCAP_END created RTE_FLOW_ITEM_TYPE_END at the end pf patterns in the encap definition which is pattern of items end by item_end. So, to treat the two situations separately we need ACTION_VXLAN_ENCAP_END, unless there is a clever way present. > >> + ACTION_VXLAN_DECAP, >> + ACTION_NVGRE_ENCAP, >> + ACTION_NVGRE_ENCAP_ETH_DST, >> + ACTION_NVGRE_ENCAP_ETH_DST_VALUE, >> + ACTION_NVGRE_ENCAP_ETH_SRC, >> + ACTION_NVGRE_ENCAP_ETH_SRC_VALUE, >> + ACTION_NVGRE_ENCAP_ETH_TYPE, >> + ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE, >> + ACTION_NVGRE_ENCAP_IPV4_DST, >> + ACTION_NVGRE_ENCAP_IPV4_DST_VALUE, >> + ACTION_NVGRE_ENCAP_IPV4_SRC, >> + ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE, >> + ACTION_NVGRE_ENCAP_IPV4_PROTO, >> + ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE, >> + ACTION_NVGRE_ENCAP_NVGRE_VSNI, >> + ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE, >> + ACTION_NVGRE_ENCAP_END, > Is ACTION_NVGRE_ENCAP_END necessary, could ACTION_END be used instead? Please see my related comment above. > >> + ACTION_NVGRE_DECAP, >> }; >> >> /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -256,6 >> +294,28 @@ struct action_rss_data { >> uint16_t queue[ACTION_RSS_QUEUE_NUM]; >> }; >> >> +#define ACTION_VXLAN_ENCAP_MAX_PATTERN 5 #define >> +ACTION_NVGRE_ENCAP_MAX_PATTERN 4 >> + >> +struct action_vxlan_encap_data { >> + struct rte_flow_action_vxlan_encap conf; >> + struct rte_flow_item pattern[ACTION_VXLAN_ENCAP_MAX_PATTERN]; >> + struct rte_flow_item_eth eth; >> + struct rte_flow_item_ipv4 ipv4; >> + struct rte_flow_item_udp udp; >> + struct rte_flow_item_vxlan vxlan; >> + uint32_t hdr_flags; >> +}; >> + >> +struct action_nvgre_encap_data { >> + struct rte_flow_action_nvgre_encap conf; >> + struct rte_flow_item pattern[ACTION_NVGRE_ENCAP_MAX_PATTERN]; >> + struct rte_flow_item_eth eth; >> + struct rte_flow_item_ipv4 ipv4; >> + struct rte_flow_item_nvgre nvgre; >> + uint32_t hdr_flags; >> +}; >> + >> /** Maximum number of subsequent tokens and arguments on the stack. */ >> #define CTX_STACK_SIZE 16 >> >> @@ -383,6 +443,13 @@ struct token { >> .size = (s), \ >> }) >> >> +#define ARGS_ENTRY_ARB_HTON(o, s) \ >> + (&(const struct arg){ \ >> + .hton = 1, \ >> + .offset = (o), \ >> + .size = (s), \ >> + }) >> + >> /** Same as ARGS_ENTRY_ARB() with bounded values. */ #define >> ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ >> (&(const struct arg){ \ >> @@ -773,6 +840,10 @@ static const enum index next_action[] = { >> ACTION_OF_SET_VLAN_PCP, >> ACTION_OF_POP_MPLS, >> ACTION_OF_PUSH_MPLS, >> + ACTION_VXLAN_ENCAP, >> + ACTION_VXLAN_DECAP, >> + ACTION_NVGRE_ENCAP, >> + ACTION_NVGRE_DECAP, >> ZERO, >> }; >> >> @@ -874,6 +945,44 @@ static const enum index action_jump[] = { >> ZERO, >> }; >> >> +static const enum index action_vxlan_encap[] = { >> + ACTION_VXLAN_ENCAP_ETH_DST, >> + ACTION_VXLAN_ENCAP_ETH_SRC, >> + ACTION_VXLAN_ENCAP_ETH_TYPE, >> + ACTION_VXLAN_ENCAP_IPV4_DST, >> + ACTION_VXLAN_ENCAP_IPV4_SRC, >> + ACTION_VXLAN_ENCAP_IPV4_PROTO, >> + ACTION_VXLAN_ENCAP_UDP_DST, >> + ACTION_VXLAN_ENCAP_UDP_SRC, >> + ACTION_VXLAN_ENCAP_VXLAN_VNI, >> + ACTION_VXLAN_ENCAP_END, >> + ACTION_NEXT, >> + ZERO, >> +}; >> + >> +static const enum index action_vxlan_decap[] = { >> + ACTION_NEXT, >> + ZERO, >> +}; >> + >> +static const enum index action_nvgre_encap[] = { >> + ACTION_NVGRE_ENCAP_ETH_DST, >> + ACTION_NVGRE_ENCAP_ETH_SRC, >> + ACTION_NVGRE_ENCAP_ETH_TYPE, >> + ACTION_NVGRE_ENCAP_IPV4_DST, >> + ACTION_NVGRE_ENCAP_IPV4_SRC, >> + ACTION_NVGRE_ENCAP_IPV4_PROTO, >> + ACTION_NVGRE_ENCAP_NVGRE_VSNI, >> + ACTION_NVGRE_ENCAP_END, >> + ACTION_NEXT, >> + ZERO, >> +}; >> + >> +static const enum index action_nvgre_decap[] = { >> + ACTION_NEXT, >> + ZERO, >> +}; >> + >> static int parse_init(struct context *, const struct token *, >> const char *, unsigned int, >> void *, unsigned int); >> @@ -896,6 +1005,42 @@ static int parse_vc_action_rss_type(struct context *, >> const struct token *, static int parse_vc_action_rss_queue(struct context *, >> const struct token *, >> const char *, unsigned int, void *, >> unsigned int); >> +static int parse_vc_action_vxlan_encap(struct context *, const struct token *, >> + const char *, unsigned int, void *, >> + unsigned int); >> +static int parse_vc_action_vxlan_decap(struct context *, const struct token *, >> + const char *, unsigned int, void *, >> + unsigned int); >> +static int parse_vc_action_vxlan_encap_fields(struct context *, >> + const struct token *, >> + const char *, unsigned int, >> + void *, unsigned int); >> +static int parse_vc_action_vxlan_encap_fields_value(struct context *, >> + const struct token *, >> + const char *, unsigned int, >> + void *, unsigned int); >> +static int parse_vc_action_vxlan_encap_end(struct context *, >> + const struct token *, >> + const char *, unsigned int, >> + void *, unsigned int); >> +static int parse_vc_action_nvgre_encap(struct context *, const struct token *, >> + const char *, unsigned int, void *, >> + unsigned int); >> +static int parse_vc_action_nvgre_decap(struct context *, const struct token *, >> + const char *, unsigned int, void *, >> + unsigned int); >> +static int parse_vc_action_nvgre_encap_fields(struct context *, >> + const struct token *, >> + const char *, unsigned int, >> + void *, unsigned int); >> +static int parse_vc_action_nvgre_encap_fields_value(struct context *, >> + const struct token *, >> + const char *, unsigned int, >> + void *, unsigned int); >> +static int parse_vc_action_nvgre_encap_end(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); >> @@ -2362,6 +2507,256 @@ static const struct token token_list[] = { >> ethertype)), >> .call = parse_vc_conf, >> }, >> + [ACTION_VXLAN_ENCAP] = { >> + .name = "vxlan_encap", >> + .help = "encap flow with vxlan tunnel definition", >> + .priv = PRIV_ACTION(VXLAN_ENCAP, >> + sizeof(struct action_vxlan_encap_data)), >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST, >> + ACTION_VXLAN_ENCAP_ETH_SRC, >> + ACTION_VXLAN_ENCAP_ETH_TYPE, >> + ACTION_VXLAN_ENCAP_IPV4_DST, >> + ACTION_VXLAN_ENCAP_IPV4_SRC, >> + ACTION_VXLAN_ENCAP_IPV4_PROTO, >> + ACTION_VXLAN_ENCAP_UDP_DST, >> + ACTION_VXLAN_ENCAP_UDP_SRC, >> + ACTION_VXLAN_ENCAP_VXLAN_VNI, >> + ACTION_VXLAN_ENCAP_END)), >> + .call = parse_vc_action_vxlan_encap, >> + }, >> + [ACTION_VXLAN_DECAP] = { >> + .name = "vxlan_decap", >> + .help = "decap flow with vxlan tunnel definition", >> + .priv = PRIV_ACTION(VXLAN_DECAP, 0), >> + .next = NEXT(action_vxlan_decap), >> + .call = parse_vc_action_vxlan_decap, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_DST] = { >> + .name = "eth_dst", >> + .help = "destination MAC for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_DST_VALUE] = { >> + .name = "eth_dst_value", >> + .help = "destination MAC for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_SRC] = { >> + .name = "eth_src", >> + .help = "source MAC for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] = { >> + .name = "eth_src_value", >> + .help = "source MAC for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_TYPE] = { >> + .name = "eth_type", >> + .help = "eth type for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] = { >> + .name = "eth_type_value", >> + .help = "eth type for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_DST] = { >> + .name = "ipv4_dst", >> + .help = "destination ipv4 IP for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] = { >> + .name = "ipv4_dst_value", >> + .help = "destination ipv4 IP for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_SRC] = { >> + .name = "ipv4_src", >> + .help = "source ipv4 IP for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] = { >> + .name = "ipv4_src_value", >> + .help = "source ipv4 IP for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_PROTO] = { >> + .name = "ipv4_proto", >> + .help = "ipv4 proto for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] = { >> + .name = "ipv4_proto_value", >> + .help = "ipv4 proto for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_UDP_DST] = { >> + .name = "udp_dst", >> + .help = "udp destination port for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_UDP_DST_VALUE] = { >> + .name = "udp_dst_value", >> + .help = "udp destination port for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_UDP_SRC] = { >> + .name = "udp_src", >> + .help = "udp source port for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] = { >> + .name = "udp_src_value", >> + .help = "udp source port for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_VXLAN_VNI] = { >> + .name = "vxlan_vni", >> + .help = "vxlan vni for vxlan tunnel", >> + .next = NEXT(action_vxlan_encap, >> + >> NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)), >> + .call = parse_vc_action_vxlan_encap_fields, >> + }, >> + [ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] = { >> + .name = "vxlan_vni_value", >> + .help = "vxlan vni for vxlan tunnel", >> + .call = parse_vc_action_vxlan_encap_fields_value, >> + }, >> + [ACTION_VXLAN_ENCAP_END] = { >> + .name = "end", >> + .help = "end of the pattern for vxlan encap", >> + .call = parse_vc_action_vxlan_encap_end, > "end" only is being parsed, could ACTION_END be used instead? Please see my related comment above. > >> + }, >> + [ACTION_NVGRE_ENCAP] = { >> + .name = "nvgre_encap", >> + .help = "encap flow with nvgre tunnel definition", >> + .priv = PRIV_ACTION(NVGRE_ENCAP, >> + sizeof(struct action_nvgre_encap_data)), >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST, >> + ACTION_NVGRE_ENCAP_ETH_SRC, >> + ACTION_NVGRE_ENCAP_ETH_TYPE, >> + ACTION_NVGRE_ENCAP_IPV4_DST, >> + ACTION_NVGRE_ENCAP_IPV4_SRC, >> + ACTION_NVGRE_ENCAP_IPV4_PROTO, >> + ACTION_NVGRE_ENCAP_NVGRE_VSNI, >> + ACTION_NVGRE_ENCAP_END)), >> + .call = parse_vc_action_nvgre_encap, >> + }, >> + [ACTION_NVGRE_DECAP] = { >> + .name = "nvgre_decap", >> + .help = "decap flow with nvgre tunnel definition", >> + .priv = PRIV_ACTION(NVGRE_DECAP, 0), >> + .next = NEXT(action_nvgre_decap), >> + .call = parse_vc_action_nvgre_decap, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_DST] = { >> + .name = "eth_dst", >> + .help = "destination MAC for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_DST_VALUE] = { >> + .name = "eth_dst_value", >> + .help = "destination MAC for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_SRC] = { >> + .name = "eth_src", >> + .help = "source MAC for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] = { >> + .name = "eth_src_value", >> + .help = "source MAC for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_TYPE] = { >> + .name = "eth_type", >> + .help = "eth type for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] = { >> + .name = "eth_type_value", >> + .help = "eth type for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_DST] = { >> + .name = "ipv4_dst", >> + .help = "destination ipv4 IP for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] = { >> + .name = "ipv4_dst_value", >> + .help = "destination ipv4 IP for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_SRC] = { >> + .name = "ipv4_src", >> + .help = "source ipv4 IP for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] = { >> + .name = "ipv4_src_value", >> + .help = "source ipv4 IP for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_PROTO] = { >> + .name = "ipv4_proto", >> + .help = "ipv4 proto for nvgre tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] = { >> + .name = "ipv4_proto_value", >> + .help = "ipv4 proto for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_NVGRE_VSNI] = { >> + .name = "nvgre_vsni", >> + .help = "nvgre vsni for NVGRE tunnel", >> + .next = NEXT(action_nvgre_encap, >> + >> NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)), >> + .call = parse_vc_action_nvgre_encap_fields, >> + }, >> + [ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] = { >> + .name = "nvgre_vsni_value", >> + .help = "nvgre vsni for nvgre tunnel", >> + .call = parse_vc_action_nvgre_encap_fields_value, >> + }, >> + [ACTION_NVGRE_ENCAP_END] = { >> + .name = "end", >> + .help = "end of the pattern for nvgre encap", >> + .call = parse_vc_action_nvgre_encap_end, > "end" only is being parsed, could ACTION_END be used instead? Please see my related comment above. > >> + }, >> }; >> >> /** Remove and return last entry from argument stack. */ @@ -2924,6 >> +3319,482 @@ parse_vc_action_rss_queue(struct context *ctx, const struct >> token *token, >> return len; >> } >> >> +/** Parse VXLAN_ENCAP action. */ >> +static int >> +parse_vc_action_vxlan_encap(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_vxlan_encap_data *data; >> + 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; >> + /* Set up default configuration. */ >> + data = ctx->object; >> + data->conf.definition = data->pattern; >> + action->conf = &data->conf; >> + >> + return ret; >> +} >> + >> +/** Parse VXLAN_DECAP action. */ >> +static int >> +parse_vc_action_vxlan_decap(struct context *ctx, const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct buffer *out = buf; >> + 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; >> + /* Point to selected object. */ >> + ctx->object = out->args.vc.data; >> + ctx->objmask = NULL; >> + return ret; >> +} >> + >> +static uint32_t get_proto_index_using_flag(uint32_t flag) { >> + uint32_t c = 0, i = 0; >> + uint32_t supported_ptypes[] = { >> + RTE_PTYPE_L2_ETHER, >> + RTE_PTYPE_L2_ETHER_VLAN, >> + RTE_PTYPE_L3_IPV4, >> + RTE_PTYPE_L4_UDP, >> + RTE_PTYPE_TUNNEL_VXLAN, >> + RTE_PTYPE_TUNNEL_NVGRE >> + }; >> + >> + for (i = 0; i != RTE_DIM(supported_ptypes); i++) { >> + if (supported_ptypes[i] & flag) >> + c++; >> + } >> + c = (c > 0) ? (c - 1) : 0; >> + >> + return c; >> +} >> + >> +/** Parse VXLAN_ENCAP action pattern fields. */ static int >> +parse_vc_action_vxlan_encap_fields(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct action_vxlan_encap_data *data; >> + uint32_t p_index; >> + >> + (void)buf; >> + (void)size; >> + /* Token name must match. */ >> + if (parse_default(ctx, token, str, len, NULL, 0) < 0) >> + return -1; >> + if (!ctx->object) >> + return len; >> + switch (ctx->curr) { >> + case ACTION_VXLAN_ENCAP_ETH_DST: >> + case ACTION_VXLAN_ENCAP_ETH_SRC: >> + case ACTION_VXLAN_ENCAP_ETH_TYPE: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_L2_ETHER; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->eth; >> + data->pattern[p_index].mask = &rte_flow_item_eth_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; >> + break; >> + case ACTION_VXLAN_ENCAP_IPV4_DST: >> + case ACTION_VXLAN_ENCAP_IPV4_SRC: >> + case ACTION_VXLAN_ENCAP_IPV4_PROTO: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_L3_IPV4; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->ipv4; >> + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; >> + break; >> + case ACTION_VXLAN_ENCAP_UDP_DST: >> + case ACTION_VXLAN_ENCAP_UDP_SRC: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_L4_UDP; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->udp; >> + data->pattern[p_index].mask = &rte_flow_item_udp_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_UDP; >> + break; >> + case ACTION_VXLAN_ENCAP_VXLAN_VNI: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_TUNNEL_VXLAN; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->vxlan; >> + data->pattern[p_index].mask = &rte_flow_item_vxlan_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VXLAN; >> + break; >> + default: >> + return -1; >> + } >> + >> + return len; >> +} >> + >> +/** Parse VXLAN_ENCAP action pattern fields value. */ static int >> +parse_vc_action_vxlan_encap_fields_value(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct action_vxlan_encap_data *data; >> + struct ether_addr mac; >> + char str2[len + 1]; >> + struct in_addr ip4; >> + uint16_t val1; >> + uint32_t val2; >> + int ret; >> + >> + (void)token; >> + (void)buf; >> + if (!ctx->object) >> + return len; >> + data = ctx->object; >> + switch (ctx->curr) { >> + case ACTION_VXLAN_ENCAP_ETH_DST_VALUE: >> + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); >> + if (ret < 0 || (unsigned int)ret != len) >> + return -1; >> + memcpy(&data->eth.dst, &mac, sizeof(mac)); >> + break; >> + case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE: >> + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); >> + if (ret < 0 || (unsigned int)ret != len) >> + return -1; >> + memcpy(&data->eth.src, &mac, sizeof(mac)); >> + break; >> + case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->eth.type = htons(val1); >> + break; >> + case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + ret = inet_pton(AF_INET, str2, &ip4); >> + if (ret != 1) >> + return -1; >> + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); >> + break; >> + case ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + ret = inet_pton(AF_INET, str2, &ip4); >> + if (ret != 1) >> + return -1; >> + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); >> + break; >> + case ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->ipv4.hdr.next_proto_id = val1; >> + break; >> + case ACTION_VXLAN_ENCAP_UDP_DST_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->udp.hdr.dst_port = htons(val1); >> + break; >> + case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->udp.hdr.src_port = htons(val1); >> + break; >> + case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val2 = strtoul(str2, NULL, 0); >> + if (val2 == 0) >> + return -1; >> + data->vxlan.vni[0] = (uint8_t)((val2 >> 16) & 0xff); >> + data->vxlan.vni[1] = (uint8_t)((val2 >> 8) & 0xff); >> + data->vxlan.vni[2] = (uint8_t)(val2 & 0xff); >> + break; >> + default: >> + return -1; >> + } >> + >> + return len; >> +} >> + >> +/** Parse VXLAN_ENCAP action pattern end. */ static int >> +parse_vc_action_vxlan_encap_end(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ > This function should not be necessary if ACTION_END be used instead? Please see my related comment above. > >> + struct action_vxlan_encap_data *data; >> + uint32_t p_index; >> + >> + (void)buf; >> + (void)size; >> + /* Token name must match. */ >> + if (parse_default(ctx, token, str, len, NULL, 0) < 0) >> + return -1; >> + if (ctx->curr != ACTION_VXLAN_ENCAP_END) >> + return -1; >> + if (!ctx->object) >> + return len; >> + data = ctx->object; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; >> + >> + return len; >> +} >> + >> +/** Parse NVGRE_ENCAP action. */ >> +static int >> +parse_vc_action_nvgre_encap(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_nvgre_encap_data *data; >> + 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; >> + /* Set up default configuration. */ >> + data = ctx->object; >> + data->conf.definition = data->pattern; >> + action->conf = &data->conf; >> + >> + return ret; >> +} >> + >> +/** Parse NVGRE_DECAP action. */ >> +static int >> +parse_vc_action_nvgre_decap(struct context *ctx, const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct buffer *out = buf; >> + 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; >> + /* Point to selected object. */ >> + ctx->object = out->args.vc.data; >> + ctx->objmask = NULL; >> + return ret; >> +} >> + >> +/** Parse NVGRE_ENCAP action pattern fields. */ static int >> +parse_vc_action_nvgre_encap_fields(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct action_nvgre_encap_data *data; >> + uint32_t p_index; >> + >> + (void)buf; >> + (void)size; >> + /* Token name must match. */ >> + if (parse_default(ctx, token, str, len, NULL, 0) < 0) >> + return -1; >> + if (!ctx->object) >> + return len; >> + switch (ctx->curr) { >> + case ACTION_NVGRE_ENCAP_ETH_DST: >> + case ACTION_NVGRE_ENCAP_ETH_SRC: >> + case ACTION_NVGRE_ENCAP_ETH_TYPE: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_L2_ETHER; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->eth; >> + data->pattern[p_index].mask = &rte_flow_item_eth_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH; >> + break; >> + case ACTION_NVGRE_ENCAP_IPV4_DST: >> + case ACTION_NVGRE_ENCAP_IPV4_SRC: >> + case ACTION_NVGRE_ENCAP_IPV4_PROTO: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_L3_IPV4; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->ipv4; >> + data->pattern[p_index].mask = &rte_flow_item_ipv4_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4; >> + break; >> + case ACTION_NVGRE_ENCAP_NVGRE_VSNI: >> + data = ctx->object; >> + data->hdr_flags |= RTE_PTYPE_TUNNEL_NVGRE; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index].spec = &data->nvgre; >> + data->pattern[p_index].mask = &rte_flow_item_nvgre_mask; >> + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_NVGRE; >> + break; >> + default: >> + return -1; >> + } >> + >> + return len; >> +} >> + >> +/** Parse NVGRE_ENCAP action pattern fields value. */ static int >> +parse_vc_action_nvgre_encap_fields_value(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ >> + struct action_nvgre_encap_data *data; >> + struct ether_addr mac; >> + char str2[len + 1]; >> + struct in_addr ip4; >> + uint16_t val1; >> + uint32_t val2; >> + int ret; >> + >> + (void)token; >> + (void)buf; >> + if (!ctx->object) >> + return len; >> + data = ctx->object; >> + switch (ctx->curr) { >> + case ACTION_NVGRE_ENCAP_ETH_DST_VALUE: >> + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); >> + if (ret < 0 || (unsigned int)ret != len) >> + return -1; >> + memcpy(&data->eth.dst, &mac, sizeof(mac)); >> + break; >> + case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE: >> + ret = cmdline_parse_etheraddr(NULL, str, &mac, size); >> + if (ret < 0 || (unsigned int)ret != len) >> + return -1; >> + memcpy(&data->eth.src, &mac, sizeof(mac)); >> + break; >> + case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->eth.type = htons(val1); >> + break; >> + case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + ret = inet_pton(AF_INET, str2, &ip4); >> + if (ret != 1) >> + return -1; >> + memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4)); >> + break; >> + case ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + ret = inet_pton(AF_INET, str2, &ip4); >> + if (ret != 1) >> + return -1; >> + memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4)); >> + break; >> + case ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val1 = strtoul(str2, NULL, 0); >> + if (val1 == 0) >> + return -1; >> + data->ipv4.hdr.next_proto_id = val1; >> + break; >> + case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE: >> + memcpy(str2, str, len); >> + str2[len] = '\0'; >> + val2 = strtoul(str2, NULL, 0); >> + if (val2 == 0) >> + return -1; >> + data->nvgre.tni[0] = (uint8_t)((val2 >> 16) & 0xff); >> + data->nvgre.tni[1] = (uint8_t)((val2 >> 8) & 0xff); >> + data->nvgre.tni[2] = (uint8_t)(val2 & 0xff); >> + break; >> + default: >> + return -1; >> + } >> + >> + return len; >> +} >> + >> +/** Parse NVGRE_ENCAP action pattern end. */ static int >> +parse_vc_action_nvgre_encap_end(struct context *ctx, >> + const struct token *token, >> + const char *str, unsigned int len, >> + void *buf, unsigned int size) >> +{ > This function should not be necessary if ACTION_END be used instead? Please see my related comment above. > >> + struct action_nvgre_encap_data *data; >> + uint32_t p_index; >> + >> + (void)buf; >> + (void)size; >> + /* Token name must match. */ >> + if (parse_default(ctx, token, str, len, NULL, 0) < 0) >> + return -1; >> + if (ctx->curr != ACTION_NVGRE_ENCAP_END) >> + return -1; >> + if (!ctx->object) >> + return len; >> + data = ctx->object; >> + p_index = get_proto_index_using_flag(data->hdr_flags); >> + data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END; >> + >> + return len; >> +} >> + >> /** Parse tokens for destroy command. */ static int parse_destroy(struct >> context *ctx, const struct token *token, @@ -2961,6 +3832,7 @@ >> parse_destroy(struct context *ctx, const struct token *token, >> return len; >> } >> >> + > Extra blank line should be removed. Removed. > >> /** Parse tokens for flush command. */ >> static int >> parse_flush(struct context *ctx, const struct token *token, >> -- >> 2.7.4 > In the Testpmd Application/User Guide, there is section 4.12. Flow rules management. > dpdk/build/doc/html/guides/testpmd_app_ug/index.html > > As the encap and decap flows are fairly complex, It might be worth adding sections on Sample Encap flow rules and Sample Decap flow rules. I will add some documentation in the flow guide. Regards, Awal. > > Regards, > > Bernard. > ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-05-11 10:45 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-05-09 16:56 [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow Mohammad Abdul Awal 2018-05-10 12:47 ` Iremonger, Bernard 2018-05-11 10:45 ` Mohammad Abdul Awal
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).