diff --git a/examples/flow_classify/flow_classify.c b/examples/flow_classify/flow_classify.c
index e74a53be7..54ae65d46 100644
--- a/examples/flow_classify/flow_classify.c
+++ b/examples/flow_classify/flow_classify.c
@@ -708,10 +708,6 @@ add_classify_rule(struct rte_eth_ntuple_filter *ntuple_filter,
 		return ret;
 	}
 
-	/* XXX but this only adds table_type of  RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE
-	 * i.e., it only ever does allocate_acl_ipv4_5tuple_rule() so the tcp_flags is
-	 * ignored! 
-	 */
 	rule = rte_flow_classify_table_entry_add(
 			cls_app->cls, &attr, pattern_ipv4_5tuple,
 			actions, &key_found, &error);
@@ -838,7 +834,8 @@ main(int argc, char *argv[])
 	int ret;
 	int socket_id;
 	struct rte_table_acl_params table_acl_params;
-	struct rte_flow_classify_table_params cls_table_params;
+	struct rte_table_acl_params table_acl_tcp_params;
+	struct rte_flow_classify_table_params cls_table_params[2];
 	struct flow_classifier *cls_app;
 	struct rte_flow_classifier_params cls_params;
 	uint32_t size;
@@ -901,16 +898,34 @@ main(int argc, char *argv[])
 	memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
 
 	/* initialise table create params */
-	cls_table_params.ops = &rte_table_acl_ops;
-	cls_table_params.arg_create = &table_acl_params;
-	cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
+	cls_table_params[0].ops = &rte_table_acl_ops;
+	cls_table_params[0].arg_create = &table_acl_params;
+	cls_table_params[0].type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
+
+	/* initialise ACL table params */
+	table_acl_tcp_params.name = "table_acl_ipv4_tcp_5tuple";
+	table_acl_tcp_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
+	table_acl_tcp_params.n_rule_fields = RTE_DIM(ipv4_defs);
+	memcpy(table_acl_tcp_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+
+	/* initialise table create params */
+	cls_table_params[1].ops = &rte_table_acl_ops;
+	cls_table_params[1].arg_create = &table_acl_tcp_params;
+	cls_table_params[1].type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE;
 
-	ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params);
+	ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params[0]);
 	if (ret) {
 		rte_flow_classifier_free(cls_app->cls);
 		rte_free(cls_app);
 		rte_exit(EXIT_FAILURE, "Failed to create classifier table\n");
 	}
+	ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params[1]);
+	if (ret) {
+		rte_flow_classifier_free(cls_app->cls);
+		rte_free(cls_app);
+		rte_exit(EXIT_FAILURE, "Failed to create classifier table\n");
+	}
+
 
 	/* read file of IPv4 5 tuple rules and initialize parameters
 	 * for rte_flow_classify_validate and rte_flow_classify_table_entry_add
diff --git a/lib/librte_flow_classify/rte_flow_classify.c b/lib/librte_flow_classify/rte_flow_classify.c
index 5ff585803..4ec36a397 100644
--- a/lib/librte_flow_classify/rte_flow_classify.c
+++ b/lib/librte_flow_classify/rte_flow_classify.c
@@ -62,6 +62,7 @@ enum {
 	DST_FIELD_IPV4,
 	SRCP_FIELD_IPV4,
 	DSTP_FIELD_IPV4,
+	TCP_FLAGS_FIELD,
 	NUM_FIELDS_IPV4
 };
 
@@ -74,6 +75,7 @@ struct classify_rules {
 	enum rte_flow_classify_rule_type type;
 	union {
 		struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
+		struct rte_flow_classify_ipv4_tcp_5tuple ipv4_tcp_5tuple;
 	} u;
 };
 
@@ -482,6 +484,81 @@ allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier *cls)
 	return rule;
 }
 
+static struct rte_flow_classify_rule *
+allocate_acl_ipv4_tcp_5tuple_rule(struct rte_flow_classifier *cls)
+{
+	struct rte_flow_classify_rule *rule;
+	int log_level;
+
+	rule = malloc(sizeof(struct rte_flow_classify_rule));
+	if (!rule)
+		return rule;
+
+	memset(rule, 0, sizeof(struct rte_flow_classify_rule));
+	rule->id = unique_id++;
+	rule->rules.type = RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_TCP_5TUPLE;
+
+	/* key add values */
+	rule->u.key.key_add.priority = cls->ntuple_filter.priority;
+	rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].mask_range.u8 =
+			cls->ntuple_filter.proto_mask;
+	rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].value.u8 =
+			cls->ntuple_filter.proto;
+	rule->rules.u.ipv4_tcp_5tuple.proto = cls->ntuple_filter.proto;
+	rule->rules.u.ipv4_tcp_5tuple.proto_mask = cls->ntuple_filter.proto_mask;
+
+	rule->u.key.key_add.field_value[SRC_FIELD_IPV4].mask_range.u32 =
+			cls->ntuple_filter.src_ip_mask;
+	rule->u.key.key_add.field_value[SRC_FIELD_IPV4].value.u32 =
+			cls->ntuple_filter.src_ip;
+	rule->rules.u.ipv4_tcp_5tuple.src_ip_mask = cls->ntuple_filter.src_ip_mask;
+	rule->rules.u.ipv4_tcp_5tuple.src_ip = cls->ntuple_filter.src_ip;
+
+	rule->u.key.key_add.field_value[DST_FIELD_IPV4].mask_range.u32 =
+			cls->ntuple_filter.dst_ip_mask;
+	rule->u.key.key_add.field_value[DST_FIELD_IPV4].value.u32 =
+			cls->ntuple_filter.dst_ip;
+	rule->rules.u.ipv4_tcp_5tuple.dst_ip_mask = cls->ntuple_filter.dst_ip_mask;
+	rule->rules.u.ipv4_tcp_5tuple.dst_ip = cls->ntuple_filter.dst_ip;
+
+	rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
+			cls->ntuple_filter.src_port_mask;
+	rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].value.u16 =
+			cls->ntuple_filter.src_port;
+	rule->rules.u.ipv4_tcp_5tuple.src_port_mask =
+			cls->ntuple_filter.src_port_mask;
+	rule->rules.u.ipv4_tcp_5tuple.src_port = cls->ntuple_filter.src_port;
+
+	rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
+			cls->ntuple_filter.dst_port_mask;
+	rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].value.u16 =
+			cls->ntuple_filter.dst_port;
+	rule->rules.u.ipv4_tcp_5tuple.dst_port_mask =
+			cls->ntuple_filter.dst_port_mask;
+	rule->rules.u.ipv4_tcp_5tuple.dst_port = cls->ntuple_filter.dst_port;
+
+	rule->u.key.key_add.field_value[TCP_FLAGS_FIELD].mask_range.u32 =
+			rte_be_to_cpu_32(0xff);
+	rule->u.key.key_add.field_value[TCP_FLAGS_FIELD].value.u32 =
+			rte_be_to_cpu_32(cls->ntuple_filter.tcp_flags);
+	rule->rules.u.ipv4_tcp_5tuple.tcp_flags = cls->ntuple_filter.tcp_flags;
+
+	log_level = rte_log_get_level(librte_flow_classify_logtype);
+
+	if (log_level == RTE_LOG_DEBUG)
+		print_acl_ipv4_key_add(&rule->u.key.key_add);
+
+	/* key delete values */
+	memcpy(&rule->u.key.key_del.field_value[PROTO_FIELD_IPV4],
+	       &rule->u.key.key_add.field_value[PROTO_FIELD_IPV4],
+	       NUM_FIELDS_IPV4 * sizeof(struct rte_acl_field));
+
+	if (log_level == RTE_LOG_DEBUG)
+		print_acl_ipv4_key_delete(&rule->u.key.key_del);
+
+	return rule;
+}
+
 struct rte_flow_classify_rule *
 rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
 		const struct rte_flow_attr *attr,
@@ -519,6 +596,13 @@ rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
 		rule->tbl_type = table_type;
 		cls->table_mask |= table_type;
 		break;
+	case RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE:
+		rule = allocate_acl_ipv4_tcp_5tuple_rule(cls);
+		if (!rule)
+			return NULL;
+		rule->tbl_type = table_type;
+		cls->table_mask |= table_type;
+		break;
 	default:
 		return NULL;
 	}
diff --git a/lib/librte_flow_classify/rte_flow_classify.h b/lib/librte_flow_classify/rte_flow_classify.h
index 74d1ecaf5..921277f90 100644
--- a/lib/librte_flow_classify/rte_flow_classify.h
+++ b/lib/librte_flow_classify/rte_flow_classify.h
@@ -78,6 +78,8 @@ enum rte_flow_classify_rule_type {
 	RTE_FLOW_CLASSIFY_RULE_TYPE_NONE,
 	/** IPv4 5tuple type */
 	RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_5TUPLE,
+	/** IPv4 TCP 5tuple type */
+	RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_TCP_5TUPLE,
 };
 
 /** Flow classify table type */
@@ -90,6 +92,8 @@ enum rte_flow_classify_table_type {
 	RTE_FLOW_CLASSIFY_TABLE_ACL_VLAN_IP4_5TUPLE = 1 << 2,
 	/** ACL QinQ IP4 5TUPLE */
 	RTE_FLOW_CLASSIFY_TABLE_ACL_QINQ_IP4_5TUPLE = 1 << 3,
+	/** ACL IP4 5TUPLE with tcp_flags */
+	RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE = 1 << 4,
 
 };
 
@@ -129,6 +133,21 @@ struct rte_flow_classify_ipv4_5tuple {
 	uint8_t proto_mask;      /**< Mask of L4 protocol. */
 };
 
+/** IPv4 5-tuple data with tcp flags*/
+struct rte_flow_classify_ipv4_tcp_5tuple {
+	uint32_t dst_ip;         /**< Destination IP address in big endian. */
+	uint32_t dst_ip_mask;    /**< Mask of destination IP address. */
+	uint32_t src_ip;         /**< Source IP address in big endian. */
+	uint32_t src_ip_mask;    /**< Mask of destination IP address. */
+	uint16_t dst_port;       /**< Destination port in big endian. */
+	uint16_t dst_port_mask;  /**< Mask of destination port. */
+	uint16_t src_port;       /**< Source Port in big endian. */
+	uint16_t src_port_mask;  /**< Mask of source port. */
+	uint8_t proto;           /**< L4 protocol. */
+	uint8_t proto_mask;      /**< Mask of L4 protocol. */
+	uint8_t tcp_flags;       /**< Tcp only */
+};
+
 /**
  * Flow stats
  *
diff --git a/lib/librte_flow_classify/rte_flow_classify_parse.c b/lib/librte_flow_classify/rte_flow_classify_parse.c
index 465330291..fe4ee05b6 100644
--- a/lib/librte_flow_classify/rte_flow_classify_parse.c
+++ b/lib/librte_flow_classify/rte_flow_classify_parse.c
@@ -216,6 +216,7 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr,
 	const struct rte_flow_action_count *count;
 	const struct rte_flow_action_mark *mark_spec;
 	uint32_t index;
+	bool have_tcp = false;
 
 	/* parse pattern */
 	index = 0;
@@ -375,6 +376,8 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr,
 		filter->dst_port  = tcp_spec->hdr.dst_port;
 		filter->src_port  = tcp_spec->hdr.src_port;
 		filter->tcp_flags = tcp_spec->hdr.tcp_flags;
+		if (filter->tcp_flags != 0)
+			have_tcp = true;
 	} else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) {
 		udp_mask = item->mask;
 
@@ -434,7 +437,10 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr,
 		return -EINVAL;
 	}
 
-	table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
+	if (have_tcp)
+		table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE;
+	else
+		table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
 
 	/* parse attr */
 	/* must be input direction */
