Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.a...@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