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

Jasvinder Singh jasvinder.singh at intel.com
Fri Dec 15 11:39:21 CET 2017


This patch removes table id parameter from all the flow
classify apis to reduce the complexity alongwith some code
cleanup.

The validate api is exposed as public api to allow user
to validate the flow before adding it to the classifier.

Signed-off-by: Jasvinder Singh <jasvinder.singh at intel.com>
---
v2:
- break the patche into multiple
- fix the error checks

 lib/librte_flow_classify/rte_flow_classify.c       | 313 +++++++++++----------
 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 +
 5 files changed, 296 insertions(+), 226 deletions(-)

diff --git a/lib/librte_flow_classify/rte_flow_classify.c b/lib/librte_flow_classify/rte_flow_classify.c
index e6f4486..c2200df 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,38 @@ flow_classify_parse_flow(
 	uint32_t i = 0;
 	int ret;
 
-	memset(&ntuple_filter, 0, sizeof(ntuple_filter));
+	if (error == NULL)
+		return -EINVAL;
+
+	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;
+	}
+
+	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 +191,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 +316,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 +344,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 +357,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 +370,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 +403,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 +428,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 +443,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 +456,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 +513,21 @@ 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 +535,95 @@ rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
 		return NULL;
 	}
 
-	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;
+
+	for (i = 0; i < cls->num_tables; i++) {
+		struct rte_cls_table *table = &cls->tables[i];
 
-	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);
+		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 +632,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 +650,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 +668,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: *;
 };
-- 
2.9.3



More information about the dev mailing list