aboutsummaryrefslogtreecommitdiffstats
path: root/lib/librte_flow_classify/rte_flow_classify.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librte_flow_classify/rte_flow_classify.c')
-rw-r--r--lib/librte_flow_classify/rte_flow_classify.c362
1 files changed, 179 insertions, 183 deletions
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);
}