From 67b9ea638096a03b7a5a2382893d5db30ea56de4 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 19:53:20 +0300 Subject: [PATCH 01/17] minor common refactorings --- common/lpm.h | 3 +++ common/range_index.h | 11 ----------- common/remap.h | 4 +--- common/value.h | 14 +++++++------- filter/compiler/helper.c | 6 +++--- 5 files changed, 14 insertions(+), 24 deletions(-) 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..ab52b54e3 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 + 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 + 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/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; } } From 10c34601c45d503a4c0b91a4e6fc0bd52f47701e Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 19:55:35 +0300 Subject: [PATCH 02/17] Fix invalid read in case of unknown device When a device was not used while filter initialization use a default one value --- filter/query/device.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/filter/query/device.h b/filter/query/device.h index 5db12d7ad..02426c543 100644 --- a/filter/query/device.h +++ b/filter/query/device.h @@ -13,6 +13,8 @@ FILTER_ATTR_QUERY_FUNC(device)( 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; + if (device_id >= t->h_dim) + device_id = 0; result[idx] = value_table_get(t, 0, device_id); } } From e16620ba0ca84528867f85d3b7709fc7745827f8 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 21:07:12 +0300 Subject: [PATCH 03/17] remove `proto` filter attribute This is obsolete and produces invalid values while query --- filter/compiler/attribute.h | 1 - filter/meson.build | 3 +- filter/query/attribute.h | 2 - filter/query/proto.h | 37 -------- filter/rule.h | 9 -- filter/tests/basic_proto.c | 106 ----------------------- filter/tests/bench_net4.c | 4 +- filter/tests/bench_net4_fast.c | 6 +- filter/tests/bench_net6.c | 4 +- filter/tests/bench_net6_fast.c | 6 +- filter/tests/combo_net4_port_proto_dst.c | 18 +++- filter/tests/helpers.h | 30 +++---- filter/tests/meson.build | 10 --- filter/tests/shm/compiler.c | 2 +- filter/tests/shm/filter.c | 2 +- 15 files changed, 44 insertions(+), 196 deletions(-) delete mode 100644 filter/query/proto.h delete mode 100644 filter/tests/basic_proto.c diff --git a/filter/compiler/attribute.h b/filter/compiler/attribute.h index 62bfa2fed..c93be402e 100644 --- a/filter/compiler/attribute.h +++ b/filter/compiler/attribute.h @@ -23,7 +23,6 @@ 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); diff --git a/filter/meson.build b/filter/meson.build index 6840a29d2..7f1c265e6 100644 --- a/filter/meson.build +++ b/filter/meson.build @@ -10,7 +10,6 @@ compiler_sources = files( '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', @@ -32,4 +31,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/attribute.h b/filter/query/attribute.h index f13e71594..0ecd8a455 100644 --- a/filter/query/attribute.h +++ b/filter/query/attribute.h @@ -8,7 +8,6 @@ #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" @@ -31,7 +30,6 @@ struct filter_attr_query { 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); 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/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_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/bench_net4.c b/filter/tests/bench_net4.c index 1533a5902..b3c74758c 100644 --- a/filter/tests/bench_net4.c +++ b/filter/tests/bench_net4.c @@ -56,9 +56,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..1a0877288 100644 --- a/filter/tests/bench_net4_fast.c +++ b/filter/tests/bench_net4_fast.c @@ -57,9 +57,11 @@ 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_proto_compile, net4_fast_dst, port_dst, proto + bench_dst_port_proto_compile, net4_fast_dst, port_dst, proto_range +); +FILTER_QUERY_DECLARE( + bench_dst_port_proto, net4_fast_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_fast_dst, port_dst, proto); //////////////////////////////////////////////////////////////////////////////// // Configuration and types diff --git a/filter/tests/bench_net6.c b/filter/tests/bench_net6.c index e1d59ae84..af2feb036 100644 --- a/filter/tests/bench_net6.c +++ b/filter/tests/bench_net6.c @@ -57,9 +57,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..39b40dd25 100644 --- a/filter/tests/bench_net6_fast.c +++ b/filter/tests/bench_net6_fast.c @@ -58,9 +58,11 @@ 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_proto_compile, net6_fast_dst, port_dst, proto + bench_dst_port_proto_compile, net6_fast_dst, port_dst, proto_range +); +FILTER_QUERY_DECLARE( + bench_dst_port_proto, net6_fast_dst, port_dst, proto_range ); -FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_fast_dst, port_dst, proto); //////////////////////////////////////////////////////////////////////////////// // Configuration and types diff --git a/filter/tests/combo_net4_port_proto_dst.c b/filter/tests/combo_net4_port_proto_dst.c index 6e2200f50..e5e618e72 100644 --- a/filter/tests/combo_net4_port_proto_dst.c +++ b/filter/tests/combo_net4_port_proto_dst.c @@ -24,10 +24,13 @@ //////////////////////////////////////////////////////////////////////////////// FILTER_COMPILER_DECLARE( - combo_net4_port_proto_dst_compile, net4_fast_dst, port_fast_dst, proto + combo_net4_port_proto_dst_compile, + net4_fast_dst, + port_fast_dst, + proto_range ); FILTER_QUERY_DECLARE( - combo_net4_port_proto_dst, net4_fast_dst, port_fast_dst, proto + combo_net4_port_proto_dst, net4_fast_dst, port_fast_dst, proto_range ); //////////////////////////////////////////////////////////////////////////////// @@ -330,7 +333,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 +346,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/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/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/shm/compiler.c b/filter/tests/shm/compiler.c index d3c03b1b3..a86edd067 100644 --- a/filter/tests/shm/compiler.c +++ b/filter/tests/shm/compiler.c @@ -16,7 +16,7 @@ #include -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) { From c4fbf648eea9bb3036d0349f90d0d49568a1c1f2 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 21:24:54 +0300 Subject: [PATCH 04/17] Normalize `net4` network while attribute building --- filter/compiler/net4.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/filter/compiler/net4.c b/filter/compiler/net4.c index 3ec9fdf61..5c107091e 100644 --- a/filter/compiler/net4.c +++ b/filter/compiler/net4.c @@ -29,6 +29,14 @@ action_get_net4_dst( *count = action->net4.dst_count; } +static inline void +net4_normalize(struct net4 *src, struct net4 *dst) { + memcpy(dst->addr, src->addr, 4); + memcpy(dst->mask, src->mask, 4); + for (uint8_t idx = 0; idx < 4; ++idx) + dst->addr[idx] &= src->mask[idx]; +} + static inline int net4_collect_values( struct net4 *start, @@ -42,12 +50,14 @@ net4_collect_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; + struct net4 normalized; + net4_normalize(net4, &normalized); + uint32_t to = *(uint32_t *)normalized.addr | + ~*(uint32_t *)normalized.mask; filter_key_inc(4, (uint8_t *)&to); uint32_t start = - radix_lookup(&range_index->radix, 4, net4->addr); + radix_lookup(&range_index->radix, 4, normalized.addr); uint32_t stop = range_index->count; if (to != 0) stop = radix_lookup( @@ -74,8 +84,10 @@ net4_collect_registry( 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; + struct net4 normalized; + net4_normalize(net4, &normalized); + uint32_t addr = *(uint32_t *)normalized.addr; + uint32_t mask = *(uint32_t *)normalized.mask; uint32_t to = addr | ~mask; lpm4_collect_values( lpm, @@ -118,10 +130,13 @@ collect_net4_values( for (struct net4 *net4 = nets; net4 < nets + net_count; ++net4) { + struct net4 normalized; + net4_normalize(net4, &normalized); if (range4_collector_add( &collector, - net4->addr, - __builtin_popcountll(*(uint32_t *)net4->mask + normalized.addr, + __builtin_popcountll( + *(uint32_t *)normalized.mask ) )) goto error_collector; From ee2cf9920590d39c7b27558a8622e8d4aa8fba06 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 21:25:43 +0300 Subject: [PATCH 05/17] Blacklist `*_fast` attributes The attributes use b-tree internal structure what is x86-specific implemented. Also b-tree lookup is slower that direct table lookups. --- filter/compiler/attribute.h | 7 -- filter/query/attribute.h | 11 -- filter/tests/basic_net4_fast.c | 118 ++++-------------- filter/tests/basic_net6_fast.c | 118 ++++-------------- filter/tests/basic_port_fast.c | 74 +++++------ filter/tests/basic_proto_range_fast.c | 44 ++----- filter/tests/bench_net4_fast.c | 20 ++- filter/tests/bench_net6_fast.c | 20 ++- filter/tests/combo_net4_port_proto_dst.c | 7 +- filter/tests/combo_net4_port_src.c | 6 +- filter/tests/combo_net6_port_src.c | 6 +- modules/balancer/controlplane/handler/rules.c | 8 +- modules/balancer/controlplane/handler/vs.c | 4 +- modules/balancer/dataplane/lookup.h | 12 +- 14 files changed, 125 insertions(+), 330 deletions(-) diff --git a/filter/compiler/attribute.h b/filter/compiler/attribute.h index c93be402e..334f2b4ec 100644 --- a/filter/compiler/attribute.h +++ b/filter/compiler/attribute.h @@ -21,19 +21,12 @@ REGISTER_ATTRIBUTE(port_src); REGISTER_ATTRIBUTE(port_dst); -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/attribute.h b/filter/query/attribute.h index 0ecd8a455..4b03ee9e0 100644 --- a/filter/query/attribute.h +++ b/filter/query/attribute.h @@ -3,13 +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_range.h" -#include "proto_range_fast.h" #include "vlan.h" typedef void (*filter_attr_query_func)( @@ -30,19 +26,12 @@ struct filter_attr_query { REGISTER_ATTRIBUTE(port_src); REGISTER_ATTRIBUTE(port_dst); -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/tests/basic_net4_fast.c b/filter/tests/basic_net4_fast.c index 69605d11b..d149e1ba8 100644 --- a/filter/tests/basic_net4_fast.c +++ b/filter/tests/basic_net4_fast.c @@ -24,16 +24,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 +65,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 +201,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 +382,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 +494,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 +503,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 +512,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 +682,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 +795,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 +901,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 +1014,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 +1128,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_fast.c b/filter/tests/basic_net6_fast.c index 65d612241..7d19b2955 100644 --- a/filter/tests/basic_net6_fast.c +++ b/filter/tests/basic_net6_fast.c @@ -24,16 +24,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 +65,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 +218,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 +515,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 +637,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 +646,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 +655,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 +843,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 +1058,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 +1225,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 +1361,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 +1538,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..ccb67b630 100644 --- a/filter/tests/basic_port_fast.c +++ b/filter/tests/basic_port_fast.c @@ -23,16 +23,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 +64,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 +201,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 +209,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 +341,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 +443,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 +452,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 +461,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 +672,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 +680,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 +801,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 +809,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 +923,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 +931,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 +1057,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 +1065,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 +1186,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 +1194,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 +1319,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 +1327,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_proto_range_fast.c b/filter/tests/basic_proto_range_fast.c index 9dca29882..e80f1052a 100644 --- a/filter/tests/basic_proto_range_fast.c +++ b/filter/tests/basic_proto_range_fast.c @@ -11,8 +11,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 +25,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 +39,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 +83,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 +93,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 +142,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 +155,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 +191,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 +201,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 +238,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 +251,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/bench_net4_fast.c b/filter/tests/bench_net4_fast.c index 1a0877288..ce5b457b5 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. * @@ -50,18 +50,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_range -); -FILTER_QUERY_DECLARE( - bench_dst_port_proto, net4_fast_dst, port_dst, proto_range + bench_dst_port_proto_compile, net4_dst, port_dst, proto_range ); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net4_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types @@ -420,7 +418,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_fast.c b/filter/tests/bench_net6_fast.c index 39b40dd25..a5d52e565 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. * @@ -51,18 +51,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_range -); -FILTER_QUERY_DECLARE( - bench_dst_port_proto, net6_fast_dst, port_dst, proto_range + bench_dst_port_proto_compile, net6_dst, port_dst, proto_range ); +FILTER_QUERY_DECLARE(bench_dst_port_proto, net6_dst, port_dst, proto_range); //////////////////////////////////////////////////////////////////////////////// // Configuration and types @@ -454,7 +452,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 e5e618e72..1b9c64fa3 100644 --- a/filter/tests/combo_net4_port_proto_dst.c +++ b/filter/tests/combo_net4_port_proto_dst.c @@ -24,13 +24,10 @@ //////////////////////////////////////////////////////////////////////////////// FILTER_COMPILER_DECLARE( - combo_net4_port_proto_dst_compile, - net4_fast_dst, - port_fast_dst, - proto_range + 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_range + combo_net4_port_proto_dst, net4_dst, port_dst, proto_range ); //////////////////////////////////////////////////////////////////////////////// diff --git a/filter/tests/combo_net4_port_src.c b/filter/tests/combo_net4_port_src.c index b1a7122f9..9d3a22841 100644 --- a/filter/tests/combo_net4_port_src.c +++ b/filter/tests/combo_net4_port_src.c @@ -22,10 +22,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..98304920a 100644 --- a/filter/tests/combo_net6_port_src.c +++ b/filter/tests/combo_net6_port_src.c @@ -23,10 +23,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/modules/balancer/controlplane/handler/rules.c b/modules/balancer/controlplane/handler/rules.c index 0ee8dfe09..b036d0d3c 100644 --- a/modules/balancer/controlplane/handler/rules.c +++ b/modules/balancer/controlplane/handler/rules.c @@ -12,12 +12,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..223a164a4 100644 --- a/modules/balancer/controlplane/handler/vs.c +++ b/modules/balancer/controlplane/handler/vs.c @@ -430,8 +430,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) { From b58196c212d33544f2112e3b4be719eb4361c5c0 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 22:16:47 +0300 Subject: [PATCH 06/17] `filter` compilation attribute virtual table This is a preparation commit introducing an attribute compilation primitives. The commit introduces a some sort of polymorphism required to get rid of filter library hard-coded filter rule format and packet handling. --- filter/compiler/declare.h | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/filter/compiler/declare.h b/filter/compiler/declare.h index 9316bbb56..cae2bc1ab 100644 --- a/filter/compiler/declare.h +++ b/filter/compiler/declare.h @@ -21,3 +21,138 @@ (struct filter_lookup_handler[] \ ){FOR_EACH(FILTER_ATTR_LOOKUP_HANDLER, __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; +}; From ae46713aea3a9c957b9ab9e0490672ddedb55b37 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 22:35:24 +0300 Subject: [PATCH 07/17] Build a compile attribute using virtual table --- filter/compiler/declare.h | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/filter/compiler/declare.h b/filter/compiler/declare.h index cae2bc1ab..f656c3bfe 100644 --- a/filter/compiler/declare.h +++ b/filter/compiler/declare.h @@ -1,5 +1,8 @@ #pragma once +#include "common/registry.h" +#include "common/remap.h" + #include "common/for_each.h" #define FILTER_ATTR_COMPILER(name) name##_attr_compiler @@ -156,3 +159,154 @@ struct filter_compile_attr_handlers { 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); +} + +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; +} + +/* + * 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; + } + + 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; +} From 537b1b558da125b7f6196f94b51d04ccfdf9cca2 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 23:03:25 +0300 Subject: [PATCH 08/17] Refactoring port attribute to a new one logic --- filter/classifiers/port.h | 23 +++ filter/compiler/declare.h | 2 +- filter/compiler/port.c | 389 ++++++++++++++++++++++++-------------- filter/filter.h | 2 + 4 files changed, 268 insertions(+), 148 deletions(-) create mode 100644 filter/classifiers/port.h 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/compiler/declare.h b/filter/compiler/declare.h index f656c3bfe..af1559b8d 100644 --- a/filter/compiler/declare.h +++ b/filter/compiler/declare.h @@ -61,7 +61,7 @@ struct filter_rule; * * The structure used to store attribute specific temporaray compilation data. */ -struct filter_compile_attr; +struct filter_compile_attr {}; /* * Compilation attribute virtual table forward declaration. * diff --git a/filter/compiler/port.c b/filter/compiler/port.c index 55410af01..858c04525 100644 --- a/filter/compiler/port.c +++ b/filter/compiler/port.c @@ -1,3 +1,4 @@ +#include "filter/classifiers/port.h" #include "common/memory.h" #include "common/registry.h" #include "common/value.h" @@ -6,157 +7,263 @@ #include -typedef void (*action_get_port_range_func)( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count +typedef void (*filter_rule_get_port_ranges_func)( + const struct filter_rule *filter_rule, + struct filter_port_ranges *port_ranges ); -static int -collect_port_values( +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_rule **actions, - uint32_t count, - action_get_port_range_func get_port_range, - struct value_table *table, - struct value_registry *registry + const struct filter_compile_attr_handlers *handlers, + const struct filter_rule **rules, + uint32_t rule_count ) { - if (value_table_init(table, memory_context, 1, 65536)) - return -1; + (void)handlers; + (void)rules; + (void)rule_count; - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, 65536)) { - goto error_remap_table; + 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; } - 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; - } - } - } + 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; } - 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; - } - } - } + 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); - // 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; - } + 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; +} -error_touch: - remap_table_free(&remap_table); +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); -error_collect: -error_remap_table: - value_table_free(table); - return -1; + 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 void -get_port_range_src( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count +static inline struct filter_query_attr * +filter_compile_attr_port_commit( + struct memory_context *memory_context, struct filter_compile_attr *attr ) { - *ranges = action->transport.srcs; - *count = action->transport.src_count; + 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 void -get_port_range_dst( - const struct filter_rule *action, - struct filter_port_range **ranges, - uint32_t *count +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 ) { - *ranges = action->transport.dsts; - *count = action->transport.dst_count; + 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_ranges_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_ranges_dst = { + .attr_handlers = filter_compile_attr_port_handlers, + .get_port_ranges = filter_rule_get_port_ranges_dst, +}; 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 +271,39 @@ 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/filter.h b/filter/filter.h index b24fdc55d..60e527477 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -34,6 +34,8 @@ #define FILTER_RULE_INVALID (uint32_t)0xffffffff +struct filter_query_attr {}; + /** * @def MAX_ATTRIBUTES * @brief Upper bound on attribute count in a filter signature. From 615193f53255631668cbbfc308537b74350435cd Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 23:21:21 +0300 Subject: [PATCH 09/17] Refactoring proto range attribute to a new one logic --- filter/classifiers/proto_range.h | 26 ++- filter/compiler/port.c | 6 +- filter/compiler/proto_range.c | 329 +++++++++++++++++++++---------- filter/query/proto_range.h | 6 +- 4 files changed, 253 insertions(+), 114 deletions(-) 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/compiler/port.c b/filter/compiler/port.c index 858c04525..2c5481989 100644 --- a/filter/compiler/port.c +++ b/filter/compiler/port.c @@ -290,7 +290,8 @@ void FILTER_ATTR_COMPILER_FREE_FUNC(port_src)( void *data, struct memory_context *memory_context ) { - struct filter_query_attr_port *attr = (struct filter_query_attr_port *)data; + struct filter_query_attr_port *attr = + (struct filter_query_attr_port *)data; if (attr == NULL) return; @@ -301,7 +302,8 @@ void FILTER_ATTR_COMPILER_FREE_FUNC(port_dst)( void *data, struct memory_context *memory_context ) { - struct filter_query_attr_port *attr = (struct filter_query_attr_port *)data; + struct filter_query_attr_port *attr = + (struct filter_query_attr_port *)data; if (attr == NULL) return; diff --git a/filter/compiler/proto_range.c b/filter/compiler/proto_range.c index 1f6734f98..4a90ac8e3 100644 --- a/filter/compiler/proto_range.c +++ b/filter/compiler/proto_range.c @@ -7,109 +7,235 @@ #include -//////////////////////////////////////////////////////////////////////////////// +typedef void (*filter_rule_get_proto_ranges_func)( + const struct filter_rule *filter_rule, + struct filter_proto_ranges *proto_ranges +); -#define PROTO_RANGE_CLASSIFIER_MAX_VALUE ((1 << 16)) +struct filter_compile_attr_proto { + struct filter_compile_attr attr; + struct filter_query_attr_proto_range *query_attr; +}; -static int -collect_proto_values( +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 count, - struct value_table *table, - struct value_registry *registry + 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( - 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 + &attr->query_attr->value_table, memory_context, 1, 65536 )) { - goto error_remap_table; + goto error_free_attr; } - 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; - } - } - } - } + 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; +} - 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; - - 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; - } +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) + ); +} -error_touch: - remap_table_free(&remap_table); +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; -error_collect: -error_remap_table: + filter_compile_attr_proto_free(memory_context, attr); - value_table_free(table); - return -1; + 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_ranges = { + .attr_handlers = filter_compile_attr_proto_handlers, + .get_proto_ranges = filter_rule_get_proto_ranges, +}; int FILTER_ATTR_COMPILER_INIT_FUNC(proto_range)( @@ -117,36 +243,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 filter_compile_attr_build( + &filter_compile_attr_proto_ranges.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context - return 0; + ); } 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/query/proto_range.h b/filter/query/proto_range.h index 391677502..e05f1864c 100644 --- a/filter/query/proto_range.h +++ b/filter/query/proto_range.h @@ -13,8 +13,8 @@ static inline void FILTER_ATTR_QUERY_FUNC(proto_range)( void *data, struct packet **packets, uint32_t *result, uint32_t count ) { - struct proto_range_classifier *c = - (struct proto_range_classifier *)data; + struct filter_query_attr_proto_range *c = + (struct filter_query_attr_proto_range *)data; for (uint32_t idx = 0; idx < count; ++idx) { struct packet *packet = packets[idx]; @@ -48,6 +48,6 @@ FILTER_ATTR_QUERY_FUNC(proto_range)( proto += icmp_header->icmp_type; } - result[idx] = value_table_get(&c->table, 0, proto); + result[idx] = value_table_get(&c->value_table, 0, proto); } } From 23832cba84b59358522d13541fe373d15dfafbf3 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sun, 3 May 2026 23:34:17 +0300 Subject: [PATCH 10/17] Refactoring vlan attribute to a new one logic --- filter/classifiers/vlan.h | 23 +++ filter/compiler/vlan.c | 317 ++++++++++++++++++++++++++++---------- filter/query/vlan.h | 5 +- 3 files changed, 259 insertions(+), 86 deletions(-) create mode 100644 filter/classifiers/vlan.h 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/vlan.c b/filter/compiler/vlan.c index 339147899..43eb2d085 100644 --- a/filter/compiler/vlan.c +++ b/filter/compiler/vlan.c @@ -1,3 +1,4 @@ +#include "filter/classifiers/vlan.h" #include "common/memory.h" #include "common/registry.h" #include "common/value.h" @@ -6,112 +7,260 @@ #include -int -FILTER_ATTR_COMPILER_INIT_FUNC(vlan)( - struct value_registry *registry, - void **data, +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, - size_t rule_count, - struct memory_context *memory_context + uint32_t rule_count ) { - struct value_table *t = - memory_balloc(memory_context, sizeof(struct value_table)); - if (t == NULL) { - return -1; - } + (void)handlers; + (void)rules; + (void)rule_count; - if (value_table_init(t, memory_context, 1, 4096)) { - goto error_init; + 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; } - SET_OFFSET_OF(data, t); - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, 4096)) { - goto error_remap_table; + 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; } - 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; + return &attr->attr; - 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; - } - } - } - } +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_vlan) + ); - 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; - } +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; +} -error_touch: - remap_table_free(&remap_table); +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); -error_collect: -error_remap_table: - value_table_free(t); - SET_OFFSET_OF(data, NULL); + if (vlan_ranges_attr->query_attr != NULL) { + value_table_free(&vlan_ranges_attr->query_attr->value_table); -error_init: - memory_bfree(memory_context, t, sizeof(struct 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; - return -1; + 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_ranges = { + .attr_handlers = filter_compile_attr_vlan_handlers, + .get_vlan_ranges = filter_rule_get_vlan_ranges, +}; + +int +FILTER_ATTR_COMPILER_INIT_FUNC(vlan)( + struct value_registry *registry, + void **data, + const struct filter_rule **rules, + size_t rule_count, + struct memory_context *memory_context +) { + 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/query/vlan.h b/filter/query/vlan.h index 5e22479e1..7cbef861d 100644 --- a/filter/query/vlan.h +++ b/filter/query/vlan.h @@ -10,10 +10,11 @@ static inline void FILTER_ATTR_QUERY_FUNC(vlan)( void *data, struct packet **packets, uint32_t *result, uint32_t count ) { - struct value_table *t = (struct value_table *)data; + struct filter_query_attr_proto_range *c = + (struct filter_query_attr_proto_range *)data; for (uint32_t idx = 0; idx < count; ++idx) { uint16_t vlan = packets[idx]->vlan; - result[idx] = value_table_get(t, 0, vlan); + result[idx] = value_table_get(&c->value_table, 0, vlan); } } From 929476a6d4ade68b8f725ac1b0b8793ed35f4435 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 11:34:02 +0300 Subject: [PATCH 11/17] Refactoring net4 attribute to a new one logic --- filter/classifiers/net4.h | 24 ++ filter/compiler/net4.c | 510 ++++++++++++++++++++++---------------- 2 files changed, 325 insertions(+), 209 deletions(-) create mode 100644 filter/classifiers/net4.h 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/compiler/net4.c b/filter/compiler/net4.c index 5c107091e..8a265986a 100644 --- a/filter/compiler/net4.c +++ b/filter/compiler/net4.c @@ -1,3 +1,4 @@ +#include "filter/classifiers/net4.h" #include "../rule.h" #include "common/lpm.h" #include "common/range_collector.h" @@ -7,295 +8,386 @@ #include "declare.h" #include "helper.h" -//////////////////////////////////////////////////////////////////////////////// - -typedef void (*rule_get_net4_func)( - const struct filter_rule *rule, struct net4 **net, uint32_t *count +typedef void (*filter_rule_get_net4s_func)( + const struct filter_rule *filter_rule, struct filter_net4s *net ); -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; -} +struct filter_compile_net_attr { + struct filter_compile_attr attr; + struct filter_query_attr_net4 *query_attr; -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; -} + struct range_index range_index; + struct value_table value_table; +}; -static inline void -net4_normalize(struct net4 *src, struct net4 *dst) { - memcpy(dst->addr, src->addr, 4); - memcpy(dst->mask, src->mask, 4); - for (uint8_t idx = 0; idx < 4; ++idx) - dst->addr[idx] &= src->mask[idx]; -} +struct filter_compile_attr_net4_handlers { + struct filter_compile_attr_handlers attr_handlers; + filter_rule_get_net4s_func get_net4s; +}; -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 +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 ) { - uint32_t *values = ADDR_OF(&range_index->values); - - for (struct net4 *net4 = start; net4 < start + count; ++net4) { - if (*(uint32_t *)net4->mask == 0x00000000) - continue; - struct net4 normalized; - net4_normalize(net4, &normalized); - uint32_t to = *(uint32_t *)normalized.addr | - ~*(uint32_t *)normalized.mask; - filter_key_inc(4, (uint8_t *)&to); - - uint32_t start = - radix_lookup(&range_index->radix, 4, normalized.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; -} + struct filter_compile_attr_net4_handlers *net_handlers = container_of( + attr_handlers, + struct filter_compile_attr_net4_handlers, + attr_handlers + ); -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) { - struct net4 normalized; - net4_normalize(net4, &normalized); - uint32_t addr = *(uint32_t *)normalized.addr; - uint32_t mask = *(uint32_t *)normalized.mask; - uint32_t to = addr | ~mask; - lpm4_collect_values( - lpm, - (uint8_t *)&addr, - (uint8_t *)&to, - lpm_collect_registry_iterator, - registry - ); + struct filter_compile_net_attr *attr = memory_balloc( + memory_context, sizeof(struct filter_compile_net_attr) + ); + if (attr == NULL) { + return NULL; } -} -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; + goto error_free; - if (action->net4.src_count == 0 && - action->net4.dst_count == 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 net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); + struct filter_net4s nets; + net_handlers->get_net4s(rule, &nets); + const struct filter_net4s *net = &nets; - for (struct net4 *net4 = nets; net4 < nets + net_count; + for (struct net4 *net4 = net->items; + net4 < net->items + net->count; ++net4) { - struct net4 normalized; - net4_normalize(net4, &normalized); + 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, - normalized.addr, - __builtin_popcountll( - *(uint32_t *)normalized.mask + from, + __builtin_popcountll(*(uint32_t *)net4->mask ) - )) + )) { goto error_collector; + } } } - if (lpm_init(lpm, memory_context)) { + + if (range_index_init(&attr->range_index, memory_context)) { goto error_collector; } - struct range_index range_index; - if (range_index_init(&range_index, memory_context)) { - goto error_lpm; + + 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, lpm, &range_index)) { - goto error_range_collect; + if (range_collector_collect( + &collector, 4, &attr->query_attr->lpm, &attr->range_index + )) { + goto error_collect; } - struct value_table table; - if (value_table_init(&table, memory_context, 1, collector.count)) - goto error_table; + if (value_table_init( + &attr->value_table, memory_context, 1, collector.count + )) { + goto error_collect; + } - struct remap_table remap_table; - if (remap_table_init(&remap_table, memory_context, collector.count)) - goto error_remap; + range_collector_free(&collector, 4); - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { + return &attr->attr; - remap_table_new_gen(&remap_table); +error_collect: + lpm_free(&attr->query_attr->lpm); - if (*action_ptr == NULL) - continue; +error_query: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_net4) + ); - const struct filter_rule *action = *action_ptr; +error_range_index: + range_index_free(&attr->range_index); + +error_collector: + range_collector_free(&collector, 4); - struct net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); +error_free: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net_attr) + ); - if (net4_collect_values( - nets, net_count, &range_index, &table, &remap_table - )) { - goto error_net_collect; + 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; + } } } - 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); + return 0; +} - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; +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 net4 *nets; - uint32_t net_count; - get_net4(action, &nets, &net_count); + struct filter_compile_net_attr *net_attr = + container_of(attr, struct filter_compile_net_attr, attr); - net4_collect_registry(nets, net_count, lpm, registry); + 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; + } } - 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); +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) + ); + } -error_remap: - value_table_free(&table); + range_index_free(&net_attr->range_index); + value_table_free(&net_attr->value_table); -error_table: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net_attr) + ); +} -error_range_collect: - range_index_free(&range_index); +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); -error_lpm: - lpm_free(lpm); + struct filter_query_attr_net4 *query_attr = net_attr->query_attr; -error_collector: - range_collector_free(&collector, 4); + struct lpm *lpm = &query_attr->lpm; -error: - return -1; + 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, +}; -// 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); } From e5c569d5cd87cc1dd973e7a6ea4c85d6ea19a763 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 12:08:23 +0300 Subject: [PATCH 12/17] Refactoring net6 attribute to a new one logic --- filter/classifiers/net6.h | 22 +- filter/compiler/net6.c | 614 ++++++++++++++++++-------------------- filter/query/net6.h | 6 +- 3 files changed, 315 insertions(+), 327 deletions(-) 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/compiler/net6.c b/filter/compiler/net6.c index ffb6e8940..1c6f61df7 100644 --- a/filter/compiler/net6.c +++ b/filter/compiler/net6.c @@ -2,36 +2,28 @@ #include "common/lpm.h" #include "common/range_collector.h" - #include "common/registry.h" -#include "../classifiers/net6.h" +#include "filter/classifiers/net6.h" #include "declare.h" -//////////////////////////////////////////////////////////////////////////////// - -typedef void (*action_get_net6_func)( - const struct filter_rule *rule, struct net6 **net, uint32_t *count +typedef void (*filter_rule_get_net6s_func)( + const struct filter_rule *filter_rule, struct filter_net6s *net6s ); -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; -} +struct filter_compile_net6s_attr { + struct filter_compile_attr attr; + struct filter_query_attr_net6 *query_attr; -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; -} + 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 @@ -49,10 +41,8 @@ net6_get_lo_part(struct net6 *net, uint8_t **addr, uint8_t **mask) { *mask = net->mask + 8; } -//////////////////////////////////////////////////////////////////////////////// - static inline void -net6_normalize(struct net6 *src, struct net6 *dst) { +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) @@ -60,11 +50,11 @@ net6_normalize(struct net6 *src, struct net6 *dst) { } static inline int -collect_net6_range( +create_net6_range( struct memory_context *memory_context, - const struct filter_rule **actions, - uint32_t count, - action_get_net6_func get_net6, + 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 @@ -73,20 +63,20 @@ collect_net6_range( if (range_collector_init(&collector, memory_context)) goto error; - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { + for (uint32_t rule_idx = 0; rule_idx < rule_count; ++rule_idx) { + const struct filter_rule *rule = rules[rule_idx]; - if (*action_ptr == NULL) + if (rule == NULL) continue; - const struct filter_rule *action = *action_ptr; - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); + struct filter_net6s net6s; + get_net6(rule, &net6s); + const struct filter_net6s *nets = &net6s; - for (struct net6 *rule_net = nets; rule_net < nets + net_count; + for (struct net6 *rule_net = nets->items; + rule_net < nets->items + nets->count; ++rule_net) { + struct net6 net6; net6_normalize(rule_net, &net6); @@ -127,231 +117,218 @@ collect_net6_range( return -1; } -static inline int -merge_net6_range( +static inline struct filter_compile_attr * +filter_compile_attr_net6s_create( 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 + const struct filter_compile_attr_handlers *attr_handlers, + const struct filter_rule **rules, + uint32_t rule_count ) { - if (value_table_init( - table, - memory_context, - ri_hi->max_value + 1, - ri_lo->max_value + 1 - )) { - return -1; + 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; } - 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; - } + 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; - uint32_t net_cnt = 0; + create_net6_range( + memory_context, + rules, + rule_count, + net6s_handlers->get_net6s, + net6_get_hi_part, + &attr->query_attr->hi, + &attr->ri_hi + ); - struct radix rdx; - radix_init(&rdx, memory_context); + create_net6_range( + memory_context, + rules, + rule_count, + net6s_handlers->get_net6s, + net6_get_lo_part, + &attr->query_attr->lo, + &attr->ri_lo + ); - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { + value_table_init( + &attr->query_attr->comb, + memory_context, + attr->ri_hi.max_value + 1, + attr->ri_lo.max_value + 1 + ); - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; + return &attr->attr; - remap_table_new_gen(&remap_table); +error_query: + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net6s_attr) + ); - uint32_t *values_hi = ADDR_OF(&ri_hi->values); - uint32_t *values_lo = ADDR_OF(&ri_lo->values); + return NULL; +} - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); +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); - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); + return net6s_attr->query_attr->comb.h_dim * + net6s_attr->query_attr->comb.v_dim; +} - 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; - } - } - } +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; } } } - remap_table_free(&remap_table); - uint32_t *values_hi = ADDR_OF(&ri_hi->values); - uint32_t *values_lo = ADDR_OF(&ri_lo->values); + return 0; +} - struct value_registry net_registry; - value_registry_init(&net_registry, memory_context); +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 +) { - for (const struct filter_rule **action_ptr = actions; - action_ptr < actions + count; - ++action_ptr) { + struct filter_compile_attr_net6s_handlers *net6s_handlers = + container_of( + attr_handlers, + struct filter_compile_attr_net6s_handlers, + attr_handlers + ); - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; + (void)attr; - struct net6 *nets; - uint32_t net_count; - get_net6(action, &nets, &net_count); + struct filter_net6s nets; + net6s_handlers->get_net6s(rule, &nets); - for (struct net6 *rule_net = nets; rule_net < nets + net_count; - ++rule_net) { - struct net6 net6; - net6_normalize(rule_net, &net6); + if (nets.count == 0) + return 1; - 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; + struct net6 net6_normalized; + net6_normalize(nets.items + 0, &net6_normalized); - if (*action_ptr == NULL) - continue; - const struct filter_rule *action = *action_ptr; + return *(uint64_t *)(net6_normalized.mask + 0) == 0 && + *(uint64_t *)(net6_normalized.mask + 8) == 0; +} - 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); +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; + } - uint32_t net_idx = radix_lookup(&rdx, 32, net6.addr); + 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; + } - 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] + 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; } @@ -359,115 +336,104 @@ merge_net6_range( } } - 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 +static inline void +filter_compile_attr_net6s_free( + struct memory_context *memory_context, struct filter_compile_attr *attr ) { - 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 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) + ); } - 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; - } + memory_bfree( + memory_context, attr, sizeof(struct filter_compile_net6s_attr) + ); +} - if (merge_net6_range( - memory_context, - actions, - count, - get_net6, - &ri_hi, - &ri_lo, - &net6->comb, - registry - )) { - goto error_merge; - } +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); - range_index_free(&ri_hi); - range_index_free(&ri_lo); + struct filter_query_attr_net6 *query_attr = net6s_attr->query_attr; + net6s_attr->query_attr = NULL; - return 0; + filter_compile_attr_net6s_free(memory_context, attr); -error_merge: - range_index_free(&ri_lo); - lpm_free(&net6->lo); + return &query_attr->attr; +} -error_lo: - range_index_free(&ri_hi); - lpm_free(&net6->hi); +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, +}; -error_hi: - memory_bfree(memory_context, net6, sizeof(struct net6_classifier)); +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; +} - return -1; +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, +}; + // 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 +443,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 +466,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/query/net6.h b/filter/query/net6.h index bf3e2c466..e1ec5f242 100644 --- a/filter/query/net6.h +++ b/filter/query/net6.h @@ -14,7 +14,8 @@ static inline void FILTER_ATTR_QUERY_FUNC(net6_dst)( void *data, struct packet **packets, uint32_t *result, uint32_t count ) { - struct net6_classifier *c = (struct net6_classifier *)data; + struct filter_query_attr_net6 *c = + (struct filter_query_attr_net6 *)data; for (uint32_t idx = 0; idx < count; ++idx) { struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); @@ -39,7 +40,8 @@ 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; + struct filter_query_attr_net6 *c = + (struct filter_query_attr_net6 *)data; for (uint32_t idx = 0; idx < count; ++idx) { struct rte_mbuf *mbuf = packet_to_mbuf(packets[idx]); From 2844496a63a60cd7626c6c28583c7e24fb557fdf Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 12:41:51 +0300 Subject: [PATCH 13/17] Refactoring device attribute to a new one logic --- filter/classifiers/device.h | 27 +++ filter/compiler/device.c | 335 ++++++++++++++++++++++++++---------- 2 files changed, 274 insertions(+), 88 deletions(-) create mode 100644 filter/classifiers/device.h 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/compiler/device.c b/filter/compiler/device.c index a7903565b..cb86bf1c6 100644 --- a/filter/compiler/device.c +++ b/filter/compiler/device.c @@ -1,3 +1,4 @@ +#include "common/container_of.h" #include "common/memory.h" #include "common/registry.h" #include "common/value.h" @@ -5,125 +6,283 @@ #include "declare.h" #include "filter/rule.h" +#include "filter/classifiers/device.h" + #include -int -FILTER_ATTR_COMPILER_INIT_FUNC(device)( - struct value_registry *registry, - void **data, +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, - size_t rule_count, - struct memory_context *memory_context + uint32_t rule_count ) { - 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) + 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; - 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 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; } } } - struct value_table *t = - memory_balloc(memory_context, sizeof(struct value_table)); - if (t == NULL) { - return -1; + if (value_table_init( + &attr->query_attr->value_table, + memory_context, + 1, + max_device_id + 1 + )) { + goto error_free_attr; } - 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; - } + return &attr->attr; - 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; +error_free_attr: + memory_bfree( + memory_context, + attr->query_attr, + sizeof(struct filter_query_attr_device) + ); - 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; - } +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; } } - remap_table_compact(&remap_table); - value_table_compact(t, &remap_table); - remap_table_free(&remap_table); + return 0; +} - for (const struct filter_rule **r_ptr = rules; - r_ptr < rules + rule_count; - ++r_ptr) { - value_registry_start(registry); +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 + ); - 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; - } - } + (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) + ); +} -error_touch: - remap_table_free(&remap_table); +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; +} -error_collect: -error_remap_table: - value_table_free(t); - SET_OFFSET_OF(data, NULL); +static const struct filter_compile_attr_device_handlers + filter_compile_attr_device = { + .attr_handlers = filter_compile_get_devices, + .get_devices = filter_rule_get_devices, +}; -error_init: - memory_bfree(memory_context, t, sizeof(struct value_table)); +int +FILTER_ATTR_COMPILER_INIT_FUNC(device)( + struct value_registry *registry, + void **data, + const struct filter_rule **rules, + size_t rule_count, + struct memory_context *memory_context +) { + return filter_compile_attr_build( + &filter_compile_attr_device.attr_handlers, + registry, + data, + rules, + rule_count, + memory_context - return -1; + ); } 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); } From 149b347efff42f68087fd780f379b487c8a80188 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 14:40:46 +0300 Subject: [PATCH 14/17] Move attribute declarations to header files --- filter/compiler/device.c | 256 +-------------------- filter/compiler/device.h | 259 +++++++++++++++++++++ filter/compiler/net4.c | 330 +-------------------------- filter/compiler/net4.h | 331 +++++++++++++++++++++++++++ filter/compiler/net6.c | 417 +-------------------------------- filter/compiler/net6.h | 418 ++++++++++++++++++++++++++++++++++ filter/compiler/port.c | 250 +------------------- filter/compiler/port.h | 251 ++++++++++++++++++++ filter/compiler/proto_range.c | 239 +------------------ filter/compiler/proto_range.h | 238 +++++++++++++++++++ filter/compiler/vlan.c | 236 +------------------ filter/compiler/vlan.h | 237 +++++++++++++++++++ 12 files changed, 1743 insertions(+), 1719 deletions(-) create mode 100644 filter/compiler/device.h create mode 100644 filter/compiler/net4.h create mode 100644 filter/compiler/net6.h create mode 100644 filter/compiler/port.h create mode 100644 filter/compiler/proto_range.h create mode 100644 filter/compiler/vlan.h diff --git a/filter/compiler/device.c b/filter/compiler/device.c index cb86bf1c6..977b4aab0 100644 --- a/filter/compiler/device.c +++ b/filter/compiler/device.c @@ -1,260 +1,6 @@ -#include "common/container_of.h" -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" +#include "device.h" #include "declare.h" -#include "filter/rule.h" - -#include "filter/classifiers/device.h" - -#include - -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, -}; int FILTER_ATTR_COMPILER_INIT_FUNC(device)( 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/net4.c b/filter/compiler/net4.c index 8a265986a..99b6ef7f7 100644 --- a/filter/compiler/net4.c +++ b/filter/compiler/net4.c @@ -1,334 +1,6 @@ -#include "filter/classifiers/net4.h" -#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 (*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, -}; int FILTER_ATTR_COMPILER_INIT_FUNC(net4_src)( 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 1c6f61df7..efe9e0754 100644 --- a/filter/compiler/net6.c +++ b/filter/compiler/net6.c @@ -1,422 +1,7 @@ -#include "../rule.h" - -#include "common/lpm.h" -#include "common/range_collector.h" -#include "common/registry.h" - -#include "filter/classifiers/net6.h" +#include "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, -}; - // Allows to initialize attribute for IPv6 destination address. int FILTER_ATTR_COMPILER_INIT_FUNC(net6_src)( 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 2c5481989..ea0f0bd66 100644 --- a/filter/compiler/port.c +++ b/filter/compiler/port.c @@ -1,252 +1,6 @@ -#include "filter/classifiers/port.h" -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" -#include "declare.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) - ); -} +#include "port.h" -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_ranges_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_ranges_dst = { - .attr_handlers = filter_compile_attr_port_handlers, - .get_port_ranges = filter_rule_get_port_ranges_dst, -}; +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(port_dst)( diff --git a/filter/compiler/port.h b/filter/compiler/port.h new file mode 100644 index 000000000..f4444c44a --- /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_ranges_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_ranges_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 4a90ac8e3..84321ab1b 100644 --- a/filter/compiler/proto_range.c +++ b/filter/compiler/proto_range.c @@ -1,241 +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 - -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); +#include "proto_range.h" - 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_ranges = { - .attr_handlers = filter_compile_attr_proto_handlers, - .get_proto_ranges = filter_rule_get_proto_ranges, -}; +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(proto_range)( diff --git a/filter/compiler/proto_range.h b/filter/compiler/proto_range.h new file mode 100644 index 000000000..5796d4b5d --- /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_ranges = { + .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 43eb2d085..944902572 100644 --- a/filter/compiler/vlan.c +++ b/filter/compiler/vlan.c @@ -1,238 +1,6 @@ -#include "filter/classifiers/vlan.h" -#include "common/memory.h" -#include "common/registry.h" -#include "common/value.h" -#include "declare.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; +#include "vlan.h" - 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_ranges = { - .attr_handlers = filter_compile_attr_vlan_handlers, - .get_vlan_ranges = filter_rule_get_vlan_ranges, -}; +#include "declare.h" int FILTER_ATTR_COMPILER_INIT_FUNC(vlan)( diff --git a/filter/compiler/vlan.h b/filter/compiler/vlan.h new file mode 100644 index 000000000..6e987b816 --- /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_ranges = { + .attr_handlers = filter_compile_attr_vlan_handlers, + .get_vlan_ranges = filter_rule_get_vlan_ranges, +}; From d9e6bddf6e9f873e3e790a288ea843a8379943fe Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 22:33:39 +0300 Subject: [PATCH 15/17] Rename attributes in sake of backward compatibility --- filter/compiler/attribute.h | 32 -------------------------------- filter/compiler/port.h | 4 ++-- filter/compiler/proto_range.h | 2 +- filter/compiler/vlan.h | 2 +- 4 files changed, 4 insertions(+), 36 deletions(-) delete mode 100644 filter/compiler/attribute.h diff --git a/filter/compiler/attribute.h b/filter/compiler/attribute.h deleted file mode 100644 index 334f2b4ec..000000000 --- a/filter/compiler/attribute.h +++ /dev/null @@ -1,32 +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(proto_range); -REGISTER_ATTRIBUTE(net4_src); -REGISTER_ATTRIBUTE(net4_dst); -REGISTER_ATTRIBUTE(net6_src); -REGISTER_ATTRIBUTE(net6_dst); -REGISTER_ATTRIBUTE(vlan); -REGISTER_ATTRIBUTE(device); - -#undef REGISTER_ATTRIBUTE diff --git a/filter/compiler/port.h b/filter/compiler/port.h index f4444c44a..9d60e12a4 100644 --- a/filter/compiler/port.h +++ b/filter/compiler/port.h @@ -239,13 +239,13 @@ filter_rule_get_port_ranges_dst( } static const struct filter_compile_attr_port_handlers - filter_compile_attr_port_ranges_src = { + 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_ranges_dst = { + 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.h b/filter/compiler/proto_range.h index 5796d4b5d..70661e5db 100644 --- a/filter/compiler/proto_range.h +++ b/filter/compiler/proto_range.h @@ -232,7 +232,7 @@ filter_rule_get_proto_ranges( } static const struct filter_compile_attr_proto_handlers - filter_compile_attr_proto_ranges = { + 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.h b/filter/compiler/vlan.h index 6e987b816..e7ba07834 100644 --- a/filter/compiler/vlan.h +++ b/filter/compiler/vlan.h @@ -231,7 +231,7 @@ filter_rule_get_vlan_ranges( } static const struct filter_compile_attr_vlan_handlers - filter_compile_attr_vlan_ranges = { + filter_compile_attr_vlan = { .attr_handlers = filter_compile_attr_vlan_handlers, .get_vlan_ranges = filter_rule_get_vlan_ranges, }; From 292f7684e42e8ad6287c24a58f7ee1b44523a7bb Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 22:55:59 +0300 Subject: [PATCH 16/17] Make value_table const for get routines --- common/value.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/value.h b/common/value.h index ab52b54e3..3288d1d55 100644 --- a/common/value.h +++ b/common/value.h @@ -89,7 +89,7 @@ value_table_init( static inline uint32_t * value_table_get_ptr( - struct value_table *value_table, uint32_t v_idx, uint32_t h_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,7 +100,7 @@ value_table_get_ptr( static inline uint32_t value_table_get( - struct value_table *value_table, uint32_t v_idx, uint32_t h_idx + const struct value_table *value_table, uint32_t v_idx, uint32_t h_idx ) { return *value_table_get_ptr(value_table, v_idx, h_idx); } From 1c05934d702ec9a68eb5f1a578dba9b316e4839e Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Mon, 4 May 2026 23:38:30 +0300 Subject: [PATCH 17/17] New filter design base on a rule attribute regions 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. --- filter/compiler.h | 536 ++++++++++++++---- filter/compiler/declare.h | 19 +- filter/compiler/vlan.h | 4 +- filter/filter.h | 44 +- filter/meson.build | 11 - filter/query.h | 109 ++-- filter/query/attribute.h | 20 - filter/query/declare.h | 30 +- filter/query/device.h | 55 +- filter/query/net4.h | 89 ++- filter/query/net6.h | 99 ++-- filter/query/port.h | 98 +++- filter/query/proto_range.h | 98 ++-- filter/query/vlan.h | 49 +- filter/tests/basic_net4.c | 1 + filter/tests/basic_net4_fast.c | 2 + filter/tests/basic_net6.c | 1 + filter/tests/basic_net6_fast.c | 2 + filter/tests/basic_port_fast.c | 2 + filter/tests/basic_ports.c | 1 + filter/tests/basic_proto_range.c | 1 + filter/tests/basic_proto_range_fast.c | 1 + filter/tests/basic_vlan.c | 1 + filter/tests/bench_net4.c | 3 + filter/tests/bench_net4_fast.c | 4 + filter/tests/bench_net6.c | 4 + filter/tests/bench_net6_fast.c | 4 + filter/tests/combo_net4_port_proto_dst.c | 4 + filter/tests/combo_net4_port_src.c | 3 + filter/tests/combo_net6_port_src.c | 3 + filter/tests/corner.c | 1 + filter/tests/macros.c | 1 + filter/tests/memory.c | 1 + filter/tests/net4_ports.c | 2 + filter/tests/shm/compiler.c | 5 +- modules/acl/api/controlplane.c | 8 +- modules/balancer/controlplane/handler/rules.c | 6 + modules/balancer/controlplane/handler/vs.c | 9 +- modules/forward/api/controlplane.c | 6 +- modules/route-mpls/api/controlplane.c | 2 + 40 files changed, 936 insertions(+), 403 deletions(-) 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/declare.h b/filter/compiler/declare.h index af1559b8d..c0bc4ec67 100644 --- a/filter/compiler/declare.h +++ b/filter/compiler/declare.h @@ -5,24 +5,11 @@ #include "common/for_each.h" -#define FILTER_ATTR_COMPILER(name) name##_attr_compiler - -#define FILTER_ATTR_COMPILER_INIT_FUNC(name) name##_attr_init -#define FILTER_ATTR_COMPILER_FREE_FUNC(name) name##_attr_free - -#define FILTER_ATTR_LOOKUP_HANDLER(name) \ - { \ - name##_attr_init, \ - name##_attr_free, \ - } +#define FILTER_ATTR_COMPILE(name) &filter_compile_attr_##name.attr_handlers #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__)}, \ + static const struct filter_compile_attr_handlers *tag[] = { \ + FOR_EACH(FILTER_ATTR_COMPILE, __VA_ARGS__), \ }; /* diff --git a/filter/compiler/vlan.h b/filter/compiler/vlan.h index e7ba07834..af9b0144e 100644 --- a/filter/compiler/vlan.h +++ b/filter/compiler/vlan.h @@ -230,8 +230,8 @@ filter_rule_get_vlan_ranges( vlan_ranges->items = rule->vlan_ranges; } -static const struct filter_compile_attr_vlan_handlers - filter_compile_attr_vlan = { +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 60e527477..2162f5abb 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -36,41 +36,15 @@ struct filter_query_attr {}; -/** - * @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 -}; - -/** - * @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 7f1c265e6..531e26273 100644 --- a/filter/meson.build +++ b/filter/meson.build @@ -4,17 +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/vlan.c', - 'compiler/net6_fast.c', - 'compiler/net4_fast.c', - 'compiler/port_fast.c', - 'compiler/segments.c', ) lib_filter_compiler = static_library( 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 4b03ee9e0..4dc46a5ed 100644 --- a/filter/query/attribute.h +++ b/filter/query/attribute.h @@ -15,23 +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_range); -REGISTER_ATTRIBUTE(net4_src); -REGISTER_ATTRIBUTE(net4_dst); -REGISTER_ATTRIBUTE(net6_src); -REGISTER_ATTRIBUTE(net6_dst); -REGISTER_ATTRIBUTE(vlan); -REGISTER_ATTRIBUTE(device); - -#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 02426c543..ef40f1b74 100644 --- a/filter/query/device.h +++ b/filter/query/device.h @@ -1,20 +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; - if (device_id >= t->h_dim) + 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; - result[idx] = value_table_get(t, 0, device_id); + 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 e1ec5f242..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,54 +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 filter_query_attr_net6 *c = - (struct filter_query_attr_net6 *)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 filter_query_attr_net6 *c = - (struct filter_query_attr_net6 *)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_range.h b/filter/query/proto_range.h index e05f1864c..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 filter_query_attr_proto_range *c = - (struct filter_query_attr_proto_range *)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->value_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 7cbef861d..8e66d05f1 100644 --- a/filter/query/vlan.h +++ b/filter/query/vlan.h @@ -6,15 +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 filter_query_attr_proto_range *c = - (struct filter_query_attr_proto_range *)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(&c->value_table, 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/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 d149e1ba8..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" 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 7d19b2955..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" diff --git a/filter/tests/basic_port_fast.c b/filter/tests/basic_port_fast.c index ccb67b630..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" 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_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 e80f1052a..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" 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 b3c74758c..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" diff --git a/filter/tests/bench_net4_fast.c b/filter/tests/bench_net4_fast.c index ce5b457b5..759dbd734 100644 --- a/filter/tests/bench_net4_fast.c +++ b/filter/tests/bench_net4_fast.c @@ -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" diff --git a/filter/tests/bench_net6.c b/filter/tests/bench_net6.c index af2feb036..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" diff --git a/filter/tests/bench_net6_fast.c b/filter/tests/bench_net6_fast.c index a5d52e565..3788c8ef0 100644 --- a/filter/tests/bench_net6_fast.c +++ b/filter/tests/bench_net6_fast.c @@ -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" diff --git a/filter/tests/combo_net4_port_proto_dst.c b/filter/tests/combo_net4_port_proto_dst.c index 1b9c64fa3..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" diff --git a/filter/tests/combo_net4_port_src.c b/filter/tests/combo_net4_port_src.c index 9d3a22841..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" diff --git a/filter/tests/combo_net6_port_src.c b/filter/tests/combo_net6_port_src.c index 98304920a..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" 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/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/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 a86edd067..bb8af8488 100644 --- a/filter/tests/shm/compiler.c +++ b/filter/tests/shm/compiler.c @@ -14,7 +14,10 @@ #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_range); 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 b036d0d3c..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" diff --git a/modules/balancer/controlplane/handler/vs.c b/modules/balancer/controlplane/handler/vs.c index 223a164a4..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 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);