[dpdk-dev] [PATCH 1/3] lib/librte_flow_classify: remove table id parameter from apis

Iremonger, Bernard bernard.iremonger at intel.com
Wed Dec 6 13:34:07 CET 2017


Hi Jasvinder,

> > > -----Original Message-----
> > > From: Singh, Jasvinder
> > > Sent: Thursday, November 23, 2017 11:32 AM
> > > To: dev at dpdk.org
> > > Cc: Iremonger, Bernard <bernard.iremonger at intel.com>
> > > Subject: [PATCH 1/3] lib/librte_flow_classify: remove table id
> > > parameter from apis
> > >
> > > This patch removes table id parameter from all the flow classify
> > > apis to reduce the complexity and and does some cleanup of the code.
> > >
> > > The validate api has been exposed as public api to allows user to
> > > validate the flow before adding it to the classifier.
> > >
> > > The sample app and unit tests have been updated to accomodate the
> > > apis changes.
> > >
> > > Signed-off-by: Jasvinder Singh <jasvinder.singh at intel.com>
> > > ---
> > >  examples/flow_classify/flow_classify.c             |  27 +-
> > >  lib/librte_flow_classify/rte_flow_classify.c       | 320 +++++++++++----------
> > >  lib/librte_flow_classify/rte_flow_classify.h       |  74 +++--
> > >  lib/librte_flow_classify/rte_flow_classify_parse.c | 118 ++++----
> > > lib/librte_flow_classify/rte_flow_classify_parse.h |  16 +-
> > >  .../rte_flow_classify_version.map                  |   1 +
> > >  test/test/test_flow_classify.c                     |  86 +++---
> > >  test/test/test_flow_classify.h                     |  10 +-
> > >  8 files changed, 365 insertions(+), 287 deletions(-)
> > >

It would be better to break this patch into three patches, a librte_flow_classify patch, a flow_classify sample app patch, and a test_flow_classify patch.
 
flow_classify  test
> > > diff --git a/examples/flow_classify/flow_classify.c
> > > b/examples/flow_classify/flow_classify.c
> > > index 766f1dd..37e6904 100644
> > > --- a/examples/flow_classify/flow_classify.c
> > > +++ b/examples/flow_classify/flow_classify.c

The flow_classify sample app should exercise the rte_flow_classify_validate() and rte_flow_classifier_run() API's.
 
> > > @@ -94,7 +94,6 @@ static const struct rte_eth_conf port_conf_default
> > > = {
> > >
> > >  struct flow_classifier {
> > >  	struct rte_flow_classifier *cls;
> > > -	uint32_t table_id[RTE_FLOW_CLASSIFY_TABLE_MAX];
> > >  };
> > >
> > >  struct flow_classifier_acl {
> > > @@ -195,7 +194,15 @@ static struct rte_flow_item  end_item = {
> > > RTE_FLOW_ITEM_TYPE_END,
> > >  /* sample actions:
> > >   * "actions count / end"
> > >   */
> > > -static struct rte_flow_action count_action = {
> > > RTE_FLOW_ACTION_TYPE_COUNT, 0};
> > > +struct rte_flow_query_count count = {
> > > +	.reset = 1,
> > > +	.hits_set = 1,
> > > +	.bytes_set = 1,
> > > +	.hits = 0,
> > > +	.bytes = 0,
> > > +};
> > > +static struct rte_flow_action count_action = {
> > > RTE_FLOW_ACTION_TYPE_COUNT,
> > > +	&count};
> > >  static struct rte_flow_action end_action = {
> > > RTE_FLOW_ACTION_TYPE_END, 0};  static struct rte_flow_action
> > > actions[2];
> > >
> > > @@ -274,7 +281,7 @@ lcore_main(struct flow_classifier *cls_app)
> > >  	int i = 0;
> > >
> > >  	ret = rte_flow_classify_table_entry_delete(cls_app->cls,
> > > -			cls_app->table_id[0], rules[7]);
> > > +			rules[7]);
> > >  	if (ret)
> > >  		printf("table_entry_delete failed [7] %d\n\n", ret);
> > >  	else
> > > @@ -317,7 +324,6 @@ lcore_main(struct flow_classifier *cls_app)
> > >  				if (rules[i]) {
> > >  					ret = rte_flow_classifier_query(
> > >  						cls_app->cls,
> > > -						cls_app->table_id[0],
> > >  						bufs, nb_rx, rules[i],
> > >  						&classify_stats);
> > >  					if (ret)
> > > @@ -635,8 +641,8 @@ add_classify_rule(struct rte_eth_ntuple_filter
> > > *ntuple_filter,
> > >  	actions[1] = end_action;
> > >
> > >  	rule = rte_flow_classify_table_entry_add(
> > > -			cls_app->cls, cls_app->table_id[0], &key_found,
> > > -			&attr, pattern_ipv4_5tuple, actions, &error);
> > > +			cls_app->cls, &attr, pattern_ipv4_5tuple,
> > > +			actions, &key_found, &error);
> > >  	if (rule == NULL) {
> > >  		printf("table entry add failed ipv4_proto = %u\n",
> > >  			ipv4_proto);
> > > @@ -809,7 +815,6 @@ main(int argc, char *argv[])
> > >
> > >  	cls_params.name = "flow_classifier";
> > >  	cls_params.socket_id = socket_id;
> > > -	cls_params.type = RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL;
> > >
> > >  	cls_app->cls = rte_flow_classifier_create(&cls_params);
> > >  	if (cls_app->cls == NULL) {
> > > @@ -824,11 +829,11 @@ 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.ops = &rte_table_acl_ops;
> > > +	cls_table_params.arg_create = &table_acl_params;
> > > +	cls_table_params.type =
> > > RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
> > >
> > > -	ret = rte_flow_classify_table_create(cls_app->cls,
> > > &cls_table_params,
> > > -			&cls_app->table_id[0]);
> > > +	ret = rte_flow_classify_table_create(cls_app->cls,
> > > &cls_table_params);
> > >  	if (ret) {
> > >  		rte_flow_classifier_free(cls_app->cls);
> > >  		rte_free(cls_app);
> > > diff --git a/lib/librte_flow_classify/rte_flow_classify.c
> > > b/lib/librte_flow_classify/rte_flow_classify.c
> > > index e6f4486..ff1bc86 100644
> > > --- a/lib/librte_flow_classify/rte_flow_classify.c
> > > +++ b/lib/librte_flow_classify/rte_flow_classify.c
> > > @@ -39,16 +39,20 @@
> > >
> > >  int librte_flow_classify_logtype;
> > >
> > > -static struct rte_eth_ntuple_filter ntuple_filter;  static uint32_t
> > > unique_id = 1;
> > >
> > > +enum rte_flow_classify_table_type table_type
> > > +	= RTE_FLOW_CLASSIFY_TABLE_TYPE_NONE;
> > >
> > >  struct rte_flow_classify_table_entry {
> > >  	/* meta-data for classify rule */
> > >  	uint32_t rule_id;
> > > +
> > > +	/* Flow action */
> > > +	struct classify_action action;
> > >  };
> > >
> > > -struct rte_table {
> > > +struct rte_cls_table {
> > >  	/* Input parameters */
> > >  	struct rte_table_ops ops;
> > >  	uint32_t entry_size;
> > > @@ -64,11 +68,16 @@ struct rte_flow_classifier {
> > >  	/* Input parameters */
> > >  	char name[RTE_FLOW_CLASSIFIER_MAX_NAME_SZ];
> > >  	int socket_id;
> > > -	enum rte_flow_classify_table_type type;
> > >
> > > -	/* Internal tables */
> > > -	struct rte_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
> > > +	/* Internal */
> > > +	/* ntuple_fliter */
> > > +	struct rte_eth_ntuple_filter ntuple_filter;
> > > +
> > > +	/* clasifier tables */
> > > +	struct rte_cls_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
> > > +	uint32_t table_mask;
> > >  	uint32_t num_tables;
> > > +
> > >  	uint16_t nb_pkts;
> > >  	struct rte_flow_classify_table_entry
> > >  		*entries[RTE_PORT_IN_BURST_SIZE_MAX];
> > > @@ -97,18 +106,19 @@ struct classify_rules {
> > >
> > >  struct rte_flow_classify_rule {
> > >  	uint32_t id; /* unique ID of classify rule */
> > > -	struct rte_flow_action action; /* action when match found */
> > > +	enum rte_flow_classify_table_type tbl_type; /* rule table */
> > >  	struct classify_rules rules; /* union of rules */
> > >  	union {
> > >  		struct acl_keys key;
> > >  	} u;
> > >  	int key_found;   /* rule key found in table */
> > > -	void *entry;     /* pointer to buffer to hold rule meta data */
> > > +	struct rte_flow_classify_table_entry entry;  /* rule meta data */
> > >  	void *entry_ptr; /* handle to the table entry for rule meta data
> > > */ };
> > >
> > > -static int
> > > -flow_classify_parse_flow(
> > > +int
> > > +rte_flow_classify_validate(
> > > +		   struct rte_flow_classifier *cls,
> > >  		   const struct rte_flow_attr *attr,
> > >  		   const struct rte_flow_item pattern[],
> > >  		   const struct rte_flow_action actions[], @@ -120,7 +130,42
> > @@
> > > flow_classify_parse_flow(
> > >  	uint32_t i = 0;
> > >  	int ret;
> > >
> > > -	memset(&ntuple_filter, 0, sizeof(ntuple_filter));
> > > +	if (cls == NULL) {
> > > +		RTE_FLOW_CLASSIFY_LOG(ERR,
> > > +			"%s: rte_flow_classifier parameter is NULL\n",
> > > +			__func__);
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (!attr) {
> > > +		rte_flow_error_set(error, EINVAL,
> > > +				   RTE_FLOW_ERROR_TYPE_ATTR,
> > > +				   NULL, "NULL attribute.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (!pattern) {
> > > +		rte_flow_error_set(error,
> > > +			EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> > > +			NULL, "NULL pattern.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (!actions) {
> > > +		rte_flow_error_set(error, EINVAL,
> > > +				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
> > > +				   NULL, "NULL action.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (!error) {
> > > +		rte_flow_error_set(error, EINVAL,
> > > +				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > > +				   NULL, "NULL error.");
> > > +		return -EINVAL;
> > > +	}

The check on error, should be the first check and should not use rte_flow_error_set().

> > > +
> > > +	memset(&cls->ntuple_filter, 0, sizeof(cls->ntuple_filter));
> > >
> > >  	/* Get the non-void item number of pattern */
> > >  	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) { @@ -
> > > 150,7 +195,7 @@ flow_classify_parse_flow(
> > >  		return -EINVAL;
> > >  	}
> > >
> > > -	ret = parse_filter(attr, items, actions, &ntuple_filter, error);
> > > +	ret = parse_filter(attr, items, actions, &cls->ntuple_filter,
> > > +error);
> > >  	free(items);
> > >  	return ret;
> > >  }
> > > @@ -275,17 +320,14 @@ rte_flow_classifier_create(struct
> > > rte_flow_classifier_params *params)
> > >  	/* Save input parameters */
> > >  	snprintf(cls->name, RTE_FLOW_CLASSIFIER_MAX_NAME_SZ, "%s",
> > >  			params->name);
> > > -	cls->socket_id = params->socket_id;
> > > -	cls->type = params->type;
> > >
> > > -	/* Initialize flow classifier internal data structure */
> > > -	cls->num_tables = 0;
> > > +	cls->socket_id = params->socket_id;
> > >
> > >  	return cls;
> > >  }
> > >
> > >  static void
> > > -rte_flow_classify_table_free(struct rte_table *table)
> > > +rte_flow_classify_table_free(struct rte_cls_table *table)
> > >  {
> > >  	if (table->ops.f_free != NULL)
> > >  		table->ops.f_free(table->h_table);
> > > @@ -306,7 +348,7 @@ rte_flow_classifier_free(struct
> > > rte_flow_classifier
> > > *cls)
> > >
> > >  	/* Free tables */
> > >  	for (i = 0; i < cls->num_tables; i++) {
> > > -		struct rte_table *table = &cls->tables[i];
> > > +		struct rte_cls_table *table = &cls->tables[i];
> > >
> > >  		rte_flow_classify_table_free(table);
> > >  	}
> > > @@ -319,8 +361,7 @@ rte_flow_classifier_free(struct
> > > rte_flow_classifier
> > > *cls)
> > >
> > >  static int
> > >  rte_table_check_params(struct rte_flow_classifier *cls,
> > > -		struct rte_flow_classify_table_params *params,
> > > -		uint32_t *table_id)
> > > +		struct rte_flow_classify_table_params *params)
> > >  {
> > >  	if (cls == NULL) {
> > >  		RTE_FLOW_CLASSIFY_LOG(ERR,
> > > @@ -333,11 +374,6 @@ rte_table_check_params(struct
> > > rte_flow_classifier *cls,
> > >  			__func__);
> > >  		return -EINVAL;
> > >  	}
> > > -	if (table_id == NULL) {
> > > -		RTE_FLOW_CLASSIFY_LOG(ERR, "%s: table_id parameter is
> > > NULL\n",
> > > -			__func__);
> > > -		return -EINVAL;
> > > -	}
> > >
> > >  	/* ops */
> > >  	if (params->ops == NULL) {
> > > @@ -371,22 +407,18 @@ rte_table_check_params(struct
> > > rte_flow_classifier *cls,
> > >
> > >  int
> > >  rte_flow_classify_table_create(struct rte_flow_classifier *cls,
> > > -	struct rte_flow_classify_table_params *params,
> > > -	uint32_t *table_id)
> > > +	struct rte_flow_classify_table_params *params)
> > >  {
> > > -	struct rte_table *table;
> > > +	struct rte_cls_table *table;
> > >  	void *h_table;
> > > -	uint32_t entry_size, id;
> > > +	uint32_t entry_size;
> > >  	int ret;
> > >
> > >  	/* Check input arguments */
> > > -	ret = rte_table_check_params(cls, params, table_id);
> > > +	ret = rte_table_check_params(cls, params);
> > >  	if (ret != 0)
> > >  		return ret;
> > >
> > > -	id = cls->num_tables;
> > > -	table = &cls->tables[id];
> > > -
> > >  	/* calculate table entry size */
> > >  	entry_size = sizeof(struct rte_flow_classify_table_entry);
> > >
> > > @@ -400,8 +432,9 @@ rte_flow_classify_table_create(struct
> > > rte_flow_classifier *cls,
> > >  	}
> > >
> > >  	/* Commit current table to the classifier */
> > > +	table = &cls->tables[cls->num_tables];
> > > +	table->type = params->type;
> > >  	cls->num_tables++;
> > > -	*table_id = id;
> > >
> > >  	/* Save input parameters */
> > >  	memcpy(&table->ops, params->ops, sizeof(struct rte_table_ops)); @@
> > > -414,7 +447,7 @@ rte_flow_classify_table_create(struct
> > > rte_flow_classifier *cls,  }
> > >
> > >  static struct rte_flow_classify_rule *
> > > -allocate_acl_ipv4_5tuple_rule(void)
> > > +allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier *cls)
> > >  {
> > >  	struct rte_flow_classify_rule *rule;
> > >  	int log_level;
> > > @@ -427,45 +460,44 @@ allocate_acl_ipv4_5tuple_rule(void)
> > >  	rule->id = unique_id++;
> > >  	rule->rules.type = RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_5TUPLE;
> > >
> > > -	memcpy(&rule->action, classify_get_flow_action(),
> > > -	       sizeof(struct rte_flow_action));
> > > -
> > >  	/* key add values */
> > > -	rule->u.key.key_add.priority = ntuple_filter.priority;
> > > +	rule->u.key.key_add.priority = cls->ntuple_filter.priority;
> > >  	rule-
> > > >u.key.key_add.field_value[PROTO_FIELD_IPV4].mask_range.u8 =
> > > -			ntuple_filter.proto_mask;
> > > +			cls->ntuple_filter.proto_mask;
> > >  	rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].value.u8 =
> > > -			ntuple_filter.proto;
> > > -	rule->rules.u.ipv4_5tuple.proto = ntuple_filter.proto;
> > > -	rule->rules.u.ipv4_5tuple.proto_mask = ntuple_filter.proto_mask;
> > > +			cls->ntuple_filter.proto;
> > > +	rule->rules.u.ipv4_5tuple.proto = cls->ntuple_filter.proto;
> > > +	rule->rules.u.ipv4_5tuple.proto_mask = cls-
> > > >ntuple_filter.proto_mask;
> > >
> > >  	rule->u.key.key_add.field_value[SRC_FIELD_IPV4].mask_range.u32
> > > =
> > > -			ntuple_filter.src_ip_mask;
> > > +			cls->ntuple_filter.src_ip_mask;
> > >  	rule->u.key.key_add.field_value[SRC_FIELD_IPV4].value.u32 =
> > > -			ntuple_filter.src_ip;
> > > -	rule->rules.u.ipv4_5tuple.src_ip_mask = ntuple_filter.src_ip_mask;
> > > -	rule->rules.u.ipv4_5tuple.src_ip = ntuple_filter.src_ip;
> > > +			cls->ntuple_filter.src_ip;
> > > +	rule->rules.u.ipv4_5tuple.src_ip_mask = cls-
> > > >ntuple_filter.src_ip_mask;
> > > +	rule->rules.u.ipv4_5tuple.src_ip = cls->ntuple_filter.src_ip;
> > >
> > >  	rule->u.key.key_add.field_value[DST_FIELD_IPV4].mask_range.u32
> > > =
> > > -			ntuple_filter.dst_ip_mask;
> > > +			cls->ntuple_filter.dst_ip_mask;
> > >  	rule->u.key.key_add.field_value[DST_FIELD_IPV4].value.u32 =
> > > -			ntuple_filter.dst_ip;
> > > -	rule->rules.u.ipv4_5tuple.dst_ip_mask = ntuple_filter.dst_ip_mask;
> > > -	rule->rules.u.ipv4_5tuple.dst_ip = ntuple_filter.dst_ip;
> > > +			cls->ntuple_filter.dst_ip;
> > > +	rule->rules.u.ipv4_5tuple.dst_ip_mask = cls-
> > > >ntuple_filter.dst_ip_mask;
> > > +	rule->rules.u.ipv4_5tuple.dst_ip = cls->ntuple_filter.dst_ip;
> > >
> > >  	rule-
> > > >u.key.key_add.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
> > > -			ntuple_filter.src_port_mask;
> > > +			cls->ntuple_filter.src_port_mask;
> > >  	rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].value.u16 =
> > > -			ntuple_filter.src_port;
> > > -	rule->rules.u.ipv4_5tuple.src_port_mask =
> > > ntuple_filter.src_port_mask;
> > > -	rule->rules.u.ipv4_5tuple.src_port = ntuple_filter.src_port;
> > > +			cls->ntuple_filter.src_port;
> > > +	rule->rules.u.ipv4_5tuple.src_port_mask =
> > > +			cls->ntuple_filter.src_port_mask;
> > > +	rule->rules.u.ipv4_5tuple.src_port = cls->ntuple_filter.src_port;
> > >
> > >  	rule-
> > > >u.key.key_add.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
> > > -			ntuple_filter.dst_port_mask;
> > > +			cls->ntuple_filter.dst_port_mask;
> > >  	rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].value.u16 =
> > > -			ntuple_filter.dst_port;
> > > -	rule->rules.u.ipv4_5tuple.dst_port_mask =
> > > ntuple_filter.dst_port_mask;
> > > -	rule->rules.u.ipv4_5tuple.dst_port = ntuple_filter.dst_port;
> > > +			cls->ntuple_filter.dst_port;
> > > +	rule->rules.u.ipv4_5tuple.dst_port_mask =
> > > +			cls->ntuple_filter.dst_port_mask;
> > > +	rule->rules.u.ipv4_5tuple.dst_port = cls->ntuple_filter.dst_port;
> > >
> > >  	log_level = rte_log_get_level(librte_flow_classify_logtype);
> > >
> > > @@ -485,34 +517,18 @@ allocate_acl_ipv4_5tuple_rule(void)
> > >
> > >  struct rte_flow_classify_rule *
> > >  rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > > -		int *key_found,
> > >  		const struct rte_flow_attr *attr,
> > >  		const struct rte_flow_item pattern[],
> > >  		const struct rte_flow_action actions[],
> > > +		int *key_found,
> > >  		struct rte_flow_error *error)
> > >  {
> > >  	struct rte_flow_classify_rule *rule;
> > >  	struct rte_flow_classify_table_entry *table_entry;
> > > +	struct classify_action *action;
> > > +	uint32_t i;
> > >  	int ret;
> > >
> > > -	if (!error)
> > > -		return NULL;
> > > -
> > > -	if (!cls) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > > -				NULL, "NULL classifier.");
> > > -		return NULL;
> > > -	}
> > > -
> > > -	if (table_id >= cls->num_tables) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > > -				NULL, "invalid table_id.");
> > > -		return NULL;
> > > -	}
> > > -
> > >  	if (key_found == NULL) {
> > >  		rte_flow_error_set(error, EINVAL,
> > >  				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, @@ -
> 520,91 +536,95 @@
> > > rte_flow_classify_table_entry_add(struct
> > > rte_flow_classifier *cls,
> > >  		return NULL;
> > >  	}
> > >

The check on error should be restored as the first check.

> > > -	if (!pattern) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> > > -				NULL, "NULL pattern.");
> > > -		return NULL;
> > > -	}
> > > -
> > > -	if (!actions) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				RTE_FLOW_ERROR_TYPE_ACTION_NUM,
> > > -				NULL, "NULL action.");
> > > -		return NULL;
> > > -	}
> > > -
> > > -	if (!attr) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				RTE_FLOW_ERROR_TYPE_ATTR,
> > > -				NULL, "NULL attribute.");
> > > -		return NULL;
> > > -	}
> > > -
> > >  	/* parse attr, pattern and actions */
> > > -	ret = flow_classify_parse_flow(attr, pattern, actions, error);
> > > +	ret = rte_flow_classify_validate(cls, attr, pattern, actions,
> > > +error);
> > >  	if (ret < 0)
> > >  		return NULL;
> > >
> > > -	switch (cls->type) {
> > > -	case RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL:
> > > -		rule = allocate_acl_ipv4_5tuple_rule();
> > > +	switch (table_type) {
> > > +	case RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE:
> > > +		rule = allocate_acl_ipv4_5tuple_rule(cls);
> > >  		if (!rule)
> > >  			return NULL;
> > > +		rule->tbl_type = table_type;
> > > +		cls->table_mask |= table_type;
> > >  		break;
> > >  	default:
> > >  		return NULL;
> > >  	}
> > >
> > > -	rule->entry = malloc(sizeof(struct rte_flow_classify_table_entry));
> > > -	if (!rule->entry) {
> > > -		free(rule);
> > > -		return NULL;
> > > -	}
> > > -
> > > -	table_entry = rule->entry;
> > > +	action = classify_get_flow_action();
> > > +	table_entry = &rule->entry;
> > >  	table_entry->rule_id = rule->id;
> > > +	table_entry->action.action_mask = action->action_mask;
> > >
> > > -	if (cls->tables[table_id].ops.f_add != NULL) {
> > > -		ret = cls->tables[table_id].ops.f_add(
> > > -			cls->tables[table_id].h_table,
> > > -			&rule->u.key.key_add,
> > > -			rule->entry,
> > > -			&rule->key_found,
> > > -			&rule->entry_ptr);
> > > -		if (ret) {
> > > -			free(rule->entry);
> > > -			free(rule);
> > > -			return NULL;
> > > +	/* Copy actions */
> > > +	if (action->action_mask & (1LLU <<
> > > RTE_FLOW_ACTION_TYPE_COUNT)) {
> > > +		memcpy(&table_entry->action.act.counter, &action-
> > > >act.counter,
> > > +				sizeof(table_entry->action.act.counter));
> > > +	}
> > > +	if (action->action_mask & (1LLU <<
> > > RTE_FLOW_ACTION_TYPE_MARK)) {
> > > +		memcpy(&table_entry->action.act.mark, &action->act.mark,
> > > +				sizeof(table_entry->action.act.mark));
> > > +	}
> > > +
> > > +	for (i = 0; i < cls->num_tables; i++) {
> > > +		struct rte_cls_table *table = &cls->tables[i];
> > > +
> > > +		if (table->type == table_type) {
> > > +			if (table->ops.f_add != NULL) {
> > > +				ret = table->ops.f_add(
> > > +					table->h_table,
> > > +					&rule->u.key.key_add,
> > > +					&rule->entry,
> > > +					&rule->key_found,
> > > +					&rule->entry_ptr);
> > > +				if (ret) {
> > > +					free(rule);
> > > +					return NULL;
> > > +				}
> > > +
> > > +			*key_found = rule->key_found;
> > > +			}
> > > +
> > > +			return rule;
> > >  		}
> > > -		*key_found = rule->key_found;
> > >  	}
> > > -	return rule;
> > > +	return NULL;
> > >  }
> > >
> > >  int
> > >  rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > >  		struct rte_flow_classify_rule *rule)  {
> > > +	uint32_t i;
> > >  	int ret = -EINVAL;
> > >
> > > -	if (!cls || !rule || table_id >= cls->num_tables)
> > > +	if (!cls || !rule)
> > >  		return ret;
> > > +	enum rte_flow_classify_table_type tbl_type = rule->tbl_type;
> > >
> > > -	if (cls->tables[table_id].ops.f_delete != NULL)
> > > -		ret = cls->tables[table_id].ops.f_delete(
> > > -			cls->tables[table_id].h_table,
> > > -			&rule->u.key.key_del,
> > > -			&rule->key_found,
> > > -			&rule->entry);
> > > +	for (i = 0; i < cls->num_tables; i++) {
> > > +		struct rte_cls_table *table = &cls->tables[i];
> > >
> > > +		if (table->type == tbl_type) {
> > > +			if (table->ops.f_delete != NULL) {
> > > +				ret = table->ops.f_delete(table->h_table,
> > > +						&rule->u.key.key_del,
> > > +						&rule->key_found,
> > > +						&rule->entry);
> > > +
> > > +				return ret;
> > > +			}
> > > +		}
> > > +	}
> > > +	free(rule);
> > >  	return ret;
> > >  }
> > >
> > >  static int
> > >  flow_classifier_lookup(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > > +		struct rte_cls_table *table,
> > >  		struct rte_mbuf **pkts,
> > >  		const uint16_t nb_pkts)
> > >  {
> > > @@ -613,8 +633,7 @@ flow_classifier_lookup(struct rte_flow_classifier
> *cls,
> > >  	uint64_t lookup_hit_mask;
> > >
> > >  	pkts_mask = RTE_LEN2MASK(nb_pkts, uint64_t);
> > > -	ret = cls->tables[table_id].ops.f_lookup(
> > > -		cls->tables[table_id].h_table,
> > > +	ret = table->ops.f_lookup(table->h_table,
> > >  		pkts, pkts_mask, &lookup_hit_mask,
> > >  		(void **)cls->entries);
> > >
> > > @@ -632,12 +651,12 @@ action_apply(struct rte_flow_classifier *cls,
> > >  		struct rte_flow_classify_stats *stats)  {
> > >  	struct rte_flow_classify_ipv4_5tuple_stats *ntuple_stats;
> > > +	struct rte_flow_classify_table_entry *entry = &rule->entry;
> > >  	uint64_t count = 0;
> > > -	int i;
> > > -	int ret = -EINVAL;
> > > +	uint32_t action_mask = entry->action.action_mask;
> > > +	int i, ret = -EINVAL;
> > >
> > > -	switch (rule->action.type) {
> > > -	case RTE_FLOW_ACTION_TYPE_COUNT:
> > > +	if (action_mask & (1LLU << RTE_FLOW_ACTION_TYPE_COUNT)) {
> > >  		for (i = 0; i < cls->nb_pkts; i++) {
> > >  			if (rule->id == cls->entries[i]->rule_id)
> > >  				count++;
> > > @@ -650,32 +669,37 @@ action_apply(struct rte_flow_classifier *cls,
> > >  			ntuple_stats->counter1 = count;
> > >  			ntuple_stats->ipv4_5tuple = rule-
> > > >rules.u.ipv4_5tuple;
> > >  		}
> > > -		break;
> > > -	default:
> > > -		ret = -ENOTSUP;
> > > -		break;
> > >  	}
> > > -
> > >  	return ret;
> > >  }
> > >
> > >  int
> > >  rte_flow_classifier_query(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > >  		struct rte_mbuf **pkts,
> > >  		const uint16_t nb_pkts,
> > >  		struct rte_flow_classify_rule *rule,
> > >  		struct rte_flow_classify_stats *stats)  {
> > > +	enum rte_flow_classify_table_type tbl_type;
> > > +	uint32_t i;
> > >  	int ret = -EINVAL;
> > >
> > > -	if (!cls || !rule || !stats || !pkts  || nb_pkts == 0 ||
> > > -		table_id >= cls->num_tables)
> > > +	if (!cls || !rule || !stats || !pkts  || nb_pkts == 0)
> > >  		return ret;
> > >
> > > -	ret = flow_classifier_lookup(cls, table_id, pkts, nb_pkts);
> > > -	if (!ret)
> > > -		ret = action_apply(cls, rule, stats);
> > > +	tbl_type = rule->tbl_type;
> > > +	for (i = 0; i < cls->num_tables; i++) {
> > > +		struct rte_cls_table *table = &cls->tables[i];
> > > +
> > > +			if (table->type == tbl_type) {
> > > +				ret = flow_classifier_lookup(cls, table,
> > > +						pkts, nb_pkts);
> > > +				if (!ret) {
> > > +					ret = action_apply(cls, rule, stats);
> > > +					return ret;
> > > +				}
> > > +			}
> > > +	}
> > >  	return ret;
> > >  }
> > >
> > > diff --git a/lib/librte_flow_classify/rte_flow_classify.h
> > > b/lib/librte_flow_classify/rte_flow_classify.h
> > > index 1211873..b9b669f 100644
> > > --- a/lib/librte_flow_classify/rte_flow_classify.h
> > > +++ b/lib/librte_flow_classify/rte_flow_classify.h
> > > @@ -86,6 +86,10 @@ extern int librte_flow_classify_logtype;
> > > rte_log(RTE_LOG_ ## level, librte_flow_classify_logtype, "%s(): " fmt, \
> > >  	__func__, ## args)
> > >
> > > +#ifndef RTE_FLOW_CLASSIFY_TABLE_MAX
> > > +#define RTE_FLOW_CLASSIFY_TABLE_MAX		32
> > > +#endif
> > > +
> > >  /** Opaque data type for flow classifier */  struct
> > > rte_flow_classifier;
> > >
> > > @@ -102,17 +106,16 @@ enum rte_flow_classify_rule_type {
> > >
> > >  /** Flow classify table type */
> > >  enum rte_flow_classify_table_type {
> > > -	/** no type */
> > > -	RTE_FLOW_CLASSIFY_TABLE_TYPE_NONE,
> > > -	/** ACL type */
> > > -	RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL,
> > > -};
> > > +	/** No type */
> > > +	RTE_FLOW_CLASSIFY_TABLE_TYPE_NONE = 1 << 0,
> > > +	/** ACL IP4 5TUPLE */
> > > +	RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE = 1 << 1,
> > > +	/** ACL VLAN IP4 5TUPLE */
> > > +	RTE_FLOW_CLASSIFY_TABLE_ACL_VLAN_IP4_5TUPLE = 1 << 2,
> > > +	/** ACL QinQ IP4 5TUPLE */
> > > +	RTE_FLOW_CLASSIFY_TABLE_ACL_QINQ_IP4_5TUPLE = 1 << 3,
> > >
> > > -/**
> > > - * Maximum number of tables allowed for any Flow Classifier instance.
> > > - * The value of this parameter cannot be changed.
> > > - */
> > > -#define RTE_FLOW_CLASSIFY_TABLE_MAX  64
> > > +};
> > >
> > >  /** Parameters for flow classifier creation */  struct
> > > rte_flow_classifier_params { @@ -122,9 +125,6 @@ struct
> > > rte_flow_classifier_params {
> > >  	/** CPU socket ID where memory for the flow classifier and its */
> > >  	/** elements (tables) should be allocated */
> > >  	int socket_id;
> > > -
> > > -	/** Table type */
> > > -	enum rte_flow_classify_table_type type;
> > >  };
> > >
> > >  /** Parameters for table creation */ @@ -134,6 +134,9 @@ struct
> > > rte_flow_classify_table_params {
> > >
> > >  	/** Opaque param to be passed to the table create operation */
> > >  	void *arg_create;
> > > +
> > > +	/** Classifier table type */
> > > +	enum rte_flow_classify_table_type type;
> > >  };
> > >
> > >  /** IPv4 5-tuple data */
> > > @@ -197,32 +200,50 @@ rte_flow_classifier_free(struct
> > > rte_flow_classifier *cls);
> > >   *   Handle to flow classifier instance
> > >   * @param params
> > >   *   Parameters for flow_classify table creation
> > > - * @param table_id
> > > - *   Table ID. Valid only within the scope of table IDs of the current
> > > - *   classifier. Only returned after a successful invocation.
> > >   * @return
> > >   *   0 on success, error code otherwise
> > >   */
> > >  int
> > >  rte_flow_classify_table_create(struct rte_flow_classifier *cls,
> > > -		struct rte_flow_classify_table_params *params,
> > > -		uint32_t *table_id);
> > > +		struct rte_flow_classify_table_params *params);
> > > +
> > > +/**
> > > + * Flow classify validate
> > > + *
> > > + * @param cls
> > > + *   Handle to flow classifier instance
> > > + * @param[in] attr
> > > + *   Flow rule attributes
> > > + * @param[in] pattern
> > > + *   Pattern specification (list terminated by the END pattern item).
> > > + * @param[in] actions
> > > + *   Associated actions (list terminated by the END pattern item).
> > > + * @param[out] error
> > > + *   Perform verbose error reporting if not NULL. Structure
> > > + *   initialised in case of error only.
> > > + * @return
> > > + *   0 on success, error code otherwise
> > > + */
> > > +int
> > > +rte_flow_classify_validate(struct rte_flow_classifier *cls,
> > > +		const struct rte_flow_attr *attr,
> > > +		const struct rte_flow_item pattern[],
> > > +		const struct rte_flow_action actions[],
> > > +		struct rte_flow_error *error);
> > >
> > >  /**
> > >   * Add a flow classify rule to the flow_classifer table.
> > >   *
> > >   * @param[in] cls
> > >   *   Flow classifier handle
> > > - * @param[in] table_id
> > > - *   id of table
> > > - * @param[out] key_found
> > > - *  returns 1 if key present already, 0 otherwise.
> > >   * @param[in] attr
> > >   *   Flow rule attributes
> > >   * @param[in] pattern
> > >   *   Pattern specification (list terminated by the END pattern item).
> > >   * @param[in] actions
> > >   *   Associated actions (list terminated by the END pattern item).
> > > + * @param[out] key_found
> > > + *  returns 1 if rule present already, 0 otherwise.
> > >   * @param[out] error
> > >   *   Perform verbose error reporting if not NULL. Structure
> > >   *   initialised in case of error only.
> > > @@ -231,11 +252,10 @@ rte_flow_classify_table_create(struct
> > > rte_flow_classifier *cls,
> > >   */
> > >  struct rte_flow_classify_rule *
> > >  rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > > -		int *key_found,
> > >  		const struct rte_flow_attr *attr,
> > >  		const struct rte_flow_item pattern[],
> > >  		const struct rte_flow_action actions[],
> > > +		int *key_found,
> > >  		struct rte_flow_error *error);
> > >
> > >  /**
> > > @@ -243,8 +263,6 @@ rte_flow_classify_table_entry_add(struct
> > > rte_flow_classifier *cls,
> > >   *
> > >   * @param[in] cls
> > >   *   Flow classifier handle
> > > - * @param[in] table_id
> > > - *   id of table
> > >   * @param[in] rule
> > >   *   Flow classify rule
> > >   * @return
> > > @@ -252,7 +270,6 @@ rte_flow_classify_table_entry_add(struct
> > > rte_flow_classifier *cls,
> > >   */
> > >  int
> > >  rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > >  		struct rte_flow_classify_rule *rule);
> > >
> > >  /**
> > > @@ -260,8 +277,6 @@ rte_flow_classify_table_entry_delete(struct
> > > rte_flow_classifier *cls,
> > >   *
> > >   * @param[in] cls
> > >   *   Flow classifier handle
> > > - * @param[in] table_id
> > > - *   id of table
> > >   * @param[in] pkts
> > >   *   Pointer to packets to process
> > >   * @param[in] nb_pkts
> > > @@ -276,7 +291,6 @@ rte_flow_classify_table_entry_delete(struct
> > > rte_flow_classifier *cls,
> > >   */
> > >  int
> > >  rte_flow_classifier_query(struct rte_flow_classifier *cls,
> > > -		uint32_t table_id,
> > >  		struct rte_mbuf **pkts,
> > >  		const uint16_t nb_pkts,
> > >  		struct rte_flow_classify_rule *rule, diff --git
> > > a/lib/librte_flow_classify/rte_flow_classify_parse.c
> > > b/lib/librte_flow_classify/rte_flow_classify_parse.c
> > > index dbfa111..9fb3e51 100644
> > > --- a/lib/librte_flow_classify/rte_flow_classify_parse.c
> > > +++ b/lib/librte_flow_classify/rte_flow_classify_parse.c
> > > @@ -40,7 +40,7 @@ struct classify_valid_pattern {
> > >  	parse_filter_t parse_filter;
> > >  };
> > >
> > > -static struct rte_flow_action action;
> > > +static struct classify_action action;
> > >
> > >  /* Pattern for IPv4 5-tuple UDP filter */  static enum
> > > rte_flow_item_type pattern_ntuple_1[] = { @@ -80,7 +80,7 @@ static
> > > struct classify_valid_pattern classify_supported_patterns[] = {
> > >  	{ pattern_ntuple_3, classify_parse_ntuple_filter },  };
> > >
> > > -struct rte_flow_action *
> > > +struct classify_action *
> > >  classify_get_flow_action(void)
> > >  {
> > >  	return &action;
> > > @@ -244,28 +244,10 @@ classify_parse_ntuple_filter(const struct
> > > rte_flow_attr *attr,
> > >  	const struct rte_flow_item_udp *udp_mask;
> > >  	const struct rte_flow_item_sctp *sctp_spec;
> > >  	const struct rte_flow_item_sctp *sctp_mask;
> > > +	const struct rte_flow_action_count *count;
> > > +	const struct rte_flow_action_mark *mark_spec;
> > >  	uint32_t index;
> > >
> > > -	if (!pattern) {
> > > -		rte_flow_error_set(error,
> > > -			EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> > > -			NULL, "NULL pattern.");
> > > -		return -EINVAL;
> > > -	}
> > > -
> > > -	if (!actions) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
> > > -				   NULL, "NULL action.");
> > > -		return -EINVAL;
> > > -	}
> > > -	if (!attr) {
> > > -		rte_flow_error_set(error, EINVAL,
> > > -				   RTE_FLOW_ERROR_TYPE_ATTR,
> > > -				   NULL, "NULL attribute.");
> > > -		return -EINVAL;
> > > -	}
> > > -
> > >  	/* parse pattern */
> > >  	index = 0;
> > >
> > > @@ -483,34 +465,7 @@ classify_parse_ntuple_filter(const struct
> > > rte_flow_attr *attr,
> > >  		return -EINVAL;
> > >  	}
> > >
> > > -	/* parse action */
> > > -	index = 0;
> > > -
> > > -	/**
> > > -	 * n-tuple only supports count,
> > > -	 * check if the first not void action is COUNT.
> > > -	 */
> > > -	memset(&action, 0, sizeof(action));
> > > -	NEXT_ITEM_OF_ACTION(act, actions, index);
> > > -	if (act->type != RTE_FLOW_ACTION_TYPE_COUNT) {
> > > -		memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
> > > -		rte_flow_error_set(error, EINVAL,
> > > -			RTE_FLOW_ERROR_TYPE_ACTION,
> > > -			item, "Not supported action.");
> > > -		return -EINVAL;
> > > -	}
> > > -	action.type = RTE_FLOW_ACTION_TYPE_COUNT;
> > > -
> > > -	/* check if the next not void item is END */
> > > -	index++;
> > > -	NEXT_ITEM_OF_ACTION(act, actions, index);
> > > -	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
> > > -		memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
> > > -		rte_flow_error_set(error, EINVAL,
> > > -			RTE_FLOW_ERROR_TYPE_ACTION,
> > > -			act, "Not supported action.");
> > > -		return -EINVAL;
> > > -	}
> > > +	table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
> > >
> > >  	/* parse attr */
> > >  	/* must be input direction */
> > > @@ -542,5 +497,68 @@ classify_parse_ntuple_filter(const struct
> > > rte_flow_attr *attr,
> > >  	if (attr->priority >  FLOW_RULE_MIN_PRIORITY)
> > >  		filter->priority = FLOW_RULE_MAX_PRIORITY;
> > >
> > > +	/* parse action */
> > > +	index = 0;
> > > +
> > > +	/**
> > > +	 * n-tuple only supports count and Mark,
> > > +	 * check if the first not void action is COUNT or MARK.
> > > +	 */
> > > +	memset(&action, 0, sizeof(action));
> > > +	NEXT_ITEM_OF_ACTION(act, actions, index);
> > > +	switch (act->type) {
> > > +	case RTE_FLOW_ACTION_TYPE_COUNT:
> > > +		action.action_mask |= 1LLU <<
> > > RTE_FLOW_ACTION_TYPE_COUNT;
> > > +		count = (const struct rte_flow_action_count *)act->conf;
> > > +		memcpy(&action.act.counter, count,
> > > sizeof(action.act.counter));
> > > +		break;
> > > +	case RTE_FLOW_ACTION_TYPE_MARK:
> > > +		action.action_mask |= 1LLU <<
> > > RTE_FLOW_ACTION_TYPE_MARK;
> > > +		mark_spec = (const struct rte_flow_action_mark *)act-
> > > >conf;
> > > +		memcpy(&action.act.mark, mark_spec,
> > > sizeof(action.act.mark));
> > > +		break;
> > > +	default:
> > > +		memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
> > > +		rte_flow_error_set(error, EINVAL,
> > > +		   RTE_FLOW_ERROR_TYPE_ACTION, act,
> > > +		   "Invalid action.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	/* check if the next not void item is MARK or COUNT or END */
> > > +	index++;
> > > +	NEXT_ITEM_OF_ACTION(act, actions, index);
> > > +	switch (act->type) {
> > > +	case RTE_FLOW_ACTION_TYPE_COUNT:
> > > +		action.action_mask |= 1LLU <<
> > > RTE_FLOW_ACTION_TYPE_COUNT;
> > > +		count = (const struct rte_flow_action_count *)act->conf;
> > > +		memcpy(&action.act.counter, count,
> > > sizeof(action.act.counter));
> > > +		break;
> > > +	case RTE_FLOW_ACTION_TYPE_MARK:
> > > +		action.action_mask |= 1LLU <<
> > > RTE_FLOW_ACTION_TYPE_MARK;
> > > +		mark_spec = (const struct rte_flow_action_mark *)act-
> > > >conf;
> > > +		memcpy(&action.act.mark, mark_spec,
> > > sizeof(action.act.mark));
> > > +		break;
> > > +	case RTE_FLOW_ACTION_TYPE_END:
> > > +		return 0;
> > > +	default:
> > > +		memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
> > > +		rte_flow_error_set(error, EINVAL,
> > > +		   RTE_FLOW_ERROR_TYPE_ACTION, act,
> > > +		   "Invalid action.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	/* check if the next not void item is END */
> > > +	index++;
> > > +	NEXT_ITEM_OF_ACTION(act, actions, index);
> > > +	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
> > > +		memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
> > > +		rte_flow_error_set(error, EINVAL,
> > > +		   RTE_FLOW_ERROR_TYPE_ACTION, act,
> > > +		   "Invalid action.");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > >  	return 0;
> > >  }
> > > diff --git a/lib/librte_flow_classify/rte_flow_classify_parse.h
> > > b/lib/librte_flow_classify/rte_flow_classify_parse.h
> > > index 1d4708a..9c1de72 100644
> > > --- a/lib/librte_flow_classify/rte_flow_classify_parse.h
> > > +++ b/lib/librte_flow_classify/rte_flow_classify_parse.h
> > > @@ -43,6 +43,20 @@
> > >  extern "C" {
> > >  #endif
> > >
> > > +extern enum rte_flow_classify_table_type table_type;
> > > +
> > > +struct classify_action {
> > > +	/* Flow action mask */
> > > +	uint64_t action_mask;
> > > +
> > > +	struct action {
> > > +		/** Integer value to return with packets */
> > > +		struct rte_flow_action_mark mark;
> > > +		/** Flow rule counter */
> > > +		struct rte_flow_query_count counter;
> > > +	} act;
> > > +};
> > > +
> > >  typedef int (*parse_filter_t)(const struct rte_flow_attr *attr,
> > >  			      const struct rte_flow_item pattern[],
> > >  			      const struct rte_flow_action actions[], @@ -64,7
> > > +78,7 @@ parse_filter_t  classify_find_parse_filter_func(struct
> > > rte_flow_item *pattern);
> > >
> > >  /* get action data */
> > > -struct rte_flow_action *
> > > +struct classify_action *
> > >  classify_get_flow_action(void);
> > >
> > >  #ifdef __cplusplus
> > > diff --git a/lib/librte_flow_classify/rte_flow_classify_version.map
> > > b/lib/librte_flow_classify/rte_flow_classify_version.map
> > > index f7695cb..49bc25c 100644
> > > --- a/lib/librte_flow_classify/rte_flow_classify_version.map
> > > +++ b/lib/librte_flow_classify/rte_flow_classify_version.map
> > > @@ -7,6 +7,7 @@ EXPERIMENTAL {
> > >  	rte_flow_classify_table_create;
> > >  	rte_flow_classify_table_entry_add;
> > >  	rte_flow_classify_table_entry_delete;
> > > +	rte_flow_classify_validate;
> > >
> > >  	local: *;
> > >  };
> > > diff --git a/test/test/test_flow_classify.c
> > > b/test/test/test_flow_classify.c index 9f331cd..4ddf4c0 100644
> > > --- a/test/test/test_flow_classify.c
> > > +++ b/test/test/test_flow_classify.c
> > > @@ -51,16 +51,10 @@
> > >
> > >

Tests should be added for rte_flow_classify_validate() and rte_flow_classifier_run  API's

> > >  #define FLOW_CLASSIFY_MAX_RULE_NUM 100 -struct flow_classifier
> > > *cls;
> > > -
> > > -struct flow_classifier {
> > > -	struct rte_flow_classifier *cls;
> > > -	uint32_t table_id[RTE_FLOW_CLASSIFY_TABLE_MAX];
> > > -	uint32_t n_tables;
> > > -};
> > > +struct flow_classifier_acl *cls;
> > >
> > >  struct flow_classifier_acl {
> > > -	struct flow_classifier cls;
> > > +	struct rte_flow_classifier *cls;
> > >  } __rte_cache_aligned;
> > >
> > >  /*
> > > @@ -73,7 +67,7 @@ test_invalid_parameters(void)
> > >  	struct rte_flow_classify_rule *rule;
> > >  	int ret;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(NULL, 1, NULL, NULL,
> > > NULL,
> > > +	rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
> > >  			NULL, NULL);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classifier_table_entry_add", __LINE__);
> > @@
> > > -81,7 +75,7 @@ test_invalid_parameters(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(NULL, 1, NULL);
> > > +	ret = rte_flow_classify_table_entry_delete(NULL, NULL);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -89,14 +83,14 @@ test_invalid_parameters(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classifier_query(NULL, 1, NULL, 0, NULL, NULL);
> > > +	ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
> > >  	if (!ret) {
> > >  		printf("Line %i: flow_classifier_query", __LINE__);
> > >  		printf(" with NULL param should have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	rule = rte_flow_classify_table_entry_add(NULL, 1, NULL, NULL,
> > > NULL,
> > > +	rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
> > >  		NULL, &error);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add ", __LINE__);
> > @@
> > > -104,7 +98,7 @@ test_invalid_parameters(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(NULL, 1, NULL);
> > > +	ret = rte_flow_classify_table_entry_delete(NULL, NULL);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -112,7 +106,7 @@ test_invalid_parameters(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classifier_query(NULL, 1, NULL, 0, NULL, NULL);
> > > +	ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
> > >  	if (!ret) {
> > >  		printf("Line %i: flow_classifier_query", __LINE__);
> > >  		printf(" with NULL param should have failed!\n"); @@ -
> > > 142,15 +136,16 @@ test_valid_parameters(void)
> > >  	actions[0] = count_action;
> > >  	actions[1] = end_action;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > > +
> > >  	if (!rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should not have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -183,15 +178,15 @@ test_invalid_patterns(void)
> > >
> > >  	pattern[0] = eth_item;
> > >  	pattern[1] = ipv4_udp_item_bad;
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -202,15 +197,15 @@ test_invalid_patterns(void)
> > >  	pattern[1] = ipv4_udp_item_1;
> > >  	pattern[2] = udp_item_bad;
> > >  	pattern[3] = end_item_bad;
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -241,15 +236,15 @@ test_invalid_actions(void)
> > >  	actions[0] = count_action_bad;
> > >  	actions[1] = end_action;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -260,15 +255,15 @@ test_invalid_actions(void)
> > >  	actions[0] = count_action;
> > >  	actions[1] = end_action_bad;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (!ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -462,15 +457,15 @@ test_query_udp(void)
> > >  	actions[0] = count_action;
> > >  	actions[1] = end_action;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (!rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should not have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classifier_query(cls->cls, 0, bufs, MAX_PKT_BURST,
> > > +	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
> > >  			rule, &udp_classify_stats);
> > >  	if (ret) {
> > >  		printf("Line %i: flow_classifier_query", __LINE__); @@ -
> > > 478,7 +473,7 @@ test_query_udp(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -520,15 +515,15 @@ test_query_tcp(void)
> > >  	actions[0] = count_action;
> > >  	actions[1] = end_action;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (!rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should not have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classifier_query(cls->cls, 0, bufs, MAX_PKT_BURST,
> > > +	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
> > >  			rule, &tcp_classify_stats);
> > >  	if (ret) {
> > >  		printf("Line %i: flow_classifier_query", __LINE__); @@ -
> > > 536,7 +531,7 @@ test_query_tcp(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -578,15 +573,15 @@ test_query_sctp(void)
> > >  	actions[0] = count_action;
> > >  	actions[1] = end_action;
> > >
> > > -	rule = rte_flow_classify_table_entry_add(cls->cls, 0, &key_found,
> > > -			&attr, pattern, actions, &error);
> > > +	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
> > > +			actions, &key_found, &error);
> > >  	if (!rule) {
> > >  		printf("Line %i: flow_classify_table_entry_add", __LINE__);
> > >  		printf(" should not have failed!\n");
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classifier_query(cls->cls, 0, bufs, MAX_PKT_BURST,
> > > +	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
> > >  			rule, &sctp_classify_stats);
> > >  	if (ret) {
> > >  		printf("Line %i: flow_classifier_query", __LINE__); @@ -
> > > 594,7 +589,7 @@ test_query_sctp(void)
> > >  		return -1;
> > >  	}
> > >
> > > -	ret = rte_flow_classify_table_entry_delete(cls->cls, 0, rule);
> > > +	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
> > >  	if (ret) {
> > >  		printf("Line %i: rte_flow_classify_table_entry_delete",
> > >  			__LINE__);
> > > @@ -622,7 +617,6 @@ test_flow_classify(void)
> > >
> > >  	cls_params.name = "flow_classifier";
> > >  	cls_params.socket_id = socket_id;
> > > -	cls_params.type = RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL;
> > >  	cls->cls = rte_flow_classifier_create(&cls_params);
> > >
> > >  	/* initialise ACL table params */
> > > @@ -632,11 +626,11 @@ test_flow_classify(void)
> > >  	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.ops = &rte_table_acl_ops;
> > > +	cls_table_params.arg_create = &table_acl_params;
> > > +	cls_table_params.type =
> > > RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
> > >
> > > -	ret = rte_flow_classify_table_create(cls->cls, &cls_table_params,
> > > -			&cls->table_id[0]);
> > > +	ret = rte_flow_classify_table_create(cls->cls, &cls_table_params);
> > >  	if (ret) {
> > >  		printf("Line %i: f_create has failed!\n", __LINE__);
> > >  		rte_flow_classifier_free(cls->cls);
> > > diff --git a/test/test/test_flow_classify.h
> > > b/test/test/test_flow_classify.h index 39535cf..af293ed 100644
> > > --- a/test/test/test_flow_classify.h
> > > +++ b/test/test/test_flow_classify.h
> > > @@ -197,7 +197,15 @@ static struct rte_flow_item  sctp_item_1 = {
> > > RTE_FLOW_ITEM_TYPE_SCTP,
> > >  /* test actions:
> > >   * "actions count / end"
> > >   */
> > > -static struct rte_flow_action count_action = {
> > > RTE_FLOW_ACTION_TYPE_COUNT, 0};
> > > +struct rte_flow_query_count count = {
> > > +	.reset = 1,
> > > +	.hits_set = 1,
> > > +	.bytes_set = 1,
> > > +	.hits = 0,
> > > +	.bytes = 0,
> > > +};
> > > +static struct rte_flow_action count_action = {
> > > RTE_FLOW_ACTION_TYPE_COUNT,
> > > +	&count};
> > >  static struct rte_flow_action count_action_bad = { -1, 0};
> > >
> > >  static struct rte_flow_action end_action = {
> > > RTE_FLOW_ACTION_TYPE_END, 0};
> > > --
> > > 2.9.3
> >
> > This patch fails to apply to the 18.02 master branch, a rebase may be needed.
> >
> > Regards,
> >
> > Bernard.
> 
> False alarm, the patch applies ok on a fresh checkout.
> 
> Regards,
> 
> Bernard.



More information about the dev mailing list