aboutsummaryrefslogtreecommitdiffstats
path: root/lib/librte_flow_classify
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librte_flow_classify')
-rw-r--r--lib/librte_flow_classify/Makefile33
-rw-r--r--lib/librte_flow_classify/meson.build7
-rw-r--r--lib/librte_flow_classify/rte_flow_classify.c362
-rw-r--r--lib/librte_flow_classify/rte_flow_classify.h130
-rw-r--r--lib/librte_flow_classify/rte_flow_classify_parse.c151
-rw-r--r--lib/librte_flow_classify/rte_flow_classify_parse.h49
-rw-r--r--lib/librte_flow_classify/rte_flow_classify_version.map1
7 files changed, 337 insertions, 396 deletions
diff --git a/lib/librte_flow_classify/Makefile b/lib/librte_flow_classify/Makefile
index ea792f5d..fe9fc47a 100644
--- a/lib/librte_flow_classify/Makefile
+++ b/lib/librte_flow_classify/Makefile
@@ -1,39 +1,12 @@
-# BSD LICENSE
-#
-# Copyright(c) 2017 Intel Corporation. All rights reserved.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Intel Corporation nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
include $(RTE_SDK)/mk/rte.vars.mk
# library name
LIB = librte_flow_classify.a
+CFLAGS += -DALLOW_EXPERIMENTAL_API
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
diff --git a/lib/librte_flow_classify/meson.build b/lib/librte_flow_classify/meson.build
new file mode 100644
index 00000000..d7e48747
--- /dev/null
+++ b/lib/librte_flow_classify/meson.build
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+allow_experimental_apis = true
+sources = files('rte_flow_classify.c', 'rte_flow_classify_parse.c')
+headers = files('rte_flow_classify.h')
+deps += ['net', 'table']
diff --git a/lib/librte_flow_classify/rte_flow_classify.c b/lib/librte_flow_classify/rte_flow_classify.c
index e6f44864..7edb2f15 100644
--- a/lib/librte_flow_classify/rte_flow_classify.c
+++ b/lib/librte_flow_classify/rte_flow_classify.c
@@ -1,36 +1,8 @@
-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2017 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
*/
+#include <rte_compat.h>
#include <rte_flow_classify.h>
#include "rte_flow_classify_parse.h"
#include <rte_flow_driver.h>
@@ -39,16 +11,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 +40,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_filter */
+ struct rte_eth_ntuple_filter ntuple_filter;
+
+ /* classifier 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 +78,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_experimental
+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 +102,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 +163,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;
}
@@ -245,7 +258,7 @@ rte_flow_classifier_check_params(struct rte_flow_classifier_params *params)
return 0;
}
-struct rte_flow_classifier *
+struct rte_flow_classifier * __rte_experimental
rte_flow_classifier_create(struct rte_flow_classifier_params *params)
{
struct rte_flow_classifier *cls;
@@ -275,23 +288,20 @@ 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);
}
-int
+int __rte_experimental
rte_flow_classifier_free(struct rte_flow_classifier *cls)
{
uint32_t i;
@@ -306,7 +316,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 +329,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 +342,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) {
@@ -369,24 +373,20 @@ rte_table_check_params(struct rte_flow_classifier *cls,
return 0;
}
-int
+int __rte_experimental
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 +400,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 +415,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 +428,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);
@@ -483,36 +483,23 @@ allocate_acl_ipv4_5tuple_rule(void)
return rule;
}
-struct rte_flow_classify_rule *
+struct rte_flow_classify_rule * __rte_experimental
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 +507,96 @@ 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;
+ free(rule);
+ return NULL;
}
-int
+int __rte_experimental
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 +605,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 +623,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 +641,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
+int __rte_experimental
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;
}
@@ -685,7 +681,7 @@ static void
librte_flow_classify_init_log(void)
{
librte_flow_classify_logtype =
- rte_log_register("librte.flow_classify");
+ rte_log_register("lib.flow_classify");
if (librte_flow_classify_logtype >= 0)
rte_log_set_level(librte_flow_classify_logtype, RTE_LOG_INFO);
}
diff --git a/lib/librte_flow_classify/rte_flow_classify.h b/lib/librte_flow_classify/rte_flow_classify.h
index 1211873a..56e06353 100644
--- a/lib/librte_flow_classify/rte_flow_classify.h
+++ b/lib/librte_flow_classify/rte_flow_classify.h
@@ -1,34 +1,5 @@
-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2017 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
*/
#ifndef _RTE_FLOW_CLASSIFY_H_
@@ -70,6 +41,8 @@
* with rte_flow_classifier_free()
*/
+#include <rte_compat.h>
+#include <rte_common.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_flow.h>
@@ -82,9 +55,16 @@ extern "C" {
extern int librte_flow_classify_logtype;
-#define RTE_FLOW_CLASSIFY_LOG(level, fmt, args...) \
-rte_log(RTE_LOG_ ## level, librte_flow_classify_logtype, "%s(): " fmt, \
- __func__, ## args)
+#define RTE_FLOW_CLASSIFY_LOG(level, ...) \
+ rte_log(RTE_LOG_ ## level, \
+ librte_flow_classify_logtype, \
+ RTE_FMT("%s(): " RTE_FMT_HEAD(__VA_ARGS__,), \
+ __func__, \
+ RTE_FMT_TAIL(__VA_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 +82,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 +101,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 +110,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 */
@@ -176,7 +155,7 @@ struct rte_flow_classify_ipv4_5tuple_stats {
* @return
* Handle to flow classifier instance on success or NULL otherwise
*/
-struct rte_flow_classifier *
+struct rte_flow_classifier * __rte_experimental
rte_flow_classifier_create(struct rte_flow_classifier_params *params);
/**
@@ -187,7 +166,7 @@ rte_flow_classifier_create(struct rte_flow_classifier_params *params);
* @return
* 0 on success, error code otherwise
*/
-int
+int __rte_experimental
rte_flow_classifier_free(struct rte_flow_classifier *cls);
/**
@@ -197,45 +176,62 @@ 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
+int __rte_experimental
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_experimental
+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.
* @return
* A valid handle in case of success, NULL otherwise.
*/
-struct rte_flow_classify_rule *
+struct rte_flow_classify_rule * __rte_experimental
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,16 +239,13 @@ 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
* 0 on success, error code otherwise.
*/
-int
+int __rte_experimental
rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
- uint32_t table_id,
struct rte_flow_classify_rule *rule);
/**
@@ -260,8 +253,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
@@ -274,9 +265,8 @@ rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
* @return
* 0 on success, error code otherwise.
*/
-int
+int __rte_experimental
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 dbfa1115..10eaf043 100644
--- a/lib/librte_flow_classify/rte_flow_classify_parse.c
+++ b/lib/librte_flow_classify/rte_flow_classify_parse.c
@@ -1,34 +1,5 @@
-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2017 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
*/
#include <rte_flow_classify.h>
@@ -40,7 +11,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 +51,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 +215,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 +436,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 +468,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 1d4708a7..365a07bd 100644
--- a/lib/librte_flow_classify/rte_flow_classify_parse.h
+++ b/lib/librte_flow_classify/rte_flow_classify_parse.h
@@ -1,34 +1,5 @@
-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2017 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
*/
#ifndef _RTE_FLOW_CLASSIFY_PARSE_H_
@@ -43,6 +14,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 +49,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 f7695cbf..49bc25c6 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: *;
};