xref: /dpdk/lib/table/rte_swx_table_wm.c (revision 42605e565109ef5d0db7a52a479b9e9c1c655c52)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2020 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson #include <stdlib.h>
599a2dd95SBruce Richardson #include <string.h>
699a2dd95SBruce Richardson #include <stdio.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_common.h>
999a2dd95SBruce Richardson #include <rte_cycles.h>
1099a2dd95SBruce Richardson #include <rte_acl.h>
1199a2dd95SBruce Richardson 
1299a2dd95SBruce Richardson #include "rte_swx_table_wm.h"
1399a2dd95SBruce Richardson 
1499a2dd95SBruce Richardson #ifndef RTE_SWX_TABLE_EM_USE_HUGE_PAGES
1599a2dd95SBruce Richardson #define RTE_SWX_TABLE_EM_USE_HUGE_PAGES 1
1699a2dd95SBruce Richardson #endif
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson #if RTE_SWX_TABLE_EM_USE_HUGE_PAGES
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson #include <rte_malloc.h>
2199a2dd95SBruce Richardson 
2299a2dd95SBruce Richardson static void *
env_malloc(size_t size,size_t alignment,int numa_node)2399a2dd95SBruce Richardson env_malloc(size_t size, size_t alignment, int numa_node)
2499a2dd95SBruce Richardson {
2599a2dd95SBruce Richardson 	return rte_zmalloc_socket(NULL, size, alignment, numa_node);
2699a2dd95SBruce Richardson }
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson static void
env_free(void * start,size_t size __rte_unused)2999a2dd95SBruce Richardson env_free(void *start, size_t size __rte_unused)
3099a2dd95SBruce Richardson {
3199a2dd95SBruce Richardson 	rte_free(start);
3299a2dd95SBruce Richardson }
3399a2dd95SBruce Richardson 
3499a2dd95SBruce Richardson #else
3599a2dd95SBruce Richardson 
3699a2dd95SBruce Richardson #include <numa.h>
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson static void *
env_malloc(size_t size,size_t alignment __rte_unused,int numa_node)3999a2dd95SBruce Richardson env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
4099a2dd95SBruce Richardson {
4199a2dd95SBruce Richardson 	return numa_alloc_onnode(size, numa_node);
4299a2dd95SBruce Richardson }
4399a2dd95SBruce Richardson 
4499a2dd95SBruce Richardson static void
env_free(void * start,size_t size)4599a2dd95SBruce Richardson env_free(void *start, size_t size)
4699a2dd95SBruce Richardson {
4799a2dd95SBruce Richardson 	numa_free(start, size);
4899a2dd95SBruce Richardson }
4999a2dd95SBruce Richardson 
5099a2dd95SBruce Richardson #endif
5199a2dd95SBruce Richardson 
get_unique_name(void)5299a2dd95SBruce Richardson static char *get_unique_name(void)
5399a2dd95SBruce Richardson {
5499a2dd95SBruce Richardson 	uint64_t tsc = rte_get_tsc_cycles();
5599a2dd95SBruce Richardson 	size_t size = sizeof(uint64_t) * 2 + 1;
5699a2dd95SBruce Richardson 	char *name = calloc(1, size);
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson 	if (!name)
5999a2dd95SBruce Richardson 		return NULL;
6099a2dd95SBruce Richardson 
6199a2dd95SBruce Richardson 	snprintf(name, size, "%016" PRIx64, tsc);
6299a2dd95SBruce Richardson 	return name;
6399a2dd95SBruce Richardson }
6499a2dd95SBruce Richardson 
6599a2dd95SBruce Richardson static uint32_t
count_entries(struct rte_swx_table_entry_list * entries)6699a2dd95SBruce Richardson count_entries(struct rte_swx_table_entry_list *entries)
6799a2dd95SBruce Richardson {
6899a2dd95SBruce Richardson 	struct rte_swx_table_entry *entry;
6999a2dd95SBruce Richardson 	uint32_t n_entries = 0;
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson 	if (!entries)
7299a2dd95SBruce Richardson 		return 0;
7399a2dd95SBruce Richardson 
7499a2dd95SBruce Richardson 	TAILQ_FOREACH(entry, entries, node)
7599a2dd95SBruce Richardson 		n_entries++;
7699a2dd95SBruce Richardson 
7799a2dd95SBruce Richardson 	return n_entries;
7899a2dd95SBruce Richardson }
7999a2dd95SBruce Richardson 
8099a2dd95SBruce Richardson static int
acl_table_cfg_get(struct rte_acl_config * cfg,struct rte_swx_table_params * p)8199a2dd95SBruce Richardson acl_table_cfg_get(struct rte_acl_config *cfg, struct rte_swx_table_params *p)
8299a2dd95SBruce Richardson {
8399a2dd95SBruce Richardson 	uint32_t byte_id = 0, field_id = 0;
8499a2dd95SBruce Richardson 
8599a2dd95SBruce Richardson 	/* cfg->num_categories. */
8699a2dd95SBruce Richardson 	cfg->num_categories = 1;
8799a2dd95SBruce Richardson 
8899a2dd95SBruce Richardson 	/* cfg->defs and cfg->num_fields. */
8999a2dd95SBruce Richardson 	for (byte_id = 0; byte_id < p->key_size; ) {
9099a2dd95SBruce Richardson 		uint32_t field_size = field_id ? 4 : 1;
9199a2dd95SBruce Richardson 		uint8_t byte = p->key_mask0 ? p->key_mask0[byte_id] : 0xFF;
9299a2dd95SBruce Richardson 
9399a2dd95SBruce Richardson 		if (!byte) {
9499a2dd95SBruce Richardson 			byte_id++;
9599a2dd95SBruce Richardson 			continue;
9699a2dd95SBruce Richardson 		}
9799a2dd95SBruce Richardson 
9899a2dd95SBruce Richardson 		if (field_id == RTE_ACL_MAX_FIELDS)
9999a2dd95SBruce Richardson 			return -1;
10099a2dd95SBruce Richardson 
10199a2dd95SBruce Richardson 		cfg->defs[field_id].type = RTE_ACL_FIELD_TYPE_BITMASK;
10299a2dd95SBruce Richardson 		cfg->defs[field_id].size = field_size;
10399a2dd95SBruce Richardson 		cfg->defs[field_id].field_index = field_id;
10499a2dd95SBruce Richardson 		cfg->defs[field_id].input_index = field_id;
10599a2dd95SBruce Richardson 		cfg->defs[field_id].offset = p->key_offset + byte_id;
10699a2dd95SBruce Richardson 
10799a2dd95SBruce Richardson 		field_id++;
10899a2dd95SBruce Richardson 		byte_id += field_size;
10999a2dd95SBruce Richardson 	}
11099a2dd95SBruce Richardson 
11199a2dd95SBruce Richardson 	if (!field_id)
11299a2dd95SBruce Richardson 		return -1;
11399a2dd95SBruce Richardson 
11499a2dd95SBruce Richardson 	cfg->num_fields = field_id;
11599a2dd95SBruce Richardson 
11699a2dd95SBruce Richardson 	/* cfg->max_size. */
11799a2dd95SBruce Richardson 	cfg->max_size = 0;
11899a2dd95SBruce Richardson 
11999a2dd95SBruce Richardson 	return 0;
12099a2dd95SBruce Richardson }
12199a2dd95SBruce Richardson 
12299a2dd95SBruce Richardson static void
acl_table_rule_field8(uint8_t * value,uint8_t * mask,uint8_t * key_mask0,uint8_t * key_mask,uint8_t * key,uint32_t offset)12399a2dd95SBruce Richardson acl_table_rule_field8(uint8_t *value,
12499a2dd95SBruce Richardson 	uint8_t *mask,
12599a2dd95SBruce Richardson 	uint8_t *key_mask0,
12699a2dd95SBruce Richardson 	uint8_t *key_mask,
12799a2dd95SBruce Richardson 	uint8_t *key,
12899a2dd95SBruce Richardson 	uint32_t offset)
12999a2dd95SBruce Richardson {
13099a2dd95SBruce Richardson 	uint8_t km0, km;
13199a2dd95SBruce Richardson 
13299a2dd95SBruce Richardson 	km0 = key_mask0 ? key_mask0[offset] : 0xFF;
13399a2dd95SBruce Richardson 	km = key_mask ? key_mask[offset] : 0xFF;
13499a2dd95SBruce Richardson 
13599a2dd95SBruce Richardson 	*value = key[offset];
13699a2dd95SBruce Richardson 	*mask = km0 & km;
13799a2dd95SBruce Richardson }
13899a2dd95SBruce Richardson 
13999a2dd95SBruce Richardson static void
acl_table_rule_field32(uint32_t * value,uint32_t * mask,uint8_t * key_mask0,uint8_t * key_mask,uint8_t * key,uint32_t key_size,uint32_t offset)14099a2dd95SBruce Richardson acl_table_rule_field32(uint32_t *value,
14199a2dd95SBruce Richardson 	uint32_t *mask,
14299a2dd95SBruce Richardson 	uint8_t *key_mask0,
14399a2dd95SBruce Richardson 	uint8_t *key_mask,
14499a2dd95SBruce Richardson 	uint8_t *key,
14599a2dd95SBruce Richardson 	uint32_t key_size,
14699a2dd95SBruce Richardson 	uint32_t offset)
14799a2dd95SBruce Richardson {
14899a2dd95SBruce Richardson 	uint32_t km0[4], km[4], k[4];
14999a2dd95SBruce Richardson 	uint32_t byte_id;
15099a2dd95SBruce Richardson 
15199a2dd95SBruce Richardson 	/* Byte 0 = MSB, byte 3 = LSB. */
15299a2dd95SBruce Richardson 	for (byte_id = 0; byte_id < 4; byte_id++) {
15399a2dd95SBruce Richardson 		if (offset + byte_id >= key_size) {
15499a2dd95SBruce Richardson 			km0[byte_id] = 0;
15599a2dd95SBruce Richardson 			km[byte_id] = 0;
15699a2dd95SBruce Richardson 			k[byte_id] = 0;
15799a2dd95SBruce Richardson 			continue;
15899a2dd95SBruce Richardson 		}
15999a2dd95SBruce Richardson 
16099a2dd95SBruce Richardson 		km0[byte_id] = key_mask0 ? key_mask0[offset + byte_id] : 0xFF;
16199a2dd95SBruce Richardson 		km[byte_id] = key_mask ? key_mask[offset + byte_id] : 0xFF;
16299a2dd95SBruce Richardson 		k[byte_id] = key[offset + byte_id];
16399a2dd95SBruce Richardson 	}
16499a2dd95SBruce Richardson 
16599a2dd95SBruce Richardson 	*value = (k[0] << 24) |
16699a2dd95SBruce Richardson 		 (k[1] << 16) |
16799a2dd95SBruce Richardson 		 (k[2] << 8) |
16899a2dd95SBruce Richardson 		 k[3];
16999a2dd95SBruce Richardson 
17099a2dd95SBruce Richardson 	*mask = ((km[0] & km0[0]) << 24) |
17199a2dd95SBruce Richardson 		((km[1] & km0[1]) << 16) |
17299a2dd95SBruce Richardson 		((km[2] & km0[2]) << 8) |
17399a2dd95SBruce Richardson 		(km[3] & km0[3]);
17499a2dd95SBruce Richardson }
17599a2dd95SBruce Richardson 
17699a2dd95SBruce Richardson RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS);
17799a2dd95SBruce Richardson 
17899a2dd95SBruce Richardson static struct rte_acl_rule *
acl_table_rules_get(struct rte_acl_config * acl_cfg,struct rte_swx_table_params * p,struct rte_swx_table_entry_list * entries,uint32_t n_entries)17999a2dd95SBruce Richardson acl_table_rules_get(struct rte_acl_config *acl_cfg,
18099a2dd95SBruce Richardson 	struct rte_swx_table_params *p,
18199a2dd95SBruce Richardson 	struct rte_swx_table_entry_list *entries,
18299a2dd95SBruce Richardson 	uint32_t n_entries)
18399a2dd95SBruce Richardson {
18499a2dd95SBruce Richardson 	struct rte_swx_table_entry *entry;
18599a2dd95SBruce Richardson 	uint8_t *memory;
18699a2dd95SBruce Richardson 	uint32_t acl_rule_size = RTE_ACL_RULE_SZ(acl_cfg->num_fields);
18799a2dd95SBruce Richardson 	uint32_t n_fields = acl_cfg->num_fields;
18899a2dd95SBruce Richardson 	uint32_t rule_id;
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson 	if (!n_entries)
19199a2dd95SBruce Richardson 		return NULL;
19299a2dd95SBruce Richardson 
19399a2dd95SBruce Richardson 	memory = malloc(n_entries * acl_rule_size);
19499a2dd95SBruce Richardson 	if (!memory)
19599a2dd95SBruce Richardson 		return NULL;
19699a2dd95SBruce Richardson 
19799a2dd95SBruce Richardson 	rule_id = 0;
19899a2dd95SBruce Richardson 	TAILQ_FOREACH(entry, entries, node) {
19999a2dd95SBruce Richardson 		uint8_t *m = &memory[rule_id * acl_rule_size];
20099a2dd95SBruce Richardson 		struct acl_rule *acl_rule = (struct acl_rule *)m;
20199a2dd95SBruce Richardson 		uint32_t field_id;
20299a2dd95SBruce Richardson 
20399a2dd95SBruce Richardson 		acl_rule->data.category_mask = 1;
20499a2dd95SBruce Richardson 		acl_rule->data.priority = RTE_ACL_MAX_PRIORITY -
20599a2dd95SBruce Richardson 			entry->key_priority;
20699a2dd95SBruce Richardson 		acl_rule->data.userdata = rule_id + 1;
20799a2dd95SBruce Richardson 
20899a2dd95SBruce Richardson 		for (field_id = 0; field_id < n_fields; field_id++) {
20999a2dd95SBruce Richardson 			struct rte_acl_field *f = &acl_rule->field[field_id];
21099a2dd95SBruce Richardson 			uint32_t size = acl_cfg->defs[field_id].size;
21199a2dd95SBruce Richardson 			uint32_t offset = acl_cfg->defs[field_id].offset -
21299a2dd95SBruce Richardson 				p->key_offset;
21399a2dd95SBruce Richardson 
21499a2dd95SBruce Richardson 			if (size == 1) {
21599a2dd95SBruce Richardson 				uint8_t value, mask;
21699a2dd95SBruce Richardson 
21799a2dd95SBruce Richardson 				acl_table_rule_field8(&value,
21899a2dd95SBruce Richardson 						      &mask,
21999a2dd95SBruce Richardson 						      p->key_mask0,
22099a2dd95SBruce Richardson 						      entry->key_mask,
22199a2dd95SBruce Richardson 						      entry->key,
22299a2dd95SBruce Richardson 						      offset);
22399a2dd95SBruce Richardson 
22499a2dd95SBruce Richardson 				f->value.u8 = value;
22599a2dd95SBruce Richardson 				f->mask_range.u8 = mask;
22699a2dd95SBruce Richardson 			} else {
22799a2dd95SBruce Richardson 				uint32_t value, mask;
22899a2dd95SBruce Richardson 
22999a2dd95SBruce Richardson 				acl_table_rule_field32(&value,
23099a2dd95SBruce Richardson 						       &mask,
23199a2dd95SBruce Richardson 						       p->key_mask0,
23299a2dd95SBruce Richardson 						       entry->key_mask,
23399a2dd95SBruce Richardson 						       entry->key,
23499a2dd95SBruce Richardson 						       p->key_size,
23599a2dd95SBruce Richardson 						       offset);
23699a2dd95SBruce Richardson 
23799a2dd95SBruce Richardson 				f->value.u32 = value;
23899a2dd95SBruce Richardson 				f->mask_range.u32 = mask;
23999a2dd95SBruce Richardson 			}
24099a2dd95SBruce Richardson 		}
24199a2dd95SBruce Richardson 
24299a2dd95SBruce Richardson 		rule_id++;
24399a2dd95SBruce Richardson 	}
24499a2dd95SBruce Richardson 
24599a2dd95SBruce Richardson 	return (struct rte_acl_rule *)memory;
24699a2dd95SBruce Richardson }
24799a2dd95SBruce Richardson 
24899a2dd95SBruce Richardson /* When the table to be created has no rules, the expected behavior is to always
24999a2dd95SBruce Richardson  * get lookup miss for any input key. To achieve this, we add a single bogus
25099a2dd95SBruce Richardson  * rule to the table with the rule user data set to 0, i.e. the value returned
25199a2dd95SBruce Richardson  * when lookup miss takes place. Whether lookup hit (the bogus rule is hit) or
25299a2dd95SBruce Richardson  * miss, a user data of 0 is returned, which for the ACL library is equivalent
25399a2dd95SBruce Richardson  * to lookup miss.
25499a2dd95SBruce Richardson  */
25599a2dd95SBruce Richardson static struct rte_acl_rule *
acl_table_rules_default_get(struct rte_acl_config * acl_cfg)25699a2dd95SBruce Richardson acl_table_rules_default_get(struct rte_acl_config *acl_cfg)
25799a2dd95SBruce Richardson {
25899a2dd95SBruce Richardson 	struct rte_acl_rule *acl_rule;
25999a2dd95SBruce Richardson 	uint32_t acl_rule_size = RTE_ACL_RULE_SZ(acl_cfg->num_fields);
26099a2dd95SBruce Richardson 
26199a2dd95SBruce Richardson 	acl_rule = calloc(1, acl_rule_size);
26299a2dd95SBruce Richardson 	if (!acl_rule)
26399a2dd95SBruce Richardson 		return NULL;
26499a2dd95SBruce Richardson 
26599a2dd95SBruce Richardson 	acl_rule->data.category_mask = 1;
26699a2dd95SBruce Richardson 	acl_rule->data.priority = RTE_ACL_MAX_PRIORITY;
26799a2dd95SBruce Richardson 	acl_rule->data.userdata = 0;
26899a2dd95SBruce Richardson 
26999a2dd95SBruce Richardson 	memset(&acl_rule[1], 0xFF, acl_rule_size - sizeof(struct rte_acl_rule));
27099a2dd95SBruce Richardson 
27199a2dd95SBruce Richardson 	return acl_rule;
27299a2dd95SBruce Richardson }
27399a2dd95SBruce Richardson 
27499a2dd95SBruce Richardson static struct rte_acl_ctx *
acl_table_create(struct rte_swx_table_params * params,struct rte_swx_table_entry_list * entries,uint32_t n_entries,int numa_node)27599a2dd95SBruce Richardson acl_table_create(struct rte_swx_table_params *params,
27699a2dd95SBruce Richardson 	struct rte_swx_table_entry_list *entries,
27799a2dd95SBruce Richardson 	uint32_t n_entries,
27899a2dd95SBruce Richardson 	int numa_node)
27999a2dd95SBruce Richardson {
28099a2dd95SBruce Richardson 	struct rte_acl_param acl_params = {0};
28199a2dd95SBruce Richardson 	struct rte_acl_config acl_cfg = {0};
28299a2dd95SBruce Richardson 	struct rte_acl_ctx *acl_ctx = NULL;
28399a2dd95SBruce Richardson 	struct rte_acl_rule *acl_rules = NULL;
28499a2dd95SBruce Richardson 	char *name = NULL;
28599a2dd95SBruce Richardson 	int status = 0;
28699a2dd95SBruce Richardson 
28799a2dd95SBruce Richardson 	/* ACL config data structures. */
28899a2dd95SBruce Richardson 	name = get_unique_name();
28999a2dd95SBruce Richardson 	if (!name) {
29099a2dd95SBruce Richardson 		status = -1;
29199a2dd95SBruce Richardson 		goto free_resources;
29299a2dd95SBruce Richardson 	}
29399a2dd95SBruce Richardson 
29499a2dd95SBruce Richardson 	status = acl_table_cfg_get(&acl_cfg, params);
29599a2dd95SBruce Richardson 	if (status)
29699a2dd95SBruce Richardson 		goto free_resources;
29799a2dd95SBruce Richardson 
29899a2dd95SBruce Richardson 	acl_rules = n_entries ?
29999a2dd95SBruce Richardson 		acl_table_rules_get(&acl_cfg, params, entries, n_entries) :
30099a2dd95SBruce Richardson 		acl_table_rules_default_get(&acl_cfg);
30199a2dd95SBruce Richardson 	if (!acl_rules) {
30299a2dd95SBruce Richardson 		status = -1;
30399a2dd95SBruce Richardson 		goto free_resources;
30499a2dd95SBruce Richardson 	}
30599a2dd95SBruce Richardson 
30699a2dd95SBruce Richardson 	n_entries = n_entries ? n_entries : 1;
30799a2dd95SBruce Richardson 
30899a2dd95SBruce Richardson 	/* ACL create. */
30999a2dd95SBruce Richardson 	acl_params.name = name;
31099a2dd95SBruce Richardson 	acl_params.socket_id = numa_node;
31199a2dd95SBruce Richardson 	acl_params.rule_size = RTE_ACL_RULE_SZ(acl_cfg.num_fields);
31299a2dd95SBruce Richardson 	acl_params.max_rule_num = n_entries;
31399a2dd95SBruce Richardson 
31499a2dd95SBruce Richardson 	acl_ctx = rte_acl_create(&acl_params);
31599a2dd95SBruce Richardson 	if (!acl_ctx) {
31699a2dd95SBruce Richardson 		status = -1;
31799a2dd95SBruce Richardson 		goto free_resources;
31899a2dd95SBruce Richardson 	}
31999a2dd95SBruce Richardson 
32099a2dd95SBruce Richardson 	/* ACL add rules. */
32199a2dd95SBruce Richardson 	status = rte_acl_add_rules(acl_ctx, acl_rules, n_entries);
32299a2dd95SBruce Richardson 	if (status)
32399a2dd95SBruce Richardson 		goto free_resources;
32499a2dd95SBruce Richardson 
32599a2dd95SBruce Richardson 	/* ACL build. */
32699a2dd95SBruce Richardson 	status = rte_acl_build(acl_ctx, &acl_cfg);
32799a2dd95SBruce Richardson 
32899a2dd95SBruce Richardson free_resources:
32999a2dd95SBruce Richardson 	if (status && acl_ctx)
33099a2dd95SBruce Richardson 		rte_acl_free(acl_ctx);
33199a2dd95SBruce Richardson 
33299a2dd95SBruce Richardson 	free(acl_rules);
33399a2dd95SBruce Richardson 
33499a2dd95SBruce Richardson 	free(name);
33599a2dd95SBruce Richardson 
33699a2dd95SBruce Richardson 	return status ? NULL : acl_ctx;
33799a2dd95SBruce Richardson }
33899a2dd95SBruce Richardson 
33999a2dd95SBruce Richardson static void
entry_data_copy(uint8_t * data,struct rte_swx_table_entry_list * entries,uint32_t n_entries,uint32_t entry_data_size)34099a2dd95SBruce Richardson entry_data_copy(uint8_t *data,
34199a2dd95SBruce Richardson 	struct rte_swx_table_entry_list *entries,
34299a2dd95SBruce Richardson 	uint32_t n_entries,
34399a2dd95SBruce Richardson 	uint32_t entry_data_size)
34499a2dd95SBruce Richardson {
34599a2dd95SBruce Richardson 	struct rte_swx_table_entry *entry;
34699a2dd95SBruce Richardson 	uint32_t i = 0;
34799a2dd95SBruce Richardson 
34899a2dd95SBruce Richardson 	if (!n_entries)
34999a2dd95SBruce Richardson 		return;
35099a2dd95SBruce Richardson 
35199a2dd95SBruce Richardson 	TAILQ_FOREACH(entry, entries, node) {
35299a2dd95SBruce Richardson 		uint64_t *d = (uint64_t *)&data[i * entry_data_size];
35399a2dd95SBruce Richardson 
35499a2dd95SBruce Richardson 		d[0] = entry->action_id;
35599a2dd95SBruce Richardson 		memcpy(&d[1], entry->action_data, entry_data_size - 8);
35699a2dd95SBruce Richardson 
35799a2dd95SBruce Richardson 		i++;
35899a2dd95SBruce Richardson 	}
35999a2dd95SBruce Richardson }
36099a2dd95SBruce Richardson 
36199a2dd95SBruce Richardson struct table {
36299a2dd95SBruce Richardson 	struct rte_acl_ctx *acl_ctx;
36399a2dd95SBruce Richardson 	uint8_t *data;
36499a2dd95SBruce Richardson 	size_t total_size;
36599a2dd95SBruce Richardson 	uint32_t entry_data_size;
36699a2dd95SBruce Richardson };
36799a2dd95SBruce Richardson 
36899a2dd95SBruce Richardson static void
table_free(void * table)36999a2dd95SBruce Richardson table_free(void *table)
37099a2dd95SBruce Richardson {
37199a2dd95SBruce Richardson 	struct table *t = table;
37299a2dd95SBruce Richardson 
37399a2dd95SBruce Richardson 	if (!t)
37499a2dd95SBruce Richardson 		return;
37599a2dd95SBruce Richardson 
37699a2dd95SBruce Richardson 	rte_acl_free(t->acl_ctx);
37799a2dd95SBruce Richardson 	env_free(t, t->total_size);
37899a2dd95SBruce Richardson }
37999a2dd95SBruce Richardson 
38099a2dd95SBruce Richardson static void *
table_create(struct rte_swx_table_params * params,struct rte_swx_table_entry_list * entries,const char * args __rte_unused,int numa_node)38199a2dd95SBruce Richardson table_create(struct rte_swx_table_params *params,
38299a2dd95SBruce Richardson 	     struct rte_swx_table_entry_list *entries,
38399a2dd95SBruce Richardson 	     const char *args __rte_unused,
38499a2dd95SBruce Richardson 	     int numa_node)
38599a2dd95SBruce Richardson {
38699a2dd95SBruce Richardson 	struct table *t = NULL;
38799a2dd95SBruce Richardson 	size_t meta_sz, data_sz, total_size;
38899a2dd95SBruce Richardson 	uint32_t entry_data_size;
38999a2dd95SBruce Richardson 	uint32_t n_entries = count_entries(entries);
39099a2dd95SBruce Richardson 
39199a2dd95SBruce Richardson 	/* Check input arguments. */
39299a2dd95SBruce Richardson 	if (!params || !params->key_size)
39399a2dd95SBruce Richardson 		goto error;
39499a2dd95SBruce Richardson 
39599a2dd95SBruce Richardson 	/* Memory allocation and initialization. */
39699a2dd95SBruce Richardson 	entry_data_size = 8 + params->action_data_size;
39799a2dd95SBruce Richardson 	meta_sz = sizeof(struct table);
39899a2dd95SBruce Richardson 	data_sz = n_entries * entry_data_size;
39999a2dd95SBruce Richardson 	total_size = meta_sz + data_sz;
40099a2dd95SBruce Richardson 
40199a2dd95SBruce Richardson 	t = env_malloc(total_size, RTE_CACHE_LINE_SIZE, numa_node);
40299a2dd95SBruce Richardson 	if (!t)
40399a2dd95SBruce Richardson 		goto error;
40499a2dd95SBruce Richardson 
40599a2dd95SBruce Richardson 	memset(t, 0, total_size);
40699a2dd95SBruce Richardson 	t->entry_data_size = entry_data_size;
40799a2dd95SBruce Richardson 	t->total_size = total_size;
40899a2dd95SBruce Richardson 	t->data = (uint8_t *)&t[1];
40999a2dd95SBruce Richardson 
41099a2dd95SBruce Richardson 	t->acl_ctx = acl_table_create(params, entries, n_entries, numa_node);
41199a2dd95SBruce Richardson 	if (!t->acl_ctx)
41299a2dd95SBruce Richardson 		goto error;
41399a2dd95SBruce Richardson 
41499a2dd95SBruce Richardson 	entry_data_copy(t->data, entries, n_entries, entry_data_size);
41599a2dd95SBruce Richardson 
41699a2dd95SBruce Richardson 	return t;
41799a2dd95SBruce Richardson 
41899a2dd95SBruce Richardson error:
41999a2dd95SBruce Richardson 	table_free(t);
42099a2dd95SBruce Richardson 	return NULL;
42199a2dd95SBruce Richardson }
42299a2dd95SBruce Richardson 
42399a2dd95SBruce Richardson struct mailbox {
42499a2dd95SBruce Richardson 
42599a2dd95SBruce Richardson };
42699a2dd95SBruce Richardson 
42799a2dd95SBruce Richardson static uint64_t
table_mailbox_size_get(void)42899a2dd95SBruce Richardson table_mailbox_size_get(void)
42999a2dd95SBruce Richardson {
43099a2dd95SBruce Richardson 	return sizeof(struct mailbox);
43199a2dd95SBruce Richardson }
43299a2dd95SBruce Richardson 
43399a2dd95SBruce Richardson static int
table_lookup(void * table,void * mailbox __rte_unused,const uint8_t ** key,uint64_t * action_id,uint8_t ** action_data,size_t * entry_id,int * hit)43499a2dd95SBruce Richardson table_lookup(void *table,
43599a2dd95SBruce Richardson 	     void *mailbox __rte_unused,
43699a2dd95SBruce Richardson 	     const uint8_t **key,
43799a2dd95SBruce Richardson 	     uint64_t *action_id,
43899a2dd95SBruce Richardson 	     uint8_t **action_data,
439*42605e56SCristian Dumitrescu 	     size_t *entry_id,
44099a2dd95SBruce Richardson 	     int *hit)
44199a2dd95SBruce Richardson {
44299a2dd95SBruce Richardson 	struct table *t = table;
44399a2dd95SBruce Richardson 	uint8_t *data;
44499a2dd95SBruce Richardson 	uint32_t user_data;
44599a2dd95SBruce Richardson 
44699a2dd95SBruce Richardson 	rte_acl_classify(t->acl_ctx, key, &user_data, 1, 1);
44799a2dd95SBruce Richardson 	if (!user_data) {
44899a2dd95SBruce Richardson 		*hit = 0;
44999a2dd95SBruce Richardson 		return 1;
45099a2dd95SBruce Richardson 	}
45199a2dd95SBruce Richardson 
45299a2dd95SBruce Richardson 	data = &t->data[(user_data - 1) * t->entry_data_size];
45399a2dd95SBruce Richardson 	*action_id = ((uint64_t *)data)[0];
45499a2dd95SBruce Richardson 	*action_data = &data[8];
455*42605e56SCristian Dumitrescu 	*entry_id = user_data - 1;
45699a2dd95SBruce Richardson 	*hit = 1;
45799a2dd95SBruce Richardson 	return 1;
45899a2dd95SBruce Richardson }
45999a2dd95SBruce Richardson 
46099a2dd95SBruce Richardson struct rte_swx_table_ops rte_swx_table_wildcard_match_ops = {
46199a2dd95SBruce Richardson 	.footprint_get = NULL,
46299a2dd95SBruce Richardson 	.mailbox_size_get = table_mailbox_size_get,
46399a2dd95SBruce Richardson 	.create = table_create,
46499a2dd95SBruce Richardson 	.add = NULL,
46599a2dd95SBruce Richardson 	.del = NULL,
46699a2dd95SBruce Richardson 	.lkp = (rte_swx_table_lookup_t)table_lookup,
46799a2dd95SBruce Richardson 	.free = table_free,
46899a2dd95SBruce Richardson };
469