1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606 * Copyright(c) 2017 Intel Corporation
32bfe3f2eSlogwang */
42bfe3f2eSlogwang
54418919fSjohnjiang #include <rte_string_fns.h>
6d30ea906Sjfb8856606 #include <rte_compat.h>
72bfe3f2eSlogwang #include <rte_flow_classify.h>
82bfe3f2eSlogwang #include "rte_flow_classify_parse.h"
92bfe3f2eSlogwang #include <rte_flow_driver.h>
102bfe3f2eSlogwang #include <rte_table_acl.h>
112bfe3f2eSlogwang #include <stdbool.h>
122bfe3f2eSlogwang
132bfe3f2eSlogwang static uint32_t unique_id = 1;
142bfe3f2eSlogwang
15d30ea906Sjfb8856606 enum rte_flow_classify_table_type table_type
16d30ea906Sjfb8856606 = RTE_FLOW_CLASSIFY_TABLE_TYPE_NONE;
172bfe3f2eSlogwang
182bfe3f2eSlogwang struct rte_flow_classify_table_entry {
192bfe3f2eSlogwang /* meta-data for classify rule */
202bfe3f2eSlogwang uint32_t rule_id;
21d30ea906Sjfb8856606
22d30ea906Sjfb8856606 /* Flow action */
23d30ea906Sjfb8856606 struct classify_action action;
242bfe3f2eSlogwang };
252bfe3f2eSlogwang
26d30ea906Sjfb8856606 struct rte_cls_table {
272bfe3f2eSlogwang /* Input parameters */
282bfe3f2eSlogwang struct rte_table_ops ops;
292bfe3f2eSlogwang uint32_t entry_size;
302bfe3f2eSlogwang enum rte_flow_classify_table_type type;
312bfe3f2eSlogwang
322bfe3f2eSlogwang /* Handle to the low-level table object */
332bfe3f2eSlogwang void *h_table;
342bfe3f2eSlogwang };
352bfe3f2eSlogwang
362bfe3f2eSlogwang #define RTE_FLOW_CLASSIFIER_MAX_NAME_SZ 256
372bfe3f2eSlogwang
382bfe3f2eSlogwang struct rte_flow_classifier {
392bfe3f2eSlogwang /* Input parameters */
402bfe3f2eSlogwang char name[RTE_FLOW_CLASSIFIER_MAX_NAME_SZ];
412bfe3f2eSlogwang int socket_id;
422bfe3f2eSlogwang
43d30ea906Sjfb8856606 /* Internal */
44d30ea906Sjfb8856606 /* ntuple_filter */
45d30ea906Sjfb8856606 struct rte_eth_ntuple_filter ntuple_filter;
46d30ea906Sjfb8856606
47d30ea906Sjfb8856606 /* classifier tables */
48d30ea906Sjfb8856606 struct rte_cls_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
49d30ea906Sjfb8856606 uint32_t table_mask;
502bfe3f2eSlogwang uint32_t num_tables;
51d30ea906Sjfb8856606
522bfe3f2eSlogwang uint16_t nb_pkts;
532bfe3f2eSlogwang struct rte_flow_classify_table_entry
542bfe3f2eSlogwang *entries[RTE_PORT_IN_BURST_SIZE_MAX];
552bfe3f2eSlogwang } __rte_cache_aligned;
562bfe3f2eSlogwang
572bfe3f2eSlogwang enum {
582bfe3f2eSlogwang PROTO_FIELD_IPV4,
592bfe3f2eSlogwang SRC_FIELD_IPV4,
602bfe3f2eSlogwang DST_FIELD_IPV4,
612bfe3f2eSlogwang SRCP_FIELD_IPV4,
622bfe3f2eSlogwang DSTP_FIELD_IPV4,
632bfe3f2eSlogwang NUM_FIELDS_IPV4
642bfe3f2eSlogwang };
652bfe3f2eSlogwang
662bfe3f2eSlogwang struct acl_keys {
672bfe3f2eSlogwang struct rte_table_acl_rule_add_params key_add; /* add key */
682bfe3f2eSlogwang struct rte_table_acl_rule_delete_params key_del; /* delete key */
692bfe3f2eSlogwang };
702bfe3f2eSlogwang
712bfe3f2eSlogwang struct classify_rules {
722bfe3f2eSlogwang enum rte_flow_classify_rule_type type;
732bfe3f2eSlogwang union {
742bfe3f2eSlogwang struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
752bfe3f2eSlogwang } u;
762bfe3f2eSlogwang };
772bfe3f2eSlogwang
782bfe3f2eSlogwang struct rte_flow_classify_rule {
792bfe3f2eSlogwang uint32_t id; /* unique ID of classify rule */
80d30ea906Sjfb8856606 enum rte_flow_classify_table_type tbl_type; /* rule table */
812bfe3f2eSlogwang struct classify_rules rules; /* union of rules */
822bfe3f2eSlogwang union {
832bfe3f2eSlogwang struct acl_keys key;
842bfe3f2eSlogwang } u;
852bfe3f2eSlogwang int key_found; /* rule key found in table */
86d30ea906Sjfb8856606 struct rte_flow_classify_table_entry entry; /* rule meta data */
872bfe3f2eSlogwang void *entry_ptr; /* handle to the table entry for rule meta data */
882bfe3f2eSlogwang };
892bfe3f2eSlogwang
904418919fSjohnjiang 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)91d30ea906Sjfb8856606 rte_flow_classify_validate(
92d30ea906Sjfb8856606 struct rte_flow_classifier *cls,
932bfe3f2eSlogwang const struct rte_flow_attr *attr,
942bfe3f2eSlogwang const struct rte_flow_item pattern[],
952bfe3f2eSlogwang const struct rte_flow_action actions[],
962bfe3f2eSlogwang struct rte_flow_error *error)
972bfe3f2eSlogwang {
982bfe3f2eSlogwang struct rte_flow_item *items;
992bfe3f2eSlogwang parse_filter_t parse_filter;
1002bfe3f2eSlogwang uint32_t item_num = 0;
1012bfe3f2eSlogwang uint32_t i = 0;
1022bfe3f2eSlogwang int ret;
1032bfe3f2eSlogwang
104d30ea906Sjfb8856606 if (error == NULL)
105d30ea906Sjfb8856606 return -EINVAL;
106d30ea906Sjfb8856606
107d30ea906Sjfb8856606 if (cls == NULL) {
108d30ea906Sjfb8856606 RTE_FLOW_CLASSIFY_LOG(ERR,
109d30ea906Sjfb8856606 "%s: rte_flow_classifier parameter is NULL\n",
110d30ea906Sjfb8856606 __func__);
111d30ea906Sjfb8856606 return -EINVAL;
112d30ea906Sjfb8856606 }
113d30ea906Sjfb8856606
114d30ea906Sjfb8856606 if (!attr) {
115d30ea906Sjfb8856606 rte_flow_error_set(error, EINVAL,
116d30ea906Sjfb8856606 RTE_FLOW_ERROR_TYPE_ATTR,
117d30ea906Sjfb8856606 NULL, "NULL attribute.");
118d30ea906Sjfb8856606 return -EINVAL;
119d30ea906Sjfb8856606 }
120d30ea906Sjfb8856606
121d30ea906Sjfb8856606 if (!pattern) {
122d30ea906Sjfb8856606 rte_flow_error_set(error,
123d30ea906Sjfb8856606 EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
124d30ea906Sjfb8856606 NULL, "NULL pattern.");
125d30ea906Sjfb8856606 return -EINVAL;
126d30ea906Sjfb8856606 }
127d30ea906Sjfb8856606
128d30ea906Sjfb8856606 if (!actions) {
129d30ea906Sjfb8856606 rte_flow_error_set(error, EINVAL,
130d30ea906Sjfb8856606 RTE_FLOW_ERROR_TYPE_ACTION_NUM,
131d30ea906Sjfb8856606 NULL, "NULL action.");
132d30ea906Sjfb8856606 return -EINVAL;
133d30ea906Sjfb8856606 }
134d30ea906Sjfb8856606
135d30ea906Sjfb8856606 memset(&cls->ntuple_filter, 0, sizeof(cls->ntuple_filter));
1362bfe3f2eSlogwang
1372bfe3f2eSlogwang /* Get the non-void item number of pattern */
1382bfe3f2eSlogwang while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
1392bfe3f2eSlogwang if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
1402bfe3f2eSlogwang item_num++;
1412bfe3f2eSlogwang i++;
1422bfe3f2eSlogwang }
1432bfe3f2eSlogwang item_num++;
1442bfe3f2eSlogwang
1452bfe3f2eSlogwang items = malloc(item_num * sizeof(struct rte_flow_item));
1462bfe3f2eSlogwang if (!items) {
1472bfe3f2eSlogwang rte_flow_error_set(error, ENOMEM,
1482bfe3f2eSlogwang RTE_FLOW_ERROR_TYPE_ITEM_NUM,
1492bfe3f2eSlogwang NULL, "No memory for pattern items.");
1502bfe3f2eSlogwang return -ENOMEM;
1512bfe3f2eSlogwang }
1522bfe3f2eSlogwang
1532bfe3f2eSlogwang memset(items, 0, item_num * sizeof(struct rte_flow_item));
1542bfe3f2eSlogwang classify_pattern_skip_void_item(items, pattern);
1552bfe3f2eSlogwang
1562bfe3f2eSlogwang parse_filter = classify_find_parse_filter_func(items);
1572bfe3f2eSlogwang if (!parse_filter) {
1582bfe3f2eSlogwang rte_flow_error_set(error, EINVAL,
1592bfe3f2eSlogwang RTE_FLOW_ERROR_TYPE_ITEM,
1602bfe3f2eSlogwang pattern, "Unsupported pattern");
1612bfe3f2eSlogwang free(items);
1622bfe3f2eSlogwang return -EINVAL;
1632bfe3f2eSlogwang }
1642bfe3f2eSlogwang
165d30ea906Sjfb8856606 ret = parse_filter(attr, items, actions, &cls->ntuple_filter, error);
1662bfe3f2eSlogwang free(items);
1672bfe3f2eSlogwang return ret;
1682bfe3f2eSlogwang }
1692bfe3f2eSlogwang
1702bfe3f2eSlogwang
1712bfe3f2eSlogwang #define uint32_t_to_char(ip, a, b, c, d) do {\
1722bfe3f2eSlogwang *a = (unsigned char)(ip >> 24 & 0xff);\
1732bfe3f2eSlogwang *b = (unsigned char)(ip >> 16 & 0xff);\
1742bfe3f2eSlogwang *c = (unsigned char)(ip >> 8 & 0xff);\
1752bfe3f2eSlogwang *d = (unsigned char)(ip & 0xff);\
1762bfe3f2eSlogwang } while (0)
1772bfe3f2eSlogwang
1782bfe3f2eSlogwang static inline void
print_acl_ipv4_key_add(struct rte_table_acl_rule_add_params * key)1792bfe3f2eSlogwang print_acl_ipv4_key_add(struct rte_table_acl_rule_add_params *key)
1802bfe3f2eSlogwang {
1812bfe3f2eSlogwang unsigned char a, b, c, d;
1822bfe3f2eSlogwang
1832bfe3f2eSlogwang printf("%s: 0x%02hhx/0x%hhx ", __func__,
1842bfe3f2eSlogwang key->field_value[PROTO_FIELD_IPV4].value.u8,
1852bfe3f2eSlogwang key->field_value[PROTO_FIELD_IPV4].mask_range.u8);
1862bfe3f2eSlogwang
1872bfe3f2eSlogwang uint32_t_to_char(key->field_value[SRC_FIELD_IPV4].value.u32,
1882bfe3f2eSlogwang &a, &b, &c, &d);
1892bfe3f2eSlogwang printf(" %hhu.%hhu.%hhu.%hhu/0x%x ", a, b, c, d,
1902bfe3f2eSlogwang key->field_value[SRC_FIELD_IPV4].mask_range.u32);
1912bfe3f2eSlogwang
1922bfe3f2eSlogwang uint32_t_to_char(key->field_value[DST_FIELD_IPV4].value.u32,
1932bfe3f2eSlogwang &a, &b, &c, &d);
1942bfe3f2eSlogwang printf("%hhu.%hhu.%hhu.%hhu/0x%x ", a, b, c, d,
1952bfe3f2eSlogwang key->field_value[DST_FIELD_IPV4].mask_range.u32);
1962bfe3f2eSlogwang
1972bfe3f2eSlogwang printf("%hu : 0x%x %hu : 0x%x",
1982bfe3f2eSlogwang key->field_value[SRCP_FIELD_IPV4].value.u16,
1992bfe3f2eSlogwang key->field_value[SRCP_FIELD_IPV4].mask_range.u16,
2002bfe3f2eSlogwang key->field_value[DSTP_FIELD_IPV4].value.u16,
2012bfe3f2eSlogwang key->field_value[DSTP_FIELD_IPV4].mask_range.u16);
2022bfe3f2eSlogwang
2032bfe3f2eSlogwang printf(" priority: 0x%x\n", key->priority);
2042bfe3f2eSlogwang }
2052bfe3f2eSlogwang
2062bfe3f2eSlogwang static inline void
print_acl_ipv4_key_delete(struct rte_table_acl_rule_delete_params * key)2072bfe3f2eSlogwang print_acl_ipv4_key_delete(struct rte_table_acl_rule_delete_params *key)
2082bfe3f2eSlogwang {
2092bfe3f2eSlogwang unsigned char a, b, c, d;
2102bfe3f2eSlogwang
2112bfe3f2eSlogwang printf("%s: 0x%02hhx/0x%hhx ", __func__,
2122bfe3f2eSlogwang key->field_value[PROTO_FIELD_IPV4].value.u8,
2132bfe3f2eSlogwang key->field_value[PROTO_FIELD_IPV4].mask_range.u8);
2142bfe3f2eSlogwang
2152bfe3f2eSlogwang uint32_t_to_char(key->field_value[SRC_FIELD_IPV4].value.u32,
2162bfe3f2eSlogwang &a, &b, &c, &d);
2172bfe3f2eSlogwang printf(" %hhu.%hhu.%hhu.%hhu/0x%x ", a, b, c, d,
2182bfe3f2eSlogwang key->field_value[SRC_FIELD_IPV4].mask_range.u32);
2192bfe3f2eSlogwang
2202bfe3f2eSlogwang uint32_t_to_char(key->field_value[DST_FIELD_IPV4].value.u32,
2212bfe3f2eSlogwang &a, &b, &c, &d);
2222bfe3f2eSlogwang printf("%hhu.%hhu.%hhu.%hhu/0x%x ", a, b, c, d,
2232bfe3f2eSlogwang key->field_value[DST_FIELD_IPV4].mask_range.u32);
2242bfe3f2eSlogwang
2252bfe3f2eSlogwang printf("%hu : 0x%x %hu : 0x%x\n",
2262bfe3f2eSlogwang key->field_value[SRCP_FIELD_IPV4].value.u16,
2272bfe3f2eSlogwang key->field_value[SRCP_FIELD_IPV4].mask_range.u16,
2282bfe3f2eSlogwang key->field_value[DSTP_FIELD_IPV4].value.u16,
2292bfe3f2eSlogwang key->field_value[DSTP_FIELD_IPV4].mask_range.u16);
2302bfe3f2eSlogwang }
2312bfe3f2eSlogwang
2322bfe3f2eSlogwang static int
rte_flow_classifier_check_params(struct rte_flow_classifier_params * params)2332bfe3f2eSlogwang rte_flow_classifier_check_params(struct rte_flow_classifier_params *params)
2342bfe3f2eSlogwang {
2352bfe3f2eSlogwang if (params == NULL) {
2362bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
2372bfe3f2eSlogwang "%s: Incorrect value for parameter params\n", __func__);
2382bfe3f2eSlogwang return -EINVAL;
2392bfe3f2eSlogwang }
2402bfe3f2eSlogwang
2412bfe3f2eSlogwang /* name */
2422bfe3f2eSlogwang if (params->name == NULL) {
2432bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
2442bfe3f2eSlogwang "%s: Incorrect value for parameter name\n", __func__);
2452bfe3f2eSlogwang return -EINVAL;
2462bfe3f2eSlogwang }
2472bfe3f2eSlogwang
2482bfe3f2eSlogwang /* socket */
249d30ea906Sjfb8856606 if (params->socket_id < 0) {
2502bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
2512bfe3f2eSlogwang "%s: Incorrect value for parameter socket_id\n",
2522bfe3f2eSlogwang __func__);
2532bfe3f2eSlogwang return -EINVAL;
2542bfe3f2eSlogwang }
2552bfe3f2eSlogwang
2562bfe3f2eSlogwang return 0;
2572bfe3f2eSlogwang }
2582bfe3f2eSlogwang
2594418919fSjohnjiang struct rte_flow_classifier *
rte_flow_classifier_create(struct rte_flow_classifier_params * params)2602bfe3f2eSlogwang rte_flow_classifier_create(struct rte_flow_classifier_params *params)
2612bfe3f2eSlogwang {
2622bfe3f2eSlogwang struct rte_flow_classifier *cls;
2632bfe3f2eSlogwang int ret;
2642bfe3f2eSlogwang
2652bfe3f2eSlogwang /* Check input parameters */
2662bfe3f2eSlogwang ret = rte_flow_classifier_check_params(params);
2672bfe3f2eSlogwang if (ret != 0) {
2682bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
2692bfe3f2eSlogwang "%s: flow classifier params check failed (%d)\n",
2702bfe3f2eSlogwang __func__, ret);
2712bfe3f2eSlogwang return NULL;
2722bfe3f2eSlogwang }
2732bfe3f2eSlogwang
2742bfe3f2eSlogwang /* Allocate memory for the flow classifier */
2752bfe3f2eSlogwang cls = rte_zmalloc_socket("FLOW_CLASSIFIER",
2762bfe3f2eSlogwang sizeof(struct rte_flow_classifier),
2772bfe3f2eSlogwang RTE_CACHE_LINE_SIZE, params->socket_id);
2782bfe3f2eSlogwang
2792bfe3f2eSlogwang if (cls == NULL) {
2802bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
2812bfe3f2eSlogwang "%s: flow classifier memory allocation failed\n",
2822bfe3f2eSlogwang __func__);
2832bfe3f2eSlogwang return NULL;
2842bfe3f2eSlogwang }
2852bfe3f2eSlogwang
2862bfe3f2eSlogwang /* Save input parameters */
2874418919fSjohnjiang strlcpy(cls->name, params->name, RTE_FLOW_CLASSIFIER_MAX_NAME_SZ);
2885af785ecSfengbojiang(姜凤波)
289d30ea906Sjfb8856606 cls->socket_id = params->socket_id;
2902bfe3f2eSlogwang
2912bfe3f2eSlogwang return cls;
2922bfe3f2eSlogwang }
2932bfe3f2eSlogwang
2942bfe3f2eSlogwang static void
rte_flow_classify_table_free(struct rte_cls_table * table)295d30ea906Sjfb8856606 rte_flow_classify_table_free(struct rte_cls_table *table)
2962bfe3f2eSlogwang {
2972bfe3f2eSlogwang if (table->ops.f_free != NULL)
2982bfe3f2eSlogwang table->ops.f_free(table->h_table);
2992bfe3f2eSlogwang }
3002bfe3f2eSlogwang
3014418919fSjohnjiang int
rte_flow_classifier_free(struct rte_flow_classifier * cls)3022bfe3f2eSlogwang rte_flow_classifier_free(struct rte_flow_classifier *cls)
3032bfe3f2eSlogwang {
3042bfe3f2eSlogwang uint32_t i;
3052bfe3f2eSlogwang
3062bfe3f2eSlogwang /* Check input parameters */
3072bfe3f2eSlogwang if (cls == NULL) {
3082bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
3092bfe3f2eSlogwang "%s: rte_flow_classifier parameter is NULL\n",
3102bfe3f2eSlogwang __func__);
3112bfe3f2eSlogwang return -EINVAL;
3122bfe3f2eSlogwang }
3132bfe3f2eSlogwang
3142bfe3f2eSlogwang /* Free tables */
3152bfe3f2eSlogwang for (i = 0; i < cls->num_tables; i++) {
316d30ea906Sjfb8856606 struct rte_cls_table *table = &cls->tables[i];
3172bfe3f2eSlogwang
3182bfe3f2eSlogwang rte_flow_classify_table_free(table);
3192bfe3f2eSlogwang }
3202bfe3f2eSlogwang
3212bfe3f2eSlogwang /* Free flow classifier memory */
3222bfe3f2eSlogwang rte_free(cls);
3232bfe3f2eSlogwang
3242bfe3f2eSlogwang return 0;
3252bfe3f2eSlogwang }
3262bfe3f2eSlogwang
3272bfe3f2eSlogwang static int
rte_table_check_params(struct rte_flow_classifier * cls,struct rte_flow_classify_table_params * params)3282bfe3f2eSlogwang rte_table_check_params(struct rte_flow_classifier *cls,
329d30ea906Sjfb8856606 struct rte_flow_classify_table_params *params)
3302bfe3f2eSlogwang {
3312bfe3f2eSlogwang if (cls == NULL) {
3322bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
3332bfe3f2eSlogwang "%s: flow classifier parameter is NULL\n",
3342bfe3f2eSlogwang __func__);
3352bfe3f2eSlogwang return -EINVAL;
3362bfe3f2eSlogwang }
3372bfe3f2eSlogwang if (params == NULL) {
3382bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR, "%s: params parameter is NULL\n",
3392bfe3f2eSlogwang __func__);
3402bfe3f2eSlogwang return -EINVAL;
3412bfe3f2eSlogwang }
3422bfe3f2eSlogwang
3432bfe3f2eSlogwang /* ops */
3442bfe3f2eSlogwang if (params->ops == NULL) {
3452bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR, "%s: params->ops is NULL\n",
3462bfe3f2eSlogwang __func__);
3472bfe3f2eSlogwang return -EINVAL;
3482bfe3f2eSlogwang }
3492bfe3f2eSlogwang
3502bfe3f2eSlogwang if (params->ops->f_create == NULL) {
3512bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
3522bfe3f2eSlogwang "%s: f_create function pointer is NULL\n", __func__);
3532bfe3f2eSlogwang return -EINVAL;
3542bfe3f2eSlogwang }
3552bfe3f2eSlogwang
3562bfe3f2eSlogwang if (params->ops->f_lookup == NULL) {
3572bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
3582bfe3f2eSlogwang "%s: f_lookup function pointer is NULL\n", __func__);
3592bfe3f2eSlogwang return -EINVAL;
3602bfe3f2eSlogwang }
3612bfe3f2eSlogwang
3622bfe3f2eSlogwang /* De we have room for one more table? */
3632bfe3f2eSlogwang if (cls->num_tables == RTE_FLOW_CLASSIFY_TABLE_MAX) {
3642bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR,
3652bfe3f2eSlogwang "%s: Incorrect value for num_tables parameter\n",
3662bfe3f2eSlogwang __func__);
3672bfe3f2eSlogwang return -EINVAL;
3682bfe3f2eSlogwang }
3692bfe3f2eSlogwang
3702bfe3f2eSlogwang return 0;
3712bfe3f2eSlogwang }
3722bfe3f2eSlogwang
3734418919fSjohnjiang int
rte_flow_classify_table_create(struct rte_flow_classifier * cls,struct rte_flow_classify_table_params * params)3742bfe3f2eSlogwang rte_flow_classify_table_create(struct rte_flow_classifier *cls,
375d30ea906Sjfb8856606 struct rte_flow_classify_table_params *params)
3762bfe3f2eSlogwang {
377d30ea906Sjfb8856606 struct rte_cls_table *table;
3782bfe3f2eSlogwang void *h_table;
379d30ea906Sjfb8856606 uint32_t entry_size;
3802bfe3f2eSlogwang int ret;
3812bfe3f2eSlogwang
3822bfe3f2eSlogwang /* Check input arguments */
383d30ea906Sjfb8856606 ret = rte_table_check_params(cls, params);
3842bfe3f2eSlogwang if (ret != 0)
3852bfe3f2eSlogwang return ret;
3862bfe3f2eSlogwang
3872bfe3f2eSlogwang /* calculate table entry size */
3882bfe3f2eSlogwang entry_size = sizeof(struct rte_flow_classify_table_entry);
3892bfe3f2eSlogwang
3902bfe3f2eSlogwang /* Create the table */
3912bfe3f2eSlogwang h_table = params->ops->f_create(params->arg_create, cls->socket_id,
3922bfe3f2eSlogwang entry_size);
3932bfe3f2eSlogwang if (h_table == NULL) {
3942bfe3f2eSlogwang RTE_FLOW_CLASSIFY_LOG(ERR, "%s: Table creation failed\n",
3952bfe3f2eSlogwang __func__);
3962bfe3f2eSlogwang return -EINVAL;
3972bfe3f2eSlogwang }
3982bfe3f2eSlogwang
3992bfe3f2eSlogwang /* Commit current table to the classifier */
400d30ea906Sjfb8856606 table = &cls->tables[cls->num_tables];
401d30ea906Sjfb8856606 table->type = params->type;
4022bfe3f2eSlogwang cls->num_tables++;
4032bfe3f2eSlogwang
4042bfe3f2eSlogwang /* Save input parameters */
4052bfe3f2eSlogwang memcpy(&table->ops, params->ops, sizeof(struct rte_table_ops));
4062bfe3f2eSlogwang
4072bfe3f2eSlogwang /* Initialize table internal data structure */
4082bfe3f2eSlogwang table->entry_size = entry_size;
4092bfe3f2eSlogwang table->h_table = h_table;
4102bfe3f2eSlogwang
4112bfe3f2eSlogwang return 0;
4122bfe3f2eSlogwang }
4132bfe3f2eSlogwang
4142bfe3f2eSlogwang static struct rte_flow_classify_rule *
allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier * cls)415d30ea906Sjfb8856606 allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier *cls)
4162bfe3f2eSlogwang {
4172bfe3f2eSlogwang struct rte_flow_classify_rule *rule;
4182bfe3f2eSlogwang
4192bfe3f2eSlogwang rule = malloc(sizeof(struct rte_flow_classify_rule));
4202bfe3f2eSlogwang if (!rule)
4212bfe3f2eSlogwang return rule;
4222bfe3f2eSlogwang
4232bfe3f2eSlogwang memset(rule, 0, sizeof(struct rte_flow_classify_rule));
4242bfe3f2eSlogwang rule->id = unique_id++;
4252bfe3f2eSlogwang rule->rules.type = RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_5TUPLE;
4262bfe3f2eSlogwang
4272bfe3f2eSlogwang /* key add values */
428d30ea906Sjfb8856606 rule->u.key.key_add.priority = cls->ntuple_filter.priority;
4292bfe3f2eSlogwang rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].mask_range.u8 =
430d30ea906Sjfb8856606 cls->ntuple_filter.proto_mask;
4312bfe3f2eSlogwang rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].value.u8 =
432d30ea906Sjfb8856606 cls->ntuple_filter.proto;
433d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.proto = cls->ntuple_filter.proto;
434d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.proto_mask = cls->ntuple_filter.proto_mask;
4352bfe3f2eSlogwang
4362bfe3f2eSlogwang rule->u.key.key_add.field_value[SRC_FIELD_IPV4].mask_range.u32 =
437d30ea906Sjfb8856606 cls->ntuple_filter.src_ip_mask;
4382bfe3f2eSlogwang rule->u.key.key_add.field_value[SRC_FIELD_IPV4].value.u32 =
439d30ea906Sjfb8856606 cls->ntuple_filter.src_ip;
440d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.src_ip_mask = cls->ntuple_filter.src_ip_mask;
441d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.src_ip = cls->ntuple_filter.src_ip;
4422bfe3f2eSlogwang
4432bfe3f2eSlogwang rule->u.key.key_add.field_value[DST_FIELD_IPV4].mask_range.u32 =
444d30ea906Sjfb8856606 cls->ntuple_filter.dst_ip_mask;
4452bfe3f2eSlogwang rule->u.key.key_add.field_value[DST_FIELD_IPV4].value.u32 =
446d30ea906Sjfb8856606 cls->ntuple_filter.dst_ip;
447d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.dst_ip_mask = cls->ntuple_filter.dst_ip_mask;
448d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.dst_ip = cls->ntuple_filter.dst_ip;
4492bfe3f2eSlogwang
4502bfe3f2eSlogwang rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
451d30ea906Sjfb8856606 cls->ntuple_filter.src_port_mask;
4522bfe3f2eSlogwang rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].value.u16 =
453d30ea906Sjfb8856606 cls->ntuple_filter.src_port;
454d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.src_port_mask =
455d30ea906Sjfb8856606 cls->ntuple_filter.src_port_mask;
456d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.src_port = cls->ntuple_filter.src_port;
4572bfe3f2eSlogwang
4582bfe3f2eSlogwang rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
459d30ea906Sjfb8856606 cls->ntuple_filter.dst_port_mask;
4602bfe3f2eSlogwang rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].value.u16 =
461d30ea906Sjfb8856606 cls->ntuple_filter.dst_port;
462d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.dst_port_mask =
463d30ea906Sjfb8856606 cls->ntuple_filter.dst_port_mask;
464d30ea906Sjfb8856606 rule->rules.u.ipv4_5tuple.dst_port = cls->ntuple_filter.dst_port;
4652bfe3f2eSlogwang
466*2d9fd380Sjfb8856606 if (rte_log_can_log(librte_flow_classify_logtype, RTE_LOG_DEBUG))
4672bfe3f2eSlogwang print_acl_ipv4_key_add(&rule->u.key.key_add);
4682bfe3f2eSlogwang
4692bfe3f2eSlogwang /* key delete values */
4702bfe3f2eSlogwang memcpy(&rule->u.key.key_del.field_value[PROTO_FIELD_IPV4],
4712bfe3f2eSlogwang &rule->u.key.key_add.field_value[PROTO_FIELD_IPV4],
4722bfe3f2eSlogwang NUM_FIELDS_IPV4 * sizeof(struct rte_acl_field));
4732bfe3f2eSlogwang
474*2d9fd380Sjfb8856606 if (rte_log_can_log(librte_flow_classify_logtype, RTE_LOG_DEBUG))
4752bfe3f2eSlogwang print_acl_ipv4_key_delete(&rule->u.key.key_del);
4762bfe3f2eSlogwang
4772bfe3f2eSlogwang return rule;
4782bfe3f2eSlogwang }
4792bfe3f2eSlogwang
4804418919fSjohnjiang struct rte_flow_classify_rule *
rte_flow_classify_table_entry_add(struct rte_flow_classifier * cls,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)4812bfe3f2eSlogwang rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
4822bfe3f2eSlogwang const struct rte_flow_attr *attr,
4832bfe3f2eSlogwang const struct rte_flow_item pattern[],
4842bfe3f2eSlogwang const struct rte_flow_action actions[],
485d30ea906Sjfb8856606 int *key_found,
4862bfe3f2eSlogwang struct rte_flow_error *error)
4872bfe3f2eSlogwang {
4882bfe3f2eSlogwang struct rte_flow_classify_rule *rule;
4892bfe3f2eSlogwang struct rte_flow_classify_table_entry *table_entry;
490d30ea906Sjfb8856606 struct classify_action *action;
491d30ea906Sjfb8856606 uint32_t i;
4922bfe3f2eSlogwang int ret;
4932bfe3f2eSlogwang
4942bfe3f2eSlogwang if (!error)
4952bfe3f2eSlogwang return NULL;
4962bfe3f2eSlogwang
4972bfe3f2eSlogwang if (key_found == NULL) {
4982bfe3f2eSlogwang rte_flow_error_set(error, EINVAL,
4992bfe3f2eSlogwang RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
5002bfe3f2eSlogwang NULL, "NULL key_found.");
5012bfe3f2eSlogwang return NULL;
5022bfe3f2eSlogwang }
5032bfe3f2eSlogwang
5042bfe3f2eSlogwang /* parse attr, pattern and actions */
505d30ea906Sjfb8856606 ret = rte_flow_classify_validate(cls, attr, pattern, actions, error);
5062bfe3f2eSlogwang if (ret < 0)
5072bfe3f2eSlogwang return NULL;
5082bfe3f2eSlogwang
509d30ea906Sjfb8856606 switch (table_type) {
510d30ea906Sjfb8856606 case RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE:
511d30ea906Sjfb8856606 rule = allocate_acl_ipv4_5tuple_rule(cls);
5122bfe3f2eSlogwang if (!rule)
5132bfe3f2eSlogwang return NULL;
514d30ea906Sjfb8856606 rule->tbl_type = table_type;
515d30ea906Sjfb8856606 cls->table_mask |= table_type;
5162bfe3f2eSlogwang break;
5172bfe3f2eSlogwang default:
5182bfe3f2eSlogwang return NULL;
5192bfe3f2eSlogwang }
5202bfe3f2eSlogwang
521d30ea906Sjfb8856606 action = classify_get_flow_action();
522d30ea906Sjfb8856606 table_entry = &rule->entry;
523d30ea906Sjfb8856606 table_entry->rule_id = rule->id;
524d30ea906Sjfb8856606 table_entry->action.action_mask = action->action_mask;
525d30ea906Sjfb8856606
526d30ea906Sjfb8856606 /* Copy actions */
527d30ea906Sjfb8856606 if (action->action_mask & (1LLU << RTE_FLOW_ACTION_TYPE_COUNT)) {
528d30ea906Sjfb8856606 memcpy(&table_entry->action.act.counter, &action->act.counter,
529d30ea906Sjfb8856606 sizeof(table_entry->action.act.counter));
530d30ea906Sjfb8856606 }
531d30ea906Sjfb8856606 if (action->action_mask & (1LLU << RTE_FLOW_ACTION_TYPE_MARK)) {
532d30ea906Sjfb8856606 memcpy(&table_entry->action.act.mark, &action->act.mark,
533d30ea906Sjfb8856606 sizeof(table_entry->action.act.mark));
5345af785ecSfengbojiang(姜凤波) }
5355af785ecSfengbojiang(姜凤波)
536d30ea906Sjfb8856606 for (i = 0; i < cls->num_tables; i++) {
537d30ea906Sjfb8856606 struct rte_cls_table *table = &cls->tables[i];
53828440c50Sjfb8856606
539d30ea906Sjfb8856606 if (table->type == table_type) {
540d30ea906Sjfb8856606 if (table->ops.f_add != NULL) {
541d30ea906Sjfb8856606 ret = table->ops.f_add(
542d30ea906Sjfb8856606 table->h_table,
5432bfe3f2eSlogwang &rule->u.key.key_add,
544d30ea906Sjfb8856606 &rule->entry,
5452bfe3f2eSlogwang &rule->key_found,
5462bfe3f2eSlogwang &rule->entry_ptr);
5472bfe3f2eSlogwang if (ret) {
5482bfe3f2eSlogwang free(rule);
5492bfe3f2eSlogwang return NULL;
5502bfe3f2eSlogwang }
551d30ea906Sjfb8856606
5522bfe3f2eSlogwang *key_found = rule->key_found;
5532bfe3f2eSlogwang }
554d30ea906Sjfb8856606
5552bfe3f2eSlogwang return rule;
5562bfe3f2eSlogwang }
557d30ea906Sjfb8856606 }
558d30ea906Sjfb8856606 free(rule);
559d30ea906Sjfb8856606 return NULL;
560d30ea906Sjfb8856606 }
5612bfe3f2eSlogwang
5624418919fSjohnjiang int
rte_flow_classify_table_entry_delete(struct rte_flow_classifier * cls,struct rte_flow_classify_rule * rule)5632bfe3f2eSlogwang rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
5642bfe3f2eSlogwang struct rte_flow_classify_rule *rule)
5652bfe3f2eSlogwang {
566d30ea906Sjfb8856606 uint32_t i;
5672bfe3f2eSlogwang int ret = -EINVAL;
5682bfe3f2eSlogwang
569d30ea906Sjfb8856606 if (!cls || !rule)
5702bfe3f2eSlogwang return ret;
571d30ea906Sjfb8856606 enum rte_flow_classify_table_type tbl_type = rule->tbl_type;
5722bfe3f2eSlogwang
573d30ea906Sjfb8856606 for (i = 0; i < cls->num_tables; i++) {
574d30ea906Sjfb8856606 struct rte_cls_table *table = &cls->tables[i];
575d30ea906Sjfb8856606
576d30ea906Sjfb8856606 if (table->type == tbl_type) {
577d30ea906Sjfb8856606 if (table->ops.f_delete != NULL) {
578d30ea906Sjfb8856606 ret = table->ops.f_delete(table->h_table,
5792bfe3f2eSlogwang &rule->u.key.key_del,
5802bfe3f2eSlogwang &rule->key_found,
5812bfe3f2eSlogwang &rule->entry);
5822bfe3f2eSlogwang
5832bfe3f2eSlogwang return ret;
5842bfe3f2eSlogwang }
585d30ea906Sjfb8856606 }
586d30ea906Sjfb8856606 }
587d30ea906Sjfb8856606 free(rule);
588d30ea906Sjfb8856606 return ret;
589d30ea906Sjfb8856606 }
5902bfe3f2eSlogwang
5912bfe3f2eSlogwang static int
flow_classifier_lookup(struct rte_flow_classifier * cls,struct rte_cls_table * table,struct rte_mbuf ** pkts,const uint16_t nb_pkts)5922bfe3f2eSlogwang flow_classifier_lookup(struct rte_flow_classifier *cls,
593d30ea906Sjfb8856606 struct rte_cls_table *table,
5942bfe3f2eSlogwang struct rte_mbuf **pkts,
5952bfe3f2eSlogwang const uint16_t nb_pkts)
5962bfe3f2eSlogwang {
5972bfe3f2eSlogwang int ret = -EINVAL;
5982bfe3f2eSlogwang uint64_t pkts_mask;
5992bfe3f2eSlogwang uint64_t lookup_hit_mask;
6002bfe3f2eSlogwang
6012bfe3f2eSlogwang pkts_mask = RTE_LEN2MASK(nb_pkts, uint64_t);
602d30ea906Sjfb8856606 ret = table->ops.f_lookup(table->h_table,
6032bfe3f2eSlogwang pkts, pkts_mask, &lookup_hit_mask,
6042bfe3f2eSlogwang (void **)cls->entries);
6052bfe3f2eSlogwang
6062bfe3f2eSlogwang if (!ret && lookup_hit_mask)
6072bfe3f2eSlogwang cls->nb_pkts = nb_pkts;
6082bfe3f2eSlogwang else
6092bfe3f2eSlogwang cls->nb_pkts = 0;
6102bfe3f2eSlogwang
6112bfe3f2eSlogwang return ret;
6122bfe3f2eSlogwang }
6132bfe3f2eSlogwang
6142bfe3f2eSlogwang static int
action_apply(struct rte_flow_classifier * cls,struct rte_flow_classify_rule * rule,struct rte_flow_classify_stats * stats)6152bfe3f2eSlogwang action_apply(struct rte_flow_classifier *cls,
6162bfe3f2eSlogwang struct rte_flow_classify_rule *rule,
6172bfe3f2eSlogwang struct rte_flow_classify_stats *stats)
6182bfe3f2eSlogwang {
6192bfe3f2eSlogwang struct rte_flow_classify_ipv4_5tuple_stats *ntuple_stats;
620d30ea906Sjfb8856606 struct rte_flow_classify_table_entry *entry = &rule->entry;
6212bfe3f2eSlogwang uint64_t count = 0;
622d30ea906Sjfb8856606 uint32_t action_mask = entry->action.action_mask;
623d30ea906Sjfb8856606 int i, ret = -EINVAL;
6242bfe3f2eSlogwang
625d30ea906Sjfb8856606 if (action_mask & (1LLU << RTE_FLOW_ACTION_TYPE_COUNT)) {
6262bfe3f2eSlogwang for (i = 0; i < cls->nb_pkts; i++) {
6272bfe3f2eSlogwang if (rule->id == cls->entries[i]->rule_id)
6282bfe3f2eSlogwang count++;
6292bfe3f2eSlogwang }
6302bfe3f2eSlogwang if (count) {
6312bfe3f2eSlogwang ret = 0;
632d30ea906Sjfb8856606 ntuple_stats = stats->stats;
6332bfe3f2eSlogwang ntuple_stats->counter1 = count;
6342bfe3f2eSlogwang ntuple_stats->ipv4_5tuple = rule->rules.u.ipv4_5tuple;
6352bfe3f2eSlogwang }
6362bfe3f2eSlogwang }
6372bfe3f2eSlogwang return ret;
6382bfe3f2eSlogwang }
6392bfe3f2eSlogwang
6404418919fSjohnjiang int
rte_flow_classifier_query(struct rte_flow_classifier * cls,struct rte_mbuf ** pkts,const uint16_t nb_pkts,struct rte_flow_classify_rule * rule,struct rte_flow_classify_stats * stats)6412bfe3f2eSlogwang rte_flow_classifier_query(struct rte_flow_classifier *cls,
6422bfe3f2eSlogwang struct rte_mbuf **pkts,
6432bfe3f2eSlogwang const uint16_t nb_pkts,
6442bfe3f2eSlogwang struct rte_flow_classify_rule *rule,
6452bfe3f2eSlogwang struct rte_flow_classify_stats *stats)
6462bfe3f2eSlogwang {
647d30ea906Sjfb8856606 enum rte_flow_classify_table_type tbl_type;
648d30ea906Sjfb8856606 uint32_t i;
6492bfe3f2eSlogwang int ret = -EINVAL;
6502bfe3f2eSlogwang
651d30ea906Sjfb8856606 if (!cls || !rule || !stats || !pkts || nb_pkts == 0)
6522bfe3f2eSlogwang return ret;
6532bfe3f2eSlogwang
654d30ea906Sjfb8856606 tbl_type = rule->tbl_type;
655d30ea906Sjfb8856606 for (i = 0; i < cls->num_tables; i++) {
656d30ea906Sjfb8856606 struct rte_cls_table *table = &cls->tables[i];
657d30ea906Sjfb8856606
658d30ea906Sjfb8856606 if (table->type == tbl_type) {
659d30ea906Sjfb8856606 ret = flow_classifier_lookup(cls, table,
660d30ea906Sjfb8856606 pkts, nb_pkts);
661d30ea906Sjfb8856606 if (!ret) {
6622bfe3f2eSlogwang ret = action_apply(cls, rule, stats);
6632bfe3f2eSlogwang return ret;
6642bfe3f2eSlogwang }
665d30ea906Sjfb8856606 }
666d30ea906Sjfb8856606 }
667d30ea906Sjfb8856606 return ret;
668d30ea906Sjfb8856606 }
6692bfe3f2eSlogwang
670*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(librte_flow_classify_logtype, lib.flow_classify, INFO);
671