diff --git a/common/lpm.h b/common/lpm.h index d70f0611e..655fa2c70 100644 --- a/common/lpm.h +++ b/common/lpm.h @@ -273,6 +273,9 @@ lpm_lookup(const struct lpm *lpm, uint8_t key_size, const uint8_t *key) { page = ADDR_OF(&value->page); } + if (value->value == LPM_VALUE_INVALID) + return LPM_VALUE_INVALID; + return LPM_VALUE_GET(value->value); } diff --git a/common/range_index.h b/common/range_index.h index 9dfffa09e..1110ee119 100644 --- a/common/range_index.h +++ b/common/range_index.h @@ -94,17 +94,6 @@ range_index_insert( return 0; } -static inline void -range_index_remap( - struct range_index *range_index, struct value_table *value_table -) { - uint32_t *values = ADDR_OF(&range_index->values); - - for (uint32_t idx = 0; idx < range_index->count; ++idx) { - values[idx] = value_table_get(value_table, 0, values[idx]); - } -} - static inline void range_index_free(struct range_index *range_index) { uint64_t capacity = 1 << uint64_log_up(range_index->count); diff --git a/common/remap.h b/common/remap.h index 2fb8d7157..d6e5050c3 100644 --- a/common/remap.h +++ b/common/remap.h @@ -208,7 +208,6 @@ remap_table_new_key(struct remap_table *table, uint32_t *key) { static inline int remap_table_touch(struct remap_table *table, uint32_t key, uint32_t *value) { - int res = 0; struct remap_item *item = remap_table_item(table, key); if (item->gen != table->gen) { @@ -218,7 +217,6 @@ remap_table_touch(struct remap_table *table, uint32_t key, uint32_t *value) { return -1; item->gen = table->gen; item->value = new_key; - res = 1; } struct remap_item *new_item = remap_table_item(table, item->value); @@ -235,7 +233,7 @@ remap_table_touch(struct remap_table *table, uint32_t key, uint32_t *value) { table->free_list = key; } - return res; + return 0; } /* diff --git a/common/value.h b/common/value.h index 3e9fb7088..3288d1d55 100644 --- a/common/value.h +++ b/common/value.h @@ -14,8 +14,8 @@ struct value_table { struct memory_context *memory_context; - uint32_t h_dim; uint32_t v_dim; + uint32_t h_dim; uint32_t **values; }; @@ -48,13 +48,13 @@ static inline int value_table_init( struct value_table *value_table, struct memory_context *memory_context, - uint32_t h_dim, - uint32_t v_dim + uint32_t v_dim, + uint32_t h_dim ) { SET_OFFSET_OF(&value_table->memory_context, memory_context); - value_table->h_dim = h_dim; value_table->v_dim = v_dim; + value_table->h_dim = h_dim; uint64_t value_count = h_dim; value_count *= v_dim; @@ -89,7 +89,7 @@ value_table_init( static inline uint32_t * value_table_get_ptr( - struct value_table *value_table, uint32_t h_idx, uint32_t v_idx + const struct value_table *value_table, uint32_t v_idx, uint32_t h_idx ) { uint32_t **values = ADDR_OF(&value_table->values); uint64_t idx = (v_idx * value_table->h_dim) + h_idx; @@ -100,9 +100,9 @@ value_table_get_ptr( static inline uint32_t value_table_get( - struct value_table *value_table, uint32_t h_idx, uint32_t v_idx + const struct value_table *value_table, uint32_t v_idx, uint32_t h_idx ) { - return *value_table_get_ptr(value_table, h_idx, v_idx); + return *value_table_get_ptr(value_table, v_idx, h_idx); } static inline void diff --git a/filter/classifiers/device.h b/filter/classifiers/device.h new file mode 100644 index 000000000..5fa06915b --- /dev/null +++ b/filter/classifiers/device.h @@ -0,0 +1,27 @@ +#pragma once + +#include "common/container_of.h" +#include "common/memory.h" +#include "common/value.h" + +#include "filter/filter.h" + +struct filter_query_attr_device { + struct filter_query_attr attr; + struct value_table value_table; +}; + +static inline void +filter_query_attr_device_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_device *device_attr = + container_of(attr, struct filter_query_attr_device, attr); + + value_table_free(&device_attr->value_table); + memory_bfree( + memory_context, + device_attr, + sizeof(struct filter_query_attr_device) + ); +} diff --git a/filter/classifiers/net4.h b/filter/classifiers/net4.h new file mode 100644 index 000000000..a20df04f8 --- /dev/null +++ b/filter/classifiers/net4.h @@ -0,0 +1,24 @@ +#pragma once + +#include "common/container_of.h" +#include "common/lpm.h" +#include "common/memory.h" +#include "filter/filter.h" + +struct filter_query_attr_net4 { + struct filter_query_attr attr; + struct lpm lpm; +}; + +static inline void +filter_query_attr_net4_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_net4 *net4_attr = + container_of(attr, struct filter_query_attr_net4, attr); + + lpm_free(&net4_attr->lpm); + memory_bfree( + memory_context, net4_attr, sizeof(struct filter_query_attr_net4) + ); +} diff --git a/filter/classifiers/net6.h b/filter/classifiers/net6.h index a1eb6e121..52925ed56 100644 --- a/filter/classifiers/net6.h +++ b/filter/classifiers/net6.h @@ -1,10 +1,28 @@ #pragma once +#include "common/container_of.h" #include "common/lpm.h" #include "common/value.h" +#include "filter/filter.h" -struct net6_classifier { +struct filter_query_attr_net6 { + struct filter_query_attr attr; struct lpm hi; struct lpm lo; struct value_table comb; -}; \ No newline at end of file +}; + +static inline void +filter_query_attr_net6_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_net6 *net6_attr = + container_of(attr, struct filter_query_attr_net6, attr); + + lpm_free(&net6_attr->hi); + lpm_free(&net6_attr->lo); + value_table_free(&net6_attr->comb); + memory_bfree( + memory_context, net6_attr, sizeof(struct filter_query_attr_net6) + ); +} diff --git a/filter/classifiers/port.h b/filter/classifiers/port.h new file mode 100644 index 000000000..7cfff15ef --- /dev/null +++ b/filter/classifiers/port.h @@ -0,0 +1,23 @@ +#pragma once + +#include "common/container_of.h" + +#include "filter/filter.h" + +struct filter_query_attr_port { + struct filter_query_attr attr; + struct value_table value_table; +}; + +static inline void +filter_query_attr_port_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_port *port_attr = + container_of(attr, struct filter_query_attr_port, attr); + + value_table_free(&port_attr->value_table); + memory_bfree( + memory_context, port_attr, sizeof(struct filter_query_attr_port) + ); +} diff --git a/filter/classifiers/proto_range.h b/filter/classifiers/proto_range.h index 12205959b..f060e3a06 100644 --- a/filter/classifiers/proto_range.h +++ b/filter/classifiers/proto_range.h @@ -1,12 +1,32 @@ #pragma once +#include "common/container_of.h" #include "common/value.h" + +#include "filter/filter.h" + #include "segments.h" -struct proto_range_classifier { - struct value_table table; +struct filter_query_attr_proto_range { + struct filter_query_attr attr; + struct value_table value_table; }; +static inline void +filter_query_attr_proto_range_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_proto_range *proto_range_attr = + container_of(attr, struct filter_query_attr_proto_range, attr); + + value_table_free(&proto_range_attr->value_table); + memory_bfree( + memory_context, + proto_range_attr, + sizeof(struct filter_query_attr_proto_range) + ); +} + struct proto_range_fast_classifier { struct segment_u16_classifier classifier; -}; \ No newline at end of file +}; diff --git a/filter/classifiers/vlan.h b/filter/classifiers/vlan.h new file mode 100644 index 000000000..a412fb820 --- /dev/null +++ b/filter/classifiers/vlan.h @@ -0,0 +1,23 @@ +#pragma once + +#include "common/container_of.h" + +#include "filter/filter.h" + +struct filter_query_attr_vlan { + struct filter_query_attr attr; + struct value_table value_table; +}; + +static inline void +filter_query_attr_vlan_free( + struct memory_context *memory_context, struct filter_query_attr *attr +) { + struct filter_query_attr_vlan *vlan_attr = + container_of(attr, struct filter_query_attr_vlan, attr); + + value_table_free(&vlan_attr->value_table); + memory_bfree( + memory_context, vlan_attr, sizeof(struct filter_query_attr_vlan) + ); +} diff --git a/filter/compiler.h b/filter/compiler.h index 2fd97d1c9..f502a15f4 100644 --- a/filter/compiler.h +++ b/filter/compiler.h @@ -1,6 +1,5 @@ #pragma once -#include "filter/compiler/attribute.h" #include "filter/compiler/declare.h" #include "filter/compiler/helper.h" #include "filter/filter.h" @@ -10,170 +9,455 @@ #include "common/value.h" #include -/** - * @file compiler.h - * @brief Build/teardown macros for filter classification trees. - * - * Defines: - * - filter_init: build a filter for a declared attribute signature - * - filter_free: free resources allocated by filter_init - */ -/** - * @def filter_init(filter, tag, rules, rule_count, ctx) - * @brief Build filter for signature tag into filter using rules. - * @param filter struct filter* - * @param tag name used in FILTER_COMPILER_DECLARE(...) - * @param rules const struct filter_rule* array - * @param rule_count size_t number of rules - * @param ctx const struct memory_context* source context - * @return int 0 on success, negative on error - */ -typedef int (*filter_lookup_init_func)( - struct value_registry *registry, - void **data, - const struct filter_rule **rules, - size_t rule_count, - struct memory_context *mctx -); +static inline int +filter_set_cb(uint32_t *value, void *data) { + uint32_t *rule_idx = (uint32_t *)data; + *value = *rule_idx; + return 0; +} -typedef void (*filter_lookup_free_func)( - void *data, struct memory_context *memory_context -); +static inline int +filter_set_rule_cb(uint32_t *value, void *data) { + if (*value != FILTER_RULE_INVALID) + return 0; -struct filter_lookup_handler { - filter_lookup_init_func init; - filter_lookup_free_func free; -}; + uint32_t *rule_idx = (uint32_t *)data; + *value = *rule_idx; + return 0; +} -struct filter_compiler { - uint64_t lookup_count; - struct filter_lookup_handler *lookups; -}; +static inline int +filter_remap_cb(uint32_t *value, void *data) { + struct remap_table *remap_table = (struct remap_table *)data; + return remap_table_touch(remap_table, *value, value); +} -static inline void -filter_free( - struct filter *filter, const struct filter_compiler *filter_compiler +static inline int +filter_compact_cb(uint32_t *value, void *data) { + struct remap_table *remap_table = (struct remap_table *)data; + *value = remap_table_compacted(remap_table, *value); + return 0; +} + +static inline int +filter_collect_cb(uint32_t *value, void *data) { + struct value_registry *registry = (struct value_registry *)data; + return value_registry_collect(registry, *value); +} + +/* + * Special handler for single attribute filter, the case implies the attribute + * range lookup returns the rule index instead of identifier of a rule + * combination. + */ +static inline int +filter_compile_single_attr( + struct filter *filter, + struct memory_context *memory_context, + const struct filter_rule **rules, + uint32_t rule_count, + const struct filter_compile_attr_handlers *attr_handlers ) { - for (size_t i = 0; i < filter_compiler->lookup_count; ++i) { - struct filter_vertex *v = - filter->v + filter_compiler->lookup_count + i; - if (v->data != NULL) { - filter_compiler->lookups[i].free( - ADDR_OF(&v->data), &filter->memory_context - ); - } - SET_OFFSET_OF(&v->data, NULL); - } - for (size_t i = 1; i < 2 * filter_compiler->lookup_count; ++i) { - value_registry_free(&filter->v[i].registry); + struct filter_query_attr **query_attrs = + (struct filter_query_attr **)memory_balloc( + memory_context, sizeof(struct filter_query_attr *) + ); + if (query_attrs == NULL) + return -1; + memset(query_attrs, 0, sizeof(struct filter_query_attr *)); + SET_OFFSET_OF(&filter->attrs, query_attrs); + + struct filter_compile_attr *attr = attr_handlers->create( + memory_context, attr_handlers, rules, rule_count + ); + + if (attr == NULL) { + goto error_free_attrs; } - for (size_t i = 1; i < filter_compiler->lookup_count; ++i) { - value_table_free(&filter->v[i].table); + + /* + * Set default value for all existing ranges in the attribute + * definition are. + */ + uint32_t invalid = FILTER_RULE_INVALID; + attr_handlers->iter(attr, attr_handlers, filter_set_cb, &invalid); + + /* + * Iterate over all rules and set rule index for each corresponding + * to a rule regions. + */ + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; + if (rule == NULL) + continue; + + attr_handlers->rule_iter( + attr, attr_handlers, rule, filter_set_rule_cb, &rule_idx + ); } - if (filter_compiler->lookup_count == 1) { - struct filter_vertex *v0 = filter->v; - value_registry_free(&v0->registry); - value_table_free(&v0->table); + + struct filter_query_attr *query_attr = + attr_handlers->commit(memory_context, attr); + + if (query_attr == NULL) { + attr_handlers->free_compile(memory_context, attr); + goto error_free_attrs; } + SET_OFFSET_OF(query_attrs, query_attr); + + return 0; + +error_free_attrs: + memory_bfree( + memory_context, query_attrs, sizeof(struct filter_query_attr *) + ); + SET_OFFSET_OF(&filter->attrs, NULL); + + return -1; } +/* + * Filter compilation routine. + * + * Filter logic implies the following logic: + * - each attribute definition area is split into regions with unique set of + * rule set corresponding to the region + * - each rule gets a list of region identifiers for each attribute + * - combine pairs of attributes into sets of next level identifiers + * - the last stage resolves corresponding rule index + * + * So in case of 5 attributes compilation schema for a rule looks like + * a0, a1, a2, a3, a4 -> sets of range identifiers matching to the rule + * produce a5 = a0 * a1, a6 = a2 * a3, a7 = a4 * a5 where ai * aj if s full + * join of containing values + * after then we set rule index for each pair in set of a6 * a7. + * + * The logic consist of three stages + * - initialize all the attributes and touch regions for all rules. The stage + * result in enumerate all regions with values defining of unique rule set + * identifier. Also we collect region values for each rule into registries. + * - merge pairs of values into a new ones + * - after only two set of identifiers remained - the last one merge will set + * a rule index into corresponding table. + */ + static inline int -filter_init( +filter_compile( struct filter *filter, - const struct filter_compiler *filter_compiler, + struct memory_context *memory_context, const struct filter_rule **rules, uint32_t rule_count, - struct memory_context *memory_context -) { - if (filter_compiler->lookup_count == 0) - return -1; - - memset(filter, 0, sizeof(struct filter)); + const struct filter_compile_attr_handlers *attr_handlers[], + uint32_t attr_handler_count +) { if (memory_context_init_from( &filter->memory_context, memory_context, "filter" )) { return -1; } + memory_context = &filter->memory_context; - for (uint64_t lookup_idx = 0; - lookup_idx < filter_compiler->lookup_count; - ++lookup_idx) { - struct filter_vertex *v = - filter->v + filter_compiler->lookup_count + lookup_idx; - if (value_registry_init( - &v->registry, &filter->memory_context - )) { - goto init_failed; - } - v->data = NULL; - if (filter_compiler->lookups[lookup_idx].init( - &v->registry, - &v->data, - rules, - rule_count, - &filter->memory_context - )) { - goto init_failed; + SET_OFFSET_OF(&filter->attrs, NULL); + SET_OFFSET_OF(&filter->joints, NULL); + + if (attr_handler_count == 1) + return filter_compile_single_attr( + filter, + memory_context, + rules, + rule_count, + attr_handlers[0] + ); + + struct filter_query_attr **query_attrs = + (struct filter_query_attr **)memory_balloc( + memory_context, + sizeof(struct filter_query_attr *) * attr_handler_count + ); + if (query_attrs == NULL) + goto error; + memset(query_attrs, + 0, + sizeof(struct filter_query_attr *) * attr_handler_count); + SET_OFFSET_OF(&filter->attrs, query_attrs); + + uint32_t joint_count = attr_handler_count - 1; + uint32_t registry_count = attr_handler_count + joint_count - 1; + struct value_registry *registries = + (struct value_registry *)memory_balloc( + memory_context, + sizeof(struct value_registry) * registry_count + ); + memset(registries, 0, sizeof(struct value_registry) * registry_count); + + /* + * Initialize all registries. + */ + for (uint32_t idx = 0; idx < registry_count; ++idx) { + if (value_registry_init(registries + idx, memory_context)) { + goto error_free_registries; } } - if (filter_compiler->lookup_count == 1) { - struct value_registry dummy; - if (init_dummy_registry( - &filter->memory_context, rule_count, &dummy - )) { - value_registry_free(&dummy); - goto init_failed; + struct value_table *joints = (struct value_table *)memory_balloc( + memory_context, sizeof(struct value_table) * joint_count + ); + if (joints == NULL) { + goto error_free_attrs; + } + memset(joints, 0, sizeof(struct value_table) * joint_count); + SET_OFFSET_OF(&filter->joints, joints); + + /* + * Process all the attributes assigned to the filter. + */ + for (uint32_t attr_idx = 0; attr_idx < attr_handler_count; ++attr_idx) { + struct filter_compile_attr *attr = + attr_handlers[attr_idx]->create( + memory_context, + attr_handlers[attr_idx], + rules, + rule_count + ); + + if (attr == NULL) { + goto error_free_attrs; } - if (merge_and_set_registry_values( - &filter->memory_context, - &dummy, - &filter->v[1].registry, - &filter->v[0].table + struct remap_table remap_table; + if (remap_table_init( + &remap_table, + memory_context, + attr_handlers[attr_idx]->size(attr) )) { - value_registry_free(&dummy); - goto init_failed; + goto error_free_attrs; } - value_registry_free(&dummy); - goto init_finish; - } + remap_table_new_gen(&remap_table); + + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; + if (rule == NULL) + continue; + if (attr_handlers[attr_idx]->rule_is_any( + attr, attr_handlers[attr_idx], rule + )) + continue; - for (size_t idx = filter_compiler->lookup_count - 1; idx >= 2; --idx) { - if (merge_and_collect_registry( - &filter->memory_context, - &filter->v[2 * idx].registry, - &filter->v[2 * idx + 1].registry, - &filter->v[idx].table, - &filter->v[idx].registry + /* + * Touch all regions mathing the rule. + */ + remap_table_new_gen(&remap_table); + + if (attr_handlers[attr_idx]->rule_iter( + attr, + attr_handlers[attr_idx], + rule, + filter_remap_cb, + &remap_table + )) { + goto error_free_attrs; + } + } + + /* + * Remove all region value gaps + */ + remap_table_compact(&remap_table); + if (attr_handlers[attr_idx]->iter( + attr, + attr_handlers[attr_idx], + filter_compact_cb, + &remap_table )) { - goto init_failed; + goto error_free_attrs; } + + remap_table_free(&remap_table); + + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + if (value_registry_start(registries + attr_idx)) + goto error_free_attrs; + + const struct filter_rule *rule = rules[rule_idx]; + if (rule == NULL) + continue; + + if (attr_handlers[attr_idx]->rule_is_any( + attr, attr_handlers[attr_idx], rule + )) { + /* + * Collect all region values into rule registry + * + * NOTE: this is a subject of a further + * optimization: we could the values only once. + */ + if (attr_handlers[attr_idx]->iter( + attr, + attr_handlers[attr_idx], + filter_collect_cb, + registries + attr_idx + )) { + goto error_free_attrs; + } + } else { + /* + * Collect the rule matching region values. + */ + if (attr_handlers[attr_idx]->rule_iter( + attr, + attr_handlers[attr_idx], + rule, + filter_collect_cb, + registries + attr_idx + )) { + goto error_free_attrs; + } + } + } + + struct filter_query_attr *query_attr = + attr_handlers[attr_idx]->commit(memory_context, attr); + + if (query_attr == NULL) { + attr_handlers[attr_idx]->free_compile( + memory_context, attr + ); + goto error_free_attrs; + } + SET_OFFSET_OF(query_attrs + attr_idx, query_attr); } - if (merge_and_set_registry_values( - &filter->memory_context, - &filter->v[2 * 1].registry, - &filter->v[2 * 1 + 1].registry, - &filter->v[1].table - )) { - goto init_failed; + for (uint32_t joint_idx = 0; joint_idx < joint_count; ++joint_idx) { + if (joint_idx < joint_count - 1) { + /* + * Join the rule values pair and produce a new set + * of derivative values + */ + if (merge_and_collect_registry( + memory_context, + registries + joint_idx * 2, + registries + joint_idx * 2 + 1, + joints + joint_idx, + registries + attr_handler_count + joint_idx + )) { + goto error_free_attrs; + } + } else { + /* + * The last stage - set rule index for the last one + * pair of values. + */ + if (merge_and_set_registry_values( + memory_context, + registries + joint_idx * 2, + registries + joint_idx * 2 + 1, + joints + joint_idx + )) { + goto error_free_attrs; + } + } } -init_finish: + for (uint32_t idx = 0; idx < registry_count; ++idx) + value_registry_free(registries + idx); + + memory_bfree( + memory_context, + registries, + sizeof(struct value_registry) * registry_count + ); + return 0; -init_failed: - filter_free(filter, filter_compiler); +error_free_attrs: + for (uint32_t attr_idx = 0; attr_idx < attr_handler_count; ++attr_idx) { + struct filter_query_attr *query_attr = + ADDR_OF(query_attrs + attr_idx); + if (query_attr == NULL) + continue; + attr_handlers[attr_idx]->free_query(memory_context, query_attr); + } + + for (uint32_t joint_idx = 0; joint_idx < joint_count; ++joint_idx) { + value_table_free(joints + joint_idx); + } + + memory_bfree( + memory_context, joints, sizeof(struct value_table) * joint_count + ); + +error_free_registries: + for (uint32_t idx = 0; idx < registry_count; ++idx) + value_registry_free(registries + idx); + memory_bfree( + memory_context, + registries, + sizeof(struct value_registry) * registry_count + ); + + SET_OFFSET_OF(&filter->attrs, NULL); + memory_bfree( + memory_context, + query_attrs, + sizeof(struct filter_query_attr *) * attr_handler_count + ); + +error: + SET_OFFSET_OF(&filter->joints, NULL); + return -1; } -// TODO: docs -static inline uint64_t -filter_memory_usage(struct filter *filter) { - struct memory_context *mctx = &filter->memory_context; - assert(mctx->balloc_size >= mctx->bfree_size); - return mctx->balloc_size - mctx->bfree_size; +static inline void +filter_destroy( + struct filter *filter, + const struct filter_compile_attr_handlers *attr_handlers[], + uint32_t attr_handler_count +) { + struct memory_context *memory_context = &filter->memory_context; + + struct filter_query_attr **query_attrs = ADDR_OF(&filter->attrs); + + if (query_attrs != NULL) { + for (uint32_t attr_idx = 0; attr_idx < attr_handler_count; + ++attr_idx) { + struct filter_query_attr *query_attr = + ADDR_OF(query_attrs + attr_idx); + if (query_attr == NULL) + continue; + attr_handlers[attr_idx]->free_query( + memory_context, query_attr + ); + } + memory_bfree( + memory_context, + query_attrs, + sizeof(struct filter_query_attr *) * attr_handler_count + ); + } + + uint32_t joint_count = attr_handler_count - 1; + struct value_table *joints = ADDR_OF(&filter->joints); + if (joints != NULL) { + for (uint32_t joint_idx = 0; joint_idx < joint_count; + ++joint_idx) { + value_table_free(joints + joint_idx); + } + memory_bfree( + memory_context, + joints, + sizeof(struct value_table) * joint_count + ); + } + memset(filter, 0, sizeof(struct filter)); } + +#define filter_init(filter, sign, rules, count, mctx) \ + filter_compile( \ + filter, mctx, rules, count, sign, sizeof(sign) / sizeof(*sign) \ + ) + +#define filter_free(filter, sign) \ + filter_destroy(filter, sign, sizeof(sign) / sizeof(*sign)) diff --git a/filter/compiler/attribute.h b/filter/compiler/attribute.h deleted file mode 100644 index 62bfa2fed..000000000 --- a/filter/compiler/attribute.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "common/memory.h" -#include "common/registry.h" - -#include "filter/rule.h" - -#include "declare.h" - -#define REGISTER_ATTRIBUTE(name) \ - int FILTER_ATTR_COMPILER_INIT_FUNC(name)( \ - struct value_registry * registry, \ - void **data, \ - const struct filter_rule **rules, \ - size_t rule_count, \ - struct memory_context *mctx \ - ); \ - void FILTER_ATTR_COMPILER_FREE_FUNC(name)( \ - void *data, struct memory_context *mctx \ - ); - -REGISTER_ATTRIBUTE(port_src); -REGISTER_ATTRIBUTE(port_dst); -REGISTER_ATTRIBUTE(port_fast_src); -REGISTER_ATTRIBUTE(port_fast_dst); -REGISTER_ATTRIBUTE(proto); -REGISTER_ATTRIBUTE(proto_range); -REGISTER_ATTRIBUTE(proto_range_fast); -REGISTER_ATTRIBUTE(net4_src); -REGISTER_ATTRIBUTE(net4_dst); -REGISTER_ATTRIBUTE(net6_src); -REGISTER_ATTRIBUTE(net6_dst); -REGISTER_ATTRIBUTE(vlan); -REGISTER_ATTRIBUTE(device); -REGISTER_ATTRIBUTE(net4_fast_dst); -REGISTER_ATTRIBUTE(net4_fast_src); -REGISTER_ATTRIBUTE(net6_fast_dst); -REGISTER_ATTRIBUTE(net6_fast_src); - -#undef REGISTER_ATTRIBUTE diff --git a/filter/compiler/declare.h b/filter/compiler/declare.h index 9316bbb56..c0bc4ec67 100644 --- a/filter/compiler/declare.h +++ b/filter/compiler/declare.h @@ -1,23 +1,299 @@ #pragma once +#include "common/registry.h" +#include "common/remap.h" + #include "common/for_each.h" -#define FILTER_ATTR_COMPILER(name) name##_attr_compiler +#define FILTER_ATTR_COMPILE(name) &filter_compile_attr_##name.attr_handlers + +#define FILTER_COMPILER_DECLARE(tag, ...) \ + static const struct filter_compile_attr_handlers *tag[] = { \ + FOR_EACH(FILTER_ATTR_COMPILE, __VA_ARGS__), \ + }; + +/* + * There are following key concepts of filter compilation: + * - filter consists of a set of attributes each attribute is responsible + * for one of rule conditions - surce network, protocol, vlan, e.t.c. + * - each attribute has some definition area where it works on + * - attribute splits the definition ares into regions with the following + * requirements: + * - a point of a region has the same set of rules mathing + * - each region has it's own identifier (value) + * to the point as any other point of the region + * - attribute provides following interfaces: + * - size retrieves count of regions known to the attribute + * - iterate over the whole definition area + * - iterate over a rule mathing regions + * - check if a rule covers the whole definition area - used in sake of + * efficiency + * - commit produces a classifier suitable for obtaining mathing region + * value for a packet. Commit detaches the classifier from attribute + * and frees resources assigned to the attribute in case of success + * - free releases all associated resources and should not be called in + * case of commit success + */ + +/* + * Filter rule forward declaration. + * + * The structure is used to obtain specific rule attribute like network, + * port range or protocol. + */ +struct filter_rule; + +/* + * Compile attribute forward declaration - compilation API handler. + * + * The structure used to store attribute specific temporaray compilation data. + */ +struct filter_compile_attr {}; +/* + * Compilation attribute virtual table forward declaration. + * + * The structure also used as compilation API handler. + */ +struct filter_compile_attr_handlers; + +/* + * Attribute creation routine builds a set of regions for provided ruleset + * and initializes each region value to zero. + */ +typedef struct filter_compile_attr *(*filter_compile_attr_create_func)( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule **rules, + uint32_t rule_count +); + +/* + * Retrieves count of regions of an attribute + */ +typedef uint32_t (*filter_compile_attr_size_func)( + const struct filter_compile_attr *attr +); + +/* + * Checks if a rule covers the whole definion area + */ +typedef int (*filter_compile_attr_rule_is_any_func)( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule *rule +); + +/* + * A callback with pointer to a region value and associated custom pointer + */ +typedef int (*filter_compile_attr_iter_cb_func)(uint32_t *value, void *data); + +/* + * Iterates over an attribute definition area with a callback for the each + * region value + */ +typedef int (*filter_compile_attr_iter_func)( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +); + +/* + * Iterates over a rule regions with a callback for the each region value + */ +typedef int (*filter_compile_attr_rule_iter_func)( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +); + +/* + * Produces a classifier and frees the attribute in case of success + */ +typedef struct filter_query_attr *(*filter_compile_attr_commit_func)( + struct memory_context *memory_context, struct filter_compile_attr *attr +); + +/* + * Frees attribute compilation data + */ +typedef void (*filter_compile_attr_free_compile_func)( + struct memory_context *memory_context, struct filter_compile_attr *attr +); + +/* + * Frees attribute classifier data + */ +typedef void (*filter_compile_attr_free_query_func)( + struct memory_context *memory_context, struct filter_query_attr *attr +); + +/* + * Compilation attribute virtual table. The table may be incorporated into + * a structure providing additional routines, for example obtaining specific + * conditions - networks, protocols and etc + */ +struct filter_compile_attr_handlers { + filter_compile_attr_create_func create; + filter_compile_attr_size_func size; + filter_compile_attr_rule_is_any_func rule_is_any; + filter_compile_attr_rule_iter_func rule_iter; + filter_compile_attr_iter_func iter; + filter_compile_attr_commit_func commit; + filter_compile_attr_free_compile_func free_compile; + filter_compile_attr_free_query_func free_query; +}; + +static inline int +filter_compile_attr_touch(uint32_t *value, void *data) { + struct remap_table *remap_table = (struct remap_table *)data; + return remap_table_touch(remap_table, *value, value); +} + +static inline int +filter_compile_attr_collect(uint32_t *value, void *data) { + struct value_registry *value_registry = (struct value_registry *)data; + return value_registry_collect(value_registry, *value); +} -#define FILTER_ATTR_COMPILER_INIT_FUNC(name) name##_attr_init -#define FILTER_ATTR_COMPILER_FREE_FUNC(name) name##_attr_free +static inline int +filter_compile_attr_compact(uint32_t *value, void *data) { + struct remap_table *remap_table = (struct remap_table *)data; + *value = remap_table_compacted(remap_table, *value); + return 0; +} -#define FILTER_ATTR_LOOKUP_HANDLER(name) \ - { \ - name##_attr_init, \ - name##_attr_free, \ +/* + * The routine provides the backward compatibility with the current + * compilation procedure and defined attributes. + */ +static inline int +filter_compile_attr_build( + const struct filter_compile_attr_handlers *attr_handlers, + struct value_registry *registry, + void **data, + const struct filter_rule **rules, + size_t rule_count, + struct memory_context *memory_context +) { + /* + * Splits the definition area int regions and initialize all of them + * with zero values. + */ + struct filter_compile_attr *attr = attr_handlers->create( + memory_context, attr_handlers, rules, rule_count + ); + if (attr == NULL) + return -1; + + /* + * `remap_table is used to enumerate regions - each rule touch its + * regions so each region gains a value specific to matching set of + * rules. + */ + struct remap_table remap_table; + if (remap_table_init( + &remap_table, memory_context, attr_handlers->size(attr) + )) { + goto error; } -#define FILTER_COMPILER_DECLARE(tag, ...) \ - static const struct filter_compiler *tag = &(struct filter_compiler){ \ - sizeof((struct filter_lookup_handler[] \ - ){FOR_EACH(FILTER_ATTR_LOOKUP_HANDLER, __VA_ARGS__)}) / \ - sizeof(struct filter_lookup_handler), \ - (struct filter_lookup_handler[] \ - ){FOR_EACH(FILTER_ATTR_LOOKUP_HANDLER, __VA_ARGS__)}, \ - }; + for (uint32_t idx = 0; idx < rule_count; ++idx) { + if (rules[idx] == NULL) + continue; + /* + * If a rule covers the whole area there is no meaning to + * touch values - all of them just gain update without any + * distinction result. + */ + if (attr_handlers->rule_is_any(attr, attr_handlers, rules[idx])) + continue; + + remap_table_new_gen(&remap_table); + + // Touch the rule mathing values + if (attr_handlers->rule_iter( + attr, + attr_handlers, + rules[idx], + filter_compile_attr_touch, + &remap_table + )) { + remap_table_free(&remap_table); + goto error; + } + } + + /* + * Remap table compation removes gaps of unsed values and makes the + * resulting set of values smaller + */ + + remap_table_compact(&remap_table); + + /* + * Now reassing compacted values to each region defined for the + * attribute. + */ + + if (attr_handlers->iter( + attr, + attr_handlers, + filter_compile_attr_compact, + &remap_table + )) { + remap_table_free(&remap_table); + goto error; + } + + remap_table_free(&remap_table); + + for (uint32_t idx = 0; idx < rule_count; ++idx) { + if (value_registry_start(registry)) + goto error; + if (rules[idx] == NULL) + continue; + /* + * Collect rule matching values - there are two options: + * - collect all known values in case if rule is matching any + * - collect rule specific attributes + * In the first case we could collect all the values only + * once which is the subject of further investigation. + */ + if (attr_handlers->rule_is_any( + attr, attr_handlers, rules[idx] + )) { + if (attr_handlers->iter( + attr, + attr_handlers, + filter_compile_attr_collect, + registry + )) + goto error; + + } else { + if (attr_handlers->rule_iter( + attr, + attr_handlers, + rules[idx], + filter_compile_attr_collect, + registry + )) + goto error; + } + } + + void *dp_data = attr_handlers->commit(memory_context, attr); + SET_OFFSET_OF(data, dp_data); + if (dp_data == NULL) + goto error; + + return 0; + +error: + attr_handlers->free_compile(memory_context, attr); + return -1; +} diff --git a/filter/compiler/device.c b/filter/compiler/device.c index a7903565b..977b4aab0 100644 --- a/filter/compiler/device.c +++ b/filter/compiler/device.c @@ -1,11 +1,6 @@ -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" +#include "device.h" #include "declare.h" -#include "filter/rule.h" - -#include int FILTER_ATTR_COMPILER_INIT_FUNC(device)( @@ -15,115 +10,25 @@ FILTER_ATTR_COMPILER_INIT_FUNC(device)( size_t rule_count, struct memory_context *memory_context ) { - uint64_t max_device_id = 0; - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - if (*r_ptr == NULL) - continue; - const struct filter_rule *r = *r_ptr; - - for (uint16_t idx = 0; idx < r->device_count; ++idx) { - if (r->devices[idx].id > max_device_id) { - max_device_id = r->devices[idx].id; - } - } - } - - struct value_table *t = - memory_balloc(memory_context, sizeof(struct value_table)); - if (t == NULL) { - return -1; - } - int res = value_table_init(t, memory_context, 1, max_device_id + 1); - if (res < 0) { - goto error_init; - } - SET_OFFSET_OF(data, t); - - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, max_device_id + 1)) { - goto error_remap_table; - } - - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - if (*r_ptr == NULL) - continue; - const struct filter_rule *r = *r_ptr; - - if (r->device_count == 0) { - continue; - } - remap_table_new_gen(&remap_table); - for (uint16_t idx = 0; idx < r->device_count; ++idx) { - uint32_t *value = - value_table_get_ptr(t, 0, r->devices[idx].id); - if (remap_table_touch(&remap_table, *value, value) < - 0) { - goto error_touch; - } - } - } - - remap_table_compact(&remap_table); - value_table_compact(t, &remap_table); - remap_table_free(&remap_table); - - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - value_registry_start(registry); - - if (*r_ptr == NULL) - continue; - const struct filter_rule *r = *r_ptr; - - if (r->device_count == 0) { - for (uint64_t id = 0; id < max_device_id + 1; ++id) { - if (value_registry_collect( - registry, value_table_get(t, 0, id) - )) { - goto error_collect; - } - } - } else { - for (uint16_t idx = 0; idx < r->device_count; ++idx) { - if (value_registry_collect( - registry, - value_table_get( - t, 0, r->devices[idx].id - ) - )) { - goto error_collect; - } - } - } - } - return 0; - -error_touch: - remap_table_free(&remap_table); - -error_collect: -error_remap_table: - value_table_free(t); - SET_OFFSET_OF(data, NULL); - -error_init: - memory_bfree(memory_context, t, sizeof(struct value_table)); - - return -1; + return filter_compile_attr_build( + &filter_compile_attr_device.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context + + ); } void FILTER_ATTR_COMPILER_FREE_FUNC(device)( void *data, struct memory_context *memory_context ) { - struct value_table *t = (struct value_table *)data; - if (t == NULL) + struct filter_query_attr_device *attr = + (struct filter_query_attr_device *)data; + if (attr == NULL) return; - value_table_free(t); - memory_bfree(memory_context, t, sizeof(struct value_table)); + + filter_query_attr_device_free(memory_context, &attr->attr); } diff --git a/filter/compiler/device.h b/filter/compiler/device.h new file mode 100644 index 000000000..f6725d0a5 --- /dev/null +++ b/filter/compiler/device.h @@ -0,0 +1,259 @@ +#pragma once + +#include + +#include "common/container_of.h" +#include "common/memory.h" +#include "common/registry.h" +#include "common/value.h" + +#include "declare.h" +#include "filter/rule.h" + +#include "filter/classifiers/device.h" + +struct filter_compile_device_attr { + struct filter_compile_attr attr; + struct filter_query_attr_device *query_attr; +}; + +typedef void (*filter_rule_get_device_func)( + const struct filter_rule *filter_rule, struct filter_devices *devices +); + +struct filter_compile_attr_device_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_device_func get_devices; +}; + +static inline struct filter_compile_attr * +filter_compile_attr_device_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + struct filter_compile_attr_device_handlers *device_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_device_handlers, + attr_handlers + ); + + struct filter_compile_device_attr *attr = + (struct filter_compile_device_attr *)memory_balloc( + memory_context, + sizeof(struct filter_compile_device_attr) + ); + if (attr == NULL) { + return NULL; + } + + attr->query_attr = (struct filter_query_attr_device *)memory_balloc( + memory_context, sizeof(struct filter_query_attr_device) + ); + + if (attr->query_attr == NULL) + goto error_free; + + uint32_t max_device_id = 0; + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; + if (rule == NULL) + continue; + + struct filter_devices devices; + device_handlers->get_devices(rule, &devices); + + for (uint32_t idx = 0; idx < devices.count; ++idx) { + if (devices.items[idx].id > max_device_id) { + max_device_id = devices.items[idx].id; + } + } + } + + if (value_table_init( + &attr->query_attr->value_table, + memory_context, + 1, + max_device_id + 1 + )) { + goto error_free_attr; + } + + return &attr->attr; + +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_device) + ); + +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_device_attr) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_device_size(const struct filter_compile_attr *attr) { + struct filter_compile_device_attr *device_attr = + container_of(attr, struct filter_compile_device_attr, attr); + + return device_attr->query_attr->value_table.h_dim * + device_attr->query_attr->value_table.v_dim; +} + +static inline int +filter_compile_attr_device_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_device_attr *device_attr = + container_of(attr, struct filter_compile_device_attr, attr); + + struct filter_query_attr_device *query_attr = device_attr->query_attr; + + for (uint32_t h_idx = 0; h_idx < query_attr->value_table.h_dim; + ++h_idx) { + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, h_idx + ), + cb_func_data + )) { + return -1; + } + } + + return 0; +} + +static inline int +filter_compile_attr_device_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + struct filter_compile_attr_device_handlers *device_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_device_handlers, + attr_handlers + ); + + (void)attr; + + struct filter_devices devices; + device_handlers->get_devices(rule, &devices); + return devices.count == 0; +} + +static inline int +filter_compile_attr_device_rule_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_device_handlers *device_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_device_handlers, + attr_handlers + ); + + struct filter_compile_device_attr *device_attr = + container_of(attr, struct filter_compile_device_attr, attr); + + struct filter_devices devices; + device_handlers->get_devices(rule, &devices); + + struct filter_query_attr_device *query_attr = device_attr->query_attr; + + for (uint32_t idx = 0; idx < devices.count; ++idx) { + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, + 0, + devices.items[idx].id + ), + cb_func_data + )) { + return -1; + } + } + + return 0; +} + +static inline void +filter_compile_attr_device_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_device_attr *device_attr = + container_of(attr, struct filter_compile_device_attr, attr); + + if (device_attr->query_attr != NULL) { + value_table_free(&device_attr->query_attr->value_table); + memory_bfree( + memory_context, + device_attr->query_attr, + sizeof(struct filter_query_attr_device) + ); + } + + memory_bfree( + memory_context, + device_attr, + sizeof(struct filter_compile_device_attr) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_device_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_device_attr *device_attr = + container_of(attr, struct filter_compile_device_attr, attr); + + struct filter_query_attr_device *query_attr = device_attr->query_attr; + + device_attr->query_attr = NULL; + filter_compile_attr_device_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers filter_compile_get_devices = { + .create = filter_compile_attr_device_create, + .size = filter_compile_attr_device_size, + .iter = filter_compile_attr_device_iter, + .rule_iter = filter_compile_attr_device_rule_iter, + .rule_is_any = filter_compile_attr_device_rule_is_any, + .commit = filter_compile_attr_device_commit, + .free_compile = filter_compile_attr_device_free, + .free_query = filter_query_attr_device_free, +}; + +static inline void +filter_rule_get_devices( + const struct filter_rule *rule, struct filter_devices *devices +) { + devices->count = rule->device_count; + devices->items = rule->devices; +} + +static const struct filter_compile_attr_device_handlers + filter_compile_attr_device = { + .attr_handlers = filter_compile_get_devices, + .get_devices = filter_rule_get_devices, +}; diff --git a/filter/compiler/helper.c b/filter/compiler/helper.c index eeaee6159..47bdb33cf 100644 --- a/filter/compiler/helper.c +++ b/filter/compiler/helper.c @@ -60,12 +60,12 @@ merge_and_set_registry_values( return -1; } - for (uint64_t v_idx = 0; v_idx < value_registry_capacity(registry2); + for (uint64_t v_idx = 0; v_idx < value_registry_capacity(registry1); ++v_idx) { for (uint64_t h_idx = 0; - h_idx < value_registry_capacity(registry1); + h_idx < value_registry_capacity(registry2); ++h_idx) { - *value_table_get_ptr(table, h_idx, v_idx) = + *value_table_get_ptr(table, v_idx, h_idx) = FILTER_RULE_INVALID; } } diff --git a/filter/compiler/net4.c b/filter/compiler/net4.c index 3ec9fdf61..99b6ef7f7 100644 --- a/filter/compiler/net4.c +++ b/filter/compiler/net4.c @@ -1,286 +1,65 @@ -#include "../rule.h" -#include "common/lpm.h" -#include "common/range_collector.h" -#include "common/registry.h" -#include "common/value.h" +#include "net4.h" #include "declare.h" -#include "helper.h" -//////////////////////////////////////////////////////////////////////////////// - -typedef void (*rule_get_net4_func)( - const struct filter_rule *rule, struct net4 **net, uint32_t *count -); - -static inline void -action_get_net4_src( - const struct filter_rule *rule, struct net4 **net, uint32_t *count -) { - *net = rule->net4.srcs; - *count = rule->net4.src_count; -} - -static inline void -action_get_net4_dst( - const struct filter_rule *action, struct net4 **net, uint32_t *count -) { - *net = action->net4.dsts; - *count = action->net4.dst_count; -} - -static inline int -net4_collect_values( - struct net4 *start, - uint32_t count, - struct range_index *range_index, - struct value_table *table, - struct remap_table *remap_table -) { - uint32_t *values = ADDR_OF(&range_index->values); - - for (struct net4 *net4 = start; net4 < start + count; ++net4) { - if (*(uint32_t *)net4->mask == 0x00000000) - continue; - uint32_t to = - *(uint32_t *)net4->addr | ~*(uint32_t *)net4->mask; - filter_key_inc(4, (uint8_t *)&to); - - uint32_t start = - radix_lookup(&range_index->radix, 4, net4->addr); - uint32_t stop = range_index->count; - if (to != 0) - stop = radix_lookup( - &range_index->radix, 4, (uint8_t *)&to - ); - - for (uint32_t idx = start; idx < stop; ++idx) { - uint32_t *value = - value_table_get_ptr(table, 0, values[idx]); - if (remap_table_touch(remap_table, *value, value) < 0) { - return -1; - } - } - } - - return 0; -} - -static inline void -net4_collect_registry( - struct net4 *start, - uint32_t count, - struct lpm *lpm, - struct value_registry *registry -) { - for (struct net4 *net4 = start; net4 < start + count; ++net4) { - uint32_t addr = *(uint32_t *)net4->addr; - uint32_t mask = *(uint32_t *)net4->mask; - uint32_t to = addr | ~mask; - lpm4_collect_values( - lpm, - (uint8_t *)&addr, - (uint8_t *)&to, - lpm_collect_registry_iterator, - registry - ); - } -} - -static inline int -collect_net4_values( - struct memory_context *memory_context, - const struct filter_rule **actions, - uint32_t count, - rule_get_net4_func get_net4, - struct lpm *lpm, - struct value_registry *registry -) { - struct range_collector collector; - if (range_collector_init(&collector, memory_context)) - goto error; - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - if (action->net4.src_count == 0 && - action->net4.dst_count == 0) { - continue; - } - - struct net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); - - for (struct net4 *net4 = nets; net4 < nets + net_count; - ++net4) { - if (range4_collector_add( - &collector, - net4->addr, - __builtin_popcountll(*(uint32_t *)net4->mask - ) - )) - goto error_collector; - } - } - if (lpm_init(lpm, memory_context)) { - goto error_collector; - } - struct range_index range_index; - if (range_index_init(&range_index, memory_context)) { - goto error_lpm; - } - - if (range_collector_collect(&collector, 4, lpm, &range_index)) { - goto error_range_collect; - } - - struct value_table table; - if (value_table_init(&table, memory_context, 1, collector.count)) - goto error_table; - - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, collector.count)) - goto error_remap; - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - - remap_table_new_gen(&remap_table); - - if (*action_ptr == NULL) - continue; - - const struct filter_rule *action = *action_ptr; - - struct net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); - - if (net4_collect_values( - nets, net_count, &range_index, &table, &remap_table - )) { - goto error_net_collect; - } - } - - remap_table_compact(&remap_table); - value_table_compact(&table, &remap_table); - lpm4_remap(lpm, &table); - lpm4_compact(lpm); - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - // A value range should be created even for empty rules - value_registry_start(registry); - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); - - net4_collect_registry(nets, net_count, lpm, registry); - } - - remap_table_free(&remap_table); - value_table_free(&table); - range_index_free(&range_index); - range_collector_free(&collector, 4); - return 0; - -error_net_collect: - remap_table_free(&remap_table); - -error_remap: - value_table_free(&table); - -error_table: - -error_range_collect: - range_index_free(&range_index); - -error_lpm: - lpm_free(lpm); - -error_collector: - range_collector_free(&collector, 4); - -error: - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// - -// Allows to initialize attribute for IPv4 source address. int FILTER_ATTR_COMPILER_INIT_FUNC(net4_src)( struct value_registry *registry, void **data, - const struct filter_rule **actions, - size_t actions_count, + const struct filter_rule **rules, + size_t rule_count, struct memory_context *memory_context ) { - struct lpm *lpm = memory_balloc(memory_context, sizeof(struct lpm)); - SET_OFFSET_OF(data, lpm); - return collect_net4_values( - memory_context, - actions, - actions_count, - action_get_net4_src, - lpm, - registry + return filter_compile_attr_build( + &filter_compile_attr_net4_src.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context + ); } -// Allows to initialize attribute for IPv4 destination address. int FILTER_ATTR_COMPILER_INIT_FUNC(net4_dst)( struct value_registry *registry, void **data, - const struct filter_rule **actions, - size_t actions_count, + const struct filter_rule **rules, + size_t rule_count, struct memory_context *memory_context ) { - struct lpm *lpm = memory_balloc(memory_context, sizeof(struct lpm)); - SET_OFFSET_OF(data, lpm); - return collect_net4_values( - memory_context, - actions, - actions_count, - action_get_net4_dst, - lpm, - registry - ); -} + return filter_compile_attr_build( + &filter_compile_attr_net4_dst.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context -// Allows to free data for IPv4 classification. -static void -free_net4(void *data, struct memory_context *memory_context) { - struct lpm *lpm = (struct lpm *)data; - if (lpm == NULL) - return; - lpm_free(lpm); - memory_bfree(memory_context, lpm, sizeof(struct lpm)); + ); } void FILTER_ATTR_COMPILER_FREE_FUNC(net4_src)( void *data, struct memory_context *memory_context ) { - free_net4(data, memory_context); + struct filter_query_attr_net4 *attr = + (struct filter_query_attr_net4 *)data; + if (attr == NULL) + return; + + filter_query_attr_net4_free(memory_context, &attr->attr); } void FILTER_ATTR_COMPILER_FREE_FUNC(net4_dst)( void *data, struct memory_context *memory_context ) { - free_net4(data, memory_context); + struct filter_query_attr_net4 *attr = + (struct filter_query_attr_net4 *)data; + if (attr == NULL) + return; + + filter_query_attr_net4_free(memory_context, &attr->attr); } diff --git a/filter/compiler/net4.h b/filter/compiler/net4.h new file mode 100644 index 000000000..4565c1536 --- /dev/null +++ b/filter/compiler/net4.h @@ -0,0 +1,331 @@ +#include "../rule.h" +#include "common/lpm.h" +#include "common/range_collector.h" +#include "common/registry.h" +#include "common/value.h" +#include "filter/classifiers/net4.h" + +#include "declare.h" +#include "helper.h" + +typedef void (*filter_rule_get_net4s_func)( + const struct filter_rule *filter_rule, struct filter_net4s *net +); + +struct filter_compile_net_attr { + struct filter_compile_attr attr; + struct filter_query_attr_net4 *query_attr; + + struct range_index range_index; + struct value_table value_table; +}; + +struct filter_compile_attr_net4_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_net4s_func get_net4s; +}; + +static inline struct filter_compile_attr * +filter_compile_attr_net_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + struct filter_compile_attr_net4_handlers *net_handlers = container_of( + attr_handlers, + struct filter_compile_attr_net4_handlers, + attr_handlers + ); + + struct filter_compile_net_attr *attr = memory_balloc( + memory_context, sizeof(struct filter_compile_net_attr) + ); + if (attr == NULL) { + return NULL; + } + + struct range_collector collector; + if (range_collector_init(&collector, memory_context)) + goto error_free; + + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; + if (rule == NULL) + continue; + + struct filter_net4s nets; + net_handlers->get_net4s(rule, &nets); + const struct filter_net4s *net = &nets; + + for (struct net4 *net4 = net->items; + net4 < net->items + net->count; + ++net4) { + uint8_t from[4]; + for (uint32_t idx = 0; idx < 4; ++idx) { + from[idx] = net4->addr[idx] & net4->mask[idx]; + } + + if (range4_collector_add( + &collector, + from, + __builtin_popcountll(*(uint32_t *)net4->mask + ) + )) { + goto error_collector; + } + } + } + + if (range_index_init(&attr->range_index, memory_context)) { + goto error_collector; + } + + attr->query_attr = (struct filter_query_attr_net4 *)memory_balloc( + memory_context, sizeof(struct filter_query_attr_net4) + ); + if (attr->query_attr == NULL) + goto error_range_index; + + // FIXME lpm should be built while commit + if (lpm_init(&attr->query_attr->lpm, memory_context)) { + goto error_query; + } + + if (range_collector_collect( + &collector, 4, &attr->query_attr->lpm, &attr->range_index + )) { + goto error_collect; + } + + if (value_table_init( + &attr->value_table, memory_context, 1, collector.count + )) { + goto error_collect; + } + + range_collector_free(&collector, 4); + + return &attr->attr; + +error_collect: + lpm_free(&attr->query_attr->lpm); + +error_query: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_net4) + ); + +error_range_index: + range_index_free(&attr->range_index); + +error_collector: + range_collector_free(&collector, 4); + +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net_attr) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_net_size(const struct filter_compile_attr *attr) { + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); + + return net_attr->value_table.v_dim * net_attr->value_table.h_dim; +} + +static inline int +filter_compile_attr_net_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + + struct filter_compile_attr_net4_handlers *net_handlers = container_of( + attr_handlers, + struct filter_compile_attr_net4_handlers, + attr_handlers + ); + + (void)attr; + + struct filter_net4s nets; + net_handlers->get_net4s(rule, &nets); + + return nets.count == 0 || + (nets.items[0].mask[0] == 0 && nets.items[0].mask[1] == 0 && + nets.items[0].mask[2] == 0 && nets.items[0].mask[3] == 0); +} + +static inline int +filter_compile_attr_net_iterate( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_net4_handlers *net_handlers = container_of( + attr_handlers, + struct filter_compile_attr_net4_handlers, + attr_handlers + ); + + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); + + struct filter_net4s nets; + net_handlers->get_net4s(rule, &nets); + const struct filter_net4s *net = &nets; + + uint32_t *range_index_values = ADDR_OF(&net_attr->range_index.values); + + for (uint32_t net_idx = 0; net_idx < net->count; ++net_idx) { + const struct net4 *net4 = net->items + net_idx; + + uint8_t from[4]; + uint8_t to[4]; + for (uint32_t idx = 0; idx < 4; ++idx) { + from[idx] = net4->addr[idx] & net4->mask[idx]; + to[idx] = net4->addr[idx] | ~net4->mask[idx]; + } + filter_key_inc(4, to); + + uint32_t start = + radix_lookup(&net_attr->range_index.radix, 4, from); + uint32_t stop = + radix_lookup(&net_attr->range_index.radix, 4, to); + if (stop == 0) { + /* + * The only chance get zero here is for the last one + * item. + */ + stop = net_attr->range_index.count; + } + + for (uint32_t idx = start; idx < stop; ++idx) { + if (iter_cb_func( + value_table_get_ptr( + &net_attr->value_table, + 0, + range_index_values[idx] + ), + cb_func_data + )) { + return -1; + } + } + } + + return 0; +} + +static inline int +filter_compile_attr_net_iterate_any( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); + + for (uint32_t idx = 0; idx < net_attr->value_table.h_dim; ++idx) { + if (iter_cb_func( + value_table_get_ptr(&net_attr->value_table, 0, idx), + cb_func_data + )) { + return -1; + } + } + + return 0; +} + +static inline void +filter_compile_attr_net_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); + + if (net_attr->query_attr != NULL) { + lpm_free(&net_attr->query_attr->lpm); + memory_bfree( + memory_context, + net_attr->query_attr, + sizeof(struct filter_query_attr_net4) + ); + } + + range_index_free(&net_attr->range_index); + value_table_free(&net_attr->value_table); + + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net_attr) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_net_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); + + struct filter_query_attr_net4 *query_attr = net_attr->query_attr; + + struct lpm *lpm = &query_attr->lpm; + + lpm4_remap(lpm, &net_attr->value_table); + lpm4_compact(lpm); + + net_attr->query_attr = NULL; + + filter_compile_attr_net_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers filter_compile_get_net = { + .create = filter_compile_attr_net_create, + .size = filter_compile_attr_net_size, + .rule_iter = filter_compile_attr_net_iterate, + .rule_is_any = filter_compile_attr_net_rule_is_any, + .iter = filter_compile_attr_net_iterate_any, + .commit = filter_compile_attr_net_commit, + .free_compile = filter_compile_attr_net_free, + .free_query = filter_query_attr_net4_free, +}; + +static inline void +get_net_src(const struct filter_rule *rule, struct filter_net4s *net) { + net->count = rule->net4.src_count; + net->items = rule->net4.srcs; +} + +static inline void +get_net_dst(const struct filter_rule *rule, struct filter_net4s *net) { + net->count = rule->net4.dst_count; + net->items = rule->net4.dsts; +} + +static const struct filter_compile_attr_net4_handlers + filter_compile_attr_net4_src = { + .attr_handlers = filter_compile_get_net, + .get_net4s = get_net_src, +}; + +static const struct filter_compile_attr_net4_handlers + filter_compile_attr_net4_dst = { + .attr_handlers = filter_compile_get_net, + .get_net4s = get_net_dst, +}; diff --git a/filter/compiler/net6.c b/filter/compiler/net6.c index ffb6e8940..efe9e0754 100644 --- a/filter/compiler/net6.c +++ b/filter/compiler/net6.c @@ -1,473 +1,24 @@ -#include "../rule.h" - -#include "common/lpm.h" -#include "common/range_collector.h" - -#include "common/registry.h" - -#include "../classifiers/net6.h" +#include "net6.h" #include "declare.h" -//////////////////////////////////////////////////////////////////////////////// - -typedef void (*action_get_net6_func)( - const struct filter_rule *rule, struct net6 **net, uint32_t *count -); - -static inline void -action_get_net6_src( - const struct filter_rule *rule, struct net6 **net, uint32_t *count -) { - *net = rule->net6.srcs; - *count = rule->net6.src_count; -} - -static inline void -action_get_net6_dst( - const struct filter_rule *action, struct net6 **net, uint32_t *count -) { - *net = action->net6.dsts; - *count = action->net6.dst_count; -} - -//////////////////////////////////////////////////////////////////////////////// - -typedef void (*net6_get_part_func)( - struct net6 *net, uint8_t **addr, uint8_t **mask -); - -static inline void -net6_get_hi_part(struct net6 *net, uint8_t **addr, uint8_t **mask) { - *addr = net->addr; - *mask = net->mask; -} - -static inline void -net6_get_lo_part(struct net6 *net, uint8_t **addr, uint8_t **mask) { - *addr = net->addr + 8; - *mask = net->mask + 8; -} - -//////////////////////////////////////////////////////////////////////////////// - -static inline void -net6_normalize(struct net6 *src, struct net6 *dst) { - memcpy(dst->addr, src->addr, 16); - memcpy(dst->mask, src->mask, 16); - for (uint8_t idx = 0; idx < 16; ++idx) - dst->addr[idx] &= src->mask[idx]; -} - -static inline int -collect_net6_range( - struct memory_context *memory_context, - const struct filter_rule **actions, - uint32_t count, - action_get_net6_func get_net6, - net6_get_part_func get_part, - struct lpm *lpm, - struct range_index *ri -) { - struct range_collector collector; - if (range_collector_init(&collector, memory_context)) - goto error; - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); - - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); - - uint8_t *addr; - uint8_t *mask; - get_part(&net6, &addr, &mask); - - if (range8_collector_add( - &collector, - addr, - __builtin_popcountll(*(uint64_t *)mask) - )) - goto error_collector; - } - } - if (lpm_init(lpm, memory_context)) { - goto error_lpm; - } - - if (range_index_init(ri, memory_context)) { - // FIXME error - goto error_collector; - } - - if (range_collector_collect(&collector, 8, lpm, ri)) { - goto error_collector; - } - - range_collector_free(&collector, 8); - - return 0; - -error_lpm: - -error_collector: - -error: - return -1; -} - -static inline int -merge_net6_range( - struct memory_context *memory_context, - const struct filter_rule **actions, - uint32_t count, - action_get_net6_func get_net6, - const struct range_index *ri_hi, - const struct range_index *ri_lo, - struct value_table *table, - struct value_registry *registry -) { - if (value_table_init( - table, - memory_context, - ri_hi->max_value + 1, - ri_lo->max_value + 1 - )) { - return -1; - } - - struct remap_table remap_table; - if (remap_table_init( - &remap_table, - memory_context, - (ri_hi->max_value + 1) * (ri_lo->max_value + 1) - )) { - goto error_remap_table; - } - - uint32_t net_cnt = 0; - - struct radix rdx; - radix_init(&rdx, memory_context); - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - remap_table_new_gen(&remap_table); - - uint32_t *values_hi = ADDR_OF(&ri_hi->values); - uint32_t *values_lo = ADDR_OF(&ri_lo->values); - - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); - - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); - - if (radix_lookup(&rdx, 32, net6.addr) != - RADIX_VALUE_INVALID) - continue; - - radix_insert(&rdx, 32, net6.addr, net_cnt++); - - uint8_t *from_hi; - uint8_t *mask_hi; - net6_get_hi_part(&net6, &from_hi, &mask_hi); - uint8_t to_hi[8]; - *(uint64_t *)to_hi = - *(uint64_t *)from_hi | ~*(uint64_t *)mask_hi; - filter_key_inc(8, to_hi); - uint32_t start_hi = - radix_lookup(&ri_hi->radix, 8, from_hi); - uint32_t stop_hi = ri_hi->count; - if (*(uint64_t *)to_hi != 0) - stop_hi = radix_lookup(&ri_hi->radix, 8, to_hi); - - uint8_t *from_lo; - uint8_t *mask_lo; - net6_get_lo_part(&net6, &from_lo, &mask_lo); - uint8_t to_lo[8]; - *(uint64_t *)to_lo = - *(uint64_t *)from_lo | ~*(uint64_t *)mask_lo; - filter_key_inc(8, to_lo); - uint32_t start_lo = - radix_lookup(&ri_lo->radix, 8, from_lo); - uint32_t stop_lo = ri_lo->count; - if (*(uint64_t *)to_lo != 0) - stop_lo = radix_lookup(&ri_lo->radix, 8, to_lo); - - if (!(*(uint64_t *)from_hi == 0 && - *(uint64_t *)to_hi == 0 && - *(uint64_t *)from_lo == 0 && - *(uint64_t *)to_lo == 0)) { - - for (uint32_t idx_hi = start_hi; - idx_hi < stop_hi; - ++idx_hi) { - for (uint32_t idx_lo = start_lo; - idx_lo < stop_lo; - ++idx_lo) { - uint32_t *value = - value_table_get_ptr( - table, - values_hi - [idx_hi], - values_lo - [idx_lo] - ); - if (remap_table_touch( - &remap_table, - *value, - value - ) < 0) { - goto error_touch; - } - } - } - } - } - } - remap_table_free(&remap_table); - - uint32_t *values_hi = ADDR_OF(&ri_hi->values); - uint32_t *values_lo = ADDR_OF(&ri_lo->values); - - struct value_registry net_registry; - value_registry_init(&net_registry, memory_context); - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); - - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); - - uint32_t net_idx = radix_lookup(&rdx, 32, net6.addr); - if (net_idx < net_registry.range_count) - continue; - - value_registry_start(&net_registry); - - uint8_t *from_hi; - uint8_t *mask_hi; - net6_get_hi_part(&net6, &from_hi, &mask_hi); - uint8_t to_hi[8]; - *(uint64_t *)to_hi = - *(uint64_t *)from_hi | ~*(uint64_t *)mask_hi; - filter_key_inc(8, to_hi); - uint32_t start_hi = - radix_lookup(&ri_hi->radix, 8, from_hi); - uint32_t stop_hi = ri_hi->count; - if (*(uint64_t *)to_hi != 0) - stop_hi = radix_lookup(&ri_hi->radix, 8, to_hi); - - uint8_t *from_lo; - uint8_t *mask_lo; - net6_get_lo_part(&net6, &from_lo, &mask_lo); - uint8_t to_lo[8]; - *(uint64_t *)to_lo = - *(uint64_t *)from_lo | ~*(uint64_t *)mask_lo; - filter_key_inc(8, to_lo); - uint32_t start_lo = - radix_lookup(&ri_lo->radix, 8, from_lo); - uint32_t stop_lo = ri_lo->count; - if (*(uint64_t *)to_lo != 0) - stop_lo = radix_lookup(&ri_lo->radix, 8, to_lo); - - for (uint32_t idx_hi = start_hi; idx_hi < stop_hi; - ++idx_hi) { - for (uint32_t idx_lo = start_lo; - idx_lo < stop_lo; - ++idx_lo) { - if (value_registry_collect( - &net_registry, - value_table_get( - table, - values_hi[idx_hi], - values_lo[idx_lo] - ) - )) { - return -1; - } - } - } - } - } - - value_registry_init(registry, memory_context); - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - // A value range should be created even for empty rules - if (value_registry_start(registry)) - return -1; - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); - - uint32_t net_idx = radix_lookup(&rdx, 32, net6.addr); - - struct value_range *rng = - ADDR_OF(&net_registry.ranges) + net_idx; - uint32_t *vls = ADDR_OF(&rng->values); - for (uint32_t idx = 0; idx < rng->count; ++idx) { - if (value_registry_collect( - registry, vls[idx] - )) { - return -1; - } - } - } - } - - radix_free(&rdx); - value_registry_free(&net_registry); - - // FIXME: free temporary resources - - return 0; - -error_touch: - remap_table_free(&remap_table); - -error_remap_table: - value_table_free(table); - - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// Initialization -//////////////////////////////////////////////////////////////////////////////// - -static inline int -init_net6( - struct value_registry *registry, - action_get_net6_func get_net6, - void **data, - const struct filter_rule **actions, - size_t count, - struct memory_context *memory_context -) { - struct net6_classifier *net6 = - memory_balloc(memory_context, sizeof(struct net6_classifier)); - if (net6 == NULL) - return -1; - SET_OFFSET_OF(data, net6); - - struct range_index ri_hi; - if (collect_net6_range( - memory_context, - actions, - count, - get_net6, - net6_get_hi_part, - &net6->hi, - &ri_hi - )) { - goto error_hi; - } - - struct range_index ri_lo; - if (collect_net6_range( - memory_context, - actions, - count, - get_net6, - net6_get_lo_part, - &net6->lo, - &ri_lo - )) { - goto error_lo; - } - - if (merge_net6_range( - memory_context, - actions, - count, - get_net6, - &ri_hi, - &ri_lo, - &net6->comb, - registry - )) { - goto error_merge; - } - - range_index_free(&ri_hi); - range_index_free(&ri_lo); - - return 0; - -error_merge: - range_index_free(&ri_lo); - lpm_free(&net6->lo); - -error_lo: - range_index_free(&ri_hi); - lpm_free(&net6->hi); - -error_hi: - memory_bfree(memory_context, net6, sizeof(struct net6_classifier)); - - return -1; -} - // Allows to initialize attribute for IPv6 destination address. int FILTER_ATTR_COMPILER_INIT_FUNC(net6_src)( struct value_registry *registry, void **data, const struct filter_rule **rules, - size_t actions_count, + size_t rule_count, struct memory_context *memory_context ) { - return init_net6( + return filter_compile_attr_build( + &filter_compile_attr_net6_src.attr_handlers, registry, - action_get_net6_src, data, rules, - actions_count, + rule_count, memory_context + ); } @@ -477,16 +28,17 @@ FILTER_ATTR_COMPILER_INIT_FUNC(net6_dst)( struct value_registry *registry, void **data, const struct filter_rule **rules, - size_t actions_count, + size_t rule_count, struct memory_context *memory_context ) { - return init_net6( + return filter_compile_attr_build( + &filter_compile_attr_net6_dst.attr_handlers, registry, - action_get_net6_dst, data, rules, - actions_count, + rule_count, memory_context + ); } @@ -499,13 +51,14 @@ static inline void free_net6(void *data, struct memory_context *memory_context) { if (data == NULL) return; - struct net6_classifier *c = (struct net6_classifier *)data; + struct filter_query_attr_net6 *c = + (struct filter_query_attr_net6 *)data; if (c == NULL) return; lpm_free(&c->lo); lpm_free(&c->hi); value_table_free(&c->comb); - memory_bfree(memory_context, c, sizeof(struct net6_classifier)); + memory_bfree(memory_context, c, sizeof(struct filter_query_attr_net6)); } void diff --git a/filter/compiler/net6.h b/filter/compiler/net6.h new file mode 100644 index 000000000..0a4d2d787 --- /dev/null +++ b/filter/compiler/net6.h @@ -0,0 +1,418 @@ +#include "../rule.h" + +#include "common/lpm.h" +#include "common/range_collector.h" +#include "common/registry.h" + +#include "filter/classifiers/net6.h" + +#include "declare.h" + +typedef void (*filter_rule_get_net6s_func)( + const struct filter_rule *filter_rule, struct filter_net6s *net6s +); + +struct filter_compile_net6s_attr { + struct filter_compile_attr attr; + struct filter_query_attr_net6 *query_attr; + + struct range_index ri_hi; + struct range_index ri_lo; +}; + +struct filter_compile_attr_net6s_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_net6s_func get_net6s; +}; + +typedef void (*net6_get_part_func)( + struct net6 *net, uint8_t **addr, uint8_t **mask +); + +static inline void +net6_get_hi_part(struct net6 *net, uint8_t **addr, uint8_t **mask) { + *addr = net->addr; + *mask = net->mask; +} + +static inline void +net6_get_lo_part(struct net6 *net, uint8_t **addr, uint8_t **mask) { + *addr = net->addr + 8; + *mask = net->mask + 8; +} + +static inline void +net6_normalize(const struct net6 *src, struct net6 *dst) { + memcpy(dst->addr, src->addr, 16); + memcpy(dst->mask, src->mask, 16); + for (uint8_t idx = 0; idx < 16; ++idx) + dst->addr[idx] &= src->mask[idx]; +} + +static inline int +create_net6_range( + struct memory_context *memory_context, + const struct filter_rule **rules, + uint32_t rule_count, + filter_rule_get_net6s_func get_net6, + net6_get_part_func get_part, + struct lpm *lpm, + struct range_index *ri +) { + struct range_collector collector; + if (range_collector_init(&collector, memory_context)) + goto error; + + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; + + if (rule == NULL) + continue; + + struct filter_net6s net6s; + get_net6(rule, &net6s); + const struct filter_net6s *nets = &net6s; + + for (struct net6 *rule_net = nets->items; + rule_net < nets->items + nets->count; + ++rule_net) { + + struct net6 net6; + net6_normalize(rule_net, &net6); + + uint8_t *addr; + uint8_t *mask; + get_part(&net6, &addr, &mask); + + if (range8_collector_add( + &collector, + addr, + __builtin_popcountll(*(uint64_t *)mask) + )) + goto error_collector; + } + } + if (lpm_init(lpm, memory_context)) { + goto error_lpm; + } + + if (range_index_init(ri, memory_context)) { + // FIXME error + goto error_collector; + } + + if (range_collector_collect(&collector, 8, lpm, ri)) { + goto error_collector; + } + + range_collector_free(&collector, 8); + + return 0; + +error_lpm: + +error_collector: + +error: + return -1; +} + +static inline struct filter_compile_attr * +filter_compile_attr_net6s_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + struct filter_compile_attr_net6s_handlers *net6s_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_net6s_handlers, + attr_handlers + ); + + struct filter_compile_net6s_attr *attr = memory_balloc( + memory_context, sizeof(struct filter_compile_net6s_attr) + ); + if (attr == NULL) { + return NULL; + } + + attr->query_attr = (struct filter_query_attr_net6 *)memory_balloc( + memory_context, sizeof(struct filter_query_attr_net6) + ); + if (attr->query_attr == NULL) + goto error_query; + + create_net6_range( + memory_context, + rules, + rule_count, + net6s_handlers->get_net6s, + net6_get_hi_part, + &attr->query_attr->hi, + &attr->ri_hi + ); + + create_net6_range( + memory_context, + rules, + rule_count, + net6s_handlers->get_net6s, + net6_get_lo_part, + &attr->query_attr->lo, + &attr->ri_lo + ); + + value_table_init( + &attr->query_attr->comb, + memory_context, + attr->ri_hi.max_value + 1, + attr->ri_lo.max_value + 1 + ); + + return &attr->attr; + +error_query: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net6s_attr) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_net6s_size(const struct filter_compile_attr *attr) { + struct filter_compile_net6s_attr *net6s_attr = + container_of(attr, struct filter_compile_net6s_attr, attr); + + return net6s_attr->query_attr->comb.h_dim * + net6s_attr->query_attr->comb.v_dim; +} + +static inline int +filter_compile_attr_net6s_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_net6s_attr *net6s_attr = + container_of(attr, struct filter_compile_net6s_attr, attr); + + struct value_table *value_table = &net6s_attr->query_attr->comb; + for (uint32_t v_idx = 0; v_idx < value_table->v_dim; ++v_idx) { + for (uint32_t h_idx = 0; h_idx < value_table->h_dim; ++h_idx) { + if (iter_cb_func( + value_table_get_ptr( + value_table, v_idx, h_idx + ), + cb_func_data + )) { + return -1; + } + } + } + + return 0; +} + +static inline int +filter_compile_attr_net6s_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + + struct filter_compile_attr_net6s_handlers *net6s_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_net6s_handlers, + attr_handlers + ); + + (void)attr; + + struct filter_net6s nets; + net6s_handlers->get_net6s(rule, &nets); + + if (nets.count == 0) + return 1; + + struct net6 net6_normalized; + net6_normalize(nets.items + 0, &net6_normalized); + + return *(uint64_t *)(net6_normalized.mask + 0) == 0 && + *(uint64_t *)(net6_normalized.mask + 8) == 0; +} + +static inline int +filter_compile_attr_net6s_rule_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_net6s_handlers *net6s_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_net6s_handlers, + attr_handlers + ); + + struct filter_compile_net6s_attr *net6s_attr = + container_of(attr, struct filter_compile_net6s_attr, attr); + + struct filter_net6s nets; + net6s_handlers->get_net6s(rule, &nets); + const struct filter_net6s *net6s = &nets; + + uint32_t *values_hi = ADDR_OF(&net6s_attr->ri_hi.values); + uint32_t *values_lo = ADDR_OF(&net6s_attr->ri_lo.values); + + for (uint32_t net_idx = 0; net_idx < net6s->count; ++net_idx) { + const struct net6 *net = net6s->items + net_idx; + + struct net6 net6_normalized; + net6_normalize(net, &net6_normalized); + struct net6 *net6 = &net6_normalized; + + uint8_t from_hi[8]; + uint8_t to_hi[8]; + for (uint32_t idx = 0; idx < 8; ++idx) { + from_hi[idx] = net6->addr[idx]; + to_hi[idx] = net6->addr[idx] | ~net6->mask[idx]; + } + filter_key_inc(8, to_hi); + uint32_t start_hi = + radix_lookup(&net6s_attr->ri_hi.radix, 8, from_hi); + uint32_t stop_hi = + radix_lookup(&net6s_attr->ri_hi.radix, 8, to_hi); + if (stop_hi == 0) { + /* + * The only chance get zero here is for the last one + * item. + */ + stop_hi = net6s_attr->ri_hi.count; + } + + uint8_t from_lo[8]; + uint8_t to_lo[8]; + for (uint32_t idx = 0; idx < 8; ++idx) { + from_lo[idx] = net6->addr[idx + 8]; + to_lo[idx] = net6->addr[idx + 8] | ~net6->mask[idx + 8]; + } + filter_key_inc(8, to_lo); + uint32_t start_lo = + radix_lookup(&net6s_attr->ri_lo.radix, 8, from_lo); + uint32_t stop_lo = + radix_lookup(&net6s_attr->ri_lo.radix, 8, to_lo); + if (stop_lo == 0) { + /* + * The only chance get zero here is for the last one + * item. + */ + stop_lo = net6s_attr->ri_lo.count; + } + + for (uint32_t idx_hi = start_hi; idx_hi < stop_hi; ++idx_hi) { + for (uint32_t idx_lo = start_lo; idx_lo < stop_lo; + ++idx_lo) { + if (iter_cb_func( + value_table_get_ptr( + &net6s_attr->query_attr + ->comb, + values_hi[idx_hi], + values_lo[idx_lo] + ), + cb_func_data + )) { + return -1; + } + } + } + } + + return 0; +} + +static inline void +filter_compile_attr_net6s_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_net6s_attr *net6s_attr = + container_of(attr, struct filter_compile_net6s_attr, attr); + + range_index_free(&net6s_attr->ri_hi); + range_index_free(&net6s_attr->ri_lo); + + if (net6s_attr->query_attr != NULL) { + lpm_free(&net6s_attr->query_attr->hi); + lpm_free(&net6s_attr->query_attr->lo); + value_table_free(&net6s_attr->query_attr->comb); + + memory_bfree( + memory_context, + net6s_attr->query_attr, + sizeof(struct filter_query_attr_net6) + ); + } + + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net6s_attr) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_net6s_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + (void)memory_context; + struct filter_compile_net6s_attr *net6s_attr = + container_of(attr, struct filter_compile_net6s_attr, attr); + + struct filter_query_attr_net6 *query_attr = net6s_attr->query_attr; + net6s_attr->query_attr = NULL; + + filter_compile_attr_net6s_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers filter_compile_get_net6s = { + .create = filter_compile_attr_net6s_create, + .size = filter_compile_attr_net6s_size, + .iter = filter_compile_attr_net6s_iter, + .rule_iter = filter_compile_attr_net6s_rule_iter, + .rule_is_any = filter_compile_attr_net6s_rule_is_any, + .commit = filter_compile_attr_net6s_commit, + .free_compile = filter_compile_attr_net6s_free, + .free_query = filter_query_attr_net6_free, +}; + +static inline void +get_net6s_src(const struct filter_rule *rule, struct filter_net6s *net6s) { + net6s->count = rule->net6.src_count; + net6s->items = rule->net6.srcs; +} + +static inline void +get_net6s_dst(const struct filter_rule *rule, struct filter_net6s *net6s) { + net6s->count = rule->net6.dst_count; + net6s->items = rule->net6.dsts; +} + +static const struct filter_compile_attr_net6s_handlers + filter_compile_attr_net6_src = { + .attr_handlers = filter_compile_get_net6s, + .get_net6s = get_net6s_src, +}; + +static const struct filter_compile_attr_net6s_handlers + filter_compile_attr_net6_dst = { + .attr_handlers = filter_compile_get_net6s, + .get_net6s = get_net6s_dst, +}; diff --git a/filter/compiler/port.c b/filter/compiler/port.c index 55410af01..ea0f0bd66 100644 --- a/filter/compiler/port.c +++ b/filter/compiler/port.c @@ -1,162 +1,23 @@ -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" -#include "declare.h" -#include "filter/rule.h" - -#include - -typedef void (*action_get_port_range_func)( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count -); - -static int -collect_port_values( - struct memory_context *memory_context, - const struct filter_rule **actions, - uint32_t count, - action_get_port_range_func get_port_range, - struct value_table *table, - struct value_registry *registry -) { - if (value_table_init(table, memory_context, 1, 65536)) - return -1; - - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, 65536)) { - goto error_remap_table; - } - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - - remap_table_new_gen(&remap_table); - - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct filter_port_range *port_ranges; - uint32_t port_range_count; - get_port_range(action, &port_ranges, &port_range_count); - for (struct filter_port_range *ports = port_ranges; - ports < port_ranges + port_range_count; - ++ports) { - if (ports->to - ports->from == 65535) - continue; - for (uint32_t port = ports->from; port <= ports->to; - ++port) { - uint32_t *value = - value_table_get_ptr(table, 0, port); - if (remap_table_touch( - &remap_table, *value, value - ) < 0) { - goto error_touch; - } - } - } - } - - remap_table_compact(&remap_table); - value_table_compact(table, &remap_table); - remap_table_free(&remap_table); - - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { - // A value range should be created even for empty rules - value_registry_start(registry); - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; - - struct filter_port_range *port_ranges; - uint32_t port_range_count; - get_port_range(action, &port_ranges, &port_range_count); - for (struct filter_port_range *ports = port_ranges; - ports < port_ranges + port_range_count; - ++ports) { - for (uint32_t port = ports->from; port <= ports->to; - ++port) { - if (value_registry_collect( - registry, - value_table_get(table, 0, port) - )) { - goto error_collect; - } - } - } - - // Handle default - the full range - if (!port_range_count) { - for (uint32_t port = 0; port <= 65535; ++port) { - if (value_registry_collect( - registry, - value_table_get(table, 0, port) - )) { - goto error_collect; - } - } - } - } +#include "port.h" - return 0; - -error_touch: - remap_table_free(&remap_table); - -error_collect: -error_remap_table: - value_table_free(table); - return -1; -} - -static void -get_port_range_src( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count -) { - *ranges = action->transport.srcs; - *count = action->transport.src_count; -} - -static void -get_port_range_dst( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count -) { - *ranges = action->transport.dsts; - *count = action->transport.dst_count; -} - -//////////////////////////////////////////////////////////////////////////////// +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(port_dst)( struct value_registry *registry, void **data, - const struct filter_rule **actions, - size_t actions_count, + const struct filter_rule **rules, + size_t rule_count, struct memory_context *memory_context ) { - struct value_table *table = - memory_balloc(memory_context, sizeof(struct value_table)); - if (table == NULL) { - return -1; - } - SET_OFFSET_OF(data, table); - return collect_port_values( - memory_context, - actions, - actions_count, - get_port_range_dst, - table, - registry + return filter_compile_attr_build( + &filter_compile_attr_port_ranges_dst.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context + ); } @@ -164,51 +25,41 @@ int FILTER_ATTR_COMPILER_INIT_FUNC(port_src)( struct value_registry *registry, void **data, - const struct filter_rule **actions, - size_t actions_count, + const struct filter_rule **rules, + size_t rule_count, struct memory_context *memory_context ) { - struct value_table *table = - memory_balloc(memory_context, sizeof(struct value_table)); - if (table == NULL) { - return -1; - } - SET_OFFSET_OF(data, table); - if (collect_port_values( - memory_context, - actions, - actions_count, - get_port_range_src, - table, - registry - )) { - SET_OFFSET_OF(data, NULL); - return -1; - } + return filter_compile_attr_build( + &filter_compile_attr_port_ranges_src.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context - return 0; + ); } void FILTER_ATTR_COMPILER_FREE_FUNC(port_src)( void *data, struct memory_context *memory_context ) { - struct value_table *table = (struct value_table *)data; - if (table == NULL) + struct filter_query_attr_port *attr = + (struct filter_query_attr_port *)data; + if (attr == NULL) return; - value_table_free(table); - memory_bfree(memory_context, table, sizeof(struct value_table)); + filter_query_attr_port_free(memory_context, &attr->attr); } void FILTER_ATTR_COMPILER_FREE_FUNC(port_dst)( void *data, struct memory_context *memory_context ) { - struct value_table *table = (struct value_table *)data; - if (table == NULL) + struct filter_query_attr_port *attr = + (struct filter_query_attr_port *)data; + if (attr == NULL) return; - value_table_free(table); - memory_bfree(memory_context, table, sizeof(struct value_table)); + filter_query_attr_port_free(memory_context, &attr->attr); } diff --git a/filter/compiler/port.h b/filter/compiler/port.h new file mode 100644 index 000000000..9d60e12a4 --- /dev/null +++ b/filter/compiler/port.h @@ -0,0 +1,251 @@ +#pragma once + +#include "common/memory.h" +#include "common/registry.h" +#include "common/value.h" +#include "declare.h" +#include "filter/classifiers/port.h" +#include "filter/rule.h" + +#include + +typedef void (*filter_rule_get_port_ranges_func)( + const struct filter_rule *filter_rule, + struct filter_port_ranges *port_ranges +); + +struct filter_compile_attr_port { + struct filter_compile_attr attr; + struct filter_query_attr_port *query_attr; +}; + +struct filter_compile_attr_port_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_port_ranges_func get_port_ranges; +}; + +static inline struct filter_compile_attr * +filter_compile_attr_port_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + (void)handlers; + (void)rules; + (void)rule_count; + + struct filter_compile_attr_port *attr = + (struct filter_compile_attr_port *)memory_balloc( + memory_context, sizeof(struct filter_compile_attr_port) + ); + if (attr == NULL) { + return NULL; + } + + attr->query_attr = (struct filter_query_attr_port *)memory_balloc( + memory_context, sizeof(struct filter_query_attr_port) + ); + if (attr->query_attr == NULL) + goto error_free; + + if (value_table_init( + &attr->query_attr->value_table, memory_context, 1, 65536 + )) { + goto error_free_attr; + } + + return &attr->attr; + +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_port) + ); + +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_attr_port) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_port_size(const struct filter_compile_attr *attr) { + (void)attr; + return 65536; +} + +static inline int +filter_compile_attr_port_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_attr_port *port_ranges_attr = + container_of(attr, struct filter_compile_attr_port, attr); + + struct filter_query_attr_port *query_attr = + port_ranges_attr->query_attr; + + for (uint32_t idx = 0; idx < 65536; ++idx) + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, idx + ), + cb_func_data + )) + return -1; + return 0; +} + +static inline int +filter_compile_attr_port_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + struct filter_compile_attr_port_handlers *port_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_port_handlers, + attr_handlers + ); + (void)attr; + + struct filter_port_ranges ranges; + port_ranges_handlers->get_port_ranges(rule, &ranges); + + return ranges.count == 0 || + ranges.items[0].to - ranges.items[0].from == 65535; +} + +static inline int +filter_compile_attr_port_rule_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_port_handlers *port_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_port_handlers, + attr_handlers + ); + + struct filter_compile_attr_port *port_ranges_attr = + container_of(attr, struct filter_compile_attr_port, attr); + + struct filter_query_attr_port *query_attr = + port_ranges_attr->query_attr; + + struct filter_port_ranges ranges; + port_ranges_handlers->get_port_ranges(rule, &ranges); + const struct filter_port_ranges *port_ranges = &ranges; + + for (uint32_t range_idx = 0; range_idx < port_ranges->count; + ++range_idx) { + const struct filter_port_range *port_range = + port_ranges->items + range_idx; + for (uint32_t port = port_range->from; port <= port_range->to; + ++port) { + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, port + ), + cb_func_data + )) { + return -1; + } + } + } + + return 0; +} + +static inline void +filter_compile_attr_port_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_port *port_ranges_attr = + container_of(attr, struct filter_compile_attr_port, attr); + + if (port_ranges_attr->query_attr != NULL) { + value_table_free(&port_ranges_attr->query_attr->value_table); + + memory_bfree( + memory_context, + port_ranges_attr->query_attr, + sizeof(struct filter_query_attr_port) + ); + } + + memory_bfree( + memory_context, + port_ranges_attr, + sizeof(struct filter_compile_attr_port) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_port_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_port *port_ranges_attr = + container_of(attr, struct filter_compile_attr_port, attr); + + struct filter_query_attr_port *query_attr = + port_ranges_attr->query_attr; + port_ranges_attr->query_attr = NULL; + + filter_compile_attr_port_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers + filter_compile_attr_port_handlers = { + .create = filter_compile_attr_port_create, + .size = filter_compile_attr_port_size, + .iter = filter_compile_attr_port_iter, + .rule_is_any = filter_compile_attr_port_rule_is_any, + .rule_iter = filter_compile_attr_port_rule_iter, + .commit = filter_compile_attr_port_commit, + .free_compile = filter_compile_attr_port_free, + .free_query = filter_query_attr_port_free, +}; + +static inline void +filter_rule_get_port_ranges_src( + const struct filter_rule *rule, struct filter_port_ranges *port_ranges +) { + port_ranges->count = rule->transport.src_count; + port_ranges->items = rule->transport.srcs; +} + +static inline void +filter_rule_get_port_ranges_dst( + const struct filter_rule *rule, struct filter_port_ranges *port_ranges +) { + port_ranges->count = rule->transport.dst_count; + port_ranges->items = rule->transport.dsts; +} + +static const struct filter_compile_attr_port_handlers + filter_compile_attr_port_src = { + .attr_handlers = filter_compile_attr_port_handlers, + .get_port_ranges = filter_rule_get_port_ranges_src, +}; + +static const struct filter_compile_attr_port_handlers + filter_compile_attr_port_dst = { + .attr_handlers = filter_compile_attr_port_handlers, + .get_port_ranges = filter_rule_get_port_ranges_dst, +}; diff --git a/filter/compiler/proto_range.c b/filter/compiler/proto_range.c index 1f6734f98..84321ab1b 100644 --- a/filter/compiler/proto_range.c +++ b/filter/compiler/proto_range.c @@ -1,115 +1,6 @@ -#include "filter/classifiers/proto_range.h" -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" -#include "declare.h" -#include "filter/rule.h" - -#include - -//////////////////////////////////////////////////////////////////////////////// - -#define PROTO_RANGE_CLASSIFIER_MAX_VALUE ((1 << 16)) - -static int -collect_proto_values( - struct memory_context *memory_context, - const struct filter_rule **rules, - uint32_t count, - struct value_table *table, - struct value_registry *registry -) { - if (value_table_init( - table, memory_context, 1, PROTO_RANGE_CLASSIFIER_MAX_VALUE - )) - return -1; - - struct remap_table remap_table; - if (remap_table_init( - &remap_table, - memory_context, - PROTO_RANGE_CLASSIFIER_MAX_VALUE - )) { - goto error_remap_table; - } - - for (const struct filter_rule **rule_ptr = rules; - rule_ptr < rules + count; - ++rule_ptr) { - if (*rule_ptr == NULL) - continue; - const struct filter_rule *rule = *rule_ptr; - - remap_table_new_gen(&remap_table); - - struct filter_proto_range *proto_ranges = - rule->transport.protos; - size_t proto_count = rule->transport.proto_count; - - for (struct filter_proto_range *proto_range = proto_ranges; - proto_range < proto_ranges + proto_count; - ++proto_range) { - for (uint32_t proto = proto_range->from; - proto <= proto_range->to; - ++proto) { - uint32_t *value = - value_table_get_ptr(table, 0, proto); - if (remap_table_touch( - &remap_table, *value, value - ) < 0) { - goto error_touch; - } - } - } - } - - remap_table_compact(&remap_table); - value_table_compact(table, &remap_table); - remap_table_free(&remap_table); - - for (const struct filter_rule **rule_ptr = rules; - rule_ptr < rules + count; - ++rule_ptr) { - // A value range should be created even for empty rules - value_registry_start(registry); - if (*rule_ptr == NULL) - continue; +#include "proto_range.h" - const struct filter_rule *rule = *rule_ptr; - - struct filter_proto_range *proto_ranges = - rule->transport.protos; - size_t proto_count = rule->transport.proto_count; - - for (struct filter_proto_range *proto_range = proto_ranges; - proto_range < proto_ranges + proto_count; - ++proto_range) { - for (uint32_t proto = proto_range->from; - proto <= proto_range->to; - ++proto) { - if (value_registry_collect( - registry, - value_table_get(table, 0, proto) - )) { - goto error_collect; - } - } - } - } - - return 0; - -error_touch: - remap_table_free(&remap_table); - -error_collect: -error_remap_table: - - value_table_free(table); - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(proto_range)( @@ -117,36 +8,27 @@ FILTER_ATTR_COMPILER_INIT_FUNC(proto_range)( void **data, const struct filter_rule **rules, size_t rule_count, - struct memory_context *mctx + struct memory_context *memory_context ) { - struct proto_range_classifier *classifier = - memory_balloc(mctx, sizeof(struct proto_range_classifier)); - if (classifier == NULL) { - return -1; - } - SET_OFFSET_OF(data, classifier); - if (collect_proto_values( - mctx, rules, rule_count, &classifier->table, registry - )) { - SET_OFFSET_OF(data, NULL); - return -1; - } - - return 0; + return filter_compile_attr_build( + &filter_compile_attr_proto_ranges.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context + + ); } void FILTER_ATTR_COMPILER_FREE_FUNC(proto_range)( void *data, struct memory_context *memory_context ) { - if (data == NULL) + struct filter_query_attr_proto_range *attr = + (struct filter_query_attr_proto_range *)data; + if (attr == NULL) return; - struct proto_range_classifier *c = - (struct proto_range_classifier *)data; - value_table_free(&c->table); - memory_bfree(memory_context, c, sizeof(*c)); -} - -//////////////////////////////////////////////////////////////////////////////// -#undef PROTO_RANGE_CLASSIFIER_MAX_VALUE + filter_query_attr_proto_range_free(memory_context, &attr->attr); +} diff --git a/filter/compiler/proto_range.h b/filter/compiler/proto_range.h new file mode 100644 index 000000000..70661e5db --- /dev/null +++ b/filter/compiler/proto_range.h @@ -0,0 +1,238 @@ +#include "common/memory.h" +#include "common/registry.h" +#include "common/value.h" +#include "declare.h" +#include "filter/classifiers/proto_range.h" +#include "filter/rule.h" + +#include + +typedef void (*filter_rule_get_proto_ranges_func)( + const struct filter_rule *filter_rule, + struct filter_proto_ranges *proto_ranges +); + +struct filter_compile_attr_proto { + struct filter_compile_attr attr; + struct filter_query_attr_proto_range *query_attr; +}; + +struct filter_compile_attr_proto_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_proto_ranges_func get_proto_ranges; +}; + +static inline struct filter_compile_attr * +filter_compile_attr_proto_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + (void)handlers; + (void)rules; + (void)rule_count; + + struct filter_compile_attr_proto *attr = + (struct filter_compile_attr_proto *)memory_balloc( + memory_context, sizeof(struct filter_compile_attr_proto) + ); + if (attr == NULL) { + return NULL; + } + + attr->query_attr = + (struct filter_query_attr_proto_range *)memory_balloc( + memory_context, + sizeof(struct filter_query_attr_proto_range) + ); + if (attr->query_attr == NULL) + goto error_free; + + if (value_table_init( + &attr->query_attr->value_table, memory_context, 1, 65536 + )) { + goto error_free_attr; + } + + return &attr->attr; + +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_proto_range) + ); + +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_attr_proto) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_proto_size(const struct filter_compile_attr *attr) { + (void)attr; + return 65536; +} + +static inline int +filter_compile_attr_proto_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_attr_proto *proto_ranges_attr = + container_of(attr, struct filter_compile_attr_proto, attr); + + struct filter_query_attr_proto_range *query_attr = + proto_ranges_attr->query_attr; + + for (uint32_t idx = 0; idx < 65536; ++idx) + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, idx + ), + cb_func_data + )) + return -1; + return 0; +} + +static inline int +filter_compile_attr_proto_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + struct filter_compile_attr_proto_handlers *proto_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_proto_handlers, + attr_handlers + ); + (void)attr; + + struct filter_proto_ranges ranges; + proto_ranges_handlers->get_proto_ranges(rule, &ranges); + + return ranges.count == 0 || + ranges.items[0].to - ranges.items[0].from == 65535; +} + +static inline int +filter_compile_attr_proto_rule_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_proto_handlers *proto_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_proto_handlers, + attr_handlers + ); + + struct filter_compile_attr_proto *proto_ranges_attr = + container_of(attr, struct filter_compile_attr_proto, attr); + + struct filter_query_attr_proto_range *query_attr = + proto_ranges_attr->query_attr; + + struct filter_proto_ranges ranges; + proto_ranges_handlers->get_proto_ranges(rule, &ranges); + const struct filter_proto_ranges *proto_ranges = &ranges; + + for (uint32_t range_idx = 0; range_idx < proto_ranges->count; + ++range_idx) { + const struct filter_proto_range *proto_range = + proto_ranges->items + range_idx; + for (uint32_t proto = proto_range->from; + proto <= proto_range->to; + ++proto) { + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, proto + ), + cb_func_data + )) { + return -1; + } + } + } + + return 0; +} + +static inline void +filter_compile_attr_proto_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_proto *proto_ranges_attr = + container_of(attr, struct filter_compile_attr_proto, attr); + + if (proto_ranges_attr->query_attr != NULL) { + value_table_free(&proto_ranges_attr->query_attr->value_table); + + memory_bfree( + memory_context, + proto_ranges_attr->query_attr, + sizeof(struct filter_query_attr_proto_range) + ); + } + + memory_bfree( + memory_context, + proto_ranges_attr, + sizeof(struct filter_compile_attr_proto) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_proto_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_proto *proto_ranges_attr = + container_of(attr, struct filter_compile_attr_proto, attr); + + struct filter_query_attr_proto_range *query_attr = + proto_ranges_attr->query_attr; + proto_ranges_attr->query_attr = NULL; + + filter_compile_attr_proto_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers + filter_compile_attr_proto_handlers = { + .create = filter_compile_attr_proto_create, + .size = filter_compile_attr_proto_size, + .iter = filter_compile_attr_proto_iter, + .rule_is_any = filter_compile_attr_proto_rule_is_any, + .rule_iter = filter_compile_attr_proto_rule_iter, + .commit = filter_compile_attr_proto_commit, + .free_compile = filter_compile_attr_proto_free, + .free_query = filter_query_attr_proto_range_free, +}; + +static inline void +filter_rule_get_proto_ranges( + const struct filter_rule *rule, struct filter_proto_ranges *proto_ranges +) { + proto_ranges->count = rule->transport.proto_count; + proto_ranges->items = rule->transport.protos; +} + +static const struct filter_compile_attr_proto_handlers + filter_compile_attr_proto_range = { + .attr_handlers = filter_compile_attr_proto_handlers, + .get_proto_ranges = filter_rule_get_proto_ranges, +}; diff --git a/filter/compiler/vlan.c b/filter/compiler/vlan.c index 339147899..944902572 100644 --- a/filter/compiler/vlan.c +++ b/filter/compiler/vlan.c @@ -1,10 +1,6 @@ -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" -#include "declare.h" -#include "filter/rule.h" +#include "vlan.h" -#include +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(vlan)( @@ -14,104 +10,25 @@ FILTER_ATTR_COMPILER_INIT_FUNC(vlan)( size_t rule_count, struct memory_context *memory_context ) { - struct value_table *t = - memory_balloc(memory_context, sizeof(struct value_table)); - if (t == NULL) { - return -1; - } - - if (value_table_init(t, memory_context, 1, 4096)) { - goto error_init; - } - SET_OFFSET_OF(data, t); - - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, 4096)) { - goto error_remap_table; - } - - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - if (*r_ptr == NULL) - continue; - const struct filter_rule *r = *r_ptr; - - if (r->vlan_range_count == 0) { - continue; - } - remap_table_new_gen(&remap_table); - for (uint32_t idx = 0; idx < r->vlan_range_count; ++idx) { - for (uint16_t vlan = r->vlan_ranges[idx].from; - vlan <= r->vlan_ranges[idx].to; - ++vlan) { - uint32_t *value = - value_table_get_ptr(t, 0, vlan); - if (remap_table_touch( - &remap_table, *value, value - ) < 0) { - goto error_touch; - } - } - } - } - - remap_table_compact(&remap_table); - value_table_compact(t, &remap_table); - remap_table_free(&remap_table); - - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - // A value range should be created even for empty rules - value_registry_start(registry); - if (*r_ptr == NULL) - continue; - const struct filter_rule *r = *r_ptr; - - if (r->vlan_range_count == 0) { - for (uint16_t vlan = 0; vlan <= 4095; ++vlan) { - value_registry_collect( - registry, value_table_get(t, 0, vlan) - ); - } - } - for (uint32_t idx = 0; idx < r->vlan_range_count; ++idx) { - for (uint16_t vlan = r->vlan_ranges[idx].from; - vlan <= r->vlan_ranges[idx].to; - ++vlan) { - if (value_registry_collect( - registry, - value_table_get(t, 0, vlan) - )) { - goto error_collect; - } - } - } - } - return 0; - -error_touch: - remap_table_free(&remap_table); - -error_collect: -error_remap_table: - value_table_free(t); - SET_OFFSET_OF(data, NULL); - -error_init: - memory_bfree(memory_context, t, sizeof(struct value_table)); - - return -1; + return filter_compile_attr_build( + &filter_compile_attr_vlan_ranges.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context + + ); } void FILTER_ATTR_COMPILER_FREE_FUNC(vlan)( void *data, struct memory_context *memory_context ) { - struct value_table *t = (struct value_table *)data; - if (t == NULL) + struct filter_query_attr_vlan *attr = + (struct filter_query_attr_vlan *)data; + if (attr == NULL) return; - value_table_free(t); - memory_bfree(memory_context, t, sizeof(struct value_table)); + + filter_query_attr_vlan_free(memory_context, &attr->attr); } diff --git a/filter/compiler/vlan.h b/filter/compiler/vlan.h new file mode 100644 index 000000000..af9b0144e --- /dev/null +++ b/filter/compiler/vlan.h @@ -0,0 +1,237 @@ +#pragma once + +#include "common/memory.h" +#include "common/registry.h" +#include "common/value.h" +#include "declare.h" +#include "filter/classifiers/vlan.h" +#include "filter/rule.h" + +#include + +typedef void (*filter_rule_get_vlan_ranges_func)( + const struct filter_rule *filter_rule, + struct filter_vlan_ranges *vlan_ranges +); + +struct filter_compile_attr_vlan { + struct filter_compile_attr attr; + struct filter_query_attr_vlan *query_attr; +}; + +struct filter_compile_attr_vlan_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_vlan_ranges_func get_vlan_ranges; +}; + +static inline struct filter_compile_attr * +filter_compile_attr_vlan_create( + struct memory_context *memory_context, + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule **rules, + uint32_t rule_count +) { + (void)handlers; + (void)rules; + (void)rule_count; + + struct filter_compile_attr_vlan *attr = + (struct filter_compile_attr_vlan *)memory_balloc( + memory_context, sizeof(struct filter_compile_attr_vlan) + ); + if (attr == NULL) { + return NULL; + } + + attr->query_attr = (struct filter_query_attr_vlan *)memory_balloc( + memory_context, sizeof(struct filter_query_attr_vlan) + ); + if (attr->query_attr == NULL) + goto error_free; + + if (value_table_init( + &attr->query_attr->value_table, memory_context, 1, 4096 + )) { + goto error_free_attr; + } + + return &attr->attr; + +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_vlan) + ); + +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_attr_vlan) + ); + + return NULL; +} + +static inline uint32_t +filter_compile_attr_vlan_size(const struct filter_compile_attr *attr) { + (void)attr; + return 4096; +} + +static inline int +filter_compile_attr_vlan_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + (void)attr_handlers; + + struct filter_compile_attr_vlan *vlan_ranges_attr = + container_of(attr, struct filter_compile_attr_vlan, attr); + + struct filter_query_attr_vlan *query_attr = + vlan_ranges_attr->query_attr; + + for (uint32_t idx = 0; idx < 4096; ++idx) + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, idx + ), + cb_func_data + )) + return -1; + return 0; +} + +static inline int +filter_compile_attr_vlan_rule_is_any( + const struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule +) { + struct filter_compile_attr_vlan_handlers *vlan_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_vlan_handlers, + attr_handlers + ); + (void)attr; + + struct filter_vlan_ranges ranges; + vlan_ranges_handlers->get_vlan_ranges(rule, &ranges); + + return ranges.count == 0 || + ranges.items[0].to - ranges.items[0].from == 65535; +} + +static inline int +filter_compile_attr_vlan_rule_iter( + struct filter_compile_attr *attr, + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule *rule, + filter_compile_attr_iter_cb_func iter_cb_func, + void *cb_func_data +) { + struct filter_compile_attr_vlan_handlers *vlan_ranges_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_vlan_handlers, + attr_handlers + ); + + struct filter_compile_attr_vlan *vlan_ranges_attr = + container_of(attr, struct filter_compile_attr_vlan, attr); + + struct filter_query_attr_vlan *query_attr = + vlan_ranges_attr->query_attr; + + struct filter_vlan_ranges ranges; + vlan_ranges_handlers->get_vlan_ranges(rule, &ranges); + const struct filter_vlan_ranges *vlan_ranges = &ranges; + + for (uint32_t range_idx = 0; range_idx < vlan_ranges->count; + ++range_idx) { + const struct filter_vlan_range *vlan_range = + vlan_ranges->items + range_idx; + for (uint32_t vlan = vlan_range->from; vlan <= vlan_range->to; + ++vlan) { + if (iter_cb_func( + value_table_get_ptr( + &query_attr->value_table, 0, vlan + ), + cb_func_data + )) { + return -1; + } + } + } + + return 0; +} + +static inline void +filter_compile_attr_vlan_free( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_vlan *vlan_ranges_attr = + container_of(attr, struct filter_compile_attr_vlan, attr); + + if (vlan_ranges_attr->query_attr != NULL) { + value_table_free(&vlan_ranges_attr->query_attr->value_table); + + memory_bfree( + memory_context, + vlan_ranges_attr->query_attr, + sizeof(struct filter_query_attr_vlan) + ); + } + + memory_bfree( + memory_context, + vlan_ranges_attr, + sizeof(struct filter_compile_attr_vlan) + ); +} + +static inline struct filter_query_attr * +filter_compile_attr_vlan_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr +) { + struct filter_compile_attr_vlan *vlan_ranges_attr = + container_of(attr, struct filter_compile_attr_vlan, attr); + + struct filter_query_attr_vlan *query_attr = + vlan_ranges_attr->query_attr; + vlan_ranges_attr->query_attr = NULL; + + filter_compile_attr_vlan_free(memory_context, attr); + + return &query_attr->attr; +} + +static const struct filter_compile_attr_handlers + filter_compile_attr_vlan_handlers = { + .create = filter_compile_attr_vlan_create, + .size = filter_compile_attr_vlan_size, + .iter = filter_compile_attr_vlan_iter, + .rule_is_any = filter_compile_attr_vlan_rule_is_any, + .rule_iter = filter_compile_attr_vlan_rule_iter, + .commit = filter_compile_attr_vlan_commit, + .free_compile = filter_compile_attr_vlan_free, + .free_query = filter_query_attr_vlan_free, +}; + +static inline void +filter_rule_get_vlan_ranges( + const struct filter_rule *rule, struct filter_vlan_ranges *vlan_ranges +) { + vlan_ranges->count = rule->vlan_range_count; + vlan_ranges->items = rule->vlan_ranges; +} + +static const struct filter_compile_attr_vlan_handlers filter_compile_attr_vlan = + { + .attr_handlers = filter_compile_attr_vlan_handlers, + .get_vlan_ranges = filter_rule_get_vlan_ranges, +}; diff --git a/filter/filter.h b/filter/filter.h index b24fdc55d..2162f5abb 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -34,41 +34,17 @@ #define FILTER_RULE_INVALID (uint32_t)0xffffffff -/** - * @def MAX_ATTRIBUTES - * @brief Upper bound on attribute count in a filter signature. - * Increase with care; affects vertex storage and slot sizing. - */ -#define MAX_ATTRIBUTES 10 - -/** - * @brief A node of the classification tree (leaf or inner). - * - * Leaf: - * - registry: holds per-attribute value ranges - * - data: attribute-specific payload used by query helper - * Inner: - * - table: value_table merged from children - * - registry: merged registry for next level - */ -struct filter_vertex { - struct value_registry registry; - struct value_table table; - void *data; // relative pointer compatible -}; +struct filter_query_attr {}; -/** - * @brief Filter instance built for a fixed attribute signature. - * - * Layout: - * - v: array-based binary tree (1..n-1 inner, n..2n-1 leaves, 0 root when n=1) - * - memory_context: owns all registries/tables backing the filter - * - * Notes: - * - Query is read-only and can be called concurrently. - * - Memory of returned actions belongs to this filter. - */ struct filter { - struct filter_vertex v[2 * MAX_ATTRIBUTES]; + struct filter_query_attr **attrs; + struct value_table *joints; struct memory_context memory_context; }; + +static inline uint64_t +filter_memory_usage(struct filter *filter) { + struct memory_context *mctx = &filter->memory_context; + assert(mctx->balloc_size >= mctx->bfree_size); + return mctx->balloc_size - mctx->bfree_size; +} diff --git a/filter/meson.build b/filter/meson.build index 6840a29d2..531e26273 100644 --- a/filter/meson.build +++ b/filter/meson.build @@ -4,18 +4,6 @@ lib_filter_query_dep = declare_dependency( compiler_sources = files( 'compiler/helper.c', - 'compiler/device.c', - 'compiler/net4.c', - 'compiler/net6.c', - 'compiler/port.c', - 'compiler/proto_range.c', - 'compiler/proto_range_fast.c', - 'compiler/proto.c', - 'compiler/vlan.c', - 'compiler/net6_fast.c', - 'compiler/net4_fast.c', - 'compiler/port_fast.c', - 'compiler/segments.c', ) lib_filter_compiler = static_library( @@ -32,4 +20,4 @@ lib_filter_compiler_dep = declare_dependency( include_directories: include_directories('.'), ) -subdir('tests') \ No newline at end of file +subdir('tests') diff --git a/filter/query.h b/filter/query.h index 219151c43..f67230ab1 100644 --- a/filter/query.h +++ b/filter/query.h @@ -22,64 +22,79 @@ //////////////////////////////////////////////////////////////////////////////// -typedef void (*filter_lookup_query_func)( - void *data, - struct packet **packets, - uint32_t *results, - uint32_t packet_count -); - -struct filter_query { - uint64_t lookup_count; - filter_lookup_query_func *lookups; -}; +static inline void +filter_process_joint( + struct value_table *value_table, + uint32_t *v_values, + uint32_t *h_values, + uint32_t *o_values, + uint32_t count +) { + for (uint32_t idx = 0; idx < count; ++idx) { + o_values[idx] = value_table_get( + value_table, v_values[idx], h_values[idx] + ); + } +} static inline void -filter_query( +filter_lookup( struct filter *filter, - const struct filter_query *filter_query, - struct packet **packets, + const struct filter_query_attr_handlers *attr_handlers[], + uint32_t attr_handler_count, + const struct packet **packets, uint32_t *results, uint32_t packet_count ) { - /* Local slots storage */ - uint32_t __slots[2 * MAX_ATTRIBUTES * packet_count + 1]; - /* compute classifiers for leaf attributes into parent slots + uint32_t joint_count = attr_handler_count - 1; + uint32_t values[packet_count * (attr_handler_count + joint_count)]; + uint32_t values_pos = 0; + + struct filter_query_attr **attrs = ADDR_OF(&filter->attrs); + /* + * Retrieve attribute values for each rule */ - for (size_t __ai = 0; __ai < filter_query->lookup_count; ++__ai) { - size_t __vtx = filter_query->lookup_count + __ai; - const struct filter_vertex *__v = &(filter)->v[__vtx]; - filter_query->lookups[__ai]( - ADDR_OF(&__v->data), + for (uint32_t attr_idx = 0; attr_idx < attr_handler_count; ++attr_idx) { + const struct filter_query_attr *attr = + ADDR_OF(attrs + attr_idx); + attr_handlers[attr_idx]->lookup( + attr, + attr_handlers[attr_idx], packets, - __slots + __vtx * packet_count, + values + values_pos, packet_count ); + + values_pos += packet_count; } - /* compute inner vertices except root, pushing up to parent */ - for (size_t __vtx = filter_query->lookup_count - 1; __vtx >= 2; - --__vtx) { - struct filter_vertex *__v = &(filter)->v[__vtx]; - for (uint32_t idx = 0; idx < packet_count; ++idx) { - uint32_t __c = value_table_get( - &__v->table, - __slots[(__vtx << 1) * packet_count + idx], - __slots[(__vtx << 1 | 1) * packet_count + idx] - ); - __slots[__vtx * packet_count + idx] = __c; - } - } - /* root (1 when n>1, else 0) */ - const size_t __root = filter_query->lookup_count > 1; - struct filter_vertex *__r = &(filter)->v[__root]; - for (uint32_t idx = 0; idx < packet_count; ++idx) { - uint32_t __res = value_table_get( - &__r->table, - __root == 0 - ? 0 - : __slots[(__root << 1) * packet_count + idx], - __slots[(__root << 1 | 1) * packet_count + idx] + + /* + * Combine pair of values to get a next one value. The last of the + * values for each packet is a rule index. + */ + struct value_table *joints = ADDR_OF(&filter->joints); + for (uint32_t joint_idx = 0; joint_idx < joint_count; ++joint_idx) { + filter_process_joint( + joints + joint_idx, + values + joint_idx * 2 * packet_count, + values + (joint_idx * 2 + 1) * packet_count, + values + values_pos, + packet_count ); - (results)[idx] = __res; + values_pos += packet_count; } + + memcpy(results, + values + values_pos - packet_count, + sizeof(uint32_t) * packet_count); } + +#define filter_query(filter, sign, packets, results, count) \ + filter_lookup( \ + filter, \ + sign, \ + sizeof(sign) / sizeof(*sign), \ + (const struct packet **)packets, \ + results, \ + count \ + ) diff --git a/filter/query/attribute.h b/filter/query/attribute.h index f13e71594..4dc46a5ed 100644 --- a/filter/query/attribute.h +++ b/filter/query/attribute.h @@ -3,14 +3,9 @@ #include "declare.h" #include "device.h" #include "net4.h" -#include "net4_fast.h" #include "net6.h" -#include "net6_fast.h" #include "port.h" -#include "port_fast.h" -#include "proto.h" #include "proto_range.h" -#include "proto_range_fast.h" #include "vlan.h" typedef void (*filter_attr_query_func)( @@ -20,31 +15,3 @@ typedef void (*filter_attr_query_func)( struct filter_attr_query { filter_attr_query_func query; }; - -#define REGISTER_ATTRIBUTE(name) \ - static inline void FILTER_ATTR_QUERY_FUNC(name)( \ - void *data, \ - struct packet **packets, \ - uint32_t *result, \ - uint32_t count \ - ); - -REGISTER_ATTRIBUTE(port_src); -REGISTER_ATTRIBUTE(port_dst); -REGISTER_ATTRIBUTE(proto); -REGISTER_ATTRIBUTE(port_fast_src); -REGISTER_ATTRIBUTE(port_fast_dst); -REGISTER_ATTRIBUTE(proto_range); -REGISTER_ATTRIBUTE(proto_range_fast); -REGISTER_ATTRIBUTE(net4_src); -REGISTER_ATTRIBUTE(net4_dst); -REGISTER_ATTRIBUTE(net6_src); -REGISTER_ATTRIBUTE(net6_dst); -REGISTER_ATTRIBUTE(vlan); -REGISTER_ATTRIBUTE(device); -REGISTER_ATTRIBUTE(net4_fast_dst); -REGISTER_ATTRIBUTE(net4_fast_src); -REGISTER_ATTRIBUTE(net6_fast_dst); -REGISTER_ATTRIBUTE(net6_fast_src); - -#undef REGISTER_ATTRIBUTE diff --git a/filter/query/declare.h b/filter/query/declare.h index b1b8df474..84fc328e4 100644 --- a/filter/query/declare.h +++ b/filter/query/declare.h @@ -1,14 +1,30 @@ #pragma once +#include + +#include "filter/filter.h" + #include "common/for_each.h" -#define FILTER_ATTR_QUERY_FUNC(name) name##_attr_query_func +#define FILTER_ATTR_QUERY(name) &filter_query_attr_##name.attr_handlers #define FILTER_QUERY_DECLARE(tag, ...) \ - static const struct filter_query *tag = &(const struct filter_query){ \ - sizeof((filter_lookup_query_func[] \ - ){FOR_EACH(FILTER_ATTR_QUERY_FUNC, __VA_ARGS__)}) / \ - sizeof(filter_lookup_query_func), \ - (filter_lookup_query_func[] \ - ){FOR_EACH(FILTER_ATTR_QUERY_FUNC, __VA_ARGS__)}, \ + static const struct filter_query_attr_handlers *tag[] = { \ + FOR_EACH(FILTER_ATTR_QUERY, __VA_ARGS__), \ }; + +struct packet; + +struct filter_query_attr_handlers; + +typedef void (*filter_query_attr_lookup_func)( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *handlers, + const struct packet **packets, + uint32_t *result, + uint32_t packet_count +); + +struct filter_query_attr_handlers { + filter_query_attr_lookup_func lookup; +}; diff --git a/filter/query/device.h b/filter/query/device.h index 5db12d7ad..ef40f1b74 100644 --- a/filter/query/device.h +++ b/filter/query/device.h @@ -1,18 +1,61 @@ #pragma once +#include "common/container_of.h" #include "common/value.h" + #include "declare.h" +#include "filter/classifiers/device.h" + #include "lib/dataplane/packet/packet.h" #include +typedef uint32_t (*packet_get_device_func)(const struct packet *packet); + +struct filter_query_attr_device_handlers { + struct filter_query_attr_handlers attr_handlers; + packet_get_device_func get_device; +}; + static inline void -FILTER_ATTR_QUERY_FUNC(device)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_device_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct value_table *t = (struct value_table *)data; - for (uint32_t idx = 0; idx < count; ++idx) { - uint64_t device_id = packets[idx]->module_device_id; - result[idx] = value_table_get(t, 0, device_id); + const struct filter_query_attr_device_handlers *device_handlers = + container_of( + attr_handlers, + struct filter_query_attr_device_handlers, + attr_handlers + ); + + const struct filter_query_attr_device *device_attr = + container_of(attr, struct filter_query_attr_device, attr); + + for (uint32_t idx = 0; idx < packet_count; ++idx) { + uint32_t device_id = device_handlers->get_device(packets[idx]); + if (device_id >= device_attr->value_table.h_dim) + device_id = 0; + results[idx] = value_table_get( + &device_attr->value_table, 0, device_id + ); } } + +static inline uint32_t +filter_packet_get_device(const struct packet *packet) { + return packet->module_device_id; +} + +static const struct filter_query_attr_handlers filter_query_device_handlers = { + .lookup = filter_query_attr_device_lookup, +}; + +static const struct filter_query_attr_device_handlers filter_query_attr_device = + { + .attr_handlers = filter_query_device_handlers, + .get_device = filter_packet_get_device, +}; diff --git a/filter/query/net4.h b/filter/query/net4.h index c34972988..e4c5963c0 100644 --- a/filter/query/net4.h +++ b/filter/query/net4.h @@ -1,7 +1,10 @@ #pragma once #include "common/lpm.h" + #include "declare.h" +#include "filter/classifiers/net4.h" + #include "lib/dataplane/packet/data.h" #include "lib/dataplane/packet/packet.h" @@ -10,36 +13,70 @@ #include +typedef const uint8_t *(*packet_get_net4_func)(const struct packet *packet); + +struct filter_query_attr_net4_handlers { + struct filter_query_attr_handlers attr_handlers; + packet_get_net4_func get_net4; +}; + static inline void -FILTER_ATTR_QUERY_FUNC(net4_src)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_net4_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct lpm *lpm = (struct lpm *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); - struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset( - mbuf, - struct rte_ipv4_hdr *, - packets[idx]->network_header.offset + const struct filter_query_attr_net4_handlers *net4_handlers = + container_of( + attr_handlers, + struct filter_query_attr_net4_handlers, + attr_handlers ); - result[idx] = lpm4_lookup(lpm, (uint8_t *)&ipv4_hdr->src_addr); + + const struct filter_query_attr_net4 *attr_net4 = + container_of(attr, struct filter_query_attr_net4, attr); + + for (uint32_t idx = 0; idx < packet_count; ++idx) { + const uint8_t *addr = net4_handlers->get_net4(packets[idx]); + results[idx] = lpm4_lookup(&attr_net4->lpm, addr); } } -static inline void -FILTER_ATTR_QUERY_FUNC(net4_dst)( - void *data, struct packet **packets, uint32_t *result, uint32_t count -) { - struct lpm *lpm = (struct lpm *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); - struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset( - mbuf, - struct rte_ipv4_hdr *, - packets[idx]->network_header.offset - ); - result[idx] = lpm4_lookup(lpm, (uint8_t *)&ipv4_hdr->dst_addr); - } +static inline const uint8_t * +filter_packet_get_net4_src(const struct packet *packet) { + + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset( + mbuf, struct rte_ipv4_hdr *, packet->network_header.offset + ); + + return (const uint8_t *)&ipv4_hdr->src_addr; } + +static inline const uint8_t * +filter_packet_get_net4_dst(const struct packet *packet) { + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset( + mbuf, struct rte_ipv4_hdr *, packet->network_header.offset + ); + + return (const uint8_t *)&ipv4_hdr->dst_addr; +} + +static const struct filter_query_attr_handlers filter_query_net4 = { + .lookup = filter_query_attr_net4_lookup, +}; + +static const struct filter_query_attr_net4_handlers filter_query_attr_net4_src = + { + .attr_handlers = filter_query_net4, + .get_net4 = filter_packet_get_net4_src, +}; + +static const struct filter_query_attr_net4_handlers filter_query_attr_net4_dst = + { + .attr_handlers = filter_query_net4, + .get_net4 = filter_packet_get_net4_dst, +}; diff --git a/filter/query/net6.h b/filter/query/net6.h index bf3e2c466..cd5cfcd18 100644 --- a/filter/query/net6.h +++ b/filter/query/net6.h @@ -1,5 +1,7 @@ #pragma once +#include "common/container_of.h" + #include "filter/classifiers/net6.h" #include "lib/dataplane/packet/packet.h" @@ -10,52 +12,71 @@ #include +typedef const uint8_t *(*packet_get_net6_func)(const struct packet *packet); + +struct filter_query_attr_net6_handlers { + struct filter_query_attr_handlers attr_handlers; + packet_get_net6_func get_net6; +}; + static inline void -FILTER_ATTR_QUERY_FUNC(net6_dst)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_net6_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct net6_classifier *c = (struct net6_classifier *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); - struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset( - mbuf, - struct rte_ipv6_hdr *, - packets[idx]->network_header.offset + const struct filter_query_attr_net6_handlers *net6_handlers = + container_of( + attr_handlers, + struct filter_query_attr_net6_handlers, + attr_handlers ); - uint32_t hi = lpm8_lookup( - &c->hi, (const uint8_t *)ipv6_hdr->dst_addr - ); - uint32_t lo = lpm8_lookup( - &c->lo, (const uint8_t *)ipv6_hdr->dst_addr + 8 - ); + struct filter_query_attr_net6 *attr_net6 = + container_of(attr, struct filter_query_attr_net6, attr); - result[idx] = value_table_get(&c->comb, hi, lo); + for (uint32_t idx = 0; idx < packet_count; ++idx) { + const uint8_t *addr = net6_handlers->get_net6(packets[idx]); + uint32_t hi = lpm8_lookup(&attr_net6->hi, addr); + uint32_t lo = lpm8_lookup(&attr_net6->lo, addr + 8); + results[idx] = *value_table_get_ptr(&attr_net6->comb, hi, lo); } } -static inline void -FILTER_ATTR_QUERY_FUNC(net6_src)( - void *data, struct packet **packets, uint32_t *result, uint32_t count -) { - struct net6_classifier *c = (struct net6_classifier *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); - struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset( - mbuf, - struct rte_ipv6_hdr *, - packets[idx]->network_header.offset - ); +static inline const uint8_t * +filter_packet_get_net6_src(const struct packet *packet) { + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset( + mbuf, struct rte_ipv6_hdr *, packet->network_header.offset + ); - uint32_t hi = lpm8_lookup( - &c->hi, (const uint8_t *)ipv6_hdr->src_addr - ); - uint32_t lo = lpm8_lookup( - &c->lo, (const uint8_t *)ipv6_hdr->src_addr + 8 - ); + return (const uint8_t *)ipv6_hdr->src_addr; +} - result[idx] = value_table_get(&c->comb, hi, lo); - } +static inline const uint8_t * +filter_packet_get_net6_dst(const struct packet *packet) { + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset( + mbuf, struct rte_ipv6_hdr *, packet->network_header.offset + ); + + return (const uint8_t *)ipv6_hdr->dst_addr; } + +static const struct filter_query_attr_handlers filter_query_net6 = { + .lookup = filter_query_attr_net6_lookup, +}; + +static const struct filter_query_attr_net6_handlers filter_query_attr_net6_src = + { + .attr_handlers = filter_query_net6, + .get_net6 = filter_packet_get_net6_src, +}; + +static const struct filter_query_attr_net6_handlers filter_query_attr_net6_dst = + { + .attr_handlers = filter_query_net6, + .get_net6 = filter_packet_get_net6_dst, +}; diff --git a/filter/query/port.h b/filter/query/port.h index ba8bbb491..6bf2392a3 100644 --- a/filter/query/port.h +++ b/filter/query/port.h @@ -12,6 +12,8 @@ #include "declare.h" +#include "filter/classifiers/port.h" + static inline uint16_t packet_src_port(const struct packet *packet) { struct rte_mbuf *mbuf = packet_to_mbuf(packet); @@ -58,30 +60,96 @@ packet_dst_port(const struct packet *packet) { } } -//////////////////////////////////////////////////////////////////////////////// +typedef uint16_t (*packet_get_port_func)(const struct packet *packet); + +struct filter_query_attr_port_handlers { + struct filter_query_attr_handlers attr_handlers; + packet_get_port_func get_port; +}; static inline void -FILTER_ATTR_QUERY_FUNC(port_src)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_port_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct value_table *table = (struct value_table *)data; + const struct filter_query_attr_port_handlers *port_handlers = + container_of( + attr_handlers, + struct filter_query_attr_port_handlers, + attr_handlers + ); - for (uint32_t idx = 0; idx < count; ++idx) { - result[idx] = value_table_get( - table, 0, packet_src_port(packets[idx]) + const struct filter_query_attr_port *port_attr = + container_of(attr, struct filter_query_attr_port, attr); + + for (uint32_t idx = 0; idx < packet_count; ++idx) { + const uint16_t port = port_handlers->get_port(packets[idx]); + results[idx] = + *value_table_get_ptr(&port_attr->value_table, 0, port); + } +} + +static inline uint16_t +filter_packet_get_port_src(const struct packet *packet) { + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + + if (packet->transport_header.type == IPPROTO_TCP) { + struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset( + mbuf, + struct rte_tcp_hdr *, + packet->transport_header.offset + ); + return rte_be_to_cpu_16(tcp_hdr->src_port); + } else if (packet->transport_header.type == IPPROTO_UDP) { + struct rte_udp_hdr *udp_hdr = rte_pktmbuf_mtod_offset( + mbuf, + struct rte_udp_hdr *, + packet->transport_header.offset ); + return rte_be_to_cpu_16(udp_hdr->src_port); } + // unreachable + return 0; } -static inline void -FILTER_ATTR_QUERY_FUNC(port_dst)( - void *data, struct packet **packets, uint32_t *result, uint32_t count -) { - struct value_table *table = (struct value_table *)data; +static inline uint16_t +filter_packet_get_port_dst(const struct packet *packet) { + struct rte_mbuf *mbuf = packet_to_mbuf(packet); - for (uint32_t idx = 0; idx < count; ++idx) { - result[idx] = value_table_get( - table, 0, packet_dst_port(packets[idx]) + if (packet->transport_header.type == IPPROTO_TCP) { + struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset( + mbuf, + struct rte_tcp_hdr *, + packet->transport_header.offset ); + return rte_be_to_cpu_16(tcp_hdr->dst_port); + } else if (packet->transport_header.type == IPPROTO_UDP) { + struct rte_udp_hdr *udp_hdr = rte_pktmbuf_mtod_offset( + mbuf, + struct rte_udp_hdr *, + packet->transport_header.offset + ); + return rte_be_to_cpu_16(udp_hdr->dst_port); } + // unreachable + return 0; } + +static const struct filter_query_attr_handlers filter_query_port = { + .lookup = filter_query_attr_port_lookup, +}; + +static const struct filter_query_attr_port_handlers filter_query_attr_port_src = + { + .attr_handlers = filter_query_port, + .get_port = filter_packet_get_port_src, +}; + +static const struct filter_query_attr_port_handlers filter_query_attr_port_dst = + { + .attr_handlers = filter_query_port, + .get_port = filter_packet_get_port_dst, +}; diff --git a/filter/query/proto.h b/filter/query/proto.h deleted file mode 100644 index 05c12e60d..000000000 --- a/filter/query/proto.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "declare.h" -#include "filter/classifiers/proto.h" -#include "lib/dataplane/packet/packet.h" - -#include -#include -#include - -#include - -static inline void -FILTER_ATTR_QUERY_FUNC(proto)( - void *data, struct packet **packets, uint32_t *result, uint32_t count -) { - struct proto_classifier *c = (struct proto_classifier *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - if (packets[idx]->transport_header.type == IPPROTO_UDP) { - result[idx] = c->max_tcp_class + 1; - } else if (packets[idx]->transport_header.type == - IPPROTO_ICMP) { - result[idx] = c->max_tcp_class + 2; - } else { // TCP - struct rte_tcp_hdr *tcp_header = - rte_pktmbuf_mtod_offset( - packet_to_mbuf(packets[idx]), - struct rte_tcp_hdr *, - packets[idx]->transport_header.offset - ); - result[idx] = value_table_get( - &c->tcp_flags, 0, tcp_header->tcp_flags - ); - } - } -} diff --git a/filter/query/proto_range.h b/filter/query/proto_range.h index 391677502..5e1c6dfbf 100644 --- a/filter/query/proto_range.h +++ b/filter/query/proto_range.h @@ -9,45 +9,67 @@ #include #include +struct filter_query_attr_proto_range_handlers { + struct filter_query_attr_handlers attr_handlers; +}; + +static inline uint16_t +filter_packet_get_proto_range(const struct packet *packet) { + uint16_t proto = packet->transport_header.type * 256; + if (packet->transport_header.type == IPPROTO_TCP) { + struct rte_tcp_hdr *tcp_header = rte_pktmbuf_mtod_offset( + packet_to_mbuf(packet), + struct rte_tcp_hdr *, + packet->transport_header.offset + ); + proto += tcp_header->tcp_flags; + } + if (packet->transport_header.type == IPPROTO_ICMP) { + struct rte_icmp_hdr *icmp_header = rte_pktmbuf_mtod_offset( + packet_to_mbuf(packet), + struct rte_icmp_hdr *, + packet->transport_header.offset + ); + proto += icmp_header->icmp_type; + } + if (packet->transport_header.type == IPPROTO_ICMPV6) { + struct rte_icmp_hdr *icmp_header = rte_pktmbuf_mtod_offset( + packet_to_mbuf(packet), + struct rte_icmp_hdr *, + packet->transport_header.offset + ); + proto += icmp_header->icmp_type; + } + return proto; +} + static inline void -FILTER_ATTR_QUERY_FUNC(proto_range)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_proto_range_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct proto_range_classifier *c = - (struct proto_range_classifier *)data; - - for (uint32_t idx = 0; idx < count; ++idx) { - struct packet *packet = packets[idx]; - - uint16_t proto = packet->transport_header.type * 256; - if (packet->transport_header.type == IPPROTO_TCP) { - struct rte_tcp_hdr *tcp_header = - rte_pktmbuf_mtod_offset( - packet_to_mbuf(packet), - struct rte_tcp_hdr *, - packet->transport_header.offset - ); - proto += tcp_header->tcp_flags; - } - if (packet->transport_header.type == IPPROTO_ICMP) { - struct rte_icmp_hdr *icmp_header = - rte_pktmbuf_mtod_offset( - packet_to_mbuf(packet), - struct rte_icmp_hdr *, - packet->transport_header.offset - ); - proto += icmp_header->icmp_type; - } - if (packet->transport_header.type == IPPROTO_ICMPV6) { - struct rte_icmp_hdr *icmp_header = - rte_pktmbuf_mtod_offset( - packet_to_mbuf(packet), - struct rte_icmp_hdr *, - packet->transport_header.offset - ); - proto += icmp_header->icmp_type; - } - - result[idx] = value_table_get(&c->table, 0, proto); + (void)attr_handlers; + + const struct filter_query_attr_proto_range *proto_range_attr = + container_of(attr, struct filter_query_attr_proto_range, attr); + + for (uint32_t idx = 0; idx < packet_count; ++idx) { + const uint16_t proto_range = + filter_packet_get_proto_range(packets[idx]); + results[idx] = *value_table_get_ptr( + &proto_range_attr->value_table, 0, proto_range + ); } } + +static const struct filter_query_attr_handlers filter_query_proto_range = { + .lookup = filter_query_attr_proto_range_lookup, +}; + +static const struct filter_query_attr_proto_range_handlers + filter_query_attr_proto_range = { + .attr_handlers = filter_query_proto_range, +}; diff --git a/filter/query/vlan.h b/filter/query/vlan.h index 5e22479e1..8e66d05f1 100644 --- a/filter/query/vlan.h +++ b/filter/query/vlan.h @@ -6,14 +6,50 @@ #include +#include "filter/classifiers/vlan.h" + +typedef uint32_t (*packet_get_vlan_func)(const struct packet *packet); + +struct filter_query_attr_vlan_handlers { + struct filter_query_attr_handlers attr_handlers; + packet_get_vlan_func get_vlan; +}; + static inline void -FILTER_ATTR_QUERY_FUNC(vlan)( - void *data, struct packet **packets, uint32_t *result, uint32_t count +filter_query_attr_vlan_lookup( + const struct filter_query_attr *attr, + const struct filter_query_attr_handlers *attr_handlers, + const struct packet **packets, + uint32_t *results, + uint32_t packet_count ) { - struct value_table *t = (struct value_table *)data; + const struct filter_query_attr_vlan_handlers *vlan_handlers = + container_of( + attr_handlers, + struct filter_query_attr_vlan_handlers, + attr_handlers + ); + + const struct filter_query_attr_vlan *vlan_attr = + container_of(attr, struct filter_query_attr_vlan, attr); - for (uint32_t idx = 0; idx < count; ++idx) { - uint16_t vlan = packets[idx]->vlan; - result[idx] = value_table_get(t, 0, vlan); + for (uint32_t idx = 0; idx < packet_count; ++idx) { + const uint16_t vlan_id = vlan_handlers->get_vlan(packets[idx]); + results[idx] = + value_table_get(&vlan_attr->value_table, 0, vlan_id); } } + +static inline uint32_t +filter_packet_get_vlan(const struct packet *packet) { + return packet->vlan; +} + +static const struct filter_query_attr_handlers filter_query_vlan_handlers = { + .lookup = filter_query_attr_vlan_lookup, +}; + +static const struct filter_query_attr_vlan_handlers filter_query_attr_vlan = { + .attr_handlers = filter_query_vlan_handlers, + .get_vlan = filter_packet_get_vlan, +}; diff --git a/filter/rule.h b/filter/rule.h index 111caa005..720da77dd 100644 --- a/filter/rule.h +++ b/filter/rule.h @@ -59,12 +59,6 @@ struct filter_port_range { #define PROTO_UNSPEC ((uint8_t)-1) -struct filter_proto { - uint8_t proto; // 1 ICMP, 6 TCP, 17 UDP - uint16_t enable_bits; // only for TCP - uint16_t disable_bits; // only for TCP -}; - struct filter_proto_range { uint16_t from; uint16_t to; @@ -74,9 +68,6 @@ struct filter_transport { uint16_t proto_count; struct filter_proto_range *protos; - // deprecated - struct filter_proto proto; - uint16_t src_count; struct filter_port_range *srcs; diff --git a/filter/tests/basic_net4.c b/filter/tests/basic_net4.c index 6ba688fed..b8bea82e6 100644 --- a/filter/tests/basic_net4.c +++ b/filter/tests/basic_net4.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/net4.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/basic_net4_fast.c b/filter/tests/basic_net4_fast.c index 69605d11b..132ac961a 100644 --- a/filter/tests/basic_net4_fast.c +++ b/filter/tests/basic_net4_fast.c @@ -4,7 +4,9 @@ #include "common/registry.h" #include "common/rng.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/net4.h" #include "filter/filter.h" #include "filter/query.h" @@ -24,16 +26,14 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE( - sign_fast_src_dst_compile, net4_fast_src, net4_fast_dst -); -FILTER_QUERY_DECLARE(sign_fast_src_dst, net4_fast_src, net4_fast_dst); +FILTER_COMPILER_DECLARE(sign_src_dst_compile, net4_src, net4_dst); +FILTER_QUERY_DECLARE(sign_src_dst, net4_src, net4_dst); -FILTER_COMPILER_DECLARE(sign_fast_src_compile, net4_fast_src); -FILTER_QUERY_DECLARE(sign_fast_src, net4_fast_src); +FILTER_COMPILER_DECLARE(sign_src_compile, net4_src); +FILTER_QUERY_DECLARE(sign_src, net4_src); -FILTER_COMPILER_DECLARE(sign_fast_dst_compile, net4_fast_dst); -FILTER_QUERY_DECLARE(sign_fast_dst, net4_fast_dst); +FILTER_COMPILER_DECLARE(sign_dst_compile, net4_dst); +FILTER_QUERY_DECLARE(sign_dst, net4_dst); //////////////////////////////////////////////////////////////////////////////// @@ -67,22 +67,14 @@ query_and_expect_actions( switch (type) { case src: - filter_query( - filter, sign_fast_src, packets, ranges, packets_count - ); + filter_query(filter, sign_src, packets, ranges, packets_count); break; case dst: - filter_query( - filter, sign_fast_dst, packets, ranges, packets_count - ); + filter_query(filter, sign_dst, packets, ranges, packets_count); break; case src_dst: filter_query( - filter, - sign_fast_src_dst, - packets, - ranges, - packets_count + filter, sign_src_dst, packets, ranges, packets_count ); break; } @@ -211,19 +203,11 @@ test_basic(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -400,19 +384,11 @@ test_multiple_nets_per_rule(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_src_compile, rule_ptrs, num_rules, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_dst_compile, rule_ptrs, num_rules, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -520,7 +496,7 @@ stress(void *arena, case src: res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, num_rules, &memory_context @@ -529,7 +505,7 @@ stress(void *arena, case dst: res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, num_rules, &memory_context @@ -538,7 +514,7 @@ stress(void *arena, case src_dst: res = filter_init( &filter, - sign_fast_src_dst_compile, + sign_src_dst_compile, rule_ptrs, num_rules, &memory_context @@ -708,19 +684,11 @@ test_no_match(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -829,19 +797,11 @@ test_overlapping_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -943,19 +903,11 @@ test_boundary_conditions(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1064,19 +1016,11 @@ test_single_host_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1186,19 +1130,11 @@ test_adjacent_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); diff --git a/filter/tests/basic_net6.c b/filter/tests/basic_net6.c index 2b970ff3b..7651ff022 100644 --- a/filter/tests/basic_net6.c +++ b/filter/tests/basic_net6.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/net6.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/basic_net6_fast.c b/filter/tests/basic_net6_fast.c index 65d612241..6ad066307 100644 --- a/filter/tests/basic_net6_fast.c +++ b/filter/tests/basic_net6_fast.c @@ -4,7 +4,9 @@ #include "common/registry.h" #include "common/rng.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/net6.h" #include "filter/filter.h" #include "filter/query.h" @@ -24,16 +26,14 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE( - sign_fast_src_dst_compile, net6_fast_src, net6_fast_dst -); -FILTER_QUERY_DECLARE(sign_fast_src_dst, net6_fast_src, net6_fast_dst); +FILTER_COMPILER_DECLARE(sign_src_dst_compile, net6_src, net6_dst); +FILTER_QUERY_DECLARE(sign_src_dst, net6_src, net6_dst); -FILTER_COMPILER_DECLARE(sign_fast_src_compile, net6_fast_src); -FILTER_QUERY_DECLARE(sign_fast_src, net6_fast_src); +FILTER_COMPILER_DECLARE(sign_src_compile, net6_src); +FILTER_QUERY_DECLARE(sign_src, net6_src); -FILTER_COMPILER_DECLARE(sign_fast_dst_compile, net6_fast_dst); -FILTER_QUERY_DECLARE(sign_fast_dst, net6_fast_dst); +FILTER_COMPILER_DECLARE(sign_dst_compile, net6_dst); +FILTER_QUERY_DECLARE(sign_dst, net6_dst); //////////////////////////////////////////////////////////////////////////////// @@ -67,22 +67,14 @@ query_and_expect_actions( switch (type) { case src: - filter_query( - filter, sign_fast_src, packets, ranges, packets_count - ); + filter_query(filter, sign_src, packets, ranges, packets_count); break; case dst: - filter_query( - filter, sign_fast_dst, packets, ranges, packets_count - ); + filter_query(filter, sign_dst, packets, ranges, packets_count); break; case src_dst: filter_query( - filter, - sign_fast_src_dst, - packets, - ranges, - packets_count + filter, sign_src_dst, packets, ranges, packets_count ); break; } @@ -228,19 +220,11 @@ test_basic(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -533,19 +517,11 @@ test_multiple_nets_per_rule(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_src_compile, rule_ptrs, num_rules, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_dst_compile, rule_ptrs, num_rules, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -663,7 +639,7 @@ stress(void *arena, case src: res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, num_rules, &memory_context @@ -672,7 +648,7 @@ stress(void *arena, case dst: res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, num_rules, &memory_context @@ -681,7 +657,7 @@ stress(void *arena, case src_dst: res = filter_init( &filter, - sign_fast_src_dst_compile, + sign_src_dst_compile, rule_ptrs, num_rules, &memory_context @@ -869,19 +845,11 @@ test_no_match(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1092,19 +1060,11 @@ test_overlapping_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1267,19 +1227,11 @@ test_boundary_conditions(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1411,19 +1363,11 @@ test_single_host_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -1596,19 +1540,11 @@ test_adjacent_networks(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_src_compile, rule_ptrs, nets_count, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - nets_count, - &mctx + &filter, sign_dst_compile, rule_ptrs, nets_count, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); diff --git a/filter/tests/basic_port_fast.c b/filter/tests/basic_port_fast.c index 2707e232f..41cbae717 100644 --- a/filter/tests/basic_port_fast.c +++ b/filter/tests/basic_port_fast.c @@ -4,7 +4,9 @@ #include "common/registry.h" #include "common/rng.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" @@ -23,16 +25,14 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE( - sign_fast_src_dst_compile, port_fast_src, port_fast_dst -); -FILTER_QUERY_DECLARE(sign_fast_src_dst, port_fast_src, port_fast_dst); +FILTER_COMPILER_DECLARE(sign_src_dst_compile, port_src, port_dst); +FILTER_QUERY_DECLARE(sign_src_dst, port_src, port_dst); -FILTER_COMPILER_DECLARE(sign_fast_src_compile, port_fast_src); -FILTER_QUERY_DECLARE(sign_fast_src, port_fast_src); +FILTER_COMPILER_DECLARE(sign_src_compile, port_src); +FILTER_QUERY_DECLARE(sign_src, port_src); -FILTER_COMPILER_DECLARE(sign_fast_dst_compile, port_fast_dst); -FILTER_QUERY_DECLARE(sign_fast_dst, port_fast_dst); +FILTER_COMPILER_DECLARE(sign_dst_compile, port_dst); +FILTER_QUERY_DECLARE(sign_dst, port_dst); //////////////////////////////////////////////////////////////////////////////// @@ -66,22 +66,14 @@ query_and_expect_actions( switch (type) { case src: - filter_query( - filter, sign_fast_src, packets, ranges, packets_count - ); + filter_query(filter, sign_src, packets, ranges, packets_count); break; case dst: - filter_query( - filter, sign_fast_dst, packets, ranges, packets_count - ); + filter_query(filter, sign_dst, packets, ranges, packets_count); break; case src_dst: filter_query( - filter, - sign_fast_src_dst, - packets, - ranges, - packets_count + filter, sign_src_dst, packets, ranges, packets_count ); break; } @@ -211,7 +203,7 @@ test_basic(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -219,7 +211,7 @@ test_basic(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -351,19 +343,11 @@ test_multiple_ranges_per_rule(void *arena, enum filter_sign sign) { struct filter filter; if (sign == src) { res = filter_init( - &filter, - sign_fast_src_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_src_compile, rule_ptrs, num_rules, &mctx ); } else { res = filter_init( - &filter, - sign_fast_dst_compile, - rule_ptrs, - num_rules, - &mctx + &filter, sign_dst_compile, rule_ptrs, num_rules, &mctx ); } TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -461,7 +445,7 @@ stress(void *arena, case src: res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, num_rules, &memory_context @@ -470,7 +454,7 @@ stress(void *arena, case dst: res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, num_rules, &memory_context @@ -479,7 +463,7 @@ stress(void *arena, case src_dst: res = filter_init( &filter, - sign_fast_src_dst_compile, + sign_src_dst_compile, rule_ptrs, num_rules, &memory_context @@ -690,7 +674,7 @@ test_no_match(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -698,7 +682,7 @@ test_no_match(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -819,7 +803,7 @@ test_overlapping_ranges(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -827,7 +811,7 @@ test_overlapping_ranges(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -941,7 +925,7 @@ test_boundary_conditions(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -949,7 +933,7 @@ test_boundary_conditions(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -1075,7 +1059,7 @@ test_single_port_ranges(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -1083,7 +1067,7 @@ test_single_port_ranges(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -1204,7 +1188,7 @@ test_adjacent_ranges(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -1212,7 +1196,7 @@ test_adjacent_ranges(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx @@ -1337,7 +1321,7 @@ test_extreme_ports(void *arena, enum filter_sign sign) { if (sign == src) { res = filter_init( &filter, - sign_fast_src_compile, + sign_src_compile, rule_ptrs, ranges_count, &mctx @@ -1345,7 +1329,7 @@ test_extreme_ports(void *arena, enum filter_sign sign) { } else { res = filter_init( &filter, - sign_fast_dst_compile, + sign_dst_compile, rule_ptrs, ranges_count, &mctx diff --git a/filter/tests/basic_ports.c b/filter/tests/basic_ports.c index 0bbd421d1..20887791f 100644 --- a/filter/tests/basic_ports.c +++ b/filter/tests/basic_ports.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/basic_proto.c b/filter/tests/basic_proto.c deleted file mode 100644 index b3b2e269f..000000000 --- a/filter/tests/basic_proto.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "filter/compiler.h" -#include "filter/filter.h" -#include "filter/query.h" - -#include "filter/tests/helpers.h" -#include "lib/utils/packet.h" - -#include "logging/log.h" -#include -#include - -FILTER_COMPILER_DECLARE(sign_proto_compile, proto); -FILTER_QUERY_DECLARE(sign_proto, proto); - -//////////////////////////////////////////////////////////////////////////////// - -static void -query_tcp_packet(struct filter *filter, uint16_t flags, uint32_t expected) { - struct packet packet = {0}; - uint8_t sip[NET4_LEN] = {0, 0, 0, 0}; - uint8_t dip[NET4_LEN] = {0, 0, 0, 0}; - int res = fill_packet_net4(&packet, sip, dip, 0, 0, IPPROTO_TCP, flags); - assert(res == 0); - struct packet *packet_ptr = &packet; - uint32_t actions; - filter_query(filter, sign_proto, &packet_ptr, &actions, 1); - assert(actions == expected); - free_packet(&packet); -} - -static void -query_udp_packet(struct filter *filter, uint32_t expected) { - struct packet packet = {0}; - uint8_t sip[NET4_LEN] = {0, 0, 0, 0}; - uint8_t dip[NET4_LEN] = {0, 0, 0, 0}; - int res = fill_packet_net4(&packet, sip, dip, 0, 0, IPPROTO_UDP, 0); - assert(res == 0); - struct packet *packet_ptr = &packet; - uint32_t actions; - filter_query(filter, sign_proto, &packet_ptr, &actions, 1); - assert(actions == expected); - free_packet(&packet); -} - -//////////////////////////////////////////////////////////////////////////////// - -static void -test_proto_1(void *memory) { - // init memory - struct block_allocator allocator; - block_allocator_init(&allocator); - block_allocator_put_arena(&allocator, memory, 1 << 24); - - struct memory_context memory_context; - int res = memory_context_init(&memory_context, "test", &allocator); - assert(res == 0); - - struct filter_rule_builder b1; - builder_init(&b1); - builder_set_proto(&b1, IPPROTO_TCP, 0b101, 0b010); - struct filter_rule r1 = build_rule(&b1); - - struct filter_rule_builder b2; - builder_init(&b2); - builder_set_proto(&b2, IPPROTO_UDP, 0, 0); - struct filter_rule r2 = build_rule(&b2); - - struct filter_rule_builder b3; - builder_init(&b3); - builder_set_proto(&b3, PROTO_UNSPEC, 0, 0); - struct filter_rule r3 = build_rule(&b3); - - const struct filter_rule *rule_ptrs[3] = {&r1, &r2, &r3}; - - struct filter filter; - res = filter_init( - &filter, sign_proto_compile, rule_ptrs, 3, &memory_context - ); - assert(res == 0); - - query_tcp_packet(&filter, 0b101, 0); - query_tcp_packet(&filter, 0b10101, 0); - query_tcp_packet(&filter, 0b1101, 0); - query_tcp_packet(&filter, (1 << 9) - 1 - 2, 0); - query_tcp_packet(&filter, 0b010, 2); - query_tcp_packet(&filter, 0b011, 2); - query_tcp_packet(&filter, 0b1110, 2); - - query_udp_packet(&filter, 1); - - filter_free(&filter, sign_proto_compile); -} - -int -main() { - log_enable_name("debug"); - void *memory = malloc(1 << 24); - - test_proto_1(memory); - - free(memory); - - LOG(INFO, "OK"); - - return 0; -} diff --git a/filter/tests/basic_proto_range.c b/filter/tests/basic_proto_range.c index d80d5d909..d2bf7807d 100644 --- a/filter/tests/basic_proto_range.c +++ b/filter/tests/basic_proto_range.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/basic_proto_range_fast.c b/filter/tests/basic_proto_range_fast.c index 9dca29882..a736412bf 100644 --- a/filter/tests/basic_proto_range_fast.c +++ b/filter/tests/basic_proto_range_fast.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" @@ -11,8 +12,8 @@ #include #include -FILTER_COMPILER_DECLARE(sign_proto_range_fast_compile, proto_range_fast); -FILTER_QUERY_DECLARE(sign_proto_range_fast, proto_range_fast); +FILTER_COMPILER_DECLARE(sign_proto_range_compile, proto_range); +FILTER_QUERY_DECLARE(sign_proto_range, proto_range); //////////////////////////////////////////////////////////////////////////////// @@ -25,7 +26,7 @@ query_tcp_packet(struct filter *filter, uint16_t flags, uint32_t expected) { assert(res == 0); struct packet *packet_ptr = &packet; uint32_t actions; - filter_query(filter, sign_proto_range_fast, &packet_ptr, &actions, 1); + filter_query(filter, sign_proto_range, &packet_ptr, &actions, 1); assert(actions == expected); free_packet(&packet); } @@ -39,7 +40,7 @@ query_udp_packet(struct filter *filter, uint32_t expected) { assert(res == 0); struct packet *packet_ptr = &packet; uint32_t actions; - filter_query(filter, sign_proto_range_fast, &packet_ptr, &actions, 1); + filter_query(filter, sign_proto_range, &packet_ptr, &actions, 1); assert(actions == expected); free_packet(&packet); } @@ -83,11 +84,7 @@ test_basic_tcp_udp(void *memory) { LOG(INFO, "filter init..."); res = filter_init( - &filter, - sign_proto_range_fast_compile, - rule_ptrs, - 2, - &memory_context + &filter, sign_proto_range_compile, rule_ptrs, 2, &memory_context ); TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -97,7 +94,7 @@ test_basic_tcp_udp(void *memory) { LOG(INFO, "query udp packet..."); query_udp_packet(&filter, 1); - filter_free(&filter, sign_proto_range_fast_compile); + filter_free(&filter, sign_proto_range_compile); return TEST_SUCCESS; } @@ -146,11 +143,7 @@ test_tcp_flags(void *memory) { struct filter filter; res = filter_init( - &filter, - sign_proto_range_fast_compile, - rule_ptrs, - 3, - &memory_context + &filter, sign_proto_range_compile, rule_ptrs, 3, &memory_context ); TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -163,7 +156,7 @@ test_tcp_flags(void *memory) { LOG(INFO, "query tcp FIN packet..."); query_tcp_packet(&filter, 0x01, 2); - filter_free(&filter, sign_proto_range_fast_compile); + filter_free(&filter, sign_proto_range_compile); return TEST_SUCCESS; } @@ -199,11 +192,7 @@ test_multiple_ranges_per_rule(void *memory) { struct filter filter; res = filter_init( - &filter, - sign_proto_range_fast_compile, - rule_ptrs, - 1, - &memory_context + &filter, sign_proto_range_compile, rule_ptrs, 1, &memory_context ); TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -213,7 +202,7 @@ test_multiple_ranges_per_rule(void *memory) { LOG(INFO, "query udp packet..."); query_udp_packet(&filter, 0); - filter_free(&filter, sign_proto_range_fast_compile); + filter_free(&filter, sign_proto_range_compile); return TEST_SUCCESS; } @@ -250,11 +239,7 @@ test_boundary_values(void *memory) { struct filter filter; res = filter_init( - &filter, - sign_proto_range_fast_compile, - rule_ptrs, - 2, - &memory_context + &filter, sign_proto_range_compile, rule_ptrs, 2, &memory_context ); TEST_ASSERT_EQUAL(res, 0, "failed to initialize filter"); @@ -267,13 +252,11 @@ test_boundary_values(void *memory) { struct packet *packet_ptr1 = &packet1; uint32_t actions1; - filter_query( - &filter, sign_proto_range_fast, &packet_ptr1, &actions1, 1 - ); + filter_query(&filter, sign_proto_range, &packet_ptr1, &actions1, 1); TEST_ASSERT_EQUAL(actions1, 0, "proto 0 should match rule 1"); free_packet(&packet1); - filter_free(&filter, sign_proto_range_fast_compile); + filter_free(&filter, sign_proto_range_compile); return TEST_SUCCESS; } diff --git a/filter/tests/basic_vlan.c b/filter/tests/basic_vlan.c index 02791258f..fa3554d1a 100644 --- a/filter/tests/basic_vlan.c +++ b/filter/tests/basic_vlan.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/vlan.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/bench_net4.c b/filter/tests/bench_net4.c index 1533a5902..bb10e476c 100644 --- a/filter/tests/bench_net4.c +++ b/filter/tests/bench_net4.c @@ -23,6 +23,9 @@ #include "common/registry.h" #include "common/rng.h" #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" #include "filter/tests/helpers.h" @@ -56,9 +59,9 @@ FILTER_COMPILER_DECLARE(bench_dst_port_compile, net4_dst, port_dst); FILTER_QUERY_DECLARE(bench_dst_port, net4_dst, port_dst); FILTER_COMPILER_DECLARE( - bench_dst_port_proto_compile, net4_dst, port_dst, proto + bench_dst_port_proto_compile, net4_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_dst, port_dst, proto); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types diff --git a/filter/tests/bench_net4_fast.c b/filter/tests/bench_net4_fast.c index ae7cc2a90..759dbd734 100644 --- a/filter/tests/bench_net4_fast.c +++ b/filter/tests/bench_net4_fast.c @@ -1,6 +1,6 @@ /** - * @file bench_net4_fast.c - * @brief Performance benchmark for net4_fast filter + * @file bench_net4.c + * @brief Performance benchmark for net4 filter * * This benchmark uses hugepages for optimal memory performance. * @@ -23,7 +23,11 @@ #include "common/registry.h" #include "common/rng.h" #include "dataplane/packet/packet.h" + #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" #include "filter/tests/helpers.h" @@ -50,16 +54,16 @@ //////////////////////////////////////////////////////////////////////////////// // Filter signature declarations -FILTER_COMPILER_DECLARE(bench_dst_compile, net4_fast_dst); -FILTER_QUERY_DECLARE(bench_dst, net4_fast_dst); +FILTER_COMPILER_DECLARE(bench_dst_compile, net4_dst); +FILTER_QUERY_DECLARE(bench_dst, net4_dst); -FILTER_COMPILER_DECLARE(bench_dst_port_compile, net4_fast_dst, port_dst); -FILTER_QUERY_DECLARE(bench_dst_port, net4_fast_dst, port_dst); +FILTER_COMPILER_DECLARE(bench_dst_port_compile, net4_dst, port_dst); +FILTER_QUERY_DECLARE(bench_dst_port, net4_dst, port_dst); FILTER_COMPILER_DECLARE( - bench_dst_port_proto_compile, net4_fast_dst, port_dst, proto + bench_dst_port_proto_compile, net4_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_fast_dst, port_dst, proto); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types @@ -418,7 +422,7 @@ print_results(const struct bench_config *config, struct bench_stats *stats) { double mpps = pps / 1e6; printf("\n"); - printf("=== Filter Benchmark: net4_fast ===\n"); + printf("=== Filter Benchmark: net4 ===\n"); printf("Signature: %s\n", signature_type_to_string(config->sig_type)); printf("Rules: %zu\n", config->num_rules); printf("Batch Size: %zu\n", config->batch_size); diff --git a/filter/tests/bench_net6.c b/filter/tests/bench_net6.c index e1d59ae84..f4566d990 100644 --- a/filter/tests/bench_net6.c +++ b/filter/tests/bench_net6.c @@ -23,7 +23,11 @@ #include "common/network.h" #include "common/registry.h" #include "common/rng.h" + #include "filter/compiler.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" #include "filter/tests/helpers.h" @@ -57,9 +61,9 @@ FILTER_COMPILER_DECLARE(bench_dst_port_compile, net6_dst, port_dst); FILTER_QUERY_DECLARE(bench_dst_port, net6_dst, port_dst); FILTER_COMPILER_DECLARE( - bench_dst_port_proto_compile, net6_dst, port_dst, proto + bench_dst_port_proto_compile, net6_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_dst, port_dst, proto); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types diff --git a/filter/tests/bench_net6_fast.c b/filter/tests/bench_net6_fast.c index e95fe0978..3788c8ef0 100644 --- a/filter/tests/bench_net6_fast.c +++ b/filter/tests/bench_net6_fast.c @@ -1,6 +1,6 @@ /** - * @file bench_net6_fast.c - * @brief Performance benchmark for net6_fast filter + * @file bench_net6.c + * @brief Performance benchmark for net6 filter * * This benchmark uses hugepages for optimal memory performance. * @@ -24,7 +24,11 @@ #include "common/registry.h" #include "common/rng.h" #include "dataplane/packet/packet.h" + #include "filter/compiler.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" #include "filter/tests/helpers.h" @@ -51,16 +55,16 @@ //////////////////////////////////////////////////////////////////////////////// // Filter signature declarations -FILTER_COMPILER_DECLARE(bench_dst_compile, net6_fast_dst); -FILTER_QUERY_DECLARE(bench_dst, net6_fast_dst); +FILTER_COMPILER_DECLARE(bench_dst_compile, net6_dst); +FILTER_QUERY_DECLARE(bench_dst, net6_dst); -FILTER_COMPILER_DECLARE(bench_dst_port_compile, net6_fast_dst, port_dst); -FILTER_QUERY_DECLARE(bench_dst_port, net6_fast_dst, port_dst); +FILTER_COMPILER_DECLARE(bench_dst_port_compile, net6_dst, port_dst); +FILTER_QUERY_DECLARE(bench_dst_port, net6_dst, port_dst); FILTER_COMPILER_DECLARE( - bench_dst_port_proto_compile, net6_fast_dst, port_dst, proto + bench_dst_port_proto_compile, net6_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_fast_dst, port_dst, proto); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types @@ -452,7 +456,7 @@ print_results(const struct bench_config *config, struct bench_stats *stats) { double mpps = pps / 1e6; printf("\n"); - printf("=== Filter Benchmark: net6_fast ===\n"); + printf("=== Filter Benchmark: net6 ===\n"); printf("Signature: %s\n", signature_type_to_string(config->sig_type)); printf("Rules: %zu\n", config->num_rules); printf("Batch Size: %zu\n", config->batch_size); diff --git a/filter/tests/combo_net4_port_proto_dst.c b/filter/tests/combo_net4_port_proto_dst.c index 6e2200f50..5bd2477f3 100644 --- a/filter/tests/combo_net4_port_proto_dst.c +++ b/filter/tests/combo_net4_port_proto_dst.c @@ -3,7 +3,11 @@ #include "common/network.h" #include "common/registry.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" #include "filter/filter.h" #include "filter/query.h" @@ -24,10 +28,10 @@ //////////////////////////////////////////////////////////////////////////////// FILTER_COMPILER_DECLARE( - combo_net4_port_proto_dst_compile, net4_fast_dst, port_fast_dst, proto + combo_net4_port_proto_dst_compile, net4_dst, port_dst, proto_range ); FILTER_QUERY_DECLARE( - combo_net4_port_proto_dst, net4_fast_dst, port_fast_dst, proto + combo_net4_port_proto_dst, net4_dst, port_dst, proto_range ); //////////////////////////////////////////////////////////////////////////////// @@ -330,7 +334,12 @@ test_tcp_flags(void *arena) { builder_init(&builder1); builder_add_net4_dst(&builder1, ip(10, 0, 0, 0), ip(255, 255, 255, 0)); builder_add_port_dst_range(&builder1, 80, 80); - builder_set_proto(&builder1, IPPROTO_TCP, 0x02, 0); // SYN flag + builder_add_proto_range( + &builder1, IPPROTO_TCP * 256 + 0x02, IPPROTO_TCP * 256 + 0x02 + ); // SYN flag + builder_add_proto_range( + &builder1, IPPROTO_TCP * 256 + 0x12, IPPROTO_TCP * 256 + 0x12 + ); // SYN + ACK flag struct filter_rule rule1 = build_rule(&builder1); // Rule 2: dst IP 10.0.0.0/24, dst port 80, TCP with ACK flag @@ -338,7 +347,9 @@ test_tcp_flags(void *arena) { builder_init(&builder2); builder_add_net4_dst(&builder2, ip(10, 0, 0, 0), ip(255, 255, 255, 0)); builder_add_port_dst_range(&builder2, 80, 80); - builder_set_proto(&builder2, IPPROTO_TCP, 0x10, 0); // ACK flag + builder_add_proto_range( + &builder2, IPPROTO_TCP * 256 + 0x10, IPPROTO_TCP * 256 + 0x10 + ); // ACK flag struct filter_rule rule2 = build_rule(&builder2); struct filter_rule rules[] = {rule1, rule2}; diff --git a/filter/tests/combo_net4_port_src.c b/filter/tests/combo_net4_port_src.c index b1a7122f9..a232ae736 100644 --- a/filter/tests/combo_net4_port_src.c +++ b/filter/tests/combo_net4_port_src.c @@ -2,7 +2,10 @@ #include "common/memory_block.h" #include "common/registry.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" @@ -22,10 +25,8 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE( - combo_net4_port_src_compile, net4_fast_src, port_fast_src -); -FILTER_QUERY_DECLARE(combo_net4_port_src, net4_fast_src, port_fast_src); +FILTER_COMPILER_DECLARE(combo_net4_port_src_compile, net4_src, port_src); +FILTER_QUERY_DECLARE(combo_net4_port_src, net4_src, port_src); //////////////////////////////////////////////////////////////////////////////// diff --git a/filter/tests/combo_net6_port_src.c b/filter/tests/combo_net6_port_src.c index 5f33ba896..89b945e70 100644 --- a/filter/tests/combo_net6_port_src.c +++ b/filter/tests/combo_net6_port_src.c @@ -3,7 +3,10 @@ #include "common/network.h" #include "common/registry.h" #include "common/test_assert.h" + #include "filter/compiler.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" @@ -23,10 +26,8 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE( - combo_net6_port_src_compile, net6_fast_src, port_fast_src -); -FILTER_QUERY_DECLARE(combo_net6_port_src, net6_fast_src, port_fast_src); +FILTER_COMPILER_DECLARE(combo_net6_port_src_compile, net6_src, port_src); +FILTER_QUERY_DECLARE(combo_net6_port_src, net6_src, port_src); //////////////////////////////////////////////////////////////////////////////// diff --git a/filter/tests/corner.c b/filter/tests/corner.c index 8becfc4a5..63adefd59 100644 --- a/filter/tests/corner.c +++ b/filter/tests/corner.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/helpers.h b/filter/tests/helpers.h index e983e4e89..a7b8517a0 100644 --- a/filter/tests/helpers.h +++ b/filter/tests/helpers.h @@ -36,8 +36,6 @@ struct filter_rule_builder { struct filter_proto_range proto_ranges[filter_TEST_MAX_RANGES]; size_t proto_ranges_count; - - struct filter_proto proto; }; static inline void @@ -50,8 +48,6 @@ builder_init(struct filter_rule_builder *b) { b->net6_dst_count = 0; b->vlan_range_count = 0; b->proto_ranges_count = 0; - b->proto = (struct filter_proto - ){.proto = PROTO_UNSPEC, .enable_bits = 0, .disable_bits = 0}; } static inline void @@ -116,16 +112,6 @@ builder_add_proto_range( b->proto_ranges[i] = (struct filter_proto_range){from, to}; } -static inline void -builder_set_proto( - struct filter_rule_builder *b, - uint8_t proto, - uint16_t enable_bits, - uint16_t disable_bits -) { - b->proto = (struct filter_proto){proto, enable_bits, disable_bits}; -} - static inline void builder_set_proto_range( struct filter_rule_builder *b, uint8_t proto, uint16_t flags_or_type @@ -136,6 +122,21 @@ builder_set_proto_range( b->proto_ranges[i] = (struct filter_proto_range){encoded, encoded}; } +static inline void +builder_set_proto( + struct filter_rule_builder *b, + uint8_t proto, + uint16_t unused1, + uint16_t unused2 +) { + (void)unused1; + (void)unused2; + // proto_range encoding: proto * 256 + flags/type + size_t i = b->proto_ranges_count++; + b->proto_ranges[i] = + (struct filter_proto_range){256 * proto, 256 * proto + 255}; +} + static inline void builder_set_vlan(struct filter_rule_builder *b, uint16_t vlan) { b->vlan_ranges[0].from = vlan; @@ -156,7 +157,6 @@ build_rule(struct filter_rule_builder *b) { r.net6.dst_count = (uint32_t)b->net6_dst_count; r.net6.dsts = b->net6_dst; - r.transport.proto = b->proto; r.transport.src_count = (uint16_t)b->src_port_ranges_count; r.transport.srcs = b->src_port_ranges; r.transport.dst_count = (uint16_t)b->dst_port_ranges_count; diff --git a/filter/tests/macros.c b/filter/tests/macros.c index fc49a0bd9..8249e03fd 100644 --- a/filter/tests/macros.c +++ b/filter/tests/macros.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/memory.c b/filter/tests/memory.c index 5b496f013..67e43a3ea 100644 --- a/filter/tests/memory.c +++ b/filter/tests/memory.c @@ -1,4 +1,5 @@ #include "filter/compiler.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/meson.build b/filter/tests/meson.build index 153a73f57..148e79c72 100644 --- a/filter/tests/meson.build +++ b/filter/tests/meson.build @@ -92,16 +92,6 @@ test_filter_memory = executable('memory', ) test('memory', test_filter_memory, suite: ['filter']) -# test proto -test_filter_proto = executable('basic_proto', - ['basic_proto.c'], - c_args: yanet_test_c_args, - link_args: yanet_link_args, - dependencies: test_deps, - link_language: 'c' -) -test('basic_proto', test_filter_proto, suite: ['filter']) - # test vlan test_filter_vlan = executable('basic_vlan', ['basic_vlan.c'], diff --git a/filter/tests/net4_ports.c b/filter/tests/net4_ports.c index 7bc46c32b..57541d925 100644 --- a/filter/tests/net4_ports.c +++ b/filter/tests/net4_ports.c @@ -1,4 +1,6 @@ #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" #include "filter/filter.h" #include "filter/query.h" diff --git a/filter/tests/shm/compiler.c b/filter/tests/shm/compiler.c index d3c03b1b3..bb8af8488 100644 --- a/filter/tests/shm/compiler.c +++ b/filter/tests/shm/compiler.c @@ -14,9 +14,12 @@ #include -#include +#include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" -FILTER_COMPILER_DECLARE(filter_sign, net4_dst, port_dst, proto); +FILTER_COMPILER_DECLARE(filter_sign, net4_dst, port_dst, proto_range); static int build_filter(struct common *common, struct memory_context *mctx) { diff --git a/filter/tests/shm/filter.c b/filter/tests/shm/filter.c index 931ae70bf..4c1c5250e 100644 --- a/filter/tests/shm/filter.c +++ b/filter/tests/shm/filter.c @@ -15,7 +15,7 @@ #include -FILTER_QUERY_DECLARE(filter_sign, net4_dst, port_dst, proto); +FILTER_QUERY_DECLARE(filter_sign, net4_dst, port_dst, proto_range); static int filter_packets(struct common *common) { diff --git a/modules/acl/api/controlplane.c b/modules/acl/api/controlplane.c index f20924ce3..c0488aaa0 100644 --- a/modules/acl/api/controlplane.c +++ b/modules/acl/api/controlplane.c @@ -14,7 +14,13 @@ #include "controlplane/agent/agent.h" -#include +#include "filter/compiler.h" +#include "filter/compiler/device.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" +#include "filter/compiler/vlan.h" FILTER_COMPILER_DECLARE(ACL_FILTER_VLAN_TAG, device, vlan); diff --git a/modules/balancer/controlplane/handler/rules.c b/modules/balancer/controlplane/handler/rules.c index 0ee8dfe09..b115c2c67 100644 --- a/modules/balancer/controlplane/handler/rules.c +++ b/modules/balancer/controlplane/handler/rules.c @@ -2,7 +2,13 @@ #include "api/vs.h" #include "common/memory.h" + #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" + #include "filter/rule.h" #include "handler.h" #include "lib/errors/errors.h" @@ -12,12 +18,8 @@ #include // Declare filter compiler signatures for VS lookup tables -FILTER_COMPILER_DECLARE( - vs_lookup_ipv4, net4_fast_dst, port_fast_dst, proto_range_fast -); -FILTER_COMPILER_DECLARE( - vs_lookup_ipv6, net6_fast_dst, port_fast_dst, proto_range_fast -); +FILTER_COMPILER_DECLARE(vs_lookup_ipv4, net4_dst, port_dst, proto_range); +FILTER_COMPILER_DECLARE(vs_lookup_ipv6, net6_dst, port_dst, proto_range); static int init_transport_rule( diff --git a/modules/balancer/controlplane/handler/vs.c b/modules/balancer/controlplane/handler/vs.c index 0fb484733..6b0010b94 100644 --- a/modules/balancer/controlplane/handler/vs.c +++ b/modules/balancer/controlplane/handler/vs.c @@ -5,7 +5,12 @@ #include "common/memory_address.h" #include "common/network.h" -#include "compiler/declare.h" +#include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/port.h" +#include "filter/compiler/proto_range.h" + #include "counters/counters.h" #include "lib/errors/errors.h" @@ -22,8 +27,6 @@ #include #include -#include "filter/compiler.h" - #define MAX_TAG_LENGTH 240 static int @@ -430,8 +433,8 @@ src_filter_rules( //////////////////////////////////////////////////////////////////////////////// -FILTER_COMPILER_DECLARE(vs_acl_ipv4, net4_fast_src, port_fast_src); -FILTER_COMPILER_DECLARE(vs_acl_ipv6, net6_fast_src, port_fast_src); +FILTER_COMPILER_DECLARE(vs_acl_ipv4, net4_src, port_src); +FILTER_COMPILER_DECLARE(vs_acl_ipv6, net6_src, port_src); //////////////////////////////////////////////////////////////////////////////// // Helper functions for rule comparison and sorting diff --git a/modules/balancer/dataplane/lookup.h b/modules/balancer/dataplane/lookup.h index 064e41124..55f9b9337 100644 --- a/modules/balancer/dataplane/lookup.h +++ b/modules/balancer/dataplane/lookup.h @@ -22,10 +22,8 @@ //////////////////////////////////////////////////////////////////////////////// -FILTER_QUERY_DECLARE( - vs_lookup_ipv4, net4_fast_dst, port_fast_dst, proto_range_fast -); -FILTER_QUERY_DECLARE(vs_acl_ipv4, net4_fast_src, port_fast_src); +FILTER_QUERY_DECLARE(vs_lookup_ipv4, net4_dst, port_dst, proto_range); +FILTER_QUERY_DECLARE(vs_acl_ipv4, net4_src, port_src); static inline uint32_t vs_v4_table_lookup(struct packet_handler *handler, struct packet *packet) { @@ -42,10 +40,8 @@ vs_v4_table_lookup(struct packet_handler *handler, struct packet *packet) { //////////////////////////////////////////////////////////////////////////////// -FILTER_QUERY_DECLARE( - vs_lookup_ipv6, net6_fast_dst, port_fast_dst, proto_range_fast -); -FILTER_QUERY_DECLARE(vs_acl_ipv6, net6_fast_src, port_fast_src); +FILTER_QUERY_DECLARE(vs_lookup_ipv6, net6_dst, port_dst, proto_range); +FILTER_QUERY_DECLARE(vs_acl_ipv6, net6_src, port_src); static inline uint32_t vs_v6_table_lookup(struct packet_handler *handler, struct packet *packet) { diff --git a/modules/forward/api/controlplane.c b/modules/forward/api/controlplane.c index 4b2fecc32..eb0c6d2b0 100644 --- a/modules/forward/api/controlplane.c +++ b/modules/forward/api/controlplane.c @@ -4,7 +4,11 @@ #include "config.h" -#include +#include "filter/compiler.h" +#include "filter/compiler/device.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/net6.h" +#include "filter/compiler/vlan.h" #include "common/container_of.h" #include "lib/errors/errors.h" diff --git a/modules/route-mpls/api/controlplane.c b/modules/route-mpls/api/controlplane.c index 2eaa0ad54..62b742412 100644 --- a/modules/route-mpls/api/controlplane.c +++ b/modules/route-mpls/api/controlplane.c @@ -9,6 +9,8 @@ #include "controlplane/agent/agent.h" #include "filter/compiler.h" +#include "filter/compiler/net4.h" +#include "filter/compiler/net6.h" FILTER_COMPILER_DECLARE(FILTER_IP4_TAG, net4_dst); FILTER_COMPILER_DECLARE(FILTER_IP6_TAG, net6_dst);