[dpdk-dev] [PATCH][PMD][GENERIC_FILTER] add NIC filters support for generic filter feature

Jingjing Wu jingjing.wu at intel.com
Sat May 17 11:35:09 CEST 2014


A generic filter mechanism for handling special packet is required. It will allows filters 
to be set in HW when available for so that specific packets may be filtered by NICs to specific
desriptor queues for processing.
Currently only the Flow Director for Intel's 10GbE 82599 devices is available. Other types of filter 
are not supported.

This pacth adds following NIC filters used to assign different packets to certain receive queues.
 ethertype filter/syn filter/2tuple filter/flex filter for E1000(82580, i350)
 ethertype filter/syn filter/5tuple filter for 10G(82599)

Signed-off-by: jingjing.wu <jingjing.wu at intel.com>
---
 app/test-pmd/cmdline.c              | 905 +++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c               | 143 ++++++
 app/test-pmd/testpmd.h              |   6 +
 lib/librte_ether/rte_ethdev.c       | 300 ++++++++++++
 lib/librte_ether/rte_ethdev.h       | 429 ++++++++++++++++-
 lib/librte_pmd_e1000/e1000_ethdev.h |  38 ++
 lib/librte_pmd_e1000/igb_ethdev.c   | 512 ++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 365 +++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  33 ++
 9 files changed, 2729 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 7becedc..32787ae 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -113,6 +113,7 @@ static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
 		"    help ports      : Configuring ports.\n"
 		"    help flowdir    : Flow Director filter help.\n"
 		"    help registers  : Reading and setting port registers.\n"
+		"    help filters    : Filters configuration help.\n"
 		"    help all        : All of the above sections.\n\n"
 	);
 
@@ -550,6 +551,68 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"    Set single bit value of a port register.\n\n"
 		);
 	}
+	if (show_all || !strcmp(res->section, "filters")) {
+
+		cmdline_printf(
+			cl,
+			"\n"
+			"filters:\n"
+			"----------\n\n"
+			
+			"add_ethertype_filter (port_id) ethertype (eth_value)"
+			" priority (enable|disable)(pri_value) queue (queue_id) index (idx) \n"
+			"    add an ethertype filter.\n\n"
+
+			"remove_ethertype_filter (port_id) index (idx)\n"
+			"    remove an ethertype filter.\n\n"
+			
+			"get_ethertype_filter (port_id) index (idx)\n"
+			"	 get info of a ethertype filter.\n\n"
+		
+			"add_2tuple_filter (port_id) protocol (pro_value) (pro_mask)"
+			" dst_port (port_value) (port_mask) flags (flg_value) priority (prio_value)"
+			" queue (queue_id) index (idx)\n"
+			"    add a 2tuple filter.\n\n"
+
+			"remove_2tuple_filter (port_id) index (idx)\n"
+			"    remove a 2tuple filter.\n\n"
+			
+			"get_2tuple_filter (port_id) index (idx)\n"
+			"	 get info of a 2tuple filter.\n\n"
+
+			"add_5tuple_filter (port_id) dst_ip (dst_address) src_ip (src_address)"
+			" dst_port (dst_port_value) src_port (src_port_value) protocol (tcp|udp|sctp|none)"
+			" mask (mask_value) priority (prio_value) queue (queue_id) index (idx) \n"
+			"	 add a 5tuple filter.\n\n"
+			
+			"remove_5tuple_filter (port_id) index (idx)\n"
+			"	 remove a 5tuple filter.\n\n"
+			
+			"get_5tuple_filter (port_id) index (idx)\n"
+			"	 get info of a 5tuple filter.\n\n"
+
+			"add_syn_filter (port_id) priority (high|low) queue (queue_id)"
+			"	 add syn filter.\n\n"
+			
+			"remove_syn_filter (port_id)"
+			"	 remove syn filter.\n\n"
+
+			"get_syn_filter (port_id) "
+			"	 get syn filter info.\n\n"
+
+			"add_felx_filter (port_id) len (len_value) bytes (bytes_string) mask (mask_value)"
+			" priority (prio_value) queue (queue_id) index (idx) \n"
+			"	 add a flex filter.\n\n"
+			
+			"remove_flex_filter (port_id) index (idx)\n"
+			"	 remove a flex filter.\n\n"
+			
+			"get_flex_filter (port_id) index (idx)\n"
+			"	 get info of a flex filter.\n\n"
+		
+		);
+		
+	}
 }
 
 cmdline_parse_token_string_t cmd_help_long_help =
@@ -558,7 +621,7 @@ cmdline_parse_token_string_t cmd_help_long_help =
 cmdline_parse_token_string_t cmd_help_long_section =
 	TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
 			"all#control#display#config#flowdir#"
-			"ports#registers");
+			"ports#registers#filters");
 
 cmdline_parse_inst_t cmd_help_long = {
 	.f = cmd_help_long_parsed,
@@ -5107,6 +5170,831 @@ cmdline_parse_inst_t cmd_dump_one = {
 	},
 };
 
+/* *** ADD/REMOVE an ethertype FILTER *** */
+struct cmd_ethertype_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t ethertype;
+	uint16_t ethertype_value;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t priority_en;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_ethertype_filter_result *res = parsed_result;
+	struct rte_ethertype_filter filter;
+
+	
+	memset(&filter, 0, sizeof(struct rte_ethertype_filter));
+	filter.ethertype = rte_cpu_to_le_16(res->ethertype_value);
+	filter.priority = res->priority_value;
+	
+	if (!strcmp(res->priority_en, "enable"))
+		filter.priority_en = 1;
+	if (!strcmp(res->filter, "add_ethertype_filter"))
+		ret = rte_eth_dev_add_ethertype_filter(res->port_id, res->index_value,
+					  &filter, res->queue_id);
+	else if (!strcmp(res->filter, "remove_ethertype_filter"))
+		ret = rte_eth_dev_remove_ethertype_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_ethertype_filter"))
+		get_ethertype_filter(res->port_id, res->index_value);
+	
+	if (ret < 0)
+		printf("ethertype filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 ethertype, "ethertype");
+cmdline_parse_token_ipaddr_t cmd_ethertype_filter_ethertype_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				 ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority, "priority");
+cmdline_parse_token_string_t cmd_ethertype_filter_priority_en =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority_en, "enable#disable");
+cmdline_parse_token_num_t cmd_ethertype_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority_value, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_ethertype_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "add_ethertype_filter");
+cmdline_parse_inst_t cmd_add_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "add an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_add_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_ethertype,
+		(void *)&cmd_ethertype_filter_ethertype_value,
+		(void *)&cmd_ethertype_filter_priority,
+		(void *)&cmd_ethertype_filter_priority_en,
+		(void *)&cmd_ethertype_filter_priority_value,
+		(void *)&cmd_ethertype_filter_queue,
+		(void *)&cmd_ethertype_filter_queue_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "remove_ethertype_filter");
+cmdline_parse_inst_t cmd_remove_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "remove an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_remove_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_ethertype_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "get_ethertype_filter");
+cmdline_parse_inst_t cmd_get_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "get an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_get_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** set SYN filter *** */
+struct cmd_set_syn_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t high;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+};
+
+static void
+cmd_set_syn_filter_parsed(void *parsed_result,
+		       __attribute__((unused)) struct cmdline *cl,
+		       __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_set_syn_filter_result *res = parsed_result;
+	if (!strcmp(res->filter, "add_syn_filter")){
+		if(!strcmp(res->high, "high"))
+			ret = rte_eth_dev_add_syn_filter(res->port_id, 1, res->queue_id);
+		else
+			ret = rte_eth_dev_add_syn_filter(res->port_id, 0, res->queue_id);
+	}else if(!strcmp(res->filter, "remove_syn_filter"))
+		ret = rte_eth_dev_remove_syn_filter(res->port_id);
+	else if(!strcmp(res->filter, "get_syn_filter"))
+		get_syn_filter(res->port_id);
+	if(ret < 0)
+		printf("syn filter setting error: (%s)\n", strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_syn_filter_portid =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				 priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "add_syn_filter");
+cmdline_parse_token_string_t cmd_syn_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "remove_syn_filter");
+cmdline_parse_inst_t cmd_add_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "add syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_add_filter,
+			(void *)&cmd_syn_filter_portid,
+			(void *)&cmd_syn_filter_priority,
+			(void *)&cmd_syn_filter_high,
+			(void *)&cmd_syn_filter_queue,
+			(void *)&cmd_syn_filter_queue_id,
+			NULL,
+		},
+};
+cmdline_parse_inst_t cmd_remove_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "remove syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_remove_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+cmdline_parse_token_string_t cmd_syn_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "get_syn_filter");
+
+cmdline_parse_inst_t cmd_get_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "get syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_get_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	uint8_t protocol_mask;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	uint16_t dst_port_mask;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_2tuple_filter filter;
+	struct cmd_2tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_2tuple_filter));
+	
+	if (!strcmp(res->filter, "add_2tuple_filter")){
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.protocol = res->protocol_value;
+		filter.dst_port_mask = (res->dst_port_mask) ? 0 : 1;
+		filter.protocol_mask = (res->protocol_mask) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+		
+		ret = rte_eth_dev_add_2tuple_filter(res->port_id, res->index_value,
+				  &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_2tuple_filter"))
+		ret = rte_eth_dev_remove_2tuple_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_2tuple_filter"))
+		get_2tuple_filter(res->port_id, res->index_value);
+
+	if(ret < 0)
+		printf("2tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol, "protocol");
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol_value, UINT8);
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     protocol_mask, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     dst_port_value, UINT16);
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     dst_port_mask, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 flags, "flags");
+cmdline_parse_token_string_t cmd_2tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_2tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "add_2tuple_filter");
+cmdline_parse_inst_t cmd_add_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_add_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_protocol,
+		(void *)&cmd_2tuple_filter_protocol_value,
+		(void *)&cmd_2tuple_filter_protocol_mask,
+		(void *)&cmd_2tuple_filter_dst_port,
+		(void *)&cmd_2tuple_filter_dst_port_value,
+		(void *)&cmd_2tuple_filter_dst_port_mask,
+		(void *)&cmd_2tuple_filter_flags,
+		(void *)&cmd_2tuple_filter_flags_value,
+		(void *)&cmd_2tuple_filter_priority,
+		(void *)&cmd_2tuple_filter_priority_value,
+		(void *)&cmd_2tuple_filter_queue,
+		(void *)&cmd_2tuple_filter_queue_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_2tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "remove_2tuple_filter");
+cmdline_parse_inst_t cmd_remove_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_remove_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_2tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "get_2tuple_filter");
+cmdline_parse_inst_t cmd_get_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_get_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t dst_ip;
+	cmdline_ipaddr_t dst_ip_value;
+	cmdline_fixed_string_t src_ip;
+	cmdline_ipaddr_t src_ip_value;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	cmdline_fixed_string_t src_port;
+	uint16_t src_port_value;
+	cmdline_fixed_string_t protocol;
+	cmdline_fixed_string_t protocol_value;
+	cmdline_fixed_string_t mask;
+	uint8_t  mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_5tuple_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_5tuple_filter filter;
+	struct cmd_5tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_5tuple_filter));
+	
+	if (!strcmp(res->filter, "add_5tuple_filter")){
+		
+		filter.dst_ip_mask = (res->mask_value & 0x10) ? 0 : 1;
+		filter.src_ip_mask = (res->mask_value & 0x08) ? 0 : 1;
+		filter.dst_port_mask = (res->mask_value & 0x04) ? 0 : 1;
+		filter.src_port_mask = (res->mask_value & 0x02) ? 0 : 1;
+		filter.l4type_mask = (res->mask_value & 0x01) ? 0 : 1;
+		filter.priority = res->priority_value; 
+
+		if (res->dst_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr;
+		else{
+			if (filter.dst_ip_mask == 0){
+				printf("can not support ipv6 invovle compare. \n");
+				return;
+			}
+			filter.dst_ip = 0;
+		}
+		
+		if (res->src_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.src_ip = res->src_ip_value.addr.ipv4.s_addr;
+		else{
+			if (filter.src_ip_mask == 0){
+				printf("can not support ipv6 invovle compare. \n");
+				return;
+			}
+			filter.src_ip = 0;
+		}
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.src_port = rte_cpu_to_be_16(res->src_port_value);
+
+		if (!strcmp(res->protocol_value, "udp"))
+			filter.l4type = RTE_FILTER_L4TYPE_UDP;
+		else if (!strcmp(res->protocol_value, "tcp"))
+			filter.l4type = RTE_FILTER_L4TYPE_TCP;
+		else if (!strcmp(res->protocol_value, "sctp"))
+			filter.l4type = RTE_FILTER_L4TYPE_SCTP;
+		else 
+			filter.l4type = RTE_FILTER_L4TYPE_NONE;
+		
+		ret = rte_eth_dev_add_5tuple_filter(res->port_id, res->index_value,
+				  &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_5tuple_filter"))
+		ret = rte_eth_dev_remove_5tuple_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_5tuple_filter"))
+		get_5tuple_filter(res->port_id, res->index_value);
+	if(ret < 0)
+		printf("5tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+
+cmdline_parse_token_num_t cmd_5tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 dst_ip, "dst_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				 dst_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 src_ip, "src_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				 src_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			     dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 src_port, "src_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			     src_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 protocol, "protocol");
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 protocol_value, "tcp#udp#sctp#none");
+cmdline_parse_token_string_t cmd_5tuple_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 mask, "mask");
+cmdline_parse_token_num_t cmd_5tuple_filter_mask_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      mask_value, INT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_5tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      index_value, UINT16);
+
+cmdline_parse_token_string_t cmd_5tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "add_5tuple_filter");
+cmdline_parse_inst_t cmd_add_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_add_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_dst_ip,
+		(void *)&cmd_5tuple_filter_dst_ip_value,
+		(void *)&cmd_5tuple_filter_src_ip,
+		(void *)&cmd_5tuple_filter_src_ip_value,
+		(void *)&cmd_5tuple_filter_dst_port,
+		(void *)&cmd_5tuple_filter_dst_port_value,
+		(void *)&cmd_5tuple_filter_src_port,
+		(void *)&cmd_5tuple_filter_src_port_value,
+		(void *)&cmd_5tuple_filter_protocol,
+		(void *)&cmd_5tuple_filter_protocol_value,
+		(void *)&cmd_5tuple_filter_mask,
+		(void *)&cmd_5tuple_filter_mask_value,
+		(void *)&cmd_5tuple_filter_priority,
+		(void *)&cmd_5tuple_filter_priority_value,
+		(void *)&cmd_5tuple_filter_queue,
+		(void *)&cmd_5tuple_filter_queue_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "remove_5tuple_filter");
+cmdline_parse_inst_t cmd_remove_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_remove_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "get_5tuple_filter");
+cmdline_parse_inst_t cmd_get_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_get_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t len;
+	uint8_t len_value;
+	cmdline_fixed_string_t bytes;
+	cmdline_fixed_string_t bytes_value;
+	cmdline_fixed_string_t mask;
+	cmdline_fixed_string_t mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static int xdigit2val(unsigned char c)
+{
+	int val;
+	if(isdigit(c)) 
+		val = c - '0';
+	else if(isupper(c))
+		val = c - 'A' + 10;
+	else 
+		val = c - 'a' + 10;
+	return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_flex_filter filter;
+	struct cmd_flex_filter_result *res = parsed_result;
+	char * bytes_ptr, *mask_ptr;
+	uint16_t len, i, j;
+	char c;
+	int val, mod = 0;
+	uint32_t dword = 0;
+	uint8_t byte = 0;
+	uint8_t hex = 0;
+
+	if (!strcmp(res->filter, "add_flex_filter")){
+		if(res->len_value > 128){
+			printf("the len exceed the max length 128\n");
+			return;
+		}
+		memset(&filter, 0, sizeof(struct rte_flex_filter));
+		filter.len = res->len_value;
+		filter.priority = res->priority_value;
+		bytes_ptr = res->bytes_value;
+		mask_ptr = res->mask_value;
+
+		j = 0;
+		 /** translate bytes string to uint_32 array*/
+		if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+			(bytes_ptr[1] == 'X')) )
+			bytes_ptr += 2;
+		
+		len = strnlen(bytes_ptr, res->len_value * 2);
+		if (len == 0 || (len % 8 != 0)){
+			printf("please check len and bytes input\n");
+			return;
+		}
+		
+		for (i = 0; i < len; i++) { 
+			c = bytes_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			mod = i % 8;
+			if (i % 2){
+				byte |= val;
+				dword |= byte << (4 * mod - 4);
+				byte = 0;
+			}
+			else
+				byte |= val << 4;
+			if (mod == 7){
+				filter.dwords[j] = dword;
+				printf("dwords[%d]:%08x ",j, filter.dwords[j]);
+				j++;
+				dword = 0;
+			}
+		}
+		printf("\n");
+		 /** translate mask string to uint8_t array*/
+		j = 0;  
+		if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+			(mask_ptr[1] == 'X')) )
+			mask_ptr += 2;
+		len = strnlen(mask_ptr, (res->len_value+3)/4);
+		if (len == 0){
+			printf("invalid input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = mask_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			hex |= (uint8_t)(val & 0x8) >> 3;
+			hex |= (uint8_t)(val & 0x4) >> 1;
+			hex |= (uint8_t)(val & 0x2) << 1;
+			hex |= (uint8_t)(val & 0x1) << 3;
+
+			if (i % 2){
+				byte |= hex << 4;
+				filter.mask[j] = byte;
+				printf("mask[%d]:%02x ",j, filter.mask[j]);
+				j++;
+				byte = 0;
+			}
+			else
+				byte |= hex;
+			hex = 0;
+		}
+		printf("\n");
+		printf("call function rte_eth_dev_add_flex_filter: "
+			"index = %d, queue-id = %d, len = %d, priority = %d\n",
+			res->index_value, res->queue_id,
+			filter.len, filter.priority);
+		ret = rte_eth_dev_add_flex_filter(res->port_id, res->index_value,
+				  &filter, res->queue_id);
+		
+	}else if (!strcmp(res->filter, "remove_flex_filter"))
+		ret = rte_eth_dev_remove_flex_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_flex_filter"))
+		get_flex_filter(res->port_id, res->index_value);
+
+	if(ret < 0)
+		printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_len =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 len, "len");
+cmdline_parse_token_string_t cmd_flex_filter_len_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				 len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_flex_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_flex_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "add_flex_filter");
+cmdline_parse_inst_t cmd_add_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "add a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_add_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_len,
+		(void *)&cmd_flex_filter_len_value,
+		(void *)&cmd_flex_filter_bytes,
+		(void *)&cmd_flex_filter_bytes_value,
+		(void *)&cmd_flex_filter_mask,
+		(void *)&cmd_flex_filter_mask_value,
+		(void *)&cmd_flex_filter_priority,
+		(void *)&cmd_flex_filter_priority_value,
+		(void *)&cmd_flex_filter_queue,
+		(void *)&cmd_flex_filter_queue_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "remove_flex_filter");
+cmdline_parse_inst_t cmd_remove_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_remove_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "get_flex_filter");
+cmdline_parse_inst_t cmd_get_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "get a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_get_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -5189,6 +6077,21 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
 	(cmdline_parse_inst_t *)&cmd_dump,
 	(cmdline_parse_inst_t *)&cmd_dump_one,
+	(cmdline_parse_inst_t *)&cmd_add_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_get_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_add_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_get_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_add_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_get_flex_filter,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 134bf07..5d8b92f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1641,3 +1641,146 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 	       "diag=%d\n", port_id, diag);
 }
 
+void
+get_ethertype_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_ethertype_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_ethertype_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get ethertype filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: \n", index);
+		printf("    ethertype:  0x%04x  \n",
+			rte_le_to_cpu_32(filter.ethertype));
+		printf("    priority: %s, %d \n",
+			filter.priority_en ? "enable" : "disable",
+			filter.priority);
+		printf("    queue: %d \n", rx_queue);
+	}
+}
+
+void
+get_syn_filter(uint8_t port_id)
+{
+	struct rte_syn_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+	
+	if (ret < 0){
+		printf("get syn filter fails(%s)\n", strerror(-ret));
+		return;
+	}
+	printf("syn filter: %s, priority: %s, queue: %d\n", 
+		filter.enable? "on" : "off",
+		filter.hig_pri? "high" : "low",
+		rx_queue);
+}
+void
+get_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_2tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_2tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: \n", index);
+		printf("    Destination Port:       0x%04x    mask: %d  \n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    protocol:  0x%02x    mask:%d",
+			filter.protocol, filter.protocol_mask ? 0 : 1);
+		printf("    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
+
+void
+get_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_5tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	const char *protocol_type[] = {"tcp", "udp", "sctp", "none"};
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_5tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 5tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: \n", index);
+		printf("    Destination IP:  0x%08x    mask: %d  \n",
+			(unsigned)rte_be_to_cpu_32(filter.dst_ip),
+			filter.dst_ip_mask ? 0 : 1);
+		printf("    Source IP:       0x%08x    mask: %d  \n",
+			(unsigned)rte_be_to_cpu_32(filter.src_ip),
+			filter.src_ip_mask ? 0 : 1);
+		printf("    Destination Port:       0x%04x    mask: %d  \n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    Source Port:       0x%04x    mask: %d  \n",
+			rte_be_to_cpu_16(filter.src_port),
+			filter.src_port_mask ? 0 :1);
+		printf("    protocol_type: %s            mask: %d  \n",
+			protocol_type[filter.l4type],
+			filter.l4type_mask ? 0 : 1);
+		printf("    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
+void
+get_flex_filter(uint8_t port_id, uint16_t index)
+
+{
+	struct rte_flex_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	int i, j;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_flex_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get flex filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: ", index);
+		printf("\n    length: %d", filter.len);
+		printf("\n    dword[]: 0x");
+		for (i = 0; i < 32; i++)
+			printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i]));
+		printf("\n    mask[]: 0b");
+		for (i = 0; i < 16; i++){
+			for(j = 0; j < 8; j++){
+				printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0');
+			}
+		}
+		printf("\n    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 5b4ee6f..1b50898 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -521,6 +521,12 @@ void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
 void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, 
 		uint64_t vf_mask, uint8_t on);
 
+void get_syn_filter(uint8_t port_id);
+void get_ethertype_filter(uint8_t port_id, uint16_t index);
+void get_2tuple_filter(uint8_t port_id, uint16_t index);
+void get_5tuple_filter(uint8_t port_id, uint16_t index);
+void get_flex_filter(uint8_t port_id, uint16_t index);
+
 /*
  * Work-around of a compilation error with ICC on invocations of the
  * rte_be_to_cpu_16() function.
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a5727dd..ec411db 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -41,6 +41,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 
 #include <rte_byteorder.h>
 #include <rte_log.h>
@@ -2335,3 +2336,302 @@ rte_eth_dev_bypass_wd_reset(uint8_t port_id)
 	return 0;
 }
 #endif
+
+int
+rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+			uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 1;
+	filter.hig_pri = high_pri;
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_syn_filter(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 0;
+	filter.hig_pri = 0;
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, 0);
+}
+
+int
+rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+	
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_syn_filter, -ENOTSUP);
+	return(*dev->dev_ops->get_syn_filter)(dev, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+				struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->ethertype == ETHER_TYPE_IPv4 || filter->ethertype == ETHER_TYPE_IPv6){
+		PMD_DEBUG_TRACE("IP and IPv6 are not supported in ethertype filter\n");
+		return (-EINVAL);
+	}
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_ethertype_filter)(dev, index, 
+							filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_ethertype_filter(uint8_t port_id,  uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_ethertype_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, 
+				struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_ethertype_filter)(dev, index, 
+						filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_2tuple_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+	
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if ((filter->l4type == RTE_FILTER_L4TYPE_NONE) &&
+		(filter->dst_port_mask == 0 || filter->src_port_mask == 0)) {
+		PMD_DEBUG_TRACE(" the L4 protocol type is none, port are meaningless " \
+				"should not involve!\n");
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_5tuple_filter)(dev, index, filter, rx_queue);
+	
+}
+
+int
+rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_5tuple_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_5tuple_filter)(dev, index, filter,
+						rx_queue);
+}
+
+int
+rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_flex_filter)(dev, index, filter, rx_queue);
+	
+}
+
+int
+rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_flex_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
+						rx_queue);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index dea7471..cd4bec6 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -808,6 +808,81 @@ struct rte_eth_dev_callback;
 /** @internal Structure to keep track of registered callbacks */
 TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 
+
+/**
+ *  Possible l4type of 5tuple filters.
+ */
+enum rte_filter_l4type{
+	RTE_FILTER_L4TYPE_TCP = 0,
+	RTE_FILTER_L4TYPE_UDP,
+	RTE_FILTER_L4TYPE_SCTP,
+	RTE_FILTER_L4TYPE_NONE,
+};
+#define TCP_UGR_FLAG 0x20
+#define TCP_ACK_FLAG 0x10
+#define TCP_PSH_FLAG 0x08
+#define TCP_RST_FLAG 0x04
+#define TCP_SYN_FLAG 0x02
+#define TCP_FIN_FLAG 0x01
+#define TCP_FLAG_ALL 0x3F
+
+/**
+ *  A structure used to define an ethertype filter.
+ */
+struct rte_ethertype_filter{
+	uint16_t ethertype;  /**<little endian*/
+	uint8_t priority_en; /**<compare priority enable*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define an syn filter.
+ */
+struct rte_syn_filter{
+	uint8_t enable;  /**<1 means enable, 0 means disable*/
+	uint8_t hig_pri; /**< 1 means higher pri than 2tuple,5tupe, and flex filter, 0 means llower pri*/
+};
+
+/**
+ *  A structure used to define a 2tuple filter.
+ */
+struct rte_2tuple_filter{
+	uint16_t dst_port;  /**<big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**< used when more than one filter matches */
+	uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+			protocol_mask   : 1;
+};
+
+/**
+ *  A structure used to define a flex filter.
+ */
+struct rte_flex_filter{  /** for E1000 filters*/
+	uint16_t len;
+	uint32_t dwords[32];  /**<flex bytes in big endian*/
+	uint8_t mask[16];     /**<if mask bit is 1b, means compare corresponding byte in dwords*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define a 5tuple filter.
+ */
+struct rte_5tuple_filter{
+	uint32_t dst_ip;   /**<destination IP address in big endian*/
+	uint32_t src_ip;   /**<source IP address in big endian*/
+	uint16_t dst_port; /**<destination port in big endian*/
+	uint16_t src_port; /**<source Port big endian*/
+	enum rte_filter_l4type l4type; /**< l4type to match: TCP/UDP/SCTP/NONE. */
+	uint16_t priority; /**< seven evels (001b-111b),  111b is highest, used when more than one filter matches */
+	uint8_t dst_ip_mask   : 1, /**<	if mask is 1b, do not compare dst ip*/
+			src_ip_mask   : 1, /**<	if mask is 1b, do not compare src ip*/
+			dst_port_mask : 1, /**<	if mask is 1b, do not compare dst port*/
+			src_port_mask : 1, /**<	if mask is 1b, do not compare src port*/
+			l4type_mask   : 1; /**<	if mask is 1b, do not compare protocol*/
+};
+
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1076,6 +1151,69 @@ typedef int32_t (*bypass_ver_show_t)(struct rte_eth_dev *dev, uint32_t *ver);
 typedef int32_t (*bypass_wd_reset_t)(struct rte_eth_dev *dev);
 #endif
 
+typedef int (*eth_set_syn_filter_t)(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+/**< @internal Set syn filter rule on an Ethernet device */
+
+typedef int (*eth_get_syn_filter_t)(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+/**< @internal Get syn filter rule on an Ethernet device */
+
+typedef int (*eth_add_ethertype_filter_t)(struct rte_eth_dev *dev, 
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_remove_ethertype_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_get_ethertype_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_add_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_2tuple_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_2tuple_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_5tuple_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_5tuple_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_flex_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new flex filter rule on an Ethernet device */
+
+typedef int (*eth_remove_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a flex filter rule on an Ethernet device */
+
+typedef int (*eth_get_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_flex_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a flex filter rule on an Ethernet device */
 
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
@@ -1152,7 +1290,20 @@ struct eth_dev_ops {
   bypass_ver_show_t bypass_ver_show;
   bypass_wd_reset_t bypass_wd_reset;
 #endif
-
+	eth_set_syn_filter_t           set_syn_filter;  /**< set syn filter. */
+	eth_get_syn_filter_t           get_syn_filter;  /**< get syn filter. */
+	eth_add_ethertype_filter_t     add_ethertype_filter;  /**< add ethertype filter. */
+	eth_remove_ethertype_filter_t  remove_ethertype_filter;  /**< remove ethertype filter*/
+	eth_get_ethertype_filter_t     get_ethertype_filter;  /**< get ethertype filter*/
+	eth_add_2tuple_filter_t        add_2tuple_filter;  /**<add 2tuple filter */
+	eth_remove_2tuple_filter_t     remove_2tuple_filter;  /**< remove 2tuple filter*/
+	eth_get_2tuple_filter_t        get_2tuple_filter;  /**< get 2tuple filter*/
+	eth_add_5tuple_filter_t        add_5tuple_filter;  /**< add 5tuple filter*/
+	eth_remove_5tuple_filter_t     remove_5tuple_filter;  /**< remove 5tuple filter*/
+	eth_get_5tuple_filter_t        get_5tuple_filter;   /**< get 5tuple filter*/
+	eth_add_flex_filter_t        add_flex_filter;  /**< add flex filter*/
+	eth_remove_flex_filter_t     remove_flex_filter;  /**< remove flex filter*/
+	eth_get_flex_filter_t        get_flex_filter;  /**< get flex filter*/
 };
 
 /**
@@ -2859,6 +3010,282 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
  */
 int rte_eth_dev_bypass_wd_reset(uint8_t port);
 
+/**
+ * add syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the syn filter.
+ * @param high_pri
+ *    1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower priority
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+				uint8_t rx_queue);
+
+/**
+ * remove syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_remove_syn_filter(uint8_t port_id);
+
+/**
+ * get syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   The pointer to the structure describing the syn filter.
+ * @param rx_queue
+ *   the point of a int type to get the queue of syn filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_get_syn_filter(uint8_t port_id,
+					struct rte_syn_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @param filter
+ *   The pointer to the structure describing the ethertype filter rule.
+ *   The *rte_ethertype_filter* structure includes the values of the different fields
+ *   to match: ethertype and priority in vlan tag.
+ *   priority in vlan tag is not supported for E1000 dev.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, 
+					struct rte_ethertype_filter *filter, uint8_t rx_queue);
+/**
+ * remove an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_ethertype_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   A pointer to a structure of type *rte_ethertype_filter* to be filled with
+ *   the information of the Ethertype filter. 
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, 
+					struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+/**
+ * Add a new 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 2tuple filter rule.
+ *   The *rte_2tuple_filter* structure includes the values of the different fields
+ *   to match: protocol, dst_port and tcp_flags if the protocol is tcp type.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+
+int rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_2tuple_filter *filter, uint8_t rx_queue);
+/**
+ * remove a 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_2tuple_filter* to be filled with
+ *   the information of the 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 5tuple filter rule.
+ *   The *rte_5tuple_filter* structure includes the values of the different fields
+ *   to match: dst src IP, dst src port, l4type and relative masks..
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_5tuple_filter *filter, uint8_t rx_queue);
+
+/**
+ * remove a 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_5tuple_filter* to be filled with
+ *   the information of the 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   The pointer to the structure describing the flex filter rule.
+ *   The *rte_flex_filter* structure includes the values of the different fields
+ *   to match: the dwords (first len bytes of packet ) and relative masks.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+					struct rte_flex_filter *filter, uint8_t rx_queue);
+/**
+ * remove a flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_flex_filter* to be filled with
+ *   the information of the flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+					struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..6b11289 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -52,6 +52,44 @@
 #define E1000_CTRL_EXT_EXTEND_VLAN  (1<<26)    /* EXTENDED VLAN */
 #define IGB_VFTA_SIZE 128
 
+#define IGB_MAX_RX_QUEUE_NUM	8
+
+#define E1000_SYN_FILTER_ENABLE		0x00000001 /** syn filter enable field*/
+#define E1000_SYN_FILTER_QUEUE      0x0000000E /** syn filter queue field*/
+#define E1000_SYN_FILTER_QUEUE_SHIFT      1 /** syn filter queue field*/
+#define E1000_RFCTL_SYNQFP 			0x00080000 /** SYNQFP in RFCTL register*/
+
+#define E1000_ETQF_ETHERTYPE 0x0000FFFF
+#define E1000_ETQF_QUEUE 	 0x00070000
+#define E1000_ETQF_QUEUE_SHIFT 16
+#define E1000_MAX_ETQF_FILTERS 8
+
+#define E1000_IMIR_DSTPORT 		0x0000FFFF
+#define E1000_IMIR_PRIORITY 	0xE0000000
+#define E1000_IMIR_EXT_SIZE_BP	0x00001000
+#define E1000_IMIR_EXT_CTRL_UGR	0x00002000
+#define E1000_IMIR_EXT_CTRL_ACK	0x00004000
+#define E1000_IMIR_EXT_CTRL_PSH	0x00008000
+#define E1000_IMIR_EXT_CTRL_RST	0x00010000
+#define E1000_IMIR_EXT_CTRL_SYN	0x00020000
+#define E1000_IMIR_EXT_CTRL_FIN	0x00040000
+#define E1000_IMIR_EXT_CTRL_BP	0x00080000
+#define E1000_MAX_TTQF_FILTERS 	8
+#define E1000_2TUPLE_MAX_PRI   7
+
+#define E1000_MAX_FLEXIBLE_FILTERS 8
+#define E1000_MAX_FHFT 4
+#define E1000_MAX_FHFT_EXT 4
+#define E1000_MAX_FLEX_FILTER_PRI 7
+#define E1000_MAX_FLEX_FILTER_LEN 128
+#define E1000_FHFT_QUEUEING_LEN   		0x0000007F
+#define E1000_FHFT_QUEUEING_QUEUE 	0x00000700
+#define E1000_FHFT_QUEUEING_PRIO   	0x00070000
+#define E1000_FHFT_QUEUEING_OFFSET 		0xFC
+#define E1000_FHFT_QUEUEING_QUEUE_SHIFT 		8
+#define E1000_FHFT_QUEUEING_PRIO_SHIFT 		16
+#define IXGBE_WUFC_FLEX_HQ	0x00004000
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
 	uint32_t flags;
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 673b4de..478688f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -123,6 +123,28 @@ static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 		struct rte_eth_rss_reta *reta_conf);
 
+static int eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, 
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index);
+static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -193,6 +215,17 @@ static struct eth_dev_ops eth_igb_ops = {
 	.mac_addr_remove      = eth_igb_rar_clear,
 	.reta_update          = eth_igb_rss_reta_update,
 	.reta_query           = eth_igb_rss_reta_query,
+	.set_syn_filter		     = eth_igb_set_syn_filter,
+	.get_syn_filter          = eth_igb_get_syn_filter,
+	.add_ethertype_filter	 = eth_igb_add_ethertype_filter,
+	.remove_ethertype_filter = eth_igb_remove_ethertype_filter,
+	.get_ethertype_filter	 = eth_igb_get_ethertype_filter,
+	.add_2tuple_filter 	     = eth_igb_add_2tuple_filter,
+	.remove_2tuple_filter	 = eth_igb_remove_2tuple_filter,
+	.get_2tuple_filter	 	 = eth_igb_get_2tuple_filter,
+	.add_flex_filter 	     = eth_igb_add_flex_filter,
+	.remove_flex_filter	 	 = eth_igb_remove_flex_filter,
+	.get_flex_filter	 	 = eth_igb_get_flex_filter,
 };
 
 /*
@@ -2182,3 +2215,482 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
  
 	return 0;
 }
+
+#define MAC_TYPE_FILTER_SUP(type) 	do{\
+	if ((type) != e1000_82580 && (type) != e1000_i350) \
+		return -ENOSYS;\
+}while(0)
+
+/*
+ *set the syn filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	
+    if (filter->enable){
+		if (synqf & E1000_SYN_FILTER_ENABLE)
+			return (-EINVAL);
+		synqf = (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) & E1000_SYN_FILTER_QUEUE) |
+						E1000_SYN_FILTER_ENABLE);
+    }else
+		synqf = 0;
+	
+	if (filter->hig_pri)
+		rfctl |= E1000_RFCTL_SYNQFP;
+	else
+		rfctl &= ~E1000_RFCTL_SYNQFP;
+	
+	E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+	return 0;
+}
+
+/*
+ *get the syn filter's info
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	filter->enable = (synqf & E1000_SYN_FILTER_ENABLE)? 1 : 0;
+	filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE)>> E1000_SYN_FILTER_QUEUE_SHIFT);
+
+	return 0;
+}
+
+/*
+ *add an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE){
+		return (-EINVAL);  /**filter index is in use*/
+	}
+	else 
+		etqf = 0;
+		
+	etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
+	etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE);
+	etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT;
+	
+	if (filter->priority_en){
+		PMD_INIT_LOG(ERR, "vlan and priority (%d) is not support in E1000.\n",
+			filter->priority);
+		return (-EINVAL);
+	}
+	
+	E1000_WRITE_REG(hw, E1000_ETQF(index), etqf);
+	
+	return 0;
+}
+
+/*
+ *remove an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	E1000_WRITE_REG(hw, E1000_ETQF(index), 0);
+	
+	return 0;
+}
+
+/*
+ *gets an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+		
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE ){
+		filter->ethertype = etqf & E1000_ETQF_ETHERTYPE;
+		filter->priority_en = 0;
+		*rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ttqf, imir = 0;
+	uint32_t imir_ext = 0;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS ||
+		rx_queue >= IGB_MAX_RX_QUEUE_NUM || filter->priority > E1000_2TUPLE_MAX_PRI)
+		return (-EINVAL);  /**filter index is out of range*/
+	if  (filter->tcp_flags > TCP_FLAG_ALL)
+		return (-EINVAL);  /**flags is invalid*/
+	
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+
+	imir = (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+	if (filter->dst_port_mask == 1) /**1b means not compare*/
+		imir |= E1000_IMIR_PORT_BP;
+	else
+		imir &= ~E1000_IMIR_PORT_BP;
+
+	imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+	ttqf = 0;
+	ttqf |= E1000_TTQF_QUEUE_ENABLE;
+	ttqf |= (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT);
+	ttqf |= (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK);
+	if (filter->protocol_mask == 1)
+		ttqf |= E1000_TTQF_MASK_ENABLE;
+	else
+		ttqf &= ~E1000_TTQF_MASK_ENABLE;
+
+	imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+	/*tcp flags bits setting*/
+	if (filter->tcp_flags & TCP_FLAG_ALL){
+		if (filter->tcp_flags & TCP_UGR_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+		if (filter->tcp_flags & TCP_ACK_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+		if (filter->tcp_flags & TCP_PSH_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+		if (filter->tcp_flags & TCP_RST_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+		if (filter->tcp_flags & TCP_SYN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+		if (filter->tcp_flags & TCP_FIN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+		imir_ext &= ~E1000_IMIR_EXT_CTRL_BP;
+	}
+	else
+		imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+	E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+	E1000_WRITE_REG(hw, E1000_TTQF(index), ttqf);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+
+	return 0;
+}
+
+/*
+ *remove a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+
+}
+
+/*
+ *get a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t imir, ttqf;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE){
+		imir = E1000_READ_REG(hw, E1000_IMIR(index));
+		filter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;
+		filter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;
+		*rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >> E1000_TTQF_QUEUE_SHIFT;
+		filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+		filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+		filter->priority = (imir & E1000_IMIR_PRIORITY) >> E1000_IMIR_PRIORITY_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, en_bits = 0;
+	uint32_t queueing = 0;
+	uint32_t reg_off = 0;
+	uint8_t i, j= 0;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN||
+		filter->len % 8 != 0 || filter->priority > E1000_MAX_FLEX_FILTER_PRI)
+		return (-EINVAL);
+
+	
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	en_bits = IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+	if ((wufc & en_bits) == en_bits)
+		return (-EINVAL);  /**the filter is  enabled*/
+	
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc | IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index));
+	
+	j = 0;
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+	for (i = 0; i < 16; i++){
+		E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+2)*4, (uint32_t)filter->mask[i]);
+		++j;
+	}
+	queueing |= filter->len | (rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) |
+		(filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT);
+	E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing);
+	return 0;
+}
+
+/*
+ *remove a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+					   uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, reg_off = 0;
+	uint8_t i;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc &(~(E1000_WUFC_FLX0 << index)));
+	
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+	
+	for (i = 0; i < 64; i++)
+		E1000_WRITE_REG(hw, reg_off + i*4, 0);
+	return 0;
+}
+
+/*
+ *get a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: the pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, queueing, wufc_en = 0;
+	uint8_t i,j;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	wufc = E1000_READ_REG(hw,E1000_WUFC);
+	wufc_en = IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+	
+	if ((wufc & wufc_en) == wufc_en){
+		uint32_t reg_off = 0;
+		
+		j = 0;
+		if (index < E1000_MAX_FHFT)
+			reg_off = E1000_FHFT(index);
+		else
+			reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+		
+		for (i = 0; i < 16; i++, j = i * 2){
+			filter->dwords[j] = E1000_READ_REG(hw, reg_off + i*4*4);
+			filter->dwords[j+1] = E1000_READ_REG(hw, reg_off + (i*4+1)*4);
+			filter->mask[i] = E1000_READ_REG(hw, reg_off + (i*4+2)*4);
+		}
+		queueing =	E1000_READ_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET);
+		filter->len = queueing & E1000_FHFT_QUEUEING_LEN;
+		filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >> E1000_FHFT_QUEUEING_PRIO_SHIFT;
+		*rx_queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >> E1000_FHFT_QUEUEING_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 89ab4aa..49ff0d1 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -181,6 +181,22 @@ static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
 		uint8_t	rule_id);
 
+static int ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+static int ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, 
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index);
+static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -300,6 +316,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.bypass_ver_show      = ixgbe_bypass_ver_show,
 	.bypass_wd_reset      = ixgbe_bypass_wd_reset,
 #endif /* RTE_NIC_BYPASS */
+	.set_syn_filter		     = ixgbe_set_syn_filter,
+	.get_syn_filter          = ixgbe_get_syn_filter,
+	.add_ethertype_filter	 = ixgbe_add_ethertype_filter,
+	.remove_ethertype_filter = ixgbe_remove_ethertype_filter,
+	.get_ethertype_filter	 = ixgbe_get_ethertype_filter,
+	.add_5tuple_filter 	     = ixgbe_add_5tuple_filter,
+	.remove_5tuple_filter	 = ixgbe_remove_5tuple_filter,
+	.get_5tuple_filter	 	 = ixgbe_get_5tuple_filter,
 };
 
 /*
@@ -3060,3 +3084,344 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
 
 	return 0;
 }
+
+/*
+ * set the syn filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	
+    if (filter->enable)
+		synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
+			IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE);
+	else
+		synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
+
+	
+	if (filter->hig_pri)
+		synqf |= IXGBE_SYN_FILTER_SYNQFP;
+	else
+		synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
+	
+	return 0;
+}
+
+/*
+ * get the syn filter's info
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue)
+
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	filter->enable = (synqf & IXGBE_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & IXGBE_SYN_FILTER_QUEUE)>> 1);
+
+	return 0;
+}
+
+/*
+ * add an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, 
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs = 0;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS || rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN)
+		return (-EINVAL);  /** filter index is in use*/
+	
+	etqf = 0;
+	etqf |= IXGBE_ETQF_FILTER_EN;
+	etqf |= (uint32_t)filter->ethertype;
+	
+	if (filter->priority_en){
+		if (filter->priority > IXGBE_ETQF_MAX_PRI)
+			return (-EINVAL);
+		etqf |= (uint32_t)((filter->priority << IXGBE_ETQF_SHIFT ) & IXGBE_ETQF_UP);
+		etqf |= IXGBE_ETQF_UP_EN;
+	}
+	etqs |= (uint32_t)((rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE);
+	etqs |= IXGBE_ETQS_QUEUE_EN;
+	
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), etqf);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), etqs);
+	
+	return 0;
+}
+
+/*
+ * remove an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+					uint16_t index)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), 0);
+	
+	return 0;
+}
+
+/*
+ * gets an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_ethertype_filter(struct rte_eth_dev *dev,
+					uint16_t index, struct rte_ethertype_filter *filter,
+					uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN){
+		filter->ethertype = etqf & IXGBE_ETQF_ETHERTYPE;
+		filter->priority_en = (etqf & IXGBE_ETQF_UP_EN)? 1 : 0;
+		if (filter->priority_en)
+			filter->priority = (etqf & IXGBE_ETQF_UP) >> 16;
+		*rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT;
+		return 0;
+	}
+	
+	return (-ENOENT);
+}
+
+/*
+ * add a 5tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, sdpqf = 0;
+	uint32_t l34timir = 0;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_FTQF_FILTERS || rx_queue >= IXGBE_MAX_RX_QUEUE_NUM ||
+		filter->priority > IXGBE_5TUPLE_MAX_PRI ||
+		filter->priority < IXGBE_5TUPLE_MIN_PRI)
+		return (-EINVAL);  /** filter index is out of range*/
+	
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBR_FTQF_ENABLE)
+		return (-EINVAL);  /** filter index is in use*/
+	ftqf = 0;
+		
+	sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDQPF_DSTPORT_SHIFT);
+	sdpqf = sdpqf |(filter->src_port & IXGBE_SDQPF_SRCPORT);
+
+	ftqf |= (uint32_t)(filter->l4type & IXGBR_FTQF_PROTOCOL);
+	ftqf |= (uint32_t)((filter->priority << IXGBR_FTQF_PRIORITY_SHIFT) & IXGBR_FTQF_PRIORITY);
+	if (filter->src_ip_mask == 1) /** 1b means not compare*/
+		ftqf |= IXGBR_FTQF_SRCIP_MASK;
+	if (filter->dst_ip_mask == 1)
+		ftqf |= IXGBR_FTQF_DSTIP_MASK;
+	if (filter->src_port_mask == 1)
+		ftqf |= IXGBR_FTQF_SRCPORT_MASK;
+	if (filter->dst_port_mask == 1)
+		ftqf |= IXGBR_FTQF_DSTPORT_MASK;
+	if (filter->l4type_mask == 1)
+		ftqf |= IXGBR_FTQF_L4TYPE_MASK;
+	ftqf |= IXGBR_FTQF_POOL_MASK;
+	ftqf |= IXGBR_FTQF_ENABLE;
+	
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf);
+
+	l34timir |= IXGBE_L34T_IMIR_RESERVE ;
+	l34timir |= (uint32_t)(rx_queue << IXGBE_L34T_IMIR_QUEUE_SHIFT);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), l34timir);
+
+	return 0;
+}
+
+/*
+ * remove a 5tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+	
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0);
+	return 0;
+
+}
+
+/*
+ * get a 5tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t sdpqf, ftqf, l34timir;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+	
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBR_FTQF_ENABLE){
+		filter->l4type = (enum rte_filter_l4type)(ftqf & IXGBR_FTQF_PROTOCOL);
+		filter->priority = (ftqf & IXGBR_FTQF_PRIORITY) >> IXGBR_FTQF_PRIORITY_SHIFT;
+		filter->src_ip_mask = (ftqf & IXGBR_FTQF_SRCIP_MASK) ? 1 : 0;
+		filter->dst_ip_mask = (ftqf & IXGBR_FTQF_DSTIP_MASK) ? 1 : 0;
+		filter->src_port_mask = (ftqf & IXGBR_FTQF_SRCPORT_MASK) ? 1 : 0;
+		filter->dst_port_mask = (ftqf & IXGBR_FTQF_DSTPORT_MASK) ? 1 : 0;
+		filter->l4type_mask = (ftqf & IXGBR_FTQF_L4TYPE_MASK) ? 1 : 0;
+		
+		sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index));
+		filter->dst_port = (sdpqf & IXGBE_SDQPF_DSTPORT) >> IXGBE_SDQPF_DSTPORT_SHIFT;
+		filter->src_port = sdpqf & IXGBE_SDQPF_SRCPORT;
+		filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index));
+		filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index));
+
+		l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index));
+		*rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >> IXGBE_L34T_IMIR_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..7c6139b 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -67,6 +67,39 @@
 #define IXGBE_LPBK_82599_NONE		0x0 /* Default value. Loopback is disabled. */
 #define IXGBE_LPBK_82599_TX_RX		0x1 /* Tx->Rx loopback operation is enabled. */
 
+#define IXGBE_SYN_FILTER_ENABLE			0x00000001 /** syn filter enable field*/
+#define IXGBE_SYN_FILTER_QUEUE      	0x000000FE /** syn filter queue field*/
+#define IXGBE_SYN_FILTER_QUEUE_SHIFT 	1        /** syn filter queue field shift*/
+#define IXGBE_SYN_FILTER_SYNQFP     	0x80000000 /**syn filter SYNQFP*/
+
+#define IXGBE_ETQF_UP 			0x00070000 /** ethertype filter priority field*/ 
+#define IXGBE_ETQF_SHIFT 		16
+#define IXGBE_ETQF_UP_EN 		0x00080000
+#define IXGBE_ETQF_ETHERTYPE 	0x0000FFFF /** ethertype filter ethertype field*/
+#define IXGBE_ETQF_MAX_PRI 		7
+
+#define IXGBE_SDQPF_DSTPORT			0xFFFF0000 /** dst port field */
+#define IXGBE_SDQPF_DSTPORT_SHIFT	16 /** dst port field shift*/
+#define IXGBE_SDQPF_SRCPORT			0x0000FFFF /** src port field */
+#define IXGBR_FTQF_PROTOCOL			0x00000003 /** protocol */
+#define IXGBR_FTQF_PRIORITY			0x0000001C /** priority */
+#define IXGBR_FTQF_PRIORITY_SHIFT   2
+#define IXGBR_FTQF_SRCIP_MASK   	0x02000000 /** src IP mask */
+#define IXGBR_FTQF_DSTIP_MASK   	0x04000000 /** dst IP mask */
+#define IXGBR_FTQF_SRCPORT_MASK 	0x08000000 /** src port mask */
+#define IXGBR_FTQF_DSTPORT_MASK 	0x10000000 /** dst port mask */
+#define IXGBR_FTQF_L4TYPE_MASK		0x20000000 /** protocol mask */
+#define IXGBR_FTQF_POOL_MASK		0x40000000 /** pool mask */
+#define IXGBR_FTQF_ENABLE			0x80000000 /** enable bit */
+#define IXGBR_FTQF_PRIORITY_DEFAULT 0x00000004
+#define IXGBE_L34T_IMIR_SIZE_BP		0x00001000
+#define IXGBE_L34T_IMIR_RESERVE  	0x00080000 /** bit 13 to 19 must be set to 1000000b*/
+#define IXGBE_L34T_IMIR_LLI			0x00100000
+#define IXGBE_L34T_IMIR_QUEUE       0x0FE00000
+#define IXGBE_L34T_IMIR_QUEUE_SHIFT 21
+#define IXGBE_5TUPLE_MAX_PRI 		7
+#define IXGBE_5TUPLE_MIN_PRI 		1
+
 /*
  * Information about the fdir mode.
  */
-- 
1.8.1.4



More information about the dev mailing list