Show a patch.

GET /api/patches/251/
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 251,
    "url": "http://patches.dpdk.org/api/patches/251/",
    "web_url": "http://patches.dpdk.org/patch/251/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk"
    },
    "msgid": "<1409105634-29980-8-git-send-email-jingjing.wu@intel.com>",
    "date": "2014-08-27T02:13:54",
    "name": "[dpdk-dev,v2,7/7] app/testpmd: add commands and config functions for i40e flow director support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d78fa5726fe632977cee340a2f2f78777f90e040",
    "submitter": {
        "id": 47,
        "url": "http://patches.dpdk.org/api/people/47/",
        "name": "Wu, Jingjing",
        "email": "jingjing.wu@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/patch/251/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/251/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/251/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<wujingji@shecgisg004.sh.intel.com>",
        "References": "<1409105634-29980-1-git-send-email-jingjing.wu@intel.com>",
        "X-Mailman-Version": "2.1.15",
        "X-IronPort-AV": "E=Sophos;i=\"5.04,408,1406617200\"; d=\"scan'208\";a=\"593783984\"",
        "From": "Jingjing Wu <jingjing.wu@intel.com>",
        "X-List-Received-Date": "Wed, 27 Aug 2014 02:11:00 -0000",
        "X-BeenThere": "dev@dpdk.org",
        "Message-Id": "<1409105634-29980-8-git-send-email-jingjing.wu@intel.com>",
        "Received": [
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 21FB9B37F\n\tfor <dev@dpdk.org>; Wed, 27 Aug 2014 04:10:58 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP; 26 Aug 2014 19:09:01 -0700",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga002.jf.intel.com with ESMTP; 26 Aug 2014 19:14:45 -0700",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id s7R2EhGv006241;\n\tWed, 27 Aug 2014 10:14:43 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid s7R2Eef3030139; Wed, 27 Aug 2014 10:14:42 +0800",
            "(from wujingji@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s7R2Ee7O030135; \n\tWed, 27 Aug 2014 10:14:40 +0800"
        ],
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "Precedence": "list",
        "Date": "Wed, 27 Aug 2014 10:13:54 +0800",
        "Subject": "[dpdk-dev] [PATCH v2 7/7]app/testpmd: add commands and config\n\tfunctions for i40e flow director support",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "X-ExtLoop1": "1",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "In-Reply-To": "<1409105634-29980-1-git-send-email-jingjing.wu@intel.com>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "To": "dev@dpdk.org"
    },
    "content": "add structure definition to construct programming packet.\nadd commands to programming 6 flow types for the flow director filters,\nwhich is called PCTYPE in fortville: ipv4, tcpv4, udpv4, ipv6, tcpv6, udpv6\nadd commands to support flushing flow director table and get info\n \nSigned-off-by: jingjing.wu <jingjing.wu@intel.com>\nReviewed-by: Helin Zhang <helin.zhang@intel.com>\nReviewed-by: Jing Chen <jing.d.chen@intel.com>\nReviewed-by: Jijiang Liu <jijiang.liu@intel.com>\n \n---\n app/test-pmd/cmdline.c | 665 +++++++++++++++++++++++++++++++++++++++++++++++++\n app/test-pmd/config.c  |  54 +++-\n app/test-pmd/testpmd.c |  22 ++\n app/test-pmd/testpmd.h |  57 +++++\n 4 files changed, 786 insertions(+), 12 deletions(-)",
    "diff": "diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex b04a4e8..d4729e7 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -74,6 +74,14 @@\n #include <rte_ethdev.h>\n #include <rte_string_fns.h>\n #include <rte_devargs.h>\n+#include <rte_ip.h>\n+#include <rte_udp.h>\n+#include <rte_tcp.h>\n+#include <rte_sctp.h>\n+#include <rte_eth_features.h>\n+#ifdef RTE_LIBRTE_I40E_PMD\n+#include <rte_i40e.h>\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \n #include <cmdline_rdline.h>\n #include <cmdline_parse.h>\n@@ -660,6 +668,25 @@ static void cmd_help_long_parsed(void *parsed_result,\n \n \t\t\t\"get_flex_filter (port_id) index (idx)\\n\"\n \t\t\t\"    get info of a flex filter.\\n\\n\"\n+\n+#ifdef RTE_LIBRTE_I40E_PMD\n+\t\t\t\"i40e_flow_director_filter (port_id) (add|del)\"\n+\t\t\t\" flow (ip4|ip6) src (src_ip_address) dst (dst_ip_address)\"\n+\t\t\t\" flexwords (flexwords_value) (drop|fwd)\"\n+\t\t\t\" queue (queue_id) fd_id (fd_id_value)\\n\"\n+\t\t\t\"    Add/Del a IP type flow director filter for i40e NIC.\\n\\n\"\n+\n+\t\t\t\"i40e_flow_director_filter (port_id) (add|del)\"\n+\t\t\t\" flow (udp4|tcp4|udp6|tcp6)\"\n+\t\t\t\" src (src_ip_address) (src_port)\"\n+\t\t\t\" dst (dst_ip_address) (dst_port)\"\n+\t\t\t\" flexwords (flexwords_value) (drop|fwd)\"\n+\t\t\t\" queue (queue_id) fd_id (fd_id_value)\\n\"\n+\t\t\t\"    Add/Del a UDP/TCP type flow director filter for i40e NIC.\\n\\n\"\n+\n+\t\t\t\"i40e_flush_flow_diretor (port_id)\\n\"\n+\t\t\t\"    Flush all flow director entries of a device on i40e NIC.\\n\\n\"\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \t\t);\n \t}\n }\n@@ -7403,6 +7430,639 @@ cmdline_parse_inst_t cmd_get_flex_filter = {\n \t},\n };\n \n+/* *** Classification Filters Control *** */\n+#ifdef RTE_LIBRTE_I40E_PMD\n+/* *** deal with i40e flow director filter *** */\n+struct cmd_i40e_flow_director_result {\n+\tcmdline_fixed_string_t flow_director_filter;\n+\tuint8_t port_id;\n+\tcmdline_fixed_string_t ops;\n+\tcmdline_fixed_string_t flow;\n+\tcmdline_fixed_string_t flow_type;\n+\tcmdline_fixed_string_t src;\n+\tcmdline_ipaddr_t ip_src;\n+\tuint16_t port_src;\n+\tcmdline_fixed_string_t dst;\n+\tcmdline_ipaddr_t ip_dst;\n+\tuint16_t port_dst;\n+\tcmdline_fixed_string_t flexwords;\n+\tcmdline_fixed_string_t flexwords_value;\n+\tcmdline_fixed_string_t drop;\n+\tcmdline_fixed_string_t queue;\n+\tuint16_t  queue_id;\n+\tcmdline_fixed_string_t fd_id;\n+\tuint32_t  fd_id_value;\n+};\n+\n+static inline int\n+parse_flexwords(const char *q_arg, uint16_t *flexwords)\n+{\n+#define MAX_NUM_WORD 8\n+\tchar s[256];\n+\tconst char *p, *p0 = q_arg;\n+\tchar *end;\n+\tunsigned long int_fld[MAX_NUM_WORD];\n+\tchar *str_fld[MAX_NUM_WORD];\n+\tint i;\n+\tunsigned size;\n+\tint num_words = -1;\n+\n+\tp = strchr(p0, '(');\n+\tif (p == NULL)\n+\t\treturn -1;\n+\t++p;\n+\tp0 = strchr(p, ')');\n+\tif (p0 == NULL)\n+\t\treturn -1;\n+\n+\tsize = p0 - p;\n+\tif (size >= sizeof(s))\n+\t\treturn -1;\n+\n+\tsnprintf(s, sizeof(s), \"%.*s\", size, p);\n+\tnum_words = rte_strsplit(s, sizeof(s), str_fld, MAX_NUM_WORD, ',');\n+\tif (num_words < 0 || num_words > MAX_NUM_WORD)\n+\t\treturn -1;\n+\tfor (i = 0; i < num_words; i++) {\n+\t\terrno = 0;\n+\t\tint_fld[i] = strtoul(str_fld[i], &end, 0);\n+\t\tif (errno != 0 || end == str_fld[i] || int_fld[i] > UINT16_MAX)\n+\t\t\treturn -1;\n+\t\tflexwords[i] = rte_cpu_to_be_16((uint16_t)int_fld[i]);\n+\t}\n+\treturn num_words;\n+}\n+\n+static inline struct rte_mbuf *\n+tx_mbuf_alloc(struct rte_mempool *mp)\n+{\n+\tstruct rte_mbuf *m;\n+\n+\tm = __rte_mbuf_raw_alloc(mp);\n+\t__rte_mbuf_sanity_check_raw(m, RTE_MBUF_PKT, 0);\n+\treturn m;\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_ip4_input(struct ipv4_other_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv4_hdr *ip;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);\n+\tip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;\n+\t/* set len to 46 bytes by default */\n+\tip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);\n+\tip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;\n+\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\tip->src_addr = flow->dst_ip;\n+\tip->dst_addr = flow->src_ip;\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_udp4_input(struct ipv4_udp_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv4_hdr *ip;\n+\tstruct udp_hdr *udp;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\tudp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv4_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv4_hdr) + sizeof(struct udp_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);\n+\tip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;\n+\t/* set len to by default */\n+\tip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);\n+\tip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;\n+\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\tip->src_addr = flow->dst_ip;\n+\tip->dst_addr = flow->src_ip;\n+\tip->next_proto_id = IPPROTO_UDP;\n+\tudp->src_port = flow->dst_port;\n+\tudp->dst_port = flow->src_port;\n+\tudp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_tcp4_input(struct ipv4_tcp_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv4_hdr *ip;\n+\tstruct tcp_hdr *tcp;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\ttcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv4_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv4_hdr) + sizeof(struct tcp_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);\n+\tip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;\n+\t/* set len by default */\n+\tip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);\n+\tip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL;\n+\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\tip->src_addr = flow->dst_ip;\n+\tip->dst_addr = flow->src_ip;\n+\tip->next_proto_id = IPPROTO_TCP;\n+\ttcp->src_port = flow->dst_port;\n+\ttcp->dst_port = flow->src_port;\n+\ttcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_ip6_input(struct ipv6_other_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv6_hdr *ip;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);\n+\tip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);\n+\tip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);\n+\tip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;\n+\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\trte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);\n+\trte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_udp6_input(struct ipv6_udp_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv6_hdr *ip;\n+\tstruct udp_hdr *udp;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\tudp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv6_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv6_hdr) + sizeof(struct udp_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);\n+\tip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);\n+\tip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);\n+\tip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\trte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);\n+\trte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);\n+\tip->proto = IPPROTO_UDP;\n+\tudp->src_port = flow->dst_port;\n+\tudp->dst_port = flow->src_port;\n+\tudp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static inline void\n+rte_i40e_fdir_construct_tcp6_input(struct ipv6_tcp_flow *flow,\n+\t\t\tunsigned char *raw_pkt)\n+{\n+\tstruct ether_hdr *ether;\n+\tstruct ipv6_hdr *ip;\n+\tstruct tcp_hdr *tcp;\n+\tunsigned char *payload;\n+\n+\tether = (struct ether_hdr *)raw_pkt;\n+\tip = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr));\n+\ttcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv6_hdr));\n+\tpayload = raw_pkt + sizeof(struct ether_hdr) +\n+\t\t\tsizeof(struct ipv6_hdr) + sizeof(struct tcp_hdr);\n+\n+\tether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);\n+\tip->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW);\n+\tip->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_DEFAULT_PAYLOAD_LEN);\n+\tip->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;\n+\t/*\n+\t * The source and destination fields in the transmitted packet need\n+\t * to be presented in a reversed order with respect to the expected\n+\t * received packets.\n+\t */\n+\trte_memcpy(&(ip->src_addr), &(flow->dst_ip), IPV6_ADDR_LEN);\n+\trte_memcpy(&(ip->dst_addr), &(flow->src_ip), IPV6_ADDR_LEN);\n+\tip->proto = IPPROTO_TCP;\n+\ttcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;\n+\ttcp->src_port = flow->dst_port;\n+\ttcp->dst_port = flow->src_port;\n+\t(void)rte_memcpy(payload,\n+\t\t\t flow->flexwords,\n+\t\t\t BYTES_PER_WORD * flow->num_flexwords);\n+}\n+\n+static void\n+cmd_i40e_flow_director_parsed(void *parsed_result,\n+\t\t\t  __attribute__((unused)) struct cmdline *cl,\n+\t\t\t  __attribute__((unused)) void *data)\n+{\n+\tstruct cmd_i40e_flow_director_result *res = parsed_result;\n+\tstruct rte_port *port;\n+\tstruct rte_i40e_fdir_entry entry;\n+\tstruct rte_mbuf *m_pkt = NULL;\n+\tuint16_t flexwords[8];\n+\tenum rte_eth_command cmd;\n+\tint num_flexwords;\n+\tint ret = 0;\n+\n+\tmemset(flexwords, 0, sizeof(flexwords));\n+\tmemset(&entry, 0, sizeof(struct rte_i40e_fdir_entry));\n+\tnum_flexwords = parse_flexwords(res->flexwords_value, flexwords);\n+\tif (num_flexwords < 0) {\n+\t\tprintf(\"error: Cannot pase flexwords input.\\n\");\n+\t\treturn;\n+\t}\n+\tport = &ports[res->port_id];\n+\tm_pkt = tx_mbuf_alloc(port->i40e_fdir_mp);\n+\tif (m_pkt == NULL) {\n+\t\tprintf(\"error: Cannot malloc mbuf for fdir.\\n\");\n+\t\treturn;\n+\t}\n+\n+\tif (!strcmp(res->flow_type, \"ip4\")) {\n+\t\tstruct ipv4_other_flow ip4_flow;\n+\t\tmemset(&ip4_flow, 0, sizeof(struct ipv4_other_flow));\n+\t\t/* no need to convert, already big endian. */\n+\t\tif (res->ip_dst.family == AF_INET)\n+\t\t\tip4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_src.family == AF_INET)\n+\t\t\tip4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tip4_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(ip4_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_ip4_input(&ip4_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV4_OTHER;\n+\t} else if (!strcmp(res->flow_type, \"udp4\")) {\n+\t\tstruct ipv4_udp_flow udp4_flow;\n+\t\tmemset(&udp4_flow, 0, sizeof(struct ipv4_udp_flow));\n+\t\t/* no need to convert, already big endian. */\n+\t\tif (res->ip_dst.family == AF_INET)\n+\t\t\tudp4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_src.family == AF_INET)\n+\t\t\tudp4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\t/* need convert to big endian. */\n+\t\tudp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst);\n+\t\tudp4_flow.src_port = rte_cpu_to_be_16(res->port_src);\n+\t\tudp4_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(udp4_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_udp4_input(&udp4_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV4_UDP;\n+\t} else if (!strcmp(res->flow_type, \"tcp4\")) {\n+\t\tstruct ipv4_tcp_flow tcp4_flow;\n+\t\tmemset(&tcp4_flow, 0, sizeof(struct ipv4_tcp_flow));\n+\t\tif (res->ip_dst.family == AF_INET)\n+\t\t\ttcp4_flow.dst_ip = res->ip_dst.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_src.family == AF_INET)\n+\t\t\ttcp4_flow.src_ip = res->ip_src.addr.ipv4.s_addr;\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\t/* need convert to big endian. */\n+\t\ttcp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst);\n+\t\ttcp4_flow.src_port = rte_cpu_to_be_16(res->port_src);\n+\t\ttcp4_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(tcp4_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_tcp4_input(&tcp4_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV4_TCP;\n+\t} else if (!strcmp(res->flow_type, \"ip6\")) {\n+\t\tstruct ipv6_other_flow ip6_flow;\n+\t\tmemset(&ip6_flow, 0, sizeof(struct ipv6_other_flow));\n+\t\tif (res->ip_src.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(ip6_flow.src_ip),\n+\t\t\t\t\t &(res->ip_src.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_dst.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(ip6_flow.dst_ip),\n+\t\t\t\t\t &(res->ip_dst.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tip6_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(ip6_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_ip6_input(&ip6_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV6_OTHER;\n+\t} else if (!strcmp(res->flow_type, \"udp6\")) {\n+\t\tstruct ipv6_udp_flow udp6_flow;\n+\t\tmemset(&udp6_flow, 0, sizeof(struct ipv6_udp_flow));\n+\t\tif (res->ip_src.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(udp6_flow.src_ip),\n+\t\t\t\t\t &(res->ip_src.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_dst.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(udp6_flow.dst_ip),\n+\t\t\t\t\t &(res->ip_dst.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tudp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst);\n+\t\tudp6_flow.src_port = rte_cpu_to_be_16(res->port_src);\n+\t\tudp6_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(udp6_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_udp6_input(&udp6_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV6_UDP;\n+\t} else if (!strcmp(res->flow_type, \"tcp6\")) {\n+\t\tstruct ipv6_tcp_flow tcp6_flow;\n+\t\tmemset(&tcp6_flow, 0, sizeof(struct ipv6_tcp_flow));\n+\t\tif (res->ip_src.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(tcp6_flow.src_ip),\n+\t\t\t\t\t &(res->ip_src.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\tif (res->ip_dst.family == AF_INET6)\n+\t\t\t(void)rte_memcpy(&(tcp6_flow.dst_ip),\n+\t\t\t\t\t &(res->ip_dst.addr.ipv6),\n+\t\t\t\t\t sizeof(struct in6_addr));\n+\t\telse {\n+\t\t\tprintf(\"error paramters.\\n\");\n+\t\t\tgoto pktbuf_free;\n+\t\t}\n+\t\ttcp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst);\n+\t\ttcp6_flow.src_port = rte_cpu_to_be_16(res->port_src);\n+\t\ttcp6_flow.num_flexwords = num_flexwords;\n+\t\trte_memcpy(tcp6_flow.flexwords,\n+\t\t\t\t flexwords,\n+\t\t\t\t BYTES_PER_WORD * num_flexwords);\n+\t\trte_i40e_fdir_construct_tcp6_input(&tcp6_flow, m_pkt->pkt.data);\n+\t\tentry.input.pctype = ETH_PCTYPE_NONF_IPV6_TCP;\n+\t}\n+\tm_pkt->pkt.data_len = I40E_FDIR_PKT_LEN;\n+\tm_pkt->pkt.next = NULL;\n+\n+\tentry.input.data = m_pkt;\n+\tentry.input.dest_vsi = 0; /* if set to 0, will use main vsi by default*/\n+\tentry.input.flex_off = 0;  /*use 0 by default*/\n+\tif (!strcmp(res->drop, \"drop\"))\n+\t\tentry.action.drop = RTE_I40E_DEST_DROP_PACKET;\n+\telse\n+\t\tentry.action.drop = RTE_I40E_DEST_DIRECT_PACKET_QINDEX;\n+\t/* set to report FD ID by default temporary*/\n+\tentry.action.report_status = RTE_I40E_FDIR_REPORT_FD_ID;\n+\tentry.action.rx_queue = res->queue_id;\n+\t/* use 0 by default, will set it to fdir counter per dev */\n+\tentry.action.cnt_index = 0;\n+\tentry.soft_id = res->fd_id_value;\n+\tif (!strcmp(res->ops, \"add\"))\n+\t\tcmd = RTE_CMD_FDIR_RULE_ADD;\n+\telse\n+\t\tcmd = RTE_CMD_FDIR_RULE_DEL;\n+\tret = rte_eth_dev_rx_classification_filter_ctl(res->port_id, cmd, &entry);\n+\tif (ret < 0)\n+\t\tprintf(\"i40e flow director programming error,\"\n+\t\t\t\" return code = %d \\n\", ret);\n+pktbuf_free:\n+\trte_pktmbuf_free(entry.input.data);\n+}\n+\n+cmdline_parse_token_string_t cmd_i40e_flow_director_filter =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t flow_director_filter, \"i40e_flow_director_filter\");\n+cmdline_parse_token_num_t cmd_i40e_flow_director_port_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      port_id, UINT8);\n+cmdline_parse_token_string_t cmd_i40e_flow_director_ops =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t ops, \"add#del\");\n+cmdline_parse_token_string_t cmd_i40e_flow_director_flow =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t flow, \"flow\");\n+cmdline_parse_token_string_t cmd_i40e_flow_director_flow_type =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t flow_type, \"ip4#tcp4#udp4#ip6#tcp6#udp6\");\n+cmdline_parse_token_string_t cmd_i40e_flow_director_src =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t src, \"src\");\n+cmdline_parse_token_ipaddr_t cmd_i40e_flow_director_ip_src =\n+\tTOKEN_IPADDR_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t ip_src);\n+cmdline_parse_token_num_t cmd_i40e_flow_director_port_src =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      port_src, UINT16);\n+cmdline_parse_token_string_t cmd_i40e_flow_director_dst =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t dst, \"dst\");\n+cmdline_parse_token_ipaddr_t cmd_i40e_flow_director_ip_dst =\n+\tTOKEN_IPADDR_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t ip_dst);\n+cmdline_parse_token_num_t cmd_i40e_flow_director_port_dst =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      port_dst, UINT16);\n+cmdline_parse_token_string_t cmd_i40e_flow_director_flexwords =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t flexwords, \"flexwords\");\n+cmdline_parse_token_string_t cmd_i40e_flow_director_flexwords_value =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      flexwords_value, NULL);\n+cmdline_parse_token_string_t cmd_i40e_flow_director_drop =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t drop, \"drop#fwd\");\n+cmdline_parse_token_string_t cmd_i40e_flow_director_queue =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t queue, \"queue\");\n+cmdline_parse_token_num_t cmd_i40e_flow_director_queue_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      queue_id, UINT16);\n+cmdline_parse_token_string_t cmd_i40e_flow_director_fd_id =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t\t fd_id, \"fd_id\");\n+cmdline_parse_token_num_t cmd_i40e_flow_director_fd_id_value =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flow_director_result,\n+\t\t\t      fd_id_value, UINT32);\n+\n+cmdline_parse_inst_t cmd_i40e_add_del_ip_flow_director = {\n+\t.f = cmd_i40e_flow_director_parsed,\n+\t.data = NULL,\n+\t.help_str = \"add or delete a ip flow director entry on i40e NIC\",\n+\t.tokens = {\n+\t\t(void *)&cmd_i40e_flow_director_filter,\n+\t\t(void *)&cmd_i40e_flow_director_port_id,\n+\t\t(void *)&cmd_i40e_flow_director_ops,\n+\t\t(void *)&cmd_i40e_flow_director_flow,\n+\t\t(void *)&cmd_i40e_flow_director_flow_type,\n+\t\t(void *)&cmd_i40e_flow_director_src,\n+\t\t(void *)&cmd_i40e_flow_director_ip_src,\n+\t\t(void *)&cmd_i40e_flow_director_dst,\n+\t\t(void *)&cmd_i40e_flow_director_ip_dst,\n+\t\t(void *)&cmd_i40e_flow_director_flexwords,\n+\t\t(void *)&cmd_i40e_flow_director_flexwords_value,\n+\t\t(void *)&cmd_i40e_flow_director_drop,\n+\t\t(void *)&cmd_i40e_flow_director_queue,\n+\t\t(void *)&cmd_i40e_flow_director_queue_id,\n+\t\t(void *)&cmd_i40e_flow_director_fd_id,\n+\t\t(void *)&cmd_i40e_flow_director_fd_id_value,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_inst_t cmd_i40e_add_del_udp_flow_director = {\n+\t.f = cmd_i40e_flow_director_parsed,\n+\t.data = NULL,\n+\t.help_str = \"add or delete a udp/tcp flow director entry on i40e NIC\",\n+\t.tokens = {\n+\t\t(void *)&cmd_i40e_flow_director_filter,\n+\t\t(void *)&cmd_i40e_flow_director_port_id,\n+\t\t(void *)&cmd_i40e_flow_director_ops,\n+\t\t(void *)&cmd_i40e_flow_director_flow,\n+\t\t(void *)&cmd_i40e_flow_director_flow_type,\n+\t\t(void *)&cmd_i40e_flow_director_src,\n+\t\t(void *)&cmd_i40e_flow_director_ip_src,\n+\t\t(void *)&cmd_i40e_flow_director_port_src,\n+\t\t(void *)&cmd_i40e_flow_director_dst,\n+\t\t(void *)&cmd_i40e_flow_director_ip_dst,\n+\t\t(void *)&cmd_i40e_flow_director_port_dst,\n+\t\t(void *)&cmd_i40e_flow_director_flexwords,\n+\t\t(void *)&cmd_i40e_flow_director_flexwords_value,\n+\t\t(void *)&cmd_i40e_flow_director_drop,\n+\t\t(void *)&cmd_i40e_flow_director_queue,\n+\t\t(void *)&cmd_i40e_flow_director_queue_id,\n+\t\t(void *)&cmd_i40e_flow_director_fd_id,\n+\t\t(void *)&cmd_i40e_flow_director_fd_id_value,\n+\t\tNULL,\n+\t},\n+};\n+\n+struct cmd_i40e_flush_flow_director_result {\n+\tcmdline_fixed_string_t flush_flow_director;\n+\tuint8_t port_id;\n+};\n+\n+cmdline_parse_token_string_t cmd_i40e_flush_flow_director_flush =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_i40e_flush_flow_director_result,\n+\t\t\t\t flush_flow_director, \"i40e_flush_flow_director\");\n+cmdline_parse_token_num_t cmd_i40e_flush_flow_director_port_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_i40e_flush_flow_director_result,\n+\t\t\t      port_id, UINT8);\n+\n+static void\n+cmd_i40e_flush_flow_director_parsed(void *parsed_result,\n+\t\t\t  __attribute__((unused)) struct cmdline *cl,\n+\t\t\t  __attribute__((unused)) void *data)\n+{\n+\tstruct cmd_i40e_flow_director_result *res = parsed_result;\n+\tint ret = 0;\n+\n+\tret = rte_eth_dev_rx_classification_filter_ctl(res->port_id,\n+\t\t\tRTE_CMD_FDIR_FLUSH, NULL);\n+\tif (ret < 0)\n+\t\tprintf(\"i40e flow director table flushing error,\"\n+\t\t\t\" return code = %d \\n\", ret);\n+}\n+\n+cmdline_parse_inst_t cmd_i40e_flush_flow_director = {\n+\t.f = cmd_i40e_flush_flow_director_parsed,\n+\t.data = NULL,\n+\t.help_str = \"flush all flow director entries of a device on i40e NIC\",\n+\t.tokens = {\n+\t\t(void *)&cmd_i40e_flush_flow_director_flush,\n+\t\t(void *)&cmd_i40e_flush_flow_director_port_id,\n+\t\tNULL,\n+\t},\n+};\n+#endif /* RTE_LIBRTE_I40E_PMD */\n+\n /* ******************************************************************************** */\n \n /* list of instructions */\n@@ -7529,6 +8189,11 @@ cmdline_parse_ctx_t main_ctx[] = {\n \t(cmdline_parse_inst_t *)&cmd_add_flex_filter,\n \t(cmdline_parse_inst_t *)&cmd_remove_flex_filter,\n \t(cmdline_parse_inst_t *)&cmd_get_flex_filter,\n+#ifdef RTE_LIBRTE_I40E_PMD\n+\t(cmdline_parse_inst_t *)&cmd_i40e_add_del_ip_flow_director,\n+\t(cmdline_parse_inst_t *)&cmd_i40e_add_del_udp_flow_director,\n+\t(cmdline_parse_inst_t *)&cmd_i40e_flush_flow_director,\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \tNULL,\n };\n \ndiff --git a/app/test-pmd/config.c b/app/test-pmd/config.c\nindex 606e34a..86a52c3 100644\n--- a/app/test-pmd/config.c\n+++ b/app/test-pmd/config.c\n@@ -93,6 +93,10 @@\n #include <rte_ether.h>\n #include <rte_ethdev.h>\n #include <rte_string_fns.h>\n+#include <rte_eth_features.h>\n+#ifdef RTE_LIBRTE_I40E_PMD\n+#include <rte_i40e.h>\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \n #include \"testpmd.h\"\n \n@@ -1781,26 +1785,52 @@ fdir_remove_signature_filter(portid_t port_id,\n void\n fdir_get_infos(portid_t port_id)\n {\n-\tstruct rte_eth_fdir fdir_infos;\n+\tstruct rte_eth_dev_info dev_info;\n \n \tstatic const char *fdir_stats_border = \"########################\";\n \n \tif (port_id_is_invalid(port_id))\n \t\treturn;\n \n-\trte_eth_dev_fdir_get_infos(port_id, &fdir_infos);\n-\n \tprintf(\"\\n  %s FDIR infos for port %-2d     %s\\n\",\n \t       fdir_stats_border, port_id, fdir_stats_border);\n-\n-\tprintf(\"  collision: %-10\"PRIu64\"  free:     %\"PRIu64\"\\n\"\n-\t       \"  maxhash:   %-10\"PRIu64\"  maxlen:   %\"PRIu64\"\\n\"\n-\t       \"  add:       %-10\"PRIu64\"  remove:   %\"PRIu64\"\\n\"\n-\t       \"  f_add:     %-10\"PRIu64\"  f_remove: %\"PRIu64\"\\n\",\n-\t       (uint64_t)(fdir_infos.collision), (uint64_t)(fdir_infos.free),\n-\t       (uint64_t)(fdir_infos.maxhash), (uint64_t)(fdir_infos.maxlen),\n-\t       fdir_infos.add, fdir_infos.remove,\n-\t       fdir_infos.f_add, fdir_infos.f_remove);\n+\tmemset(&dev_info, 0, sizeof(dev_info));\n+\trte_eth_dev_info_get(port_id, &dev_info);\n+#ifdef RTE_LIBRTE_I40E_PMD\n+\tif (strstr(dev_info.driver_name, \"i40e\") != NULL) {\n+\t\tstruct rte_i40e_fdir_info i40e_fdir_info;\n+\t\tmemset(&i40e_fdir_info, 0, sizeof(struct rte_i40e_fdir_info));\n+\t\trte_eth_dev_rx_classification_filter_ctl(port_id,\n+\t\t\tRTE_CMD_FDIR_INFO_GET, (void *)&i40e_fdir_info);\n+\t\tif (i40e_fdir_info.mode) {\n+\t\t\tprintf(\"  FDIR is enabled\\n\");\n+\t\t\tprintf(\"  guarant_space: %-10\"PRIu16\n+\t\t\t       \"  best_space:     %\"PRIu16\"\\n\",\n+\t\t\t       i40e_fdir_info.guarant_spc,\n+\t\t\t       i40e_fdir_info.best_spc);\n+\t\t\tprintf(\"  guarant_count: %-10\"PRIu16\n+\t\t\t       \"  best_count:     %\"PRIu16\"\\n\",\n+\t\t\t       i40e_fdir_info.guarant_cnt,\n+\t\t\t       i40e_fdir_info.best_cnt);\n+\t\t} else\n+\t\t\tprintf(\"  FDIR is disabled\\n\");\n+\t} else {\n+#endif /* RTE_LIBRTE_I40E_PMD */\n+\t\tstruct rte_eth_fdir fdir_infos;\n+\n+\t\trte_eth_dev_fdir_get_infos(port_id, &fdir_infos);\n+\n+\t\tprintf(\"  collision: %-10\"PRIu64\"  free:     %\"PRIu64\"\\n\"\n+\t\t       \"  maxhash:   %-10\"PRIu64\"  maxlen:   %\"PRIu64\"\\n\"\n+\t\t       \"  add:       %-10\"PRIu64\"  remove:   %\"PRIu64\"\\n\"\n+\t\t       \"  f_add:     %-10\"PRIu64\"  f_remove: %\"PRIu64\"\\n\",\n+\t\t       (uint64_t)(fdir_infos.collision), (uint64_t)(fdir_infos.free),\n+\t\t       (uint64_t)(fdir_infos.maxhash), (uint64_t)(fdir_infos.maxlen),\n+\t\t       fdir_infos.add, fdir_infos.remove,\n+\t\t       fdir_infos.f_add, fdir_infos.f_remove);\n+#ifdef RTE_LIBRTE_I40E_PMD\n+\t}\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \tprintf(\"  %s############################%s\\n\",\n \t       fdir_stats_border, fdir_stats_border);\n }\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex a112559..f36866a 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -1688,6 +1688,28 @@ init_port_config(void)\n \t\tport = &ports[pid];\n \t\tport->dev_conf.rxmode = rx_mode;\n \t\tport->dev_conf.fdir_conf = fdir_conf;\n+#ifdef RTE_LIBRTE_I40E_PMD\n+#define I40E_FDIR_NB_MBUF          4\n+#define I40E_FDIR_MBUF_SIZE        (512 + sizeof(struct rte_mbuf))\n+#define I40E_FDIR_PKT_LEN          512\n+#define MEMPOOL_CACHE_SIZE         256\n+#define I40E_FDIR_MBUF_NAME        \"FDIR_MBUF_POOL\"\n+\n+\t\tport->i40e_fdir_mp = rte_mempool_lookup(I40E_FDIR_MBUF_NAME);\n+\t\tif (port->i40e_fdir_mp == NULL) {\n+\t\t\tport->i40e_fdir_mp = rte_mempool_create(I40E_FDIR_MBUF_NAME,\n+\t\t\t\tI40E_FDIR_NB_MBUF, I40E_FDIR_MBUF_SIZE,\n+\t\t\t\tMEMPOOL_CACHE_SIZE,\n+\t\t\t\tsizeof(struct rte_pktmbuf_pool_private),\n+\t\t\t\trte_pktmbuf_pool_init, NULL,\n+\t\t\t\trte_pktmbuf_init, NULL,\n+\t\t\t\t0, 0);\n+\n+\t\t\tif (port->i40e_fdir_mp == NULL)\n+\t\t\t\tprintf(\"error: Cannot init mbuf pool for\"\n+\t\t\t\t\t\"i40e flow director.\\n\");\n+\t\t}\n+#endif /* RTE_LIBRTE_I40E_PMD */\n \t\tif (nb_rxq > 1) {\n \t\t\tport->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;\n \t\t\tport->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf;\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex b8322a2..ddcc9e9 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -73,6 +73,9 @@ int main(int argc, char **argv);\n #define NUMA_NO_CONFIG 0xFF\n #define UMA_NO_CONFIG  0xFF\n \n+#define BYTES_PER_WORD  2\n+#define IPV6_ADDR_LEN 16\n+\n typedef uint8_t  lcoreid_t;\n typedef uint8_t  portid_t;\n typedef uint16_t queueid_t;\n@@ -155,6 +158,9 @@ struct rte_port {\n \tuint8_t\t\t\tdcb_flag;   /**< enable dcb */\n \tstruct rte_eth_rxconf   rx_conf;    /**< rx configuration */\n \tstruct rte_eth_txconf   tx_conf;    /**< tx configuration */\n+#ifdef RTE_LIBRTE_I40E_PMD\n+\tstruct rte_mempool      *i40e_fdir_mp;  /**< mempool used for fdir programing */\n+#endif /* RTE_LIBRTE_I40E_PMD */\n };\n \n /**\n@@ -352,6 +358,57 @@ extern uint32_t param_total_num_mbufs;\n \n extern struct rte_fdir_conf fdir_conf;\n \n+#ifdef RTE_LIBRTE_I40E_PMD\n+struct ipv4_udp_flow {\n+\tuint32_t src_ip;         /**< IPv4 source address to match. */\n+\tuint32_t dst_ip;         /**< IPv4 destination address to match. */\n+\tuint16_t src_port;       /**< UDP Source port to match. */\n+\tuint16_t dst_port;       /**< UDP Destination port to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+\n+struct ipv4_tcp_flow {\n+\tuint32_t src_ip;         /**< IPv4 source address to match. */\n+\tuint32_t dst_ip;         /**< IPv4 destination address to match. */\n+\tuint16_t src_port;       /**< TCP Source port to match. */\n+\tuint16_t dst_port;       /**< TCP Destination port to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+\n+struct ipv4_other_flow {\n+\tuint32_t src_ip;         /**< IPv4 source address to match. */\n+\tuint32_t dst_ip;         /**< IPv4 destination address to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+\n+struct ipv6_udp_flow {\n+\tuint32_t src_ip[4];      /**< IPv6 source address to match. */\n+\tuint32_t dst_ip[4];      /**< IPv6 destination address to match. */\n+\tuint16_t src_port;       /**< UDP Source port to match. */\n+\tuint16_t dst_port;       /**< UDP Destination port to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+\n+struct ipv6_tcp_flow {\n+\tuint32_t src_ip[4];      /**< IPv6 source address to match. */\n+\tuint32_t dst_ip[4];      /**< IPv6 destination address to match. */\n+\tuint16_t src_port;       /**< TCP Source port to match. */\n+\tuint16_t dst_port;       /**< TCP Destination port to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+\n+struct ipv6_other_flow {\n+\tuint32_t src_ip[4];      /**< IPv6 source address to match. */\n+\tuint32_t dst_ip[4];      /**< IPv6 destination address to match. */\n+\tuint8_t num_flexwords;   /**< number of the flexwords. */\n+\tuint16_t flexwords[8];   /**< flexwords in payload. */\n+};\n+#endif /* RTE_LIBRTE_I40E_PMD */\n /*\n  * Configuration of packet segments used by the \"txonly\" processing engine.\n  */\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "7/7"
    ]
}