From patchwork Wed Oct 22 01:01:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 898 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id A73057EDF; Wed, 22 Oct 2014 02:54:12 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 7C3207EBB for ; Wed, 22 Oct 2014 02:54:01 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 21 Oct 2014 18:02:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,766,1406617200"; d="scan'208";a="593421686" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga001.jf.intel.com with ESMTP; 21 Oct 2014 18:02:04 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id s9M122vh030373; Wed, 22 Oct 2014 09:02:02 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s9M120PS011254; Wed, 22 Oct 2014 09:02:02 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s9M11xY8011250; Wed, 22 Oct 2014 09:01:59 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Wed, 22 Oct 2014 09:01:12 +0800 Message-Id: <1413939687-11177-7-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1413939687-11177-1-git-send-email-jingjing.wu@intel.com> References: <1411711418-12881-1-git-send-email-jingjing.wu@intel.com> <1413939687-11177-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH v4 06/21] testpmd: add test commands to add/delete flow director filter X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" add commands which can be used to test adding or deleting 8 flow types of the flow director filters: ipv4, tcpv4, udpv4, sctpv4, ipv6, tcpv6, udpv6, sctpv6 Signed-off-by: Jingjing Wu --- app/test-pmd/cmdline.c | 447 +++++++++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 3 + 2 files changed, 450 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0b972f9..5705b65 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -660,6 +660,28 @@ static void cmd_help_long_parsed(void *parsed_result, "get_flex_filter (port_id) index (idx)\n" " get info of a flex filter.\n\n" + + "flow_director_filter (port_id) (add|del|update)" + " flow (ip4|ip6) src (src_ip_address) dst (dst_ip_address)" + " flexwords (flexwords_value)" + " (drop|fwd) queue (queue_id) fd_id (fd_id_value)\n" + " Add/Del a IP type flow director filter.\n\n" + + "flow_director_filter (port_id) (add|del|update)" + " flow (udp4|tcp4|udp6|tcp6)" + " src (src_ip_address) (src_port)" + " dst (dst_ip_address) (dst_port)" + " flexwords (flexwords_value)" + " (drop|fwd) queue (queue_id) fd_id (fd_id_value)\n" + " Add/Del a UDP/TCP type flow director filter.\n\n" + + "flow_director_filter (port_id) (add|del|update)" + " flow (sctp4|sctp6)" + " src (src_ip_address) dst (dst_ip_address)" + " tag (verification_tag)" + " flexwords (flexwords_value) (drop|fwd)" + " queue (queue_id) fd_id (fd_id_value)\n" + " Add/Del a SCTP type flow director filter.\n\n" ); } } @@ -7415,6 +7437,428 @@ cmdline_parse_inst_t cmd_get_flex_filter = { }, }; +/* *** Filters Control *** */ + +/* *** deal with flow director filter *** */ +struct cmd_flow_director_result { + cmdline_fixed_string_t flow_director_filter; + uint8_t port_id; + cmdline_fixed_string_t ops; + cmdline_fixed_string_t flow; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t src; + cmdline_ipaddr_t ip_src; + uint16_t port_src; + cmdline_fixed_string_t dst; + cmdline_ipaddr_t ip_dst; + uint16_t port_dst; + cmdline_fixed_string_t verify_tag; + uint32_t verify_tag_value; + cmdline_fixed_string_t flexwords; + cmdline_fixed_string_t flexwords_value; + cmdline_fixed_string_t drop; + cmdline_fixed_string_t queue; + uint16_t queue_id; + cmdline_fixed_string_t fd_id; + uint32_t fd_id_value; +}; + +static inline int +parse_flexwords(const char *q_arg, uint16_t *flexwords) +{ +#define MAX_NUM_WORD 8 + char s[256]; + const char *p, *p0 = q_arg; + char *end; + unsigned long int_fld[MAX_NUM_WORD]; + char *str_fld[MAX_NUM_WORD]; + int i; + unsigned size; + int num_words = -1; + + p = strchr(p0, '('); + if (p == NULL) + return -1; + ++p; + p0 = strchr(p, ')'); + if (p0 == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + num_words = rte_strsplit(s, sizeof(s), str_fld, MAX_NUM_WORD, ','); + if (num_words < 0 || num_words > MAX_NUM_WORD) + return -1; + for (i = 0; i < num_words; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > UINT16_MAX) + return -1; + flexwords[i] = rte_cpu_to_be_16((uint16_t)int_fld[i]); + } + return num_words; +} + +static void +cmd_flow_director_filter_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_flow_director_result *res = parsed_result; + struct rte_eth_fdir_filter entry; + uint16_t flexwords[8]; + int num_flexwords; + int ret = 0; + + ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR); + if (ret < 0) { + printf("flow director is not supported on port %u.\n", + res->port_id); + return; + } + memset(flexwords, 0, sizeof(flexwords)); + memset(&entry, 0, sizeof(struct rte_eth_fdir_filter)); + num_flexwords = parse_flexwords(res->flexwords_value, flexwords); + if (num_flexwords < 0) { + printf("error: Cannot parse flexwords input.\n"); + return; + } + + if (!strcmp(res->flow_type, "ip4")) { + /* no need to convert, already big endian. */ + if (res->ip_dst.family == AF_INET) + entry.input.flow.ip4_flow.dst_ip = + res->ip_dst.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + if (res->ip_src.family == AF_INET) + entry.input.flow.ip4_flow.src_ip = + res->ip_src.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + entry.input.flow_type = RTE_ETH_FLOW_TYPE_IPV4_OTHER; + } else if (!strcmp(res->flow_type, "udp4")) { + /* no need to convert, already big endian. */ + if (res->ip_dst.family == AF_INET) + entry.input.flow.udp4_flow.dst_ip = + res->ip_dst.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + if (res->ip_src.family == AF_INET) + entry.input.flow.udp4_flow.src_ip = + res->ip_src.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + /* need convert to big endian. */ + entry.input.flow.udp4_flow.dst_port = + rte_cpu_to_be_16(res->port_dst); + entry.input.flow.udp4_flow.src_port = + rte_cpu_to_be_16(res->port_src); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_UDPV4; + } else if (!strcmp(res->flow_type, "tcp4")) { + if (res->ip_dst.family == AF_INET) + entry.input.flow.tcp4_flow.dst_ip = + res->ip_dst.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + if (res->ip_src.family == AF_INET) + entry.input.flow.tcp4_flow.src_ip = + res->ip_src.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + /* need convert to big endian. */ + entry.input.flow.tcp4_flow.dst_port = + rte_cpu_to_be_16(res->port_dst); + entry.input.flow.tcp4_flow.src_port = + rte_cpu_to_be_16(res->port_src); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_TCPV4; + } else if (!strcmp(res->flow_type, "sctp4")) { + if (res->ip_dst.family == AF_INET) + entry.input.flow.sctp4_flow.dst_ip = + res->ip_dst.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + if (res->ip_src.family == AF_INET) + entry.input.flow.sctp4_flow.src_ip = + res->ip_src.addr.ipv4.s_addr; + else { + printf("error paramters.\n"); + return; + } + /* need convert to big endian. */ + entry.input.flow.sctp4_flow.verify_tag = + rte_cpu_to_be_32(res->verify_tag_value); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_SCTPV4; + } else if (!strcmp(res->flow_type, "ip6")) { + if (res->ip_src.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.ip6_flow.src_ip), + &(res->ip_src.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + if (res->ip_dst.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.ip6_flow.dst_ip), + &(res->ip_dst.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + entry.input.flow_type = RTE_ETH_FLOW_TYPE_IPV6_OTHER; + } else if (!strcmp(res->flow_type, "udp6")) { + if (res->ip_src.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.udp6_flow.src_ip), + &(res->ip_src.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + if (res->ip_dst.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.udp6_flow.dst_ip), + &(res->ip_dst.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + entry.input.flow.udp6_flow.dst_port = + rte_cpu_to_be_16(res->port_dst); + entry.input.flow.udp6_flow.src_port = + rte_cpu_to_be_16(res->port_src); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_UDPV6; + } else if (!strcmp(res->flow_type, "tcp6")) { + if (res->ip_src.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.tcp6_flow.src_ip), + &(res->ip_src.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + if (res->ip_dst.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.tcp6_flow.dst_ip), + &(res->ip_dst.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + entry.input.flow.tcp6_flow.dst_port = + rte_cpu_to_be_16(res->port_dst); + entry.input.flow.tcp6_flow.src_port = + rte_cpu_to_be_16(res->port_src); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_TCPV6; + } else if (!strcmp(res->flow_type, "sctp6")) { + if (res->ip_src.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.sctp6_flow.src_ip), + &(res->ip_src.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + if (res->ip_dst.family == AF_INET6) + (void)rte_memcpy(&(entry.input.flow.sctp6_flow.dst_ip), + &(res->ip_dst.addr.ipv6), + sizeof(struct in6_addr)); + else { + printf("error paramters.\n"); + return; + } + entry.input.flow.sctp6_flow.verify_tag = + rte_cpu_to_be_32(res->verify_tag_value); + entry.input.flow_type = RTE_ETH_FLOW_TYPE_SCTPV6; + } + + entry.input.flow_ext.num_flexwords = num_flexwords; + rte_memcpy(entry.input.flow_ext.flexwords, + flexwords, + BYTES_PER_WORD * num_flexwords); + + entry.input.flow_ext.dest_id = 0; /* if set to 0, will use main vsi by default */ + entry.action.flex_off = 0; /*use 0 by default */ + if (!strcmp(res->drop, "drop")) + entry.action.drop = 1; + else + entry.action.drop = 0; + /* set to report FD ID by default */ + entry.action.report_status = RTE_ETH_FDIR_REPORT_FD_ID; + entry.action.rx_queue = res->queue_id; + /* use 0 by default, will set it to fdir counter per dev */ + entry.action.cnt_idx = 0; + entry.soft_id = res->fd_id_value; + if (!strcmp(res->ops, "add")) + ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_ADD, &entry); + else + ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_DELETE, &entry); + if (ret < 0) + printf("flow director programming error: (%s)\n", + strerror(-ret)); +} + +cmdline_parse_token_string_t cmd_flow_director_filter = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + flow_director_filter, "flow_director_filter"); +cmdline_parse_token_num_t cmd_flow_director_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_flow_director_ops = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + ops, "add#del#update"); +cmdline_parse_token_string_t cmd_flow_director_flow = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + flow, "flow"); +cmdline_parse_token_string_t cmd_flow_director_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + flow_type, + "ip4#tcp4#udp4#sctp4#ip6#tcp6#udp6#sctp6"); +cmdline_parse_token_string_t cmd_flow_director_src = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + src, "src"); +cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src = + TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result, + ip_src); +cmdline_parse_token_num_t cmd_flow_director_port_src = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + port_src, UINT16); +cmdline_parse_token_string_t cmd_flow_director_dst = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + dst, "dst"); +cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst = + TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result, + ip_dst); +cmdline_parse_token_num_t cmd_flow_director_port_dst = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + port_dst, UINT16); +cmdline_parse_token_string_t cmd_flow_director_verify_tag = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + verify_tag, "verify_tag"); +cmdline_parse_token_num_t cmd_flow_director_verify_tag_value = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + verify_tag_value, UINT32); +cmdline_parse_token_string_t cmd_flow_director_flexwords = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + flexwords, "flexwords"); +cmdline_parse_token_string_t cmd_flow_director_flexwords_value = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + flexwords_value, NULL); +cmdline_parse_token_string_t cmd_flow_director_drop = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + drop, "drop#fwd"); +cmdline_parse_token_string_t cmd_flow_director_queue = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + queue, "queue"); +cmdline_parse_token_num_t cmd_flow_director_queue_id = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + queue_id, UINT16); +cmdline_parse_token_string_t cmd_flow_director_fd_id = + TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, + fd_id, "fd_id"); +cmdline_parse_token_num_t cmd_flow_director_fd_id_value = + TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, + fd_id_value, UINT32); + +cmdline_parse_inst_t cmd_add_del_ip_flow_director = { + .f = cmd_flow_director_filter_parsed, + .data = NULL, + .help_str = "add or delete a ip flow director entry on NIC", + .tokens = { + (void *)&cmd_flow_director_filter, + (void *)&cmd_flow_director_port_id, + (void *)&cmd_flow_director_ops, + (void *)&cmd_flow_director_flow, + (void *)&cmd_flow_director_flow_type, + (void *)&cmd_flow_director_src, + (void *)&cmd_flow_director_ip_src, + (void *)&cmd_flow_director_dst, + (void *)&cmd_flow_director_ip_dst, + (void *)&cmd_flow_director_flexwords, + (void *)&cmd_flow_director_flexwords_value, + (void *)&cmd_flow_director_drop, + (void *)&cmd_flow_director_queue, + (void *)&cmd_flow_director_queue_id, + (void *)&cmd_flow_director_fd_id, + (void *)&cmd_flow_director_fd_id_value, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_add_del_udp_flow_director = { + .f = cmd_flow_director_filter_parsed, + .data = NULL, + .help_str = "add or delete a udp/tcp flow director entry on NIC", + .tokens = { + (void *)&cmd_flow_director_filter, + (void *)&cmd_flow_director_port_id, + (void *)&cmd_flow_director_ops, + (void *)&cmd_flow_director_flow, + (void *)&cmd_flow_director_flow_type, + (void *)&cmd_flow_director_src, + (void *)&cmd_flow_director_ip_src, + (void *)&cmd_flow_director_port_src, + (void *)&cmd_flow_director_dst, + (void *)&cmd_flow_director_ip_dst, + (void *)&cmd_flow_director_port_dst, + (void *)&cmd_flow_director_flexwords, + (void *)&cmd_flow_director_flexwords_value, + (void *)&cmd_flow_director_drop, + (void *)&cmd_flow_director_queue, + (void *)&cmd_flow_director_queue_id, + (void *)&cmd_flow_director_fd_id, + (void *)&cmd_flow_director_fd_id_value, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_add_del_sctp_flow_director = { + .f = cmd_flow_director_filter_parsed, + .data = NULL, + .help_str = "add or delete a sctp flow director entry on NIC", + .tokens = { + (void *)&cmd_flow_director_filter, + (void *)&cmd_flow_director_port_id, + (void *)&cmd_flow_director_ops, + (void *)&cmd_flow_director_flow, + (void *)&cmd_flow_director_flow_type, + (void *)&cmd_flow_director_src, + (void *)&cmd_flow_director_ip_src, + (void *)&cmd_flow_director_dst, + (void *)&cmd_flow_director_ip_dst, + (void *)&cmd_flow_director_verify_tag, + (void *)&cmd_flow_director_verify_tag_value, + (void *)&cmd_flow_director_flexwords, + (void *)&cmd_flow_director_flexwords_value, + (void *)&cmd_flow_director_drop, + (void *)&cmd_flow_director_queue, + (void *)&cmd_flow_director_queue_id, + (void *)&cmd_flow_director_fd_id, + (void *)&cmd_flow_director_fd_id_value, + NULL, + }, +}; + /* ******************************************************************************** */ /* list of instructions */ @@ -7541,6 +7985,9 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_add_flex_filter, (cmdline_parse_inst_t *)&cmd_remove_flex_filter, (cmdline_parse_inst_t *)&cmd_get_flex_filter, + (cmdline_parse_inst_t *)&cmd_add_del_ip_flow_director, + (cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director, + (cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director, NULL, }; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 9cbfeac..74c0c0c 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -73,6 +73,9 @@ int main(int argc, char **argv); #define NUMA_NO_CONFIG 0xFF #define UMA_NO_CONFIG 0xFF +#define BYTES_PER_WORD 2 +#define IPV6_ADDR_LEN 16 + typedef uint8_t lcoreid_t; typedef uint8_t portid_t; typedef uint16_t queueid_t;