X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Fcmdline_flow.c;h=7a1c5aba9b6595c3f6002e347e845306feeb2cbc;hb=35b2d13fd6fdcbd191f2a30d74648faeb1186c65;hp=91e2e3507b67c2049ea64ce0fd90dc2d27a10ef7;hpb=a4391f8bae85db0153e1f101c21c61151573baad;p=dpdk.git diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 91e2e3507b..7a1c5aba9b 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -13,8 +13,8 @@ #include #include +#include #include -#include #include #include #include @@ -35,6 +35,7 @@ enum index { PREFIX, BOOLEAN, STRING, + HEX, MAC_ADDR, IPV4_ADDR, IPV6_ADDR, @@ -1122,6 +1123,9 @@ static int parse_boolean(struct context *, const struct token *, static int parse_string(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_hex(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size); static int parse_mac_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1198,6 +1202,13 @@ static const struct token token_list[] = { .call = parse_string, .comp = comp_none, }, + [HEX] = { + .name = "{hex}", + .type = "HEX", + .help = "fixed string", + .call = parse_hex, + .comp = comp_none, + }, [MAC_ADDR] = { .name = "{MAC address}", .type = "MAC-48", @@ -2306,7 +2317,7 @@ static const struct token token_list[] = { [ACTION_RSS_KEY] = { .name = "key", .help = "RSS hash key", - .next = NEXT(action_rss, NEXT_ENTRY(STRING)), + .next = NEXT(action_rss, NEXT_ENTRY(HEX)), .args = ARGS(ARGS_ENTRY_ARB(0, 0), ARGS_ENTRY_ARB (offsetof(struct action_rss_data, conf) + @@ -3248,15 +3259,26 @@ parse_vc_action_rss(struct context *ctx, const struct token *token, .func = RTE_ETH_HASH_FUNCTION_DEFAULT, .level = 0, .types = rss_hf, - .key_len = 0, + .key_len = sizeof(action_rss_data->key), .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM), - .key = NULL, + .key = action_rss_data->key, .queue = action_rss_data->queue, }, + .key = "testpmd's default RSS hash key, " + "override it for better balancing", .queue = { 0 }, }; for (i = 0; i < action_rss_data->conf.queue_num; ++i) action_rss_data->queue[i] = i; + if (!port_id_is_invalid(ctx->port, DISABLED_WARN) && + ctx->port != (portid_t)RTE_PORT_ALL) { + struct rte_eth_dev_info info; + + rte_eth_dev_info_get(ctx->port, &info); + action_rss_data->conf.key_len = + RTE_MIN(sizeof(action_rss_data->key), + info.hash_key_size); + } action->conf = &action_rss_data->conf; return ret; } @@ -3471,9 +3493,9 @@ parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, .item_vxlan.flags = 0, }; memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, - vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN); + vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, - vxlan_encap_conf.eth_src, ETHER_ADDR_LEN); + vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); if (!vxlan_encap_conf.select_ipv4) { memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, &vxlan_encap_conf.ipv6_src, @@ -3490,6 +3512,38 @@ parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, if (!vxlan_encap_conf.select_vlan) action_vxlan_encap_data->items[1].type = RTE_FLOW_ITEM_TYPE_VOID; + if (vxlan_encap_conf.select_tos_ttl) { + if (vxlan_encap_conf.select_ipv4) { + static struct rte_flow_item_ipv4 ipv4_mask_tos; + + memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, + sizeof(ipv4_mask_tos)); + ipv4_mask_tos.hdr.type_of_service = 0xff; + ipv4_mask_tos.hdr.time_to_live = 0xff; + action_vxlan_encap_data->item_ipv4.hdr.type_of_service = + vxlan_encap_conf.ip_tos; + action_vxlan_encap_data->item_ipv4.hdr.time_to_live = + vxlan_encap_conf.ip_ttl; + action_vxlan_encap_data->items[2].mask = + &ipv4_mask_tos; + } else { + static struct rte_flow_item_ipv6 ipv6_mask_tos; + + memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, + sizeof(ipv6_mask_tos)); + ipv6_mask_tos.hdr.vtc_flow |= + RTE_BE32(0xfful << IPV6_HDR_TC_SHIFT); + ipv6_mask_tos.hdr.hop_limits = 0xff; + action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= + rte_cpu_to_be_32 + ((uint32_t)vxlan_encap_conf.ip_tos << + IPV6_HDR_TC_SHIFT); + action_vxlan_encap_data->item_ipv6.hdr.hop_limits = + vxlan_encap_conf.ip_ttl; + action_vxlan_encap_data->items[2].mask = + &ipv6_mask_tos; + } + } memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, RTE_DIM(vxlan_encap_conf.vni)); action->conf = &action_vxlan_encap_data->conf; @@ -3562,9 +3616,9 @@ parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, .item_nvgre.flow_id = 0, }; memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, - nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN); + nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, - nvgre_encap_conf.eth_src, ETHER_ADDR_LEN); + nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); if (!nvgre_encap_conf.select_ipv4) { memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, &nvgre_encap_conf.ipv6_src, @@ -3626,22 +3680,22 @@ parse_vc_action_l2_encap(struct context *ctx, const struct token *token, }; header = action_encap_data->data; if (l2_encap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); else if (l2_encap_conf.select_ipv4) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(eth.dst.addr_bytes, - l2_encap_conf.eth_dst, ETHER_ADDR_LEN); + l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(eth.src.addr_bytes, - l2_encap_conf.eth_src, ETHER_ADDR_LEN); + l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (l2_encap_conf.select_vlan) { if (l2_encap_conf.select_ipv4) - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(header, &vlan, sizeof(vlan)); header += sizeof(vlan); } @@ -3690,7 +3744,7 @@ parse_vc_action_l2_decap(struct context *ctx, const struct token *token, }; header = action_decap_data->data; if (l2_decap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (l2_decap_conf.select_vlan) { @@ -3761,22 +3815,22 @@ parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, }; header = action_encap_data->data; if (mplsogre_encap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); else if (mplsogre_encap_conf.select_ipv4) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(eth.dst.addr_bytes, - mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN); + mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(eth.src.addr_bytes, - mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN); + mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (mplsogre_encap_conf.select_vlan) { if (mplsogre_encap_conf.select_ipv4) - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(header, &vlan, sizeof(vlan)); header += sizeof(vlan); } @@ -3797,6 +3851,7 @@ parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, header += sizeof(gre); memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, RTE_DIM(mplsogre_encap_conf.label)); + mpls.label_tc_s[2] |= 0x1; memcpy(header, &mpls, sizeof(mpls)); header += sizeof(mpls); action_encap_data->conf.size = header - @@ -3855,22 +3910,22 @@ parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, }; header = action_decap_data->data; if (mplsogre_decap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); else if (mplsogre_encap_conf.select_ipv4) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(eth.dst.addr_bytes, - mplsogre_encap_conf.eth_dst, ETHER_ADDR_LEN); + mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(eth.src.addr_bytes, - mplsogre_encap_conf.eth_src, ETHER_ADDR_LEN); + mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (mplsogre_encap_conf.select_vlan) { if (mplsogre_encap_conf.select_ipv4) - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(header, &vlan, sizeof(vlan)); header += sizeof(vlan); } @@ -3951,22 +4006,22 @@ parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, }; header = action_encap_data->data; if (mplsoudp_encap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); else if (mplsoudp_encap_conf.select_ipv4) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(eth.dst.addr_bytes, - mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN); + mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(eth.src.addr_bytes, - mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN); + mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (mplsoudp_encap_conf.select_vlan) { if (mplsoudp_encap_conf.select_ipv4) - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(header, &vlan, sizeof(vlan)); header += sizeof(vlan); } @@ -3987,6 +4042,7 @@ parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, header += sizeof(udp); memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, RTE_DIM(mplsoudp_encap_conf.label)); + mpls.label_tc_s[2] |= 0x1; memcpy(header, &mpls, sizeof(mpls)); header += sizeof(mpls); action_encap_data->conf.size = header - @@ -4047,22 +4103,22 @@ parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, }; header = action_decap_data->data; if (mplsoudp_decap_conf.select_vlan) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); else if (mplsoudp_encap_conf.select_ipv4) - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(eth.dst.addr_bytes, - mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN); + mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); memcpy(eth.src.addr_bytes, - mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN); + mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); memcpy(header, ð, sizeof(eth)); header += sizeof(eth); if (mplsoudp_encap_conf.select_vlan) { if (mplsoudp_encap_conf.select_ipv4) - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv4); else - vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPv6); memcpy(header, &vlan, sizeof(vlan)); header += sizeof(vlan); } @@ -4314,6 +4370,8 @@ parse_int(struct context *ctx, const struct token *token, } buf = (uint8_t *)ctx->object + arg->offset; size = arg->size; + if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) + return -1; objmask: switch (size) { case sizeof(uint8_t): @@ -4428,6 +4486,121 @@ error: return -1; } +static int +parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) +{ + char *c = NULL; + uint32_t i, len; + char tmp[3]; + + /* Check input parameters */ + if ((src == NULL) || + (dst == NULL) || + (size == NULL) || + (*size == 0)) + return -1; + + /* Convert chars to bytes */ + for (i = 0, len = 0; i < *size; i += 2) { + snprintf(tmp, 3, "%s", src + i); + dst[len++] = strtoul(tmp, &c, 16); + if (*c != 0) { + len--; + dst[len] = 0; + *size = len; + return -1; + } + } + dst[len] = 0; + *size = len; + + return 0; +} + +static int +parse_hex(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + const struct arg *arg_data = pop_args(ctx); + const struct arg *arg_len = pop_args(ctx); + const struct arg *arg_addr = pop_args(ctx); + char tmp[16]; /* Ought to be enough. */ + int ret; + unsigned int hexlen = len; + unsigned int length = 256; + uint8_t hex_tmp[length]; + + /* Arguments are expected. */ + if (!arg_data) + return -1; + if (!arg_len) { + push_args(ctx, arg_data); + return -1; + } + if (!arg_addr) { + push_args(ctx, arg_len); + push_args(ctx, arg_data); + return -1; + } + size = arg_data->size; + /* Bit-mask fill is not supported. */ + if (arg_data->mask) + goto error; + if (!ctx->object) + return len; + + /* translate bytes string to array. */ + if (str[0] == '0' && ((str[1] == 'x') || + (str[1] == 'X'))) { + str += 2; + hexlen -= 2; + } + if (hexlen > length) + return -1; + ret = parse_hex_string(str, hex_tmp, &hexlen); + if (ret < 0) + goto error; + /* Let parse_int() fill length information first. */ + ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); + if (ret < 0) + goto error; + push_args(ctx, arg_len); + ret = parse_int(ctx, token, tmp, ret, NULL, 0); + if (ret < 0) { + pop_args(ctx); + goto error; + } + buf = (uint8_t *)ctx->object + arg_data->offset; + /* Output buffer is not necessarily NUL-terminated. */ + memcpy(buf, hex_tmp, hexlen); + memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); + if (ctx->objmask) + memset((uint8_t *)ctx->objmask + arg_data->offset, + 0xff, hexlen); + /* Save address if requested. */ + if (arg_addr->size) { + memcpy((uint8_t *)ctx->object + arg_addr->offset, + (void *[]){ + (uint8_t *)ctx->object + arg_data->offset + }, + arg_addr->size); + if (ctx->objmask) + memcpy((uint8_t *)ctx->objmask + arg_addr->offset, + (void *[]){ + (uint8_t *)ctx->objmask + arg_data->offset + }, + arg_addr->size); + } + return len; +error: + push_args(ctx, arg_addr); + push_args(ctx, arg_len); + push_args(ctx, arg_data); + return -1; + +} + /** * Parse a MAC address. * @@ -4440,7 +4613,7 @@ parse_mac_addr(struct context *ctx, const struct token *token, void *buf, unsigned int size) { const struct arg *arg = pop_args(ctx); - struct ether_addr tmp; + struct rte_ether_addr tmp; int ret; (void)token; @@ -4647,7 +4820,7 @@ comp_boolean(struct context *ctx, const struct token *token, (void)token; for (i = 0; boolean_name[i]; ++i) if (buf && i == ent) - return snprintf(buf, size, "%s", boolean_name[i]); + return strlcpy(buf, boolean_name[i], size); if (buf) return -1; return i; @@ -4664,8 +4837,8 @@ comp_action(struct context *ctx, const struct token *token, (void)token; for (i = 0; next_action[i]; ++i) if (buf && i == ent) - return snprintf(buf, size, "%s", - token_list[next_action[i]].name); + return strlcpy(buf, token_list[next_action[i]].name, + size); if (buf) return -1; return i; @@ -4729,7 +4902,7 @@ comp_vc_action_rss_type(struct context *ctx, const struct token *token, if (!buf) return i + 1; if (ent < i) - return snprintf(buf, size, "%s", rss_type_table[ent].str); + return strlcpy(buf, rss_type_table[ent].str, size); if (ent == i) return snprintf(buf, size, "end"); return -1; @@ -4914,7 +5087,7 @@ cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, if (index >= i) return -1; token = &token_list[list[index]]; - snprintf(dst, size, "%s", token->name); + strlcpy(dst, token->name, size); /* Save index for cmd_flow_get_help(). */ ctx->prev = list[index]; return 0; @@ -4931,7 +5104,7 @@ cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) if (!size) return -1; /* Set token type and update global help with details. */ - snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); + strlcpy(dst, (token->type ? token->type : "TOKEN"), size); if (token->help) cmd_flow.help_str = token->help; else