From aa67c623161839ce72b9f8a48ccd980cf668cbee Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Tue, 21 May 2024 12:25:47 +0300 Subject: [PATCH 001/195] Counters optimization, step 1: - The identifier array was returned to the consumers of the class, corrected to return only the first index. - Also, in one place, to get the size of the selected counters, a method has been added that returns the desired result. --- controlplane/balancer.cpp | 10 +++++----- controlplane/counter.h | 25 +++++++++---------------- controlplane/route.cpp | 8 ++++---- controlplane/tun64.cpp | 8 ++++---- 4 files changed, 22 insertions(+), 29 deletions(-) diff --git a/controlplane/balancer.cpp b/controlplane/balancer.cpp index 0d8ebd8d..f17855f4 100644 --- a/controlplane/balancer.cpp +++ b/controlplane/balancer.cpp @@ -212,7 +212,7 @@ void balancer_t::controlplane_values(common::icp::controlplane_values::response& controlplane_values.emplace_back("balancer.reals_unordered.size", std::to_string(reals_unordered.size())); controlplane_values.emplace_back("balancer.reals_unordered_ids_unused.size", std::to_string(reals_unordered_ids_unused.size())); } - controlplane_values.emplace_back("balancer.real_counters.size", std::to_string(real_counters.get_counters().size())); + controlplane_values.emplace_back("balancer.real_counters.size", std::to_string(real_counters.size())); } void balancer_t::reload_before() @@ -780,7 +780,7 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, balancer::real_key_global_t key = {module_name, {virtual_ip, proto, virtual_port}, {real_ip, real_port}}; - const auto counter_ids = real_counters.get_ids(key); + const auto counter_id = real_counters.get_id(key); uint32_t real_unordered_id = 0; { @@ -800,15 +800,15 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, req_reals.emplace_back(common::idp::updateGlobalBase::update_balancer_services::real{ real_unordered_id, real_ip, - counter_ids[0]}); + counter_id}); req_binding.emplace_back(real_unordered_id); } - const auto counter_ids = service_counters.get_ids({module_name, {virtual_ip, proto, virtual_port}}); + const auto counter_id = service_counters.get_id({module_name, {virtual_ip, proto, virtual_port}}); req_services.emplace_back(common::idp::updateGlobalBase::update_balancer_services::service{ service_id, flags, - counter_ids[0], + counter_id, scheduler, forwarding_method, balancer.default_wlc_power, // todo use scheduler_params.wlc_power when other services will be able to set it diff --git a/controlplane/counter.h b/controlplane/counter.h index e33a7bc5..ed1f454c 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -314,7 +314,7 @@ class counter_t } } - std::array get_ids(const key_T& key) + tCounterId get_id(const key_T& key) { std::lock_guard guard(mutex); @@ -322,26 +322,13 @@ class counter_t if (iter == counters.end()) { /// fallback - std::array result; - for (size_t i = 0; - i < size_T; - i++) - { - result[i] = i; - } - - return result; + return 0; } const auto& [counter_ids, refcount] = iter->second; (void)refcount; - return counter_ids; - } - - tCounterId get_id(const key_T& key) - { - return get_ids(key)[0]; + return counter_ids[0]; } std::map> get_counters() const ///< get_values @@ -384,6 +371,12 @@ class counter_t return result; } + size_t size() const + { + std::lock_guard guard(mutex); + return counters_allocated.size(); + } + void gc() { std::lock_guard guard(mutex); diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 4d7b066c..e1cac29d 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1700,7 +1700,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa if (exist(interfaces, egress_interface_id)) { - const auto counter_ids = tunnel_counter.get_ids({fallback.is_ipv4(), peer_id, nexthop, origin_as}); + const auto counter_id = tunnel_counter.get_id({fallback.is_ipv4(), peer_id, nexthop, origin_as}); uint16_t flags = 0; if (neighbor_address.is_default()) @@ -1708,7 +1708,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa flags |= YANET_NEXTHOP_FLAG_DIRECTLY; } - update_nexthops.emplace_back(egress_interface_id, counter_ids[0], label, nexthop, neighbor_address, flags); + update_nexthops.emplace_back(egress_interface_id, counter_id, label, nexthop, neighbor_address, flags); weights.emplace_back(weight); tunnel_value_lookup[value_id][socket_id].emplace_back(nexthop, @@ -1730,7 +1730,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; (void)egress_interface_name; - const auto counter_ids = tunnel_counter.get_ids({fallback.is_ipv4(), peer_id, nexthop, origin_as}); + const auto counter_id = tunnel_counter.get_id({fallback.is_ipv4(), peer_id, nexthop, origin_as}); uint16_t flags = 0; if (neighbor_address.is_default()) @@ -1738,7 +1738,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa flags |= YANET_NEXTHOP_FLAG_DIRECTLY; } - update_nexthops.emplace_back(egress_interface_id, counter_ids[0], label, nexthop, neighbor_address, flags); + update_nexthops.emplace_back(egress_interface_id, counter_id, label, nexthop, neighbor_address, flags); weights.emplace_back(weight); tunnel_value_lookup[value_id][socket_id].emplace_back(nexthop, diff --git a/controlplane/tun64.cpp b/controlplane/tun64.cpp index cccc46d1..09ee3968 100644 --- a/controlplane/tun64.cpp +++ b/controlplane/tun64.cpp @@ -123,9 +123,9 @@ void tun64_t::compile(common::idp::updateGlobalBase::request& globalbase, { for (auto& [name, tunnel] : generation_config.config_tunnels) { - const auto counter_ids = tunnel_counters.get_ids(name); + const auto counter_id = tunnel_counters.get_id(name); - tunnel.flow.counter_id = counter_ids[0]; + tunnel.flow.counter_id = counter_id; globalbase.emplace_back(common::idp::updateGlobalBase::requestType::tun64_update, common::idp::updateGlobalBase::tun64_update::request{tunnel.tun64Id, tunnel.dscpMarkType, @@ -139,13 +139,13 @@ void tun64_t::compile(common::idp::updateGlobalBase::request& globalbase, for (const auto& [ipv4_address, mapping] : tunnel.mappings) { const auto& [ipv6_address, location] = mapping; - const auto counter_ids = mappings_counters.get_ids({name, ipv4_address}); + const auto counter_id = mappings_counters.get_id({name, ipv4_address}); (void)location; tun64mappings_update_request.emplace_back(tunnel.tun64Id, ipv4_address, ipv6_address, - counter_ids[0]); + counter_id); } globalbase.emplace_back(common::idp::updateGlobalBase::requestType::tun64mappings_update, From cecd7e9150b99d7ec2f42397094de51e55abffa9 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Fri, 24 May 2024 18:22:41 +0300 Subject: [PATCH 002/195] Counters optimization, step 2: - Instead of passing an array with a list of selected identifiers, only the first index is now being transmitted. This is acceptable since the list of identifiers increases sequentially by 1. - A simple allocator has been made that is much more productive than the old one and works in: O(log(number of continuous free segments)). --- controlplane/counter.h | 257 +++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 139 deletions(-) diff --git a/controlplane/counter.h b/controlplane/counter.h index ed1f454c..9a0e1804 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -1,108 +1,121 @@ #pragma once #include +#include #include "type.h" #include "common/idataplane.h" #include "common/refarray.h" -class counter_manager_t +class SegmentAllocator { public: - static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE); + SegmentAllocator(size_t start, size_t size, size_t error_result) : + size_(size), error_result_(error_result) + { + Insert(start, size); + } - counter_manager_t() + size_t Allocate(size_t size) { - for (unsigned int counter_id = (uint32_t)common::globalBase::static_counter_type::size; - counter_id < YANET_CONFIG_COUNTERS_SIZE; - counter_id++) + auto iter = segments_size_.lower_bound({size, 0}); + if (iter == segments_size_.end()) { - counter_unused_ids.emplace(counter_id); + return error_result_; } - counter_unused_ids_size = counter_unused_ids.size(); - counter_shifts.resize(YANET_CONFIG_COUNTERS_SIZE, 0); - } + size_t index = iter->second; - std::tuple stats() const - { - return {YANET_CONFIG_COUNTERS_SIZE - counter_unused_ids_size, YANET_CONFIG_COUNTERS_SIZE}; - } + if (size < iter->first) + { + Insert(index + size, iter->first - size); + } -protected: - template - friend class counter_t; + segments_start_.erase({index, iter->first}); + segments_size_.erase(iter); + size_ -= size; - template - std::array counter_reserve() - { - static_assert(size_T <= YANET_CONFIG_COUNTER_FALLBACK_SIZE); + return index; + } - std::lock_guard guard(counter_mutex); + bool Free(size_t start, size_t size) + { + auto iter_right = segments_start_.upper_bound({start, 0}); + auto iter_left = (iter_right == segments_start_.begin() ? segments_start_.end() : std::prev(iter_right)); // если тот что справа самый первый, то левее уже никого - /// @todo: opt std::array reserve_ids; - std::vector reserve_ids; - reserve_ids.reserve(size_T); - std::set bad_counter_ids; - while (counter_unused_ids.size()) + if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second > start)) { - const uint32_t counter_id = *counter_unused_ids.begin(); - counter_unused_ids.erase(counter_id); + return false; // Освобождаем в отрезке который и так свободен + } + else if ((iter_right != segments_start_.end()) && (start + size > iter_right->first)) + { + return false; // Освобождаем в отрезке который и так свободен + } - if (reserve_ids.size()) - { - if (reserve_ids.back() + 1 != counter_id) - { - for (const auto& counter_id : reserve_ids) - { - bad_counter_ids.emplace(counter_id); - } + if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second == start)) + { // Объединяем с левым сегментом + start = iter_left->first; + size += iter_left->second; + segments_size_.erase({iter_left->second, iter_left->first}); + segments_start_.erase(iter_left); + } - reserve_ids.clear(); - } - } + if ((iter_right != segments_start_.end()) && (start + size == iter_right->first)) + { // Объединяем с правым сегментом + size += iter_right->second; + segments_size_.erase({iter_right->second, iter_right->first}); + segments_start_.erase(iter_right); + } - reserve_ids.emplace_back(counter_id); + Insert(start, size); + size_ += size; + return true; + } - if (reserve_ids.size() == size_T) - { - for (const auto& counter_id : bad_counter_ids) - { - counter_unused_ids.emplace(counter_id); - } - bad_counter_ids.clear(); + size_t Size() const + { + return size_; + } - counter_unused_ids_size = counter_unused_ids.size(); +private: + std::set> segments_start_; + std::set> segments_size_; + size_t size_; + size_t error_result_; - std::array result; - std::copy_n(reserve_ids.begin(), size_T, result.begin()); - return result; - } - } + void Insert(size_t start, size_t size) + { + segments_start_.insert({start, size}); + segments_size_.insert({size, start}); + } +}; - for (const auto& counter_id : reserve_ids) - { - counter_unused_ids.emplace(counter_id); - } +class counter_manager_t +{ +public: + static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE); - for (const auto& counter_id : bad_counter_ids) - { - counter_unused_ids.emplace(counter_id); - } - bad_counter_ids.clear(); + counter_manager_t() : + counter_shifts(YANET_CONFIG_COUNTERS_SIZE, 0), + allocator((uint32_t)common::globalBase::static_counter_type::size, YANET_CONFIG_COUNTERS_SIZE - (uint32_t)common::globalBase::static_counter_type::size, 0) + { + } - YANET_LOG_WARNING("not enough counters\n"); + std::tuple stats() const + { + std::lock_guard guard(counter_mutex); + return {YANET_CONFIG_COUNTERS_SIZE - allocator.Size(), YANET_CONFIG_COUNTERS_SIZE}; + } - /// fallback - std::array result; - for (size_t i = 0; - i < size_T; - i++) - { - result[i] = i; - } - return result; +protected: + template + friend class counter_t; + + tCounterId counter_reserve(size_t size) + { + std::lock_guard guard(counter_mutex); + return allocator.Allocate(size); } void counter_allocate(const std::vector& counter_ids) @@ -141,22 +154,17 @@ class counter_manager_t return result; } - void counter_release(const std::vector& counter_ids) + void counter_release(tCounterId counter_id, size_t size) { std::lock_guard guard(counter_mutex); - for (const auto& counter_id : counter_ids) - { - counter_unused_ids.emplace(counter_id); - } - counter_unused_ids_size = counter_unused_ids.size(); + allocator.Free(counter_id, size); } protected: mutable std::mutex counter_mutex; interface::dataPlane counter_dataplane; - std::set counter_unused_ids; - std::atomic counter_unused_ids_size; std::vector counter_shifts; + SegmentAllocator allocator; }; template counter_ids; counter_ids.reserve(counters_inserted.size() * size_T); - for (const auto& [key, counter_ids_array] : counters_inserted) + for (const auto& [key, counter_id] : counters_inserted) { - for (const auto& counter_id : counter_ids_array) + for (size_t index = 0; index < size_T; index++) { - counter_ids.emplace_back(counter_id); + counter_ids.push_back(counter_id + index); } - counters_allocated.emplace(key, counter_ids_array); + counters_allocated.emplace(key, counter_id); callback(key); } counters_inserted.clear(); @@ -206,22 +216,14 @@ class counter_t { std::lock_guard guard(mutex); - std::vector counter_ids; - counter_ids.reserve(counters_gc_removed.size() * size_T); - for (const auto& [key, counter_ids_array] : counters_gc_removed) + for (const auto& [key, counter_id] : counters_gc_removed) { - for (const auto& counter_id : counter_ids_array) - { - counter_ids.emplace_back(counter_id); - } - callback(key); counters.erase(key); counters_allocated.erase(key); + manager->counter_release(counter_id, size_T); } counters_gc_removed.clear(); - - manager->counter_release(counter_ids); } void release() @@ -249,14 +251,12 @@ class counter_t } else { - const auto counter_ids = manager->counter_reserve(); + const auto counter_id = manager->counter_reserve(size_T); counters.emplace_hint(counters_it, key, - std::tuple, - uint32_t>(counter_ids, - 1)); - counters_inserted.emplace(key, counter_ids); + std::tuple(counter_id, 1)); + counters_inserted.emplace(key, counter_id); } } @@ -268,7 +268,7 @@ class counter_t auto counters_it = counters.find(key); if (counters_it != counters.end()) { - auto& [counter_ids_array, refcount] = counters_it->second; + auto& [counter_id, refcount] = counters_it->second; if (!refcount) { @@ -283,12 +283,7 @@ class counter_t auto counters_inserted_it = counters_inserted.find(key); if (counters_inserted_it != counters_inserted.end()) { - std::vector counter_ids_removed; - for (const auto& counter_id : counters_inserted_it->second) - { - counter_ids_removed.emplace_back(counter_id); - } - manager->counter_release(counter_ids_removed); + manager->counter_release(counters_inserted_it->second, size_T); if (counters_allocated.count(key)) { @@ -303,7 +298,7 @@ class counter_t uint32_t timestamp = time(nullptr); timestamp += timeout; - counters_removed.emplace(key, std::tuple, uint32_t>(counter_ids_array, timestamp)); + counters_removed.emplace(key, std::tuple(counter_id, timestamp)); } } } @@ -325,10 +320,10 @@ class counter_t return 0; } - const auto& [counter_ids, refcount] = iter->second; + const auto& [counter_id, refcount] = iter->second; (void)refcount; - return counter_ids[0]; + return counter_id; } std::map> get_counters() const ///< get_values @@ -337,13 +332,13 @@ class counter_t /// @todo: opt std::vector manager_counter_ids; - for (const auto& [key, counter_ids_array] : counters_allocated) + for (const auto& [key, counter_id] : counters_allocated) { (void)key; - for (const auto& counter_id : counter_ids_array) + for (size_t index = 0; index < size_T; index++) { - manager_counter_ids.emplace_back(counter_id); + manager_counter_ids.emplace_back(counter_id + index); } } @@ -352,9 +347,9 @@ class counter_t std::map> result; size_t i = 0; - for (const auto& [key, counter_ids_array] : counters_allocated) + for (const auto& [key, counter_id] : counters_allocated) { - (void)counter_ids_array; + (void)counter_id; std::array array; for (size_t array_i = 0; @@ -389,11 +384,11 @@ class counter_t counters_removed_it != counters_removed.end();) { const auto& [key, ids_timestamp] = *counters_removed_it; - const auto& [counter_ids_array, timestamp] = ids_timestamp; + const auto& [counter_id, timestamp] = ids_timestamp; if (current_time >= timestamp) { - counters_gc_removed.emplace(key, counter_ids_array); + counters_gc_removed.emplace(key, counter_id); counters_removed_it = counters_removed.erase(counters_removed_it); continue; @@ -409,25 +404,9 @@ class counter_t mutable std::mutex mutex; - std::map, - uint32_t>> - counters; ///< refcount - - std::map> - counters_inserted; - - std::map, - uint32_t>> - counters_removed; ///< timestamp - - std::map> - counters_gc_removed; - - std::map> - counters_allocated; + std::map> counters; ///< refcount + std::map counters_inserted; + std::map> counters_removed; ///< timestamp + std::map counters_gc_removed; + std::map counters_allocated; }; From d482fd0e2aa15358ce6e97f1898fc1877f9ff95e Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Mon, 3 Jun 2024 18:19:19 +0300 Subject: [PATCH 003/195] Counters optimization, step 3: - Added a new Segment Allocator for counters that works for O(1) time. - Added unittests for the new allocator. - A command has been added to the cli "counters stat" that outputs statistics on the use of counters, an example of its output is given below: Counters usage info Free blocks: 2046, counters: 8388356 Errors external: 0, internal: 0 size: 2, used blocks: 1, busy blocks: 0, used segments: 2 size: 4, used blocks: 1, busy blocks: 0, used segments: 30 --- cli/main.cpp | 1 + cli/show.h | 15 + common/icontrolplane.h | 5 + common/icp.h | 23 +- controlplane/controlplane.cpp | 9 + controlplane/controlplane.h | 1 + controlplane/counter.h | 114 ++------ controlplane/segment_allocator.h | 308 ++++++++++++++++++++ controlplane/unittest/meson.build | 1 + controlplane/unittest/segment_allocator.cpp | 232 +++++++++++++++ 10 files changed, 623 insertions(+), 86 deletions(-) create mode 100644 controlplane/segment_allocator.h create mode 100644 controlplane/unittest/segment_allocator.cpp diff --git a/cli/main.cpp b/cli/main.cpp index 414c2f1d..e76751f3 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -132,6 +132,7 @@ std::vector ", [](const auto& args) { call(latch::dataplane_update, args); }}, {"counter", "[counter_name] ", [](const auto& args) { call(show::counter_by_name, args); }}, + {"counters stat", "", [](const auto& args) { call(show::counters_stat, args); }}, {"latch update dataplane", " ", [](const auto& args) { call(latch::dataplane_update, args); }}, {}, {"convert logical_module", "", [](const auto& args) { call(convert::logical_module, args); }}}; diff --git a/cli/show.h b/cli/show.h index 57b4b00f..b9f2e7e8 100644 --- a/cli/show.h +++ b/cli/show.h @@ -924,4 +924,19 @@ void shm_tsc_set_base_value(std::string counter_name, uint32_t value) } } +void counters_stat() +{ + interface::controlPlane controlplane; + auto [common_info, sizes_info] = controlplane.counters_stat(); + auto [free_blocks, free_cells, errors_external, errors_internal] = common_info; + printf("Counters usage info\n"); + printf("Free blocks: %d, counters: %d\n", free_blocks, free_cells); + printf("Errors external: %ld, internal: %ld\n", errors_external, errors_internal); + + for (auto [size, used_blocks, busy_blocks, used_segments] : sizes_info) + { + printf("size: %d, used blocks: %d, busy blocks: %d, used segments: %d\n", size, used_blocks, busy_blocks, used_segments); + } +} + } diff --git a/common/icontrolplane.h b/common/icontrolplane.h index f123f080..b12701d5 100644 --- a/common/icontrolplane.h +++ b/common/icontrolplane.h @@ -337,6 +337,11 @@ class controlPlane return get(request); } + auto counters_stat() const + { + return get(); + } + protected: void connectToControlPlane() const { diff --git a/common/icp.h b/common/icp.h index 3b2b7810..093e8526 100644 --- a/common/icp.h +++ b/common/icp.h @@ -87,6 +87,7 @@ enum class requestType : uint32_t nat46clat_announce, nat46clat_stats, convert, + counters_stat, size // size should always be at the bottom of the list, this enum allows us to find out the size of the enum list }; @@ -220,6 +221,8 @@ inline const char* requestType_toString(requestType t) return "nat46clat_stats"; case requestType::convert: return "convert"; + case requestType::counters_stat: + return "counters_stat"; case requestType::size: return "unknown"; } @@ -907,6 +910,22 @@ using response = std::vector>; ///< name } +namespace counters_stat +{ +using one_size_info = std::tuple; ///< used_segments + +using common_info = std::tuple; ///< errors_internal_ + +using response = std::tuple>; +} + using request = std::tuple, acl_unwind::request, @@ -974,7 +993,7 @@ using response = std::variant, nat46clat_config::response, nat46clat_announce::response, nat46clat_stats::response, - convert::response>; + convert::response, + counters_stat::response>; } - } diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index d8919c29..89acaafe 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -149,6 +149,10 @@ eResult cControlPlane::init(const std::string& jsonFilePath) return command_convert(std::get(std::get<1>(request))); }); + register_command(common::icp::requestType::counters_stat, [this]() { + return command_counters_stat(); + }); + if (!jsonFilePath.empty()) { std::ifstream fromFileStream(jsonFilePath); @@ -818,6 +822,11 @@ common::icp::convert::response cControlPlane::command_convert(const common::icp: return response; } +common::icp::counters_stat::response cControlPlane::command_counters_stat() +{ + return counter_manager.full_stat(); +} + common::icp::convert::response cControlPlane::convert_logical_module() { common::icp::convert::response response; diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index 8d038a22..cfcf82f7 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -123,6 +123,7 @@ class cControlPlane common::icp::loadConfig::response command_loadConfig(const common::icp::loadConfig::request& request); common::icp::version::response command_version(); common::icp::convert::response command_convert(const common::icp::convert::request& request); + common::icp::counters_stat::response command_counters_stat(); common::icp::convert::response convert_logical_module(); diff --git a/controlplane/counter.h b/controlplane/counter.h index 9a0e1804..63f4e1a3 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -3,108 +3,51 @@ #include #include +#include "segment_allocator.h" #include "type.h" +#include "common/icp.h" #include "common/idataplane.h" #include "common/refarray.h" -class SegmentAllocator +class counter_manager_t { public: - SegmentAllocator(size_t start, size_t size, size_t error_result) : - size_(size), error_result_(error_result) + static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE); + + counter_manager_t() : + counter_shifts(YANET_CONFIG_COUNTERS_SIZE, 0) { - Insert(start, size); } - size_t Allocate(size_t size) + std::tuple stats() const { - auto iter = segments_size_.lower_bound({size, 0}); - if (iter == segments_size_.end()) - { - return error_result_; - } - size_t index = iter->second; - - if (size < iter->first) - { - Insert(index + size, iter->first - size); - } - - segments_start_.erase({index, iter->first}); - segments_size_.erase(iter); - size_ -= size; - - return index; + std::lock_guard guard(counter_mutex); + return {YANET_CONFIG_COUNTERS_SIZE - allocator.Size(), YANET_CONFIG_COUNTERS_SIZE}; } - bool Free(size_t start, size_t size) + common::icp::counters_stat::response full_stat() const { - auto iter_right = segments_start_.upper_bound({start, 0}); - auto iter_left = (iter_right == segments_start_.begin() ? segments_start_.end() : std::prev(iter_right)); // если тот что справа самый первый, то левее уже никого + std::lock_guard guard(counter_mutex); - if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second > start)) + const auto* blocks_stat = allocator.GetBlocksStat(); + std::vector sizes_info; + for (uint16_t size = 1; size <= max_buffer_size; size++) { - return false; // Освобождаем в отрезке который и так свободен - } - else if ((iter_right != segments_start_.end()) && (start + size > iter_right->first)) - { - return false; // Освобождаем в отрезке который и так свободен - } - - if ((iter_left != segments_start_.end()) && (iter_left->first + iter_left->second == start)) - { // Объединяем с левым сегментом - start = iter_left->first; - size += iter_left->second; - segments_size_.erase({iter_left->second, iter_left->first}); - segments_start_.erase(iter_left); - } - - if ((iter_right != segments_start_.end()) && (start + size == iter_right->first)) - { // Объединяем с правым сегментом - size += iter_right->second; - segments_size_.erase({iter_right->second, iter_right->first}); - segments_start_.erase(iter_right); + const auto& block = blocks_stat[size]; + if ((block.used_blocks != 0) || (block.busy_blocks != 0) || (block.used_segments != 0)) + { + sizes_info.emplace_back(size, block.used_blocks, block.busy_blocks, block.used_segments); + } } - Insert(start, size); - size_ += size; - return true; - } - - size_t Size() const - { - return size_; - } - -private: - std::set> segments_start_; - std::set> segments_size_; - size_t size_; - size_t error_result_; + auto [errors_external, errors_internal] = allocator.GetErrors(); + common::icp::counters_stat::common_info common_info(blocks_stat[0].used_blocks, ///< free_blocks + allocator.Size(), ///< free_cells_ + errors_external, ///< errors_external_ + errors_internal); ///< errors_internal_ - void Insert(size_t start, size_t size) - { - segments_start_.insert({start, size}); - segments_size_.insert({size, start}); - } -}; - -class counter_manager_t -{ -public: - static_assert((uint32_t)common::globalBase::static_counter_type::size <= YANET_CONFIG_COUNTERS_SIZE); - - counter_manager_t() : - counter_shifts(YANET_CONFIG_COUNTERS_SIZE, 0), - allocator((uint32_t)common::globalBase::static_counter_type::size, YANET_CONFIG_COUNTERS_SIZE - (uint32_t)common::globalBase::static_counter_type::size, 0) - { - } - - std::tuple stats() const - { - std::lock_guard guard(counter_mutex); - return {YANET_CONFIG_COUNTERS_SIZE - allocator.Size(), YANET_CONFIG_COUNTERS_SIZE}; + return {common_info, sizes_info}; } protected: @@ -161,10 +104,13 @@ class counter_manager_t } protected: + static constexpr uint32_t counter_index_begin = (((uint32_t)common::globalBase::static_counter_type::size + 63) / 64) * 64; + static constexpr uint32_t max_buffer_size = 64; + mutable std::mutex counter_mutex; interface::dataPlane counter_dataplane; std::vector counter_shifts; - SegmentAllocator allocator; + SegmentAllocator allocator; }; template +#include + +#include + +#define ENABLE_BIT(v, b) (v) |= ((uint64_t)1) << (b) +#define GET_BIT(v, b) (((v) >> (b)) & 1) +#define DISABLE_BIT(v, b) (v) &= ~(((uint64_t)1) << (b)) + +template +class SegmentAllocator +{ +public: + static_assert((BlockSize % 64) == 0); + static_assert((BlockSize <= 64 * 64) && (BlockSize >= 64)); + static_assert((MaxBufferSize <= 64) && (MaxBufferSize >= 1)); + // Last block can't be less than MaxBufferSize + static_assert(((IndexEnd - IndexBegin) % BlockSize == 0) || ((IndexEnd - IndexBegin) % BlockSize >= MaxBufferSize)); + + struct OneSizeBlockInfo + { + uint32_t head_block = 0; + uint32_t used_blocks = 0; + uint32_t busy_blocks = 0; + uint32_t used_segments = 0; + }; + + SegmentAllocator() + { + free_cells_ = IndexEnd - IndexBegin; + + // Initialize blocks in main list of free blocks and set size of each block + for (uint32_t index = 0; index < total_blocks_; ++index) + { + all_blocks_[index].Initialize(index - 1, index + 1); + } + all_blocks_[0].previous = null_block_; + all_blocks_[total_blocks_ - 1].next = null_block_; + // the size of the last block may vary + all_blocks_[total_blocks_ - 1].block_size = IndexEnd - IndexBegin - (total_blocks_ - 1) * BlockSize; + + // Initialize data for each size of segments + for (uint32_t index = 1; index <= MaxBufferSize; ++index) + { + sizes_info_[index].head_block = null_block_; + } + // size = 0 - free blocks, at start head_block = 0 + sizes_info_[0].used_blocks = total_blocks_; + } + + uint32_t Allocate(uint16_t size) + { + if ((size == 0) || (size > MaxBufferSize)) + { + // bad size + errors_external_++; + return ErrorResult; + } + + // try find block + OneSizeBlockInfo& size_info = sizes_info_[size]; + if (size_info.head_block == null_block_) + { + uint32_t block_index = sizes_info_[0].head_block; + // no free blocks this size + if (block_index == null_block_) + { + // no free blocks + return ErrorResult; + } + else + { + // move block from list of free to blocks of this size + RemoveFromList(block_index, 0); + all_blocks_[block_index].SetSize(size); + InsertToList(block_index, size); + } + } + + OneBlock& block = all_blocks_[size_info.head_block]; + uint16_t index_in_block = block.Allocate(); + if (index_in_block == error_in_block_) + { + errors_internal_++; + return ErrorResult; + } + uint32_t result = size_info.head_block * BlockSize + index_in_block * size + IndexBegin; + if (block.free_segments == 0) + { + // block is busy + RemoveFromList(size_info.head_block, size); + size_info.busy_blocks++; + } + size_info.used_segments++; + + free_cells_ -= size; + return result; + } + + uint32_t Free(uint32_t start, uint16_t size) + { + if ((size == 0) || (size > MaxBufferSize) || (start >= IndexEnd) || (start < IndexBegin)) + { + errors_external_++; + return false; + } + + uint32_t block_index = (start - IndexBegin) / BlockSize; + OneBlock& block = all_blocks_[block_index]; + if (block.one_segment_size != size) + { + errors_external_++; + return false; + } + else if ((start - block_index * BlockSize - IndexBegin) % size != 0) + { + errors_external_++; + return false; + } + + bool block_was_busy = (block.free_segments == 0); + uint16_t index = (start - block_index * BlockSize - IndexBegin) / size; + if (block.Free(index) == error_in_block_) + { + errors_external_++; + return false; + } + + OneSizeBlockInfo& size_info = sizes_info_[size]; + if (block_was_busy) + { + if ((block.previous != null_block_) || (block.next != null_block_)) + { + errors_internal_++; + } + InsertToList(block_index, size); + size_info.busy_blocks--; + } + if (block.free_segments == block.total_segments) + { + RemoveFromList(block_index, size); + InsertToList(block_index, 0); + } + + size_info.used_segments--; + free_cells_ += size; + return true; + } + + uint32_t Size() const + { + return free_cells_; + } + + const OneSizeBlockInfo* GetBlocksStat() const + { + return sizes_info_; + } + + std::pair GetErrors() const + { + return {errors_external_, errors_internal_}; + } + +private: + struct OneBlock + { + // indexes of previous and next blocks in list + uint32_t previous; + uint32_t next; + + // block structure + uint16_t block_size; + uint16_t one_segment_size; + uint16_t total_segments; + uint16_t free_segments; + + // bit masks of segments usage + uint64_t group_mask; + uint64_t masks[BlockSize / 64]; + + void Initialize(uint32_t previous, uint32_t next) + { + this->previous = previous; + this->next = next; + block_size = BlockSize; + group_mask = 0; + memset(masks, 0, sizeof(masks)); + } + + void SetSize(uint16_t segment_size) + { + one_segment_size = segment_size; + total_segments = block_size / segment_size; + free_segments = total_segments; + } + + uint16_t Allocate() + { + // calling the function implies that we are sure that there are free segments + if ((~group_mask) == 0) + { + return error_in_block_; + } + + uint16_t group = __builtin_ctzll(~group_mask); + if ((group >= sizeof(masks) / sizeof(masks[0])) || ((~masks[group]) == 0)) + { + return error_in_block_; + } + uint16_t index_in_group = __builtin_ctzll(~masks[group]); + uint16_t index = group * 64 + index_in_group; + + if (index >= total_segments) + { + return error_in_block_; + } + + // set bits usage + ENABLE_BIT(masks[group], index_in_group); + if ((~masks[group]) == 0) + { + ENABLE_BIT(group_mask, group); + } + + // change number of free segments + free_segments--; + + return index; + } + + uint16_t Free(uint16_t index) + { + if (index >= total_segments) + { + return error_in_block_; + } + + uint16_t group = index >> 6; // divide by 64 + index &= 0x003f; // % 64 + + if (GET_BIT(masks[group], index) == 0) + { + return error_in_block_; + } + + // set bits usage + DISABLE_BIT(masks[group], index); + if (masks[group] == 0) + { + DISABLE_BIT(group_mask, group); + } + + // change number of free segments + free_segments++; + + return 0; + } + }; + + static constexpr uint32_t total_blocks_ = (IndexEnd - IndexBegin + BlockSize - 1) / BlockSize; + static constexpr uint32_t null_block_ = static_cast(-1); + static constexpr uint16_t error_in_block_ = static_cast(-1); + + OneBlock all_blocks_[total_blocks_]; + OneSizeBlockInfo sizes_info_[MaxBufferSize + 1]; + + uint32_t free_cells_; + uint64_t errors_external_ = 0; + uint64_t errors_internal_ = 0; + + void RemoveFromList(uint32_t block_index, uint16_t size) + { + OneBlock& block = all_blocks_[block_index]; + sizes_info_[size].used_blocks--; + + // change links in previous and next block + if (block.previous != null_block_) + { + all_blocks_[block.previous].next = block.next; + } + if (block.next != null_block_) + { + all_blocks_[block.next].previous = block.previous; + } + + // if it was head + if (sizes_info_[size].head_block == block_index) + { + sizes_info_[size].head_block = block.next; + } + + // we don't have to delete links to the previous and next one, but we do it only + // for internal verification when we add it to the list + block.previous = null_block_; + block.next = null_block_; + } + + void InsertToList(uint32_t block_index, uint16_t size) + { + all_blocks_[block_index].next = sizes_info_[size].head_block; + all_blocks_[block_index].previous = null_block_; + sizes_info_[size].head_block = block_index; + sizes_info_[size].used_blocks++; + } +}; diff --git a/controlplane/unittest/meson.build b/controlplane/unittest/meson.build index c419e7a0..fadbdf6d 100644 --- a/controlplane/unittest/meson.build +++ b/controlplane/unittest/meson.build @@ -23,6 +23,7 @@ sources = files('unittest.cpp', 'acl_tree.cpp', 'network.cpp', 'parser.cpp', + 'segment_allocator.cpp', 'type.cpp') arch = 'corei7' diff --git a/controlplane/unittest/segment_allocator.cpp b/controlplane/unittest/segment_allocator.cpp new file mode 100644 index 00000000..0af3cf37 --- /dev/null +++ b/controlplane/unittest/segment_allocator.cpp @@ -0,0 +1,232 @@ +#include + +#include "controlplane/segment_allocator.h" + +static constexpr uint32_t error_result = 0; +using Allocator = SegmentAllocator<15, 6 * 64, 2 * 64, 64, error_result>; +using Errors = std::pair; +using BlockStat = std::tuple; + +BlockStat Block(const Allocator& allocator, uint16_t size) +{ + const auto& info = allocator.GetBlocksStat()[size]; + return {info.busy_blocks, info.used_blocks, info.used_segments}; +} + +TEST(SegmentAllocator, Simple) +{ + + Errors no_errors(0, 0); + + Allocator allocator; + + // Interval [15, 384), BlockSize = 128. + // 3 intervals [15, 143), [143, 271), [271, 384) - length of the last block = 113 < 128. + // Blocks 0,2 - the blocks will be used for segments of length 23, block 1 - 27. + // Capacity of blocks: 0 => [128/23] = 5, 1 => [128/27] = 4, 2 => [113/23] = 4. + + // -------------------------------------------------------------------------------------------- + // STEP 1: - Allocate segments, we will get results: + // len=23: Block 0 (15, 38, 61, 84, 107), Block 2 (271, 294, 317, 340) + // len=27: Block 1 (143, 170, 197, 224) + + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 3, 0)); + + EXPECT_EQ(allocator.Allocate(23), 15); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 2, 0)); // Block 0 for 23 + EXPECT_EQ(Block(allocator, 23), BlockStat(0, 1, 1)); + + EXPECT_EQ(allocator.Allocate(27), 143); // Block 1 for 27 + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 27), BlockStat(0, 1, 1)); + + EXPECT_EQ(allocator.Allocate(23), 38); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(0, 1, 2)); + + EXPECT_EQ(allocator.Allocate(23), 61); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(0, 1, 3)); + + EXPECT_EQ(allocator.Allocate(23), 84); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(0, 1, 4)); + + EXPECT_EQ(allocator.Allocate(23), 107); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 0, 5)); // Block 0 - busy + + EXPECT_EQ(allocator.Allocate(27), 170); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 27), BlockStat(0, 1, 2)); + + EXPECT_EQ(allocator.Allocate(27), 197); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + EXPECT_EQ(Block(allocator, 27), BlockStat(0, 1, 3)); + + EXPECT_EQ(allocator.Allocate(23), 271); // Block 2 for 23 + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 0, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 1, 6)); + + EXPECT_EQ(allocator.Allocate(23), 294); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 1, 7)); + + EXPECT_EQ(allocator.Allocate(27), 224); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 27), BlockStat(1, 0, 4)); // Block 1 - busy + + EXPECT_EQ(allocator.Allocate(23), 317); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 1, 8)); + + EXPECT_EQ(allocator.Allocate(27), 0); + EXPECT_EQ(allocator.GetErrors(), no_errors); + + EXPECT_EQ(allocator.Allocate(23), 340); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 23), BlockStat(2, 0, 9)); // Block 2 - busy + + EXPECT_EQ(allocator.Allocate(23), 0); + EXPECT_EQ(allocator.GetErrors(), no_errors); + + // Finish allocate: + // - no free blocks + // - len=23 (2 - busy blocks, 9 - segments) + // - len=27 (1 - busy block, 4 - segments) + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 0, 0)); + EXPECT_EQ(Block(allocator, 23), BlockStat(2, 0, 9)); + EXPECT_EQ(Block(allocator, 27), BlockStat(1, 0, 4)); + + // -------------------------------------------------------------------------------------------- + // STEP 2: - Release the length 23 segments (271, 294, 317, 340) from block 2 and then place + // the length 27 segments in it + + EXPECT_TRUE(allocator.Free(271, 23)); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 1, 8)); // Block 2 - in list 23 + EXPECT_TRUE(allocator.Free(294, 23)); + EXPECT_TRUE(allocator.Free(317, 23)); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 1, 6)); + + // release last segment of the length 23 + EXPECT_TRUE(allocator.Free(340, 23)); + EXPECT_EQ(Block(allocator, 23), BlockStat(1, 0, 5)); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); // Block 2 - free + + // start allocate segments len=27 + EXPECT_EQ(allocator.Allocate(27), 271); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 27), BlockStat(1, 1, 5)); // Block 2 for 27 + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 0, 0)); + + // Allocate other segments + EXPECT_EQ(allocator.Allocate(27), 298); + EXPECT_EQ(allocator.Allocate(27), 325); + EXPECT_EQ(allocator.Allocate(27), 352); + EXPECT_EQ(allocator.Allocate(27), 0); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 27), BlockStat(2, 0, 8)); + + // -------------------------------------------------------------------------------------------- + // STEP 3: - Release all segments + + // Block 2 + EXPECT_TRUE(allocator.Free(298, 27)); + EXPECT_TRUE(allocator.Free(352, 27)); + EXPECT_TRUE(allocator.Free(325, 27)); + EXPECT_TRUE(allocator.Free(271, 27)); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 27), BlockStat(1, 0, 4)); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 1, 0)); + + // Block 0 + EXPECT_TRUE(allocator.Free(15, 23)); + EXPECT_TRUE(allocator.Free(38, 23)); + EXPECT_TRUE(allocator.Free(61, 23)); + EXPECT_TRUE(allocator.Free(84, 23)); + EXPECT_TRUE(allocator.Free(107, 23)); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 23), BlockStat(0, 0, 0)); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 2, 0)); + + // Block 1 + EXPECT_TRUE(allocator.Free(143, 27)); + EXPECT_TRUE(allocator.Free(170, 27)); + EXPECT_TRUE(allocator.Free(197, 27)); + EXPECT_TRUE(allocator.Free(224, 27)); + EXPECT_EQ(allocator.GetErrors(), no_errors); + EXPECT_EQ(Block(allocator, 27), BlockStat(0, 0, 0)); + EXPECT_EQ(Block(allocator, 0), BlockStat(0, 3, 0)); + EXPECT_EQ(allocator.GetErrors(), no_errors); +} + +TEST(SegmentAllocator, BigSize) +{ + static constexpr uint32_t index_begin = 128; + static constexpr uint32_t index_end = 8 * 1024 * 1024; + using AllocatorBig = SegmentAllocator; + + uint8_t data[sizeof(AllocatorBig)]; + memset((void*)data, -1, sizeof(AllocatorBig)); + AllocatorBig* allocator = new (data) AllocatorBig(); + + uint16_t size = 4; + uint32_t full_size = index_end - index_begin; + for (uint32_t index = index_begin; index < index_end; index += size) + { + EXPECT_EQ(allocator->Allocate(size), index); + full_size -= size; + EXPECT_EQ(allocator->Size(), full_size); + } + + for (uint32_t index = index_begin; index < index_end; index += size) + { + EXPECT_TRUE(allocator->Free(index, size)); + full_size += size; + EXPECT_EQ(allocator->Size(), full_size); + } + + Errors no_errors(0, 0); + EXPECT_EQ(allocator->GetErrors(), no_errors); +} + +TEST(SegmentAllocator, OnlyErrors) +{ + Allocator allocator; + + EXPECT_EQ(allocator.Allocate(23), 15); + + EXPECT_EQ(allocator.Allocate(0), 0); // size = 0 + EXPECT_EQ(allocator.Allocate(65), 0); // size > 64 + EXPECT_EQ(allocator.GetErrors(), Errors(2, 0)); + + // 4 errors for this case: + // ((size == 0) || (size > MaxBufferSize) || (start >= IndexEnd) || (start < IndexBegin)) + EXPECT_FALSE(allocator.Free(50, 0)); + EXPECT_FALSE(allocator.Free(50, 65)); + EXPECT_FALSE(allocator.Free(0, 10)); + EXPECT_FALSE(allocator.Free(500, 0)); + EXPECT_EQ(allocator.GetErrors(), Errors(6, 0)); + + EXPECT_FALSE(allocator.Free(15, 27)); // segment size 27 != 23 + EXPECT_FALSE(allocator.Free(16, 23)); // segments starts at (15, 15+23, ...) + EXPECT_FALSE(allocator.Free(38, 23)); // segment free + EXPECT_EQ(allocator.GetErrors(), Errors(9, 0)); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 255ec3d09023c54c85641fb58a2789db549cb2bb Mon Sep 17 00:00:00 2001 From: Levon Akopian Date: Thu, 13 Jun 2024 12:42:32 +0300 Subject: [PATCH 004/195] Update readme: added instructions for mac --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 932559c1..612774a4 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ docker pull yanetplatform/builder Add alias for run commands on docker: ``` alias yanet-builder="docker run --rm -it -v /run/yanet:/run/yanet -v \$PWD:/project yanetplatform/builder" +(for Mac: alias yanet-builder="docker run --platform linux/amd64 --rm -it -v /run/yanet:/run/yanet -v \$PWD:/project yanetplatform/builder") ``` Once setup `build_autotest` directory: From acbea7c1a024a1478486b78bb224d6aff09619c6 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 23 Jul 2024 15:42:04 +0300 Subject: [PATCH 005/195] Improves logic of route.v4.lpm and route.v6.lpm reallocations. Closes: #237 Adds support of providing unique_ptr from memory_manager. Splits logic of create() that was previously not only creating but also resizing and copying data from old lpm member. --- dataplane/globalbase.cpp | 42 +++---- dataplane/lpm.h | 12 ++ dataplane/memory_manager.h | 40 +++++++ dataplane/updater.h | 238 ++++++++++--------------------------- 4 files changed, 131 insertions(+), 201 deletions(-) diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index e2327ff1..360c06f2 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -199,7 +199,7 @@ eResult generation::init() return result; } - route_lpm4 = updater.route_lpm4->pointer; + route_lpm4 = updater.route_lpm4->pointer(); } { @@ -212,7 +212,7 @@ eResult generation::init() return result; } - route_lpm6 = updater.route_lpm6->pointer; + route_lpm6 = updater.route_lpm6->pointer(); } { @@ -225,7 +225,7 @@ eResult generation::init() return result; } - route_tunnel_lpm4 = updater.route_tunnel_lpm4->pointer; + route_tunnel_lpm4 = updater.route_tunnel_lpm4->pointer(); } { @@ -238,7 +238,7 @@ eResult generation::init() return result; } - route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer; + route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer(); } return result; @@ -1775,22 +1775,15 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ { YADECAP_LOG_DEBUG("route lpm clear\n"); - result = updater.route_lpm4->clear(); - if (result != eResult::success) - { - return result; - } + updater.route_lpm4->clear(); + updater.route_lpm6->clear(); - result = updater.route_lpm6->clear(); - if (result != eResult::success) - { - return result; - } + return eResult::success; } } - route_lpm4 = updater.route_lpm4->pointer; - route_lpm6 = updater.route_lpm6->pointer; + route_lpm4 = updater.route_lpm4->pointer(); + route_lpm6 = updater.route_lpm6->pointer(); return result; } @@ -1947,22 +1940,15 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: { YADECAP_LOG_DEBUG("route_tunnel lpm clear\n"); - result = updater.route_tunnel_lpm4->clear(); - if (result != eResult::success) - { - return result; - } + updater.route_tunnel_lpm4->clear(); + updater.route_tunnel_lpm6->clear(); - result = updater.route_tunnel_lpm6->clear(); - if (result != eResult::success) - { - return result; - } + return eResult::success; } } - route_tunnel_lpm4 = updater.route_tunnel_lpm4->pointer; - route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer; + route_tunnel_lpm4 = updater.route_tunnel_lpm4->pointer(); + route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer(); return result; } diff --git a/dataplane/lpm.h b/dataplane/lpm.h index 51c82ce1..672f861c 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -48,6 +48,12 @@ class lpm4_24bit_8bit_atomic uint64_t extended_chunks_size; uint32_t max_used_chunk_id; tEntry free_chunk_cache; + void clear() + { + extended_chunks_count = 0; + max_used_chunk_id = 0; + free_chunk_cache.flags = 0; + } }; static uint64_t calculate_sizeof(const uint64_t extended_chunks_size) @@ -715,6 +721,12 @@ class lpm6_8x16bit_atomic uint64_t extended_chunks_size; uint32_t max_used_chunk_id; tEntry free_chunk_cache; + void clear() + { + extended_chunks_count = 0; + max_used_chunk_id = 0; + free_chunk_cache.flags = 0; + } }; static uint64_t calculate_sizeof(const uint64_t extended_chunks_size) diff --git a/dataplane/memory_manager.h b/dataplane/memory_manager.h index 78e006c0..35a76a6b 100644 --- a/dataplane/memory_manager.h +++ b/dataplane/memory_manager.h @@ -42,6 +42,45 @@ class memory_manager const uint64_t size, const std::function& destructor = [](void*) {}); + class Deleter + { + memory_manager* manager_; + + public: + Deleter(memory_manager* const manager) : + manager_{manager} {} + Deleter(Deleter&& other) = default; + Deleter(const Deleter& other) = default; + Deleter& operator=(Deleter&& other) = default; + Deleter& operator=(const Deleter& other) = default; + template + void operator()(T* ptr) + { + manager_->destroy(ptr); + } + }; + + template + using unique_ptr = std::unique_ptr; + + template + unique_ptr create_unique(const char* name, + const tSocketId socket_id, + const uint64_t size, + args_t&&... args) + { + void* pointer = alloc(name, + socket_id, + size, + [](void* pointer) { + reinterpret_cast(pointer)->~type(); + }); + return std::unique_ptr{ + new (pointer) type(std::forward(args)...), + Deleter{this}}; + } + template type* create(const char* name, @@ -114,6 +153,7 @@ class memory_manager void destroy(void* pointer); void debug(tSocketId socket_id); bool check_memory_limit(const std::string& name, const uint64_t size); + Deleter deleter() { return Deleter{this}; } protected: cDataPlane* dataplane; diff --git a/dataplane/updater.h b/dataplane/updater.h index f5f8ee6f..ee6591af 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -38,98 +38,83 @@ namespace dataplane } // - -class updater_lpm4_24bit_8bit +template +class updater_lpm { -public: - using object_type = lpm4_24bit_8bit_atomic; + [[nodiscard]] dataplane::memory_manager::unique_ptr Allocate(std::size_t size) + { + return memory_manager->create_unique(name.c_str(), + socket_id, + ObjectType::calculate_sizeof(size)); + } - updater_lpm4_24bit_8bit(const char* name, - dataplane::memory_manager* memory_manager, - const tSocketId socket_id) : +public: + using stats_t = typename ObjectType::stats_t; + updater_lpm(const char* name, + dataplane::memory_manager* memory_manager, + tSocketId socket_id) : name(name), memory_manager(memory_manager), socket_id(socket_id), - pointer(nullptr) + pointer_{nullptr, memory_manager->deleter()} { stats.extended_chunks_count = 0; - stats.extended_chunks_size = 0; stats.max_used_chunk_id = 0; stats.free_chunk_cache.flags = 0; } eResult init() { - return create(2 * object_type::extended_chunks_size_min); - } - - eResult create(const uint64_t extended_chunks_size) - { - auto* next_pointer = memory_manager->create(name.data(), - socket_id, - object_type::calculate_sizeof(extended_chunks_size)); - if (next_pointer == nullptr) + auto default_chunks_size = 2 * ObjectType::extended_chunks_size_min; + pointer_ = Allocate(default_chunks_size); + if (!pointer_) { - return eResult::errorAllocatingMemory; + stats.extended_chunks_size = default_chunks_size; + return eResult::success; } - - object_type::stats_t next_stats; - next_stats.extended_chunks_count = 0; - next_stats.extended_chunks_size = extended_chunks_size; - next_stats.max_used_chunk_id = 0; - next_stats.free_chunk_cache.flags = 0; - - if (pointer) + else { - next_pointer->copy(next_stats, stats, *pointer); - memory_manager->destroy(pointer); + return eResult::errorAllocatingMemory; } - - stats = next_stats; - pointer = next_pointer; - - return eResult::success; } - eResult insert(const uint32_t& ip_address, + eResult insert(const Address& ip_address, const uint8_t& mask, const uint32_t& value_id) { - if (stats.extended_chunks_size - stats.extended_chunks_count < object_type::extended_chunks_size_min) + if (NeedToGrow()) { - eResult result = create(stats.extended_chunks_size * 2); + eResult result = Resize(GrowSize()); if (result != eResult::success) { return result; } } - return pointer->insert(stats, ip_address, mask, value_id); + return pointer_->insert(stats, ip_address, mask, value_id); } - eResult remove(const uint32_t& ip_address, + eResult remove(const Address& ip_address, const uint8_t& mask) { - eResult result = eResult::success; - if (stats.extended_chunks_size - stats.extended_chunks_count < object_type::extended_chunks_size_min) + if (NeedToGrow()) { - result = create(stats.extended_chunks_size * 2); + eResult result = Resize(GrowSize()); if (result != eResult::success) { return result; } } - result = pointer->remove(stats, ip_address, mask); + eResult result = pointer_->remove(stats, ip_address, mask); if (result != eResult::success) { return result; } - if (stats.extended_chunks_size > 2 * object_type::extended_chunks_size_min && - stats.extended_chunks_count < stats.extended_chunks_size / 4) + if (NeedToShrink()) { - result = create(stats.extended_chunks_size / 2); + eResult result = Resize(ShrinkSize()); if (result != eResult::success) { return result; @@ -139,15 +124,17 @@ class updater_lpm4_24bit_8bit return result; } - eResult clear() + void clear() { - if (pointer) + if (pointer_) { - memory_manager->destroy(pointer); - pointer = nullptr; + pointer_->clear(); + stats.clear(); + if (NeedToShrink()) + { + Resize(2 * ObjectType::extended_chunks_size_min); + } } - - return create(2 * object_type::extended_chunks_size_min); } void limits(common::idp::limits::response& limits) const @@ -160,161 +147,66 @@ class updater_lpm4_24bit_8bit void report(nlohmann::json& report) const { - report["pointer"] = to_hex(pointer); + report["pointer"] = to_hex(pointer_.get()); report["extended_chunks_count"] = stats.extended_chunks_count; report["extended_chunks_size"] = stats.extended_chunks_size; } -protected: - std::string name; - dataplane::memory_manager* memory_manager; - tSocketId socket_id; - - object_type::stats_t stats; - -public: - object_type* pointer; -}; - -// - -class updater_lpm6_8x16bit -{ -public: - using object_type = lpm6_8x16bit_atomic; - - updater_lpm6_8x16bit(const char* name, - dataplane::memory_manager* memory_manager, - const tSocketId socket_id) : - name(name), - memory_manager(memory_manager), - socket_id(socket_id), - pointer(nullptr) + ObjectType* pointer() { - stats.extended_chunks_count = 0; - stats.extended_chunks_size = 0; - stats.max_used_chunk_id = 0; - stats.free_chunk_cache.flags = 0; + return pointer_.get(); } - eResult init() - { - return create(2 * object_type::extended_chunks_size_min); - } +private: + std::string name; + dataplane::memory_manager* memory_manager; + tSocketId socket_id; + stats_t stats; + dataplane::memory_manager::unique_ptr pointer_; - eResult create(const uint64_t extended_chunks_size) + eResult Resize(const std::size_t size) { - auto* next_pointer = memory_manager->create(name.data(), - socket_id, - object_type::calculate_sizeof(extended_chunks_size)); - if (next_pointer == nullptr) + memory_manager::unique_ptr next = Allocate(size); + if (!next) { return eResult::errorAllocatingMemory; } - object_type::stats_t next_stats; + stats_t next_stats; next_stats.extended_chunks_count = 0; - next_stats.extended_chunks_size = extended_chunks_size; + next_stats.extended_chunks_size = size; next_stats.max_used_chunk_id = 0; next_stats.free_chunk_cache.flags = 0; - if (pointer) - { - next_pointer->copy(next_stats, stats, *pointer); - memory_manager->destroy(pointer); - } - + next->copy(next_stats, stats, *pointer_); stats = next_stats; - pointer = next_pointer; - + std::swap(pointer_, next); return eResult::success; } - eResult insert(const std::array& ip_address, - const uint8_t& mask, - const uint32_t& value_id) - { - if (stats.extended_chunks_size - stats.extended_chunks_count < object_type::extended_chunks_size_min) - { - eResult result = create(stats.extended_chunks_size * 2); - if (result != eResult::success) - { - return result; - } - } - - return pointer->insert(stats, ip_address, mask, value_id); - } - - eResult remove(const std::array& ip_address, - const uint8_t& mask) + bool NeedToGrow() const { - eResult result = eResult::success; - if (stats.extended_chunks_size - stats.extended_chunks_count < object_type::extended_chunks_size_min) - { - result = create(stats.extended_chunks_size * 2); - if (result != eResult::success) - { - return result; - } - } - - result = pointer->remove(stats, ip_address, mask); - if (result != eResult::success) - { - return result; - } - - if (stats.extended_chunks_size > 2 * object_type::extended_chunks_size_min && - stats.extended_chunks_count < stats.extended_chunks_size / 4) - { - result = create(stats.extended_chunks_size / 2); - if (result != eResult::success) - { - return result; - } - } - - return result; + return stats.extended_chunks_size - stats.extended_chunks_count < ObjectType::extended_chunks_size_min; } - eResult clear() + std::size_t GrowSize() const { - if (pointer) - { - memory_manager->destroy(pointer); - pointer = nullptr; - } - - return create(2 * object_type::extended_chunks_size_min); + return stats.extended_chunks_size * 2; } - void limits(common::idp::limits::response& limits) const + std::size_t ShrinkSize() const { - limits.emplace_back(name + ".extended_chunks", - socket_id, - stats.extended_chunks_count, - stats.extended_chunks_size); + return stats.extended_chunks_size / 2; } - void report(nlohmann::json& report) const + bool NeedToShrink() const { - report["pointer"] = to_hex(pointer); - report["extended_chunks_count"] = stats.extended_chunks_count; - report["extended_chunks_size"] = stats.extended_chunks_size; + return ShrinkSize() > std::max(ObjectType::extended_chunks_size_min, GrowSize()); } - -protected: - std::string name; - dataplane::memory_manager* memory_manager; - tSocketId socket_id; - - object_type::stats_t stats; - -public: - object_type* pointer; }; +using updater_lpm4_24bit_8bit = updater_lpm; +using updater_lpm6_8x16bit = updater_lpm, lpm6_8x16bit_atomic>; // class updater_lpm4_24bit_8bit_id32 From eb8765a41048a845086e32c1f22a44853a351636 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 29 Jul 2024 21:14:08 +0300 Subject: [PATCH 006/195] Changes style to conform to google code style --- dataplane/memory_manager.h | 18 +++++------ dataplane/updater.h | 63 ++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/dataplane/memory_manager.h b/dataplane/memory_manager.h index 35a76a6b..14b51a58 100644 --- a/dataplane/memory_manager.h +++ b/dataplane/memory_manager.h @@ -63,21 +63,21 @@ class memory_manager template using unique_ptr = std::unique_ptr; - template - unique_ptr create_unique(const char* name, - const tSocketId socket_id, - const uint64_t size, - args_t&&... args) + template + unique_ptr create_unique(const char* name, + const tSocketId socket_id, + const uint64_t size, + Args&&... args) { void* pointer = alloc(name, socket_id, size, [](void* pointer) { - reinterpret_cast(pointer)->~type(); + reinterpret_cast(pointer)->~T(); }); - return std::unique_ptr{ - new (pointer) type(std::forward(args)...), + return std::unique_ptr{ + new (pointer) T(std::forward(args)...), Deleter{this}}; } diff --git a/dataplane/updater.h b/dataplane/updater.h index ee6591af..6f50d7b3 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -41,10 +41,10 @@ namespace dataplane template class updater_lpm { - [[nodiscard]] dataplane::memory_manager::unique_ptr Allocate(std::size_t size) + [[nodiscard]] memory_manager::unique_ptr Allocate(std::size_t size) { - return memory_manager->create_unique(name.c_str(), - socket_id, + return memory_manager_->create_unique(name_.c_str(), + socket_id_, ObjectType::calculate_sizeof(size)); } @@ -53,14 +53,14 @@ class updater_lpm updater_lpm(const char* name, dataplane::memory_manager* memory_manager, tSocketId socket_id) : - name(name), - memory_manager(memory_manager), - socket_id(socket_id), - pointer_{nullptr, memory_manager->deleter()} + name_(name), + memory_manager_(memory_manager), + socket_id_(socket_id), + pointer_{nullptr, memory_manager_->deleter()} { - stats.extended_chunks_count = 0; - stats.max_used_chunk_id = 0; - stats.free_chunk_cache.flags = 0; + stats_.extended_chunks_count = 0; + stats_.max_used_chunk_id = 0; + stats_.free_chunk_cache.flags = 0; } eResult init() @@ -68,14 +68,11 @@ class updater_lpm auto default_chunks_size = 2 * ObjectType::extended_chunks_size_min; pointer_ = Allocate(default_chunks_size); if (!pointer_) - { - stats.extended_chunks_size = default_chunks_size; - return eResult::success; - } - else { return eResult::errorAllocatingMemory; } + stats_.extended_chunks_size = default_chunks_size; + return eResult::success; } eResult insert(const Address& ip_address, @@ -91,7 +88,7 @@ class updater_lpm } } - return pointer_->insert(stats, ip_address, mask, value_id); + return pointer_->insert(stats_, ip_address, mask, value_id); } eResult remove(const Address& ip_address, @@ -106,7 +103,7 @@ class updater_lpm } } - eResult result = pointer_->remove(stats, ip_address, mask); + eResult result = pointer_->remove(stats_, ip_address, mask); if (result != eResult::success) { return result; @@ -129,7 +126,7 @@ class updater_lpm if (pointer_) { pointer_->clear(); - stats.clear(); + stats_.clear(); if (NeedToShrink()) { Resize(2 * ObjectType::extended_chunks_size_min); @@ -139,17 +136,17 @@ class updater_lpm void limits(common::idp::limits::response& limits) const { - limits.emplace_back(name + ".extended_chunks", - socket_id, - stats.extended_chunks_count, - stats.extended_chunks_size); + limits.emplace_back(name_ + ".extended_chunks", + socket_id_, + stats_.extended_chunks_count, + stats_.extended_chunks_size); } void report(nlohmann::json& report) const { report["pointer"] = to_hex(pointer_.get()); - report["extended_chunks_count"] = stats.extended_chunks_count; - report["extended_chunks_size"] = stats.extended_chunks_size; + report["extended_chunks_count"] = stats_.extended_chunks_count; + report["extended_chunks_size"] = stats_.extended_chunks_size; } ObjectType* pointer() @@ -158,10 +155,10 @@ class updater_lpm } private: - std::string name; - dataplane::memory_manager* memory_manager; - tSocketId socket_id; - stats_t stats; + std::string name_; + dataplane::memory_manager* memory_manager_; + tSocketId socket_id_; + stats_t stats_; dataplane::memory_manager::unique_ptr pointer_; eResult Resize(const std::size_t size) @@ -178,25 +175,25 @@ class updater_lpm next_stats.max_used_chunk_id = 0; next_stats.free_chunk_cache.flags = 0; - next->copy(next_stats, stats, *pointer_); - stats = next_stats; + next->copy(next_stats, stats_, *pointer_); + stats_ = next_stats; std::swap(pointer_, next); return eResult::success; } bool NeedToGrow() const { - return stats.extended_chunks_size - stats.extended_chunks_count < ObjectType::extended_chunks_size_min; + return stats_.extended_chunks_size - stats_.extended_chunks_count < ObjectType::extended_chunks_size_min; } std::size_t GrowSize() const { - return stats.extended_chunks_size * 2; + return stats_.extended_chunks_size * 2; } std::size_t ShrinkSize() const { - return stats.extended_chunks_size / 2; + return stats_.extended_chunks_size / 2; } bool NeedToShrink() const From 8961c0ae0244317a3a116796fba3f69ea26fd7fa Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 23 Jul 2024 17:26:07 +0300 Subject: [PATCH 007/195] Adds aborting if no ifaces 'interfacesRequired'. Closes: #236 --- dataplane/dataplane.cpp | 9 +++++++++ dataplane/dataplane.h | 1 + 2 files changed, 10 insertions(+) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 73b4db70..baf58035 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -528,9 +528,16 @@ eResult cDataPlane::initPorts() for (const auto& interface_name : remove_keys) { + YANET_LOG_ERROR("Failed to init interface '%s'\n", std::get<0>(config.ports.at(interface_name.c_str())).c_str()); config.ports.erase(interface_name); } + if (config.interfaces_required && config.ports.empty()) + { + YANET_LOG_ERROR("Failed to configure at least one interface\n"); + return eResult::errorInitEthernetDevice; + } + return eResult::success; } @@ -1558,6 +1565,8 @@ eResult cDataPlane::parseConfig(const std::string& configFilePath) config.use_kernel_interface = rootJson.find("use_kernel_interface").value(); } + config.interfaces_required = rootJson.value("interfacesRequired", config.interfaces_required); + if (rootJson.find("rateLimits") != rootJson.end()) { result = parseRateLimits(rootJson.find("rateLimits").value()); diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 1671bdac..f2c4b403 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -49,6 +49,7 @@ struct tDataPlaneConfig std::map> workers; bool useHugeMem = true; bool use_kernel_interface = true; + bool interfaces_required = true; uint64_t rssFlags = RTE_ETH_RSS_IP; uint32_t SWNormalPriorityRateLimitPerWorker = 0; uint32_t SWICMPOutRateLimit = 0; From b9a116db270b730f0908d4e7c4d0978b49cc9895 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Sat, 24 Aug 2024 14:55:12 +0300 Subject: [PATCH 008/195] Update build workflow --- .github/workflows/docker-image.yml | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 2301c70c..a884deb1 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -17,21 +17,8 @@ jobs: clang-format-version: '10' exclude-regex: .*\.proto - - build-image-builder: - needs: formatting-check - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v3 - - name: Build the yanetplatform/builder - run: | - cd image - # todo - - build-unittest: - needs: build-image-builder + needs: formatting-check runs-on: ubuntu-latest container: image: yanetplatform/builder-lite @@ -51,8 +38,8 @@ jobs: retention-days: 1 build-autotest: - needs: build-image-builder - runs-on: builder + needs: formatting-check + runs-on: ubuntu-latest container: image: yanetplatform/builder-lite steps: @@ -72,7 +59,7 @@ jobs: retention-days: 1 build: - needs: build-image-builder + needs: formatting-check runs-on: ubuntu-latest container: image: yanetplatform/builder-lite @@ -87,7 +74,7 @@ jobs: build-ubuntu1804: name: build (Ubuntu 18.04) - needs: build-image-builder + needs: formatting-check runs-on: ubuntu-latest container: image: yanetplatform/builder_ubuntu18.04-lite @@ -117,7 +104,7 @@ jobs: autotest-001_one_port: name: 001_one_port needs: build-autotest - runs-on: autotest + runs-on: ubuntu-latest container: image: yanetplatform/builder-lite steps: From df144cb62cd0e1a9a7393e2babd1e501b4b48082 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 16 May 2024 13:10:04 +0300 Subject: [PATCH 009/195] Change controlplane/src/acl.h to controlplane/acl.h in unwind.cpp I have no idea how that worked previously, we don't have an "src" folder in controlplane. --- unwind/unwind.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unwind/unwind.cpp b/unwind/unwind.cpp index 0fa8a3a9..1856b41f 100644 --- a/unwind/unwind.cpp +++ b/unwind/unwind.cpp @@ -12,8 +12,8 @@ #include #include "common/type.h" -#include "controlplane/src/acl.h" -#include "controlplane/src/acl/rule.h" +#include "controlplane/acl.h" +#include "controlplane/acl/rule.h" auto make_default_acl(tAclId aclId = 1) { From 07e2c722f623afce484c4ab72a380f2b8c384c60 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 20 May 2024 13:56:08 +0300 Subject: [PATCH 010/195] Turn static is_nonterm_action to a rule_t method is_term First of all, is_nonterm makes implementation a bit more complex, as everywhere we use !is_nonterm, which does not makes sense. It would be better to just use is_term instead. Next, we don't need this as a static function defined in acl.cpp, as acl_compiler.cpp also wants the same functionality to fill `rule.terminating` field. So we make this a rule_t method. --- controlplane/acl.cpp | 13 ++----------- controlplane/acl/rule.h | 10 ++++++++++ controlplane/acl_compiler.cpp | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index ebdaf3bb..18ed0bda 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -381,15 +381,6 @@ static inline auto is_term_filter(const ref_t& filter) return (!filter || (!filter->src && !filter->dst && !filter->flags && !filter->proto)); } -static inline auto is_nonterm_action(const std::variant& action) -{ - if (std::holds_alternative(action)) - { - return true; - } - return false; -} - // gather matching rules from dispatcher static bool unwind_dispatcher(const dispatcher_rules_t& dispatcher, const ref_t& filter, @@ -421,7 +412,7 @@ static bool unwind_dispatcher(const dispatcher_rules_t& dispatcher, ids.resize(idSize); ACL_DBGMSG("gathered..."); - if (is_term_filter(rule.filter) && !is_nonterm_action(rule.action)) + if (is_term_filter(rule.filter) && (rule.is_term() || rule.is_skipto())) { ACL_DBGMSG("terminating filter..."); break; @@ -507,7 +498,7 @@ static bool unwind(int64_t start_from, firewall_rules_t& fw, const dispatcher_ru } ids.resize(idSize); - if (is_term_filter(rule.filter) && !is_nonterm_action(rule.action)) + if (is_term_filter(rule.filter) && (rule.is_term() || rule.is_skipto())) { ACL_DBGMSG("terminating filter..."); return true; diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 8bc8c45b..46b8ac82 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1226,6 +1226,16 @@ struct rule_t { return action == o.action && filter == o.filter && log == o.log; } + + bool is_term() const + { + return std::holds_alternative(action); + } + + bool is_skipto() const + { + return std::holds_alternative(action); + } }; } //namespace acl diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index aa18f92d..42bf041f 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -286,7 +286,7 @@ void compiler_t::collect(const std::vector& unwind_rules) /// terminating { - rule.terminating = std::holds_alternative(unwind_rule.action); + rule.terminating = unwind_rule.is_term(); } YANET_LOG_DEBUG("acl::compile: rule: %s\n", unwind_rule.to_string().data()); From 7fbfcbb65854fe17ddf346e7b9a209dab359c39a Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 13 Jun 2024 22:38:08 +0300 Subject: [PATCH 011/195] Remove invalid dump rules on unwind step Previous code was ignoring rules with too large dump_id at value::compile step, but this can be done way earlier --- controlplane/acl.cpp | 30 +++++++++++++++++++++++------- controlplane/acl_value.cpp | 3 +-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 18ed0bda..f204ed61 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -874,9 +874,12 @@ std::vector unwind_used_rules(const std::map(rule.action)) { auto& flow = std::get(rule.action); @@ -916,15 +919,28 @@ std::vector unwind_used_rules(const std::map(rule.action); if (!action.dump_tag.empty()) { - auto it = result.tag_to_dump_id.find(action.dump_tag); - if (it == result.tag_to_dump_id.end()) + if (result.dump_id_to_tag.size() >= YANET_CONFIG_DUMP_ID_TO_TAG_SIZE) { - result.dump_id_to_tag.emplace_back(action.dump_tag); - it = result.tag_to_dump_id.emplace_hint(it, action.dump_tag, result.dump_id_to_tag.size()); + // We should remove this rule because the dump_id would exceed the limit + remove_rule = true; + } + else + { + auto it = result.tag_to_dump_id.find(action.dump_tag); + if (it == result.tag_to_dump_id.end()) + { + result.dump_id_to_tag.emplace_back(action.dump_tag); + it = result.tag_to_dump_id.emplace_hint(it, action.dump_tag, result.dump_id_to_tag.size()); + } + action.dump_id = it->second; } - action.dump_id = it->second; } } + + if (remove_rule) + rules_iter = rules.erase(rules_iter); + else + ++rules_iter; } auto [it, inserted] = rules_map.try_emplace(std::move(rules), aclId); diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index 0593abb0..c719dbb1 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -64,8 +64,7 @@ void value_t::compile() { if (auto action = std::get_if(&it)) { - if (dumps_counter >= YANET_CONFIG_DUMP_ID_SIZE || - action->dump_id >= YANET_CONFIG_DUMP_ID_TO_TAG_SIZE) + if (dumps_counter >= YANET_CONFIG_DUMP_ID_SIZE) { continue; } From 7d8b6792940d733e7484f288a5d01f81d6e4f2a1 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:06:31 +0300 Subject: [PATCH 012/195] Apply clang-format to controlplane/acl/rule.h --- controlplane/acl/rule.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 46b8ac82..b8100d20 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -88,8 +88,8 @@ struct ref_t /* inline ref_t(ref_t&& _ref) { - filter = _ref.filter; - _ref.filter = nullptr; + filter = _ref.filter; + _ref.filter = nullptr; } */ @@ -1238,7 +1238,7 @@ struct rule_t } }; -} //namespace acl +} // namespace acl namespace { From 56267463c8f72111bcedcc2f2d3d3e8380450bbf Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:12:54 +0300 Subject: [PATCH 013/195] Refactor rule_t: add rule_action alias and extract common init code Introduce rule_action alias for std::variant to simplify code that will be in the next commits. Removed code duplication by extracting common initialization logic into a separate method. --- controlplane/acl/rule.h | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index b8100d20..ad86c56c 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1028,10 +1028,18 @@ inline ref_t and_op(const ref_t& a, const ref_t& b const int64_t DISPATCHER = -1; +// TODO: When rewriting the current ACL library into LibFilter, we should consider not using repetitive variants +// to represent rule actions. Currently, we have this one, which is not even fully correct since it contains +// int64_t for representing a line number for the SKIPTO instruction, which is not a rule action in an unwound rule +// sense. +// +// Additionally, we might have another variant for representing rules that are suitable for execution in the dataplane. +using rule_action = std::variant; + struct rule_t { ref_t filter; - std::variant action; + rule_action action; ids_t ids; int64_t ruleno; mutable std::string text; @@ -1039,23 +1047,19 @@ struct rule_t std::set via; bool log; +private: + rule_t(const ref_t& _filter, rule_action _action, ids_t _ids, bool _log) : + filter(_filter), action(std::move(_action)), ids(std::move(_ids)), ruleno(DISPATCHER), log(_log) + {} + +public: rule_t(const ref_t& _filter, common::globalBase::tFlow flow, const ids_t& ids, bool log) : - filter(_filter), - action(flow), - ids(ids), - log(log) - { - ruleno = DISPATCHER; - } + rule_t(_filter, rule_action(flow), ids, log) + {} rule_t(const ref_t& _filter, common::acl::action_t action, const ids_t& ids, bool log) : - filter(_filter), - action(action), - ids(ids), - log(log) - { - ruleno = DISPATCHER; - } + rule_t(_filter, rule_action(action), ids, log) + {} rule_t(const ref_t& _filter, int64_t num, int64_t skipto) : filter(_filter), From cceab290b03a0160c608360faa416c115a8a5573 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:24:21 +0300 Subject: [PATCH 014/195] Extract action_t class from common/acl.h to new common/actions.h file It will be better to have all action-related definitions in a separate file --- common/acl.h | 48 ------------------------------- common/actions.h | 63 +++++++++++++++++++++++++++++++++++++++++ controlplane/acl/rule.h | 1 + 3 files changed, 64 insertions(+), 48 deletions(-) create mode 100644 common/actions.h diff --git a/common/acl.h b/common/acl.h index a4d4d852..388f2967 100644 --- a/common/acl.h +++ b/common/acl.h @@ -104,54 +104,6 @@ struct transport_key_t tAclGroupId network_flags : 8; }; -// class action_t is used to store all non-terminating rule data that -// shouldn't be stored in common::globalBase::tFlow -class action_t -{ -public: - action_t() : - dump_id(0), - dump_tag("") - {} - - action_t(std::string dump_tag) : - dump_id(0), - dump_tag(dump_tag) - {} - - inline bool operator==(const action_t& o) const - { - return std::tie(dump_id, dump_tag) == - std::tie(o.dump_id, o.dump_tag); - } - - inline bool operator!=(const action_t& o) const - { - return !operator==(o); - } - - constexpr bool operator<(const action_t& o) const - { - return std::tie(dump_id, dump_tag) < - std::tie(o.dump_id, o.dump_tag); - } - - void pop(stream_in_t& stream) - { - stream.pop(dump_id); - stream.pop(dump_tag); - } - - void push(stream_out_t& stream) const - { - stream.push(dump_id); - stream.push(dump_tag); - } - - uint64_t dump_id; - std::string dump_tag; -}; - struct total_key_t { constexpr bool operator<(const total_key_t& second) const diff --git a/common/actions.h b/common/actions.h new file mode 100644 index 00000000..f6e84e87 --- /dev/null +++ b/common/actions.h @@ -0,0 +1,63 @@ +#pragma once + +#include "stream.h" +#include + +namespace common +{ + +namespace acl +{ +// class action_t is used to store all non-terminating rule data that +// shouldn't be stored in common::globalBase::tFlow +// TODO: I don't think that storing all non-terminating rule data in one struct is a good thing. +// This will pollute the abstraction and the class size will grow when we will introduce new nonterminating +// kind of rules. I think that defining a new struct/class for each rule kind and then using it in an std::variant +// is a preffered approach. If so, then this class should not be called "action_t" and rather "dump_t". +class action_t +{ +public: + action_t() : + dump_id(0), + dump_tag("") + {} + + action_t(std::string dump_tag) : + dump_id(0), + dump_tag(std::move(dump_tag)) + {} + + inline bool operator==(const action_t& o) const + { + return std::tie(dump_id, dump_tag) == + std::tie(o.dump_id, o.dump_tag); + } + + inline bool operator!=(const action_t& o) const + { + return !operator==(o); + } + + constexpr bool operator<(const action_t& o) const + { + return std::tie(dump_id, dump_tag) < + std::tie(o.dump_id, o.dump_tag); + } + + void pop(stream_in_t& stream) + { + stream.pop(dump_id); + stream.pop(dump_tag); + } + + void push(stream_out_t& stream) const + { + stream.push(dump_id); + stream.push(dump_tag); + } + + uint64_t dump_id; + std::string dump_tag; +}; +} // namespace acl +} // namespace common diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index ad86c56c..d6e427b7 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -7,6 +7,7 @@ #include #include +#include "common/actions.h" #include "libfwparser/fw_parser.h" #include "network.h" From e7a72fa406e7354bbc24a176c6d5c7f9f2d1e1e8 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:17:19 +0300 Subject: [PATCH 015/195] Add new check-state action in unwind step Conveniently, parser tokens were already present in the codebase, so we don't have to change them. Although we discussed that we might want to enrich our ipfw syntax by allowing the check-state action to go with filters like `add check-state tcp from X to Y`, this is a task for a future improvement. For now, check-state rules do not hold any information aside from the fact that a check-state should occur. Therefore, the related structure does not have any fields and is effectively a minimal one-byte struct. Consequently, we need some value to uniquely identify and hash it. --- common/actions.h | 17 +++++++++++++++++ controlplane/acl.cpp | 9 +++++++++ controlplane/acl/rule.h | 21 ++++++++++++++++++++- controlplane/acl_compiler.cpp | 8 +++++++- libfwparser/fw_config.cpp | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/common/actions.h b/common/actions.h index f6e84e87..a8cc6940 100644 --- a/common/actions.h +++ b/common/actions.h @@ -59,5 +59,22 @@ class action_t uint64_t dump_id; std::string dump_tag; }; + +struct check_state_t +{ + // Unique identifier for hash calculation + static constexpr int64_t HASH_IDENTIFIER = 12345; + + bool operator==([[maybe_unused]] const check_state_t& o) const + { + return true; // TODO: why do we need this operator? + } + + constexpr bool operator<([[maybe_unused]] const check_state_t& o) const + { + return true; // TODO: why do we need this operator? + } +}; + } // namespace acl } // namespace common diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index f204ed61..e481bb0d 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -324,6 +324,7 @@ struct firewall_rules_t case ipfw::rule_action_t::ALLOW: case ipfw::rule_action_t::DUMP: case ipfw::rule_action_t::DENY: + case ipfw::rule_action_t::CHECKSTATE: { // handle only meaning rules auto& ruleref = yanet_rules.emplace_back(rulep, configp); @@ -488,6 +489,14 @@ static bool unwind(int64_t start_from, firewall_rules_t& fw, const dispatcher_ru log || rule.log); ACL_DBGMSG("tFlow gathered..."); } + else if (std::holds_alternative(rule.action)) + { + rules.emplace_back(std::move(result_filter), + std::get(rule.action), + ids, + log || rule.log); + ACL_DBGMSG("check_state gathered..."); + } else { rules.emplace_back(std::move(result_filter), diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index d6e427b7..bfc24a34 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1035,7 +1035,7 @@ const int64_t DISPATCHER = -1; // sense. // // Additionally, we might have another variant for representing rules that are suitable for execution in the dataplane. -using rule_action = std::variant; +using rule_action = std::variant; struct rule_t { @@ -1062,6 +1062,10 @@ struct rule_t rule_t(_filter, rule_action(action), ids, log) {} + rule_t(const ref_t& _filter, common::acl::check_state_t action, const ids_t& ids, bool log) : + rule_t(_filter, rule_action(action), ids, log) + {} + rule_t(const ref_t& _filter, int64_t num, int64_t skipto) : filter(_filter), action(skipto), @@ -1103,6 +1107,9 @@ struct rule_t case ipfw::rule_action_t::ALLOW: action = DISPATCHER; break; + case ipfw::rule_action_t::CHECKSTATE: + action = common::acl::check_state_t{}; + break; case ipfw::rule_action_t::DUMP: action = common::acl::action_t(std::get(rulep->action_arg)); break; @@ -1179,6 +1186,10 @@ struct rule_t text = "dump(" + rule_action.dump_tag + ")"; } } + else if (std::holds_alternative(action)) + { + text = "check-state"; + } else { auto arg = std::get(action); @@ -1356,6 +1367,14 @@ struct hash auto flow = std::get(r.action); hash_combine(h, 1, (uint64_t(flow.type) << 32) & flow.data.atomic); } + else if (std::holds_alternative(r.action)) + { + // Since check_state_t acts as a marker (either present or not), + // it doesn't have specific members to hash. + // To uniquely identify its presence in the hash, we use a + // predefined static constant as a unique identifier. + hash_combine(h, common::acl::check_state_t::HASH_IDENTIFIER); + } else { auto action = std::get(r.action); diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index 42bf041f..3b4a29ca 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -272,8 +272,10 @@ void compiler_t::collect(const std::vector& unwind_rules) rule.transport_table_filter_id)); } - /// value { + // FIXME: unwind_rule being const makes that we cannot use move semantics, even though at this point + // we don't need unwinded rules anymore. It will be nice to use moves, but this requires a little bit API + // tweaking. Move here does nothing, as this is a const pointer, so just passing by value if (auto flow = std::get_if(&unwind_rule.action)) { rule.value_filter_id = value.collect({*flow}); @@ -282,6 +284,10 @@ void compiler_t::collect(const std::vector& unwind_rules) { rule.value_filter_id = value.collect({*action}); } + else if (auto check_state = std::get_if(&unwind_rule.action)) + { + rule.value_filter_id = value.collect({*check_state}); + } } /// terminating diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index b8568b04..7e2f17d7 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -1098,6 +1098,7 @@ bool fw_config_t::validate_rule(rule_ptr_t rulep) case rule_action_t::DENY: case rule_action_t::SKIPTO: case rule_action_t::DUMP: + case rule_action_t::CHECKSTATE: break; default: return true; From 6a861dc4062504ea6e7cf5f656309e6c2039e725 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:42:04 +0300 Subject: [PATCH 016/195] Add TODO in stream* classes to remove DefaultConstructible restriction The class offers serialization/deserialization but is too restrictive. The `pop` method interface, which returns objects by reference in an argument, prevents usage with non-DefaultConstructible objects. This limitation means we cannot deserialize an object directly without first creating a default instance. --- common/stream.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/stream.h b/common/stream.h index 36413cd3..961ec9c0 100644 --- a/common/stream.h +++ b/common/stream.h @@ -16,6 +16,12 @@ namespace common { +// TODO: This class offers serialization/deserialization of objects, but it is too restrictive. +// Due to the pop method interface, which returns objects by reference in an argument, +// we cannot use this with non DefaultConstructible objects. +// This means that even though we serialize an object and want to deserialize it by +// creating an object directly, without needing to first create a default one, +// we are unable to do so. class stream_in_t { public: From 87b2363b18169a8297ca08d54a1adb2887f7847e Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:49:44 +0300 Subject: [PATCH 017/195] Use std::move instead of vector's swap method in acl_compiler.cpp The previous implementation used vector's swap method, which was a strange way to pass a vector without copying. Using std::move achieves the same result more appropriately by transferring ownership of the vector. --- controlplane/acl_compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index 3b4a29ca..b6bacd4c 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -101,7 +101,7 @@ void compiler_t::compile(const std::vector& unwind_rules, result.acl_total_table.emplace_back(key, value); } - result.acl_values.swap(value.vector); + result.acl_values = std::move(value.vector); YANET_LOG_INFO("acl::compile: done\n"); } From 4e54486a06f5513148e77bc767725f2b0b63eff3 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 15:58:40 +0300 Subject: [PATCH 018/195] Remove unused fileds in controlplane/acl_total_table.cpp These fields are unused so remove them --- controlplane/acl_total_table.cpp | 8 -------- controlplane/acl_total_table.h | 13 +------------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/controlplane/acl_total_table.cpp b/controlplane/acl_total_table.cpp index 7478d8ee..0edd04d8 100644 --- a/controlplane/acl_total_table.cpp +++ b/controlplane/acl_total_table.cpp @@ -12,16 +12,9 @@ total_table_t::total_table_t(compiler_t* compiler) : void total_table_t::clear() { table.clear(); - remap_group_ids.clear(); - group_id = 1; filters.clear(); filter_ids.clear(); - filter_id_by_rule_id.clear(); filter_id_group_ids.clear(); - bitmask.clear(); - map.clear(); - reverse_map.clear(); - reverse_map_next.clear(); } unsigned int total_table_t::collect(const unsigned int rule_id, const filter& filter) @@ -35,7 +28,6 @@ unsigned int total_table_t::collect(const unsigned int rule_id, const filter& fi it = filter_ids.emplace_hint(it, filter, filter_ids.size()); } - filter_id_by_rule_id.emplace_back(it->second); return it->second; } diff --git a/controlplane/acl_total_table.h b/controlplane/acl_total_table.h index db93de46..6ae3dd41 100644 --- a/controlplane/acl_total_table.h +++ b/controlplane/acl_total_table.h @@ -1,6 +1,5 @@ #pragma once -#include "acl/bitset.h" #include "acl_base.h" #include "common/acl.h" @@ -21,26 +20,16 @@ class total_table_t unsigned int collect(const unsigned int rule_id, const filter& filter); void prepare(); void compile(); - void compile_thread(const unsigned int thread_id, const unsigned int threads_count); + public: acl::compiler_t* compiler; std::map table; - std::vector remap_group_ids; - tAclGroupId group_id; - std::vector filters; std::map filter_ids; - std::vector filter_id_by_rule_id; std::vector> filter_id_group_ids; - - std::vector bitmask; /// @todo: bitmask_t - - std::unordered_map map; - std::map reverse_map; - std::map reverse_map_next; }; } From eb93fbe6b6aa73437d858a80ccd9e889fdb91af5 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 16:38:22 +0300 Subject: [PATCH 019/195] Remove mControlPlane class forward declaration in worker.h There are no such class anywhere whatsoever, so we don't need these lines too --- dataplane/worker.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/dataplane/worker.h b/dataplane/worker.h index e0352ee2..39363e79 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -19,8 +19,6 @@ #include "sharedmemory.h" class cDataPlane; -class mControlPlane; - namespace worker { @@ -224,7 +222,6 @@ class cWorker friend class cDataPlane; friend class cReport; friend class cControlPlane; - friend class mControlPlane; friend class dregress_t; friend class worker_gc_t; friend class dataplane::globalBase::generation; From a0b3ee85c87352367f6f635024a8ed42c4c229be Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 16:39:28 +0300 Subject: [PATCH 020/195] Remove cDataPlane class forward declaration in worker.h This class definition is provided by common/type.h anyway --- dataplane/worker.h | 1 - 1 file changed, 1 deletion(-) diff --git a/dataplane/worker.h b/dataplane/worker.h index 39363e79..994dfeb9 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -18,7 +18,6 @@ #include "samples.h" #include "sharedmemory.h" -class cDataPlane; namespace worker { From d47dc90db8ce96dfbdfb0bcd4b7f02936c54cfb8 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 17:10:41 +0300 Subject: [PATCH 021/195] Add new Actions class to replace old value_t class The value_t class previously represented a sequence of actions to be performed in the dataplane upon packet match. It contained a list of dump_ids and a flow (allow/deny/etc.), which was awkward as not all fields were necessary if certain rule types weren't matched. Additionally, adding new classes for new rule types was inconvenient. The new Actions class addresses these issues by storing a vector of "abstract" Actions that are matched and executed in the dataplane one by one, as intended. This makes the compilation of total_table (mapping from group_id to the actions to be performed for the packet) readable and efficient. --- common/actions.h | 253 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 1 deletion(-) diff --git a/common/actions.h b/common/actions.h index a8cc6940..45157c9e 100644 --- a/common/actions.h +++ b/common/actions.h @@ -1,7 +1,17 @@ #pragma once -#include "stream.h" #include +#include + +#include "common/type.h" +#include "config.release.h" +#include "stream.h" + +#define FIXME_ACTIONS 1 + +#if FIXME_ACTIONS +#include +#endif namespace common { @@ -77,4 +87,245 @@ struct check_state_t }; } // namespace acl + +// TODO: When rewriting the current ACL library into LibFilter, we could consider using inheritance. +// All "action" classes should implement some operators and pop/push methods, so it's beneficial to enforce this +// at the language level. However, if the same structures are used in the dataplane, it could impact performance +// due to extra pointer dereferences in vtable, if compiler does not succeed in devirtualization. +// Anyway, this is something to think about. + +/** + * @brief Represents an action that dumps packets to a specified ring. + * + * Only one DumpAction is allowed in an Actions object. + */ +struct DumpAction final +{ + // Maximum count of DumpAction objects allowed. + static constexpr size_t MAX_COUNT = YANET_CONFIG_DUMP_ID_SIZE; + // The identifier for the dump ring. + uint64_t dump_id; + + DumpAction(const acl::action_t& dump_action) : + dump_id(dump_action.dump_id){}; + + DumpAction() : + dump_id(0){}; + + void execute() const + { +#if FIXME_ACTIONS + std::cout << __PRETTY_FUNCTION__ << std::endl; + assert(false && "Semantics for actions are not implemented"); +#endif + } + + [[nodiscard]] bool terminating() const { return false; } + + void pop(stream_in_t& stream) + { + stream.pop(dump_id); + } + + void push(stream_out_t& stream) const + { + stream.push(dump_id); + } +}; + +/** + * @brief Represents an action that processes a packet flow. + * + * Only one FlowAction is allowed in an Actions object. + */ +struct FlowAction final +{ + // Maximum count of FlowAction objects allowed. + static constexpr size_t MAX_COUNT = 1; + // The flow associated with this action. + globalBase::tFlow flow; + + FlowAction(const globalBase::tFlow& flow) : + flow(flow){}; + + FlowAction(globalBase::tFlow&& flow) : + flow(std::move(flow)) {} + + FlowAction() : + flow(globalBase::tFlow()) {} + + void execute() const + { +#if FIXME_ACTIONS + std::cout << __PRETTY_FUNCTION__ << std::endl; + assert(false && "Semantics for actions are not implemented"); +#endif + } + + [[nodiscard]] bool terminating() const { return true; } + + void pop(stream_in_t& stream) + { + stream.pop(flow); + } + + void push(stream_out_t& stream) const + { + stream.push(flow); + } +}; + +/** + * @brief Represents an action that checks the dynamic firewall state. + * + * This class doesn't have any specific info to store, + * because check-state rule doesn't need anything. + * + * Only one CheckStateAction is allowed in an Actions object. + */ +struct CheckStateAction final +{ + static constexpr size_t MAX_COUNT = 1; + + CheckStateAction(const acl::check_state_t&){}; + CheckStateAction() = default; + + void execute() const + { +#if FIXME_ACTIONS + std::cout << __PRETTY_FUNCTION__ << std::endl; + assert(false && "Semantics for actions are not implemented"); +#endif + } + + [[nodiscard]] bool terminating() const { return false; } + + void pop(stream_in_t& stream) + { + stream.pop(reinterpret_cast(*this)); + } + + void push(stream_out_t& stream) const + { + stream.push(reinterpret_cast(*this)); + } +}; + +/** + * @brief Represents a generic action. + */ +struct Action +{ + std::variant raw_action; + + Action() : + raw_action(FlowAction()) {} + + template + Action(T action) : + raw_action(std::move(action)) {} + + void pop(stream_in_t& stream) + { + stream.pop(raw_action); + } + void push(stream_out_t& stream) const + { + stream.push(raw_action); + } + + void execute() const + { + std::visit([](const auto& act) { act.execute(); }, raw_action); + } +}; + +/** + * @brief Represents a collection of actions to be performed on a packet. + * + * The last rule in the path_ is always a terminating rule. + */ +class Actions +{ +private: + // The sequence of actions to be executed. + std::vector path_{}; + // Count of each type of action. + std::array> action_counts_ = {0}; + +public: + Actions() = default; + Actions(const Action& action) { add(action); }; + + void execute() const + { + for (const auto& action : path_) + { + action.execute(); + } + } + + void add(const Action& action) + { + size_t index = action.raw_action.index(); + + if (std::holds_alternative(action.raw_action)) + { + assert(action_counts_[index] == 0 && "Incorrectly requested to add more than one FlowAction"); + } + else + { + size_t max_count = std::visit([](auto&& arg) { return std::decay_t::MAX_COUNT; }, + action.raw_action); + if (action_counts_[index] >= max_count) + { + return; + } + } + + action_counts_[index]++; + path_.push_back(action); + } + + [[nodiscard]] const Action& get_last() const + { + assert(!path_.empty()); + return path_.back(); + } + + Action& get_last() + { + assert(!path_.empty()); + return path_.back(); + } + + [[nodiscard]] const common::globalBase::tFlow& get_flow() const + { + assert(std::holds_alternative(get_last().raw_action)); + return std::get(get_last().raw_action).flow; + } + + [[nodiscard]] common::globalBase::tFlow& get_flow() + { + assert(std::holds_alternative(get_last().raw_action)); + return std::get(get_last().raw_action).flow; + } + + // TODO: Why do we need it?.. + bool operator<(const Actions& second) const + { + return get_flow() < second.get_flow(); + } + + void pop(stream_in_t& stream) + { + stream.pop(path_); + } + + void push(stream_out_t& stream) const + { + stream.push(path_); + } +}; + } // namespace common From 39cf11b7c042b2932c781da7c41adfbd6a519568 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 16:32:55 +0300 Subject: [PATCH 022/195] Create a set to get all groups Total_table compile will use this. Idk if it's already presented. probably. Also, I think that we don't need groups to be ordered, we can just use vector, I guess (need to check this when semantics will be done, check whether all tests pass) --- controlplane/acl_transport_table.cpp | 1 + controlplane/acl_transport_table.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/controlplane/acl_transport_table.cpp b/controlplane/acl_transport_table.cpp index b6576dfc..c127f693 100644 --- a/controlplane/acl_transport_table.cpp +++ b/controlplane/acl_transport_table.cpp @@ -492,6 +492,7 @@ void transport_table::thread_t::populate() filter_id_group_ids[filter_id].emplace_back(i); group_id_filter_ids[i].emplace(filter_id); transport_table_filter_id_group_ids[filter_id].emplace_back(i); + all_groups.insert(i); } } } diff --git a/controlplane/acl_transport_table.h b/controlplane/acl_transport_table.h index 789b3197..caebf658 100644 --- a/controlplane/acl_transport_table.h +++ b/controlplane/acl_transport_table.h @@ -68,6 +68,9 @@ class thread_t std::vector> filter_id_group_ids; std::map> group_id_filter_ids; std::vector> transport_table_filter_id_group_ids; + // FIXME: I have a strong feeling that a containter with all groups should be already presented somewhere. + // Even if it does not, maybe all I need is a vector, since we don't have to order groups. + std::set all_groups; common::idp::updateGlobalBase::acl_transport_table::request acl_transport_table; From e35839a1ad5e722466415a544b5008ee23150b4f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 17:20:01 +0300 Subject: [PATCH 023/195] Use Actions instead of old value_t to represent actions for the packet The previous implementation used a `value_t` structure to represent actions required for packet processing. This approach was cumbersome when adding new functionality, as it required modifications to a monolithic structure. Changes: - Replaced `value_t` with a more flexible `Actions` structure. - Removed the outdated `value_t` definition and its associated methods. - Simplified the algorithm for filling {group_id, acl_id} by directly iterating over groups and not through each rule_id (time complexity has not changed, as we still need to iterate over all rule_ids, but we do that on "prepare" step now) Actions are now managed in a more modular and decoupled manner. --- common/acl.h | 28 -------- common/idp.h | 3 +- controlplane/acl_compiler.cpp | 23 +++--- controlplane/acl_rule.h | 1 - controlplane/acl_total_table.cpp | 119 +++++++++++++++---------------- controlplane/acl_total_table.h | 15 ++-- controlplane/acl_value.cpp | 63 ++++------------ controlplane/acl_value.h | 35 ++++++--- dataplane/globalbase.h | 2 +- 9 files changed, 113 insertions(+), 176 deletions(-) diff --git a/common/acl.h b/common/acl.h index 388f2967..fdc64871 100644 --- a/common/acl.h +++ b/common/acl.h @@ -116,34 +116,6 @@ struct total_key_t tAclGroupId transport_id; }; -struct value_t -{ - value_t() - { - memset(dump_ids, 0, sizeof(dump_ids)); - } - - constexpr bool operator<(const value_t& second) const - { - return flow < second.flow; - } - - void pop(stream_in_t& stream) - { - stream.pop(flow); - stream.pop(dump_ids); - } - - void push(stream_out_t& stream) const - { - stream.push(flow); - stream.push(dump_ids); - } - - common::globalBase::tFlow flow; - uint32_t dump_ids[YANET_CONFIG_DUMP_ID_SIZE]; -}; - template class range_t { diff --git a/common/idp.h b/common/idp.h index 3b2647e1..5fff9294 100644 --- a/common/idp.h +++ b/common/idp.h @@ -14,6 +14,7 @@ #include "acl.h" #include "balancer.h" +#include "common/actions.h" #include "config.h" #include "memory_manager.h" #include "neighbor.h" @@ -368,7 +369,7 @@ using request = std::vector>; namespace acl_values { -using request = std::vector; +using request = std::vector; } namespace dump_tags_ids diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index b6bacd4c..d33bd357 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -1,5 +1,6 @@ #include "acl_compiler.h" #include "acl_filter.h" +#include "acl_value.h" using namespace acl; @@ -266,11 +267,9 @@ void compiler_t::collect(const std::vector& unwind_rules) } /// total_table - { - rule.total_table_filter_id = total_table.collect(rule_id, - std::tie(rule.via_filter_id, - rule.transport_table_filter_id)); - } + total_table.collect(rule_id, + std::tie(rule.via_filter_id, + rule.transport_table_filter_id)); { // FIXME: unwind_rule being const makes that we cannot use move semantics, even though at this point @@ -278,15 +277,15 @@ void compiler_t::collect(const std::vector& unwind_rules) // tweaking. Move here does nothing, as this is a const pointer, so just passing by value if (auto flow = std::get_if(&unwind_rule.action)) { - rule.value_filter_id = value.collect({*flow}); + rule.value_filter_id = value.collect_initial_rule(*flow); } else if (auto action = std::get_if(&unwind_rule.action)) { - rule.value_filter_id = value.collect({*action}); + rule.value_filter_id = value.collect_initial_rule(*action); } else if (auto check_state = std::get_if(&unwind_rule.action)) { - rule.value_filter_id = value.collect({*check_state}); + rule.value_filter_id = value.collect_initial_rule(*check_state); } } @@ -307,7 +306,6 @@ void compiler_t::collect(const std::vector& unwind_rules) YANET_LOG_DEBUG("acl::compile: transport_filter_id: %u\n", rule.transport_filter_id); YANET_LOG_DEBUG("acl::compile: transport_table_filter_id: %u\n", rule.transport_table_filter_id); YANET_LOG_DEBUG("acl::compile: via_filter_id: %u\n", rule.via_filter_id); - YANET_LOG_DEBUG("acl::compile: total_table_filter_id: %u\n", rule.total_table_filter_id); YANET_LOG_DEBUG("acl::compile: value_filter_id: %u\n", rule.value_filter_id); } @@ -329,11 +327,8 @@ void compiler_t::collect(const std::vector& unwind_rules) YANET_LOG_INFO("acl::compile: transport_table.filters: %lu\n", transport_table.filters.size()); - YANET_LOG_INFO("acl::compile: total_table.filters: %lu\n", - total_table.filters.size()); - - YANET_LOG_INFO("acl::compile: value.filters: %lu\n", - value.filters.size()); + YANET_LOG_INFO("acl::compile: value.vector: %lu\n", + value.vector.size()); } void compiler_t::network_compile() diff --git a/controlplane/acl_rule.h b/controlplane/acl_rule.h index 1b500ec9..242df10b 100644 --- a/controlplane/acl_rule.h +++ b/controlplane/acl_rule.h @@ -22,7 +22,6 @@ class rule_t unsigned int transport_filter_id; unsigned int transport_table_filter_id; unsigned int via_filter_id; - unsigned int total_table_filter_id; unsigned int value_filter_id; bool terminating; }; diff --git a/controlplane/acl_total_table.cpp b/controlplane/acl_total_table.cpp index 0edd04d8..46191dc9 100644 --- a/controlplane/acl_total_table.cpp +++ b/controlplane/acl_total_table.cpp @@ -12,89 +12,84 @@ total_table_t::total_table_t(compiler_t* compiler) : void total_table_t::clear() { table.clear(); - filters.clear(); - filter_ids.clear(); - filter_id_group_ids.clear(); } -unsigned int total_table_t::collect(const unsigned int rule_id, const filter& filter) +void total_table_t::collect(const unsigned int rule_id, const filter& filter) { - (void)rule_id; - - auto it = filter_ids.find(filter); - if (it == filter_ids.end()) - { - filters.emplace_back(filter); - it = filter_ids.emplace_hint(it, filter, filter_ids.size()); - } - - return it->second; + auto [via_filter_id, transport_table_filter_id] = filter; + acl_rules_by_filter_id[transport_table_filter_id].emplace_back(rule_id, via_filter_id); } void total_table_t::prepare() { - filter_id_group_ids.resize(filter_ids.size()); + for (auto& thread : compiler->transport_table.threads) + { + for (auto group : thread.all_groups) + { + for (auto filter_id : thread.group_id_filter_ids[group]) + { + for (const auto& [rule_id, acl_id] : acl_rules_by_filter_id[filter_id]) + { + group_to_acl_rule_map[group][acl_id].insert(rule_id); + } + } + } + } } +/** + * @brief Compiles the total table by processing groups and their associated ACL rules. + * + * This function iterates through all threads, groups, and their respective ACL rules, + * and fills the total table with rules. The rules are processed until a terminating rule + * is encountered or all rules have been processed. If no terminating rule is found, a + * default "drop" action is appended at the end (see `value_t::compile()`). + */ void total_table_t::compile() { - common::acl::total_key_t key; - memset(&key, 0, sizeof(key)); + YANET_LOG_DEBUG("Compiling total table\n"); - for (const auto& rule : compiler->rules) + for (auto& thread : compiler->transport_table.threads) { - const auto filter_id = rule.total_table_filter_id; - const auto group_id = rule.value_filter_id; - - if (!filter_id_group_ids[filter_id].empty()) + for (auto group : thread.all_groups) { - continue; - } - - const auto& [acl_id, transport_table_filter_id] = filters[filter_id]; - /// @todo: acl_id -> via_filter_id + YANET_LOG_DEBUG("Processing group %u:\n", group); - key.acl_id = acl_id; - bool used = false; - for (const auto& thread : compiler->transport_table.threads) - { - for (const auto transport_table_group_id : thread.transport_table_filter_id_group_ids[transport_table_filter_id]) + auto& acl_rules_map = group_to_acl_rule_map[group]; + for (auto& [acl_id, rule_ids] : acl_rules_map) { - key.transport_id = transport_table_group_id; - auto it = table.find(key); - if (it == table.end()) - { - // If there is no such key in table, then we save [key, group_id] - // without any additional checks. - it = table.emplace_hint(it, key, group_id); - used = true; - } - else + common::acl::total_key_t key{acl_id, group}; + + YANET_LOG_DEBUG("\tFilling key {%u, %u}\n", key.transport_id, key.acl_id); + + // At this point there's nothing in this group hence we should add at least one rule. + // Do it here, cause there are a decent chance that there will be only one rule or it + // will be terminating, so the following loop will be unnecessary. + auto rule_iter = rule_ids.begin(); + const auto& first_rule = compiler->rules[*rule_iter]; + YANET_LOG_DEBUG("\t\tAdding rule %u\n", first_rule.rule_id); + table[key] = compiler->value.collect(first_rule.value_filter_id); + compiler->used_rules.push_back(first_rule.rule_id); + + if (first_rule.terminating) + continue; + + YANET_LOG_DEBUG("\t\tThat rule was not terminating, so continue\n"); + + for (++rule_iter; rule_iter != rule_ids.end(); ++rule_iter) { - // If table already has such key, then we are trying to collect - // new combination of the previous group_id and the current group_id. - // If new_group_id differs from the current group_id, then we replace - // the previous group_id with the new one. Otherwise we don't do anything. - const auto new_group_id = compiler->value.collect(it->second, group_id); - if (new_group_id != it->second) + const auto& rule = compiler->rules[*rule_iter]; + compiler->value.append_to_last(rule.value_filter_id); + compiler->used_rules.push_back(rule.rule_id); + YANET_LOG_DEBUG("\t\tAppending rule %u\n", rule.rule_id); + + if (rule.terminating) { - it->second = new_group_id; - used = true; + YANET_LOG_DEBUG("\t\tThat rule was terminating, so break from processing for this acl_id and group\n"); + break; } } - - if (rule.terminating && used) - { - // If the rule is termineting and has been used, then we mark filter_id - // as filled in to prevent further additional checks. - filter_id_group_ids[filter_id].emplace(it->second); - } } } - - if (used) - { - compiler->used_rules.emplace_back(rule.rule_id); - } } } diff --git a/controlplane/acl_total_table.h b/controlplane/acl_total_table.h index 6ae3dd41..b2b0becd 100644 --- a/controlplane/acl_total_table.h +++ b/controlplane/acl_total_table.h @@ -17,19 +17,16 @@ class total_table_t unsigned int>; ///< transport_table_filter_id void clear(); - unsigned int collect(const unsigned int rule_id, const filter& filter); + void collect(const unsigned int rule_id, const filter& filter); void prepare(); void compile(); - public: - acl::compiler_t* compiler; - - std::map table; + std::map table; - std::vector filters; - std::map filter_ids; - std::vector> filter_id_group_ids; +private: + acl::compiler_t* compiler; + std::unordered_map> acl_rules_by_filter_id; + std::unordered_map>> group_to_acl_rule_map; }; - } diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index c719dbb1..27143eb6 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -1,5 +1,4 @@ #include "acl_value.h" -#include "acl_compiler.h" using namespace acl::compiler; @@ -11,72 +10,38 @@ value_t::value_t() void value_t::clear() { vector.clear(); - filters.clear(); - filter_ids.clear(); + rule_actions.clear(); { /// @todo: find default_flow + common::globalBase::flow_t default_flow; default_flow.type = common::globalBase::eFlowType::drop; - collect({default_flow}); + collect_initial_rule(std::move(default_flow)); } } -unsigned int value_t::collect(const filter& filter) +unsigned int value_t::collect(unsigned int rule_action_id) { - auto it = filter_ids.find(filter); - if (it == filter_ids.end()) - { - filters.emplace_back(filter); - it = filter_ids.emplace_hint(it, filter, filter_ids.size()); - } - - return it->second; + vector.emplace_back(rule_actions[rule_action_id]); + return vector.size() - 1; } -// This collect function is only used in acl_total_table compiler to squash -// non-terminating and terminating rules into one unique group_id. -unsigned int value_t::collect(const tAclGroupId prev_id, const tAclGroupId id) +void value_t::append_to_last(unsigned int rule_action_id) { - unsigned int ret; - auto prev_filter = filters[prev_id]; - if (std::holds_alternative(prev_filter.back())) - { - ret = prev_id; - } - else - { - const auto& filter = filters[id]; - prev_filter.emplace_back(filter.back()); - ret = collect(prev_filter); - } - - return ret; + vector.back().add(rule_actions[rule_action_id]); } void value_t::compile() { - for (const auto& filter : filters) + for (auto& actions : vector) { - int dumps_counter = 0; - common::acl::value_t value; - for (const auto& it : filter) + auto last_action = actions.get_last(); + + if (!std::visit([](const auto& act) { return act.terminating(); }, last_action.raw_action)) { - if (auto action = std::get_if(&it)) - { - if (dumps_counter >= YANET_CONFIG_DUMP_ID_SIZE) - { - continue; - } - value.dump_ids[dumps_counter] = action->dump_id; - dumps_counter++; - } - else - { - value.flow = std::get(it); - } + // Adding default "drop" rule to the end + actions.add(rule_actions[0]); } - - vector.emplace_back(std::move(value)); } } diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 10350d9a..805e6efb 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -1,9 +1,6 @@ #pragma once -#include "acl_base.h" - -#include "common/acl.h" -#include "common/type.h" +#include "common/actions.h" namespace acl::compiler { @@ -14,18 +11,34 @@ class value_t value_t(); public: - using filter = std::vector>; - void clear(); - unsigned int collect(const filter& filter); - unsigned int collect(const tAclGroupId prev_id, const tAclGroupId id); + + template + unsigned int collect_initial_rule(T&& rule) + { + static_assert(std::is_same_v, common::globalBase::tFlow> || + std::is_same_v, common::acl::action_t> || + std::is_same_v, common::acl::check_state_t>, + "Unsupported type in rule_action"); + + rule_actions.emplace_back(std::forward(rule)); + return rule_actions.size() - 1; + } + + unsigned int collect(unsigned int rule_actions_id); + void compile(); public: - std::vector vector; + // FIXME: I don't like this name.. Why was it called like that previously? + std::vector vector; + + // FIXME: The initial objects are created using collect_inintial_rule and stored here. + // Then we create copies in vector. I've tried to use shared pointers and/or real pointers, + // but then a bunch of issues arise when serializing a `vector` with stream.push/pop + std::vector rule_actions; - std::vector filters; - std::map filter_ids; + void append_to_last(unsigned int rule_action_id); }; } diff --git a/dataplane/globalbase.h b/dataplane/globalbase.h index a8f6584c..1f7aaca7 100644 --- a/dataplane/globalbase.h +++ b/dataplane/globalbase.h @@ -70,7 +70,7 @@ using network_table = dataplane::updater_dynamic_table; using transport_layers = dataplane::updater_array; using transport_table = dataplane::updater_hashtable_mod_id32; using total_table = dataplane::updater_hashtable_mod_id32; -using values = dataplane::updater_array; +using values = dataplane::updater_array; } namespace nat64stateful From 677916c185c1bc43a736f9511856ae004b45d27c Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 2 Jul 2024 20:00:44 +0300 Subject: [PATCH 024/195] Rename common::acl::action_t to dump_t This structure lost it's meaning as one struct to store all non-terminating rule data. This is not a good thing anyway as tHis will pollute the abstraction and the class size will grow when we will introduce new nonterminating kind of rules. Defining a new struct/class for each rule kind and then using it in an std::variant is a preffered approach. Therefore this class should not be called "action_t" but rather "dump_t" --- common/actions.h | 20 +++++++------------- controlplane/acl.cpp | 8 ++++---- controlplane/acl/rule.h | 12 ++++++------ controlplane/acl_compiler.cpp | 4 ++-- controlplane/acl_value.h | 2 +- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/common/actions.h b/common/actions.h index 45157c9e..d7ffa084 100644 --- a/common/actions.h +++ b/common/actions.h @@ -18,37 +18,31 @@ namespace common namespace acl { -// class action_t is used to store all non-terminating rule data that -// shouldn't be stored in common::globalBase::tFlow -// TODO: I don't think that storing all non-terminating rule data in one struct is a good thing. -// This will pollute the abstraction and the class size will grow when we will introduce new nonterminating -// kind of rules. I think that defining a new struct/class for each rule kind and then using it in an std::variant -// is a preffered approach. If so, then this class should not be called "action_t" and rather "dump_t". -class action_t +class dump_t { public: - action_t() : + dump_t() : dump_id(0), dump_tag("") {} - action_t(std::string dump_tag) : + dump_t(std::string dump_tag) : dump_id(0), dump_tag(std::move(dump_tag)) {} - inline bool operator==(const action_t& o) const + inline bool operator==(const dump_t& o) const { return std::tie(dump_id, dump_tag) == std::tie(o.dump_id, o.dump_tag); } - inline bool operator!=(const action_t& o) const + inline bool operator!=(const dump_t& o) const { return !operator==(o); } - constexpr bool operator<(const action_t& o) const + constexpr bool operator<(const dump_t& o) const { return std::tie(dump_id, dump_tag) < std::tie(o.dump_id, o.dump_tag); @@ -106,7 +100,7 @@ struct DumpAction final // The identifier for the dump ring. uint64_t dump_id; - DumpAction(const acl::action_t& dump_action) : + DumpAction(const acl::dump_t& dump_action) : dump_id(dump_action.dump_id){}; DumpAction() : diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index e481bb0d..7e337291 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -500,10 +500,10 @@ static bool unwind(int64_t start_from, firewall_rules_t& fw, const dispatcher_ru else { rules.emplace_back(std::move(result_filter), - std::get(rule.action), + std::get(rule.action), ids, log || rule.log); - ACL_DBGMSG("action_t gathered..."); + ACL_DBGMSG("dump_t gathered..."); } ids.resize(idSize); @@ -923,9 +923,9 @@ std::vector unwind_used_rules(const std::map(rule.action)) + else if (std::holds_alternative(rule.action)) { - auto& action = std::get(rule.action); + auto& action = std::get(rule.action); if (!action.dump_tag.empty()) { if (result.dump_id_to_tag.size() >= YANET_CONFIG_DUMP_ID_TO_TAG_SIZE) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index bfc24a34..c3f4712d 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1035,7 +1035,7 @@ const int64_t DISPATCHER = -1; // sense. // // Additionally, we might have another variant for representing rules that are suitable for execution in the dataplane. -using rule_action = std::variant; +using rule_action = std::variant; struct rule_t { @@ -1058,7 +1058,7 @@ struct rule_t rule_t(_filter, rule_action(flow), ids, log) {} - rule_t(const ref_t& _filter, common::acl::action_t action, const ids_t& ids, bool log) : + rule_t(const ref_t& _filter, common::acl::dump_t action, const ids_t& ids, bool log) : rule_t(_filter, rule_action(action), ids, log) {} @@ -1111,7 +1111,7 @@ struct rule_t action = common::acl::check_state_t{}; break; case ipfw::rule_action_t::DUMP: - action = common::acl::action_t(std::get(rulep->action_arg)); + action = common::acl::dump_t(std::get(rulep->action_arg)); break; default: YANET_LOG_WARNING("unexpected rule action in rule '%s'\n", rulep->text.data()); @@ -1178,9 +1178,9 @@ struct rule_t text = "flow " + std::string(eFlowType_toString(flow.type)) + "(" + std::to_string(flow.data.atomic) + ")"; } } - else if (std::holds_alternative(action)) + else if (std::holds_alternative(action)) { - auto rule_action = std::get(action); + auto rule_action = std::get(action); if (!rule_action.dump_tag.empty()) { text = "dump(" + rule_action.dump_tag + ")"; @@ -1377,7 +1377,7 @@ struct hash } else { - auto action = std::get(r.action); + auto action = std::get(r.action); hash_combine(h, action.dump_id); } if (r.filter) diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index d33bd357..599421e9 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -279,9 +279,9 @@ void compiler_t::collect(const std::vector& unwind_rules) { rule.value_filter_id = value.collect_initial_rule(*flow); } - else if (auto action = std::get_if(&unwind_rule.action)) + else if (auto dump = std::get_if(&unwind_rule.action)) { - rule.value_filter_id = value.collect_initial_rule(*action); + rule.value_filter_id = value.collect_initial_rule(*dump); } else if (auto check_state = std::get_if(&unwind_rule.action)) { diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 805e6efb..b2e82a48 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -17,7 +17,7 @@ class value_t unsigned int collect_initial_rule(T&& rule) { static_assert(std::is_same_v, common::globalBase::tFlow> || - std::is_same_v, common::acl::action_t> || + std::is_same_v, common::acl::dump_t> || std::is_same_v, common::acl::check_state_t>, "Unsupported type in rule_action"); From e3e2cb174a6661c1c97197d8a76e47b14cbe6fb1 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 28 Jun 2024 17:03:46 +0300 Subject: [PATCH 025/195] Adjust unittests for changes in value_t structure Since value_t changed from a monolithic class with all data required to perform all matched actions on a packet to a vector of individual actions, we need to adjust unittests to use the new get_flow() method. --- controlplane/unittest/acl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 1ab63424..74fefa00 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -152,8 +152,8 @@ add 7 deny ip from any to any (void)total_table_key; const auto& value = result.acl_values[total_table_value]; - EXPECT_THAT(value.flow.counter_id, ::testing::Ge(1)); - EXPECT_THAT(value.flow.counter_id, ::testing::Lt(5)); + EXPECT_THAT(value.get_flow().counter_id, ::testing::Ge(1)); + EXPECT_THAT(value.get_flow().counter_id, ::testing::Lt(5)); } EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1, 2, 5)); @@ -182,7 +182,7 @@ add 2 allow ip from { 1.2.3.4 } to any in (void)total_table_key; const auto& value = result.acl_values[total_table_value]; - EXPECT_THAT(value.flow.type, ::testing::Eq(common::globalBase::eFlowType::drop)); + EXPECT_THAT(value.get_flow().type, ::testing::Eq(common::globalBase::eFlowType::drop)); } EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1)); @@ -357,7 +357,7 @@ add 300 deny ip from any to any for (const auto& [total_table_key, total_table_value] : result.acl_total_table) { (void)total_table_key; - EXPECT_THAT(result.acl_values[total_table_value].flow.flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); + EXPECT_THAT(result.acl_values[total_table_value].get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); } auto& ids_map = result.ids_map; From 8a0cdbda08704d1c15ec1b93f528cf5ddd03eb03 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 21 Jun 2024 18:01:14 +0300 Subject: [PATCH 026/195] Add semantics for Actions rules Add ActionDispatcher class to implement specific semantics for executing actions within the dataplane. FIXME: There is an uncertainty regarding the best way to execute actions in the dataplane, it involves passing numerous parameters to the execute method. --- common/actions.h | 48 ++--------- dataplane/action_dispatcher.h | 109 +++++++++++++++++++++++ dataplane/common.h | 6 ++ dataplane/worker.cpp | 157 ++-------------------------------- dataplane/worker.h | 8 ++ 5 files changed, 133 insertions(+), 195 deletions(-) create mode 100644 dataplane/action_dispatcher.h diff --git a/common/actions.h b/common/actions.h index d7ffa084..dcd20bd2 100644 --- a/common/actions.h +++ b/common/actions.h @@ -7,12 +7,6 @@ #include "config.release.h" #include "stream.h" -#define FIXME_ACTIONS 1 - -#if FIXME_ACTIONS -#include -#endif - namespace common { @@ -106,14 +100,6 @@ struct DumpAction final DumpAction() : dump_id(0){}; - void execute() const - { -#if FIXME_ACTIONS - std::cout << __PRETTY_FUNCTION__ << std::endl; - assert(false && "Semantics for actions are not implemented"); -#endif - } - [[nodiscard]] bool terminating() const { return false; } void pop(stream_in_t& stream) @@ -148,14 +134,6 @@ struct FlowAction final FlowAction() : flow(globalBase::tFlow()) {} - void execute() const - { -#if FIXME_ACTIONS - std::cout << __PRETTY_FUNCTION__ << std::endl; - assert(false && "Semantics for actions are not implemented"); -#endif - } - [[nodiscard]] bool terminating() const { return true; } void pop(stream_in_t& stream) @@ -184,14 +162,6 @@ struct CheckStateAction final CheckStateAction(const acl::check_state_t&){}; CheckStateAction() = default; - void execute() const - { -#if FIXME_ACTIONS - std::cout << __PRETTY_FUNCTION__ << std::endl; - assert(false && "Semantics for actions are not implemented"); -#endif - } - [[nodiscard]] bool terminating() const { return false; } void pop(stream_in_t& stream) @@ -227,11 +197,6 @@ struct Action { stream.push(raw_action); } - - void execute() const - { - std::visit([](const auto& act) { act.execute(); }, raw_action); - } }; /** @@ -251,14 +216,6 @@ class Actions Actions() = default; Actions(const Action& action) { add(action); }; - void execute() const - { - for (const auto& action : path_) - { - action.execute(); - } - } - void add(const Action& action) { size_t index = action.raw_action.index(); @@ -320,6 +277,11 @@ class Actions { stream.push(path_); } + + [[nodiscard]] const std::vector& get_actions() const + { + return path_; + } }; } // namespace common diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h new file mode 100644 index 00000000..184ded05 --- /dev/null +++ b/dataplane/action_dispatcher.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" +#include "metadata.h" +#include "worker.h" + +#include + +namespace dataplane +{ + +struct ActionDispatcherArgs +{ + cWorker* worker; + rte_mbuf* mbuf; + metadata* meta; + const base::generation* base; +}; + +template +struct ActionDispatcher +{ + static void execute(const common::Actions& actions, const ActionDispatcherArgs& args) + { + for (const auto& action : actions.get_actions()) + { + std::visit([&](const auto& act) { + execute(act, actions.get_flow(), args); + }, + action.raw_action); + } + } + + static void execute(const common::DumpAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + { + auto ring_id = args.base->globalBase->dump_id_to_tag[action.dump_id]; + if (ring_id == -1) + { + return; + } + + auto& ring = args.worker->dumpRings[ring_id]; + ring.write(args.mbuf, flow.type); + } + + static void execute(const common::FlowAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + { + auto worker = args.worker; + auto mbuf = args.mbuf; + + if (action.flow.type == common::globalBase::eFlowType::drop) + { + // Try to match against stateful dynamic rules. If so - a packet will be handled. + if constexpr (Direction == FlowDirection::Egress) + { + if (worker->acl_egress_try_keepstate(mbuf)) + { + return; + } + } + else + { + if (worker->acl_try_keepstate(mbuf)) + { + return; + } + } + } + + worker->aclCounters[action.flow.counter_id]++; + + tAclId acl_id = 0; + + if constexpr (Direction == FlowDirection::Egress) + { + acl_id = args.meta->aclId; + } + else + { + acl_id = args.meta->flow.data.aclId; + } + + if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) + { + worker->acl_log(mbuf, action.flow, acl_id); + } + if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) + { + worker->acl_create_keepstate(mbuf, acl_id, action.flow); + } + + if constexpr (Direction == FlowDirection::Egress) + { + worker->acl_egress_flow(mbuf, action.flow); + } + else + { + worker->acl_ingress_flow(mbuf, action.flow); + } + } + + static void execute([[maybe_unused]] const common::CheckStateAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, [[maybe_unused]] const ActionDispatcherArgs& args) + { + std::cout << "CheckStateAction matched" << std::endl; + // Implementation here + } +}; + +} // namespace dataplane diff --git a/dataplane/common.h b/dataplane/common.h index 2e0225eb..2dca6b62 100644 --- a/dataplane/common.h +++ b/dataplane/common.h @@ -99,4 +99,10 @@ namespace dataplane class memory_pointer; class memory_manager; +enum class FlowDirection +{ + Ingress, + Egress +}; + } diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index dc9b7f7b..3f7506ec 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -20,6 +20,7 @@ #include "common/fallback.h" #include "common/nat46clat.h" +#include "action_dispatcher.h" #include "checksum.h" #include "common.h" #include "dataplane.h" @@ -1543,44 +1544,7 @@ inline void cWorker::acl_ingress_handle4() const auto& value = acl.values[total_value]; - if (value.flow.type == common::globalBase::eFlowType::drop) - { - // Try to match against stateful dynamic rules. If so - a packet will be handled. - if (acl_try_keepstate(mbuf)) - { - continue; - } - } - - aclCounters[value.flow.counter_id]++; - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) - { - acl_log(mbuf, value.flow, metadata->flow.data.aclId); - } - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) - { - acl_create_keepstate(mbuf, metadata->flow.data.aclId, value.flow); - } - - for (auto dump_id : value.dump_ids) - { - if (dump_id == 0) - { - break; - } - - auto ring_id = base.globalBase->dump_id_to_tag[dump_id]; - if (ring_id == -1) - { - continue; - } - auto& ring = dumpRings[ring_id]; - ring.write(mbuf, value.flow.type); - } - - acl_ingress_flow(mbuf, value.flow); + dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); } acl_ingress_stack4.clear(); @@ -1734,44 +1698,7 @@ inline void cWorker::acl_ingress_handle6() const auto& value = acl.values[total_value]; - if (value.flow.type == common::globalBase::eFlowType::drop) - { - // Try to match against stateful dynamic rules. If so - a packet will be handled. - if (acl_try_keepstate(mbuf)) - { - continue; - } - } - - aclCounters[value.flow.counter_id]++; - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) - { - acl_log(mbuf, value.flow, metadata->flow.data.aclId); - } - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) - { - acl_create_keepstate(mbuf, metadata->flow.data.aclId, value.flow); - } - - for (auto dump_id : value.dump_ids) - { - if (dump_id == 0) - { - break; - } - - auto ring_id = base.globalBase->dump_id_to_tag[dump_id]; - if (ring_id == -1) - { - continue; - } - auto& ring = dumpRings[ring_id]; - ring.write(mbuf, value.flow.type); - } - - acl_ingress_flow(mbuf, value.flow); + dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); } acl_ingress_stack6.clear(); @@ -5311,44 +5238,7 @@ inline void cWorker::acl_egress_handle4() const auto& value = acl.values[total_value]; - if (value.flow.type == common::globalBase::eFlowType::drop) - { - // Try to match against stateful dynamic rules. If so - a packet will be handled. - if (acl_egress_try_keepstate(mbuf)) - { - continue; - } - } - - aclCounters[value.flow.counter_id]++; - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) - { - acl_log(mbuf, value.flow, metadata->aclId); - } - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) - { - acl_create_keepstate(mbuf, metadata->aclId, value.flow); - } - - for (auto dump_id : value.dump_ids) - { - if (dump_id == 0) - { - break; - } - - auto ring_id = base.globalBase->dump_id_to_tag[dump_id]; - if (ring_id == -1) - { - continue; - } - auto& ring = dumpRings[ring_id]; - ring.write(mbuf, value.flow.type); - } - - acl_egress_flow(mbuf, value.flow); + dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); } acl_egress_stack4.clear(); @@ -5495,44 +5385,7 @@ inline void cWorker::acl_egress_handle6() const auto& value = acl.values[total_value]; - if (value.flow.type == common::globalBase::eFlowType::drop) - { - // Try to match against stateful dynamic rules. If so - a packet will be handled. - if (acl_egress_try_keepstate(mbuf)) - { - continue; - } - } - - aclCounters[value.flow.counter_id]++; - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) - { - acl_log(mbuf, value.flow, metadata->aclId); - } - - if (value.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) - { - acl_create_keepstate(mbuf, metadata->aclId, value.flow); - } - - for (auto dump_id : value.dump_ids) - { - if (dump_id == 0) - { - break; - } - - auto ring_id = base.globalBase->dump_id_to_tag[dump_id]; - if (ring_id == -1) - { - continue; - } - auto& ring = dumpRings[ring_id]; - ring.write(mbuf, value.flow.type); - } - - acl_egress_flow(mbuf, value.flow); + dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); } acl_egress_stack6.clear(); diff --git a/dataplane/worker.h b/dataplane/worker.h index 994dfeb9..3144efb6 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -18,6 +18,12 @@ #include "samples.h" #include "sharedmemory.h" +namespace dataplane +{ +template +struct ActionDispatcher; +} + namespace worker { @@ -224,6 +230,8 @@ class cWorker friend class dregress_t; friend class worker_gc_t; friend class dataplane::globalBase::generation; + friend struct dataplane::ActionDispatcher; + friend struct dataplane::ActionDispatcher; cDataPlane* dataPlane; tCoreId coreId; From dd9769f60f89167cd1c1f0263b98fb204e82d1ae Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 1 Jul 2024 22:19:16 +0300 Subject: [PATCH 027/195] Update try_keepstate methods to return std::optional This change will help in implementing proper check-state semantics in the future. Previously, the code was checking state and immediately performing egress/ingress flow. With this update, we will retrieve the flow and perform it after executing nonterminating rules. --- dataplane/action_dispatcher.h | 6 ++++-- dataplane/worker.cpp | 33 +++++++++++++++------------------ dataplane/worker.h | 9 +++++---- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 184ded05..0494fc37 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -53,15 +53,17 @@ struct ActionDispatcher // Try to match against stateful dynamic rules. If so - a packet will be handled. if constexpr (Direction == FlowDirection::Egress) { - if (worker->acl_egress_try_keepstate(mbuf)) + if (auto flow = worker->acl_egress_try_keepstate(mbuf); flow) { + worker->acl_egress_flow(mbuf, flow.value()); return; } } else { - if (worker->acl_try_keepstate(mbuf)) + if (auto flow = worker->acl_try_keepstate(mbuf); flow) { + worker->acl_ingress_flow(mbuf, flow.value()); return; } } diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 3f7506ec..fe0449bc 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -4737,7 +4738,7 @@ inline void cWorker::balancer_icmp_forward_handle() balancer_icmp_forward_stack.clear(); } -inline bool cWorker::acl_try_keepstate(rte_mbuf* mbuf) +inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -4814,19 +4815,19 @@ inline bool cWorker::acl_try_keepstate(rte_mbuf* mbuf) return acl_try_keepstate(mbuf, value, locker); } - return false; + return std::nullopt; } -inline bool cWorker::acl_try_keepstate(rte_mbuf* mbuf, - dataplane::globalBase::fw_state_value_t* value, - dataplane::spinlock_nonrecursive_t* locker) +inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf, + dataplane::globalBase::fw_state_value_t* value, + dataplane::spinlock_nonrecursive_t* locker) { // Checking both value and locker for non-being-nullptr seems redundant. if (value == nullptr) { // No record found, the caller should continue as usual. locker->unlock(); - return false; + return std::nullopt; } uint8_t flags = 0; @@ -4845,9 +4846,7 @@ inline bool cWorker::acl_try_keepstate(rte_mbuf* mbuf, value->tcp.dst_flags |= flags; locker->unlock(); - // Handle the packet according its flow. - acl_ingress_flow(mbuf, flow); - return true; + return {flow}; } inline void cWorker::acl_create_keepstate(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow) @@ -5466,7 +5465,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc stats.logs_packets++; } -inline bool cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) +inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -5543,19 +5542,19 @@ inline bool cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) return acl_egress_try_keepstate(mbuf, value, locker); } - return false; + return std::nullopt; } -inline bool cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf, - dataplane::globalBase::fw_state_value_t* value, - dataplane::spinlock_nonrecursive_t* locker) +inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf, + dataplane::globalBase::fw_state_value_t* value, + dataplane::spinlock_nonrecursive_t* locker) { // Checking both value and locker for non-being-nullptr seems redundant. if (value == nullptr) { // No record found, the caller should continue as usual. locker->unlock(); - return false; + return std::nullopt; } uint8_t flags = 0; @@ -5574,9 +5573,7 @@ inline bool cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf, value->tcp.dst_flags |= flags; locker->unlock(); - // Handle the packet according its flow. - acl_egress_flow(mbuf, flow); - return true; + return {flow}; } inline void cWorker::acl_egress_flow(rte_mbuf* mbuf, const common::globalBase::tFlow& flow) diff --git a/dataplane/worker.h b/dataplane/worker.h index 3144efb6..c887fff4 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -183,10 +183,11 @@ class cWorker inline void balancer_touch_state(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::balancer_state_value_t* value); /// fw state - inline bool acl_try_keepstate(rte_mbuf* mbuf); - inline bool acl_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); - inline bool acl_egress_try_keepstate(rte_mbuf* mbuf); - inline bool acl_egress_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); + using FlowFromState = std::optional; + inline FlowFromState acl_try_keepstate(rte_mbuf* mbuf); + inline FlowFromState acl_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); + inline FlowFromState acl_egress_try_keepstate(rte_mbuf* mbuf); + inline FlowFromState acl_egress_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); inline void acl_create_keepstate(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow); inline void acl_state_emit(tAclId aclId, const dataplane::globalBase::fw_state_sync_frame_t& frame); From 94e9c795aa96013129fde3658e9ff35234e7febe Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 1 Jul 2024 22:22:57 +0300 Subject: [PATCH 028/195] Rename try_keepstate methods to checkstate Well, they are checking the state, so let's call them like that --- dataplane/action_dispatcher.h | 4 ++-- dataplane/worker.cpp | 24 ++++++++++++------------ dataplane/worker.h | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 0494fc37..f9852ba7 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -53,7 +53,7 @@ struct ActionDispatcher // Try to match against stateful dynamic rules. If so - a packet will be handled. if constexpr (Direction == FlowDirection::Egress) { - if (auto flow = worker->acl_egress_try_keepstate(mbuf); flow) + if (auto flow = worker->acl_egress_checkstate(mbuf); flow) { worker->acl_egress_flow(mbuf, flow.value()); return; @@ -61,7 +61,7 @@ struct ActionDispatcher } else { - if (auto flow = worker->acl_try_keepstate(mbuf); flow) + if (auto flow = worker->acl_checkstate(mbuf); flow) { worker->acl_ingress_flow(mbuf, flow.value()); return; diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index fe0449bc..ccb286ae 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -4738,7 +4738,7 @@ inline void cWorker::balancer_icmp_forward_handle() balancer_icmp_forward_stack.clear(); } -inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf) +inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -4776,7 +4776,7 @@ inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf) dataplane::spinlock_nonrecursive_t* locker; basePermanently.globalBaseAtomic->fw4_state->lookup(key, value, locker); - return acl_try_keepstate(mbuf, value, locker); + return acl_checkstate(mbuf, value, locker); } else if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { @@ -4812,15 +4812,15 @@ inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf) dataplane::spinlock_nonrecursive_t* locker; basePermanently.globalBaseAtomic->fw6_state->lookup(key, value, locker); - return acl_try_keepstate(mbuf, value, locker); + return acl_checkstate(mbuf, value, locker); } return std::nullopt; } -inline cWorker::FlowFromState cWorker::acl_try_keepstate(rte_mbuf* mbuf, - dataplane::globalBase::fw_state_value_t* value, - dataplane::spinlock_nonrecursive_t* locker) +inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf, + dataplane::globalBase::fw_state_value_t* value, + dataplane::spinlock_nonrecursive_t* locker) { // Checking both value and locker for non-being-nullptr seems redundant. if (value == nullptr) @@ -5465,7 +5465,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc stats.logs_packets++; } -inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) +inline cWorker::FlowFromState cWorker::acl_egress_checkstate(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -5503,7 +5503,7 @@ inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) dataplane::spinlock_nonrecursive_t* locker; basePermanently.globalBaseAtomic->fw4_state->lookup(key, value, locker); - return acl_egress_try_keepstate(mbuf, value, locker); + return acl_egress_checkstate(mbuf, value, locker); } else if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { @@ -5539,15 +5539,15 @@ inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf) dataplane::spinlock_nonrecursive_t* locker; basePermanently.globalBaseAtomic->fw6_state->lookup(key, value, locker); - return acl_egress_try_keepstate(mbuf, value, locker); + return acl_egress_checkstate(mbuf, value, locker); } return std::nullopt; } -inline cWorker::FlowFromState cWorker::acl_egress_try_keepstate(rte_mbuf* mbuf, - dataplane::globalBase::fw_state_value_t* value, - dataplane::spinlock_nonrecursive_t* locker) +inline cWorker::FlowFromState cWorker::acl_egress_checkstate(rte_mbuf* mbuf, + dataplane::globalBase::fw_state_value_t* value, + dataplane::spinlock_nonrecursive_t* locker) { // Checking both value and locker for non-being-nullptr seems redundant. if (value == nullptr) diff --git a/dataplane/worker.h b/dataplane/worker.h index c887fff4..c178ba5e 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -184,10 +184,10 @@ class cWorker /// fw state using FlowFromState = std::optional; - inline FlowFromState acl_try_keepstate(rte_mbuf* mbuf); - inline FlowFromState acl_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); - inline FlowFromState acl_egress_try_keepstate(rte_mbuf* mbuf); - inline FlowFromState acl_egress_try_keepstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); + inline FlowFromState acl_checkstate(rte_mbuf* mbuf); + inline FlowFromState acl_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); + inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf); + inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); inline void acl_create_keepstate(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow); inline void acl_state_emit(tAclId aclId, const dataplane::globalBase::fw_state_sync_frame_t& frame); From 77d6ff148409d8c32847699c2d4751b570ab7203 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 3 Jul 2024 18:16:17 +0300 Subject: [PATCH 029/195] Implement check-state semantics This commit implements proper check-state semantics for the packet processing logic: Introduced the `BaseActions` class with two specializations: - `BaseActions`: Handles action sequences that contain a check-state action. - `BaseActions`: Handles action sequences that do not contain a check-state action. Updated the `ActionDispatcher` to use `std::variant` to differentiate between `BaseActions` and `BaseActions`. This reduces runtime branching by making compile-time decisions. Refactored the `execute_impl` method in `ActionDispatcher` to check the state and decide the action path based on the presence of a check-state action. If a check-state action is present and the state check succeeds, it executes the check-state path. The final flow action is handled by the CheckStateAction execute method. --- common/actions.h | 150 ++++++++++++++++++++++++++++++---- controlplane/acl_value.cpp | 23 ++++-- controlplane/acl_value.h | 3 + dataplane/action_dispatcher.h | 63 ++++++++++++-- 4 files changed, 210 insertions(+), 29 deletions(-) diff --git a/common/actions.h b/common/actions.h index dcd20bd2..77142cee 100644 --- a/common/actions.h +++ b/common/actions.h @@ -199,20 +199,26 @@ struct Action } }; +namespace acl +{ /** - * @brief Represents a collection of actions to be performed on a packet. + * This struct is used for an intermediate representation of an object that + * describes a list of actions that needs to be performed on a packet that matched some group. + * + * Such objects are created in total_table_t::compile. * - * The last rule in the path_ is always a terminating rule. + * This representation is intermediate cause the Actions objects that are we going to use in dataplane + * will have slightly different representation of the internal vector based on whether we have + * a "check-state" action or not. This way we can reduce a number of branching in the dataplane and + * also reduce the size of the object since we will use std::variant to hold either a "check-state"-object, + * or a regular one (see common::Actions definition below) */ -class Actions +struct Actions { -private: - // The sequence of actions to be executed. - std::vector path_{}; - // Count of each type of action. - std::array> action_counts_ = {0}; + std::vector path{}; + std::array> action_counts = {0}; + std::optional check_state_index{}; -public: Actions() = default; Actions(const Action& action) { add(action); }; @@ -222,21 +228,44 @@ class Actions if (std::holds_alternative(action.raw_action)) { - assert(action_counts_[index] == 0 && "Incorrectly requested to add more than one FlowAction"); + assert(action_counts[index] == 0 && "Incorrectly requested to add more than one FlowAction"); } else { size_t max_count = std::visit([](auto&& arg) { return std::decay_t::MAX_COUNT; }, action.raw_action); - if (action_counts_[index] >= max_count) + if (action_counts[index] >= max_count) { return; } } - action_counts_[index]++; - path_.push_back(action); + if (std::holds_alternative(action.raw_action)) + { + check_state_index = path.size(); + } + + action_counts[index]++; + path.push_back(action); } +}; + +} // namespace acl + +template +class BaseActions; + +template<> +class BaseActions +{ +private: + std::vector path_{}; + +public: + BaseActions() = default; + + BaseActions(acl::Actions&& actions) : + path_(std::move(actions.path)) {} [[nodiscard]] const Action& get_last() const { @@ -250,6 +279,11 @@ class Actions return path_.back(); } + [[nodiscard]] const std::vector& get_actions() const + { + return path_; + } + [[nodiscard]] const common::globalBase::tFlow& get_flow() const { assert(std::holds_alternative(get_last().raw_action)); @@ -262,8 +296,7 @@ class Actions return std::get(get_last().raw_action).flow; } - // TODO: Why do we need it?.. - bool operator<(const Actions& second) const + bool operator<(const BaseActions& second) const { return get_flow() < second.get_flow(); } @@ -277,11 +310,98 @@ class Actions { stream.push(path_); } +}; + +template<> +class BaseActions +{ +private: + std::vector path_{}; + // TODO: This is a prefix of a path_, in C++-20 I would use std::span to avoid extra copying + std::vector check_state_path_{}; + +public: + BaseActions() = default; + BaseActions(acl::Actions&& actions) + { + assert(actions.check_state_index.has_value()); + auto check_state_index = static_cast(actions.check_state_index.value()); + + path_ = std::move(actions.path); + + // check_state_path_ is the prefix up to the check-state action inclusively + check_state_path_.assign(path_.begin(), path_.begin() + check_state_index + 1); + + // Remove the check-state action from the main path_ + path_.erase(path_.begin() + check_state_index); + } [[nodiscard]] const std::vector& get_actions() const { return path_; } + + [[nodiscard]] const std::vector& get_check_state_actions() const + { + return check_state_path_; + } + + [[nodiscard]] const Action& get_last() const + { + assert(!path_.empty()); + return path_.back(); + } + + Action& get_last() + { + assert(!path_.empty()); + return path_.back(); + } + + [[nodiscard]] const common::globalBase::tFlow& get_flow() const + { + assert(std::holds_alternative(get_last().raw_action)); + return std::get(get_last().raw_action).flow; + } + + [[nodiscard]] common::globalBase::tFlow& get_flow() + { + assert(std::holds_alternative(get_last().raw_action)); + return std::get(get_last().raw_action).flow; + } + + bool operator<(const BaseActions& second) const + { + return get_flow() < second.get_flow(); + } + + void pop(stream_in_t& stream) + { + stream.pop(path_); + stream.pop(check_state_path_); + } + + void push(stream_out_t& stream) const + { + stream.push(path_); + stream.push(check_state_path_); + } }; +/** + * The Actions type is defined as a std::variant to efficiently handle two possible states of action sequences: + * - BaseActions: This specialization is used when the action sequence contains a check-state action. + * - BaseActions: This specialization is used when the action sequence does not contain a check-state action. + * + * This approach allows us to avoid runtime branching to check for the presence of a check-state action, thereby + * enhancing performance. Instead, the decision is made once when constructing the Actions object. + * + * During packet processing in the dataplane, this enables a more efficient execution path, as the + * type of Actions being processed (with or without check-state) can be resolved at compile time using std::visit. + * We will still have one extra branch on packet cause we need to know whether it will require a check-state, but + * that will be only once. Once the result of a check-state is determined, we will choose correct path and execute it + * without any additional checks. + */ +using Actions = std::variant, BaseActions>; + } // namespace common diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index 27143eb6..7ecf6085 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -9,7 +9,7 @@ value_t::value_t() void value_t::clear() { - vector.clear(); + intermediate_vector.clear(); rule_actions.clear(); { @@ -23,25 +23,34 @@ void value_t::clear() unsigned int value_t::collect(unsigned int rule_action_id) { - vector.emplace_back(rule_actions[rule_action_id]); - return vector.size() - 1; + intermediate_vector.emplace_back(rule_actions[rule_action_id]); + return intermediate_vector.size() - 1; } void value_t::append_to_last(unsigned int rule_action_id) { - vector.back().add(rule_actions[rule_action_id]); + intermediate_vector.back().add(rule_actions[rule_action_id]); } void value_t::compile() { - for (auto& actions : vector) + for (auto& intermediate_actions : intermediate_vector) { - auto last_action = actions.get_last(); + auto last_action = intermediate_actions.path.back(); if (!std::visit([](const auto& act) { return act.terminating(); }, last_action.raw_action)) { // Adding default "drop" rule to the end - actions.add(rule_actions[0]); + intermediate_actions.add(rule_actions[0]); + } + + if (intermediate_actions.check_state_index.has_value()) + { + vector.emplace_back(common::BaseActions(std::move(intermediate_actions))); + } + else + { + vector.emplace_back(common::BaseActions(std::move(intermediate_actions))); } } } diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index b2e82a48..0aff3e4e 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -30,6 +30,9 @@ class value_t void compile(); public: + // FIXME: I don't like this name.. Why was it called like that previously? + std::vector intermediate_vector; + // FIXME: I don't like this name.. Why was it called like that previously? std::vector vector; diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index f9852ba7..03f0aa81 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -4,8 +4,6 @@ #include "metadata.h" #include "worker.h" -#include - namespace dataplane { @@ -22,10 +20,55 @@ struct ActionDispatcher { static void execute(const common::Actions& actions, const ActionDispatcherArgs& args) { - for (const auto& action : actions.get_actions()) + std::visit([&](const auto& specific_actions) { + execute_impl(specific_actions, args); + }, + actions); + } + + /** + * Determine the correct path to execute based on the presence of a check-state action. + * + * If HasCheckState is true and the state check succeeds, + * it executes the check_state_path_ and then returns. + * Otherwise, it executes the regular path. The egress/ingress flow + * is handled by the CheckStateAction execute method. + */ + template + static void execute_impl(const common::BaseActions& actions, const ActionDispatcherArgs& args) + { + if constexpr (HasCheckState) + { + auto worker = args.worker; + auto mbuf = args.mbuf; + cWorker::FlowFromState flow; + + if constexpr (Direction == FlowDirection::Egress) + { + flow = worker->acl_egress_checkstate(mbuf); + } + else + { + flow = worker->acl_checkstate(mbuf); + } + + if (flow) + { + execute_path(actions.get_check_state_actions(), flow.value(), args); + return; + } + } + + // Execute regular path + execute_path(actions.get_actions(), actions.get_flow(), args); + } + + static void execute_path(const std::vector& actions, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + { + for (const auto& action : actions) { std::visit([&](const auto& act) { - execute(act, actions.get_flow(), args); + execute(act, flow, args); }, action.raw_action); } @@ -101,10 +144,16 @@ struct ActionDispatcher } } - static void execute([[maybe_unused]] const common::CheckStateAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, [[maybe_unused]] const ActionDispatcherArgs& args) + static void execute([[maybe_unused]] const common::CheckStateAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) { - std::cout << "CheckStateAction matched" << std::endl; - // Implementation here + if constexpr (Direction == FlowDirection::Egress) + { + args.worker->acl_egress_flow(args.mbuf, flow); + } + else + { + args.worker->acl_ingress_flow(args.mbuf, flow); + } } }; From 2005d2b50aab5e7bd4b481942e6db60898d99ba3 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 8 Jul 2024 14:47:46 +0300 Subject: [PATCH 030/195] Remove check-state from IgnoredOptions test check-state is no longer an ignored option --- controlplane/unittest/parser.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/controlplane/unittest/parser.cpp b/controlplane/unittest/parser.cpp index ae21e320..fa912554 100644 --- a/controlplane/unittest/parser.cpp +++ b/controlplane/unittest/parser.cpp @@ -219,12 +219,10 @@ TEST(Parser, 020_IgnoredOptions) { const auto rules = R"IPFW( # just ignore antispoof, diverted, logamount, tag, tagged, -# check-state add allow tcp from 10.0.0.0/8 to 10.0.0.0/8 80 in antispoof add 65534 allow ip from any to any diverted keep-state add deny log logamount 500 all from any to any add allow tag 653 ip4 from { 10.0.0.0/8 } to me -add check-state add allow ip from any to any tagged 31000 add skipto :HELP ip from any to any not tagged 63 )IPFW"; From 3fff4846d359973b202cf78bd07b1eae29fea842 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 3 Jul 2024 19:02:08 +0300 Subject: [PATCH 031/195] Update unittests to handle std::variant in acl_values Changed unittests to use std::visit for accessing get_flow() due to acl_values now being a std::variant of BaseActions and BaseActions. --- controlplane/unittest/acl.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 74fefa00..3a2f4d04 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -152,8 +152,8 @@ add 7 deny ip from any to any (void)total_table_key; const auto& value = result.acl_values[total_table_value]; - EXPECT_THAT(value.get_flow().counter_id, ::testing::Ge(1)); - EXPECT_THAT(value.get_flow().counter_id, ::testing::Lt(5)); + std::visit([&](const auto& actions) { EXPECT_THAT(actions.get_flow().counter_id, ::testing::Ge(1)); }, value); + std::visit([&](const auto& actions) { EXPECT_THAT(actions.get_flow().counter_id, ::testing::Lt(5)); }, value); } EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1, 2, 5)); @@ -182,7 +182,10 @@ add 2 allow ip from { 1.2.3.4 } to any in (void)total_table_key; const auto& value = result.acl_values[total_table_value]; - EXPECT_THAT(value.get_flow().type, ::testing::Eq(common::globalBase::eFlowType::drop)); + std::visit([&](const auto& actions) { + EXPECT_THAT(actions.get_flow().type, ::testing::Eq(common::globalBase::eFlowType::drop)); + }, + value); } EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1)); @@ -357,7 +360,10 @@ add 300 deny ip from any to any for (const auto& [total_table_key, total_table_value] : result.acl_total_table) { (void)total_table_key; - EXPECT_THAT(result.acl_values[total_table_value].get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); + std::visit([&](const auto& actions) { + EXPECT_THAT(actions.get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); + }, + result.acl_values[total_table_value]); } auto& ids_map = result.ids_map; From 75621244df0c65cc5c6b0a030b16b8e02609901c Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 3 Jul 2024 21:17:47 +0300 Subject: [PATCH 032/195] Add unittests for check-state functionality These tests ensure that: - The BaseActions specialization is used when check-state is present. - The check-state path includes the check-state action at the end. - The regular path does not include the check-state action. - We're ignoring multiple check-states and only looking at the first one. --- controlplane/unittest/acl.cpp | 111 ++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 3a2f4d04..db5f5b28 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -480,4 +480,115 @@ add 200 deny ip from any to any EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny")); } +TEST(ACL, 019_CheckStateBasic) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add 100 check-state +add 200 allow ip from { 1.2.3.4 } to any +add 300 deny ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + for (const auto& [total_table_key, total_table_value] : result.acl_total_table) + { + (void)total_table_key; + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path does not include the check-state action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_FALSE(std::holds_alternative(actions.get_actions()[0].raw_action)); + + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + +TEST(ACL, 020_ManyCheckStates) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add 100 check-state +add 200 dump ring1 ip from { 1.2.3.4 } to any +add 300 check-state +add 400 deny ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + // We're interested in second group, i.e the group where src ip is { 1.2.3.4 } + auto total_table_value = std::get<1>(result.acl_total_table[1]); + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the actions after the first and second check-states + EXPECT_THAT(actions.get_actions().size(), 2); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[1].raw_action)); + + // Check that the check-state path includes the first check-state action and no other actions + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); +} + +TEST(ACL, 021_CheckStateComplex) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add 100 dump ring1 ip from { 1.2.3.4 } to any +add 200 check-state +add 300 dump ring2 ip from { 1.2.3.4 } to any +add 500 check-state +add 500 deny ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + // We're interested in second group, i.e the group where src ip is { 1.2.3.4 } + auto total_table_value = std::get<1>(result.acl_total_table[1]); + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes actions before and after the check-state + EXPECT_THAT(actions.get_actions().size(), 3); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[1].raw_action)); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[2].raw_action)); + + // Check that the check-state path includes actions up to and including the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 2); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[0].raw_action)); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[1].raw_action)); + } + }, + value); +} + } // namespace From ab8f8c27c559cb592270e4e54f98d030926c4228 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 3 Jul 2024 21:58:54 +0300 Subject: [PATCH 033/195] Add to_string methods for new Action classes Makes it easier to debug --- common/actions.h | 24 ++++++++++++++++++++++++ common/type.h | 11 +++++++++++ dataplane/action_dispatcher.h | 3 +++ 3 files changed, 38 insertions(+) diff --git a/common/actions.h b/common/actions.h index 77142cee..cebbcc5b 100644 --- a/common/actions.h +++ b/common/actions.h @@ -111,6 +111,13 @@ struct DumpAction final { stream.push(dump_id); } + + [[nodiscard]] std::string to_string() const + { + std::ostringstream oss; + oss << "DumpAction(dump_id=" << dump_id << ")"; + return oss.str(); + } }; /** @@ -145,6 +152,13 @@ struct FlowAction final { stream.push(flow); } + + [[nodiscard]] std::string to_string() const + { + std::ostringstream oss; + oss << "FlowAction(flow=" << flow.to_string() << ")"; + return oss.str(); + } }; /** @@ -173,6 +187,11 @@ struct CheckStateAction final { stream.push(reinterpret_cast(*this)); } + + [[nodiscard]] std::string to_string() const + { + return "CheckStateAction()"; + } }; /** @@ -197,6 +216,11 @@ struct Action { stream.push(raw_action); } + + [[nodiscard]] std::string to_string() const + { + return std::visit([](auto&& action) { return action.to_string(); }, raw_action); + } }; namespace acl diff --git a/common/type.h b/common/type.h index 898a3f11..e3f0d28e 100644 --- a/common/type.h +++ b/common/type.h @@ -2365,6 +2365,17 @@ class tFlow stream.push(reinterpret_cast(*this)); } + [[nodiscard]] std::string to_string() const + { + std::ostringstream oss; + oss << "tFlow { type: " << eFlowType_toString(type) + << ", flags: " << static_cast(flags) + << ", counter_id: " << counter_id + << ", data: { atomic: " << data.atomic + << " } }"; + return oss.str(); + } + public: union { diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 03f0aa81..ac7aad1e 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -52,6 +52,8 @@ struct ActionDispatcher flow = worker->acl_checkstate(mbuf); } + YANET_LOG_DEBUG("Check state was matched and state was%s found\n", flow ? "" : " not"); + if (flow) { execute_path(actions.get_check_state_actions(), flow.value(), args); @@ -68,6 +70,7 @@ struct ActionDispatcher for (const auto& action : actions) { std::visit([&](const auto& act) { + YANET_LOG_DEBUG("Executing action %s\n", act.to_string().c_str()); execute(act, flow, args); }, action.raw_action); From 5d12f9a03d1af89f3166646ba4e32982291dcb8b Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 16 Apr 2024 13:27:23 +0300 Subject: [PATCH 034/195] Add class encapsulating creation/destruction of kernel interfaces --- common/type.h | 1 + dataplane/kernel_interface_handle.cpp | 157 ++++++++++++++++++++++++++ dataplane/kernel_interface_handle.h | 70 ++++++++++++ dataplane/meson.build | 1 + 4 files changed, 229 insertions(+) create mode 100644 dataplane/kernel_interface_handle.cpp create mode 100644 dataplane/kernel_interface_handle.h diff --git a/common/type.h b/common/type.h index e3f0d28e..558433e9 100644 --- a/common/type.h +++ b/common/type.h @@ -21,6 +21,7 @@ using tCoreId = uint32_t; using tSocketId = uint32_t; using tPortId = uint16_t; +constexpr tPortId INVALID_PORT_ID = std::numeric_limits::max(); using tQueueId = uint8_t; using tCounterId = uint32_t; using tLogicalPortId = uint32_t; diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp new file mode 100644 index 00000000..d27f4d50 --- /dev/null +++ b/dataplane/kernel_interface_handle.cpp @@ -0,0 +1,157 @@ +#include +#include +#include + +#include + +#include "kernel_interface_handle.h" +namespace dataplane +{ + +bool KernelInterfaceHandle::SetUp() const +{ + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (socket < 0) + { + return false; + } + + struct ifreq request; + memset(&request, 0, sizeof request); + + strncpy(request.ifr_name, m_vdev_name.data(), IFNAMSIZ); + + request.ifr_flags |= IFF_UP; + if (auto res = ioctl(socket, SIOCSIFFLAGS, &request)) + { + YANET_LOG_ERROR("failed to set interface %s up, ioctl returned (%d)", m_vdev_name.data(), res); + return false; + } + return true; +} + +KernelInterfaceHandle::~KernelInterfaceHandle() +{ + if (Valid()) + Remove(); +} +KernelInterfaceHandle::KernelInterfaceHandle(KernelInterfaceHandle&& other) +{ + *this = std::move(other); +} +bool KernelInterfaceHandle::Start() const +{ + auto rc = rte_eth_dev_start(m_kni_port); + if (rc) + { + YADECAP_LOG_ERROR("can't start eth dev(%d, %d): %s\n", + rc, + rte_errno, + rte_strerror(rte_errno)); + return false; + } + return true; +} + +KernelInterfaceHandle& KernelInterfaceHandle::operator=(KernelInterfaceHandle&& other) +{ + if (this != &other) + { + std::swap(m_kni_port, other.m_kni_port); + std::swap(m_vdev_name, other.m_vdev_name); + } + return *this; +} + +std::string KernelInterfaceHandle::vdevArgs(const std::string& name, const tPortId port_id, uint64_t queue_size) +{ + rte_ether_addr ether_addr; + rte_eth_macaddr_get(port_id, ðer_addr); + std::stringstream ss; + ss << "path=/dev/vhost-net" + << ",queues=1" + << ",queue_size=" << queue_size + << ",iface=" << name.data() + << ",mac=" << common::mac_address_t(ether_addr.addr_bytes).toString().data(); + return ss.str(); +} + +bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& args) +{ + if (rte_eal_hotplug_add("vdev", vdev_name.data(), args.data()) != 0) + { + YADECAP_LOG_ERROR("failed to hotplug vdev interface '%s' with '%s'\n", + vdev_name.data(), + args.data()); + return false; + } + + if (rte_eth_dev_get_port_by_name(vdev_name.data(), &m_kni_port) != 0) + { + YADECAP_LOG_ERROR("vdev interface '%s' not found\n", vdev_name.data()); + return false; + } + return true; +} +void KernelInterfaceHandle::Remove() +{ + rte_eal_hotplug_remove("vdev", m_vdev_name.data()); + MarkInvalid(); +} + +bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) +{ + int ret = rte_eth_dev_configure(m_kni_port, + 1, + 1, + ð_conf); + if (ret < 0) + { + YADECAP_LOG_ERROR("rte_eth_dev_configure() = %d\n", ret); + return false; + } + return true; +} +bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) const +{ + uint16_t mtu; + if (rte_eth_dev_get_mtu(port_id, &mtu) != 0) + return false; + + rte_eth_dev_set_mtu(m_kni_port, mtu); + return true; +} + +bool KernelInterfaceHandle::SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) +{ + int rc = rte_eth_rx_queue_setup(m_kni_port, + queue, + m_queue_size, + socket, + nullptr, + mempool); + if (rc < 0) + { + YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", m_kni_port, 0, rc); + return false; + } + + return true; +} +bool KernelInterfaceHandle::SetupTxQueue(tQueueId queue, tSocketId socket) +{ + int rc = rte_eth_tx_queue_setup(m_kni_port, + queue, + m_queue_size, + socket, + nullptr); + if (rc < 0) + { + YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", m_kni_port, 0, rc); + return false; + } + + return true; +} + +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/kernel_interface_handle.h b/dataplane/kernel_interface_handle.h new file mode 100644 index 00000000..ea519ebb --- /dev/null +++ b/dataplane/kernel_interface_handle.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "common.h" +#include "common/type.h" + +namespace dataplane +{ + +class KernelInterfaceHandle +{ + tPortId m_kni_port = INVALID_PORT_ID; + std::string m_vdev_name; + uint16_t m_queue_size = 0; + + KernelInterfaceHandle() noexcept = default; + +public: + ~KernelInterfaceHandle(); + KernelInterfaceHandle(const KernelInterfaceHandle&) = delete; + KernelInterfaceHandle(KernelInterfaceHandle&& other) noexcept; + [[nodiscard]] static std::optional + MakeKernelInterfaceHandle( + const std::string& name, + tPortId port, + uint16_t queue_size) + { + KernelInterfaceHandle kni; + kni.m_queue_size = queue_size; + kni.m_vdev_name = vdevName(name, port); + std::string vdev_args = vdevArgs(name, port, queue_size); + if (!kni.Add(kni.m_vdev_name, vdev_args) || + !kni.Configure(DefaultConfig())) + { + return std::nullopt; + } + + return std::optional{std::move(kni)}; + } + const tPortId& Id() const noexcept { return m_kni_port; } + bool Start() const noexcept; + KernelInterfaceHandle& operator=(const KernelInterfaceHandle&) = delete; + KernelInterfaceHandle& operator=(KernelInterfaceHandle&& other) noexcept; + [[nodiscard]] bool SetUp() const; + bool SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); + bool SetupTxQueue(tQueueId queue, tSocketId socket); + +private: + static std::string vdevName(const std::string& name, const tPortId port_id) + { + std::stringstream ss; + ss << "virtio_user_" << name << "_" << port_id; + return ss.str(); + } + static std::string vdevArgs(const std::string& name, const tPortId port_id, uint64_t queue_size); + bool Add(const std::string& vdev_name, const std::string& args); + void Remove(); + static rte_eth_conf DefaultConfig() + { + rte_eth_conf eth_conf; + memset(ð_conf, 0, sizeof(eth_conf)); + return eth_conf; + } + bool Configure(const rte_eth_conf& eth_conf) noexcept; + bool CloneMTU(const uint16_t) const; + void MarkInvalid() { m_kni_port = INVALID_PORT_ID; } + [[nodiscard]] bool Valid() { return m_kni_port != INVALID_PORT_ID; } +}; +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/meson.build b/dataplane/meson.build index f3599582..b7bb20d1 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -10,6 +10,7 @@ sources = files('bus.cpp', 'debug_latch.cpp', 'dregress.cpp', 'fragmentation.cpp', + 'kernel_interface_handle.cpp', 'globalbase.cpp', 'main.cpp', 'memory_manager.cpp', From e2d168d751fe8b079160dbda11fe4833734c2e10 Mon Sep 17 00:00:00 2001 From: vimes Date: Fri, 26 Apr 2024 18:05:11 +0300 Subject: [PATCH 035/195] Adds separate class for kernel interface handler --- dataplane/dpdk.h | 16 ++ dataplane/kernel_interface_handle.cpp | 92 ++++++++--- dataplane/kernel_interface_handle.h | 66 +++----- dataplane/kernel_interface_handler.cpp | 219 +++++++++++++++++++++++++ dataplane/kernel_interface_handler.h | 103 ++++++++++++ dataplane/meson.build | 1 + 6 files changed, 426 insertions(+), 71 deletions(-) create mode 100644 dataplane/dpdk.h create mode 100644 dataplane/kernel_interface_handler.cpp create mode 100644 dataplane/kernel_interface_handler.h diff --git a/dataplane/dpdk.h b/dataplane/dpdk.h new file mode 100644 index 00000000..ba6ad3fd --- /dev/null +++ b/dataplane/dpdk.h @@ -0,0 +1,16 @@ +#pragma once +#include + +namespace dpdk +{ + +struct Endpoint +{ + tPortId port; + tQueueId queue; + Endpoint() = default; + Endpoint(tPortId port, tQueueId queue) : + port{port}, queue{queue} {} +}; + +} // namespace dpdk \ No newline at end of file diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp index d27f4d50..90d4c108 100644 --- a/dataplane/kernel_interface_handle.cpp +++ b/dataplane/kernel_interface_handle.cpp @@ -4,11 +4,12 @@ #include +#include "common.h" #include "kernel_interface_handle.h" namespace dataplane { -bool KernelInterfaceHandle::SetUp() const +bool KernelInterfaceHandle::SetUp() const noexcept { int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) @@ -19,12 +20,12 @@ bool KernelInterfaceHandle::SetUp() const struct ifreq request; memset(&request, 0, sizeof request); - strncpy(request.ifr_name, m_vdev_name.data(), IFNAMSIZ); + strncpy(request.ifr_name, vdev_name_.data(), IFNAMSIZ); request.ifr_flags |= IFF_UP; if (auto res = ioctl(socket, SIOCSIFFLAGS, &request)) { - YANET_LOG_ERROR("failed to set interface %s up, ioctl returned (%d)", m_vdev_name.data(), res); + YANET_LOG_ERROR("failed to set interface %s up, ioctl returned (%d)", vdev_name_.data(), res); return false; } return true; @@ -35,13 +36,15 @@ KernelInterfaceHandle::~KernelInterfaceHandle() if (Valid()) Remove(); } -KernelInterfaceHandle::KernelInterfaceHandle(KernelInterfaceHandle&& other) + +KernelInterfaceHandle::KernelInterfaceHandle(KernelInterfaceHandle&& other) noexcept { *this = std::move(other); } + bool KernelInterfaceHandle::Start() const { - auto rc = rte_eth_dev_start(m_kni_port); + auto rc = rte_eth_dev_start(kni_port_); if (rc) { YADECAP_LOG_ERROR("can't start eth dev(%d, %d): %s\n", @@ -53,17 +56,44 @@ bool KernelInterfaceHandle::Start() const return true; } -KernelInterfaceHandle& KernelInterfaceHandle::operator=(KernelInterfaceHandle&& other) +KernelInterfaceHandle& KernelInterfaceHandle::operator=(KernelInterfaceHandle&& other) noexcept { if (this != &other) { - std::swap(m_kni_port, other.m_kni_port); - std::swap(m_vdev_name, other.m_vdev_name); + std::swap(kni_port_, other.kni_port_); + std::swap(vdev_name_, other.vdev_name_); + std::swap(queue_size_, other.queue_size_); } return *this; } -std::string KernelInterfaceHandle::vdevArgs(const std::string& name, const tPortId port_id, uint64_t queue_size) +std::optional +KernelInterfaceHandle::MakeKernelInterfaceHandle( + std::string_view name, + tPortId port, + uint16_t queue_size) noexcept +{ + KernelInterfaceHandle kni; + kni.queue_size_ = queue_size; + kni.vdev_name_ = VdevName(name, port); + std::string vdev_args = VdevArgs(name, port, queue_size); + if (!kni.Add(kni.vdev_name_, vdev_args) || + !kni.Configure(DefaultConfig())) + { + return std::nullopt; + } + + return std::optional{std::move(kni)}; +} + +std::string KernelInterfaceHandle::VdevName(std::string_view name, const tPortId port_id) +{ + std::stringstream ss; + ss << "virtio_user_" << name << "_" << port_id; + return ss.str(); +} + +std::string KernelInterfaceHandle::VdevArgs(std::string_view name, const tPortId port_id, uint64_t queue_size) { rte_ether_addr ether_addr; rte_eth_macaddr_get(port_id, ðer_addr); @@ -71,12 +101,12 @@ std::string KernelInterfaceHandle::vdevArgs(const std::string& name, const tPort ss << "path=/dev/vhost-net" << ",queues=1" << ",queue_size=" << queue_size - << ",iface=" << name.data() - << ",mac=" << common::mac_address_t(ether_addr.addr_bytes).toString().data(); + << ",iface=" << name + << ",mac=" << common::mac_address_t(ether_addr.addr_bytes).toString(); return ss.str(); } -bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& args) +bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& args) noexcept { if (rte_eal_hotplug_add("vdev", vdev_name.data(), args.data()) != 0) { @@ -86,22 +116,30 @@ bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& return false; } - if (rte_eth_dev_get_port_by_name(vdev_name.data(), &m_kni_port) != 0) + if (rte_eth_dev_get_port_by_name(vdev_name.data(), &kni_port_) != 0) { YADECAP_LOG_ERROR("vdev interface '%s' not found\n", vdev_name.data()); return false; } return true; } -void KernelInterfaceHandle::Remove() + +void KernelInterfaceHandle::Remove() noexcept { - rte_eal_hotplug_remove("vdev", m_vdev_name.data()); + rte_eal_hotplug_remove("vdev", vdev_name_.data()); MarkInvalid(); } +rte_eth_conf KernelInterfaceHandle::DefaultConfig() noexcept +{ + rte_eth_conf eth_conf; + memset(ð_conf, 0, sizeof(eth_conf)); + return eth_conf; +} + bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) { - int ret = rte_eth_dev_configure(m_kni_port, + int ret = rte_eth_dev_configure(kni_port_, 1, 1, ð_conf); @@ -112,42 +150,44 @@ bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) } return true; } -bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) const + +bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) const noexcept { uint16_t mtu; if (rte_eth_dev_get_mtu(port_id, &mtu) != 0) return false; - rte_eth_dev_set_mtu(m_kni_port, mtu); + rte_eth_dev_set_mtu(kni_port_, mtu); return true; } -bool KernelInterfaceHandle::SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) +bool KernelInterfaceHandle::SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) noexcept { - int rc = rte_eth_rx_queue_setup(m_kni_port, + int rc = rte_eth_rx_queue_setup(kni_port_, queue, - m_queue_size, + queue_size_, socket, nullptr, mempool); if (rc < 0) { - YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", m_kni_port, 0, rc); + YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", kni_port_, 0, rc); return false; } return true; } -bool KernelInterfaceHandle::SetupTxQueue(tQueueId queue, tSocketId socket) + +bool KernelInterfaceHandle::SetupTxQueue(tQueueId queue, tSocketId socket) noexcept { - int rc = rte_eth_tx_queue_setup(m_kni_port, + int rc = rte_eth_tx_queue_setup(kni_port_, queue, - m_queue_size, + queue_size_, socket, nullptr); if (rc < 0) { - YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", m_kni_port, 0, rc); + YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", kni_port_, 0, rc); return false; } diff --git a/dataplane/kernel_interface_handle.h b/dataplane/kernel_interface_handle.h index ea519ebb..653a772f 100644 --- a/dataplane/kernel_interface_handle.h +++ b/dataplane/kernel_interface_handle.h @@ -2,7 +2,6 @@ #include -#include "common.h" #include "common/type.h" namespace dataplane @@ -10,9 +9,9 @@ namespace dataplane class KernelInterfaceHandle { - tPortId m_kni_port = INVALID_PORT_ID; - std::string m_vdev_name; - uint16_t m_queue_size = 0; + tPortId kni_port_ = INVALID_PORT_ID; + std::string vdev_name_; + uint16_t queue_size_ = 0; KernelInterfaceHandle() noexcept = default; @@ -20,51 +19,28 @@ class KernelInterfaceHandle ~KernelInterfaceHandle(); KernelInterfaceHandle(const KernelInterfaceHandle&) = delete; KernelInterfaceHandle(KernelInterfaceHandle&& other) noexcept; - [[nodiscard]] static std::optional - MakeKernelInterfaceHandle( - const std::string& name, - tPortId port, - uint16_t queue_size) - { - KernelInterfaceHandle kni; - kni.m_queue_size = queue_size; - kni.m_vdev_name = vdevName(name, port); - std::string vdev_args = vdevArgs(name, port, queue_size); - if (!kni.Add(kni.m_vdev_name, vdev_args) || - !kni.Configure(DefaultConfig())) - { - return std::nullopt; - } - - return std::optional{std::move(kni)}; - } - const tPortId& Id() const noexcept { return m_kni_port; } - bool Start() const noexcept; KernelInterfaceHandle& operator=(const KernelInterfaceHandle&) = delete; KernelInterfaceHandle& operator=(KernelInterfaceHandle&& other) noexcept; - [[nodiscard]] bool SetUp() const; - bool SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); - bool SetupTxQueue(tQueueId queue, tSocketId socket); + [[nodiscard]] static std::optional + MakeKernelInterfaceHandle(std::string_view name, + tPortId port, + uint16_t queue_size) noexcept; + const tPortId& Id() const noexcept { return kni_port_; } + bool Start() const noexcept; + [[nodiscard]] bool SetUp() const noexcept; + bool SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) noexcept; + bool SetupTxQueue(tQueueId queue, tSocketId socket) noexcept; private: - static std::string vdevName(const std::string& name, const tPortId port_id) - { - std::stringstream ss; - ss << "virtio_user_" << name << "_" << port_id; - return ss.str(); - } - static std::string vdevArgs(const std::string& name, const tPortId port_id, uint64_t queue_size); - bool Add(const std::string& vdev_name, const std::string& args); - void Remove(); - static rte_eth_conf DefaultConfig() - { - rte_eth_conf eth_conf; - memset(ð_conf, 0, sizeof(eth_conf)); - return eth_conf; - } + static std::string VdevName(std::string_view name, const tPortId port_id); + static std::string VdevArgs(std::string_view name, const tPortId port_id, uint64_t queue_size); + bool Add(const std::string& vdev_name, const std::string& args) noexcept; + void Remove() noexcept; + static rte_eth_conf DefaultConfig() noexcept; bool Configure(const rte_eth_conf& eth_conf) noexcept; - bool CloneMTU(const uint16_t) const; - void MarkInvalid() { m_kni_port = INVALID_PORT_ID; } - [[nodiscard]] bool Valid() { return m_kni_port != INVALID_PORT_ID; } + bool CloneMTU(const uint16_t) const noexcept; + void MarkInvalid() noexcept { kni_port_ = INVALID_PORT_ID; } + [[nodiscard]] bool Valid() const { return kni_port_ != INVALID_PORT_ID; } }; + } // namespace dataplane \ No newline at end of file diff --git a/dataplane/kernel_interface_handler.cpp b/dataplane/kernel_interface_handler.cpp new file mode 100644 index 00000000..bd554ab0 --- /dev/null +++ b/dataplane/kernel_interface_handler.cpp @@ -0,0 +1,219 @@ +#include "kernel_interface_handler.h" + +namespace dataplane +{ +KernelInterface::KernelInterface(tPortId port, tQueueId queue) : + endpoint_{port, queue} +{ +} + +KernelInterface::KernelInterface(const dpdk::Endpoint& e) : + endpoint_{e} +{ +} + +void KernelInterface::Flush() +{ + auto sent = rte_eth_tx_burst(endpoint_.port, endpoint_.queue, burst_, burst_length_); + const auto remain = burst_length_ - sent; + if (remain) + { + rte_pktmbuf_free_bulk(burst_ + sent, remain); + } + burst_length_ = 0; +} + +KernelInterface::DirectionStats KernelInterface::FlushTracked() +{ + DirectionStats stats; + stats.bytes = std::accumulate(burst_, burst_ + burst_length_, 0, [](uint64_t total, rte_mbuf* mbuf) { + return total + rte_pktmbuf_pkt_len(mbuf); + }); + stats.packets = rte_eth_tx_burst(endpoint_.port, endpoint_.queue, burst_, burst_length_); + + stats.dropped = burst_length_ - stats.packets; + if (stats.dropped) + { + stats.bytes = std::accumulate(burst_ + stats.packets, burst_ + burst_length_, stats.bytes, [](uint64_t total, rte_mbuf* mbuf) { + return total - rte_pktmbuf_pkt_len(mbuf); + }); + rte_pktmbuf_free_bulk(burst_ + stats.packets, stats.dropped); + } + burst_length_ = 0; + + return stats; +} + +void KernelInterface::Push(rte_mbuf* mbuf) +{ + if (burst_length_ == YANET_CONFIG_BURST_SIZE) + { + Flush(); + } + burst_[burst_length_++] = mbuf; +} + +KernelInterface::DirectionStats KernelInterface::PushTracked(rte_mbuf* mbuf) +{ + DirectionStats res; + if (burst_length_ == YANET_CONFIG_BURST_SIZE) + { + res = FlushTracked(); + } + burst_[burst_length_++] = mbuf; + return res; +} + +const tPortId& KernelInterface::port() const +{ + return endpoint_.port; +} + +const tQueueId& KernelInterface::queue() const +{ + return endpoint_.queue; +} + +void KernelInterfaceWorker::RecvFree(const KernelInterface& iface) +{ + rte_mbuf* burst[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + auto len = rte_eth_rx_burst(iface.port(), iface.queue(), burst, CONFIG_YADECAP_MBUFS_BURST_SIZE); + rte_pktmbuf_free_bulk(burst, len); +} + +KernelInterfaceWorker::KernelInterfaceWorker(const KernelInterfaceWorkerConfig& config) : + port_mapper_{config.port_mapper} +{ + for (const auto& iface : config.interfaces) + { + phy_ports_[size_] = iface.phy.port; + phy_queues_[size_] = iface.phy.queue; + forward_[size_] = KernelInterface{iface.forward}; + in_dump_[size_] = KernelInterface{iface.in_dump}; + out_dump_[size_] = KernelInterface{iface.out_dump}; + drop_dump_[size_] = KernelInterface{iface.drop_dump}; + ++size_; + } +} + +KernelInterfaceWorker::ConstPortArrayRange +KernelInterfaceWorker::PortsIds() const +{ + return {phy_ports_.begin(), phy_ports_.begin() + size_}; +} + +KernelInterfaceWorker::ConstPortArrayRange +KernelInterfaceWorker::PortsStats() const +{ + return {stats_.begin(), stats_.begin() + size_}; +} + +std::optional> +KernelInterfaceWorker::PortStats(tPortId pid) const +{ + for (std::size_t i = 0; i < size_; ++i) + { + if (phy_ports_[i] == pid) + { + return stats_[i]; + } + } + return std::nullopt; +} + +/// @brief Transmit accumulated packets. Those that could not be sent are freed +void KernelInterfaceWorker::Flush() +{ + for (std::size_t i = 0; i < size_; ++i) + { + const auto& delta = forward_[i].FlushTracked(); + stats_[i].opackets += delta.packets; + stats_[i].obytes += delta.bytes; + stats_[i].odropped += delta.dropped; + in_dump_[i].Flush(); + out_dump_[i].Flush(); + drop_dump_[i].Flush(); + } +} + +/// @brief Receive from in.X/out.X/drop.X interfaces and free packets +void KernelInterfaceWorker::RecvFree() +{ + for (std::size_t i = 0; i < size_; ++i) + { + RecvFree(in_dump_[i]); + RecvFree(out_dump_[i]); + RecvFree(drop_dump_[i]); + } +} + +/// @brief Receive packets from kernel interface and send to physical port +void KernelInterfaceWorker::ForwardToPhy() +{ + for (std::size_t i = 0; i < size_; ++i) + { + rte_mbuf* burst[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + auto packets = rte_eth_rx_burst(forward_[i].port(), forward_[i].queue(), burst, CONFIG_YADECAP_MBUFS_BURST_SIZE); + uint64_t bytes = std::accumulate(burst, burst + packets, 0, [](uint64_t total, rte_mbuf* mbuf) { + return total + rte_pktmbuf_pkt_len(mbuf); + }); + auto transmitted = rte_eth_tx_burst(phy_ports_[i], phy_queues_[i], burst, packets); + const auto remain = packets - transmitted; + + if (remain) + { + bytes = std::accumulate(burst, burst + packets, bytes, [](uint64_t total, rte_mbuf* mbuf) { + return total - rte_pktmbuf_pkt_len(mbuf); + }); + rte_pktmbuf_free_bulk(burst + transmitted, remain); + } + + auto& stats = stats_[i]; + stats.opackets += transmitted; + stats.obytes += bytes; + stats.odropped += remain; + } +} + +void KernelInterfaceWorker::HandlePacketDump(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + if (!port_mapper_->ValidDpdk(metadata->flow.data.dump.id)) + { + unknown_dump_interface_++; + rte_pktmbuf_free(mbuf); + return; + } + const auto local_port_id = port_mapper_->ToLogical(metadata->flow.data.dump.id); + + using dumpType = common::globalBase::dump_type_e; + switch (metadata->flow.data.dump.type) + { + case dumpType::physicalPort_ingress: + in_dump_[local_port_id].Push(mbuf); + break; + case dumpType::physicalPort_egress: + out_dump_[local_port_id].Push(mbuf); + break; + case dumpType::physicalPort_drop: + drop_dump_[local_port_id].Push(mbuf); + break; + default: + unknown_dump_interface_++; + rte_pktmbuf_free(mbuf); + } +} + +void KernelInterfaceWorker::HandlePacketFromForwardingPlane(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + const auto i = port_mapper_->ToLogical(metadata->fromPortId); + const auto& delta = forward_[i].PushTracked(mbuf); + stats_[i].opackets += delta.packets; + stats_[i].obytes += delta.bytes; + stats_[i].odropped += delta.dropped; +} + +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/kernel_interface_handler.h b/dataplane/kernel_interface_handler.h new file mode 100644 index 00000000..3b6ce7df --- /dev/null +++ b/dataplane/kernel_interface_handler.h @@ -0,0 +1,103 @@ +#pragma once +#include + +#include + +#include "base.h" +#include "dpdk.h" +#include "metadata.h" + +namespace dataplane +{ + +struct sKniStats +{ + uint64_t ipackets = 0; + uint64_t ibytes = 0; + uint64_t idropped = 0; + uint64_t opackets = 0; + uint64_t obytes = 0; + uint64_t odropped = 0; +}; + +class KernelInterface +{ + dpdk::Endpoint endpoint_; + rte_mbuf* burst_[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + uint16_t burst_length_ = 0; + +public: + KernelInterface() = default; + KernelInterface(tPortId port, tQueueId queue); + KernelInterface(const dpdk::Endpoint& e); + struct DirectionStats + { + uint64_t bytes = 0; + uint64_t packets = 0; + uint64_t dropped = 0; + }; + void Flush(); + DirectionStats FlushTracked(); + void Push(rte_mbuf* mbuf); + DirectionStats PushTracked(rte_mbuf* mbuf); + const tPortId& port() const; + const tQueueId& queue() const; +}; + +struct KernelInterfaceBundleConfig +{ + dpdk::Endpoint phy; + dpdk::Endpoint forward; + dpdk::Endpoint in_dump; + dpdk::Endpoint out_dump; + dpdk::Endpoint drop_dump; +}; + +struct KernelInterfaceWorkerConfig +{ + std::vector interfaces; + dataplane::base::PortMapper* port_mapper; +}; + +class KernelInterfaceWorker +{ +public: + template + using PortArray = std::array; + template + using ConstPortArrayRange = std::pair::const_iterator, typename PortArray::const_iterator>; + +private: + std::size_t size_ = 0; + PortArray phy_ports_; + PortArray phy_queues_; + PortArray stats_; + PortArray forward_; + PortArray in_dump_; + PortArray out_dump_; + PortArray drop_dump_; + const dataplane::base::PortMapper* port_mapper_; + uint64_t unknown_dump_interface_ = 0; + + /** + * @brief Receive packets from interface and free them. + * @param iface Interface to receive packets from. + */ + void RecvFree(const KernelInterface& iface); + +public: + KernelInterfaceWorker(const KernelInterfaceWorkerConfig& config); + ConstPortArrayRange PortsIds() const; + ConstPortArrayRange PortsStats() const; + std::optional> PortStats(tPortId pid) const; + + /// @brief Transmit accumulated packets. Those that could not be sent are freed + void Flush(); + /// @brief Receive from in.X/out.X/drop.X interfaces and free packets + void RecvFree(); + /// @brief Receive packets from kernel interface and send to physical port + void ForwardToPhy(); + void HandlePacketDump(rte_mbuf* mbuf); + void HandlePacketFromForwardingPlane(rte_mbuf* mbuf); +}; +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/meson.build b/dataplane/meson.build index b7bb20d1..a86156e8 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -11,6 +11,7 @@ sources = files('bus.cpp', 'dregress.cpp', 'fragmentation.cpp', 'kernel_interface_handle.cpp', + 'kernel_interface_handler.cpp', 'globalbase.cpp', 'main.cpp', 'memory_manager.cpp', From eee291eb836cdeeda5c766ad672a63e1ea959727 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 16 Apr 2024 16:38:43 +0300 Subject: [PATCH 036/195] Moves kernel interfaces initialization to cDataPlane Kernel Network Interfaces were previously managed by cControlPlane Their initialization is moved to cDataPlane, which should be the only entity managing environment in which application works. KernelInterfaceHandles are used as a convenient safer abstraction to manage KNIs --- dataplane/controlplane.cpp | 239 +------------------------------------ dataplane/controlplane.h | 13 +- dataplane/dataplane.cpp | 161 +++++++++++++++++++++++++ dataplane/dataplane.h | 23 +++- 4 files changed, 193 insertions(+), 243 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 5e377fbf..9ea9b893 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -37,19 +37,6 @@ cControlPlane::cControlPlane(cDataPlane* dataPlane) : cControlPlane::~cControlPlane() { - if (use_kernel_interface) - { - const auto& portmapper = slowWorker->basePermanently.ports; - for (tPortId i = 0; i < portmapper.size(); ++i) - { - const auto port_id = portmapper.ToDpdk(i); - remove_kernel_interface(port_id, kernel_interfaces[i].interface_name); - remove_kernel_interface(port_id, in_dump_kernel_interfaces[i].interface_name); - remove_kernel_interface(port_id, out_dump_kernel_interfaces[i].interface_name); - remove_kernel_interface(port_id, drop_dump_kernel_interfaces[i].interface_name); - } - } - if (mempool) { rte_mempool_free(mempool); @@ -109,14 +96,6 @@ void cControlPlane::start() rte_eth_promiscuous_enable(portId); } - if (use_kernel_interface) - { - if (init_kernel_interfaces() != eResult::success) - { - abort(); - } - } - rc = pthread_barrier_wait(&dataPlane->runBarrier); if (rc == PTHREAD_BARRIER_SERIAL_THREAD) { @@ -129,14 +108,6 @@ void cControlPlane::start() return; } - if (use_kernel_interface) - { - for (uint16_t i = 0; i < slowWorker->basePermanently.ports.size(); ++i) - { - set_kernel_interface_up(kernel_interfaces[i].interface_name); - } - } - mainThread(); } @@ -1383,218 +1354,10 @@ void cControlPlane::waitAllWorkers() eResult cControlPlane::initMempool() { - mempool = rte_mempool_create("cp", - CONFIG_YADECAP_MBUFS_COUNT + dataPlane->getConfigValues().fragmentation_size + dataPlane->getConfigValues().master_mempool_size + 4 * CONFIG_YADECAP_PORTS_SIZE * CONFIG_YADECAP_MBUFS_BURST_SIZE + 4 * dataPlane->ports.size() * dataPlane->getConfigValues().kernel_interface_queue_size, - CONFIG_YADECAP_MBUF_SIZE, - 0, - sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, - nullptr, - rte_pktmbuf_init, - nullptr, - rte_socket_id(), - 0); ///< multi-producers, multi-consumers - if (!mempool) - { - YADECAP_LOG_ERROR("rte_mempool_create(): %s [%u]\n", rte_strerror(rte_errno), rte_errno); - return eResult::errorInitMempool; - } - + mempool = dataPlane->socket_cplane_mempools[rte_lcore_to_socket_id(dataPlane->config.controlPlaneCoreId)]; return eResult::success; } -eResult cControlPlane::init_kernel_interfaces() -{ - const auto& portmapper = slowWorker->basePermanently.ports; - for (tPortId i = 0; i < portmapper.size(); ++i) - { - const auto port_id = portmapper.ToDpdk(i); - const auto& interface_name = std::get<0>(dataPlane->ports.at(port_id)); - - { - auto kernel_port_id = add_kernel_interface(port_id, interface_name); - if (!kernel_port_id) - { - return eResult::errorAllocatingKernelInterface; - } - - kernel_interfaces[i] = {interface_name, - *kernel_port_id, - {}, - {}}; - } - - { - auto kernel_port_id = add_kernel_interface(port_id, "in." + interface_name); - if (!kernel_port_id) - { - return eResult::errorAllocatingKernelInterface; - } - - in_dump_kernel_interfaces[i] = {"in." + interface_name, - *kernel_port_id, - {}, - {}}; - } - - { - auto kernel_port_id = add_kernel_interface(port_id, "out." + interface_name); - if (!kernel_port_id) - { - return eResult::errorAllocatingKernelInterface; - } - - out_dump_kernel_interfaces[i] = {"out." + interface_name, - *kernel_port_id, - {}, - {}}; - } - - { - auto kernel_port_id = add_kernel_interface(port_id, "drop." + interface_name); - if (!kernel_port_id) - { - return eResult::errorAllocatingKernelInterface; - } - - drop_dump_kernel_interfaces[i] = {"drop." + interface_name, - *kernel_port_id, - {}, - {}}; - } - } - - return eResult::success; -} - -std::optional cControlPlane::add_kernel_interface(const tPortId port_id, - const std::string& interface_name) -{ - rte_ether_addr ether_addr; - rte_eth_macaddr_get(port_id, ðer_addr); - - char vdev_name[RTE_DEV_NAME_MAX_LEN]; - char vdev_args[256]; - - snprintf(vdev_name, - sizeof(vdev_name), - "virtio_user_%s_%u", - interface_name.data(), - port_id); - - snprintf(vdev_args, - sizeof(vdev_args), - "path=/dev/vhost-net,queues=1,queue_size=%lu,iface=%s,mac=%s", - dataPlane->getConfigValues().kernel_interface_queue_size, - interface_name.data(), - common::mac_address_t(ether_addr.addr_bytes).toString().data()); - - if (rte_eal_hotplug_add("vdev", vdev_name, vdev_args) != 0) - { - YADECAP_LOG_ERROR("failed to hotplug vdev interface '%s' with '%s'\n", - vdev_name, - vdev_args); - return std::nullopt; - } - - uint16_t kernel_port_id; - if (rte_eth_dev_get_port_by_name(vdev_name, &kernel_port_id) != 0) - { - YADECAP_LOG_ERROR("vdev interface '%s' not found\n", vdev_name); - rte_eal_hotplug_remove("vdev", vdev_name); - return std::nullopt; - } - - rte_eth_conf eth_conf; - memset(ð_conf, 0, sizeof(eth_conf)); - - int ret = rte_eth_dev_configure(kernel_port_id, - 1, - 1, - ð_conf); - if (ret < 0) - { - YADECAP_LOG_ERROR("rte_eth_dev_configure() = %d\n", ret); - rte_eal_hotplug_remove("vdev", vdev_name); - return std::nullopt; - } - - uint16_t mtu; - if (rte_eth_dev_get_mtu(port_id, &mtu) == 0) - { - rte_eth_dev_set_mtu(kernel_port_id, mtu); - } - - int rc = rte_eth_rx_queue_setup(kernel_port_id, - 0, - dataPlane->getConfigValues().kernel_interface_queue_size, - 0, ///< @todo: socket - nullptr, - mempool); - if (rc < 0) - { - YADECAP_LOG_ERROR("rte_eth_rx_queue_setup() = %d\n", rc); - rte_eal_hotplug_remove("vdev", vdev_name); - return std::nullopt; - } - - rc = rte_eth_tx_queue_setup(kernel_port_id, - 0, - dataPlane->getConfigValues().kernel_interface_queue_size, - 0, ///< @todo: socket - nullptr); - if (rc < 0) - { - YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", kernel_port_id, 0, ret); - rte_eal_hotplug_remove("vdev", vdev_name); - return std::nullopt; - } - - rc = rte_eth_dev_start(kernel_port_id); - if (rc) - { - YADECAP_LOG_ERROR("can't start eth dev(%d, %d): %s\n", - rc, - rte_errno, - rte_strerror(rte_errno)); - rte_eal_hotplug_remove("vdev", vdev_name); - return std::nullopt; - } - - return kernel_port_id; -} - -void cControlPlane::remove_kernel_interface(const tPortId port_id, - const std::string& interface_name) -{ - char vdev_name[RTE_DEV_NAME_MAX_LEN]; - - snprintf(vdev_name, - sizeof(vdev_name), - "virtio_user_%s_%u", - interface_name.data(), - port_id); - - rte_eal_hotplug_remove("vdev", vdev_name); -} - -void cControlPlane::set_kernel_interface_up(const std::string& interface_name) -{ - int socket = ::socket(AF_INET, SOCK_DGRAM, 0); - if (socket < 0) - { - return; - } - - struct ifreq request; - memset(&request, 0, sizeof request); - - strncpy(request.ifr_name, interface_name.data(), IFNAMSIZ); - - request.ifr_flags |= IFF_UP; - ioctl(socket, SIOCSIFFLAGS, &request); -} - void cControlPlane::flush_kernel_interface(KniPortData& port_data, sKniStats& stats) { diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index c052f159..c42975dc 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -19,6 +19,7 @@ #include "dregress.h" #include "fragmentation.h" +#include "kernel_interface_handle.h" #include "type.h" class cControlPlane ///< @todo: move to cDataPlane @@ -80,10 +81,6 @@ class cControlPlane ///< @todo: move to cDataPlane protected: eResult initMempool(); - eResult init_kernel_interfaces(); - std::optional add_kernel_interface(const tPortId port_id, const std::string& interface_name); - void remove_kernel_interface(const tPortId port_id, const std::string& interface_name); - void set_kernel_interface_up(const std::string& interface_name); void mainThread(); unsigned ring_handle(rte_ring* ring_to_free_mbuf, rte_ring* ring); @@ -134,6 +131,14 @@ class cControlPlane ///< @todo: move to cDataPlane rte_mempool* mempool; bool use_kernel_interface; + struct KniHandleBundle + { + dataplane::KernelInterfaceHandle forward; + dataplane::KernelInterfaceHandle in_dump; + dataplane::KernelInterfaceHandle out_dump; + dataplane::KernelInterfaceHandle drop_dump; + }; + struct KniPortData { std::string interface_name; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index baf58035..731d7c10 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -108,6 +108,15 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } + if (config.use_kernel_interface) + { + result = init_kernel_interfaces(); + if (result != eResult::success) + { + return result; + } + } + mempool_log = rte_mempool_create("log", YANET_CONFIG_SAMPLES_SIZE, sizeof(samples::sample_t), 0, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, MEMPOOL_F_NO_IOVA_CONTIG); result = initGlobalBases(); @@ -116,6 +125,32 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } + for (auto socket : socket_ids) + { + auto pool = rte_mempool_create(("cp-" + std::to_string(socket)).c_str(), + CONFIG_YADECAP_MBUFS_COUNT + + configValues.fragmentation_size + + configValues.master_mempool_size + + 4 * CONFIG_YADECAP_PORTS_SIZE * CONFIG_YADECAP_MBUFS_BURST_SIZE + + 4 * ports.size() * configValues.kernel_interface_queue_size, + CONFIG_YADECAP_MBUF_SIZE, + 0, + sizeof(struct rte_pktmbuf_pool_private), + rte_pktmbuf_pool_init, + nullptr, + rte_pktmbuf_init, + nullptr, + socket, + 0); ///< multi-producers, multi-consumers + if (!pool) + { + YADECAP_LOG_ERROR("rte_mempool_create(): %s [%u]\n", rte_strerror(rte_errno), rte_errno); + return eResult::errorAllocatingMemory; + } + socket_cplane_mempools.emplace(socket, pool); + YANET_LOG_ERROR("created mempool cp-%s\n", std::to_string(socket).c_str()); + } + result = initWorkers(); if (result != eResult::success) { @@ -541,6 +576,112 @@ eResult cDataPlane::initPorts() return eResult::success; } +void cDataPlane::StartInterfaces() +{ + /// start devices + for (const auto& portIter : ports) + { + const tPortId& portId = portIter.first; + + int rc = rte_eth_dev_start(portId); + if (rc) + { + YADECAP_LOG_ERROR("can't start eth dev(%d, %d): %s\n", + rc, + rte_errno, + rte_strerror(rte_errno)); + std::abort(); + } + + rte_eth_promiscuous_enable(portId); + } + + if (config.use_kernel_interface) + { + for (auto& [portid, handles] : kni_interface_handles) + { + if (!handles.forward.SetUp()) + { + YANET_LOG_ERROR("Failed to set kni interface belonging to %s up", std::get<0>(ports.at(portid)).c_str()); + std::abort(); + } + } + } +} + +void cDataPlane::InitPortsBarrier() +{ + int rc = pthread_barrier_wait(&initPortBarrier); + if (rc == PTHREAD_BARRIER_SERIAL_THREAD) + { + pthread_barrier_destroy(&initPortBarrier); + } + else if (rc) + { + YANET_LOG_ERROR("init_ports_barrier pthread_barrier_wait() = %d\n", rc); + std::abort(); + } + + if (rte_get_main_lcore() == rte_lcore_id()) + { + StartInterfaces(); + } +} + +eResult cDataPlane::init_kernel_interfaces() +{ + const uint16_t queue_size = getConfigValues().kernel_interface_queue_size; + for (const auto& [port_id, info] : ports) + { + const auto& interface_name = std::get<0>(info); + + auto forward = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); + auto in = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); + auto out = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); + auto drop = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); + + if (!forward || !in || !out || !drop) + { + return eResult::errorAllocatingKernelInterface; + } + + kni_interface_handles.emplace(port_id, KniHandleBundle{std::move(forward.value()), std::move(in.value()), std::move(out.value()), std::move(drop.value())}); + } + + return eResult::success; +} + +bool cDataPlane::KNIAddTxQueue(tQueueId queue, tSocketId socket) +{ + for (auto& bundle : kni_interface_handles) + { + auto& [fwd, in, out, drop] = bundle.second; + if (!fwd.SetupTxQueue(queue, socket) || + !in.SetupTxQueue(queue, socket) || + !out.SetupTxQueue(queue, socket) || + !drop.SetupTxQueue(queue, socket)) + { + return false; + } + } + return true; +} +bool cDataPlane::KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) +{ + for (auto& bundle : kni_interface_handles) + { + auto& [fwd, in, out, drop] = bundle.second; + if (!fwd.SetupRxQueue(queue, socket, mempool) || + !in.SetupRxQueue(queue, socket, mempool) || + !out.SetupRxQueue(queue, socket, mempool) || + !drop.SetupRxQueue(queue, socket, mempool)) + { + return false; + } + } + return true; +} + eResult cDataPlane::initGlobalBases() { eResult result = eResult::success; @@ -1031,6 +1172,26 @@ eResult cDataPlane::initQueues() return eResult::success; } +eResult cDataPlane::initKniQueues() +{ + for (auto& it : kni_interface_handles) + { + uint16_t port_id = it.first; + for (std::size_t i = 0, max = 1; i < max; ++i) + { + const auto& socket_id = rte_eth_dev_socket_id(port_id); + KNIAddTxQueue(i, socket_id); + } + + for (std::size_t i = 0, max = 1; i < max; ++i) + { + const auto& socket_id = rte_eth_dev_socket_id(port_id); + KNIAddRxQueue(i, socket_id, socket_cplane_mempools.at(socket_id)); + } + } + return eResult::success; +} + void cDataPlane::init_worker_base() { std::vector> base_nexts; diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index f2c4b403..10b0d4e4 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -105,6 +105,7 @@ class cDataPlane { return current_time; } + std::string InterfaceNameFromPort(tPortId id) { return std::get<0>(ports[id]); }; protected: eResult parseConfig(const std::string& configFilePath); @@ -116,9 +117,18 @@ class cDataPlane eResult initEal(const std::string& binaryPath, const std::string& filePrefix); eResult initPorts(); - eResult initRingPorts(); + +public: + void StartInterfaces(); + void InitPortsBarrier(); + +protected: + eResult init_kernel_interfaces(); + bool KNIAddTxQueue(tQueueId queue, tSocketId socket); + bool KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); eResult initGlobalBases(); eResult initWorkers(); + eResult initKniQueues(); eResult initQueues(); void init_worker_base(); @@ -142,6 +152,15 @@ class cDataPlane tDataPlaneConfig config; + struct KniHandleBundle + { + dataplane::KernelInterfaceHandle forward; + dataplane::KernelInterfaceHandle in_dump; + dataplane::KernelInterfaceHandle out_dump; + dataplane::KernelInterfaceHandle drop_dump; + }; + std::map kni_interface_handles; + std::map, ///< rx_queues @@ -186,6 +205,8 @@ class cDataPlane std::set socket_ids; std::map socket_worker_gcs; + std::map socket_cplane_mempools; + std::vector workers_vector; std::mutex switch_worker_base_mutex; From 8bcc7c1d5e43809110fb123e23fff0e1ed0630cd Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 13 May 2024 14:44:01 +0300 Subject: [PATCH 037/195] Delete unused controlPlane_drops --- cli/telegraf.h | 5 ++--- dataplane/controlplane.cpp | 32 ++------------------------------ dataplane/report.cpp | 2 +- 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/cli/telegraf.h b/cli/telegraf.h index ae0e4ee9..708cbbd7 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -178,11 +178,10 @@ void unsafe() { printf("worker,coreId=%u,physicalPortName=%s " "physicalPort_egress_drops=%luu," - "controlPlane_drops=%luu\n", + "controlPlane_drops=0\n", // @todo: DELETE coreId, physicalPortName.data(), - stats.physicalPort_egress_drops, - stats.controlPlane_drops); + stats.physicalPort_egress_drops); } } diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 9ea9b893..a0763f2c 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -450,24 +450,10 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo } const auto& stats = kernel_stats[portmapper.ToLogical(portId)]; - uint64_t controlPlane_drops = 0; - for (const auto& [coreId, worker] : dataPlane->workers) - { - (void)coreId; - - /* @todo This line assumes dpdk port id of a port is equal to logical id, and logical - * ids of diferent workers are the same. - * one can't just assume worker ports are enumerated identically. - * Moreover indexing should be by logical id, inter worker communications - * by dpdk portId's - */ - controlPlane_drops += worker->statsPorts[portId].controlPlane_drops; - } - response[portId] = {stats.ipackets, stats.ibytes, 0, - stats.idropped + controlPlane_drops, + stats.idropped, stats.opackets, stats.obytes, 0, @@ -484,24 +470,10 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo const auto& stats = kernel_stats[i]; const auto& portId = portmapper.ToDpdk(i); - uint64_t controlPlane_drops = 0; - for (const auto& [coreId, worker] : dataPlane->workers) - { - (void)coreId; - - /* @todo This line assumes dpdk port id of a port is equal to logical id, and logical - * ids of diferent workers are the same. - * one can't just assume worker ports are enumerated identically. - * Moreover indexing should be by logical id, inter worker communications - * by dpdk portId's - */ - controlPlane_drops += worker->statsPorts[portId].controlPlane_drops; - } - response[portId] = {stats.ipackets, stats.ibytes, 0, - stats.idropped + controlPlane_drops, + stats.idropped, stats.opackets, stats.obytes, 0, diff --git a/dataplane/report.cpp b/dataplane/report.cpp index ca8917bf..582829b6 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -169,7 +169,7 @@ nlohmann::json cReport::convertWorker(const cWorker* worker) jsonPort["portId"] = portId; jsonPort["physicalPort_egress_drops"] = worker->statsPorts[portId].physicalPort_egress_drops; - jsonPort["controlPlane_drops"] = worker->statsPorts[portId].controlPlane_drops; + jsonPort["controlPlane_drops"] = 0; // @todo: DELETE json["statsPorts"].emplace_back(jsonPort); } From 672c6a3f313cc65551dfbe8a2fefad4423ba0ef6 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 29 Jul 2024 14:18:20 +0300 Subject: [PATCH 038/195] Adds addition operation to fragmentation and dregress stats --- common/type.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/common/type.h b/common/type.h index 558433e9..b53566c9 100644 --- a/common/type.h +++ b/common/type.h @@ -2440,6 +2440,19 @@ struct stats_t uint64_t intersect_packets; uint64_t unknown_network_type_packets; uint64_t timeout_packets; + + stats_t& operator+=(const stats_t& other) + { + current_count_packets += other.current_count_packets; + total_overflow_packets += other.total_overflow_packets; + not_fragment_packets += other.not_fragment_packets; + empty_packets += other.empty_packets; + flow_overflow_packets += other.flow_overflow_packets; + intersect_packets += other.intersect_packets; + unknown_network_type_packets += other.unknown_network_type_packets; + timeout_packets += other.timeout_packets; + return *this; + } }; } @@ -2491,6 +2504,25 @@ struct stats_t uint64_t tcp_ok; uint64_t tcp_timeout_sessions; uint64_t tcp_unknown_sessions; + + stats_t& operator+=(const stats_t& other) + { + bad_decap_transport += other.bad_decap_transport; + fragment += other.fragment; + bad_transport += other.bad_transport; + lookup_miss += other.lookup_miss; + local += other.local; + tcp_syn += other.tcp_syn; + tcp_unknown_option += other.tcp_unknown_option; + tcp_no_option += other.tcp_no_option; + tcp_insert_sessions += other.tcp_insert_sessions; + tcp_close_sessions += other.tcp_close_sessions; + tcp_retransmission += other.tcp_retransmission; + tcp_ok += other.tcp_ok; + tcp_timeout_sessions += other.tcp_timeout_sessions; + tcp_unknown_sessions += other.tcp_unknown_sessions; + return *this; + } }; using value_t = std::tuple Date: Mon, 29 Jul 2024 14:19:22 +0300 Subject: [PATCH 039/195] Unties fragmentation from controlplane and dataplane --- dataplane/bus.cpp | 2 +- dataplane/config_values.h | 21 +++++--- dataplane/controlplane.cpp | 12 +++-- dataplane/controlplane.h | 2 +- dataplane/dataplane.cpp | 21 ++++++-- dataplane/dataplane.h | 6 +-- dataplane/fragmentation.cpp | 100 ++++++++++++++++++++---------------- dataplane/fragmentation.h | 35 ++++++++----- 8 files changed, 120 insertions(+), 79 deletions(-) diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 2ba40c5b..47df25cd 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -15,13 +15,13 @@ cBus::cBus(cDataPlane* dataPlane) : dataPlane(dataPlane), - controlPlane(dataPlane->controlPlane.get()), serverSocket(-1) { } eResult cBus::init() { + controlPlane = dataPlane->controlPlane.get(); serverSocket = socket(AF_UNIX, SOCK_STREAM, 0); if (serverSocket < 0) { diff --git a/dataplane/config_values.h b/dataplane/config_values.h index 0900038b..31711723 100644 --- a/dataplane/config_values.h +++ b/dataplane/config_values.h @@ -5,6 +5,14 @@ #include "common/config.h" +struct FragmentationConfig +{ + uint64_t size = 1024; + uint64_t timeout_first = 32; + uint64_t timeout_last = 16; + uint64_t packets_per_flow = 64; +}; + struct ConfigValues { uint64_t port_rx_queue_size = 4096; @@ -14,10 +22,7 @@ struct ConfigValues uint64_t ring_lowPriority_size = 64; uint64_t ring_toFreePackets_size = 64; uint64_t ring_log_size = 1024; - uint64_t fragmentation_size = 1024; - uint64_t fragmentation_timeout_first = 32; - uint64_t fragmentation_timeout_last = 16; - uint64_t fragmentation_packets_per_flow = 64; + FragmentationConfig fragmentation; uint64_t stateful_firewall_tcp_timeout = 120; uint64_t stateful_firewall_tcp_syn_timeout = YANET_CONFIG_STATE_TIMEOUT_DEFAULT; uint64_t stateful_firewall_tcp_syn_ack_timeout = YANET_CONFIG_STATE_TIMEOUT_DEFAULT; @@ -51,10 +56,10 @@ inline void from_json(const nlohmann::json& j, ConfigValues& cfg) cfg.ring_lowPriority_size = j.value("ring_lowPriority_size", cfg.ring_lowPriority_size); cfg.ring_toFreePackets_size = j.value("ring_toFreePackets_size", cfg.ring_toFreePackets_size); cfg.ring_log_size = j.value("ring_log_size", cfg.ring_log_size); - cfg.fragmentation_size = j.value("fragmentation_size", cfg.fragmentation_size); - cfg.fragmentation_timeout_first = j.value("fragmentation_timeout_first", cfg.fragmentation_timeout_first); - cfg.fragmentation_timeout_last = j.value("fragmentation_timeout_last", cfg.fragmentation_timeout_last); - cfg.fragmentation_packets_per_flow = j.value("fragmentation_packets_per_flow", cfg.fragmentation_packets_per_flow); + cfg.fragmentation.size = j.value("fragmentation_size", cfg.fragmentation.size); + cfg.fragmentation.timeout_first = j.value("fragmentation_timeout_first", cfg.fragmentation.timeout_first); + cfg.fragmentation.timeout_last = j.value("fragmentation_timeout_last", cfg.fragmentation.timeout_last); + cfg.fragmentation.packets_per_flow = j.value("fragmentation_packets_per_flow", cfg.fragmentation.packets_per_flow); { /* diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index a0763f2c..4964faaf 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -25,7 +25,11 @@ cControlPlane::cControlPlane(cDataPlane* dataPlane) : dataPlane(dataPlane), - fragmentation(this, dataPlane), + fragmentation_( + [this](rte_mbuf* pkt, const common::globalBase::tFlow& flow) { + sendPacketToSlowWorker(pkt, flow); + }, + dataPlane->getConfigValues().fragmentation), dregress(this, dataPlane), mempool(nullptr), use_kernel_interface(false), @@ -487,7 +491,7 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo common::idp::getFragmentationStats::response cControlPlane::getFragmentationStats() { - return fragmentation.getStats(); + return fragmentation_.getStats(); } common::idp::getFWState::response cControlPlane::getFWState() @@ -1453,7 +1457,7 @@ void cControlPlane::mainThread() } } - fragmentation.handle(); + fragmentation_.handle(); dregress.handle(); if (use_kernel_interface) @@ -2265,7 +2269,7 @@ void cControlPlane::handlePacket_fragment(rte_mbuf* mbuf) if (nat64stateless.defrag_farm_prefix.empty() || metadata->network_headerType != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) || nat64stateless.farm) { - fragmentation.insert(mbuf); + fragmentation_.insert(mbuf); return; } diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index c42975dc..fbe24dcc 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -119,7 +119,7 @@ class cControlPlane ///< @todo: move to cDataPlane cDataPlane* dataPlane; - fragmentation_t fragmentation; + fragmentation::Fragmentation fragmentation_; dregress_t dregress; std::mutex mutex; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 731d7c10..319c20d2 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -45,7 +45,6 @@ cDataPlane::cDataPlane() : currentGlobalBaseId(0), globalBaseSerial(0), report(this), - controlPlane(new cControlPlane(this)), bus(this), memory_manager(this) { @@ -102,6 +101,12 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } + result = InitControlPlane(); + if (result != eResult::success) + { + return result; + } + result = initPorts(); if (result != eResult::success) { @@ -129,10 +134,10 @@ eResult cDataPlane::init(const std::string& binaryPath, { auto pool = rte_mempool_create(("cp-" + std::to_string(socket)).c_str(), CONFIG_YADECAP_MBUFS_COUNT + - configValues.fragmentation_size + - configValues.master_mempool_size + + config_values_.fragmentation.size + + config_values_.master_mempool_size + 4 * CONFIG_YADECAP_PORTS_SIZE * CONFIG_YADECAP_MBUFS_BURST_SIZE + - 4 * ports.size() * configValues.kernel_interface_queue_size, + 4 * ports.size() * config_values_.kernel_interface_queue_size, CONFIG_YADECAP_MBUF_SIZE, 0, sizeof(struct rte_pktmbuf_pool_private), @@ -628,6 +633,12 @@ void cDataPlane::InitPortsBarrier() } } +eResult cDataPlane::InitControlPlane() +{ + controlPlane = std::make_unique(this); + return eResult::success; +} + eResult cDataPlane::init_kernel_interfaces() { const uint16_t queue_size = getConfigValues().kernel_interface_queue_size; @@ -1839,7 +1850,7 @@ eResult cDataPlane::parseJsonPorts(const nlohmann::json& json) eResult cDataPlane::parseConfigValues(const nlohmann::json& json) { - configValues = json; + config_values_ = json; return eResult::success; } diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 10b0d4e4..02817658 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -92,7 +92,7 @@ class cDataPlane void start(); void join(); - const ConfigValues& getConfigValues() const { return configValues; } + const ConfigValues& getConfigValues() const { return config_values_; } std::map getPortStats(const tPortId& portId) const; std::optional interface_name_to_port_id(const std::string& interface_name); const std::set& get_socket_ids() const; @@ -123,6 +123,7 @@ class cDataPlane void InitPortsBarrier(); protected: + eResult InitControlPlane(); eResult init_kernel_interfaces(); bool KNIAddTxQueue(tQueueId queue, tSocketId socket); bool KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); @@ -151,6 +152,7 @@ class cDataPlane friend class worker_gc_t; tDataPlaneConfig config; + ConfigValues config_values_; struct KniHandleBundle { @@ -180,8 +182,6 @@ class cDataPlane std::map> globalBases; uint32_t globalBaseSerial; - ConfigValues configValues; - std::map dataPlane->getConfigValues().fragmentation_size) + if (stats_.current_count_packets > config_.size) { - stats.total_overflow_packets++; + YANET_LOG_DEBUG("Frag limit exceeded\n"); + stats_.total_overflow_packets++; rte_pktmbuf_free(mbuf); return; } @@ -48,7 +59,7 @@ void fragmentation_t::insert(rte_mbuf* mbuf) dataplane::metadata* metadata = YADECAP_METADATA(mbuf); if (!(metadata->network_flags & YANET_NETWORK_FLAG_FRAGMENT)) { - stats.not_fragment_packets++; + stats_.not_fragment_packets++; rte_pktmbuf_free(mbuf); return; } @@ -67,7 +78,7 @@ void fragmentation_t::insert(rte_mbuf* mbuf) if (range_from == range_to) { - stats.empty_packets++; + stats_.empty_packets++; rte_pktmbuf_free(mbuf); return; } @@ -98,7 +109,7 @@ void fragmentation_t::insert(rte_mbuf* mbuf) if (range_from == range_to) { - stats.empty_packets++; + stats_.empty_packets++; rte_pktmbuf_free(mbuf); return; } @@ -120,33 +131,33 @@ void fragmentation_t::insert(rte_mbuf* mbuf) } else { - stats.unknown_network_type_packets++; + stats_.unknown_network_type_packets++; rte_pktmbuf_free(mbuf); return; } - if (!exist(fragments, key)) + if (!exist(fragments_, key)) { - fragments[key] = {{{range_from, - {range_to, - mbuf}}}, - currentTime, - currentTime}; + fragments_[key] = {{{range_from, + {range_to, + mbuf}}}, + currentTime, + currentTime}; } else { - auto& value = fragments[key]; + auto& value = fragments_[key]; - if (std::get<0>(value).size() > dataPlane->getConfigValues().fragmentation_packets_per_flow) + if (std::get<0>(value).size() > config_.packets_per_flow) { - stats.flow_overflow_packets++; + stats_.flow_overflow_packets++; rte_pktmbuf_free(mbuf); return; } if (isIntersect(value, range_from, range_to)) { - stats.intersect_packets++; + stats_.intersect_packets++; rte_pktmbuf_free(mbuf); return; } @@ -155,14 +166,14 @@ void fragmentation_t::insert(rte_mbuf* mbuf) std::get<2>(value) = currentTime; } - stats.current_count_packets++; + stats_.current_count_packets++; } -void fragmentation_t::handle() +void Fragmentation::handle() { std::vector gc_keys; - for (auto& [key, value] : fragments) + for (auto& [key, value] : fragments_) { if (isTimeout(value)) { @@ -214,8 +225,8 @@ void fragmentation_t::handle() dataplane::metadata* metadata = YADECAP_METADATA(mbuf); metadata->flow.data = firstPacket_metadata->flow.data; - controlPlane->sendPacketToSlowWorker(mbuf, metadata->flow); - stats.current_count_packets--; + callback_(mbuf, metadata->flow); + stats_.current_count_packets--; } std::get<0>(value).clear(); @@ -225,33 +236,33 @@ void fragmentation_t::handle() for (const auto& key : gc_keys) { - for (auto& [range_from, range_value] : std::get<0>(fragments[key])) + for (auto& [range_from, range_value] : std::get<0>(fragments_[key])) { (void)range_from; const auto& [range_to, mbuf] = range_value; (void)range_to; - stats.timeout_packets++; + stats_.timeout_packets++; rte_pktmbuf_free(mbuf); - stats.current_count_packets--; + stats_.current_count_packets--; } - fragments.erase(key); + fragments_.erase(key); } } -bool fragmentation_t::isTimeout(const fragmentation::value_t& value) +bool Fragmentation::isTimeout(const fragmentation::value_t& value) const { uint16_t currentTime = time(nullptr); - if ((uint16_t)(currentTime - std::get<1>(value)) >= dataPlane->getConfigValues().fragmentation_timeout_first) + if ((uint16_t)(currentTime - std::get<1>(value)) >= config_.timeout_first) { return true; } - if ((uint16_t)(currentTime - std::get<2>(value)) >= dataPlane->getConfigValues().fragmentation_timeout_last) + if ((uint16_t)(currentTime - std::get<2>(value)) >= config_.timeout_last) { return true; } @@ -259,7 +270,7 @@ bool fragmentation_t::isTimeout(const fragmentation::value_t& value) return false; } -bool fragmentation_t::isCollected(const fragmentation::value_t& value) +bool Fragmentation::isCollected(const fragmentation::value_t& value) const { uint32_t next_range_from = 0; for (const auto& [range_from, range_value] : std::get<0>(value)) @@ -283,9 +294,9 @@ bool fragmentation_t::isCollected(const fragmentation::value_t& value) return false; } -bool fragmentation_t::isIntersect(const fragmentation::value_t& value, - const uint32_t& second_range_from, - const uint32_t& second_range_to) +bool Fragmentation::isIntersect(const fragmentation::value_t& value, + const uint32_t& second_range_from, + const uint32_t& second_range_to) const { for (const auto& [range_from, range_value] : std::get<0>(value)) { @@ -306,3 +317,4 @@ bool fragmentation_t::isIntersect(const fragmentation::value_t& value, return false; } +} // namespace fragmentation \ No newline at end of file diff --git a/dataplane/fragmentation.h b/dataplane/fragmentation.h index da1bc659..e25070e2 100644 --- a/dataplane/fragmentation.h +++ b/dataplane/fragmentation.h @@ -11,6 +11,7 @@ #include "common/type.h" +#include "config_values.h" #include "type.h" namespace fragmentation @@ -37,30 +38,38 @@ using value_t = std::tuple; ///< last packet time -} - -class fragmentation_t +class Fragmentation { public: - fragmentation_t(cControlPlane* controlPlane, cDataPlane* dataPlane); - ~fragmentation_t(); + using OnCollected = std::function; + Fragmentation(OnCollected callback); + Fragmentation(OnCollected callback, const FragmentationConfig& cfg); + Fragmentation(Fragmentation&& other); + ~Fragmentation(); + + Fragmentation& operator=(Fragmentation&& other) = default; public: - common::fragmentation::stats_t getStats(); + common::fragmentation::stats_t getStats() const; + OnCollected& Callback() { return callback_; } + void Configure(const FragmentationConfig& cfg) { config_ = cfg; } void insert(rte_mbuf* mbuf); void handle(); protected: - bool isTimeout(const fragmentation::value_t& value); - bool isCollected(const fragmentation::value_t& value); - bool isIntersect(const fragmentation::value_t& value, const uint32_t& range_from, const uint32_t& range_to); + bool isTimeout(const value_t& value) const; + bool isCollected(const value_t& value) const; + bool isIntersect(const value_t& value, const uint32_t& range_from, const uint32_t& range_to) const; protected: - cControlPlane* controlPlane; - cDataPlane* dataPlane; + OnCollected callback_; - common::fragmentation::stats_t stats; + FragmentationConfig config_; - std::map fragments; + common::fragmentation::stats_t stats_; + + std::map fragments_; }; + +} // namespace fragmentation \ No newline at end of file From 315c6e41c51c3d4519ef81933035f27f035b0e54 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 18 Jun 2024 17:18:48 +0300 Subject: [PATCH 040/195] Adds merge and move operations to ctree --- common/ctree.h | 134 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 38 deletions(-) diff --git a/common/ctree.h b/common/ctree.h index cccee863..50c737c7 100644 --- a/common/ctree.h +++ b/common/ctree.h @@ -10,9 +10,10 @@ namespace common template -class ctree +struct ctree { -public: + using values_t = std::array; + ctree() { if constexpr (sizeof...(counters_T) > 0) @@ -24,6 +25,19 @@ class ctree root_node = new node_base_t(); } } + ctree(ctree&& other) : + root_node{} + { + if (this != &other) + { + *this = std::move(other); + } + } + ctree& operator=(ctree&& other) + { + std::swap(root_node, other.root_node); + return *this; + } ~ctree() { @@ -32,9 +46,8 @@ class ctree /// @todo: delete copy -public: void append(const counters_T&... counters, - const std::array& values) + const values_t& values) { if constexpr (sizeof...(counters_T) > 0) { @@ -47,7 +60,7 @@ class ctree } void apply(const counters_T&... counters, - const std::function...>, std::array&)>& callback) + const std::function...>, values_t&)>& callback) { std::tuple...> keys; @@ -84,7 +97,7 @@ class ctree } void print(const std::vector& key_names, - const std::function&)>& callback) const + const std::function& callback) const { root_node->print("", 0, key_names, callback); } @@ -99,34 +112,31 @@ class ctree root_node->push(stream); } -public: - class node_base_t + void merge(const ctree& other) { - public: - node_base_t() - { - for (auto& value : values) - { - value = 0; - } - } - - virtual ~node_base_t() - { - } + root_node->merge(other.root_node); + } - public: - void append(const std::array& values) + struct node_base_t + { + node_base_t() = default; + node_base_t(const node_base_t& other) : + values{other.values} {} + node_base_t(const values_t& values) : + values{values} {} + virtual ~node_base_t() = default; + + void append(const values_t& values) { - for (std::size_t i = 0; - i < values_size_T; - i++) + auto& a = this->values; + auto& b = values; + for (std::size_t i = 0, e = a.size(); i < e; ++i) { - this->values[i] += values[i]; + a[i] += b[i]; } } - void apply(const std::function...>, std::array&)>& callback, + void apply(const std::function...>, values_t&)>& callback, std::tuple...>& keys) { callback(keys, this->values); @@ -135,7 +145,7 @@ class ctree virtual void print(const std::string& key, const uint32_t& key_index, const std::vector& key_names, - const std::function&)>& callback) const + const std::function& callback) const { (void)key_index; (void)key_names; @@ -153,15 +163,34 @@ class ctree stream.push(values); } - public: - std::array values; + virtual void merge(const node_base_t* other) + { + this->append(other->values); + } + + values_t values; }; template - class node_t : public node_base_t + struct node_t : public node_base_t { - public: + node_t() = default; + node_t(const node_t& other) : + node_base_t{other}, convert{other.convert} + { + for (const auto& [key, value] : other.next) + { + if constexpr (sizeof...(next_counters_T) != 0) + { + next.emplace(key, new node_t{*static_cast(value)}); + } + else + { + next.emplace(key, new node_base_t{*value}); + } + } + } ~node_t() override { for (auto& [next_counter, next_node] : next) @@ -171,13 +200,12 @@ class ctree } } - public: using node_base_t::append; using node_base_t::apply; void append(const next_counter_T& next_counter, const next_counters_T&... next_counters, - const std::array& values) + const values_t& values) { node_base_t::append(values); @@ -205,7 +233,7 @@ class ctree void apply(const next_counter_T& next_counter, const next_counters_T&... next_counters, - const std::function...>, std::array&)>& callback, + const std::function...>, values_t&)>& callback, std::tuple...>& keys) { node_base_t::apply(callback, keys); @@ -252,7 +280,7 @@ class ctree void print(const std::string& key, const uint32_t& key_index, const std::vector& key_names, - const std::function&)>& callback) const override + const std::function& callback) const override { node_base_t::print(key, key_index, key_names, callback); @@ -323,7 +351,37 @@ class ctree } } - public: + void merge(const node_base_t* other) override + { + for (const auto& [key, node] : static_cast(other)->next) + { + if (auto it = next.find(key); it != next.end()) + { + it->second->merge(node); + } + else + { + if constexpr (sizeof...(next_counters_T) != 0) + { + using actual = node_t; + next.emplace(key, new actual(*static_cast(node))); + } + else + { + next.emplace(key, new node_base_t(*node)); + } + } + } + + for (const auto& [key, value] : static_cast(other)->convert) + { + if (convert.find(key) == convert.end()) + { + convert.emplace(key, value); + } + } + } + std::map next; @@ -336,4 +394,4 @@ class ctree node_base_t* root_node; }; -} +} // namespace common From b66e7b3ffcdf92ce8f251bb7f2c4639bdb5cc09c Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 27 Jun 2024 19:24:59 +0300 Subject: [PATCH 041/195] Out of class hastable stats Derclaring stats as a dependent type of hastable interferes with nlohmann ability do find conversion functions. --- dataplane/hashtable.h | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index 2ddfece8..20401522 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -621,6 +621,22 @@ class hashtable_chain_t static_assert(pairsPerExtendedChunk_T <= 7); } __rte_aligned(RTE_CACHE_LINE_SIZE); +struct hashtable_chain_spinlock_stats_t +{ + uint64_t extendedChunksCount; + uint64_t longestChain; + uint64_t pairs; + uint64_t insertFailed; + hashtable_chain_spinlock_stats_t& operator+=(const hashtable_chain_spinlock_stats_t& other) + { + extendedChunksCount += other.extendedChunksCount; + longestChain += other.longestChain; + pairs += other.pairs; + insertFailed += other.insertFailed; + return *this; + } +}; + template Date: Fri, 28 Jun 2024 12:38:40 +0300 Subject: [PATCH 042/195] Dregress codestyle changes --- dataplane/dregress.cpp | 4 ++-- dataplane/hashtable.h | 33 ++++++++++++++++---------------- dataplane/report.cpp | 2 +- dataplane/unittest/hashtable.cpp | 18 ++++++++--------- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index 70835f11..1bd20b84 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -646,10 +646,10 @@ void dregress_t::limits(common::idp::limits::response& response) { limit_insert(response, "dregress.ht.keys", - connections->getStats().pairs, + connections->stats().pairs, connections->keysSize); limit_insert(response, "dregress.ht.extended_chunks", - connections->getStats().extendedChunksCount, + connections->stats().extendedChunksCount, YANET_CONFIG_DREGRESS_HT_EXTENDED_SIZE); } diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index 20401522..1d51edd0 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -661,7 +661,7 @@ class hashtable_chain_spinlock_t extendedChunk.setNextExtendedChunkId(extendedChunkIdUnknown); freeExtendedChunkId = 0; - memset(&stats, 0, sizeof(stats)); + memset(&stats_, 0, sizeof(stats_)); } constexpr static uint64_t keysSize = size_T * pairsPerChunk_T + extendedSize_T * pairsPerExtendedChunk_T; @@ -808,8 +808,8 @@ class hashtable_chain_spinlock_t chunk.setValid(chunk_key_i); - __atomic_add_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); - stats.longestChain = RTE_MAX(stats.longestChain, longestChain); + __atomic_add_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); + stats_.longestChain = RTE_MAX(stats_.longestChain, longestChain); return eResult::success; } @@ -842,8 +842,8 @@ class hashtable_chain_spinlock_t extendedChunk.setValid(extended_chunk_key_i); - __atomic_add_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); - stats.longestChain = RTE_MAX(stats.longestChain, longestChain); + __atomic_add_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); + stats_.longestChain = RTE_MAX(stats_.longestChain, longestChain); return eResult::success; } @@ -853,7 +853,7 @@ class hashtable_chain_spinlock_t /// chain is full - __atomic_add_fetch(&stats.insertFailed, 1, __ATOMIC_RELAXED); + __atomic_add_fetch(&stats_.insertFailed, 1, __ATOMIC_RELAXED); chunk.locker.unlock(); return eResult::isFull; @@ -879,7 +879,7 @@ class hashtable_chain_spinlock_t chunk.unsetValid(chunk_key_i); - __atomic_sub_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); chunk.locker.unlock(); return true; @@ -903,7 +903,7 @@ class hashtable_chain_spinlock_t /// use gc for remove extended chunk - __atomic_sub_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); chunk.locker.unlock(); return true; @@ -937,7 +937,7 @@ class hashtable_chain_spinlock_t { chunk.unsetValid(chunk_key_i); - __atomic_sub_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); } } @@ -953,7 +953,7 @@ class hashtable_chain_spinlock_t { extendedChunk.unsetValid(extended_chunk_key_i); - __atomic_sub_fetch(&stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&stats_.pairs, 1, __ATOMIC_RELAXED); } } @@ -1052,7 +1052,7 @@ class hashtable_chain_spinlock_t { chunk.unsetValid(key_i); - __atomic_sub_fetch(&hashtable->stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&hashtable->stats_.pairs, 1, __ATOMIC_RELAXED); } else if (chunk.getNextExtendedChunkId() != extendedChunkIdUnknown) { @@ -1060,7 +1060,7 @@ class hashtable_chain_spinlock_t extendedChunk.unsetValid(key_i - pairsPerChunk_T); - __atomic_sub_fetch(&hashtable->stats.pairs, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(&hashtable->stats_.pairs, 1, __ATOMIC_RELAXED); } } @@ -1419,7 +1419,7 @@ class hashtable_chain_spinlock_t freeExtendedChunkId = extendedChunk.getNextExtendedChunkId(); extendedChunk.setNextExtendedChunkId(extendedChunkIdUnknown); - stats.extendedChunksCount++; + stats_.extendedChunksCount++; extendedChunkLocker.unlock(); return chunkId; @@ -1439,17 +1439,16 @@ class hashtable_chain_spinlock_t extendedChunk.setNextExtendedChunkId(freeExtendedChunkId); freeExtendedChunkId = extendedChunkId; - stats.extendedChunksCount--; + stats_.extendedChunksCount--; extendedChunkLocker.unlock(); } hashtable_chain_spinlock_stats_t stats_; public: - hashtable_chain_spinlock_stats_t stats; - const hashtable_chain_spinlock_stats_t& getStats() const + const hashtable_chain_spinlock_stats_t& stats() const { - return stats; + return stats_; } protected: diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 582829b6..8fe70c3c 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -15,7 +15,7 @@ nlohmann::json convertHashtable(const hashtable_chain_T& hashtable) { nlohmann::json json; - const auto& stats = hashtable.getStats(); + const auto& stats = hashtable.stats(); json["extendedChunksCount"] = stats.extendedChunksCount; json["longestChain"] = stats.longestChain; diff --git a/dataplane/unittest/hashtable.cpp b/dataplane/unittest/hashtable.cpp index 98f57c72..92d2311c 100644 --- a/dataplane/unittest/hashtable.cpp +++ b/dataplane/unittest/hashtable.cpp @@ -70,7 +70,7 @@ TEST(HashtableTest, Extended) } EXPECT_TRUE(ok); - EXPECT_NE(t.getStats().extendedChunksCount, 0); + EXPECT_NE(t.stats().extendedChunksCount, 0); uint32_t from = 0; for (auto iter : t.range(from, 8192)) @@ -100,8 +100,8 @@ TEST(HashtableTest, Extended) iter.unlock(); } - EXPECT_EQ(t.getStats().extendedChunksCount, 0); - EXPECT_EQ(t.getStats().pairs, 0); + EXPECT_EQ(t.stats().extendedChunksCount, 0); + EXPECT_EQ(t.stats().pairs, 0); for (int k = 0; k < 512; ++k) { @@ -127,21 +127,21 @@ TEST(HashtableTest, Extended) iter.unlock(); } - EXPECT_EQ(t.getStats().extendedChunksCount, 0); - EXPECT_EQ(t.getStats().pairs, 0); + EXPECT_EQ(t.stats().extendedChunksCount, 0); + EXPECT_EQ(t.stats().pairs, 0); for (int k = 0; k < 100500; ++k) { t.insert(k, k); } - EXPECT_EQ(t.getStats().extendedChunksCount, 128); - EXPECT_EQ(t.getStats().pairs, 128 * 2 + 128 * 4); + EXPECT_EQ(t.stats().extendedChunksCount, 128); + EXPECT_EQ(t.stats().pairs, 128 * 2 + 128 * 4); t.clear(); - EXPECT_EQ(t.getStats().extendedChunksCount, 0); - EXPECT_EQ(t.getStats().pairs, 0); + EXPECT_EQ(t.stats().extendedChunksCount, 0); + EXPECT_EQ(t.stats().pairs, 0); } TEST(hashtable_mod_id32, basic) From 390b1087d21b7796ebe16cbaa32cb5b91755ca8d Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 27 Jun 2024 13:18:18 +0300 Subject: [PATCH 043/195] Dregress changed to depending on slow worker --- dataplane/controlplane.cpp | 33 ++++++++++++-- dataplane/controlplane.h | 7 +++ dataplane/dregress.cpp | 93 ++++++++++++++++++++------------------ dataplane/dregress.h | 58 ++++++++++++++++++------ dataplane/meson.build | 1 + dataplane/report.cpp | 69 ++++++++++++++++------------ dataplane/slow_worker.cpp | 25 ++++++++++ dataplane/slow_worker.h | 22 +++++++++ dataplane/worker.h | 5 ++ 9 files changed, 222 insertions(+), 91 deletions(-) create mode 100644 dataplane/slow_worker.cpp create mode 100644 dataplane/slow_worker.h diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 4964faaf..7f738056 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -30,7 +30,10 @@ cControlPlane::cControlPlane(cDataPlane* dataPlane) : sendPacketToSlowWorker(pkt, flow); }, dataPlane->getConfigValues().fragmentation), - dregress(this, dataPlane), + slow_(this), + dregress(&slow_, + dataPlane, + dataPlane->getConfigValues().gc_step), mempool(nullptr), use_kernel_interface(false), slowWorker(nullptr), @@ -381,7 +384,12 @@ common::idp::get_worker_gc_stats::response cControlPlane::get_worker_gc_stats() common::idp::get_dregress_counters::response cControlPlane::get_dregress_counters() { - return dregress.get_dregress_counters(); + auto guard = dregress.LockCounters(); + common::stream_out_t stream; + dregress.Counters4().push(stream); + dregress.Counters6().push(stream); + dregress.ClearCounters(); + return stream.getBuffer(); } common::idp::get_ports_stats::response cControlPlane::get_ports_stats() @@ -494,6 +502,16 @@ common::idp::getFragmentationStats::response cControlPlane::getFragmentationStat return fragmentation_.getStats(); } +common::dregress::stats_t cControlPlane::DregressStats() const +{ + return dregress.Stats(); +} + +dataplane::hashtable_chain_spinlock_stats_t cControlPlane::DregressConnectionsStats() const +{ + return dregress.Connections()->stats(); +} + common::idp::getFWState::response cControlPlane::getFWState() { common::idp::getFWState::response response; @@ -916,7 +934,16 @@ common::idp::limits::response cControlPlane::limits() worker_gc->limits(response); } - dregress.limits(response); + auto dregress = this->dregress.limits(); + + limit_insert(response, + "dregress.ht.keys", + dregress.pairs, + dregress.keysSize); + limit_insert(response, + "dregress.ht.extended_chunks", + dregress.extendedChunksCount, + YANET_CONFIG_DREGRESS_HT_EXTENDED_SIZE); return response; } diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index fbe24dcc..a18608b7 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -20,6 +20,7 @@ #include "dregress.h" #include "fragmentation.h" #include "kernel_interface_handle.h" +#include "slow_worker.h" #include "type.h" class cControlPlane ///< @todo: move to cDataPlane @@ -45,6 +46,8 @@ class cControlPlane ///< @todo: move to cDataPlane common::idp::getControlPlanePortStats::response getControlPlanePortStats(const common::idp::getControlPlanePortStats::request& request); common::idp::getPortStatsEx::response getPortStatsEx(); common::idp::getFragmentationStats::response getFragmentationStats(); + common::dregress::stats_t DregressStats() const; + dataplane::hashtable_chain_spinlock_stats_t DregressConnectionsStats() const; common::idp::getFWState::response getFWState(); common::idp::getFWStateStats::response getFWStateStats(); eResult clearFWState(); @@ -120,6 +123,7 @@ class cControlPlane ///< @todo: move to cDataPlane cDataPlane* dataPlane; fragmentation::Fragmentation fragmentation_; + dataplane::SlowWorker slow_; dregress_t dregress; std::mutex mutex; @@ -159,7 +163,10 @@ class cControlPlane ///< @todo: move to cDataPlane common::slowworker::stats_t stats; common::idp::getErrors::response errors; ///< @todo: class errorsManager +public: cWorker* slowWorker; + +protected: std::queue> slowWorkerMbufs; diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index 1bd20b84..0da1b766 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -4,19 +4,45 @@ #include "common/fallback.h" #include "checksum.h" -#include "controlplane.h" #include "dataplane.h" #include "dregress.h" #include "metadata.h" -#include "worker.h" +#include "slow_worker.h" + +dregress_t::dregress_t(dataplane::SlowWorker* slow, cDataPlane* dataplane, uint32_t gc_step) : + slow_worker_{slow}, + dataplane{dataplane}, + stats{}, + connections{new dregress::ConnTable}, + gc_step{gc_step} +{} +dregress_t::dregress_t(dregress_t&& other) : + connections{nullptr} +{ + *this = std::move(other); + + other.connections = nullptr; +} -dregress_t::dregress_t(cControlPlane* controlplane, - cDataPlane* dataplane) : - controlplane(controlplane), - dataplane(dataplane) +dregress_t& dregress_t::operator=(dregress_t&& other) { - memset(&stats, 0, sizeof(stats)); - connections = new dataplane::hashtable_chain_spinlock_t(); + slow_worker_ = other.slow_worker_; + dataplane = other.dataplane; + stats = other.stats; + std::swap(connections, other.connections); + + auto pre_guard = std::lock_guard(other.prefixes_mutex); + std::swap(local_prefixes_v4, other.local_prefixes_v4); + std::swap(local_prefixes_v6, other.local_prefixes_v6); + std::swap(prefixes, other.prefixes); + std::swap(values, other.values); + + auto count_guard = std::lock_guard(other.counters_mutex); + std::swap(counters_v4, other.counters_v4); + std::swap(counters_v6, other.counters_v6); + + gc_step = other.gc_step; + return *this; } dregress_t::~dregress_t() @@ -28,14 +54,14 @@ void dregress_t::insert(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - const auto& base = controlplane->slowWorker->bases[controlplane->slowWorker->localBaseId & 1]; + const auto& base = slow_worker_->current_base(); const auto& dregress = base.globalBase->dregresses[metadata->flow.data.dregressId]; if (metadata->network_flags & YANET_NETWORK_FLAG_FRAGMENT) { stats.fragment++; - controlplane->sendPacketToSlowWorker(mbuf, dregress.flow); + slow_worker_->SendToSlowWorker(mbuf, dregress.flow); return; } @@ -43,7 +69,7 @@ void dregress_t::insert(rte_mbuf* mbuf) { stats.bad_transport++; - controlplane->sendPacketToSlowWorker(mbuf, dregress.flow); + slow_worker_->SendToSlowWorker(mbuf, dregress.flow); return; } @@ -84,7 +110,7 @@ void dregress_t::insert(rte_mbuf* mbuf) { stats.lookup_miss++; - controlplane->sendPacketToSlowWorker(mbuf, dregress.flow); + slow_worker_->SendToSlowWorker(mbuf, dregress.flow); return; } @@ -122,7 +148,7 @@ void dregress_t::insert(rte_mbuf* mbuf) { stats.lookup_miss++; - controlplane->sendPacketToSlowWorker(mbuf, dregress.flow); + slow_worker_->SendToSlowWorker(mbuf, dregress.flow); return; } @@ -388,8 +414,8 @@ void dregress_t::insert(rte_mbuf* mbuf) } /// @todo: opt - controlplane->slowWorker->preparePacket(mbuf); - controlplane->sendPacketToSlowWorker(mbuf, dregress.flow); + slow_worker_->PreparePacket(mbuf); + slow_worker_->SendToSlowWorker(mbuf, dregress.flow); } void dregress_t::handle() @@ -430,7 +456,7 @@ void dregress_t::handle() std::optional dregress_t::lookup(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - const auto& base = controlplane->slowWorker->bases[controlplane->slowWorker->localBaseId & 1]; + const auto& base = slow_worker_->current_base(); const auto& dregress = base.globalBase->dregresses[metadata->flow.data.dregressId]; std::map guard(counters_mutex); ///< @todo: free lock - common::stream_out_t stream; - counters_v4.push(stream); - counters_v6.push(stream); - response = stream.getBuffer(); - - YANET_MEMORY_BARRIER_COMPILE; - - counters_v4.clear(); ///< @todo: swap - counters_v6.clear(); ///< @todo: swap - } - - return response; -} - -void dregress_t::limits(common::idp::limits::response& response) +dregress::LimitsStats dregress_t::limits() const { - limit_insert(response, - "dregress.ht.keys", - connections->stats().pairs, - connections->keysSize); - limit_insert(response, - "dregress.ht.extended_chunks", - connections->stats().extendedChunksCount, - YANET_CONFIG_DREGRESS_HT_EXTENDED_SIZE); + return { + connections->stats().pairs, + connections->keysSize, + connections->stats().extendedChunksCount, + }; } diff --git a/dataplane/dregress.h b/dataplane/dregress.h index bb35ae4a..9a7b68ed 100644 --- a/dataplane/dregress.h +++ b/dataplane/dregress.h @@ -43,36 +43,68 @@ using direction_t = std::tuple; ///< origin_as -} +using ConnTable = dataplane::hashtable_chain_spinlock_t; + +struct LimitsStats +{ + uint64_t pairs; + uint64_t keysSize; + uint64_t extendedChunksCount; + LimitsStats& operator+=(const LimitsStats& other) + { + pairs += other.pairs; + keysSize += other.keysSize; + extendedChunksCount += other.extendedChunksCount; + return *this; + } +}; + +} // namespace dregress + +namespace dataplane +{ +class SlowWorker; +} // namespace dataplane class dregress_t { public: - dregress_t(cControlPlane* controlplane, cDataPlane* dataplane); + dregress_t(dataplane::SlowWorker* slow, cDataPlane* dataplane, uint32_t gc_step); + dregress_t(dregress_t&& other); ~dregress_t(); + dregress_t& operator=(dregress_t&& other); + void insert(rte_mbuf* mbuf); void handle(); std::optional lookup(rte_mbuf* mbuf); bool tcp_parse(rte_mbuf* mbuf, uint16_t& rtt, uint32_t& loss_count, uint32_t& ack_count); - - common::idp::get_dregress_counters::response get_dregress_counters(); - void limits(common::idp::limits::response& response); + dregress::LimitsStats limits() const; + const common::dregress::stats_t& Stats() const { return stats; } + const dregress::ConnTable* Connections() const { return connections; } + [[nodiscard]] std::lock_guard LockCounters() { return std::lock_guard{counters_mutex}; } + const common::dregress::counters_t& Counters4() const { return counters_v4; } + const common::dregress::counters_t& Counters6() const { return counters_v6; } + void ClearCounters() + { + counters_v4.clear(); + counters_v6.clear(); + } public: - cControlPlane* controlplane; + dataplane::SlowWorker* slow_worker_; cDataPlane* dataplane; constexpr static double median_multiplier = 0.01; common::dregress::stats_t stats; - dataplane::hashtable_chain_spinlock_t* connections; + dregress::ConnTable* connections; std::mutex prefixes_mutex; std::set local_prefixes_v4; ///< @todo: set @@ -80,7 +112,7 @@ class dregress_t common::btree prefixes; std::map> values; - std::mutex counters_mutex; + mutable std::mutex counters_mutex; common::dregress::counters_t counters_v4; common::dregress::counters_t counters_v6; diff --git a/dataplane/meson.build b/dataplane/meson.build index a86156e8..eeb4fb99 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -18,6 +18,7 @@ sources = files('bus.cpp', 'neighbor.cpp', 'report.cpp', 'sharedmemory.cpp', + 'slow_worker.cpp', 'sock_dev.cpp', 'worker.cpp', 'worker_gc.cpp') diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 8fe70c3c..303bdc8f 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -10,21 +10,6 @@ namespace { -template -nlohmann::json convertHashtable(const hashtable_chain_T& hashtable) -{ - nlohmann::json json; - - const auto& stats = hashtable.stats(); - - json["extendedChunksCount"] = stats.extendedChunksCount; - json["longestChain"] = stats.longestChain; - json["pairs"] = stats.pairs; - json["insertFailed"] = stats.insertFailed; - - return json; -} - template nlohmann::json convertHashtable(const hashtable_mod_T& hashtable, const stats_T& stats_generation) @@ -49,6 +34,31 @@ nlohmann::json convertHashtable(const hashtable_mod_T& hashtable, const stats_T& } // namespace +namespace common +{ +namespace dregress +{ +void to_json(nlohmann::json& j, const stats_t& stats) +{ + j = nlohmann::json{ + {"bad_decap_transport", stats.bad_decap_transport}, + {"fragment", stats.fragment}, + {"bad_transport", stats.bad_transport}, + {"lookup_miss", stats.lookup_miss}, + {"local", stats.local}, + {"tcp_syn", stats.tcp_syn}, + {"tcp_unknown_option", stats.tcp_unknown_option}, + {"tcp_no_option", stats.tcp_no_option}, + {"tcp_insert_sessions", stats.tcp_insert_sessions}, + {"tcp_close_sessions", stats.tcp_close_sessions}, + {"tcp_retransmission", stats.tcp_retransmission}, + {"tcp_ok", stats.tcp_ok}, + {"tcp_timeout_sessions", stats.tcp_timeout_sessions}, + {"tcp_unknown_sessions", stats.tcp_unknown_sessions}}; +} +} // namespace dregress +} // namespace common + cReport::cReport(cDataPlane* dataPlane) : dataPlane(dataPlane) { @@ -352,6 +362,18 @@ nlohmann::json cReport::convertPort(const tPortId& portId) return json; } +namespace dataplane +{ +void to_json(nlohmann::json& j, const hashtable_chain_spinlock_stats_t& stats) +{ + j = nlohmann::json{ + {"extendedChunksCount", stats.extendedChunksCount}, + {"longestChain", stats.longestChain}, + {"pairs", stats.pairs}, + {"insertFailed", stats.insertFailed}}; +} +} // namespace dataplane + nlohmann::json cReport::convertControlPlane(const cControlPlane* controlPlane) { nlohmann::json json; @@ -386,21 +408,8 @@ nlohmann::json cReport::convertControlPlane(const cControlPlane* controlPlane) json["slowworker_packets"] = controlPlane->stats.slowworker_packets; json["mempool_is_empty"] = controlPlane->stats.mempool_is_empty; - json["dregress"]["bad_decap_transport"] = controlPlane->dregress.stats.bad_decap_transport; - json["dregress"]["fragment"] = controlPlane->dregress.stats.fragment; - json["dregress"]["bad_transport"] = controlPlane->dregress.stats.bad_transport; - json["dregress"]["lookup_miss"] = controlPlane->dregress.stats.lookup_miss; - json["dregress"]["local"] = controlPlane->dregress.stats.local; - json["dregress"]["tcp_syn"] = controlPlane->dregress.stats.tcp_syn; - json["dregress"]["tcp_unknown_option"] = controlPlane->dregress.stats.tcp_unknown_option; - json["dregress"]["tcp_no_option"] = controlPlane->dregress.stats.tcp_no_option; - json["dregress"]["tcp_insert_sessions"] = controlPlane->dregress.stats.tcp_insert_sessions; - json["dregress"]["tcp_close_sessions"] = controlPlane->dregress.stats.tcp_close_sessions; - json["dregress"]["tcp_retransmission"] = controlPlane->dregress.stats.tcp_retransmission; - json["dregress"]["tcp_ok"] = controlPlane->dregress.stats.tcp_ok; - json["dregress"]["tcp_timeout_sessions"] = controlPlane->dregress.stats.tcp_timeout_sessions; - json["dregress"]["tcp_unknown_sessions"] = controlPlane->dregress.stats.tcp_unknown_sessions; - json["dregress"]["connections"] = convertHashtable(*controlPlane->dregress.connections); + json["dregress"] = controlPlane->DregressStats(); + json["dregress"]["connections"] = controlPlane->DregressConnectionsStats(); return json; } diff --git a/dataplane/slow_worker.cpp b/dataplane/slow_worker.cpp new file mode 100644 index 00000000..35ca7125 --- /dev/null +++ b/dataplane/slow_worker.cpp @@ -0,0 +1,25 @@ +#include "slow_worker.h" + +#include "common/type.h" +#include "controlplane.h" +#include "worker.h" + +namespace dataplane +{ + +SlowWorker::SlowWorker(cControlPlane* cplane) : + cplane_{cplane} {} +const dataplane::base::generation& SlowWorker::current_base() +{ + return cplane_->slowWorker->current_base(); +} +void SlowWorker::SendToSlowWorker(rte_mbuf* pkt, const common::globalBase::tFlow& flow) +{ + cplane_->sendPacketToSlowWorker(pkt, flow); +} +void SlowWorker::PreparePacket(rte_mbuf* pkt) +{ + cplane_->slowWorker->preparePacket(pkt); +} + +} // dataplane \ No newline at end of file diff --git a/dataplane/slow_worker.h b/dataplane/slow_worker.h new file mode 100644 index 00000000..04ebdead --- /dev/null +++ b/dataplane/slow_worker.h @@ -0,0 +1,22 @@ +#pragma once +#include "base.h" + +class cControlPlane; + +namespace dataplane +{ + +/* + * Stub of SlowWorker to divide refactoring dregress and cControlPlane + */ +class SlowWorker +{ + cControlPlane* cplane_; +public: + explicit SlowWorker(cControlPlane* cplane); + const dataplane::base::generation& current_base(); + void SendToSlowWorker(rte_mbuf* pkt, const common::globalBase::tFlow& flow); + void PreparePacket(rte_mbuf* pkt); +}; + +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/worker.h b/dataplane/worker.h index c178ba5e..c904c294 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -72,14 +72,19 @@ class cWorker void fillStatsNamesToAddrsTable(std::unordered_map& table); + const dataplane::base::generation& current_base() { return bases[localBaseId & 1]; } + protected: eResult sanityCheck(); YANET_NEVER_INLINE void mainThread(); inline void calcHash(rte_mbuf* mbuf, uint8_t without_ports = 0); + +public: void preparePacket(rte_mbuf* mbuf); ///< @todo: inline +protected: constexpr static uint32_t translation_ignore = 0xFFFFFFFFu; inline void translation_ipv4_to_ipv6(rte_mbuf* mbuf, const ipv6_address_t& ipv6_source, const ipv6_address_t& ipv6_destination, const uint32_t port_source, const uint32_t port_destination, const uint32_t identifier); inline void translation_ipv6_to_ipv4(rte_mbuf* mbuf, const ipv4_address_t& ipv4_source, const ipv4_address_t& ipv4_destination, const uint32_t port_source, const uint32_t port_destination, const uint32_t identifier); From ce68fab58a5ec727196d4ac8367f860f8d89970d Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 18 Jun 2024 20:34:36 +0300 Subject: [PATCH 044/195] Fixes dump rings choosing in autotests Information about dump rings was previously added to a map with ring tag as a key. This resulted in ring information being overwritten by next ring with the same tag, leaving only the last parsed ring information. This commit switches to using ring unique name as a key, tests are changed accordingly --- autotest/autotest.cpp | 4 ++-- autotest/units/001_one_port/067_dump_after_term/autotest.yaml | 2 +- autotest/units/001_one_port/067_dump_default/autotest.yaml | 2 +- autotest/units/001_one_port/067_dump_with_deny/autotest.yaml | 2 +- .../001_one_port/067_intersecting_dump_rules/autotest.yaml | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 1930d955..6e951afc 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -163,7 +163,7 @@ eResult tAutotest::initSharedMemory() for (const auto& shmInfo : dataPlaneSharedMemory) { - std::string tag = std::get<1>(shmInfo); + std::string name = std::get<0>(shmInfo); unsigned int unitSize = std::get<2>(shmInfo); unsigned int unitsNumber = std::get<3>(shmInfo); key_t ipcKey = std::get<6>(shmInfo); @@ -171,7 +171,7 @@ eResult tAutotest::initSharedMemory() void* shm = shm_by_key[ipcKey]; auto memaddr = (void*)((intptr_t)shm + offset); - dumpRings[tag] = common::bufferring(memaddr, unitSize, unitsNumber); + dumpRings[name] = common::bufferring(memaddr, unitSize, unitsNumber); } return eResult::success; diff --git a/autotest/units/001_one_port/067_dump_after_term/autotest.yaml b/autotest/units/001_one_port/067_dump_after_term/autotest.yaml index e6eb3fca..5a50389d 100644 --- a/autotest/units/001_one_port/067_dump_after_term/autotest.yaml +++ b/autotest/units/001_one_port/067_dump_after_term/autotest.yaml @@ -6,5 +6,5 @@ steps: send: 001-send.pcap expect: 001-expect.pcap - dumpPackets: - - ringTag: ring1 + - ringTag: shm_2_0 expect: 001-expect-dump-ring1.pcap diff --git a/autotest/units/001_one_port/067_dump_default/autotest.yaml b/autotest/units/001_one_port/067_dump_default/autotest.yaml index e6eb3fca..5a50389d 100644 --- a/autotest/units/001_one_port/067_dump_default/autotest.yaml +++ b/autotest/units/001_one_port/067_dump_default/autotest.yaml @@ -6,5 +6,5 @@ steps: send: 001-send.pcap expect: 001-expect.pcap - dumpPackets: - - ringTag: ring1 + - ringTag: shm_2_0 expect: 001-expect-dump-ring1.pcap diff --git a/autotest/units/001_one_port/067_dump_with_deny/autotest.yaml b/autotest/units/001_one_port/067_dump_with_deny/autotest.yaml index e6eb3fca..5a50389d 100644 --- a/autotest/units/001_one_port/067_dump_with_deny/autotest.yaml +++ b/autotest/units/001_one_port/067_dump_with_deny/autotest.yaml @@ -6,5 +6,5 @@ steps: send: 001-send.pcap expect: 001-expect.pcap - dumpPackets: - - ringTag: ring1 + - ringTag: shm_2_0 expect: 001-expect-dump-ring1.pcap diff --git a/autotest/units/001_one_port/067_intersecting_dump_rules/autotest.yaml b/autotest/units/001_one_port/067_intersecting_dump_rules/autotest.yaml index 0cdfb29e..d9204293 100644 --- a/autotest/units/001_one_port/067_intersecting_dump_rules/autotest.yaml +++ b/autotest/units/001_one_port/067_intersecting_dump_rules/autotest.yaml @@ -6,7 +6,7 @@ steps: send: 001-send.pcap expect: 001-expect.pcap - dumpPackets: - - ringTag: ring1 + - ringTag: shm_2_0 expect: 001-expect-dump-ring1.pcap - - ringTag: ring2 + - ringTag: shm_2_1 expect: 001-expect-dump-ring2.pcap From 298e5f7df8f767865e0beffb0e4f6800f488c5a7 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 3 Jun 2024 17:33:00 +0300 Subject: [PATCH 045/195] Moves icmp translations logic to separate file --- dataplane/controlplane.cpp | 515 +------------------------------ dataplane/icmp_translations.cpp | 516 ++++++++++++++++++++++++++++++++ dataplane/icmp_translations.h | 13 + dataplane/meson.build | 1 + 4 files changed, 533 insertions(+), 512 deletions(-) create mode 100644 dataplane/icmp_translations.cpp create mode 100644 dataplane/icmp_translations.h diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 7f738056..f2978432 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -19,6 +19,7 @@ #include "dataplane.h" #include "debug_latch.h" #include "icmp.h" +#include "icmp_translations.h" #include "metadata.h" #include "prepare.h" #include "worker.h" @@ -1702,263 +1703,6 @@ void cControlPlane::handlePacketFromForwardingPlane(rte_mbuf* mbuf) } } -static bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, - const dataplane::globalBase::nat64stateless_translation_t& translation) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - rte_ipv4_hdr* ipv4ExtHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); - - if (ipv4ExtHeader->next_proto_id != IPPROTO_ICMP) - { - return false; - } - - unsigned int payloadExtLen = rte_be_to_cpu_16(ipv4ExtHeader->total_length) - sizeof(rte_ipv4_hdr); - - if (payloadExtLen < sizeof(icmp_header_t*) + sizeof(rte_ipv6_hdr)) - { - return false; - } - - icmp_header_t* icmpHeader = rte_pktmbuf_mtod_offset(mbuf, icmp_header_t*, metadata->network_headerOffset + sizeof(rte_ipv4_hdr)); - uint8_t type = icmpHeader->type; - uint8_t code = icmpHeader->code; - - if (type == ICMP6_DST_UNREACH) - { - type = ICMP_DEST_UNREACH; - - if (code == ICMP6_DST_UNREACH_NOROUTE || code == ICMP6_DST_UNREACH_BEYONDSCOPE || - code == ICMP6_DST_UNREACH_ADDR) - { - code = ICMP_HOST_UNREACH; - } - else if (code == ICMP6_DST_UNREACH_ADMIN) - { - code = ICMP_HOST_ANO; - } - else if (code == ICMP6_DST_UNREACH_NOPORT) - { - code = ICMP_PORT_UNREACH; - } - else - { - return false; - } - } - else if (type == ICMP6_PACKET_TOO_BIG) - { - type = ICMP_DEST_UNREACH; - code = ICMP_FRAG_NEEDED; - - uint32_t mtu = rte_be_to_cpu_32(icmpHeader->data32[0]) - 20; - icmpHeader->data32[0] = 0; - icmpHeader->data16[1] = rte_cpu_to_be_16(mtu); - } - else if (type == ICMP6_TIME_EXCEEDED) - { - type = ICMP_TIME_EXCEEDED; - } - else if (type == ICMP6_PARAM_PROB) - { - - if (code == ICMP6_PARAMPROB_HEADER) - { - type = ICMP_PARAMETERPROB; - code = 0; - uint32_t ptr = rte_be_to_cpu_32(icmpHeader->data32[0]); - icmpHeader->data32[0] = 0; - - if (ptr == 0 || ptr == 1) - { - /// unchanged - } - else if (ptr == 4 || ptr == 5) - { - ptr = 2; - } - else if (ptr == 6) - { - ptr = 9; - } - else if (ptr == 7) - { - ptr = 8; - } - else if (ptr >= 8 && ptr < 24) - { - ptr = 12; - } - else if (ptr >= 24 && ptr < 40) - { - ptr = 16; - } - else - { - return false; - } - - icmpHeader->data8[0] = ptr; - } - else if (code == ICMP6_PARAMPROB_NEXTHEADER) - { - type = ICMP_DEST_UNREACH; - code = ICMP_PROT_UNREACH; - icmpHeader->data32[0] = 0; - } - } - else - { - return false; - } - - icmpHeader->type = type; - icmpHeader->code = code; - - rte_ipv6_hdr* ipv6PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset + sizeof(rte_ipv4_hdr) + sizeof(icmp_header_t)); - - /// @todo: think about it. - if (memcmp(ipv6PayloadHeader->dst_addr, translation.ipv6Address.bytes, 16)) - { - return false; - } - - if (memcmp(ipv6PayloadHeader->src_addr, translation.ipv6DestinationAddress.bytes, 12)) - { - return false; - } - - uint32_t addressSource = *(uint32_t*)&ipv6PayloadHeader->src_addr[12]; - - if (addressSource != ipv4ExtHeader->dst_addr) - { - return false; - } - - uint32_t addressDestination = *(uint32_t*)&ipv6PayloadHeader->dst_addr[12]; - addressDestination = translation.ipv4Address.address; - - uint16_t checksum6 = yanet_checksum(&ipv6PayloadHeader->src_addr[0], 32); - uint16_t payloadLength = rte_be_to_cpu_16(ipv6PayloadHeader->payload_len); - - unsigned int ipv6PayloadHeaderSize = sizeof(rte_ipv6_hdr); - - uint16_t packet_id = 0x3421; ///< @todo: nat64statelessPacketId; - uint16_t fragment_offset = 0; ///< @todo: rte_cpu_to_be_16(RTE_IPV4_HDR_DF_FLAG); - uint8_t nextPayloadHeader = ipv6PayloadHeader->proto; - - if (nextPayloadHeader == IPPROTO_FRAGMENT) - { - if (payloadExtLen < sizeof(icmp_header_t*) + sizeof(rte_ipv6_hdr) + sizeof(tIPv6ExtensionFragment*)) - { - return false; - } - tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + ipv6PayloadHeaderSize); - packet_id = static_cast(extension->identification >> 16); - fragment_offset = rte_cpu_to_be_16(rte_be_to_cpu_16(extension->offsetFlagM) >> 3); - fragment_offset |= (extension->offsetFlagM & 0x0100) >> 3; - - nextPayloadHeader = extension->nextHeader; - - ipv6PayloadHeaderSize += 8; - } - - if (nextPayloadHeader == IPPROTO_HOPOPTS || - nextPayloadHeader == IPPROTO_ROUTING || - nextPayloadHeader == IPPROTO_FRAGMENT || - nextPayloadHeader == IPPROTO_NONE || - nextPayloadHeader == IPPROTO_DSTOPTS || - nextPayloadHeader == IPPROTO_MH) - { - /// @todo: ipv6 extensions - - return false; - } - - if (nextPayloadHeader == IPPROTO_ICMPV6) - { - nextPayloadHeader = IPPROTO_ICMP; - } - - rte_ipv4_hdr* ipv4PayloadHeader = (rte_ipv4_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr)); - - ipv4PayloadHeader->version_ihl = 0x45; - ipv4PayloadHeader->type_of_service = (rte_be_to_cpu_32(ipv6PayloadHeader->vtc_flow) >> 20) & 0xFF; - ipv4PayloadHeader->total_length = rte_cpu_to_be_16(payloadLength + 20 - (ipv6PayloadHeaderSize - 40)); - ipv4PayloadHeader->packet_id = packet_id; - ipv4PayloadHeader->fragment_offset = fragment_offset; - ipv4PayloadHeader->time_to_live = ipv6PayloadHeader->hop_limits; - ipv4PayloadHeader->next_proto_id = nextPayloadHeader; - ipv4PayloadHeader->src_addr = addressSource; - ipv4PayloadHeader->dst_addr = addressDestination; - - yanet_ipv4_checksum(ipv4PayloadHeader); - - uint16_t checksum4 = yanet_checksum(&ipv4PayloadHeader->src_addr, 8); - - { - unsigned int delta = ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr); - - memcpy(rte_pktmbuf_mtod_offset(mbuf, char*, delta), - rte_pktmbuf_mtod(mbuf, char*), - metadata->network_headerOffset + sizeof(rte_ipv4_hdr) + sizeof(icmp_header_t)); - - rte_pktmbuf_adj(mbuf, delta); - - icmpHeader = (icmp_header_t*)((char*)icmpHeader + delta); - ipv4ExtHeader = (rte_ipv4_hdr*)((char*)ipv4ExtHeader + delta); - - uint16_t csum = ~ipv4ExtHeader->hdr_checksum; - csum = csum_minus(csum, ipv4ExtHeader->total_length); - ipv4ExtHeader->total_length = rte_cpu_to_be_16(rte_be_to_cpu_16(ipv4ExtHeader->total_length) - delta); - csum = csum_plus(csum, ipv4ExtHeader->total_length); - ipv4ExtHeader->hdr_checksum = (csum == 0xffff) ? csum : ~csum; - } - - if ((fragment_offset & 0xFF1F) == 0) - { - if (nextPayloadHeader == IPPROTO_TCP) - { - /// @todo: check packet size - - rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); - yanet_tcp_checksum_v6_to_v4(tcpPayloadHeader, checksum6, checksum4); - } - else if (nextPayloadHeader == IPPROTO_UDP) - { - /// @todo: check packet size - - rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); - yanet_udp_checksum_v6_to_v4(udpPayloadHeader, checksum6, checksum4); - } - else if (nextPayloadHeader == IPPROTO_ICMP) - { - /// @todo: check packet size - - icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); - - if ((fragment_offset & 0xFF3F) != 0 || - !yanet_icmp_translate_v6_to_v4(icmpPayloadHeader, - payloadLength, - checksum6)) - { - return false; - } - } - else - { - return false; - } - } - - icmpHeader->checksum = 0; - uint32_t sum = __rte_raw_cksum(icmpHeader, sizeof(icmp_header_t) + sizeof(rte_ipv4_hdr) + payloadLength, 0); - icmpHeader->checksum = ~__rte_raw_cksum_reduce(sum); - - return true; -} - void cControlPlane::handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -1969,7 +1713,7 @@ void cControlPlane::handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf) slowWorker->slowWorkerTranslation(mbuf, nat64stateless, translation, true); - if (do_icmp_translate_v6_to_v4(mbuf, translation)) + if (dataplane::do_icmp_translate_v6_to_v4(mbuf, translation)) { slowWorker->stats.nat64stateless_ingressPackets++; sendPacketToSlowWorker(mbuf, nat64stateless.flow); @@ -1981,259 +1725,6 @@ void cControlPlane::handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf) } } -static bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, - const dataplane::globalBase::nat64stateless_translation_t& translation) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - rte_ipv6_hdr* ipv6ExtHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); - - if (ipv6ExtHeader->proto != IPPROTO_ICMPV6) - { - return false; - } - - unsigned int ipv6ExtHeaderSize = sizeof(rte_ipv6_hdr); - - unsigned int payloadLen = rte_be_to_cpu_16(ipv6ExtHeader->payload_len); - - if (payloadLen < sizeof(icmp_header_t) + sizeof(rte_ipv4_hdr)) - { - return false; - } - - icmp_header_t* icmpHeader = rte_pktmbuf_mtod_offset(mbuf, icmp_header_t*, metadata->network_headerOffset + ipv6ExtHeaderSize); - uint8_t type = icmpHeader->type; - uint8_t code = icmpHeader->code; - - if (type == ICMP_DEST_UNREACH) - { - type = ICMP6_DST_UNREACH; - - if (code == ICMP_NET_UNREACH || code == ICMP_HOST_UNREACH || - code == ICMP_SR_FAILED || code == ICMP_NET_UNKNOWN || - code == ICMP_HOST_UNKNOWN || code == ICMP_HOST_ISOLATED || - code == ICMP_NET_UNR_TOS || code == ICMP_HOST_UNR_TOS) - { - code = ICMP6_DST_UNREACH_NOROUTE; - } - else if (code == ICMP_PORT_UNREACH) - { - code = ICMP6_DST_UNREACH_NOPORT; - } - else if (code == ICMP_NET_ANO || code == ICMP_HOST_ANO || - code == ICMP_PKT_FILTERED || code == ICMP_PREC_CUTOFF) - { - code = ICMP6_DST_UNREACH_ADMIN; - } - else if (code == ICMP_PROT_UNREACH) - { - type = ICMP6_PARAM_PROB; - code = ICMP6_PARAMPROB_NEXTHEADER; - - icmpHeader->data32[0] = rte_cpu_to_be_32(6); - } - else if (code == ICMP_FRAG_NEEDED) - { - type = ICMP6_PACKET_TOO_BIG; - code = 0; - - uint32_t mtu = rte_be_to_cpu_16(icmpHeader->data16[1]) + 20; - if (mtu < 1280) - { - mtu = 1280; - } - - icmpHeader->data32[0] = rte_cpu_to_be_32(mtu); - } - else - { - return false; - } - } - else if (type == ICMP_TIME_EXCEEDED) - { - type = ICMP6_TIME_EXCEEDED; - } - else if (type == ICMP_PARAMETERPROB) - { - if (code != 0 && code != 2) - { - return false; - } - - uint8_t ptr = icmpHeader->data8[0]; - - if (ptr == 0 || ptr == 1) - { - /// unchanged - } - else if (ptr == 2 || ptr == 3) - { - ptr = 4; - } - else if (ptr == 8) - { - ptr = 7; - } - else if (ptr == 9) - { - ptr = 6; - } - else if (ptr >= 12 && ptr < 16) - { - ptr = 8; - } - else if (ptr >= 16 && ptr < 20) - { - ptr = 24; - } - else - { - return false; - } - - type = ICMP6_PARAM_PROB; - code = ICMP6_PARAMPROB_HEADER; - - icmpHeader->data32[0] = rte_cpu_to_be_32(ptr); - } - else - { - return false; - } - - icmpHeader->type = type; - icmpHeader->code = code; - - rte_ipv4_hdr* ipv4PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); - - /// @todo: check ipv4 payload header length - - if (ipv4PayloadHeader->src_addr != translation.ipv4Address.address) - { - return false; - } - - unsigned int ipv6PayloadHeaderSize = sizeof(rte_ipv6_hdr); - - if ((ipv4PayloadHeader->fragment_offset & 0xFF3F) != 0) - { - ipv6PayloadHeaderSize += 8; - } - - { - unsigned int delta = ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr); - - rte_pktmbuf_prepend(mbuf, delta); - - memcpy(rte_pktmbuf_mtod(mbuf, char*), - rte_pktmbuf_mtod_offset(mbuf, char*, delta), - metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); - - icmpHeader = (icmp_header_t*)((char*)icmpHeader - delta); - ipv6ExtHeader = (rte_ipv6_hdr*)((char*)ipv6ExtHeader - delta); - payloadLen += delta; - ipv6ExtHeader->payload_len = rte_cpu_to_be_16(payloadLen); - } - - rte_ipv6_hdr* ipv6PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); - - uint32_t addressDestination = ipv4PayloadHeader->dst_addr; - uint16_t checksum4 = yanet_checksum(&ipv4PayloadHeader->src_addr, 8); - - uint16_t fragment_offset = ipv4PayloadHeader->fragment_offset; - uint8_t nextPayloadHeader = ipv4PayloadHeader->next_proto_id; - - if (nextPayloadHeader == IPPROTO_ICMP) - { - nextPayloadHeader = IPPROTO_ICMPV6; - } - - if ((fragment_offset & 0xFF3F) != 0) - { - tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + sizeof(rte_ipv6_hdr)); - extension->nextHeader = nextPayloadHeader; - extension->reserved = 0; - extension->offsetFlagM = rte_cpu_to_be_16(rte_be_to_cpu_16(fragment_offset) << 3); - extension->offsetFlagM |= (fragment_offset & 0x0020) << 3; - - /// @todo: it is not original identification. - extension->identification = ipv4PayloadHeader->packet_id; - - ipv6PayloadHeader->proto = IPPROTO_FRAGMENT; - } - else - { - ipv6PayloadHeader->proto = nextPayloadHeader; - } - - ipv6PayloadHeader->vtc_flow = rte_cpu_to_be_32((0x6 << 28) | (ipv4PayloadHeader->type_of_service << 20)); - ipv6PayloadHeader->payload_len = rte_cpu_to_be_16(rte_be_to_cpu_16(ipv4PayloadHeader->total_length) - 20 + (ipv6PayloadHeaderSize - 40)); - ipv6PayloadHeader->hop_limits = ipv4PayloadHeader->time_to_live; - ; - - memcpy(ipv6PayloadHeader->src_addr, translation.ipv6Address.bytes, 16); - - if (memcmp(ipv6PayloadHeader->src_addr, ipv6ExtHeader->dst_addr, 16)) - { - return false; - } - - memcpy(&ipv6PayloadHeader->dst_addr[0], translation.ipv6DestinationAddress.bytes, 12); - memcpy(&ipv6PayloadHeader->dst_addr[12], &addressDestination, 4); - - uint16_t checksum6 = yanet_checksum(&ipv6PayloadHeader->src_addr[0], 32); - - if ((fragment_offset & 0xFF1F) == 0) - { - if (nextPayloadHeader == IPPROTO_TCP) - { - /// @todo: check packet size - - rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); - yanet_tcp_checksum_v4_to_v6(tcpPayloadHeader, checksum4, checksum6); - } - else if (nextPayloadHeader == IPPROTO_UDP) - { - /// @todo: check packet size - - rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); - yanet_udp_checksum_v4_to_v6(udpPayloadHeader, checksum4, checksum6); - } - else if (nextPayloadHeader == IPPROTO_ICMPV6) - { - /// @todo: check packet size - - icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); - - if ((fragment_offset & 0xFF3F) != 0 || - !yanet_icmp_translate_v4_to_v6(icmpPayloadHeader, - rte_be_to_cpu_16(ipv6PayloadHeader->payload_len), - checksum6)) - { - return false; - } - } - else - { - return false; - } - } - - icmpHeader->checksum = 0; - uint32_t sum = __rte_raw_cksum(ipv6ExtHeader->src_addr, 16, 0); - sum = __rte_raw_cksum(ipv6ExtHeader->dst_addr, 16, sum); - - uint32_t tmp = ((uint32_t)rte_cpu_to_be_16(IPPROTO_ICMPV6) << 16) + rte_cpu_to_be_16(payloadLen); - sum = __rte_raw_cksum(&tmp, 4, sum); - sum = __rte_raw_cksum(icmpHeader, payloadLen, sum); - - icmpHeader->checksum = ~__rte_raw_cksum_reduce(sum); - - return true; -} - void cControlPlane::handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -2244,7 +1735,7 @@ void cControlPlane::handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf) slowWorker->slowWorkerTranslation(mbuf, nat64stateless, translation, false); - if (do_icmp_translate_v4_to_v6(mbuf, translation)) + if (dataplane::do_icmp_translate_v4_to_v6(mbuf, translation)) { slowWorker->stats.nat64stateless_egressPackets++; sendPacketToSlowWorker(mbuf, nat64stateless.flow); diff --git a/dataplane/icmp_translations.cpp b/dataplane/icmp_translations.cpp new file mode 100644 index 00000000..25fe1ec1 --- /dev/null +++ b/dataplane/icmp_translations.cpp @@ -0,0 +1,516 @@ +#include "icmp_translations.h" + +namespace dataplane +{ + +bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, + const dataplane::globalBase::nat64stateless_translation_t& translation) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + rte_ipv4_hdr* ipv4ExtHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); + + if (ipv4ExtHeader->next_proto_id != IPPROTO_ICMP) + { + return false; + } + + unsigned int payloadExtLen = rte_be_to_cpu_16(ipv4ExtHeader->total_length) - sizeof(rte_ipv4_hdr); + + if (payloadExtLen < sizeof(icmp_header_t*) + sizeof(rte_ipv6_hdr)) + { + return false; + } + + icmp_header_t* icmpHeader = rte_pktmbuf_mtod_offset(mbuf, icmp_header_t*, metadata->network_headerOffset + sizeof(rte_ipv4_hdr)); + uint8_t type = icmpHeader->type; + uint8_t code = icmpHeader->code; + + if (type == ICMP6_DST_UNREACH) + { + type = ICMP_DEST_UNREACH; + + if (code == ICMP6_DST_UNREACH_NOROUTE || code == ICMP6_DST_UNREACH_BEYONDSCOPE || + code == ICMP6_DST_UNREACH_ADDR) + { + code = ICMP_HOST_UNREACH; + } + else if (code == ICMP6_DST_UNREACH_ADMIN) + { + code = ICMP_HOST_ANO; + } + else if (code == ICMP6_DST_UNREACH_NOPORT) + { + code = ICMP_PORT_UNREACH; + } + else + { + return false; + } + } + else if (type == ICMP6_PACKET_TOO_BIG) + { + type = ICMP_DEST_UNREACH; + code = ICMP_FRAG_NEEDED; + + uint32_t mtu = rte_be_to_cpu_32(icmpHeader->data32[0]) - 20; + icmpHeader->data32[0] = 0; + icmpHeader->data16[1] = rte_cpu_to_be_16(mtu); + } + else if (type == ICMP6_TIME_EXCEEDED) + { + type = ICMP_TIME_EXCEEDED; + } + else if (type == ICMP6_PARAM_PROB) + { + + if (code == ICMP6_PARAMPROB_HEADER) + { + type = ICMP_PARAMETERPROB; + code = 0; + uint32_t ptr = rte_be_to_cpu_32(icmpHeader->data32[0]); + icmpHeader->data32[0] = 0; + + if (ptr == 0 || ptr == 1) + { + /// unchanged + } + else if (ptr == 4 || ptr == 5) + { + ptr = 2; + } + else if (ptr == 6) + { + ptr = 9; + } + else if (ptr == 7) + { + ptr = 8; + } + else if (ptr >= 8 && ptr < 24) + { + ptr = 12; + } + else if (ptr >= 24 && ptr < 40) + { + ptr = 16; + } + else + { + return false; + } + + icmpHeader->data8[0] = ptr; + } + else if (code == ICMP6_PARAMPROB_NEXTHEADER) + { + type = ICMP_DEST_UNREACH; + code = ICMP_PROT_UNREACH; + icmpHeader->data32[0] = 0; + } + } + else + { + return false; + } + + icmpHeader->type = type; + icmpHeader->code = code; + + rte_ipv6_hdr* ipv6PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset + sizeof(rte_ipv4_hdr) + sizeof(icmp_header_t)); + + /// @todo: think about it. + if (memcmp(ipv6PayloadHeader->dst_addr, translation.ipv6Address.bytes, 16)) + { + return false; + } + + if (memcmp(ipv6PayloadHeader->src_addr, translation.ipv6DestinationAddress.bytes, 12)) + { + return false; + } + + uint32_t addressSource = *(uint32_t*)&ipv6PayloadHeader->src_addr[12]; + + if (addressSource != ipv4ExtHeader->dst_addr) + { + return false; + } + + uint32_t addressDestination = *(uint32_t*)&ipv6PayloadHeader->dst_addr[12]; + addressDestination = translation.ipv4Address.address; + + uint16_t checksum6 = yanet_checksum(&ipv6PayloadHeader->src_addr[0], 32); + uint16_t payloadLength = rte_be_to_cpu_16(ipv6PayloadHeader->payload_len); + + unsigned int ipv6PayloadHeaderSize = sizeof(rte_ipv6_hdr); + + uint16_t packet_id = 0x3421; ///< @todo: nat64statelessPacketId; + uint16_t fragment_offset = 0; ///< @todo: rte_cpu_to_be_16(RTE_IPV4_HDR_DF_FLAG); + uint8_t nextPayloadHeader = ipv6PayloadHeader->proto; + + if (nextPayloadHeader == IPPROTO_FRAGMENT) + { + if (payloadExtLen < sizeof(icmp_header_t*) + sizeof(rte_ipv6_hdr) + sizeof(tIPv6ExtensionFragment*)) + { + return false; + } + tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + ipv6PayloadHeaderSize); + packet_id = static_cast(extension->identification >> 16); + fragment_offset = rte_cpu_to_be_16(rte_be_to_cpu_16(extension->offsetFlagM) >> 3); + fragment_offset |= (extension->offsetFlagM & 0x0100) >> 3; + + nextPayloadHeader = extension->nextHeader; + + ipv6PayloadHeaderSize += 8; + } + + if (nextPayloadHeader == IPPROTO_HOPOPTS || + nextPayloadHeader == IPPROTO_ROUTING || + nextPayloadHeader == IPPROTO_FRAGMENT || + nextPayloadHeader == IPPROTO_NONE || + nextPayloadHeader == IPPROTO_DSTOPTS || + nextPayloadHeader == IPPROTO_MH) + { + /// @todo: ipv6 extensions + + return false; + } + + if (nextPayloadHeader == IPPROTO_ICMPV6) + { + nextPayloadHeader = IPPROTO_ICMP; + } + + rte_ipv4_hdr* ipv4PayloadHeader = (rte_ipv4_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr)); + + ipv4PayloadHeader->version_ihl = 0x45; + ipv4PayloadHeader->type_of_service = (rte_be_to_cpu_32(ipv6PayloadHeader->vtc_flow) >> 20) & 0xFF; + ipv4PayloadHeader->total_length = rte_cpu_to_be_16(payloadLength + 20 - (ipv6PayloadHeaderSize - 40)); + ipv4PayloadHeader->packet_id = packet_id; + ipv4PayloadHeader->fragment_offset = fragment_offset; + ipv4PayloadHeader->time_to_live = ipv6PayloadHeader->hop_limits; + ipv4PayloadHeader->next_proto_id = nextPayloadHeader; + ipv4PayloadHeader->src_addr = addressSource; + ipv4PayloadHeader->dst_addr = addressDestination; + + yanet_ipv4_checksum(ipv4PayloadHeader); + + uint16_t checksum4 = yanet_checksum(&ipv4PayloadHeader->src_addr, 8); + + { + unsigned int delta = ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr); + + memcpy(rte_pktmbuf_mtod_offset(mbuf, char*, delta), + rte_pktmbuf_mtod(mbuf, char*), + metadata->network_headerOffset + sizeof(rte_ipv4_hdr) + sizeof(icmp_header_t)); + + rte_pktmbuf_adj(mbuf, delta); + + icmpHeader = (icmp_header_t*)((char*)icmpHeader + delta); + ipv4ExtHeader = (rte_ipv4_hdr*)((char*)ipv4ExtHeader + delta); + + uint16_t csum = ~ipv4ExtHeader->hdr_checksum; + csum = csum_minus(csum, ipv4ExtHeader->total_length); + ipv4ExtHeader->total_length = rte_cpu_to_be_16(rte_be_to_cpu_16(ipv4ExtHeader->total_length) - delta); + csum = csum_plus(csum, ipv4ExtHeader->total_length); + ipv4ExtHeader->hdr_checksum = (csum == 0xffff) ? csum : ~csum; + } + + if ((fragment_offset & 0xFF1F) == 0) + { + if (nextPayloadHeader == IPPROTO_TCP) + { + /// @todo: check packet size + + rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + yanet_tcp_checksum_v6_to_v4(tcpPayloadHeader, checksum6, checksum4); + } + else if (nextPayloadHeader == IPPROTO_UDP) + { + /// @todo: check packet size + + rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + yanet_udp_checksum_v6_to_v4(udpPayloadHeader, checksum6, checksum4); + } + else if (nextPayloadHeader == IPPROTO_ICMP) + { + /// @todo: check packet size + + icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + + if ((fragment_offset & 0xFF3F) != 0 || + !yanet_icmp_translate_v6_to_v4(icmpPayloadHeader, + payloadLength, + checksum6)) + { + return false; + } + } + else + { + return false; + } + } + + icmpHeader->checksum = 0; + uint32_t sum = __rte_raw_cksum(icmpHeader, sizeof(icmp_header_t) + sizeof(rte_ipv4_hdr) + payloadLength, 0); + icmpHeader->checksum = ~__rte_raw_cksum_reduce(sum); + + return true; +} + +bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, + const dataplane::globalBase::nat64stateless_translation_t& translation) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + rte_ipv6_hdr* ipv6ExtHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); + + if (ipv6ExtHeader->proto != IPPROTO_ICMPV6) + { + return false; + } + + unsigned int ipv6ExtHeaderSize = sizeof(rte_ipv6_hdr); + + unsigned int payloadLen = rte_be_to_cpu_16(ipv6ExtHeader->payload_len); + + if (payloadLen < sizeof(icmp_header_t) + sizeof(rte_ipv4_hdr)) + { + return false; + } + + icmp_header_t* icmpHeader = rte_pktmbuf_mtod_offset(mbuf, icmp_header_t*, metadata->network_headerOffset + ipv6ExtHeaderSize); + uint8_t type = icmpHeader->type; + uint8_t code = icmpHeader->code; + + if (type == ICMP_DEST_UNREACH) + { + type = ICMP6_DST_UNREACH; + + if (code == ICMP_NET_UNREACH || code == ICMP_HOST_UNREACH || + code == ICMP_SR_FAILED || code == ICMP_NET_UNKNOWN || + code == ICMP_HOST_UNKNOWN || code == ICMP_HOST_ISOLATED || + code == ICMP_NET_UNR_TOS || code == ICMP_HOST_UNR_TOS) + { + code = ICMP6_DST_UNREACH_NOROUTE; + } + else if (code == ICMP_PORT_UNREACH) + { + code = ICMP6_DST_UNREACH_NOPORT; + } + else if (code == ICMP_NET_ANO || code == ICMP_HOST_ANO || + code == ICMP_PKT_FILTERED || code == ICMP_PREC_CUTOFF) + { + code = ICMP6_DST_UNREACH_ADMIN; + } + else if (code == ICMP_PROT_UNREACH) + { + type = ICMP6_PARAM_PROB; + code = ICMP6_PARAMPROB_NEXTHEADER; + + icmpHeader->data32[0] = rte_cpu_to_be_32(6); + } + else if (code == ICMP_FRAG_NEEDED) + { + type = ICMP6_PACKET_TOO_BIG; + code = 0; + + uint32_t mtu = rte_be_to_cpu_16(icmpHeader->data16[1]) + 20; + if (mtu < 1280) + { + mtu = 1280; + } + + icmpHeader->data32[0] = rte_cpu_to_be_32(mtu); + } + else + { + return false; + } + } + else if (type == ICMP_TIME_EXCEEDED) + { + type = ICMP6_TIME_EXCEEDED; + } + else if (type == ICMP_PARAMETERPROB) + { + if (code != 0 && code != 2) + { + return false; + } + + uint8_t ptr = icmpHeader->data8[0]; + + if (ptr == 0 || ptr == 1) + { + /// unchanged + } + else if (ptr == 2 || ptr == 3) + { + ptr = 4; + } + else if (ptr == 8) + { + ptr = 7; + } + else if (ptr == 9) + { + ptr = 6; + } + else if (ptr >= 12 && ptr < 16) + { + ptr = 8; + } + else if (ptr >= 16 && ptr < 20) + { + ptr = 24; + } + else + { + return false; + } + + type = ICMP6_PARAM_PROB; + code = ICMP6_PARAMPROB_HEADER; + + icmpHeader->data32[0] = rte_cpu_to_be_32(ptr); + } + else + { + return false; + } + + icmpHeader->type = type; + icmpHeader->code = code; + + rte_ipv4_hdr* ipv4PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); + + /// @todo: check ipv4 payload header length + + if (ipv4PayloadHeader->src_addr != translation.ipv4Address.address) + { + return false; + } + + unsigned int ipv6PayloadHeaderSize = sizeof(rte_ipv6_hdr); + + if ((ipv4PayloadHeader->fragment_offset & 0xFF3F) != 0) + { + ipv6PayloadHeaderSize += 8; + } + + { + unsigned int delta = ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr); + + rte_pktmbuf_prepend(mbuf, delta); + + memcpy(rte_pktmbuf_mtod(mbuf, char*), + rte_pktmbuf_mtod_offset(mbuf, char*, delta), + metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); + + icmpHeader = (icmp_header_t*)((char*)icmpHeader - delta); + ipv6ExtHeader = (rte_ipv6_hdr*)((char*)ipv6ExtHeader - delta); + payloadLen += delta; + ipv6ExtHeader->payload_len = rte_cpu_to_be_16(payloadLen); + } + + rte_ipv6_hdr* ipv6PayloadHeader = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset + ipv6ExtHeaderSize + sizeof(icmp_header_t)); + + uint32_t addressDestination = ipv4PayloadHeader->dst_addr; + uint16_t checksum4 = yanet_checksum(&ipv4PayloadHeader->src_addr, 8); + + uint16_t fragment_offset = ipv4PayloadHeader->fragment_offset; + uint8_t nextPayloadHeader = ipv4PayloadHeader->next_proto_id; + + if (nextPayloadHeader == IPPROTO_ICMP) + { + nextPayloadHeader = IPPROTO_ICMPV6; + } + + if ((fragment_offset & 0xFF3F) != 0) + { + tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + sizeof(rte_ipv6_hdr)); + extension->nextHeader = nextPayloadHeader; + extension->reserved = 0; + extension->offsetFlagM = rte_cpu_to_be_16(rte_be_to_cpu_16(fragment_offset) << 3); + extension->offsetFlagM |= (fragment_offset & 0x0020) << 3; + + /// @todo: it is not original identification. + extension->identification = ipv4PayloadHeader->packet_id; + + ipv6PayloadHeader->proto = IPPROTO_FRAGMENT; + } + else + { + ipv6PayloadHeader->proto = nextPayloadHeader; + } + + ipv6PayloadHeader->vtc_flow = rte_cpu_to_be_32((0x6 << 28) | (ipv4PayloadHeader->type_of_service << 20)); + ipv6PayloadHeader->payload_len = rte_cpu_to_be_16(rte_be_to_cpu_16(ipv4PayloadHeader->total_length) - 20 + (ipv6PayloadHeaderSize - 40)); + ipv6PayloadHeader->hop_limits = ipv4PayloadHeader->time_to_live; + ; + + memcpy(ipv6PayloadHeader->src_addr, translation.ipv6Address.bytes, 16); + + if (memcmp(ipv6PayloadHeader->src_addr, ipv6ExtHeader->dst_addr, 16)) + { + return false; + } + + memcpy(&ipv6PayloadHeader->dst_addr[0], translation.ipv6DestinationAddress.bytes, 12); + memcpy(&ipv6PayloadHeader->dst_addr[12], &addressDestination, 4); + + uint16_t checksum6 = yanet_checksum(&ipv6PayloadHeader->src_addr[0], 32); + + if ((fragment_offset & 0xFF1F) == 0) + { + if (nextPayloadHeader == IPPROTO_TCP) + { + /// @todo: check packet size + + rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + yanet_tcp_checksum_v4_to_v6(tcpPayloadHeader, checksum4, checksum6); + } + else if (nextPayloadHeader == IPPROTO_UDP) + { + /// @todo: check packet size + + rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + yanet_udp_checksum_v4_to_v6(udpPayloadHeader, checksum4, checksum6); + } + else if (nextPayloadHeader == IPPROTO_ICMPV6) + { + /// @todo: check packet size + + icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + + if ((fragment_offset & 0xFF3F) != 0 || + !yanet_icmp_translate_v4_to_v6(icmpPayloadHeader, + rte_be_to_cpu_16(ipv6PayloadHeader->payload_len), + checksum6)) + { + return false; + } + } + else + { + return false; + } + } + + icmpHeader->checksum = 0; + uint32_t sum = __rte_raw_cksum(ipv6ExtHeader->src_addr, 16, 0); + sum = __rte_raw_cksum(ipv6ExtHeader->dst_addr, 16, sum); + + uint32_t tmp = ((uint32_t)rte_cpu_to_be_16(IPPROTO_ICMPV6) << 16) + rte_cpu_to_be_16(payloadLen); + sum = __rte_raw_cksum(&tmp, 4, sum); + sum = __rte_raw_cksum(icmpHeader, payloadLen, sum); + + icmpHeader->checksum = ~__rte_raw_cksum_reduce(sum); + + return true; +} + +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/icmp_translations.h b/dataplane/icmp_translations.h new file mode 100644 index 00000000..333701c5 --- /dev/null +++ b/dataplane/icmp_translations.h @@ -0,0 +1,13 @@ +#include + +#include "globalbase.h" +#include "icmp.h" + +namespace dataplane +{ +bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, + const dataplane::globalBase::nat64stateless_translation_t& translation); +bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, + const dataplane::globalBase::nat64stateless_translation_t& translation); + +} // namespace dataplane \ No newline at end of file diff --git a/dataplane/meson.build b/dataplane/meson.build index eeb4fb99..0bfe16c0 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -10,6 +10,7 @@ sources = files('bus.cpp', 'debug_latch.cpp', 'dregress.cpp', 'fragmentation.cpp', + 'icmp_translations.cpp', 'kernel_interface_handle.cpp', 'kernel_interface_handler.cpp', 'globalbase.cpp', From f7fad570cc871ce26c25acd85c9d40573091526e Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 21 May 2024 19:58:49 +0300 Subject: [PATCH 046/195] Fixes rte_eth_dev_get_port_by_name for sock_dev sock_dev was previously registered with its path as name in dpdk. This prevented figuring out dpdk port_id from interface name. Given that path is generally not required to contain interface name i added name as argument to sock_dev_create --- dataplane/dataplane.cpp | 2 +- dataplane/sock_dev.cpp | 11 ++++++----- dataplane/sock_dev.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 319c20d2..0aaaddc9 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -450,7 +450,7 @@ eResult cDataPlane::initPorts() tPortId portId; if (strncmp(name.data(), SOCK_DEV_PREFIX, strlen(SOCK_DEV_PREFIX)) == 0) { - portId = sock_dev_create(name.data(), 0); + portId = sock_dev_create(name.data() + strlen(SOCK_DEV_PREFIX), interfaceName.c_str(), 0); } else if (rte_eth_dev_get_port_by_name(name.data(), &portId)) { diff --git a/dataplane/sock_dev.cpp b/dataplane/sock_dev.cpp index 810d247c..e2cba99d 100644 --- a/dataplane/sock_dev.cpp +++ b/dataplane/sock_dev.cpp @@ -103,7 +103,10 @@ sock_dev_close(struct rte_eth_dev* dev) close(internals->fd); unlink(internals->sockaddr.sun_path); - rte_free(internals); + if (internals) + { + rte_free(internals); + } return 0; } #else @@ -408,10 +411,8 @@ int sock_dev_stats_get(struct rte_eth_dev* dev, return 0; } -int sock_dev_create(const char* name, uint8_t numa_node) +int sock_dev_create(const char* path, const char* name, uint8_t numa_node) { - const char* path = name + strlen(SOCK_DEV_PREFIX); - struct sock_internals* internals = (struct sock_internals*) rte_zmalloc_socket(path, sizeof(struct sock_internals), 0, numa_node); if (internals == NULL) @@ -452,7 +453,7 @@ int sock_dev_create(const char* name, uint8_t numa_node) internals->conFd = -1; struct rte_eth_dev* eth_dev = NULL; - eth_dev = rte_eth_dev_allocate(path); + eth_dev = rte_eth_dev_allocate(name); if (eth_dev == NULL) { close(internals->fd); diff --git a/dataplane/sock_dev.h b/dataplane/sock_dev.h index 47553147..5513c4cd 100644 --- a/dataplane/sock_dev.h +++ b/dataplane/sock_dev.h @@ -4,4 +4,4 @@ #define SOCK_DEV_PREFIX "sock_dev:" -int sock_dev_create(const char* path, uint8_t numa_node); +int sock_dev_create(const char* path, const char* name, uint8_t numa_node); From 6a00a67ff5339fa0e9761a69c7bf9963ccc5c3a2 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 12 Aug 2024 16:50:11 +0300 Subject: [PATCH 047/195] Switches sockdev checking from using raw strings --- dataplane/dataplane.cpp | 14 +++++++++++--- dataplane/sock_dev.h | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 0aaaddc9..50428e51 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -41,6 +41,11 @@ common::log::LogPriority common::log::logPriority = common::log::TLOG_INFO; +bool StartsWith(const std::string& str, const std::string& prefix) +{ + return str.compare(0, prefix.length(), prefix) == 0; +} + cDataPlane::cDataPlane() : currentGlobalBaseId(0), globalBaseSerial(0), @@ -448,9 +453,12 @@ eResult cDataPlane::initPorts() (void)pci; tPortId portId; - if (strncmp(name.data(), SOCK_DEV_PREFIX, strlen(SOCK_DEV_PREFIX)) == 0) + + if (StartsWith(name, SOCK_DEV_PREFIX)) { - portId = sock_dev_create(name.data() + strlen(SOCK_DEV_PREFIX), interfaceName.c_str(), 0); + std::string name_part = name.substr(SOCK_DEV_PREFIX.length()); + YANET_LOG_INFO("Opening sockdev with path %s\n", name_part.data()); + portId = sock_dev_create(name_part.c_str(), interfaceName.c_str(), 0); } else if (rte_eth_dev_get_port_by_name(name.data(), &portId)) { @@ -2014,7 +2022,7 @@ eResult cDataPlane::initEal(const std::string& binaryPath, (void)rss_flags; // Do not whitelist sock dev virtual devices - if (strncmp(pci.data(), SOCK_DEV_PREFIX, strlen(SOCK_DEV_PREFIX)) == 0) + if (StartsWith(name, SOCK_DEV_PREFIX)) { continue; } diff --git a/dataplane/sock_dev.h b/dataplane/sock_dev.h index 5513c4cd..020759cc 100644 --- a/dataplane/sock_dev.h +++ b/dataplane/sock_dev.h @@ -1,7 +1,10 @@ #pragma once #include +#include -#define SOCK_DEV_PREFIX "sock_dev:" +//#define SOCK_DEV_PREFIX "sock_dev:" +using namespace std::string_literals; +const std::string SOCK_DEV_PREFIX = "sock_dev:"s; int sock_dev_create(const char* path, const char* name, uint8_t numa_node); From b214c1d9588e14338c574deea745c7b0a889829a Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 24 Jun 2024 18:30:51 +0300 Subject: [PATCH 048/195] Fixes perfect forwarding of args in memory manager --- dataplane/memory_manager.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dataplane/memory_manager.h b/dataplane/memory_manager.h index 14b51a58..ccbd1c39 100644 --- a/dataplane/memory_manager.h +++ b/dataplane/memory_manager.h @@ -82,11 +82,11 @@ class memory_manager } template + typename... Args> type* create(const char* name, const tSocketId socket_id, const uint64_t size, - const args_t&... args) + Args&&... args) { void* pointer = alloc(name, socket_id, size, [](void* pointer) { reinterpret_cast(pointer)->~type(); @@ -97,14 +97,14 @@ class memory_manager return nullptr; } - return new (reinterpret_cast(pointer)) type(args...); + return new (reinterpret_cast(pointer)) type(std::forward(args)...); } template + typename... Args> type* create_static(const char* name, const tSocketId socket_id, - const args_t&... args) + Args&&... args) { void* pointer = alloc(name, socket_id, sizeof(type), [](void* pointer) { reinterpret_cast(pointer)->~type(); @@ -115,15 +115,15 @@ class memory_manager return nullptr; } - return new (reinterpret_cast(pointer)) type(args...); + return new (reinterpret_cast(pointer)) type(std::forward(args)...); } template + typename... Args> type* create_static_array(const char* name, const uint64_t count, const tSocketId socket_id, - const args_t&... args) + Args&&... args) { void* pointer = alloc(name, socket_id, count * sizeof(type), [count](void* pointer) { for (uint64_t i = 0; @@ -144,7 +144,7 @@ class memory_manager i < count; i++) { - new ((reinterpret_cast(pointer)) + i) type(args...); + new ((reinterpret_cast(pointer)) + i) type(std::forward(args)...); } return reinterpret_cast(pointer); From 718e5f303bcb299fbfa152ea8deb32602bd81f29 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 23 Apr 2024 18:16:35 +0300 Subject: [PATCH 049/195] Switches to using bitset to edit EAL cores mask --- dataplane/dataplane.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 50428e51..3c6b18cb 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -1986,18 +1988,18 @@ eResult cDataPlane::initEal(const std::string& binaryPath, insert_eal_arg("-c"); - uint64_t coresMask = 0; - coresMask |= (((uint64_t)1) << (uint64_t)config.controlPlaneCoreId); + std::bitset::digits> cores_mask; + cores_mask[config.controlPlaneCoreId] = true; for (const auto& coreId : config.workerGCs) { - coresMask |= (((uint64_t)1) << (uint64_t)coreId); + cores_mask[coreId] = true; } for (const auto& iter : config.workers) { const tCoreId& coreId = iter.first; - coresMask |= (((uint64_t)1) << (uint64_t)coreId); + cores_mask[coreId] = true; } - insert_eal_arg("0x%" PRIx64, coresMask); + insert_eal_arg("0x%" PRIx64, static_cast(cores_mask.to_ullong())); #if RTE_VERSION >= RTE_VERSION_NUM(20, 11, 0, 0) insert_eal_arg("--main-lcore"); From 175988bdc243d17306eda8edaada594bd53effb8 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 12 Aug 2024 20:59:28 +0300 Subject: [PATCH 050/195] Adds StaticVector We frequently need a vector like container that stores it's elements on stack. Using C-Style arrays with separate counter for stored elements is cumbersome and error-prone. std::array doesn't support tracking how many elements are currently stored. boost::static_vector fits the bill, but since we don't use boost StaticVector is written. --- common/static_vector.h | 234 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 common/static_vector.h diff --git a/common/static_vector.h b/common/static_vector.h new file mode 100644 index 00000000..b4642847 --- /dev/null +++ b/common/static_vector.h @@ -0,0 +1,234 @@ +#pragma once +#include + +#include + +namespace utils +{ + +#ifdef STATIC_VECTOR_USE_EXCEPTIONS +static constexpr bool USE_EXCEPTIONS = true; +#else +static constexpr bool USE_EXCEPTIONS = false; +#endif + +template +class StaticVector +{ + alignas(T) unsigned char buf_[sizeof(T[Cap])]; + std::size_t len_ = 0; + + T* AddressOfIndex(std::size_t idx) + { + return reinterpret_cast(buf_) + idx; + } + + const T* AddressOfIndex(std::size_t idx) const + { + return reinterpret_cast(buf_) + idx; + } + + void TrivialCopy(const StaticVector& other) + { + std::copy(std::begin(other.buf_), + std::begin(other.buf_) + other.len_ * sizeof(T), + std::begin(buf_)); + len_ = other.len_; + } + + void PerElementCopy(const StaticVector& other) + { + clear(); + for (const auto& elem : other) + { + PushBackUnsafe(elem); + } + } + + void PerElementCopy(StaticVector&& other) + { + clear(); + for (auto& elem : other) + { + PushBackUnsafe(std::move(elem)); + } + } + + void HandleOutOfRange() + { + if constexpr (USE_EXCEPTIONS) + { + throw std::out_of_range(""); + } + else + { + std::abort(); + } + } + + void PushBackUnsafe(const T& elem) + { + new (AddressOfIndex(len_)) T(elem); + ++len_; + } + + void PushBackUnsafe(T&& elem) + { + new (AddressOfIndex(len_)) T(std::move(elem)); + ++len_; + } + +public: + using iterator = T*; + using const_iterator = const T*; + StaticVector() = default; + + StaticVector(StaticVector&& other) + { + *this = std::move(other); + } + + StaticVector& operator=(StaticVector&& other) + { + if (this == &other) + { + return *this; + } + + if constexpr (std::is_trivially_copyable_v) + { + TrivialCopy(other); + } + else + { + PerElementMove(other); + } + return *this; + } + + StaticVector(const StaticVector& other) + { + *this = other; + } + + StaticVector& operator=(const StaticVector& other) + { + if (this == &other) + { + return *this; + } + clear(); + if constexpr (std::is_trivially_copyable_v) + { + TrivialCopy(other); + } + else + { + PerElementCopy(other); + } + return *this; + } + + void push_back(const T& elem) + { + if (Full()) + { + HandleOutOfRange(); + return; + } + PushBackUnsafe(elem); + } + + void push_back(T&& elem) + { + if (Full()) + { + HandleOutOfRange(); + return; + } + PushBackUnsafe(std::move(elem)); + } + + template + void emplace_back(Args&&... args) + { + new (AddressOfIndex(len_)) T(std::forward(args)...); + ++len_; + } + + void pop_back() + { + if (empty()) + { + HandleOutOfRange(); + return; + } + at(--len_).~T(); + } + + T& operator[](std::size_t pos) + { + return *AddressOfIndex(pos); + // return reinterpret_cast(buf_[pos * sizeof(T)]); + } + + const T& operator[](std::size_t pos) const + { + return *AddressOfIndex(pos); + } + + T& at(std::size_t pos) + { + if (pos >= size()) + { + HandleOutOfRange(); + abort(); + } + return *AddressOfIndex(pos); + // return reinterpret_cast(buf_[pos * sizeof(T)]); + } + + const T& at(std::size_t pos) const + { + if (pos >= size()) + { + HandleOutOfRange(); + abort(); + } + return *AddressOfIndex(pos); + } + + iterator begin() { return AddressOfIndex(0); } + iterator end() { return AddressOfIndex(size()); } + const_iterator begin() const { return AddressOfIndex(0); } + const_iterator end() const { return AddressOfIndex(size()); } + const_iterator cbegin() const { return AddressOfIndex(0); } + const_iterator cend() const { return AddressOfIndex(size()); } + + [[nodiscard]] bool empty() const + { + return size() == 0; + } + + constexpr std::size_t capacity() const { return Cap; } + + void clear() + { + if constexpr (std::is_trivially_destructible_v) + { + len_ = 0; + } + else + { + while (!empty()) + { + pop_back(); + } + } + } + + std::size_t size() const { return len_; } + bool Full() const { return size() == capacity(); } +}; + +} // namespace utils From 5e4ff9e6cd8f63dcfa9c129e4e436edc3dc3bac6 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 19 Aug 2024 13:59:34 +0300 Subject: [PATCH 051/195] Adds StaticVector unit tests --- common/unittest/meson.build | 23 ++++++++++++++ common/unittest/static_vector.cpp | 50 +++++++++++++++++++++++++++++++ meson.build | 1 + 3 files changed, 74 insertions(+) create mode 100644 common/unittest/meson.build create mode 100644 common/unittest/static_vector.cpp diff --git a/common/unittest/meson.build b/common/unittest/meson.build new file mode 100644 index 00000000..f3cd3852 --- /dev/null +++ b/common/unittest/meson.build @@ -0,0 +1,23 @@ +dependencies = [] +dependencies += dependency('threads') +dependencies += dependency('gtest') +dependencies += dependency('gtest_main') + +common_sources = files() + +sources = files('static_vector.cpp', + ) + +arch = 'corei7' +cpp_args_append = ['-march=' + arch] + +unittest = executable('yanet-common-unittest', + [common_sources, sources], + include_directories: yanet_rootdir, + dependencies: dependencies, + cpp_args: cpp_args_append, + override_options: 'b_lto=false') + +test('common', + unittest, + protocol: 'gtest') diff --git a/common/unittest/static_vector.cpp b/common/unittest/static_vector.cpp new file mode 100644 index 00000000..bb4049ab --- /dev/null +++ b/common/unittest/static_vector.cpp @@ -0,0 +1,50 @@ +#include +#include + +#define STATIC_VECTOR_USE_EXCEPTIONS +#include "../static_vector.h" + +namespace +{ +using utils::StaticVector; + +static constexpr std::string_view hw = "Hello World!"; + +TEST(StaticVector, 001_Basic_element_store) +{ + StaticVector v; + ASSERT_TRUE(v.empty()); + for (auto& c : hw) + { + v.push_back(c); + } + ASSERT_EQ(hw.length(), v.size()); + ASSERT_EQ(v.size(), v.capacity()); + ASSERT_TRUE(v.Full()); + bool caught = false; + try + { + v.push_back('c'); + } + catch (std::out_of_range& e) + { + caught = true; + } + ASSERT_TRUE(caught); +} + +TEST(StaticVector, 002_POD_copy_move) +{ + std::vector ref; + StaticVector v; + for (auto e : ref) + { + v.push_back(e); + } + auto copy = v; + ASSERT_TRUE(std::mismatch(v.begin(), v.end(), copy.begin()).first == v.end()); + auto moved = std::move(copy); + ASSERT_TRUE(std::mismatch(v.begin(), v.end(), moved.begin()).first == v.end()); +} + +} // namespace \ No newline at end of file diff --git a/meson.build b/meson.build index 970a7484..a77af658 100644 --- a/meson.build +++ b/meson.build @@ -65,6 +65,7 @@ elif target_option.contains('unittest') subdir('libfwparser') subdir('dataplane/unittest') subdir('controlplane/unittest') + subdir('common/unittest') subdir_done() endif From 35ada2178f055e552b4cd9526ecc5d539b084d85 Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 24 Jun 2024 19:19:59 +0300 Subject: [PATCH 052/195] Refactors GC for pernuma slow workers. Removes GC dependency on cControlPlane and cDataplane. Implements single GC working with multiple slow workers. --- common/config.release.h | 2 + dataplane/controlplane.cpp | 17 ++--- dataplane/controlplane.h | 3 + dataplane/dataplane.cpp | 42 ++++++++--- dataplane/dataplane.h | 2 +- dataplane/dpdk.h | 70 ++++++++++++++++++- dataplane/globalbase.cpp | 1 + dataplane/report.cpp | 1 + dataplane/utils.h | 48 +++++++++++++ dataplane/worker_gc.cpp | 140 ++++++++++++++++--------------------- dataplane/worker_gc.h | 25 ++++--- 11 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 dataplane/utils.h diff --git a/common/config.release.h b/common/config.release.h index e77beb6c..3522b6da 100644 --- a/common/config.release.h +++ b/common/config.release.h @@ -34,6 +34,8 @@ #define YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE (16) #define YANET_CONFIG_ACL_COUNTERS_SIZE (128 * 1024) #define YANET_CONFIG_NUMA_SIZE 2 +inline constexpr auto YANET_CONFIG_MAX_SLOW_WORKERS_PER_GC = 2; +inline constexpr auto YANET_CONFIG_MAX_SAMPLED_WORKERS_PER_GC = 16; #define YANET_CONFIG_COUNTERS_SIZE (8 * 1024 * 1024) #define YANET_CONFIG_ROUTE_TUNNEL_WEIGHTS_SIZE (2 * 1024 * 1024) #define YANET_CONFIG_COUNTER_FALLBACK_SIZE (64) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index f2978432..90158e4a 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -23,6 +23,7 @@ #include "metadata.h" #include "prepare.h" #include "worker.h" +#include "worker_gc.h" cControlPlane::cControlPlane(cDataPlane* dataPlane) : dataPlane(dataPlane), @@ -1460,20 +1461,14 @@ void cControlPlane::mainThread() } /// dequeue packets from worker_gc's ring to slowworker - for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) + rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + unsigned rxSize; + for (auto& gc : to_gcs_) { - (void)core_id; - - rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; - - unsigned rxSize = rte_ring_sc_dequeue_burst(worker_gc->ring_to_slowworker, - (void**)mbufs, - CONFIG_YADECAP_MBUFS_BURST_SIZE, - nullptr); - + rxSize = gc.process.DequeueBurstSC(mbufs); for (uint16_t mbuf_i = 0; mbuf_i < rxSize; mbuf_i++) { - rte_mbuf* mbuf = convertMempool(worker_gc->ring_to_free_mbuf, mbufs[mbuf_i]); + rte_mbuf* mbuf = convertMempool(gc.free._Underlying(), mbufs[mbuf_i]); if (!mbuf) { continue; diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index a18608b7..ef3e6d0b 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -15,9 +15,11 @@ #include "common/idp.h" #include "common/result.h" +#include "common/static_vector.h" #include "common/type.h" #include "dregress.h" +#include "dpdk.h" #include "fragmentation.h" #include "kernel_interface_handle.h" #include "slow_worker.h" @@ -167,6 +169,7 @@ class cControlPlane ///< @todo: move to cDataPlane cWorker* slowWorker; protected: + utils::StaticVector, YANET_CONFIG_NUMA_SIZE> to_gcs_; std::queue> slowWorkerMbufs; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 3c6b18cb..c5178417 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -40,6 +40,7 @@ #include "report.h" #include "sock_dev.h" #include "worker.h" +#include "worker_gc.h" common::log::LogPriority common::log::logPriority = common::log::TLOG_INFO; @@ -865,8 +866,6 @@ eResult cDataPlane::initGlobalBases() eResult cDataPlane::initWorkers() { - tQueueId outQueueId = 0; - /// slow worker { const tCoreId& coreId = config.controlPlaneCoreId; @@ -884,7 +883,7 @@ eResult cDataPlane::initWorkers() dataplane::base::permanently basePermanently; basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; - basePermanently.outQueueId = outQueueId; ///< 0 + basePermanently.outQueueId = out_queues_; ///< 0 for (const auto& portIter : ports) { if (!basePermanently.ports.Register(portIter.first)) @@ -910,7 +909,7 @@ eResult cDataPlane::initWorkers() controlPlane->slowWorker = worker; workers_vector.emplace_back(worker); - outQueueId++; + out_queues_++; } for (const auto& configWorkerIter : config.workers) @@ -1039,7 +1038,7 @@ eResult cDataPlane::initWorkers() } } - basePermanently.outQueueId = outQueueId; + basePermanently.outQueueId = out_queues_; dataplane::base::generation base; { @@ -1064,7 +1063,14 @@ eResult cDataPlane::initWorkers() workers[coreId] = worker; workers_vector.emplace_back(worker); - outQueueId++; + out_queues_++; + } + + worker_gc_t::PortToSocketArray port_to_socket; + for (const auto& [port_id, port] : ports) + { + (void)port; + port_to_socket[port_id] = rte_eth_dev_socket_id(port_id); } /// worker_gc @@ -1074,9 +1080,20 @@ eResult cDataPlane::initWorkers() YADECAP_LOG_INFO("initWorker. coreId: %u [worker_gc]\n", core_id); + worker_gc_t::SamplersVector samplers; + for (cWorker* worker : workers_vector) + { + if (worker->socketId != socket_id) + continue; + + samplers.push_back(&worker->sampler); + } + auto* worker = memory_manager.create_static("worker_gc", socket_id, - this); + config_values_, + port_to_socket, + std::move(samplers)); if (!worker) { return eResult::errorAllocatingMemory; @@ -1144,6 +1161,15 @@ eResult cDataPlane::initWorkers() worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[core_id]); worker_gcs[core_id] = worker; socket_worker_gcs[socket_id] = worker; + + auto conn = worker->RegisterSlowWorker("cw" + core_id, + config_values_.ring_normalPriority_size, + config_values_.ring_toFreePackets_size); + if (!conn) + { + YANET_LOG_ERROR("Failed no link garbage collector with slow worker"); + } + controlPlane->to_gcs_.push_back(conn.value()); } return eResult::success; @@ -1254,7 +1280,7 @@ int cDataPlane::lcoreThread(void* args) } else if (exist(dataPlane->worker_gcs, rte_lcore_id())) { - dataPlane->worker_gcs[rte_lcore_id()]->start(); + dataPlane->worker_gcs[rte_lcore_id()]->start(&dataPlane->runBarrier); } else { diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 02817658..8fdb3a06 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -26,7 +26,6 @@ #include "neighbor.h" #include "report.h" #include "type.h" -#include "worker_gc.h" struct tDataPlaneConfig { @@ -172,6 +171,7 @@ class cDataPlane bool ///< symmetric_mode >> ports; + tQueueId out_queues_ = 0; std::map workers; std::map worker_gcs; diff --git a/dataplane/dpdk.h b/dataplane/dpdk.h index ba6ad3fd..d08d1e46 100644 --- a/dataplane/dpdk.h +++ b/dataplane/dpdk.h @@ -1,8 +1,74 @@ #pragma once -#include +#include +#include + +#include + +#include "common/type.h" namespace dpdk { +template +class Ring +{ + rte_ring* ring_; + Ring(rte_ring* ring) : + ring_{ring} {} + +public: + Ring(const Ring& other) : + ring_{other.ring_} + { + } + static std::optional> Make(const std::string& name, + unsigned int count, + int socket_id, + unsigned int flags) + { + return Wrap(rte_ring_create(name.c_str(), + count, + socket_id, + flags)); + } + static std::optional> Wrap(rte_ring* r) + { + if (!r) + { + return std::nullopt; + } + else + { + return std::optional{std::move(Ring{r})}; + } + } + int EnqueueSP(T obj) + { + return rte_ring_sp_enqueue(ring_, reinterpret_cast(obj)); + } + + template + int DequeueBurstSC(rte_mbuf* (&mbufs)[MAX_COUNT]) + { + return rte_ring_sc_dequeue_burst(ring_, + (void**)mbufs, + MAX_COUNT, + nullptr); + } + + void Destroy() + { + rte_ring_free(ring_); + } + + rte_ring* _Underlying() { return ring_; } +}; + +template +struct RingConn +{ + Ring process; + Ring free; +}; struct Endpoint { @@ -13,4 +79,4 @@ struct Endpoint port{port}, queue{queue} {} }; -} // namespace dpdk \ No newline at end of file +} // namespace dpdk diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 360c06f2..68cf9801 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -6,6 +6,7 @@ #include "dataplane.h" #include "globalbase.h" #include "worker.h" +#include "worker_gc.h" #include "common/counters.h" #include "common/define.h" diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 303bdc8f..6f8d717c 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -6,6 +6,7 @@ #include "dataplane.h" #include "report.h" #include "worker.h" +#include "worker_gc.h" namespace { diff --git a/dataplane/utils.h b/dataplane/utils.h new file mode 100644 index 00000000..fffef6d8 --- /dev/null +++ b/dataplane/utils.h @@ -0,0 +1,48 @@ +#pragma once +#include + +#include "common/config.h" +#include "common/define.h" +#include "common/type.h" +#include "dpdk.h" +#include "metadata.h" + +namespace utils +{ + +inline void SetFlow(rte_mbuf* mbuf, const common::globalBase::tFlow& flow) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + metadata->flow = flow; +} + +inline void SetFlowType(rte_mbuf* mbuf, const common::globalBase::eFlowType& type) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + metadata->flow.type = type; +} + +template +class RoundRobinIterator +{ + It begin_; + It end_; + It curr_; + +public: + RoundRobinIterator(It range_start, It range_end) : + begin_{range_start}, end_{range_end}, curr_{range_start} + { + } + It operator->() { return curr_; } + RoundRobinIterator& operator++() + { + if (++curr_ == end_) + { + curr_ = begin_; + } + return *this; + } +}; + +} // namespace utils \ No newline at end of file diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 91e688d5..8d255167 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -10,18 +10,19 @@ #include "worker.h" #include "worker_gc.h" -worker_gc_t::worker_gc_t(cDataPlane* dataplane) : - dataplane(dataplane), - controlplane(nullptr), +worker_gc_t::worker_gc_t(const ConfigValues& cfg, const PortToSocketArray& pts, SamplersVector&& samplers) : mempool(nullptr), core_id(-1), socket_id(-1), iteration(0), current_base_id(0), local_base_id(0), - ring_to_slowworker(nullptr), - ring_to_free_mbuf(nullptr), - callback_id(0) + toSlowWorker_(toSlowWorkers_.begin(), toSlowWorkers_.end()), + port_id_to_socket_id{pts}, + samplers_{samplers}, + callback_id(0), + gc_step{static_cast(cfg.gc_step)}, + sample_gc_step{static_cast(cfg.sample_gc_step)} { memset(counters, 0, sizeof(counters)); } @@ -33,14 +34,14 @@ worker_gc_t::~worker_gc_t() rte_mempool_free(mempool); } - if (ring_to_slowworker) + for (auto& ring : toSlowWorkers_) { - rte_ring_free(ring_to_slowworker); + ring.Destroy(); } - if (ring_to_free_mbuf) + for (auto& ring : toFree_) { - rte_ring_free(ring_to_free_mbuf); + ring.Destroy(); } } @@ -55,17 +56,6 @@ eResult worker_gc_t::init(const tCoreId& core_id, this->bases[local_base_id] = base; this->bases[local_base_id ^ 1] = base; - this->controlplane = dataplane->controlPlane.get(); - - for (const auto& [port_id, port] : dataplane->ports) - { - (void)port; - port_id_to_socket_id[port_id] = rte_eth_dev_socket_id(port_id); - } - - gc_step = dataplane->getConfigValues().gc_step; - sample_gc_step = dataplane->getConfigValues().sample_gc_step; - mempool = rte_mempool_create(("wgc" + std::to_string(core_id)).data(), CONFIG_YADECAP_MBUFS_COUNT + 3 * CONFIG_YADECAP_PORTS_SIZE * CONFIG_YADECAP_MBUFS_BURST_SIZE, CONFIG_YADECAP_MBUF_SIZE, @@ -83,37 +73,57 @@ eResult worker_gc_t::init(const tCoreId& core_id, return eResult::errorInitMempool; } - ring_to_slowworker = rte_ring_create(("r_tsw_" + std::to_string(core_id)).c_str(), - dataplane->getConfigValues().ring_normalPriority_size, - socket_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (!ring_to_slowworker) + return eResult::success; +} + +[[nodiscard]] std::optional> worker_gc_t::RegisterSlowWorker(const std::string& name, + unsigned int capacity, + unsigned int capacity_to_free) +{ + if (toSlowWorkers_.Full() || toFree_.Full()) + { + YANET_LOG_ERROR("Trying to assign to many workers to garbage collector on core %d\n", core_id); + return std::nullopt; + } + auto rs = dpdk::Ring::Make( + "r_gc" + std::to_string(socket_id) + "_to_" + name, + capacity, + socket_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (!rs) { - return eResult::errorInitRing; + return std::nullopt; } - ring_to_free_mbuf = rte_ring_create(("r_tfmb_" + std::to_string(core_id)).c_str(), - dataplane->getConfigValues().ring_toFreePackets_size, - socket_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (!ring_to_free_mbuf) + auto rf = dpdk::Ring::Make( + "r_tfmb_gc" + std::to_string(socket_id) + "_from_" + name, + capacity_to_free, + socket_id, + RING_F_SP_ENQ | RING_F_SC_DEQ); + + if (!rf) { - return eResult::errorInitRing; + rs.value().Destroy(); + return std::nullopt; } - return eResult::success; + toSlowWorkers_.push_back(rs.value()); + toFree_.push_back(rf.value()); + + toSlowWorker_ = {toSlowWorkers_.begin(), toSlowWorkers_.end()}; + return dpdk::RingConn{std::move(rs.value()), std::move(rf.value())}; } -void worker_gc_t::start() +void worker_gc_t::start(pthread_barrier_t* runBarrier) { /// @todo: prepare int rc; - rc = pthread_barrier_wait(&dataplane->runBarrier); + rc = pthread_barrier_wait(runBarrier); if (rc == PTHREAD_BARRIER_SERIAL_THREAD) { - pthread_barrier_destroy(&dataplane->runBarrier); + pthread_barrier_destroy(runBarrier); } else if (rc != 0) { @@ -830,7 +840,8 @@ void worker_gc_t::handle_acl_sync() mbuf_clone->pkt_len = mbuf->pkt_len; stats.fwsync_multicast_egress_packets++; - send_to_slowworker(mbuf_clone, flow); + utils::SetFlow(mbuf_clone, flow); + SendToSlowWorker(mbuf_clone); } if (!fw_state_config.ipv6_address_unicast.empty()) @@ -858,7 +869,8 @@ void worker_gc_t::handle_acl_sync() mbuf_clone->pkt_len = mbuf->pkt_len; stats.fwsync_unicast_egress_packets++; - send_to_slowworker(mbuf_clone, fw_state_config.ingress_flow); + utils::SetFlow(mbuf_clone, fw_state_config.ingress_flow); + SendToSlowWorker(mbuf_clone); } } } @@ -910,16 +922,10 @@ void worker_gc_t::handle_free_mbuf() rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; unsigned int mbufs_count; - mbufs_count = rte_ring_sc_dequeue_burst(ring_to_free_mbuf, - (void**)mbufs, - CONFIG_YADECAP_MBUFS_BURST_SIZE, - nullptr); - for (unsigned int mbuf_i = 0; - mbuf_i < mbufs_count; - mbuf_i++) + for (auto& ring : toFree_) { - rte_mbuf* mbuf = mbufs[mbuf_i]; - rte_pktmbuf_free(mbuf); + mbufs_count = ring.DequeueBurstSC(mbufs); + rte_pktmbuf_free_bulk(mbufs, mbufs_count); } } @@ -974,30 +980,9 @@ void worker_gc_t::nat64stateful_remove_state(const dataplane::globalBase::nat64s } } -void worker_gc_t::send_to_slowworker(rte_mbuf* mbuf, - const common::globalBase::eFlowType& flow_type) +void worker_gc_t::SendToSlowWorker(rte_mbuf* mbuf) { - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - metadata->flow.type = flow_type; - - if (rte_ring_sp_enqueue(ring_to_slowworker, (void*)mbuf)) - { - stats.ring_to_slowworker_drops++; - rte_pktmbuf_free(mbuf); - } - else - { - stats.ring_to_slowworker_packets++; - } -} - -void worker_gc_t::send_to_slowworker(rte_mbuf* mbuf, - const common::globalBase::tFlow& flow) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - metadata->flow = flow; - - if (rte_ring_sp_enqueue(ring_to_slowworker, (void*)mbuf)) + if (toSlowWorker_->EnqueueSP(mbuf)) { stats.ring_to_slowworker_drops++; rte_pktmbuf_free(mbuf); @@ -1017,14 +1002,9 @@ void worker_gc_t::handle_samples() std::lock_guard guard(samples_mutex); - for (const auto& iter : dataplane->workers) + for (auto sampler : samplers_) { - if (iter.second->socketId != socket_id) - continue; - - auto& sampler = iter.second->sampler; - - sampler.visit6([this](auto& sample) { + sampler->visit6([this](auto& sample) { if (samples.size() < YANET_CONFIG_SAMPLES_SIZE * 8) { samples.emplace(sample.proto, sample.in_logicalport_id, sample.out_logicalport_id, sample.src_port, sample.dst_port, sample.src_addr.bytes, sample.dst_addr.bytes); @@ -1034,7 +1014,7 @@ void worker_gc_t::handle_samples() stats.drop_samples++; } }); - sampler.visit4([this](auto& sample) { + sampler->visit4([this](auto& sample) { if (samples.size() < YANET_CONFIG_SAMPLES_SIZE * 8) { samples.emplace(sample.proto, sample.in_logicalport_id, sample.out_logicalport_id, sample.src_port, sample.dst_port, rte_be_to_cpu_32(sample.src_addr.address), rte_be_to_cpu_32(sample.dst_addr.address)); @@ -1044,7 +1024,7 @@ void worker_gc_t::handle_samples() stats.drop_samples++; } }); - sampler.clear(); + sampler->clear(); } if (samples_current_base_id != current_base_id) diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index 0243662d..58ea89a6 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -6,19 +6,23 @@ #include "base.h" #include "common.h" #include "hashtable.h" +#include "utils.h" #include "common/generation.h" #include "common/idp.h" +#include "common/static_vector.h" #include "hashtable.h" class worker_gc_t { public: - worker_gc_t(cDataPlane* dataplane); + using PortToSocketArray = std::array; + using SamplersVector = utils::StaticVector; + worker_gc_t(const ConfigValues& cfg, const PortToSocketArray& pts, SamplersVector&& samplers); ~worker_gc_t(); eResult init(const tCoreId& core_id, const tSocketId& socket_id, const dataplane::base::permanently& base_permanently, const dataplane::base::generation& base); - void start(); + void start(pthread_barrier_t* runBarrier); void run_on_this_thread(const std::function& callback); void nat64stateful_state(const common::idp::nat64stateful_state::request& request, common::idp::nat64stateful_state::response& response); @@ -44,14 +48,15 @@ class worker_gc_t void nat64stateful_remove_state(const dataplane::globalBase::nat64stateful_lan_key& lan_key, const dataplane::globalBase::nat64stateful_wan_key& wan_key); - void send_to_slowworker(rte_mbuf* mbuf, const common::globalBase::eFlowType& flow_type); - void send_to_slowworker(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); + void SendToSlowWorker(rte_mbuf* mbuf); void handle_samples(); public: - cDataPlane* dataplane; - cControlPlane* controlplane; + [[nodiscard]] std::optional> RegisterSlowWorker(const std::string& name, + unsigned int capacity, + unsigned int capacity_to_free); + rte_mempool* mempool; tCoreId core_id; tSocketId socket_id; @@ -64,13 +69,15 @@ class worker_gc_t YADECAP_CACHE_ALIGNED(align1); - rte_ring* ring_to_slowworker; - rte_ring* ring_to_free_mbuf; + utils::StaticVector, YANET_CONFIG_MAX_SLOW_WORKERS_PER_GC> toSlowWorkers_; + utils::StaticVector, YANET_CONFIG_MAX_SLOW_WORKERS_PER_GC> toFree_; + utils::RoundRobinIterator toSlowWorker_; - tSocketId port_id_to_socket_id[CONFIG_YADECAP_PORTS_SIZE]; + PortToSocketArray port_id_to_socket_id; YADECAP_CACHE_ALIGNED(align2); + SamplersVector samplers_; std::set samples; uint32_t samples_current_base_id; std::mutex samples_mutex; From 6fa550b520de0f0566d024227cfee2ece0f9f66c Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 22 Apr 2024 21:12:25 +0300 Subject: [PATCH 053/195] Adds config parsing for plane workers Adds parsing of control plane workers configuration from config file. Expected config file section is: "controlPlaneWorkers": [ { "core" : 42, "interfaces": [ ] } ] In case section is not present, configuration for single control plane worker, responsible for all dataplane interfaces and residing on controlPlaneCoreId is generated. This Is done to ease transition on already deployed appliances. Section is checked for - Every configured dataplane interface is assigned to a control plane worker - Each interface is assigned to single control plane worker - Interfaces not configured for use by dataplane, but listed in controlplane workers are treated as errors --- dataplane/dataplane.cpp | 171 ++++++++++++++++++++++++++++++++++++++++ dataplane/dataplane.h | 15 +++- 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index c5178417..03eebb1f 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1759,6 +1759,13 @@ eResult cDataPlane::parseConfig(const std::string& configFilePath) } } + auto cp_workers = parseControlPlaneWorkers(rootJson); + if (!cp_workers) + { + return eResult::invalidConfigurationFile; + } + config.controlplane_workers = std::move(cp_workers.value()); + if (rootJson.find("hugeMem") != rootJson.end()) { config.useHugeMem = rootJson.find("hugeMem").value(); @@ -1884,6 +1891,124 @@ eResult cDataPlane::parseJsonPorts(const nlohmann::json& json) return eResult::success; } +std::optional>> cDataPlane::parseControlPlaneWorkers(const nlohmann::json& root) +{ + nlohmann::json dflt; + auto cpw = root.find("controlPlaneWorkers"); + if (cpw == root.end()) + { + dflt = makeLegacyControlPlaneWorkerConfig(); + YADECAP_LOG_WARNING("no config for control plane workers provided, using default legacy config\"%s\"\n", + dflt.dump().c_str()); + cpw = dflt.find("controlPlaneWorkers"); + } + + std::map> result; + + auto add_worker = [&](const nlohmann::json& j) { + auto worker = parseControlPlaneWorker(j); + if (!worker) + { + YADECAP_LOG_ERROR("invalid control plane worker config \"%s\"\n", j.dump().c_str()); + return false; + } + result[worker->first] = worker->second; + return true; + }; + + if (!cpw->is_array()) + { + if (!add_worker(cpw.value())) + { + return std::nullopt; + } + } + else + { + for (auto j : cpw.value()) + { + if (!add_worker(j)) + { + return std::nullopt; + } + } + } + return std::optional{std::move(result)}; +} + +nlohmann::json cDataPlane::makeLegacyControlPlaneWorkerConfig() +{ + nlohmann::json j; + j["core"] = config.controlPlaneCoreId; + j["interfaces"] = workerInterfacesToService(); + return nlohmann::json{{"controlPlaneWorkers", j}}; +} + +std::set cDataPlane::workerInterfacesToService() +{ + std::set res; + for (const auto& p : config.workers) + { + const auto& ifaces = p.second; + for (const auto& i : ifaces) + { + res.emplace(i); + } + } + return res; +} + +std::optional>> cDataPlane::parseControlPlaneWorker(const nlohmann::json& cpwj) +{ + auto jcore = cpwj.find("core"); + if (jcore == cpwj.end()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry has no \"core\" field\n"); + return std::nullopt; + } + if (!jcore.value().is_number_unsigned()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry \"core\" field is not an unsigned integer\n"); + return std::nullopt; + } + tCoreId core = jcore.value(); + + auto jports = cpwj.find("interfaces"); + if (jports == cpwj.end()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry has no \"interfaces\" field\n"); + return std::nullopt; + } + if (jports.value().is_number_unsigned()) + { + const std::set ifaces = jports.value(); + return std::optional{ + std::pair>{ + core, + std::set{InterfaceName{jports.value()}}}}; + } + if (!jports.value().is_array()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry \"interfaces\" has invalid type.\n"); + return std::nullopt; + } + + std::set worker_ports; + for (auto j : jports.value()) + { + if (!j.is_string()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry \"interfaces\" contains invalid type."); + return std::nullopt; + } + worker_ports.insert(InterfaceName{j}); + } + return std::optional{ + std::pair>{ + core, + std::move(worker_ports)}}; +} + eResult cDataPlane::parseConfigValues(const nlohmann::json& json) { config_values_ = json; @@ -1985,9 +2110,55 @@ eResult cDataPlane::checkConfig() } } + if (!checkControlPlaneWorkersConfig()) + { + return eResult::invalidConfigurationFile; + } + return eResult::success; } +bool cDataPlane::checkControlPlaneWorkersConfig() +{ + std::set assigned; + std::set to_assign = workerInterfacesToService(); + bool result = true; + for (const auto& [core, worker_ports] : config.controlplane_workers) + { + for (const auto& p : worker_ports) + { + + if (assigned.find(p) != assigned.end()) + { + YADECAP_LOG_ERROR("Duplicate port in control plane worker config: core: %d, port: %s\n", core, p.c_str()); + result = false; + continue; + } + + if (to_assign.find(p) == to_assign.end()) + { + YADECAP_LOG_ERROR("Control plane worker config contains port not assigned to fast worker: core: %d, port: %s\n", core, p.c_str()); + result = false; + continue; + } + + assigned.emplace(p); + to_assign.erase(p); + } + } + if (!to_assign.empty()) + { + std::stringstream ss; + for (const auto& p : to_assign) + { + ss << p << ' '; + } + YADECAP_LOG_ERROR("Ports { %s } are not assigned a control plane worker\n", ss.str().c_str()); + result = false; + } + return result; +} + eResult cDataPlane::initEal(const std::string& binaryPath, const std::string& filePrefix) { diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 8fdb3a06..6634d57b 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -27,6 +27,8 @@ #include "report.h" #include "type.h" +using InterfaceName = std::string; + struct tDataPlaneConfig { /* @@ -35,7 +37,7 @@ struct tDataPlaneConfig and an identifier (typically pci id) used to lookup the port within DPDK. */ - std::map workerGCs; tCoreId controlPlaneCoreId; - std::map> workers; + std::map> controlplane_workers; + std::map> workers; bool useHugeMem = true; bool use_kernel_interface = true; bool interfaces_required = true; @@ -109,10 +112,16 @@ class cDataPlane protected: eResult parseConfig(const std::string& configFilePath); eResult parseJsonPorts(const nlohmann::json& json); + std::optional>> parseControlPlaneWorkers(const nlohmann::json& config); + std::optional>> parseControlPlaneWorker(const nlohmann::json& cpwj); + nlohmann::json makeLegacyControlPlaneWorkerConfig(); + std::set workerInterfacesToService(); eResult parseConfigValues(const nlohmann::json& json); eResult parseRateLimits(const nlohmann::json& json); eResult parseSharedMemory(const nlohmann::json& json); eResult checkConfig(); + bool checkControlPlaneWorkersConfig(); + bool checkValidCoreId(const nlohmann::json& j); eResult initEal(const std::string& binaryPath, const std::string& filePrefix); eResult initPorts(); @@ -163,7 +172,7 @@ class cDataPlane std::map kni_interface_handles; std::map, ///< rx_queues unsigned int, ///< tx_queues_count common::mac_address_t, ///< mac_address From d12ba8c095bfa4a82c997ea33ad8964c0f499b18 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 21 May 2024 13:52:54 +0300 Subject: [PATCH 054/195] Adds controlplane workers to EAL cores mask --- dataplane/dataplane.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 03eebb1f..0d1460ee 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -2187,6 +2187,11 @@ eResult cDataPlane::initEal(const std::string& binaryPath, std::bitset::digits> cores_mask; cores_mask[config.controlPlaneCoreId] = true; + for (const auto& iter : config.controlplane_workers) + { + const tCoreId& coreId = iter.first; + cores_mask[coreId] = true; + } for (const auto& coreId : config.workerGCs) { cores_mask[coreId] = true; From 404abe6f3190878acb90234091f6139488c66fd8 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 2 Jul 2024 16:12:53 +0300 Subject: [PATCH 055/195] Moves ICMP rate limiter out of control plane loop. --- dataplane/controlplane.cpp | 35 +---------------------------------- dataplane/controlplane.h | 2 -- dataplane/dataplane.cpp | 33 +++++++++++++++++++++++++++++++++ dataplane/dataplane.h | 2 ++ 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 90158e4a..e678bd73 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -38,8 +38,7 @@ cControlPlane::cControlPlane(cDataPlane* dataPlane) : dataPlane->getConfigValues().gc_step), mempool(nullptr), use_kernel_interface(false), - slowWorker(nullptr), - prevTimePointForSWRateLimiter(std::chrono::high_resolution_clock::now()) + slowWorker(nullptr) { memset(&stats, 0, sizeof(stats)); } @@ -1408,11 +1407,6 @@ void cControlPlane::mainThread() for (;;) { - if (dataPlane->config.SWNormalPriorityRateLimitPerWorker || dataPlane->config.SWICMPOutRateLimit) - { - SWRateLimiterTimeTracker(); - } - slowWorker->slowWorkerBeforeHandlePackets(); /// dequeue packets from worker's rings @@ -2483,30 +2477,3 @@ void cControlPlane::freeWorkerPacket(rte_ring* ring_to_free_mbuf, std::this_thread::yield(); } } - -void cControlPlane::SWRateLimiterTimeTracker() -{ - // seem to be sufficiently fast function for slowWorker whose threshold is 200'000 packets per second - std::chrono::high_resolution_clock::time_point curTimePointForSWRateLimiter = std::chrono::high_resolution_clock::now(); - - // is it time to reset icmpPacketsToSW counters? - if (std::chrono::duration_cast(curTimePointForSWRateLimiter - prevTimePointForSWRateLimiter) >= std::chrono::milliseconds(1000 / dataPlane->config.rateLimitDivisor)) - { - // the only place thread-shared variable icmpPacketsToSW is changed - for (auto& [coreId, worker] : dataPlane->workers) - { - (void)coreId; - - if (slowWorker == worker) - { - continue; - } - - __atomic_store_n(&worker->packetsToSWNPRemainder, dataPlane->config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); - } - - icmpOutRemainder = dataPlane->config.SWICMPOutRateLimit / dataPlane->config.rateLimitDivisor; - - prevTimePointForSWRateLimiter = curTimePointForSWRateLimiter; - } -} diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index ef3e6d0b..1f9bf553 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -102,8 +102,6 @@ class cControlPlane ///< @todo: move to cDataPlane void handlePacket_balancer_icmp_forward(rte_mbuf* mbuf); void handlePacket_dump(rte_mbuf* mbuf); - void SWRateLimiterTimeTracker(); - rte_mbuf* convertMempool(rte_ring* ring_to_free_mbuf, rte_mbuf* mbuf); protected: diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 0d1460ee..4d383e2a 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -50,6 +50,7 @@ bool StartsWith(const std::string& str, const std::string& prefix) } cDataPlane::cDataPlane() : + prevTimePointForSWRateLimiter(std::chrono::high_resolution_clock::now()), currentGlobalBaseId(0), globalBaseSerial(0), report(this), @@ -1264,6 +1265,33 @@ void cDataPlane::init_worker_base() neighbor.update_worker_base(base_nexts); } +void cDataPlane::SWRateLimiterTimeTracker() +{ + for (;;) + { + // seem to be sufficiently fast function for slowWorker whose threshold is 200'000 packets per second + std::chrono::high_resolution_clock::time_point curTimePointForSWRateLimiter = std::chrono::high_resolution_clock::now(); + + // is it time to reset icmpPacketsToSW counters? + if (std::chrono::duration_cast(curTimePointForSWRateLimiter - prevTimePointForSWRateLimiter) >= std::chrono::milliseconds(1000 / config.rateLimitDivisor)) + { + // the only place thread-shared variable icmpPacketsToSW is changed + for (auto& [coreId, worker] : workers) + { + (void)coreId; + + __atomic_store_n(&worker->packetsToSWNPRemainder, config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); + } + + controlPlane->icmpOutRemainder = config.SWICMPOutRateLimit / config.rateLimitDivisor; + + prevTimePointForSWRateLimiter = curTimePointForSWRateLimiter; + } + using namespace std::chrono_literals; + std::this_thread::sleep_for(100ms / config.rateLimitDivisor); + } +} + int cDataPlane::lcoreThread(void* args) { cDataPlane* dataPlane = (cDataPlane*)args; @@ -1320,6 +1348,11 @@ void cDataPlane::start() timestamp_thread(); }); + threads.emplace_back([this]() { + YANET_LOG_INFO("Rate limiter started\n"); + SWRateLimiterTimeTracker(); + }); + bus.run(); /// run forwarding plane and control plane diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 6634d57b..528e4374 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -150,6 +150,8 @@ class cDataPlane static int lcoreThread(void* args); void timestamp_thread(); + void SWRateLimiterTimeTracker(); + std::chrono::high_resolution_clock::time_point prevTimePointForSWRateLimiter; protected: friend class cWorker; From da1d5a6be7a40f78a297f27e7737c8eca36d57bb Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 4 Jul 2024 18:41:41 +0300 Subject: [PATCH 056/195] Refactors worker rx ports Changes unnamed embedded strut describing rx worker port to Endpoint Changes container of rx worker ports to static vector --- dataplane/base.h | 18 +++++------------- dataplane/controlplane.cpp | 6 ++---- dataplane/report.cpp | 26 ++++++++++++-------------- dataplane/worker.cpp | 35 ++++++++++++++--------------------- dataplane/worker.h | 2 +- 5 files changed, 34 insertions(+), 53 deletions(-) diff --git a/dataplane/base.h b/dataplane/base.h index 6c077acd..1222aa40 100644 --- a/dataplane/base.h +++ b/dataplane/base.h @@ -8,6 +8,8 @@ #include #include +#include "common/static_vector.h" +#include "dpdk.h" #include "neighbor.h" #include "type.h" @@ -60,7 +62,6 @@ class permanently public: permanently() : globalBaseAtomic(nullptr), - workerPortsCount(0), nat64stateful_numa_mask(0xFFFFu), nat64stateful_numa_reverse_mask(0), nat64stateful_numa_id(0) @@ -79,15 +80,11 @@ class permanently bool add_worker_port(const tPortId port_id, tQueueId queue_id) { - if (workerPortsCount >= CONFIG_YADECAP_WORKER_PORTS_SIZE) + if (rx_points.Full()) { return false; } - - workerPorts[workerPortsCount].inPortId = port_id; - workerPorts[workerPortsCount].inQueueId = queue_id; - workerPortsCount++; - + rx_points.emplace_back(port_id, queue_id); return true; } @@ -97,12 +94,7 @@ class permanently /// Used to distribute firewall states. dataplane::globalBase::atomic* globalBaseAtomics[YANET_CONFIG_NUMA_SIZE]; - unsigned int workerPortsCount; - struct - { - tPortId inPortId; - tQueueId inQueueId; - } workerPorts[CONFIG_YADECAP_WORKER_PORTS_SIZE]; + utils::StaticVector rx_points; PortMapper ports; tQueueId outQueueId; diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index e678bd73..be62e3e6 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -694,11 +694,9 @@ common::idp::getConfig::response cControlPlane::getConfig() const const tCoreId& coreId = workerIter.first; const cWorker* worker = workerIter.second; - for (unsigned int worker_port_i = 0; - worker_port_i < worker->basePermanently.workerPortsCount; - worker_port_i++) + for (const auto& endpoint : worker->basePermanently.rx_points) { - std::get<0>(response_workers[coreId]).emplace_back(worker->basePermanently.workerPorts[worker_port_i].inPortId); + std::get<0>(response_workers[coreId]).emplace_back(endpoint.port); } std::get<1>(response_workers[coreId]) = worker->socketId; diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 6f8d717c..fbab5cb0 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -203,16 +203,15 @@ nlohmann::json cReport::convertWorker(const cWorker* worker) /// permanently base json["permanentlyBase"]["globalBaseAtomic"]["pointer"] = pointerToHex(worker->basePermanently.globalBaseAtomic); - json["permanentlyBase"]["workerPortsCount"] = worker->basePermanently.workerPortsCount; - for (unsigned int worker_port_i = 0; - worker_port_i < worker->basePermanently.workerPortsCount; - worker_port_i++) + json["permanentlyBase"]["workerPortsCount"] = worker->basePermanently.rx_points.size(); + std::size_t idx{}; + for (const auto& [port, queue] : worker->basePermanently.rx_points) { nlohmann::json jsonPort; - jsonPort["worker_port_i"] = worker_port_i; - jsonPort["inPortId"] = worker->basePermanently.workerPorts[worker_port_i].inPortId; - jsonPort["inQueueId"] = worker->basePermanently.workerPorts[worker_port_i].inQueueId; + jsonPort["worker_port_i"] = idx++; + jsonPort["inPortId"] = port; + jsonPort["inQueueId"] = queue; json["permanentlyBase"]["workerPorts"].emplace_back(jsonPort); } @@ -281,16 +280,15 @@ nlohmann::json cReport::convertWorkerGC(const worker_gc_t* worker) /// permanently base json["permanentlyBase"]["globalBaseAtomic"]["pointer"] = pointerToHex(worker->base_permanently.globalBaseAtomic); - json["permanentlyBase"]["workerPortsCount"] = worker->base_permanently.workerPortsCount; - for (unsigned int worker_port_i = 0; - worker_port_i < worker->base_permanently.workerPortsCount; - worker_port_i++) + json["permanentlyBase"]["workerPortsCount"] = worker->base_permanently.rx_points.size(); + std::size_t idx{}; + for (const auto& [port, queue] : worker->base_permanently.rx_points) { nlohmann::json jsonPort; - jsonPort["worker_port_i"] = worker_port_i; - jsonPort["inPortId"] = worker->base_permanently.workerPorts[worker_port_i].inPortId; - jsonPort["inQueueId"] = worker->base_permanently.workerPorts[worker_port_i].inQueueId; + jsonPort["worker_port_i"] = idx++; + jsonPort["inPortId"] = port; + jsonPort["inQueueId"] = queue; json["permanentlyBase"]["workerPorts"].emplace_back(jsonPort); } diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index ccb286ae..0c1d3123 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -97,8 +97,8 @@ eResult cWorker::init(const tCoreId& coreId, this->bases[currentBaseId] = base; this->bases[currentBaseId ^ 1] = base; - unsigned int elements_count = 2 * basePermanently.workerPortsCount * dataPlane->getConfigValues().port_rx_queue_size + - 2 * basePermanently.workerPortsCount * dataPlane->getConfigValues().port_tx_queue_size + + unsigned int elements_count = 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_rx_queue_size + + 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_tx_queue_size + 2 * dataPlane->getConfigValues().ring_highPriority_size + 2 * dataPlane->getConfigValues().ring_normalPriority_size + 2 * dataPlane->getConfigValues().ring_lowPriority_size; @@ -201,8 +201,8 @@ void cWorker::start() /// @todo: prepare() - unsigned int mbufs_count_expect = 2 * basePermanently.workerPortsCount * dataPlane->getConfigValues().port_rx_queue_size + - 2 * basePermanently.workerPortsCount * dataPlane->getConfigValues().port_tx_queue_size + + unsigned int mbufs_count_expect = 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_rx_queue_size + + 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_tx_queue_size + 2 * dataPlane->getConfigValues().ring_highPriority_size + 2 * dataPlane->getConfigValues().ring_normalPriority_size + 2 * dataPlane->getConfigValues().ring_lowPriority_size; @@ -233,17 +233,12 @@ void cWorker::start() abort(); } - for (unsigned int worker_port_i = 0; - worker_port_i < basePermanently.workerPortsCount; - worker_port_i++) + for (const auto& [port, queue]: basePermanently.rx_points) { - const auto& portId = basePermanently.workerPorts[worker_port_i].inPortId; - const auto& queueId = basePermanently.workerPorts[worker_port_i].inQueueId; - - rc = rte_eth_rx_queue_setup(portId, - queueId, + rc = rte_eth_rx_queue_setup(port, + queue, dataPlane->getConfigValues().port_rx_queue_size, - rte_eth_dev_socket_id(portId), + rte_eth_dev_socket_id(port), nullptr, ///< @todo mempool); if (rc < 0) @@ -393,12 +388,10 @@ YANET_NEVER_INLINE void cWorker::mainThread() localBaseId = currentBaseId; /// @todo: opt - for (unsigned int worker_port_i = 0; - worker_port_i < basePermanently.workerPortsCount; - worker_port_i++) + for (const auto& rx_point : basePermanently.rx_points) { toFreePackets_handle(); - physicalPort_ingress_handle(worker_port_i); + physicalPort_ingress_handle(rx_point); if (unlikely(logicalPort_ingress_stack.mbufsCount == 0)) { @@ -1024,11 +1017,11 @@ inline void cWorker::handlePackets() static_assert(CONFIG_YADECAP_PORTS_SIZE == 8, "(vlanId << 3) | metadata->fromPortId"); static_assert(CONFIG_YADECAP_LOGICALPORTS_SIZE == CONFIG_YADECAP_PORTS_SIZE * 8192, "base.globalBase->logicalPorts[CALCULATE_LOGICALPORT_ID(metadata->fromPortId, vlanId)]"); -inline void cWorker::physicalPort_ingress_handle(const unsigned int& worker_port_i) +inline void cWorker::physicalPort_ingress_handle(const dpdk::Endpoint& rx_point) { /// read packets from ports - uint16_t rxSize = rte_eth_rx_burst(basePermanently.workerPorts[worker_port_i].inPortId, - basePermanently.workerPorts[worker_port_i].inQueueId, + uint16_t rxSize = rte_eth_rx_burst(rx_point.port, + rx_point.queue, logicalPort_ingress_stack.mbufs, CONFIG_YADECAP_MBUFS_BURST_SIZE); @@ -1040,7 +1033,7 @@ inline void cWorker::physicalPort_ingress_handle(const unsigned int& worker_port rte_mbuf* mbuf = logicalPort_ingress_stack.mbufs[mbuf_i]; dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - metadata->fromPortId = basePermanently.workerPorts[worker_port_i].inPortId; + metadata->fromPortId = rx_point.port; metadata->repeat_ttl = YANET_CONFIG_REPEAT_TTL; metadata->flowLabel = 0; metadata->already_early_decapped = 0; diff --git a/dataplane/worker.h b/dataplane/worker.h index c904c294..15024ddc 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -93,7 +93,7 @@ class cWorker inline void handlePackets(); - inline void physicalPort_ingress_handle(const unsigned int& worker_port_i); + inline void physicalPort_ingress_handle(const dpdk::Endpoint& rx_point); inline void physicalPort_egress_handle(); From 637b03b736d9ae8e1aa8fc43532c7353e8f27df3 Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 4 Jul 2024 20:04:31 +0300 Subject: [PATCH 057/195] Moves rx queues initialization out of workers For each worker to configure it's own rx queues it must be aware of dataplane configuration. This forces us to leak dataplane abstraction into worker. Configuring rx queues on dataplane level allows us to get rid of synchronization bariier and simplify startup logic. --- dataplane/controlplane.cpp | 14 +------- dataplane/dataplane.cpp | 72 ++++++++++++++++++++------------------ dataplane/dataplane.h | 7 ++-- dataplane/worker.cpp | 26 -------------- 4 files changed, 41 insertions(+), 78 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index be62e3e6..324d23cb 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -74,18 +74,6 @@ eResult cControlPlane::init(bool use_kernel_interface) void cControlPlane::start() { - int rc = pthread_barrier_wait(&dataPlane->initPortBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(&dataPlane->initPortBarrier); - } - else if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_wait() = %d\n", rc); - /// @todo: stop - return; - } - /// start devices for (const auto& portIter : dataPlane->ports) { @@ -104,7 +92,7 @@ void cControlPlane::start() rte_eth_promiscuous_enable(portId); } - rc = pthread_barrier_wait(&dataPlane->runBarrier); + auto rc = pthread_barrier_wait(&dataPlane->runBarrier); if (rc == PTHREAD_BARRIER_SERIAL_THREAD) { pthread_barrier_destroy(&dataPlane->runBarrier); diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 4d383e2a..34c4bbb7 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -217,7 +217,13 @@ eResult cDataPlane::init(const std::string& binaryPath, } numaNodesInUse = worker_gcs.size(); - result = initQueues(); + result = InitTxQueues(); + if (result != eResult::success) + { + return result; + } + + result = InitRxQueues(); if (result != eResult::success) { return result; @@ -243,16 +249,8 @@ eResult cDataPlane::init(const std::string& binaryPath, init_worker_base(); - /// init sync barrier - int rc = pthread_barrier_init(&initPortBarrier, nullptr, workers.size()); - if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_init() = %d\n", rc); - return eResult::errorInitBarrier; - } - /// init run sync barrier - rc = pthread_barrier_init(&runBarrier, nullptr, workers.size() + worker_gcs.size()); + auto rc = pthread_barrier_init(&runBarrier, nullptr, workers.size() + worker_gcs.size()); if (rc != 0) { YADECAP_LOG_ERROR("pthread_barrier_init() = %d\n", rc); @@ -626,25 +624,6 @@ void cDataPlane::StartInterfaces() } } -void cDataPlane::InitPortsBarrier() -{ - int rc = pthread_barrier_wait(&initPortBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(&initPortBarrier); - } - else if (rc) - { - YANET_LOG_ERROR("init_ports_barrier pthread_barrier_wait() = %d\n", rc); - std::abort(); - } - - if (rte_get_main_lcore() == rte_lcore_id()) - { - StartInterfaces(); - } -} - eResult cDataPlane::InitControlPlane() { controlPlane = std::make_unique(this); @@ -884,7 +863,7 @@ eResult cDataPlane::initWorkers() dataplane::base::permanently basePermanently; basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; - basePermanently.outQueueId = out_queues_; ///< 0 + basePermanently.outQueueId = tx_queues_; ///< 0 for (const auto& portIter : ports) { if (!basePermanently.ports.Register(portIter.first)) @@ -910,7 +889,7 @@ eResult cDataPlane::initWorkers() controlPlane->slowWorker = worker; workers_vector.emplace_back(worker); - out_queues_++; + tx_queues_++; } for (const auto& configWorkerIter : config.workers) @@ -1039,7 +1018,7 @@ eResult cDataPlane::initWorkers() } } - basePermanently.outQueueId = out_queues_; + basePermanently.outQueueId = tx_queues_; dataplane::base::generation base; { @@ -1064,7 +1043,7 @@ eResult cDataPlane::initWorkers() workers[coreId] = worker; workers_vector.emplace_back(worker); - out_queues_++; + tx_queues_++; } worker_gc_t::PortToSocketArray port_to_socket; @@ -1194,14 +1173,14 @@ std::optional cDataPlane::getCounterValueByName(const std::string& cou return std::optional(counter_value); } -eResult cDataPlane::initQueues() +eResult cDataPlane::InitTxQueues() { for (const auto& portIter : ports) { const tPortId& portId = portIter.first; for (tQueueId queueId = 0; - queueId < workers.size(); + queueId < tx_queues_; queueId++) { int ret = rte_eth_tx_queue_setup(portId, @@ -1220,6 +1199,29 @@ eResult cDataPlane::initQueues() return eResult::success; } +eResult cDataPlane::InitRxQueues() +{ + for (const auto& worker : workers_vector) + { + for (const auto& [port, queue] : worker->basePermanently.rx_points) + { + int ret = rte_eth_rx_queue_setup(port, + queue, + getConfigValues().port_rx_queue_size, + worker->socketId, + nullptr, + worker->mempool); + if (ret < 0) + { + YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", port, queue, ret); + return eResult::errorInitQueue; + } + } + } + + return eResult::success; +} + eResult cDataPlane::initKniQueues() { for (auto& it : kni_interface_handles) diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 528e4374..ad97d310 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -128,7 +128,6 @@ class cDataPlane public: void StartInterfaces(); - void InitPortsBarrier(); protected: eResult InitControlPlane(); @@ -138,7 +137,8 @@ class cDataPlane eResult initGlobalBases(); eResult initWorkers(); eResult initKniQueues(); - eResult initQueues(); + eResult InitTxQueues(); + eResult InitRxQueues(); void init_worker_base(); eResult allocateSharedMemory(); @@ -182,7 +182,7 @@ class cDataPlane bool ///< symmetric_mode >> ports; - tQueueId out_queues_ = 0; + tQueueId tx_queues_ = 0; std::map workers; std::map worker_gcs; @@ -199,7 +199,6 @@ class cDataPlane rte_ring*>> ringPorts; - pthread_barrier_t initPortBarrier; pthread_barrier_t runBarrier; rte_mempool* mempool_log; diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 0c1d3123..e0beef3b 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -233,38 +233,12 @@ void cWorker::start() abort(); } - for (const auto& [port, queue]: basePermanently.rx_points) - { - rc = rte_eth_rx_queue_setup(port, - queue, - dataPlane->getConfigValues().port_rx_queue_size, - rte_eth_dev_socket_id(port), - nullptr, ///< @todo - mempool); - if (rc < 0) - { - YADECAP_LOG_ERROR("rte_eth_rx_queue_setup() = %d\n", rc); - abort(); - } - } - if (rte_mempool_default_cache(mempool, coreId)) { YADECAP_LOG_ERROR("mempool cache not empty\n"); abort(); } - rc = pthread_barrier_wait(&dataPlane->initPortBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(&dataPlane->initPortBarrier); - } - else if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_wait() = %d\n", rc); - abort(); - } - rc = pthread_barrier_wait(&dataPlane->runBarrier); if (rc == PTHREAD_BARRIER_SERIAL_THREAD) { From 52b3f620b329085012b4fdca2b9929d2aad7a74f Mon Sep 17 00:00:00 2001 From: vimes Date: Fri, 5 Jul 2024 19:43:16 +0300 Subject: [PATCH 058/195] Removes startup (runBarrier) synchronization Since all pre startup configuration is now done from dataplane there remains no reasons to synchronize workers at startup. rte_eal_mp_remote_launch is called when ethernet devices are configured and strted. This provides the only startup synchronization workers need. --- dataplane/controlplane.cpp | 108 +++++++++++--------------------- dataplane/dataplane.cpp | 124 ++++++++++++++++++++----------------- dataplane/dataplane.h | 6 +- dataplane/globalbase.cpp | 6 +- dataplane/report.cpp | 3 +- dataplane/worker.cpp | 11 ---- dataplane/worker_gc.cpp | 17 +---- dataplane/worker_gc.h | 2 +- 8 files changed, 112 insertions(+), 165 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 324d23cb..64106c97 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -74,36 +74,6 @@ eResult cControlPlane::init(bool use_kernel_interface) void cControlPlane::start() { - /// start devices - for (const auto& portIter : dataPlane->ports) - { - const tPortId& portId = portIter.first; - - int rc = rte_eth_dev_start(portId); - if (rc) - { - YADECAP_LOG_ERROR("can't start eth dev(%d, %d): %s\n", - rc, - rte_errno, - rte_strerror(rte_errno)); - abort(); - } - - rte_eth_promiscuous_enable(portId); - } - - auto rc = pthread_barrier_wait(&dataPlane->runBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(&dataPlane->runBarrier); - } - else if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_wait() = %d\n", rc); - /// @todo: stop - return; - } - mainThread(); } @@ -248,15 +218,12 @@ common::idp::getOtherStats::response cControlPlane::getOtherStats() /// workers { - for (const auto& iter : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - const tCoreId& coreId = iter.first; - const cWorker* worker = iter.second; - std::array bursts; memcpy(&bursts[0], worker->bursts, sizeof(worker->bursts)); - response_workers[coreId] = {bursts}; + response_workers[worker->coreId] = {bursts}; } } @@ -273,9 +240,21 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common { for (const auto& coreId : request) { - /// @todo: check coreId + const cWorker* worker; - const auto& worker = dataPlane->workers.find(coreId)->second; + if (auto it = dataPlane->workers.find(coreId); it != dataPlane->workers.end()) + { + worker = it->second; + } + if (!worker && coreId == dataPlane->config.controlPlaneCoreId) + { + worker = dataPlane->slow_worker; + } + if (!worker) + { + YANET_LOG_ERROR("Worker stats requested for unused core id (%d)\n", coreId); + continue; + } std::map portsStats; for (const auto& portIter : dataPlane->ports) @@ -292,7 +271,7 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common { /// all workers - for (const auto& [coreId, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { std::map portsStats; for (const auto& portIter : dataPlane->ports) @@ -300,9 +279,9 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common portsStats[portIter.first] = worker->statsPorts[portIter.first]; } - response[coreId] = {worker->iteration, - worker->stats, - portsStats}; + response[worker->coreId] = {worker->iteration, + worker->stats, + portsStats}; } } @@ -396,10 +375,8 @@ common::idp::get_ports_stats::response cControlPlane::get_ports_stats() } uint64_t physicalPort_egress_drops = 0; - for (const auto& [coreId, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)coreId; - physicalPort_egress_drops += worker->statsPorts[portId].physicalPort_egress_drops; } @@ -580,10 +557,8 @@ common::idp::getAclCounters::response cControlPlane::getAclCounters() common::idp::getAclCounters::response response; response.resize(YANET_CONFIG_ACL_COUNTERS_SIZE); - for (const auto& [coreId, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)coreId; - for (size_t i = 0; i < YANET_CONFIG_ACL_COUNTERS_SIZE; i++) { response[i] += worker->aclCounters[i]; @@ -647,9 +622,8 @@ common::idp::getCounters::response cControlPlane::getCounters(const common::idp: } uint64_t counter = 0; - for (const auto& [core_id, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)core_id; counter += worker->counters[counter_id]; } @@ -677,17 +651,14 @@ common::idp::getConfig::response cControlPlane::getConfig() const pci}; } - for (const auto& workerIter : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - const tCoreId& coreId = workerIter.first; - const cWorker* worker = workerIter.second; - for (const auto& endpoint : worker->basePermanently.rx_points) { - std::get<0>(response_workers[coreId]).emplace_back(endpoint.port); + std::get<0>(response_workers[worker->coreId]).emplace_back(endpoint.port); } - std::get<1>(response_workers[coreId]) = worker->socketId; + std::get<1>(response_workers[worker->coreId]) = worker->socketId; } /// @todo: worker_gcs @@ -1123,13 +1094,12 @@ common::idp::get_counter_by_name::response cControlPlane::get_counter_by_name(co } // core_id was not specified, return counter for each core_id - for (const auto& [core_id, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)worker; - std::optional counter_val = dataPlane->getCounterValueByName(counter_name, core_id); + std::optional counter_val = dataPlane->getCounterValueByName(counter_name, worker->coreId); if (counter_val.has_value()) { - response[core_id] = counter_val.value(); + response[worker->coreId] = counter_val.value(); } } @@ -1252,10 +1222,8 @@ void cControlPlane::switchBase() { YADECAP_MEMORY_BARRIER_COMPILE; - for (auto& iter : dataPlane->workers) + for (cWorker* worker : dataPlane->workers_vector) { - auto* worker = iter.second; - worker->currentBaseId ^= 1; } @@ -1272,9 +1240,8 @@ void cControlPlane::switchBase() YADECAP_MEMORY_BARRIER_COMPILE; - for (auto& iter : dataPlane->workers) + for (cWorker* worker : dataPlane->workers_vector) { - auto* worker = iter.second; auto& base = worker->bases[worker->currentBaseId]; auto& baseNext = worker->bases[worker->currentBaseId ^ 1]; @@ -1313,10 +1280,8 @@ void cControlPlane::waitAllWorkers() { YADECAP_MEMORY_BARRIER_COMPILE; - for (const auto& [core_id, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)core_id; - uint64_t startIteration = worker->iteration; uint64_t nextIteration = startIteration; while (nextIteration - startIteration <= (uint64_t)16) @@ -1401,9 +1366,8 @@ void cControlPlane::mainThread() for (unsigned hIter = 0; hIter < YANET_CONFIG_RING_PRIORITY_RATIO; hIter++) { unsigned hProcessed = 0; - for (const auto& iter : dataPlane->workers) + for (cWorker* worker : dataPlane->workers_vector) { - cWorker* worker = iter.second; hProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_highPriority); } if (!hProcessed) @@ -1413,9 +1377,8 @@ void cControlPlane::mainThread() } unsigned nProcessed = 0; - for (const auto& iter : dataPlane->workers) + for (cWorker* worker : dataPlane->workers_vector) { - cWorker* worker = iter.second; nProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_normalPriority); } if (!nProcessed) @@ -1423,9 +1386,8 @@ void cControlPlane::mainThread() break; } } - for (const auto& iter : dataPlane->workers) + for (cWorker* worker : dataPlane->workers_vector) { - cWorker* worker = iter.second; ring_handle(worker->ring_toFreePackets, worker->ring_lowPriority); } diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 34c4bbb7..39471c0f 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -178,11 +178,11 @@ eResult cDataPlane::init(const std::string& binaryPath, } /// sanity check - if (rte_lcore_count() != workers.size() + worker_gcs.size()) + if (rte_lcore_count() != workers.size() + worker_gcs.size() + 1) { YADECAP_LOG_ERROR("invalid cores count: %u != %lu\n", rte_lcore_count(), - workers.size()); + workers.size() + worker_gcs.size() + 1); return eResult::invalidCoresCount; } @@ -191,9 +191,8 @@ eResult cDataPlane::init(const std::string& binaryPath, std::set worker_sockets_used; std::set gc_sockets_used; - for (const auto& [core_id, worker] : workers) + for (const cWorker* const worker : workers_vector) { - (void)core_id; worker_sockets_used.emplace(worker->socketId); } @@ -249,14 +248,6 @@ eResult cDataPlane::init(const std::string& binaryPath, init_worker_base(); - /// init run sync barrier - auto rc = pthread_barrier_init(&runBarrier, nullptr, workers.size() + worker_gcs.size()); - if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_init() = %d\n", rc); - return eResult::errorInitBarrier; - } - return result; } @@ -885,7 +876,7 @@ eResult cDataPlane::initWorkers() worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[coreId]); - workers[coreId] = worker; + slow_worker = worker; controlPlane->slowWorker = worker; workers_vector.emplace_back(worker); @@ -1245,10 +1236,8 @@ eResult cDataPlane::initKniQueues() void cDataPlane::init_worker_base() { std::vector> base_nexts; - for (auto& [core_id, worker] : workers) + for (cWorker* worker : workers_vector) { - (void)core_id; - auto* base = &worker->bases[worker->currentBaseId]; auto* base_next = &worker->bases[worker->currentBaseId ^ 1]; base_nexts.emplace_back(worker->socketId, base); @@ -1278,10 +1267,8 @@ void cDataPlane::SWRateLimiterTimeTracker() if (std::chrono::duration_cast(curTimePointForSWRateLimiter - prevTimePointForSWRateLimiter) >= std::chrono::milliseconds(1000 / config.rateLimitDivisor)) { // the only place thread-shared variable icmpPacketsToSW is changed - for (auto& [coreId, worker] : workers) + for (cWorker* worker : workers_vector) { - (void)coreId; - __atomic_store_n(&worker->packetsToSWNPRemainder, config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); } @@ -1294,33 +1281,6 @@ void cDataPlane::SWRateLimiterTimeTracker() } } -int cDataPlane::lcoreThread(void* args) -{ - cDataPlane* dataPlane = (cDataPlane*)args; - - if (rte_lcore_id() == dataPlane->config.controlPlaneCoreId) - { - dataPlane->controlPlane->start(); - return 0; - } - - if (exist(dataPlane->workers, rte_lcore_id())) - { - dataPlane->workers[rte_lcore_id()]->start(); - } - else if (exist(dataPlane->worker_gcs, rte_lcore_id())) - { - dataPlane->worker_gcs[rte_lcore_id()]->start(&dataPlane->runBarrier); - } - else - { - YADECAP_LOG_ERROR("invalid core id: '%u'\n", rte_lcore_id()); - /// @todo: stop - } - - return 0; -} - void cDataPlane::timestamp_thread() { uint32_t prev_time = 0; @@ -1344,6 +1304,21 @@ void cDataPlane::timestamp_thread() } } +int cDataPlane::LcoreFunc(void* args) +{ + const auto& workloads = *reinterpret_cast>*>(args); + if (auto it = workloads.find(rte_lcore_id()); it != workloads.end()) + { + it->second(); + return 0; + } + else + { + YADECAP_LOG_ERROR("invalid core id: '%u'\n", rte_lcore_id()); + return -1; + } +} + void cDataPlane::start() { threads.emplace_back([this]() { @@ -1357,8 +1332,47 @@ void cDataPlane::start() bus.run(); - /// run forwarding plane and control plane - rte_eal_mp_remote_launch(lcoreThread, this, CALL_MAIN); + /// run forwarding plane + for (auto& [core, worker] : workers) + { + if (coreFunctions_.find(core) != coreFunctions_.end()) + { + YANET_LOG_ERROR("Worker: Multiple workloads assigned to core %d\n", core); + } + YANET_LOG_INFO("Worker assigned to core %d\n", core); + coreFunctions_.emplace(core, [worker]() { + worker->start(); + }); + } + + for (auto& [core, garbage_collector] : worker_gcs) + { + if (coreFunctions_.find(core) != coreFunctions_.end()) + { + YANET_LOG_ERROR("GC: Multiple workloads assigned to core %d\n", core); + } + YANET_LOG_INFO("GC assigned to core %d\n", core); + coreFunctions_.emplace(core, [garbage_collector]() { + garbage_collector->start(); + }); + } + + if (coreFunctions_.find(config.controlPlaneCoreId) != coreFunctions_.end()) + { + YANET_LOG_ERROR("CP: Multiple workloads assigned to core %d\n", config.controlPlaneCoreId); + } + YANET_LOG_INFO("Worker assigned to core %d\n", config.controlPlaneCoreId); + coreFunctions_.emplace(config.controlPlaneCoreId, [&]() { + controlPlane->start(); + }); + + StartInterfaces(); + + if (rte_eal_mp_remote_launch(LcoreFunc, this, CALL_MAIN)) + { + YANET_LOG_ERROR("Failed to launch workers: some of assigned lcores busy\n"); + abort(); + } } void cDataPlane::join() @@ -1523,7 +1537,7 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() } /// split memory per worker - for (auto& [core_id, worker] : workers) + for (cWorker* worker : workers_vector) { const auto& socket_id = worker->socketId; const auto& it = shm_by_socket_id.find(socket_id); @@ -1551,7 +1565,7 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() size += RTE_CACHE_LINE_SIZE - size % RTE_CACHE_LINE_SIZE; /// round up } - auto name = "shm_" + std::to_string(core_id) + "_" + std::to_string(ring_id); + auto name = "shm_" + std::to_string(worker->coreId) + "_" + std::to_string(ring_id); auto offset = offsets[shm]; @@ -1565,7 +1579,7 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() worker->dumpRings[ring_id] = ring; - auto meta = common::idp::get_shm_info::dump_meta(name, tag, unit_size, units_number, core_id, socket_id, key, offset); + auto meta = common::idp::get_shm_info::dump_meta(name, tag, unit_size, units_number, worker->coreId, socket_id, key, offset); dumps_meta.emplace_back(meta); tag_to_id[tag] = ring_id; @@ -1574,7 +1588,7 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() } } - for (auto& [core_id, worker] : workers) + for (cWorker* worker : workers_vector) { const auto& socket_id = worker->socketId; const auto& it = shm_by_socket_id.find(socket_id); @@ -1589,7 +1603,7 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() memset(worker->tsc_deltas, 0, sizeof(dataplane::perf::tsc_deltas)); offsets[shm] += sizeof(dataplane::perf::tsc_deltas); - auto meta = common::idp::get_shm_tsc_info::tsc_meta(core_id, socket_id, key, offset); + auto meta = common::idp::get_shm_tsc_info::tsc_meta(worker->coreId, socket_id, key, offset); tscs_meta.emplace_back(meta); } @@ -1708,10 +1722,8 @@ void cDataPlane::switch_worker_base() /// collect all base_next std::vector> base_nexts; - for (auto& [core_id, worker] : workers) + for (cWorker* worker : workers_vector) { - (void)core_id; - auto* base_next = &worker->bases[worker->currentBaseId ^ 1]; base_nexts.emplace_back(worker->socketId, base_next); } diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index ad97d310..66acad9a 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -126,6 +126,9 @@ class cDataPlane eResult initEal(const std::string& binaryPath, const std::string& filePrefix); eResult initPorts(); + std::map> coreFunctions_; + static int LcoreFunc(void* args); + public: void StartInterfaces(); @@ -185,6 +188,7 @@ class cDataPlane tQueueId tx_queues_ = 0; std::map workers; std::map worker_gcs; + cWorker* slow_worker; std::mutex currentGlobalBaseId_mutex; uint8_t currentGlobalBaseId; @@ -199,8 +203,6 @@ class cDataPlane rte_ring*>> ringPorts; - pthread_barrier_t runBarrier; - rte_mempool* mempool_log; common::idp::get_shm_info::response dumps_meta; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 68cf9801..c7e53e9f 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -1538,9 +1538,8 @@ eResult generation::update_balancer_services(const common::idp::updateGlobalBase for (tCounterId i = 0; i < (tCounterId)::balancer::real_counter::size; ++i) { uint64_t sum_worker = 0, sum_gc = 0; - for (const auto& [core_id, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)core_id; sum_worker += worker->counters[counter_id + i]; } for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) @@ -1625,9 +1624,8 @@ inline uint64_t generation::count_real_connections(uint32_t counter_id) { uint64_t sessions_created = 0; uint64_t sessions_destroyed = 0; - for (const auto& [core_id, worker] : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - (void)core_id; sessions_created += worker->counters[counter_id + (tCounterId)::balancer::real_counter::sessions_created]; sessions_destroyed += worker->counters[counter_id + (tCounterId)::balancer::real_counter::sessions_destroyed]; } diff --git a/dataplane/report.cpp b/dataplane/report.cpp index fbab5cb0..128e4798 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -69,9 +69,8 @@ nlohmann::json cReport::getReport() { nlohmann::json jsonReport; - for (const auto& iter : dataPlane->workers) + for (const cWorker* worker : dataPlane->workers_vector) { - const cWorker* worker = iter.second; jsonReport["workers"].emplace_back(convertWorker(worker)); } diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index e0beef3b..d7d017a8 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -239,17 +239,6 @@ void cWorker::start() abort(); } - rc = pthread_barrier_wait(&dataPlane->runBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(&dataPlane->runBarrier); - } - else if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_wait() = %d\n", rc); - abort(); - } - for (unsigned int mbuf_i = 0; mbuf_i < mbufs_count; mbuf_i++) diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 8d255167..92849dee 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -114,23 +114,8 @@ eResult worker_gc_t::init(const tCoreId& core_id, return dpdk::RingConn{std::move(rs.value()), std::move(rf.value())}; } -void worker_gc_t::start(pthread_barrier_t* runBarrier) +void worker_gc_t::start() { - /// @todo: prepare - - int rc; - - rc = pthread_barrier_wait(runBarrier); - if (rc == PTHREAD_BARRIER_SERIAL_THREAD) - { - pthread_barrier_destroy(runBarrier); - } - else if (rc != 0) - { - YADECAP_LOG_ERROR("pthread_barrier_wait() = %d\n", rc); - abort(); - } - thread(); } diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index 58ea89a6..02e16cfd 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -22,7 +22,7 @@ class worker_gc_t ~worker_gc_t(); eResult init(const tCoreId& core_id, const tSocketId& socket_id, const dataplane::base::permanently& base_permanently, const dataplane::base::generation& base); - void start(pthread_barrier_t* runBarrier); + void start(); void run_on_this_thread(const std::function& callback); void nat64stateful_state(const common::idp::nat64stateful_state::request& request, common::idp::nat64stateful_state::response& response); From ac96522427d9923c224f5553ffdc957d3f7d86b4 Mon Sep 17 00:00:00 2001 From: vimes Date: Fri, 16 Aug 2024 16:48:46 +0300 Subject: [PATCH 059/195] Adds guarding mutex access --- dataplane/controlplane.cpp | 99 +++++++++++++++++++++----------------- dataplane/controlplane.h | 20 +++++--- dataplane/globalbase.cpp | 5 +- dataplane/utils.h | 17 +++++++ 4 files changed, 87 insertions(+), 54 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 64106c97..adb9bee8 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -1036,34 +1036,32 @@ common::idp::balancer_real_connections::response cControlPlane::balancer_real_co eResult cControlPlane::unrdup_vip_to_balancers(const common::idp::unrdup_vip_to_balancers::request& request) { - std::lock_guard guard(unrdup_mutex); + return vip_to_balancers.apply([&](auto& vtb) { + uint32_t balancer_id = std::get<0>(request); - uint32_t balancer_id = std::get<0>(request); - - if (vip_to_balancers.size() <= balancer_id) - { - vip_to_balancers.resize(balancer_id + 1); - } - - vip_to_balancers[balancer_id] = std::get<1>(request); + if (vtb.size() <= balancer_id) + { + vtb.resize(balancer_id + 1); + } - return eResult::success; + vtb[balancer_id] = std::get<1>(request); + return eResult::success; + }); } eResult cControlPlane::update_vip_vport_proto(const common::idp::update_vip_vport_proto::request& request) { - std::lock_guard guard(vip_vport_proto_mutex); - - uint32_t balancer_id = std::get<0>(request); - - if (vip_vport_proto.size() <= balancer_id) - { - vip_vport_proto.resize(balancer_id + 1); - } + return vip_vport_proto.apply([&](auto& vvp) { + uint32_t balancer_id = std::get<0>(request); - vip_vport_proto[balancer_id] = std::get<1>(request); + if (vvp.size() <= balancer_id) + { + vvp.resize(balancer_id + 1); + } - return eResult::success; + vvp[balancer_id] = std::get<1>(request); + return eResult::success; + }); } common::idp::version::response cControlPlane::version() @@ -1865,15 +1863,17 @@ bool cControlPlane::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) } tAclId aclId; + if (!dataPlane->controlPlane->fw_state_multicast_acl_ids.apply([&](auto& fw_state_multicast_acl_ids) { + auto it = fw_state_multicast_acl_ids.find(common::ipv6_address_t(ipv6Header->dst_addr)); + if (it == fw_state_multicast_acl_ids.end()) + { + return false; + } + aclId = it->second; + return true; + })) { - std::lock_guard lock(fw_state_multicast_acl_ids_mutex); - auto it = fw_state_multicast_acl_ids.find(common::ipv6_address_t(ipv6Header->dst_addr)); - if (it == std::end(fw_state_multicast_acl_ids)) - { - return false; - } - - aclId = it->second; + return false; } const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; @@ -2063,24 +2063,11 @@ bool cControlPlane::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) return true; } -void cControlPlane::handlePacket_balancer_icmp_forward(rte_mbuf* mbuf) +void cControlPlane::BalancerICMPForwardCriticalSection( + rte_mbuf* mbuf, + cControlPlane::VipToBalancers& vip_to_balancers, + cControlPlane::VipVportProto& vip_vport_proto) { - if (dataPlane->config.SWICMPOutRateLimit != 0) - { - if (icmpOutRemainder == 0) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached]++; - rte_pktmbuf_free(mbuf); - return; - } - - --icmpOutRemainder; - } - - std::lock_guard unrdup_guard(unrdup_mutex); - std::lock_guard interfaces_ips_guard(interfaces_ips_mutex); - std::lock_guard services_guard(vip_vport_proto_mutex); - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -2314,6 +2301,28 @@ void cControlPlane::handlePacket_balancer_icmp_forward(rte_mbuf* mbuf) slowWorker->preparePacket(mbuf_clone); sendPacketToSlowWorker(mbuf_clone, flow); } +} + + +void cControlPlane::handlePacket_balancer_icmp_forward(rte_mbuf* mbuf) +{ + if (dataPlane->config.SWICMPOutRateLimit != 0) + { + if (icmpOutRemainder == 0) + { + slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached]++; + rte_pktmbuf_free(mbuf); + return; + } + + --icmpOutRemainder; + } + + dataPlane->controlPlane->vip_to_balancers.apply([&](auto& vip_to_balancers) { + dataPlane->controlPlane->vip_vport_proto.apply([&](auto& vip_vport_proto) { + BalancerICMPForwardCriticalSection(mbuf, vip_to_balancers, vip_vport_proto); + }); + }); // packet itself is not going anywhere, only its clones with prepended header rte_pktmbuf_free(mbuf); diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 1f9bf553..01dce02b 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -18,12 +18,13 @@ #include "common/static_vector.h" #include "common/type.h" -#include "dregress.h" #include "dpdk.h" +#include "dregress.h" #include "fragmentation.h" #include "kernel_interface_handle.h" #include "slow_worker.h" #include "type.h" +#include "utils.h" class cControlPlane ///< @todo: move to cDataPlane { @@ -99,6 +100,12 @@ class cControlPlane ///< @todo: move to cDataPlane void handlePacket_farm(rte_mbuf* mbuf); void handlePacket_fw_state_sync(rte_mbuf* mbuf); bool handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf); + using VipToBalancers = std::vector>>; + using VipVportProto = std::vector, uint8_t>>>; + void BalancerICMPForwardCriticalSection( + rte_mbuf* mbuf, + VipToBalancers& vip_to_balancers, + VipVportProto& vip_vport_proto); void handlePacket_balancer_icmp_forward(rte_mbuf* mbuf); void handlePacket_dump(rte_mbuf* mbuf); @@ -128,9 +135,6 @@ class cControlPlane ///< @todo: move to cDataPlane std::mutex mutex; std::mutex balancer_mutex; - std::mutex unrdup_mutex; - std::mutex interfaces_ips_mutex; - std::mutex vip_vport_proto_mutex; rte_mempool* mempool; bool use_kernel_interface; @@ -172,12 +176,14 @@ class cControlPlane ///< @todo: move to cDataPlane common::globalBase::tFlow>> slowWorkerMbufs; std::mutex fw_state_multicast_acl_ids_mutex; - std::map fw_state_multicast_acl_ids; + using FwStateMulticastAclIds = std::map; + utils::Sequential fw_state_multicast_acl_ids; // provided by unrdup.cfg, used to clone some icmp packets to neighbor balancers, index is balancer_id - std::vector>> vip_to_balancers; + utils::Sequential vip_to_balancers; + // check presence prior to cloning - std::vector, uint8_t>>> vip_vport_proto; + utils::Sequential vip_vport_proto; std::chrono::high_resolution_clock::time_point prevTimePointForSWRateLimiter; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index c7e53e9f..ce4ae75c 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -2454,8 +2454,9 @@ eResult generation::fwstate_synchronization_update(const common::idp::updateGlob fw_state_multicast_acl_ids.emplace(multicastIpv6Address, aclId); } - std::lock_guard lock(dataPlane->controlPlane->fw_state_multicast_acl_ids_mutex); - std::swap(dataPlane->controlPlane->fw_state_multicast_acl_ids, fw_state_multicast_acl_ids); + dataPlane->controlPlane->fw_state_multicast_acl_ids.apply([&](auto& fsm_ids) { + std::swap(fsm_ids, fw_state_multicast_acl_ids); + }); return eResult::success; } diff --git a/dataplane/utils.h b/dataplane/utils.h index fffef6d8..d8e8afae 100644 --- a/dataplane/utils.h +++ b/dataplane/utils.h @@ -1,4 +1,6 @@ #pragma once +#include + #include #include "common/config.h" @@ -45,4 +47,19 @@ class RoundRobinIterator } }; +template +class Sequential +{ + std::mutex mutex_; + T data_; + +public: + template + auto apply(F func) + { + std::lock_guard lock(mutex_); + return func(data_); + } +}; + } // namespace utils \ No newline at end of file From 311aca6e010aa77248bc5d4685a7fceb118591a4 Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 2 Jul 2024 14:07:26 +0300 Subject: [PATCH 060/195] Multiple slow workers. --- common/type.h | 13 + dataplane/bus.cpp | 2 +- dataplane/controlplane.cpp | 1308 ++++-------------------------------- dataplane/controlplane.h | 114 ++-- dataplane/dataplane.cpp | 384 +++++++---- dataplane/dataplane.h | 28 +- dataplane/dpdk.h | 1 + dataplane/globalbase.cpp | 71 +- dataplane/report.cpp | 54 +- dataplane/slow_worker.cpp | 983 ++++++++++++++++++++++++++- dataplane/slow_worker.h | 144 +++- dataplane/work_runner.h | 71 ++ dataplane/worker.h | 14 +- 13 files changed, 1732 insertions(+), 1455 deletions(-) create mode 100644 dataplane/work_runner.h diff --git a/common/type.h b/common/type.h index b53566c9..6c7276da 100644 --- a/common/type.h +++ b/common/type.h @@ -2556,6 +2556,19 @@ struct stats_t uint64_t slowworker_drops; uint64_t mempool_is_empty; uint64_t unknown_dump_interface; + + stats_t& operator+=(const stats_t& b) + { + repeat_packets += b.repeat_packets; + tofarm_packets += b.tofarm_packets; + farm_packets += b.farm_packets; + fwsync_multicast_ingress_packets += b.fwsync_multicast_ingress_packets; + slowworker_packets += b.slowworker_packets; + slowworker_drops += b.slowworker_drops; + mempool_is_empty += b.mempool_is_empty; + unknown_dump_interface += b.unknown_dump_interface; + return *this; + } }; } diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 47df25cd..4b880b77 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -212,7 +212,7 @@ void cBus::clientThread(int clientSocket) } else if (type == common::idp::requestType::getSlowWorkerStats) { - response = callWithResponse(&cControlPlane::getSlowWorkerStats, request); + response = callWithResponse(&cControlPlane::SlowWorkerStatsResponse, request); } else if (type == common::idp::requestType::get_worker_gc_stats) { diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index adb9bee8..4808cf31 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -11,6 +11,7 @@ #include "common/fallback.h" #include "common/idp.h" +#include "common/type.h" #include "common/version.h" #include "checksum.h" @@ -27,56 +28,20 @@ cControlPlane::cControlPlane(cDataPlane* dataPlane) : dataPlane(dataPlane), - fragmentation_( - [this](rte_mbuf* pkt, const common::globalBase::tFlow& flow) { - sendPacketToSlowWorker(pkt, flow); - }, - dataPlane->getConfigValues().fragmentation), - slow_(this), - dregress(&slow_, - dataPlane, - dataPlane->getConfigValues().gc_step), - mempool(nullptr), - use_kernel_interface(false), - slowWorker(nullptr) + use_kernel_interface(false) { memset(&stats, 0, sizeof(stats)); } -cControlPlane::~cControlPlane() -{ - if (mempool) - { - rte_mempool_free(mempool); - } -} - eResult cControlPlane::init(bool use_kernel_interface) { this->use_kernel_interface = use_kernel_interface; eResult result = eResult::success; - /// init mempool for kernel interfaces and slow worker - result = initMempool(); - if (result != eResult::success) - { - return result; - } - - gc_step = dataPlane->getConfigValues().gc_step; - dregress.gc_step = gc_step; - - icmpOutRemainder = dataPlane->config.SWICMPOutRateLimit / dataPlane->config.rateLimitDivisor; - return result; } -void cControlPlane::start() -{ - mainThread(); -} - common::idp::updateGlobalBase::response cControlPlane::updateGlobalBase(const common::idp::updateGlobalBase::request& request) { std::lock_guard guard(mutex); @@ -236,35 +201,41 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common common::idp::getWorkerStats::response response; - if (request.size()) + auto add_stats_to_response = [this, &response](tCoreId coreId, const cWorker* worker) { + std::map portsStats; + for (const auto& portIter : dataPlane->ports) + { + portsStats[portIter.first] = worker->statsPorts[portIter.first]; + } + + response[coreId] = {worker->iteration, + worker->stats, + portsStats}; + }; + + if (!request.empty()) { for (const auto& coreId : request) { const cWorker* worker; - if (auto it = dataPlane->workers.find(coreId); it != dataPlane->workers.end()) { worker = it->second; } - if (!worker && coreId == dataPlane->config.controlPlaneCoreId) + if (!worker) { - worker = dataPlane->slow_worker; + if (auto slow = dataPlane->slow_workers.find(coreId); slow != dataPlane->slow_workers.end()) + { + worker = slow->second->GetWorker(); + } } if (!worker) { - YANET_LOG_ERROR("Worker stats requested for unused core id (%d)\n", coreId); + YANET_LOG_ERROR("Worker stats requested for non-worker core id (%d)\n", coreId); continue; } - std::map portsStats; - for (const auto& portIter : dataPlane->ports) - { - portsStats[portIter.first] = worker->statsPorts[portIter.first]; - } - - response[coreId] = {worker->iteration, - worker->stats, - portsStats}; + add_stats_to_response(coreId, worker); } } else @@ -273,29 +244,39 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common for (const cWorker* worker : dataPlane->workers_vector) { - std::map portsStats; - for (const auto& portIter : dataPlane->ports) - { - portsStats[portIter.first] = worker->statsPorts[portIter.first]; - } - - response[worker->coreId] = {worker->iteration, - worker->stats, - portsStats}; + add_stats_to_response(worker->coreId, worker); } } return response; } -common::idp::getSlowWorkerStats::response cControlPlane::getSlowWorkerStats() +const std::vector& cControlPlane::workers_vector() const +{ + return dataPlane->workers_vector; +} + +const std::map& cControlPlane::slow_workers() const +{ + return dataPlane->slow_workers; +} + +common::slowworker::stats_t cControlPlane::SlowWorkerStats() const +{ + return accumulateSlowWorkerStats( + [](dataplane::SlowWorker* worker) { + return worker->Stats(); + }); +} + +common::idp::getSlowWorkerStats::response cControlPlane::SlowWorkerStatsResponse() { /// unsafe common::idp::getSlowWorkerStats::response response; auto& [slowworker_stats, hashtable_gc_stats] = response; - slowworker_stats = stats; + slowworker_stats = SlowWorkerStats(); /// @todo // hashtable_gc_stats.emplace_back(slowWorker->socketId, // "dregress", @@ -352,11 +333,19 @@ common::idp::get_worker_gc_stats::response cControlPlane::get_worker_gc_stats() common::idp::get_dregress_counters::response cControlPlane::get_dregress_counters() { - auto guard = dregress.LockCounters(); + common::dregress::counters_t counters_v4; + common::dregress::counters_t counters_v6; + for (auto it : dataPlane->slow_workers) + { + dregress_t& dregress = it.second->Dregress(); + auto guard = dregress.LockCounters(); + counters_v4.merge(dregress.Counters4()); + counters_v6.merge(dregress.Counters6()); + dregress.ClearCounters(); + } common::stream_out_t stream; - dregress.Counters4().push(stream); - dregress.Counters6().push(stream); - dregress.ClearCounters(); + counters_v4.push(stream); + counters_v6.push(stream); return stream.getBuffer(); } @@ -374,11 +363,10 @@ common::idp::get_ports_stats::response cControlPlane::get_ports_stats() rte_eth_stats_get(portId, &stats); } - uint64_t physicalPort_egress_drops = 0; - for (const cWorker* worker : dataPlane->workers_vector) - { - physicalPort_egress_drops += worker->statsPorts[portId].physicalPort_egress_drops; - } + uint64_t physicalPort_egress_drops = accumulateWorkerStats( + [portId](cWorker* worker) { + return worker->statsPorts[portId].physicalPort_egress_drops; + }); response[portId] = {stats.ipackets, stats.ibytes, @@ -416,17 +404,21 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo common::idp::getControlPlanePortStats::response response; - const auto& portmapper = slowWorker->basePermanently.ports; + if (!use_kernel_interface) + { + return response; + } if (request.size()) { for (const auto& portId : request) { - if ((!use_kernel_interface) || (!portmapper.ValidDpdk(portId))) + const auto& maybe_stats = KniStats(portId); + if (!maybe_stats) { YANET_LOG_ERROR("Controlplane statistics requested for invalid port id ( %u )", portId); } - const auto& stats = kernel_stats[portmapper.ToLogical(portId)]; + const dataplane::sKniStats& stats = maybe_stats.value(); response[portId] = {stats.ipackets, stats.ibytes, @@ -441,21 +433,21 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo else { /// all ports - if (use_kernel_interface) + for (auto it : dataPlane->slow_workers) { - for (tPortId i = 0; i < portmapper.size(); ++i) + const auto& kni_worker = it.second->KniWorker(); + + auto stats = kni_worker.PortsStats().first; + for (auto [current, end] = kni_worker.PortsIds(); current != end; ++current, ++stats) { - const auto& stats = kernel_stats[i]; - const auto& portId = portmapper.ToDpdk(i); - - response[portId] = {stats.ipackets, - stats.ibytes, - 0, - stats.idropped, - stats.opackets, - stats.obytes, - 0, - stats.odropped}; + response[*current] = {stats->ipackets, + stats->ibytes, + 0, + stats->idropped, + stats->opackets, + stats->obytes, + 0, + stats->odropped}; } } } @@ -463,19 +455,49 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo return response; } -common::idp::getFragmentationStats::response cControlPlane::getFragmentationStats() +common::idp::getFragmentationStats::response cControlPlane::getFragmentationStats() const { - return fragmentation_.getStats(); + return accumulateSlowWorkerStats( + [](dataplane::SlowWorker* worker) { + return worker->Fragmentation().getStats(); + }); } common::dregress::stats_t cControlPlane::DregressStats() const { - return dregress.Stats(); + return accumulateSlowWorkerStats( + [](dataplane::SlowWorker* worker) { + return worker->Dregress().Stats(); + }); +} + +std::optional> cControlPlane::KniStats(tPortId pid) const +{ + // Dumb iteration over slow workers and their assigned ports, should not be a bottleneck + for (auto it : dataPlane->slow_workers) + { + if (const auto& stats = it.second->KniWorker().PortStats(pid)) + { + return stats; + } + } + return std::nullopt; } dataplane::hashtable_chain_spinlock_stats_t cControlPlane::DregressConnectionsStats() const { - return dregress.Connections()->stats(); + return accumulateSlowWorkerStats( + [](dataplane::SlowWorker* worker) { + return worker->Dregress().Connections()->stats(); + }); +} + +dregress::LimitsStats cControlPlane::DregressLimitsStats() const +{ + return accumulateSlowWorkerStats( + [](dataplane::SlowWorker* worker) { + return worker->Dregress().limits(); + }); } common::idp::getFWState::response cControlPlane::getFWState() @@ -621,13 +643,10 @@ common::idp::getCounters::response cControlPlane::getCounters(const common::idp: continue; } - uint64_t counter = 0; - for (const cWorker* worker : dataPlane->workers_vector) - { - counter += worker->counters[counter_id]; - } - - response[i] = counter; + response[i] = accumulateWorkerStats( + [counter_id](cWorker* worker) { + return worker->counters[counter_id]; + }); } return response; @@ -892,7 +911,7 @@ common::idp::limits::response cControlPlane::limits() worker_gc->limits(response); } - auto dregress = this->dregress.limits(); + auto dregress = DregressLimitsStats(); limit_insert(response, "dregress.ht.keys", @@ -1305,12 +1324,6 @@ void cControlPlane::waitAllWorkers() YADECAP_MEMORY_BARRIER_COMPILE; } -eResult cControlPlane::initMempool() -{ - mempool = dataPlane->socket_cplane_mempools[rte_lcore_to_socket_id(dataPlane->config.controlPlaneCoreId)]; - return eResult::success; -} - void cControlPlane::flush_kernel_interface(KniPortData& port_data, sKniStats& stats) { @@ -1349,1088 +1362,3 @@ void cControlPlane::flush_kernel_interface(KniPortData& port_data) port_data.mbufs_count = 0; } - -void cControlPlane::mainThread() -{ - rte_mbuf* operational[CONFIG_YADECAP_MBUFS_BURST_SIZE]; - - for (;;) - { - slowWorker->slowWorkerBeforeHandlePackets(); - - /// dequeue packets from worker's rings - for (unsigned nIter = 0; nIter < YANET_CONFIG_RING_PRIORITY_RATIO; nIter++) - { - for (unsigned hIter = 0; hIter < YANET_CONFIG_RING_PRIORITY_RATIO; hIter++) - { - unsigned hProcessed = 0; - for (cWorker* worker : dataPlane->workers_vector) - { - hProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_highPriority); - } - if (!hProcessed) - { - break; - } - } - - unsigned nProcessed = 0; - for (cWorker* worker : dataPlane->workers_vector) - { - nProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_normalPriority); - } - if (!nProcessed) - { - break; - } - } - for (cWorker* worker : dataPlane->workers_vector) - { - ring_handle(worker->ring_toFreePackets, worker->ring_lowPriority); - } - - if (use_kernel_interface) - { - for (int i = 0; i < slowWorker->basePermanently.ports.size(); ++i) - { - flush_kernel_interface(kernel_interfaces[i], kernel_stats[i]); - flush_kernel_interface(in_dump_kernel_interfaces[i]); - flush_kernel_interface(out_dump_kernel_interfaces[i]); - flush_kernel_interface(drop_dump_kernel_interfaces[i]); - } - } - - /// dequeue packets from worker_gc's ring to slowworker - rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; - unsigned rxSize; - for (auto& gc : to_gcs_) - { - rxSize = gc.process.DequeueBurstSC(mbufs); - for (uint16_t mbuf_i = 0; mbuf_i < rxSize; mbuf_i++) - { - rte_mbuf* mbuf = convertMempool(gc.free._Underlying(), mbufs[mbuf_i]); - if (!mbuf) - { - continue; - } - - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - sendPacketToSlowWorker(mbuf, metadata->flow); - } - } - - fragmentation_.handle(); - dregress.handle(); - - if (use_kernel_interface) - { - /// recv packets from kernel interface and send to physical port - for (int i = 0; i < slowWorker->basePermanently.ports.size(); ++i) - { - auto kernel_port_id = kernel_interfaces[i].kernel_port_id; - - unsigned rxSize = rte_eth_rx_burst(kernel_port_id, - 0, - operational, - CONFIG_YADECAP_MBUFS_BURST_SIZE); - uint64_t bytes = 0; - for (uint16_t i = 0; i < rxSize; ++i) - { - bytes += rte_pktmbuf_pkt_len(operational[i]); - } - uint16_t txSize = rte_eth_tx_burst(slowWorker->basePermanently.ports.ToDpdk(i), - 0, - operational, - rxSize); - for (auto i = rxSize; i < txSize; ++i) - { - bytes -= rte_pktmbuf_pkt_len(operational[i]); - } - auto to_drop = rxSize - txSize; - rte_pktmbuf_free_bulk(operational + txSize, to_drop); - sKniStats& stats = kernel_stats[i]; - stats.odropped += to_drop; - stats.opackets += txSize; - stats.obytes += bytes; - } - - /// recv from in.X/out.X/drop.X interfaces and free packets - for (int i = 0; i < slowWorker->basePermanently.ports.size(); ++i) - { - unsigned rxSize; - rxSize = rte_eth_rx_burst(in_dump_kernel_interfaces[i].kernel_port_id, - 0, - operational, - CONFIG_YADECAP_MBUFS_BURST_SIZE); - rte_pktmbuf_free_bulk(operational, rxSize); - - rxSize = rte_eth_rx_burst(out_dump_kernel_interfaces[i].kernel_port_id, - 0, - operational, - CONFIG_YADECAP_MBUFS_BURST_SIZE); - rte_pktmbuf_free_bulk(operational, rxSize); - - rxSize = rte_eth_rx_burst(drop_dump_kernel_interfaces[i].kernel_port_id, - 0, - operational, - CONFIG_YADECAP_MBUFS_BURST_SIZE); - rte_pktmbuf_free_bulk(operational, rxSize); - } - } - - /// push packets to slow worker - while (!slowWorkerMbufs.empty()) - { - for (unsigned int i = 0; - i < CONFIG_YADECAP_MBUFS_BURST_SIZE; - i++) - { - if (slowWorkerMbufs.empty()) - { - break; - } - - auto& tuple = slowWorkerMbufs.front(); - slowWorker->slowWorkerFlow(std::get<0>(tuple), std::get<1>(tuple)); - - slowWorkerMbufs.pop(); - } - - slowWorker->slowWorkerHandlePackets(); - } - - slowWorker->slowWorkerAfterHandlePackets(); - - /// @todo: AUTOTEST_CONTROLPLANE - - std::this_thread::yield(); - -#ifdef CONFIG_YADECAP_AUTOTEST - std::this_thread::sleep_for(std::chrono::microseconds{1}); -#endif // CONFIG_YADECAP_AUTOTEST - } -} - -unsigned cControlPlane::ring_handle(rte_ring* ring_to_free_mbuf, - rte_ring* ring) -{ - rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; - - unsigned rxSize = rte_ring_sc_dequeue_burst(ring, - (void**)mbufs, - CONFIG_YADECAP_MBUFS_BURST_SIZE, - nullptr); - -#ifdef CONFIG_YADECAP_AUTOTEST - if (rxSize) - { - std::this_thread::sleep_for(std::chrono::microseconds{400}); - } -#endif // CONFIG_YADECAP_AUTOTEST - - for (uint16_t mbuf_i = 0; mbuf_i < rxSize; mbuf_i++) - { - rte_mbuf* mbuf = convertMempool(ring_to_free_mbuf, mbufs[mbuf_i]); - if (!mbuf) - { - continue; - } - - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_ingress_icmp) - { - handlePacket_icmp_translate_v6_to_v4(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_ingress_fragmentation) - { - metadata->flow.type = common::globalBase::eFlowType::nat64stateless_ingress_checked; - handlePacket_fragment(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_icmp) - { - handlePacket_icmp_translate_v4_to_v6(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_fragmentation) - { - metadata->flow.type = common::globalBase::eFlowType::nat64stateless_egress_checked; - handlePacket_fragment(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_dregress) - { - handlePacket_dregress(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_farm) - { - handlePacket_farm(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_dump) - { - handlePacket_dump(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_repeat) - { - handlePacket_repeat(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_fw_sync) - { - handlePacket_fw_state_sync(mbuf); - } - else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_balancer_icmp_forward) - { - handlePacket_balancer_icmp_forward(mbuf); - } - else - { - handlePacketFromForwardingPlane(mbuf); - } - } - return rxSize; -} - -void cControlPlane::handlePacketFromForwardingPlane(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - if (handlePacket_fw_state_sync_ingress(mbuf)) - { - stats.fwsync_multicast_ingress_packets++; - rte_pktmbuf_free(mbuf); - return; - } - -#ifdef CONFIG_YADECAP_AUTOTEST - if (metadata->flow.type != common::globalBase::eFlowType::slowWorker_kni_local) - { - // drop by default in tests - stats.slowworker_drops++; - rte_pktmbuf_free(mbuf); - return; - } - rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, rte_ether_hdr*); - memset(ethernetHeader->dst_addr.addr_bytes, - 0x71, - 6); - -#endif - - if (!use_kernel_interface) - { - // TODO stats - unsigned txSize = rte_eth_tx_burst(metadata->fromPortId, 0, &mbuf, 1); - if (!txSize) - { - rte_pktmbuf_free(mbuf); - } - return; - } - else - { - const auto& portmapper = slowWorker->basePermanently.ports; - - auto& iface = kernel_interfaces[portmapper.ToLogical(metadata->fromPortId)]; - if (iface.mbufs_count == CONFIG_YADECAP_MBUFS_BURST_SIZE) - { - flush_kernel_interface(iface, kernel_stats[portmapper.ToLogical(metadata->fromPortId)]); - } - iface.mbufs[iface.mbufs_count++] = mbuf; - } -} - -void cControlPlane::handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; - const auto& translation = base.globalBase->nat64statelessTranslations[metadata->flow.data.nat64stateless.translationId]; - - slowWorker->slowWorkerTranslation(mbuf, nat64stateless, translation, true); - - if (dataplane::do_icmp_translate_v6_to_v4(mbuf, translation)) - { - slowWorker->stats.nat64stateless_ingressPackets++; - sendPacketToSlowWorker(mbuf, nat64stateless.flow); - } - else - { - slowWorker->stats.nat64stateless_ingressUnknownICMP++; - rte_pktmbuf_free(mbuf); - } -} - -void cControlPlane::handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; - const auto& translation = base.globalBase->nat64statelessTranslations[metadata->flow.data.nat64stateless.translationId]; - - slowWorker->slowWorkerTranslation(mbuf, nat64stateless, translation, false); - - if (dataplane::do_icmp_translate_v4_to_v6(mbuf, translation)) - { - slowWorker->stats.nat64stateless_egressPackets++; - sendPacketToSlowWorker(mbuf, nat64stateless.flow); - } - else - { - slowWorker->stats.nat64stateless_egressUnknownICMP++; - rte_pktmbuf_free(mbuf); - } -} - -void cControlPlane::handlePacket_dregress(rte_mbuf* mbuf) -{ - dregress.insert(mbuf); -} - -void cControlPlane::handlePacket_repeat(rte_mbuf* mbuf) -{ - const rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, rte_ether_hdr*); - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) - { - const rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); - - metadata->flow.data.logicalPortId = CALCULATE_LOGICALPORT_ID(metadata->fromPortId, rte_be_to_cpu_16(vlanHeader->vlan_tci)); - } - else - { - metadata->flow.data.logicalPortId = CALCULATE_LOGICALPORT_ID(metadata->fromPortId, 0); - } - - /// @todo: opt - slowWorker->preparePacket(mbuf); - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& logicalPort = base.globalBase->logicalPorts[metadata->flow.data.logicalPortId]; - - stats.repeat_packets++; - sendPacketToSlowWorker(mbuf, logicalPort.flow); -} - -void cControlPlane::handlePacket_fragment(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; - - if (nat64stateless.defrag_farm_prefix.empty() || metadata->network_headerType != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) || nat64stateless.farm) - { - fragmentation_.insert(mbuf); - return; - } - - stats.tofarm_packets++; - slowWorker->slowWorkerHandleFragment(mbuf); - sendPacketToSlowWorker(mbuf, nat64stateless.flow); -} - -void cControlPlane::handlePacket_farm(rte_mbuf* mbuf) -{ - stats.farm_packets++; - slowWorker->slowWorkerFarmHandleFragment(mbuf); -} - -void cControlPlane::handlePacket_fw_state_sync(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& fw_state_config = base.globalBase->fw_state_sync_configs[metadata->flow.data.aclId]; - - metadata->network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); - metadata->network_headerOffset = sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr); - metadata->transport_headerType = IPPROTO_UDP; - metadata->transport_headerOffset = metadata->network_headerOffset + sizeof(rte_ipv6_hdr); - - generic_rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, generic_rte_ether_hdr*); - ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); - rte_ether_addr_copy(&fw_state_config.ether_address_destination, ðernetHeader->dst_addr); - - rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); - vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); - - rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); - ipv6Header->vtc_flow = rte_cpu_to_be_32(0x6 << 28); - ipv6Header->payload_len = rte_cpu_to_be_16(sizeof(rte_udp_hdr) + sizeof(dataplane::globalBase::fw_state_sync_frame_t)); - ipv6Header->proto = IPPROTO_UDP; - ipv6Header->hop_limits = 64; - memcpy(ipv6Header->src_addr, fw_state_config.ipv6_address_source.bytes, 16); - memcpy(ipv6Header->dst_addr, fw_state_config.ipv6_address_multicast.bytes, 16); - - rte_udp_hdr* udpHeader = rte_pktmbuf_mtod_offset(mbuf, rte_udp_hdr*, metadata->network_headerOffset + sizeof(rte_ipv6_hdr)); - udpHeader->src_port = fw_state_config.port_multicast; // IPFW reuses the same port for both src and dst. - udpHeader->dst_port = fw_state_config.port_multicast; - udpHeader->dgram_len = rte_cpu_to_be_16(sizeof(rte_udp_hdr) + sizeof(dataplane::globalBase::fw_state_sync_frame_t)); - udpHeader->dgram_cksum = 0; - udpHeader->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6Header, udpHeader); - - // Iterate for all interested ports. - for (unsigned int port_id = 0; port_id < fw_state_config.flows_size; port_id++) - { - rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool); - if (mbuf_clone == nullptr) - { - slowWorker->stats.fwsync_multicast_egress_drops++; - continue; - } - - *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); - - memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), - rte_pktmbuf_mtod(mbuf, char*), - mbuf->data_len); - mbuf_clone->data_len = mbuf->data_len; - mbuf_clone->pkt_len = mbuf->pkt_len; - - const auto& flow = fw_state_config.flows[port_id]; - slowWorker->stats.fwsync_multicast_egress_packets++; - sendPacketToSlowWorker(mbuf_clone, flow); - } - - if (!fw_state_config.ipv6_address_unicast.empty()) - { - memcpy(ipv6Header->src_addr, fw_state_config.ipv6_address_unicast_source.bytes, 16); - memcpy(ipv6Header->dst_addr, fw_state_config.ipv6_address_unicast.bytes, 16); - udpHeader->src_port = fw_state_config.port_unicast; - udpHeader->dst_port = fw_state_config.port_unicast; - udpHeader->dgram_cksum = 0; - udpHeader->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6Header, udpHeader); - - rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool); - if (mbuf_clone == nullptr) - { - slowWorker->stats.fwsync_unicast_egress_drops++; - } - else - { - *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); - - memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), - rte_pktmbuf_mtod(mbuf, char*), - mbuf->data_len); - mbuf_clone->data_len = mbuf->data_len; - mbuf_clone->pkt_len = mbuf->pkt_len; - - slowWorker->stats.fwsync_unicast_egress_packets++; - sendPacketToSlowWorker(mbuf_clone, fw_state_config.ingress_flow); - } - } - - rte_pktmbuf_free(mbuf); -} - -bool cControlPlane::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - generic_rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, generic_rte_ether_hdr*); - if ((ethernetHeader->dst_addr.addr_bytes[0] & 1) == 0) - { - return false; - } - - // Confirmed multicast packet. - // Try to match against our multicast groups. - if (ethernetHeader->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) - { - return false; - } - - rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); - if (vlanHeader->eth_proto != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) - { - return false; - } - - rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr)); - if (metadata->transport_headerType != IPPROTO_UDP) - { - return false; - } - - const auto udp_payload_len = rte_be_to_cpu_16(ipv6Header->payload_len) - sizeof(rte_udp_hdr); - // Can contain multiple states per sync packet. - if (udp_payload_len % sizeof(dataplane::globalBase::fw_state_sync_frame_t) != 0) - { - return false; - } - - tAclId aclId; - if (!dataPlane->controlPlane->fw_state_multicast_acl_ids.apply([&](auto& fw_state_multicast_acl_ids) { - auto it = fw_state_multicast_acl_ids.find(common::ipv6_address_t(ipv6Header->dst_addr)); - if (it == fw_state_multicast_acl_ids.end()) - { - return false; - } - aclId = it->second; - return true; - })) - { - return false; - } - - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - const auto& fw_state_config = base.globalBase->fw_state_sync_configs[aclId]; - - if (memcmp(ipv6Header->src_addr, fw_state_config.ipv6_address_source.bytes, 16) == 0) - { - // Ignore self-generated packets. - return false; - } - - rte_udp_hdr* udpHeader = rte_pktmbuf_mtod_offset(mbuf, rte_udp_hdr*, sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr) + sizeof(rte_ipv6_hdr)); - if (udpHeader->dst_port != fw_state_config.port_multicast) - { - return false; - } - - for (size_t idx = 0; idx < udp_payload_len / sizeof(dataplane::globalBase::fw_state_sync_frame_t); ++idx) - { - dataplane::globalBase::fw_state_sync_frame_t* payload = rte_pktmbuf_mtod_offset( - mbuf, - dataplane::globalBase::fw_state_sync_frame_t*, - sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr) + sizeof(rte_ipv6_hdr) + sizeof(rte_udp_hdr) + idx * sizeof(dataplane::globalBase::fw_state_sync_frame_t)); - - if (payload->addr_type == 6) - { - dataplane::globalBase::fw6_state_key_t key; - key.proto = payload->proto; - key.__nap = 0; - // Swap src and dst addresses. - memcpy(key.dst_addr.bytes, payload->src_ip6.bytes, 16); - memcpy(key.src_addr.bytes, payload->dst_ip6.bytes, 16); - - if (payload->proto == IPPROTO_TCP || payload->proto == IPPROTO_UDP) - { - // Swap src and dst ports. - key.dst_port = payload->src_port; - key.src_port = payload->dst_port; - } - else - { - key.dst_port = 0; - key.src_port = 0; - } - - dataplane::globalBase::fw_state_value_t value; - value.type = static_cast(payload->proto); - value.owner = dataplane::globalBase::fw_state_owner_e::external; - value.last_seen = slowWorker->basePermanently.globalBaseAtomic->currentTime; - value.flow = fw_state_config.ingress_flow; - value.acl_id = aclId; - value.last_sync = slowWorker->basePermanently.globalBaseAtomic->currentTime; - value.packets_since_last_sync = 0; - value.packets_backward = 0; - value.packets_forward = 0; - value.tcp.unpack(payload->flags); - - uint32_t state_timeout = dataPlane->getConfigValues().stateful_firewall_other_protocols_timeout; - if (payload->proto == IPPROTO_UDP) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_udp_timeout; - } - else if (payload->proto == IPPROTO_TCP) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_timeout; - uint8_t flags = value.tcp.src_flags | value.tcp.dst_flags; - if (flags & (uint8_t)common::fwstate::tcp_flags_e::ACK) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_ack_timeout; - } - else if (flags & (uint8_t)common::fwstate::tcp_flags_e::SYN) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_timeout; - } - if (flags & (uint8_t)common::fwstate::tcp_flags_e::FIN) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_fin_timeout; - } - } - value.state_timeout = state_timeout; - - for (auto& [socketId, globalBaseAtomic] : dataPlane->globalBaseAtomics) - { - (void)socketId; - - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; - const uint32_t hash = globalBaseAtomic->fw6_state->lookup(key, lookup_value, locker); - if (lookup_value) - { - // Keep state alive for us even if there were no packets received. - // Do not reset other counters. - lookup_value->last_seen = slowWorker->basePermanently.globalBaseAtomic->currentTime; - lookup_value->tcp.src_flags |= value.tcp.src_flags; - lookup_value->tcp.dst_flags |= value.tcp.dst_flags; - lookup_value->state_timeout = std::max(lookup_value->state_timeout, value.state_timeout); - } - else - { - globalBaseAtomic->fw6_state->insert(hash, key, value); - } - locker->unlock(); - } - } - else if (payload->addr_type == 4) - { - dataplane::globalBase::fw4_state_key_t key; - key.proto = payload->proto; - key.__nap = 0; - // Swap src and dst addresses. - key.dst_addr.address = payload->src_ip; - key.src_addr.address = payload->dst_ip; - - if (payload->proto == IPPROTO_TCP || payload->proto == IPPROTO_UDP) - { - // Swap src and dst ports. - key.dst_port = payload->src_port; - key.src_port = payload->dst_port; - } - else - { - key.dst_port = 0; - key.src_port = 0; - } - - dataplane::globalBase::fw_state_value_t value; - value.type = static_cast(payload->proto); - value.owner = dataplane::globalBase::fw_state_owner_e::external; - value.last_seen = slowWorker->basePermanently.globalBaseAtomic->currentTime; - value.flow = fw_state_config.ingress_flow; - value.acl_id = aclId; - value.last_sync = slowWorker->basePermanently.globalBaseAtomic->currentTime; - value.packets_since_last_sync = 0; - value.packets_backward = 0; - value.packets_forward = 0; - value.tcp.unpack(payload->flags); - - uint32_t state_timeout = dataPlane->getConfigValues().stateful_firewall_other_protocols_timeout; - if (payload->proto == IPPROTO_UDP) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_udp_timeout; - } - else if (payload->proto == IPPROTO_TCP) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_timeout; - uint8_t flags = value.tcp.src_flags | value.tcp.dst_flags; - if (flags & (uint8_t)common::fwstate::tcp_flags_e::ACK) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_ack_timeout; - } - else if (flags & (uint8_t)common::fwstate::tcp_flags_e::SYN) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_timeout; - } - if (flags & (uint8_t)common::fwstate::tcp_flags_e::FIN) - { - state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_fin_timeout; - } - } - value.state_timeout = state_timeout; - - for (auto& [socketId, globalBaseAtomic] : dataPlane->globalBaseAtomics) - { - (void)socketId; - - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; - const uint32_t hash = globalBaseAtomic->fw4_state->lookup(key, lookup_value, locker); - if (lookup_value) - { - // Keep state alive for us even if there were no packets received. - // Do not reset other counters. - lookup_value->last_seen = slowWorker->basePermanently.globalBaseAtomic->currentTime; - lookup_value->tcp.src_flags |= value.tcp.src_flags; - lookup_value->tcp.dst_flags |= value.tcp.dst_flags; - lookup_value->state_timeout = std::max(lookup_value->state_timeout, value.state_timeout); - } - else - { - globalBaseAtomic->fw4_state->insert(hash, key, value); - } - locker->unlock(); - } - } - } - - return true; -} - -void cControlPlane::BalancerICMPForwardCriticalSection( - rte_mbuf* mbuf, - cControlPlane::VipToBalancers& vip_to_balancers, - cControlPlane::VipVportProto& vip_vport_proto) -{ - const auto& base = slowWorker->bases[slowWorker->localBaseId & 1]; - - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - common::ip_address_t original_src_from_icmp_payload; - common::ip_address_t src_from_ip_header; - uint16_t original_src_port_from_icmp_payload; - - uint32_t balancer_id = metadata->flow.data.balancer.id; - - dataplane::metadata inner_metadata; - - if (metadata->transport_headerType == IPPROTO_ICMP) - { - rte_ipv4_hdr* ipv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); - src_from_ip_header = common::ip_address_t(rte_be_to_cpu_32(ipv4Header->src_addr)); - - rte_ipv4_hdr* icmpPayloadIpv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->transport_headerOffset + sizeof(icmpv4_header_t)); - original_src_from_icmp_payload = common::ip_address_t(rte_be_to_cpu_32(icmpPayloadIpv4Header->src_addr)); - - inner_metadata.network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); - inner_metadata.network_headerOffset = metadata->transport_headerOffset + sizeof(icmpv4_header_t); - } - else - { - rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); - src_from_ip_header = common::ip_address_t(ipv6Header->src_addr); - - rte_ipv6_hdr* icmpPayloadIpv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->transport_headerOffset + sizeof(icmpv6_header_t)); - original_src_from_icmp_payload = common::ip_address_t(icmpPayloadIpv6Header->src_addr); - - inner_metadata.network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); - inner_metadata.network_headerOffset = metadata->transport_headerOffset + sizeof(icmpv6_header_t); - } - - if (!prepareL3(mbuf, &inner_metadata)) - { - /* we are not suppossed to get in here anyway, same check was done earlier by balancer_icmp_forward_handle(), - but we needed to call prepareL3() to determine icmp payload original packets transport header offset */ - if (inner_metadata.network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_ip]++; - } - else - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_ip]++; - } - - rte_pktmbuf_free(mbuf); - return; - } - - if (inner_metadata.transport_headerType != IPPROTO_TCP && inner_metadata.transport_headerType != IPPROTO_UDP) - { - // not supported protocol for cloning and distributing, drop - rte_pktmbuf_free(mbuf); - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unexpected_transport_protocol]++; - return; - } - - // check whether ICMP payload is too short to contain "offending" packet's IP header and ports is performed earlier by balancer_icmp_forward_handle() - void* icmpPayloadTransportHeader = rte_pktmbuf_mtod_offset(mbuf, void*, inner_metadata.transport_headerOffset); - - // both TCP and UDP headers have src port (16 bits) as the first field - original_src_port_from_icmp_payload = rte_be_to_cpu_16(*(uint16_t*)icmpPayloadTransportHeader); - - if (vip_to_balancers.size() <= balancer_id) - { - // no vip_to_balancers table for this balancer_id - rte_pktmbuf_free(mbuf); - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_no_unrdup_table_for_balancer_id]++; - return; - } - - if (!vip_to_balancers[balancer_id].count(original_src_from_icmp_payload)) - { - // vip is not listed in unrdup config - neighbor balancers are unknown, drop - rte_pktmbuf_free(mbuf); - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unrdup_vip_not_found]++; - return; - } - - if (vip_vport_proto.size() <= balancer_id) - { - // no vip_vport_proto table for this balancer_id - rte_pktmbuf_free(mbuf); - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id]++; - return; - } - - if (!vip_vport_proto[balancer_id].count({original_src_from_icmp_payload, original_src_port_from_icmp_payload, inner_metadata.transport_headerType})) - { - // such combination of vip-vport-protocol is absent, don't clone, drop - rte_pktmbuf_free(mbuf); - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unknown_service]++; - return; - } - - const auto& neighbor_balancers = vip_to_balancers[balancer_id][original_src_from_icmp_payload]; - - for (const auto& neighbor_balancer : neighbor_balancers) - { - // will not send a cloned packet if source address in "balancer" section of controlplane.conf is absent - if (neighbor_balancer.is_ipv4() && !base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv4.address) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv4]++; - continue; - } - - if (neighbor_balancer.is_ipv6() && base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv6.empty()) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv6]++; - continue; - } - - rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool); - if (mbuf_clone == nullptr) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_failed_to_clone]++; - continue; - } - - *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); - dataplane::metadata* clone_metadata = YADECAP_METADATA(mbuf_clone); - - rte_memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), - rte_pktmbuf_mtod(mbuf, char*), - mbuf->data_len); - - if (neighbor_balancer.is_ipv4()) - { - rte_pktmbuf_prepend(mbuf_clone, sizeof(rte_ipv4_hdr)); - memmove(rte_pktmbuf_mtod(mbuf_clone, char*), - rte_pktmbuf_mtod_offset(mbuf_clone, char*, sizeof(rte_ipv4_hdr)), - clone_metadata->network_headerOffset); - - rte_ipv4_hdr* outerIpv4Header = rte_pktmbuf_mtod_offset(mbuf_clone, rte_ipv4_hdr*, clone_metadata->network_headerOffset); - - outerIpv4Header->src_addr = base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv4.address; - outerIpv4Header->dst_addr = rte_cpu_to_be_32(neighbor_balancer.get_ipv4()); - - outerIpv4Header->version_ihl = 0x45; - outerIpv4Header->type_of_service = 0x00; - outerIpv4Header->packet_id = rte_cpu_to_be_16(0x01); - outerIpv4Header->fragment_offset = 0; - outerIpv4Header->time_to_live = 64; - - outerIpv4Header->total_length = rte_cpu_to_be_16((uint16_t)(mbuf->pkt_len - clone_metadata->network_headerOffset + sizeof(rte_ipv4_hdr))); - - if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) - { - outerIpv4Header->next_proto_id = IPPROTO_IPIP; - } - else - { - outerIpv4Header->next_proto_id = IPPROTO_IPV6; - } - - yanet_ipv4_checksum(outerIpv4Header); - - mbuf_clone->data_len = mbuf->data_len + sizeof(rte_ipv4_hdr); - mbuf_clone->pkt_len = mbuf->pkt_len + sizeof(rte_ipv4_hdr); - - // might need to change next protocol type in ethernet/vlan header in cloned packet - - rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf_clone, rte_ether_hdr*); - if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) - { - rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf_clone, rte_vlan_hdr*, sizeof(rte_ether_hdr)); - vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); - } - else - { - ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); - } - } - else if (neighbor_balancer.is_ipv6()) - { - rte_pktmbuf_prepend(mbuf_clone, sizeof(rte_ipv6_hdr)); - memmove(rte_pktmbuf_mtod(mbuf_clone, char*), - rte_pktmbuf_mtod_offset(mbuf_clone, char*, sizeof(rte_ipv6_hdr)), - clone_metadata->network_headerOffset); - - rte_ipv6_hdr* outerIpv6Header = rte_pktmbuf_mtod_offset(mbuf_clone, rte_ipv6_hdr*, clone_metadata->network_headerOffset); - - rte_memcpy(outerIpv6Header->src_addr, base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv6.bytes, sizeof(outerIpv6Header->src_addr)); - if (src_from_ip_header.is_ipv6()) - { - ((uint32_t*)outerIpv6Header->src_addr)[2] = ((uint32_t*)src_from_ip_header.get_ipv6().data())[2] ^ ((uint32_t*)src_from_ip_header.get_ipv6().data())[3]; - } - else - { - ((uint32_t*)outerIpv6Header->src_addr)[2] = src_from_ip_header.get_ipv4(); - } - rte_memcpy(outerIpv6Header->dst_addr, neighbor_balancer.get_ipv6().data(), sizeof(outerIpv6Header->dst_addr)); - - outerIpv6Header->vtc_flow = rte_cpu_to_be_32((0x6 << 28)); - outerIpv6Header->payload_len = rte_cpu_to_be_16((uint16_t)(mbuf->pkt_len - clone_metadata->network_headerOffset)); - outerIpv6Header->hop_limits = 64; - - if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) - { - outerIpv6Header->proto = IPPROTO_IPIP; - } - else - { - outerIpv6Header->proto = IPPROTO_IPV6; - } - - mbuf_clone->data_len = mbuf->data_len + sizeof(rte_ipv6_hdr); - mbuf_clone->pkt_len = mbuf->pkt_len + sizeof(rte_ipv6_hdr); - - // might need to change next protocol type in ethernet/vlan header in cloned packet - - rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf_clone, rte_ether_hdr*); - if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) - { - rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf_clone, rte_vlan_hdr*, sizeof(rte_ether_hdr)); - vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); - } - else - { - ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); - } - } - - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_clone_forwarded]++; - - const auto& flow = base.globalBase->balancers[metadata->flow.data.balancer.id].flow; - - slowWorker->preparePacket(mbuf_clone); - sendPacketToSlowWorker(mbuf_clone, flow); - } -} - - -void cControlPlane::handlePacket_balancer_icmp_forward(rte_mbuf* mbuf) -{ - if (dataPlane->config.SWICMPOutRateLimit != 0) - { - if (icmpOutRemainder == 0) - { - slowWorker->counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached]++; - rte_pktmbuf_free(mbuf); - return; - } - - --icmpOutRemainder; - } - - dataPlane->controlPlane->vip_to_balancers.apply([&](auto& vip_to_balancers) { - dataPlane->controlPlane->vip_vport_proto.apply([&](auto& vip_vport_proto) { - BalancerICMPForwardCriticalSection(mbuf, vip_to_balancers, vip_vport_proto); - }); - }); - - // packet itself is not going anywhere, only its clones with prepended header - rte_pktmbuf_free(mbuf); -} - -void cControlPlane::handlePacket_dump(rte_mbuf* mbuf) -{ - dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto& portmapper = slowWorker->basePermanently.ports; - if (!portmapper.ValidDpdk(metadata->flow.data.dump.id)) - { - stats.unknown_dump_interface++; - rte_pktmbuf_free(mbuf); - return; - } - const auto local_port_id = portmapper.ToLogical(metadata->flow.data.dump.id); - - auto push = [this, mbuf](KniPortData& iface) { - if (iface.mbufs_count == CONFIG_YADECAP_MBUFS_BURST_SIZE) - { - flush_kernel_interface(iface); - } - iface.mbufs[iface.mbufs_count++] = mbuf; - }; - - if (metadata->flow.data.dump.type == common::globalBase::dump_type_e::physicalPort_ingress) - { - push(in_dump_kernel_interfaces[local_port_id]); - return; - } - else if (metadata->flow.data.dump.type == common::globalBase::dump_type_e::physicalPort_egress) - { - push(out_dump_kernel_interfaces[local_port_id]); - return; - } - else if (metadata->flow.data.dump.type == common::globalBase::dump_type_e::physicalPort_drop) - { - push(drop_dump_kernel_interfaces[local_port_id]); - return; - } - - stats.unknown_dump_interface++; - rte_pktmbuf_free(mbuf); -} - -rte_mbuf* cControlPlane::convertMempool(rte_ring* ring_to_free_mbuf, - rte_mbuf* old_mbuf) -{ - /// we dont support attached mbufs - - rte_mbuf* mbuf = rte_pktmbuf_alloc(mempool); - if (!mbuf) - { - stats.mempool_is_empty++; - - freeWorkerPacket(ring_to_free_mbuf, old_mbuf); - return nullptr; - } - - *YADECAP_METADATA(mbuf) = *YADECAP_METADATA(old_mbuf); - - /// @todo: rte_pktmbuf_append() and check error - - memcpy(rte_pktmbuf_mtod(mbuf, char*), - rte_pktmbuf_mtod(old_mbuf, char*), - old_mbuf->data_len); - - mbuf->data_len = old_mbuf->data_len; - mbuf->pkt_len = old_mbuf->pkt_len; - - freeWorkerPacket(ring_to_free_mbuf, old_mbuf); - - if (rte_mbuf_refcnt_read(mbuf) != 1) - { - YADECAP_LOG_ERROR("something wrong\n"); - } - - return mbuf; -} - -void cControlPlane::sendPacketToSlowWorker(rte_mbuf* mbuf, - const common::globalBase::tFlow& flow) -{ - /// we dont support attached mbufs - - if (slowWorkerMbufs.size() >= 1024) ///< @todo: variable - { - stats.slowworker_drops++; - rte_pktmbuf_free(mbuf); - return; - } - - stats.slowworker_packets++; - slowWorkerMbufs.emplace(mbuf, flow); -} - -void cControlPlane::freeWorkerPacket(rte_ring* ring_to_free_mbuf, - rte_mbuf* mbuf) -{ - if (ring_to_free_mbuf == slowWorker->ring_toFreePackets) - { - rte_pktmbuf_free(mbuf); - return; - } - - while (rte_ring_sp_enqueue(ring_to_free_mbuf, mbuf) != 0) - { - std::this_thread::yield(); - } -} diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 01dce02b..b8cd44b0 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -28,12 +28,22 @@ class cControlPlane ///< @todo: move to cDataPlane { +protected: + struct sKniStats + { + uint64_t ipackets = 0; + uint64_t ibytes = 0; + uint64_t idropped = 0; + uint64_t opackets = 0; + uint64_t obytes = 0; + uint64_t odropped = 0; + }; + public: cControlPlane(cDataPlane* dataPlane); - virtual ~cControlPlane(); + virtual ~cControlPlane() = default; eResult init(bool use_kernel_interface); - void start(); void stop(); void join(); @@ -41,16 +51,19 @@ class cControlPlane ///< @todo: move to cDataPlane eResult updateGlobalBaseBalancer(const common::idp::updateGlobalBaseBalancer::request& request); common::idp::getGlobalBase::response getGlobalBase(const common::idp::getGlobalBase::request& request); common::idp::getWorkerStats::response getWorkerStats(const common::idp::getWorkerStats::request& request); - common::idp::getSlowWorkerStats::response getSlowWorkerStats(); + common::slowworker::stats_t SlowWorkerStats() const; + common::idp::getSlowWorkerStats::response SlowWorkerStatsResponse(); common::idp::get_worker_gc_stats::response get_worker_gc_stats(); common::idp::get_dregress_counters::response get_dregress_counters(); common::idp::get_ports_stats::response get_ports_stats(); common::idp::get_ports_stats_extended::response get_ports_stats_extended(); common::idp::getControlPlanePortStats::response getControlPlanePortStats(const common::idp::getControlPlanePortStats::request& request); common::idp::getPortStatsEx::response getPortStatsEx(); - common::idp::getFragmentationStats::response getFragmentationStats(); + common::idp::getFragmentationStats::response getFragmentationStats() const; common::dregress::stats_t DregressStats() const; + std::optional> KniStats(tPortId) const; dataplane::hashtable_chain_spinlock_stats_t DregressConnectionsStats() const; + dregress::LimitsStats DregressLimitsStats() const; common::idp::getFWState::response getFWState(); common::idp::getFWStateStats::response getFWStateStats(); eResult clearFWState(); @@ -82,34 +95,39 @@ class cControlPlane ///< @todo: move to cDataPlane void switchGlobalBase(); virtual void waitAllWorkers(); - void sendPacketToSlowWorker(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); ///< @todo: remove flow - void freeWorkerPacket(rte_ring* ring_to_free_mbuf, rte_mbuf* mbuf); +private: + const std::vector& workers_vector() const; + const std::map& slow_workers() const; -protected: - eResult initMempool(); - - void mainThread(); - unsigned ring_handle(rte_ring* ring_to_free_mbuf, rte_ring* ring); - - void handlePacketFromForwardingPlane(rte_mbuf* mbuf); ///< @todo: rename - void handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf); - void handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf); - void handlePacket_dregress(rte_mbuf* mbuf); - void handlePacket_repeat(rte_mbuf* mbuf); - void handlePacket_fragment(rte_mbuf* mbuf); - void handlePacket_farm(rte_mbuf* mbuf); - void handlePacket_fw_state_sync(rte_mbuf* mbuf); - bool handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf); - using VipToBalancers = std::vector>>; - using VipVportProto = std::vector, uint8_t>>>; - void BalancerICMPForwardCriticalSection( - rte_mbuf* mbuf, - VipToBalancers& vip_to_balancers, - VipVportProto& vip_vport_proto); - void handlePacket_balancer_icmp_forward(rte_mbuf* mbuf); - void handlePacket_dump(rte_mbuf* mbuf); - - rte_mbuf* convertMempool(rte_ring* ring_to_free_mbuf, rte_mbuf* mbuf); + template + // @brief returns sum of results of applying F to all cWorker*s + auto accumulateWorkerStats(F func) const + { + using R = std::invoke_result_t; + return std::accumulate( + workers_vector().begin(), + workers_vector().end(), + R{}, + [func](R total, cWorker* worker) { + total += func(worker); + return total; + }); + } + + template + // @brief returns sum of results of applying F to all SlowWorker*s + auto accumulateSlowWorkerStats(F func) const + { + using R = std::invoke_result_t; + return std::accumulate( + slow_workers().begin(), + slow_workers().end(), + R{}, + [&func](R total, const auto& pair) { + total += func(pair.second); + return total; + }); + } protected: friend class cReport; @@ -117,26 +135,11 @@ class cControlPlane ///< @todo: move to cDataPlane friend class dataplane::globalBase::generation; friend class dregress_t; - struct sKniStats - { - uint64_t ipackets = 0; - uint64_t ibytes = 0; - uint64_t idropped = 0; - uint64_t opackets = 0; - uint64_t obytes = 0; - uint64_t odropped = 0; - }; - cDataPlane* dataPlane; - fragmentation::Fragmentation fragmentation_; - dataplane::SlowWorker slow_; - dregress_t dregress; - std::mutex mutex; std::mutex balancer_mutex; - rte_mempool* mempool; bool use_kernel_interface; struct KniHandleBundle @@ -167,26 +170,19 @@ class cControlPlane ///< @todo: move to cDataPlane common::slowworker::stats_t stats; common::idp::getErrors::response errors; ///< @todo: class errorsManager -public: - cWorker* slowWorker; - -protected: - utils::StaticVector, YANET_CONFIG_NUMA_SIZE> to_gcs_; std::queue> slowWorkerMbufs; - std::mutex fw_state_multicast_acl_ids_mutex; - using FwStateMulticastAclIds = std::map; - utils::Sequential fw_state_multicast_acl_ids; - // provided by unrdup.cfg, used to clone some icmp packets to neighbor balancers, index is balancer_id +public: + using VipToBalancers = std::vector>>; utils::Sequential vip_to_balancers; - + using VipVportProto = std::vector, uint8_t>>>; // check presence prior to cloning utils::Sequential vip_vport_proto; + using FwStateMulticastAclIds = std::map; + utils::Sequential fw_state_multicast_acl_ids; - std::chrono::high_resolution_clock::time_point prevTimePointForSWRateLimiter; - - uint32_t icmpOutRemainder; +protected: uint32_t gc_step; }; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 39471c0f..037aa28a 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -39,6 +39,7 @@ #include "lpm.h" #include "report.h" #include "sock_dev.h" +#include "work_runner.h" #include "worker.h" #include "worker_gc.h" @@ -54,6 +55,7 @@ cDataPlane::cDataPlane() : currentGlobalBaseId(0), globalBaseSerial(0), report(this), + controlPlane(std::make_unique(this)), bus(this), memory_manager(this) { @@ -65,6 +67,10 @@ cDataPlane::~cDataPlane() { rte_mempool_free(mempool_log); } + for (auto it : socket_cplane_mempools) + { + rte_mempool_free(it.second); + } } eResult cDataPlane::init(const std::string& binaryPath, @@ -110,12 +116,6 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } - result = InitControlPlane(); - if (result != eResult::success) - { - return result; - } - result = initPorts(); if (result != eResult::success) { @@ -162,7 +162,6 @@ eResult cDataPlane::init(const std::string& binaryPath, return eResult::errorAllocatingMemory; } socket_cplane_mempools.emplace(socket, pool); - YANET_LOG_ERROR("created mempool cp-%s\n", std::to_string(socket).c_str()); } result = initWorkers(); @@ -171,6 +170,12 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } + result = InitSlowWorkers(); + if (result != eResult::success) + { + return result; + } + result = splitSharedMemoryPerWorkers(); if (result != eResult::success) { @@ -178,11 +183,13 @@ eResult cDataPlane::init(const std::string& binaryPath, } /// sanity check - if (rte_lcore_count() != workers.size() + worker_gcs.size() + 1) + if (rte_lcore_count() != workers.size() + worker_gcs.size() + slow_workers.size()) { - YADECAP_LOG_ERROR("invalid cores count: %u != %lu\n", + YADECAP_LOG_ERROR("invalid cores count: %u != %luwork + %lugc + %luslow\n", rte_lcore_count(), - workers.size() + worker_gcs.size() + 1); + workers.size(), + worker_gcs.size(), + slow_workers.size()); return eResult::invalidCoresCount; } @@ -615,12 +622,6 @@ void cDataPlane::StartInterfaces() } } -eResult cDataPlane::InitControlPlane() -{ - controlPlane = std::make_unique(this); - return eResult::success; -} - eResult cDataPlane::init_kernel_interfaces() { const uint16_t queue_size = getConfigValues().kernel_interface_queue_size; @@ -837,52 +838,6 @@ eResult cDataPlane::initGlobalBases() eResult cDataPlane::initWorkers() { - /// slow worker - { - const tCoreId& coreId = config.controlPlaneCoreId; - const tSocketId socket_id = rte_lcore_to_socket_id(coreId); - - YADECAP_LOG_INFO("initWorker. coreId: %u [slow worker]\n", coreId); - - auto* worker = memory_manager.create_static("worker", - socket_id, - this); - if (!worker) - { - return eResult::errorAllocatingMemory; - } - - dataplane::base::permanently basePermanently; - basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; - basePermanently.outQueueId = tx_queues_; ///< 0 - for (const auto& portIter : ports) - { - if (!basePermanently.ports.Register(portIter.first)) - return eResult::invalidPortsCount; - } - - basePermanently.SWNormalPriorityRateLimitPerWorker = config.SWNormalPriorityRateLimitPerWorker; - - dataplane::base::generation base; - base.globalBase = globalBases[socket_id][currentGlobalBaseId]; - - eResult result = worker->init(coreId, - basePermanently, - base); - if (result != eResult::success) - { - return result; - } - - worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[coreId]); - - slow_worker = worker; - controlPlane->slowWorker = worker; - workers_vector.emplace_back(worker); - - tx_queues_++; - } - for (const auto& configWorkerIter : config.workers) { const tCoreId& coreId = configWorkerIter.first; @@ -1132,15 +1087,139 @@ eResult cDataPlane::initWorkers() worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[core_id]); worker_gcs[core_id] = worker; socket_worker_gcs[socket_id] = worker; + } + + return eResult::success; +} + +eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& cfg) +{ + const tSocketId socket_id = rte_lcore_to_socket_id(core); + + YADECAP_LOG_INFO("initWorker. coreId: %u [controlplane worker]\n", core); + + auto* worker = memory_manager.create_static("worker", + socket_id, + this); + if (!worker) + { + return eResult::errorAllocatingMemory; + } + + dataplane::base::permanently basePermanently; + basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; + basePermanently.outQueueId = tx_queues_; + for (const auto& port : ports) + { + if (!basePermanently.ports.Register(port.first)) + return eResult::invalidPortsCount; + } + + basePermanently.SWNormalPriorityRateLimitPerWorker = config.SWNormalPriorityRateLimitPerWorker; + + dataplane::base::generation base; + base.globalBase = globalBases[socket_id][currentGlobalBaseId]; + + eResult result = worker->init(core, + basePermanently, + base); + if (result != eResult::success) + { + return result; + } + + worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[core]); + + workers_vector.emplace_back(worker); + + std::vector kni_bundleconf; + + std::vector ports_to_service; + if (config.use_kernel_interface) + { + for (auto& iface : cfg.interfaces) + { + tPortId port; + if (rte_eth_dev_get_port_by_name(iface.data(), &port)) + { + YANET_LOG_ERROR("Failed to get port id by interface name \"%s\"\n", iface.data()); + std::terminate(); + } + ports_to_service.push_back(port); + auto& [fwd, in, out, drop] = kni_interface_handles.at(port); + kni_bundleconf.emplace_back( + dataplane::KernelInterfaceBundleConfig{ + {port, tx_queues_}, + {fwd.Id(), 0}, + {in.Id(), 0}, + {out.Id(), 0}, + {drop.Id(), 0}}); + } + std::stringstream ss; + for (auto p : ports_to_service) + { + ss << p; + } + YANET_LOG_INFO("controlplane worker on core %d, serving [%s]\n", core, ss.str().c_str()); + } + YANET_LOG_ERROR("ending with kni bundleconf\n"); + + dataplane::KernelInterfaceWorkerConfig kni_config{std::move(kni_bundleconf), &basePermanently.ports}; + + std::vector workers_to_service; + for (auto& core : cfg.workers) + { + workers_to_service.push_back(workers.at(core)); + } + + std::vector gcs_to_service; + for (auto& core : cfg.gcs) + { + gcs_to_service.push_back(worker_gcs.at(core)); + } + + std::vector> rings_from_gcs; + for (auto& gccore : cfg.gcs) + { + auto r = worker_gcs.at(gccore)->RegisterSlowWorker("cw" + core, + config_values_.ring_normalPriority_size, + config_values_.ring_toFreePackets_size); + if (r) + { + rings_from_gcs.push_back(r.value()); + } + else + { + abort(); + } + } - auto conn = worker->RegisterSlowWorker("cw" + core_id, - config_values_.ring_normalPriority_size, - config_values_.ring_toFreePackets_size); - if (!conn) + auto slow = new dataplane::SlowWorker(worker, + std::move(ports_to_service), + std::move(workers_to_service), + std::move(rings_from_gcs), + kni_config, + socket_cplane_mempools.at(socket_id), + config.use_kernel_interface, + config.SWICMPOutRateLimit); + if (!slow) + { + return eResult::dataplaneIsBroken; + } + slow_workers.emplace(core, slow); + YANET_LOG_ERROR("slow workers size is %lu\n", slow_workers.size()); + ++tx_queues_; + return eResult::success; +} + +eResult cDataPlane::InitSlowWorkers() +{ + for (auto& [core, cfg] : config.controlplane_workers) + { + if (auto res = InitSlowWorker(core, cfg); res != eResult::success) { - YANET_LOG_ERROR("Failed no link garbage collector with slow worker"); + return res; } - controlPlane->to_gcs_.push_back(conn.value()); } return eResult::success; @@ -1192,7 +1271,7 @@ eResult cDataPlane::InitTxQueues() eResult cDataPlane::InitRxQueues() { - for (const auto& worker : workers_vector) + for (const cWorker* worker : workers_vector) { for (const auto& [port, queue] : worker->basePermanently.rx_points) { @@ -1218,13 +1297,13 @@ eResult cDataPlane::initKniQueues() for (auto& it : kni_interface_handles) { uint16_t port_id = it.first; - for (std::size_t i = 0, max = 1; i < max; ++i) + for (std::size_t i = 0, max = slow_workers.size(); i < max; ++i) { const auto& socket_id = rte_eth_dev_socket_id(port_id); KNIAddTxQueue(i, socket_id); } - for (std::size_t i = 0, max = 1; i < max; ++i) + for (std::size_t i = 0, max = slow_workers.size(); i < max; ++i) { const auto& socket_id = rte_eth_dev_socket_id(port_id); KNIAddRxQueue(i, socket_id, socket_cplane_mempools.at(socket_id)); @@ -1243,6 +1322,17 @@ void cDataPlane::init_worker_base() base_nexts.emplace_back(worker->socketId, base); base_nexts.emplace_back(worker->socketId, base_next); } + + for (auto& iter : slow_workers) + { + cWorker* worker = iter.second->GetWorker(); + + auto* base = &worker->bases[worker->currentBaseId]; + auto* base_next = &worker->bases[worker->currentBaseId ^ 1]; + base_nexts.emplace_back(worker->socketId, base); + base_nexts.emplace_back(worker->socketId, base_next); + } + for (auto& [core_id, worker] : worker_gcs) { (void)core_id; @@ -1256,51 +1346,56 @@ void cDataPlane::init_worker_base() neighbor.update_worker_base(base_nexts); } -void cDataPlane::SWRateLimiterTimeTracker() +void cDataPlane::timestamp_thread() { + uint32_t prev_time = 0; + for (;;) { - // seem to be sufficiently fast function for slowWorker whose threshold is 200'000 packets per second - std::chrono::high_resolution_clock::time_point curTimePointForSWRateLimiter = std::chrono::high_resolution_clock::now(); + current_time = time(nullptr); - // is it time to reset icmpPacketsToSW counters? - if (std::chrono::duration_cast(curTimePointForSWRateLimiter - prevTimePointForSWRateLimiter) >= std::chrono::milliseconds(1000 / config.rateLimitDivisor)) + if (current_time != prev_time) { - // the only place thread-shared variable icmpPacketsToSW is changed - for (cWorker* worker : workers_vector) + for (const auto& [socket_id, globalbase_atomic] : globalBaseAtomics) { - __atomic_store_n(&worker->packetsToSWNPRemainder, config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); + (void)socket_id; + globalbase_atomic->currentTime = current_time; } - controlPlane->icmpOutRemainder = config.SWICMPOutRateLimit / config.rateLimitDivisor; - - prevTimePointForSWRateLimiter = curTimePointForSWRateLimiter; + prev_time = current_time; } - using namespace std::chrono_literals; - std::this_thread::sleep_for(100ms / config.rateLimitDivisor); + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } -void cDataPlane::timestamp_thread() +void cDataPlane::SWRateLimiterTimeTracker() { - uint32_t prev_time = 0; - for (;;) { - current_time = time(nullptr); + using namespace std::chrono_literals; + // seem to be sufficiently fast function for slowWorker whose threshold is 200'000 packets per second + std::chrono::high_resolution_clock::time_point curTimePointForSWRateLimiter = std::chrono::high_resolution_clock::now(); - if (current_time != prev_time) + // is it time to reset icmpPacketsToSW counters? + if (std::chrono::duration_cast( + curTimePointForSWRateLimiter - prevTimePointForSWRateLimiter) >= 1000ms / config.rateLimitDivisor) { - for (const auto& [socket_id, globalbase_atomic] : globalBaseAtomics) + // the only place thread-shared variable icmpPacketsToSW is changed + for (cWorker* worker : workers_vector) { - (void)socket_id; - globalbase_atomic->currentTime = current_time; + + __atomic_store_n(&worker->packetsToSWNPRemainder, config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); } - prev_time = current_time; - } + for (auto it : slow_workers) + { + it.second->ResetIcmpOutRemainder(config.SWICMPOutRateLimit / config.rateLimitDivisor); + } - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + prevTimePointForSWRateLimiter = curTimePointForSWRateLimiter; + } + std::this_thread::sleep_for(100ms / config.rateLimitDivisor); } } @@ -1337,9 +1432,8 @@ void cDataPlane::start() { if (coreFunctions_.find(core) != coreFunctions_.end()) { - YANET_LOG_ERROR("Worker: Multiple workloads assigned to core %d\n", core); + YANET_LOG_ERROR("Multiple workloads assigned to core %d\n", core); } - YANET_LOG_INFO("Worker assigned to core %d\n", core); coreFunctions_.emplace(core, [worker]() { worker->start(); }); @@ -1349,22 +1443,24 @@ void cDataPlane::start() { if (coreFunctions_.find(core) != coreFunctions_.end()) { - YANET_LOG_ERROR("GC: Multiple workloads assigned to core %d\n", core); + YANET_LOG_ERROR("Multiple workloads assigned to core %d\n", core); } - YANET_LOG_INFO("GC assigned to core %d\n", core); coreFunctions_.emplace(core, [garbage_collector]() { garbage_collector->start(); }); } - if (coreFunctions_.find(config.controlPlaneCoreId) != coreFunctions_.end()) + for (auto& [core, slow] : slow_workers) { - YANET_LOG_ERROR("CP: Multiple workloads assigned to core %d\n", config.controlPlaneCoreId); + if (coreFunctions_.find(core) != coreFunctions_.end()) + { + YANET_LOG_ERROR("Multiple workloads assigned to core %d\n", core); + } + coreFunctions_.emplace(core, [slow]() { + auto work_runner = dpdk::WorkRunner{slow, dpdk::Yielder{}}; + work_runner.Run(); + }); } - YANET_LOG_INFO("Worker assigned to core %d\n", config.controlPlaneCoreId); - coreFunctions_.emplace(config.controlPlaneCoreId, [&]() { - controlPlane->start(); - }); StartInterfaces(); @@ -1727,6 +1823,7 @@ void cDataPlane::switch_worker_base() auto* base_next = &worker->bases[worker->currentBaseId ^ 1]; base_nexts.emplace_back(worker->socketId, base_next); } + for (auto& [core_id, worker] : worker_gcs) { (void)core_id; @@ -1938,7 +2035,7 @@ eResult cDataPlane::parseJsonPorts(const nlohmann::json& json) return eResult::success; } -std::optional>> cDataPlane::parseControlPlaneWorkers(const nlohmann::json& root) +std::optional> cDataPlane::parseControlPlaneWorkers(const nlohmann::json& root) { nlohmann::json dflt; auto cpw = root.find("controlPlaneWorkers"); @@ -1950,7 +2047,7 @@ std::optional>> cDataPlane::parseContr cpw = dflt.find("controlPlaneWorkers"); } - std::map> result; + std::map result; auto add_worker = [&](const nlohmann::json& j) { auto worker = parseControlPlaneWorker(j); @@ -1988,6 +2085,7 @@ nlohmann::json cDataPlane::makeLegacyControlPlaneWorkerConfig() nlohmann::json j; j["core"] = config.controlPlaneCoreId; j["interfaces"] = workerInterfacesToService(); + j["serviced_cores"] = FastWorkerCores(); return nlohmann::json{{"controlPlaneWorkers", j}}; } @@ -2005,7 +2103,20 @@ std::set cDataPlane::workerInterfacesToService() return res; } -std::optional>> cDataPlane::parseControlPlaneWorker(const nlohmann::json& cpwj) +const std::set cDataPlane::FastWorkerCores() const +{ + std::set cores; + for (auto it : config.workers) + { + if (!cores.insert(it.first).second) + { + YANET_LOG_ERROR("Same core specified in config for multiple workers\n"); + } + } + return cores; +} + +std::optional> cDataPlane::parseControlPlaneWorker(const nlohmann::json& cpwj) { auto jcore = cpwj.find("core"); if (jcore == cpwj.end()) @@ -2026,14 +2137,7 @@ std::optional>> cDataPlane::parseCont YADECAP_LOG_ERROR("controlPlaneWorker entry has no \"interfaces\" field\n"); return std::nullopt; } - if (jports.value().is_number_unsigned()) - { - const std::set ifaces = jports.value(); - return std::optional{ - std::pair>{ - core, - std::set{InterfaceName{jports.value()}}}}; - } + if (!jports.value().is_array()) { YADECAP_LOG_ERROR("controlPlaneWorker entry \"interfaces\" has invalid type.\n"); @@ -2050,10 +2154,46 @@ std::optional>> cDataPlane::parseCont } worker_ports.insert(InterfaceName{j}); } - return std::optional{ - std::pair>{ - core, - std::move(worker_ports)}}; + + auto jworkers = cpwj.find("serviced_cores"); + if (!jworkers.value().is_array()) + { + YADECAP_LOG_ERROR("controlPlaneWorker entry \"workers\" has invalid type.\n"); + return std::nullopt; + } + + std::set worker_cores; + for (auto& j : jworkers.value()) + { + if (!j.is_number_unsigned()) + { + YANET_LOG_ERROR("controlPlaneWorker entry in \"serviced_cores\" is not an unsigned integer\n"); + return std::nullopt; + } + tCoreId id = j; + if (config.workers.find(id) == config.workers.end()) + { + YANET_LOG_ERROR("controlPlaneWorker entry in \"serviced_cores\" is not a valid worker core id\n"); + } + if (!worker_cores.insert(id).second) + { + YANET_LOG_ERROR("controlPlaneWorker entry %d in \"serviced_cores\" is duplicate\n", id); + } + } + + std::set gc_cores; + for (auto& gc_core : config.workerGCs) + { + if (rte_lcore_to_socket_id(gc_core) == rte_lcore_to_socket_id(core)) + { + gc_cores.insert(gc_core); + } + } + + return std::make_pair(core, + CPlaneWorkerConfig{std::move(worker_ports), + std::move(worker_cores), + std::move(gc_cores)}); } eResult cDataPlane::parseConfigValues(const nlohmann::json& json) @@ -2170,9 +2310,9 @@ bool cDataPlane::checkControlPlaneWorkersConfig() std::set assigned; std::set to_assign = workerInterfacesToService(); bool result = true; - for (const auto& [core, worker_ports] : config.controlplane_workers) + for (const auto& [core, cfg] : config.controlplane_workers) { - for (const auto& p : worker_ports) + for (const auto& p : cfg.interfaces) { if (assigned.find(p) != assigned.end()) diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 66acad9a..31491954 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -22,13 +22,22 @@ #include "config_values.h" #include "controlplane.h" #include "globalbase.h" +#include "kernel_interface_handler.h" #include "memory_manager.h" #include "neighbor.h" #include "report.h" +#include "slow_worker.h" #include "type.h" using InterfaceName = std::string; +struct CPlaneWorkerConfig +{ + std::set interfaces; + std::set workers; + std::set gcs; +}; + struct tDataPlaneConfig { /* @@ -47,7 +56,7 @@ struct tDataPlaneConfig std::set workerGCs; tCoreId controlPlaneCoreId; - std::map> controlplane_workers; + std::map controlplane_workers; std::map> workers; bool useHugeMem = true; bool use_kernel_interface = true; @@ -98,6 +107,7 @@ class cDataPlane std::map getPortStats(const tPortId& portId) const; std::optional interface_name_to_port_id(const std::string& interface_name); const std::set& get_socket_ids() const; + const std::set FastWorkerCores() const; const std::vector& get_workers() const; void run_on_worker_gc(const tSocketId socket_id, const std::function& callback); @@ -112,8 +122,8 @@ class cDataPlane protected: eResult parseConfig(const std::string& configFilePath); eResult parseJsonPorts(const nlohmann::json& json); - std::optional>> parseControlPlaneWorkers(const nlohmann::json& config); - std::optional>> parseControlPlaneWorker(const nlohmann::json& cpwj); + std::optional> parseControlPlaneWorkers(const nlohmann::json& config); + std::optional> parseControlPlaneWorker(const nlohmann::json& cpwj); nlohmann::json makeLegacyControlPlaneWorkerConfig(); std::set workerInterfacesToService(); eResult parseConfigValues(const nlohmann::json& json); @@ -121,7 +131,6 @@ class cDataPlane eResult parseSharedMemory(const nlohmann::json& json); eResult checkConfig(); bool checkControlPlaneWorkersConfig(); - bool checkValidCoreId(const nlohmann::json& j); eResult initEal(const std::string& binaryPath, const std::string& filePrefix); eResult initPorts(); @@ -133,12 +142,13 @@ class cDataPlane void StartInterfaces(); protected: - eResult InitControlPlane(); eResult init_kernel_interfaces(); bool KNIAddTxQueue(tQueueId queue, tSocketId socket); bool KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); eResult initGlobalBases(); eResult initWorkers(); + eResult InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& ports); + eResult InitSlowWorkers(); eResult initKniQueues(); eResult InitTxQueues(); eResult InitRxQueues(); @@ -151,7 +161,6 @@ class cDataPlane common::idp::get_shm_info::response getShmInfo(); common::idp::get_shm_tsc_info::response getShmTscInfo(); - static int lcoreThread(void* args); void timestamp_thread(); void SWRateLimiterTimeTracker(); std::chrono::high_resolution_clock::time_point prevTimePointForSWRateLimiter; @@ -188,11 +197,16 @@ class cDataPlane tQueueId tx_queues_ = 0; std::map workers; std::map worker_gcs; - cWorker* slow_worker; + std::map slow_workers; + std::map kni_workers; std::mutex currentGlobalBaseId_mutex; uint8_t currentGlobalBaseId; + +public: std::map globalBaseAtomics; + +protected: size_t numaNodesInUse; std::map> globalBases; uint32_t globalBaseSerial; diff --git a/dataplane/dpdk.h b/dataplane/dpdk.h index d08d1e46..26d24f59 100644 --- a/dataplane/dpdk.h +++ b/dataplane/dpdk.h @@ -2,6 +2,7 @@ #include #include +#include #include #include "common/type.h" diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index ce4ae75c..3c5be433 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -2341,10 +2341,14 @@ eResult generation::dregress_prefix_update(const common::idp::updateGlobalBase:: { eResult result = eResult::success; - for (const auto& [prefix, value_id] : request) + for (auto it : dataPlane->slow_workers) { - std::lock_guard guard(dataPlane->controlPlane->dregress.prefixes_mutex); - dataPlane->controlPlane->dregress.prefixes.insert(prefix, value_id); + ::dregress_t& dregress = it.second->Dregress(); + for (const auto& [prefix, value_id] : request) + { + std::lock_guard guard(dregress.prefixes_mutex); + dregress.prefixes.insert(prefix, value_id); + } } return result; @@ -2354,12 +2358,15 @@ eResult generation::dregress_prefix_remove(const common::idp::updateGlobalBase:: { eResult result = eResult::success; - for (const auto& prefix : request) + for (auto it : dataPlane->slow_workers) { - std::lock_guard guard(dataPlane->controlPlane->dregress.prefixes_mutex); - dataPlane->controlPlane->dregress.prefixes.remove(prefix); + ::dregress_t& dregress = it.second->Dregress(); + for (const auto& prefix : request) + { + std::lock_guard guard(dregress.prefixes_mutex); + dregress.prefixes.remove(prefix); + } } - return result; } @@ -2367,8 +2374,12 @@ eResult generation::dregress_prefix_clear() { eResult result = eResult::success; - std::lock_guard guard(dataPlane->controlPlane->dregress.prefixes_mutex); - dataPlane->controlPlane->dregress.prefixes.clear(); + for (auto it : dataPlane->slow_workers) + { + ::dregress_t& dregress = it.second->Dregress(); + std::lock_guard guard(dregress.prefixes_mutex); + dregress.prefixes.clear(); + } return result; } @@ -2377,23 +2388,26 @@ eResult generation::dregress_local_prefix_update(const common::idp::updateGlobal { eResult result = eResult::success; - std::lock_guard guard(dataPlane->controlPlane->dregress.prefixes_mutex); + for (auto it : dataPlane->slow_workers) + { + ::dregress_t& dregress = it.second->Dregress(); + std::lock_guard guard(dregress.prefixes_mutex); - dataPlane->controlPlane->dregress.local_prefixes_v4.clear(); - dataPlane->controlPlane->dregress.local_prefixes_v6.clear(); + dregress.local_prefixes_v4.clear(); + dregress.local_prefixes_v6.clear(); - for (const auto& prefix : request) - { - if (prefix.is_ipv4()) - { - dataPlane->controlPlane->dregress.local_prefixes_v4.emplace(prefix.get_ipv4()); - } - else + for (const auto& prefix : request) { - dataPlane->controlPlane->dregress.local_prefixes_v6.emplace(prefix.get_ipv6()); + if (prefix.is_ipv4()) + { + dregress.local_prefixes_v4.insert(prefix.get_ipv4()); + } + else + { + dregress.local_prefixes_v6.insert(prefix.get_ipv6()); + } } } - return result; } @@ -2401,15 +2415,18 @@ eResult generation::dregress_value_update(const common::idp::updateGlobalBase::d { eResult result = eResult::success; - std::lock_guard guard(dataPlane->controlPlane->dregress.prefixes_mutex); - - for (const auto& [value_id, value] : request) + for (auto it : dataPlane->slow_workers) { - /// @todo: check value_id + ::dregress_t& dregress = it.second->Dregress(); + std::lock_guard guard(dregress.prefixes_mutex); - dataPlane->controlPlane->dregress.values[value_id] = value; - } + for (const auto& [value_id, value] : request) + { + /// @todo: check value_id + dregress.values[value_id] = value; + } + } return result; } diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 128e4798..ca037fb8 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -376,35 +376,43 @@ nlohmann::json cReport::convertControlPlane(const cControlPlane* controlPlane) { nlohmann::json json; - json["mempool"] = convertMempool(controlPlane->mempool); - - auto& portmapper = controlPlane->slowWorker->basePermanently.ports; - for (int i = 0; i < portmapper.size(); ++i) + json["mempool"] = convertMempool(dataPlane->slow_workers.begin()->second->Mempool()); + for (const auto& it : dataPlane->slow_workers) { - nlohmann::json jsonKni; + json["mempools"].emplace_back(convertMempool(it.second->Mempool())); + } - const auto& port = controlPlane->kernel_interfaces[i]; - const auto& stats = controlPlane->kernel_stats[i]; + for (const auto it : dataPlane->slow_workers) + { + const dataplane::KernelInterfaceWorker& worker = it.second->KniWorker(); - jsonKni["portId"] = portmapper.ToDpdk(i); - jsonKni["interfaceName"] = port.interface_name; - jsonKni["stats"]["ipackets"] = stats.ipackets; - jsonKni["stats"]["ibytes"] = stats.ibytes; - jsonKni["stats"]["idropped"] = stats.idropped; - jsonKni["stats"]["opackets"] = stats.opackets; - jsonKni["stats"]["obytes"] = stats.obytes; - jsonKni["stats"]["odropped"] = stats.odropped; + auto stats_it = worker.PortsStats().first; - json["knis"].emplace_back(jsonKni); + for (auto [current, end] = worker.PortsIds(); current != end; ++current, ++stats_it) + { + nlohmann::json jsonKni; + jsonKni["portId"] = *current; + jsonKni["interfaceName"] = dataPlane->InterfaceNameFromPort(*current); + jsonKni["stats"]["ipackets"] = stats_it->ipackets; + jsonKni["stats"]["ibytes"] = stats_it->ibytes; + jsonKni["stats"]["idropped"] = stats_it->idropped; + jsonKni["stats"]["opackets"] = stats_it->opackets; + jsonKni["stats"]["obytes"] = stats_it->obytes; + jsonKni["stats"]["odropped"] = stats_it->odropped; + + json["knis"].emplace_back(std::move(jsonKni)); + } } - json["repeat_packets"] = controlPlane->stats.repeat_packets; - json["tofarm_packets"] = controlPlane->stats.tofarm_packets; - json["farm_packets"] = controlPlane->stats.farm_packets; - json["fwsync_multicast_ingress_packets"] = controlPlane->stats.fwsync_multicast_ingress_packets; - json["slowworker_drops"] = controlPlane->stats.slowworker_drops; - json["slowworker_packets"] = controlPlane->stats.slowworker_packets; - json["mempool_is_empty"] = controlPlane->stats.mempool_is_empty; + const auto& slow_stats = controlPlane->SlowWorkerStats(); + + json["repeat_packets"] = slow_stats.repeat_packets; + json["tofarm_packets"] = slow_stats.tofarm_packets; + json["farm_packets"] = slow_stats.farm_packets; + json["fwsync_multicast_ingress_packets"] = slow_stats.fwsync_multicast_ingress_packets; + json["slowworker_drops"] = slow_stats.slowworker_drops; + json["slowworker_packets"] = slow_stats.slowworker_packets; + json["mempool_is_empty"] = slow_stats.mempool_is_empty; json["dregress"] = controlPlane->DregressStats(); json["dregress"]["connections"] = controlPlane->DregressConnectionsStats(); diff --git a/dataplane/slow_worker.cpp b/dataplane/slow_worker.cpp index 35ca7125..6354200f 100644 --- a/dataplane/slow_worker.cpp +++ b/dataplane/slow_worker.cpp @@ -1,25 +1,984 @@ #include "slow_worker.h" -#include "common/type.h" -#include "controlplane.h" -#include "worker.h" +#include "common/fallback.h" +#include "dataplane.h" +#include "icmp_translations.h" +#include "prepare.h" namespace dataplane { +SlowWorker::SlowWorker(cWorker* worker, + std::vector&& ports_to_service, + std::vector&& workers_to_service, + std::vector>&& from_gcs, + KernelInterfaceWorker&& kni, + rte_mempool* mempool, + bool use_kni, + uint32_t sw_icmp_out_rate_limit) : + ports_serviced_{std::move(ports_to_service)}, + workers_serviced_{std::move(workers_to_service)}, + from_gcs_{std::move(from_gcs)}, + slow_worker_{worker}, + mempool_{mempool}, + fragmentation_( + SlowWorkerSender(), + slow_worker_->dataPlane->getConfigValues().fragmentation), + dregress_(this, + slow_worker_->dataPlane, + static_cast(slow_worker_->dataPlane->getConfigValues().gc_step)), // @TODO fix mismatch in type of config value and actually used one + config_{sw_icmp_out_rate_limit, use_kni}, + kni_worker_{std::move(kni)} +{ + workers_serviced_.emplace_back(slow_worker_); +} + +SlowWorker::SlowWorker(SlowWorker&& other) : + ports_serviced_{std::move(other.ports_serviced_)}, + workers_serviced_{std::move(other.workers_serviced_)}, + slow_worker_{other.slow_worker_}, + mempool_{other.mempool_}, + fragmentation_{std::move(other.fragmentation_)}, + dregress_{std::move(other.dregress_)}, + kni_worker_{std::move(other.kni_worker_)} +{ + fragmentation_.Callback() = SlowWorkerSender(); +} + +SlowWorker& SlowWorker::operator=(SlowWorker&& other) +{ + ports_serviced_ = std::move(other.ports_serviced_); + workers_serviced_ = std::move(other.workers_serviced_); + slow_worker_ = other.slow_worker_; + mempool_ = other.mempool_; + fragmentation_ = std::move(other.fragmentation_); + fragmentation_.Callback() = SlowWorkerSender(); + dregress_ = std::move(other.dregress_); + kni_worker_ = std::move(other.kni_worker_); + return *this; +} + +void SlowWorker::freeWorkerPacket(rte_ring* ring_to_free_mbuf, + rte_mbuf* mbuf) +{ + if (ring_to_free_mbuf == slow_worker_->ring_toFreePackets) + { + rte_pktmbuf_free(mbuf); + return; + } + + while (rte_ring_sp_enqueue(ring_to_free_mbuf, mbuf) != 0) + { + std::this_thread::yield(); + } +} + +rte_mbuf* SlowWorker::convertMempool(rte_ring* ring_to_free_mbuf, rte_mbuf* old_mbuf) +{ + /// we dont support attached mbufs + + rte_mbuf* mbuf = rte_pktmbuf_alloc(mempool_); + if (!mbuf) + { + stats_.mempool_is_empty++; + + freeWorkerPacket(ring_to_free_mbuf, old_mbuf); + return nullptr; + } + + *YADECAP_METADATA(mbuf) = *YADECAP_METADATA(old_mbuf); + + /// @todo: rte_pktmbuf_append() and check error + + memcpy(rte_pktmbuf_mtod(mbuf, char*), + rte_pktmbuf_mtod(old_mbuf, char*), + old_mbuf->data_len); + + mbuf->data_len = old_mbuf->data_len; + mbuf->pkt_len = old_mbuf->pkt_len; + + freeWorkerPacket(ring_to_free_mbuf, old_mbuf); + + if (rte_mbuf_refcnt_read(mbuf) != 1) + { + YADECAP_LOG_ERROR("something wrong\n"); + } + + return mbuf; +} + +void SlowWorker::SendToSlowWorker(rte_mbuf* mbuf, const common::globalBase::tFlow& flow) +{ + /// we dont support attached mbufs + + if (slow_worker_mbufs_.size() >= 1024) ///< @todo: variable + { + stats_.slowworker_drops++; + rte_pktmbuf_free(mbuf); + return; + } + + stats_.slowworker_packets++; + slow_worker_mbufs_.emplace(mbuf, flow); +} + +unsigned SlowWorker::ring_handle(rte_ring* ring_to_free_mbuf, + rte_ring* ring) +{ + rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + + unsigned rxSize = rte_ring_sc_dequeue_burst(ring, + (void**)mbufs, + CONFIG_YADECAP_MBUFS_BURST_SIZE, + nullptr); + +#ifdef CONFIG_YADECAP_AUTOTEST + if (rxSize) + { + std::this_thread::sleep_for(std::chrono::microseconds{400}); + } +#endif // CONFIG_YADECAP_AUTOTEST + + for (uint16_t mbuf_i = 0; mbuf_i < rxSize; mbuf_i++) + { + rte_mbuf* mbuf = convertMempool(ring_to_free_mbuf, mbufs[mbuf_i]); + if (!mbuf) + { + continue; + } + + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_ingress_icmp) + { + handlePacket_icmp_translate_v6_to_v4(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_ingress_fragmentation) + { + metadata->flow.type = common::globalBase::eFlowType::nat64stateless_ingress_checked; + handlePacket_fragment(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_icmp) + { + handlePacket_icmp_translate_v4_to_v6(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_fragmentation) + { + metadata->flow.type = common::globalBase::eFlowType::nat64stateless_egress_checked; + handlePacket_fragment(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_dregress) + { + handlePacket_dregress(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_nat64stateless_egress_farm) + { + handlePacket_farm(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_dump) + { + kni_worker_.HandlePacketDump(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_repeat) + { + handlePacket_repeat(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_fw_sync) + { + handlePacket_fw_state_sync(mbuf); + } + else if (metadata->flow.type == common::globalBase::eFlowType::slowWorker_balancer_icmp_forward) + { + handlePacket_balancer_icmp_forward(mbuf); + } + else + { + handlePacketFromForwardingPlane(mbuf); + } + } + return rxSize; +} + +void SlowWorker::handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + const auto& base = slow_worker_->current_base(); + const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; + const auto& translation = base.globalBase->nat64statelessTranslations[metadata->flow.data.nat64stateless.translationId]; + + slow_worker_->slowWorkerTranslation(mbuf, nat64stateless, translation, true); + + if (do_icmp_translate_v6_to_v4(mbuf, translation)) + { + slow_worker_->Stats().nat64stateless_ingressPackets++; + SendToSlowWorker(mbuf, nat64stateless.flow); + } + else + { + slow_worker_->Stats().nat64stateless_ingressUnknownICMP++; + rte_pktmbuf_free(mbuf); + } +} + +void SlowWorker::handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + const auto& base = slow_worker_->current_base(); + const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; + const auto& translation = base.globalBase->nat64statelessTranslations[metadata->flow.data.nat64stateless.translationId]; + + slow_worker_->slowWorkerTranslation(mbuf, nat64stateless, translation, false); + + if (do_icmp_translate_v4_to_v6(mbuf, translation)) + { + slow_worker_->Stats().nat64stateless_egressPackets++; + SendToSlowWorker(mbuf, nat64stateless.flow); + } + else + { + slow_worker_->Stats().nat64stateless_egressUnknownICMP++; + rte_pktmbuf_free(mbuf); + } +} + +void SlowWorker::handlePacket_fragment(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + const auto& base = slow_worker_->current_base(); + const auto& nat64stateless = base.globalBase->nat64statelesses[metadata->flow.data.nat64stateless.id]; + + if (nat64stateless.defrag_farm_prefix.empty() || metadata->network_headerType != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) || nat64stateless.farm) + { + fragmentation_.insert(mbuf); + return; + } + + stats_.tofarm_packets++; + slow_worker_->slowWorkerHandleFragment(mbuf); + SendToSlowWorker(mbuf, nat64stateless.flow); +} + +void SlowWorker::handlePacket_dregress(rte_mbuf* mbuf) +{ + dregress_.insert(mbuf); +} + +void SlowWorker::handlePacket_farm(rte_mbuf* mbuf) +{ + stats_.farm_packets++; + slow_worker_->slowWorkerFarmHandleFragment(mbuf); +} + +void SlowWorker::handlePacket_repeat(rte_mbuf* mbuf) +{ + const rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, rte_ether_hdr*); + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) + { + const rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); + + metadata->flow.data.logicalPortId = CALCULATE_LOGICALPORT_ID(metadata->fromPortId, rte_be_to_cpu_16(vlanHeader->vlan_tci)); + } + else + { + metadata->flow.data.logicalPortId = CALCULATE_LOGICALPORT_ID(metadata->fromPortId, 0); + } + + /// @todo: opt + slow_worker_->preparePacket(mbuf); + + const auto& base = slow_worker_->current_base(); + const auto& logicalPort = base.globalBase->logicalPorts[metadata->flow.data.logicalPortId]; + + stats_.repeat_packets++; + SendToSlowWorker(mbuf, logicalPort.flow); +} + +void SlowWorker::handlePacket_fw_state_sync(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + const auto& base = slow_worker_->current_base(); + const auto& fw_state_config = base.globalBase->fw_state_sync_configs[metadata->flow.data.aclId]; + + metadata->network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); + metadata->network_headerOffset = sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr); + metadata->transport_headerType = IPPROTO_UDP; + metadata->transport_headerOffset = metadata->network_headerOffset + sizeof(rte_ipv6_hdr); + + generic_rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, generic_rte_ether_hdr*); + ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); + rte_ether_addr_copy(&fw_state_config.ether_address_destination, ðernetHeader->dst_addr); + + rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); + vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); + + rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); + ipv6Header->vtc_flow = rte_cpu_to_be_32(0x6 << 28); + ipv6Header->payload_len = rte_cpu_to_be_16(sizeof(rte_udp_hdr) + sizeof(dataplane::globalBase::fw_state_sync_frame_t)); + ipv6Header->proto = IPPROTO_UDP; + ipv6Header->hop_limits = 64; + memcpy(ipv6Header->src_addr, fw_state_config.ipv6_address_source.bytes, 16); + memcpy(ipv6Header->dst_addr, fw_state_config.ipv6_address_multicast.bytes, 16); + + rte_udp_hdr* udpHeader = rte_pktmbuf_mtod_offset(mbuf, rte_udp_hdr*, metadata->network_headerOffset + sizeof(rte_ipv6_hdr)); + udpHeader->src_port = fw_state_config.port_multicast; // IPFW reuses the same port for both src and dst. + udpHeader->dst_port = fw_state_config.port_multicast; + udpHeader->dgram_len = rte_cpu_to_be_16(sizeof(rte_udp_hdr) + sizeof(dataplane::globalBase::fw_state_sync_frame_t)); + udpHeader->dgram_cksum = 0; + udpHeader->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6Header, udpHeader); + + // Iterate for all interested ports. + for (unsigned int port_id = 0; port_id < fw_state_config.flows_size; port_id++) + { + rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool_); + if (mbuf_clone == nullptr) + { + slow_worker_->Stats().fwsync_multicast_egress_drops++; + continue; + } + + *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); + + memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), + rte_pktmbuf_mtod(mbuf, char*), + mbuf->data_len); + mbuf_clone->data_len = mbuf->data_len; + mbuf_clone->pkt_len = mbuf->pkt_len; + + const auto& flow = fw_state_config.flows[port_id]; + slow_worker_->Stats().fwsync_multicast_egress_packets++; + SendToSlowWorker(mbuf_clone, flow); + } + + if (!fw_state_config.ipv6_address_unicast.empty()) + { + memcpy(ipv6Header->src_addr, fw_state_config.ipv6_address_unicast_source.bytes, 16); + memcpy(ipv6Header->dst_addr, fw_state_config.ipv6_address_unicast.bytes, 16); + udpHeader->src_port = fw_state_config.port_unicast; + udpHeader->dst_port = fw_state_config.port_unicast; + udpHeader->dgram_cksum = 0; + udpHeader->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6Header, udpHeader); + + rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool_); + if (mbuf_clone == nullptr) + { + slow_worker_->Stats().fwsync_unicast_egress_drops++; + } + else + { + *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); + + memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), + rte_pktmbuf_mtod(mbuf, char*), + mbuf->data_len); + mbuf_clone->data_len = mbuf->data_len; + mbuf_clone->pkt_len = mbuf->pkt_len; + + slow_worker_->Stats().fwsync_unicast_egress_packets++; + SendToSlowWorker(mbuf_clone, fw_state_config.ingress_flow); + } + } + + rte_pktmbuf_free(mbuf); +} + +bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) +{ + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + generic_rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, generic_rte_ether_hdr*); + if ((ethernetHeader->dst_addr.addr_bytes[0] & 1) == 0) + { + return false; + } + + // Confirmed multicast packet. + // Try to match against our multicast groups. + if (ethernetHeader->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) + { + return false; + } + + rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf, rte_vlan_hdr*, sizeof(rte_ether_hdr)); + if (vlanHeader->eth_proto != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) + { + return false; + } + + rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr)); + if (metadata->transport_headerType != IPPROTO_UDP) + { + return false; + } + + const auto udp_payload_len = rte_be_to_cpu_16(ipv6Header->payload_len) - sizeof(rte_udp_hdr); + // Can contain multiple states per sync packet. + if (udp_payload_len % sizeof(dataplane::globalBase::fw_state_sync_frame_t) != 0) + { + return false; + } + + tAclId aclId; + if (!slow_worker_->dataPlane->controlPlane->fw_state_multicast_acl_ids.apply([&](auto& fw_state_multicast_acl_ids) { + auto it = fw_state_multicast_acl_ids.find(common::ipv6_address_t(ipv6Header->dst_addr)); + if (it == fw_state_multicast_acl_ids.end()) + { + return false; + } + aclId = it->second; + return true; + })) + { + return false; + } + + const auto& base = slow_worker_->current_base(); + const auto& fw_state_config = base.globalBase->fw_state_sync_configs[aclId]; + + if (memcmp(ipv6Header->src_addr, fw_state_config.ipv6_address_source.bytes, 16) == 0) + { + // Ignore self-generated packets. + return false; + } + + rte_udp_hdr* udpHeader = rte_pktmbuf_mtod_offset(mbuf, rte_udp_hdr*, sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr) + sizeof(rte_ipv6_hdr)); + if (udpHeader->dst_port != fw_state_config.port_multicast) + { + return false; + } + + for (size_t idx = 0; idx < udp_payload_len / sizeof(dataplane::globalBase::fw_state_sync_frame_t); ++idx) + { + dataplane::globalBase::fw_state_sync_frame_t* payload = rte_pktmbuf_mtod_offset( + mbuf, + dataplane::globalBase::fw_state_sync_frame_t*, + sizeof(rte_ether_hdr) + sizeof(rte_vlan_hdr) + sizeof(rte_ipv6_hdr) + sizeof(rte_udp_hdr) + idx * sizeof(dataplane::globalBase::fw_state_sync_frame_t)); + + if (payload->addr_type == 6) + { + dataplane::globalBase::fw6_state_key_t key; + key.proto = payload->proto; + key.__nap = 0; + // Swap src and dst addresses. + memcpy(key.dst_addr.bytes, payload->src_ip6.bytes, 16); + memcpy(key.src_addr.bytes, payload->dst_ip6.bytes, 16); + + if (payload->proto == IPPROTO_TCP || payload->proto == IPPROTO_UDP) + { + // Swap src and dst ports. + key.dst_port = payload->src_port; + key.src_port = payload->dst_port; + } + else + { + key.dst_port = 0; + key.src_port = 0; + } + + dataplane::globalBase::fw_state_value_t value; + value.type = static_cast(payload->proto); + value.owner = dataplane::globalBase::fw_state_owner_e::external; + value.last_seen = slow_worker_->CurrentTime(); + value.flow = fw_state_config.ingress_flow; + value.acl_id = aclId; + value.last_sync = slow_worker_->CurrentTime(); + value.packets_since_last_sync = 0; + value.packets_backward = 0; + value.packets_forward = 0; + value.tcp.unpack(payload->flags); + + auto& dataPlane = slow_worker_->dataPlane; + uint32_t state_timeout = dataPlane->getConfigValues().stateful_firewall_other_protocols_timeout; + if (payload->proto == IPPROTO_UDP) + { + state_timeout = dataPlane->getConfigValues().stateful_firewall_udp_timeout; + } + else if (payload->proto == IPPROTO_TCP) + { + state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_timeout; + uint8_t flags = value.tcp.src_flags | value.tcp.dst_flags; + if (flags & (uint8_t)common::fwstate::tcp_flags_e::ACK) + { + state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_ack_timeout; + } + else if (flags & (uint8_t)common::fwstate::tcp_flags_e::SYN) + { + state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_syn_timeout; + } + if (flags & (uint8_t)common::fwstate::tcp_flags_e::FIN) + { + state_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_fin_timeout; + } + } + value.state_timeout = state_timeout; + + for (auto& [socketId, globalBaseAtomic] : slow_worker_->dataPlane->globalBaseAtomics) + { + (void)socketId; + + dataplane::globalBase::fw_state_value_t* lookup_value; + dataplane::spinlock_nonrecursive_t* locker; + const uint32_t hash = globalBaseAtomic->fw6_state->lookup(key, lookup_value, locker); + if (lookup_value) + { + // Keep state alive for us even if there were no packets received. + // Do not reset other counters. + lookup_value->last_seen = slow_worker_->CurrentTime(); + lookup_value->tcp.src_flags |= value.tcp.src_flags; + lookup_value->tcp.dst_flags |= value.tcp.dst_flags; + lookup_value->state_timeout = std::max(lookup_value->state_timeout, value.state_timeout); + } + else + { + globalBaseAtomic->fw6_state->insert(hash, key, value); + } + locker->unlock(); + } + } + else if (payload->addr_type == 4) + { + dataplane::globalBase::fw4_state_key_t key; + key.proto = payload->proto; + key.__nap = 0; + // Swap src and dst addresses. + key.dst_addr.address = payload->src_ip; + key.src_addr.address = payload->dst_ip; + + if (payload->proto == IPPROTO_TCP || payload->proto == IPPROTO_UDP) + { + // Swap src and dst ports. + key.dst_port = payload->src_port; + key.src_port = payload->dst_port; + } + else + { + key.dst_port = 0; + key.src_port = 0; + } + + dataplane::globalBase::fw_state_value_t value; + value.type = static_cast(payload->proto); + value.owner = dataplane::globalBase::fw_state_owner_e::external; + value.last_seen = slow_worker_->CurrentTime(); + value.flow = fw_state_config.ingress_flow; + value.acl_id = aclId; + value.last_sync = slow_worker_->CurrentTime(); + value.packets_since_last_sync = 0; + value.packets_backward = 0; + value.packets_forward = 0; + value.tcp.unpack(payload->flags); + + auto& cfg = slow_worker_->dataPlane->getConfigValues(); + uint32_t state_timeout = cfg.stateful_firewall_other_protocols_timeout; + if (payload->proto == IPPROTO_UDP) + { + state_timeout = cfg.stateful_firewall_udp_timeout; + } + else if (payload->proto == IPPROTO_TCP) + { + state_timeout = cfg.stateful_firewall_tcp_timeout; + uint8_t flags = value.tcp.src_flags | value.tcp.dst_flags; + if (flags & (uint8_t)common::fwstate::tcp_flags_e::ACK) + { + state_timeout = cfg.stateful_firewall_tcp_syn_ack_timeout; + } + else if (flags & (uint8_t)common::fwstate::tcp_flags_e::SYN) + { + state_timeout = cfg.stateful_firewall_tcp_syn_timeout; + } + if (flags & (uint8_t)common::fwstate::tcp_flags_e::FIN) + { + state_timeout = cfg.stateful_firewall_tcp_fin_timeout; + } + } + value.state_timeout = state_timeout; + + for (auto& [socketId, globalBaseAtomic] : slow_worker_->dataPlane->globalBaseAtomics) + { + (void)socketId; + + dataplane::globalBase::fw_state_value_t* lookup_value; + dataplane::spinlock_nonrecursive_t* locker; + const uint32_t hash = globalBaseAtomic->fw4_state->lookup(key, lookup_value, locker); + if (lookup_value) + { + // Keep state alive for us even if there were no packets received. + // Do not reset other counters. + lookup_value->last_seen = slow_worker_->CurrentTime(); + lookup_value->tcp.src_flags |= value.tcp.src_flags; + lookup_value->tcp.dst_flags |= value.tcp.dst_flags; + lookup_value->state_timeout = std::max(lookup_value->state_timeout, value.state_timeout); + } + else + { + globalBaseAtomic->fw4_state->insert(hash, key, value); + } + locker->unlock(); + } + } + } + + return true; +} + +void SlowWorker::BalancerICMPForwardCriticalSection( + rte_mbuf* mbuf, + cControlPlane::VipToBalancers& vip_to_balancers, + cControlPlane::VipVportProto& vip_vport_proto) +{ + const auto& base = slow_worker_->current_base(); + + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + common::ip_address_t original_src_from_icmp_payload; + common::ip_address_t src_from_ip_header; + uint16_t original_src_port_from_icmp_payload; + + uint32_t balancer_id = metadata->flow.data.balancer.id; + + dataplane::metadata inner_metadata; + + if (metadata->transport_headerType == IPPROTO_ICMP) + { + rte_ipv4_hdr* ipv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); + src_from_ip_header = common::ip_address_t(rte_be_to_cpu_32(ipv4Header->src_addr)); + + rte_ipv4_hdr* icmpPayloadIpv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->transport_headerOffset + sizeof(icmpv4_header_t)); + original_src_from_icmp_payload = common::ip_address_t(rte_be_to_cpu_32(icmpPayloadIpv4Header->src_addr)); + + inner_metadata.network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + inner_metadata.network_headerOffset = metadata->transport_headerOffset + sizeof(icmpv4_header_t); + } + else + { + rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); + src_from_ip_header = common::ip_address_t(ipv6Header->src_addr); + + rte_ipv6_hdr* icmpPayloadIpv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->transport_headerOffset + sizeof(icmpv6_header_t)); + original_src_from_icmp_payload = common::ip_address_t(icmpPayloadIpv6Header->src_addr); + + inner_metadata.network_headerType = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); + inner_metadata.network_headerOffset = metadata->transport_headerOffset + sizeof(icmpv6_header_t); + } + + if (!prepareL3(mbuf, &inner_metadata)) + { + /* we are not suppossed to get in here anyway, same check was done earlier by balancer_icmp_forward_handle(), + but we needed to call prepareL3() to determine icmp payload original packets transport header offset */ + if (inner_metadata.network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_ip); + } + else + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_ip); + } + + return; + } + + if (inner_metadata.transport_headerType != IPPROTO_TCP && inner_metadata.transport_headerType != IPPROTO_UDP) + { + // not supported protocol for cloning and distributing, drop + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_unexpected_transport_protocol); + return; + } + + // check whether ICMP payload is too short to contain "offending" packet's IP header and ports is performed earlier by balancer_icmp_forward_handle() + void* icmpPayloadTransportHeader = rte_pktmbuf_mtod_offset(mbuf, void*, inner_metadata.transport_headerOffset); + + // both TCP and UDP headers have src port (16 bits) as the first field + original_src_port_from_icmp_payload = rte_be_to_cpu_16(*(uint16_t*)icmpPayloadTransportHeader); + + if (vip_to_balancers.size() <= balancer_id) + { + // no vip_to_balancers table for this balancer_id + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_no_unrdup_table_for_balancer_id); + return; + } + + if (!vip_to_balancers[balancer_id].count(original_src_from_icmp_payload)) + { + // vip is not listed in unrdup config - neighbor balancers are unknown, drop + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_unrdup_vip_not_found); + return; + } + + if (vip_vport_proto.size() <= balancer_id) + { + // no vip_vport_proto table for this balancer_id + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id); + return; + } + + if (!vip_vport_proto[balancer_id].count({original_src_from_icmp_payload, original_src_port_from_icmp_payload, inner_metadata.transport_headerType})) + { + // such combination of vip-vport-protocol is absent, don't clone, drop + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_drop_unknown_service); + return; + } -SlowWorker::SlowWorker(cControlPlane* cplane) : - cplane_{cplane} {} -const dataplane::base::generation& SlowWorker::current_base() + const auto& neighbor_balancers = vip_to_balancers[balancer_id][original_src_from_icmp_payload]; + + for (const auto& neighbor_balancer : neighbor_balancers) + { + // will not send a cloned packet if source address in "balancer" section of controlplane.conf is absent + if (neighbor_balancer.is_ipv4() && !base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv4.address) + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv4); + continue; + } + + if (neighbor_balancer.is_ipv6() && base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv6.empty()) + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv6); + continue; + } + + rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool_); + if (mbuf_clone == nullptr) + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_failed_to_clone); + continue; + } + + *YADECAP_METADATA(mbuf_clone) = *YADECAP_METADATA(mbuf); + dataplane::metadata* clone_metadata = YADECAP_METADATA(mbuf_clone); + + rte_memcpy(rte_pktmbuf_mtod(mbuf_clone, char*), + rte_pktmbuf_mtod(mbuf, char*), + mbuf->data_len); + + if (neighbor_balancer.is_ipv4()) + { + rte_pktmbuf_prepend(mbuf_clone, sizeof(rte_ipv4_hdr)); + memmove(rte_pktmbuf_mtod(mbuf_clone, char*), + rte_pktmbuf_mtod_offset(mbuf_clone, char*, sizeof(rte_ipv4_hdr)), + clone_metadata->network_headerOffset); + + rte_ipv4_hdr* outerIpv4Header = rte_pktmbuf_mtod_offset(mbuf_clone, rte_ipv4_hdr*, clone_metadata->network_headerOffset); + + outerIpv4Header->src_addr = base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv4.address; + outerIpv4Header->dst_addr = rte_cpu_to_be_32(neighbor_balancer.get_ipv4()); + + outerIpv4Header->version_ihl = 0x45; + outerIpv4Header->type_of_service = 0x00; + outerIpv4Header->packet_id = rte_cpu_to_be_16(0x01); + outerIpv4Header->fragment_offset = 0; + outerIpv4Header->time_to_live = 64; + + outerIpv4Header->total_length = rte_cpu_to_be_16((uint16_t)(mbuf->pkt_len - clone_metadata->network_headerOffset + sizeof(rte_ipv4_hdr))); + + if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) + { + outerIpv4Header->next_proto_id = IPPROTO_IPIP; + } + else + { + outerIpv4Header->next_proto_id = IPPROTO_IPV6; + } + + yanet_ipv4_checksum(outerIpv4Header); + + mbuf_clone->data_len = mbuf->data_len + sizeof(rte_ipv4_hdr); + mbuf_clone->pkt_len = mbuf->pkt_len + sizeof(rte_ipv4_hdr); + + // might need to change next protocol type in ethernet/vlan header in cloned packet + + rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf_clone, rte_ether_hdr*); + if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) + { + rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf_clone, rte_vlan_hdr*, sizeof(rte_ether_hdr)); + vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + } + else + { + ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + } + } + else if (neighbor_balancer.is_ipv6()) + { + rte_pktmbuf_prepend(mbuf_clone, sizeof(rte_ipv6_hdr)); + memmove(rte_pktmbuf_mtod(mbuf_clone, char*), + rte_pktmbuf_mtod_offset(mbuf_clone, char*, sizeof(rte_ipv6_hdr)), + clone_metadata->network_headerOffset); + + rte_ipv6_hdr* outerIpv6Header = rte_pktmbuf_mtod_offset(mbuf_clone, rte_ipv6_hdr*, clone_metadata->network_headerOffset); + + rte_memcpy(outerIpv6Header->src_addr, base.globalBase->balancers[metadata->flow.data.balancer.id].source_ipv6.bytes, sizeof(outerIpv6Header->src_addr)); + if (src_from_ip_header.is_ipv6()) + { + ((uint32_t*)outerIpv6Header->src_addr)[2] = ((uint32_t*)src_from_ip_header.get_ipv6().data())[2] ^ ((uint32_t*)src_from_ip_header.get_ipv6().data())[3]; + } + else + { + ((uint32_t*)outerIpv6Header->src_addr)[2] = src_from_ip_header.get_ipv4(); + } + rte_memcpy(outerIpv6Header->dst_addr, neighbor_balancer.get_ipv6().data(), sizeof(outerIpv6Header->dst_addr)); + + outerIpv6Header->vtc_flow = rte_cpu_to_be_32((0x6 << 28)); + outerIpv6Header->payload_len = rte_cpu_to_be_16((uint16_t)(mbuf->pkt_len - clone_metadata->network_headerOffset)); + outerIpv6Header->hop_limits = 64; + + if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) + { + outerIpv6Header->proto = IPPROTO_IPIP; + } + else + { + outerIpv6Header->proto = IPPROTO_IPV6; + } + + mbuf_clone->data_len = mbuf->data_len + sizeof(rte_ipv6_hdr); + mbuf_clone->pkt_len = mbuf->pkt_len + sizeof(rte_ipv6_hdr); + + // might need to change next protocol type in ethernet/vlan header in cloned packet + + rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf_clone, rte_ether_hdr*); + if (ethernetHeader->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) + { + rte_vlan_hdr* vlanHeader = rte_pktmbuf_mtod_offset(mbuf_clone, rte_vlan_hdr*, sizeof(rte_ether_hdr)); + vlanHeader->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); + } + else + { + ethernetHeader->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); + } + } + + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_clone_forwarded); + + const auto& flow = base.globalBase->balancers[metadata->flow.data.balancer.id].flow; + + slow_worker_->preparePacket(mbuf_clone); + SendToSlowWorker(mbuf_clone, flow); + } +} + +void SlowWorker::handlePacket_balancer_icmp_forward(rte_mbuf* mbuf) +{ + if (config_.SWICMPOutRateLimit != 0) + { + if (icmp_out_remainder_ == 0) + { + slow_worker_->IncrementCounter(common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached); + rte_pktmbuf_free(mbuf); + return; + } + + --icmp_out_remainder_; + } + + slow_worker_->dataPlane->controlPlane->vip_to_balancers.apply([&](auto& vip_to_balancers) { + slow_worker_->dataPlane->controlPlane->vip_vport_proto.apply([&](auto& vip_vport_proto) { + BalancerICMPForwardCriticalSection(mbuf, vip_to_balancers, vip_vport_proto); + }); + }); + + // packet itself is not going anywhere, only its clones with prepended header + rte_pktmbuf_free(mbuf); +} + +void SlowWorker::handlePacketFromForwardingPlane(rte_mbuf* mbuf) { - return cplane_->slowWorker->current_base(); + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + if (handlePacket_fw_state_sync_ingress(mbuf)) + { + stats_.fwsync_multicast_ingress_packets++; + rte_pktmbuf_free(mbuf); + return; + } + +#ifdef CONFIG_YADECAP_AUTOTEST + if (metadata->flow.type != common::globalBase::eFlowType::slowWorker_kni_local) + { + // drop by default in tests + stats_.slowworker_drops++; + rte_pktmbuf_free(mbuf); + return; + } + rte_ether_hdr* ethernetHeader = rte_pktmbuf_mtod(mbuf, rte_ether_hdr*); + memset(ethernetHeader->dst_addr.addr_bytes, + 0x71, + 6); + +#endif + + if (!config_.use_kernel_interface) + { + // TODO stats + unsigned txSize = rte_eth_tx_burst(metadata->fromPortId, 0, &mbuf, 1); + if (!txSize) + { + rte_pktmbuf_free(mbuf); + } + return; + } + else + { + kni_worker_.HandlePacketFromForwardingPlane(mbuf); + } } -void SlowWorker::SendToSlowWorker(rte_mbuf* pkt, const common::globalBase::tFlow& flow) + +void SlowWorker::HandleWorkerRings() { - cplane_->sendPacketToSlowWorker(pkt, flow); + for (unsigned nIter = 0; nIter < YANET_CONFIG_RING_PRIORITY_RATIO; nIter++) + { + for (unsigned hIter = 0; hIter < YANET_CONFIG_RING_PRIORITY_RATIO; hIter++) + { + unsigned hProcessed = 0; + for (cWorker* worker : workers_serviced_) + { + hProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_highPriority); + } + if (!hProcessed) + { + break; + } + } + + unsigned nProcessed = 0; + for (cWorker* worker : workers_serviced_) + { + nProcessed += ring_handle(worker->ring_toFreePackets, worker->ring_normalPriority); + } + if (!nProcessed) + { + break; + } + } + for (cWorker* worker : workers_serviced_) + { + ring_handle(worker->ring_toFreePackets, worker->ring_lowPriority); + } } -void SlowWorker::PreparePacket(rte_mbuf* pkt) + +void SlowWorker::DequeueGC() { - cplane_->slowWorker->preparePacket(pkt); + for (auto& [process, free] : from_gcs_) + { + rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; + + unsigned rxSize = process.DequeueBurstSC(mbufs); + + for (uint16_t mbuf_i = 0; mbuf_i < rxSize; mbuf_i++) + { + rte_mbuf* mbuf = convertMempool(free._Underlying(), mbufs[mbuf_i]); + if (!mbuf) + { + continue; + } + + dataplane::metadata* metadata = YADECAP_METADATA(mbuf); + + SendToSlowWorker(mbuf, metadata->flow); + } + } } -} // dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/slow_worker.h b/dataplane/slow_worker.h index 04ebdead..bd1791af 100644 --- a/dataplane/slow_worker.h +++ b/dataplane/slow_worker.h @@ -1,22 +1,144 @@ #pragma once -#include "base.h" +#include +#include +#include -class cControlPlane; +#include "dpdk.h" +#include "dregress.h" +#include "fragmentation.h" +#include "kernel_interface_handler.h" +#include "worker.h" namespace dataplane { -/* - * Stub of SlowWorker to divide refactoring dregress and cControlPlane - */ class SlowWorker { - cControlPlane* cplane_; public: - explicit SlowWorker(cControlPlane* cplane); - const dataplane::base::generation& current_base(); - void SendToSlowWorker(rte_mbuf* pkt, const common::globalBase::tFlow& flow); - void PreparePacket(rte_mbuf* pkt); + struct Config + { + uint32_t SWICMPOutRateLimit = 0; + bool use_kernel_interface; + }; + +private: + std::vector ports_serviced_; + std::vector workers_serviced_; + std::vector> from_gcs_; + cWorker* slow_worker_; + std::queue> slow_worker_mbufs_; + rte_mempool* mempool_; // from cControlPlane + common::slowworker::stats_t stats_; + fragmentation::Fragmentation fragmentation_; + dregress_t dregress_; + uint32_t icmp_out_remainder_; + Config config_; + dataplane::KernelInterfaceWorker kni_worker_; + + auto SlowWorkerSender() + { + return [this](rte_mbuf* pkt, const common::globalBase::tFlow& flow) { + SendToSlowWorker(pkt, flow); + }; + } + using VipToBalancers = std::vector>>; + using VipVportProto = std::vector, uint8_t>>>; + void BalancerICMPForwardCriticalSection( + rte_mbuf* mbuf, + VipToBalancers& vip_to_balancers, + VipVportProto& vip_vport_proto); + +public: + SlowWorker(cWorker* worker, + std::vector&& ports_to_service, + std::vector&& workers_to_service, + std::vector>&& from_gcs, + KernelInterfaceWorker&& kni, + rte_mempool* mempool, + bool use_kni, + uint32_t sw_icmp_out_rate_limit); + SlowWorker(const SlowWorker&) = delete; + SlowWorker(SlowWorker&& other); + SlowWorker& operator=(const SlowWorker&) = delete; + SlowWorker& operator=(SlowWorker&& other); + + cWorker* GetWorker() { return slow_worker_; } + const dataplane::KernelInterfaceWorker& KniWorker() const { return kni_worker_; } + const dataplane::base::generation& current_base() { return slow_worker_->current_base(); } + const fragmentation::Fragmentation& Fragmentation() const { return fragmentation_; } + dregress_t& Dregress() { return dregress_; } + const dregress_t& Dregress() const { return dregress_; } + void freeWorkerPacket(rte_ring* ring_to_free_mbuf, rte_mbuf* mbuf); + rte_mbuf* convertMempool(rte_ring* ring_to_free_mbuf, rte_mbuf* old_mbuf); + rte_mempool* Mempool() { return mempool_; } + void PreparePacket(rte_mbuf* mbuf) { slow_worker_->preparePacket(mbuf); } + void SendToSlowWorker(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); + void ResetIcmpOutRemainder(uint32_t limit) { icmp_out_remainder_ = limit; } + + const common::slowworker::stats_t& Stats() const { return stats_; } + unsigned ring_handle(rte_ring* ring_to_free_mbuf, rte_ring* ring); + void handlePacket_icmp_translate_v6_to_v4(rte_mbuf* mbuf); + void handlePacket_icmp_translate_v4_to_v6(rte_mbuf* mbuf); + void handlePacket_fragment(rte_mbuf* mbuf); + void handlePacket_dregress(rte_mbuf* mbuf); + void handlePacket_farm(rte_mbuf* mbuf); + void handlePacket_repeat(rte_mbuf* mbuf); + void handlePacket_fw_state_sync(rte_mbuf* mbuf); + bool handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf); + void handlePacket_balancer_icmp_forward(rte_mbuf* mbuf); + void handlePacketFromForwardingPlane(rte_mbuf* mbuf); + void HandleWorkerRings(); + + // \brief dequeue packets from worker_gc's ring to slowworker + void DequeueGC(); + + void Iteration() + { + slow_worker_->slowWorkerBeforeHandlePackets(); + + HandleWorkerRings(); + + if (config_.use_kernel_interface) + { + kni_worker_.Flush(); + } + + DequeueGC(); + fragmentation_.handle(); + dregress_.handle(); + + if (config_.use_kernel_interface) + { + kni_worker_.ForwardToPhy(); + kni_worker_.RecvFree(); + } + + /// push packets to slow worker + while (!slow_worker_mbufs_.empty()) + { + for (unsigned int i = 0; + i < CONFIG_YADECAP_MBUFS_BURST_SIZE; + i++) + { + if (slow_worker_mbufs_.empty()) + { + break; + } + + auto& tuple = slow_worker_mbufs_.front(); + slow_worker_->slowWorkerFlow(std::get<0>(tuple), std::get<1>(tuple)); + + slow_worker_mbufs_.pop(); + } + + slow_worker_->slowWorkerHandlePackets(); + } + + slow_worker_->slowWorkerAfterHandlePackets(); +#ifdef CONFIG_YADECAP_AUTOTEST + std::this_thread::sleep_for(std::chrono::microseconds{1}); +#endif // CONFIG_YADECAP_AUTOTEST + } }; -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/work_runner.h b/dataplane/work_runner.h new file mode 100644 index 00000000..8c033ae1 --- /dev/null +++ b/dataplane/work_runner.h @@ -0,0 +1,71 @@ +#pragma once +#include +#include +#include + +namespace dpdk +{ + +namespace internal +{ +template +void CallIteration(F* f) +{ + f->Iteration(); +} + +template +void CallIteration(F f) +{ + f.Iteration(); +} + +} // namespace internal + +template +class WorkRunner +{ + std::tuple m_workers; + template + void Iteration() + { + if constexpr (I != sizeof...(Workloads)) + { + internal::CallIteration(std::get(m_workers)); + Iteration(); + } + } + +public: + void Run() + { + while (true) + { + Iteration(); + } + } + WorkRunner(Workloads... loads) : + m_workers{loads...} + { + } +}; + +template +class Sleeper +{ +public: + void Iteration() + { + std::this_thread::sleep_for(Duration{duration_value}); + } +}; + +struct Yielder +{ + void Iteration() + { + std::this_thread::yield(); + } +}; + +} // namespace dpdk \ No newline at end of file diff --git a/dataplane/worker.h b/dataplane/worker.h index 15024ddc..cfcf44f6 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -67,12 +67,11 @@ class cWorker ~cWorker(); eResult init(const tCoreId& coreId, const dataplane::base::permanently& basePermanently, const dataplane::base::generation& base); - void start(); void fillStatsNamesToAddrsTable(std::unordered_map& table); - const dataplane::base::generation& current_base() { return bases[localBaseId & 1]; } + const dataplane::base::generation& current_base() const { return bases[localBaseId & 1]; } protected: eResult sanityCheck(); @@ -221,15 +220,21 @@ class cWorker protected: /// @todo: move to slow_worker_t +public: YANET_NEVER_INLINE void slowWorkerBeforeHandlePackets(); YANET_NEVER_INLINE void slowWorkerHandlePackets(); + YANET_NEVER_INLINE void slowWorkerHandleFragment(rte_mbuf* mbuf); YANET_NEVER_INLINE void slowWorkerFarmHandleFragment(rte_mbuf* mbuf); + YANET_NEVER_INLINE void slowWorkerAfterHandlePackets(); + YANET_NEVER_INLINE void slowWorkerFlow(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); YANET_NEVER_INLINE void slowWorkerTranslation(rte_mbuf* mbuf, const dataplane::globalBase::tNat64stateless& nat64stateless, const dataplane::globalBase::nat64stateless_translation_t& translation, bool direction); /** true: ingress, false: egress */ + const dataplane::base::generation& CurrentBase() { return bases[localBaseId & 1]; } + void IncrementCounter(common::globalBase::static_counter_type type) { counters[(uint32_t)type]++; } + uint32_t CurrentTime() const { return basePermanently.globalBaseAtomic->currentTime; } -public: friend class cDataPlane; friend class cReport; friend class cControlPlane; @@ -329,12 +334,15 @@ class cWorker worker::tStack<> after_early_decap_stack4; worker::tStack<> after_early_decap_stack6; +public: rte_ring* ring_highPriority; rte_ring* ring_normalPriority; rte_ring* ring_lowPriority; dataplane::perf::tsc_deltas* tsc_deltas; rte_ring* ring_toFreePackets; + common::worker::stats::common& Stats() { return stats; } +protected: rte_ring* ring_log; common::worker::stats::common stats; From cf622792f637a7bb5b701e0afad6c994a04c38d3 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 1 Jul 2024 22:21:46 +0300 Subject: [PATCH 061/195] Do not perform check-state on drop action Removed the logic that was performing check-state on drop actions. This behavior does not align with how ipfw works, where a proper check-state rule is required to check state. Unittests relying on the previous behavior will be fixed later. --- dataplane/action_dispatcher.h | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index ac7aad1e..d0c76aaa 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -94,27 +94,6 @@ struct ActionDispatcher auto worker = args.worker; auto mbuf = args.mbuf; - if (action.flow.type == common::globalBase::eFlowType::drop) - { - // Try to match against stateful dynamic rules. If so - a packet will be handled. - if constexpr (Direction == FlowDirection::Egress) - { - if (auto flow = worker->acl_egress_checkstate(mbuf); flow) - { - worker->acl_egress_flow(mbuf, flow.value()); - return; - } - } - else - { - if (auto flow = worker->acl_checkstate(mbuf); flow) - { - worker->acl_ingress_flow(mbuf, flow.value()); - return; - } - } - } - worker->aclCounters[action.flow.counter_id]++; tAclId acl_id = 0; From 90bdef0f83b1f8a40b7ea1103cba6887a8e0cb2f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 3 Jul 2024 21:59:13 +0300 Subject: [PATCH 062/195] Update firewall rules in autotests to include check-state Previously if the packet should be dropped, the state was being checked and if it was found the packet would not be dropped. This behavior was incorrect according to the ipfw-like semantics. Now, the behavior has been updated to be ipfw-like, meaning state checking is not performed unless a check-state rule is explicitly matched. --- autotest/units/001_one_port/036_firewall_keepstate/firewall.txt | 1 + .../001_one_port/037_firewall_keepstate_with_sync/firewall.txt | 1 + .../039_firewall_keepstate_with_sync_tcp/firewall.txt | 1 + .../040_firewall_keepstate_with_sync_mixed/firewall.txt | 1 + .../firewall.txt | 1 + .../units/001_one_port/050_firewall_state_resend/firewall.txt | 1 + .../051_firewall_keepstate_with_sync_unicast/firewall.txt | 1 + autotest/units/001_one_port/052_firewall_samples/firewall.txt | 1 + 8 files changed, 8 insertions(+) diff --git a/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt b/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt index 38585f7c..16de46b8 100644 --- a/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt +++ b/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow udp from 11.0.0.0/24 to any 53 keep-state add allow udp from any to 2a03:6b8:ff1c:2030::/60 53 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt index aabcef63..f6ccd41e 100644 --- a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt +++ b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow udp from 10.0.0.0/24 to any 53 keep-state add allow udp from any to 2121:bbb8:ff1c:2030::/60 53 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt index f23b28e8..bfb1c8bd 100644 --- a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt +++ b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow tcp from 12.0.0.0/24 to any 12345 keep-state add allow tcp from any to 2a22:6b8:ff1c:2030::/60 12345 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt index 7ba1b01a..006dd4db 100644 --- a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt +++ b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt @@ -5,4 +5,5 @@ add skipto :IN ip from any to any in add allow ip from 13.0.0.0/24 to any keep-state add allow ip from any to 2332:898:ff1c:2030::/64 keep-state add allow tcp from 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: to 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: 10053 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall.txt b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall.txt index b26438d7..75176e15 100644 --- a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall.txt +++ b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall.txt @@ -1,3 +1,4 @@ :BEGIN +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt b/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt index 9554503a..30bd0e70 100644 --- a/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt +++ b/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow udp from 10.0.0.0/24 to any 53 keep-state add allow udp from any to 2020:ddd:ff1c:2030::/60 53 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt index 539109ae..07bd7ff1 100644 --- a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt +++ b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow tcp from 12.0.0.0/24 to any 12345 keep-state add allow tcp from any to 2220:ddd:ff1c:2030::/60 12345 keep-state +add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/052_firewall_samples/firewall.txt b/autotest/units/001_one_port/052_firewall_samples/firewall.txt index d9986a09..aa8609f8 100644 --- a/autotest/units/001_one_port/052_firewall_samples/firewall.txt +++ b/autotest/units/001_one_port/052_firewall_samples/firewall.txt @@ -4,4 +4,5 @@ add skipto :IN ip from any to any in :IN add allow tcp from 11.0.0.0/24 to any 53 keep-state add allow tcp from any to 2111:aaa:ff1c:2030::/60 53 keep-state +add check-state add deny ip from any to any From 55c08dc08bfac8aed3406a9476975921e5084f95 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 4 Jul 2024 14:37:15 +0300 Subject: [PATCH 063/195] Change keep-state with record-state in whole project In YANET the keep-state directive only stores the state of packets, similar to ipfw's record-state, and does not include an implicit check-state for all packets like in ipfw. So we rename keep-state to record-state to accurately reflect its function. Closes #166 --- .../036_firewall_keepstate/firewall.txt | 4 ++-- .../firewall.txt | 4 ++-- .../firewall.txt | 4 ++-- .../firewall.txt | 6 ++--- .../045_firewall_out/firewall.txt | 2 +- .../050_firewall_state_resend/firewall.txt | 4 ++-- .../firewall.txt | 4 ++-- .../052_firewall_samples/firewall.txt | 4 ++-- .../059_firewall_tablearg/firewall.conf.txt | 2 +- cli/acl.h | 12 +++++----- cli/main.cpp | 2 +- common/icp.h | 2 +- common/type.h | 2 +- controlplane/acl.cpp | 18 +++++++-------- controlplane/acl.h | 2 +- controlplane/acl/rule.h | 22 +++++++++---------- controlplane/controlplane.cpp | 4 ++-- controlplane/unittest/parser.cpp | 6 ++--- dataplane/action_dispatcher.h | 4 ++-- dataplane/worker.cpp | 2 +- dataplane/worker.h | 2 +- libfwparser/fw_config.cpp | 4 ++-- libfwparser/fw_config.h | 4 ++-- libfwparser/fw_parser.y | 12 +++++----- libfwparser/token.l | 2 +- parser/fw_dump.cpp | 2 +- 26 files changed, 68 insertions(+), 68 deletions(-) diff --git a/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt b/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt index 16de46b8..dd8d6708 100644 --- a/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt +++ b/autotest/units/001_one_port/036_firewall_keepstate/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow udp from 11.0.0.0/24 to any 53 keep-state -add allow udp from any to 2a03:6b8:ff1c:2030::/60 53 keep-state +add allow udp from 11.0.0.0/24 to any 53 record-state +add allow udp from any to 2a03:6b8:ff1c:2030::/60 53 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt index f6ccd41e..ffaa4284 100644 --- a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt +++ b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow udp from 10.0.0.0/24 to any 53 keep-state -add allow udp from any to 2121:bbb8:ff1c:2030::/60 53 keep-state +add allow udp from 10.0.0.0/24 to any 53 record-state +add allow udp from any to 2121:bbb8:ff1c:2030::/60 53 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt index bfb1c8bd..084006e1 100644 --- a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt +++ b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow tcp from 12.0.0.0/24 to any 12345 keep-state -add allow tcp from any to 2a22:6b8:ff1c:2030::/60 12345 keep-state +add allow tcp from 12.0.0.0/24 to any 12345 record-state +add allow tcp from any to 2a22:6b8:ff1c:2030::/60 12345 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt index 006dd4db..c68ee906 100644 --- a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt +++ b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall.txt @@ -2,8 +2,8 @@ add skipto :IN ip from any to any in :IN -add allow ip from 13.0.0.0/24 to any keep-state -add allow ip from any to 2332:898:ff1c:2030::/64 keep-state -add allow tcp from 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: to 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: 10053 keep-state +add allow ip from 13.0.0.0/24 to any record-state +add allow ip from any to 2332:898:ff1c:2030::/64 record-state +add allow tcp from 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: to 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: 10053 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/045_firewall_out/firewall.txt b/autotest/units/001_one_port/045_firewall_out/firewall.txt index 39d1f64b..2f4949f6 100644 --- a/autotest/units/001_one_port/045_firewall_out/firewall.txt +++ b/autotest/units/001_one_port/045_firewall_out/firewall.txt @@ -38,7 +38,7 @@ add deny ip from any to any :SKP2 add allow tcp from f805@2222:898:c00::/40 to { 2222:898:bf00:400::1 } 443 -add allow tcp from f805@2222:898:c00::/40 to { 2222:898:bf00:400::2 } 443 keep-state +add allow tcp from f805@2222:898:c00::/40 to { 2222:898:bf00:400::2 } 443 record-state add allow ip from any to any frag add deny tcp from any to any tcpflags rst diff --git a/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt b/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt index 30bd0e70..1959f6e5 100644 --- a/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt +++ b/autotest/units/001_one_port/050_firewall_state_resend/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow udp from 10.0.0.0/24 to any 53 keep-state -add allow udp from any to 2020:ddd:ff1c:2030::/60 53 keep-state +add allow udp from 10.0.0.0/24 to any 53 record-state +add allow udp from any to 2020:ddd:ff1c:2030::/60 53 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt index 07bd7ff1..dc5cdb30 100644 --- a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt +++ b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow tcp from 12.0.0.0/24 to any 12345 keep-state -add allow tcp from any to 2220:ddd:ff1c:2030::/60 12345 keep-state +add allow tcp from 12.0.0.0/24 to any 12345 record-state +add allow tcp from any to 2220:ddd:ff1c:2030::/60 12345 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/052_firewall_samples/firewall.txt b/autotest/units/001_one_port/052_firewall_samples/firewall.txt index aa8609f8..8659e613 100644 --- a/autotest/units/001_one_port/052_firewall_samples/firewall.txt +++ b/autotest/units/001_one_port/052_firewall_samples/firewall.txt @@ -2,7 +2,7 @@ add skipto :IN ip from any to any in :IN -add allow tcp from 11.0.0.0/24 to any 53 keep-state -add allow tcp from any to 2111:aaa:ff1c:2030::/60 53 keep-state +add allow tcp from 11.0.0.0/24 to any 53 record-state +add allow tcp from any to 2111:aaa:ff1c:2030::/60 53 record-state add check-state add deny ip from any to any diff --git a/autotest/units/001_one_port/059_firewall_tablearg/firewall.conf.txt b/autotest/units/001_one_port/059_firewall_tablearg/firewall.conf.txt index e8c2346d..66f4d26d 100644 --- a/autotest/units/001_one_port/059_firewall_tablearg/firewall.conf.txt +++ b/autotest/units/001_one_port/059_firewall_tablearg/firewall.conf.txt @@ -35,5 +35,5 @@ add deny log logamount 500 all from any to any :TUN64_SKP5 add deny tcp from any to any setup add allow udp from any src-port 53 to any dst-port 1025-65535 -add allow ip from any to any keep-state in +add allow ip from any to any record-state in add deny log logamount 500 all from any to any diff --git a/cli/acl.h b/cli/acl.h index 719b098d..7579300f 100644 --- a/cli/acl.h +++ b/cli/acl.h @@ -25,7 +25,7 @@ void unwind(const std::string& in_module, std::optional transport_source, std::optional transport_destination, std::optional transport_flags, - std::optional keepstate) + std::optional recordstate) { std::optional module = in_module; @@ -38,7 +38,7 @@ void unwind(const std::string& in_module, optional_helper(transport_source); optional_helper(transport_destination); optional_helper(transport_flags); - optional_helper(keepstate); + optional_helper(recordstate); interface::controlPlane controlplane; auto response = controlplane.acl_unwind({module, @@ -50,7 +50,7 @@ void unwind(const std::string& in_module, transport_source, transport_destination, transport_flags, - keepstate}); + recordstate}); table_t table({.optional_null = "any"}); table.insert("module", @@ -62,12 +62,12 @@ void unwind(const std::string& in_module, "transport_source", "transport_destination", "transport_flags", - "keepstate", + "recordstate", "next_module", "ids", "log"); - for (const auto& [module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, keepstate, next_module, ids, log] : response) + for (const auto& [module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, recordstate, next_module, ids, log] : response) { table.insert(module, direction, @@ -78,7 +78,7 @@ void unwind(const std::string& in_module, transport_source, transport_destination, transport_flags, - keepstate, + recordstate, next_module, ids, log); diff --git a/cli/main.cpp b/cli/main.cpp index e76751f3..ccd74548 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -39,7 +39,7 @@ std::vector ", [](const auto& args) { call(acl::unwind, args); }}, + {"acl unwind", "[module] ", [](const auto& args) { call(acl::unwind, args); }}, {"acl lookup", " ", [](const auto& args) { call(acl::lookup, args); }}, {"decap", "", [](const auto& args) { call(show::decap::summary, args); }}, {"decap announce", "", [](const auto& args) { call(show::decap::announce, args); }}, diff --git a/common/icp.h b/common/icp.h index 093e8526..39091d6b 100644 --- a/common/icp.h +++ b/common/icp.h @@ -727,7 +727,7 @@ using request = std::tuple, ///< module std::optional, ///< transport_source std::optional, ///< transport_destination std::optional, ///< transport_flags - std::optional>; ///< keepstate + std::optional>; ///< recordstate using response = std::vector, std::optional, diff --git a/common/type.h b/common/type.h index 6c7276da..bc7e4e74 100644 --- a/common/type.h +++ b/common/type.h @@ -2249,7 +2249,7 @@ inline const char* eFlowType_toString(eFlowType t) enum class eFlowFlags : uint8_t { - keepstate = 1, + recordstate = 1, log = 2, }; diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 7e337291..d767dbf9 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -569,7 +569,7 @@ unwind_result unwind(const std::map& acl const std::optional& transport_source, const std::optional& transport_destination, const std::optional& transport_flags, - const std::optional& in_keepstate) + const std::optional& in_recordstate) { (void)module; @@ -664,7 +664,7 @@ unwind_result unwind(const std::map& acl std::string transport_source = "any"; std::string transport_destination = "any"; std::string transport_flags = "any"; - std::string keepstate = "false"; + std::string recordstate = "false"; std::string next_module = "any"; std::string log = rule.log ? "true" : "false"; @@ -719,13 +719,13 @@ unwind_result unwind(const std::map& acl } } - if (rule.filter->keepstate) + if (rule.filter->recordstate) { - keepstate = "true"; + recordstate = "true"; } - if (in_keepstate && - keepstate != *in_keepstate) + if (in_recordstate && + recordstate != *in_recordstate) { continue; } @@ -754,7 +754,7 @@ unwind_result unwind(const std::map& acl transport_source, transport_destination, transport_flags, - keepstate, + recordstate, next_module, ids, log); @@ -893,9 +893,9 @@ std::vector unwind_used_rules(const std::map(rule.action); - if (rule.filter->keepstate) + if (rule.filter->recordstate) { - flow.flags |= (int)common::globalBase::eFlowFlags::keepstate; + flow.flags |= (int)common::globalBase::eFlowFlags::recordstate; } if (rule.log) { diff --git a/controlplane/acl.h b/controlplane/acl.h index 077bb083..e3a73405 100644 --- a/controlplane/acl.h +++ b/controlplane/acl.h @@ -67,7 +67,7 @@ unwind_result unwind(const std::map& acl const std::optional& transport_source, const std::optional& transport_destination, const std::optional& transport_flags, - const std::optional& keepstate); + const std::optional& recordstate); std::set lookup(const std::map& acls, const acl::iface_map_t& ifaces, diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index c3f4712d..ea0beccd 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -850,7 +850,7 @@ struct filter_t : filter_base_t ref_t flags; ref_t proto; ref_t dir; - ref_t keepstate; + ref_t recordstate; filter_t(const ref_t& _acl_id, const ref_t& _src, @@ -858,14 +858,14 @@ struct filter_t : filter_base_t const ref_t& _flags, const ref_t& _proto, const ref_t& _dir, - const ref_t& keepstate) : + const ref_t& recordstate) : acl_id(_acl_id), src(_src), dst(_dst), flags(_flags), proto(_proto), dir(_dir), - keepstate(keepstate) + recordstate(recordstate) {} filter_t(ipfw::rule_ptr_t rulep) @@ -919,15 +919,15 @@ struct filter_t : filter_base_t dir = new filter_id_t(1); break; } - if (rulep->keepstate) + if (rulep->recordstate) { - keepstate = new filter_bool_t(true); + recordstate = new filter_bool_t(true); } } virtual bool is_none() const { - return acl_id.is_none() || src.is_none() || dst.is_none() || proto.is_none() || dir.is_none() || keepstate.is_none(); + return acl_id.is_none() || src.is_none() || dst.is_none() || proto.is_none() || dir.is_none() || recordstate.is_none(); } virtual std::string to_string() const @@ -954,9 +954,9 @@ struct filter_t : filter_base_t { ret += " frag " + frag_to_string(flags); } - if (keepstate) + if (recordstate) { - ret += " keepstate"; + ret += " recordstate"; } if (acl_id) @@ -969,7 +969,7 @@ struct filter_t : filter_base_t bool operator==(const filter_t& o) const { - return src == o.src && dst == o.dst && flags == o.flags && proto == o.proto && dir == o.dir && keepstate == o.keepstate; + return src == o.src && dst == o.dst && flags == o.flags && proto == o.proto && dir == o.dir && recordstate == o.recordstate; } }; @@ -1024,7 +1024,7 @@ inline ref_t and_op(const ref_t& a, const ref_t& b a.filter->flags & b.filter->flags, a.filter->proto & b.filter->proto, a.filter->dir & b.filter->dir, - a.filter->keepstate & b.filter->keepstate); + a.filter->recordstate & b.filter->recordstate); } const int64_t DISPATCHER = -1; @@ -1345,7 +1345,7 @@ struct hash size_t operator()(const acl::filter_t& f) const noexcept { size_t h = 0; - hash_combine(h, f.src, f.dst, f.flags, f.proto, f.dir, f.keepstate); + hash_combine(h, f.src, f.dst, f.flags, f.proto, f.dir, f.recordstate); return h; } diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index 89acaafe..2b2b8b83 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -415,7 +415,7 @@ common::icp::limit_summary::response cControlPlane::limit_summary() const common::icp::acl_unwind::response cControlPlane::acl_unwind(const common::icp::acl_unwind::request& request) const { - const auto& [module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, keepstate] = request; + const auto& [module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, recordstate] = request; generations.current_lock(); std::map acls = generations.current().acls; @@ -434,7 +434,7 @@ common::icp::acl_unwind::response cControlPlane::acl_unwind(const common::icp::a acls.swap(acls_next); } - return acl::unwind(acls, iface_map, module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, keepstate); + return acl::unwind(acls, iface_map, module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, recordstate); } common::icp::acl_lookup::response cControlPlane::acl_lookup(const common::icp::acl_lookup::request& request) const diff --git a/controlplane/unittest/parser.cpp b/controlplane/unittest/parser.cpp index fa912554..14534002 100644 --- a/controlplane/unittest/parser.cpp +++ b/controlplane/unittest/parser.cpp @@ -172,10 +172,10 @@ add allow udp from { _CNETS_ or _DNETS_ } dst-port 3784,4784 to { _CNETS_ or _DN EXPECT_FALSE(parse_rules(rules)); } -TEST(Parser, 017_KeepStateOption) +TEST(Parser, 017_RecordStateOption) { const auto rules = R"IPFW( -add allow icmp from me to any icmptypes 8 out keep-state +add allow icmp from me to any icmptypes 8 out record-state )IPFW"; EXPECT_TRUE(parse_rules(rules)); } @@ -220,7 +220,7 @@ TEST(Parser, 020_IgnoredOptions) const auto rules = R"IPFW( # just ignore antispoof, diverted, logamount, tag, tagged, add allow tcp from 10.0.0.0/8 to 10.0.0.0/8 80 in antispoof -add 65534 allow ip from any to any diverted keep-state +add 65534 allow ip from any to any diverted record-state add deny log logamount 500 all from any to any add allow tag 653 ip4 from { 10.0.0.0/8 } to me add allow ip from any to any tagged 31000 diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index d0c76aaa..ee399965 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -111,9 +111,9 @@ struct ActionDispatcher { worker->acl_log(mbuf, action.flow, acl_id); } - if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::keepstate) + if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::recordstate) { - worker->acl_create_keepstate(mbuf, acl_id, action.flow); + worker->acl_create_state(mbuf, acl_id, action.flow); } if constexpr (Direction == FlowDirection::Egress) diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index d7d017a8..06db1d24 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -4805,7 +4805,7 @@ inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf, return {flow}; } -inline void cWorker::acl_create_keepstate(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow) +inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); diff --git a/dataplane/worker.h b/dataplane/worker.h index cfcf44f6..a11c017b 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -192,7 +192,7 @@ class cWorker inline FlowFromState acl_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf); inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); - inline void acl_create_keepstate(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow); + inline void acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow); inline void acl_state_emit(tAclId aclId, const dataplane::globalBase::fw_state_sync_frame_t& frame); inline void acl_egress_entry(rte_mbuf* mbuf, tAclId aclId); diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index 7e2f17d7..286c04d3 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -832,8 +832,8 @@ void fw_config_t::add_rule_opcode(const rule_t::opcode_arg_t& value) case rule_t::opcode_t::DIRECTION: m_curr_rule->direction |= std::get(value); break; - case rule_t::opcode_t::KEEPSTATE: - m_curr_rule->keepstate = true; + case rule_t::opcode_t::RECORDSTATE: + m_curr_rule->recordstate = true; break; case rule_t::opcode_t::IPID: break; diff --git a/libfwparser/fw_config.h b/libfwparser/fw_config.h index f51f3a0e..91a49437 100644 --- a/libfwparser/fw_config.h +++ b/libfwparser/fw_config.h @@ -216,7 +216,7 @@ struct rule_t enum class opcode_t { DIRECTION, - KEEPSTATE, + RECORDSTATE, IPID, IPLEN, IPTTL, @@ -299,7 +299,7 @@ struct rule_t location_history_t location; // file:lineno rule_state_t state = rule_state_t::UNKNOWN; - bool keepstate = false; + bool recordstate = false; bool log = false; // has log option unsigned int logamount = 0; // log limit unsigned int setno = 0; // set number diff --git a/libfwparser/fw_parser.y b/libfwparser/fw_parser.y index 5c06b966..7371da48 100644 --- a/libfwparser/fw_parser.y +++ b/libfwparser/fw_parser.y @@ -108,7 +108,7 @@ REASS CONFIG BW WEIGHT BUCKETS MASK SCHEDMASK NOERROR PLR DROPTAIL FLOWID PDELAY SCHED FLOWMASK LINK PRIORITY TYPE VALTYPE ALGO FIB PROFILE BURST CHECKSTATE FWD LOG LOGAMOUNT - LOGDST SETUP ESTABLISHED FRAG MF RF DF OFFSET KEEPSTATE + LOGDST SETUP ESTABLISHED FRAG MF RF DF OFFSET RECORDSTATE ICMPTYPES ICMP6TYPES FROM TO ME ME6 ANY IN OUT VIA XMIT RECV OR NOT LIMIT TABLE TCPFLAGS TCPOPTIONS T_IP T_IP4 T_IP6 IPLEN IPID IPOPTIONS IPTOS IPTTL TCPDATALEN TCPSEQ TCPWIN @@ -1260,9 +1260,9 @@ optiontoken: } icmptypes | - keepstate + recordstate { - cfg.set_rule_opcode(rule_t::opcode_t::KEEPSTATE); + cfg.set_rule_opcode(rule_t::opcode_t::RECORDSTATE); cfg.add_rule_opcode(1); } | @@ -1451,10 +1451,10 @@ fragtoken: cfg.clear_rule_flag(rule_t::ipoff_flags_t::OFFSET); } ; -keepstate: - KEEPSTATE +recordstate: + RECORDSTATE | - KEEPSTATE LABEL + RECORDSTATE LABEL ; dscpspec: dscpspectoken diff --git a/libfwparser/token.l b/libfwparser/token.l index 1bdda844..b62857b1 100644 --- a/libfwparser/token.l +++ b/libfwparser/token.l @@ -162,7 +162,7 @@ mf return ipfw::fw_parser_t::make_MF(*ploc); rf return ipfw::fw_parser_t::make_RF(*ploc); df return ipfw::fw_parser_t::make_DF(*ploc); offset return ipfw::fw_parser_t::make_OFFSET(*ploc); -keep-state return ipfw::fw_parser_t::make_KEEPSTATE(*ploc); +record-state return ipfw::fw_parser_t::make_RECORDSTATE(*ploc); icmptype|icmptypes return ipfw::fw_parser_t::make_ICMPTYPES(*ploc); icmp6type|icmp6types return ipfw::fw_parser_t::make_ICMP6TYPES(*ploc); from return ipfw::fw_parser_t::make_FROM(*ploc); diff --git a/parser/fw_dump.cpp b/parser/fw_dump.cpp index 67452ed4..1fcbf41d 100644 --- a/parser/fw_dump.cpp +++ b/parser/fw_dump.cpp @@ -239,7 +239,7 @@ void fw_dump_t::dump_rule(rule_ptr_t rulep) { std::cerr << "# frag = set(" << std::hex << (int)rulep->ipoff_setflags << "), clear(" << (int)rulep->ipoff_clearflags << ")" << std::dec << std::endl; } - std::cerr << "# keepstate = " << rulep->keepstate << std::endl; + std::cerr << "# recordstate = " << rulep->recordstate << std::endl; if (rulep->direction == rule_t::direction_t::IN) std::cerr << "# direction = IN" << std::endl; else if (rulep->direction == rule_t::direction_t::OUT) From cdfeacde11796f9318fdbc4502f7ac067ca889c0 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 9 Jul 2024 12:15:22 +0300 Subject: [PATCH 064/195] Add implicit check-state rule generation for keep-state action To handle the keep-state action which requires an implicit check-state, we decided to add the implicit check-state rule during the parsing step. This involves unwrapping a rule with keep-state into a separate check-state rule and a rule with record-state. The keep-state option is only reflected in the rule's text field. --- libfwparser/fw_config.cpp | 74 ++++++++++++++++++++++++++++++++------- libfwparser/fw_config.h | 18 ++++++++++ libfwparser/fw_parser.y | 13 ++++++- libfwparser/token.l | 1 + 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index 286c04d3..a0c21485 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -545,6 +545,11 @@ std::string trim_spaces(const std::string& str) void fw_config_t::fill_rule_text(void) { + if (m_curr_rule->implicit_check_state) + { + add_implicit_check_state_rule(); + } + m_curr_rule->text = trim_spaces(m_lexer.m_line); m_curr_rule->location.lineno = m_location.top().begin.line; m_curr_rule->location.fileno = m_fileno.top(); @@ -552,18 +557,7 @@ void fw_config_t::fill_rule_text(void) m_curr_rule->ruleid = ++m_ruleid_last; FW_CONF_DEBUG(m_curr_rule->text); - // user may specify rule number, if it is greather than - // last added, use it for automatic numeration - if (m_curr_rule->ruleno > m_ruleno_last) - { - m_ruleno_last = m_curr_rule->ruleno; - } - // if rulenumber is not specified, use automatic numeration - if (m_curr_rule->ruleno == 0) - { - m_curr_rule->ruleno = m_ruleno_last + m_ruleno_step; - m_ruleno_last = m_curr_rule->ruleno; - } + fill_rule_number_if_needed(); m_rules[m_curr_rule->ruleno].emplace_back(m_curr_rule); m_prev_rule = m_curr_rule; m_curr_rule = std::make_shared(); @@ -835,6 +829,10 @@ void fw_config_t::add_rule_opcode(const rule_t::opcode_arg_t& value) case rule_t::opcode_t::RECORDSTATE: m_curr_rule->recordstate = true; break; + case rule_t::opcode_t::KEEPSTATE: + m_curr_rule->implicit_check_state = true; + m_curr_rule->recordstate = true; + break; case rule_t::opcode_t::IPID: break; case rule_t::opcode_t::IPLEN: @@ -889,6 +887,48 @@ void fw_config_t::add_rule_opcode(const rule_t::opcode_arg_t& value) } } +void fw_config_t::fill_rule_number_if_needed() +{ + // user may specify rule number, if it is greather than + // last added, use it for automatic numeration + if (m_curr_rule->ruleno > m_ruleno_last) + { + m_ruleno_last = m_curr_rule->ruleno; + } + // if rulenumber is not specified, use automatic numeration + if (m_curr_rule->ruleno == 0) + { + m_curr_rule->ruleno = m_ruleno_last + m_ruleno_step; + m_ruleno_last = m_curr_rule->ruleno; + } +} + +void fw_config_t::add_implicit_check_state_rule() +{ + // Save the current rule + auto current_rule = m_curr_rule; + + // Create a new check-state rule + m_curr_rule = std::make_shared(); + set_rule_action(rule_action_t::CHECKSTATE); + m_curr_rule->ruleno = current_rule->ruleno; + m_curr_rule->location = current_rule->location; + m_curr_rule->location.implicitly_generated_rule = true; + m_curr_rule->ruleid = ++m_ruleid_last; + m_curr_rule->text = "check-state"; + + fill_rule_number_if_needed(); + + // Add the check-state rule like fill_rule_text method does + m_rules[m_curr_rule->ruleno].emplace_back(m_curr_rule); + + // Restore the original rule + m_curr_rule = current_rule; + + // Reset rule number for automatic generation + m_curr_rule->ruleno = 0; +} + void fw_config_t::set_rule_flag(uint32_t flag) { FW_CONF_DEBUG("flag " << flag); @@ -1023,7 +1063,15 @@ std::string fw_config_t::format_location(const location_history_t& loc) { filename = "UNKNOWN"; } - return filename + ":" + std::to_string(loc.lineno); + + std::string location_str = filename + ":" + std::to_string(loc.lineno); + + if (loc.implicitly_generated_rule) + { + return "This rule is implicit, generated by the rule at " + location_str; + } + + return location_str; } bool fw_config_t::resolve_labels() diff --git a/libfwparser/fw_config.h b/libfwparser/fw_config.h index 91a49437..fd711d79 100644 --- a/libfwparser/fw_config.h +++ b/libfwparser/fw_config.h @@ -39,6 +39,7 @@ using location_history_t = struct location_history { size_t lineno; // line number in the config file size_t fileno; // file number in the history + bool implicitly_generated_rule = false; // flag for implicitly generated rules }; using label_info_t = std::tuplelog = true; } + void fill_rule_number_if_needed(); void fill_rule_proto(uint8_t); void fill_rule_proto(const std::string&); void fill_rule_ipver(rule_t::ip_version_t ver); @@ -498,6 +502,20 @@ class fw_config_t void set_rule_flag(uint32_t); void clear_rule_flag(uint32_t); + /** + * @brief Adds an implicit check-state rule. + * + * This function creates a check-state rule based on the current rule's + * configuration. The newly created rule is marked as implicitly generated + * and is inserted into the rules list. After adding the check-state rule, + * the original rule configuration is restored, and the rule number is reset + * for automatic generation. + * + * This is used to handle the `keep-state` option, which requires an implicit + * check-state rule to be added before the original rule. + */ + void add_implicit_check_state_rule(); + std::string format_location(const location_history_t& loc); const auto& labels() const { diff --git a/libfwparser/fw_parser.y b/libfwparser/fw_parser.y index 7371da48..eb977810 100644 --- a/libfwparser/fw_parser.y +++ b/libfwparser/fw_parser.y @@ -108,7 +108,7 @@ REASS CONFIG BW WEIGHT BUCKETS MASK SCHEDMASK NOERROR PLR DROPTAIL FLOWID PDELAY SCHED FLOWMASK LINK PRIORITY TYPE VALTYPE ALGO FIB PROFILE BURST CHECKSTATE FWD LOG LOGAMOUNT - LOGDST SETUP ESTABLISHED FRAG MF RF DF OFFSET RECORDSTATE + LOGDST SETUP ESTABLISHED FRAG MF RF DF OFFSET RECORDSTATE KEEPSTATE ICMPTYPES ICMP6TYPES FROM TO ME ME6 ANY IN OUT VIA XMIT RECV OR NOT LIMIT TABLE TCPFLAGS TCPOPTIONS T_IP T_IP4 T_IP6 IPLEN IPID IPOPTIONS IPTOS IPTTL TCPDATALEN TCPSEQ TCPWIN @@ -1266,6 +1266,12 @@ optiontoken: cfg.add_rule_opcode(1); } | + keepstate + { + cfg.set_rule_opcode(rule_t::opcode_t::KEEPSTATE); + cfg.add_rule_opcode(1); + } + | DIVERTED { } @@ -1456,6 +1462,11 @@ recordstate: | RECORDSTATE LABEL ; +keepstate: + KEEPSTATE + | + KEEPSTATE LABEL + ; dscpspec: dscpspectoken | diff --git a/libfwparser/token.l b/libfwparser/token.l index b62857b1..0164da45 100644 --- a/libfwparser/token.l +++ b/libfwparser/token.l @@ -163,6 +163,7 @@ rf return ipfw::fw_parser_t::make_RF(*ploc); df return ipfw::fw_parser_t::make_DF(*ploc); offset return ipfw::fw_parser_t::make_OFFSET(*ploc); record-state return ipfw::fw_parser_t::make_RECORDSTATE(*ploc); +keep-state return ipfw::fw_parser_t::make_KEEPSTATE(*ploc); icmptype|icmptypes return ipfw::fw_parser_t::make_ICMPTYPES(*ploc); icmp6type|icmp6types return ipfw::fw_parser_t::make_ICMP6TYPES(*ploc); from return ipfw::fw_parser_t::make_FROM(*ploc); From 86358b42ef93eede69a06adb4da6c500038434e6 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 9 Jul 2024 14:08:30 +0300 Subject: [PATCH 065/195] Add unit tests for keep-state firewall rules These tests verify that a rule with keep-state generates an additional check-state rule during parsing. --- controlplane/unittest/acl.cpp | 109 ++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index db5f5b28..a02e0bb0 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -591,4 +591,113 @@ add 500 deny ip from any to any value); } +TEST(ACL, KeepState_Basic) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add allow ip from any to any keep-state +add deny ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 1); + + for (const auto& [total_table_key, total_table_value] : result.acl_total_table) + { + (void)total_table_key; + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + +TEST(ACL, KeepState_MultipleRules) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add allow ip from { 1.2.3.4 } to any keep-state +add allow ip from any to any 22 keep-state +add deny ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + for (const auto& [total_table_key, total_table_value] : result.acl_total_table) + { + (void)total_table_key; + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + +TEST(ACL, KeepState_WithSkipTo) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add skipto :IN ip from { 1.2.3.4 } to any in +add deny ip from any to any + +:IN +add allow ip from any to any keep-state +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + for (const auto& [total_table_key, total_table_value] : result.acl_total_table) + { + (void)total_table_key; + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + } // namespace From aebfbd4620903f52dfd6e867c9d160969fea08e0 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 9 Jul 2024 17:25:32 +0300 Subject: [PATCH 066/195] Add autotests for keep-state firewall rules in existing test suite Previously, we modified our test suite to use check-state with record-state in firewall rules. Now, we want to extend our tests to also cover keep-state functionality. To achieve this, we need to duplicate the existing tests with slight modifications to the firewall ruleset to use keep-state instead of check-state with record-state. But since each other config piece remains the same we just expand the autotest.yaml file There might be a better way to handle this though, but current autotest.cpp does not support explicitly specifying the firewall.txt file. Thus reusing the "reload" function, as the firewall.txt paths are defined within the controlplane.conf files. --- autotest/autotest.cpp | 7 +- .../036_firewall_keepstate/autotest.yaml | 15 +++++ .../controlplane_keepstate.conf | 42 ++++++++++++ .../firewall_keepstate.txt | 7 ++ .../autotest.yaml | 34 ++++++++++ .../controlplane_keepstate.conf | 64 ++++++++++++++++++ .../firewall_keepstate.txt | 7 ++ .../autotest.yaml | 40 +++++++++++ .../controlplane_keepstate.conf | 64 ++++++++++++++++++ .../firewall_keepstate.txt | 7 ++ .../autotest.yaml | 38 +++++++++++ .../controlplane_keepstate.conf | 64 ++++++++++++++++++ .../firewall_keepstate.txt | 8 +++ .../autotest.yaml | 16 +++++ .../controlplane_keepstate.conf | 64 ++++++++++++++++++ .../firewall_keepstate.txt | 3 + .../050_firewall_state_resend/autotest.yaml | 64 ++++++++++++++++++ .../controlplane_keepstate.conf | 64 ++++++++++++++++++ .../firewall_keepstate.txt | 7 ++ .../autotest.yaml | 41 ++++++++++++ .../controlplane_keepstate.conf | 67 +++++++++++++++++++ .../firewall_keepstate.txt | 7 ++ .../052_firewall_samples/autotest.yaml | 26 +++++++ .../controlplane_keepstate.conf | 43 ++++++++++++ .../firewall_keepstate.txt | 7 ++ 25 files changed, 805 insertions(+), 1 deletion(-) create mode 100644 autotest/units/001_one_port/036_firewall_keepstate/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/036_firewall_keepstate/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/037_firewall_keepstate_with_sync/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/050_firewall_state_resend/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/050_firewall_state_resend/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall_keepstate.txt create mode 100644 autotest/units/001_one_port/052_firewall_samples/controlplane_keepstate.conf create mode 100644 autotest/units/001_one_port/052_firewall_samples/firewall_keepstate.txt diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 6e951afc..db946bb1 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -1354,7 +1354,12 @@ void tAutotest::mainThread() { bool result = true; - if (yamlStep["ipv4Update"]) + if (yamlStep["subtest"]) + { + auto test_name = yamlStep["subtest"].as(); + YANET_LOG_PRINT(ANSI_COLOR_BLUE "Running subtest: '%s'\n" ANSI_COLOR_RESET, test_name.c_str()); + } + else if (yamlStep["ipv4Update"]) { YANET_LOG_DEBUG("step: ipv4Update\n"); diff --git a/autotest/units/001_one_port/036_firewall_keepstate/autotest.yaml b/autotest/units/001_one_port/036_firewall_keepstate/autotest.yaml index f79a3246..79c2772d 100644 --- a/autotest/units/001_one_port/036_firewall_keepstate/autotest.yaml +++ b/autotest/units/001_one_port/036_firewall_keepstate/autotest.yaml @@ -1,6 +1,21 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/036_firewall_keepstate/controlplane_keepstate.conf b/autotest/units/001_one_port/036_firewall_keepstate/controlplane_keepstate.conf new file mode 100644 index 00000000..98d3dfec --- /dev/null +++ b/autotest/units/001_one_port/036_firewall_keepstate/controlplane_keepstate.conf @@ -0,0 +1,42 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + } + } + } + } +} diff --git a/autotest/units/001_one_port/036_firewall_keepstate/firewall_keepstate.txt b/autotest/units/001_one_port/036_firewall_keepstate/firewall_keepstate.txt new file mode 100644 index 00000000..38585f7c --- /dev/null +++ b/autotest/units/001_one_port/036_firewall_keepstate/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow udp from 11.0.0.0/24 to any 53 keep-state +add allow udp from any to 2a03:6b8:ff1c:2030::/60 53 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/autotest.yaml b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/autotest.yaml index d035a819..4796b30e 100644 --- a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/autotest.yaml +++ b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/autotest.yaml @@ -1,6 +1,40 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap +- sendPackets: + - port: kni0 + send: 005-send.pcap + expect: 005-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 006-send.pcap + expect: 006-expect.pcap +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/controlplane_keepstate.conf b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/controlplane_keepstate.conf new file mode 100644 index 00000000..9e4cc575 --- /dev/null +++ b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/controlplane_keepstate.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "multicastDestinationPort": 11995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall_keepstate.txt b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall_keepstate.txt new file mode 100644 index 00000000..aabcef63 --- /dev/null +++ b/autotest/units/001_one_port/037_firewall_keepstate_with_sync/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow udp from 10.0.0.0/24 to any 53 keep-state +add allow udp from any to 2121:bbb8:ff1c:2030::/60 53 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/autotest.yaml b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/autotest.yaml index 03cef021..811d356b 100644 --- a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/autotest.yaml +++ b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/autotest.yaml @@ -1,6 +1,46 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap +- sendPackets: + - port: kni0 + send: 005-send.pcap + expect: 005-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 006-send.pcap + expect: 006-expect.pcap +- sendPackets: + - port: kni0 + send: 007-send.pcap + expect: 007-expect.pcap +- cli: "fw list states | grep 'allow tcp from 2a22:6b8:ff1c:2030::1 12345 to 1111:2222::1 777' | grep 'flags SAF:SAF'" +- cli: "fw list states | grep 'allow tcp from 1.1.1.10 54321 to 12.0.0.10 10000' | grep 'flags S:S'" +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/controlplane_keepstate.conf b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/controlplane_keepstate.conf new file mode 100644 index 00000000..9e4cc575 --- /dev/null +++ b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/controlplane_keepstate.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "multicastDestinationPort": 11995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall_keepstate.txt b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall_keepstate.txt new file mode 100644 index 00000000..f23b28e8 --- /dev/null +++ b/autotest/units/001_one_port/039_firewall_keepstate_with_sync_tcp/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow tcp from 12.0.0.0/24 to any 12345 keep-state +add allow tcp from any to 2a22:6b8:ff1c:2030::/60 12345 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/autotest.yaml b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/autotest.yaml index 14d809f0..a053c054 100644 --- a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/autotest.yaml +++ b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/autotest.yaml @@ -1,6 +1,44 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 005-send.pcap + expect: 005-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 006-send.pcap + expect: 006-expect.pcap +- sendPackets: + - port: kni0 + send: 007-send.pcap + expect: 007-expect.pcap +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/controlplane_keepstate.conf b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/controlplane_keepstate.conf new file mode 100644 index 00000000..9e4cc575 --- /dev/null +++ b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/controlplane_keepstate.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "multicastDestinationPort": 11995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall_keepstate.txt b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall_keepstate.txt new file mode 100644 index 00000000..7ba1b01a --- /dev/null +++ b/autotest/units/001_one_port/040_firewall_keepstate_with_sync_mixed/firewall_keepstate.txt @@ -0,0 +1,8 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow ip from 13.0.0.0/24 to any keep-state +add allow ip from any to 2332:898:ff1c:2030::/64 keep-state +add allow tcp from 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: to 2332:898:ffee:0:0:5678::/ffff:ffff:ffff:0000:ffff:ffff:: 10053 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml index 5bb93d47..426667a9 100644 --- a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml +++ b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml @@ -1,6 +1,22 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/controlplane_keepstate.conf b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/controlplane_keepstate.conf new file mode 100644 index 00000000..9e4cc575 --- /dev/null +++ b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/controlplane_keepstate.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "multicastDestinationPort": 11995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall_keepstate.txt b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall_keepstate.txt new file mode 100644 index 00000000..8c1fb879 --- /dev/null +++ b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/firewall_keepstate.txt @@ -0,0 +1,3 @@ +:BEGIN +add deny ip from any to any keep-state + diff --git a/autotest/units/001_one_port/050_firewall_state_resend/autotest.yaml b/autotest/units/001_one_port/050_firewall_state_resend/autotest.yaml index d7eafc9a..43d17796 100644 --- a/autotest/units/001_one_port/050_firewall_state_resend/autotest.yaml +++ b/autotest/units/001_one_port/050_firewall_state_resend/autotest.yaml @@ -1,6 +1,70 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sleep: 10 +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 005-send.pcap + expect: 005-expect.pcap +- sleep: 9 +- sendPackets: + - port: kni0 + send: 006-send.pcap + expect: 006-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 007-send.pcap + expect: 007-expect.pcap +- sendPackets: + - port: kni0 + send: 008-send.pcap + expect: 008-expect.pcap +- sleep: 10 +- sendPackets: + - port: kni0 + send: 009-send.pcap + expect: 009-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 010-send.pcap + expect: 010-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 011-send.pcap + expect: 011-expect.pcap +- sleep: 9 +- sendPackets: + - port: kni0 + send: 012-send.pcap + expect: 012-expect.pcap +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/050_firewall_state_resend/controlplane_keepstate.conf b/autotest/units/001_one_port/050_firewall_state_resend/controlplane_keepstate.conf new file mode 100644 index 00000000..9e4cc575 --- /dev/null +++ b/autotest/units/001_one_port/050_firewall_state_resend/controlplane_keepstate.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "multicastDestinationPort": 11995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/050_firewall_state_resend/firewall_keepstate.txt b/autotest/units/001_one_port/050_firewall_state_resend/firewall_keepstate.txt new file mode 100644 index 00000000..9554503a --- /dev/null +++ b/autotest/units/001_one_port/050_firewall_state_resend/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow udp from 10.0.0.0/24 to any 53 keep-state +add allow udp from any to 2020:ddd:ff1c:2030::/60 53 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/autotest.yaml b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/autotest.yaml index 9f1cc3e0..2b09840a 100644 --- a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/autotest.yaml +++ b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/autotest.yaml @@ -1,6 +1,47 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- clearFWState: 1 +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap +- sendPackets: + - port: kni0 + send: 005-send.pcap + expect: 005-expect.pcap +- sleep: 1 +- sendPackets: + - port: kni0 + send: 006-send.pcap + expect: 006-expect.pcap +- sendPackets: + - port: kni0 + send: 007-send.pcap + expect: + - 007-expect-tcp.pcap + - 007-expect-tech.pcap +- cli: "fw list states | grep 'allow tcp from 2220:ddd:ff1c:2030::1 12345 to 1111:2222::1 777' | grep 'flags SAF:SAF'" +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/controlplane_keepstate.conf b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/controlplane_keepstate.conf new file mode 100644 index 00000000..33910b06 --- /dev/null +++ b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/controlplane_keepstate.conf @@ -0,0 +1,67 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.2000": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "2000", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "synchronization": { + "ipv6SourceAddress": "fe80::f1", + "multicastIpv6Address": "ff02::1", + "unicastIpv6SourceAddress": "3333::4444", + "unicastIpv6Address": "2222::1111", + "multicastDestinationPort": 11995, + "unicastDestinationPort": 21995, + "logicalPorts": [ + "lp0.2000" + ], + "ingressNextModule": "vrf0" + }, + "nextModules": [ + "vrf0" + ] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.2000": { + "ipAddresses": ["ff02::2000"], + "neighborIPv6Address": "fe80::2000", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.2000" + } + } + } + } +} diff --git a/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall_keepstate.txt b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall_keepstate.txt new file mode 100644 index 00000000..539109ae --- /dev/null +++ b/autotest/units/001_one_port/051_firewall_keepstate_with_sync_unicast/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow tcp from 12.0.0.0/24 to any 12345 keep-state +add allow tcp from any to 2220:ddd:ff1c:2030::/60 12345 keep-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/052_firewall_samples/autotest.yaml b/autotest/units/001_one_port/052_firewall_samples/autotest.yaml index 1abe1fd5..a383fb56 100644 --- a/autotest/units/001_one_port/052_firewall_samples/autotest.yaml +++ b/autotest/units/001_one_port/052_firewall_samples/autotest.yaml @@ -1,6 +1,32 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" - ipv6Update: "::/0 -> fe80::1" + +- subtest: with check-state and record-state +- sleep: 1 +- cli: "samples show" +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- cli: "samples dump | diff - TESTDIR/samples.json" +- clearFWState: 1 + +- reload: controlplane_keepstate.conf + +- subtest: with just keep-state - sleep: 1 - cli: "samples show" - sendPackets: diff --git a/autotest/units/001_one_port/052_firewall_samples/controlplane_keepstate.conf b/autotest/units/001_one_port/052_firewall_samples/controlplane_keepstate.conf new file mode 100644 index 00000000..ca255bcc --- /dev/null +++ b/autotest/units/001_one_port/052_firewall_samples/controlplane_keepstate.conf @@ -0,0 +1,43 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall_keepstate.txt", + "nextModules": [ + "vrf0" + ], + "storeSamples": true + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + } + } + } + } +} diff --git a/autotest/units/001_one_port/052_firewall_samples/firewall_keepstate.txt b/autotest/units/001_one_port/052_firewall_samples/firewall_keepstate.txt new file mode 100644 index 00000000..d9986a09 --- /dev/null +++ b/autotest/units/001_one_port/052_firewall_samples/firewall_keepstate.txt @@ -0,0 +1,7 @@ +:BEGIN +add skipto :IN ip from any to any in + +:IN +add allow tcp from 11.0.0.0/24 to any 53 keep-state +add allow tcp from any to 2111:aaa:ff1c:2030::/60 53 keep-state +add deny ip from any to any From 4f590ec54a4154275a2efbebc7cd50fc4860b882 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 2 Aug 2024 14:49:27 +0300 Subject: [PATCH 067/195] Add pragma once to config.release.h In this header file there was no guard against including it multiple times --- common/config.release.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/config.release.h b/common/config.release.h index 3522b6da..9811ed3e 100644 --- a/common/config.release.h +++ b/common/config.release.h @@ -1,3 +1,5 @@ +#pragma once + #define CONFIG_YADECAP_MBUFS_COUNT (48 * 1024) #define CONFIG_YADECAP_MBUF_SIZE (10 * 1024) #define CONFIG_YADECAP_WORKER_PORTS_SIZE (8) From 35cbc86483456c182f331e59bc953165c40118d6 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Tue, 10 Sep 2024 16:42:04 +0300 Subject: [PATCH 068/195] Append yanet-announcer.py into YANET image --- build/Dockerfile.image | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/Dockerfile.image b/build/Dockerfile.image index 72e3c3aa..2380b47a 100644 --- a/build/Dockerfile.image +++ b/build/Dockerfile.image @@ -1,5 +1,5 @@ ARG RELEASE=22.04 -FROM --platform=linux/amd64 ubuntu:${RELEASE} as environment +FROM --platform=linux/amd64 ubuntu:${RELEASE} AS environment RUN apt-get update RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ @@ -28,7 +28,8 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ RUN python3 -m pip install meson==0.61.2 -FROM environment as builder + +FROM environment AS builder ARG YANET_VERSION_MAJOR=0 ARG YANET_VERSION_MINOR=0 @@ -50,6 +51,7 @@ RUN meson setup --prefix=/target \ RUN meson compile -C build + FROM --platform=linux/amd64 ubuntu:${RELEASE} RUN apt-get update @@ -61,8 +63,10 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ libmlx5-1 \ libnuma1 \ libpcap0.8 \ - netbase + netbase \ + python3 COPY --from=builder /opt/yanet/build/controlplane/yanet-controlplane /usr/bin/ COPY --from=builder /opt/yanet/build/dataplane/yanet-dataplane /usr/bin/ COPY --from=builder /opt/yanet/build/cli/yanet-cli /usr/bin/ +COPY --from=builder /opt/yanet/yanet-announcer.py /usr/bin/yanet-announcer From 1757a3f0ee7311fd8187fa7b8ba728457c837096 Mon Sep 17 00:00:00 2001 From: Alexander Lopintsev Date: Sat, 7 Sep 2024 20:05:21 +0300 Subject: [PATCH 069/195] Add total counters for ingress and egress packet drops --- cli/telegraf.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cli/telegraf.h b/cli/telegraf.h index 708cbbd7..20257f3b 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -106,10 +106,13 @@ void unsafe() const auto& [memory_groups, memory_objects] = memory_stats; const auto durations = controlplane.controlplane_durations(); + uint64_t total_acl_ingress_dropPackets = 0, total_acl_egress_dropPackets = 0; for (const auto& [coreId, worker] : responseWorkers) { const auto& [iterations, stats, ports_stats] = worker; + total_acl_ingress_dropPackets += stats.acl_ingress_dropPackets; + total_acl_egress_dropPackets += stats.acl_egress_dropPackets; printf("worker,coreId=%u " "iterations=%luu," @@ -174,6 +177,12 @@ void unsafe() stats.logs_drops, stats.logs_packets); + printf("worker,coreId=all " + "acl_ingress_dropPackets=%luu," + "acl_egress_dropPackets=%luu\n", + total_acl_ingress_dropPackets, + total_acl_egress_dropPackets); + for (const auto& [physicalPortName, stats] : ports_stats) { printf("worker,coreId=%u,physicalPortName=%s " From 82834ccb7eb950db475f96bf17e3c470b13f9077 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 11 Sep 2024 17:50:48 +0300 Subject: [PATCH 070/195] Fixes maybe uninitialized worker pointer. --- dataplane/controlplane.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 4808cf31..72171e78 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -217,7 +217,7 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common { for (const auto& coreId : request) { - const cWorker* worker; + const cWorker* worker{}; if (auto it = dataPlane->workers.find(coreId); it != dataPlane->workers.end()) { worker = it->second; From 459e1f1177beb08d52495c68c3f8c3dcc90d4e4f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 19 Aug 2024 16:28:22 +0300 Subject: [PATCH 071/195] Add README section for running unit tests --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 612774a4..97d99004 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,31 @@ For more information about the autotests run: ``` yanet-builder ./autotest/yanet-autotest-run.py -h ``` + +## Running Unit Tests + +To run the unit tests for the project, follow these steps: + +Setup the build directory for unittest targeting: +```sh +meson setup -Dtarget=unittest build_unittest +``` +Next, compile the project within the setup build directory: + +```sh +meson compile -C build_unittest +``` + +After compilation, run all the unit tests with: + +```sh +meson test -C build_unittest +``` +- To view more detailed output, you can run the tests with -v flag: + +```sh +meson test -C build_unittest -v +``` ## Dependencies - [DPDK](https://github.com/DPDK/dpdk) - [JSON](https://github.com/nlohmann/json) From 7de8eab3e4d7488faa7f3117cbd33cf8fdac1d32 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Wed, 14 Aug 2024 17:04:42 +0300 Subject: [PATCH 072/195] Update release workflow --- .github/workflows/release.yml | 56 +++++------------------------------ 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5a77bd6e..59d50be4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ on: jobs: build-debian-package-jammy: name: build (Ubuntu 22.04) - runs-on: builder + runs-on: ubuntu-latest container: image: yanetplatform/builder-lite steps: @@ -23,35 +23,15 @@ jobs: export YANET_VERSION_REVISION=${{github.run_number}} export YANET_VERSION_HASH=${{github.sha}} export YANET_VERSION_CUSTOM=stable - meson setup --prefix=/target \ - -Dtarget=release \ - -Darch=corei7,broadwell,knl \ - -Dversion_major=$YANET_VERSION_MAJOR \ - -Dversion_minor=$YANET_VERSION_MINOR \ - -Dversion_revision=$YANET_VERSION_REVISION \ - -Dversion_hash=$YANET_VERSION_HASH \ - -Dversion_custom=$YANET_VERSION_CUSTOM \ - build - meson compile -C build - - run: meson install -C build - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - cp -r debian /target/DEBIAN - sed -i "s/__VERSION__/${YANET_VERSION}/g" /target/DEBIAN/control - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - mkdir /export - dpkg-deb -b "/target" /export/yanet_${YANET_VERSION}_ubuntu22.04.deb + dpkg-buildpackage -b - uses: actions/upload-artifact@v3 with: - name: target_debian - path: /export/yanet*.deb + name: target_debian22.04 + path: /__w/yanet/yanet*.deb build-debian-package-bionic: name: build (Ubuntu 18.04) - runs-on: builder + runs-on: ubuntu-latest container: image: yanetplatform/builder_ubuntu18.04-lite steps: @@ -66,28 +46,8 @@ jobs: export YANET_VERSION_REVISION=${{github.run_number}} export YANET_VERSION_HASH=${{github.sha}} export YANET_VERSION_CUSTOM=stable - meson setup --prefix=/target \ - -Dtarget=release \ - -Darch=corei7,broadwell,knl \ - -Dversion_major=$YANET_VERSION_MAJOR \ - -Dversion_minor=$YANET_VERSION_MINOR \ - -Dversion_revision=$YANET_VERSION_REVISION \ - -Dversion_hash=$YANET_VERSION_HASH \ - -Dversion_custom=$YANET_VERSION_CUSTOM \ - build - meson compile -C build - - run: meson install -C build - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - cp -r debian /target/DEBIAN - sed -i "s/__VERSION__/${YANET_VERSION}/g" /target/DEBIAN/control - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - mkdir /export - dpkg-deb -b "/target" /export/yanet_${YANET_VERSION}_ubuntu18.04.deb + dpkg-buildpackage -b - uses: actions/upload-artifact@v3 with: - name: target_debian - path: /export/yanet*.deb + name: target_debian18.04 + path: /__w/yanet/yanet*.deb From 716dc07b4f1741af6aeeb5840c136ffcf9536e37 Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Thu, 22 Aug 2024 14:26:06 +0300 Subject: [PATCH 073/195] Export image to Dockerhub --- .github/workflows/release.yml | 64 ++++++++++++++--------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59d50be4..90407dd6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,52 +2,38 @@ name: Release on: push: - tags: - - 'v[0-9]+.[0-9]+' + branch: + - 'release/*' jobs: build-debian-package-jammy: - name: build (Ubuntu 22.04) + name: build-image runs-on: ubuntu-latest - container: - image: yanetplatform/builder-lite + permissions: + packages: write + contents: read + id-token: write steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 with: submodules: recursive - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - export YANET_VERSION_MAJOR=${YANET_VERSION%.*} - export YANET_VERSION_MINOR=${YANET_VERSION#*.} - export YANET_VERSION_REVISION=${{github.run_number}} - export YANET_VERSION_HASH=${{github.sha}} - export YANET_VERSION_CUSTOM=stable - dpkg-buildpackage -b - - uses: actions/upload-artifact@v3 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 with: - name: target_debian22.04 - path: /__w/yanet/yanet*.deb - - build-debian-package-bionic: - name: build (Ubuntu 18.04) - runs-on: ubuntu-latest - container: - image: yanetplatform/builder_ubuntu18.04-lite - steps: - - uses: actions/checkout@v1 + images: yanetplatform/yanet + - name: Log in to Docker Hub + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: - submodules: recursive - - run: | - export YANET_VERSION=${{github.ref_name}} - export YANET_VERSION=${YANET_VERSION#v} - export YANET_VERSION_MAJOR=${YANET_VERSION%.*} - export YANET_VERSION_MINOR=${YANET_VERSION#*.} - export YANET_VERSION_REVISION=${{github.run_number}} - export YANET_VERSION_HASH=${{github.sha}} - export YANET_VERSION_CUSTOM=stable - dpkg-buildpackage -b - - uses: actions/upload-artifact@v3 + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build and push Docker image + id: push + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 with: - name: target_debian18.04 - path: /__w/yanet/yanet*.deb + context: . + file: ./build/Dockerfile.image + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} From 0a00e51fc828c547eb36c38698faae8b5ab4f3fe Mon Sep 17 00:00:00 2001 From: Georgy Kirichenko Date: Tue, 17 Sep 2024 16:48:48 +0300 Subject: [PATCH 074/195] Export version variables --- .github/workflows/release.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90407dd6..6abc23de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,15 @@ jobs: uses: actions/checkout@v4 with: submodules: recursive + - name: version + run: | + export YANET_VERSION=${{github.ref_name}} + export YANET_VERSION=${YANET_VERSION} + export YANET_VERSION_MAJOR=${YANET_VERSION%.*} + export YANET_VERSION_MINOR=${YANET_VERSION#*.} + export YANET_VERSION_REVISION=${{github.run_number}} + export YANET_VERSION_HASH=${{github.sha}} + export YANET_VERSION_CUSTOM=stable - name: Docker meta id: meta uses: docker/metadata-action@v5 From 5e2ae53b56cc25ec2b55621d1d1a52c93d082f64 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Wed, 11 Sep 2024 16:58:27 +0300 Subject: [PATCH 075/195] Functions for working with shared memory are implemented - Work with shared memory Posix standard and System V is supported. - Two functions are implemented for each standard - to create a buffer (on the server) and to open the created buffer (on the client). - When creating a buffer, one can, if necessary, specify the socket (numa node) on which to allocate memory, and whether to use HugeMem. --- common/shared_memory.h | 342 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 common/shared_memory.h diff --git a/common/shared_memory.h b/common/shared_memory.h new file mode 100644 index 00000000..0d118e1c --- /dev/null +++ b/common/shared_memory.h @@ -0,0 +1,342 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "define.h" +#include "type.h" + +namespace common::ipc +{ + +class SharedMemory +{ +public: + static constexpr int mode_create = 0644; + + /* + * Check if HugeTLB Pages usage is available + * Searches for a string of the type "Hugetlb: zzz kB" in the /proc/meminfo and returns true + * if the parameter value is not 0 + * Some details in the Linux kernel source file Documentation/admin-guide/mm/hugetlbpage.rst + */ + static bool HugeTlbEnabled() + { + const char* path_meminfo = "/proc/meminfo"; + const char* str_hugetlb = "Hugetlb:"; + + FILE* fd = fopen(path_meminfo, "r"); + if (fd == NULL) + { + YANET_LOG_ERROR("Cannot open %s, error %d: %s\n", path_meminfo, errno, strerror(errno)); + return false; + } + + bool hugetlb_enabled = false; + bool line_found = false; + unsigned hugetlb_len = sizeof(str_hugetlb); + char buffer[256]; + while (fgets(buffer, sizeof(buffer), fd)) + { + if (strncmp(buffer, str_hugetlb, hugetlb_len) == 0) + { + char* str = &buffer[hugetlb_len]; + while (isspace((int)*str)) + { + str++; + } + char* endptr; + unsigned long long size = strtoull(str, &endptr, 0); + // The string still contains kB (or mB, gB), but it only matters to us + // whether the value is 0 or not + if (errno != 0) + { + YANET_LOG_ERROR("Error parsing size of %s in file %s\n", str_hugetlb, path_meminfo); + return false; + } + hugetlb_enabled = (size != 0); + line_found = true; + break; + } + } + fclose(fd); + + if (!line_found) + { + YANET_LOG_WARNING("Not found string '%s' in file: %s\n", str_hugetlb, path_meminfo); + } + + return hugetlb_enabled; + } + + /* + * Creating a buffer in shared memory (POSIX shared memory) + * Params: + * - filename - the name of the file without a path, the file is created in /dev/shm + * - size - buffer size + * - use_huge_tlb - if true, it will use MAP_HUGETLB + * - socket_id - id of the numa node on which one want to allocate a buffer, + * if std::nullptr - it will be selected automatically by the system + * Return value: + * void* - address of the allocated buffer, nullptr if an error occurred + */ + static void* CreateBufferFile(std::string filename, size_t size, bool use_huge_tlb, std::optional socket_id) + { + // Open or creare shared memory file + int flags_open = O_RDWR | O_CREAT; + int fd = shm_open(filename.c_str(), flags_open, mode_create); + if (fd == -1) + { + YANET_LOG_ERROR("shm_open(%s, %d, %o): %s\n", filename.c_str(), flags_open, mode_create, strerror(errno)); + return nullptr; + } + + // Truncate - set file size + int res_trunc = ftruncate(fd, size); + if (res_trunc < 0) + { + YANET_LOG_ERROR("filename=%s, ftruncate(%d, %lu): %s\n", filename.c_str(), fd, size, strerror(errno)); + close(fd); + return nullptr; + } + + // Set memory policy if necessary + auto [oldmask, oldpolicy] = SetMemoryPolicy(socket_id); + + // Mmap memory + int prot = PROT_READ | PROT_WRITE; + int flags_mmap = GetFlags(MAP_SHARED, use_huge_tlb, MAP_HUGETLB); + void* addr = mmap(nullptr, size, prot, flags_mmap, fd, 0); + if (addr == MAP_FAILED) + { + // The error occurs when trying to use HugeTlb when this feature is not enabled in the kernel + YANET_LOG_ERROR("filename=%s, mmap(%p, %lu, %d, %d, %d, 0)\n", filename.c_str(), nullptr, size, prot, flags_mmap, fd); + return nullptr; + } + + // Zero memory + memset(addr, 0, size); + + // Restore memory policy if necessary + RestoreMemoryPolicy(socket_id, oldmask, oldpolicy); + + // Close file + if (close(fd) != 0) + { + YANET_LOG_ERROR("filename=%s, error fclose %d: %s\n", filename.c_str(), errno, strerror(errno)); + } + + return addr; + } + + /* + * Creating a buffer in shared memory (System V shared memory) + * Params: + * - key - the identifier of segment + * - size - buffer size + * - use_huge_tlb - if true, it will use MAP_HUGETLB + * - socket_id - id of the numa node on which one want to allocate a buffer, + * if std::nullptr - it will be selected automatically by the system + * Return value: + * void* - address of the allocated buffer, nullptr if an error occurred + */ + static void* CreateBufferKey(key_t key, size_t size, bool use_huge_tlb, std::optional socket_id) + { + // Delete old segment + int shmid = shmget(key, 0, 0); + if ((shmid != -1) && (shmctl(shmid, IPC_RMID, nullptr) < 0)) + { + YANET_LOG_ERROR("key = %d, shmctl(%d, IPC_RMID, nullptr): %s\n", key, shmid, strerror(errno)); + return nullptr; + } + + // Creare shared memory segment + int flags = GetFlags(IPC_CREAT | mode_create, use_huge_tlb, SHM_HUGETLB); + shmid = shmget(key, size, flags); + if (shmid == -1) + { + YANET_LOG_ERROR("shmget(%d, %lu, %d): %s\n", key, size, flags, strerror(errno)); + return nullptr; + } + + // Set memory policy if necessary + auto [oldmask, oldpolicy] = SetMemoryPolicy(socket_id); + + // Mmap memory + void* addr = shmat(shmid, nullptr, 0); + if (addr == (void*)-1) + { + YANET_LOG_ERROR("shmat(%d, %p, %d): %s\n", shmid, nullptr, 0, strerror(errno)); + return nullptr; + } + + // Zero memory + memset(addr, 0, size); + + // Restore memory policy if necessary + RestoreMemoryPolicy(socket_id, oldmask, oldpolicy); + + return addr; + } + + /* + * Open an existing buffer in shared memory (POSIX shared memory) + * Params: + * - filename - the name of the file without a path, the file is created in /dev/shm + * - use_huge_tlb - if true, it will use MAP_HUGETLB + * Return values: + * - void* - address of the allocated buffer, nullptr if an error occurred + * - size - buffer size + */ + static std::pair OpenBufferFile(std::string filename, bool use_huge_tlb) + { + // Open shared memory file + int flags_open = O_RDONLY; + int fd = shm_open(filename.c_str(), flags_open, mode_create); + if (fd == -1) + { + YANET_LOG_ERROR("shm_open(%s, %d, %o): %s\n", filename.c_str(), flags_open, mode_create, strerror(errno)); + return {nullptr, 0}; + } + + // Get the size of file + struct stat buffer; + int status = fstat(fd, &buffer); + if (status != 0) + { + YANET_LOG_ERROR("filename=%s, fstat(%d, &buffer): %s\n", filename.c_str(), fd, strerror(errno)); + close(fd); + return {nullptr, 0}; + } + size_t size = buffer.st_size; + + // Mmap memory + int prot = PROT_READ; + int flags_mmap = GetFlags(MAP_SHARED, use_huge_tlb, MAP_HUGETLB); + void* addr = mmap(nullptr, size, prot, flags_mmap, fd, 0); + if (addr == MAP_FAILED) + { + YANET_LOG_ERROR("filename=%s, mmap(%p, %lu, %d, %d, %d, 0)\n", filename.c_str(), nullptr, size, prot, flags_mmap, fd); + close(fd); + return {nullptr, 0}; + } + + // Close file + if (close(fd) != 0) + { + YANET_LOG_ERROR("filename=%s, error fclose %d: %s\n", filename.c_str(), errno, strerror(errno)); + } + + return {addr, size}; + } + + /* + * Open an existing buffer in shared memory (System V shared memory) + * Params: + * - key - the identifier of segment + * - use_huge_tlb - if true, it will use MAP_HUGETLB + * Return values: + * - void* - address of the allocated buffer, nullptr if an error occurred + * - size - buffer size + */ + static std::pair OpenBufferKey(key_t key, bool use_huge_tlb) + { + // Open shared memory segment + int flags = GetFlags(0, use_huge_tlb, SHM_HUGETLB); + int shmid = shmget(key, 0, flags); + if (shmid == -1) + { + YANET_LOG_ERROR("shmget(%d, %d, %d): %s\n", key, 0, flags, strerror(errno)); + return {nullptr, 0}; + } + + // Get the size of segment + struct shmid_ds buf; + if (shmctl(shmid, IPC_STAT, &buf) == -1) + { + YANET_LOG_ERROR("key=%d, shmctl(%d, IPC_STAT, &buf): %s\n", key, shmid, strerror(errno)); + return {nullptr, 0}; + } + size_t size = buf.shm_segsz; + + // Mmap memory + int shmflg = SHM_RDONLY; + auto addr = shmat(shmid, nullptr, shmflg); + if (addr == (void*)-1) + { + YANET_LOG_ERROR("key=%d, shmat(%d, %p, %d) = -1\n", key, shmid, nullptr, shmflg); + return {nullptr, 0}; + } + + return {addr, size}; + } + +private: + static std::pair SetMemoryPolicy(std::optional socket_id) + { + struct bitmask* oldmask = nullptr; + int oldpolicy; + if (socket_id.has_value()) + { + oldmask = numa_allocate_nodemask(); + if (get_mempolicy(&oldpolicy, oldmask->maskp, oldmask->size + 1, 0, 0) < 0) + { + YANET_LOG_WARNING("get_mempolicy(): %s, continue with the use of sockets turned off\n", strerror(errno)); + oldpolicy = MPOL_DEFAULT; + socket_id = std::nullopt; + } + else + { + numa_set_preferred(*socket_id); + if (errno != 0) + { + YANET_LOG_ERROR("numa_set_preferred(%d): %s\n", *socket_id, strerror(errno)); + } + } + } + return {oldmask, oldpolicy}; + } + + static void RestoreMemoryPolicy(std::optional socket_id, struct bitmask* oldmask, int oldpolicy) + { + if (socket_id.has_value()) + { + if (oldpolicy == MPOL_DEFAULT) + { + numa_set_localalloc(); + } + else if (set_mempolicy(oldpolicy, oldmask->maskp, oldmask->size + 1) < 0) + { + YANET_LOG_ERROR("set_mempolicy(): %s\n", strerror(errno)); + numa_set_localalloc(); + } + numa_free_cpumask(oldmask); + } + } + + static int GetFlags(int start_value, bool use_huge_tlb, int flag_of_huge_tlb) + { + int flags = start_value; + if (use_huge_tlb) + { + if (!HugeTlbEnabled()) + { + YANET_LOG_ERROR("Attempt to use HugeTlb, but it is not enabled\n"); + } + else + { + flags |= flag_of_huge_tlb; + } + } + return flags; + } +}; + +} // namespace common::ipc From 1e92e461bccea1a97fbd177118fd8fff53fb5244 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 19:37:01 +0300 Subject: [PATCH 076/195] Added unit tests to check the work with shared memory --- common/unittest/meson.build | 5 ++- common/unittest/shared_memory.cpp | 53 +++++++++++++++++++++++++++++++ common/unittest/unittest.cpp | 3 ++ meson.build | 2 ++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 common/unittest/shared_memory.cpp create mode 100644 common/unittest/unittest.cpp diff --git a/common/unittest/meson.build b/common/unittest/meson.build index f3cd3852..53458d48 100644 --- a/common/unittest/meson.build +++ b/common/unittest/meson.build @@ -1,11 +1,14 @@ dependencies = [] +dependencies += libjson.get_variable('nlohmann_json_dep') dependencies += dependency('threads') dependencies += dependency('gtest') dependencies += dependency('gtest_main') common_sources = files() -sources = files('static_vector.cpp', +sources = files('unittest.cpp', + 'static_vector.cpp', + 'shared_memory.cpp', ) arch = 'corei7' diff --git a/common/unittest/shared_memory.cpp b/common/unittest/shared_memory.cpp new file mode 100644 index 00000000..67e7c971 --- /dev/null +++ b/common/unittest/shared_memory.cpp @@ -0,0 +1,53 @@ +#include + +#include "../shared_memory.h" + +void TestForSize(void* buffer_writer, void* buffer_reader, size_t size, size_t size_reader) +{ + ASSERT_TRUE(buffer_writer != nullptr); + ASSERT_TRUE(buffer_reader != nullptr); + ASSERT_EQ(size, size_reader); + + uint8_t* buffer_writer8 = reinterpret_cast(buffer_writer); + uint8_t* buffer_reader8 = reinterpret_cast(buffer_reader); + + for (uint64_t index = 0; index < size; index++) + { + buffer_writer8[index] = (index & 0xff); + } + + for (uint64_t index = 0; index < size; index++) + { + ASSERT_EQ(buffer_writer8[index], buffer_reader8[index]); + } +} + +static std::vector sizes_test = {1024, 512, 4096, 8192, 4096, 1024}; + +TEST(SharedMemory, CreateAndOpenSharedMemoryBufferFile) +{ + bool use_huge_tlb = common::ipc::SharedMemory::HugeTlbEnabled(); + std::string filename("test_shared_memory.shm"); + for (size_t size : sizes_test) + { + void* buffer_writer = common::ipc::SharedMemory::CreateBufferFile(filename, size, use_huge_tlb, 0); + auto [buffer_reader, size_reader] = common::ipc::SharedMemory::OpenBufferFile(filename, use_huge_tlb); + TestForSize(buffer_writer, buffer_reader, size, size_reader); + ASSERT_EQ(munmap(buffer_writer, size), 0); + ASSERT_EQ(munmap(buffer_reader, size), 0); + } +} + +TEST(SharedMemory, CreateAndOpenSharedMemoryBufferKey) +{ + bool use_huge_tlb = common::ipc::SharedMemory::HugeTlbEnabled(); + key_t key = 54321; + for (size_t size : sizes_test) + { + void* buffer_writer = common::ipc::SharedMemory::CreateBufferKey(key, size, use_huge_tlb, 0); + auto [buffer_reader, size_reader] = common::ipc::SharedMemory::OpenBufferKey(key, use_huge_tlb); + TestForSize(buffer_writer, buffer_reader, size, size_reader); + ASSERT_EQ(shmdt(buffer_writer), 0); + ASSERT_EQ(shmdt(buffer_reader), 0); + } +} diff --git a/common/unittest/unittest.cpp b/common/unittest/unittest.cpp new file mode 100644 index 00000000..9cfa1ba3 --- /dev/null +++ b/common/unittest/unittest.cpp @@ -0,0 +1,3 @@ +#include "common/define.h" + +common::log::LogPriority common::log::logPriority = common::log::TLOG_DEBUG; diff --git a/meson.build b/meson.build index a77af658..29fd6af9 100644 --- a/meson.build +++ b/meson.build @@ -37,6 +37,8 @@ add_global_arguments(compiler_args, language: 'cpp') add_global_arguments('-DGOOGLE_PROTOBUF_NO_RTTI', language: 'cpp') +add_project_link_arguments('-lnuma', language : 'cpp') + add_global_arguments('-Wno-unused-parameter', language: 'cpp') if target_option.contains('librib') From 55ab0ce476ebeeaded3cee0c219083c62399b76f Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 20:45:07 +0300 Subject: [PATCH 077/195] An interface implemented for storing data related to counters in shared memory --- common/sdpclient.h | 462 ++++++++++++++++++++++++++++++++++++++++++ common/sdpcommon.h | 237 ++++++++++++++++++++++ dataplane/sdpserver.h | 220 ++++++++++++++++++++ 3 files changed, 919 insertions(+) create mode 100644 common/sdpclient.h create mode 100644 common/sdpcommon.h create mode 100644 dataplane/sdpserver.h diff --git a/common/sdpclient.h b/common/sdpclient.h new file mode 100644 index 00000000..b2b91007 --- /dev/null +++ b/common/sdpclient.h @@ -0,0 +1,462 @@ +#pragma once + +#include + +#include "result.h" +#include "sdpcommon.h" +#include "shared_memory.h" + +#define SHARED_MEMORY_REREAD_TIMEOUT_MICROSECONDS 100 +#define SHARED_MEMORY_REREAD_MAXIMUM_ATTEMPTS 100 + +namespace common::sdp +{ + +class SdpClient +{ +public: + /* + * The function opens buffers created in Dataplane in shared memory and fills in the necessary fields in the + * DataPlaneInSharedMemory structure + * Params: + * sdp_data - the Data Plane In Shared Memory object contains data about connection to shared memory buffers + * open_workers_data - if false, only the main file is opened, if true, files with workers counters on + * different numa nodes are also opened + * Returns: result::success if successful, in case of error hresult::error InitSharedMemory + */ + [[nodiscard]] static eResult ReadSharedMemoryData(DataPlaneInSharedMemory& sdp_data, bool open_workers_data) + { + // Read main file + int number_of_attempts = 0; + eResultRead result = eResultRead::need_reread; + while (result != eResultRead::ok) + { + number_of_attempts++; + std::string message_error; + uint64_t size_mmap; + result = ReadItAgainMainFileDataplane(sdp_data, size_mmap, message_error); + if (result == eResultRead::error) + { +#ifdef YANET_USE_POSIX_SHARED_MEMORY + YANET_LOG_ERROR("File %s. %s\n", YANET_SHARED_MEMORY_FILE_DATAPLANE, message_error.c_str()); +#else + YANET_LOG_ERROR("Key %d. %s\n", YANET_SHARED_MEMORY_KEY_DATAPLANE, message_error.c_str()); +#endif + sdp_data.UnmapBuffers(size_mmap); + return eResult::errorInitSharedMemory; + } + else if (result == eResultRead::need_reread) + { + sdp_data.UnmapBuffers(size_mmap); + if (number_of_attempts >= SHARED_MEMORY_REREAD_MAXIMUM_ATTEMPTS) + { +#ifdef YANET_USE_POSIX_SHARED_MEMORY + YANET_LOG_ERROR("File %s. Attempts were made to read: %d. %s\n", + YANET_SHARED_MEMORY_FILE_DATAPLANE, + number_of_attempts, + message_error.c_str()); +#else + YANET_LOG_ERROR("Key %d. Attempts were made to read: %d. %s\n", + YANET_SHARED_MEMORY_KEY_DATAPLANE, + number_of_attempts, + message_error.c_str()); +#endif + return eResult::errorInitSharedMemory; + } +#ifdef YANET_USE_POSIX_SHARED_MEMORY + YANET_LOG_WARNING("File %s. %s\n", YANET_SHARED_MEMORY_FILE_DATAPLANE, message_error.c_str()); +#else + YANET_LOG_WARNING("KEY %d. %s\n", YANET_SHARED_MEMORY_KEY_DATAPLANE, message_error.c_str()); +#endif + std::this_thread::sleep_for(std::chrono::microseconds{SHARED_MEMORY_REREAD_TIMEOUT_MICROSECONDS}); + } + } + + if (!open_workers_data) + { + return eResult::success; + } + + // Read workers files + + // Get all sockets + std::map> sockets_buffer; + for (const auto& iter : sdp_data.workers) + { + sockets_buffer[iter.second.socket] = {nullptr, 0}; + } + for (const auto& iter : sdp_data.workers_gc) + { + sockets_buffer[iter.second.socket] = {nullptr, 0}; + } + + // Open buffers for each socket +#ifndef YANET_USE_POSIX_SHARED_MEMORY + key_t key_shared_memory_segment = YANET_SHARED_MEMORY_KEY_DATAPLANE; +#endif + for (auto& iter : sockets_buffer) + { +#ifdef YANET_USE_POSIX_SHARED_MEMORY + std::string filename = FileNameWorkerOnNumaNode(iter.first); + auto [buffer, size] = common::ipc::SharedMemory::OpenBufferFile(filename, false); + if (buffer == nullptr) + { + YANET_LOG_ERROR("Error openning shared memory buffer from file: %s\n", filename.c_str()); + return eResult::errorInitSharedMemory; + } +#else + key_shared_memory_segment++; + auto [buffer, size] = common::ipc::SharedMemory::OpenBufferKey(key_shared_memory_segment, false); + if (buffer == nullptr) + { + YANET_LOG_ERROR("Error openning shared memory buffer from segment: %d\n", key_shared_memory_segment); + return eResult::errorInitSharedMemory; + } +#endif + iter.second = {buffer, size}; + } + + // Set buffers for workers + for (auto& iter : sdp_data.workers) + { + uint64_t shift = iter.second.shift_in_socket; + auto [buffer, size] = sockets_buffer[iter.second.socket]; + if (shift + sdp_data.metadata_worker.size > size) + { + YANET_LOG_ERROR("Error in file for socket: %d, file size: %ld, worker: %d, metadata_worker.size: %ld, shift: %ld\n", + iter.second.socket, + size, + iter.first, + sdp_data.metadata_worker.size, + shift); + return eResult::errorInitSharedMemory; + } + iter.second.buffer = ShiftBuffer(buffer, shift); + } + for (auto& iter : sdp_data.workers_gc) + { + uint64_t shift = iter.second.shift_in_socket; + auto [buffer, size] = sockets_buffer[iter.second.socket]; + if (shift + sdp_data.metadata_worker_gc.size > size) + { + YANET_LOG_ERROR("Error in file for socket: %d, file size: %ld, worker: %d, metadata_worker_gc.size: %ld, shift: %ld\n", + iter.second.socket, + size, + iter.first, + sdp_data.metadata_worker_gc.size, + shift); + return eResult::errorInitSharedMemory; + } + iter.second.buffer = ShiftBuffer(buffer, shift); + } + + return eResult::success; + } + + /* + * The counter name function gets its value on workers. + * Params: + * - sdp_data - the Data Plane In Shared Memory object contains data about connection to shared memory buffers + * - counter_name - the name of the counter + * - core_id is the id of the core on which the worker is running for which it need to get the counter value, + * if it passed std::nullopt, then it gets from all workers + * Return: The counter value for each core + */ + static std::map GetCounterByName(const DataPlaneInSharedMemory& sdp_data, + const std::string& counter_name, + std::optional core_id) + { + std::map result; + + // Find counter in workers + const auto& iter_workers = sdp_data.metadata_worker.counter_positions.find(counter_name); + if (iter_workers != sdp_data.metadata_worker.counter_positions.end()) + { + uint64_t index = iter_workers->second; + for (const auto& [worker_core_id, worker_info] : sdp_data.workers) + { + if (!core_id.has_value() || worker_core_id == core_id) + { + uint64_t* counters = common::sdp::ShiftBuffer(worker_info.buffer, + sdp_data.metadata_worker.start_counters); + result[worker_core_id] = counters[index]; + } + } + } + + // Find counter in workers_gc + const auto& iter_workers_gc = sdp_data.metadata_worker_gc.counter_positions.find(counter_name); + if (iter_workers_gc != sdp_data.metadata_worker_gc.counter_positions.end()) + { + uint64_t index = iter_workers_gc->second; + for (const auto& [worker_core_id, worker_info] : sdp_data.workers_gc) + { + if (!core_id.has_value() || worker_core_id == core_id) + { + uint64_t* counters = common::sdp::ShiftBuffer(worker_info.buffer, + sdp_data.metadata_worker.start_counters); + result[worker_core_id] = counters[index]; + } + } + } + + return result; + } + + /* + * The function works like the previous one, but it opens buffers in shared memory by itself. In case of + * an opening error, it calls exit(). + */ + static std::map GetCounterByName(const std::string& counter_name, + std::optional core_id) + { + DataPlaneInSharedMemory sdp_data; + if (ReadSharedMemoryData(sdp_data, true) != eResult::success) + { + std::exit(1); + } + return GetCounterByName(sdp_data, counter_name, core_id); + } + + /* + * The function for each counter ID gets the sum of the values for it from all workers + * Params: + * - sdp_data - the Data Plane In Shared Memory object contains data about connection to shared memory buffers + * - counter_ids - counter IDs + * Return: Aggregated counter values + */ + static std::vector GetCounters(const DataPlaneInSharedMemory& sdp_data, + const std::vector& counter_ids) + { + std::vector result(counter_ids.size()); + std::vector buffers; + for (const auto& iter : sdp_data.workers) + { + buffers.push_back(common::sdp::ShiftBuffer(iter.second.buffer, + sdp_data.metadata_worker.start_counters)); + } + + for (size_t i = 0; i < counter_ids.size(); i++) + { + auto counter_id = counter_ids[i]; + if (counter_id >= YANET_CONFIG_COUNTERS_SIZE) + { + continue; + } + + uint64_t counter = 0; + for (const auto& buffer : buffers) + { + counter += buffer[counter_id]; + } + + result[i] = counter; + } + + return result; + } + + /* + * The function works like the previous one, but it opens buffers in shared memory by itself. In case of + * an opening error, it calls exit(). + */ + static std::vector GetCounters(const std::vector& counter_ids) + { + DataPlaneInSharedMemory sdp_data; + if (ReadSharedMemoryData(sdp_data, true) != eResult::success) + { + std::exit(1); + } + return GetCounters(sdp_data, counter_ids); + } + +private: + enum class eResultRead : uint8_t + { + ok, + need_reread, + error + }; + + static eResultRead ReadMainFileDataplane(DataPlaneInSharedMemory& sdp_data, uint64_t& size_mmap, std::string& message) + { + // Try open buffer +#ifdef YANET_USE_POSIX_SHARED_MEMORY + auto [buffer, size] = common::ipc::SharedMemory::OpenBufferFile(YANET_SHARED_MEMORY_FILE_DATAPLANE, false); +#else + auto [buffer, size] = common::ipc::SharedMemory::OpenBufferKey(YANET_SHARED_MEMORY_KEY_DATAPLANE, false); +#endif + size_mmap = size; + if (buffer == nullptr) + { + message = "File opening error"; + return eResultRead::error; + } + sdp_data.dataplane_data = buffer; + + // Compare size of buffer and size header of metadata dataplane + if (size < common::sdp::DataPlaneInSharedMemory::size_header) + { + message = "Size of file " + std::to_string(size) + " < " + + std::to_string(common::sdp::DataPlaneInSharedMemory::size_header) + " size of header"; + return eResultRead::need_reread; + } + + // WORKERS + { + sdp_data.workers.clear(); + sdp_data.workers_gc.clear(); + + uint64_t start_workers = ReadValue(buffer, 0); + uint64_t size_workers = ReadValue(buffer, 1); + if ((start_workers + size_workers > size) || (2 * sizeof(uint64_t) > size_workers)) + { + message = "Bad postion info section WORKERS"; + return eResultRead::need_reread; + } + uint64_t index = start_workers / sizeof(uint64_t); + + uint64_t count_workers = ReadValue(buffer, index++); + uint64_t count_workers_gc = ReadValue(buffer, index++); + if ((2 + 3 * (count_workers + count_workers_gc)) * sizeof(uint64_t) > size_workers) + { + message = "Size of section WORKERS < (2 + 3 * (count_workers + count_workers_gc)) * sizeof(uint64_t)"; + return eResultRead::need_reread; + } + + for (uint64_t index_worker = 0; index_worker < count_workers; index_worker++) + { + uint64_t coreId = ReadValue(buffer, index++); + tSocketId socket = ReadValue(buffer, index++); + uint64_t shift_in_socket = ReadValue(buffer, index++); + sdp_data.workers[coreId] = {socket, shift_in_socket, nullptr}; + } + + for (uint64_t index_worker = 0; index_worker < count_workers_gc; index_worker++) + { + uint64_t coreId = ReadValue(buffer, index++); + tSocketId socket = ReadValue(buffer, index++); + uint64_t shift_in_socket = ReadValue(buffer, index++); + sdp_data.workers_gc[coreId] = {socket, shift_in_socket, nullptr}; + } + } + + // WORKERS_METADATA + { + uint64_t start_workers_metadata = ReadValue(buffer, 2); + uint64_t size_workers_metadata = ReadValue(buffer, 3); + if ((start_workers_metadata + size_workers_metadata > size) || (size_workers_metadata < 128)) + { + message = "Bad postion info section WORKERS_METADATA"; + return eResultRead::need_reread; + } + uint64_t index = start_workers_metadata / sizeof(uint64_t); + + // 0-5 - values from MetadataWorker + sdp_data.metadata_worker.start_counters = ReadValue(buffer, index); + sdp_data.metadata_worker.start_acl_counters = ReadValue(buffer, index + 1); + sdp_data.metadata_worker.start_bursts = ReadValue(buffer, index + 2); + sdp_data.metadata_worker.start_stats = ReadValue(buffer, index + 3); + sdp_data.metadata_worker.start_stats_ports = ReadValue(buffer, index + 4); + sdp_data.metadata_worker.size = ReadValue(buffer, index + 5); + // 6 - n1 = size MetadataWorker.counter_positions + uint64_t n1 = ReadValue(buffer, index + 6); + // 7-9 - значения из MetadataWorker + sdp_data.metadata_worker_gc.start_counters = ReadValue(buffer, index + 7); + sdp_data.metadata_worker_gc.start_stats = ReadValue(buffer, index + 8); + sdp_data.metadata_worker_gc.size = ReadValue(buffer, index + 9); + // 10 - n2 = size MetadataWorker.counter_positions + uint64_t n2 = ReadValue(buffer, index + 10); + + if (128 * (1 + n1 + n2) > size_workers_metadata) + { + message = "Size of section WORKERS_METADATA < 128 * (1 + n1 + n2)"; + return eResultRead::need_reread; + } + + if (!ReadMap(sdp_data.metadata_worker.counter_positions, buffer, start_workers_metadata + 128, n1)) + { + return eResultRead::need_reread; + } + if (!ReadMap(sdp_data.metadata_worker_gc.counter_positions, buffer, start_workers_metadata + 128 * (1 + n1), n2)) + { + return eResultRead::need_reread; + } + } + + // BUS + { + sdp_data.start_bus_section = ReadValue(buffer, 4); + sdp_data.size_bus_section = ReadValue(buffer, 5); + if (sdp_data.start_bus_section + sdp_data.size_bus_section > size) + { + message = "Bad postion info section BUS"; + return eResultRead::need_reread; + } + } + + return eResultRead::ok; + } + + static eResultRead ReadItAgainMainFileDataplane(DataPlaneInSharedMemory& sdp_data, uint64_t& size_mmap, std::string& message) + { + // First read + DataPlaneInSharedMemory tmp_data; + eResultRead result = ReadMainFileDataplane(tmp_data, size_mmap, message); + tmp_data.UnmapBuffers(size_mmap); + if (result != eResultRead::ok) + { + return result; + } + + // Sleep + std::this_thread::sleep_for(std::chrono::microseconds{SHARED_MEMORY_REREAD_TIMEOUT_MICROSECONDS}); + + // Second read + result = ReadMainFileDataplane(sdp_data, size_mmap, message); + if (result != eResultRead::ok) + { + return result; + } + else if (!(sdp_data == tmp_data)) + { + message = "The data changed during the re-reading"; + return eResultRead::need_reread; + } + + return eResultRead::ok; + } + + static uint64_t ReadValue(void* buffer, uint64_t index) + { + uint8_t* data = common::sdp::ShiftBuffer(buffer, index * sizeof(uint64_t)); + uint64_t result = 0; + for (int i = 0; i < 8; i++) + { + result = 256 * result + data[i]; + } + return result; + } + + static bool ReadMap(std::map& values, void* buffer, uint64_t shift, uint64_t count) + { + values.clear(); + for (uint64_t index = 0; index < count; index++) + { + void* current = common::sdp::ShiftBuffer(buffer, shift + 128 * index); + uint64_t value = ReadValue(current, 0); + char* str = common::sdp::ShiftBuffer(current, 8); + if (str[119] != 0) + { + // 119 - index of last symbol + return false; + } + std::string name = std::string(str); + values[name] = value; + } + + return true; + } +}; + +} // namespace common::sdp diff --git a/common/sdpcommon.h b/common/sdpcommon.h new file mode 100644 index 00000000..d3d7900c --- /dev/null +++ b/common/sdpcommon.h @@ -0,0 +1,237 @@ +#pragma once + +#include +#include +#include + +#include "define.h" +#include "idp.h" +#include "shared_memory.h" +#include "stream.h" +#include "type.h" + +// #define YANET_USE_POSIX_SHARED_MEMORY + +#ifdef YANET_USE_POSIX_SHARED_MEMORY + +#define YANET_SHARED_MEMORY_FILE_DATAPLANE "yanet_dataplane.shm" +#define YANET_SHARED_MEMORY_PREFIX_WORKERS "yanet_workers_node_" + +#else + +#define YANET_SHARED_MEMORY_KEY_DATAPLANE 54321 + +#endif + +/* + +The structure of data storage in memory DataPlaneInSharedMemory + +The following files are created to store data in shared memory: +1) The main file with information about workers, metadata, some common counters of the system +2) A separate file is created for each socket (numa node) - it stores the data of the worker counters + +All numeric values are stored as 64-bit numbers in Big Endian + +--------------------------------------- +1 - The main file +The file contains the following sections: +- HEADER +- WORKERS +- WORKERS_METADATA +- BUS + +HEADER - 1024 bytes in size (DataPlaneInSharedMemory::size_header) +Contains the beginning and the size of the remaining sections, 2 numbers each: +- 0,1 - WORKERS +- 2,3 - WORKERS_MET +- 4,5 - BUS + The remaining values are reserved + +WORKERS +Contains the following values: + 0 - n1 = number of workers + 1 - n2 = number of worker_gc + The following contains n1 + n2 triples of numbers: + n - core_id + n+1 - socket + n+2 - shift in socket + +WORKERS_METADATA + At the beginning, 11 64-bit numbers are written: + 0-5 - values from MetadataWorker + 6 - n1 = size MetadataWorker.counter_positions + 7-9 - values from MetadataWorker + 10 - n2 = size MetadataWorker.counter_positions + + Starting from 128 bytes, there are n1+n2 entries from counter_positions, each entry occupies 128 bytes: + The first 8 bytes are the value from the map + The remaining 120 bytes are a string (key), ending with a null byte + +BUS +Contains a buffer used by cBus counters + +--------------------------------------- +2 - Socket data file +The file consists of several blocks, each block corresponds to a worker or worker_gc. + +Block for worker + The block size is equal to MetadataWorker::size. + This block is divided into 5 blocks - counters, acl_counters, bursts, stats, stats_port. + To determine the beginning of a block, for example, stats: + DataPlaneInSharedMemory::workers_info[core_id].shift_in_socket + MetadataWorker::start_stats + +Block for worker_gc + The block size is equal to MetadataWorkerGc::size. + This block is divided into 2 blocks - counters, stats. + +*/ + +namespace common::sdp +{ + +#ifdef YANET_USE_POSIX_SHARED_MEMORY +inline std::string FileNameWorkerOnNumaNode(tSocketId socket_id) +{ + return YANET_SHARED_MEMORY_PREFIX_WORKERS + std::to_string(socket_id) + ".shm"; +} +#endif + +template +inline TResult ShiftBuffer(TBuffer buffer, uint64_t size) +{ + return reinterpret_cast((reinterpret_cast(buffer) + size)); +} + +template +bool MapsEqual(const std::map& left, const std::map& right) +{ + if (left.size() != right.size()) + { + return false; + } + + auto [stop_left, stop_right] = std::mismatch(left.begin(), left.end(), right.begin(), right.end()); + + return (stop_left == left.end()) && (stop_right == right.end()); +} + +struct MetadataWorker +{ + uint64_t start_counters; + uint64_t start_acl_counters; + uint64_t start_bursts; + uint64_t start_stats; + uint64_t start_stats_ports; + uint64_t size; + + std::map counter_positions; + + bool operator==(const MetadataWorker& other) const + { + return other.start_counters == start_counters && + other.start_acl_counters == start_acl_counters && + other.start_bursts == start_bursts && + other.start_stats == start_stats && + other.start_stats_ports == start_stats_ports && + other.size == size && + MapsEqual(other.counter_positions, counter_positions); + } +}; + +struct MetadataWorkerGc +{ + uint64_t start_counters; + uint64_t start_stats; + uint64_t size; + + std::map counter_positions; + + bool operator==(const MetadataWorkerGc& other) const + { + return other.start_counters == start_counters && + other.start_stats == start_stats && + other.size == size && + MapsEqual(other.counter_positions, counter_positions); + } +}; + +struct WorkerInSharedMemory +{ + tSocketId socket; + uint64_t shift_in_socket; + void* buffer; + + bool operator==(const WorkerInSharedMemory& other) const + { + return other.socket == socket && + other.shift_in_socket == shift_in_socket; + } +}; + +struct DataPlaneInSharedMemory +{ + static constexpr uint64_t size_header = 1024; + + using workers_info = std::map; + + workers_info workers; + workers_info workers_gc; + + MetadataWorker metadata_worker; + MetadataWorkerGc metadata_worker_gc; + + uint64_t size_workers_section; + uint64_t size_workers_metadata_section; + uint64_t size_bus_section; + + uint64_t size_dataplane_buffer; + void* dataplane_data = nullptr; + uint64_t start_bus_section; + + void UnmapBuffers(uint64_t size) + { + if (dataplane_data != nullptr) + { + if (munmap(dataplane_data, size) < 0) + { + YANET_LOG_ERROR("Error munmap %d: %s", errno, strerror(errno)); + } + dataplane_data = nullptr; + } + } + + bool operator==(const DataPlaneInSharedMemory& other) const + { + return other.metadata_worker == metadata_worker && + other.metadata_worker_gc == metadata_worker_gc && + other.start_bus_section == start_bus_section && + MapsEqual(other.workers, workers) && + MapsEqual(other.workers_gc, workers_gc); + } + + void FillSizes() + { + size_workers_section = Allign64((2 + 3 * (workers.size() + workers_gc.size())) * sizeof(uint64_t)); + size_workers_metadata_section = 128 * (1 + metadata_worker.counter_positions.size() + metadata_worker_gc.counter_positions.size()); + size_bus_section = Allign64(size_bus_section); + size_dataplane_buffer = size_header + size_workers_section + size_workers_metadata_section + size_bus_section; + } + + static uint64_t Allign64(uint64_t value) + { + return ((value + 63) / 64) * 64; + } + + std::tuple BuffersBus() const + { + uint32_t count_errors = static_cast(common::idp::errorType::size); + uint32_t count_requests = static_cast(common::idp::requestType::size); + uint64_t* requests = common::sdp::ShiftBuffer(dataplane_data, start_bus_section); + uint64_t* errors = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + count_requests * sizeof(uint64_t)); + uint64_t* durations = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + (count_requests + count_errors) * sizeof(uint64_t)); + return {requests, errors, durations}; + } +}; + +} // namespace common::sdp diff --git a/dataplane/sdpserver.h b/dataplane/sdpserver.h new file mode 100644 index 00000000..e224ee92 --- /dev/null +++ b/dataplane/sdpserver.h @@ -0,0 +1,220 @@ +#pragma once + +#include "common/result.h" +#include "common/sdpcommon.h" +#include "type.h" + +namespace common::sdp +{ + +class SdrSever +{ +public: + static eResult PrepareSharedMemoryData(DataPlaneInSharedMemory& sdp_data, + const std::vector& workers_id, + const std::vector& workers_gc_id, + bool use_huge_tlb) + { + // Part 1 - prepare data workers + // + std::map sockets_shifts; + + // Fill workers info + for (tCoreId core_id : workers_id) + { + tSocketId socket_id = GetNumaNode(core_id); + sdp_data.workers[core_id] = {socket_id, sockets_shifts[socket_id], nullptr}; + sockets_shifts[socket_id] += sdp_data.metadata_worker.size; + } + + // Fill workers_gc info + for (tCoreId core_id : workers_gc_id) + { + tSocketId socket_id = GetNumaNode(core_id); + sdp_data.workers_gc[core_id] = {socket_id, sockets_shifts[socket_id], nullptr}; + sockets_shifts[socket_id] += sdp_data.metadata_worker_gc.size; + } + + // Create buffers in shared memory for workers in numa nodes +#ifndef YANET_USE_POSIX_SHARED_MEMORY + key_t key_shared_memory_segment = YANET_SHARED_MEMORY_KEY_DATAPLANE; +#endif + std::map sockets_buffers; + for (auto [socket_id, size] : sockets_shifts) + { +#ifdef YANET_USE_POSIX_SHARED_MEMORY + std::string filename = common::sdp::FileNameWorkerOnNumaNode(socket_id); + void* buffer = common::ipc::SharedMemory::CreateBufferFile(filename, size, use_huge_tlb, socket_id); + if (buffer == nullptr) + { + YANET_LOG_ERROR("Error create buffer in shared memory for workers on numa=%d, filename=%s, size=%ld", + socket_id, + filename.c_str(), + size); + return eResult::errorInitSharedMemory; + } +#else + key_shared_memory_segment++; + void* buffer = common::ipc::SharedMemory::CreateBufferKey(key_shared_memory_segment, size, use_huge_tlb, socket_id); + if (buffer == nullptr) + { + YANET_LOG_ERROR("Error create buffer in shared memory for workers on numa=%d, key=%d, size=%ld", + socket_id, + key_shared_memory_segment, + size); + return eResult::errorInitSharedMemory; + } +#endif + sockets_buffers[socket_id] = buffer; + } + + // Fill workers buffers + for (auto& worker_info : sdp_data.workers) + { + worker_info.second.buffer = (char*)sockets_buffers[worker_info.second.socket] + worker_info.second.shift_in_socket; + } + + // Fill workers_gc buffers + for (auto& worker_info : sdp_data.workers_gc) + { + worker_info.second.buffer = (char*)sockets_buffers[worker_info.second.socket] + worker_info.second.shift_in_socket; + } + + // Part 2 - prepare data dataplane + // Create buffer in shared memory for dataplane data + sdp_data.FillSizes(); +#ifdef YANET_USE_POSIX_SHARED_MEMORY + sdp_data.dataplane_data = common::ipc::SharedMemory::CreateBufferFile(YANET_SHARED_MEMORY_FILE_DATAPLANE, + sdp_data.size_dataplane_buffer, + use_huge_tlb, + std::nullopt); + if (sdp_data.dataplane_data == nullptr) + { + YANET_LOG_ERROR("Error create buffer in shared memory for dataplane data, filename=%s, size=%ld", + YANET_SHARED_MEMORY_FILE_DATAPLANE, + sdp_data.size_dataplane_buffer); + return eResult::errorInitSharedMemory; + } +#else + sdp_data.dataplane_data = common::ipc::SharedMemory::CreateBufferKey(YANET_SHARED_MEMORY_KEY_DATAPLANE, + sdp_data.size_dataplane_buffer, + use_huge_tlb, + std::nullopt); + if (sdp_data.dataplane_data == nullptr) + { + YANET_LOG_ERROR("Error create buffer in shared memory for dataplane data, key=%d, size=%ld", + key_shared_memory_segment, + sdp_data.size_dataplane_buffer); + return eResult::errorInitSharedMemory; + } +#endif + + WriteMainDataToBuffer(sdp_data); + + return eResult::success; + } + + static uint64_t GetStartData(uint64_t size, uint64_t& current_start) + { + static constexpr uint64_t cache_line_size = 64; + uint64_t result = current_start; + current_start += size; + current_start = cache_line_size * ((current_start + cache_line_size - 1) / cache_line_size); + return result; + } + +private: + static void WriteMainDataToBuffer(DataPlaneInSharedMemory& sdp_data) + { + // HEADER + uint64_t start_workers = DataPlaneInSharedMemory::size_header; + WriteValue(sdp_data, 0, start_workers); + WriteValue(sdp_data, 1, sdp_data.size_workers_section); + + uint64_t start_workers_metadata = start_workers + sdp_data.size_workers_section; + WriteValue(sdp_data, 2, start_workers_metadata); + WriteValue(sdp_data, 3, sdp_data.size_workers_metadata_section); + + sdp_data.start_bus_section = start_workers_metadata + sdp_data.size_workers_metadata_section; + WriteValue(sdp_data, 4, sdp_data.start_bus_section); + WriteValue(sdp_data, 5, sdp_data.size_bus_section); + + // WORKERS + { + uint64_t index = start_workers / sizeof(uint64_t); + WriteValue(sdp_data, index++, sdp_data.workers.size()); + WriteValue(sdp_data, index++, sdp_data.workers_gc.size()); + + for (const auto& [coreId, info] : sdp_data.workers) + { + WriteValue(sdp_data, index++, coreId); + WriteValue(sdp_data, index++, info.socket); + WriteValue(sdp_data, index++, info.shift_in_socket); + } + + for (const auto& [coreId, info] : sdp_data.workers_gc) + { + WriteValue(sdp_data, index++, coreId); + WriteValue(sdp_data, index++, info.socket); + WriteValue(sdp_data, index++, info.shift_in_socket); + } + } + + // WORKERS_METADATA + { + uint64_t index = start_workers_metadata / sizeof(uint64_t); + + // 0-5 - values from MetadataWorker + WriteValue(sdp_data, index, sdp_data.metadata_worker.start_counters); + WriteValue(sdp_data, index + 1, sdp_data.metadata_worker.start_acl_counters); + WriteValue(sdp_data, index + 2, sdp_data.metadata_worker.start_bursts); + WriteValue(sdp_data, index + 3, sdp_data.metadata_worker.start_stats); + WriteValue(sdp_data, index + 4, sdp_data.metadata_worker.start_stats_ports); + WriteValue(sdp_data, index + 5, sdp_data.metadata_worker.size); + // 6 - n1 = size MetadataWorker.counter_positions + WriteValue(sdp_data, index + 6, sdp_data.metadata_worker.counter_positions.size()); + // 7-9 - значения из MetadataWorker + WriteValue(sdp_data, index + 7, sdp_data.metadata_worker_gc.start_counters); + WriteValue(sdp_data, index + 8, sdp_data.metadata_worker_gc.start_stats); + WriteValue(sdp_data, index + 9, sdp_data.metadata_worker_gc.size); + // 10 - n2 = size MetadataWorker.counter_positions + WriteValue(sdp_data, index + 10, sdp_data.metadata_worker_gc.counter_positions.size()); + + WriteMap(sdp_data, start_workers_metadata + 128, sdp_data.metadata_worker.counter_positions); + WriteMap(sdp_data, start_workers_metadata + 128 * (1 + sdp_data.metadata_worker.counter_positions.size()), sdp_data.metadata_worker_gc.counter_positions); + } + } + + static void WriteMap(DataPlaneInSharedMemory& sdp_data, uint64_t index, const std::map& values) + { + for (const auto& [key, value] : values) + { + WriteValue(sdp_data, index / sizeof(uint64_t), value); + WriteString(sdp_data, index, key); + index += 128; + } + } + + static void WriteValue(DataPlaneInSharedMemory& sdp_data, uint64_t index, uint64_t value) + { + ((uint64_t*)sdp_data.dataplane_data)[index] = rte_cpu_to_be_64(value); + } + + static void WriteString(DataPlaneInSharedMemory& sdp_data, uint64_t index, const std::string& str) + { + snprintf(reinterpret_cast(sdp_data.dataplane_data) + index + 8, 120, "%s", str.c_str()); + } + + static int GetNumaNode(tCoreId core_id) + { + int socket_id = numa_node_of_cpu(core_id); + if (socket_id == -1) + { + YANET_LOG_ERROR("numa_node_of_cpu(%d) err: %s\n", core_id, strerror(errno)); + socket_id = 0; + } + return socket_id; + } +}; + +} // namespace common::sdp From c674a93db1b17a415c6ac52961d1546a6c8577d6 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 21:03:26 +0300 Subject: [PATCH 078/195] Unittests for the interface for working with counters in shared memory --- dataplane/unittest/meson.build | 3 +- dataplane/unittest/sdp.cpp | 368 +++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 dataplane/unittest/sdp.cpp diff --git a/dataplane/unittest/meson.build b/dataplane/unittest/meson.build index 71429fb4..18c19364 100644 --- a/dataplane/unittest/meson.build +++ b/dataplane/unittest/meson.build @@ -8,7 +8,8 @@ dependencies += dependency('gtest_main') sources = files('unittest.cpp', 'ip_address.cpp', - 'hashtable.cpp') + 'hashtable.cpp', + 'sdp.cpp') arch = 'corei7' cpp_args_append = ['-march=' + arch] diff --git a/dataplane/unittest/sdp.cpp b/dataplane/unittest/sdp.cpp new file mode 100644 index 00000000..312e024f --- /dev/null +++ b/dataplane/unittest/sdp.cpp @@ -0,0 +1,368 @@ +#include + +#include "../../common/idp.h" +#include "../../common/sdpclient.h" +#include "../sdpserver.h" + +class TestBus +{ +public: + static uint64_t GetSizeForCounters() + { + uint32_t count_errors = static_cast(common::idp::errorType::size); + uint32_t count_requests = static_cast(common::idp::requestType::size); + return (count_errors + 2 * count_requests) * sizeof(uint64_t); + } + + void SetBufferForCounters(const common::sdp::DataPlaneInSharedMemory& sdp_data) + { + auto [requests, errors, durations] = sdp_data.BuffersBus(); + stats.requests = requests; + stats.errors = errors; + stats.durations = durations; + } + + void SetTestValues() + { + for (uint32_t index = 0; index < static_cast(common::idp::requestType::size); index++) + { + if (index % 2 == 0) + { + stats.requests[index] = index * index; + stats.durations[index] = index * index * index; + } + } + + stats.errors[static_cast(common::idp::errorType::busRead)] = 19; + } + + void CompareWithClient(const common::sdp::DataPlaneInSharedMemory& sdp_data_client) + { + void* buffer = common::sdp::ShiftBuffer(sdp_data_client.dataplane_data, sdp_data_client.start_bus_section); + uint32_t count_errors = static_cast(common::idp::errorType::size); + uint32_t count_requests = static_cast(common::idp::requestType::size); + uint64_t* requests = common::sdp::ShiftBuffer(buffer, 0); + uint64_t* errors = common::sdp::ShiftBuffer(buffer, count_requests * sizeof(uint64_t)); + uint64_t* durations = common::sdp::ShiftBuffer(buffer, (count_requests + count_errors) * sizeof(uint64_t)); + + for (uint32_t index = 0; index < static_cast(common::idp::requestType::size); index++) + { + ASSERT_EQ(stats.requests[index], requests[index]); + ASSERT_EQ(stats.durations[index], durations[index]); + } + + for (uint32_t index = 0; index < static_cast(common::idp::requestType::size); index++) + { + ASSERT_EQ(stats.errors[index], errors[index]); + } + } + +protected: + struct sStats + { + uint64_t* requests; // common::idp::requestType::size + uint64_t* errors; // common::idp::errorType::size + uint64_t* durations; // common::idp::requestType::size + } stats; +}; + +class TestWorker +{ +public: + static void FillMetadataWorkerCounters(common::sdp::MetadataWorker& metadata) + { + metadata.size = 0; + metadata.start_counters = common::sdp::SdrSever::GetStartData(YANET_CONFIG_COUNTERS_SIZE * sizeof(uint64_t), metadata.size); + metadata.start_acl_counters = common::sdp::SdrSever::GetStartData(YANET_CONFIG_ACL_COUNTERS_SIZE * sizeof(uint64_t), metadata.size); + metadata.start_bursts = common::sdp::SdrSever::GetStartData((CONFIG_YADECAP_MBUFS_BURST_SIZE + 1) * sizeof(uint64_t), metadata.size); + metadata.start_stats = common::sdp::SdrSever::GetStartData(sizeof(common::worker::stats::common), metadata.size); + metadata.start_stats_ports = common::sdp::SdrSever::GetStartData(sizeof(common::worker::stats::port[CONFIG_YADECAP_PORTS_SIZE]), metadata.size); + + // stats + std::map counters_stats; + counters_stats["brokenPackets"] = offsetof(common::worker::stats::common, brokenPackets); + counters_stats["dropPackets"] = offsetof(common::worker::stats::common, dropPackets); + counters_stats["ring_highPriority_drops"] = offsetof(common::worker::stats::common, ring_highPriority_drops); + counters_stats["ring_normalPriority_drops"] = offsetof(common::worker::stats::common, ring_normalPriority_drops); + counters_stats["ring_lowPriority_drops"] = offsetof(common::worker::stats::common, ring_lowPriority_drops); + counters_stats["ring_highPriority_packets"] = offsetof(common::worker::stats::common, ring_highPriority_packets); + counters_stats["ring_normalPriority_packets"] = offsetof(common::worker::stats::common, ring_normalPriority_packets); + counters_stats["ring_lowPriority_packets"] = offsetof(common::worker::stats::common, ring_lowPriority_packets); + counters_stats["decap_packets"] = offsetof(common::worker::stats::common, decap_packets); + counters_stats["decap_fragments"] = offsetof(common::worker::stats::common, decap_fragments); + counters_stats["decap_unknownExtensions"] = offsetof(common::worker::stats::common, decap_unknownExtensions); + counters_stats["interface_lookupMisses"] = offsetof(common::worker::stats::common, interface_lookupMisses); + counters_stats["interface_hopLimits"] = offsetof(common::worker::stats::common, interface_hopLimits); + counters_stats["interface_neighbor_invalid"] = offsetof(common::worker::stats::common, interface_neighbor_invalid); + counters_stats["nat64stateless_ingressPackets"] = offsetof(common::worker::stats::common, nat64stateless_ingressPackets); + counters_stats["nat64stateless_ingressFragments"] = offsetof(common::worker::stats::common, nat64stateless_ingressFragments); + counters_stats["nat64stateless_ingressUnknownICMP"] = offsetof(common::worker::stats::common, nat64stateless_ingressUnknownICMP); + counters_stats["nat64stateless_egressPackets"] = offsetof(common::worker::stats::common, nat64stateless_egressPackets); + counters_stats["nat64stateless_egressFragments"] = offsetof(common::worker::stats::common, nat64stateless_egressFragments); + counters_stats["nat64stateless_egressUnknownICMP"] = offsetof(common::worker::stats::common, nat64stateless_egressUnknownICMP); + counters_stats["balancer_invalid_reals_count"] = offsetof(common::worker::stats::common, balancer_invalid_reals_count); + counters_stats["fwsync_multicast_egress_drops"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_drops); + counters_stats["fwsync_multicast_egress_packets"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_packets); + counters_stats["fwsync_multicast_egress_imm_packets"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_imm_packets); + counters_stats["fwsync_no_config_drops"] = offsetof(common::worker::stats::common, fwsync_no_config_drops); + counters_stats["fwsync_unicast_egress_drops"] = offsetof(common::worker::stats::common, fwsync_unicast_egress_drops); + counters_stats["fwsync_unicast_egress_packets"] = offsetof(common::worker::stats::common, fwsync_unicast_egress_packets); + counters_stats["acl_ingress_dropPackets"] = offsetof(common::worker::stats::common, acl_ingress_dropPackets); + counters_stats["acl_egress_dropPackets"] = offsetof(common::worker::stats::common, acl_egress_dropPackets); + counters_stats["repeat_ttl"] = offsetof(common::worker::stats::common, repeat_ttl); + counters_stats["leakedMbufs"] = offsetof(common::worker::stats::common, leakedMbufs); + counters_stats["logs_packets"] = offsetof(common::worker::stats::common, logs_packets); + counters_stats["logs_drops"] = offsetof(common::worker::stats::common, logs_drops); + for (const auto& iter : counters_stats) + { + metadata.counter_positions[iter.first] = (metadata.start_stats + iter.second) / sizeof(uint64_t); + } + + // counters + std::map counters_named; + counters_named["balancer_state_insert_failed"] = common::globalBase::static_counter_type::balancer_state_insert_failed; + counters_named["balancer_state_insert_done"] = common::globalBase::static_counter_type::balancer_state_insert_done; + counters_named["balancer_icmp_generated_echo_reply_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv4; + counters_named["balancer_icmp_generated_echo_reply_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv6; + counters_named["balancer_icmp_drop_icmpv4_payload_too_short_ip"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_ip; + counters_named["balancer_icmp_drop_icmpv4_payload_too_short_port"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_port; + counters_named["balancer_icmp_drop_icmpv6_payload_too_short_ip"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_ip; + counters_named["balancer_icmp_drop_icmpv6_payload_too_short_port"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_port; + counters_named["balancer_icmp_unmatching_src_from_original_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv4; + counters_named["balancer_icmp_unmatching_src_from_original_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv6; + counters_named["balancer_icmp_drop_real_disabled"] = common::globalBase::static_counter_type::balancer_icmp_drop_real_disabled; + counters_named["balancer_icmp_no_balancer_src_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv4; + counters_named["balancer_icmp_no_balancer_src_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv6; + counters_named["balancer_icmp_drop_already_cloned"] = common::globalBase::static_counter_type::balancer_icmp_drop_already_cloned; + counters_named["balancer_icmp_drop_no_unrdup_table_for_balancer_id"] = common::globalBase::static_counter_type::balancer_icmp_drop_no_unrdup_table_for_balancer_id; + counters_named["balancer_icmp_drop_unrdup_vip_not_found"] = common::globalBase::static_counter_type::balancer_icmp_drop_unrdup_vip_not_found; + counters_named["balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id"] = common::globalBase::static_counter_type::balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id; + counters_named["balancer_icmp_drop_unexpected_transport_protocol"] = common::globalBase::static_counter_type::balancer_icmp_drop_unexpected_transport_protocol; + counters_named["balancer_icmp_drop_unknown_service"] = common::globalBase::static_counter_type::balancer_icmp_drop_unknown_service; + counters_named["balancer_icmp_failed_to_clone"] = common::globalBase::static_counter_type::balancer_icmp_failed_to_clone; + counters_named["balancer_icmp_clone_forwarded"] = common::globalBase::static_counter_type::balancer_icmp_clone_forwarded; + counters_named["balancer_icmp_sent_to_real"] = common::globalBase::static_counter_type::balancer_icmp_sent_to_real; + counters_named["balancer_icmp_out_rate_limit_reached"] = common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached; + counters_named["slow_worker_normal_priority_rate_limit_exceeded"] = common::globalBase::static_counter_type::slow_worker_normal_priority_rate_limit_exceeded; + + counters_named["acl_ingress_v4_broken_packet"] = common::globalBase::static_counter_type::acl_ingress_v4_broken_packet; + counters_named["acl_ingress_v6_broken_packet"] = common::globalBase::static_counter_type::acl_ingress_v6_broken_packet; + counters_named["acl_egress_v4_broken_packet"] = common::globalBase::static_counter_type::acl_egress_v4_broken_packet; + counters_named["acl_egress_v6_broken_packet"] = common::globalBase::static_counter_type::acl_egress_v6_broken_packet; + counters_named["balancer_fragment_drops"] = common::globalBase::static_counter_type::balancer_fragment_drops; + + for (const auto& iter : counters_named) + { + metadata.counter_positions[iter.first] = metadata.start_counters / sizeof(uint64_t) + static_cast(iter.second); + } + } + + void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorker& metadata) + { + counters = common::sdp::ShiftBuffer(buffer, metadata.start_counters); + aclCounters = common::sdp::ShiftBuffer(buffer, metadata.start_acl_counters); + bursts = common::sdp::ShiftBuffer(buffer, metadata.start_bursts); + stats = common::sdp::ShiftBuffer(buffer, metadata.start_stats); + statsPorts = common::sdp::ShiftBuffer(buffer, metadata.start_stats_ports); + } + + void SetTestValues(tCoreId coreId) + { + // stats + stats->dropPackets = (coreId + 1) * (coreId + 1); + + // statsPorts + for (uint32_t index = 0; index < CONFIG_YADECAP_PORTS_SIZE + 1; index++) + { + statsPorts[index].controlPlane_drops = 3 * (index + coreId); + statsPorts[index].physicalPort_egress_drops = 4 * (index + coreId); + } + + // bursts + for (uint32_t index = 0; index < CONFIG_YADECAP_MBUFS_BURST_SIZE + 1; index++) + { + bursts[index] = 5 * (index + coreId); + } + + // counters + for (uint32_t index = YANET_CONFIG_COUNTER_FALLBACK_SIZE; index < YANET_CONFIG_COUNTERS_SIZE; index++) + { + counters[index] = (index + coreId) * (index + coreId); + } + + // aclCounters + for (uint32_t index = 0; index < YANET_CONFIG_ACL_COUNTERS_SIZE; index++) + { + aclCounters[index] = index + coreId; + } + } + + void CompareWithClient(tCoreId coreId, const common::sdp::DataPlaneInSharedMemory& sdp_data_client) + { + auto iter = sdp_data_client.workers.find(coreId); + ASSERT_TRUE(iter != sdp_data_client.workers.end()); + void* buffer = iter->second.buffer; + + // stats + ASSERT_EQ(common::sdp::SdpClient::GetCounterByName(sdp_data_client, "dropPackets", coreId)[coreId], stats->dropPackets); + + // statsPorts + common::worker::stats::port* bufStatsPorts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_stats_ports); + for (uint32_t index = 0; index < CONFIG_YADECAP_PORTS_SIZE + 1; index++) + { + ASSERT_EQ(statsPorts[index].controlPlane_drops, bufStatsPorts[index].controlPlane_drops); + ASSERT_EQ(statsPorts[index].physicalPort_egress_drops, bufStatsPorts[index].physicalPort_egress_drops); + } + + // bursts + uint64_t* bufBursts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_bursts); + for (uint32_t index = 0; index < CONFIG_YADECAP_MBUFS_BURST_SIZE + 1; index++) + { + ASSERT_EQ(bursts[index], bufBursts[index]); + } + + // counters + uint64_t* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_counters); + for (uint32_t index = 0; index < YANET_CONFIG_COUNTERS_SIZE; index++) + { + ASSERT_EQ(counters[index], bufCounters[index]); + } + + // aclCounters + uint64_t* bufAclCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_acl_counters); + for (uint32_t index = 0; index < YANET_CONFIG_ACL_COUNTERS_SIZE; index++) + { + ASSERT_EQ(aclCounters[index], bufAclCounters[index]); + } + } + +protected: + common::worker::stats::common* stats; + common::worker::stats::port* statsPorts; // CONFIG_YADECAP_PORTS_SIZE + uint64_t* bursts; // CONFIG_YADECAP_MBUFS_BURST_SIZE + 1 + uint64_t* counters; // YANET_CONFIG_COUNTERS_SIZE + uint64_t* aclCounters; // YANET_CONFIG_ACL_COUNTERS_SIZE +}; + +class TestWorkerGc +{ +public: + static void FillMetadataWorkerCounters(common::sdp::MetadataWorkerGc& metadata) + { + metadata.size = 0; + metadata.start_counters = common::sdp::SdrSever::GetStartData(YANET_CONFIG_COUNTERS_SIZE * sizeof(uint64_t), metadata.size); + metadata.start_stats = common::sdp::SdrSever::GetStartData(sizeof(common::worker_gc::stats_t), metadata.size); + + // stats + static_assert(std::is_trivially_destructible::value, "invalid struct destructible"); + std::map counters_stats; + counters_stats["broken_packets"] = offsetof(common::worker_gc::stats_t, broken_packets); + counters_stats["drop_packets"] = offsetof(common::worker_gc::stats_t, drop_packets); + counters_stats["ring_to_slowworker_packets"] = offsetof(common::worker_gc::stats_t, ring_to_slowworker_packets); + counters_stats["ring_to_slowworker_drops"] = offsetof(common::worker_gc::stats_t, ring_to_slowworker_drops); + counters_stats["fwsync_multicast_egress_packets"] = offsetof(common::worker_gc::stats_t, fwsync_multicast_egress_packets); + counters_stats["fwsync_multicast_egress_drops"] = offsetof(common::worker_gc::stats_t, fwsync_multicast_egress_drops); + counters_stats["fwsync_unicast_egress_packets"] = offsetof(common::worker_gc::stats_t, fwsync_unicast_egress_packets); + counters_stats["fwsync_unicast_egress_drops"] = offsetof(common::worker_gc::stats_t, fwsync_unicast_egress_drops); + counters_stats["drop_samples"] = offsetof(common::worker_gc::stats_t, drop_samples); + counters_stats["balancer_state_insert_failed"] = offsetof(common::worker_gc::stats_t, balancer_state_insert_failed); + counters_stats["balancer_state_insert_done"] = offsetof(common::worker_gc::stats_t, balancer_state_insert_done); + + for (const auto& iter : counters_stats) + { + metadata.counter_positions[iter.first] = (metadata.start_stats + iter.second) / sizeof(uint64_t); + } + } + + void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorkerGc& metadata) + { + counters = common::sdp::ShiftBuffer(buffer, metadata.start_counters); + stats = common::sdp::ShiftBuffer(buffer, metadata.start_stats); + } + + void SetTestValues(tCoreId coreId) + { + // stats + stats->drop_samples = 7 * (coreId + 1) * (coreId + 1); + + // counters + for (uint32_t index = YANET_CONFIG_COUNTER_FALLBACK_SIZE; index < YANET_CONFIG_COUNTERS_SIZE; index++) + { + counters[index] = 11 * (index + coreId) * (index + coreId); + } + } + + void CompareWithClient(tCoreId coreId, const common::sdp::DataPlaneInSharedMemory& sdp_data_client) + { + auto iter = sdp_data_client.workers_gc.find(coreId); + ASSERT_TRUE(iter != sdp_data_client.workers_gc.end()); + void* buffer = iter->second.buffer; + + // stats + ASSERT_EQ(common::sdp::SdpClient::GetCounterByName(sdp_data_client, "drop_samples", coreId)[coreId], stats->drop_samples); + + // counters + uint64_t* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker_gc.start_counters); + for (uint32_t index = 0; index < YANET_CONFIG_COUNTERS_SIZE; index++) + { + ASSERT_EQ(counters[index], bufCounters[index]); + } + } + +protected: + uint64_t* counters; // YANET_CONFIG_COUNTERS_SIZE + common::worker_gc::stats_t* stats; +}; + +TEST(SDP, FullTests) +{ + bool useHugeMem = false; + std::vector workers_id = {1, 2, 5}; + std::vector workers_gc_id = {0, 3}; + + // Initialize server + common::sdp::DataPlaneInSharedMemory sdp_data_server; + TestWorker::FillMetadataWorkerCounters(sdp_data_server.metadata_worker); + TestWorkerGc::FillMetadataWorkerCounters(sdp_data_server.metadata_worker_gc); + sdp_data_server.size_bus_section = TestBus::GetSizeForCounters(); + ASSERT_EQ(common::sdp::SdrSever::PrepareSharedMemoryData(sdp_data_server, workers_id, workers_gc_id, useHugeMem), eResult::success); + + // Initialize client + common::sdp::DataPlaneInSharedMemory sdp_data_client; + ASSERT_EQ(common::sdp::SdpClient::ReadSharedMemoryData(sdp_data_client, true), eResult::success); + + // Check, that server structure = client structure + ASSERT_EQ(sdp_data_server, sdp_data_client); + + // Test work bus + TestBus bus; + bus.SetBufferForCounters(sdp_data_server); + bus.SetTestValues(); + bus.CompareWithClient(sdp_data_client); + + // Test workers + std::map> workers; + for (tCoreId coreId : workers_id) + { + workers[coreId] = std::make_shared(); + workers[coreId]->SetBufferForCounters(sdp_data_server.workers[coreId].buffer, sdp_data_server.metadata_worker); + workers[coreId]->SetTestValues(coreId); + } + for (tCoreId coreId : workers_id) + { + workers[coreId]->CompareWithClient(coreId, sdp_data_client); + } + + // Test workers_gc + std::map> workers_gc; + for (tCoreId coreId : workers_gc_id) + { + workers_gc[coreId] = std::make_shared(); + workers_gc[coreId]->SetBufferForCounters(sdp_data_server.workers_gc[coreId].buffer, sdp_data_server.metadata_worker_gc); + workers_gc[coreId]->SetTestValues(coreId); + } + for (tCoreId coreId : workers_id) + { + workers[coreId]->CompareWithClient(coreId, sdp_data_client); + } +} From 668fc7c7fefa9e5585fb8eccd1d5fcf50bece2b6 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 21:36:57 +0300 Subject: [PATCH 079/195] Counters from Worker, Workers and Bus has been transferred to shared memory --- dataplane/bus.cpp | 15 +++ dataplane/bus.h | 14 +- dataplane/controlplane.cpp | 6 +- dataplane/dataplane.cpp | 38 ++++++ dataplane/dataplane.h | 4 + dataplane/report.cpp | 78 +++++------ dataplane/worker.cpp | 259 +++++++++++++++++++++++++------------ dataplane/worker.h | 15 ++- dataplane/worker_gc.cpp | 78 +++++++---- dataplane/worker_gc.h | 7 +- 10 files changed, 352 insertions(+), 162 deletions(-) diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 4b880b77..ac58a5ac 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -55,6 +55,21 @@ void cBus::join() } } +uint64_t cBus::GetSizeForCounters() +{ + uint32_t count_errors = static_cast(common::idp::errorType::size); + uint32_t count_requests = static_cast(common::idp::requestType::size); + return (count_errors + 2 * count_requests) * sizeof(uint64_t); +} + +void cBus::SetBufferForCounters(const common::sdp::DataPlaneInSharedMemory& sdp_data) +{ + auto [requests, errors, durations] = sdp_data.BuffersBus(); + stats.requests = requests; + stats.errors = errors; + stats.durations = durations; +} + static bool recvAll(int clientSocket, char* buffer, uint64_t size) diff --git a/dataplane/bus.h b/dataplane/bus.h index c52607e3..1a43f223 100644 --- a/dataplane/bus.h +++ b/dataplane/bus.h @@ -12,6 +12,7 @@ #include "common/idp.h" #include "common/result.h" +#include "sdpserver.h" #include "type.h" class cBus @@ -24,6 +25,9 @@ class cBus void stop(); void join(); + static uint64_t GetSizeForCounters(); + void SetBufferForCounters(const common::sdp::DataPlaneInSharedMemory& sdp_data); + protected: void mainLoop(); void clientThread(int clientSocket); @@ -67,13 +71,9 @@ class cBus struct sStats { - sStats() - { - memset(this, 0, sizeof(*this)); - } - - uint64_t requests[(uint32_t)common::idp::requestType::size]; - uint64_t errors[(uint32_t)common::idp::errorType::size]; + uint64_t* requests; // common::idp::requestType::size + uint64_t* errors; // common::idp::errorType::size + uint64_t* durations; // common::idp::requestType::size } stats; cDataPlane* dataPlane; diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 72171e78..894d0a6b 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -186,7 +186,7 @@ common::idp::getOtherStats::response cControlPlane::getOtherStats() for (const cWorker* worker : dataPlane->workers_vector) { std::array bursts; - memcpy(&bursts[0], worker->bursts, sizeof(worker->bursts)); + memcpy(&bursts[0], worker->bursts, (CONFIG_YADECAP_MBUFS_BURST_SIZE + 1) * sizeof(uint64_t)); response_workers[worker->coreId] = {bursts}; } @@ -209,7 +209,7 @@ common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common } response[coreId] = {worker->iteration, - worker->stats, + *worker->stats, portsStats}; }; @@ -325,7 +325,7 @@ common::idp::get_worker_gc_stats::response cControlPlane::get_worker_gc_stats() for (const auto& [core_id, worker] : dataPlane->worker_gcs) { response[core_id] = {worker->iteration, - worker->stats}; + *worker->stats}; } return response; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 037aa28a..f1487649 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -164,6 +164,12 @@ eResult cDataPlane::init(const std::string& binaryPath, socket_cplane_mempools.emplace(socket, pool); } + result = initSharedMemory(); + if (result != eResult::success) + { + return result; + } + result = initWorkers(); if (result != eResult::success) { @@ -246,6 +252,7 @@ eResult cDataPlane::init(const std::string& binaryPath, { return result; } + bus.SetBufferForCounters(sdp_data); result = neighbor.init(this); if (result != eResult::success) @@ -853,6 +860,8 @@ eResult cDataPlane::initWorkers() return eResult::errorAllocatingMemory; } + worker->SetBufferForCounters(sdp_data.workers[coreId].buffer, sdp_data.metadata_worker); + dataplane::base::permanently basePermanently; { auto iter = globalBaseAtomics.find(socket_id); @@ -1025,6 +1034,8 @@ eResult cDataPlane::initWorkers() return eResult::errorAllocatingMemory; } + worker->SetBufferForCounters(sdp_data.workers_gc[core_id].buffer, sdp_data.metadata_worker_gc); + dataplane::base::permanently basePermanently; { auto iter = globalBaseAtomics.find(socket_id); @@ -1106,6 +1117,8 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& return eResult::errorAllocatingMemory; } + worker->SetBufferForCounters(sdp_data.workers[core].buffer, sdp_data.metadata_worker); + dataplane::base::permanently basePermanently; basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; basePermanently.outQueueId = tx_queues_; @@ -1494,6 +1507,31 @@ void cDataPlane::run_on_worker_gc(const tSocketId socket_id, socket_worker_gcs.find(socket_id)->second->run_on_this_thread(callback); } +eResult cDataPlane::initSharedMemory() +{ + std::vector workers_id; + std::vector workers_gc_id; + + // workers + for (const auto& worker : config.workers) + { + workers_id.push_back(worker.first); + } + // slow worker + workers_id.push_back(config.controlPlaneCoreId); + // workers gc + for (const auto& coreId : config.workerGCs) + { + workers_gc_id.push_back(coreId); + } + + cWorker::FillMetadataWorkerCounters(sdp_data.metadata_worker); + worker_gc_t::FillMetadataWorkerCounters(sdp_data.metadata_worker_gc); + sdp_data.size_bus_section = cBus::GetSizeForCounters(); + + return common::sdp::SdrSever::PrepareSharedMemoryData(sdp_data, workers_id, workers_gc_id, config.useHugeMem); +} + eResult cDataPlane::allocateSharedMemory() { /// precalculation of shared memory size for each numa diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 31491954..e72d3af4 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -26,6 +26,7 @@ #include "memory_manager.h" #include "neighbor.h" #include "report.h" +#include "sdpserver.h" #include "slow_worker.h" #include "type.h" @@ -152,6 +153,7 @@ class cDataPlane eResult initKniQueues(); eResult InitTxQueues(); eResult InitRxQueues(); + eResult initSharedMemory(); void init_worker_base(); eResult allocateSharedMemory(); @@ -242,6 +244,8 @@ class cDataPlane mutable std::mutex dpdk_mutex; + common::sdp::DataPlaneInSharedMemory sdp_data; + public: ///< modules cReport report; std::unique_ptr controlPlane; diff --git a/dataplane/report.cpp b/dataplane/report.cpp index ca037fb8..19ebf3e5 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -139,37 +139,37 @@ nlohmann::json cReport::convertWorker(const cWorker* worker) json["mempool"] = convertMempool(worker->mempool); json["iteration"] = worker->iteration; - json["stats"]["brokenPackets"] = worker->stats.brokenPackets; - json["stats"]["dropPackets"] = worker->stats.dropPackets; - json["stats"]["ring_highPriority_drops"] = worker->stats.ring_highPriority_drops; - json["stats"]["ring_normalPriority_drops"] = worker->stats.ring_normalPriority_drops; - json["stats"]["ring_lowPriority_drops"] = worker->stats.ring_lowPriority_drops; - json["stats"]["decap_packets"] = worker->stats.decap_packets; - json["stats"]["decap_fragments"] = worker->stats.decap_fragments; - json["stats"]["decap_unknownExtensions"] = worker->stats.decap_unknownExtensions; - json["stats"]["interface_lookupMisses"] = worker->stats.interface_lookupMisses; - json["stats"]["interface_hopLimits"] = worker->stats.interface_hopLimits; - json["stats"]["interface_neighbor_invalid"] = worker->stats.interface_neighbor_invalid; - json["stats"]["nat64stateless_ingressPackets"] = worker->stats.nat64stateless_ingressPackets; - json["stats"]["nat64stateless_ingressFragments"] = worker->stats.nat64stateless_ingressFragments; - json["stats"]["nat64stateless_ingressUnknownICMP"] = worker->stats.nat64stateless_ingressUnknownICMP; - json["stats"]["nat64stateless_egressPackets"] = worker->stats.nat64stateless_egressPackets; - json["stats"]["nat64stateless_egressFragments"] = worker->stats.nat64stateless_egressFragments; - json["stats"]["nat64stateless_egressUnknownICMP"] = worker->stats.nat64stateless_egressUnknownICMP; - json["stats"]["balancer_invalid_reals_count"] = worker->stats.balancer_invalid_reals_count; - json["stats"]["fwsync_multicast_egress_drops"] = worker->stats.fwsync_multicast_egress_drops; - json["stats"]["fwsync_multicast_egress_packets"] = worker->stats.fwsync_multicast_egress_packets; - json["stats"]["fwsync_unicast_egress_drops"] = worker->stats.fwsync_unicast_egress_drops; - json["stats"]["fwsync_unicast_egress_packets"] = worker->stats.fwsync_unicast_egress_packets; - json["stats"]["fwsync_multicast_egress_imm_packets"] = worker->stats.fwsync_multicast_egress_imm_packets; - json["stats"]["fwsync_no_config_drops"] = worker->stats.fwsync_no_config_drops; - json["stats"]["acl_ingress_dropPackets"] = worker->stats.acl_ingress_dropPackets; - json["stats"]["acl_egress_dropPackets"] = worker->stats.acl_egress_dropPackets; - json["stats"]["repeat_ttl"] = worker->stats.repeat_ttl; - json["stats"]["leakedMbufs"] = worker->stats.leakedMbufs; + json["stats"]["brokenPackets"] = worker->stats->brokenPackets; + json["stats"]["dropPackets"] = worker->stats->dropPackets; + json["stats"]["ring_highPriority_drops"] = worker->stats->ring_highPriority_drops; + json["stats"]["ring_normalPriority_drops"] = worker->stats->ring_normalPriority_drops; + json["stats"]["ring_lowPriority_drops"] = worker->stats->ring_lowPriority_drops; + json["stats"]["decap_packets"] = worker->stats->decap_packets; + json["stats"]["decap_fragments"] = worker->stats->decap_fragments; + json["stats"]["decap_unknownExtensions"] = worker->stats->decap_unknownExtensions; + json["stats"]["interface_lookupMisses"] = worker->stats->interface_lookupMisses; + json["stats"]["interface_hopLimits"] = worker->stats->interface_hopLimits; + json["stats"]["interface_neighbor_invalid"] = worker->stats->interface_neighbor_invalid; + json["stats"]["nat64stateless_ingressPackets"] = worker->stats->nat64stateless_ingressPackets; + json["stats"]["nat64stateless_ingressFragments"] = worker->stats->nat64stateless_ingressFragments; + json["stats"]["nat64stateless_ingressUnknownICMP"] = worker->stats->nat64stateless_ingressUnknownICMP; + json["stats"]["nat64stateless_egressPackets"] = worker->stats->nat64stateless_egressPackets; + json["stats"]["nat64stateless_egressFragments"] = worker->stats->nat64stateless_egressFragments; + json["stats"]["nat64stateless_egressUnknownICMP"] = worker->stats->nat64stateless_egressUnknownICMP; + json["stats"]["balancer_invalid_reals_count"] = worker->stats->balancer_invalid_reals_count; + json["stats"]["fwsync_multicast_egress_drops"] = worker->stats->fwsync_multicast_egress_drops; + json["stats"]["fwsync_multicast_egress_packets"] = worker->stats->fwsync_multicast_egress_packets; + json["stats"]["fwsync_unicast_egress_drops"] = worker->stats->fwsync_unicast_egress_drops; + json["stats"]["fwsync_unicast_egress_packets"] = worker->stats->fwsync_unicast_egress_packets; + json["stats"]["fwsync_multicast_egress_imm_packets"] = worker->stats->fwsync_multicast_egress_imm_packets; + json["stats"]["fwsync_no_config_drops"] = worker->stats->fwsync_no_config_drops; + json["stats"]["acl_ingress_dropPackets"] = worker->stats->acl_ingress_dropPackets; + json["stats"]["acl_egress_dropPackets"] = worker->stats->acl_egress_dropPackets; + json["stats"]["repeat_ttl"] = worker->stats->repeat_ttl; + json["stats"]["leakedMbufs"] = worker->stats->leakedMbufs; json["stats"]["samples_drops"] = worker->sampler.get_drops(); - json["stats"]["logs_packets"] = worker->stats.logs_packets; - json["stats"]["logs_drops"] = worker->stats.logs_drops; + json["stats"]["logs_packets"] = worker->stats->logs_packets; + json["stats"]["logs_drops"] = worker->stats->logs_drops; for (tPortId portId = 0; portId < dataPlane->ports.size(); @@ -267,15 +267,15 @@ nlohmann::json cReport::convertWorkerGC(const worker_gc_t* worker) json["iteration"] = worker->iteration; json["samples"] = worker->samples.size(); - json["stats"]["broken_packets"] = worker->stats.broken_packets; - json["stats"]["drop_packets"] = worker->stats.drop_packets; - json["stats"]["drop_samples"] = worker->stats.drop_samples; - json["stats"]["fwsync_multicast_egress_packets"] = worker->stats.fwsync_multicast_egress_packets; - json["stats"]["fwsync_multicast_egress_drops"] = worker->stats.fwsync_multicast_egress_drops; - json["stats"]["fwsync_unicast_egress_packets"] = worker->stats.fwsync_unicast_egress_packets; - json["stats"]["fwsync_unicast_egress_drops"] = worker->stats.fwsync_unicast_egress_drops; - json["stats"]["balancer_state_insert_failed"] = worker->stats.balancer_state_insert_failed; - json["stats"]["balancer_state_insert_done"] = worker->stats.balancer_state_insert_done; + json["stats"]["broken_packets"] = worker->stats->broken_packets; + json["stats"]["drop_packets"] = worker->stats->drop_packets; + json["stats"]["drop_samples"] = worker->stats->drop_samples; + json["stats"]["fwsync_multicast_egress_packets"] = worker->stats->fwsync_multicast_egress_packets; + json["stats"]["fwsync_multicast_egress_drops"] = worker->stats->fwsync_multicast_egress_drops; + json["stats"]["fwsync_unicast_egress_packets"] = worker->stats->fwsync_unicast_egress_packets; + json["stats"]["fwsync_unicast_egress_drops"] = worker->stats->fwsync_unicast_egress_drops; + json["stats"]["balancer_state_insert_failed"] = worker->stats->balancer_state_insert_failed; + json["stats"]["balancer_state_insert_done"] = worker->stats->balancer_state_insert_done; /// permanently base json["permanentlyBase"]["globalBaseAtomic"]["pointer"] = pointerToHex(worker->base_permanently.globalBaseAtomic); diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 06db1d24..98fe32b2 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -47,8 +47,6 @@ cWorker::cWorker(cDataPlane* dataPlane) : ring_log(nullptr), packetsToSWNPRemainder(dataPlane->config.SWNormalPriorityRateLimitPerWorker) { - memset(bursts, 0, sizeof(bursts)); - memset(counters, 0, sizeof(counters)); } cWorker::~cWorker() @@ -262,39 +260,39 @@ void cWorker::start() void cWorker::fillStatsNamesToAddrsTable(std::unordered_map& table) { - table["brokenPackets"] = &stats.brokenPackets; - table["dropPackets"] = &stats.dropPackets; - table["ring_highPriority_drops"] = &stats.ring_highPriority_drops; - table["ring_normalPriority_drops"] = &stats.ring_normalPriority_drops; - table["ring_lowPriority_drops"] = &stats.ring_lowPriority_drops; - table["ring_highPriority_packets"] = &stats.ring_highPriority_packets; - table["ring_normalPriority_packets"] = &stats.ring_normalPriority_packets; - table["ring_lowPriority_packets"] = &stats.ring_lowPriority_packets; - table["decap_packets"] = &stats.decap_packets; - table["decap_fragments"] = &stats.decap_fragments; - table["decap_unknownExtensions"] = &stats.decap_unknownExtensions; - table["interface_lookupMisses"] = &stats.interface_lookupMisses; - table["interface_hopLimits"] = &stats.interface_hopLimits; - table["interface_neighbor_invalid"] = &stats.interface_neighbor_invalid; - table["nat64stateless_ingressPackets"] = &stats.nat64stateless_ingressPackets; - table["nat64stateless_ingressFragments"] = &stats.nat64stateless_ingressFragments; - table["nat64stateless_ingressUnknownICMP"] = &stats.nat64stateless_ingressUnknownICMP; - table["nat64stateless_egressPackets"] = &stats.nat64stateless_egressPackets; - table["nat64stateless_egressFragments"] = &stats.nat64stateless_egressFragments; - table["nat64stateless_egressUnknownICMP"] = &stats.nat64stateless_egressUnknownICMP; - table["balancer_invalid_reals_count"] = &stats.balancer_invalid_reals_count; - table["fwsync_multicast_egress_drops"] = &stats.fwsync_multicast_egress_drops; - table["fwsync_multicast_egress_packets"] = &stats.fwsync_multicast_egress_packets; - table["fwsync_multicast_egress_imm_packets"] = &stats.fwsync_multicast_egress_imm_packets; - table["fwsync_no_config_drops"] = &stats.fwsync_no_config_drops; - table["fwsync_unicast_egress_drops"] = &stats.fwsync_unicast_egress_drops; - table["fwsync_unicast_egress_packets"] = &stats.fwsync_unicast_egress_packets; - table["acl_ingress_dropPackets"] = &stats.acl_ingress_dropPackets; - table["acl_egress_dropPackets"] = &stats.acl_egress_dropPackets; - table["repeat_ttl"] = &stats.repeat_ttl; - table["leakedMbufs"] = &stats.leakedMbufs; - table["logs_packets"] = &stats.logs_packets; - table["logs_drops"] = &stats.logs_drops; + table["brokenPackets"] = &stats->brokenPackets; + table["dropPackets"] = &stats->dropPackets; + table["ring_highPriority_drops"] = &stats->ring_highPriority_drops; + table["ring_normalPriority_drops"] = &stats->ring_normalPriority_drops; + table["ring_lowPriority_drops"] = &stats->ring_lowPriority_drops; + table["ring_highPriority_packets"] = &stats->ring_highPriority_packets; + table["ring_normalPriority_packets"] = &stats->ring_normalPriority_packets; + table["ring_lowPriority_packets"] = &stats->ring_lowPriority_packets; + table["decap_packets"] = &stats->decap_packets; + table["decap_fragments"] = &stats->decap_fragments; + table["decap_unknownExtensions"] = &stats->decap_unknownExtensions; + table["interface_lookupMisses"] = &stats->interface_lookupMisses; + table["interface_hopLimits"] = &stats->interface_hopLimits; + table["interface_neighbor_invalid"] = &stats->interface_neighbor_invalid; + table["nat64stateless_ingressPackets"] = &stats->nat64stateless_ingressPackets; + table["nat64stateless_ingressFragments"] = &stats->nat64stateless_ingressFragments; + table["nat64stateless_ingressUnknownICMP"] = &stats->nat64stateless_ingressUnknownICMP; + table["nat64stateless_egressPackets"] = &stats->nat64stateless_egressPackets; + table["nat64stateless_egressFragments"] = &stats->nat64stateless_egressFragments; + table["nat64stateless_egressUnknownICMP"] = &stats->nat64stateless_egressUnknownICMP; + table["balancer_invalid_reals_count"] = &stats->balancer_invalid_reals_count; + table["fwsync_multicast_egress_drops"] = &stats->fwsync_multicast_egress_drops; + table["fwsync_multicast_egress_packets"] = &stats->fwsync_multicast_egress_packets; + table["fwsync_multicast_egress_imm_packets"] = &stats->fwsync_multicast_egress_imm_packets; + table["fwsync_no_config_drops"] = &stats->fwsync_no_config_drops; + table["fwsync_unicast_egress_drops"] = &stats->fwsync_unicast_egress_drops; + table["fwsync_unicast_egress_packets"] = &stats->fwsync_unicast_egress_packets; + table["acl_ingress_dropPackets"] = &stats->acl_ingress_dropPackets; + table["acl_egress_dropPackets"] = &stats->acl_egress_dropPackets; + table["repeat_ttl"] = &stats->repeat_ttl; + table["leakedMbufs"] = &stats->leakedMbufs; + table["logs_packets"] = &stats->logs_packets; + table["logs_drops"] = &stats->logs_drops; table["balancer_state_insert_failed"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_state_insert_failed]; table["balancer_state_insert_done"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_state_insert_done]; @@ -327,6 +325,103 @@ void cWorker::fillStatsNamesToAddrsTable(std::unordered_map counters_stats; + counters_stats["brokenPackets"] = offsetof(common::worker::stats::common, brokenPackets); + counters_stats["dropPackets"] = offsetof(common::worker::stats::common, dropPackets); + counters_stats["ring_highPriority_drops"] = offsetof(common::worker::stats::common, ring_highPriority_drops); + counters_stats["ring_normalPriority_drops"] = offsetof(common::worker::stats::common, ring_normalPriority_drops); + counters_stats["ring_lowPriority_drops"] = offsetof(common::worker::stats::common, ring_lowPriority_drops); + counters_stats["ring_highPriority_packets"] = offsetof(common::worker::stats::common, ring_highPriority_packets); + counters_stats["ring_normalPriority_packets"] = offsetof(common::worker::stats::common, ring_normalPriority_packets); + counters_stats["ring_lowPriority_packets"] = offsetof(common::worker::stats::common, ring_lowPriority_packets); + counters_stats["decap_packets"] = offsetof(common::worker::stats::common, decap_packets); + counters_stats["decap_fragments"] = offsetof(common::worker::stats::common, decap_fragments); + counters_stats["decap_unknownExtensions"] = offsetof(common::worker::stats::common, decap_unknownExtensions); + counters_stats["interface_lookupMisses"] = offsetof(common::worker::stats::common, interface_lookupMisses); + counters_stats["interface_hopLimits"] = offsetof(common::worker::stats::common, interface_hopLimits); + counters_stats["interface_neighbor_invalid"] = offsetof(common::worker::stats::common, interface_neighbor_invalid); + counters_stats["nat64stateless_ingressPackets"] = offsetof(common::worker::stats::common, nat64stateless_ingressPackets); + counters_stats["nat64stateless_ingressFragments"] = offsetof(common::worker::stats::common, nat64stateless_ingressFragments); + counters_stats["nat64stateless_ingressUnknownICMP"] = offsetof(common::worker::stats::common, nat64stateless_ingressUnknownICMP); + counters_stats["nat64stateless_egressPackets"] = offsetof(common::worker::stats::common, nat64stateless_egressPackets); + counters_stats["nat64stateless_egressFragments"] = offsetof(common::worker::stats::common, nat64stateless_egressFragments); + counters_stats["nat64stateless_egressUnknownICMP"] = offsetof(common::worker::stats::common, nat64stateless_egressUnknownICMP); + counters_stats["balancer_invalid_reals_count"] = offsetof(common::worker::stats::common, balancer_invalid_reals_count); + counters_stats["fwsync_multicast_egress_drops"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_drops); + counters_stats["fwsync_multicast_egress_packets"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_packets); + counters_stats["fwsync_multicast_egress_imm_packets"] = offsetof(common::worker::stats::common, fwsync_multicast_egress_imm_packets); + counters_stats["fwsync_no_config_drops"] = offsetof(common::worker::stats::common, fwsync_no_config_drops); + counters_stats["fwsync_unicast_egress_drops"] = offsetof(common::worker::stats::common, fwsync_unicast_egress_drops); + counters_stats["fwsync_unicast_egress_packets"] = offsetof(common::worker::stats::common, fwsync_unicast_egress_packets); + counters_stats["acl_ingress_dropPackets"] = offsetof(common::worker::stats::common, acl_ingress_dropPackets); + counters_stats["acl_egress_dropPackets"] = offsetof(common::worker::stats::common, acl_egress_dropPackets); + counters_stats["repeat_ttl"] = offsetof(common::worker::stats::common, repeat_ttl); + counters_stats["leakedMbufs"] = offsetof(common::worker::stats::common, leakedMbufs); + counters_stats["logs_packets"] = offsetof(common::worker::stats::common, logs_packets); + counters_stats["logs_drops"] = offsetof(common::worker::stats::common, logs_drops); + for (const auto& iter : counters_stats) + { + metadata.counter_positions[iter.first] = (metadata.start_stats + iter.second) / sizeof(uint64_t); + } + + // counters + std::map counters_named; + counters_named["balancer_state_insert_failed"] = common::globalBase::static_counter_type::balancer_state_insert_failed; + counters_named["balancer_state_insert_done"] = common::globalBase::static_counter_type::balancer_state_insert_done; + counters_named["balancer_icmp_generated_echo_reply_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv4; + counters_named["balancer_icmp_generated_echo_reply_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv6; + counters_named["balancer_icmp_drop_icmpv4_payload_too_short_ip"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_ip; + counters_named["balancer_icmp_drop_icmpv4_payload_too_short_port"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_port; + counters_named["balancer_icmp_drop_icmpv6_payload_too_short_ip"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_ip; + counters_named["balancer_icmp_drop_icmpv6_payload_too_short_port"] = common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_port; + counters_named["balancer_icmp_unmatching_src_from_original_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv4; + counters_named["balancer_icmp_unmatching_src_from_original_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv6; + counters_named["balancer_icmp_drop_real_disabled"] = common::globalBase::static_counter_type::balancer_icmp_drop_real_disabled; + counters_named["balancer_icmp_no_balancer_src_ipv4"] = common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv4; + counters_named["balancer_icmp_no_balancer_src_ipv6"] = common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv6; + counters_named["balancer_icmp_drop_already_cloned"] = common::globalBase::static_counter_type::balancer_icmp_drop_already_cloned; + counters_named["balancer_icmp_drop_no_unrdup_table_for_balancer_id"] = common::globalBase::static_counter_type::balancer_icmp_drop_no_unrdup_table_for_balancer_id; + counters_named["balancer_icmp_drop_unrdup_vip_not_found"] = common::globalBase::static_counter_type::balancer_icmp_drop_unrdup_vip_not_found; + counters_named["balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id"] = common::globalBase::static_counter_type::balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id; + counters_named["balancer_icmp_drop_unexpected_transport_protocol"] = common::globalBase::static_counter_type::balancer_icmp_drop_unexpected_transport_protocol; + counters_named["balancer_icmp_drop_unknown_service"] = common::globalBase::static_counter_type::balancer_icmp_drop_unknown_service; + counters_named["balancer_icmp_failed_to_clone"] = common::globalBase::static_counter_type::balancer_icmp_failed_to_clone; + counters_named["balancer_icmp_clone_forwarded"] = common::globalBase::static_counter_type::balancer_icmp_clone_forwarded; + counters_named["balancer_icmp_sent_to_real"] = common::globalBase::static_counter_type::balancer_icmp_sent_to_real; + counters_named["balancer_icmp_out_rate_limit_reached"] = common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached; + counters_named["slow_worker_normal_priority_rate_limit_exceeded"] = common::globalBase::static_counter_type::slow_worker_normal_priority_rate_limit_exceeded; + + counters_named["acl_ingress_v4_broken_packet"] = common::globalBase::static_counter_type::acl_ingress_v4_broken_packet; + counters_named["acl_ingress_v6_broken_packet"] = common::globalBase::static_counter_type::acl_ingress_v6_broken_packet; + counters_named["acl_egress_v4_broken_packet"] = common::globalBase::static_counter_type::acl_egress_v4_broken_packet; + counters_named["acl_egress_v6_broken_packet"] = common::globalBase::static_counter_type::acl_egress_v6_broken_packet; + counters_named["balancer_fragment_drops"] = common::globalBase::static_counter_type::balancer_fragment_drops; + + for (const auto& iter : counters_named) + { + metadata.counter_positions[iter.first] = metadata.start_counters / sizeof(uint64_t) + static_cast(iter.second); + } +} + +void cWorker::SetBufferForCounters(void* buffer, const common::sdp::MetadataWorker& metadata) +{ + counters = common::sdp::ShiftBuffer(buffer, metadata.start_counters); + aclCounters = common::sdp::ShiftBuffer(buffer, metadata.start_acl_counters); + bursts = common::sdp::ShiftBuffer(buffer, metadata.start_bursts); + stats = common::sdp::ShiftBuffer(buffer, metadata.start_stats); + statsPorts = common::sdp::ShiftBuffer(buffer, metadata.start_stats_ports); +} + eResult cWorker::sanityCheck() { if (coreId != rte_lcore_id()) @@ -453,7 +548,7 @@ void cWorker::preparePacket(rte_mbuf* mbuf) // will traverse through ipv4 options/ipv6 extensions and try to determine transport header type and offset if (!prepareL3(mbuf, metadata)) { - stats.brokenPackets++; + stats->brokenPackets++; return; } @@ -475,7 +570,7 @@ void cWorker::preparePacket(rte_mbuf* mbuf) if ((!(metadata->network_flags & YANET_NETWORK_FLAG_NOT_FIRST_FRAGMENT)) && network_payload_length < basePermanently.transportSizes[metadata->transport_headerType]) { - stats.brokenPackets++; + stats->brokenPackets++; metadata->transport_headerType = YANET_TRANSPORT_TYPE_UNKNOWN; return; } @@ -1309,7 +1404,7 @@ inline void cWorker::logicalPort_egress_handle() } if (rte_mbuf_refcnt_read(mbuf) < 1) { - stats.leakedMbufs++; + stats->leakedMbufs++; #ifdef CONFIG_YADECAP_AUTOTEST YADECAP_LOG_ERROR("mbuf[%p] is broken\n", mbuf); @@ -1766,7 +1861,7 @@ inline void cWorker::acl_ingress_flow(rte_mbuf* mbuf, } else { - stats.acl_ingress_dropPackets++; ///< @todo + stats->acl_ingress_dropPackets++; ///< @todo drop(mbuf); } } @@ -1977,7 +2072,7 @@ inline void cWorker::decap_handle() mark_ipv4_dscp(mbuf, decap.ipv4DSCPFlags); } - stats.decap_packets++; + stats->decap_packets++; decap_flow(mbuf, decap.flow); } @@ -2019,7 +2114,7 @@ inline bool cWorker::decap_cut(rte_mbuf* mbuf) const rte_gre_hdr* greHeader = rte_pktmbuf_mtod_offset(mbuf, rte_gre_hdr*, metadata->transport_headerOffset); if (((*(uint32_t*)greHeader) & 0xFFFFFF4F) != 0x00080000) ///< |X|0|X|X|0|0|0x0800|. @todo: ACL_GRE { - stats.decap_unknownExtensions++; + stats->decap_unknownExtensions++; return false; } @@ -2061,7 +2156,7 @@ inline bool cWorker::decap_cut(rte_mbuf* mbuf) return true; } - stats.decap_unknownExtensions++; + stats->decap_unknownExtensions++; return false; } @@ -2120,7 +2215,7 @@ inline void cWorker::route_handle4() if (route_ipv4_values[mbuf_i] == dataplane::lpmValueIdInvalid) { - stats.interface_lookupMisses++; + stats->interface_lookupMisses++; rte_pktmbuf_free(mbuf); continue; } @@ -2134,7 +2229,7 @@ inline void cWorker::route_handle4() rte_ipv4_hdr* ipv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); if (ipv4Header->time_to_live <= 1) { - stats.interface_hopLimits++; + stats->interface_hopLimits++; drop(mbuf); continue; } @@ -2167,7 +2262,7 @@ inline void cWorker::route_handle4() } else { - stats.interface_neighbor_invalid++; + stats->interface_neighbor_invalid++; drop(mbuf); neighbor_resolve.insert_or_update(key, 0); @@ -2194,7 +2289,7 @@ inline void cWorker::route_handle4() metadata->repeat_ttl--; if (metadata->repeat_ttl == 0) { - stats.repeat_ttl++; + stats->repeat_ttl++; rte_pktmbuf_free(mbuf); } else @@ -2245,7 +2340,7 @@ inline void cWorker::route_handle6() if (route_ipv6_values[mbuf_i] == dataplane::lpmValueIdInvalid) { - stats.interface_lookupMisses++; + stats->interface_lookupMisses++; rte_pktmbuf_free(mbuf); continue; } @@ -2259,7 +2354,7 @@ inline void cWorker::route_handle6() rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); if (ipv6Header->hop_limits <= 1) { - stats.interface_hopLimits++; + stats->interface_hopLimits++; drop(mbuf); continue; } @@ -2288,7 +2383,7 @@ inline void cWorker::route_handle6() } else { - stats.interface_neighbor_invalid++; + stats->interface_neighbor_invalid++; drop(mbuf); neighbor_resolve.insert_or_update(key, 0); @@ -2313,7 +2408,7 @@ inline void cWorker::route_handle6() metadata->repeat_ttl--; if (metadata->repeat_ttl == 0) { - stats.repeat_ttl++; + stats->repeat_ttl++; rte_pktmbuf_free(mbuf); } else @@ -2451,7 +2546,7 @@ inline void cWorker::route_tunnel_handle4() if (route_ipv4_values[mbuf_i] == dataplane::lpmValueIdInvalid) { - stats.interface_lookupMisses++; + stats->interface_lookupMisses++; rte_pktmbuf_free(mbuf); continue; } @@ -2467,7 +2562,7 @@ inline void cWorker::route_tunnel_handle4() rte_ipv4_hdr* ipv4Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); if (ipv4Header->time_to_live <= 1) { - stats.interface_hopLimits++; + stats->interface_hopLimits++; drop(mbuf); continue; } @@ -2500,7 +2595,7 @@ inline void cWorker::route_tunnel_handle4() } else { - stats.interface_neighbor_invalid++; + stats->interface_neighbor_invalid++; drop(mbuf); neighbor_resolve.insert_or_update(key, 0); @@ -2530,7 +2625,7 @@ inline void cWorker::route_tunnel_handle4() metadata->repeat_ttl--; if (metadata->repeat_ttl == 0) { - stats.repeat_ttl++; + stats->repeat_ttl++; rte_pktmbuf_free(mbuf); } else @@ -2582,7 +2677,7 @@ inline void cWorker::route_tunnel_handle6() if (route_ipv6_values[mbuf_i] == dataplane::lpmValueIdInvalid) { - stats.interface_lookupMisses++; + stats->interface_lookupMisses++; rte_pktmbuf_free(mbuf); continue; } @@ -2598,7 +2693,7 @@ inline void cWorker::route_tunnel_handle6() rte_ipv6_hdr* ipv6Header = rte_pktmbuf_mtod_offset(mbuf, rte_ipv6_hdr*, metadata->network_headerOffset); if (ipv6Header->hop_limits <= 1) { - stats.interface_hopLimits++; + stats->interface_hopLimits++; drop(mbuf); continue; } @@ -2627,7 +2722,7 @@ inline void cWorker::route_tunnel_handle6() } else { - stats.interface_neighbor_invalid++; + stats->interface_neighbor_invalid++; drop(mbuf); neighbor_resolve.insert_or_update(key, 0); @@ -2655,7 +2750,7 @@ inline void cWorker::route_tunnel_handle6() metadata->repeat_ttl--; if (metadata->repeat_ttl == 0) { - stats.repeat_ttl++; + stats->repeat_ttl++; rte_pktmbuf_free(mbuf); } else @@ -3371,7 +3466,7 @@ inline void cWorker::nat64stateless_ingress_handle() nat64stateless_ingress_translation(mbuf, nat64stateless, translation); - stats.nat64stateless_ingressPackets++; + stats->nat64stateless_ingressPackets++; nat64stateless_ingress_flow(mbuf, nat64stateless.flow); } @@ -3490,7 +3585,7 @@ inline void cWorker::nat64stateless_egress_handle() nat64stateless_egress_translation(mbuf, translation); - stats.nat64stateless_egressPackets++; + stats->nat64stateless_egressPackets++; nat64stateless_egress_flow(mbuf, nat64stateless.flow); } @@ -4085,7 +4180,7 @@ inline void cWorker::balancer_handle() { locker->unlock(); - stats.balancer_invalid_reals_count++; + stats->balancer_invalid_reals_count++; drop(mbuf); continue; } @@ -4895,7 +4990,7 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common if (base.globalBase->fw_state_sync_configs[aclId].flows_size == 0) { // No fw state synchronization configured. - stats.fwsync_no_config_drops++; + stats->fwsync_no_config_drops++; return; } @@ -4992,7 +5087,7 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common if (base.globalBase->fw_state_sync_configs[aclId].flows_size == 0) { // No fw state synchronization configured. - stats.fwsync_no_config_drops++; + stats->fwsync_no_config_drops++; return; } @@ -5010,7 +5105,7 @@ inline void cWorker::acl_state_emit(tAclId aclId, const dataplane::globalBase::f rte_mbuf* mbuf = rte_pktmbuf_alloc(mempool); if (mbuf == nullptr) { - stats.fwsync_multicast_egress_drops++; + stats->fwsync_multicast_egress_drops++; return; } @@ -5030,7 +5125,7 @@ inline void cWorker::acl_state_emit(tAclId aclId, const dataplane::globalBase::f // Push packet to the ring through stack. metadata->flow.type = common::globalBase::eFlowType::slowWorker_fw_sync; controlPlane_stack.insert(mbuf); - stats.fwsync_multicast_egress_imm_packets++; + stats->fwsync_multicast_egress_imm_packets++; } inline void cWorker::acl_egress_entry(rte_mbuf* mbuf, tAclId aclId) @@ -5350,7 +5445,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc { if (rte_ring_full(ring_log)) { - stats.logs_drops++; + stats->logs_drops++; return; } @@ -5360,7 +5455,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc samples::sample_t* sample; if (rte_mempool_get(dataPlane->mempool_log, (void**)&sample) != 0) { - stats.logs_drops++; + stats->logs_drops++; return; } @@ -5380,7 +5475,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc } else { - stats.logs_drops++; + stats->logs_drops++; rte_mempool_put(dataPlane->mempool_log, sample); return; } @@ -5414,11 +5509,11 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc if (rte_ring_enqueue(ring_log, sample) != 0) { - stats.logs_drops++; + stats->logs_drops++; rte_mempool_put(dataPlane->mempool_log, sample); return; } - stats.logs_packets++; + stats->logs_packets++; } inline cWorker::FlowFromState cWorker::acl_egress_checkstate(rte_mbuf* mbuf) @@ -5538,12 +5633,12 @@ inline void cWorker::acl_egress_flow(rte_mbuf* mbuf, const common::globalBase::t if (flow.type == common::globalBase::eFlowType::controlPlane) { - stats.acl_egress_dropPackets++; + stats->acl_egress_dropPackets++; controlPlane(mbuf); } else if (flow.type == common::globalBase::eFlowType::drop) { - stats.acl_egress_dropPackets++; + stats->acl_egress_dropPackets++; drop(mbuf); } else if (metadata->flow.type == common::globalBase::eFlowType::logicalPort_egress || metadata->flow.type == common::globalBase::eFlowType::acl_egress) @@ -5615,18 +5710,18 @@ inline void cWorker::controlPlane_handle() mbuf_i++) { rte_mbuf* mbuf = controlPlane_stack.mbufs[mbuf_i]; - stats.ring_normalPriority_drops++; + stats->ring_normalPriority_drops++; rte_pktmbuf_free(mbuf); } - stats.ring_normalPriority_packets += count; + stats->ring_normalPriority_packets += count; controlPlane_stack.clear(); } inline void cWorker::drop(rte_mbuf* mbuf) { - stats.dropPackets++; + stats->dropPackets++; dataplane::metadata* metadata = YADECAP_METADATA(mbuf); if (basePermanently.globalBaseAtomic->physicalPort_flags[metadata->fromPortId] & YANET_PHYSICALPORT_FLAG_DROP_DUMP) @@ -5681,12 +5776,12 @@ inline void cWorker::slowWorker_entry_highPriority(rte_mbuf* mbuf, if (rte_ring_sp_enqueue(ring_highPriority, (void*)mbuf)) { - stats.ring_highPriority_drops++; + stats->ring_highPriority_drops++; rte_pktmbuf_free(mbuf); } else { - stats.ring_highPriority_packets++; + stats->ring_highPriority_packets++; } } @@ -5708,12 +5803,12 @@ inline void cWorker::slowWorker_entry_normalPriority(rte_mbuf* mbuf, if (rte_ring_sp_enqueue(ring_normalPriority, (void*)mbuf)) { - stats.ring_normalPriority_drops++; + stats->ring_normalPriority_drops++; rte_pktmbuf_free(mbuf); } else { - stats.ring_normalPriority_packets++; + stats->ring_normalPriority_packets++; } } @@ -5723,12 +5818,12 @@ inline void cWorker::slowWorker_entry_lowPriority(rte_mbuf* mbuf) if (rte_ring_sp_enqueue(ring_lowPriority, (void*)mbuf)) { - stats.ring_lowPriority_drops++; + stats->ring_lowPriority_drops++; rte_pktmbuf_free(mbuf); } else { - stats.ring_lowPriority_packets++; + stats->ring_lowPriority_packets++; } } @@ -5866,7 +5961,7 @@ YANET_NEVER_INLINE void cWorker::slowWorkerFarmHandleFragment(rte_mbuf* mbuf) metadata->repeat_ttl--; if (metadata->repeat_ttl == 0) { - stats.repeat_ttl++; + stats->repeat_ttl++; rte_pktmbuf_free(mbuf); return; } diff --git a/dataplane/worker.h b/dataplane/worker.h index a11c017b..455e2972 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -16,6 +16,7 @@ #include "common.h" #include "globalbase.h" #include "samples.h" +#include "sdpserver.h" #include "sharedmemory.h" namespace dataplane @@ -70,6 +71,8 @@ class cWorker void start(); void fillStatsNamesToAddrsTable(std::unordered_map& table); + static void FillMetadataWorkerCounters(common::sdp::MetadataWorker& metadata); + void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorker& metadata); const dataplane::base::generation& current_base() const { return bases[localBaseId & 1]; } @@ -340,16 +343,16 @@ class cWorker rte_ring* ring_lowPriority; dataplane::perf::tsc_deltas* tsc_deltas; rte_ring* ring_toFreePackets; - common::worker::stats::common& Stats() { return stats; } + common::worker::stats::common& Stats() { return *stats; } protected: rte_ring* ring_log; - common::worker::stats::common stats; - common::worker::stats::port statsPorts[CONFIG_YADECAP_PORTS_SIZE]; - uint64_t bursts[CONFIG_YADECAP_MBUFS_BURST_SIZE + 1]; - uint64_t counters[YANET_CONFIG_COUNTERS_SIZE]; - uint64_t aclCounters[YANET_CONFIG_ACL_COUNTERS_SIZE]; + common::worker::stats::common* stats; + common::worker::stats::port* statsPorts; // CONFIG_YADECAP_PORTS_SIZE + uint64_t* bursts; // CONFIG_YADECAP_MBUFS_BURST_SIZE + 1 + uint64_t* counters; // YANET_CONFIG_COUNTERS_SIZE + uint64_t* aclCounters; // YANET_CONFIG_ACL_COUNTERS_SIZE // will decrease with each new packet sent to slow worker, replenishes each N mseconds int32_t packetsToSWNPRemainder; diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 92849dee..9517dcf0 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -24,7 +24,6 @@ worker_gc_t::worker_gc_t(const ConfigValues& cfg, const PortToSocketArray& pts, gc_step{static_cast(cfg.gc_step)}, sample_gc_step{static_cast(cfg.sample_gc_step)} { - memset(counters, 0, sizeof(counters)); } worker_gc_t::~worker_gc_t() @@ -156,17 +155,50 @@ void worker_gc_t::limits(common::idp::limits::response& response) const void worker_gc_t::fillStatsNamesToAddrsTable(std::unordered_map& table) { - table["broken_packets"] = &stats.broken_packets; - table["drop_packets"] = &stats.drop_packets; - table["ring_to_slowworker_packets"] = &stats.ring_to_slowworker_packets; - table["ring_to_slowworker_drops"] = &stats.ring_to_slowworker_drops; - table["fwsync_multicast_egress_packets"] = &stats.fwsync_multicast_egress_packets; - table["fwsync_multicast_egress_drops"] = &stats.fwsync_multicast_egress_drops; - table["fwsync_unicast_egress_packets"] = &stats.fwsync_unicast_egress_packets; - table["fwsync_unicast_egress_drops"] = &stats.fwsync_unicast_egress_drops; - table["drop_samples"] = &stats.drop_samples; - table["balancer_state_insert_failed"] = &stats.balancer_state_insert_failed; - table["balancer_state_insert_done"] = &stats.balancer_state_insert_done; + table["broken_packets"] = &stats->broken_packets; + table["drop_packets"] = &stats->drop_packets; + table["ring_to_slowworker_packets"] = &stats->ring_to_slowworker_packets; + table["ring_to_slowworker_drops"] = &stats->ring_to_slowworker_drops; + table["fwsync_multicast_egress_packets"] = &stats->fwsync_multicast_egress_packets; + table["fwsync_multicast_egress_drops"] = &stats->fwsync_multicast_egress_drops; + table["fwsync_unicast_egress_packets"] = &stats->fwsync_unicast_egress_packets; + table["fwsync_unicast_egress_drops"] = &stats->fwsync_unicast_egress_drops; + table["drop_samples"] = &stats->drop_samples; + table["balancer_state_insert_failed"] = &stats->balancer_state_insert_failed; + table["balancer_state_insert_done"] = &stats->balancer_state_insert_done; +} + +void worker_gc_t::FillMetadataWorkerCounters(common::sdp::MetadataWorkerGc& metadata) +{ + metadata.size = 0; + metadata.start_counters = common::sdp::SdrSever::GetStartData(YANET_CONFIG_COUNTERS_SIZE * sizeof(uint64_t), metadata.size); + metadata.start_stats = common::sdp::SdrSever::GetStartData(sizeof(common::worker_gc::stats_t), metadata.size); + + // stats + static_assert(std::is_trivially_destructible::value, "invalid struct destructible"); + std::map counters_stats; + counters_stats["broken_packets"] = offsetof(common::worker_gc::stats_t, broken_packets); + counters_stats["drop_packets"] = offsetof(common::worker_gc::stats_t, drop_packets); + counters_stats["ring_to_slowworker_packets"] = offsetof(common::worker_gc::stats_t, ring_to_slowworker_packets); + counters_stats["ring_to_slowworker_drops"] = offsetof(common::worker_gc::stats_t, ring_to_slowworker_drops); + counters_stats["fwsync_multicast_egress_packets"] = offsetof(common::worker_gc::stats_t, fwsync_multicast_egress_packets); + counters_stats["fwsync_multicast_egress_drops"] = offsetof(common::worker_gc::stats_t, fwsync_multicast_egress_drops); + counters_stats["fwsync_unicast_egress_packets"] = offsetof(common::worker_gc::stats_t, fwsync_unicast_egress_packets); + counters_stats["fwsync_unicast_egress_drops"] = offsetof(common::worker_gc::stats_t, fwsync_unicast_egress_drops); + counters_stats["drop_samples"] = offsetof(common::worker_gc::stats_t, drop_samples); + counters_stats["balancer_state_insert_failed"] = offsetof(common::worker_gc::stats_t, balancer_state_insert_failed); + counters_stats["balancer_state_insert_done"] = offsetof(common::worker_gc::stats_t, balancer_state_insert_done); + + for (const auto& iter : counters_stats) + { + metadata.counter_positions[iter.first] = (metadata.start_stats + iter.second) / sizeof(uint64_t); + } +} + +void worker_gc_t::SetBufferForCounters(void* buffer, const common::sdp::MetadataWorkerGc& metadata) +{ + counters = common::sdp::ShiftBuffer(buffer, metadata.start_counters); + stats = common::sdp::ShiftBuffer(buffer, metadata.start_stats); } YANET_INLINE_NEVER void worker_gc_t::thread() @@ -452,7 +484,7 @@ void worker_gc_t::handle_balancer_gc() if (saved) { - stats.balancer_state_insert_done++; + stats->balancer_state_insert_done++; const auto& real_from_base = base.globalBase->balancer_reals[value.real_unordered_id]; if (updated) { @@ -470,7 +502,7 @@ void worker_gc_t::handle_balancer_gc() } else { - stats.balancer_state_insert_failed++; + stats->balancer_state_insert_failed++; } } @@ -812,7 +844,7 @@ void worker_gc_t::handle_acl_sync() rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool); if (mbuf_clone == nullptr) { - stats.fwsync_multicast_egress_drops++; + stats->fwsync_multicast_egress_drops++; continue; } @@ -824,7 +856,7 @@ void worker_gc_t::handle_acl_sync() mbuf_clone->data_len = mbuf->data_len; mbuf_clone->pkt_len = mbuf->pkt_len; - stats.fwsync_multicast_egress_packets++; + stats->fwsync_multicast_egress_packets++; utils::SetFlow(mbuf_clone, flow); SendToSlowWorker(mbuf_clone); } @@ -841,7 +873,7 @@ void worker_gc_t::handle_acl_sync() rte_mbuf* mbuf_clone = rte_pktmbuf_alloc(mempool); if (mbuf_clone == nullptr) { - stats.fwsync_unicast_egress_drops++; + stats->fwsync_unicast_egress_drops++; } else { @@ -853,7 +885,7 @@ void worker_gc_t::handle_acl_sync() mbuf_clone->data_len = mbuf->data_len; mbuf_clone->pkt_len = mbuf->pkt_len; - stats.fwsync_unicast_egress_packets++; + stats->fwsync_unicast_egress_packets++; utils::SetFlow(mbuf_clone, fw_state_config.ingress_flow); SendToSlowWorker(mbuf_clone); } @@ -969,12 +1001,12 @@ void worker_gc_t::SendToSlowWorker(rte_mbuf* mbuf) { if (toSlowWorker_->EnqueueSP(mbuf)) { - stats.ring_to_slowworker_drops++; + stats->ring_to_slowworker_drops++; rte_pktmbuf_free(mbuf); } else { - stats.ring_to_slowworker_packets++; + stats->ring_to_slowworker_packets++; } } @@ -996,7 +1028,7 @@ void worker_gc_t::handle_samples() } else { - stats.drop_samples++; + stats->drop_samples++; } }); sampler->visit4([this](auto& sample) { @@ -1006,7 +1038,7 @@ void worker_gc_t::handle_samples() } else { - stats.drop_samples++; + stats->drop_samples++; } }); sampler->clear(); @@ -1015,7 +1047,7 @@ void worker_gc_t::handle_samples() if (samples_current_base_id != current_base_id) { // config changed, aclId may be invalid now - stats.drop_samples += samples.size(); + stats->drop_samples += samples.size(); samples.clear(); samples_current_base_id = current_base_id; } diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index 02e16cfd..ba6b7bae 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -12,6 +12,7 @@ #include "common/idp.h" #include "common/static_vector.h" #include "hashtable.h" +#include "sdpserver.h" class worker_gc_t { @@ -31,6 +32,8 @@ class worker_gc_t void limits(common::idp::limits::response& response) const; void fillStatsNamesToAddrsTable(std::unordered_map& table); + static void FillMetadataWorkerCounters(common::sdp::MetadataWorkerGc& metadata); + void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorkerGc& metadata); protected: YANET_INLINE_NEVER void thread(); @@ -64,7 +67,7 @@ class worker_gc_t uint32_t current_base_id; uint32_t local_base_id; dataplane::base::permanently base_permanently; - common::worker_gc::stats_t stats; + common::worker_gc::stats_t* stats; dataplane::base::generation bases[2]; YADECAP_CACHE_ALIGNED(align1); @@ -101,7 +104,7 @@ class worker_gc_t generation_manager balancer_real_connections; generation_manager balancer_state_stats; - uint64_t counters[YANET_CONFIG_COUNTERS_SIZE]; + uint64_t* counters; // YANET_CONFIG_COUNTERS_SIZE uint32_t current_time; dataplane::hashtable_gc_t nat64stateful_lan_state_gc; From 766505f2a6e2ab32550dd77c4a1d9f4a2cce7e76 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 22:48:06 +0300 Subject: [PATCH 080/195] Getting the main counters via bus is replaced by getting them via shared memory --- autotest/autotest.cpp | 9 +++++++-- autotest/autotest.h | 2 ++ cli/develop.h | 3 ++- cli/show.h | 5 ++--- cli/telegraf.h | 3 ++- controlplane/controlplane.cpp | 33 +++++++++++++++++++++++++++++++-- controlplane/controlplane.h | 5 +++++ controlplane/counter.h | 12 +++++++++--- controlplane/telegraf.cpp | 17 +++++++++++------ controlplane/telegraf.h | 2 +- 10 files changed, 72 insertions(+), 19 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index db946bb1..4f38664a 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -78,6 +78,11 @@ eResult tAutotest::init(const std::string& binaryPath, return ret; } + if (auto ret = common::sdp::SdpClient::ReadSharedMemoryData(sdp_data, true); ret != eResult::success) + { + return ret; + } + return eResult::success; } @@ -1746,7 +1751,7 @@ bool tAutotest::step_memorize_counter_value(const YAML::Node& yamlStep) uint32_t coreId = std::stoi(yamlStep.as().substr(delim_pos + 1)); - const auto response = dataPlane.get_counter_by_name({counter_name, coreId}); + const auto response = common::sdp::SdpClient::GetCounterByName(sdp_data, counter_name, coreId); if (response.empty()) { @@ -1805,7 +1810,7 @@ bool tAutotest::step_diff_with_kept_counter_value(const YAML::Node& yamlStep) return false; } - const auto response = dataPlane.get_counter_by_name({counter_name, coreId}); + const auto response = common::sdp::SdpClient::GetCounterByName(sdp_data, counter_name, coreId); if (response.empty()) { diff --git a/autotest/autotest.h b/autotest/autotest.h index edd2c840..873e9ef4 100644 --- a/autotest/autotest.h +++ b/autotest/autotest.h @@ -11,6 +11,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" #include "common/result.h" +#include "common/sdpclient.h" namespace nAutotest { @@ -96,6 +97,7 @@ class tAutotest interface::dataPlane dataPlane; interface::controlPlane controlPlane; + common::sdp::DataPlaneInSharedMemory sdp_data; common::idp::getConfig::response dataPlaneConfig; common::idp::get_shm_info::response dataPlaneSharedMemory; diff --git a/cli/develop.h b/cli/develop.h index 88c4e0b7..46eba193 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -9,6 +9,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" +#include "common/sdpclient.h" #include "common/tsc_deltas.h" #include "helper.h" @@ -151,7 +152,7 @@ void counter(const uint32_t& counter_id, } } - const auto response = dataplane.getCounters(counter_ids); + const auto response = common::sdp::SdpClient::GetCounters(counter_ids); table_t table; table.insert("counter_id", diff --git a/cli/show.h b/cli/show.h index b9f2e7e8..6de4f7ca 100644 --- a/cli/show.h +++ b/cli/show.h @@ -6,6 +6,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" +#include "common/sdpclient.h" #include "common/tsc_deltas.h" #include "common/version.h" @@ -800,9 +801,7 @@ inline void version() inline void counter_by_name(std::string counter_name, const std::optional& core_id) { - interface::dataPlane dataplane; - - const auto response = dataplane.get_counter_by_name({counter_name, core_id}); + const auto response = common::sdp::SdpClient::GetCounterByName(counter_name, core_id); if (response.empty()) { diff --git a/cli/telegraf.h b/cli/telegraf.h index 20257f3b..0d9993e4 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -3,6 +3,7 @@ #include "common/counters.h" #include "common/icontrolplane.h" #include "common/idataplane.h" +#include "common/sdpclient.h" #include "helper.h" #include "influxdb_format.h" @@ -100,7 +101,7 @@ void unsafe() const auto [responseWorkers, responseWorkerGCs, responseSlowWorkerHashtableGC, responseFragmentation, responseFWState, responseTun64, response_nat64stateful, responseControlplane] = controlplane.telegraf_unsafe(); const auto& [responseSlowWorker, hashtable_gc] = responseSlowWorkerHashtableGC; - const auto static_counters = dataplane.getCounters(vector_range(0, (tCounterId)common::globalBase::static_counter_type::size)); + const auto static_counters = common::sdp::SdpClient::GetCounters(vector_range(0, (tCounterId)common::globalBase::static_counter_type::size)); const auto neighbor_stats = dataplane.neighbor_stats(); const auto memory_stats = dataplane.memory_manager_stats(); const auto& [memory_groups, memory_objects] = memory_stats; diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index 2b2b8b83..b51b43f6 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -42,6 +42,13 @@ eResult cControlPlane::init(const std::string& jsonFilePath) sockets.emplace(std::get<1>(iter.second)); ///< @todo } + result = common::sdp::SdpClient::ReadSharedMemoryData(sdp_data, true); + if (result != eResult::success) + { + return result; + } + counter_manager.init(&sdp_data); + modules.emplace_back(new telegraf_t); ///< @todo modules.emplace_back(new rib_t); ///< @todo modules.emplace_back(new controlplane::module::bus); ///< @todo @@ -264,6 +271,11 @@ eResult cControlPlane::getPhysicalPortName(const tPortId& portId, return eResult::invalidPortId; } +const common::sdp::DataPlaneInSharedMemory* cControlPlane::getSdpData() const +{ + return &sdp_data; +} + common::icp::getPhysicalPorts::response cControlPlane::getPhysicalPorts() const { common::icp::getPhysicalPorts::response response; @@ -613,7 +625,7 @@ common::icp::getFwList::response cControlPlane::command_getFwList(const common:: if (rules_type == common::icp::getFwList::requestType::static_rules_original || rules_type == common::icp::getFwList::requestType::static_rules_generated) { - auto counters = dataPlane.getAclCounters(); + auto counters = getAclCounters(); auto current_guard = generations.current_lock_guard(); const auto& current = generations.current(); const auto need_orig = (rules_type == common::icp::getFwList::requestType::static_rules_original); @@ -877,7 +889,7 @@ eResult cControlPlane::loadConfig(const std::string& rootFilePath, { { std::unique_lock aclCountersDelta_lock(aclCountersDelta_mutex); - aclCountersDelta = dataPlane.getAclCounters(); + aclCountersDelta = getAclCounters(); } generations.next_lock(); @@ -988,3 +1000,20 @@ void cControlPlane::register_service(google::protobuf::Service* service) { services[service->GetDescriptor()->name()] = service; } + +std::vector cControlPlane::getAclCounters() +{ + std::vector response(YANET_CONFIG_ACL_COUNTERS_SIZE); + + uint64_t start_acl_counters = sdp_data.metadata_worker.start_acl_counters; + for (const auto& iter : sdp_data.workers) + { + uint64_t* aclCounters = common::sdp::ShiftBuffer(iter.second.buffer, start_acl_counters); + for (size_t i = 0; i < YANET_CONFIG_ACL_COUNTERS_SIZE; i++) + { + response[i] += aclCounters[i]; + } + } + + return response; +} diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index cfcf82f7..9ff14ab5 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -16,6 +16,7 @@ #include "common/idataplane.h" #include "common/idp.h" #include "common/result.h" +#include "common/sdpclient.h" #include "libprotobuf/controlplane.pb.h" #include "balancer.h" @@ -100,6 +101,8 @@ class cControlPlane } } + const common::sdp::DataPlaneInSharedMemory* getSdpData() const; + protected: /** commands */ common::icp::getPhysicalPorts::response getPhysicalPorts() const; common::icp::getLogicalPorts::response getLogicalPorts() const; @@ -197,6 +200,8 @@ class cControlPlane private: /// used only in loadConfig() controlplane::base_t base; + common::sdp::DataPlaneInSharedMemory sdp_data; void register_service(google::protobuf::Service* service); + std::vector getAclCounters(); }; diff --git a/controlplane/counter.h b/controlplane/counter.h index 63f4e1a3..c961ab99 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -9,6 +9,7 @@ #include "common/icp.h" #include "common/idataplane.h" #include "common/refarray.h" +#include "common/sdpclient.h" class counter_manager_t { @@ -20,6 +21,11 @@ class counter_manager_t { } + void init(const common::sdp::DataPlaneInSharedMemory* sdp_data) + { + this->sdp_data = sdp_data; + } + std::tuple stats() const { std::lock_guard guard(counter_mutex); @@ -65,7 +71,7 @@ class counter_manager_t { /// @todo: check counter_ids are reserved - const auto getCountersResponse = counter_dataplane.getCounters(counter_ids); + const auto getCountersResponse = common::sdp::SdpClient::GetCounters(*sdp_data, counter_ids); std::lock_guard guard(counter_mutex); for (unsigned int i = 0; @@ -82,7 +88,7 @@ class counter_manager_t { std::vector result(counter_ids.size()); - const auto getCountersResponse = counter_dataplane.getCounters(counter_ids); + const auto getCountersResponse = common::sdp::SdpClient::GetCounters(*sdp_data, counter_ids); std::lock_guard guard(counter_mutex); for (unsigned int i = 0; @@ -108,9 +114,9 @@ class counter_manager_t static constexpr uint32_t max_buffer_size = 64; mutable std::mutex counter_mutex; - interface::dataPlane counter_dataplane; std::vector counter_shifts; SegmentAllocator allocator; + const common::sdp::DataPlaneInSharedMemory* sdp_data; }; template> currWorkers; + const common::sdp::DataPlaneInSharedMemory* sdp_data = controlPlane->getSdpData(); + for (const auto& [coreId, worker_info] : sdp_data->workers) + { + std::array bursts; + uint64_t* worker_bursts = + common::sdp::ShiftBuffer(worker_info.buffer, sdp_data->metadata_worker.start_bursts); + memcpy(&bursts[0], worker_bursts, sizeof(uint64_t) * (CONFIG_YADECAP_MBUFS_BURST_SIZE + 1)); + currWorkers[coreId] = bursts; + } - const auto getOtherStatsResponse = dataPlane.getOtherStats(); const auto portsStatsExtended = dataPlane.get_ports_stats_extended(); // - const auto& [currWorkers] = getOtherStatsResponse; - common::icp::telegraf_other::response response; auto& [response_flagFirst, response_workers, response_ports] = response; @@ -323,8 +329,7 @@ common::icp::telegraf_other::response telegraf_t::telegraf_other() { for (const auto& [coreId, workerStats] : currWorkers) { - response_workers[coreId] = {calcUsage(std::get<0>(workerStats), - std::get<0>(prevWorkers[coreId]))}; + response_workers[coreId] = {calcUsage(workerStats, prevWorkers[coreId])}; } } else diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index b432bf2f..926f3570 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -88,7 +88,7 @@ class telegraf_t : public module_t bool flagFirst; - std::map prevWorkers; + std::map> prevWorkers; std::map, std::array> route_tunnel_peer_counters; ///< @todo: gc std::map> dregress_traffic_counters_prev; From 6a6af73d3ce6d91c35713568e1ef6f19f568aee8 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 22:52:02 +0300 Subject: [PATCH 081/195] The interface for receiving basic counters via bus has been removed --- common/idataplane.h | 20 ------- common/idp.h | 35 ------------- dataplane/bus.cpp | 16 ------ dataplane/controlplane.cpp | 105 ------------------------------------- dataplane/controlplane.h | 4 -- dataplane/dataplane.cpp | 22 -------- dataplane/dataplane.h | 5 -- dataplane/worker.cpp | 67 ----------------------- dataplane/worker.h | 1 - dataplane/worker_gc.cpp | 15 ------ dataplane/worker_gc.h | 1 - 11 files changed, 291 deletions(-) diff --git a/common/idataplane.h b/common/idataplane.h index 5e1c40b9..53e3919d 100644 --- a/common/idataplane.h +++ b/common/idataplane.h @@ -103,26 +103,11 @@ class dataPlane return get(); } - common::idp::getAclCounters::response getAclCounters() const - { - return get(); - } - common::idp::getPortStatsEx::response getPortStatsEx() const { return get(); } - common::idp::getCounters::response getCounters(const common::idp::getCounters::request& request) const - { - return get(request); - } - - common::idp::getOtherStats::response getOtherStats() const - { - return get(); - } - common::idp::getConfig::response getConfig() const { return get(); @@ -193,11 +178,6 @@ class dataPlane return get(); } - auto get_counter_by_name(const common::idp::get_counter_by_name::request& request) const - { - return get(request); - } - auto get_shm_info() const { return get(); diff --git a/common/idp.h b/common/idp.h index 5fff9294..19eca0d8 100644 --- a/common/idp.h +++ b/common/idp.h @@ -48,13 +48,10 @@ enum class requestType : uint32_t get_ports_stats_extended, getControlPlanePortStats, getPortStatsEx, - getCounters, getFragmentationStats, getFWState, getFWStateStats, clearFWState, - getAclCounters, - getOtherStats, getConfig, getErrors, getReport, @@ -70,7 +67,6 @@ enum class requestType : uint32_t unrdup_vip_to_balancers, update_vip_vport_proto, version, - get_counter_by_name, get_shm_info, get_shm_tsc_info, set_shm_tsc_state, @@ -663,13 +659,6 @@ namespace getPortStatsEx using response = ::common::getPortStatsEx::response; } -namespace getCounters -{ -using request = std::vector; - -using response = std::vector; -} - namespace getFragmentationStats { using response = fragmentation::stats_t; @@ -703,18 +692,6 @@ namespace getFWStateStats using response = fwstate::stats_t; } -namespace getAclCounters -{ -using response = std::vector; -} - -namespace getOtherStats -{ -using worker = std::tuple>; ///< bursts - -using response = std::tuple>; -} - namespace getConfig { enum class value_type ///< @todo: delete @@ -863,13 +840,6 @@ using response = std::tuple; ///< custom } -namespace get_counter_by_name -{ -using request = std::tuple>; - -using response = std::map; -} - namespace get_shm_info { using dump_meta = std::tuple, get_ports_stats::response, ///< + getControlPlanePortStats::response get_ports_stats_extended::response, getPortStatsEx::response, - getOtherStats::response, getFragmentationStats::response, getFWState::response, getFWStateStats::response, - getAclCounters::response, ///< + getCounters::response getConfig::response, getErrors::response, getReport::response, @@ -1044,7 +1010,6 @@ using response = std::variant, version::response, limits::response, samples::response, - get_counter_by_name::response, get_shm_info::response, get_shm_tsc_info::response, neighbor_show::response, diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index ac58a5ac..69df3bbf 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -269,14 +269,6 @@ void cBus::clientThread(int clientSocket) { response = callWithResponse(&cControlPlane::clearFWState, request); } - else if (type == common::idp::requestType::getCounters) - { - response = callWithResponse(&cControlPlane::getCounters, request); - } - else if (type == common::idp::requestType::getOtherStats) - { - response = callWithResponse(&cControlPlane::getOtherStats, request); - } else if (type == common::idp::requestType::getConfig) { response = callWithResponse(&cControlPlane::getConfig, request); @@ -301,10 +293,6 @@ void cBus::clientThread(int clientSocket) { response = callWithResponse(&cControlPlane::limits, request); } - else if (type == common::idp::requestType::getAclCounters) - { - response = callWithResponse(&cControlPlane::getAclCounters, request); - } else if (type == common::idp::requestType::balancer_connection) { response = callWithResponse(&cControlPlane::balancer_connection, request); @@ -337,10 +325,6 @@ void cBus::clientThread(int clientSocket) { response = callWithResponse(&cControlPlane::version, request); } - else if (type == common::idp::requestType::get_counter_by_name) - { - response = callWithResponse(&cControlPlane::get_counter_by_name, request); - } else if (type == common::idp::requestType::nat64stateful_state) { response = callWithResponse(&cControlPlane::nat64stateful_state, request); diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 894d0a6b..525bfa4f 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -176,25 +176,6 @@ common::idp::getGlobalBase::response cControlPlane::getGlobalBase(const common:: return response; } -common::idp::getOtherStats::response cControlPlane::getOtherStats() -{ - common::idp::getOtherStats::response response; - auto& [response_workers] = response; - - /// workers - { - for (const cWorker* worker : dataPlane->workers_vector) - { - std::array bursts; - memcpy(&bursts[0], worker->bursts, (CONFIG_YADECAP_MBUFS_BURST_SIZE + 1) * sizeof(uint64_t)); - - response_workers[worker->coreId] = {bursts}; - } - } - - return response; -} - common::idp::getWorkerStats::response cControlPlane::getWorkerStats(const common::idp::getWorkerStats::request& request) { /// unsafe @@ -572,24 +553,6 @@ eResult cControlPlane::clearFWState() return common::result_e::success; } -common::idp::getAclCounters::response cControlPlane::getAclCounters() -{ - std::lock_guard guard(mutex); - - common::idp::getAclCounters::response response; - - response.resize(YANET_CONFIG_ACL_COUNTERS_SIZE); - for (const cWorker* worker : dataPlane->workers_vector) - { - for (size_t i = 0; i < YANET_CONFIG_ACL_COUNTERS_SIZE; i++) - { - response[i] += worker->aclCounters[i]; - } - } - - return response; -} - common::idp::getPortStatsEx::response cControlPlane::getPortStatsEx() { common::idp::getPortStatsEx::response response; @@ -625,33 +588,6 @@ common::idp::getPortStatsEx::response cControlPlane::getPortStatsEx() return response; } -common::idp::getCounters::response cControlPlane::getCounters(const common::idp::getCounters::request& request) -{ - common::idp::getCounters::response response; - response.resize(request.size()); - - for (size_t i = 0; - i < request.size(); - i++) - { - const auto& counter_id = request[i]; - - if (counter_id >= YANET_CONFIG_COUNTERS_SIZE) - { - std::lock_guard guard(mutex); - ++errors["getCounters: invalid counterId"]; - continue; - } - - response[i] = accumulateWorkerStats( - [counter_id](cWorker* worker) { - return worker->counters[counter_id]; - }); - } - - return response; -} - common::idp::getConfig::response cControlPlane::getConfig() const { common::idp::getConfig::response response; @@ -1092,47 +1028,6 @@ common::idp::version::response cControlPlane::version() version_custom()}; } -common::idp::get_counter_by_name::response cControlPlane::get_counter_by_name(const common::idp::get_counter_by_name::request& request) -{ - common::idp::get_counter_by_name::response response; - - const auto& [counter_name, optional_core_id] = request; - - if (optional_core_id.has_value()) - { - std::optional counter_val = dataPlane->getCounterValueByName(counter_name, optional_core_id.value()); - if (counter_val.has_value()) - { - response[optional_core_id.value()] = counter_val.value(); - } - - // if counter with provided name does not exist, empty map will be returned, and its emptiness should be checked on another end - return response; - } - - // core_id was not specified, return counter for each core_id - for (const cWorker* worker : dataPlane->workers_vector) - { - std::optional counter_val = dataPlane->getCounterValueByName(counter_name, worker->coreId); - if (counter_val.has_value()) - { - response[worker->coreId] = counter_val.value(); - } - } - - for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) - { - (void)worker_gc; - std::optional counter_val = dataPlane->getCounterValueByName(counter_name, core_id); - if (counter_val.has_value()) - { - response[core_id] = counter_val.value(); - } - } - - return response; -} - common::idp::get_shm_info::response cControlPlane::get_shm_info() { common::idp::get_shm_info::response response; diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index b8cd44b0..182aa590 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -67,9 +67,6 @@ class cControlPlane ///< @todo: move to cDataPlane common::idp::getFWState::response getFWState(); common::idp::getFWStateStats::response getFWStateStats(); eResult clearFWState(); - common::idp::getAclCounters::response getAclCounters(); - common::idp::getCounters::response getCounters(const common::idp::getCounters::request& request); - common::idp::getOtherStats::response getOtherStats(); common::idp::getConfig::response getConfig() const; common::idp::getErrors::response getErrors(); common::idp::getReport::response getReport(); @@ -84,7 +81,6 @@ class cControlPlane ///< @todo: move to cDataPlane eResult unrdup_vip_to_balancers(const common::idp::unrdup_vip_to_balancers::request& request); eResult update_vip_vport_proto(const common::idp::update_vip_vport_proto::request& request); common::idp::version::response version(); - common::idp::get_counter_by_name::response get_counter_by_name(const common::idp::get_counter_by_name::request& request); common::idp::nat64stateful_state::response nat64stateful_state(const common::idp::nat64stateful_state::request& request); common::idp::get_shm_info::response get_shm_info(); common::idp::get_shm_tsc_info::response get_shm_tsc_info(); diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index f1487649..b443d3e7 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -994,7 +994,6 @@ eResult cDataPlane::initWorkers() return result; } - worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[coreId]); workers[coreId] = worker; workers_vector.emplace_back(worker); @@ -1095,7 +1094,6 @@ eResult cDataPlane::initWorkers() return result; } - worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[core_id]); worker_gcs[core_id] = worker; socket_worker_gcs[socket_id] = worker; } @@ -1141,8 +1139,6 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& return result; } - worker->fillStatsNamesToAddrsTable(coreId_to_stats_tables[core]); - workers_vector.emplace_back(worker); std::vector kni_bundleconf; @@ -1238,24 +1234,6 @@ eResult cDataPlane::InitSlowWorkers() return eResult::success; } -std::optional cDataPlane::getCounterValueByName(const std::string& counter_name, uint32_t coreId) -{ - if (coreId_to_stats_tables.count(coreId) == 0) - { - return std::optional(); - } - - const auto& specific_core_table = coreId_to_stats_tables[coreId]; - - if (specific_core_table.count(counter_name) == 0) - { - return std::optional(); - } - - uint64_t counter_value = *(specific_core_table.at(counter_name)); - return std::optional(counter_value); -} - eResult cDataPlane::InitTxQueues() { for (const auto& portIter : ports) diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index e72d3af4..453a8cec 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -159,7 +159,6 @@ class cDataPlane eResult allocateSharedMemory(); eResult splitSharedMemoryPerWorkers(); - std::optional getCounterValueByName(const std::string& counter_name, uint32_t coreId); common::idp::get_shm_info::response getShmInfo(); common::idp::get_shm_tsc_info::response getShmTscInfo(); @@ -171,7 +170,6 @@ class cDataPlane friend class cWorker; friend class cReport; friend class cControlPlane; - friend class cBus; friend class dataplane::globalBase::generation; friend class worker_gc_t; @@ -226,9 +224,6 @@ class cDataPlane common::idp::get_shm_tsc_info::response tscs_meta; - // array instead of the table - how many coreIds can be there? - std::unordered_map> coreId_to_stats_tables; - std::map> shm_by_socket_id; std::set socket_ids; diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 98fe32b2..aa5b09ce 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -258,73 +258,6 @@ void cWorker::start() mainThread(); } -void cWorker::fillStatsNamesToAddrsTable(std::unordered_map& table) -{ - table["brokenPackets"] = &stats->brokenPackets; - table["dropPackets"] = &stats->dropPackets; - table["ring_highPriority_drops"] = &stats->ring_highPriority_drops; - table["ring_normalPriority_drops"] = &stats->ring_normalPriority_drops; - table["ring_lowPriority_drops"] = &stats->ring_lowPriority_drops; - table["ring_highPriority_packets"] = &stats->ring_highPriority_packets; - table["ring_normalPriority_packets"] = &stats->ring_normalPriority_packets; - table["ring_lowPriority_packets"] = &stats->ring_lowPriority_packets; - table["decap_packets"] = &stats->decap_packets; - table["decap_fragments"] = &stats->decap_fragments; - table["decap_unknownExtensions"] = &stats->decap_unknownExtensions; - table["interface_lookupMisses"] = &stats->interface_lookupMisses; - table["interface_hopLimits"] = &stats->interface_hopLimits; - table["interface_neighbor_invalid"] = &stats->interface_neighbor_invalid; - table["nat64stateless_ingressPackets"] = &stats->nat64stateless_ingressPackets; - table["nat64stateless_ingressFragments"] = &stats->nat64stateless_ingressFragments; - table["nat64stateless_ingressUnknownICMP"] = &stats->nat64stateless_ingressUnknownICMP; - table["nat64stateless_egressPackets"] = &stats->nat64stateless_egressPackets; - table["nat64stateless_egressFragments"] = &stats->nat64stateless_egressFragments; - table["nat64stateless_egressUnknownICMP"] = &stats->nat64stateless_egressUnknownICMP; - table["balancer_invalid_reals_count"] = &stats->balancer_invalid_reals_count; - table["fwsync_multicast_egress_drops"] = &stats->fwsync_multicast_egress_drops; - table["fwsync_multicast_egress_packets"] = &stats->fwsync_multicast_egress_packets; - table["fwsync_multicast_egress_imm_packets"] = &stats->fwsync_multicast_egress_imm_packets; - table["fwsync_no_config_drops"] = &stats->fwsync_no_config_drops; - table["fwsync_unicast_egress_drops"] = &stats->fwsync_unicast_egress_drops; - table["fwsync_unicast_egress_packets"] = &stats->fwsync_unicast_egress_packets; - table["acl_ingress_dropPackets"] = &stats->acl_ingress_dropPackets; - table["acl_egress_dropPackets"] = &stats->acl_egress_dropPackets; - table["repeat_ttl"] = &stats->repeat_ttl; - table["leakedMbufs"] = &stats->leakedMbufs; - table["logs_packets"] = &stats->logs_packets; - table["logs_drops"] = &stats->logs_drops; - - table["balancer_state_insert_failed"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_state_insert_failed]; - table["balancer_state_insert_done"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_state_insert_done]; - table["balancer_icmp_generated_echo_reply_ipv4"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv4]; - table["balancer_icmp_generated_echo_reply_ipv6"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_generated_echo_reply_ipv6]; - table["balancer_icmp_drop_icmpv4_payload_too_short_ip"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_ip]; - table["balancer_icmp_drop_icmpv4_payload_too_short_port"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv4_payload_too_short_port]; - table["balancer_icmp_drop_icmpv6_payload_too_short_ip"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_ip]; - table["balancer_icmp_drop_icmpv6_payload_too_short_port"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_icmpv6_payload_too_short_port]; - table["balancer_icmp_unmatching_src_from_original_ipv4"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv4]; - table["balancer_icmp_unmatching_src_from_original_ipv6"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_unmatching_src_from_original_ipv6]; - table["balancer_icmp_drop_real_disabled"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_real_disabled]; - table["balancer_icmp_no_balancer_src_ipv4"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv4]; - table["balancer_icmp_no_balancer_src_ipv6"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_no_balancer_src_ipv6]; - table["balancer_icmp_drop_already_cloned"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_already_cloned]; - table["balancer_icmp_drop_no_unrdup_table_for_balancer_id"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_no_unrdup_table_for_balancer_id]; - table["balancer_icmp_drop_unrdup_vip_not_found"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unrdup_vip_not_found]; - table["balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_no_vip_vport_proto_table_for_balancer_id]; - table["balancer_icmp_drop_unexpected_transport_protocol"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unexpected_transport_protocol]; - table["balancer_icmp_drop_unknown_service"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_drop_unknown_service]; - table["balancer_icmp_failed_to_clone"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_failed_to_clone]; - table["balancer_icmp_clone_forwarded"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_clone_forwarded]; - table["balancer_icmp_sent_to_real"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_sent_to_real]; - table["balancer_icmp_out_rate_limit_reached"] = &counters[(uint32_t)common::globalBase::static_counter_type::balancer_icmp_out_rate_limit_reached]; - table["slow_worker_normal_priority_rate_limit_exceeded"] = &counters[(uint32_t)common::globalBase::static_counter_type::slow_worker_normal_priority_rate_limit_exceeded]; - - table["acl_ingress_v4_broken_packet"] = &counters[(uint32_t)common::globalBase::static_counter_type::acl_ingress_v4_broken_packet]; - table["acl_ingress_v6_broken_packet"] = &counters[(uint32_t)common::globalBase::static_counter_type::acl_ingress_v6_broken_packet]; - table["acl_egress_v4_broken_packet"] = &counters[(uint32_t)common::globalBase::static_counter_type::acl_egress_v4_broken_packet]; - table["acl_egress_v6_broken_packet"] = &counters[(uint32_t)common::globalBase::static_counter_type::acl_egress_v6_broken_packet]; -} - void cWorker::FillMetadataWorkerCounters(common::sdp::MetadataWorker& metadata) { metadata.size = 0; diff --git a/dataplane/worker.h b/dataplane/worker.h index 455e2972..8595206c 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -70,7 +70,6 @@ class cWorker eResult init(const tCoreId& coreId, const dataplane::base::permanently& basePermanently, const dataplane::base::generation& base); void start(); - void fillStatsNamesToAddrsTable(std::unordered_map& table); static void FillMetadataWorkerCounters(common::sdp::MetadataWorker& metadata); void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorker& metadata); diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 9517dcf0..832f18cb 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -153,21 +153,6 @@ void worker_gc_t::limits(common::idp::limits::response& response) const globalbase_atomic->updater.fw6_state.limits(response, "acl.state.v6.ht"); } -void worker_gc_t::fillStatsNamesToAddrsTable(std::unordered_map& table) -{ - table["broken_packets"] = &stats->broken_packets; - table["drop_packets"] = &stats->drop_packets; - table["ring_to_slowworker_packets"] = &stats->ring_to_slowworker_packets; - table["ring_to_slowworker_drops"] = &stats->ring_to_slowworker_drops; - table["fwsync_multicast_egress_packets"] = &stats->fwsync_multicast_egress_packets; - table["fwsync_multicast_egress_drops"] = &stats->fwsync_multicast_egress_drops; - table["fwsync_unicast_egress_packets"] = &stats->fwsync_unicast_egress_packets; - table["fwsync_unicast_egress_drops"] = &stats->fwsync_unicast_egress_drops; - table["drop_samples"] = &stats->drop_samples; - table["balancer_state_insert_failed"] = &stats->balancer_state_insert_failed; - table["balancer_state_insert_done"] = &stats->balancer_state_insert_done; -} - void worker_gc_t::FillMetadataWorkerCounters(common::sdp::MetadataWorkerGc& metadata) { metadata.size = 0; diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index ba6b7bae..a74c56c9 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -31,7 +31,6 @@ class worker_gc_t void limits(common::idp::limits::response& response) const; - void fillStatsNamesToAddrsTable(std::unordered_map& table); static void FillMetadataWorkerCounters(common::sdp::MetadataWorkerGc& metadata); void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorkerGc& metadata); From 1cb5dcf55530445dc44a72f9c41578767ee95791 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 15 Sep 2024 23:09:14 +0300 Subject: [PATCH 082/195] Added new options to the cli - Bus operation time measurements are enabled. - Added error message output when connecting via socket to a dataplane before calling an exception. - 3 commands for getting bus statistics have been added to the cli. - The command to get the main counters has been added to the cli. --- cli/bus.h | 160 ++++++++++++++++++++++++++++++++++++++++++++ cli/helper.h | 10 +++ cli/main.cpp | 7 ++ cli/telegraf.h | 30 +++++++++ common/idataplane.h | 7 +- dataplane/bus.cpp | 2 + 6 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 cli/bus.h diff --git a/cli/bus.h b/cli/bus.h new file mode 100644 index 00000000..e26c2456 --- /dev/null +++ b/cli/bus.h @@ -0,0 +1,160 @@ +#pragma once + +#include "helper.h" +#include "influxdb_format.h" + +namespace bus +{ + +using bus_request_info = std::tuple; + +inline std::vector get_bus_requests(common::sdp::DataPlaneInSharedMemory& sdp_data) +{ + auto [requests, errors, durations] = sdp_data.BuffersBus(); + (void)errors; + + std::map names = { + {common::idp::requestType::updateGlobalBase, "updateGlobalBase"}, + {common::idp::requestType::updateGlobalBaseBalancer, "updateGlobalBaseBalancer"}, + {common::idp::requestType::getGlobalBase, "getGlobalBase"}, + {common::idp::requestType::getWorkerStats, "getWorkerStats"}, + {common::idp::requestType::getSlowWorkerStats, "getSlowWorkerStats"}, + {common::idp::requestType::get_worker_gc_stats, "get_worker_gc_stats"}, + {common::idp::requestType::get_dregress_counters, "get_dregress_counters"}, + {common::idp::requestType::get_ports_stats, "get_ports_stats"}, + {common::idp::requestType::get_ports_stats_extended, "get_ports_stats_extended"}, + {common::idp::requestType::getControlPlanePortStats, "getControlPlanePortStats"}, + {common::idp::requestType::getPortStatsEx, "getPortStatsEx"}, + {common::idp::requestType::getFragmentationStats, "getFragmentationStats"}, + {common::idp::requestType::getFWState, "getFWState"}, + {common::idp::requestType::getFWStateStats, "getFWStateStats"}, + {common::idp::requestType::clearFWState, "clearFWState"}, + {common::idp::requestType::getConfig, "getConfig"}, + {common::idp::requestType::getErrors, "getErrors"}, + {common::idp::requestType::getReport, "getReport"}, + {common::idp::requestType::lpm4LookupAddress, "lpm4LookupAddress"}, + {common::idp::requestType::lpm6LookupAddress, "lpm6LookupAddress"}, + {common::idp::requestType::nat64stateful_state, "nat64stateful_state"}, + {common::idp::requestType::balancer_connection, "balancer_connection"}, + {common::idp::requestType::balancer_service_connections, "balancer_service_connections"}, + {common::idp::requestType::balancer_real_connections, "balancer_real_connections"}, + {common::idp::requestType::limits, "limits"}, + {common::idp::requestType::samples, "samples"}, + {common::idp::requestType::debug_latch_update, "debug_latch_update"}, + {common::idp::requestType::unrdup_vip_to_balancers, "unrdup_vip_to_balancers"}, + {common::idp::requestType::update_vip_vport_proto, "update_vip_vport_proto"}, + {common::idp::requestType::version, "version"}, + {common::idp::requestType::get_shm_info, "get_shm_info"}, + {common::idp::requestType::get_shm_tsc_info, "get_shm_tsc_info"}, + {common::idp::requestType::set_shm_tsc_state, "set_shm_tsc_state"}, + {common::idp::requestType::dump_physical_port, "dump_physical_port"}, + {common::idp::requestType::balancer_state_clear, "balancer_state_clear"}, + {common::idp::requestType::neighbor_show, "neighbor_show"}, + {common::idp::requestType::neighbor_insert, "neighbor_insert"}, + {common::idp::requestType::neighbor_remove, "neighbor_remove"}, + {common::idp::requestType::neighbor_clear, "neighbor_clear"}, + {common::idp::requestType::neighbor_flush, "neighbor_flush"}, + {common::idp::requestType::neighbor_update_interfaces, "neighbor_update_interfaces"}, + {common::idp::requestType::neighbor_stats, "neighbor_stats"}, + {common::idp::requestType::memory_manager_update, "memory_manager_update"}, + {common::idp::requestType::memory_manager_stats, "memory_manager_stats"}}; + + std::vector result; + for (uint32_t index = 0; index < (uint32_t)common::idp::requestType::size; ++index) + { + if ((requests[index] != 0) || (durations[index] != 0)) + { + const auto& iter = names.find(static_cast(index)); + result.emplace_back((iter != names.end() ? iter->second : "unknown"), requests[index], durations[index]); + } + } + + return result; +} + +inline void bus_requests() +{ + common::sdp::DataPlaneInSharedMemory sdp_data; + OpenSharedMemoryDataplaneBuffers(sdp_data, false); + auto requests = get_bus_requests(sdp_data); + + table_t table; + table.insert("request", "count", "duration_ms"); + for (const auto& [request, count, duration] : requests) + { + if ((count != 0) || (duration != 0)) + { + table.insert(request, count, duration); + } + } + + table.print(); +} + +inline std::vector> get_bus_errors(const common::sdp::DataPlaneInSharedMemory& sdp_data) +{ + auto [requests, errors, durations] = sdp_data.BuffersBus(); + (void)requests; + (void)durations; + + std::map names = { + {common::idp::errorType::busRead, "busRead"}, + {common::idp::errorType::busWrite, "busWrite"}, + {common::idp::errorType::busParse, "busParse"}, + }; + + std::vector> result; + for (uint32_t index = 0; index < (uint32_t)common::idp::errorType::size; ++index) + { + const auto& iter = names.find(static_cast(index)); + result.emplace_back((iter != names.end() ? iter->second : "unknown"), errors[index]); + } + + return result; +} + +inline void bus_errors() +{ + common::sdp::DataPlaneInSharedMemory sdp_data; + OpenSharedMemoryDataplaneBuffers(sdp_data, false); + auto errors = get_bus_errors(sdp_data); + + table_t table; + table.insert("error", "count"); + for (const auto& [error, count] : errors) + { + table.insert(error, count); + } + + table.print(); +} + +inline void bus_telegraf() +{ + common::sdp::DataPlaneInSharedMemory sdp_data; + OpenSharedMemoryDataplaneBuffers(sdp_data, false); + + auto errors = get_bus_errors(sdp_data); + std::vector infl_errors; + for (const auto& [error, count] : errors) + { + infl_errors.emplace_back(error.data(), count); + } + influxdb_format::print("bus_errors", {}, infl_errors); + + auto requests = get_bus_requests(sdp_data); + if (!requests.empty()) + { + std::vector infl_counts; + std::vector infl_durations; + for (const auto& [request, count, duration] : requests) + { + infl_counts.emplace_back(request.data(), count); + infl_durations.emplace_back(request.data(), duration); + } + influxdb_format::print("bus_counts", {}, infl_counts); + influxdb_format::print("bus_durations", {}, infl_durations); + } +} + +} // namespace bus diff --git a/cli/helper.h b/cli/helper.h index 66890a57..4d4ceea6 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -12,6 +12,7 @@ #include +#include "common/sdpclient.h" #include "converter.h" template @@ -466,3 +467,12 @@ class table_t std::vector> table; std::vector columnLengths; }; + +void OpenSharedMemoryDataplaneBuffers(common::sdp::DataPlaneInSharedMemory& sdp_data, bool open_workers_data) +{ + if (common::sdp::SdpClient::ReadSharedMemoryData(sdp_data, open_workers_data) != eResult::success) + { + YANET_LOG_ERROR("Error openning shared memory dataplane buffers\n"); + std::exit(1); + } +} diff --git a/cli/main.cpp b/cli/main.cpp index ccd74548..fc54b443 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -5,6 +5,7 @@ #include "acl.h" #include "balancer.h" +#include "bus.h" #include "config.h" #include "convert.h" #include "develop.h" @@ -127,12 +128,18 @@ std::vector ", [](const auto& args) { call(latch::dataplane_update, args); }}, {"counter", "[counter_name] ", [](const auto& args) { call(show::counter_by_name, args); }}, {"counters stat", "", [](const auto& args) { call(show::counters_stat, args); }}, + + {"bus requests", "", [](const auto& args) { call(bus::bus_requests, args); }}, + {"bus errors", "", [](const auto& args) { call(bus::bus_errors, args); }}, + {"latch update dataplane", " ", [](const auto& args) { call(latch::dataplane_update, args); }}, {}, {"convert logical_module", "", [](const auto& args) { call(convert::logical_module, args); }}}; diff --git a/cli/telegraf.h b/cli/telegraf.h index 0d9993e4..1c24b0e0 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -702,4 +702,34 @@ void service() } +void main_counters() +{ + common::sdp::DataPlaneInSharedMemory sdp_data; + OpenSharedMemoryDataplaneBuffers(sdp_data, true); + + for (const auto& [coreId, worker_info] : sdp_data.workers) + { + std::vector values; + uint64_t* buffer = common::sdp::ShiftBuffer(worker_info.buffer, + sdp_data.metadata_worker.start_counters); + for (const auto& [name, index] : sdp_data.metadata_worker.counter_positions) + { + values.emplace_back(name.data(), buffer[index]); + } + influxdb_format::print("worker", {{"coreId", coreId}}, values); + } + + for (const auto& [coreId, worker_info] : sdp_data.workers_gc) + { + std::vector values; + uint64_t* buffer = common::sdp::ShiftBuffer(worker_info.buffer, + sdp_data.metadata_worker.start_counters); + for (const auto& [name, index] : sdp_data.metadata_worker_gc.counter_positions) + { + values.emplace_back(name.data(), buffer[index]); + } + influxdb_format::print("worker_gc", {{"coreId", coreId}}, values); + } +} + } diff --git a/common/idataplane.h b/common/idataplane.h index 53e3919d..eb131d56 100644 --- a/common/idataplane.h +++ b/common/idataplane.h @@ -267,7 +267,12 @@ class dataPlane int ret = connect(clientSocket, (struct sockaddr*)&address, sizeof(address)); if (ret == -1) { - throw std::string("connect(): ") + strerror(errno); + int error = errno; + YANET_LOG_ERROR("Error connect to socket %s, error: %d - %s\n", + common::idp::socketPath, + error, + strerror(error)); + throw std::string("connect(): ") + strerror(error); } } diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 69df3bbf..95a81a03 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -405,6 +405,8 @@ void cBus::clientThread(int clientSocket) std::chrono::duration duration = std::chrono::system_clock::now() - startTime; + // The duration time is measured in milliseconds + stats.durations[(uint32_t)type] += static_cast(1000 * duration.count()); YANET_LOG_DEBUG("request type %d processed - %.3f sec\n", (int)type, duration.count()); From 6d8e640b18cfef3ed20e8af7d6c94bb78322f687 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sat, 14 Sep 2024 21:15:36 +0300 Subject: [PATCH 083/195] Added autotest for counters in shared memory --- .../075_counters_shared_memory/autotest.yaml | 5 +++ .../controlplane.conf | 32 +++++++++++++++++++ autotest/yanet-autotest-run.py | 1 + 3 files changed, 38 insertions(+) create mode 100644 autotest/units/001_one_port/075_counters_shared_memory/autotest.yaml create mode 100644 autotest/units/001_one_port/075_counters_shared_memory/controlplane.conf diff --git a/autotest/units/001_one_port/075_counters_shared_memory/autotest.yaml b/autotest/units/001_one_port/075_counters_shared_memory/autotest.yaml new file mode 100644 index 00000000..ff96e5f0 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_shared_memory/autotest.yaml @@ -0,0 +1,5 @@ +steps: +- cli: "telegraf counters" +- cli: "telegraf bus" +- cli: "bus errors" +- cli: "bus requests" diff --git a/autotest/units/001_one_port/075_counters_shared_memory/controlplane.conf b/autotest/units/001_one_port/075_counters_shared_memory/controlplane.conf new file mode 100644 index 00000000..a49ff792 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_shared_memory/controlplane.conf @@ -0,0 +1,32 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "vrf0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "vrf0" + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.200" + } + } + } + } +} diff --git a/autotest/yanet-autotest-run.py b/autotest/yanet-autotest-run.py index 492c16a8..19ce51b5 100755 --- a/autotest/yanet-autotest-run.py +++ b/autotest/yanet-autotest-run.py @@ -86,6 +86,7 @@ def start(self, dataplane_conf_path, units): os.makedirs("/run/yanet", exist_ok=True) self.run_dataplane(dataplane_conf_path) + time.sleep(5) self.run_controlplane() self.run_autotest(units) From 74982e3e850ecd6f783ee0224d5bf1e7342c5d84 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Tue, 20 Aug 2024 16:42:19 +0300 Subject: [PATCH 084/195] Update build.sh: extend usage examples --- build.sh | 74 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/build.sh b/build.sh index c2b352b6..214072c3 100755 --- a/build.sh +++ b/build.sh @@ -1,56 +1,80 @@ #!/bin/bash output="packages" -release="22.04" -version="64.0.0" +ubuntu_release="22.04" +yanet_version="64.0.0" usage() { - echo "Usage: $0 [ -o ARTIFACTS_DIR ] [ -r RELEASE ] [ -v VERSION ] -t package|image" + cat < Date: Fri, 20 Sep 2024 00:31:45 +0300 Subject: [PATCH 085/195] Fixes ctree copy constructor miscasting --- common/ctree.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/ctree.h b/common/ctree.h index 50c737c7..c12259af 100644 --- a/common/ctree.h +++ b/common/ctree.h @@ -183,7 +183,8 @@ struct ctree { if constexpr (sizeof...(next_counters_T) != 0) { - next.emplace(key, new node_t{*static_cast(value)}); + using child_t = node_t; + next.emplace(key, new child_t{*static_cast(value)}); } else { @@ -363,8 +364,8 @@ struct ctree { if constexpr (sizeof...(next_counters_T) != 0) { - using actual = node_t; - next.emplace(key, new actual(*static_cast(node))); + using child_t = node_t; + next.emplace(key, new child_t(*static_cast(node))); } else { From 014614bb7d565487a8c969c507cda293bd9318fa Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 18 Sep 2024 22:48:09 +0400 Subject: [PATCH 086/195] Ensure worker-local fw_state reflects cleared global firewall state The clearFWState() function clears global firewall state by invalidating all entries in the fw4_state and fw6_state hashtables via the clear() method. However, the worker-local fw_state, which caches firewall states for each worker, was not being updated to reflect these cleared entries. This led to inconsistencies where stale firewall state entries remained in the worker's fw_state cache, even though they had been cleared globally. The issue arose because the handle_acl_gc() function only removed entries from fw_state based on timeout conditions. Entries that were invalidated by clearFWState() were skipped during garbage collection, as gc() only processes valid entries. Updated handle_acl_gc() to explicitly check for invalidated entries (i.e., entries where the valid_mask has been cleared) during the gc() process. When such invalid entries are encountered, they are now added to fw_state_remove_stack, ensuring they are removed from the worker's fw_state cache. --- dataplane/worker_gc.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 832f18cb..759c8703 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -621,6 +621,22 @@ void worker_gc_t::handle_acl_gc() iter.unlock(); } + else + { + // The entry is invalid, likely due to a call to clearFWState(). + iter.lock(); + auto key = *iter.key(); + iter.unlock(); + + common::idp::getFWState::key_t fw_key( + std::uint8_t(key.proto), + {rte_be_to_cpu_32(key.src_addr.address)}, + {rte_be_to_cpu_32(key.dst_addr.address)}, + key.src_port, + key.dst_port); + + fw_state_remove_stack.emplace_back(fw_key); + } } if (fw4_state_gc.offset == 0) @@ -729,6 +745,22 @@ void worker_gc_t::handle_acl_gc() iter.unlock(); } + else + { + // The entry is invalid, likely due to a call to clearFWState(). + iter.lock(); + auto key = *iter.key(); + iter.unlock(); + + common::idp::getFWState::key_t fw_key( + std::uint8_t(key.proto), + {key.src_addr.bytes}, + {key.dst_addr.bytes}, + key.src_port, + key.dst_port); + + fw_state_remove_stack.emplace_back(fw_key); + } } if (fw6_state_gc.offset == 0) From 1090a5800a6ceea26b703c7f1ceafcd848366421 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 2 Aug 2024 14:47:58 +0300 Subject: [PATCH 087/195] Use alias for std::variant with raw actions in Actions class Makes it easier to read and avoid writing decltype where we need such type --- common/actions.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/actions.h b/common/actions.h index cebbcc5b..3b7ea32a 100644 --- a/common/actions.h +++ b/common/actions.h @@ -194,12 +194,15 @@ struct CheckStateAction final } }; +using RawAction = std::variant; + + /** * @brief Represents a generic action. */ struct Action { - std::variant raw_action; + RawAction raw_action; Action() : raw_action(FlowAction()) {} @@ -240,7 +243,7 @@ namespace acl struct Actions { std::vector path{}; - std::array> action_counts = {0}; + std::array> action_counts = {0}; std::optional check_state_index{}; Actions() = default; From 53970411a00e42f4ef0c4ff70d97d02ec0ec70e6 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 5 Aug 2024 17:58:49 +0300 Subject: [PATCH 088/195] Add dummy state-timeout rule This commit introduces parsing for the state-timeout rule. The tests and the actual semantics will be implemented later. Note that the current implementation does not properly manage StateTimeout yet, as we are only interested in the last action for performance optimization. Storing only the last state-timeout action reduces the number of actions processed in the dataplane, enhancing performance. In general, we can optimize performance for actions that only need to be executed once. For instance, only the first execution of CheckStateAction matters, as we cannot add new states while processing the current packet actions. Similarly, only the last StateTimeoutAction is relevant, as it provides the most accurate timeout value. By storing only the relevant action and tracking its index during the "compile" step, we can use this information to optimize performance. For example, instead of storing a StateTimeoutAction, we could directly add the timeout field to the FlowAction. The next commit will propose a generic way to handle this optimization across various action types. --- common/actions.h | 81 ++++++++++++++++++++++++++++++++++- controlplane/acl.cpp | 9 ++++ controlplane/acl/rule.h | 20 ++++++++- controlplane/acl_compiler.cpp | 4 ++ controlplane/acl_value.h | 3 +- dataplane/action_dispatcher.h | 6 +++ libfwparser/fw_config.cpp | 1 + libfwparser/fw_config.h | 1 + libfwparser/fw_parser.y | 7 +++ libfwparser/token.l | 1 + 10 files changed, 129 insertions(+), 4 deletions(-) diff --git a/common/actions.h b/common/actions.h index 3b7ea32a..0c26e09c 100644 --- a/common/actions.h +++ b/common/actions.h @@ -74,6 +74,44 @@ struct check_state_t } }; +struct state_timeout_t +{ + state_timeout_t() : + timeout(0) + {} + + state_timeout_t(uint32_t timeout) : + timeout(timeout) + {} + + bool operator==(const state_timeout_t& o) const + { + return timeout == o.timeout; + } + + bool operator!=(const state_timeout_t& o) const + { + return !operator==(o); + } + + constexpr bool operator<(const state_timeout_t& o) const + { + return timeout < o.timeout; + } + + void pop(stream_in_t& stream) + { + stream.pop(timeout); + } + + void push(stream_out_t& stream) const + { + stream.push(timeout); + } + + uint32_t timeout; +}; + } // namespace acl // TODO: When rewriting the current ACL library into LibFilter, we could consider using inheritance. @@ -194,8 +232,44 @@ struct CheckStateAction final } }; -using RawAction = std::variant; +/** + * @brief Represents an action that sets timeout for the dynamic firewall rule. + */ +struct StateTimeoutAction final +{ + // Maximum count of StateTimeoutActions objects allowed. + // We have one here since only the last timeout matters. + static constexpr size_t MAX_COUNT = 1; + // Timeout in seconds + uint32_t timeout; + + StateTimeoutAction(const acl::state_timeout_t& timeout_action) : + timeout(timeout_action.timeout){}; + + StateTimeoutAction() : + timeout(0){}; + + [[nodiscard]] bool terminating() const { return false; } + + void pop(stream_in_t& stream) + { + stream.pop(timeout); + } + + void push(stream_out_t& stream) const + { + stream.push(timeout); + } + + [[nodiscard]] std::string to_string() const + { + std::ostringstream oss; + oss << "StateTimeoutAction(timeout=" << timeout << ")"; + return oss.str(); + } +}; +using RawAction = std::variant; /** * @brief Represents a generic action. @@ -238,13 +312,16 @@ namespace acl * will have slightly different representation of the internal vector based on whether we have * a "check-state" action or not. This way we can reduce a number of branching in the dataplane and * also reduce the size of the object since we will use std::variant to hold either a "check-state"-object, - * or a regular one (see common::Actions definition below) + * or a regular one (see common::Actions definition below). + * Also, it manages the StateTimeoutActions to reduce number of actions in the dataplane by saving only the + * last timeout action. */ struct Actions { std::vector path{}; std::array> action_counts = {0}; std::optional check_state_index{}; + std::optional state_timeout_index{}; Actions() = default; Actions(const Action& action) { add(action); }; diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index d767dbf9..0ceef7a5 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -325,6 +325,7 @@ struct firewall_rules_t case ipfw::rule_action_t::DUMP: case ipfw::rule_action_t::DENY: case ipfw::rule_action_t::CHECKSTATE: + case ipfw::rule_action_t::STATETIMEOUT: { // handle only meaning rules auto& ruleref = yanet_rules.emplace_back(rulep, configp); @@ -497,6 +498,14 @@ static bool unwind(int64_t start_from, firewall_rules_t& fw, const dispatcher_ru log || rule.log); ACL_DBGMSG("check_state gathered..."); } + else if (std::holds_alternative(rule.action)) + { + rules.emplace_back(std::move(result_filter), + std::get(rule.action), + ids, + log || rule.log); + ACL_DBGMSG("state_timeout gathered..."); + } else { rules.emplace_back(std::move(result_filter), diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index ea0beccd..598dd77e 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1035,7 +1035,7 @@ const int64_t DISPATCHER = -1; // sense. // // Additionally, we might have another variant for representing rules that are suitable for execution in the dataplane. -using rule_action = std::variant; +using rule_action = std::variant; struct rule_t { @@ -1066,6 +1066,10 @@ struct rule_t rule_t(_filter, rule_action(action), ids, log) {} + rule_t(const ref_t& _filter, common::acl::state_timeout_t action, const ids_t& ids, bool log) : + rule_t(_filter, rule_action(action), ids, log) + {} + rule_t(const ref_t& _filter, int64_t num, int64_t skipto) : filter(_filter), action(skipto), @@ -1113,6 +1117,9 @@ struct rule_t case ipfw::rule_action_t::DUMP: action = common::acl::dump_t(std::get(rulep->action_arg)); break; + case ipfw::rule_action_t::STATETIMEOUT: + action = common::acl::state_timeout_t(std::get(rulep->action_arg)); + break; default: YANET_LOG_WARNING("unexpected rule action in rule '%s'\n", rulep->text.data()); return; @@ -1190,6 +1197,11 @@ struct rule_t { text = "check-state"; } + else if (std::holds_alternative(action)) + { + auto rule_action = std::get(action); + text = "state-timeout(" + std::to_string(rule_action.timeout) + ")"; + } else { auto arg = std::get(action); @@ -1375,11 +1387,17 @@ struct hash // predefined static constant as a unique identifier. hash_combine(h, common::acl::check_state_t::HASH_IDENTIFIER); } + else if (std::holds_alternative(r.action)) + { + auto action = std::get(r.action); + hash_combine(h, action.timeout); + } else { auto action = std::get(r.action); hash_combine(h, action.dump_id); } + if (r.filter) { hash_combine(h, **r.filter); diff --git a/controlplane/acl_compiler.cpp b/controlplane/acl_compiler.cpp index 599421e9..a3d07aa9 100644 --- a/controlplane/acl_compiler.cpp +++ b/controlplane/acl_compiler.cpp @@ -287,6 +287,10 @@ void compiler_t::collect(const std::vector& unwind_rules) { rule.value_filter_id = value.collect_initial_rule(*check_state); } + else if (auto state_timeout = std::get_if(&unwind_rule.action)) + { + rule.value_filter_id = value.collect_initial_rule(*state_timeout); + } } /// terminating diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 0aff3e4e..3cd95039 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -18,7 +18,8 @@ class value_t { static_assert(std::is_same_v, common::globalBase::tFlow> || std::is_same_v, common::acl::dump_t> || - std::is_same_v, common::acl::check_state_t>, + std::is_same_v, common::acl::check_state_t> || + std::is_same_v, common::acl::state_timeout_t>, "Unsupported type in rule_action"); rule_actions.emplace_back(std::forward(rule)); diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index ee399965..04ed9b80 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -89,6 +89,12 @@ struct ActionDispatcher ring.write(args.mbuf, flow.type); } + // FIXME: temporary + static void execute(const common::StateTimeoutAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + { + YANET_LOG_DEBUG("Timeout specified is %d\n", action.timeout); + } + static void execute(const common::FlowAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) { auto worker = args.worker; diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index a0c21485..0af9df32 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -1147,6 +1147,7 @@ bool fw_config_t::validate_rule(rule_ptr_t rulep) case rule_action_t::SKIPTO: case rule_action_t::DUMP: case rule_action_t::CHECKSTATE: + case rule_action_t::STATETIMEOUT: break; default: return true; diff --git a/libfwparser/fw_config.h b/libfwparser/fw_config.h index fd711d79..6f6b002f 100644 --- a/libfwparser/fw_config.h +++ b/libfwparser/fw_config.h @@ -170,6 +170,7 @@ enum class rule_action_t SRCPRJID, DSTPRJID, DUMP, + STATETIMEOUT, }; enum class rule_action_modifier_t diff --git a/libfwparser/fw_parser.y b/libfwparser/fw_parser.y index eb977810..f5e68008 100644 --- a/libfwparser/fw_parser.y +++ b/libfwparser/fw_parser.y @@ -131,6 +131,7 @@ SRCPRJID DSTPRJID RED ALL LMAX DSTIP6 SRCIP6 TCPSETMSS NAT64CLAT NAT64LSN NAT64STL NPTV6 SRCADDR QM DSTADDR SRCPORT DSTPORT SRCIP DSTIP EQUAL COMMA MINUS EOL M4LQ M4RQ DUMP + STATETIMEOUT // QUEUE could be an argument to *MASK %precedence QUEUE @@ -505,6 +506,12 @@ action: cfg.set_rule_action(rule_action_t::DUMP); } | + STATETIMEOUT NUMBER + { + cfg.set_rule_action(rule_action_t::STATETIMEOUT); + cfg.set_rule_action_arg($2); + } + | T_REJECT { cfg.set_rule_action(rule_action_t::UNREACH); diff --git a/libfwparser/token.l b/libfwparser/token.l index 0164da45..1cb0c44f 100644 --- a/libfwparser/token.l +++ b/libfwparser/token.l @@ -110,6 +110,7 @@ permit return ipfw::fw_parser_t::make_ALLOW(*ploc); deny_in return ipfw::fw_parser_t::make_DENY_IN(*ploc); deny|drop return ipfw::fw_parser_t::make_DENY(*ploc); dump return ipfw::fw_parser_t::make_DUMP(*ploc); +state-timeout return ipfw::fw_parser_t::make_STATETIMEOUT(*ploc); reject return ipfw::fw_parser_t::make_T_REJECT(*ploc); unreach return ipfw::fw_parser_t::make_UNREACH(*ploc); unreach6 return ipfw::fw_parser_t::make_UNREACH6(*ploc); From 6987acfd95229e8fd8bf3bb9c1cc883dd5eab457 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 13:21:29 +0400 Subject: [PATCH 089/195] Add helper structures for metaprogramming with tuples Adds simple structures to make the folliwing VarinatTraitMap implementation easier --- common/tuple.h | 129 +++++++++++++++++++++++++++++++++ common/unittest/meson.build | 1 + common/unittest/tuple.cpp | 137 ++++++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 common/tuple.h create mode 100644 common/unittest/tuple.cpp diff --git a/common/tuple.h b/common/tuple.h new file mode 100644 index 00000000..68058c1c --- /dev/null +++ b/common/tuple.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include + +namespace utils +{ + +/** + * @brief Helper structure to extract types from a std::variant. + * + * This template specialization will convert a std::variant into a std::tuple. + * + * Example: + * using Variant = std::variant; + * using TupleTypes = VariantTypes::type; // std::tuple + * + * @tparam Variant The std::variant type from which to extract types. + */ +template +struct VariantTypes; + +template +struct VariantTypes> +{ + using type = std::tuple; +}; + +/** + * @brief Helper structure to filter types in a parameter pack according to a trait. + * + * Filters the types in a parameter pack based on whether they satisfy a given trait. + * The result is a std::tuple containing only the types that satisfy the trait. + * + * Example: + * using Filtered = FilteredTuple::type; // std::tuple + * + * @tparam Trait The trait to filter types by. + * @tparam Ts The types to filter. + */ +template class Trait, typename... Ts> +struct FilteredTuple +{ + using type = decltype(std::tuple_cat( + std::conditional_t::value, std::tuple, std::tuple<>>{}...)); +}; + +/** + * @brief Helper structure to filter types in a std::tuple according to a trait. + * + * This specialization allows you to pass a std::tuple of types to FilteredTuple. + * + * Example: + * using MyTuple = std::tuple; + * using Filtered = FilteredTupleFromTuple::type; // std::tuple + * + * @tparam Trait The trait to filter types by. + * @tparam Tuple The std::tuple containing types to filter. + */ +template class Trait, typename... Ts> +struct FilteredTuple> +{ + using type = typename FilteredTuple::type; +}; + +/** + * @brief Helper structure to check if a type is present in a std::tuple. + * + * Example: + * using MyTuple = std::tuple; + * constexpr bool isInTuple = IsInTuple::value; // true + * + * @tparam T The type to check for. + * @tparam Tuple The std::tuple type to check within. + */ +template +struct IsInTuple; + +template +struct IsInTuple> : std::disjunction...> +{}; + +/** + * @brief Helper structure to get the index of a first occurence of a type in a std::tuple. + * + * This structure calculates the zero-based index of type T within a std::tuple. + * If the type is not found, a compile-time error is raised. + * + * Example: + * using MyTuple = std::tuple; + * constexpr std::size_t index = IndexOf::value; // index will be 1 + * + * @tparam T The type to find the index of. + * @tparam Tuple The std::tuple type containing the types. + */ +template +struct IndexOf; + +template +struct IndexOf> +{ +private: + template + struct Helper + { + static constexpr std::size_t value() + { + if constexpr (Index >= sizeof...(Types)) + { + static_assert(Index < sizeof...(Types), "Type T not found in tuple"); + return 0; // This line will never be reached + } + else if constexpr (std::is_same_v>>) + { + return Index; + } + else + { + return Helper::value(); + } + } + }; + +public: + static constexpr std::size_t value = Helper<0>::value(); +}; + +} // namespace utils diff --git a/common/unittest/meson.build b/common/unittest/meson.build index 53458d48..0aa4a95a 100644 --- a/common/unittest/meson.build +++ b/common/unittest/meson.build @@ -9,6 +9,7 @@ common_sources = files() sources = files('unittest.cpp', 'static_vector.cpp', 'shared_memory.cpp', + 'tuple.cpp', ) arch = 'corei7' diff --git a/common/unittest/tuple.cpp b/common/unittest/tuple.cpp new file mode 100644 index 00000000..906d2d3c --- /dev/null +++ b/common/unittest/tuple.cpp @@ -0,0 +1,137 @@ +#include +#include + +#include "common/tuple.h" + +namespace +{ + +using utils::VariantTypes; + +TEST(VariantTypes, BasicExtraction) +{ + using Variant = std::variant; + using ExpectedTuple = std::tuple; + using ExtractedTuple = typename VariantTypes::type; + + static_assert(std::is_same_v, "Extracted tuple doesn't match expected"); +} + +TEST(VariantTypes, EmptyVariant) +{ + using Variant = std::variant<>; + using ExpectedTuple = std::tuple<>; + using ExtractedTuple = typename VariantTypes::type; + + static_assert(std::is_same_v, "Extracted empty tuple doesn't match expected"); +} + +using utils::FilteredTuple; + +TEST(FilteredTuple, FilteredTypes) +{ + using Filtered = typename FilteredTuple::type; + using Expected = std::tuple; + + static_assert(std::is_same_v, "Filtered tuple does not match expected"); + + using InputTuple = std::tuple; + using Filtered = typename FilteredTuple::type; + + static_assert(std::is_same_v, "Filtered tuple does not match expected"); +} + +TEST(FilteredTuple, NoMatch) +{ + using Filtered = typename FilteredTuple::type; + using Expected = std::tuple<>; + + static_assert(std::is_same_v, "Expected empty tuple when no types match"); + + using InputTuple = std::tuple; + using Filtered = typename FilteredTuple::type; + + static_assert(std::is_same_v, "Expected empty tuple when no types match"); +} + +TEST(FilteredTuple, AllMatch) +{ + using Filtered = typename FilteredTuple::type; + using Expected = std::tuple; + + static_assert(std::is_same_v, "Filtered tuple should include all types"); + + using InputTuple = std::tuple; + using Filtered = typename FilteredTuple::type; + + static_assert(std::is_same_v, "Filtered tuple should include all types"); +} + +using utils::IsInTuple; + +TEST(IsInTuple, TypeInTuple) +{ + using MyTuple = std::tuple; + + constexpr bool is_int = IsInTuple::value; + EXPECT_TRUE(is_int); + + constexpr bool is_float = IsInTuple::value; + EXPECT_FALSE(is_float); +} + +TEST(IsInTuple, EmptyTuple) +{ + using EmptyTuple = std::tuple<>; + + constexpr bool is_int = IsInTuple::value; + EXPECT_FALSE(is_int); +} + +using utils::IndexOf; + +TEST(IndexOf, IndexCalculation) +{ + using MyTuple = std::tuple; + + constexpr std::size_t index1 = IndexOf::value; + constexpr std::size_t index2 = IndexOf::value; + constexpr std::size_t index3 = IndexOf::value; + + EXPECT_EQ(index1, 0); + EXPECT_EQ(index2, 1); + EXPECT_EQ(index3, 2); +} + +TEST(IndexOf, MultipleOccurrences) +{ + using MyTuple = std::tuple; + + constexpr std::size_t index1 = IndexOf::value; + constexpr std::size_t index2 = IndexOf::value; + constexpr std::size_t index3 = IndexOf::value; + + EXPECT_EQ(index1, 0); // IndexOf should return the first occurrence of 'int' + EXPECT_EQ(index2, 1); // 'double' appears at index 1 + EXPECT_EQ(index3, 3); // 'char' appears at index 3 +} + +TEST(IndexOf, TypeNotFound) +{ + using MyTuple [[maybe_unused]] = std::tuple; + + // Expect compile-time failure for a type not present in the tuple + // The following line should trigger a compile-time error + // constexpr std::size_t invalidIndex = IndexOf::value; +} + +TEST(IndexOf, EmptyTuple) +{ + using EmptyTuple [[maybe_unused]] = std::tuple<>; + + // Expect a compile-time failure if trying to get index from an empty tuple + // Uncommenting the following line should trigger a compile-time error: + // constexpr std::size_t invalidIndex = IndexOf::value; +} + +} // namespace From 984219638399c503288a15a644f85ac9e8b27783 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 16 Sep 2024 19:23:57 +0400 Subject: [PATCH 090/195] Add VariantTraitMap to track action indices with specific traits Introduce the `VariantTraitMap`, a generic helper that maps types within a `std::variant` to a value (e.g., `std::optional`) based on a given trait. Why this is needed: Some actions, (those with `MAX_COUNT=1`), only need to be executed once or only the first/last occurrence of them matters. For example: - CheckStateAction: Only the first occurrence of this action is meaningful. - StateTimeoutAction: Only the last occurrence of this action should be stored and processed, as it provides the most accurate or latest information. To optimize contolplane, we can store only one of those actions with their index. This way, on "compile" step in value_t we can do something with this information to increase contolplane performance. For example, compeletly ditch the StateTimeoutAction and just add the timeout to the FlowAction as a field. Therefore, to avoid writing boilerplate code like `std::optional check_state_index, state_timeout_index`, we can use VariantTraitMap to directly map Actions with MAX_COUNT=1 to their index. --- common/unittest/meson.build | 1 + common/unittest/variant_trait_map.cpp | 110 +++++++++++++++++++++++ common/variant_trait_map.h | 124 ++++++++++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 common/unittest/variant_trait_map.cpp create mode 100644 common/variant_trait_map.h diff --git a/common/unittest/meson.build b/common/unittest/meson.build index 0aa4a95a..da6ace33 100644 --- a/common/unittest/meson.build +++ b/common/unittest/meson.build @@ -10,6 +10,7 @@ sources = files('unittest.cpp', 'static_vector.cpp', 'shared_memory.cpp', 'tuple.cpp', + 'variant_trait_map.cpp', ) arch = 'corei7' diff --git a/common/unittest/variant_trait_map.cpp b/common/unittest/variant_trait_map.cpp new file mode 100644 index 00000000..0aa76df2 --- /dev/null +++ b/common/unittest/variant_trait_map.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +#include "common/variant_trait_map.h" + +struct A +{}; +struct B +{}; +struct C +{}; +struct D +{}; + +// Trait that holds for A and C +template +struct SomeTrait : std::false_type +{}; + +template<> +struct SomeTrait : std::true_type +{}; + +template<> +struct SomeTrait : std::true_type +{}; + +// Trait that holds for all types +template +struct AllTrait : std::true_type +{}; + +// Trait that holds for no types +template +struct NoTrait : std::false_type +{}; + +using utils::VariantTraitMap; + +TEST(VariantTraitMap, BasicUsage) +{ + using MyVariant = std::variant; + VariantTraitMap map; + + map.get() = 42; + EXPECT_EQ(map.get(), 42); + + map.get() = 100; + EXPECT_EQ(map.get(), 100); + + ++map.get(); + EXPECT_EQ(map.get(), 43); + + map.set(200); + EXPECT_EQ(map.get(), 200); + + MyVariant runtime_variant(A{}); + + std::visit([&map](auto&& actual_variant) { + using T = std::decay_t; + + if constexpr (SomeTrait::value) + { + EXPECT_EQ(map.get(), 43); + } + }, + runtime_variant); + + // The following lines should cause compile-time errors if uncommented + // map.get(); // B does not satisfy SomeTrait + // map.get(); // D is not in MyVariant +} + +TEST(VariantTraitMap, NoTypesTrait) +{ + using MyVariant [[maybe_unused]] = std::variant; + // The following line should cause a compile-time error because no types satisfy the trait + // VariantTraitMap map; +} + +TEST(VariantTraitMap, SingleTypeVariant) +{ + using MyVariant = std::variant; + VariantTraitMap map; + + map.get() = 10; + EXPECT_EQ(map.get(), 10); +} + +TEST(VariantTraitMap, AllTypesTrait) +{ + using MyVariant = std::variant; + VariantTraitMap> map; + + map.get() = 1; + map.get() = -2; + + EXPECT_EQ(map.get().value(), 1); + EXPECT_EQ(map.get().value(), -2); + // will be default constructed + EXPECT_EQ(map.get(), std::nullopt); +} + +TEST(VariantTraitMap, EmptyVariant) +{ + using MyVariant [[maybe_unused]] = std::variant<>; + // The following line should cause a compile-time error because the variant is empty + // VariantTraitMap map; +} diff --git a/common/variant_trait_map.h b/common/variant_trait_map.h new file mode 100644 index 00000000..bf96785e --- /dev/null +++ b/common/variant_trait_map.h @@ -0,0 +1,124 @@ +#pragma once + +#include "tuple.h" + +namespace utils +{ + +/** + * @brief A class that maps types in a variant to a value V, based on a trait. + * + * This class uses a std::tuple to hold values of type V for each type in the + * variant that satisfies the trait. + * + * Example Usage: + * struct A {}; + * struct B {}; + * struct C {}; + * + * template + * struct IsSpecial : std::false_type {}; + * + * template<> + * struct IsSpecial : std::true_type {}; + * + * template<> + * struct IsSpecial : std::true_type {}; + * + * using Variant = std::variant; + * using MyMap = VariantTraitMap>; + * + * MyMap map; + * map.set(42); // Works because A satisfies IsSpecial + * map.set(99); // Works because C satisfies IsSpecial + * auto val = map.get(); // Returns 42 + * auto val = map.get(); // Compile-time error because B does not satisfy IsSpecial + * + * @tparam Variant The std::variant type containing different types. + * @tparam Trait The trait that defines which types are mapped to a value. + * @tparam V The value type to map the types to + */ +template class Trait, typename V> +class VariantTraitMap +{ +private: + using AllTypes = typename VariantTypes::type; + static_assert(std::tuple_size::value > 0, "Variant is empty"); + + using FilteredTypes = typename FilteredTuple::type; + static_assert(std::tuple_size::value > 0, "No types satisfy the trait"); + + template + struct StorageFromTuple; + + template + struct StorageFromTuple> + { + using type = std::tuple; + }; + + using Storage = typename StorageFromTuple::type; + + // Storage is a tuple of V types repeated for each type in FilteredTypes + Storage storage_; + +public: + VariantTraitMap() = default; + + /** + * @brief Retrieves the value associated with a specific type. + * + * This function retrieves the value of type V that is associated with a type T in the variant. + * + * Example: + * map.get() = 42; + * size_t value = map.get(); + * + * @tparam T The type to retrieve the value for. + * @return V& The value of type V associated with type T. + */ + template + V& get() + { + static_assert(IsInTuple::value, "Type T is not in Variant"); + static_assert(Trait::value, "Type T does not satisfy Trait"); + constexpr std::size_t index = IndexOf::value; + return std::get(storage_); + } + + /** + * @brief Retrieves the value associated with a specific type (const version). + * + * This function retrieves the const value of type V that is associated with a type T in the variant. + * + * @tparam T The type to retrieve the value for. + * @return const V& The const value of type V associated with type T. + */ + template + const V& get() const + { + static_assert(IsInTuple::value, "Type T is not in Variant"); + static_assert(Trait::value, "Type T does not satisfy Trait"); + constexpr std::size_t index = IndexOf::value; + return std::get(storage_); + } + + /** + * @brief Sets the value associated with a specific type. + * + * This function sets the value of type V for a specific type T in the variant. + * + * Example: + * map.set(42); + * + * @tparam T The type to set the value for. + * @param val The value of type V to set. + */ + template + void set(const V& val) + { + get() = val; + } +}; + +} // namespace utils From e96c33c785ee9633ca42a4d925620bf032b7b692 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 13:29:42 +0400 Subject: [PATCH 091/195] Add common/utils.h with small utility functions This commit introduces a new common/utils.h file to store small utility functions, as such a file didn't previously exist. It also adds the always_false trait, which is a trait that evaluates to false for any type. This trait is useful for triggering static assertions in order to identify the exact type that caused a compilation error. --- common/utils.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 common/utils.h diff --git a/common/utils.h b/common/utils.h new file mode 100644 index 00000000..d979370f --- /dev/null +++ b/common/utils.h @@ -0,0 +1,14 @@ + +#pragma once + +#include + +namespace utils +{ + +template +struct always_false : std::false_type +{}; + +} +// namespace utils From de1d69129c5db0d94f6aed8ad2ee6f86fef9cd42 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 16 Sep 2024 15:41:22 +0400 Subject: [PATCH 092/195] Introduce generic handling of unique actions indices This commit refactors the way actions with `MAX_COUNT=1` are tracked by using `VariantTraitMap`. The change enables storing the index of the first or last occurrence of specific actions, like `CheckStateAction` or `StateTimeoutAction`, in a more generic way. Previously, actions like `check_state_index` and `state_timeout_index` were handled manually with specific member variables. Now, these actions are handled through a type-safe mechanism based on traits, allowing easy extension for other actions in the future. This improves control plane performance by reducing redundant actions, as only the relevant instances are processed and stored. --- common/actions.h | 175 ++++++++++++++++++++++++++++++++----- common/variant_trait_map.h | 2 + controlplane/acl_value.h | 8 +- 3 files changed, 161 insertions(+), 24 deletions(-) diff --git a/common/actions.h b/common/actions.h index 0c26e09c..e400f1df 100644 --- a/common/actions.h +++ b/common/actions.h @@ -1,11 +1,8 @@ #pragma once -#include -#include - #include "common/type.h" -#include "config.release.h" -#include "stream.h" +#include "common/utils.h" +#include "common/variant_trait_map.h" namespace common { @@ -318,39 +315,175 @@ namespace acl */ struct Actions { + template + struct has_max_count_one + { + static constexpr bool value = (T::MAX_COUNT == 1); + }; + + /** + * Trait to check if we should store the first occurrence + * + * Define first-matters actions here. + */ + template + struct is_first_matters + { + static constexpr bool value = std::is_same_v; + }; + + /** + * Trait to check if we should store the last occurrence + * + * Define last-matters actions here. + */ + template + struct is_last_matters + { + static constexpr bool value = std::is_same_v; + }; + std::vector path{}; std::array> action_counts = {0}; - std::optional check_state_index{}; - std::optional state_timeout_index{}; + // Using VariantTraitMap to store indices of actions with MAX_COUNT=1. + using OptionalIndexMap = utils::VariantTraitMap>; + OptionalIndexMap indices{}; Actions() = default; - Actions(const Action& action) { add(action); }; - + Actions(const Action& action) { add(action); } + + /** + * @brief Adds an action to the current path while adhering to the following: + * + * Either: + * - Only the first occurrence of an action is kept. + * - Only the last occurrence of an action is kept (previous occurrences are removed). + * - Actions are added as long as they don't exceed their defined `MAX_COUNT`. + * + * Adding a new action type is as simple as placing the action type in the corresponding group. + */ void add(const Action& action) { - size_t index = action.raw_action.index(); + size_t variant_index = action.raw_action.index(); + + // Extract the type info at the beginning. + std::visit([&](auto&& actual_action) { + using T = std::decay_t; + + if constexpr (has_max_count_one::value) + { + handle_unique_action(action, variant_index); + } + else if (action_counts[variant_index] < T::MAX_COUNT) + { + add_to_path(action, variant_index); + } + }, + action.raw_action); + } + +private: + // Add the action to the path and increment its count + void add_to_path(const Action& action, size_t variant_index) + { + path.push_back(action); + action_counts[variant_index]++; + } - if (std::holds_alternative(action.raw_action)) + // We're interested in storing only the first or last occurrence + template + void handle_unique_action(const Action& action, size_t variant_index) + { + if constexpr (is_first_matters::value) { - assert(action_counts[index] == 0 && "Incorrectly requested to add more than one FlowAction"); + handle_first_matters_action(action, variant_index); } - else + else if constexpr (is_last_matters::value) + { + handle_last_matters_action(action, variant_index); + } + else if constexpr (std::is_same_v) { - size_t max_count = std::visit([](auto&& arg) { return std::decay_t::MAX_COUNT; }, - action.raw_action); - if (action_counts[index] >= max_count) + /* + * FlowAction should only appear once in the `path`. If a second + * FlowAction is added, this indicates an error in YANET's + * `total_table_t::compile()`. Ideally, this should not happen, + * but if it does, we log an error rather than crashing the application. + * In that case, we will use the last occurrence of FlowAction and proceed. + */ + if (indices.get().has_value()) { - return; + YANET_LOG_ERROR("Multiple FlowAction instances detected in the " + "path. Check total_table_t::compile(). Will use " + "the last occurrence.\n"); } + + handle_last_matters_action(action, variant_index); + } + else + { + static_assert(utils::always_false::value, "Not all unique actions with MAX_COUNT = 1 are properly categorized. " + "Please add the missing actions to either `is_first_matters` or `is_last_matters` " + "to ensure their index is tracked. Tracking the index of such actions could " + "enhance dataplane performance if this information is utilized in " + "`value_t::compile()`."); } + } + + // Only store the first occurrence. + template + void handle_first_matters_action(const Action& action, size_t variant_index) + { + auto& path_index = indices.get(); - if (std::holds_alternative(action.raw_action)) + if (!path_index.has_value()) { - check_state_index = path.size(); + add_to_path(action, variant_index); + path_index = path.size() - 1; } + // Ignore subsequent occurrences as we're only interested in the first. + } - action_counts[index]++; - path.push_back(action); + // Only store the last occurrence. + template + void handle_last_matters_action(const Action& action, size_t variant_index) + { + auto& path_index = indices.get(); + + if (path_index.has_value()) + { + // Remove the previous occurrence + remove_action_at(path_index.value()); + adjust_indices_after_removal(path_index.value()); + } + + // Add the new occurrence + add_to_path(action, variant_index); + path_index = path.size() - 1; + } + + void remove_action_at(std::ptrdiff_t path_index) + { + path.erase(path.begin() + path_index); + } + + // Loop through each type in FilteredTypes and adjust the corresponding index + void adjust_indices_after_removal(std::ptrdiff_t removed_index) + { + std::apply([&](auto&&... types) { + (adjust_index>(removed_index), ...); + }, + OptionalIndexMap::Types{}); + } + + template + void adjust_index(std::ptrdiff_t removed_index) + { + auto& path_index = indices.get(); + if (path_index && *path_index > removed_index) + { + *path_index -= 1; + } } }; diff --git a/common/variant_trait_map.h b/common/variant_trait_map.h index bf96785e..16fee0b4 100644 --- a/common/variant_trait_map.h +++ b/common/variant_trait_map.h @@ -63,6 +63,8 @@ class VariantTraitMap Storage storage_; public: + using Types = FilteredTypes; + VariantTraitMap() = default; /** diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 3cd95039..6265e0ee 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -37,9 +37,11 @@ class value_t // FIXME: I don't like this name.. Why was it called like that previously? std::vector vector; - // FIXME: The initial objects are created using collect_inintial_rule and stored here. - // Then we create copies in vector. I've tried to use shared pointers and/or real pointers, - // but then a bunch of issues arise when serializing a `vector` with stream.push/pop + // FIXME: + // The initial objects are created using collect_inintial_rule and stored here. + // Then we create copies in intermediate_vector. + // I've tried to use shared pointers and/or real pointers, but then a bunch + // of issues arise when serializing a `vector` with stream.push/pop std::vector rule_actions; void append_to_last(unsigned int rule_action_id); From 5184a907e12c27db4c5165aa119f7d2f37b78f8b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 11:33:03 +0400 Subject: [PATCH 093/195] Rename acl::Actions to acl::IntermediateActions This is a representation of a processed action, but not quite ready for use in dataplane yet. Here we build the actions for the packet, and on "compile" step we will shape the final form of a structure, hence Intermediate name --- common/actions.h | 10 +++++----- controlplane/acl_value.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/actions.h b/common/actions.h index e400f1df..0f737d47 100644 --- a/common/actions.h +++ b/common/actions.h @@ -313,7 +313,7 @@ namespace acl * Also, it manages the StateTimeoutActions to reduce number of actions in the dataplane by saving only the * last timeout action. */ -struct Actions +struct IntermediateActions { template struct has_max_count_one @@ -349,8 +349,8 @@ struct Actions using OptionalIndexMap = utils::VariantTraitMap>; OptionalIndexMap indices{}; - Actions() = default; - Actions(const Action& action) { add(action); } + IntermediateActions() = default; + IntermediateActions(const Action& action) { add(action); } /** * @brief Adds an action to the current path while adhering to the following: @@ -501,7 +501,7 @@ class BaseActions public: BaseActions() = default; - BaseActions(acl::Actions&& actions) : + BaseActions(acl::IntermediateActions&& actions) : path_(std::move(actions.path)) {} [[nodiscard]] const Action& get_last() const @@ -559,7 +559,7 @@ class BaseActions public: BaseActions() = default; - BaseActions(acl::Actions&& actions) + BaseActions(acl::IntermediateActions&& actions) { assert(actions.check_state_index.has_value()); auto check_state_index = static_cast(actions.check_state_index.value()); diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 6265e0ee..3cac47ca 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -32,7 +32,7 @@ class value_t public: // FIXME: I don't like this name.. Why was it called like that previously? - std::vector intermediate_vector; + std::vector intermediate_vector; // FIXME: I don't like this name.. Why was it called like that previously? std::vector vector; From 5bd819a6a3092a37ec2734f71ac5172f25627c29 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 14:48:54 +0400 Subject: [PATCH 094/195] Add get and remove methods to IntermediateActions These are helpful methods that will reduce code duplication later --- common/actions.h | 85 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 13 deletions(-) diff --git a/common/actions.h b/common/actions.h index 0f737d47..b37240b9 100644 --- a/common/actions.h +++ b/common/actions.h @@ -382,14 +382,60 @@ struct IntermediateActions action.raw_action); } -private: - // Add the action to the path and increment its count - void add_to_path(const Action& action, size_t variant_index) + /** + * @brief Retrieves a pointer to a unique action of type T from the path. + * + * This method returns a pointer of type T if it exists in the path. + * The action type T must have MAX_COUNT == 1. + * + * @tparam T The action type to retrieve. + * @return Pointer to the action of type T. + */ + template + T* get() { - path.push_back(action); - action_counts[variant_index]++; + static_assert(has_max_count_one::value, "Can get only unique actions from path"); + + return indices.get().has_value() ? &get_action() : nullptr; } + /** + * @brief Retrieves a const reference to a unique action of type T from the path. + * + * This method returns a const pointer to the action of type T + * if it exists in the path. The action type T must have MAX_COUNT == 1. + * + * @tparam T The action type to retrieve. + * @return A const pointer to the action of type T. + */ + template + [[nodiscard]] const T* get() const + { + static_assert(has_max_count_one::value, "Can get only unique actions from path"); + + return indices.get().has_value() ? &get_action() : nullptr; + } + + /** + * @brief Removes a unique action of type T from the path. + * + * This method removes the action of type T from the path if it exists. + * The action type T must have MAX_COUNT == 1. + * + * @tparam T The action type to remove. + */ + template + void remove() + { + static_assert(has_max_count_one::value, "Can remove only unique actions from path"); + + if (auto& path_index = indices.get()) + { + remove_action_at(path_index.value()); + } + } + +private: // We're interested in storing only the first or last occurrence template void handle_unique_action(const Action& action, size_t variant_index) @@ -448,23 +494,36 @@ struct IntermediateActions template void handle_last_matters_action(const Action& action, size_t variant_index) { - auto& path_index = indices.get(); - - if (path_index.has_value()) - { - // Remove the previous occurrence - remove_action_at(path_index.value()); - adjust_indices_after_removal(path_index.value()); - } + // Remove the previous occurrence + remove(); // Add the new occurrence + auto& path_index = indices.get(); + add_to_path(action, variant_index); path_index = path.size() - 1; } + // Add the action to the path and increment its count. + void add_to_path(const Action& action, size_t variant_index) + { + path.push_back(action); + action_counts[variant_index]++; + } + + // Retrieves reference to an action of type T. Action should exist. + template + T& get_action() + { + size_t path_index = indices.get().value(); + return std::get(path[path_index].raw_action); + } + + // Remove action at index and adjust saved indices void remove_action_at(std::ptrdiff_t path_index) { path.erase(path.begin() + path_index); + adjust_indices_after_removal(path_index); } // Loop through each type in FilteredTypes and adjust the corresponding index From cbbf2c99ad01b316e88cceb672c814ee9450dfa4 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 14:53:57 +0400 Subject: [PATCH 095/195] Use new API to get action indices and refactor compile method Refactored the compile method by splitting it into two functions --- common/actions.h | 4 ++-- controlplane/acl_value.cpp | 43 ++++++++++++++++++++++++-------------- controlplane/acl_value.h | 12 +++++++++++ 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/common/actions.h b/common/actions.h index b37240b9..c3c29bc6 100644 --- a/common/actions.h +++ b/common/actions.h @@ -620,8 +620,8 @@ class BaseActions BaseActions() = default; BaseActions(acl::IntermediateActions&& actions) { - assert(actions.check_state_index.has_value()); - auto check_state_index = static_cast(actions.check_state_index.value()); + assert(actions.indices.get().has_value()); + auto check_state_index = actions.indices.get().value(); path_ = std::move(actions.path); diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index 7ecf6085..089dda13 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -1,5 +1,7 @@ #include "acl_value.h" +#include "common/actions.h" + using namespace acl::compiler; value_t::value_t() @@ -32,25 +34,34 @@ void value_t::append_to_last(unsigned int rule_action_id) intermediate_vector.back().add(rule_actions[rule_action_id]); } +void value_t::ensure_termination(IntermediateActions& actions) +{ + auto& last_action = actions.path.back(); + + if (!std::holds_alternative(last_action.raw_action)) + { + // Adding default "drop" rule to the end + actions.add(rule_actions[0]); + } +} + +void value_t::finalize_actions(IntermediateActions&& actions) +{ + if (actions.indices.get().has_value()) + { + vector.emplace_back(common::BaseActions(std::move(actions))); + } + else + { + vector.emplace_back(common::BaseActions(std::move(actions))); + } +} + void value_t::compile() { for (auto& intermediate_actions : intermediate_vector) { - auto last_action = intermediate_actions.path.back(); - - if (!std::visit([](const auto& act) { return act.terminating(); }, last_action.raw_action)) - { - // Adding default "drop" rule to the end - intermediate_actions.add(rule_actions[0]); - } - - if (intermediate_actions.check_state_index.has_value()) - { - vector.emplace_back(common::BaseActions(std::move(intermediate_actions))); - } - else - { - vector.emplace_back(common::BaseActions(std::move(intermediate_actions))); - } + ensure_termination(intermediate_actions); + finalize_actions(std::move(intermediate_actions)); } } diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 3cac47ca..82cd2429 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -7,6 +7,18 @@ namespace acl::compiler class value_t { + using IntermediateActions = common::acl::IntermediateActions; + + /** + * Ensures that the last action in each path is terminating. If not, a default "drop" rule is added. + */ + void ensure_termination(IntermediateActions& actions); + + /** + * Finalizes the intermediate actions into a vector of BaseActions objects. + */ + void finalize_actions(IntermediateActions&& actions); + public: value_t(); From e4e9d56a6aac94b846535ff34b41d43cb248c3be Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 14:56:33 +0400 Subject: [PATCH 096/195] Move StateTimeoutAction timeout directly to FlowAction Remove StateTimeoutAction to improve performance of dataplane, since now it wont have to execute this action. By tracking only the last timeout and adding its value directly to FlowAction we can just fill the required timeout on FlowAction execution --- common/actions.h | 8 +++++++- controlplane/acl_value.cpp | 13 +++++++++++++ controlplane/acl_value.h | 6 ++++++ dataplane/action_dispatcher.h | 3 +-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/common/actions.h b/common/actions.h index c3c29bc6..ff3ed6de 100644 --- a/common/actions.h +++ b/common/actions.h @@ -166,6 +166,8 @@ struct FlowAction final static constexpr size_t MAX_COUNT = 1; // The flow associated with this action. globalBase::tFlow flow; + // Timeout for the state + std::optional timeout; FlowAction(const globalBase::tFlow& flow) : flow(flow){}; @@ -181,17 +183,21 @@ struct FlowAction final void pop(stream_in_t& stream) { stream.pop(flow); + stream.pop(timeout); } void push(stream_out_t& stream) const { stream.push(flow); + stream.push(timeout); } [[nodiscard]] std::string to_string() const { std::ostringstream oss; - oss << "FlowAction(flow=" << flow.to_string() << ")"; + oss << "FlowAction(flow=" << flow.to_string() << ", timeout = " + << (timeout.has_value() ? std::to_string(timeout.value()) : "not specified") + << ")"; return oss.str(); } }; diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index 089dda13..beabebb5 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -45,6 +45,18 @@ void value_t::ensure_termination(IntermediateActions& actions) } } +void value_t::move_timeout_from_state_timeout_to_flow(IntermediateActions& actions) +{ + if (const auto* state_timeout_action = actions.get()) + { + // Flow action should exist at this point + auto* flow_action = actions.get(); + flow_action->timeout = state_timeout_action->timeout; + + actions.remove(); + } +} + void value_t::finalize_actions(IntermediateActions&& actions) { if (actions.indices.get().has_value()) @@ -62,6 +74,7 @@ void value_t::compile() for (auto& intermediate_actions : intermediate_vector) { ensure_termination(intermediate_actions); + move_timeout_from_state_timeout_to_flow(intermediate_actions); finalize_actions(std::move(intermediate_actions)); } } diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 82cd2429..1b152a47 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -14,6 +14,12 @@ class value_t */ void ensure_termination(IntermediateActions& actions); + /** + * Removes the StateTimeoutAction to reduce dataplane load + * by moving the timeout value directly into the FlowAction. + */ + void move_timeout_from_state_timeout_to_flow(IntermediateActions& actions); + /** * Finalizes the intermediate actions into a vector of BaseActions objects. */ diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 04ed9b80..4cf67965 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -89,10 +89,9 @@ struct ActionDispatcher ring.write(args.mbuf, flow.type); } - // FIXME: temporary static void execute(const common::StateTimeoutAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) { - YANET_LOG_DEBUG("Timeout specified is %d\n", action.timeout); + YANET_LOG_DEBUG("Asked to execute StateTimeoutAction, which should not occur. Check value_t::compile()\n"); } static void execute(const common::FlowAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) From dd56221a2e5c3d054f57a3bd4b752c3a8076120c Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 16:43:14 +0400 Subject: [PATCH 097/195] Fill state_timeout only on creation acl_touch_state is used only in acl_create_state and acl_checkstate. The former creates the state, while the latter attempts to match a packet with it. During state creation, we need to fill the `value` with the appropriate timeout, which is initialized to zero by default. However, in acl_checkstate, we still need to "touch" the state, ensuring that the last_seen field is updated with the current time. The issue with the current code is that it unnecessarily fills the state_timeout value every time, even though this value doesn't change once set. It is defined during state creation and later used to check for timeouts, but we don't modify it afterward. Recalculating it each time adds extra complexity/branches to the dataplane without any benefit. This commit removes that behavior. --- dataplane/worker.cpp | 10 ++++++++-- dataplane/worker.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index aa5b09ce..a58ca2ac 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -4876,10 +4876,11 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common key.src_port = 0; } - dataplane::globalBase::fw_state_value_t value; + dataplane::globalBase::fw_state_value_t value{}; value.type = static_cast(metadata->transport_headerType); value.owner = dataplane::globalBase::fw_state_owner_e::internal; acl_touch_state(mbuf, metadata, &value); + acl_fill_state_timeout(mbuf, metadata, &value); value.flow = flow; value.acl_id = aclId; value.last_sync = basePermanently.globalBaseAtomic->currentTime; @@ -4973,10 +4974,11 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common key.src_port = 0; } - dataplane::globalBase::fw_state_value_t value; + dataplane::globalBase::fw_state_value_t value{}; value.type = static_cast(metadata->transport_headerType); value.owner = dataplane::globalBase::fw_state_owner_e::internal; acl_touch_state(mbuf, metadata, &value); + acl_fill_state_timeout(mbuf, metadata, &value); value.flow = flow; value.acl_id = aclId; value.last_sync = basePermanently.globalBaseAtomic->currentTime; @@ -5908,6 +5910,10 @@ YANET_NEVER_INLINE void cWorker::slowWorkerFarmHandleFragment(rte_mbuf* mbuf) inline void cWorker::acl_touch_state(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value) { value->last_seen = basePermanently.globalBaseAtomic->currentTime; +} + +inline void cWorker::acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value) +{ value->state_timeout = get_state_timeout(mbuf, metadata, acl_state_config); } diff --git a/dataplane/worker.h b/dataplane/worker.h index 8595206c..706da2da 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -203,6 +203,7 @@ class cWorker inline void acl_egress_flow(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); inline void acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAclId aclId); inline void acl_touch_state(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value); + inline void acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value); inline void dregress_entry(rte_mbuf* mbuf); From 236a4ac17dcfece1f2192541a63f8bce4d8f1766 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 17 Sep 2024 16:54:49 +0400 Subject: [PATCH 098/195] Use timeout retrieved from StateTimeoutAction for state creation Modifies `acl_create_state` to accept an optional timeout value. If provided, this value is used to set the state's timeout. If not, get timeout as before. --- dataplane/action_dispatcher.h | 2 +- dataplane/worker.cpp | 10 +++++----- dataplane/worker.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 4cf67965..7ac0118d 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -118,7 +118,7 @@ struct ActionDispatcher } if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::recordstate) { - worker->acl_create_state(mbuf, acl_id, action.flow); + worker->acl_create_state(mbuf, acl_id, action.flow, action.timeout); } if constexpr (Direction == FlowDirection::Egress) diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index a58ca2ac..2f2a2875 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -4833,7 +4833,7 @@ inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf, return {flow}; } -inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow) +inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow, std::optional timeout) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); @@ -4880,7 +4880,7 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common value.type = static_cast(metadata->transport_headerType); value.owner = dataplane::globalBase::fw_state_owner_e::internal; acl_touch_state(mbuf, metadata, &value); - acl_fill_state_timeout(mbuf, metadata, &value); + acl_fill_state_timeout(mbuf, metadata, &value, timeout); value.flow = flow; value.acl_id = aclId; value.last_sync = basePermanently.globalBaseAtomic->currentTime; @@ -4978,7 +4978,7 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common value.type = static_cast(metadata->transport_headerType); value.owner = dataplane::globalBase::fw_state_owner_e::internal; acl_touch_state(mbuf, metadata, &value); - acl_fill_state_timeout(mbuf, metadata, &value); + acl_fill_state_timeout(mbuf, metadata, &value, timeout); value.flow = flow; value.acl_id = aclId; value.last_sync = basePermanently.globalBaseAtomic->currentTime; @@ -5912,9 +5912,9 @@ inline void cWorker::acl_touch_state(rte_mbuf* mbuf, dataplane::metadata* metada value->last_seen = basePermanently.globalBaseAtomic->currentTime; } -inline void cWorker::acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value) +inline void cWorker::acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value, std::optional timeout) { - value->state_timeout = get_state_timeout(mbuf, metadata, acl_state_config); + value->state_timeout = timeout.has_value() ? timeout.value() : get_state_timeout(mbuf, metadata, acl_state_config); } inline void cWorker::balancer_touch_state(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::balancer_state_value_t* value) diff --git a/dataplane/worker.h b/dataplane/worker.h index 706da2da..e158641e 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -194,7 +194,7 @@ class cWorker inline FlowFromState acl_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf); inline FlowFromState acl_egress_checkstate(rte_mbuf* mbuf, dataplane::globalBase::fw_state_value_t* value, dataplane::spinlock_nonrecursive_t* locker); - inline void acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow); + inline void acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common::globalBase::tFlow& flow, std::optional timeout); inline void acl_state_emit(tAclId aclId, const dataplane::globalBase::fw_state_sync_frame_t& frame); inline void acl_egress_entry(rte_mbuf* mbuf, tAclId aclId); @@ -203,7 +203,7 @@ class cWorker inline void acl_egress_flow(rte_mbuf* mbuf, const common::globalBase::tFlow& flow); inline void acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAclId aclId); inline void acl_touch_state(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value); - inline void acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value); + inline void acl_fill_state_timeout(rte_mbuf* mbuf, dataplane::metadata* metadata, dataplane::globalBase::fw_state_value_t* value, std::optional timeout); inline void dregress_entry(rte_mbuf* mbuf); From 674f9d86ae3c924406ce83ad8720e9686afcf184 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 16 Sep 2024 12:23:44 +0400 Subject: [PATCH 099/195] Add unittests for state timeout Verify the correct behavior when moving state-timeout timeout to flow action. Checks that only the last state timeout is stored in the flow action. --- controlplane/unittest/acl.cpp | 116 ++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index a02e0bb0..a80b6fd6 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -700,4 +700,120 @@ add allow ip from any to any keep-state } } +TEST(ACL, StateTimeout_Basic) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add state-timeout 5000 ip from any to any +add allow ip from any to any keep-state +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 1); + + for (const auto& [total_table_key, total_table_value] : result.acl_total_table) + { + (void)total_table_key; + + const auto& value = result.acl_values[total_table_value]; + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + const auto& flow_action = std::get(actions.get_actions()[0].raw_action); + EXPECT_EQ(flow_action.timeout, 5000); + + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + +TEST(ACL, StateTimeout_RestrictiveSubset) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add state-timeout 8000 ip from any to any +add state-timeout 3000 ip from 192.168.1.0/24 to any +add allow ip from any to any keep-state +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 2); + + { + // First group, ip not in 192.168.1.0/24 + auto total_table_value = std::get<1>(result.acl_total_table[0]); + const auto& value = result.acl_values[total_table_value]; + + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + const auto& flow_action = std::get(actions.get_actions()[0].raw_action); + EXPECT_EQ(flow_action.timeout, 8000); + + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } + { + // Second group, ip is in 192.168.1.0/24 + auto total_table_value = std::get<1>(result.acl_total_table[1]); + const auto& value = result.acl_values[total_table_value]; + + std::visit([&](const auto& actions) { + if constexpr (std::is_same_v, common::BaseActions>) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + + const auto& flow_action = std::get(actions.get_actions()[0].raw_action); + EXPECT_EQ(flow_action.timeout, 3000); // Verify that the timeout for 192.168.1.0/24 is 3000 + + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }, + value); + } +} + +TEST(ACL, StateTimeout_NoTimeout) +{ + auto fw = make_default_acl(R"IPFW( +:BEGIN +add allow ip from any to any +)IPFW"); + + std::map acls{{"acl0", std::move(fw)}}; + acl::result_t result; + acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + + ASSERT_EQ(result.acl_total_table.size(), 1); + + auto total_table_value = std::get<1>(result.acl_total_table[0]); + const auto& value = result.acl_values[total_table_value]; + + const auto& last_action = std::visit([&](const auto& actions) { return actions.get_last(); }, value); + const auto& flow_action = std::get(last_action.raw_action); + // Check that by default timeout in flow_action is std::nullopt + EXPECT_EQ(flow_action.timeout, std::nullopt); +} + } // namespace From 50b82a196c8d2a3663adf2e942a63e2aaa535643 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 18 Sep 2024 00:42:40 +0400 Subject: [PATCH 100/195] Add autotests for state timeout --- .../077_state_timeout/001-expect.pcap | Bin 0 -> 94 bytes .../077_state_timeout/001-send.pcap | Bin 0 -> 94 bytes .../077_state_timeout/autotest.yaml | 52 ++++++++++++++ .../077_state_timeout/controlplane.conf | 26 +++++++ .../077_state_timeout/firewall.txt | 9 +++ .../001_one_port/077_state_timeout/gen.py | 29 ++++++++ .../001-expect.pcap | Bin 0 -> 164 bytes .../001-send.pcap | Bin 0 -> 164 bytes .../autotest.yaml | 41 +++++++++++ .../controlplane.conf | 26 +++++++ .../firewall.txt | 4 ++ .../077_state_timeout_different_groups/gen.py | 31 ++++++++ .../001-expect-dump-ring1.pcap | Bin 0 -> 82 bytes .../001-expect.pcap | Bin 0 -> 82 bytes .../077_state_timeout_with_dump/001-send.pcap | Bin 0 -> 82 bytes .../002-expect-dump-ring1.pcap | Bin 0 -> 140 bytes .../002-expect.pcap | Bin 0 -> 82 bytes .../077_state_timeout_with_dump/002-send.pcap | Bin 0 -> 82 bytes .../077_state_timeout_with_dump/autotest.yaml | 66 ++++++++++++++++++ .../controlplane.conf | 26 +++++++ .../077_state_timeout_with_dump/firewall.txt | 6 ++ .../077_state_timeout_with_dump/gen.py | 50 +++++++++++++ 22 files changed, 366 insertions(+) create mode 100644 autotest/units/001_one_port/077_state_timeout/001-expect.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout/001-send.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout/autotest.yaml create mode 100644 autotest/units/001_one_port/077_state_timeout/controlplane.conf create mode 100644 autotest/units/001_one_port/077_state_timeout/firewall.txt create mode 100644 autotest/units/001_one_port/077_state_timeout/gen.py create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/001-expect.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/001-send.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/autotest.yaml create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/controlplane.conf create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/firewall.txt create mode 100644 autotest/units/001_one_port/077_state_timeout_different_groups/gen.py create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/001-expect-dump-ring1.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/001-expect.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/001-send.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/002-expect-dump-ring1.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/002-expect.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/002-send.pcap create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/controlplane.conf create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/firewall.txt create mode 100644 autotest/units/001_one_port/077_state_timeout_with_dump/gen.py diff --git a/autotest/units/001_one_port/077_state_timeout/001-expect.pcap b/autotest/units/001_one_port/077_state_timeout/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..fddb8179243bd70fe822430e6217b892626b3132 GIT binary patch literal 94 zcmca|c+)~A1{MYw`2U}Qff2~zyZbUNa6TV{8ITRaKp-e6$RMa>>=Mes;L5_Scm4QJ6q|AXW c?JO4q0}~K48dx#}fE0p20FwfPcQ^wB05=2;#{d8T literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout/autotest.yaml b/autotest/units/001_one_port/077_state_timeout/autotest.yaml new file mode 100644 index 00000000..3c221e95 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout/autotest.yaml @@ -0,0 +1,52 @@ +steps: +- ipv4Update: "0.0.0.0/0 -> 10.0.0.2" + +- clearFWState: 1 # to make sure we have no states +- sleep: 2 # to make sure clearFwState finished + +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- -------------------------------------------------------------------------------------------- + 16777215 16777215 allow tcp from 10.0.0.1 80 to 10.0.0.2 12345 [own, last seen: 2s ago flags S:][packets: 0/0] + +- sleep: 6 # Wait for state to expire + +- cli_check: | + fw list states + id ruleno label rule + -- ------ ----- ---- + +- clearFWState: 1 + +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- -------------------------------------------------------------------------------------------- + 16777215 16777215 allow tcp from 10.0.0.1 80 to 10.0.0.2 12345 [own, last seen: 2s ago flags S:][packets: 0/0] + +- sleep: 3 # Wait but state should still be present + + # note that last seen value changes +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- -------------------------------------------------------------------------------------------- + 16777215 16777215 allow tcp from 10.0.0.1 80 to 10.0.0.2 12345 [own, last seen: 5s ago flags S:][packets: 0/0] + +- sleep: 3 # Wait for state to expire + +- cli_check: | + fw list states + id ruleno label rule + -- ------ ----- ---- diff --git a/autotest/units/001_one_port/077_state_timeout/controlplane.conf b/autotest/units/001_one_port/077_state_timeout/controlplane.conf new file mode 100644 index 00000000..7cbab619 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout/controlplane.conf @@ -0,0 +1,26 @@ +{ + "modules": { + "lp0": { + "type": "logicalPort", + "physicalPort": "kni0", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall.txt", + "nextModules": ["vrf0"] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0": { + "ipv4Prefix": "10.0.0.1/24", + "neighborIPv4Address": "10.0.0.2", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0" + } + } + } + } +} diff --git a/autotest/units/001_one_port/077_state_timeout/firewall.txt b/autotest/units/001_one_port/077_state_timeout/firewall.txt new file mode 100644 index 00000000..a719ec80 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout/firewall.txt @@ -0,0 +1,9 @@ +:BEGIN +add state-timeout 1 ip from any to any +add state-timeout 2 ip from any to any +add state-timeout 3 ip from any to any +add state-timeout 4 ip from any to any +add state-timeout 5 ip from any to any +# only the last occurence matters +add allow ip from any to any keep-state + diff --git a/autotest/units/001_one_port/077_state_timeout/gen.py b/autotest/units/001_one_port/077_state_timeout/gen.py new file mode 100644 index 00000000..1c886159 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout/gen.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from typing import List + +from scapy.layers.inet import IP, TCP +from scapy.layers.l2 import Ether +from scapy.packet import Packet +from scapy.utils import PcapWriter + +def write_pcap(path: str, packets: List[Packet]) -> None: + with PcapWriter(path, sync=True) as fh: + for p in packets: + fh.write(p) + +def ipv4_send(src: str, dst: str) -> Packet: + return Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11") / IP(src=src, dst=dst, ttl=64) + +def ipv4_recv(src: str, dst: str) -> Packet: + return Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55") / IP(src=src, dst=dst, ttl=63) + +# Send packet from 10.0.0.2 to 10.0.0.1 +write_pcap("001-send.pcap", [ + ipv4_send("10.0.0.2", "10.0.0.1") / TCP(sport=12345, dport=80, flags="S"), +]) + +# Expect the packet forwarded +write_pcap("001-expect.pcap", [ + ipv4_recv("10.0.0.2", "10.0.0.1") / TCP(sport=12345, dport=80, flags="S"), +]) diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/001-expect.pcap b/autotest/units/001_one_port/077_state_timeout_different_groups/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..0eeb4fa99dd5a72b0cf6b18c27a4416ba678654d GIT binary patch literal 164 zcmca|c+)~A1{MYw`2U}Qff2}&fATWz#y36&Gaws;fk04DkU>z%*d>&M!IgnQ1EkEJ zZG+5#6^vY5Kurdg3;_^@3=9EG3JjB%K}^Z{PS}+7LI+kbiGWS9LN#U5Yz77ZsV5rb literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/001-send.pcap b/autotest/units/001_one_port/077_state_timeout_different_groups/001-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..6f39337a78c929fb5437d9d6dea816ece2449e48 GIT binary patch literal 164 zcmca|c+)~A1{MYw`2U}Qff2}&fATV|^D`fV8ITRa41!9=E}_Scm4QJ6q|AYB yz083Xj9gqmO$L?>0U(7S5Wu9sFnJlol%y|&O<5;&U 10.0.0.2" + +- clearFWState: 1 # to make sure we have no states +- sleep: 2 # to make sure clearFwState finished + +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------------ + 16777215 16777215 allow tcp from 10.0.0.1 80 to 192.168.1.10 12345 [own, last seen: 2s ago flags S:][packets: 0/0] + 16777216 16777215 allow tcp from 10.0.0.1 80 to 192.168.2.20 12346 [own, last seen: 2s ago flags S:][packets: 0/0] + +- sleep: 3 # Wait, states should still be present + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------------ + 16777215 16777215 allow tcp from 10.0.0.1 80 to 192.168.1.10 12345 [own, last seen: 5s ago flags S:][packets: 0/0] + 16777216 16777215 allow tcp from 10.0.0.1 80 to 192.168.2.20 12346 [own, last seen: 5s ago flags S:][packets: 0/0] + +- sleep: 3 # Wait for first state to expire (total sleep 6s) + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------------ + 16777215 16777215 allow tcp from 10.0.0.1 80 to 192.168.2.20 12346 [own, last seen: 8s ago flags S:][packets: 0/0] + +- sleep: 3 # Wait for second state to expire (total sleep 9s) + +- cli_check: | + fw list states + id ruleno label rule + -- ------ ----- ---- diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/controlplane.conf b/autotest/units/001_one_port/077_state_timeout_different_groups/controlplane.conf new file mode 100644 index 00000000..7cbab619 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_different_groups/controlplane.conf @@ -0,0 +1,26 @@ +{ + "modules": { + "lp0": { + "type": "logicalPort", + "physicalPort": "kni0", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall.txt", + "nextModules": ["vrf0"] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0": { + "ipv4Prefix": "10.0.0.1/24", + "neighborIPv4Address": "10.0.0.2", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0" + } + } + } + } +} diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/firewall.txt b/autotest/units/001_one_port/077_state_timeout_different_groups/firewall.txt new file mode 100644 index 00000000..673febc8 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_different_groups/firewall.txt @@ -0,0 +1,4 @@ +:BEGIN +add state-timeout 5 ip from 192.168.1.0/24 to any +add state-timeout 10 ip from 192.168.2.0/24 to any +add allow ip from any to any keep-state diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/gen.py b/autotest/units/001_one_port/077_state_timeout_different_groups/gen.py new file mode 100644 index 00000000..9b7bc692 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_different_groups/gen.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from typing import List + +from scapy.layers.inet import IP, TCP +from scapy.layers.l2 import Ether +from scapy.packet import Packet +from scapy.utils import PcapWriter + +def write_pcap(path: str, packets: List[Packet]) -> None: + with PcapWriter(path, sync=True) as fh: + for p in packets: + fh.write(p) + +def ipv4_send(src: str, dst: str, ttl: int = 64) -> Packet: + return Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11") / IP(src=src, dst=dst, ttl=ttl) + +def ipv4_recv(src: str, dst: str, ttl: int = 63) -> Packet: + return Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55") / IP(src=src, dst=dst, ttl=ttl) + +# Send packets from two different subnets +write_pcap("001-send.pcap", [ + ipv4_send("192.168.1.10", "10.0.0.1") / TCP(sport=12345, dport=80, flags="S"), + ipv4_send("192.168.2.20", "10.0.0.1") / TCP(sport=12346, dport=80, flags="S"), +]) + +# Expect the same packets forwarded +write_pcap("001-expect.pcap", [ + ipv4_recv("192.168.1.10", "10.0.0.1") / TCP(sport=12345, dport=80, flags="S"), + ipv4_recv("192.168.2.20", "10.0.0.1") / TCP(sport=12346, dport=80, flags="S"), +]) diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/001-expect-dump-ring1.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/001-expect-dump-ring1.pcap new file mode 100644 index 0000000000000000000000000000000000000000..c0cc66151b834804e812921560ba482e54061f2c GIT binary patch literal 82 zcmca|c+)~A1{MYw`2U}Qff2~@d-*c0`xqC47LX0X41!9=E}_Scm4QJ9q|8Au T4XB2J3y2wkW|%T?Jf8;ut}6~B literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/001-expect.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..535358ac7dd18e91616d20a7486b2361c286b2f9 GIT binary patch literal 82 zcmca|c+)~A1{MYw`2U}Qff2~@d-*ag>nIn47LX0XKp-e6$RMa>>=Mes;L5-t15#!$ Vn0}0lfq@H%8G&Y)GH^Vf2LPfr4gmlF literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/001-send.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/001-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..4ea57dfbf578ea434d2e300463e40a2df7e75219 GIT binary patch literal 82 zcmca|c+)~A1{MYw`2U}Qff2~@d-*bL=3y=dEg&0&83dJ#T|z;$pdbf>D+7ZJNST9R U+A%H$1}-3G1e#&W!0~(@0I+}#E&u=k literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/002-expect-dump-ring1.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/002-expect-dump-ring1.pcap new file mode 100644 index 0000000000000000000000000000000000000000..8c9d89d8dc6cf87468a1e37c18224f89d60c0304 GIT binary patch literal 140 zcmca|c+)~A1{MYw`2U}Qff2~@d-*c0?j#q37LX0X41!9=E}_Scm4QJ9q|8Au Z?HCsW0~Zi80?jaG;CMa{r1KeBIsq^o7pedN literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/002-expect.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/002-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..bcd52bf0b48662c06950abbbacf42b93c003e896 GIT binary patch literal 82 zcmca|c+)~A1{MYw`2U}Qff2~@d-*c0?*tcv7LX0XKp-e6$RMa>>=Mes;L5-t15#!$ Vn0}0lfq@H%8G&Y)GH^Vf2LP&V4k!Qs literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/002-send.pcap b/autotest/units/001_one_port/077_state_timeout_with_dump/002-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..bc24465eb8eda1e094838b6667eda2b0a7a1d78f GIT binary patch literal 82 zcmca|c+)~A1{MYw`2U}Qff2~@d-*bL)^RQdEg&0&83dJ#T|z;$pdbf>D+7ZJNST9R U+A%H$1}-3G1e#&W!0~(@0I`Y=GXMYp literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml b/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml new file mode 100644 index 00000000..c86cc4c2 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml @@ -0,0 +1,66 @@ +steps: +- ipv4Update: "0.0.0.0/0 -> 10.0.0.2" + +- clearFWState: 1 # to make sure we have no states +- sleep: 2 # to make sure clearFwState finished + +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap + +- dumpPackets: + - ringTag: shm_2_0 + expect: 001-expect-dump-ring1.pcap + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------- + 16777215 16777215 allow udp from 10.0.0.1 53 to 10.0.0.10 1024 [own, last seen: 2s ago flags :][packets: 0/0] + +- sleep: 3 # Wait, state should still be present + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------- + 16777215 16777215 allow udp from 10.0.0.1 53 to 10.0.0.10 1024 [own, last seen: 5s ago flags :][packets: 0/0] + +- sleep: 3 # Wait for state to expire (total sleep 6s) + +- cli_check: | + fw list states + id ruleno label rule + -- ------ ----- ---- + +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap + +- dumpPackets: + - ringTag: shm_2_0 + expect: 002-expect-dump-ring1.pcap + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------- + 16777215 16777215 allow udp from 10.0.0.1 53 to 10.0.0.10 1024 [own, last seen: 2s ago flags :][packets: 0/0] + +- sleep: 3 # Wait, state should still be present + +- cli_check: | + fw list states + id ruleno label rule + -------- -------- ----- ------------------------------------------------------------------------------------------- + 16777215 16777215 allow udp from 10.0.0.1 53 to 10.0.0.10 1024 [own, last seen: 5s ago flags :][packets: 0/0] + +- sleep: 3 # Wait for state to expire (total sleep 6s) + +- cli_check: | + fw list states + id ruleno label rule + -- ------ ----- ---- + diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/controlplane.conf b/autotest/units/001_one_port/077_state_timeout_with_dump/controlplane.conf new file mode 100644 index 00000000..7cbab619 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_with_dump/controlplane.conf @@ -0,0 +1,26 @@ +{ + "modules": { + "lp0": { + "type": "logicalPort", + "physicalPort": "kni0", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "firewall": "firewall.txt", + "nextModules": ["vrf0"] + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0": { + "ipv4Prefix": "10.0.0.1/24", + "neighborIPv4Address": "10.0.0.2", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0" + } + } + } + } +} diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/firewall.txt b/autotest/units/001_one_port/077_state_timeout_with_dump/firewall.txt new file mode 100644 index 00000000..1bec0169 --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_with_dump/firewall.txt @@ -0,0 +1,6 @@ +:BEGIN +add state-timeout 5 ip from any to any +add check-state +add dump ring1 ip from any to any +add allow udp from 10.0.0.0/24 to any 53 record-state +add deny ip from any to any diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/gen.py b/autotest/units/001_one_port/077_state_timeout_with_dump/gen.py new file mode 100644 index 00000000..83ce705a --- /dev/null +++ b/autotest/units/001_one_port/077_state_timeout_with_dump/gen.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from typing import List + +from scapy.layers.inet import IP, UDP +from scapy.layers.l2 import Ether +from scapy.packet import Packet +from scapy.utils import PcapWriter + +def write_pcap(path: str, packets: List[Packet]) -> None: + with PcapWriter(path, sync=True) as fh: + for p in packets: + fh.write(p) + +def ipv4_send(src: str, dst: str, ttl: int = 64) -> Packet: + return Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11") / IP(src=src, dst=dst, ttl=ttl) + +def ipv4_recv(src: str, dst: str, ttl: int = 63) -> Packet: + return Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55") / IP(src=src, dst=dst, ttl=ttl) + +# Initial packet to create state +write_pcap("001-send.pcap", [ + ipv4_send("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) + +# Expect the packet to be forwarded +write_pcap("001-expect.pcap", [ + ipv4_recv("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) + +# Expected dump (initial packet) +write_pcap("001-expect-dump-ring1.pcap", [ + ipv4_send("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) + +# Packet after state expiration +write_pcap("002-send.pcap", [ + ipv4_send("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) + +# Expect the packet to be forwarded +write_pcap("002-expect.pcap", [ + ipv4_recv("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) + +# Expected dump after state expiration +write_pcap("002-expect-dump-ring1.pcap", [ + ipv4_send("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), #result of a first dump (the ring is the same) + ipv4_send("10.0.0.10", "10.0.0.1") / UDP(sport=1024, dport=53), +]) From cba03ee42523c59ae89925545fc9a2f92e4c50e2 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 18 Sep 2024 14:05:49 +0400 Subject: [PATCH 101/195] Add missing clearFWState to some firewall tests Some tests were missing clearFWState, which resulted in other tests wrong behaviour due to the presence of states from previous runs --- .../autotest.yaml | 1 + .../units/001_one_port/059_firewall_tablearg/autotest.yaml | 3 ++- autotest/units/001_one_port/077_state_timeout/autotest.yaml | 3 --- .../077_state_timeout_different_groups/autotest.yaml | 3 --- .../001_one_port/077_state_timeout_with_dump/autotest.yaml | 3 --- 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml index 426667a9..d2263f5e 100644 --- a/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml +++ b/autotest/units/001_one_port/041_firewall_keepstate_with_sync_multi_state_in_single_packet/autotest.yaml @@ -26,3 +26,4 @@ steps: - port: kni0 send: 002-send.pcap expect: 002-expect.pcap +- clearFWState: 1 diff --git a/autotest/units/001_one_port/059_firewall_tablearg/autotest.yaml b/autotest/units/001_one_port/059_firewall_tablearg/autotest.yaml index 41862999..f1b4ae9d 100644 --- a/autotest/units/001_one_port/059_firewall_tablearg/autotest.yaml +++ b/autotest/units/001_one_port/059_firewall_tablearg/autotest.yaml @@ -1,7 +1,8 @@ steps: - ipv4Update: "0.0.0.0/0 -> 200.0.0.1" -- clearFWState: +- clearFWState: 1 - sendPackets: - port: kni0 send: 001-send.pcap expect: 001-expect.pcap +- clearFWState: 1 diff --git a/autotest/units/001_one_port/077_state_timeout/autotest.yaml b/autotest/units/001_one_port/077_state_timeout/autotest.yaml index 3c221e95..c3b65f85 100644 --- a/autotest/units/001_one_port/077_state_timeout/autotest.yaml +++ b/autotest/units/001_one_port/077_state_timeout/autotest.yaml @@ -1,9 +1,6 @@ steps: - ipv4Update: "0.0.0.0/0 -> 10.0.0.2" -- clearFWState: 1 # to make sure we have no states -- sleep: 2 # to make sure clearFwState finished - - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/077_state_timeout_different_groups/autotest.yaml b/autotest/units/001_one_port/077_state_timeout_different_groups/autotest.yaml index 6f5990cc..5a6d588b 100644 --- a/autotest/units/001_one_port/077_state_timeout_different_groups/autotest.yaml +++ b/autotest/units/001_one_port/077_state_timeout_different_groups/autotest.yaml @@ -1,9 +1,6 @@ steps: - ipv4Update: "0.0.0.0/0 -> 10.0.0.2" -- clearFWState: 1 # to make sure we have no states -- sleep: 2 # to make sure clearFwState finished - - sendPackets: - port: kni0 send: 001-send.pcap diff --git a/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml b/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml index c86cc4c2..267b8761 100644 --- a/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml +++ b/autotest/units/001_one_port/077_state_timeout_with_dump/autotest.yaml @@ -1,9 +1,6 @@ steps: - ipv4Update: "0.0.0.0/0 -> 10.0.0.2" -- clearFWState: 1 # to make sure we have no states -- sleep: 2 # to make sure clearFwState finished - - sendPackets: - port: kni0 send: 001-send.pcap From 1d30f2017fe35844aa02db2c6d39072b889056db Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Thu, 19 Sep 2024 20:06:15 +0300 Subject: [PATCH 102/195] The receipt of counters by route is implemented Commands have also been added to controlplane to get counters for route and route tunnel. --- common/icontrolplane.h | 10 +++ common/icp.h | 25 ++++++ common/idp.h | 1 + controlplane/route.cpp | 175 ++++++++++++++++++++++++++++++++------- controlplane/route.h | 20 ++++- dataplane/globalbase.cpp | 3 +- dataplane/type.h | 1 + dataplane/worker.cpp | 6 ++ 8 files changed, 207 insertions(+), 34 deletions(-) diff --git a/common/icontrolplane.h b/common/icontrolplane.h index b12701d5..c16a182a 100644 --- a/common/icontrolplane.h +++ b/common/icontrolplane.h @@ -177,6 +177,16 @@ class controlPlane return get(request); } + auto route_counters() const + { + return get(); + } + + auto route_tunnel_counters() const + { + return get(); + } + auto route_tunnel_lookup(const common::icp::route_tunnel_lookup::request& request) const { return get(request); diff --git a/common/icp.h b/common/icp.h index 39091d6b..8f377312 100644 --- a/common/icp.h +++ b/common/icp.h @@ -88,6 +88,8 @@ enum class requestType : uint32_t nat46clat_stats, convert, counters_stat, + route_counters, + route_tunnel_counters, size // size should always be at the bottom of the list, this enum allows us to find out the size of the enum list }; @@ -223,6 +225,10 @@ inline const char* requestType_toString(requestType t) return "convert"; case requestType::counters_stat: return "counters_stat"; + case requestType::route_counters: + return "route_counters"; + case requestType::route_tunnel_counters: + return "route_tunnel_counters"; case requestType::size: return "unknown"; } @@ -780,6 +786,23 @@ using request = std::tuple>; ///< size +} + +namespace route_tunnel_counters +{ +using response = std::vector>; ///< size +} + namespace route_tunnel_lookup { using request = std::tuple, acl_unwind::response, acl_lookup::response, route_lookup::response, ///< + route_get::response + route_counters::response, + route_tunnel_counters::response, route_tunnel_lookup::response, ///< + route_tunnel_get::response getRibStats::response, getDefenders::response, diff --git a/common/idp.h b/common/idp.h index 19eca0d8..aac44526 100644 --- a/common/idp.h +++ b/common/idp.h @@ -381,6 +381,7 @@ using request = lpm::request; namespace route_value_update { using interface = std::vector, ///< labels ip_address_t, ///< neighbor_address uint16_t>>; ///< nexthop_flags diff --git a/controlplane/route.cpp b/controlplane/route.cpp index e1cac29d..6b12cbc5 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1,6 +1,23 @@ #include "route.h" #include "controlplane.h" +uint32_t ExtractPeerIdFromPathInformation(const std::string& path_information) +{ + auto pi_it = path_information.find_last_of(':'); + if (pi_it != std::string::npos) + { + try + { + return std::stoll(path_information.substr(pi_it + 1), nullptr, 0); + } + catch (...) + { + YANET_LOG_WARNING("bad peer_id: %s\n", path_information.data()); + } + } + return 0; +} + eResult route_t::init() { { @@ -14,6 +31,8 @@ eResult route_t::init() tunnel_counter.insert({true, 0, ip_address_t(), 0}); ///< fallback v4 tunnel_counter.insert({false, 0, ip_address_t(), 0}); ///< fallback v6 + route_counter.init(&controlPlane->counter_manager); + controlPlane->register_command(common::icp::requestType::route_config, [this]() { return route_config(); }); @@ -30,6 +49,14 @@ eResult route_t::init() return route_get(std::get(std::get<1>(request))); }); + controlPlane->register_command(common::icp::requestType::route_counters, [this]() { + return route_counters(); + }); + + controlPlane->register_command(common::icp::requestType::route_tunnel_counters, [this]() { + return route_tunnel_counters(); + }); + controlPlane->register_command(common::icp::requestType::route_interface, [this]() { return route_interface(); }); @@ -60,8 +87,7 @@ void route_t::prefix_update(const std::tuple& vrf_priorit std::size_t, std::string, uint32_t>, - std::set>>> + route::destination_interface_t> interface_destination_next; for (const auto& [pptn_index, path_info_to_nh_ptr] : *nexthops) { @@ -89,7 +115,7 @@ void route_t::prefix_update(const std::tuple& vrf_priorit for (const auto& [path_info, nh_ptr] : path_info_to_nh_ptr) { - (void)path_info; + uint32_t peer_id = ExtractPeerIdFromPathInformation(path_info); const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = *nh_ptr; (void)communities; @@ -99,7 +125,7 @@ void route_t::prefix_update(const std::tuple& vrf_priorit aspath.size(), origin, med}] - .emplace(nexthop, labels); + .emplace(nexthop, peer_id, prefix, labels); } } @@ -200,7 +226,6 @@ void route_t::tunnel_prefix_update(const std::tuple& vrf_ { if (labels.size() == 1) { - uint32_t peer_id = 0; uint32_t origin_as = 0; uint32_t weight = 0; std::optional override_length; @@ -210,18 +235,7 @@ void route_t::tunnel_prefix_update(const std::tuple& vrf_ origin_as = aspath.back(); } - auto pi_it = path_information.find_last_of(':'); - if (pi_it != std::string::npos) - { - try - { - peer_id = std::stoll(path_information.substr(pi_it + 1), nullptr, 0); - } - catch (...) - { - YANET_LOG_WARNING("bad peer_id: %s\n", path_information.data()); - } - } + uint32_t peer_id = ExtractPeerIdFromPathInformation(path_information); if (peer_id < 10000 || peer_id >= 11000) @@ -386,11 +400,13 @@ void route_t::prefix_flush() generations_neighbors.next_lock(); tunnel_counter.allocate(); + route_counter.allocate(); compile(globalbase, generations.current()); dataplane.updateGlobalBase(globalbase); ///< может вызвать исключение, которое никто не поймает, и это приведёт к abort() tunnel_counter.release(); + route_counter.release(); generations_neighbors.next_unlock(); generations.next_unlock(); @@ -537,6 +553,46 @@ common::icp::route_get::response route_t::route_get(const common::icp::route_get return result; } +common::icp::route_counters::response route_t::route_counters() +{ + common::icp::route_counters::response result; + + auto current_guard = generations.current_lock_guard(); + auto counter_values = route_counter.get_counters(); + + for (const auto& [key, counts] : counter_values) + { + const auto [link_id, nexthop, prefix] = key; + if (counts[0] != 0 || counts[1] != 0) + { + result.emplace_back(link_id, nexthop, prefix, counts[0], counts[1]); + } + } + + return result; +} + +common::icp::route_tunnel_counters::response route_t::route_tunnel_counters() +{ + common::icp::route_tunnel_counters::response result; + + auto current_guard = generations.current_lock_guard(); + auto counter_values = tunnel_counter.get_counters(); + + for (const auto& [key, counts] : counter_values) + { + const auto [is_ipv4, link_id, nexthop, origin_as] = key; + (void)is_ipv4; + (void)origin_as; + if (counts[0] != 0 || counts[1] != 0) + { + result.emplace_back(link_id, nexthop, counts[0], counts[1]); + } + } + + return result; +} + common::icp::route_interface::response route_t::route_interface() const { common::icp::route_interface::response response; @@ -947,6 +1003,7 @@ void route_t::reload(const controlplane::base_t& base_prev, #endif // CONFIG_YADECAP_AUTOTEST tunnel_counter.allocate(); + route_counter.allocate(); compile(globalbase, generations.next()); compile_interface(globalbase, generations.next(), generations_neighbors.next()); @@ -955,6 +1012,7 @@ void route_t::reload(const controlplane::base_t& base_prev, void route_t::reload_after() { tunnel_counter.release(); + route_counter.release(); generations_neighbors.switch_generation(); generations.switch_generation(); generations_neighbors.next_unlock(); @@ -1100,12 +1158,56 @@ void route_t::tunnel_prefix_flush_values(common::idp::updateGlobalBase::request& std::optional route_t::value_insert(const route::value_key_t& value_key) { - return values.update_or_insert(value_key); + if (values.exist_value(value_key)) + { + values.update(value_key); + return values.get_id(value_key); + } + + auto value_id = values.insert(value_key); + if (!value_id) + { + return std::nullopt; + } + + const auto& [vrf_priority, destination, fallback] = value_key; + (void)vrf_priority; + (void)fallback; + + /// counters + if (const auto nexthops = std::get_if(&destination)) + { + for (const auto& [nexthop, peer_id, prefix, labels] : *nexthops) + { + (void)labels; + + route_counter.insert({peer_id, nexthop, prefix}); + } + } + + return value_id; } void route_t::value_remove(const uint32_t& value_id) { - values.remove_id(value_id); + auto value_key = values.remove_id(value_id); + if (value_key) + { + const auto& [vrf_priority, destination, fallback] = *value_key; + (void)vrf_priority; + (void)fallback; + + /// counters + if (const auto nexthops = std::get_if(&destination)) + { + for (const auto& [nexthop, peer_id, prefix, labels] : *nexthops) + { + (void)labels; + + route_counter.remove({peer_id, nexthop, prefix}, 20); + } + } + } } void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, @@ -1144,13 +1246,15 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, interface_id, interface_name, std::vector(), - ipv4_address_t()); ///< default + ipv4_address_t(), ///< default + 0, + fallback); } else { for (const auto& destination_iter : std::get<0>(destination)) ///< interface { - const auto& [nexthop, labels] = destination_iter; + const auto& [nexthop, peer_id, prefix, labels] = destination_iter; if (nexthop.is_default()) { @@ -1185,7 +1289,9 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, interface_id, interface_name, labels, - nexthop); + nexthop, + peer_id, + prefix); continue; } @@ -1281,17 +1387,19 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, /// same numa for (const auto& item : request_interface) { - const auto& [nexthop, egress_interface_id, egress_interface_name, labels, neighbor_address] = item; + const auto& [nexthop, egress_interface_id, egress_interface_name, labels, neighbor_address, peer, prefix] = item; if (exist(interfaces, egress_interface_id)) { + const auto counter_id = route_counter.get_id({peer, nexthop, prefix}); + uint16_t flags = 0; if (neighbor_address.is_default()) { flags |= YANET_NEXTHOP_FLAG_DIRECTLY; } - update_interface.emplace_back(egress_interface_id, labels, neighbor_address, flags); + update_interface.emplace_back(egress_interface_id, counter_id, labels, neighbor_address, flags); value_lookup[value_id][socket_id].emplace_back(nexthop, egress_interface_name, @@ -1304,7 +1412,9 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, { for (const auto& item : request_interface) { - const auto& [nexthop, egress_interface_id, egress_interface_name, labels, neighbor_address] = item; + const auto& [nexthop, egress_interface_id, egress_interface_name, labels, neighbor_address, peer, prefix] = item; + + const auto counter_id = route_counter.get_id({peer, nexthop, prefix}); uint16_t flags = 0; if (neighbor_address.is_default()) @@ -1312,7 +1422,7 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, flags |= YANET_NEXTHOP_FLAG_DIRECTLY; } - update_interface.emplace_back(egress_interface_id, labels, neighbor_address, flags); + update_interface.emplace_back(egress_interface_id, counter_id, labels, neighbor_address, flags); value_lookup[value_id][socket_id].emplace_back(nexthop, egress_interface_name, @@ -1349,7 +1459,7 @@ void route_t::value_compile_label(common::idp::updateGlobalBase::request& global for (const auto& destination_iter : std::get<0>(destination)) ///< interface { - auto [nexthop, labels] = destination_iter; + auto [nexthop, peer_id, prefix, labels] = destination_iter; if (labels.size() != 1) { @@ -1371,7 +1481,9 @@ void route_t::value_compile_label(common::idp::updateGlobalBase::request& global interface_id, interface_name, labels, - nexthop); + nexthop, + peer_id, + prefix); } else { @@ -1400,7 +1512,7 @@ void route_t::value_compile_fallback(common::idp::updateGlobalBase::request& glo for (const auto& destination_iter : std::get<0>(destination)) ///< interface { - const auto& [nexthop, labels] = destination_iter; + const auto& [nexthop, peer_id, prefix, labels] = destination_iter; auto interface = generation.get_interface_by_neighbor(nexthop); if (interface) @@ -1418,7 +1530,9 @@ void route_t::value_compile_fallback(common::idp::updateGlobalBase::request& glo interface_id, interface_name, labels, - nexthop); + nexthop, + peer_id, + prefix); } } } @@ -1820,6 +1934,7 @@ void route_t::tunnel_gc_thread() while (!flagStop) { tunnel_counter.gc(); + route_counter.gc(); std::this_thread::sleep_for(std::chrono::seconds(3)); } } diff --git a/controlplane/route.h b/controlplane/route.h index 88f7025d..87a87253 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -18,8 +18,14 @@ namespace route using directly_connected_destination_t = std::tuple; ///< interface_name -using destination_t = std::variant>>, +using destination_interface_t = std::set< + std::tuple< + ip_address_t, ///< nexthop + uint32_t, ///< peer_id + ip_prefix_t, ///< prefix + std::vector>>; ///< labels + +using destination_t = std::variant; ///< virtual_port_id @@ -32,11 +38,16 @@ using value_interface_t = std::tuple, - ip_address_t>; ///< neighbor_address + ip_address_t, ///< neighbor_address + uint32_t, ///< peer_id + ip_prefix_t>; ///< prefix using lookup_t = std::tuple>; ///< labels +using route_counter_key_t = std::tuple; ///< prefix using tunnel_destination_interface_t = std::set< std::tuple< @@ -218,6 +229,8 @@ class route_t : public module_t common::icp::route_summary::response route_summary() const; common::icp::route_lookup::response route_lookup(const common::icp::route_lookup::request& request); common::icp::route_get::response route_get(const common::icp::route_get::request& request); + common::icp::route_counters::response route_counters(); + common::icp::route_tunnel_counters::response route_tunnel_counters(); common::icp::route_interface::response route_interface() const; common::icp::route_tunnel_lookup::response route_tunnel_lookup(const common::icp::route_tunnel_lookup::request& request); common::icp::route_tunnel_get::response route_tunnel_get(const common::icp::route_tunnel_get::request& request); @@ -297,4 +310,5 @@ class route_t : public module_t friend class telegraf_t; counter_t tunnel_counter; + counter_t route_counter; }; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 3c5be433..3bb61b86 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -1824,7 +1824,7 @@ eResult generation::route_value_update(const common::idp::updateGlobalBase::rout ecmp_i < request_interface.size(); ecmp_i++) { - const auto& [interface_id, labels, neighbor_address, nexthop_flags] = request_interface[ecmp_i]; + const auto& [interface_id, counter_id, labels, neighbor_address, nexthop_flags] = request_interface[ecmp_i]; if (interface_id >= CONFIG_YADECAP_INTERFACES_SIZE) { @@ -1834,6 +1834,7 @@ eResult generation::route_value_update(const common::idp::updateGlobalBase::rout route_value.interface.nexthops[ecmp_i].interfaceId = interface_id; route_value.interface.nexthops[ecmp_i].flags = nexthop_flags; + route_value.interface.nexthops[ecmp_i].counter_id = counter_id; route_value.interface.nexthops[ecmp_i].neighbor_address = ipv6_address_t::convert(neighbor_address); route_value.interface.nexthops[ecmp_i].is_ipv6 = neighbor_address.is_ipv6(); diff --git a/dataplane/type.h b/dataplane/type.h index 4ce58a3f..b82ffa82 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -383,6 +383,7 @@ struct nexthop ///< @todo { tInterfaceId interfaceId : 16; uint16_t flags; + tCounterId counter_id; ipv6_address_t neighbor_address; uint32_t labelExpTransport; ///< @todo: rename first uint32_t labelExpService; ///< @todo: rename second diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 2f2a2875..848df723 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -2203,6 +2203,9 @@ inline void cWorker::route_handle4() continue; } + counters[nexthop.counter_id]++; + counters[nexthop.counter_id + 1] += mbuf->pkt_len; + route_nexthop(mbuf, nexthop); ipv4Header->time_to_live--; @@ -2324,6 +2327,9 @@ inline void cWorker::route_handle6() continue; } + counters[nexthop.counter_id]++; + counters[nexthop.counter_id + 1] += mbuf->pkt_len; + route_nexthop(mbuf, nexthop); ipv6Header->hop_limits--; From 7dd65ce2794db6e0f78478c8ca21392a74587330 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Thu, 19 Sep 2024 20:09:51 +0300 Subject: [PATCH 103/195] 4 new commands have been added to cli to get counters by route, route tunnel Added commands: - route counters - route tunnel counters - telegraf route - telegraf route tunnel --- cli/main.cpp | 4 ++++ cli/route.h | 38 ++++++++++++++++++++++++++++++++++++++ cli/telegraf.h | 21 +++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/cli/main.cpp b/cli/main.cpp index fc54b443..0cd2acb3 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -78,6 +78,8 @@ std::vector Date: Tue, 17 Sep 2024 18:40:55 +0300 Subject: [PATCH 104/195] Added autotests that check the work of new commands in the cli --- .../075_counters_route/autotest.yaml | 85 +++++++++++ .../075_counters_route/controlplane.conf | 64 +++++++++ .../075_counters_route/expect.pcap | Bin 0 -> 566 bytes .../001_one_port/075_counters_route/gen.py | 42 ++++++ .../001_one_port/075_counters_route/send.pcap | Bin 0 -> 542 bytes .../075_counters_route_tunnel/001-expect.pcap | Bin 0 -> 1528 bytes .../075_counters_route_tunnel/001-send.pcap | Bin 0 -> 1656 bytes .../075_counters_route_tunnel/002-expect.pcap | Bin 0 -> 1528 bytes .../075_counters_route_tunnel/002-send.pcap | Bin 0 -> 1656 bytes .../075_counters_route_tunnel/autotest.yaml | 133 ++++++++++++++++++ .../controlplane.conf | 69 +++++++++ .../075_counters_route_tunnel/gen.py | 97 +++++++++++++ 12 files changed, 490 insertions(+) create mode 100644 autotest/units/001_one_port/075_counters_route/autotest.yaml create mode 100644 autotest/units/001_one_port/075_counters_route/controlplane.conf create mode 100644 autotest/units/001_one_port/075_counters_route/expect.pcap create mode 100644 autotest/units/001_one_port/075_counters_route/gen.py create mode 100644 autotest/units/001_one_port/075_counters_route/send.pcap create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/001-expect.pcap create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/001-send.pcap create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/002-expect.pcap create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/002-send.pcap create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/autotest.yaml create mode 100644 autotest/units/001_one_port/075_counters_route_tunnel/controlplane.conf create mode 100755 autotest/units/001_one_port/075_counters_route_tunnel/gen.py diff --git a/autotest/units/001_one_port/075_counters_route/autotest.yaml b/autotest/units/001_one_port/075_counters_route/autotest.yaml new file mode 100644 index 00000000..332abc61 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_route/autotest.yaml @@ -0,0 +1,85 @@ +steps: + +# default (see neighbor in controlplane.conf) +- cli: | + rib static insert default 0.0.0.0/0 200.0.2.1 + +################################################################################################################# +# 1 prepare rib +################################################################################################################# +- rib_insert: + attribute: + protocol: autotest + tables: + - table_name: ipv4 mpls-vpn + peer: 10.10.10.1 + med: 0 + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 200.0.3.1 + prefix: 1.0.0.0/24 + path_information: 200.0.2.1:10001 + labels: + - 1100 + - table_name: ipv4 mpls-vpn + peer: 10.10.10.2 + med: 0 + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 200.0.4.1 + prefix: 2.0.0.0/24 + path_information: 200.0.3.1:10002 + labels: + - 1100 + - table_name: ipv4 mpls-vpn + peer: 10.10.10.2 + med: 0 + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 200.0.5.1 + prefix: 3.0.0.0/24 + path_information: 200.0.3.1:10003 + labels: + - 1100 + +- cli_check: | + rib + vrf priority protocol peer table_name prefixes paths eor + ------- -------- -------- ---------- ------------- -------- ----- ----- + default 10000 autotest 10.10.10.1 ipv4 mpls-vpn 1 1 false + default 10000 autotest 10.10.10.2 ipv4 mpls-vpn 2 2 false + default 10000 static :: 2 2 true + +- cli_check: | + rib prefixes + vrf priority prefix protocol peer table_name path_information nexthop labels local_preference aspath origin med communities large_communities + ------- -------- ---------- -------- ---------- ------------- ---------------- --------- ------ ---------------- ------ ---------- --- ----------- ----------------- + default 10000 0.0.0.0/0 static :: 200.0.2.1 200.0.2.1 0 0 n/s n/s + default 10000 1.0.0.0/24 autotest 10.10.10.1 ipv4 mpls-vpn 200.0.2.1:10001 200.0.3.1 1100 0 incomplete 0 n/s 13238:1:1 + default 10000 2.0.0.0/24 autotest 10.10.10.2 ipv4 mpls-vpn 200.0.3.1:10002 200.0.4.1 1100 0 incomplete 0 n/s 13238:1:1 + default 10000 3.0.0.0/24 autotest 10.10.10.2 ipv4 mpls-vpn 200.0.3.1:10003 200.0.5.1 1100 0 incomplete 0 n/s 13238:1:1 + default 10000 fe80::/64 static :: :: 0 0 n/s n/s + +- cli_check: | + route tunnel get route0 1.0.0.0/24 + ingress_physical_ports nexthop label egress_interface peer weight (%) + ---------------------- --------- ----- ---------------- ---- ---------- + kni0 200.0.3.1 1100 kni0.200 100.00 + +################################################################################################################# +# 2 send packets and check route counters +################################################################################################################# + +- sendPackets: + - port: kni0 + send: send.pcap + expect: expect.pcap + +- cli: + - route counters + +- cli: + - telegraf route diff --git a/autotest/units/001_one_port/075_counters_route/controlplane.conf b/autotest/units/001_one_port/075_counters_route/controlplane.conf new file mode 100644 index 00000000..2808ddc2 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_route/controlplane.conf @@ -0,0 +1,64 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "lp0.400": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "400", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "route0": { + "type": "route", + "interfaces": { + "kni0.100": { + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.2.0/24", + "neighborIPv4Address": "200.0.2.1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.200" + }, + "kni0.300": { + "ipv4Prefix": "200.0.2.0/24", + "neighborIPv4Address": "200.0.3.1", + "neighborMacAddress": "00:00:00:11:11:22", + "nextModule": "lp0.300" + }, + "kni0.400": { + "ipv4Prefix": "200.0.3.0/24", + "neighborIPv4Address": "200.0.4.1", + "neighborMacAddress": "00:00:00:11:11:33", + "nextModule": "lp0.400" + }, + "kni0.500": { + "ipv4Prefix": "200.0.3.0/24", + "neighborIPv4Address": "200.0.5.1", + "neighborMacAddress": "00:00:00:11:11:55", + "nextModule": "lp0.400" + } + } + } + } +} diff --git a/autotest/units/001_one_port/075_counters_route/expect.pcap b/autotest/units/001_one_port/075_counters_route/expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..65c6e28e979309967d0bd2ac26fc1d2c7cdb7525 GIT binary patch literal 566 zcmca|c+)~A1{MYw`2U}Qff2?5(sob`qyz<(7zCA!T|yff7I7|!0?Y5b`Ak&x`7}(HFTeAmYniY@ dCH#t5-WyDdr32C1~14YW(Ec}bd%QXA0%29 kU2Nf`i!EGqv4xv1w(!u!7GAp8!bcZd_~~Mc0HwA70DZNtNB{r; literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/075_counters_route_tunnel/autotest.yaml b/autotest/units/001_one_port/075_counters_route_tunnel/autotest.yaml new file mode 100644 index 00000000..db8f93ac --- /dev/null +++ b/autotest/units/001_one_port/075_counters_route_tunnel/autotest.yaml @@ -0,0 +1,133 @@ +steps: +- rib_insert: + attribute: + protocol: autotest + tables: + - table_name: ipv4 mpls-vpn + peer: 0.0.0.0 + med: 0 + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 88.88.88.1 + prefix: 1.0.0.0/24 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 1.0.0.0/24 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - table_name: ipv4 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 88.88.88.1 + prefix: 1.0.0.254/32 + path_information: 88.88.88.1:11000 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 1.0.0.254/32 + path_information: 88.88.88.2:11001 + labels: + - 1200 + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 8888::1 + prefix: 7e57::/64 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e57::/64 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - nexthop: 8888::1 + prefix: 7e57::fffe/128 + path_information: 88.88.88.1:9999 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e57::fffe/128 + path_information: 88.88.88.2:15000 + labels: + - 1200 + - table_name: ipv4 mpls-vpn + peer: 0.0.0.0 + med: 0 + large_communities: + - 13238:1:0 + prefixes: + - nexthop: 88.88.88.1 + prefix: 1.0.0.253/32 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 1.0.0.253/32 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - table_name: ipv4 mpls-vpn + peer: 0.0.0.0 + med: 0 + prefixes: + - nexthop: 88.88.88.1 + prefix: 1.0.0.252/32 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 1.0.0.252/32 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:0 + prefixes: + - nexthop: 8888::1 + prefix: 7e57::fffd/128 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e57::fffd/128 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - table_name: ipv6 mpls-vpn + prefixes: + - nexthop: 8888::1 + prefix: 7e57::fffc/128 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e57::fffc/128 + path_information: 88.88.88.2:10001 + labels: + - 1200 +- ipv4Update: + - "0.0.0.0/0 -> 100.0.0.1 200.0.0.1" +- ipv6Update: + - "::/0 -> c0de::100:1 c0de::200:1" +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap + +- cli: + - route tunnel counters + +- cli: + - telegraf route tunnel diff --git a/autotest/units/001_one_port/075_counters_route_tunnel/controlplane.conf b/autotest/units/001_one_port/075_counters_route_tunnel/controlplane.conf new file mode 100644 index 00000000..224078a3 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_route_tunnel/controlplane.conf @@ -0,0 +1,69 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "nextModules": [ + "decap0", + "decap1" + ] + }, + "decap0": { + "type": "decap", + "ipv6DestinationPrefixes": [ + "2222::aaaa/128" + ], + "nextModule": "route0" + }, + "decap1": { + "type": "decap", + "ipv6DestinationPrefixes": [ + "2222::cccc/128" + ], + "ipv6_enabled": true, + "nextModule": "route0:tunnel" + }, + "route0": { + "type": "route", + "ipv4SourceAddress": "10.50.0.1", + "ipv6SourceAddress": "2222:1111:0:1234:5678:0101:ca11:ca11", + "udpDestinationPort": 6635, + "interfaces": { + "kni0.100": { + "neighborIPv4Address": "100.0.0.1", + "neighborIPv6Address": "c0de::100:1", + "neighborMacAddress": "00:00:00:00:00:01", + "nextModule": "lp0.100" + }, + "kni0.200": { + "neighborIPv4Address": "200.0.0.1", + "neighborIPv6Address": "c0de::200:1", + "neighborMacAddress": "00:00:00:00:00:02", + "nextModule": "lp0.200" + } + }, + "localPrefixes": [ + "1.0.0.255/32", + "7e57::ffff/128" + ], + "peers": { + "1": "A", + "2": "B", + "3": "C" + } + } + } +} diff --git a/autotest/units/001_one_port/075_counters_route_tunnel/gen.py b/autotest/units/001_one_port/075_counters_route_tunnel/gen.py new file mode 100755 index 00000000..0629de99 --- /dev/null +++ b/autotest/units/001_one_port/075_counters_route_tunnel/gen.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from scapy.all import * +from scapy.contrib.mpls import MPLS + + +def write_pcap(filename, *packetsList): + if len(packetsList) == 0: + PcapWriter(filename)._write_header(Ether()) + return + + PcapWriter(filename) + + for packets in packetsList: + if type(packets) == list: + for packet in packets: + packet.time = 0 + wrpcap(filename, [p for p in packet], append=True) + else: + packets.time = 0 + wrpcap(filename, [p for p in packets], append=True) + + +write_pcap("001-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::2", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::3", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::4", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::5", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::6", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::7", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::8", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::9", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::10", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::11", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::12", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::13", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::14", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::15", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::16", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP()) + +write_pcap("001-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP()) + +write_pcap("002-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=2)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=3)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=4)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=5)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=6)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=7)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=8)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=9)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=10)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=11)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=12)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=13)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=14)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=15)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1", fl=16)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP()) + +write_pcap("002-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x89ed | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x2355 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x9b9f | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x3127 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0xb81e | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x12a6 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0xc98a | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x6332 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0xea0b | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.2", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x40b3 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0xf879 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x52c1 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0xdbf8 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x7140 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="88.88.88.1", src="10.50.0.1", ttl=64)/UDP(dport=6635, sport=0x1b51 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP()) + + From 889ad19160ac68d3605eaad722ca7ac15cd6729b Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Thu, 19 Sep 2024 20:13:50 +0300 Subject: [PATCH 105/195] Comments have been added to the definition of rib types, the unused type removed --- common/type.h | 2 +- controlplane/rib.h | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/common/type.h b/common/type.h index bc7e4e74..71cb910b 100644 --- a/common/type.h +++ b/common/type.h @@ -2845,7 +2845,7 @@ using nexthop_stuff_t = std::tuple; -using nexthop_map_t = std::unordered_map protocol, peer, table_name std::unordered_map>; diff --git a/controlplane/rib.h b/controlplane/rib.h index c436dc3b..b2147c3c 100644 --- a/controlplane/rib.h +++ b/controlplane/rib.h @@ -21,8 +21,6 @@ namespace rib { -using nexthop_t = common::rib::nexthop_t; - using vrf_priority_t = common::rib::vrf_priority_t; using pptn_t = common::rib::pptn_t; @@ -92,8 +90,8 @@ class rib_t : public cModule std::string, ///< protocol ip_address_t, ///< peer std::string>, ///< table_name - std::tuple> + std::tuple> ///< eor summary; }; From 69023ce448ba822c5d0b365092614e5df5aec53d Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 1 Aug 2024 12:49:33 +0300 Subject: [PATCH 106/195] Refactor acl::rule_t hash function using std::visit for clarity Simplifyes handling of different data types in acl::rule_t actions. This way we can see possible variants more cleanly --- controlplane/acl/rule.h | 65 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 598dd77e..40406012 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1369,40 +1369,47 @@ struct hash size_t operator()(const acl::rule_t& r) const noexcept { size_t h = 0; - if (std::holds_alternative(r.action)) - { - const auto& act = std::get(r.action); - hash_combine(h, act); - } - else if (std::holds_alternative(r.action)) - { - auto flow = std::get(r.action); - hash_combine(h, 1, (uint64_t(flow.type) << 32) & flow.data.atomic); - } - else if (std::holds_alternative(r.action)) - { - // Since check_state_t acts as a marker (either present or not), - // it doesn't have specific members to hash. - // To uniquely identify its presence in the hash, we use a - // predefined static constant as a unique identifier. - hash_combine(h, common::acl::check_state_t::HASH_IDENTIFIER); - } - else if (std::holds_alternative(r.action)) - { - auto action = std::get(r.action); - hash_combine(h, action.timeout); - } - else - { - auto action = std::get(r.action); - hash_combine(h, action.dump_id); - } + // value to hash based on the type of action + size_t action_value = 0; + + std::visit([&action_value](const auto& action) { + using T = std::decay_t; + + if constexpr (std::is_same_v) + { + action_value = action; + } + else if constexpr (std::is_same_v) + { + uint64_t high_part = static_cast(action.type) << 32; + uint64_t low_part = static_cast(action.data.atomic); + action_value = high_part | low_part; + } + else if constexpr (std::is_same_v) + { + // Since check_state_t acts as a marker (either present or not), + // it doesn't have specific members to hash. + // To uniquely identify its presence in the hash, we use a + // predefined static constant as a unique identifier. + action_value = common::acl::check_state_t::HASH_IDENTIFIER; + } + else if constexpr (std::is_same_v) + { + action_value = action.dump_id; + } + else if constexpr (std::is_same_v) + { + action_value = action.timeout; + } + }, + r.action); if (r.filter) { hash_combine(h, **r.filter); } - hash_combine(h, r.log); + + hash_combine(h, action_value, r.log); return h; } From f47e37de09eae287aec0e9500dfbe2bf659f01aa Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 1 Aug 2024 17:40:59 +0300 Subject: [PATCH 107/195] Update static_assert in collect_initial_rule for clarity Simplified the static_assert to exclude int64_t directly --- controlplane/acl_value.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 1b152a47..2e1a90f4 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -34,11 +34,8 @@ class value_t template unsigned int collect_initial_rule(T&& rule) { - static_assert(std::is_same_v, common::globalBase::tFlow> || - std::is_same_v, common::acl::dump_t> || - std::is_same_v, common::acl::check_state_t> || - std::is_same_v, common::acl::state_timeout_t>, - "Unsupported type in rule_action"); + static_assert(!std::is_same_v, int64_t>, + "int64_t should not be a type of action in unwinded rule"); rule_actions.emplace_back(std::forward(rule)); return rule_actions.size() - 1; From 8bb495893c72ac52d32c707ee85ffffa271ded71 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 1 Aug 2024 17:47:26 +0300 Subject: [PATCH 108/195] Refactor rule handling in acl.cpp using std::visit Replaced multiple if-else cases with a std::visit and generic lambda in the ACL rule processing logic. Makes future modifications easier and ensures that we processed all possible variant types --- controlplane/acl.cpp | 69 +++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 0ceef7a5..2f02f414 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -464,56 +464,33 @@ static bool unwind(int64_t start_from, firewall_rules_t& fw, const dispatcher_ru ids.insert(ids.end(), rule.ids.begin(), rule.ids.end()); ACL_DBGMSG("advancing further..."); - if (std::holds_alternative(rule.action)) - { - // handle skipto && allow action - start_from = std::get(rule.action); - if (start_from != DISPATCHER) + std::visit([&](const auto& action) { + using T = std::decay_t; + + if constexpr (std::is_same_v) { - ACL_DBGMSG("skipto " << start_from); - term_rule = unwind(start_from, fw, dispatcher, result_filter, iface, ids, rules, log || rule.log, recursion_limit + 1); - // if we have reached DISPATCHER, it will be handled next + // handle skipto && allow action + start_from = action; + if (start_from != DISPATCHER) + { + ACL_DBGMSG("skipto " << start_from); + term_rule = unwind(start_from, fw, dispatcher, result_filter, iface, ids, rules, log || rule.log, recursion_limit + 1); + // if we have reached DISPATCHER, it will be handled next + } + if (start_from == DISPATCHER) + { + ACL_DBGMSG("go to dispatcher..."); + term_rule = unwind_dispatcher(dispatcher, result_filter, iface, ids, rules, log || rule.log); + } } - - if (start_from == DISPATCHER) + else { - ACL_DBGMSG("go to dispatcher..."); - term_rule = unwind_dispatcher(dispatcher, result_filter, iface, ids, rules, log || rule.log); + // Handle other types by emplacing them directly into rules + rules.emplace_back(std::move(result_filter), action, ids, log || rule.log); + ACL_DBGMSG(typeid(T).name() << " gathered..."); } - } - else if (std::holds_alternative(rule.action)) - { - // handle tFlows - rules.emplace_back(std::move(result_filter), - std::get(rule.action), - ids, - log || rule.log); - ACL_DBGMSG("tFlow gathered..."); - } - else if (std::holds_alternative(rule.action)) - { - rules.emplace_back(std::move(result_filter), - std::get(rule.action), - ids, - log || rule.log); - ACL_DBGMSG("check_state gathered..."); - } - else if (std::holds_alternative(rule.action)) - { - rules.emplace_back(std::move(result_filter), - std::get(rule.action), - ids, - log || rule.log); - ACL_DBGMSG("state_timeout gathered..."); - } - else - { - rules.emplace_back(std::move(result_filter), - std::get(rule.action), - ids, - log || rule.log); - ACL_DBGMSG("dump_t gathered..."); - } + }, + rule.action); ids.resize(idSize); if (is_term_filter(rule.filter) && (rule.is_term() || rule.is_skipto())) From d94a66905bc82206b1558cdaa4d636d8ac7ec9d4 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 16 Sep 2024 12:21:16 +0400 Subject: [PATCH 109/195] Remove inline keyword from dump_t member function declaration This is completly redundant: [class.mfct]: "A member function may be defined (9.5) in its class definition, in which case it is an inline (9.2.7) member function if it is attached to the global module" --- common/actions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/actions.h b/common/actions.h index ff3ed6de..b6b8205a 100644 --- a/common/actions.h +++ b/common/actions.h @@ -22,13 +22,13 @@ class dump_t dump_tag(std::move(dump_tag)) {} - inline bool operator==(const dump_t& o) const + bool operator==(const dump_t& o) const { return std::tie(dump_id, dump_tag) == std::tie(o.dump_id, o.dump_tag); } - inline bool operator!=(const dump_t& o) const + bool operator!=(const dump_t& o) const { return !operator==(o); } From 580aafd5e842e3c1e192a1a3b1af4eeaebd269bd Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 2 Aug 2024 13:42:42 +0300 Subject: [PATCH 110/195] Remove some description from Actions objects This is redundant, we have a MAX_COUNT fields with the description --- common/actions.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/common/actions.h b/common/actions.h index b6b8205a..857b37cf 100644 --- a/common/actions.h +++ b/common/actions.h @@ -119,8 +119,6 @@ struct state_timeout_t /** * @brief Represents an action that dumps packets to a specified ring. - * - * Only one DumpAction is allowed in an Actions object. */ struct DumpAction final { @@ -207,8 +205,6 @@ struct FlowAction final * * This class doesn't have any specific info to store, * because check-state rule doesn't need anything. - * - * Only one CheckStateAction is allowed in an Actions object. */ struct CheckStateAction final { From 5d4bce8717bb887068841ad2093f829cb3cc132e Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 13 Aug 2024 18:35:09 +0300 Subject: [PATCH 111/195] Add documentation to acl_value Add a little description to an acl_value functions. Also extract functionality from a compile method into different methods for clarity --- controlplane/acl_value.cpp | 8 ++++---- controlplane/acl_value.h | 25 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index beabebb5..f51ccf52 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -71,10 +71,10 @@ void value_t::finalize_actions(IntermediateActions&& actions) void value_t::compile() { - for (auto& intermediate_actions : intermediate_vector) + for (auto& actions : intermediate_vector) { - ensure_termination(intermediate_actions); - move_timeout_from_state_timeout_to_flow(intermediate_actions); - finalize_actions(std::move(intermediate_actions)); + ensure_termination(actions); + move_timeout_from_state_timeout_to_flow(actions); + finalize_actions(std::move(actions)); } } diff --git a/controlplane/acl_value.h b/controlplane/acl_value.h index 2e1a90f4..55db4236 100644 --- a/controlplane/acl_value.h +++ b/controlplane/acl_value.h @@ -28,9 +28,13 @@ class value_t public: value_t(); -public: void clear(); + /** + * Collects an initial rule and stores it for later use. + * + * @return The index of the collected rule in the rule_actions vector. + */ template unsigned int collect_initial_rule(T&& rule) { @@ -41,13 +45,27 @@ class value_t return rule_actions.size() - 1; } + /** + * Collects an action from the rule_actions vector and stores it in the intermediate vector. + * + * @param rule_actions_id The index of the rule in the rule_actions vector. + * @return The index of the collected action in the intermediate_vector. + */ unsigned int collect(unsigned int rule_actions_id); + /** + * Compiles the collected actions into a final set of executable actions. + * + * The compile process involves: + * 1. Ensuring that the last action in the path is terminating. + * If not, a default "drop" rule is added. + * 2. Removing StateTimeout action and moving it's timeout value to FlowAction + * 3. Finalizing the actions into a vector of BaseActions objects + */ void compile(); -public: // FIXME: I don't like this name.. Why was it called like that previously? - std::vector intermediate_vector; + std::vector intermediate_vector; // FIXME: I don't like this name.. Why was it called like that previously? std::vector vector; @@ -61,5 +79,4 @@ class value_t void append_to_last(unsigned int rule_action_id); }; - } From 5ac052e772af002f5559f4aef97041c2c2d1ec8f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 2 Sep 2024 17:14:03 +0300 Subject: [PATCH 112/195] Refactor to_string() implementation in rule.h to utilize std::visit. Increases readability and maintainability. --- controlplane/acl/rule.h | 74 +++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 40406012..e82c2235 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1173,50 +1173,52 @@ struct rule_t const std::string& to_string() const { - if (std::holds_alternative(action)) - { - auto flow = std::get(action); - if (flow.type == common::globalBase::eFlowType::drop || flow.type == common::globalBase::eFlowType::controlPlane) + std::visit([this](const auto& rule) { + using T = std::decay_t; + if constexpr (std::is_same_v) { - text = "deny"; + if (rule.type == common::globalBase::eFlowType::drop || + rule.type == common::globalBase::eFlowType::controlPlane) + { + text = "deny"; + } + else + { + text = "flow " + std::string(eFlowType_toString(rule.type)) + + "(" + std::to_string(rule.data.atomic) + ")"; + } } - else + else if constexpr (std::is_same_v) { - text = "flow " + std::string(eFlowType_toString(flow.type)) + "(" + std::to_string(flow.data.atomic) + ")"; + if (!rule.dump_tag.empty()) + { + text = "dump(" + rule.dump_tag + ")"; + } } - } - else if (std::holds_alternative(action)) - { - auto rule_action = std::get(action); - if (!rule_action.dump_tag.empty()) + else if constexpr (std::is_same_v) { - text = "dump(" + rule_action.dump_tag + ")"; + text = "check-state"; } - } - else if (std::holds_alternative(action)) - { - text = "check-state"; - } - else if (std::holds_alternative(action)) - { - auto rule_action = std::get(action); - text = "state-timeout(" + std::to_string(rule_action.timeout) + ")"; - } - else - { - auto arg = std::get(action); - switch (arg) + else if constexpr (std::is_same_v) { - case DISPATCHER: - text = "allow"; - break; - case 0: - text = "skipto tablearg"; - break; - default: - text = "skipto " + std::to_string(arg); + text = "state-timeout(" + std::to_string(rule.timeout) + ")"; } - } + else if constexpr (std::is_same_v) + { + switch (rule) + { + case DISPATCHER: + text = "allow"; + break; + case 0: + text = "skipto tablearg"; + break; + default: + text = "skipto " + std::to_string(rule); + } + } + }, + action); if (log) { From fc8a38992c6ea4feca9f44336ddc2403af364a1e Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 19 Sep 2024 17:39:08 +0400 Subject: [PATCH 113/195] Add support for string literals in YANET_THROW macro --- common/define.h | 14 ++++++++------ controlplane/unittest/network.cpp | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/define.h b/common/define.h index 03846a26..2f4986f2 100644 --- a/common/define.h +++ b/common/define.h @@ -1,10 +1,12 @@ #pragma once #include +#include #include #include #include #include +#include #include #include @@ -90,13 +92,13 @@ extern LogPriority logPriority; #define CALCULATE_LOGICALPORT_ID(portId, vlanId) ((portId << 13) | ((vlanId & 0xFFF) << 1) | 1) #if __cpp_exceptions -#define YANET_THROW(string) throw string +#define YANET_THROW(message) throw std::runtime_error(std::string(message)) #else // __cpp_exceptions -#define YANET_THROW(string) \ - do \ - { \ - YANET_LOG_ERROR("%s\n", string.data()); \ - std::abort(); \ +#define YANET_THROW(message) \ + do \ + { \ + YANET_LOG_ERROR("%s\n", std::string_view(message).data()); \ + std::abort(); \ } while (0) #endif // __cpp_exceptions diff --git a/controlplane/unittest/network.cpp b/controlplane/unittest/network.cpp index 927feb82..8c743054 100644 --- a/controlplane/unittest/network.cpp +++ b/controlplane/unittest/network.cpp @@ -74,8 +74,8 @@ TEST(network_t, IPv6MaskGapped) TEST(network_t, IPWithoutMaskAfterSlash) { - EXPECT_THROW(network_t("1.2.3.4/"), std::string); // todo: WUT? Make normal exception type. - EXPECT_THROW(network_t("::1/"), std::string); + EXPECT_THROW(network_t("1.2.3.4/"), std::runtime_error); + EXPECT_THROW(network_t("::1/"), std::runtime_error); } } // namespace From 276bdacb288b06236bcdcc066f489dd181f3a6bc Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 19 Sep 2024 18:34:43 +0400 Subject: [PATCH 114/195] Use alias for ActionDispatcher in worker.cpp Otherwise the name is a little too long --- dataplane/worker.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 848df723..b696979d 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -1388,6 +1388,9 @@ inline void cWorker::acl_ingress_entry(rte_mbuf* mbuf) } } +using ActionsIngress = dataplane::ActionDispatcher; +using ActionsEgress = dataplane::ActionDispatcher; + inline void cWorker::acl_ingress_handle4() { const auto& base = bases[localBaseId & 1]; @@ -1529,7 +1532,7 @@ inline void cWorker::acl_ingress_handle4() const auto& value = acl.values[total_value]; - dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); + ActionsIngress::execute(value, {this, mbuf, metadata, &base}); } acl_ingress_stack4.clear(); @@ -1683,7 +1686,7 @@ inline void cWorker::acl_ingress_handle6() const auto& value = acl.values[total_value]; - dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); + ActionsIngress::execute(value, {this, mbuf, metadata, &base}); } acl_ingress_stack6.clear(); @@ -5229,7 +5232,7 @@ inline void cWorker::acl_egress_handle4() const auto& value = acl.values[total_value]; - dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); + ActionsEgress::execute(value, {this, mbuf, metadata, &base}); } acl_egress_stack4.clear(); @@ -5376,7 +5379,7 @@ inline void cWorker::acl_egress_handle6() const auto& value = acl.values[total_value]; - dataplane::ActionDispatcher::execute(value, {this, mbuf, metadata, &base}); + ActionsEgress::execute(value, {this, mbuf, metadata, &base}); } acl_egress_stack6.clear(); From d8472c1dc9fe048d355f7b6e9227c2805ba530ce Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 11 Sep 2024 16:15:30 +0400 Subject: [PATCH 115/195] Refactor BaseActions<> template arguments from bool to enum The previous use of true and false as template arguments did not immediately convey their meaning without referencing the Actions definition. So replacing true/false with ActionsPath::WithCheckState and ActionsPath::Default will improve readability --- common/actions.h | 18 ++++++++++++------ controlplane/acl_value.cpp | 4 ++-- controlplane/unittest/acl.cpp | 12 ++++++------ dataplane/action_dispatcher.h | 6 +++--- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/common/actions.h b/common/actions.h index 857b37cf..8d6cf0b0 100644 --- a/common/actions.h +++ b/common/actions.h @@ -550,11 +550,17 @@ struct IntermediateActions } // namespace acl -template +enum class ActionsPath +{ + Default, + WithCheckState +}; + +template class BaseActions; template<> -class BaseActions +class BaseActions { private: std::vector path_{}; @@ -611,7 +617,7 @@ class BaseActions }; template<> -class BaseActions +class BaseActions { private: std::vector path_{}; @@ -688,8 +694,8 @@ class BaseActions /** * The Actions type is defined as a std::variant to efficiently handle two possible states of action sequences: - * - BaseActions: This specialization is used when the action sequence contains a check-state action. - * - BaseActions: This specialization is used when the action sequence does not contain a check-state action. + * - BaseActions: This specialization is used when the action sequence contains a check-state action. + * - BaseActions: This specialization is used when the action sequence does not contain a check-state action. * * This approach allows us to avoid runtime branching to check for the presence of a check-state action, thereby * enhancing performance. Instead, the decision is made once when constructing the Actions object. @@ -700,6 +706,6 @@ class BaseActions * that will be only once. Once the result of a check-state is determined, we will choose correct path and execute it * without any additional checks. */ -using Actions = std::variant, BaseActions>; +using Actions = std::variant, BaseActions>; } // namespace common diff --git a/controlplane/acl_value.cpp b/controlplane/acl_value.cpp index f51ccf52..35e1fe43 100644 --- a/controlplane/acl_value.cpp +++ b/controlplane/acl_value.cpp @@ -61,11 +61,11 @@ void value_t::finalize_actions(IntermediateActions&& actions) { if (actions.indices.get().has_value()) { - vector.emplace_back(common::BaseActions(std::move(actions))); + vector.emplace_back(common::BaseActions(std::move(actions))); } else { - vector.emplace_back(common::BaseActions(std::move(actions))); + vector.emplace_back(common::BaseActions(std::move(actions))); } } diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index a80b6fd6..3f4ebe3c 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -501,7 +501,7 @@ add 300 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path does not include the check-state action EXPECT_THAT(actions.get_actions().size(), 1); @@ -537,7 +537,7 @@ add 400 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path includes the actions after the first and second check-states EXPECT_THAT(actions.get_actions().size(), 2); @@ -574,7 +574,7 @@ add 500 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path includes actions before and after the check-state EXPECT_THAT(actions.get_actions().size(), 3); @@ -611,7 +611,7 @@ add deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); @@ -647,7 +647,7 @@ add deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); @@ -685,7 +685,7 @@ add allow ip from any to any keep-state const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (std::is_same_v, common::BaseActions>) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 7ac0118d..d6fbede1 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -34,10 +34,10 @@ struct ActionDispatcher * Otherwise, it executes the regular path. The egress/ingress flow * is handled by the CheckStateAction execute method. */ - template - static void execute_impl(const common::BaseActions& actions, const ActionDispatcherArgs& args) + template + static void execute_impl(const common::BaseActions& actions, const ActionDispatcherArgs& args) { - if constexpr (HasCheckState) + if constexpr (Path == common::ActionsPath::WithCheckState) { auto worker = args.worker; auto mbuf = args.mbuf; From 75e295ef3683f4164261fcb82c09f184816db61f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 19 Sep 2024 18:39:07 +0400 Subject: [PATCH 116/195] Refactor BaseActions<> to reduce code duplication The changes are: - Publically inherit BaseActions from BaseActions The check-state version should have all the functionality of the default path. Inheriting minimizes code duplication by directly reusing path manipulation methods. We avoid using overriding, as the only methods that differ between the two classes (push and pop) are never called from the base class pointers. Since we're not aiming to use polymorphism there's no need to introduce a vtable and the associated runtime overhead. - Add helper methods for retrieving the size of paths and accessing the last actions from both the check-state and default paths (helps with tests) --- common/actions.h | 81 ++++++++++++++++------------------- dataplane/action_dispatcher.h | 8 ++-- 2 files changed, 40 insertions(+), 49 deletions(-) diff --git a/common/actions.h b/common/actions.h index 8d6cf0b0..1eeee311 100644 --- a/common/actions.h +++ b/common/actions.h @@ -562,42 +562,48 @@ class BaseActions; template<> class BaseActions { -private: +protected: std::vector path_{}; public: BaseActions() = default; BaseActions(acl::IntermediateActions&& actions) : - path_(std::move(actions.path)) {} + path_(std::move(actions.path)) + { + if (path_.empty()) + { + YANET_THROW("Path cannot be empty"); + } + if (!std::holds_alternative(default_path_last_raw_action())) + { + YANET_THROW("Last action in the default path must be a FlowAction"); + } + } - [[nodiscard]] const Action& get_last() const + [[nodiscard]] const std::vector& default_path() const { - assert(!path_.empty()); - return path_.back(); + return path_; } - Action& get_last() + [[nodiscard]] size_t default_path_size() const { - assert(!path_.empty()); - return path_.back(); + return path_.size(); } - [[nodiscard]] const std::vector& get_actions() const + [[nodiscard]] const RawAction& default_path_raw_action(size_t idx) const { - return path_; + return path_[idx].raw_action; } - [[nodiscard]] const common::globalBase::tFlow& get_flow() const + [[nodiscard]] const RawAction& default_path_last_raw_action() const { - assert(std::holds_alternative(get_last().raw_action)); - return std::get(get_last().raw_action).flow; + return path_.back().raw_action; } - [[nodiscard]] common::globalBase::tFlow& get_flow() + [[nodiscard]] const common::globalBase::tFlow& get_flow() const { - assert(std::holds_alternative(get_last().raw_action)); - return std::get(get_last().raw_action).flow; + return std::get(default_path_last_raw_action()).flow; } bool operator<(const BaseActions& second) const @@ -617,18 +623,22 @@ class BaseActions }; template<> -class BaseActions +class BaseActions : public BaseActions { private: - std::vector path_{}; // TODO: This is a prefix of a path_, in C++-20 I would use std::span to avoid extra copying std::vector check_state_path_{}; public: BaseActions() = default; + BaseActions(acl::IntermediateActions&& actions) { - assert(actions.indices.get().has_value()); + if (!actions.indices.get().has_value()) + { + YANET_THROW("Check-state index should be provided"); + } + auto check_state_index = actions.indices.get().value(); path_ = std::move(actions.path); @@ -640,43 +650,24 @@ class BaseActions path_.erase(path_.begin() + check_state_index); } - [[nodiscard]] const std::vector& get_actions() const - { - return path_; - } - - [[nodiscard]] const std::vector& get_check_state_actions() const + [[nodiscard]] const std::vector& check_state_path() const { return check_state_path_; } - [[nodiscard]] const Action& get_last() const - { - assert(!path_.empty()); - return path_.back(); - } - - Action& get_last() + [[nodiscard]] size_t check_state_path_size() const { - assert(!path_.empty()); - return path_.back(); + return check_state_path_.size(); } - [[nodiscard]] const common::globalBase::tFlow& get_flow() const + [[nodiscard]] const RawAction& check_state_path_raw_action(size_t idx) const { - assert(std::holds_alternative(get_last().raw_action)); - return std::get(get_last().raw_action).flow; + return check_state_path_[idx].raw_action; } - [[nodiscard]] common::globalBase::tFlow& get_flow() + [[nodiscard]] const RawAction& check_state_path_last_raw_action() const { - assert(std::holds_alternative(get_last().raw_action)); - return std::get(get_last().raw_action).flow; - } - - bool operator<(const BaseActions& second) const - { - return get_flow() < second.get_flow(); + return check_state_path_.back().raw_action; } void pop(stream_in_t& stream) diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index d6fbede1..26ee253e 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -31,7 +31,7 @@ struct ActionDispatcher * * If HasCheckState is true and the state check succeeds, * it executes the check_state_path_ and then returns. - * Otherwise, it executes the regular path. The egress/ingress flow + * Otherwise, it executes the default path. The egress/ingress flow * is handled by the CheckStateAction execute method. */ template @@ -56,13 +56,13 @@ struct ActionDispatcher if (flow) { - execute_path(actions.get_check_state_actions(), flow.value(), args); + execute_path(actions.check_state_path(), flow.value(), args); return; } } - // Execute regular path - execute_path(actions.get_actions(), actions.get_flow(), args); + // Execute default path + execute_path(actions.default_path(), actions.get_flow(), args); } static void execute_path(const std::vector& actions, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) From 90c80c7ae800df851f06c7c2a365c04844697a2c Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 11 Sep 2024 17:21:41 +0400 Subject: [PATCH 117/195] Reduce boilerplate code in unittests and action_dispatcher with type aliases Some types are used a lot like common::globalBase::tFlow, so we can save some time by adding an alias --- controlplane/unittest/acl.cpp | 79 +++++++++++++++++++---------------- dataplane/action_dispatcher.h | 17 ++++---- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 3f4ebe3c..809b3b56 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -9,12 +9,13 @@ namespace using common::ipv4_address_t; using common::globalBase::eFlowType; +using controlplane::base::acl_t; -auto make_default_acl(const std::string& rules, tAclId aclId = 1) -> controlplane::base::acl_t +auto make_default_acl(const std::string& rules, tAclId aclId = 1) -> acl_t { - controlplane::base::acl_t acl; + acl_t acl; common::globalBase::tFlow flow{}; - flow.type = common::globalBase::eFlowType::route; + flow.type = eFlowType::route; acl.aclId = aclId; acl.nextModules = {"unmatched"}; @@ -76,7 +77,7 @@ add allow tcp from { 2abc:123:ff1c:2030:aabb:5678::/ffff:ffff:ffff:fff0:ffff:fff add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } @@ -92,7 +93,7 @@ add allow tcp from { 1.2.3.4 } to any dst-port 80 add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } @@ -101,7 +102,7 @@ TEST(ACL, 003_Over500) { auto fw = make_default_acl(generate_firewall_conf(500)); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } @@ -110,7 +111,7 @@ TEST(ACL, 004_Over1000) { auto fw = make_default_acl(generate_firewall_conf(1000)); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } @@ -119,7 +120,7 @@ TEST(ACL, 005_Over4000) { auto fw = make_default_acl(generate_firewall_conf(4000)); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } @@ -141,7 +142,7 @@ add 6 allow tcp from { 1.2.3.5 } to any dst-port 80 add 7 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -170,7 +171,7 @@ add 1 deny ip from any to any in add 2 allow ip from { 1.2.3.4 } to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -183,7 +184,7 @@ add 2 allow ip from { 1.2.3.4 } to any in const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - EXPECT_THAT(actions.get_flow().type, ::testing::Eq(common::globalBase::eFlowType::drop)); + EXPECT_THAT(actions.get_flow().type, ::testing::Eq(eFlowType::drop)); }, value); } @@ -199,7 +200,7 @@ add 1 allow ip from { 1.2.3.4 } to any in add 2 deny ip from any to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -220,7 +221,7 @@ add 1 allow ip from { 1.2.3.4 } to any in via port0 add 2 deny ip from any to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "port0"}, {true, "port1"}}}}, result); @@ -249,7 +250,7 @@ add allow ip from { 1.2.3.5 } to any out via port1 // id 2 add deny ip from any to any out // id 3 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}}}}, result); @@ -281,7 +282,7 @@ add deny ip from any to any out // id 4 add allow ip from any to any in // id 5 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}, {true, "port0"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 6); @@ -311,7 +312,7 @@ TEST(ACL, 013_DefaultAction) add 1 allow icmp from { 1.2.3.4 } to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}, {false, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 3); @@ -342,7 +343,7 @@ add 200 deny log ip from any to any in add 300 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "port0"}, {true, "port1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 3); @@ -396,7 +397,7 @@ add 200 allow proto tcp dst-addr fc00/23@2abc:123:c00::/40 add 300 allow proto tcp dst-addr 1234567@2abc:123:c00::/40 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 4); @@ -421,7 +422,7 @@ add 400 allow tcp from any to any tcpflags rst add 500 allow tcp from any to any established )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 7); @@ -448,7 +449,7 @@ add 200 deny ip from any to any icmptypes 1,2,3,9,10,13 add 300 allow ip from any to any icmp6types 133,134,135,136 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 4); @@ -469,7 +470,7 @@ add 100 allow icmp from any to unknown.hostname.tld icmptypes 0,8 add 200 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); ASSERT_EQ(ret.size(), 1); @@ -480,6 +481,12 @@ add 200 deny ip from any to any EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny")); } +template +constexpr bool is_with_check_state() +{ + return std::is_same_v, common::BaseActions>; +} + TEST(ACL, 019_CheckStateBasic) { auto fw = make_default_acl(R"IPFW( @@ -489,7 +496,7 @@ add 200 allow ip from { 1.2.3.4 } to any add 300 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -501,7 +508,7 @@ add 300 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path does not include the check-state action EXPECT_THAT(actions.get_actions().size(), 1); @@ -526,7 +533,7 @@ add 300 check-state add 400 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -537,7 +544,7 @@ add 400 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the actions after the first and second check-states EXPECT_THAT(actions.get_actions().size(), 2); @@ -563,7 +570,7 @@ add 500 check-state add 500 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -574,7 +581,7 @@ add 500 deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes actions before and after the check-state EXPECT_THAT(actions.get_actions().size(), 3); @@ -599,7 +606,7 @@ add allow ip from any to any keep-state add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -611,7 +618,7 @@ add deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); @@ -635,7 +642,7 @@ add allow ip from any to any 22 keep-state add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -647,7 +654,7 @@ add deny ip from any to any const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); @@ -673,7 +680,7 @@ add deny ip from any to any add allow ip from any to any keep-state )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; + std::map acls{{"acl0", std::move(fw)}}; acl::result_t result; acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); @@ -685,7 +692,7 @@ add allow ip from any to any keep-state const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); @@ -720,7 +727,7 @@ add allow ip from any to any keep-state const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action with the correct timeout EXPECT_THAT(actions.get_actions().size(), 1); @@ -757,7 +764,7 @@ add allow ip from any to any keep-state const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action with the correct timeout EXPECT_THAT(actions.get_actions().size(), 1); @@ -777,7 +784,7 @@ add allow ip from any to any keep-state const auto& value = result.acl_values[total_table_value]; std::visit([&](const auto& actions) { - if constexpr (std::is_same_v, common::BaseActions>) + if constexpr (is_with_check_state()) { // Check that the regular path includes the allow action with the correct timeout EXPECT_THAT(actions.get_actions().size(), 1); diff --git a/dataplane/action_dispatcher.h b/dataplane/action_dispatcher.h index 26ee253e..2b57f141 100644 --- a/dataplane/action_dispatcher.h +++ b/dataplane/action_dispatcher.h @@ -18,6 +18,9 @@ struct ActionDispatcherArgs template struct ActionDispatcher { + using Flow = common::globalBase::tFlow; + using FlowFlags = common::globalBase::eFlowFlags; + static void execute(const common::Actions& actions, const ActionDispatcherArgs& args) { std::visit([&](const auto& specific_actions) { @@ -65,7 +68,7 @@ struct ActionDispatcher execute_path(actions.default_path(), actions.get_flow(), args); } - static void execute_path(const std::vector& actions, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + static void execute_path(const std::vector& actions, const Flow& flow, const ActionDispatcherArgs& args) { for (const auto& action : actions) { @@ -77,7 +80,7 @@ struct ActionDispatcher } } - static void execute(const common::DumpAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + static void execute(const common::DumpAction& action, const Flow& flow, const ActionDispatcherArgs& args) { auto ring_id = args.base->globalBase->dump_id_to_tag[action.dump_id]; if (ring_id == -1) @@ -89,12 +92,12 @@ struct ActionDispatcher ring.write(args.mbuf, flow.type); } - static void execute(const common::StateTimeoutAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + static void execute(const common::StateTimeoutAction& action, const Flow& flow, const ActionDispatcherArgs& args) { YANET_LOG_DEBUG("Asked to execute StateTimeoutAction, which should not occur. Check value_t::compile()\n"); } - static void execute(const common::FlowAction& action, [[maybe_unused]] const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + static void execute(const common::FlowAction& action, [[maybe_unused]] const Flow& flow, const ActionDispatcherArgs& args) { auto worker = args.worker; auto mbuf = args.mbuf; @@ -112,11 +115,11 @@ struct ActionDispatcher acl_id = args.meta->flow.data.aclId; } - if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::log) + if (action.flow.flags & (uint8_t)FlowFlags::log) { worker->acl_log(mbuf, action.flow, acl_id); } - if (action.flow.flags & (uint8_t)common::globalBase::eFlowFlags::recordstate) + if (action.flow.flags & (uint8_t)FlowFlags::recordstate) { worker->acl_create_state(mbuf, acl_id, action.flow, action.timeout); } @@ -131,7 +134,7 @@ struct ActionDispatcher } } - static void execute([[maybe_unused]] const common::CheckStateAction& action, const common::globalBase::tFlow& flow, const ActionDispatcherArgs& args) + static void execute([[maybe_unused]] const common::CheckStateAction& action, const Flow& flow, const ActionDispatcherArgs& args) { if constexpr (Direction == FlowDirection::Egress) { From 81aebeed2ace580976793cec871bdc26f64aa21b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 11 Sep 2024 19:46:06 +0400 Subject: [PATCH 118/195] Refactor ACL tests to reduce duplication using GoogleTest fixtures Centralize setup and action visitation logic, reducing duplicated code in unittests --- controlplane/unittest/acl.cpp | 470 ++++++++++++++-------------------- 1 file changed, 190 insertions(+), 280 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 809b3b56..28d2c86b 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -62,9 +62,61 @@ add deny ip from any to any return rules; } -TEST(ACL, 001_Basic) +class ACL : public ::testing::Test { - auto fw = make_default_acl(R"IPFW( +protected: + acl::result_t result; + + // Helper function to compile the ACL with the interface map + void compile_acl(const std::string& acl_rules, const acl::iface_map_t& iface_map = {{1, {{true, "vlan1"}}}}) + { + auto fw = make_default_acl(acl_rules); + std::map acls{{"acl0", std::move(fw)}}; + + acl::compile(acls, iface_map, result); + } + + // Helper function to visit a specific group based on its index + template + void visit_action_group(size_t group_index, Func&& func) + { + ASSERT_LT(group_index, result.acl_total_table.size()) << "Group index out of range."; + auto total_table_value = std::get<1>(result.acl_total_table[group_index]); + const auto& value = result.acl_values[total_table_value]; + + std::visit(std::forward(func), value); + } + + // Helper function to visit actions and apply the provided lambda to all action groups + template + void visit_actions(Func&& func) + { + for (size_t group_index = 0; group_index < result.acl_total_table.size(); ++group_index) + { + visit_action_group(group_index, std::forward(func)); + } + } +}; + +class ACLWithUnwind : public ACL +{ +protected: + acl::unwind_result unwind_result; + + void unwind_and_compile_acl(const std::string& acl_rules, const acl::iface_map_t& iface_map = {{1, {{true, "vlan1"}}}}) + { + auto fw = make_default_acl(acl_rules); + std::map acls{{"acl0", std::move(fw)}}; + + unwind_result = acl::unwind(acls, iface_map, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); + + acl::compile(acls, iface_map, result); + } +}; + +TEST_F(ACL, 001_Basic) +{ + compile_acl(R"IPFW( :BEGIN add skipto :IN ip from any to any in @@ -76,15 +128,11 @@ add allow tcp from { 2abc:123:ff1c:2030:0:5678::/ffff:ffff:ffff:fff0:ffff:ffff:: add allow tcp from { 2abc:123:ff1c:2030:aabb:5678::/ffff:ffff:ffff:fff0:ffff:ffff:: } to any 84 add deny ip from any to any )IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } -TEST(ACL, 002_IPv4Only) +TEST_F(ACL, 002_IPv4Only) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add skipto :IN ip from any to any in @@ -92,42 +140,26 @@ add skipto :IN ip from any to any in add allow tcp from { 1.2.3.4 } to any dst-port 80 add deny ip from any to any )IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); } -TEST(ACL, 003_Over500) +TEST_F(ACL, 003_Over500) { - auto fw = make_default_acl(generate_firewall_conf(500)); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + compile_acl(generate_firewall_conf(500)); } -TEST(ACL, 004_Over1000) +TEST_F(ACL, 004_Over1000) { - auto fw = make_default_acl(generate_firewall_conf(1000)); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + compile_acl(generate_firewall_conf(1000)); } -TEST(ACL, 005_Over4000) +TEST_F(ACL, 005_Over4000) { - auto fw = make_default_acl(generate_firewall_conf(4000)); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + compile_acl(generate_firewall_conf(4000)); } -TEST(ACL, 006_Counters) +TEST_F(ACL, 006_Counters) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 1 skipto :IN ip from any to any in @@ -142,20 +174,14 @@ add 6 allow tcp from { 1.2.3.5 } to any dst-port 80 add 7 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + visit_actions([&](const auto& actions) { + EXPECT_THAT(actions.get_flow().counter_id, ::testing::Ge(1)); + EXPECT_THAT(actions.get_flow().counter_id, ::testing::Lt(5)); + }); auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 5); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { EXPECT_THAT(actions.get_flow().counter_id, ::testing::Ge(1)); }, value); - std::visit([&](const auto& actions) { EXPECT_THAT(actions.get_flow().counter_id, ::testing::Lt(5)); }, value); - } EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1, 2, 5)); EXPECT_THAT(ids_map[2], ::testing::ElementsAre(1, 2, 7)); @@ -163,47 +189,34 @@ add 7 deny ip from any to any EXPECT_THAT(ids_map[4], ::testing::ElementsAre(1, 4)); } -TEST(ACL, 007_OrderDeny) +TEST_F(ACL, 007_OrderDeny) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 1 deny ip from any to any in add 2 allow ip from { 1.2.3.4 } to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + visit_actions([&](const auto& actions) { + EXPECT_THAT(actions.get_flow().type, ::testing::Eq(eFlowType::drop)); + }); - auto& ids_map = result.ids_map; ASSERT_EQ(result.acl_total_table.size(), 1); - ASSERT_EQ(ids_map.size(), 2); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - EXPECT_THAT(actions.get_flow().type, ::testing::Eq(eFlowType::drop)); - }, - value); - } + auto& ids_map = result.ids_map; + ASSERT_EQ(ids_map.size(), 2); EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1)); } -TEST(ACL, 008_OrderAllow) +TEST_F(ACL, 008_OrderAllow) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 1 allow ip from { 1.2.3.4 } to any in add 2 deny ip from any to any in )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - auto& ids_map = result.ids_map; ASSERT_EQ(result.acl_total_table.size(), 2); ASSERT_EQ(ids_map.size(), 3); @@ -213,17 +226,14 @@ add 2 deny ip from any to any in EXPECT_THAT(ids_map[2], ::testing::ElementsAre(2)); } -TEST(ACL, 010_Via) +TEST_F(ACL, 010_Via) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 1 allow ip from { 1.2.3.4 } to any in via port0 add 2 deny ip from any to any in -)IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "port0"}, {true, "port1"}}}}, result); +)IPFW", + {{1, {{true, "port0"}, {true, "port1"}}}}); auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 3); @@ -241,18 +251,15 @@ add 2 deny ip from any to any in EXPECT_THAT(acl_map[1], ::testing::ElementsAre(1, 2)); } -TEST(ACL, 011_ViaOut) +TEST_F(ACL, 011_ViaOut) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add allow ip from { 1.2.3.4 } to any out via port0 // id 1 add allow ip from { 1.2.3.5 } to any out via port1 // id 2 add deny ip from any to any out // id 3 -)IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}}}}, result); +)IPFW", + {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}}}}); auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 4); @@ -269,9 +276,17 @@ add deny ip from any to any out // id 3 EXPECT_THAT(ifaces["port3"], 3); } -TEST(ACL, 012_Lookup) +// stringify a tuple +template +std::string stringify(Tuple&& v) { - auto fw = make_default_acl(R"IPFW( + return std::apply([](auto&&... e) { return (((e ? *e : "any") + "|") + ...); }, + std::forward(v)); +} + +TEST_F(ACLWithUnwind, 012_Lookup) +{ + unwind_and_compile_acl(R"IPFW( :BEGIN add skipto :ALL ip from any to any // id 1 @@ -280,12 +295,10 @@ add allow ip from { 1.2.3.4 } to any out via port0 // id 2 add allow log ip from { 1.2.3.5 } to any out via port1 // id 3 add deny ip from any to any out // id 4 add allow ip from any to any in // id 5 -)IPFW"); +)IPFW", + {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}, {true, "port0"}}}}); - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{false, "port0"}, {false, "port1"}, {false, "port2"}, {false, "port3"}, {true, "port0"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 6); + ASSERT_EQ(unwind_result.size(), 6); std::set expect = {"port2 port3 |1|any|any|any|any|any|any|any|false|drop(0)|1, 4|false|", "port0 |1|1.2.3.4/255.255.255.255|any|any|any|any|any|any|false|logicalPort_egress(0)|1, 2|false|", @@ -294,9 +307,7 @@ add allow ip from any to any in // id 5 "port1 |1|1.2.3.5/255.255.255.255|any|any|any|any|any|any|false|logicalPort_egress(0)|1, 3|true|", "port1 |1|any|any|any|any|any|any|any|false|drop(0)|1, 4|false|"}; - auto stringify = [](auto& v) { return std::apply([](auto... e) { return (((e ? *e : "any") + "|") + ...); }, v); }; - - for (const auto& r : ret) + for (const auto& r : unwind_result) { auto str = stringify(r); @@ -305,26 +316,19 @@ add allow ip from any to any in // id 5 } } -TEST(ACL, 013_DefaultAction) +TEST_F(ACLWithUnwind, 013_DefaultAction) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 1 allow icmp from { 1.2.3.4 } to any in -)IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; +)IPFW", + {{1, {{true, "vlan1"}, {false, "vlan1"}}}}); - auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}, {false, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 3); + ASSERT_EQ(unwind_result.size(), 3); - auto stringify = [](auto& v) { return std::apply([](auto... e) { return (((e ? *e : "any") + "|") + ...); }, v); }; - - EXPECT_THAT(stringify(ret[0]), ::testing::Eq("vlan1 |0|1.2.3.4/255.255.255.255|any|any|1|any|any|any|false|route(0)|1|false|")); - EXPECT_THAT(stringify(ret[1]), ::testing::Eq("vlan1 |0|any|any|any|any|any|any|any|false|route(0)||false|")); - EXPECT_THAT(stringify(ret[2]), ::testing::Eq("vlan1 |1|any|any|any|any|any|any|any|false|logicalPort_egress(0)||false|")); - - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}, {false, "vlan1"}}}}, result); + EXPECT_THAT(stringify(unwind_result[0]), ::testing::Eq("vlan1 |0|1.2.3.4/255.255.255.255|any|any|1|any|any|any|false|route(0)|1|false|")); + EXPECT_THAT(stringify(unwind_result[1]), ::testing::Eq("vlan1 |0|any|any|any|any|any|any|any|false|route(0)||false|")); + EXPECT_THAT(stringify(unwind_result[2]), ::testing::Eq("vlan1 |1|any|any|any|any|any|any|any|false|logicalPort_egress(0)||false|")); auto& ids_map = result.ids_map; ASSERT_EQ(result.acl_total_table.size(), 4); @@ -334,38 +338,27 @@ add 1 allow icmp from { 1.2.3.4 } to any in EXPECT_THAT(ids_map[1], ::testing::ElementsAre(1)); } -TEST(ACL, 014_Log) +TEST_F(ACLWithUnwind, 014_Log) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 100 allow log ip from { 1.2.3.4 } to any in via port0 add 200 deny log ip from any to any in add 300 deny ip from any to any -)IPFW"); - - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{true, "port0"}, {true, "port1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 3); +)IPFW", + {{1, {{true, "port0"}, {true, "port1"}}}}); - auto stringify = [](auto& v) { return std::apply([](auto... e) { return (((e ? *e : "any") + "|") + ...); }, v); }; + ASSERT_EQ(unwind_result.size(), 3); - EXPECT_THAT(stringify(ret[0]), ::testing::Eq("port1 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); - EXPECT_THAT(stringify(ret[1]), ::testing::Eq("port0 |0|1.2.3.4/255.255.255.255|any|any|any|any|any|any|false|route(0)|1|true|")); - EXPECT_THAT(stringify(ret[2]), ::testing::Eq("port0 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); + EXPECT_THAT(stringify(unwind_result[0]), ::testing::Eq("port1 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); + EXPECT_THAT(stringify(unwind_result[1]), ::testing::Eq("port0 |0|1.2.3.4/255.255.255.255|any|any|any|any|any|any|false|route(0)|1|true|")); + EXPECT_THAT(stringify(unwind_result[2]), ::testing::Eq("port0 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); - acl::result_t result; - acl::compile(acls, {{1, {{true, "port0"}, {true, "port1"}}}}, result); + visit_actions([&](const auto& actions) { + EXPECT_THAT(actions.get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); + }); ASSERT_EQ(result.acl_total_table.size(), 4); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - std::visit([&](const auto& actions) { - EXPECT_THAT(actions.get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); - }, - result.acl_values[total_table_value]); - } auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 3); @@ -388,31 +381,26 @@ add 300 deny ip from any to any EXPECT_THAT(std::get<2>(result.rules[300].front()), ::testing::Eq("deny ip from any to any")); } -TEST(ACL, 015_GappedMask) +TEST_F(ACLWithUnwind, 015_GappedMask) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 100 allow proto tcp dst-addr 4242@2abc:123:c00::/40 add 200 allow proto tcp dst-addr fc00/23@2abc:123:c00::/40 add 300 allow proto tcp dst-addr 1234567@2abc:123:c00::/40 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 4); + ASSERT_EQ(unwind_result.size(), 4); - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); // check that parser correctly expands gapped mask in rules -> compare with generated text EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("allow dst-addr 2abc:123:c00::4242:0:0/ffff:ffff:ff00:0:ffff:ffff:: proto 6")); EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("allow dst-addr 2abc:123:c00::fc00:0:0/ffff:ffff:ff00:0:ffff:fe00:: proto 6")); EXPECT_THAT(std::get<1>(result.rules[300].front()), ::testing::Eq("allow dst-addr 2abc:123:c00:0:123:4567::/ffff:ffff:ff00:0:ffff:ffff:: proto 6")); } -TEST(ACL, 016_TcpFlags) +TEST_F(ACLWithUnwind, 016_TcpFlags) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 100 deny tcp from any to any setup add 150 deny tcp from any to any tcpflags syn,!ack // the same as setup @@ -422,13 +410,7 @@ add 400 allow tcp from any to any tcpflags rst add 500 allow tcp from any to any established )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 7); - - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + ASSERT_EQ(unwind_result.size(), 7); // check that parser correctly expands tcpflags and then filter correctly formats them EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("deny proto 6 setup")); EXPECT_THAT(std::get<1>(result.rules[150].front()), ::testing::Eq("deny proto 6 setup")); @@ -438,9 +420,9 @@ add 500 allow tcp from any to any established EXPECT_THAT(std::get<1>(result.rules[500].front()), ::testing::Eq("allow proto 6 etsablished")); } -TEST(ACL, 017_IcmpTypes) +TEST_F(ACLWithUnwind, 017_IcmpTypes) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 100 allow icmp from any to any icmptypes 0,8,3,11,12 # parser automatically inserts ICMP or ICMPv6 protocol @@ -449,34 +431,22 @@ add 200 deny ip from any to any icmptypes 1,2,3,9,10,13 add 300 allow ip from any to any icmp6types 133,134,135,136 )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 4); - - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + ASSERT_EQ(unwind_result.size(), 4); // check that parser correctly expands icmptypes and then filter correctly formats them EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("allow proto 1 icmptypes 0,3,8,11,12")); EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny proto 1 icmptypes 1,2,3,9,10,13")); EXPECT_THAT(std::get<1>(result.rules[300].front()), ::testing::Eq("allow proto 58 icmp6types 133,134,135,136")); } -TEST(ACL, 018_EmptyDst) +TEST_F(ACLWithUnwind, 018_EmptyDst) { - auto fw = make_default_acl(R"IPFW( + unwind_and_compile_acl(R"IPFW( :BEGIN add 100 allow icmp from any to unknown.hostname.tld icmptypes 0,8 add 200 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - - auto ret = acl::unwind(acls, {{1, {{true, "vlan1"}}}}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}); - ASSERT_EQ(ret.size(), 1); - - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); + ASSERT_EQ(unwind_result.size(), 1); // we expect that after validation rule 100 will be omitted and only one rule will remain EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny")); } @@ -487,45 +457,34 @@ constexpr bool is_with_check_state() return std::is_same_v, common::BaseActions>; } -TEST(ACL, 019_CheckStateBasic) +TEST_F(ACL, 019_CheckStateBasic) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 100 check-state add 200 allow ip from { 1.2.3.4 } to any add 300 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path does not include the check-state action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_FALSE(std::holds_alternative(actions.get_actions()[0].raw_action)); + visit_actions([&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path does not include the check-state action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_FALSE(std::holds_alternative(actions.get_actions()[0].raw_action)); - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }); } -TEST(ACL, 020_ManyCheckStates) +TEST_F(ACL, 020_ManyCheckStates) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 100 check-state add 200 dump ring1 ip from { 1.2.3.4 } to any @@ -533,17 +492,10 @@ add 300 check-state add 400 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); // We're interested in second group, i.e the group where src ip is { 1.2.3.4 } - auto total_table_value = std::get<1>(result.acl_total_table[1]); - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { + visit_action_group(1, [&](const auto& actions) { if constexpr (is_with_check_state()) { // Check that the regular path includes the actions after the first and second check-states @@ -555,13 +507,12 @@ add 400 deny ip from any to any EXPECT_THAT(actions.get_check_state_actions().size(), 1); EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); } - }, - value); + }); } -TEST(ACL, 021_CheckStateComplex) +TEST_F(ACL, 021_CheckStateComplex) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add 100 dump ring1 ip from { 1.2.3.4 } to any add 200 check-state @@ -570,17 +521,10 @@ add 500 check-state add 500 deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); // We're interested in second group, i.e the group where src ip is { 1.2.3.4 } - auto total_table_value = std::get<1>(result.acl_total_table[1]); - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { + visit_action_group(1, [&](const auto& actions) { if constexpr (is_with_check_state()) { // Check that the regular path includes actions before and after the check-state @@ -594,84 +538,61 @@ add 500 deny ip from any to any EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[0].raw_action)); EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[1].raw_action)); } - }, - value); + }); } -TEST(ACL, KeepState_Basic) +TEST_F(ACL, KeepState_Basic) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add allow ip from any to any keep-state add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 1); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + visit_actions([&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }); } -TEST(ACL, KeepState_MultipleRules) +TEST_F(ACL, KeepState_MultipleRules) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add allow ip from { 1.2.3.4 } to any keep-state add allow ip from any to any 22 keep-state add deny ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + visit_actions([&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }); } -TEST(ACL, KeepState_WithSkipTo) +TEST_F(ACL, KeepState_WithSkipTo) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add skipto :IN ip from { 1.2.3.4 } to any in add deny ip from any to any @@ -680,31 +601,20 @@ add deny ip from any to any add allow ip from any to any keep-state )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; - - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + visit_actions([&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Check that the check-state path includes the check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + } + }); } TEST(ACL, StateTimeout_Basic) From af376d346953844b58074ff8b8516cbc249e0ba4 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 11 Sep 2024 22:37:29 +0400 Subject: [PATCH 119/195] Simplify ACL tests by using custom matchers and EXPECT_EQ Introduce custom GTest matchers to check for specific variants in `RawAction`. Replace EXPECT_THAT with ::testing::Eq mather with `EXPECT_EQ`. Overall, these changes reduces verbosity and make the code easier to follow. --- controlplane/unittest/acl.cpp | 159 ++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 47 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 28d2c86b..f761cb6a 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -1,8 +1,10 @@ +#include #include #include #include #include "../acl.h" +#include "common/actions.h" namespace { @@ -197,12 +199,12 @@ add 1 deny ip from any to any in add 2 allow ip from { 1.2.3.4 } to any in )IPFW"); + ASSERT_EQ(result.acl_total_table.size(), 1); + visit_actions([&](const auto& actions) { - EXPECT_THAT(actions.get_flow().type, ::testing::Eq(eFlowType::drop)); + EXPECT_EQ(eFlowType::drop, actions.get_flow().type); }); - ASSERT_EQ(result.acl_total_table.size(), 1); - auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 2); EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); @@ -217,8 +219,9 @@ add 1 allow ip from { 1.2.3.4 } to any in add 2 deny ip from any to any in )IPFW"); - auto& ids_map = result.ids_map; ASSERT_EQ(result.acl_total_table.size(), 2); + + auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 3); EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); @@ -325,13 +328,13 @@ add 1 allow icmp from { 1.2.3.4 } to any in {{1, {{true, "vlan1"}, {false, "vlan1"}}}}); ASSERT_EQ(unwind_result.size(), 3); + ASSERT_EQ(result.acl_total_table.size(), 4); - EXPECT_THAT(stringify(unwind_result[0]), ::testing::Eq("vlan1 |0|1.2.3.4/255.255.255.255|any|any|1|any|any|any|false|route(0)|1|false|")); - EXPECT_THAT(stringify(unwind_result[1]), ::testing::Eq("vlan1 |0|any|any|any|any|any|any|any|false|route(0)||false|")); - EXPECT_THAT(stringify(unwind_result[2]), ::testing::Eq("vlan1 |1|any|any|any|any|any|any|any|false|logicalPort_egress(0)||false|")); + EXPECT_EQ("vlan1 |0|1.2.3.4/255.255.255.255|any|any|1|any|any|any|false|route(0)|1|false|", stringify(unwind_result[0])); + EXPECT_EQ("vlan1 |0|any|any|any|any|any|any|any|false|route(0)||false|", stringify(unwind_result[1])); + EXPECT_EQ("vlan1 |1|any|any|any|any|any|any|any|false|logicalPort_egress(0)||false|", stringify(unwind_result[2])); auto& ids_map = result.ids_map; - ASSERT_EQ(result.acl_total_table.size(), 4); ASSERT_EQ(ids_map.size(), 2); EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); @@ -349,17 +352,16 @@ add 300 deny ip from any to any {{1, {{true, "port0"}, {true, "port1"}}}}); ASSERT_EQ(unwind_result.size(), 3); + ASSERT_EQ(result.acl_total_table.size(), 4); - EXPECT_THAT(stringify(unwind_result[0]), ::testing::Eq("port1 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); - EXPECT_THAT(stringify(unwind_result[1]), ::testing::Eq("port0 |0|1.2.3.4/255.255.255.255|any|any|any|any|any|any|false|route(0)|1|true|")); - EXPECT_THAT(stringify(unwind_result[2]), ::testing::Eq("port0 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|")); + EXPECT_EQ("port1 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|", stringify(unwind_result[0])); + EXPECT_EQ("port0 |0|1.2.3.4/255.255.255.255|any|any|any|any|any|any|false|route(0)|1|true|", stringify(unwind_result[1])); + EXPECT_EQ("port0 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|", stringify(unwind_result[2])); visit_actions([&](const auto& actions) { - EXPECT_THAT(actions.get_flow().flags, ::testing::Eq((uint8_t)common::globalBase::eFlowFlags::log)); + EXPECT_EQ(actions.get_flow().flags, common::globalBase::eFlowFlags::log); }); - ASSERT_EQ(result.acl_total_table.size(), 4); - auto& ids_map = result.ids_map; ASSERT_EQ(ids_map.size(), 3); EXPECT_THAT(ids_map[0], ::testing::ElementsAre()); @@ -376,9 +378,9 @@ add 300 deny ip from any to any EXPECT_THAT(acl_map[1], ::testing::ElementsAre(1, 2)); ASSERT_EQ(result.rules.size(), 3); - EXPECT_THAT(std::get<2>(result.rules[100].front()), ::testing::Eq("allow log ip from { 1.2.3.4 } to any in via port0")); - EXPECT_THAT(std::get<2>(result.rules[200].front()), ::testing::Eq("deny log ip from any to any in")); - EXPECT_THAT(std::get<2>(result.rules[300].front()), ::testing::Eq("deny ip from any to any")); + EXPECT_EQ("allow log ip from { 1.2.3.4 } to any in via port0", std::get<2>(result.rules[100].front())); + EXPECT_EQ("deny log ip from any to any in", std::get<2>(result.rules[200].front())); + EXPECT_EQ("deny ip from any to any", std::get<2>(result.rules[300].front())); } TEST_F(ACLWithUnwind, 015_GappedMask) @@ -393,9 +395,9 @@ add 300 allow proto tcp dst-addr 1234567@2abc:123:c00::/40 ASSERT_EQ(unwind_result.size(), 4); // check that parser correctly expands gapped mask in rules -> compare with generated text - EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("allow dst-addr 2abc:123:c00::4242:0:0/ffff:ffff:ff00:0:ffff:ffff:: proto 6")); - EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("allow dst-addr 2abc:123:c00::fc00:0:0/ffff:ffff:ff00:0:ffff:fe00:: proto 6")); - EXPECT_THAT(std::get<1>(result.rules[300].front()), ::testing::Eq("allow dst-addr 2abc:123:c00:0:123:4567::/ffff:ffff:ff00:0:ffff:ffff:: proto 6")); + EXPECT_EQ("allow dst-addr 2abc:123:c00::4242:0:0/ffff:ffff:ff00:0:ffff:ffff:: proto 6", std::get<1>(result.rules[100].front())); + EXPECT_EQ("allow dst-addr 2abc:123:c00::fc00:0:0/ffff:ffff:ff00:0:ffff:fe00:: proto 6", std::get<1>(result.rules[200].front())); + EXPECT_EQ("allow dst-addr 2abc:123:c00:0:123:4567::/ffff:ffff:ff00:0:ffff:ffff:: proto 6", std::get<1>(result.rules[300].front())); } TEST_F(ACLWithUnwind, 016_TcpFlags) @@ -412,12 +414,12 @@ add 500 allow tcp from any to any established ASSERT_EQ(unwind_result.size(), 7); // check that parser correctly expands tcpflags and then filter correctly formats them - EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("deny proto 6 setup")); - EXPECT_THAT(std::get<1>(result.rules[150].front()), ::testing::Eq("deny proto 6 setup")); - EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny proto 6 tcpflags fin,psh,urg")); - EXPECT_THAT(std::get<1>(result.rules[300].front()), ::testing::Eq("deny proto 6 tcpflags !fin,!syn,!rst,!psh,!ack,!urg")); - EXPECT_THAT(std::get<1>(result.rules[400].front()), ::testing::Eq("allow proto 6 tcpflags rst")); - EXPECT_THAT(std::get<1>(result.rules[500].front()), ::testing::Eq("allow proto 6 etsablished")); + EXPECT_EQ("deny proto 6 setup", std::get<1>(result.rules[100].front())); + EXPECT_EQ("deny proto 6 setup", std::get<1>(result.rules[150].front())); + EXPECT_EQ("deny proto 6 tcpflags fin,psh,urg", std::get<1>(result.rules[200].front())); + EXPECT_EQ("deny proto 6 tcpflags !fin,!syn,!rst,!psh,!ack,!urg", std::get<1>(result.rules[300].front())); + EXPECT_EQ("allow proto 6 tcpflags rst", std::get<1>(result.rules[400].front())); + EXPECT_EQ("allow proto 6 etsablished", std::get<1>(result.rules[500].front())); } TEST_F(ACLWithUnwind, 017_IcmpTypes) @@ -433,9 +435,9 @@ add 300 allow ip from any to any icmp6types 133,134,135,136 ASSERT_EQ(unwind_result.size(), 4); // check that parser correctly expands icmptypes and then filter correctly formats them - EXPECT_THAT(std::get<1>(result.rules[100].front()), ::testing::Eq("allow proto 1 icmptypes 0,3,8,11,12")); - EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny proto 1 icmptypes 1,2,3,9,10,13")); - EXPECT_THAT(std::get<1>(result.rules[300].front()), ::testing::Eq("allow proto 58 icmp6types 133,134,135,136")); + EXPECT_EQ("allow proto 1 icmptypes 0,3,8,11,12", std::get<1>(result.rules[100].front())); + EXPECT_EQ("deny proto 1 icmptypes 1,2,3,9,10,13", std::get<1>(result.rules[200].front())); + EXPECT_EQ("allow proto 58 icmp6types 133,134,135,136", std::get<1>(result.rules[300].front())); } TEST_F(ACLWithUnwind, 018_EmptyDst) @@ -448,13 +450,76 @@ add 200 deny ip from any to any ASSERT_EQ(unwind_result.size(), 1); // we expect that after validation rule 100 will be omitted and only one rule will remain - EXPECT_THAT(std::get<1>(result.rules[200].front()), ::testing::Eq("deny")); + EXPECT_EQ("deny", std::get<1>(result.rules[200].front())); } +// Custom matcher to check if a variant holds a specific type +template +class HoldsAlternativeMatcher : public ::testing::MatcherInterface +{ +public: + bool MatchAndExplain(const common::RawAction& v, ::testing::MatchResultListener* listener) const override + { + return std::holds_alternative(v); + } + + void DescribeTo(std::ostream* os) const override + { + *os << "holds alternative of type " << typeid(T).name(); + } +}; + +template +::testing::Matcher HoldsAlternative() +{ + return ::testing::MakeMatcher(new HoldsAlternativeMatcher()); +} + +::testing::Matcher IsCheckStateAction() +{ + return HoldsAlternative(); +} + +::testing::Matcher IsFlowAction() +{ + return HoldsAlternative(); +} + +::testing::Matcher IsDumpAction() +{ + return HoldsAlternative(); +} + +using common::ActionsPath; +using common::BaseActions; + template constexpr bool is_with_check_state() { - return std::is_same_v, common::BaseActions>; + return std::is_same_v, BaseActions>; +} + +const common::RawAction& regular_path_action(const common::Actions& actions, size_t idx) +{ + return std::visit([idx](const auto& action_variant) -> const common::RawAction& { + return action_variant.get_actions()[idx].raw_action; + }, + actions); +} + +const common::RawAction& regular_path_first_action(const common::Actions& actions) +{ + return regular_path_action(actions, 0); +} + +const common::RawAction& check_state_path_last_action(const common::Actions& actions) +{ + if (const auto& check_state_actions = std::get_if>(&actions)) + { + return check_state_actions->get_check_state_actions().back().raw_action; + } + + throw std::runtime_error("Attempted to get check-state action from Default path"); } TEST_F(ACL, 019_CheckStateBasic) @@ -473,11 +538,11 @@ add 300 deny ip from any to any { // Check that the regular path does not include the check-state action EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_FALSE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_THAT(regular_path_first_action(actions), Not(IsCheckStateAction())); // Check that the check-state path includes the check-state action EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); } }); } @@ -500,12 +565,12 @@ add 400 deny ip from any to any { // Check that the regular path includes the actions after the first and second check-states EXPECT_THAT(actions.get_actions().size(), 2); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[1].raw_action)); + EXPECT_THAT(regular_path_action(actions, 0), IsDumpAction()); + EXPECT_THAT(regular_path_action(actions, 1), IsFlowAction()); // Check that the check-state path includes the first check-state action and no other actions EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); } }); } @@ -529,14 +594,14 @@ add 500 deny ip from any to any { // Check that the regular path includes actions before and after the check-state EXPECT_THAT(actions.get_actions().size(), 3); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[1].raw_action)); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[2].raw_action)); + EXPECT_THAT(regular_path_action(actions, 0), IsDumpAction()); + EXPECT_THAT(regular_path_action(actions, 1), IsDumpAction()); + EXPECT_THAT(regular_path_action(actions, 2), IsFlowAction()); // Check that the check-state path includes actions up to and including the check-state action EXPECT_THAT(actions.get_check_state_actions().size(), 2); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[0].raw_action)); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions()[1].raw_action)); + EXPECT_THAT(actions.get_check_state_actions()[0].raw_action, IsDumpAction()); + EXPECT_THAT(actions.get_check_state_actions()[1].raw_action, IsCheckStateAction()); } }); } @@ -556,11 +621,11 @@ add deny ip from any to any { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); // Check that the check-state path includes the check-state action EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); } }); } @@ -581,11 +646,11 @@ add deny ip from any to any { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); // Check that the check-state path includes the check-state action EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); } }); } @@ -608,11 +673,11 @@ add allow ip from any to any keep-state { // Check that the regular path includes the allow action EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_actions()[0].raw_action)); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); // Check that the check-state path includes the check-state action EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); } }); } From 070bddd883448a06a51244addcba8468dd064adf Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 19 Sep 2024 13:24:04 +0400 Subject: [PATCH 120/195] Apply ACL test refactoring features to StateTiemout tests --- controlplane/unittest/acl.cpp | 137 ++++++++++++++-------------------- 1 file changed, 54 insertions(+), 83 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index f761cb6a..879ad7a9 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -682,120 +682,91 @@ add allow ip from any to any keep-state }); } -TEST(ACL, StateTimeout_Basic) +TEST_F(ACL, StateTimeout_Basic) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add state-timeout 5000 ip from any to any add allow ip from any to any keep-state )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 1); - for (const auto& [total_table_key, total_table_value] : result.acl_total_table) - { - (void)total_table_key; + visit_actions([&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); + const auto& flow_action = std::get(regular_path_first_action(actions)); + EXPECT_EQ(flow_action.timeout, 5000); - const auto& value = result.acl_values[total_table_value]; - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - const auto& flow_action = std::get(actions.get_actions()[0].raw_action); - EXPECT_EQ(flow_action.timeout, 5000); - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); + } + }); } -TEST(ACL, StateTimeout_RestrictiveSubset) +TEST_F(ACL, StateTimeout_RestrictiveSubset) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add state-timeout 8000 ip from any to any add state-timeout 3000 ip from 192.168.1.0/24 to any add allow ip from any to any keep-state )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 2); - { - // First group, ip not in 192.168.1.0/24 - auto total_table_value = std::get<1>(result.acl_total_table[0]); - const auto& value = result.acl_values[total_table_value]; + // First group, ip not in 192.168.1.0/24 + visit_action_group(0, [&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); + const auto& flow_action = std::get(regular_path_first_action(actions)); + EXPECT_EQ(flow_action.timeout, 8000); - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - const auto& flow_action = std::get(actions.get_actions()[0].raw_action); - EXPECT_EQ(flow_action.timeout, 8000); - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } - { - // Second group, ip is in 192.168.1.0/24 - auto total_table_value = std::get<1>(result.acl_total_table[1]); - const auto& value = result.acl_values[total_table_value]; + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); + } + }); - std::visit([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - - const auto& flow_action = std::get(actions.get_actions()[0].raw_action); - EXPECT_EQ(flow_action.timeout, 3000); // Verify that the timeout for 192.168.1.0/24 is 3000 - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_TRUE(std::holds_alternative(actions.get_check_state_actions().back().raw_action)); - } - }, - value); - } + // Second group, ip is in 192.168.1.0/24 + visit_action_group(1, [&](const auto& actions) { + if constexpr (is_with_check_state()) + { + // Check that the regular path includes the allow action with the correct timeout + EXPECT_THAT(actions.get_actions().size(), 1); + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); + const auto& flow_action = std::get(regular_path_first_action(actions)); + EXPECT_EQ(flow_action.timeout, 3000); // Verify that the timeout for 192.168.1.0/24 is 3000 + + // Check that the check-state path includes only check-state action + EXPECT_THAT(actions.get_check_state_actions().size(), 1); + EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); + } + }); } -TEST(ACL, StateTimeout_NoTimeout) +TEST_F(ACL, StateTimeout_NoTimeout) { - auto fw = make_default_acl(R"IPFW( + compile_acl(R"IPFW( :BEGIN add allow ip from any to any )IPFW"); - std::map acls{{"acl0", std::move(fw)}}; - acl::result_t result; - acl::compile(acls, {{1, {{true, "vlan1"}}}}, result); - ASSERT_EQ(result.acl_total_table.size(), 1); - auto total_table_value = std::get<1>(result.acl_total_table[0]); - const auto& value = result.acl_values[total_table_value]; - - const auto& last_action = std::visit([&](const auto& actions) { return actions.get_last(); }, value); - const auto& flow_action = std::get(last_action.raw_action); - // Check that by default timeout in flow_action is std::nullopt - EXPECT_EQ(flow_action.timeout, std::nullopt); + visit_actions([&](const auto& actions) { + EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); + const auto& flow_action = std::get(regular_path_first_action(actions)); + // Check that by default timeout in flow_action is std::nullopt + EXPECT_EQ(flow_action.timeout, std::nullopt); + }); } } // namespace From 044c58e3041ffab1c791478266fa10464f2d2fe7 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 19 Sep 2024 18:43:41 +0400 Subject: [PATCH 121/195] Move paths validation from tests main body to compile_acl Moved path validation logic into `compile_acl` to reduce code duplication. Also using newly added methods to `BaseActions` for cleaner access to default and check-state paths. --- controlplane/unittest/acl.cpp | 255 +++++++++++----------------------- 1 file changed, 79 insertions(+), 176 deletions(-) diff --git a/controlplane/unittest/acl.cpp b/controlplane/unittest/acl.cpp index 879ad7a9..623b3650 100644 --- a/controlplane/unittest/acl.cpp +++ b/controlplane/unittest/acl.cpp @@ -64,6 +64,43 @@ add deny ip from any to any return rules; } +// Custom matcher to check if a variant holds a specific type +template +class HoldsAlternativeMatcher : public ::testing::MatcherInterface +{ +public: + bool MatchAndExplain(const common::RawAction& v, ::testing::MatchResultListener* listener) const override + { + return std::holds_alternative(v); + } + + void DescribeTo(std::ostream* os) const override + { + *os << "holds alternative of type " << typeid(T).name(); + } +}; + +template +::testing::Matcher HoldsAlternative() +{ + return ::testing::MakeMatcher(new HoldsAlternativeMatcher()); +} + +::testing::Matcher IsCheckStateAction() +{ + return HoldsAlternative(); +} + +::testing::Matcher IsFlowAction() +{ + return HoldsAlternative(); +} + +::testing::Matcher IsDumpAction() +{ + return HoldsAlternative(); +} + class ACL : public ::testing::Test { protected: @@ -76,6 +113,8 @@ class ACL : public ::testing::Test std::map acls{{"acl0", std::move(fw)}}; acl::compile(acls, iface_map, result); + + validate_paths(); } // Helper function to visit a specific group based on its index @@ -98,6 +137,26 @@ class ACL : public ::testing::Test visit_action_group(group_index, std::forward(func)); } } + + template + static constexpr bool is_with_check_state() + { + return std::is_same_v, common::BaseActions>; + } + + void validate_paths() + { + visit_actions([&](const auto& actions) { + // Default path should always end with a FlowAction + EXPECT_THAT(actions.default_path_last_raw_action(), IsFlowAction()); + + if constexpr (is_with_check_state()) + { + // Check-state path should always end with CheckStateAction + EXPECT_THAT(actions.check_state_path_last_raw_action(), IsCheckStateAction()); + } + }); + } }; class ACLWithUnwind : public ACL @@ -359,7 +418,7 @@ add 300 deny ip from any to any EXPECT_EQ("port0 |0|any|any|any|any|any|any|any|false|drop(0)|2|true|", stringify(unwind_result[2])); visit_actions([&](const auto& actions) { - EXPECT_EQ(actions.get_flow().flags, common::globalBase::eFlowFlags::log); + EXPECT_EQ(actions.get_flow().flags, static_cast(common::globalBase::eFlowFlags::log)); }); auto& ids_map = result.ids_map; @@ -453,75 +512,6 @@ add 200 deny ip from any to any EXPECT_EQ("deny", std::get<1>(result.rules[200].front())); } -// Custom matcher to check if a variant holds a specific type -template -class HoldsAlternativeMatcher : public ::testing::MatcherInterface -{ -public: - bool MatchAndExplain(const common::RawAction& v, ::testing::MatchResultListener* listener) const override - { - return std::holds_alternative(v); - } - - void DescribeTo(std::ostream* os) const override - { - *os << "holds alternative of type " << typeid(T).name(); - } -}; - -template -::testing::Matcher HoldsAlternative() -{ - return ::testing::MakeMatcher(new HoldsAlternativeMatcher()); -} - -::testing::Matcher IsCheckStateAction() -{ - return HoldsAlternative(); -} - -::testing::Matcher IsFlowAction() -{ - return HoldsAlternative(); -} - -::testing::Matcher IsDumpAction() -{ - return HoldsAlternative(); -} - -using common::ActionsPath; -using common::BaseActions; - -template -constexpr bool is_with_check_state() -{ - return std::is_same_v, BaseActions>; -} - -const common::RawAction& regular_path_action(const common::Actions& actions, size_t idx) -{ - return std::visit([idx](const auto& action_variant) -> const common::RawAction& { - return action_variant.get_actions()[idx].raw_action; - }, - actions); -} - -const common::RawAction& regular_path_first_action(const common::Actions& actions) -{ - return regular_path_action(actions, 0); -} - -const common::RawAction& check_state_path_last_action(const common::Actions& actions) -{ - if (const auto& check_state_actions = std::get_if>(&actions)) - { - return check_state_actions->get_check_state_actions().back().raw_action; - } - - throw std::runtime_error("Attempted to get check-state action from Default path"); -} - TEST_F(ACL, 019_CheckStateBasic) { compile_acl(R"IPFW( @@ -532,19 +522,6 @@ add 300 deny ip from any to any )IPFW"); ASSERT_EQ(result.acl_total_table.size(), 2); - - visit_actions([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path does not include the check-state action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), Not(IsCheckStateAction())); - - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } - }); } TEST_F(ACL, 020_ManyCheckStates) @@ -563,14 +540,10 @@ add 400 deny ip from any to any visit_action_group(1, [&](const auto& actions) { if constexpr (is_with_check_state()) { - // Check that the regular path includes the actions after the first and second check-states - EXPECT_THAT(actions.get_actions().size(), 2); - EXPECT_THAT(regular_path_action(actions, 0), IsDumpAction()); - EXPECT_THAT(regular_path_action(actions, 1), IsFlowAction()); - - // Check that the check-state path includes the first check-state action and no other actions - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); + // Check that the default path includes the actions after the first and second check-states + EXPECT_THAT(actions.default_path_size(), 2); + EXPECT_THAT(actions.default_path_raw_action(0), IsDumpAction()); + EXPECT_THAT(actions.default_path_raw_action(1), IsFlowAction()); } }); } @@ -592,16 +565,16 @@ add 500 deny ip from any to any visit_action_group(1, [&](const auto& actions) { if constexpr (is_with_check_state()) { - // Check that the regular path includes actions before and after the check-state - EXPECT_THAT(actions.get_actions().size(), 3); - EXPECT_THAT(regular_path_action(actions, 0), IsDumpAction()); - EXPECT_THAT(regular_path_action(actions, 1), IsDumpAction()); - EXPECT_THAT(regular_path_action(actions, 2), IsFlowAction()); + // Check that the default path includes actions before and after the check-state + EXPECT_THAT(actions.default_path_size(), 3); + EXPECT_THAT(actions.default_path_raw_action(0), IsDumpAction()); + EXPECT_THAT(actions.default_path_raw_action(1), IsDumpAction()); + EXPECT_THAT(actions.default_path_raw_action(2), IsFlowAction()); // Check that the check-state path includes actions up to and including the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 2); - EXPECT_THAT(actions.get_check_state_actions()[0].raw_action, IsDumpAction()); - EXPECT_THAT(actions.get_check_state_actions()[1].raw_action, IsCheckStateAction()); + EXPECT_THAT(actions.check_state_path_size(), 2); + EXPECT_THAT(actions.check_state_path_raw_action(0), IsDumpAction()); + EXPECT_THAT(actions.check_state_path_raw_action(1), IsCheckStateAction()); } }); } @@ -615,19 +588,6 @@ add deny ip from any to any )IPFW"); ASSERT_EQ(result.acl_total_table.size(), 1); - - visit_actions([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } - }); } TEST_F(ACL, KeepState_MultipleRules) @@ -640,19 +600,6 @@ add deny ip from any to any )IPFW"); ASSERT_EQ(result.acl_total_table.size(), 2); - - visit_actions([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } - }); } TEST_F(ACL, KeepState_WithSkipTo) @@ -667,19 +614,6 @@ add allow ip from any to any keep-state )IPFW"); ASSERT_EQ(result.acl_total_table.size(), 2); - - visit_actions([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - - // Check that the check-state path includes the check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } - }); } TEST_F(ACL, StateTimeout_Basic) @@ -693,18 +627,8 @@ add allow ip from any to any keep-state ASSERT_EQ(result.acl_total_table.size(), 1); visit_actions([&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - const auto& flow_action = std::get(regular_path_first_action(actions)); - EXPECT_EQ(flow_action.timeout, 5000); - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } + const auto& flow_action = std::get(actions.default_path_last_raw_action()); + EXPECT_EQ(flow_action.timeout, 5000); }); } @@ -721,34 +645,14 @@ add allow ip from any to any keep-state // First group, ip not in 192.168.1.0/24 visit_action_group(0, [&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - const auto& flow_action = std::get(regular_path_first_action(actions)); - EXPECT_EQ(flow_action.timeout, 8000); - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } + const auto& flow_action = std::get(actions.default_path_last_raw_action()); + EXPECT_EQ(flow_action.timeout, 8000); }); // Second group, ip is in 192.168.1.0/24 visit_action_group(1, [&](const auto& actions) { - if constexpr (is_with_check_state()) - { - // Check that the regular path includes the allow action with the correct timeout - EXPECT_THAT(actions.get_actions().size(), 1); - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - const auto& flow_action = std::get(regular_path_first_action(actions)); - EXPECT_EQ(flow_action.timeout, 3000); // Verify that the timeout for 192.168.1.0/24 is 3000 - - // Check that the check-state path includes only check-state action - EXPECT_THAT(actions.get_check_state_actions().size(), 1); - EXPECT_THAT(check_state_path_last_action(actions), IsCheckStateAction()); - } + const auto& flow_action = std::get(actions.default_path_last_raw_action()); + EXPECT_EQ(flow_action.timeout, 3000); // Verify that the timeout for 192.168.1.0/24 is 3000 }); } @@ -762,8 +666,7 @@ add allow ip from any to any ASSERT_EQ(result.acl_total_table.size(), 1); visit_actions([&](const auto& actions) { - EXPECT_THAT(regular_path_first_action(actions), IsFlowAction()); - const auto& flow_action = std::get(regular_path_first_action(actions)); + const auto& flow_action = std::get(actions.default_path_last_raw_action()); // Check that by default timeout in flow_action is std::nullopt EXPECT_EQ(flow_action.timeout, std::nullopt); }); From a69935d194222fdf5697d3bf0ad46821609fa6d8 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 18:47:23 +0400 Subject: [PATCH 122/195] Refactor rule_t constructors with templated variant handler Replaced multiple constructors of `rule_t` with a single templated constructor to handle all variants of `rule_action`. This reduces code duplication. Constructor for `skipto` remains unchanged. --- controlplane/acl/rule.h | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index e82c2235..6e03740f 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -1048,28 +1048,14 @@ struct rule_t std::set via; bool log; -private: - rule_t(const ref_t& _filter, rule_action _action, ids_t _ids, bool _log) : - filter(_filter), action(std::move(_action)), ids(std::move(_ids)), ruleno(DISPATCHER), log(_log) - {} - public: - rule_t(const ref_t& _filter, common::globalBase::tFlow flow, const ids_t& ids, bool log) : - rule_t(_filter, rule_action(flow), ids, log) - {} - - rule_t(const ref_t& _filter, common::acl::dump_t action, const ids_t& ids, bool log) : - rule_t(_filter, rule_action(action), ids, log) - {} - - rule_t(const ref_t& _filter, common::acl::check_state_t action, const ids_t& ids, bool log) : - rule_t(_filter, rule_action(action), ids, log) - {} - - rule_t(const ref_t& _filter, common::acl::state_timeout_t action, const ids_t& ids, bool log) : - rule_t(_filter, rule_action(action), ids, log) + // Templated constructor to handle all variants of rule_action + template + rule_t(const ref_t& _filter, T action, ids_t ids, bool log) : + filter(_filter), action(rule_action(action)), ids(std::move(ids)), ruleno(DISPATCHER), log(log) {} + // Specialized constructor for skipto rule_t(const ref_t& _filter, int64_t num, int64_t skipto) : filter(_filter), action(skipto), From 01d2e3dd4fdbfd7655ac101c90167c54250018e3 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 25 Sep 2024 21:09:39 +0400 Subject: [PATCH 123/195] Clean rib default in 075_counters_route test --- autotest/units/001_one_port/075_counters_route/autotest.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autotest/units/001_one_port/075_counters_route/autotest.yaml b/autotest/units/001_one_port/075_counters_route/autotest.yaml index 332abc61..f9f81f55 100644 --- a/autotest/units/001_one_port/075_counters_route/autotest.yaml +++ b/autotest/units/001_one_port/075_counters_route/autotest.yaml @@ -83,3 +83,7 @@ steps: - cli: - telegraf route + +# cleanup +- cli: | + rib static remove default 0.0.0.0/0 200.0.2.1 From 907215ccad21ba87bdb05f9e652c23e095f946a1 Mon Sep 17 00:00:00 2001 From: Boris Litvinenko Date: Wed, 2 Oct 2024 12:48:58 +0300 Subject: [PATCH 124/195] remove announce on yanet-cli problem --- yanet-announcer.py | 69 +++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/yanet-announcer.py b/yanet-announcer.py index 6318b450..c4bb6325 100755 --- a/yanet-announcer.py +++ b/yanet-announcer.py @@ -146,19 +146,25 @@ def bgp_remove_ipv6(prefix): Executer.run(command) -def bgp_update(prefix): - if ":" in prefix: - bgp_update_ipv6(prefix) - else: - bgp_update_ipv4(prefix) - - -def bgp_remove(prefix): - if ":" in prefix: - bgp_remove_ipv6(prefix) - else: - bgp_remove_ipv4(prefix) +def bgp_update(prefix_list): + for prefix in prefix_list: + try: + if ":" in prefix: + bgp_update_ipv6(prefix) + else: + bgp_update_ipv4(prefix) + except Exception as error: + LOGGER.error("Can not update bgp prefix: %s with error: %s", prefix, error) +def bgp_remove(prefix_list): + for prefix in prefix_list: + try: + if ":" in prefix: + bgp_remove_ipv6(prefix) + else: + bgp_remove_ipv4(prefix) + except Exception as error: + LOGGER.error("Can not remove bgp prefix: %s with error: %s", prefix, error) def get_announces(types): for type in types: @@ -458,7 +464,8 @@ def main(): signal.signal(signal.SIGTERM, signal_handler) current_prefixes = [] - report_counter: int = 0 + report_config_counter: int = 0 + report_getannounces_counter: int = 0 is_firewall_machine: bool = False try: @@ -475,10 +482,11 @@ def main(): try: update_config() + report_config_counter = 0 except Exception as error: - if report_counter % 25 == 0: + if report_config_counter == 0: LOGGER.error("Fail: %s", error) - report_counter += 1 + report_config_counter = 1 time.sleep(1) continue @@ -489,34 +497,31 @@ def main(): if check_module(module): prefixes.extend(module["announces"]) - except: - pass + report_getannounces_counter = 0 + except Exception as error: + if report_getannounces_counter == 0: + LOGGER.error("Can not get announces with error: %s", error) + report_getannounces_counter = 1 + if len(current_prefixes) > 0: + LOGGER.warning( + "Problem with get_announce(dp/cp in down state?), remove current announces: %s", current_prefixes + ) + bgp_remove(current_prefixes) if is_firewall_machine and check_firewall_module(): prefixes.extend(["firewall::/128"]) - for prefix in list(set(prefixes) - set(current_prefixes)): - try: - bgp_update(prefix) - except: - pass + bgp_update(list(set(prefixes) - set(current_prefixes))) - for prefix in list(set(current_prefixes) - set(prefixes)): - try: - bgp_remove(prefix) - except: - pass + bgp_remove(list(set(current_prefixes) - set(prefixes))) if not OPTIONS.daemon: return current_prefixes = prefixes if SIGNAL_RECV: - for prefix in current_prefixes: - try: - bgp_remove(prefix) - except: - pass + LOGGER.warning("Detect SIGNAL_RECV, remove announces and exit...") + bgp_remove(current_prefixes) return time.sleep(1) From 9459d235758011f9c5b0fe2535de469c44694551 Mon Sep 17 00:00:00 2001 From: Boris Litvinenko Date: Wed, 2 Oct 2024 12:52:33 +0300 Subject: [PATCH 125/195] black run --- yanet-announcer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yanet-announcer.py b/yanet-announcer.py index c4bb6325..e0d59719 100755 --- a/yanet-announcer.py +++ b/yanet-announcer.py @@ -156,6 +156,7 @@ def bgp_update(prefix_list): except Exception as error: LOGGER.error("Can not update bgp prefix: %s with error: %s", prefix, error) + def bgp_remove(prefix_list): for prefix in prefix_list: try: @@ -166,6 +167,7 @@ def bgp_remove(prefix_list): except Exception as error: LOGGER.error("Can not remove bgp prefix: %s with error: %s", prefix, error) + def get_announces(types): for type in types: table_decap = Executer.get(f"yanet-cli {type}") From 16a5443301da0471b57931586013f67a4df8079e Mon Sep 17 00:00:00 2001 From: Boris Litvinenko Date: Wed, 2 Oct 2024 18:46:47 +0300 Subject: [PATCH 126/195] use ipaddress --- yanet-announcer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/yanet-announcer.py b/yanet-announcer.py index e0d59719..34fb0eea 100755 --- a/yanet-announcer.py +++ b/yanet-announcer.py @@ -7,6 +7,7 @@ import logging import signal import subprocess +import ipaddress import textwrap import time import typing @@ -149,7 +150,8 @@ def bgp_remove_ipv6(prefix): def bgp_update(prefix_list): for prefix in prefix_list: try: - if ":" in prefix: + parsed = ipaddress.ip_network(prefix) + if parsed.version == 6: bgp_update_ipv6(prefix) else: bgp_update_ipv4(prefix) @@ -160,7 +162,8 @@ def bgp_update(prefix_list): def bgp_remove(prefix_list): for prefix in prefix_list: try: - if ":" in prefix: + parsed = ipaddress.ip_network(prefix) + if parsed.version == 6: bgp_remove_ipv6(prefix) else: bgp_remove_ipv4(prefix) From 719c87ef1776f2f9b86608af1113877805e0c836 Mon Sep 17 00:00:00 2001 From: Boris Litvinenko Date: Thu, 3 Oct 2024 13:31:56 +0300 Subject: [PATCH 127/195] processing firewall prefix in yanet-announcer --- yanet-announcer.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/yanet-announcer.py b/yanet-announcer.py index 34fb0eea..cd1e9098 100755 --- a/yanet-announcer.py +++ b/yanet-announcer.py @@ -68,7 +68,7 @@ def get(command: str) -> typing.List[typing.Dict[str, str]]: # don't use generator output, because LRU cache return wrong response parsed_output: typing.List[typing.Dict[str, str]] = [] - out = subprocess.check_output(command, shell=True).decode("ascii").splitlines() + out = subprocess.check_output(command, shell=True, stderr=subprocess.DEVNULL).decode("ascii").splitlines() if len(out) <= 1: return parsed_output @@ -156,7 +156,11 @@ def bgp_update(prefix_list): else: bgp_update_ipv4(prefix) except Exception as error: - LOGGER.error("Can not update bgp prefix: %s with error: %s", prefix, error) + if "firewall" in prefix: + bgp_update_ipv6(prefix) + LOGGER.info("Update bgp with custom prefix: %s", prefix) + else: + LOGGER.error("Can not update bgp prefix: %s with error: %s", prefix, error) def bgp_remove(prefix_list): @@ -168,7 +172,11 @@ def bgp_remove(prefix_list): else: bgp_remove_ipv4(prefix) except Exception as error: - LOGGER.error("Can not remove bgp prefix: %s with error: %s", prefix, error) + if "firewall" in prefix: + bgp_remove_ipv6(prefix) + LOGGER.info("Remove bgp with custom prefix: %s", prefix) + else: + LOGGER.error("Can not remove bgp prefix: %s with error: %s", prefix, error) def get_announces(types): @@ -512,6 +520,8 @@ def main(): "Problem with get_announce(dp/cp in down state?), remove current announces: %s", current_prefixes ) bgp_remove(current_prefixes) + current_prefixes = [] + continue if is_firewall_machine and check_firewall_module(): prefixes.extend(["firewall::/128"]) From c116973b3bcdaeba3ee5e2e80c8c916aca041fcb Mon Sep 17 00:00:00 2001 From: vimes Date: Mon, 23 Sep 2024 11:00:47 +0300 Subject: [PATCH 128/195] Fixes port mixup while forwarding packets to slow worker --- dataplane/base.h | 21 +++++ dataplane/controlplane.h | 8 -- dataplane/dataplane.cpp | 120 ++++++++++++++++--------- dataplane/dataplane.h | 10 ++- dataplane/dpdk.cpp | 28 ++++++ dataplane/dpdk.h | 8 +- dataplane/kernel_interface_handle.cpp | 25 +++--- dataplane/kernel_interface_handle.h | 3 +- dataplane/kernel_interface_handler.cpp | 55 +++++++++--- dataplane/kernel_interface_handler.h | 13 ++- dataplane/meson.build | 1 + dataplane/worker.cpp | 30 +++---- dataplane/worker.h | 2 + 13 files changed, 222 insertions(+), 102 deletions(-) create mode 100644 dataplane/dpdk.cpp diff --git a/dataplane/base.h b/dataplane/base.h index 1222aa40..a6de2202 100644 --- a/dataplane/base.h +++ b/dataplane/base.h @@ -22,13 +22,33 @@ class PortMapper uint16_t ports_count_ = 0; tPortId dpdk_ports_[std::numeric_limits::max() + 1]; // logical to dpdk tPortId logical_ports_[std::numeric_limits::max() + 1]; // dpdk to logical + public: PortMapper() { std::fill(std::begin(dpdk_ports_), std::end(dpdk_ports_), INVALID_PORT_ID); std::fill(std::begin(logical_ports_), std::end(logical_ports_), INVALID_PORT_ID); } + + PortMapper(const PortMapper& other) + { + *this = other; + } + + PortMapper& operator=(const PortMapper& other) + { + ports_count_ = other.ports_count_; + std::copy(std::begin(other.dpdk_ports_), + std::end(other.dpdk_ports_), + std::begin(dpdk_ports_)); + std::copy(std::begin(other.logical_ports_), + std::end(other.logical_ports_), + std::begin(logical_ports_)); + return *this; + } + uint16_t size() const { return ports_count_; } + [[nodiscard]] std::optional Register(tPortId dpdk_port) { if (ports_count_ < CONFIG_YADECAP_PORTS_SIZE) @@ -51,6 +71,7 @@ class PortMapper return {}; } } + tPortId ToDpdk(tPortId logical) const { return dpdk_ports_[logical]; } tPortId ToLogical(tPortId dpdk) const { return logical_ports_[dpdk]; } bool ValidDpdk(tPortId dpdk) const { return logical_ports_[dpdk] != INVALID_PORT_ID; } diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 182aa590..17bc2cfe 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -138,14 +138,6 @@ class cControlPlane ///< @todo: move to cDataPlane bool use_kernel_interface; - struct KniHandleBundle - { - dataplane::KernelInterfaceHandle forward; - dataplane::KernelInterfaceHandle in_dump; - dataplane::KernelInterfaceHandle out_dump; - dataplane::KernelInterfaceHandle drop_dump; - }; - struct KniPortData { std::string interface_name; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index b443d3e7..3afd6cda 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -139,7 +139,14 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } - for (auto socket : socket_ids) + std::set slow_sockets; + for (auto [port, info] : ports) + { + (void)info; + slow_sockets.insert(rte_eth_dev_socket_id(port)); + } + + for (auto socket : slow_sockets) { auto pool = rte_mempool_create(("cp-" + std::to_string(socket)).c_str(), CONFIG_YADECAP_MBUFS_COUNT + @@ -241,6 +248,12 @@ eResult cDataPlane::init(const std::string& binaryPath, return result; } + result = initKniQueues(); + if (result != eResult::success) + { + return result; + } + result = controlPlane->init(config.use_kernel_interface); if (result != eResult::success) { @@ -525,7 +538,7 @@ eResult cDataPlane::initPorts() std::map rx_queues; uint16_t rxQueuesCount = 0; - uint16_t txQueuesCount = config.workers.size() + 1; ///< tx queue '0' for control plane + uint16_t txQueuesCount = config.workers.size() + config.controlplane_workers.size(); ///< last tx queue for control plane for (const auto& configWorkerIter : config.workers) { const tCoreId& coreId = configWorkerIter.first; @@ -620,6 +633,11 @@ void cDataPlane::StartInterfaces() { for (auto& [portid, handles] : kni_interface_handles) { + if (!handles.Start()) + { + YANET_LOG_ERROR("Failed to start kni interfaces"); + std::abort(); + } if (!handles.forward.SetUp()) { YANET_LOG_ERROR("Failed to set kni interface belonging to %s up", std::get<0>(ports.at(portid)).c_str()); @@ -637,15 +655,20 @@ eResult cDataPlane::init_kernel_interfaces() const auto& interface_name = std::get<0>(info); auto forward = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); - auto in = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); - auto out = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); - auto drop = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); + auto in = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("in." + interface_name, port_id, queue_size); + auto out = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("out." + interface_name, port_id, queue_size); + auto drop = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("drop." + interface_name, port_id, queue_size); if (!forward || !in || !out || !drop) { return eResult::errorAllocatingKernelInterface; } + forward->CloneMTU(port_id); + in->CloneMTU(port_id); + out->CloneMTU(port_id); + drop->CloneMTU(port_id); + kni_interface_handles.emplace(port_id, KniHandleBundle{std::move(forward.value()), std::move(in.value()), std::move(out.value()), std::move(drop.value())}); } @@ -802,8 +825,10 @@ eResult cDataPlane::initGlobalBases() }; /// slow worker + for (const auto& [core, _] : config.controlplane_workers) { - tSocketId socketId = rte_lcore_to_socket_id(config.controlPlaneCoreId); + (void)_; + tSocketId socketId = rte_lcore_to_socket_id(core); result = create_globalbase_atomics(socketId); if (result != eResult::success) @@ -824,7 +849,6 @@ eResult cDataPlane::initGlobalBases() { const tCoreId& coreId = configWorkerIter.first; tSocketId socketId = rte_lcore_to_socket_id(coreId); - result = create_globalbase_atomics(socketId); if (result != eResult::success) { @@ -1101,7 +1125,7 @@ eResult cDataPlane::initWorkers() return eResult::success; } -eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& cfg) +eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, tQueueId phy_queue) { const tSocketId socket_id = rte_lcore_to_socket_id(core); @@ -1119,7 +1143,7 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& dataplane::base::permanently basePermanently; basePermanently.globalBaseAtomic = globalBaseAtomics[socket_id]; - basePermanently.outQueueId = tx_queues_; + basePermanently.outQueueId = phy_queue; for (const auto& port : ports) { if (!basePermanently.ports.Register(port.first)) @@ -1149,16 +1173,17 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& for (auto& iface : cfg.interfaces) { tPortId port; - if (rte_eth_dev_get_port_by_name(iface.data(), &port)) + const auto name = std::get<0>(config.ports.at(iface.data())).c_str(); + if (rte_eth_dev_get_port_by_name(name, &port)) { - YANET_LOG_ERROR("Failed to get port id by interface name \"%s\"\n", iface.data()); + YANET_LOG_ERROR("Failed to get port id for interface \"%s\" by name \"%s\"\n", iface.data(), name); std::terminate(); } ports_to_service.push_back(port); auto& [fwd, in, out, drop] = kni_interface_handles.at(port); kni_bundleconf.emplace_back( dataplane::KernelInterfaceBundleConfig{ - {port, tx_queues_}, + {port, phy_queue}, {fwd.Id(), 0}, {in.Id(), 0}, {out.Id(), 0}, @@ -1167,14 +1192,12 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& std::stringstream ss; for (auto p : ports_to_service) { - ss << p; + ss << p << ' '; } YANET_LOG_INFO("controlplane worker on core %d, serving [%s]\n", core, ss.str().c_str()); } YANET_LOG_ERROR("ending with kni bundleconf\n"); - dataplane::KernelInterfaceWorkerConfig kni_config{std::move(kni_bundleconf), &basePermanently.ports}; - std::vector workers_to_service; for (auto& core : cfg.workers) { @@ -1190,7 +1213,7 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& std::vector> rings_from_gcs; for (auto& gccore : cfg.gcs) { - auto r = worker_gcs.at(gccore)->RegisterSlowWorker("cw" + core, + auto r = worker_gcs.at(gccore)->RegisterSlowWorker("cw" + std::to_string(core), config_values_.ring_normalPriority_size, config_values_.ring_toFreePackets_size); if (r) @@ -1207,7 +1230,7 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& std::move(ports_to_service), std::move(workers_to_service), std::move(rings_from_gcs), - kni_config, + dataplane::KernelInterfaceWorker{kni_bundleconf}, socket_cplane_mempools.at(socket_id), config.use_kernel_interface, config.SWICMPOutRateLimit); @@ -1216,20 +1239,33 @@ eResult cDataPlane::InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& return eResult::dataplaneIsBroken; } slow_workers.emplace(core, slow); - YANET_LOG_ERROR("slow workers size is %lu\n", slow_workers.size()); ++tx_queues_; return eResult::success; } +void cDataPlane::ChooseGCs(tCoreId core, CPlaneWorkerConfig& cfg) const +{ + for (const auto& gc : config.workerGCs) + { + if (rte_lcore_to_socket_id(gc) == rte_lcore_to_socket_id(core)) + { + cfg.gcs.insert(gc); + } + } +} + eResult cDataPlane::InitSlowWorkers() { + auto q = tx_queues_; for (auto& [core, cfg] : config.controlplane_workers) { - if (auto res = InitSlowWorker(core, cfg); res != eResult::success) + ChooseGCs(core, cfg); + if (auto res = InitSlowWorker(core, cfg, q--); res != eResult::success) { return res; } } + YANET_LOG_ERROR("slow workers size is %lu\n", slow_workers.size()); return eResult::success; } @@ -1288,16 +1324,15 @@ eResult cDataPlane::initKniQueues() for (auto& it : kni_interface_handles) { uint16_t port_id = it.first; - for (std::size_t i = 0, max = slow_workers.size(); i < max; ++i) + const auto& socket_id = rte_eth_dev_socket_id(port_id); + if (!KNIAddTxQueue(0, socket_id)) { - const auto& socket_id = rte_eth_dev_socket_id(port_id); - KNIAddTxQueue(i, socket_id); + return eResult::errorInitQueue; } - for (std::size_t i = 0, max = slow_workers.size(); i < max; ++i) + if (!KNIAddRxQueue(0, socket_id, socket_cplane_mempools.at(socket_id))) { - const auto& socket_id = rte_eth_dev_socket_id(port_id); - KNIAddRxQueue(i, socket_id, socket_cplane_mempools.at(socket_id)); + return eResult::errorInitQueue; } } return eResult::success; @@ -1495,8 +1530,11 @@ eResult cDataPlane::initSharedMemory() { workers_id.push_back(worker.first); } - // slow worker - workers_id.push_back(config.controlPlaneCoreId); + // slow workers + for (const auto& worker : config.controlplane_workers) + { + workers_id.push_back(worker.first); + } // workers gc for (const auto& coreId : config.workerGCs) { @@ -1536,8 +1574,9 @@ eResult cDataPlane::allocateSharedMemory() } /// slow worker + for (const auto& [coreId, _] : config.controlplane_workers) { - const int coreId = config.controlPlaneCoreId; + (void)_; auto socket_id = numa_node_of_cpu(coreId); if (socket_id == -1) @@ -1588,7 +1627,7 @@ eResult cDataPlane::allocateSharedMemory() it = shm_size_per_socket.emplace_hint(it, socket_id, 0); } - it->second += sizeof(dataplane::perf::tsc_deltas) * (num + ((int)socket_id == numa_node_of_cpu(config.controlPlaneCoreId))); + it->second += sizeof(dataplane::perf::tsc_deltas) * (num + 1); } /// allocating IPC shared memory @@ -2197,19 +2236,10 @@ std::optional> cDataPlane::parseControlPl } } - std::set gc_cores; - for (auto& gc_core : config.workerGCs) - { - if (rte_lcore_to_socket_id(gc_core) == rte_lcore_to_socket_id(core)) - { - gc_cores.insert(gc_core); - } - } - return std::make_pair(core, CPlaneWorkerConfig{std::move(worker_ports), std::move(worker_cores), - std::move(gc_cores)}); + {}}); } eResult cDataPlane::parseConfigValues(const nlohmann::json& json) @@ -2267,10 +2297,14 @@ eResult cDataPlane::checkConfig() return eResult::invalidConfigurationFile; } - if (config.controlPlaneCoreId >= std::thread::hardware_concurrency()) + for (auto& [core, _] : config.controlplane_workers) { - YADECAP_LOG_ERROR("invalid coreId: '%u'\n", config.controlPlaneCoreId); - return eResult::invalidConfigurationFile; + (void)_; + if (core >= std::thread::hardware_concurrency()) + { + YADECAP_LOG_ERROR("invalid coreId: '%u'\n", core); + return eResult::invalidConfigurationFile; + } } { @@ -2297,7 +2331,7 @@ eResult cDataPlane::checkConfig() const tCoreId& coreId = workerIter.first; if (coreId >= std::thread::hardware_concurrency() || - coreId == config.controlPlaneCoreId) + config.controlplane_workers.find(coreId) != config.controlplane_workers.end()) { YADECAP_LOG_ERROR("invalid coreId: '%u'\n", coreId); return eResult::invalidConfigurationFile; diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 453a8cec..fd8959aa 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -123,6 +123,7 @@ class cDataPlane protected: eResult parseConfig(const std::string& configFilePath); eResult parseJsonPorts(const nlohmann::json& json); + void ChooseGCs(tCoreId core, CPlaneWorkerConfig& cfg) const; std::optional> parseControlPlaneWorkers(const nlohmann::json& config); std::optional> parseControlPlaneWorker(const nlohmann::json& cpwj); nlohmann::json makeLegacyControlPlaneWorkerConfig(); @@ -148,7 +149,7 @@ class cDataPlane bool KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); eResult initGlobalBases(); eResult initWorkers(); - eResult InitSlowWorker(const tCoreId core, const CPlaneWorkerConfig& ports); + eResult InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& ports, tQueueId phy_queue); eResult InitSlowWorkers(); eResult initKniQueues(); eResult InitTxQueues(); @@ -182,6 +183,13 @@ class cDataPlane dataplane::KernelInterfaceHandle in_dump; dataplane::KernelInterfaceHandle out_dump; dataplane::KernelInterfaceHandle drop_dump; + bool Start() + { + return forward.Start() && + in_dump.Start() && + out_dump.Start() && + drop_dump.Start(); + } }; std::map kni_interface_handles; diff --git a/dataplane/dpdk.cpp b/dataplane/dpdk.cpp new file mode 100644 index 00000000..60a11cca --- /dev/null +++ b/dataplane/dpdk.cpp @@ -0,0 +1,28 @@ +#include + +namespace dpdk +{ + +std::optional GetNameByPort(tPortId pid) +{ + char cname[256]; + if (int res = rte_eth_dev_get_name_by_port(pid, cname); res) + { + YANET_LOG_ERROR("Failed to get name for port %d (%s)", pid, strerror(res)); + return std::nullopt; + } + return std::optional{cname}; +} + +std::optional GetMacAddress(tPortId pid) +{ + rte_ether_addr ether_addr; + if (int res = rte_eth_macaddr_get(pid, ðer_addr)) + { + YANET_LOG_ERROR("Failed to get MAC for port %d (%s)", pid, strerror(res)); + return std::nullopt; + } + return std::optional{ether_addr.addr_bytes}; +} + +} \ No newline at end of file diff --git a/dataplane/dpdk.h b/dataplane/dpdk.h index 26d24f59..f04a76ee 100644 --- a/dataplane/dpdk.h +++ b/dataplane/dpdk.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -75,9 +76,14 @@ struct Endpoint { tPortId port; tQueueId queue; - Endpoint() = default; + Endpoint() : + Endpoint(-1, -1) {} Endpoint(tPortId port, tQueueId queue) : port{port}, queue{queue} {} }; +std::optional GetNameByPort(tPortId pid); + +std::optional GetMacAddress(tPortId pid); + } // namespace dpdk diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp index 90d4c108..eeda1156 100644 --- a/dataplane/kernel_interface_handle.cpp +++ b/dataplane/kernel_interface_handle.cpp @@ -20,12 +20,12 @@ bool KernelInterfaceHandle::SetUp() const noexcept struct ifreq request; memset(&request, 0, sizeof request); - strncpy(request.ifr_name, vdev_name_.data(), IFNAMSIZ); + strncpy(request.ifr_name, name_.data(), IFNAMSIZ); request.ifr_flags |= IFF_UP; if (auto res = ioctl(socket, SIOCSIFFLAGS, &request)) { - YANET_LOG_ERROR("failed to set interface %s up, ioctl returned (%d)", vdev_name_.data(), res); + YANET_LOG_ERROR("failed to set interface %s up, ioctl returned (%d)", name_.data(), res); return false; } return true; @@ -61,6 +61,7 @@ KernelInterfaceHandle& KernelInterfaceHandle::operator=(KernelInterfaceHandle&& if (this != &other) { std::swap(kni_port_, other.kni_port_); + std::swap(name_, other.name_); std::swap(vdev_name_, other.vdev_name_); std::swap(queue_size_, other.queue_size_); } @@ -75,6 +76,7 @@ KernelInterfaceHandle::MakeKernelInterfaceHandle( { KernelInterfaceHandle kni; kni.queue_size_ = queue_size; + kni.name_ = name; kni.vdev_name_ = VdevName(name, port); std::string vdev_args = VdevArgs(name, port, queue_size); if (!kni.Add(kni.vdev_name_, vdev_args) || @@ -82,7 +84,7 @@ KernelInterfaceHandle::MakeKernelInterfaceHandle( { return std::nullopt; } - + YANET_LOG_INFO("Created vdev device %s (%d)\n", kni.name_.c_str(), kni.kni_port_); return std::optional{std::move(kni)}; } @@ -121,6 +123,7 @@ bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& YADECAP_LOG_ERROR("vdev interface '%s' not found\n", vdev_name.data()); return false; } + YANET_LOG_INFO("Successfully added vdev interface '%s' with pid %d (%s)\n", vdev_name.data(), kni_port_, args.data()); return true; } @@ -132,9 +135,7 @@ void KernelInterfaceHandle::Remove() noexcept rte_eth_conf KernelInterfaceHandle::DefaultConfig() noexcept { - rte_eth_conf eth_conf; - memset(ð_conf, 0, sizeof(eth_conf)); - return eth_conf; + return rte_eth_conf{}; } bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) @@ -151,14 +152,14 @@ bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) return true; } -bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) const noexcept +bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) noexcept { uint16_t mtu; - if (rte_eth_dev_get_mtu(port_id, &mtu) != 0) - return false; - - rte_eth_dev_set_mtu(kni_port_, mtu); - return true; + if (rte_eth_dev_get_mtu(port_id, &mtu)) + { + return (rte_eth_dev_set_mtu(kni_port_, mtu) == 0); + } + return false; } bool KernelInterfaceHandle::SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) noexcept diff --git a/dataplane/kernel_interface_handle.h b/dataplane/kernel_interface_handle.h index 653a772f..49dcb80b 100644 --- a/dataplane/kernel_interface_handle.h +++ b/dataplane/kernel_interface_handle.h @@ -10,6 +10,7 @@ namespace dataplane class KernelInterfaceHandle { tPortId kni_port_ = INVALID_PORT_ID; + std::string name_; std::string vdev_name_; uint16_t queue_size_ = 0; @@ -30,6 +31,7 @@ class KernelInterfaceHandle [[nodiscard]] bool SetUp() const noexcept; bool SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) noexcept; bool SetupTxQueue(tQueueId queue, tSocketId socket) noexcept; + bool CloneMTU(const uint16_t) noexcept; private: static std::string VdevName(std::string_view name, const tPortId port_id); @@ -38,7 +40,6 @@ class KernelInterfaceHandle void Remove() noexcept; static rte_eth_conf DefaultConfig() noexcept; bool Configure(const rte_eth_conf& eth_conf) noexcept; - bool CloneMTU(const uint16_t) const noexcept; void MarkInvalid() noexcept { kni_port_ = INVALID_PORT_ID; } [[nodiscard]] bool Valid() const { return kni_port_ != INVALID_PORT_ID; } }; diff --git a/dataplane/kernel_interface_handler.cpp b/dataplane/kernel_interface_handler.cpp index bd554ab0..a8a06e4d 100644 --- a/dataplane/kernel_interface_handler.cpp +++ b/dataplane/kernel_interface_handler.cpp @@ -81,11 +81,16 @@ void KernelInterfaceWorker::RecvFree(const KernelInterface& iface) rte_pktmbuf_free_bulk(burst, len); } -KernelInterfaceWorker::KernelInterfaceWorker(const KernelInterfaceWorkerConfig& config) : - port_mapper_{config.port_mapper} +KernelInterfaceWorker::KernelInterfaceWorker(std::vector& interfaces) { - for (const auto& iface : config.interfaces) + for (const auto& iface : interfaces) { + auto mapped = port_mapper_.Register(iface.phy.port); + if (!mapped || mapped != size_) + { + YANET_LOG_ERROR("Failed to register port with kernel interface worker (%d)\n", iface.phy.port); + abort(); + } phy_ports_[size_] = iface.phy.port; phy_queues_[size_] = iface.phy.queue; forward_[size_] = KernelInterface{iface.forward}; @@ -96,6 +101,27 @@ KernelInterfaceWorker::KernelInterfaceWorker(const KernelInterfaceWorkerConfig& } } +KernelInterfaceWorker::KernelInterfaceWorker(KernelInterfaceWorker&& other) +{ + *this = std::move(other); +} + +KernelInterfaceWorker& KernelInterfaceWorker::operator=(KernelInterfaceWorker&& other) +{ + size_ = std::exchange(other.size_, 0); + for (std::size_t i = 0; i < size_; ++i) + { + phy_ports_[i] = other.phy_ports_[i]; + phy_queues_[i] = other.phy_queues_[i]; + forward_[i] = other.forward_[i]; + in_dump_[i] = other.in_dump_[i]; + out_dump_[i] = other.out_dump_[i]; + drop_dump_[i] = other.drop_dump_[i]; + } + port_mapper_ = std::move(other.port_mapper_); + return *this; +} + KernelInterfaceWorker::ConstPortArrayRange KernelInterfaceWorker::PortsIds() const { @@ -169,9 +195,9 @@ void KernelInterfaceWorker::ForwardToPhy() } auto& stats = stats_[i]; - stats.opackets += transmitted; - stats.obytes += bytes; - stats.odropped += remain; + stats.ipackets += transmitted; + stats.ibytes += bytes; + stats.idropped += remain; } } @@ -179,13 +205,13 @@ void KernelInterfaceWorker::HandlePacketDump(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - if (!port_mapper_->ValidDpdk(metadata->flow.data.dump.id)) + if (!port_mapper_.ValidDpdk(metadata->flow.data.dump.id)) { unknown_dump_interface_++; rte_pktmbuf_free(mbuf); return; } - const auto local_port_id = port_mapper_->ToLogical(metadata->flow.data.dump.id); + const auto local_port_id = port_mapper_.ToLogical(metadata->flow.data.dump.id); using dumpType = common::globalBase::dump_type_e; switch (metadata->flow.data.dump.type) @@ -208,8 +234,17 @@ void KernelInterfaceWorker::HandlePacketDump(rte_mbuf* mbuf) void KernelInterfaceWorker::HandlePacketFromForwardingPlane(rte_mbuf* mbuf) { dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - - const auto i = port_mapper_->ToLogical(metadata->fromPortId); + if (!port_mapper_.ValidDpdk(metadata->fromPortId)) + { + if (unknown_forward_interface_ < 100 || unknown_forward_interface_ % 100 == 0) + { + YANET_LOG_ERROR("Failed to map dpdk port %d while handling packet from forwarding plane (occurance %ld)\n", metadata->fromPortId, unknown_forward_interface_); + } + ++unknown_forward_interface_; + rte_pktmbuf_free(mbuf); + return; + } + const auto i = port_mapper_.ToLogical(metadata->fromPortId); const auto& delta = forward_[i].PushTracked(mbuf); stats_[i].opackets += delta.packets; stats_[i].obytes += delta.bytes; diff --git a/dataplane/kernel_interface_handler.h b/dataplane/kernel_interface_handler.h index 3b6ce7df..c3b43728 100644 --- a/dataplane/kernel_interface_handler.h +++ b/dataplane/kernel_interface_handler.h @@ -53,12 +53,6 @@ struct KernelInterfaceBundleConfig dpdk::Endpoint drop_dump; }; -struct KernelInterfaceWorkerConfig -{ - std::vector interfaces; - dataplane::base::PortMapper* port_mapper; -}; - class KernelInterfaceWorker { public: @@ -76,8 +70,9 @@ class KernelInterfaceWorker PortArray in_dump_; PortArray out_dump_; PortArray drop_dump_; - const dataplane::base::PortMapper* port_mapper_; + dataplane::base::PortMapper port_mapper_; uint64_t unknown_dump_interface_ = 0; + uint64_t unknown_forward_interface_ = 0; /** * @brief Receive packets from interface and free them. @@ -86,7 +81,9 @@ class KernelInterfaceWorker void RecvFree(const KernelInterface& iface); public: - KernelInterfaceWorker(const KernelInterfaceWorkerConfig& config); + KernelInterfaceWorker(std::vector& config); + KernelInterfaceWorker(KernelInterfaceWorker&& other); + KernelInterfaceWorker& operator=(KernelInterfaceWorker&& other); ConstPortArrayRange PortsIds() const; ConstPortArrayRange PortsStats() const; std::optional> PortStats(tPortId pid) const; diff --git a/dataplane/meson.build b/dataplane/meson.build index 0bfe16c0..73962ecd 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -8,6 +8,7 @@ sources = files('bus.cpp', 'controlplane.cpp', 'dataplane.cpp', 'debug_latch.cpp', + 'dpdk.cpp', 'dregress.cpp', 'fragmentation.cpp', 'icmp_translations.cpp', diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index b696979d..861edc75 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -81,6 +81,17 @@ cWorker::~cWorker() } } +unsigned int cWorker::MempoolSize() const +{ + const auto& config = dataPlane->getConfigValues(); + unsigned int rx_points_factor = 2 * basePermanently.rx_points.size(); + return rx_points_factor * config.port_rx_queue_size + + rx_points_factor * config.port_tx_queue_size + + 2 * config.ring_highPriority_size + + 2 * config.ring_normalPriority_size + + 2 * config.ring_lowPriority_size; +} + eResult cWorker::init(const tCoreId& coreId, const dataplane::base::permanently& basePermanently, const dataplane::base::generation& base) @@ -95,11 +106,7 @@ eResult cWorker::init(const tCoreId& coreId, this->bases[currentBaseId] = base; this->bases[currentBaseId ^ 1] = base; - unsigned int elements_count = 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_rx_queue_size + - 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_tx_queue_size + - 2 * dataPlane->getConfigValues().ring_highPriority_size + - 2 * dataPlane->getConfigValues().ring_normalPriority_size + - 2 * dataPlane->getConfigValues().ring_lowPriority_size; + unsigned int elements_count = MempoolSize(); YADECAP_LOG_DEBUG("elements_count: %u\n", elements_count); @@ -199,20 +206,7 @@ void cWorker::start() /// @todo: prepare() - unsigned int mbufs_count_expect = 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_rx_queue_size + - 2 * basePermanently.rx_points.size() * dataPlane->getConfigValues().port_tx_queue_size + - 2 * dataPlane->getConfigValues().ring_highPriority_size + - 2 * dataPlane->getConfigValues().ring_normalPriority_size + - 2 * dataPlane->getConfigValues().ring_lowPriority_size; - unsigned int mbufs_count = rte_mempool_avail_count(mempool); - if (mbufs_count != mbufs_count_expect) - { - YADECAP_LOG_ERROR("mbufs_count: %u != %u\n", - mbufs_count, - mbufs_count_expect); - abort(); - } std::vector mbufs; mbufs.resize(mbufs_count); diff --git a/dataplane/worker.h b/dataplane/worker.h index e158641e..bc49d05c 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -63,6 +63,8 @@ class tStack class cWorker { + unsigned int MempoolSize() const; + public: cWorker(cDataPlane* dataPlane); ~cWorker(); From 0fd9130f741353b1cfb337e0d84116326950a583 Mon Sep 17 00:00:00 2001 From: vimes Date: Fri, 11 Oct 2024 14:23:03 +0300 Subject: [PATCH 129/195] Removes invalid error message --- dataplane/dataplane.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 3afd6cda..e434c628 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1196,7 +1196,6 @@ eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, } YANET_LOG_INFO("controlplane worker on core %d, serving [%s]\n", core, ss.str().c_str()); } - YANET_LOG_ERROR("ending with kni bundleconf\n"); std::vector workers_to_service; for (auto& core : cfg.workers) From eab59db6d49490e70411479718b665be1cd887ec Mon Sep 17 00:00:00 2001 From: vimes Date: Tue, 15 Oct 2024 17:42:18 +0300 Subject: [PATCH 130/195] Simplifies slow worker configuration for each controlplane worker one needs to provide only the core used for the worker and list of fast worker cores serviced. "controlPlaneWorkers": [ { "core": 42, "serviced_cores": [4, 2] } ] --- dataplane/dataplane.cpp | 261 ++++++++++---------------- dataplane/dataplane.h | 81 +++++--- dataplane/dpdk.cpp | 15 +- dataplane/dpdk.h | 1 + dataplane/kernel_interface_handle.cpp | 24 +-- dataplane/kernel_interface_handle.h | 7 +- dataplane/main.cpp | 2 +- 7 files changed, 178 insertions(+), 213 deletions(-) diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index e434c628..41d71f2a 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -140,10 +140,25 @@ eResult cDataPlane::init(const std::string& binaryPath, } std::set slow_sockets; - for (auto [port, info] : ports) + for (const auto& [core, serviced] : config.controlplane_workers) { - (void)info; - slow_sockets.insert(rte_eth_dev_socket_id(port)); + auto ifaces = config.WorkersInterfaces(serviced); + for (const auto& iface : ifaces) + { + std::string device_name = std::get<0>(config.ports.at(iface)); + if (StartsWith(device_name, SOCK_DEV_PREFIX)) + { + device_name = iface; + } + auto port = dpdk::GetPortByName(device_name); + if (!port) + { + YANET_LOG_ERROR("No port!\n"); + std::abort(); + } + slow_sockets.insert(rte_eth_dev_socket_id(port.value())); + } + slow_sockets.insert(rte_lcore_to_socket_id(core)); } for (auto socket : slow_sockets) @@ -650,14 +665,21 @@ void cDataPlane::StartInterfaces() eResult cDataPlane::init_kernel_interfaces() { const uint16_t queue_size = getConfigValues().kernel_interface_queue_size; + auto vdev_queues = config.VdevQueues(); for (const auto& [port_id, info] : ports) { const auto& interface_name = std::get<0>(info); + if (vdev_queues.find(interface_name) == vdev_queues.end()) + { + YANET_LOG_INFO("Not creating kernel interface for '%s'", interface_name.c_str()); + continue; + } + const auto& queues = vdev_queues.at(interface_name); - auto forward = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queue_size); - auto in = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("in." + interface_name, port_id, queue_size); - auto out = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("out." + interface_name, port_id, queue_size); - auto drop = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("drop." + interface_name, port_id, queue_size); + auto forward = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle(interface_name, port_id, queues, queue_size); + auto in = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("in." + interface_name, port_id, queues, queue_size); + auto out = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("out." + interface_name, port_id, queues, queue_size); + auto drop = dataplane::KernelInterfaceHandle::MakeKernelInterfaceHandle("drop." + interface_name, port_id, queues, queue_size); if (!forward || !in || !out || !drop) { @@ -669,41 +691,29 @@ eResult cDataPlane::init_kernel_interfaces() out->CloneMTU(port_id); drop->CloneMTU(port_id); - kni_interface_handles.emplace(port_id, KniHandleBundle{std::move(forward.value()), std::move(in.value()), std::move(out.value()), std::move(drop.value())}); + kni_interface_handles.emplace(port_id, KniHandleBundle{0, std::move(forward.value()), std::move(in.value()), std::move(out.value()), std::move(drop.value())}); } return eResult::success; } -bool cDataPlane::KNIAddTxQueue(tQueueId queue, tSocketId socket) +bool cDataPlane::KNIAddTxQueue(KniHandleBundle& bundle, tQueueId queue, tSocketId socket) { - for (auto& bundle : kni_interface_handles) - { - auto& [fwd, in, out, drop] = bundle.second; - if (!fwd.SetupTxQueue(queue, socket) || - !in.SetupTxQueue(queue, socket) || - !out.SetupTxQueue(queue, socket) || - !drop.SetupTxQueue(queue, socket)) - { - return false; - } - } - return true; + auto& [_, fwd, in, out, drop] = bundle; + (void)_; + return fwd.SetupTxQueue(queue, socket) && + in.SetupTxQueue(queue, socket) && + out.SetupTxQueue(queue, socket) && + drop.SetupTxQueue(queue, socket); } -bool cDataPlane::KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) +bool cDataPlane::KNIAddRxQueue(KniHandleBundle& bundle, tQueueId queue, tSocketId socket, rte_mempool* mempool) { - for (auto& bundle : kni_interface_handles) - { - auto& [fwd, in, out, drop] = bundle.second; - if (!fwd.SetupRxQueue(queue, socket, mempool) || - !in.SetupRxQueue(queue, socket, mempool) || - !out.SetupRxQueue(queue, socket, mempool) || - !drop.SetupRxQueue(queue, socket, mempool)) - { - return false; - } - } - return true; + auto& [_, fwd, in, out, drop] = bundle; + (void)_; + return fwd.SetupRxQueue(queue, socket, mempool) && + in.SetupRxQueue(queue, socket, mempool) && + out.SetupRxQueue(queue, socket, mempool) && + drop.SetupRxQueue(queue, socket, mempool); } eResult cDataPlane::initGlobalBases() @@ -1125,7 +1135,7 @@ eResult cDataPlane::initWorkers() return eResult::success; } -eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, tQueueId phy_queue) +eResult cDataPlane::InitSlowWorker(tCoreId core, const std::set& worker_cores, tQueueId phy_queue) { const tSocketId socket_id = rte_lcore_to_socket_id(core); @@ -1170,24 +1180,26 @@ eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, std::vector ports_to_service; if (config.use_kernel_interface) { - for (auto& iface : cfg.interfaces) + std::set interfaces = config.WorkersInterfaces(worker_cores); + for (auto& iface : interfaces) { - tPortId port; const auto name = std::get<0>(config.ports.at(iface.data())).c_str(); - if (rte_eth_dev_get_port_by_name(name, &port)) + auto port = dpdk::GetPortByName(name); + if (!port) { - YANET_LOG_ERROR("Failed to get port id for interface \"%s\" by name \"%s\"\n", iface.data(), name); + YANET_LOG_ERROR("No port\n"); std::terminate(); } - ports_to_service.push_back(port); - auto& [fwd, in, out, drop] = kni_interface_handles.at(port); + ports_to_service.push_back(port.value()); + auto& [kni_queue, fwd, in, out, drop] = kni_interface_handles.at(port.value()); kni_bundleconf.emplace_back( dataplane::KernelInterfaceBundleConfig{ - {port, phy_queue}, - {fwd.Id(), 0}, - {in.Id(), 0}, - {out.Id(), 0}, - {drop.Id(), 0}}); + {port.value(), phy_queue}, + {fwd.Id(), kni_queue}, + {in.Id(), kni_queue}, + {out.Id(), kni_queue}, + {drop.Id(), kni_queue}}); + ++kni_queue; } std::stringstream ss; for (auto p : ports_to_service) @@ -1198,19 +1210,32 @@ eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, } std::vector workers_to_service; - for (auto& core : cfg.workers) + for (auto& core : worker_cores) { - workers_to_service.push_back(workers.at(core)); + workers_to_service.push_back(cDataPlane::workers.at(core)); } - std::vector gcs_to_service; - for (auto& core : cfg.gcs) + std::vector gcs_to_service; + if (config.controlplane_workers.size() == 1) { - gcs_to_service.push_back(worker_gcs.at(core)); + for (auto gc : config.workerGCs) + { + gcs_to_service.push_back(gc); + } + } + else + { + for (auto gc : config.workerGCs) + { + if (rte_lcore_to_socket_id(gc) == rte_lcore_to_socket_id(core)) + { + gcs_to_service.push_back(gc); + } + } } std::vector> rings_from_gcs; - for (auto& gccore : cfg.gcs) + for (auto& gccore : gcs_to_service) { auto r = worker_gcs.at(gccore)->RegisterSlowWorker("cw" + std::to_string(core), config_values_.ring_normalPriority_size, @@ -1242,29 +1267,17 @@ eResult cDataPlane::InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& cfg, return eResult::success; } -void cDataPlane::ChooseGCs(tCoreId core, CPlaneWorkerConfig& cfg) const -{ - for (const auto& gc : config.workerGCs) - { - if (rte_lcore_to_socket_id(gc) == rte_lcore_to_socket_id(core)) - { - cfg.gcs.insert(gc); - } - } -} - eResult cDataPlane::InitSlowWorkers() { auto q = tx_queues_; for (auto& [core, cfg] : config.controlplane_workers) { - ChooseGCs(core, cfg); if (auto res = InitSlowWorker(core, cfg, q--); res != eResult::success) { return res; } } - YANET_LOG_ERROR("slow workers size is %lu\n", slow_workers.size()); + YANET_LOG_INFO("slow workers size is %lu\n", slow_workers.size()); return eResult::success; } @@ -1320,18 +1333,23 @@ eResult cDataPlane::InitRxQueues() eResult cDataPlane::initKniQueues() { - for (auto& it : kni_interface_handles) + for (auto& [port_id, bundle] : kni_interface_handles) { - uint16_t port_id = it.first; const auto& socket_id = rte_eth_dev_socket_id(port_id); - if (!KNIAddTxQueue(0, socket_id)) + for (tQueueId q = 0; q < bundle.queues; ++q) { - return eResult::errorInitQueue; + if (!KNIAddTxQueue(bundle, q, socket_id)) + { + return eResult::errorInitQueue; + } } - if (!KNIAddRxQueue(0, socket_id, socket_cplane_mempools.at(socket_id))) + for (tQueueId q = 0; q < bundle.queues; ++q) { - return eResult::errorInitQueue; + if (!KNIAddRxQueue(bundle, q, socket_id, socket_cplane_mempools.at(socket_id))) + { + return eResult::errorInitQueue; + } } } return eResult::success; @@ -2089,7 +2107,7 @@ eResult cDataPlane::parseJsonPorts(const nlohmann::json& json) return eResult::success; } -std::optional> cDataPlane::parseControlPlaneWorkers(const nlohmann::json& root) +std::optional>> cDataPlane::parseControlPlaneWorkers(const nlohmann::json& root) { nlohmann::json dflt; auto cpw = root.find("controlPlaneWorkers"); @@ -2101,7 +2119,7 @@ std::optional> cDataPlane::parseControlPla cpw = dflt.find("controlPlaneWorkers"); } - std::map result; + std::map> result; auto add_worker = [&](const nlohmann::json& j) { auto worker = parseControlPlaneWorker(j); @@ -2131,6 +2149,7 @@ std::optional> cDataPlane::parseControlPla } } } + return std::optional{std::move(result)}; } @@ -2138,25 +2157,10 @@ nlohmann::json cDataPlane::makeLegacyControlPlaneWorkerConfig() { nlohmann::json j; j["core"] = config.controlPlaneCoreId; - j["interfaces"] = workerInterfacesToService(); j["serviced_cores"] = FastWorkerCores(); return nlohmann::json{{"controlPlaneWorkers", j}}; } -std::set cDataPlane::workerInterfacesToService() -{ - std::set res; - for (const auto& p : config.workers) - { - const auto& ifaces = p.second; - for (const auto& i : ifaces) - { - res.emplace(i); - } - } - return res; -} - const std::set cDataPlane::FastWorkerCores() const { std::set cores; @@ -2170,7 +2174,7 @@ const std::set cDataPlane::FastWorkerCores() const return cores; } -std::optional> cDataPlane::parseControlPlaneWorker(const nlohmann::json& cpwj) +std::optional>> cDataPlane::parseControlPlaneWorker(const nlohmann::json& cpwj) { auto jcore = cpwj.find("core"); if (jcore == cpwj.end()) @@ -2184,30 +2188,7 @@ std::optional> cDataPlane::parseControlPl return std::nullopt; } tCoreId core = jcore.value(); - - auto jports = cpwj.find("interfaces"); - if (jports == cpwj.end()) - { - YADECAP_LOG_ERROR("controlPlaneWorker entry has no \"interfaces\" field\n"); - return std::nullopt; - } - - if (!jports.value().is_array()) - { - YADECAP_LOG_ERROR("controlPlaneWorker entry \"interfaces\" has invalid type.\n"); - return std::nullopt; - } - - std::set worker_ports; - for (auto j : jports.value()) - { - if (!j.is_string()) - { - YADECAP_LOG_ERROR("controlPlaneWorker entry \"interfaces\" contains invalid type."); - return std::nullopt; - } - worker_ports.insert(InterfaceName{j}); - } + std::set worker_cores; auto jworkers = cpwj.find("serviced_cores"); if (!jworkers.value().is_array()) @@ -2216,7 +2197,6 @@ std::optional> cDataPlane::parseControlPl return std::nullopt; } - std::set worker_cores; for (auto& j : jworkers.value()) { if (!j.is_number_unsigned()) @@ -2227,7 +2207,7 @@ std::optional> cDataPlane::parseControlPl tCoreId id = j; if (config.workers.find(id) == config.workers.end()) { - YANET_LOG_ERROR("controlPlaneWorker entry in \"serviced_cores\" is not a valid worker core id\n"); + YANET_LOG_ERROR("controlPlaneWorker entry %d in \"serviced_cores\" is not a valid worker core id\n", id); } if (!worker_cores.insert(id).second) { @@ -2235,10 +2215,7 @@ std::optional> cDataPlane::parseControlPl } } - return std::make_pair(core, - CPlaneWorkerConfig{std::move(worker_ports), - std::move(worker_cores), - {}}); + return std::make_pair(core, std::move(worker_cores)); } eResult cDataPlane::parseConfigValues(const nlohmann::json& json) @@ -2346,55 +2323,9 @@ eResult cDataPlane::checkConfig() } } - if (!checkControlPlaneWorkersConfig()) - { - return eResult::invalidConfigurationFile; - } - return eResult::success; } -bool cDataPlane::checkControlPlaneWorkersConfig() -{ - std::set assigned; - std::set to_assign = workerInterfacesToService(); - bool result = true; - for (const auto& [core, cfg] : config.controlplane_workers) - { - for (const auto& p : cfg.interfaces) - { - - if (assigned.find(p) != assigned.end()) - { - YADECAP_LOG_ERROR("Duplicate port in control plane worker config: core: %d, port: %s\n", core, p.c_str()); - result = false; - continue; - } - - if (to_assign.find(p) == to_assign.end()) - { - YADECAP_LOG_ERROR("Control plane worker config contains port not assigned to fast worker: core: %d, port: %s\n", core, p.c_str()); - result = false; - continue; - } - - assigned.emplace(p); - to_assign.erase(p); - } - } - if (!to_assign.empty()) - { - std::stringstream ss; - for (const auto& p : to_assign) - { - ss << p << ' '; - } - YADECAP_LOG_ERROR("Ports { %s } are not assigned a control plane worker\n", ss.str().c_str()); - result = false; - } - return result; -} - eResult cDataPlane::initEal(const std::string& binaryPath, const std::string& filePrefix) { diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index fd8959aa..e11b0f87 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -32,13 +32,6 @@ using InterfaceName = std::string; -struct CPlaneWorkerConfig -{ - std::set interfaces; - std::set workers; - std::set gcs; -}; - struct tDataPlaneConfig { /* @@ -57,7 +50,7 @@ struct tDataPlaneConfig std::set workerGCs; tCoreId controlPlaneCoreId; - std::map controlplane_workers; + std::map> controlplane_workers; std::map> workers; bool useHugeMem = true; bool use_kernel_interface = true; @@ -70,6 +63,35 @@ struct tDataPlaneConfig std::map> shared_memory; std::vector ealArgs; + std::set WorkersInterfaces(std::set cores) + { + std::set ifaces; + for (auto core : cores) + { + auto worker = workers.at(core); + ifaces.insert(worker.begin(), worker.end()); + } + return ifaces; + } + std::map VdevQueues() + { + std::map total; + for (auto& [_, cores] : controlplane_workers) + { + (void)_; + std::set ifaces; + for (auto core : cores) + { + const auto& w = workers.at(core); + ifaces.insert(w.begin(), w.end()); + } + for (auto& iface : ifaces) + { + ++total[iface]; + } + } + return total; + } }; class hugepage_pointer @@ -123,16 +145,13 @@ class cDataPlane protected: eResult parseConfig(const std::string& configFilePath); eResult parseJsonPorts(const nlohmann::json& json); - void ChooseGCs(tCoreId core, CPlaneWorkerConfig& cfg) const; - std::optional> parseControlPlaneWorkers(const nlohmann::json& config); - std::optional> parseControlPlaneWorker(const nlohmann::json& cpwj); + std::optional>> parseControlPlaneWorkers(const nlohmann::json& config); + std::optional>> parseControlPlaneWorker(const nlohmann::json& cpwj); nlohmann::json makeLegacyControlPlaneWorkerConfig(); - std::set workerInterfacesToService(); eResult parseConfigValues(const nlohmann::json& json); eResult parseRateLimits(const nlohmann::json& json); eResult parseSharedMemory(const nlohmann::json& json); eResult checkConfig(); - bool checkControlPlaneWorkersConfig(); eResult initEal(const std::string& binaryPath, const std::string& filePrefix); eResult initPorts(); @@ -140,16 +159,32 @@ class cDataPlane std::map> coreFunctions_; static int LcoreFunc(void* args); + struct KniHandleBundle + { + tQueueId queues = 0; + dataplane::KernelInterfaceHandle forward; + dataplane::KernelInterfaceHandle in_dump; + dataplane::KernelInterfaceHandle out_dump; + dataplane::KernelInterfaceHandle drop_dump; + bool Start() + { + return forward.Start() && + in_dump.Start() && + out_dump.Start() && + drop_dump.Start(); + } + }; + public: void StartInterfaces(); protected: eResult init_kernel_interfaces(); - bool KNIAddTxQueue(tQueueId queue, tSocketId socket); - bool KNIAddRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool); + bool KNIAddTxQueue(KniHandleBundle& bundle, tQueueId queue, tSocketId socket); + bool KNIAddRxQueue(KniHandleBundle& bundle, tQueueId queue, tSocketId socket, rte_mempool* mempool); eResult initGlobalBases(); eResult initWorkers(); - eResult InitSlowWorker(tCoreId core, const CPlaneWorkerConfig& ports, tQueueId phy_queue); + eResult InitSlowWorker(tCoreId core, const std::set& workers, tQueueId phy_queue); eResult InitSlowWorkers(); eResult initKniQueues(); eResult InitTxQueues(); @@ -177,20 +212,6 @@ class cDataPlane tDataPlaneConfig config; ConfigValues config_values_; - struct KniHandleBundle - { - dataplane::KernelInterfaceHandle forward; - dataplane::KernelInterfaceHandle in_dump; - dataplane::KernelInterfaceHandle out_dump; - dataplane::KernelInterfaceHandle drop_dump; - bool Start() - { - return forward.Start() && - in_dump.Start() && - out_dump.Start() && - drop_dump.Start(); - } - }; std::map kni_interface_handles; std::map GetNameByPort(tPortId pid) char cname[256]; if (int res = rte_eth_dev_get_name_by_port(pid, cname); res) { - YANET_LOG_ERROR("Failed to get name for port %d (%s)", pid, strerror(res)); + YANET_LOG_ERROR("Failed to get name for port %d (%s)\n", pid, strerror(res)); return std::nullopt; } return std::optional{cname}; } +std::optional GetPortByName(const std::string& name) +{ + tPortId port; + if (int res = rte_eth_dev_get_port_by_name(name.c_str(), &port); res) + { + YANET_LOG_ERROR("Failed to get port for name %s (%s)\n", name.c_str(), strerror(res)); + return std::nullopt; + } + return port; +} + std::optional GetMacAddress(tPortId pid) { rte_ether_addr ether_addr; if (int res = rte_eth_macaddr_get(pid, ðer_addr)) { - YANET_LOG_ERROR("Failed to get MAC for port %d (%s)", pid, strerror(res)); + YANET_LOG_ERROR("Failed to get MAC for port %d (%s)\n", pid, strerror(res)); return std::nullopt; } return std::optional{ether_addr.addr_bytes}; diff --git a/dataplane/dpdk.h b/dataplane/dpdk.h index f04a76ee..ca8dec2f 100644 --- a/dataplane/dpdk.h +++ b/dataplane/dpdk.h @@ -83,6 +83,7 @@ struct Endpoint }; std::optional GetNameByPort(tPortId pid); +std::optional GetPortByName(const std::string& name); std::optional GetMacAddress(tPortId pid); diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp index eeda1156..db4a1555 100644 --- a/dataplane/kernel_interface_handle.cpp +++ b/dataplane/kernel_interface_handle.cpp @@ -72,36 +72,36 @@ std::optional KernelInterfaceHandle::MakeKernelInterfaceHandle( std::string_view name, tPortId port, + tQueueId queue_count, uint16_t queue_size) noexcept { KernelInterfaceHandle kni; kni.queue_size_ = queue_size; kni.name_ = name; kni.vdev_name_ = VdevName(name, port); - std::string vdev_args = VdevArgs(name, port, queue_size); + std::string vdev_args = VdevArgs(name, port, queue_count, queue_size); if (!kni.Add(kni.vdev_name_, vdev_args) || - !kni.Configure(DefaultConfig())) + !kni.Configure(DefaultConfig(), queue_count)) { return std::nullopt; } - YANET_LOG_INFO("Created vdev device %s (%d)\n", kni.name_.c_str(), kni.kni_port_); return std::optional{std::move(kni)}; } -std::string KernelInterfaceHandle::VdevName(std::string_view name, const tPortId port_id) +std::string KernelInterfaceHandle::VdevName(std::string_view name, tPortId port_id) { std::stringstream ss; ss << "virtio_user_" << name << "_" << port_id; return ss.str(); } -std::string KernelInterfaceHandle::VdevArgs(std::string_view name, const tPortId port_id, uint64_t queue_size) +std::string KernelInterfaceHandle::VdevArgs(std::string_view name, tPortId port_id, tQueueId queues, uint64_t queue_size) { rte_ether_addr ether_addr; rte_eth_macaddr_get(port_id, ðer_addr); std::stringstream ss; ss << "path=/dev/vhost-net" - << ",queues=1" + << ",queues=" << static_cast(queues) << ",queue_size=" << queue_size << ",iface=" << name << ",mac=" << common::mac_address_t(ether_addr.addr_bytes).toString(); @@ -123,7 +123,7 @@ bool KernelInterfaceHandle::Add(const std::string& vdev_name, const std::string& YADECAP_LOG_ERROR("vdev interface '%s' not found\n", vdev_name.data()); return false; } - YANET_LOG_INFO("Successfully added vdev interface '%s' with pid %d (%s)\n", vdev_name.data(), kni_port_, args.data()); + YANET_LOG_INFO("vdev '%s' with portId %d (%s)\n", vdev_name.data(), kni_port_, args.data()); return true; } @@ -138,11 +138,11 @@ rte_eth_conf KernelInterfaceHandle::DefaultConfig() noexcept return rte_eth_conf{}; } -bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf) +bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf, tQueueId queue_count) { int ret = rte_eth_dev_configure(kni_port_, - 1, - 1, + queue_count, + queue_count, ð_conf); if (ret < 0) { @@ -172,7 +172,7 @@ bool KernelInterfaceHandle::SetupRxQueue(tQueueId queue, tSocketId socket, rte_m mempool); if (rc < 0) { - YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", kni_port_, 0, rc); + YADECAP_LOG_ERROR("rte_eth_rx_queue_setup(%u, %u) = %d\n", kni_port_, queue, rc); return false; } @@ -188,7 +188,7 @@ bool KernelInterfaceHandle::SetupTxQueue(tQueueId queue, tSocketId socket) noexc nullptr); if (rc < 0) { - YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", kni_port_, 0, rc); + YADECAP_LOG_ERROR("rte_eth_tx_queue_setup(%u, %u) = %d\n", kni_port_, queue, rc); return false; } diff --git a/dataplane/kernel_interface_handle.h b/dataplane/kernel_interface_handle.h index 49dcb80b..94569104 100644 --- a/dataplane/kernel_interface_handle.h +++ b/dataplane/kernel_interface_handle.h @@ -25,6 +25,7 @@ class KernelInterfaceHandle [[nodiscard]] static std::optional MakeKernelInterfaceHandle(std::string_view name, tPortId port, + tQueueId queue_count, uint16_t queue_size) noexcept; const tPortId& Id() const noexcept { return kni_port_; } bool Start() const noexcept; @@ -34,12 +35,12 @@ class KernelInterfaceHandle bool CloneMTU(const uint16_t) noexcept; private: - static std::string VdevName(std::string_view name, const tPortId port_id); - static std::string VdevArgs(std::string_view name, const tPortId port_id, uint64_t queue_size); + static std::string VdevName(std::string_view name, tPortId port_id); + static std::string VdevArgs(std::string_view name, tPortId port_id, tQueueId queues_count, uint64_t queue_size); bool Add(const std::string& vdev_name, const std::string& args) noexcept; void Remove() noexcept; static rte_eth_conf DefaultConfig() noexcept; - bool Configure(const rte_eth_conf& eth_conf) noexcept; + bool Configure(const rte_eth_conf& eth_conf, tQueueId queue_count) noexcept; void MarkInvalid() noexcept { kni_port_ = INVALID_PORT_ID; } [[nodiscard]] bool Valid() const { return kni_port_ != INVALID_PORT_ID; } }; diff --git a/dataplane/main.cpp b/dataplane/main.cpp index e88d5ab3..af754505 100644 --- a/dataplane/main.cpp +++ b/dataplane/main.cpp @@ -58,7 +58,7 @@ int main(int argc, /** @todo if (signal(SIGINT, handleSignal) == SIG_ERR) { - return 3; + return 3; } */ From a2dd2be795033faa127e66e552e669ab20b2b985 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 24 Jun 2024 18:54:57 +0300 Subject: [PATCH 131/195] Remove inline keyword from member function declarations This is completly redundant: [class.mfct]: "A member function may be defined (9.5) in its class definition, in which case it is an inline (9.2.7) member function if it is attached to the global module" Moreover, the inline keyword has nothing to do with inlining. It's about whether multiple identical definitions of the function are permitted in different translation units --- common/acl.h | 20 ++-- common/icontrolplane.h | 2 +- common/idataplane.h | 4 +- common/type.h | 18 ++-- controlplane/acl/bitset.h | 24 ++--- controlplane/acl/dict.h | 2 +- dataplane/hashtable.h | 200 +++++++++++++++++++------------------- dataplane/lpm.h | 110 ++++++++++----------- dataplane/type.h | 4 +- ext/xxhash32.h | 4 +- 10 files changed, 194 insertions(+), 194 deletions(-) diff --git a/common/acl.h b/common/acl.h index fdc64871..dddc272b 100644 --- a/common/acl.h +++ b/common/acl.h @@ -19,32 +19,32 @@ class tree_value_t return id < second.id; } - inline bool is_empty() const + bool is_empty() const { return !id; } - inline uint32_t get_group_id() const + uint32_t get_group_id() const { return id; } - inline void set_group_id(const uint32_t group_id) + void set_group_id(const uint32_t group_id) { id = group_id; } - inline bool is_chunk_id() const + bool is_chunk_id() const { return id & 0x80000000u; } - inline uint32_t get_chunk_id() const + uint32_t get_chunk_id() const { return id ^ 0x80000000u; } - inline void set_chunk_id(const uint32_t chunk_id) + void set_chunk_id(const uint32_t chunk_id) { id = chunk_id ^ 0x80000000u; } @@ -62,12 +62,12 @@ class tree_chunk_t { } - inline void pop(common::stream_in_t& stream) + void pop(common::stream_in_t& stream) { stream.pop(values); } - inline void push(common::stream_out_t& stream) const + void push(common::stream_out_t& stream) const { stream.push(values); } @@ -142,12 +142,12 @@ class range_t } public: - inline type_t from() const + type_t from() const { return std::get<0>(from_to); } - inline type_t to() const + type_t to() const { return std::get<1>(from_to); } diff --git a/common/icontrolplane.h b/common/icontrolplane.h index c16a182a..e8170105 100644 --- a/common/icontrolplane.h +++ b/common/icontrolplane.h @@ -387,7 +387,7 @@ class controlPlane } template> - inline common::icp::response call(const Req& request = Req()) const + common::icp::response call(const Req& request = Req()) const { std::lock_guard guard(mutex); connectToControlPlane(); diff --git a/common/idataplane.h b/common/idataplane.h index eb131d56..c0e8fbf1 100644 --- a/common/idataplane.h +++ b/common/idataplane.h @@ -283,7 +283,7 @@ class dataPlane } template - inline common::idp::response call(const Req& request) const + common::idp::response call(const Req& request) const { std::lock_guard guard(mutex); connectToDataPlane(); @@ -297,7 +297,7 @@ class dataPlane } template - inline common::idp::response call(Req&& request) const + common::idp::response call(Req&& request) const { std::lock_guard guard(mutex); connectToDataPlane(); diff --git a/common/type.h b/common/type.h index 71cb910b..1a9d2d72 100644 --- a/common/type.h +++ b/common/type.h @@ -62,40 +62,40 @@ class default_value_t using this_type = default_value_t; public: - inline default_value_t() : + default_value_t() : value(default_value) { } - inline default_value_t(const type_t& value) : + default_value_t(const type_t& value) : value(value) { } - inline operator const type_t&() const + operator const type_t&() const { return value; } - inline this_type& operator+=(const this_type& second) + this_type& operator+=(const this_type& second) { this->value += second.value; return *this; } - inline this_type& operator-=(const this_type& second) + this_type& operator-=(const this_type& second) { this->value -= second.value; return *this; } - inline this_type& operator++() + this_type& operator++() { this->value++; return *this; } - inline this_type& operator--() + this_type& operator--() { this->value--; return *this; @@ -2317,12 +2317,12 @@ class tFlow data.atomic = 0; } - inline bool operator==(const tFlow& second) const + bool operator==(const tFlow& second) const { return std::tie(type_params_atomic, data.atomic) == std::tie(second.type_params_atomic, second.data.atomic); } - inline bool operator!=(const tFlow& second) const + bool operator!=(const tFlow& second) const { return !operator==(second); } diff --git a/controlplane/acl/bitset.h b/controlplane/acl/bitset.h index be17730d..a0e9c042 100644 --- a/controlplane/acl/bitset.h +++ b/controlplane/acl/bitset.h @@ -18,19 +18,19 @@ namespace acl struct bitset_t { public: - inline void insert(size_t i) + void insert(size_t i) { vals[i / 64] |= ((uint64_t)(1) << (i % 64)); first_one = std::min(first_one, i / 64); } - inline bool operator[](size_t i) const + bool operator[](size_t i) const { return (vals[i / 64] & ((uint64_t)(1) << (i % 64))) != 0; } - inline bool empty() const + bool empty() const { return first_one == size; } @@ -59,7 +59,7 @@ struct bitset_t } #endif - inline bitset_t& operator|=(bitset_t const& other) + bitset_t& operator|=(bitset_t const& other) { if (other.empty()) { @@ -74,7 +74,7 @@ struct bitset_t return *this; } - inline bitset_t& operator&=(bitset_t const& other) + bitset_t& operator&=(bitset_t const& other) { if (empty()) { @@ -95,14 +95,14 @@ struct bitset_t return *this; } - friend inline bitset_t operator&(const bitset_t& rs1, const bitset_t& rs2) + friend bitset_t operator&(const bitset_t& rs1, const bitset_t& rs2) { bitset_t r = rs1; return r &= rs2; } - friend inline bool operator==(const bitset_t& p1, const bitset_t& p2) + friend bool operator==(const bitset_t& p1, const bitset_t& p2) { for (size_t i = p1.start(p2); i < p1.size; ++i) { @@ -115,12 +115,12 @@ struct bitset_t return true; } - friend inline bool operator!=(const bitset_t& p1, const bitset_t& p2) + friend bool operator!=(const bitset_t& p1, const bitset_t& p2) { return !(p1 == p2); } - inline std::tuple minAnd(const bitset_t& p) const + std::tuple minAnd(const bitset_t& p) const { for (size_t i = std::max(first_one, p.first_one); i < size; ++i) { @@ -134,8 +134,8 @@ struct bitset_t return {0, false}; } - inline std::tuple minAnd(const bitset_t& p1, - const bitset_t& p2) const + std::tuple minAnd(const bitset_t& p1, + const bitset_t& p2) const { for (size_t i = std::max(std::max(first_one, p1.first_one), p2.first_one); i < size; ++i) { @@ -149,7 +149,7 @@ struct bitset_t return {0, false}; } - inline bool emptyAnd(const bitset_t& p1) const + bool emptyAnd(const bitset_t& p1) const { for (size_t i = std::max(first_one, p1.first_one); i < size; ++i) { diff --git a/controlplane/acl/dict.h b/controlplane/acl/dict.h index 000e905e..e340ec1a 100644 --- a/controlplane/acl/dict.h +++ b/controlplane/acl/dict.h @@ -477,7 +477,7 @@ struct id_dict_t { } - inline void insert(unsigned int id, unsigned int idx) + void insert(unsigned int id, unsigned int idx) { if (id >= table.size()) { diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index 1d51edd0..d645b9c8 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -82,14 +82,14 @@ class spinlock_t final } public: - inline void lock() + void lock() { YADECAP_MEMORY_BARRIER_COMPILE; rte_spinlock_recursive_lock(&locker); YADECAP_MEMORY_BARRIER_COMPILE; } - inline void unlock() + void unlock() { YADECAP_MEMORY_BARRIER_COMPILE; rte_spinlock_recursive_unlock(&locker); @@ -111,12 +111,12 @@ class spinlock_nonrecursive_t final } public: - inline void lock() + void lock() { rte_spinlock_lock(&locker); } - inline void unlock() + void unlock() { rte_spinlock_unlock(&locker); } @@ -166,9 +166,9 @@ class hashtable_chain_t constexpr static uint64_t keysSize = size_T * pairsPerChunk_T + extendedSize_T * pairsPerExtendedChunk_T; public: - inline void lookup(const TKey* keys, - TValue** values, - const unsigned int& count) + void lookup(const TKey* keys, + TValue** values, + const unsigned int& count) { for (unsigned int key_i = 0; key_i < count; @@ -229,8 +229,8 @@ class hashtable_chain_t } } - inline bool lookup(const TKey& key, - TValue*& value) const + bool lookup(const TKey& key, + TValue*& value) const { lookup(&key, &value, 1); return (value != nullptr); @@ -416,7 +416,7 @@ class hashtable_chain_t } public: - inline uint32_t getNextExtendedChunkId() const + uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -426,7 +426,7 @@ class hashtable_chain_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - inline bool isValid(const unsigned int& key_i) const + bool isValid(const unsigned int& key_i) const { return keyValids & (1 << key_i); } @@ -443,22 +443,22 @@ class hashtable_chain_t YADECAP_MEMORY_BARRIER_COMPILE; } - inline const TKey& getKey(unsigned int key_i) const + const TKey& getKey(unsigned int key_i) const { return pairs[key_i].key; } - inline TKey& getKey(unsigned int key_i) + TKey& getKey(unsigned int key_i) { return pairs[key_i].key; } - inline const TValue& getValue(unsigned int key_i) const + const TValue& getValue(unsigned int key_i) const { return pairs[key_i].value; } - inline TValue& getValue(unsigned int key_i) + TValue& getValue(unsigned int key_i) { return pairs[key_i].value; } @@ -492,7 +492,7 @@ class hashtable_chain_t } public: - inline uint32_t getNextExtendedChunkId() const + uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -502,7 +502,7 @@ class hashtable_chain_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - inline bool isValid(const unsigned int& key_i) const + bool isValid(const unsigned int& key_i) const { return keyValids & (1 << key_i); } @@ -519,22 +519,22 @@ class hashtable_chain_t YADECAP_MEMORY_BARRIER_COMPILE; } - inline const TKey& getKey(unsigned int key_i) const + const TKey& getKey(unsigned int key_i) const { return pairs[key_i].key; } - inline TKey& getKey(unsigned int key_i) + TKey& getKey(unsigned int key_i) { return pairs[key_i].key; } - inline const TValue& getValue(unsigned int key_i) const + const TValue& getValue(unsigned int key_i) const { return pairs[key_i].value; } - inline TValue& getValue(unsigned int key_i) + TValue& getValue(unsigned int key_i) { return pairs[key_i].value; } @@ -559,8 +559,8 @@ class hashtable_chain_t }; protected: - static inline bool compareKeys(const TKey& first, - const TKey& second) + static bool compareKeys(const TKey& first, + const TKey& second) { return !memcmp(&first, &second, sizeof(TKey)); } @@ -667,9 +667,9 @@ class hashtable_chain_spinlock_t constexpr static uint64_t keysSize = size_T * pairsPerChunk_T + extendedSize_T * pairsPerExtendedChunk_T; public: - inline void lookup(const key_T& key, - value_T*& value, - spinlock_t*& locker) + void lookup(const key_T& key, + value_T*& value, + spinlock_t*& locker) { const uint32_t hash = rte_hash_crc(&key, sizeof(key_T), 0); auto& chunk = chunks[hash & (size_T - 1)]; @@ -717,8 +717,8 @@ class hashtable_chain_spinlock_t locker->unlock(); } - inline bool insert(const key_T& key, - const value_T& value) + bool insert(const key_T& key, + const value_T& value) { value_T* chunk_value{nullptr}; spinlock_t* locker{nullptr}; @@ -742,7 +742,7 @@ class hashtable_chain_spinlock_t /// /// Returns "false" when the table is full, in this case the lock is /// automatically unlocked. - inline eResult get(const key_T& key, value_T*& value, spinlock_t*& locker) + eResult get(const key_T& key, value_T*& value, spinlock_t*& locker) { const uint32_t hash = rte_hash_crc(&key, sizeof(key_T), 0); @@ -859,7 +859,7 @@ class hashtable_chain_spinlock_t return eResult::isFull; } - inline bool remove(const key_T& key) + bool remove(const key_T& key) { const uint32_t hash = rte_hash_crc(&key, sizeof(key_T), 0); auto& chunk = chunks[hash & (size_T - 1)]; @@ -1245,27 +1245,27 @@ class hashtable_chain_spinlock_t } public: - inline uint32_t getNextExtendedChunkId() const + uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } - inline void setNextExtendedChunkId(const uint32_t& extendedChunkId) + void setNextExtendedChunkId(const uint32_t& extendedChunkId) { nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - inline bool isValid(const unsigned int& key_i) const + bool isValid(const unsigned int& key_i) const { return keyValids & (1u << key_i); } - inline void setValid(const unsigned int& key_i) + void setValid(const unsigned int& key_i) { keyValids |= (1u << key_i); } - inline void unsetValid(const unsigned int& key_i) + void unsetValid(const unsigned int& key_i) { keyValids &= ~(1u << key_i); } @@ -1277,22 +1277,22 @@ class hashtable_chain_spinlock_t YADECAP_MEMORY_BARRIER_COMPILE; } - inline const key_T& getKey(unsigned int key_i) const + const key_T& getKey(unsigned int key_i) const { return pairs[key_i].key; } - inline key_T& getKey(unsigned int key_i) + key_T& getKey(unsigned int key_i) { return pairs[key_i].key; } - inline const value_T& getValue(unsigned int key_i) const + const value_T& getValue(unsigned int key_i) const { return pairs[key_i].value; } - inline value_T& getValue(unsigned int key_i) + value_T& getValue(unsigned int key_i) { return pairs[key_i].value; } @@ -1326,27 +1326,27 @@ class hashtable_chain_spinlock_t } public: - inline uint32_t getNextExtendedChunkId() const + uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } - inline void setNextExtendedChunkId(const uint32_t& extendedChunkId) + void setNextExtendedChunkId(const uint32_t& extendedChunkId) { nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - inline bool isValid(const unsigned int& key_i) const + bool isValid(const unsigned int& key_i) const { return keyValids & (1u << key_i); } - inline void setValid(const unsigned int& key_i) + void setValid(const unsigned int& key_i) { keyValids |= (1u << key_i); } - inline void unsetValid(const unsigned int& key_i) + void unsetValid(const unsigned int& key_i) { keyValids &= ~(1u << key_i); } @@ -1358,22 +1358,22 @@ class hashtable_chain_spinlock_t YADECAP_MEMORY_BARRIER_COMPILE; } - inline const key_T& getKey(unsigned int key_i) const + const key_T& getKey(unsigned int key_i) const { return pairs[key_i].key; } - inline key_T& getKey(unsigned int key_i) + key_T& getKey(unsigned int key_i) { return pairs[key_i].key; } - inline const value_T& getValue(unsigned int key_i) const + const value_T& getValue(unsigned int key_i) const { return pairs[key_i].value; } - inline value_T& getValue(unsigned int key_i) + value_T& getValue(unsigned int key_i) { return pairs[key_i].value; } @@ -1398,8 +1398,8 @@ class hashtable_chain_spinlock_t }; protected: - static inline bool compareKeys(const key_T& first, - const key_T& second) + static bool compareKeys(const key_T& first, + const key_T& second) { return !memcmp(&first, &second, sizeof(key_T)); } @@ -1570,10 +1570,10 @@ class hashtable_mod_id32 /// & 1VV & 0VV & VVV /// ^ 100 ^ 100 ^ 100 /// = 0VV = 1VV = 1VV - inline uint32_t lookup(uint32_t (&hashes)[burst_size], - const key_t (&keys)[burst_size], - uint32_t (&values)[burst_size], - const unsigned int count) const + uint32_t lookup(uint32_t (&hashes)[burst_size], + const key_t (&keys)[burst_size], + uint32_t (&values)[burst_size], + const unsigned int count) const { uint32_t mask = mask_full; @@ -1754,17 +1754,17 @@ class hashtable_mod_id32 } pairs[total_size]; protected: - inline bool is_valid(const uint32_t index) const + bool is_valid(const uint32_t index) const { return (pairs[index].value >> shift_valid) & 1; } - inline bool is_equal(const uint32_t index, const key_t& key) const + bool is_equal(const uint32_t index, const key_t& key) const { return !memcmp(&pairs[index].key, &key, sizeof(key_t)); } - inline bool is_valid_and_equal(const uint32_t index, const key_t& key) const + bool is_valid_and_equal(const uint32_t index, const key_t& key) const { return is_valid(index) && is_equal(index, key); } @@ -1830,10 +1830,10 @@ class hashtable_mod_id32_dynamic /// valid invalid /// = 0VV = 1VV template - inline uint32_t lookup(uint32_t (&hashes)[burst_size], - const key_t (&keys)[burst_size], - uint32_t (&values)[burst_size], - const unsigned int count) const + uint32_t lookup(uint32_t (&hashes)[burst_size], + const key_t (&keys)[burst_size], + uint32_t (&values)[burst_size], + const unsigned int count) const { uint32_t mask = mask_full; @@ -1991,17 +1991,17 @@ class hashtable_mod_id32_dynamic } protected: - inline bool is_valid(const uint32_t index) const + bool is_valid(const uint32_t index) const { return (pairs[index].value >> shift_valid) & 1; } - inline bool is_equal(const uint32_t index, const key_t& key) const + bool is_equal(const uint32_t index, const key_t& key) const { return !memcmp(&pairs[index].key, &key, sizeof(key_t)); } - inline bool is_valid_and_equal(const uint32_t index, const key_t& key) const + bool is_valid_and_equal(const uint32_t index, const key_t& key) const { return is_valid(index) && is_equal(index, key); } @@ -2079,9 +2079,9 @@ class hashtable_mod_spinlock } public: - inline uint32_t lookup(const key_t& key, - value_t*& value, - spinlock_nonrecursive_t*& locker) + uint32_t lookup(const key_t& key, + value_t*& value, + spinlock_nonrecursive_t*& locker) { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & (total_size / chunk_size - 1)]; @@ -2122,9 +2122,9 @@ class hashtable_mod_spinlock return hash; } - inline bool insert(const uint32_t hash, - const key_t& key, - const value_t& value) + bool insert(const uint32_t hash, + const key_t& key, + const value_t& value) { auto& chunk = chunks[hash & (total_size / chunk_size - 1)]; @@ -2177,8 +2177,8 @@ class hashtable_mod_spinlock return false; } - inline bool insert_or_update(const key_t& key, - const value_t& value) + bool insert_or_update(const key_t& key, + const value_t& value) { bool result = true; @@ -2353,17 +2353,17 @@ class hashtable_mod_spinlock } pairs[chunk_size]; } chunks[total_size / chunk_size]; - inline bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const + bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const { return (chunk.valid_mask >> pair_index) & 1; } - inline bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return !memcmp(&chunk.pairs[pair_index].key, &key, sizeof(key_t)); } - inline bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return is_valid(chunk, pair_index) && is_equal(chunk, pair_index, key); } @@ -2556,9 +2556,9 @@ class hashtable_mod_spinlock_dynamic } public: - inline uint32_t lookup(const key_t& key, - value_t*& value, - spinlock_nonrecursive_t*& locker) + uint32_t lookup(const key_t& key, + value_t*& value, + spinlock_nonrecursive_t*& locker) { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & total_mask]; @@ -2599,9 +2599,9 @@ class hashtable_mod_spinlock_dynamic return hash; } - inline bool insert(const uint32_t hash, - const key_t& key, - const value_t& value) + bool insert(const uint32_t hash, + const key_t& key, + const value_t& value) { auto& chunk = chunks[hash & total_mask]; @@ -2654,8 +2654,8 @@ class hashtable_mod_spinlock_dynamic return false; } - inline bool insert_or_update(const key_t& key, - const value_t& value) + bool insert_or_update(const key_t& key, + const value_t& value) { bool result = true; @@ -2676,7 +2676,7 @@ class hashtable_mod_spinlock_dynamic return result; } - inline void remove(const key_t& key) + void remove(const key_t& key) { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & total_mask]; @@ -2867,17 +2867,17 @@ class hashtable_mod_spinlock_dynamic } pairs[chunk_size]; } chunks[]; - inline bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const + bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const { return (chunk.valid_mask >> pair_index) & 1; } - inline bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return !memcmp(&chunk.pairs[pair_index].key, &key, sizeof(key_t)); } - inline bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return is_valid(chunk, pair_index) && is_equal(chunk, pair_index, key); } @@ -3106,8 +3106,8 @@ class hashtable_mod_dynamic } public: - inline uint32_t lookup(const key_t& key, - value_t*& value) + uint32_t lookup(const key_t& key, + value_t*& value) { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & total_mask]; @@ -3145,8 +3145,8 @@ class hashtable_mod_dynamic return hash; } - inline uint32_t lookup(const key_t& key, - value_t const*& value) const + uint32_t lookup(const key_t& key, + value_t const*& value) const { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & total_mask]; @@ -3184,9 +3184,9 @@ class hashtable_mod_dynamic return hash; } - inline bool insert(const uint32_t hash, - const key_t& key, - const value_t& value) + bool insert(const uint32_t hash, + const key_t& key, + const value_t& value) { auto& chunk = chunks[hash & total_mask]; @@ -3239,8 +3239,8 @@ class hashtable_mod_dynamic return false; } - inline bool insert_or_update(const key_t& key, - const value_t& value) + bool insert_or_update(const key_t& key, + const value_t& value) { bool result = true; @@ -3259,7 +3259,7 @@ class hashtable_mod_dynamic return result; } - inline bool remove(const key_t& key) + bool remove(const key_t& key) { uint32_t hash = calculate_hash(key); auto& chunk = chunks[hash & total_mask]; @@ -3432,17 +3432,17 @@ class hashtable_mod_dynamic } pairs[chunk_size]; } chunks[]; - inline bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const + bool is_valid(const chunk_t& chunk, const uint32_t pair_index) const { return (chunk.valid_mask >> pair_index) & 1; } - inline bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return !memcmp(&chunk.pairs[pair_index].key, &key, sizeof(key_t)); } - inline bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const + bool is_valid_and_equal(const chunk_t& chunk, const uint32_t pair_index, const key_t& key) const { return is_valid(chunk, pair_index) && is_equal(chunk, pair_index, key); } diff --git a/dataplane/lpm.h b/dataplane/lpm.h index 672f861c..319301fc 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -138,9 +138,9 @@ class lpm4_24bit_8bit_atomic return copy_root_chunk(stats, remap_chunks, second); } - inline void lookup(const uint32_t* ipAddresses, - uint32_t* valueIds, - const unsigned int& count) const + void lookup(const uint32_t* ipAddresses, + uint32_t* valueIds, + const unsigned int& count) const { /// @todo: OPT: le -> be @@ -175,9 +175,9 @@ class lpm4_24bit_8bit_atomic } template - inline void lookup(rte_mbuf** mbufs, - uint32_t* valueIds, - const unsigned int& count) const + void lookup(rte_mbuf** mbufs, + uint32_t* valueIds, + const unsigned int& count) const { uint32_t ipAddresses[CONFIG_YADECAP_MBUFS_BURST_SIZE]; @@ -194,8 +194,8 @@ class lpm4_24bit_8bit_atomic lookup(ipAddresses, valueIds, count); } - inline bool lookup(const uint32_t& ipAddress, - uint32_t* valueId = nullptr) const + bool lookup(const uint32_t& ipAddress, + uint32_t* valueId = nullptr) const { uint32_t lvalueId; @@ -831,9 +831,9 @@ class lpm6_8x16bit_atomic return copy_root_chunk(stats, remap_chunks, second); } - inline void lookup(const ipv6_address_t* ipv6Addresses, - uint32_t* valueIds, - const unsigned int& count) const + void lookup(const ipv6_address_t* ipv6Addresses, + uint32_t* valueIds, + const unsigned int& count) const { /// @todo: OPT: le -> be @@ -876,10 +876,10 @@ class lpm6_8x16bit_atomic constexpr static uint32_t mask_full = 0xFFFFFFFFu; - inline void lookup(const uint32_t mask, - const ipv6_address_t* ipv6Addresses, - uint32_t* valueIds, - const unsigned int& count) const + void lookup(const uint32_t mask, + const ipv6_address_t* ipv6Addresses, + uint32_t* valueIds, + const unsigned int& count) const { /// @todo: OPT: le -> be @@ -931,9 +931,9 @@ class lpm6_8x16bit_atomic } template - inline void lookup(rte_mbuf** mbufs, - uint32_t* valueIds, - const unsigned int& count) const + void lookup(rte_mbuf** mbufs, + uint32_t* valueIds, + const unsigned int& count) const { ipv6_address_t ipv6Addresses[CONFIG_YADECAP_MBUFS_BURST_SIZE]; @@ -952,8 +952,8 @@ class lpm6_8x16bit_atomic lookup(ipv6Addresses, valueIds, count); } - inline bool lookup(const std::array& ipv6Address, - uint32_t* valueId = nullptr) const + bool lookup(const std::array& ipv6Address, + uint32_t* valueId = nullptr) const { ipv6_address_t lipv6Address; uint32_t lvalueId; @@ -974,8 +974,8 @@ class lpm6_8x16bit_atomic return false; } - inline bool lookup(const uint8_t* ipv6_address, - uint32_t* value_id = nullptr) const + bool lookup(const uint8_t* ipv6_address, + uint32_t* value_id = nullptr) const { ipv6_address_t lipv6Address; uint32_t lvalueId; @@ -1514,7 +1514,7 @@ class lpm4_24bit_8bit_id32 remap_chunks.resize(tree_size, 0); } - inline unsigned int allocate_extended_chunk() + unsigned int allocate_extended_chunk() { if (extended_chunks_count >= extended_chunks_size) { @@ -1527,7 +1527,7 @@ class lpm4_24bit_8bit_id32 return new_chunk_id; } - inline unsigned int& remap(const unsigned int from_chunk_id) + unsigned int& remap(const unsigned int from_chunk_id) { return remap_chunks[from_chunk_id]; } @@ -1576,9 +1576,9 @@ class lpm4_24bit_8bit_id32 public: template - inline void lookup(const ipv4_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const ipv4_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -1788,9 +1788,9 @@ class lpm4_24bit_8bit_id32_dynamic } template - inline void lookup(const ipv4_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const ipv4_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -1997,7 +1997,7 @@ class lpm6_8x16bit_id32 remap_chunks.resize(tree_size, 0); } - inline unsigned int allocate_chunk() + unsigned int allocate_chunk() { if (chunks_count >= chunks_size) { @@ -2010,7 +2010,7 @@ class lpm6_8x16bit_id32 return new_chunk_id; } - inline unsigned int& remap(const unsigned int from_chunk_id) + unsigned int& remap(const unsigned int from_chunk_id) { return remap_chunks[from_chunk_id]; } @@ -2049,9 +2049,9 @@ class lpm6_8x16bit_id32 public: template - inline void lookup(const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2084,10 +2084,10 @@ class lpm6_8x16bit_id32 } template - inline void lookup(const uint32_t mask, - const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const uint32_t mask, + const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2279,7 +2279,7 @@ class lpm6_8x16bit_id32_dynamic } protected: - inline unsigned int allocate_chunk() + unsigned int allocate_chunk() { if (chunks_count >= chunks_size) { @@ -2383,9 +2383,9 @@ class lpm6_8x16bit_id32_dynamic public: template - inline void lookup(const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2418,10 +2418,10 @@ class lpm6_8x16bit_id32_dynamic } template - inline void lookup(const uint32_t mask, - const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const uint32_t mask, + const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2519,9 +2519,9 @@ class lpm6_16x8bit_id32_dynamic } template - inline void lookup(const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2554,10 +2554,10 @@ class lpm6_16x8bit_id32_dynamic } template - inline void lookup(const uint32_t mask, - const ipv6_address_t (&addresses)[burst_size], - uint32_t (&group_ids)[burst_size], - const unsigned int count) const + void lookup(const uint32_t mask, + const ipv6_address_t (&addresses)[burst_size], + uint32_t (&group_ids)[burst_size], + const unsigned int count) const { /// @todo: OPT: le -> be @@ -2618,7 +2618,7 @@ class lpm6_16x8bit_id32_dynamic constexpr static unsigned int root_chunk_id = 0; constexpr static uint32_t mask_full = 0xFFFFFFFFu; - inline unsigned int allocate_extended_chunk(stats_t& stats) + unsigned int allocate_extended_chunk(stats_t& stats) { if (stats.extended_chunks_count >= stats.extended_chunks_size) { diff --git a/dataplane/type.h b/dataplane/type.h index b82ffa82..9fedb934 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -739,7 +739,7 @@ struct fw_state_sync_frame_t uint32_t flow_id6; uint32_t extra; - static inline fw_state_sync_frame_t from_state_key(const fw4_state_key_t& key) + static fw_state_sync_frame_t from_state_key(const fw4_state_key_t& key) { fw_state_sync_frame_t sync_frame{}; sync_frame.proto = uint8_t(key.proto); @@ -752,7 +752,7 @@ struct fw_state_sync_frame_t return sync_frame; } - static inline fw_state_sync_frame_t from_state_key(const fw6_state_key_t& key) + static fw_state_sync_frame_t from_state_key(const fw6_state_key_t& key) { fw_state_sync_frame_t sync_frame{}; sync_frame.proto = uint8_t(key.proto); diff --git a/ext/xxhash32.h b/ext/xxhash32.h index e801f503..857ad54a 100644 --- a/ext/xxhash32.h +++ b/ext/xxhash32.h @@ -163,13 +163,13 @@ class XXHash32 uint64_t totalLength; /// rotate bits, should compile to a single CPU instruction (ROL) - static inline uint32_t rotateLeft(uint32_t x, unsigned char bits) + static uint32_t rotateLeft(uint32_t x, unsigned char bits) { return (x << bits) | (x >> (32 - bits)); } /// process a block of 4x4 bytes, this is the main part of the XXHash32 algorithm - static inline void process(const void* data, uint32_t& state0, uint32_t& state1, uint32_t& state2, uint32_t& state3) + static void process(const void* data, uint32_t& state0, uint32_t& state1, uint32_t& state2, uint32_t& state3) { const uint32_t* block = (const uint32_t*) data; state0 = rotateLeft(state0 + block[0] * Prime2, 13) * Prime1; From 60f361da03970b21a2d36310e81cb04a7cab0edf Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 19:29:11 +0400 Subject: [PATCH 132/195] Initialize fields in a member initializer of the constructor --- autotest/autotest.cpp | 6 +++--- common/bufferring.h | 3 +-- common/refarray.h | 7 +++---- common/type.h | 4 ++-- controlplane/acl/network.h | 8 ++------ controlplane/acl/rule.h | 8 ++++---- controlplane/acl_transport_table.cpp | 3 +-- controlplane/segment_allocator.h | 5 ++--- dataplane/globalbase.cpp | 4 +--- libfwparser/fw_config.cpp | 8 ++------ 10 files changed, 21 insertions(+), 35 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 4f38664a..2eddb847 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -412,9 +412,9 @@ class PcapDumper { public: PcapDumper(const std::string& path, int capsize = MAX_PACK_LEN) : - tmpFilePath(path) + tmpFilePath(path), pcap(pcap_open_dead(DLT_EN10MB, capsize)) { - pcap = pcap_open_dead(DLT_EN10MB, capsize); + if (!pcap) { YANET_LOG_ERROR("error: pcap_open_dead()\n"); @@ -2023,4 +2023,4 @@ void tAutotest::fflushSharedMemory() memset(memaddr, 0, size); } -} // namespace autotest \ No newline at end of file +} // namespace autotest diff --git a/common/bufferring.h b/common/bufferring.h index 6f54a2f5..dfe016fe 100644 --- a/common/bufferring.h +++ b/common/bufferring.h @@ -26,9 +26,8 @@ class bufferring } bufferring(void* memory, int unit_size, int units_number) : unit_size(unit_size), - units_number(units_number) + units_number(units_number), ring((ring_t*)memory) { - ring = (ring_t*)memory; } struct ring_header_t diff --git a/common/refarray.h b/common/refarray.h index a2c770a6..4c2046eb 100644 --- a/common/refarray.h +++ b/common/refarray.h @@ -17,10 +17,9 @@ class refarray_t using id_t = uint64_t; public: - refarray_t() ///< @todo: fallback value? + refarray_t() : + ids_unused_size(size_T) ///< @todo: fallback value? { - ids_unused_size = size_T; - ids_unused_watermark = 0; } bool exist_id(const id_t& id) @@ -203,7 +202,7 @@ class refarray_t protected: std::vector ids_unused; - std::atomic ids_unused_watermark; + std::atomic ids_unused_watermark{0}; std::map(pref)), mask(std::get<1>(pref)) { - addr = std::get<0>(pref); - mask = std::get<1>(pref); } network_t(const ipfw::ipv6_prefix_mask_t& pref) : - family(6) + family(6), addr(std::get<0>(pref).getAddress128()), mask(std::get<1>(pref).getAddress128()) { - addr = std::get<0>(pref).getAddress128(); - mask = std::get<1>(pref).getAddress128(); } network_t(const common::ip_prefix_t& pref) diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 6e03740f..875d05bd 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -80,9 +80,9 @@ struct ref_t ref_inc(); } - inline ref_t(const ref_t& _ref) + inline ref_t(const ref_t& _ref) : + filter(_ref.filter) { - filter = _ref.filter; ref_inc(); } @@ -1063,9 +1063,9 @@ struct rule_t log(false) {} - rule_t(ipfw::rule_ptr_t rulep, ipfw::fw_config_ptr_t configp) + rule_t(ipfw::rule_ptr_t rulep, ipfw::fw_config_ptr_t configp) : + text(rulep->text) { - text = rulep->text; switch (rulep->action) { case ipfw::rule_action_t::SKIPTO: diff --git a/controlplane/acl_transport_table.cpp b/controlplane/acl_transport_table.cpp index c127f693..f4af5cb6 100644 --- a/controlplane/acl_transport_table.cpp +++ b/controlplane/acl_transport_table.cpp @@ -72,9 +72,8 @@ transport_table::thread_t::thread_t(transport_table_t* transport_table, const unsigned int threads_count) : transport_table(transport_table), thread_id(thread_id), - threads_count(threads_count) + threads_count(threads_count), group_id(1 + thread_id) { - group_id = 1 + thread_id; } void transport_table::thread_t::start() diff --git a/controlplane/segment_allocator.h b/controlplane/segment_allocator.h index 78957e26..b4dfe6d2 100644 --- a/controlplane/segment_allocator.h +++ b/controlplane/segment_allocator.h @@ -27,10 +27,9 @@ class SegmentAllocator uint32_t used_segments = 0; }; - SegmentAllocator() + SegmentAllocator() : + free_cells_(IndexEnd - IndexBegin) { - free_cells_ = IndexEnd - IndexBegin; - // Initialize blocks in main list of free blocks and set size of each block for (uint32_t index = 0; index < total_blocks_; ++index) { diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 3bb61b86..38cb1362 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -18,7 +18,7 @@ using namespace dataplane::globalBase; atomic::atomic(cDataPlane* dataPlane, const tSocketId& socketId) : dataPlane(dataPlane), - socketId(socketId) + socketId(socketId), tsc_active_state(dataPlane->getConfigValues().tsc_active_state) { fw_state_config.tcp_timeout = dataPlane->getConfigValues().stateful_firewall_tcp_timeout; fw_state_config.udp_timeout = dataPlane->getConfigValues().stateful_firewall_udp_timeout; @@ -28,8 +28,6 @@ atomic::atomic(cDataPlane* dataPlane, memset(physicalPort_flags, 0, sizeof(physicalPort_flags)); memset(counter_shifts, 0, sizeof(counter_shifts)); memset(gc_counter_shifts, 0, sizeof(gc_counter_shifts)); - - tsc_active_state = dataPlane->getConfigValues().tsc_active_state; } atomic::~atomic() diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index 0af9df32..091e978f 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -16,17 +16,13 @@ using namespace ipfw; std::cerr << "DEBUG: " << __func__ << ": " << msg << std::endl; \ } while (0) -fw_config_t::fw_config_t(int step) +fw_config_t::fw_config_t(int step) : + m_curr_entity(entity_type::NONE), m_debug(0), m_ruleid_last(0), m_ruleno_last(0) { // use limits like in FreeBSD kernel const auto value = std::clamp(step, 1, 1000); - m_debug = 0; - m_ruleid_last = 0; - m_ruleno_last = 0; m_ruleno_step = value; - - m_curr_entity = entity_type::NONE; m_curr_rule = std::make_shared(); m_prev_rule = nullptr; From d1117e40929bf5a32ba3f8b251c965e0fb8e983a Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 19:50:37 +0400 Subject: [PATCH 133/195] Use nullptr instead of NULL --- autotest/autotest.cpp | 10 +++++----- cli/develop.h | 4 ++-- common/shared_memory.h | 2 +- dataplane/dataplane.cpp | 10 +++++----- dataplane/sock_dev.cpp | 10 +++++----- librib/libyabird.cpp | 2 +- logger/main.cpp | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 2eddb847..70da8ee2 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -141,10 +141,10 @@ eResult tAutotest::initSharedMemory() return eResult::errorInitSharedMemory; } - shmaddr = shmat(shmid, NULL, 0); + shmaddr = shmat(shmid, nullptr, 0); if (shmaddr == (void*)-1) { - YANET_LOG_ERROR("shmat(%d, NULL, 0) = %d\n", shmid, errno); + YANET_LOG_ERROR("shmat(%d, nullptr, 0) = %d\n", shmid, errno); return eResult::errorInitSharedMemory; } @@ -720,7 +720,7 @@ void tAutotest::recvThread(std::string interfaceName, auto packetSize = tmp_pcap_packetHeader.len; YANET_LOG_DEBUG("unexpected %u\n", packetSize); - dumper.dump(NULL, NULL, buffer, buffer + packetSize); + dumper.dump(nullptr, nullptr, buffer, buffer + packetSize); } success = false; @@ -1864,7 +1864,7 @@ std::string exec(const char* cmd) try { - while (fgets(buffer, sizeof buffer, pipe) != NULL) + while (fgets(buffer, sizeof buffer, pipe) != nullptr) { result += buffer; } @@ -1998,7 +1998,7 @@ bool tAutotest::step_dumpPackets(const YAML::Node& yamlStep, if (dumpPackets) { YANET_LOG_DEBUG("dump [%s]: unexpected %u\n", tag.data(), shm_packet->header.size); - dumper.dump(NULL, NULL, shm_packet->memory, shm_packet->memory + header.len); + dumper.dump(nullptr, nullptr, shm_packet->memory, shm_packet->memory + header.len); } } diff --git a/cli/develop.h b/cli/develop.h index 46eba193..1f736727 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -189,10 +189,10 @@ class tsc_monitoring_t { throw std::string("shmget(") + std::to_string(ipc_key) + ", 0, 0) = " + std::strerror(errno); } - auto shmaddr = shmat(shmid, NULL, SHM_RDONLY); + auto shmaddr = shmat(shmid, nullptr, SHM_RDONLY); if (shmaddr == (void*)-1) { - throw std::string("shmat(") + std::to_string(ipc_key) + ", NULL, 0) = " + std::strerror(errno); + throw std::string("shmat(") + std::to_string(ipc_key) + ", nullptr, 0) = " + std::strerror(errno); } ipc_cache[ipc_key] = shmaddr; diff --git a/common/shared_memory.h b/common/shared_memory.h index 0d118e1c..dbd46621 100644 --- a/common/shared_memory.h +++ b/common/shared_memory.h @@ -33,7 +33,7 @@ class SharedMemory const char* str_hugetlb = "Hugetlb:"; FILE* fd = fopen(path_meminfo, "r"); - if (fd == NULL) + if (fd == nullptr) { YANET_LOG_ERROR("Cannot open %s, error %d: %s\n", path_meminfo, errno, strerror(errno)); return false; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 41d71f2a..28ab5eac 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -131,7 +131,7 @@ eResult cDataPlane::init(const std::string& binaryPath, } } - mempool_log = rte_mempool_create("log", YANET_CONFIG_SAMPLES_SIZE, sizeof(samples::sample_t), 0, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, MEMPOOL_F_NO_IOVA_CONTIG); + mempool_log = rte_mempool_create("log", YANET_CONFIG_SAMPLES_SIZE, sizeof(samples::sample_t), 0, 0, nullptr, nullptr, nullptr, nullptr, SOCKET_ID_ANY, MEMPOOL_F_NO_IOVA_CONTIG); result = initGlobalBases(); if (result != eResult::success) @@ -1660,9 +1660,9 @@ eResult cDataPlane::allocateSharedMemory() int shmid = shmget(key, 0, 0); if (shmid != -1) { - if (shmctl(shmid, IPC_RMID, NULL) < 0) + if (shmctl(shmid, IPC_RMID, nullptr) < 0) { - YADECAP_LOG_ERROR("shmctl(%d, IPC_RMID, NULL): %s\n", shmid, strerror(errno)); + YADECAP_LOG_ERROR("shmctl(%d, IPC_RMID, nullptr): %s\n", shmid, strerror(errno)); return eResult::errorInitSharedMemory; } } @@ -1680,10 +1680,10 @@ eResult cDataPlane::allocateSharedMemory() return eResult::errorInitSharedMemory; } - void* shmaddr = shmat(shmid, NULL, 0); + void* shmaddr = shmat(shmid, nullptr, 0); if (shmaddr == (void*)-1) { - YADECAP_LOG_ERROR("shmat(%d, NULL, %d): %s\n", shmid, 0, strerror(errno)); + YADECAP_LOG_ERROR("shmat(%d, nullptr, %d): %s\n", shmid, 0, strerror(errno)); return eResult::errorInitSharedMemory; } diff --git a/dataplane/sock_dev.cpp b/dataplane/sock_dev.cpp index e2cba99d..14852e6d 100644 --- a/dataplane/sock_dev.cpp +++ b/dataplane/sock_dev.cpp @@ -261,7 +261,7 @@ sock_dev_rx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) if (sq->internals->conFd < 0) { - sq->internals->conFd = accept4(sq->internals->fd, NULL, NULL, SOCK_NONBLOCK); + sq->internals->conFd = accept4(sq->internals->fd, nullptr, nullptr, SOCK_NONBLOCK); } if (sq->internals->conFd < 0) @@ -299,7 +299,7 @@ sock_dev_rx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) struct rte_mbuf* mbuf; mbuf = rte_pktmbuf_alloc(sq->mb_pool); - if (unlikely(mbuf == NULL)) + if (unlikely(mbuf == nullptr)) { sq->internals->eth_stats.ierrors++; return 0; @@ -415,7 +415,7 @@ int sock_dev_create(const char* path, const char* name, uint8_t numa_node) { struct sock_internals* internals = (struct sock_internals*) rte_zmalloc_socket(path, sizeof(struct sock_internals), 0, numa_node); - if (internals == NULL) + if (internals == nullptr) return ENOSPC; internals->pci_id.device_id = 0xBEEF; @@ -452,9 +452,9 @@ int sock_dev_create(const char* path, const char* name, uint8_t numa_node) listen(internals->fd, 1); internals->conFd = -1; - struct rte_eth_dev* eth_dev = NULL; + struct rte_eth_dev* eth_dev = nullptr; eth_dev = rte_eth_dev_allocate(name); - if (eth_dev == NULL) + if (eth_dev == nullptr) { close(internals->fd); unlink(internals->sockaddr.sun_path); diff --git a/librib/libyabird.cpp b/librib/libyabird.cpp index abc464f0..aed7c5e6 100644 --- a/librib/libyabird.cpp +++ b/librib/libyabird.cpp @@ -375,7 +375,7 @@ yanet_open(void) { std::cerr << __func__ << " failed" << std::endl; } - return (NULL); + return (nullptr); } extern "C" void diff --git a/logger/main.cpp b/logger/main.cpp index 1492ee98..f9f31ce7 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -46,7 +46,7 @@ int initLogger() { auto coreId = it.first; auto ring = rte_ring_lookup(("r_log_" + std::to_string(coreId)).c_str()); - if (ring != NULL) + if (ring != nullptr) { YANET_LOG_DEBUG("found log ring on #%u core\n", coreId); From 67963b98117d69ef738ea49d06cf4c8318801aca Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 20:02:06 +0400 Subject: [PATCH 134/195] Use '= default' to define a trivial default constructor --- autotest/autotest.cpp | 4 ---- autotest/autotest.h | 2 +- cli/influxdb_format.h | 4 +--- common/bufferring.h | 4 +--- common/controlplaneconfig.h | 4 +--- common/rpc_controller.h | 2 +- common/stream.h | 6 +----- common/type.h | 28 +++++++--------------------- controlplane/acl/rule.h | 6 +++--- controlplane/base.h | 28 +++++++--------------------- controlplane/controlplane.cpp | 4 ---- controlplane/controlplane.h | 2 +- controlplane/dregress.h | 4 +--- controlplane/module.cpp | 4 ---- controlplane/module.h | 2 +- controlplane/rib.cpp | 8 -------- controlplane/rib.h | 4 ++-- controlplane/route.h | 4 +--- controlplane/telegraf.cpp | 4 ---- controlplane/telegraf.h | 6 ++---- controlplane/tun64.cpp | 8 -------- controlplane/tun64.h | 4 ++-- dataplane/globalbase.cpp | 8 -------- dataplane/globalbase.h | 4 ++-- dataplane/lpm.h | 8 ++------ 25 files changed, 37 insertions(+), 125 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 70da8ee2..242d89cc 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -56,10 +56,6 @@ tAutotest::tAutotest() : ::testing::GTEST_FLAG(throw_on_failure) = true; } -tAutotest::~tAutotest() -{ -} - eResult tAutotest::init(const std::string& binaryPath, bool dumpPackets, const std::vector& configFilePaths) diff --git a/autotest/autotest.h b/autotest/autotest.h index 873e9ef4..40e26103 100644 --- a/autotest/autotest.h +++ b/autotest/autotest.h @@ -36,7 +36,7 @@ class tAutotest { public: tAutotest(); - ~tAutotest(); + ~tAutotest() = default; eResult init(const std::string& binaryPath, bool dumpPackets, diff --git a/cli/influxdb_format.h b/cli/influxdb_format.h index ff95b706..9b1a9bdc 100644 --- a/cli/influxdb_format.h +++ b/cli/influxdb_format.h @@ -88,9 +88,7 @@ std::string to_string(const char* key, class base_t { public: - virtual ~base_t() - { - } + virtual ~base_t() = default; const std::string& to_string() const { diff --git a/common/bufferring.h b/common/bufferring.h index dfe016fe..a27d2b98 100644 --- a/common/bufferring.h +++ b/common/bufferring.h @@ -21,9 +21,7 @@ namespace common class bufferring { public: - bufferring() - { - } + bufferring() = default; bufferring(void* memory, int unit_size, int units_number) : unit_size(unit_size), units_number(units_number), ring((ring_t*)memory) diff --git a/common/controlplaneconfig.h b/common/controlplaneconfig.h index a763589f..090f8bed 100644 --- a/common/controlplaneconfig.h +++ b/common/controlplaneconfig.h @@ -90,9 +90,7 @@ namespace route class interface_t { public: - interface_t() - { - } + interface_t() = default; /** @todo: tag:CP_MODULES void load(const nlohmann::json& json); diff --git a/common/rpc_controller.h b/common/rpc_controller.h index f538877a..c65c5321 100644 --- a/common/rpc_controller.h +++ b/common/rpc_controller.h @@ -11,7 +11,7 @@ class RpcController : public google::protobuf::RpcController { public: RpcController() { _reset(); } - virtual ~RpcController() {} + ~RpcController() override = default; virtual void Reset() { diff --git a/common/stream.h b/common/stream.h index 961ec9c0..8e0af69e 100644 --- a/common/stream.h +++ b/common/stream.h @@ -99,7 +99,7 @@ class stream_out_t using integer_t = uint64_t; public: - stream_out_t(); + stream_out_t() = default; template inline void push(const TType& value); @@ -560,10 +560,6 @@ inline void stream_in_t::popVariant(std::variant& variant, // -inline stream_out_t::stream_out_t() -{ -} - template inline void stream_out_t::push(const TType& value) { diff --git a/common/type.h b/common/type.h index 7ba14a61..f88ae72e 100644 --- a/common/type.h +++ b/common/type.h @@ -550,9 +550,7 @@ class ipv6_address_t class ip_address_t { public: - constexpr ip_address_t() - { - } + constexpr ip_address_t() = default; ip_address_t(const uint8_t ip_version, const uint8_t* bytes) { @@ -853,9 +851,7 @@ class ipv4_prefix_t class ipv4_prefix_with_announces_t { public: - ipv4_prefix_with_announces_t() - { - } + ipv4_prefix_with_announces_t() = default; ipv4_prefix_with_announces_t(const nlohmann::json& prefixJson) { @@ -1200,9 +1196,7 @@ class ipv6_prefix_with_announces_t class ip_prefix_t { public: - constexpr ip_prefix_t() - { - } + constexpr ip_prefix_t() = default; constexpr ip_prefix_t(const ipv4_prefix_t& prefix) : prefix(prefix) @@ -1433,9 +1427,7 @@ class ip_prefix_with_announces_t public: using variant_t = std::variant; - ip_prefix_with_announces_t() - { - } + ip_prefix_with_announces_t() = default; ip_prefix_with_announces_t(const nlohmann::json& prefixJson) { @@ -1679,9 +1671,7 @@ class large_community_t class values_t { public: - values_t() - { - } + values_t() = default; template values_t(const args_T&... args) @@ -1729,9 +1719,7 @@ class values_t class range_t { public: - constexpr range_t() - { - } + constexpr range_t() = default; constexpr range_t(const uint64_t& value) : range(value, value) @@ -1849,9 +1837,7 @@ class flags_t class ranges_t ///< @todo: rename filter_t { public: - ranges_t() - { - } + ranges_t() = default; ranges_t(const uint64_t& value) { diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 875d05bd..5320136f 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -45,7 +45,7 @@ struct filter_base_t inline constexpr filter_base_t() : ref_count(0) {} virtual bool is_none() const = 0; - virtual ~filter_base_t() {} + virtual ~filter_base_t() = default; virtual std::string to_string() const = 0; }; @@ -182,7 +182,7 @@ struct filter_network_t : filter_base_t { std::vector networks; - inline filter_network_t() {} + inline filter_network_t() = default; filter_network_t(const ipfw::rule_t::address_t& target) { @@ -270,7 +270,7 @@ struct filter_prm_t : filter_base_t { std::vector> ranges; - inline filter_prm_t() {} + inline filter_prm_t() = default; filter_prm_t(const common::ranges_t& _ranges) { diff --git a/controlplane/base.h b/controlplane/base.h index 6b06b13d..91eadbc4 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -114,9 +114,7 @@ class nat64stateless_t class acl_rule_network_ipv4_t { public: - acl_rule_network_ipv4_t() - { - } + acl_rule_network_ipv4_t() = default; acl_rule_network_ipv4_t(const std::set& sourcePrefixes, const std::set& destinationPrefixes) : @@ -133,9 +131,7 @@ class acl_rule_network_ipv4_t class acl_rule_network_ipv6_t { public: - acl_rule_network_ipv6_t() - { - } + acl_rule_network_ipv6_t() = default; acl_rule_network_ipv6_t(const std::set& sourcePrefixes, const std::set& destinationPrefixes) : @@ -152,9 +148,7 @@ class acl_rule_network_ipv6_t class acl_rule_transport_tcp_t { public: - acl_rule_transport_tcp_t() - { - } + acl_rule_transport_tcp_t() = default; acl_rule_transport_tcp_t(const ranges_t& sourcePorts, const ranges_t& destinationPorts) : @@ -172,9 +166,7 @@ class acl_rule_transport_tcp_t class acl_rule_transport_udp_t { public: - acl_rule_transport_udp_t() - { - } + acl_rule_transport_udp_t() = default; acl_rule_transport_udp_t(const ranges_t& sourcePorts, const ranges_t& destinationPorts) : @@ -271,9 +263,7 @@ class acl_rule_transport_icmpv6_t class acl_rule_transport_other_t { public: - acl_rule_transport_other_t() - { - } + acl_rule_transport_other_t() = default; acl_rule_transport_other_t(const ranges_t& protocolTypes) : protocolTypes(protocolTypes) @@ -295,9 +285,7 @@ class acl_rule_t }; public: - acl_rule_t() - { - } + acl_rule_t() = default; template acl_rule_t(const std::variant& network, @@ -395,9 +383,7 @@ class acl_sync_config_t class acl_t { public: - acl_t() - { - } + acl_t() = default; public: tAclId aclId; diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index b51b43f6..ea72defb 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -21,10 +21,6 @@ cControlPlane::cControlPlane() : { } -cControlPlane::~cControlPlane() -{ -} - eResult cControlPlane::init(const std::string& jsonFilePath) { eResult result = eResult::success; diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index 9ff14ab5..9716cd88 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -38,7 +38,7 @@ class cControlPlane { public: cControlPlane(); - ~cControlPlane(); + ~cControlPlane() = default; eResult init(const std::string& jsonFilePath); void start(); diff --git a/controlplane/dregress.h b/controlplane/dregress.h index 3ea8cd41..55782c34 100644 --- a/controlplane/dregress.h +++ b/controlplane/dregress.h @@ -26,9 +26,7 @@ using value_key_t = std::tuplecontrolPlane = controlPlane; diff --git a/controlplane/module.h b/controlplane/module.h index fd107bdc..1fc336b5 100644 --- a/controlplane/module.h +++ b/controlplane/module.h @@ -20,7 +20,7 @@ class cModule { public: cModule(); - virtual ~cModule(); + virtual ~cModule() = default; eResult moduleInit(cControlPlane* controlPlane); void moduleStart(); diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index c66e21ed..fddf2cb6 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -3,14 +3,6 @@ using namespace controlplane::module; -rib_t::rib_t() -{ -} - -rib_t::~rib_t() -{ -} - eResult rib_t::init() { controlPlane->register_command(common::icp::requestType::rib_update, [this](const common::icp::request& request) { diff --git a/controlplane/rib.h b/controlplane/rib.h index b2147c3c..7bde0a4f 100644 --- a/controlplane/rib.h +++ b/controlplane/rib.h @@ -36,8 +36,8 @@ using path_info_to_nexthop_stuff_ptr_t = common::rib::path_info_to_nexthop_stuff class rib_t : public cModule { public: - rib_t(); - ~rib_t() override; + rib_t() = default; + ~rib_t() override = default; eResult init() override; void reload(const controlplane::base_t& base_prev, const controlplane::base_t& base_next, common::idp::updateGlobalBase::request& globalbase) override; diff --git a/controlplane/route.h b/controlplane/route.h index 87a87253..dca9f385 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -97,9 +97,7 @@ using tunnel_counter_key_t = std::tupleregister_command(common::icp::requestType::telegraf_unsafe, [this]() { diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index 926f3570..99561cdc 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -17,9 +17,7 @@ namespace telegraf class generation_t { public: - generation_t() - { - } + generation_t() = default; void update(const controlplane::base_t& base_prev, const controlplane::base_t& base_next) @@ -64,7 +62,7 @@ class telegraf_t : public module_t { public: telegraf_t(); - ~telegraf_t(); + ~telegraf_t() override = default; eResult init() override; void reload_before() override; diff --git a/controlplane/tun64.cpp b/controlplane/tun64.cpp index 09ee3968..ed454867 100644 --- a/controlplane/tun64.cpp +++ b/controlplane/tun64.cpp @@ -1,14 +1,6 @@ #include "tun64.h" #include "controlplane.h" -tun64_t::tun64_t() -{ -} - -tun64_t::~tun64_t() -{ -} - eResult tun64_t::init() { tunnel_counters.init(&controlPlane->counter_manager); diff --git a/controlplane/tun64.h b/controlplane/tun64.h index 850c5e86..9fd1bbe5 100644 --- a/controlplane/tun64.h +++ b/controlplane/tun64.h @@ -38,8 +38,8 @@ class generation_config_t class tun64_t : public module_t { public: - tun64_t(); - ~tun64_t(); + tun64_t() = default; + ~tun64_t() override = default; eResult init() override; void reload_before() override; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 38cb1362..d6d5ddb7 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -30,10 +30,6 @@ atomic::atomic(cDataPlane* dataPlane, memset(gc_counter_shifts, 0, sizeof(gc_counter_shifts)); } -atomic::~atomic() -{ -} - generation::generation(cDataPlane* dataPlane, const tSocketId& socketId) : dataPlane(dataPlane), @@ -48,10 +44,6 @@ generation::generation(cDataPlane* dataPlane, balancer_real_state_t()); } -generation::~generation() -{ -} - eResult generation::init() { eResult result = eResult::success; diff --git a/dataplane/globalbase.h b/dataplane/globalbase.h index 1f7aaca7..fbb38538 100644 --- a/dataplane/globalbase.h +++ b/dataplane/globalbase.h @@ -88,7 +88,7 @@ class atomic { public: atomic(cDataPlane* dataPlane, const tSocketId& socketId); - ~atomic(); + ~atomic() = default; public: ///< @todo cDataPlane* dataPlane; @@ -134,7 +134,7 @@ class generation { public: generation(cDataPlane* dataPlane, const tSocketId& socketId); - ~generation(); + ~generation() = default; public: eResult init(); diff --git a/dataplane/lpm.h b/dataplane/lpm.h index 319301fc..37c7c0c1 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -68,9 +68,7 @@ class lpm4_24bit_8bit_atomic } public: - lpm4_24bit_8bit_atomic() - { - } + lpm4_24bit_8bit_atomic() = default; eResult insert(stats_t& stats, const uint32_t& ipAddress, @@ -741,9 +739,7 @@ class lpm6_8x16bit_atomic } public: - lpm6_8x16bit_atomic() - { - } + lpm6_8x16bit_atomic() = default; static std::array createMask(uint8_t ones) { From 0c849107b2fb844428a4a98f10f7c30ff1459ddc Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 20:47:58 +0400 Subject: [PATCH 135/195] Use default initizliation instead of specifying value in default constructor --- autotest/autotest.cpp | 6 ++-- common/acl.h | 14 +++------ common/controlplaneconfig.h | 62 ++++++++++++------------------------- common/ctree.h | 5 ++- common/icontrolplane.h | 7 ++--- common/idataplane.h | 7 ++--- common/memory_manager.h | 7 ++--- common/nat46clat.h | 10 ++---- common/rpc_channel.h | 6 ++-- common/stream.h | 8 ++--- common/type.h | 3 +- common/weight.h | 3 +- controlplane/acl/rule.h | 5 ++- controlplane/balancer.h | 17 +++------- controlplane/base.h | 62 ++++++++++++------------------------- controlplane/counter.h | 7 ++--- dataplane/base.h | 24 +++++--------- dataplane/dynamic_table.h | 7 ++--- dataplane/hashtable.h | 23 +++++--------- dataplane/lpm.h | 52 +++++++++---------------------- dataplane/type.h | 19 ++++-------- dataplane/updater.h | 10 +++--- dataplane/worker.h | 7 ++--- 23 files changed, 116 insertions(+), 255 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 242d89cc..e653a68e 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -475,7 +475,7 @@ class pcap_expectation { public: pcap_expectation(std::string filename) : - filename(filename), has_packet(true), packetsCount(0), buffer(MAX_PACK_LEN, 0) + filename(filename), buffer(MAX_PACK_LEN, 0) { char pcap_errbuf[PCAP_ERRBUF_SIZE]; pcap = pcap_open_offline(filename.c_str(), pcap_errbuf); @@ -567,9 +567,9 @@ class pcap_expectation private: std::string filename; - bool has_packet; + bool has_packet{true}; struct pcap_pkthdr header; - uint64_t packetsCount; + uint64_t packetsCount{}; pcap_t* pcap; std::vector buffer; }; diff --git a/common/acl.h b/common/acl.h index dddc272b..4a2932ae 100644 --- a/common/acl.h +++ b/common/acl.h @@ -9,10 +9,7 @@ namespace common::acl class tree_value_t { public: - tree_value_t() : - id(0) - { - } + tree_value_t() = default; constexpr bool operator<(const tree_value_t& second) const { @@ -50,17 +47,14 @@ class tree_value_t } protected: - uint32_t id; ///< stored group_id or chunk_id + uint32_t id{}; ///< stored group_id or chunk_id }; template class tree_chunk_t { public: - tree_chunk_t() : - is_multirefs(0) - { - } + tree_chunk_t() = default; void pop(common::stream_in_t& stream) { @@ -72,7 +66,7 @@ class tree_chunk_t stream.push(values); } - uint8_t is_multirefs; + uint8_t is_multirefs{}; tree_value_t values[1u << bits]; }; diff --git a/common/controlplaneconfig.h b/common/controlplaneconfig.h index 090f8bed..0bcce0f7 100644 --- a/common/controlplaneconfig.h +++ b/common/controlplaneconfig.h @@ -13,15 +13,7 @@ namespace controlplane class state_timeout { public: - state_timeout() : - tcp_syn(YANET_CONFIG_STATE_TIMEOUT_DEFAULT), - tcp_ack(YANET_CONFIG_STATE_TIMEOUT_DEFAULT), - tcp_fin(YANET_CONFIG_STATE_TIMEOUT_DEFAULT), - udp(YANET_CONFIG_STATE_TIMEOUT_DEFAULT), - icmp(YANET_CONFIG_STATE_TIMEOUT_DEFAULT), - other(YANET_CONFIG_STATE_TIMEOUT_DEFAULT) - { - } + state_timeout() = default; operator std::tuple() const { @@ -29,12 +21,12 @@ class state_timeout } public: - uint16_t tcp_syn; - uint16_t tcp_ack; - uint16_t tcp_fin; - uint16_t udp; - uint16_t icmp; - uint16_t other; + uint16_t tcp_syn{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; + uint16_t tcp_ack{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; + uint16_t tcp_fin{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; + uint16_t udp{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; + uint16_t icmp{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; + uint16_t other{YANET_CONFIG_STATE_TIMEOUT_DEFAULT}; }; [[maybe_unused]] static void from_json(const nlohmann::json& json, @@ -142,11 +134,7 @@ class interface_t class config_t { public: - config_t() : - vrf("default"), - tunnel_enabled(false) - { - } + config_t() = default; /** @todo: tag:CP_MODULES void load(const nlohmann::json& json); @@ -186,8 +174,8 @@ class config_t public: tRouteId routeId; std::set to_kernel_prefixes; - std::string vrf; - bool tunnel_enabled; + std::string vrf{"default"}; + bool tunnel_enabled{}; std::set ignore_tables; common::ipv4_address_t ipv4_source_address; common::ipv6_address_t ipv6_source_address; @@ -315,10 +303,7 @@ using service_t = std::tuple prefixes; std::map ipv6_prefixes; std::vector ipv4_prefixes; std::set announces; diff --git a/common/ctree.h b/common/ctree.h index c12259af..eeb8c975 100644 --- a/common/ctree.h +++ b/common/ctree.h @@ -25,8 +25,7 @@ struct ctree root_node = new node_base_t(); } } - ctree(ctree&& other) : - root_node{} + ctree(ctree&& other) { if (this != &other) { @@ -392,7 +391,7 @@ struct ctree convert; }; - node_base_t* root_node; + node_base_t* root_node{}; }; } // namespace common diff --git a/common/icontrolplane.h b/common/icontrolplane.h index e8170105..88f25283 100644 --- a/common/icontrolplane.h +++ b/common/icontrolplane.h @@ -13,10 +13,7 @@ namespace interface class controlPlane { public: - controlPlane() : - clientSocket(-1) - { - } + controlPlane() = default; ~controlPlane() { @@ -395,7 +392,7 @@ class controlPlane } protected: - mutable int clientSocket; + mutable int clientSocket{-1}; mutable std::mutex mutex; }; diff --git a/common/idataplane.h b/common/idataplane.h index c0e8fbf1..8ede607d 100644 --- a/common/idataplane.h +++ b/common/idataplane.h @@ -14,10 +14,7 @@ namespace interface class dataPlane { public: - dataPlane() : - clientSocket(-1) - { - } + dataPlane() = default; ~dataPlane() { @@ -305,7 +302,7 @@ class dataPlane } protected: - mutable int clientSocket; + mutable int clientSocket{-1}; mutable std::mutex mutex; }; diff --git a/common/memory_manager.h b/common/memory_manager.h index 04e994a8..07f2a1cb 100644 --- a/common/memory_manager.h +++ b/common/memory_manager.h @@ -38,10 +38,7 @@ inline uint64_t convert_string_to_bytes(std::string string) class memory_group { public: - memory_group() : - limit(0) - { - } + memory_group() = default; template std::set for_each(const callback_t& callback) const @@ -84,7 +81,7 @@ class memory_group public: std::string name; - uint64_t limit; + uint64_t limit{}; std::vector> memory_groups; }; diff --git a/common/nat46clat.h b/common/nat46clat.h index b3c587d8..d38c0543 100644 --- a/common/nat46clat.h +++ b/common/nat46clat.h @@ -18,11 +18,7 @@ enum class module_counter : tCounterId class config { public: - config() : - dscp_mark_type(common::eDscpMarkType::never), - dscp(0) - { - } + config() = default; void pop(common::stream_in_t& stream) { @@ -54,8 +50,8 @@ class config nat46clat_id_t nat46clat_id; common::ipv6_address_t ipv6_source; common::ipv6_address_t ipv6_destination; - common::eDscpMarkType dscp_mark_type; - uint8_t dscp; + common::eDscpMarkType dscp_mark_type{common::eDscpMarkType::never}; + uint8_t dscp{}; std::set ipv6_prefixes; std::set ipv4_prefixes; std::set announces; diff --git a/common/rpc_channel.h b/common/rpc_channel.h index fc406d02..2986e1ff 100644 --- a/common/rpc_channel.h +++ b/common/rpc_channel.h @@ -16,10 +16,8 @@ namespace common::proto class UnixProtobufRpcChannel : public google::protobuf::RpcChannel { public: - UnixProtobufRpcChannel(const std::string& socketPath) : - clientSocket(-1) + UnixProtobufRpcChannel(const std::string& socketPath) { - connectChannel(socketPath); } @@ -103,7 +101,7 @@ class UnixProtobufRpcChannel : public google::protobuf::RpcChannel } private: - mutable int clientSocket; + mutable int clientSocket{-1}; mutable std::mutex mutex{}; std::vector buffer; }; diff --git a/common/stream.h b/common/stream.h index 8e0af69e..e320756d 100644 --- a/common/stream.h +++ b/common/stream.h @@ -87,8 +87,8 @@ class stream_in_t protected: const std::vector& inBuffer; - uint64_t inPosition; - bool failed; + uint64_t inPosition{}; + bool failed{}; }; // @@ -287,9 +287,7 @@ class stream_out_t // inline stream_in_t::stream_in_t(const std::vector& buffer) : - inBuffer(buffer), - inPosition(0), - failed(false) + inBuffer(buffer) { } diff --git a/common/type.h b/common/type.h index f88ae72e..dd7bc704 100644 --- a/common/type.h +++ b/common/type.h @@ -2288,7 +2288,6 @@ class tFlow { public: tFlow() : - type(eFlowType::controlPlane), ///< @todo: drop flags(0), counter_id(0) { @@ -2369,7 +2368,7 @@ class tFlow uint32_t type_params_atomic; struct { - eFlowType type; + eFlowType type{eFlowType::controlPlane}; ///< @todo: drop uint8_t flags : 2; uint32_t counter_id : 22; }; diff --git a/common/weight.h b/common/weight.h index 0b882301..20c1fb84 100644 --- a/common/weight.h +++ b/common/weight.h @@ -16,7 +16,6 @@ class weight_t public: weight_t() : - size(0), current(0) { base.resize(size_T, 0); @@ -114,7 +113,7 @@ class weight_t mutable std::vector base; - uint32_t size; + uint32_t size{}; mutable std::atomic current; }; diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 5320136f..66c88029 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -40,10 +40,9 @@ struct range_t : std::tuple struct filter_base_t { - unsigned long ref_count; + unsigned long ref_count{}; - inline constexpr filter_base_t() : - ref_count(0) {} + inline constexpr filter_base_t() = default; virtual bool is_none() const = 0; virtual ~filter_base_t() = default; virtual std::string to_string() const = 0; diff --git a/controlplane/balancer.h b/controlplane/balancer.h index 926f6ac2..f3bc4f2b 100644 --- a/controlplane/balancer.h +++ b/controlplane/balancer.h @@ -37,11 +37,7 @@ using real_counter_key_t = real_key_global_t; class generation_config_t { public: - generation_config_t() : - services_count(0), - reals_count(0) - { - } + generation_config_t() = default; void update(const controlplane::base_t& base_prev, const controlplane::base_t& base_next) @@ -61,20 +57,17 @@ class generation_config_t public: std::map name_id; std::map config_balancers; - uint64_t services_count; - uint64_t reals_count; + uint64_t services_count{}; + uint64_t reals_count{}; }; class generation_services_t { public: - generation_services_t() : - reals_enabled_count(0) - { - } + generation_services_t() = default; public: - uint64_t reals_enabled_count; + uint64_t reals_enabled_count{}; common::icp::balancer_summary::response summary; common::icp::balancer_service::response services; common::icp::balancer_real_find::response reals; diff --git a/controlplane/base.h b/controlplane/base.h index 91eadbc4..94b35318 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -21,20 +21,16 @@ namespace base class logical_port_t { public: - logical_port_t() : - vlanId(0), - promiscuousMode(0) - { - } + logical_port_t() = default; public: tLogicalPortId logicalPortId; std::string physicalPort; tPortId physicalPortId; - uint16_t vlanId; + uint16_t vlanId{}; mac_address_t macAddress; - uint8_t promiscuousMode; + uint8_t promiscuousMode{}; std::string nextModule; common::globalBase::tFlow flow; }; @@ -42,11 +38,7 @@ class logical_port_t class decap_t { public: - decap_t() : - dscpMarkType(common::eDscpMarkType::never), - dscp(0) - { - } + decap_t() = default; std::set prefixes() const { @@ -62,8 +54,8 @@ class decap_t tDecapId decapId; std::set ipv6DestinationPrefixes; - common::eDscpMarkType dscpMarkType; - uint8_t dscp; + common::eDscpMarkType dscpMarkType{common::eDscpMarkType::never}; + uint8_t dscp{}; uint8_t ipv6_enabled; std::string nextModule; common::globalBase::tFlow flow; @@ -72,19 +64,13 @@ class decap_t class nat64stateless_t { public: - nat64stateless_t() : - dscpMarkType(common::eDscpMarkType::never), - dscp(0), - firewall(1), - farm(0) - { - } + nat64stateless_t() = default; public: tNat64statelessId nat64statelessId; - common::eDscpMarkType dscpMarkType; - uint8_t dscp; + common::eDscpMarkType dscpMarkType{common::eDscpMarkType::never}; + uint8_t dscp{}; std::map> translations; - uint8_t firewall; + uint8_t firewall{1}; std::optional nat64_wkp_prefix; std::optional nat64_src_prefix; @@ -105,7 +91,7 @@ class nat64stateless_t std::optional defrag_farm_prefix; std::optional defrag_source_prefix; - uint8_t farm; + uint8_t farm{}; /// @todo: ingressFlow; /// @todo: egressFlow; @@ -416,26 +402,18 @@ class base_rib class base_t { public: - base_t() : - interfacesCount(0), - nat64statelessTranslationsCount(0), - services_count(0), - reals_count(0), - tun64MappingsCount(0), - storeSamples(false), - serial(0), - nat64stateful_pool_size(0) + base_t() { variables["balancer_real_timeout"] = 900; } public: std::map moduleTypes; - tInterfaceId interfacesCount; - tNat64statelessTranslationId nat64statelessTranslationsCount; - balancer_service_id_t services_count; - balancer_real_id_t reals_count; - tun64_id_t tun64MappingsCount; + tInterfaceId interfacesCount{}; + tNat64statelessTranslationId nat64statelessTranslationsCount{}; + balancer_service_id_t services_count{}; + balancer_real_id_t reals_count{}; + tun64_id_t tun64MappingsCount{}; std::map interfaceNames; ///< @todo: per route std::map> socket_interfaces; ///< @todo: per route @@ -456,8 +434,8 @@ class base_t acl::iface_map_t result_iface_map; std::vector dump_id_to_tag; std::map logicalport_id_to_name; - bool storeSamples; - uint32_t serial; + bool storeSamples{}; + uint32_t serial{}; std::map variables; std::map>> vrf_fqdns; - uint32_t nat64stateful_pool_size; + uint32_t nat64stateful_pool_size{}; std::map> diff --git a/controlplane/counter.h b/controlplane/counter.h index c961ab99..91d4770a 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -126,10 +126,7 @@ class counter_t public: static_assert(size_T <= YANET_CONFIG_COUNTER_FALLBACK_SIZE); - counter_t() : - manager(nullptr) - { - } + counter_t() = default; void init(counter_manager_t* manager) { @@ -352,7 +349,7 @@ class counter_t } protected: - counter_manager_t* manager; + counter_manager_t* manager{}; mutable std::mutex mutex; diff --git a/dataplane/base.h b/dataplane/base.h index a6de2202..6fbb4d0d 100644 --- a/dataplane/base.h +++ b/dataplane/base.h @@ -81,11 +81,7 @@ class PortMapper class permanently { public: - permanently() : - globalBaseAtomic(nullptr), - nat64stateful_numa_mask(0xFFFFu), - nat64stateful_numa_reverse_mask(0), - nat64stateful_numa_id(0) + permanently() { memset(globalBaseAtomics, 0, sizeof(globalBaseAtomics)); @@ -109,7 +105,7 @@ class permanently return true; } - dataplane::globalBase::atomic* globalBaseAtomic; + dataplane::globalBase::atomic* globalBaseAtomic{}; /// Pointers to all globalBaseAtomic for each CPU socket. /// /// Used to distribute firewall states. @@ -123,22 +119,16 @@ class permanently uint32_t SWNormalPriorityRateLimitPerWorker; uint8_t transportSizes[256]; - uint16_t nat64stateful_numa_mask; - uint16_t nat64stateful_numa_reverse_mask; - uint16_t nat64stateful_numa_id; + uint16_t nat64stateful_numa_mask{0xFFFFu}; + uint16_t nat64stateful_numa_reverse_mask{}; + uint16_t nat64stateful_numa_id{}; }; class generation { public: - generation() : - globalBase(nullptr), - neighbor_hashtable(nullptr) - { - } - - dataplane::globalBase::generation* globalBase; - dataplane::neighbor::hashtable const* neighbor_hashtable; + dataplane::globalBase::generation* globalBase{}; + dataplane::neighbor::hashtable const* neighbor_hashtable{}; } __rte_aligned(2 * RTE_CACHE_LINE_SIZE); } diff --git a/dataplane/dynamic_table.h b/dataplane/dynamic_table.h index 5bfb1e01..a3eec75f 100644 --- a/dataplane/dynamic_table.h +++ b/dataplane/dynamic_table.h @@ -35,10 +35,7 @@ class dynamic_table } public: - dynamic_table() : - width_bits(0) - { - } + dynamic_table() = default; template inline void lookup(const uint32_t (&k1s)[burst_size], @@ -97,7 +94,7 @@ class dynamic_table } protected: - uint32_t width_bits; + uint32_t width_bits{}; value_t values[]; }; diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index d645b9c8..30e0d446 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -129,16 +129,9 @@ class spinlock_nonrecursive_t final struct hashtable_gc_t { - hashtable_gc_t() : - offset(0), - valid_keys(0), - iterations(0) - { - } - - uint32_t offset; - uint64_t valid_keys; - uint64_t iterations; + uint32_t offset{}; + uint64_t valid_keys{}; + uint64_t iterations{}; }; template; public: - hashtable_chain_spinlock_t() : - gcIndex(0) + hashtable_chain_spinlock_t() { for (uint32_t id = 0; id < extendedSize_T - 1; ++id) { @@ -1166,8 +1158,7 @@ class hashtable_chain_spinlock_t iterator_t(hashtable_t* hashtable, const uint32_t& chunk_i) : hashtable(hashtable), - chunk_i(chunk_i), - key_i(0) + chunk_i(chunk_i) { } @@ -1175,7 +1166,7 @@ class hashtable_chain_spinlock_t hashtable_t* hashtable; uint32_t chunk_i; - uint32_t key_i; + uint32_t key_i{}; }; iterator_t begin() const @@ -1453,7 +1444,7 @@ class hashtable_chain_spinlock_t protected: spinlock_t extendedChunkLocker; - uint32_t gcIndex; + uint32_t gcIndex{}; uint32_t freeExtendedChunkId; YADECAP_CACHE_ALIGNED(align1); diff --git a/dataplane/lpm.h b/dataplane/lpm.h index 37c7c0c1..f58c835b 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -1498,10 +1498,7 @@ class lpm4_24bit_8bit_id32 class updater { public: - updater() : - extended_chunks_count(1) - { - } + updater() = default; void clear(const unsigned int tree_size) { @@ -1539,7 +1536,7 @@ class lpm4_24bit_8bit_id32 } public: - unsigned int extended_chunks_count; + unsigned int extended_chunks_count{1}; std::vector remap_chunks; }; @@ -1612,12 +1609,9 @@ class lpm4_24bit_8bit_id32 struct value_t { - value_t() : - id(0) - { - } + value_t() = default; - uint32_t id; + uint32_t id{}; }; struct chunk_step1_t @@ -1981,10 +1975,7 @@ class lpm6_8x16bit_id32 class updater { public: - updater() : - chunks_count(1) ///< 0 is root chunk - { - } + updater() = default; void clear(const unsigned int tree_size) { @@ -2012,7 +2003,7 @@ class lpm6_8x16bit_id32 } public: - unsigned int chunks_count; + unsigned int chunks_count{1}; ///< 0 is root chunk std::vector remap_chunks; }; @@ -2139,12 +2130,9 @@ class lpm6_8x16bit_id32 struct value_t { - value_t() : - id(0) - { - } + value_t() = default; - uint32_t id; + uint32_t id{}; }; struct chunk_t @@ -2234,11 +2222,7 @@ class lpm6_8x16bit_id32_dynamic class updater { public: - updater() : - lpm(nullptr), - chunks_size(0) - { - } + updater() = default; void update_pointer(lpm6_8x16bit_id32_dynamic* lpm, const tSocketId socket_id, @@ -2358,9 +2342,9 @@ class lpm6_8x16bit_id32_dynamic } public: - lpm6_8x16bit_id32_dynamic* lpm; + lpm6_8x16bit_id32_dynamic* lpm{}; tSocketId socket_id; - unsigned int chunks_size; + unsigned int chunks_size{}; unsigned int chunks_count; std::vector remap_chunks; }; @@ -2466,12 +2450,9 @@ class lpm6_8x16bit_id32_dynamic struct value_t { - value_t() : - id(0) - { - } + value_t() = default; - uint32_t id; + uint32_t id{}; }; struct chunk_t @@ -2680,12 +2661,9 @@ class lpm6_16x8bit_id32_dynamic protected: struct value_t { - value_t() : - id(0) - { - } + value_t() = default; - uint32_t id; + uint32_t id{}; }; struct chunk_t diff --git a/dataplane/type.h b/dataplane/type.h index 9fedb934..25e25bd5 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -301,8 +301,7 @@ struct tInterface struct nat64stateful_t { - nat64stateful_t() : - pool_size(0) + nat64stateful_t() { state_timeout.tcp_syn = YANET_CONFIG_STATE_TIMEOUT_DEFAULT; state_timeout.tcp_ack = YANET_CONFIG_STATE_TIMEOUT_DEFAULT; @@ -315,7 +314,7 @@ struct nat64stateful_t /// @todo: uint8_t enabled; uint32_t pool_start; - uint32_t pool_size; + uint32_t pool_size{}; tCounterId counter_id; uint8_t ipv4_dscp_flags; struct @@ -405,12 +404,9 @@ static_assert(YANET_CONFIG_COUNTERS_SIZE <= 0xFFFFFF, "invalid YANET_CONFIG_COUN struct route_value_t { - route_value_t() : - type(common::globalBase::eNexthopType::controlPlane) - { - } + route_value_t() = default; - common::globalBase::eNexthopType type; ///< @todo: DELETE + common::globalBase::eNexthopType type{common::globalBase::eNexthopType::controlPlane}; ///< @todo: DELETE union { @@ -425,12 +421,9 @@ struct route_value_t struct route_tunnel_value_t { - route_tunnel_value_t() : - type(common::globalBase::eNexthopType::controlPlane) - { - } + route_tunnel_value_t() = default; - common::globalBase::eNexthopType type; ///< @todo: DELETE + common::globalBase::eNexthopType type{common::globalBase::eNexthopType::controlPlane}; ///< @todo: DELETE union { diff --git a/dataplane/updater.h b/dataplane/updater.h index 6f50d7b3..06088de0 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -216,8 +216,7 @@ class updater_lpm4_24bit_8bit_id32 const tSocketId socket_id) : name(name), memory_manager(memory_manager), - socket_id(socket_id), - pointer(nullptr) + socket_id(socket_id) { } @@ -291,7 +290,7 @@ class updater_lpm4_24bit_8bit_id32 object_type::stats_t stats; public: - object_type* pointer; + object_type* pointer{}; }; // @@ -306,8 +305,7 @@ class updater_lpm6_16x8bit_id32 const tSocketId socket_id) : name(name), memory_manager(memory_manager), - socket_id(socket_id), - pointer(nullptr) + socket_id(socket_id) { } @@ -381,7 +379,7 @@ class updater_lpm6_16x8bit_id32 object_type::stats_t stats; public: - object_type* pointer; + object_type* pointer{}; }; // diff --git a/dataplane/worker.h b/dataplane/worker.h index bc49d05c..93b92742 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -32,10 +32,7 @@ template class tStack { public: - tStack() : - mbufsCount(0) - { - } + tStack() = default; inline void insert(rte_mbuf** mbufs, unsigned int mbufsCount) { @@ -55,7 +52,7 @@ class tStack } public: - unsigned int mbufsCount; + unsigned int mbufsCount{}; rte_mbuf* mbufs[TSize]; }; From 7a1f7d6b5d85d27adbdb5ccd49a1bd3d94c47691 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 14:23:32 +0400 Subject: [PATCH 136/195] Use nullptr instead of zero for pointer types --- autotest/autotest.cpp | 4 ++-- common/shared_memory.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index e653a68e..50c4ceb5 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -505,8 +505,8 @@ class pcap_expectation { return; } - pcap_pkthdr* h = 0; - const u_char* data = 0; + pcap_pkthdr* h = nullptr; + const u_char* data = nullptr; if (pcap_next_ex(pcap, &h, &data) >= 0) { memcpy(&header, h, sizeof(struct pcap_pkthdr)); diff --git a/common/shared_memory.h b/common/shared_memory.h index dbd46621..39cddf37 100644 --- a/common/shared_memory.h +++ b/common/shared_memory.h @@ -286,7 +286,7 @@ class SharedMemory if (socket_id.has_value()) { oldmask = numa_allocate_nodemask(); - if (get_mempolicy(&oldpolicy, oldmask->maskp, oldmask->size + 1, 0, 0) < 0) + if (get_mempolicy(&oldpolicy, oldmask->maskp, oldmask->size + 1, nullptr, 0) < 0) { YANET_LOG_WARNING("get_mempolicy(): %s, continue with the use of sockets turned off\n", strerror(errno)); oldpolicy = MPOL_DEFAULT; From 43294938c8a0743d6e30179ffac32b3ee42d5e91 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 14:28:32 +0400 Subject: [PATCH 137/195] Pass by value and use std::move instead of passing by const reference Switching to pass by value and using std::move improves efficiency by reducing unnecessary copies and allowing better handling of rvalue arguments. --- autotest/autotest.cpp | 5 ++- common/acl.h | 2 + controlplane/base.h | 69 +++++++++++++++++----------------- controlplane/configconverter.h | 10 +++-- controlplane/configparser.h | 3 +- 5 files changed, 48 insertions(+), 41 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 50c4ceb5..51821078 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -407,8 +408,8 @@ class TextDumper class PcapDumper { public: - PcapDumper(const std::string& path, int capsize = MAX_PACK_LEN) : - tmpFilePath(path), pcap(pcap_open_dead(DLT_EN10MB, capsize)) + PcapDumper(std::string path, int capsize = MAX_PACK_LEN) : + tmpFilePath(std::move(path)), pcap(pcap_open_dead(DLT_EN10MB, capsize)) { if (!pcap) diff --git a/common/acl.h b/common/acl.h index 4a2932ae..fba42e72 100644 --- a/common/acl.h +++ b/common/acl.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "stream.h" #include "type.h" diff --git a/controlplane/base.h b/controlplane/base.h index 94b35318..e358c65b 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -2,6 +2,7 @@ #include #include +#include #include #include "common/controlplaneconfig.h" @@ -136,10 +137,10 @@ class acl_rule_transport_tcp_t public: acl_rule_transport_tcp_t() = default; - acl_rule_transport_tcp_t(const ranges_t& sourcePorts, - const ranges_t& destinationPorts) : - sourcePorts(sourcePorts), - destinationPorts(destinationPorts) + acl_rule_transport_tcp_t(ranges_t sourcePorts, + ranges_t destinationPorts) : + sourcePorts(std::move(sourcePorts)), + destinationPorts(std::move(destinationPorts)) { } @@ -154,10 +155,10 @@ class acl_rule_transport_udp_t public: acl_rule_transport_udp_t() = default; - acl_rule_transport_udp_t(const ranges_t& sourcePorts, - const ranges_t& destinationPorts) : - sourcePorts(sourcePorts), - destinationPorts(destinationPorts) + acl_rule_transport_udp_t(ranges_t sourcePorts, + ranges_t destinationPorts) : + sourcePorts(std::move(sourcePorts)), + destinationPorts(std::move(destinationPorts)) { } @@ -176,27 +177,27 @@ class acl_rule_transport_icmpv4_t { } - acl_rule_transport_icmpv4_t(const ranges_t& types) : - types(types), + acl_rule_transport_icmpv4_t(ranges_t types) : + types(std::move(types)), codes(range_t{0x00, 0xFF}), identifiers(range_t{0x0000, 0xFFFF}) { } - acl_rule_transport_icmpv4_t(const ranges_t& types, - const ranges_t& codes) : - types(types), - codes(codes), + acl_rule_transport_icmpv4_t(ranges_t types, + ranges_t codes) : + types(std::move(types)), + codes(std::move(codes)), identifiers(range_t{0x0000, 0xFFFF}) { } - acl_rule_transport_icmpv4_t(const ranges_t& types, - const ranges_t& codes, - const ranges_t& identifiers) : - types(types), - codes(codes), - identifiers(identifiers) + acl_rule_transport_icmpv4_t(ranges_t types, + ranges_t codes, + ranges_t identifiers) : + types(std::move(types)), + codes(std::move(codes)), + identifiers(std::move(identifiers)) { } @@ -216,27 +217,27 @@ class acl_rule_transport_icmpv6_t { } - acl_rule_transport_icmpv6_t(const ranges_t& types) : - types(types), + acl_rule_transport_icmpv6_t(ranges_t types) : + types(std::move(types)), codes(range_t{0x00, 0xFF}), identifiers(range_t{0x0000, 0xFFFF}) { } - acl_rule_transport_icmpv6_t(const ranges_t& types, - const ranges_t& codes) : - types(types), - codes(codes), + acl_rule_transport_icmpv6_t(ranges_t types, + ranges_t codes) : + types(std::move(types)), + codes(std::move(codes)), identifiers(range_t{0x0000, 0xFFFF}) { } - acl_rule_transport_icmpv6_t(const ranges_t& types, - const ranges_t& codes, - const ranges_t& identifiers) : - types(types), - codes(codes), - identifiers(identifiers) + acl_rule_transport_icmpv6_t(ranges_t types, + ranges_t codes, + ranges_t identifiers) : + types(std::move(types)), + codes(std::move(codes)), + identifiers(std::move(identifiers)) { } @@ -251,8 +252,8 @@ class acl_rule_transport_other_t public: acl_rule_transport_other_t() = default; - acl_rule_transport_other_t(const ranges_t& protocolTypes) : - protocolTypes(protocolTypes) + acl_rule_transport_other_t(ranges_t protocolTypes) : + protocolTypes(std::move(protocolTypes)) { } diff --git a/controlplane/configconverter.h b/controlplane/configconverter.h index 12c2da88..7be12d6a 100644 --- a/controlplane/configconverter.h +++ b/controlplane/configconverter.h @@ -1,16 +1,18 @@ #pragma once +#include + #include "base.h" class config_converter_t { public: config_converter_t(cControlPlane* controlplane, - const controlplane::base_t& baseNext, - const common::idp::limits::response& limits) : + controlplane::base_t baseNext, + common::idp::limits::response limits) : controlplane(controlplane), - baseNext(baseNext), - limits(limits) + baseNext(std::move(baseNext)), + limits(std::move(limits)) { } diff --git a/controlplane/configparser.h b/controlplane/configparser.h index ad8af05f..a3c9b7d9 100644 --- a/controlplane/configparser.h +++ b/controlplane/configparser.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "common/controlplaneconfig.h" @@ -10,7 +11,7 @@ class config_parser_t { public: config_parser_t(common::idp::getConfig::response dataPlaneConfig) : - dataPlaneConfig(dataPlaneConfig) + dataPlaneConfig(std::move(dataPlaneConfig)) {} controlplane::base_t loadConfig(const std::string& rootFilePath, const nlohmann::json& rootJson, const std::map& jsons = {}); From c182db6698446dec760014dd60ebc3eaf981cb42 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 14:34:06 +0400 Subject: [PATCH 138/195] Add missing includes Include "config_values.h" for symbol ConfigValues Include "samples.h" for symbol samples::Sampler Include "libfwparser/fw_config.h" for symbol ipfw::rule_ptr_t Include for symbol uint32_t Include for symbol std::string Include "common/idp.h" for symbol common::idp::debug_latch_update::id Include "common/idataplane.h" for symbol interface::dataPlane Include for symbol std::pair --- cli/latch.h | 3 +++ controlplane/errors.h | 1 + controlplane/segment_allocator.h | 1 + dataplane/worker_gc.h | 2 ++ librib/libyabird.h | 1 + parser/fw_dump.h | 3 ++- 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cli/latch.h b/cli/latch.h index 1302378c..841ed303 100644 --- a/cli/latch.h +++ b/cli/latch.h @@ -1,7 +1,10 @@ #pragma once +#include "common/idataplane.h" +#include "common/idp.h" #include #include +#include namespace latch { diff --git a/controlplane/errors.h b/controlplane/errors.h index 81f63891..2f0c64dd 100644 --- a/controlplane/errors.h +++ b/controlplane/errors.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "common/result.h" diff --git a/controlplane/segment_allocator.h b/controlplane/segment_allocator.h index b4dfe6d2..240fe11a 100644 --- a/controlplane/segment_allocator.h +++ b/controlplane/segment_allocator.h @@ -2,6 +2,7 @@ #include #include +#include #include diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index a74c56c9..476eb699 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -5,7 +5,9 @@ #include "base.h" #include "common.h" +#include "config_values.h" #include "hashtable.h" +#include "samples.h" #include "utils.h" #include "common/generation.h" diff --git a/librib/libyabird.h b/librib/libyabird.h index d7214a73..2df72c03 100644 --- a/librib/libyabird.h +++ b/librib/libyabird.h @@ -1,6 +1,7 @@ #ifndef _LIBYABIRD_H_ #define _LIBYABIRD_H_ +#include #ifdef __cplusplus /* * Simple LIST implementation used in bird2. diff --git a/parser/fw_dump.h b/parser/fw_dump.h index 7551b19e..ea0598f4 100644 --- a/parser/fw_dump.h +++ b/parser/fw_dump.h @@ -1,6 +1,7 @@ #pragma once -#include "fw_parser.h" +#include "libfwparser/fw_parser.h" +#include "libfwparser/fw_config.h" #include namespace ipfw From 20d2af910c77ca7dcafc9a78c4f7a19cd1f66730 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 19:29:25 +0400 Subject: [PATCH 139/195] Use range-based for loop instead of regular loop where applicable --- cli/config.cpp | 6 +-- controlplane/acl_network.h | 6 +-- controlplane/acl_network_table.cpp | 9 +--- controlplane/acl_transport.cpp | 18 ++----- controlplane/acl_transport_table.cpp | 5 +- dataplane/globalbase.cpp | 48 ++++++----------- dataplane/lpm.h | 78 ++++++++-------------------- dataplane/unittest/hashtable.cpp | 36 +++++-------- dataplane/worker.cpp | 16 ++---- dataplane/worker_gc.cpp | 38 ++++---------- logger/main.cpp | 4 +- 11 files changed, 76 insertions(+), 188 deletions(-) diff --git a/cli/config.cpp b/cli/config.cpp index 8d03d107..5b4ffe6f 100644 --- a/cli/config.cpp +++ b/cli/config.cpp @@ -139,16 +139,16 @@ bool allowPrefix(nlohmann::json& prefixes, } // check whether current announces includes announceRaw - for (auto announceIt = announces->begin(); announceIt != announces->end(); ++announceIt) + for (auto& announceIt : *announces) { // sanity check that announce has string type - if (!announceIt->is_string()) + if (!announceIt.is_string()) { throw std::string{"invalid type of prefix item announce. Should be string"}; } // announce already presented within the prefix - if (announceIt->get_ref() == announceRaw) + if (announceIt.get_ref() == announceRaw) { return false; } diff --git a/controlplane/acl_network.h b/controlplane/acl_network.h index 3171a253..ca5d2799 100644 --- a/controlplane/acl_network.h +++ b/controlplane/acl_network.h @@ -63,14 +63,12 @@ class network_t void compile() { - for (unsigned int filter_id = 0; - filter_id < filters.size(); - filter_id++) + for (auto& filter : filters) { remap_group_ids.resize(0); remap_group_ids.resize(group_id, 0); - for (const auto& network : filters[filter_id]) + for (const auto& network : filter) { tree.insert(network.addr, network.mask, group_id, remap_group_ids); } diff --git a/controlplane/acl_network_table.cpp b/controlplane/acl_network_table.cpp index 89b2da4c..c682c8e3 100644 --- a/controlplane/acl_network_table.cpp +++ b/controlplane/acl_network_table.cpp @@ -61,18 +61,11 @@ void network_table_t::prepare(const uint32_t height, const uint32_t width) void network_table_t::compile() { - for (unsigned int filter_id = 0; - filter_id < filters.size(); - filter_id++) + for (auto [network_ipv4_source_filter_id, network_ipv4_destination_filter_id, network_ipv6_source_filter_id, network_ipv6_destination_filter_id] : filters) { remap_group_ids.clear(); remap_group_ids.resize(group_id, 0); - const auto& [network_ipv4_source_filter_id, - network_ipv4_destination_filter_id, - network_ipv6_source_filter_id, - network_ipv6_destination_filter_id] = filters[filter_id]; - const auto& network_ipv4_source_group_ids = compiler->network_ipv4_source.filter_group_ids[network_ipv4_source_filter_id]; const auto& network_ipv4_destination_group_ids = compiler->network_ipv4_destination.filter_group_ids[network_ipv4_destination_filter_id]; const auto& network_ipv6_source_group_ids = compiler->network_ipv6_source.filter_group_ids[network_ipv6_source_filter_id]; diff --git a/controlplane/acl_transport.cpp b/controlplane/acl_transport.cpp index 2eaa3edc..82bf04e4 100644 --- a/controlplane/acl_transport.cpp +++ b/controlplane/acl_transport.cpp @@ -105,12 +105,8 @@ void transport_t::distribute() void transport_t::compile() { - for (unsigned int layer_id = 0; - layer_id < layers.size(); - layer_id++) + for (auto& layer : layers) { - auto& layer = layers[layer_id]; - for (const auto filter_id : layer.filter_ids_set) { const auto& filter = filters[filter_id]; @@ -144,12 +140,8 @@ void transport_t::compile() layer.icmp_identifier.prepare(); } - for (unsigned int layer_id = 0; - layer_id < layers.size(); - layer_id++) + for (auto& layer : layers) { - auto& layer = layers[layer_id]; - layer.protocol.compile(); layer.tcp_source.compile(); layer.tcp_destination.compile(); @@ -163,12 +155,8 @@ void transport_t::compile() void transport_t::populate() { - for (unsigned int layer_id = 0; - layer_id < layers.size(); - layer_id++) + for (auto& layer : layers) { - auto& layer = layers[layer_id]; - layer.protocol.populate(); layer.tcp_source.populate(); layer.tcp_destination.populate(); diff --git a/controlplane/acl_transport_table.cpp b/controlplane/acl_transport_table.cpp index f4af5cb6..6a6bb050 100644 --- a/controlplane/acl_transport_table.cpp +++ b/controlplane/acl_transport_table.cpp @@ -158,14 +158,11 @@ void transport_table::thread_t::compile() std::array table_indexes; table_indexes.fill(0); - for (unsigned int filter_id = 0; - filter_id < transport_table->filters.size(); - filter_id++) + for (auto [network_table_filter_id, network_flags_filter_id, transport_filter_id] : transport_table->filters) { remap_group_ids.clear(); remap_group_ids.resize(group_id, 0); - const auto& [network_table_filter_id, network_flags_filter_id, transport_filter_id] = transport_table->filters[filter_id]; const auto& network_table_group_ids_orig = transport_table->compiler->network_table.filter_id_group_ids[network_table_filter_id]; const auto& network_flags_group_ids = transport_table->compiler->network_flags.filter_id_group_ids[network_flags_filter_id]; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index d6d5ddb7..1b3bc7ac 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -541,53 +541,39 @@ eResult generation::get(const common::idp::getGlobalBase::request& request, eResult generation::clear() { - for (unsigned int logicalPortId = 0; - logicalPortId < CONFIG_YADECAP_LOGICALPORTS_SIZE; - logicalPortId++) + for (auto& logicalPort : logicalPorts) { - logicalPorts[logicalPortId] = dataplane::globalBase::tLogicalPort(); + logicalPort = dataplane::globalBase::tLogicalPort(); } - for (tun64_id_t tun64Id = 0; - tun64Id < CONFIG_YADECAP_TUN64_SIZE; - tun64Id++) + for (auto& tun64tunnel : tun64tunnels) { - tun64tunnels[tun64Id] = dataplane::globalBase::tun64_t(); + tun64tunnel = dataplane::globalBase::tun64_t(); } - for (unsigned int decapId = 0; - decapId < CONFIG_YADECAP_DECAPS_SIZE; - decapId++) + for (auto& decap : decaps) { - decaps[decapId] = dataplane::globalBase::tDecap(); + decap = dataplane::globalBase::tDecap(); } - for (unsigned int interfaceId = 0; - interfaceId < CONFIG_YADECAP_INTERFACES_SIZE; - interfaceId++) + for (auto& interface : interfaces) { - interfaces[interfaceId] = dataplane::globalBase::tInterface(); + interface = dataplane::globalBase::tInterface(); } - for (unsigned int nat64statefulId = 0; - nat64statefulId < YANET_CONFIG_NAT64STATEFULS_SIZE; - nat64statefulId++) + for (auto& nat64stateful : nat64statefuls) { - nat64statefuls[nat64statefulId] = dataplane::globalBase::nat64stateful_t(); + nat64stateful = dataplane::globalBase::nat64stateful_t(); } - for (unsigned int nat64statelessId = 0; - nat64statelessId < CONFIG_YADECAP_NAT64STATELESSES_SIZE; - nat64statelessId++) + for (auto& nat64statelesse : nat64statelesses) { - nat64statelesses[nat64statelessId] = dataplane::globalBase::tNat64stateless(); + nat64statelesse = dataplane::globalBase::tNat64stateless(); } - for (unsigned int balancer_id = 0; - balancer_id < YANET_CONFIG_BALANCERS_SIZE; - balancer_id++) + for (auto& balancer : balancers) { - balancers[balancer_id] = dataplane::globalBase::balancer_t(); + balancer = dataplane::globalBase::balancer_t(); } tun64_enabled = 0; @@ -602,11 +588,9 @@ eResult generation::clear() tun64mappingsTable.clear(); - for (unsigned int fw_state_sync_config_id = 0; - fw_state_sync_config_id < CONFIG_YADECAP_ACLS_SIZE; - fw_state_sync_config_id++) + for (auto& fw_state_sync_config : fw_state_sync_configs) { - fw_state_sync_configs[fw_state_sync_config_id] = fw_state_sync_config_t{}; + fw_state_sync_config = fw_state_sync_config_t{}; } // NOTE: we don't explicitly clear current fw states, as there might be responding packets. diff --git a/dataplane/lpm.h b/dataplane/lpm.h index f58c835b..ba653d3c 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -304,11 +304,9 @@ class lpm4_24bit_8bit_atomic YADECAP_MEMORY_BARRIER_COMPILE; - for (unsigned int entry_i = 0; - entry_i < 256; - entry_i++) + for (auto& entrie : chunk.entries) { - chunk.entries[entry_i].atomic = newEntry.atomic; + entrie.atomic = newEntry.atomic; } chunk.entries[0].flags |= flag; @@ -346,12 +344,10 @@ class lpm4_24bit_8bit_atomic } bool merge = true; - for (unsigned int next_entry_i = 0; - next_entry_i < 256; - next_entry_i++) + for (auto& entrie : extendedChunks[extendedChunkId].entries) { - if (!(extendedChunks[extendedChunkId].entries[next_entry_i].flags & flagValid && - extendedChunks[extendedChunkId].entries[next_entry_i].valueId == valueId)) + if (!(entrie.flags & flagValid && + entrie.valueId == valueId)) { merge = false; break; @@ -502,11 +498,9 @@ class lpm4_24bit_8bit_atomic } bool isEmpty = true; - for (unsigned int next_entry_i = 0; - next_entry_i < 256; - next_entry_i++) + for (auto& entrie : extendedChunks[extendedChunkId].entries) { - if (extendedChunks[extendedChunkId].entries[next_entry_i].flags & (flagExtended | flagValid)) + if (entrie.flags & (flagExtended | flagValid)) { isEmpty = false; break; @@ -637,12 +631,8 @@ class lpm4_24bit_8bit_atomic memcpy(rootChunk.entries, from_chunk.entries, sizeof(from_chunk.entries)); std::vector> nexts; - for (uint32_t i = 0; - i < (1u << 24); - i++) + for (auto& chunk_value : rootChunk.entries) { - auto& chunk_value = rootChunk.entries[i]; - if (chunk_value.flags & flagExtended) { auto& chunk_id = remap_chunks[chunk_value.extendedChunkId]; @@ -1043,13 +1033,11 @@ class lpm6_8x16bit_atomic return; } - for (unsigned int entry_i = 0; - entry_i < 256 * 256; - entry_i++) + for (auto& entrie : extendedChunk.entries) { - if (extendedChunk.entries[entry_i].flags & flagExtended) + if (entrie.flags & flagExtended) { - freeExtendedChunk(stats, extendedChunk.entries[entry_i].extendedChunkId); + freeExtendedChunk(stats, entrie.extendedChunkId); } } @@ -1088,11 +1076,9 @@ class lpm6_8x16bit_atomic YADECAP_MEMORY_BARRIER_COMPILE; - for (unsigned int entry_i = 0; - entry_i < 256 * 256; - entry_i++) + for (auto& entrie : chunk.entries) { - chunk.entries[entry_i].atomic = newEntry.atomic; + entrie.atomic = newEntry.atomic; } chunk.entries[0].flags |= flag; @@ -1153,12 +1139,10 @@ class lpm6_8x16bit_atomic } bool merge = true; - for (unsigned int next_entry_i = 0; - next_entry_i < 256 * 256; - next_entry_i++) + for (auto& entrie : extendedChunks[extendedChunkId].entries) { - if (!(extendedChunks[extendedChunkId].entries[next_entry_i].flags & flagValid && - extendedChunks[extendedChunkId].entries[next_entry_i].valueId == valueId)) + if (!(entrie.flags & flagValid && + entrie.valueId == valueId)) { merge = false; break; @@ -1288,11 +1272,9 @@ class lpm6_8x16bit_atomic } bool isEmpty = true; - for (unsigned int next_entry_i = 0; - next_entry_i < 256 * 256; - next_entry_i++) + for (auto& entrie : extendedChunks[extendedChunkId].entries) { - if (extendedChunks[extendedChunkId].entries[next_entry_i].flags & (flagExtended | flagValid)) + if (entrie.flags & (flagExtended | flagValid)) { isEmpty = false; break; @@ -1402,12 +1384,8 @@ class lpm6_8x16bit_atomic memcpy(rootChunk.entries, from_chunk.entries, sizeof(from_chunk.entries)); std::vector> nexts; - for (uint32_t i = 0; - i < (1u << 16); - i++) + for (auto& chunk_value : rootChunk.entries) { - auto& chunk_value = rootChunk.entries[i]; - if (chunk_value.flags & flagExtended) { auto& chunk_id = remap_chunks[chunk_value.extendedChunkId]; @@ -1449,12 +1427,8 @@ class lpm6_8x16bit_atomic memcpy(chunk.entries, from_chunk.entries, sizeof(from_chunk.entries)); std::vector> nexts; - for (uint32_t i = 0; - i < (1u << 16); - i++) + for (auto& chunk_value : chunk.entries) { - auto& chunk_value = chunk.entries[i]; - if (chunk_value.flags & flagExtended) { auto& chunk_id = remap_chunks[chunk_value.extendedChunkId]; @@ -2305,12 +2279,8 @@ class lpm6_8x16bit_id32_dynamic std::vector> nexts; - for (uint32_t i = 0; - i < (1u << bits); - i++) + for (auto& chunk_value : chunk.values) { - auto& chunk_value = chunk.values[i]; - if (chunk_value.id & 0x80000000u) ///< is_chunk_id { auto& chunk_id = remap_chunks[chunk_value.id ^ 0x80000000u]; @@ -2622,12 +2592,8 @@ class lpm6_16x8bit_id32_dynamic std::vector> nexts; - for (uint32_t i = 0; - i < (1u << bits); - i++) + for (auto& chunk_value : chunk.values) { - auto& chunk_value = chunk.values[i]; - if (chunk_value.id & 0x80000000u) ///< is_chunk_id { auto& chunk_id = stats.remap_chunks[chunk_value.id ^ 0x80000000u]; diff --git a/dataplane/unittest/hashtable.cpp b/dataplane/unittest/hashtable.cpp index 92d2311c..94c1ee19 100644 --- a/dataplane/unittest/hashtable.cpp +++ b/dataplane/unittest/hashtable.cpp @@ -220,47 +220,37 @@ TEST(hashtable_mod_id32, burst) { const auto mask = ht.lookup(hashes, keys, values, YANET_CONFIG_BURST_SIZE); EXPECT_EQ(0, mask); - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (unsigned int value : values) { - EXPECT_EQ(0x80000000, values[i] & (1u << 31)); + EXPECT_EQ(0x80000000, value & (1u << 31)); } } - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (auto key : keys) { - EXPECT_EQ(eResult::success, ht.insert(updater, keys[i], value1)); + EXPECT_EQ(eResult::success, ht.insert(updater, key, value1)); } { const auto mask = ht.lookup(hashes, keys, values, YANET_CONFIG_BURST_SIZE); EXPECT_EQ(0xFFFFFFFF, mask); - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (unsigned int value : values) { - EXPECT_EQ(value1, values[i]); + EXPECT_EQ(value1, value); } } - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (auto key : keys) { - EXPECT_EQ(eResult::success, ht.insert(updater, keys[i], value2)); + EXPECT_EQ(eResult::success, ht.insert(updater, key, value2)); } { const auto mask = ht.lookup(hashes, keys, values, YANET_CONFIG_BURST_SIZE); EXPECT_EQ(0xFFFFFFFF, mask); - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (unsigned int value : values) { - EXPECT_EQ(value2, values[i]); + EXPECT_EQ(value2, value); } } @@ -269,11 +259,9 @@ TEST(hashtable_mod_id32, burst) { const auto mask = ht.lookup(hashes, keys, values, YANET_CONFIG_BURST_SIZE); EXPECT_EQ(0, mask); - for (unsigned int i = 0; - i < YANET_CONFIG_BURST_SIZE; - i++) + for (unsigned int value : values) { - EXPECT_EQ(0x80000000, values[i] & (1u << 31)); + EXPECT_EQ(0x80000000, value & (1u << 31)); } } } diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 861edc75..a494c5ea 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -3074,11 +3074,8 @@ inline void cWorker::nat64stateful_lan_handle() } /// @todo: create cross-numa state over slowworker? - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : basePermanently.globalBaseAtomics) { - auto* globalbase_atomic = basePermanently.globalBaseAtomics[numa_i]; if (globalbase_atomic == basePermanently.globalBaseAtomic) { continue; @@ -3114,11 +3111,8 @@ inline void cWorker::nat64stateful_lan_handle() /// @todo: create cross-numa state over slowworker? value.timestamp_last_packet = basePermanently.globalBaseAtomic->currentTime - YANET_CONFIG_STATE_TIMEOUT_MAX; - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : basePermanently.globalBaseAtomics) { - auto* globalbase_atomic = basePermanently.globalBaseAtomics[numa_i]; if (globalbase_atomic == basePermanently.globalBaseAtomic) { continue; @@ -4894,9 +4888,8 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common value.tcp.dst_flags = 0; bool emit = false; - for (unsigned int idx = 0; idx < YANET_CONFIG_NUMA_SIZE; ++idx) + for (auto atomic : basePermanently.globalBaseAtomics) { - dataplane::globalBase::atomic* atomic = basePermanently.globalBaseAtomics[idx]; if (atomic == nullptr) { break; @@ -4992,9 +4985,8 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common value.tcp.dst_flags = 0; bool emit = false; - for (unsigned int idx = 0; idx < YANET_CONFIG_NUMA_SIZE; ++idx) + for (auto atomic : basePermanently.globalBaseAtomics) { - dataplane::globalBase::atomic* atomic = basePermanently.globalBaseAtomics[idx]; if (atomic == nullptr) { break; diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 759c8703..50cc901e 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -246,11 +246,8 @@ void worker_gc_t::handle_nat64stateful_gc() const auto& nat64stateful = base.globalBase->nat64statefuls[wan_key.nat64stateful_id]; /// check other wan tables - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - auto* globalbase_atomic = base_permanently.globalBaseAtomics[numa_i]; if (globalbase_atomic == base_permanently.globalBaseAtomic) { continue; @@ -282,12 +279,9 @@ void worker_gc_t::handle_nat64stateful_gc() lan_key.port_destination = wan_key.port_source; /// check lan tables - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - auto* globalbase_atomic = base_permanently.globalBaseAtomics[numa_i]; - if (globalbase_atomic == nullptr) + if (globalbase_atomic == nullptr) { break; } @@ -431,12 +425,9 @@ void worker_gc_t::handle_balancer_gc() auto value = *iter.value(); iter.unlock(); - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic_other : base_permanently.globalBaseAtomics) { - dataplane::globalBase::atomic* globalbase_atomic_other = base_permanently.globalBaseAtomics[numa_i]; - if (globalbase_atomic_other == nullptr) + if (globalbase_atomic_other == nullptr) { break; } @@ -988,12 +979,9 @@ void worker_gc_t::nat64stateful_remove_state(const dataplane::globalBase::nat64s const dataplane::globalBase::nat64stateful_wan_key& wan_key) { /// remove on other numas - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - auto* globalbase_atomic = base_permanently.globalBaseAtomics[numa_i]; - if (globalbase_atomic == base_permanently.globalBaseAtomic) + if (globalbase_atomic == base_permanently.globalBaseAtomic) { continue; } @@ -1110,11 +1098,8 @@ void worker_gc_t::nat64stateful_state(const common::idp::nat64stateful_state::re uint16_t wan_last_seen = calc_last_seen(wan_value.timestamp_last_packet); /// check other wan tables - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - auto* globalbase_atomic = base_permanently.globalBaseAtomics[numa_i]; if (globalbase_atomic == base_permanently.globalBaseAtomic) { continue; @@ -1145,12 +1130,9 @@ void worker_gc_t::nat64stateful_state(const common::idp::nat64stateful_state::re lan_key.port_destination = wan_key.port_source; /// check lan tables - for (unsigned int numa_i = 0; - numa_i < YANET_CONFIG_NUMA_SIZE; - numa_i++) + for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - auto* globalbase_atomic = base_permanently.globalBaseAtomics[numa_i]; - if (globalbase_atomic == nullptr) + if (globalbase_atomic == nullptr) { break; } diff --git a/logger/main.cpp b/logger/main.cpp index f9f31ce7..564b0590 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -295,9 +295,9 @@ int main(int argc, args.push_back(masterLcoreId.data()); YANET_LOG_DEBUG("eal args:\n"); - for (uint32_t i = 0; i < args.size(); ++i) + for (auto& arg : args) { - YANET_LOG_DEBUG("%s\n", args[i]); + YANET_LOG_DEBUG("%s\n", arg); } ret = rte_eal_init(args.size(), (char**)args.data()); From 766910e8f5fddb5e9d7504b248d63fe5fd6bc04c Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:03:46 +0400 Subject: [PATCH 140/195] Initizile uninitalized variables Initializing variables to default values, even when they will be filled later, prevents the use of uninitialized memory, which can lead to UB or hard-to-track bugs. --- autotest/autotest.cpp | 18 ++++---- common/refarray.h | 2 +- common/rpc_channel.h | 2 +- common/sdpclient.h | 2 +- common/sendrecv.h | 2 +- common/shared_memory.h | 4 +- common/stream.h | 2 +- controlplane/bus.cpp | 2 +- controlplane/configparser.cpp | 4 +- controlplane/isystem.cpp | 20 ++++----- controlplane/protobus.cpp | 2 +- controlplane/rib.cpp | 2 +- controlplane/unittest/parser.cpp | 2 +- dataplane/bus.cpp | 2 +- dataplane/controlplane.cpp | 4 +- dataplane/dataplane.cpp | 2 +- dataplane/dpdk.cpp | 4 +- dataplane/dregress.cpp | 12 ++--- dataplane/hashtable.h | 14 +++--- dataplane/icmp.h | 4 +- dataplane/kernel_interface_handle.cpp | 4 +- dataplane/lpm.h | 14 +++--- dataplane/prepare.h | 2 +- dataplane/samples.h | 2 +- dataplane/slow_worker.cpp | 12 ++--- dataplane/sock_dev.cpp | 2 +- dataplane/unittest/hashtable.cpp | 14 +++--- dataplane/worker.cpp | 64 +++++++++++++-------------- dataplane/worker_gc.cpp | 24 +++++----- libfwparser/fw_lexer.cpp | 2 +- librib/libyabird.cpp | 12 ++--- parser/main.cpp | 4 +- unwind/unwind.cpp | 2 +- 33 files changed, 132 insertions(+), 132 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 51821078..796f67f3 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -123,9 +123,9 @@ eResult tAutotest::initSharedMemory() dataPlaneSharedMemory = dataPlane.get_shm_info(); std::map shm_by_key; - key_t ipcKey; - int shmid; - void* shmaddr; + key_t ipcKey = 0; + int shmid = 0; + void* shmaddr = nullptr; for (const auto& shmInfo : dataPlaneSharedMemory) { @@ -237,8 +237,8 @@ void tAutotest::sendThread(std::string interfaceName, throw ""; } - pcap_pkthdr* header; - const u_char* data; + pcap_pkthdr* header = nullptr; + const u_char* data = nullptr; static u_char zeros[MAX_PACK_LEN]; auto iface = pcaps[interfaceName]; @@ -1927,7 +1927,7 @@ bool tAutotest::step_dumpPackets(const YAML::Node& yamlStep, std::string expectFilePath = path + "/" + yamlDump["expect"].as(); bool success = true; - common::bufferring* ring; + common::bufferring* ring = nullptr; { /// searching memory ring by tag auto it = dumpRings.find(tag); if (it == dumpRings.end()) @@ -1938,7 +1938,7 @@ bool tAutotest::step_dumpPackets(const YAML::Node& yamlStep, ring = &it->second; } - pcap_t* pcap; + pcap_t* pcap = nullptr; { /// open pcap file with expected data char pcap_errbuf[PCAP_ERRBUF_SIZE]; pcap = pcap_open_offline(expectFilePath.data(), pcap_errbuf); @@ -1950,8 +1950,8 @@ bool tAutotest::step_dumpPackets(const YAML::Node& yamlStep, } struct pcap_pkthdr header; - const u_char* pcap_packet; - common::bufferring::item_t* shm_packet; + const u_char* pcap_packet = nullptr; + common::bufferring::item_t* shm_packet = nullptr; uint64_t position = 0; /// read packets from pcap and compare them with packets from memory ring diff --git a/common/refarray.h b/common/refarray.h index 4c2046eb..a7b838ab 100644 --- a/common/refarray.h +++ b/common/refarray.h @@ -58,7 +58,7 @@ class refarray_t return std::nullopt; } - id_t id; + id_t id = 0; ids_unused_size--; if (ids_unused.size()) { diff --git a/common/rpc_channel.h b/common/rpc_channel.h index 2986e1ff..2f84875a 100644 --- a/common/rpc_channel.h +++ b/common/rpc_channel.h @@ -84,7 +84,7 @@ class UnixProtobufRpcChannel : public google::protobuf::RpcChannel // single response - uint64_t messageSize; + uint64_t messageSize = 0; if (auto err = common::recvAll(clientSocket, (char*)&messageSize, sizeof(messageSize)); err != 0) { controller->SetFailed(std::string("recv response: ") + strerror(err)); diff --git a/common/sdpclient.h b/common/sdpclient.h index b2b91007..f9abf909 100644 --- a/common/sdpclient.h +++ b/common/sdpclient.h @@ -33,7 +33,7 @@ class SdpClient { number_of_attempts++; std::string message_error; - uint64_t size_mmap; + uint64_t size_mmap = 0; result = ReadItAgainMainFileDataplane(sdp_data, size_mmap, message_error); if (result == eResultRead::error) { diff --git a/common/sendrecv.h b/common/sendrecv.h index 328338f6..6054d061 100644 --- a/common/sendrecv.h +++ b/common/sendrecv.h @@ -122,7 +122,7 @@ static inline Resp recv(int clientSocket) //unsafe { std::vector buffer; - uint64_t messageSize; + uint64_t messageSize = 0; if (auto err = recvAll(clientSocket, (char*)&messageSize, sizeof(messageSize)); err != 0) { throw std::string("recv(): ") + strerror(err); diff --git a/common/shared_memory.h b/common/shared_memory.h index 39cddf37..20f03f61 100644 --- a/common/shared_memory.h +++ b/common/shared_memory.h @@ -52,7 +52,7 @@ class SharedMemory { str++; } - char* endptr; + char* endptr = nullptr; unsigned long long size = strtoull(str, &endptr, 0); // The string still contains kB (or mB, gB), but it only matters to us // whether the value is 0 or not @@ -282,7 +282,7 @@ class SharedMemory static std::pair SetMemoryPolicy(std::optional socket_id) { struct bitmask* oldmask = nullptr; - int oldpolicy; + int oldpolicy = 0; if (socket_id.has_value()) { oldmask = numa_allocate_nodemask(); diff --git a/common/stream.h b/common/stream.h index e320756d..623dc503 100644 --- a/common/stream.h +++ b/common/stream.h @@ -336,7 +336,7 @@ inline void stream_in_t::pop(char* buffer, uint64_t bufferSize) inline void stream_in_t::pop(std::string& value) { - std::string::size_type size; + std::string::size_type size = 0; pop(size); if (this->inBuffer.size() - inPosition < size) diff --git a/controlplane/bus.cpp b/controlplane/bus.cpp index 0cd8d2ad..8584b4c5 100644 --- a/controlplane/bus.cpp +++ b/controlplane/bus.cpp @@ -103,7 +103,7 @@ void bus::clientThread(int clientSocket) for (;;) { - uint64_t messageSize; + uint64_t messageSize = 0; if (auto err = common::recvAll(clientSocket, (char*)&messageSize, sizeof(messageSize)); err != 0) { /// @todo: log diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index af331d5e..cc6aa182 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -1655,7 +1655,7 @@ void config_parser_t::loadConfig_balancer_services(controlplane::base_t& baseNex std::string scheduler_string = service_json["scheduler"]; - balancer::scheduler scheduler; + balancer::scheduler scheduler{}; balancer::scheduler_params scheduler_params{}; if (scheduler_string == "rr") { @@ -1678,7 +1678,7 @@ void config_parser_t::loadConfig_balancer_services(controlplane::base_t& baseNex throw error_result_t(eResult::invalidConfigurationFile, "unknown scheduler: " + scheduler_string); } - balancer::forwarding_method forwarding_method; + balancer::forwarding_method forwarding_method{}; if (!exist(service_json, "lvs_method")) { diff --git a/controlplane/isystem.cpp b/controlplane/isystem.cpp index f95db2d0..e993f532 100644 --- a/controlplane/isystem.cpp +++ b/controlplane/isystem.cpp @@ -41,11 +41,11 @@ bool system::getEtherAddress(const uint32_t& ipAddress, { /// @todo: try to connect - int arpSocket; + int arpSocket = 0; struct arpreq request; - struct sockaddr_in* sin; - struct ifaddrs* interfaces; - struct ifaddrs* interfaceNext; + struct sockaddr_in* sin = nullptr; + struct ifaddrs* interfaces = nullptr; + struct ifaddrs* interfaceNext = nullptr; arpSocket = socket(AF_INET, SOCK_DGRAM, 0); if (arpSocket == -1) @@ -242,9 +242,9 @@ std::set system::getLocalIpAddresses() { std::set result; - struct ifaddrs* ifaddr; - struct ifaddrs* ifa; - int n; + struct ifaddrs* ifaddr = nullptr; + struct ifaddrs* ifa = nullptr; + int n = 0; if (getifaddrs(&ifaddr) == -1) { @@ -276,9 +276,9 @@ std::set> system::getLocalIPv6Addresses() { std::set> result; - struct ifaddrs* ifaddr; - struct ifaddrs* ifa; - int n; + struct ifaddrs* ifaddr = nullptr; + struct ifaddrs* ifa = nullptr; + int n = 0; if (getifaddrs(&ifaddr) == -1) { diff --git a/controlplane/protobus.cpp b/controlplane/protobus.cpp index d0316793..71b4d518 100644 --- a/controlplane/protobus.cpp +++ b/controlplane/protobus.cpp @@ -101,7 +101,7 @@ void protoBus::clientThread(int clientSocket) for (;;) { - uint64_t messageSize; + uint64_t messageSize = 0; if (auto err = common::recvAll(clientSocket, (char*)&messageSize, sizeof(messageSize)); err != 0) { if (err > 0) diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index fddf2cb6..43b6c5f6 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -553,7 +553,7 @@ void rib_t::rib_eor(const common::icp::rib_update::eor& request) void rib_t::rib_flush(bool force_flush) { - bool flush; + bool flush = false; { std::lock_guard rib_update_guard(rib_update_mutex); std::lock_guard prefixes_guard(prefixes_mutex); diff --git a/controlplane/unittest/parser.cpp b/controlplane/unittest/parser.cpp index 14534002..c07b9e62 100644 --- a/controlplane/unittest/parser.cpp +++ b/controlplane/unittest/parser.cpp @@ -8,7 +8,7 @@ namespace auto parse_rules(const std::string& rules, bool validation = false) { - bool ret; + bool ret = false; ipfw::fw_config_t firewall; firewall.schedule_string(rules); diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 95a81a03..57e70177 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -160,7 +160,7 @@ void cBus::clientThread(int clientSocket) for (;;) { - uint64_t messageSize; + uint64_t messageSize = 0; if (!recvAll(clientSocket, (char*)&messageSize, sizeof(messageSize))) { stats.errors[(uint32_t)common::idp::errorType::busRead]++; diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 525bfa4f..d493091c 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -713,7 +713,7 @@ common::idp::lpm4LookupAddress::response cControlPlane::lpm4LookupAddress(const const tSocketId& socketId = iter.first; const auto* globalBase = iter.second[dataPlane->currentGlobalBaseId]; - uint32_t valueId; + uint32_t valueId = 0; if (globalBase->route_lpm4->lookup(ipAddress, &valueId)) { response[socketId] = {true, @@ -745,7 +745,7 @@ common::idp::lpm6LookupAddress::response cControlPlane::lpm6LookupAddress(const const tSocketId& socketId = iter.first; const auto* globalBase = iter.second[dataPlane->currentGlobalBaseId]; - uint32_t valueId; + uint32_t valueId = 0; if (globalBase->route_lpm6->lookup(request, &valueId)) { response[socketId] = {true, diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 28ab5eac..6ff792b9 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -487,7 +487,7 @@ eResult cDataPlane::initPorts() const auto& [pci, name, symmetric_mode, rss_flags] = configPortIter.second; (void)pci; - tPortId portId; + tPortId portId = 0; if (StartsWith(name, SOCK_DEV_PREFIX)) { diff --git a/dataplane/dpdk.cpp b/dataplane/dpdk.cpp index 2d05d4f5..c799536d 100644 --- a/dataplane/dpdk.cpp +++ b/dataplane/dpdk.cpp @@ -16,7 +16,7 @@ std::optional GetNameByPort(tPortId pid) std::optional GetPortByName(const std::string& name) { - tPortId port; + tPortId port = 0; if (int res = rte_eth_dev_get_port_by_name(name.c_str(), &port); res) { YANET_LOG_ERROR("Failed to get port for name %s (%s)\n", name.c_str(), strerror(res)); @@ -36,4 +36,4 @@ std::optional GetMacAddress(tPortId pid) return std::optional{ether_addr.addr_bytes}; } -} \ No newline at end of file +} diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index 0da1b766..0d04ec6f 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -128,13 +128,13 @@ void dregress_t::insert(rte_mbuf* mbuf) } else { - dregress::connection_value_t* value; - dataplane::spinlock_t* locker; + dregress::connection_value_t* value = nullptr; + dataplane::spinlock_t* locker = nullptr; connections->lookup(key, value, locker); - uint32_t loss_count; - uint32_t ack_count; + uint32_t loss_count = 0; + uint32_t ack_count = 0; int32_t ack_diff = 0; int32_t loss_diff = 0; @@ -158,7 +158,7 @@ void dregress_t::insert(rte_mbuf* mbuf) labelled_label = label; ipv6_address_t prefix_address; - uint8_t prefix_mask; + uint8_t prefix_mask = 0; if (prefix.is_ipv4()) { prefix_address = ipv6_address_t::convert(prefix.get_ipv4().address()); @@ -334,7 +334,7 @@ void dregress_t::insert(rte_mbuf* mbuf) } } - uint16_t payload_length; + uint16_t payload_length = 0; if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { rte_ipv4_hdr* ipv4HeaderInner = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index 30e0d446..01b801fb 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -62,7 +62,7 @@ inline uint32_t calculate_hash_crc(const key_t& key) template inline uint32_t calculate_hash_murmur3(const key_t& key) { - uint32_t result; + uint32_t result = 0; MurmurHash3_x86_32(&key, sizeof(key), 19, &result); return result; } @@ -1645,7 +1645,7 @@ class hashtable_mod_id32 for (const auto& [key, value] : keys) { - eResult insert_result; + eResult insert_result = eResult::success; if constexpr (std::is_same_v) { insert_result = insert(updater, key, value); @@ -2173,8 +2173,8 @@ class hashtable_mod_spinlock { bool result = true; - value_t* ht_value; - spinlock_nonrecursive_t* locker; + value_t* ht_value = nullptr; + spinlock_nonrecursive_t* locker = nullptr; uint32_t hash = lookup(key, ht_value, locker); if (ht_value) @@ -2650,8 +2650,8 @@ class hashtable_mod_spinlock_dynamic { bool result = true; - value_t* ht_value; - spinlock_nonrecursive_t* locker; + value_t* ht_value = nullptr; + spinlock_nonrecursive_t* locker = nullptr; uint32_t hash = lookup(key, ht_value, locker); if (ht_value) @@ -3235,7 +3235,7 @@ class hashtable_mod_dynamic { bool result = true; - value_t* ht_value; + value_t* ht_value = nullptr; uint32_t hash = lookup(key, ht_value); if (ht_value) diff --git a/dataplane/icmp.h b/dataplane/icmp.h index 84a2a692..b6f9faa7 100644 --- a/dataplane/icmp.h +++ b/dataplane/icmp.h @@ -10,7 +10,7 @@ inline bool yanet_icmp_translate_v6_to_v4(icmp_header_t* icmpHeader, uint16_t length, uint16_t checksum6) { - uint8_t type; + uint8_t type = 0; if (icmpHeader->type == ICMP6_ECHO_REQUEST) { @@ -46,7 +46,7 @@ inline bool yanet_icmp_translate_v4_to_v6(icmp_header_t* icmpHeader, uint16_t length, uint16_t checksum6) { - uint8_t type; + uint8_t type = 0; if (icmpHeader->type == ICMP_ECHO) { diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp index db4a1555..7c57b7c5 100644 --- a/dataplane/kernel_interface_handle.cpp +++ b/dataplane/kernel_interface_handle.cpp @@ -154,7 +154,7 @@ bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf, tQueueId que bool KernelInterfaceHandle::CloneMTU(const uint16_t port_id) noexcept { - uint16_t mtu; + uint16_t mtu = 0; if (rte_eth_dev_get_mtu(port_id, &mtu)) { return (rte_eth_dev_set_mtu(kni_port_, mtu) == 0); @@ -195,4 +195,4 @@ bool KernelInterfaceHandle::SetupTxQueue(tQueueId queue, tSocketId socket) noexc return true; } -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/lpm.h b/dataplane/lpm.h index ba653d3c..d4d959b8 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -195,7 +195,7 @@ class lpm4_24bit_8bit_atomic bool lookup(const uint32_t& ipAddress, uint32_t* valueId = nullptr) const { - uint32_t lvalueId; + uint32_t lvalueId = 0; lookup(&ipAddress, &lvalueId, 1); @@ -379,7 +379,7 @@ class lpm4_24bit_8bit_atomic return eResult::success; } - uint32_t extendedChunkId; + uint32_t extendedChunkId = 0; if (!newExtendedChunk(stats, extendedChunkId)) { return eResult::isFull; @@ -526,7 +526,7 @@ class lpm4_24bit_8bit_atomic { /// valid - uint32_t extendedChunkId; + uint32_t extendedChunkId = 0; if (!newExtendedChunk(stats, extendedChunkId)) { return eResult::isFull; @@ -942,7 +942,7 @@ class lpm6_8x16bit_atomic uint32_t* valueId = nullptr) const { ipv6_address_t lipv6Address; - uint32_t lvalueId; + uint32_t lvalueId = 0; memcpy(lipv6Address.bytes, ipv6Address.data(), 16); lookup(&lipv6Address, &lvalueId, 1); @@ -964,7 +964,7 @@ class lpm6_8x16bit_atomic uint32_t* value_id = nullptr) const { ipv6_address_t lipv6Address; - uint32_t lvalueId; + uint32_t lvalueId = 0; memcpy(lipv6Address.bytes, ipv6_address, 16); lookup(&lipv6Address, &lvalueId, 1); @@ -1174,7 +1174,7 @@ class lpm6_8x16bit_atomic return eResult::success; } - uint32_t extendedChunkId; + uint32_t extendedChunkId = 0; if (!newExtendedChunk(stats, extendedChunkId)) { YADECAP_LOG_WARNING("lpm6 is full\n"); @@ -1300,7 +1300,7 @@ class lpm6_8x16bit_atomic { /// valid - uint32_t extendedChunkId; + uint32_t extendedChunkId = 0; if (!newExtendedChunk(stats, extendedChunkId)) { YADECAP_LOG_WARNING("lpm6 is full\n"); diff --git a/dataplane/prepare.h b/dataplane/prepare.h index 42aed03a..57630cbb 100644 --- a/dataplane/prepare.h +++ b/dataplane/prepare.h @@ -64,7 +64,7 @@ inline bool prepareL3(rte_mbuf* mbuf, dataplane::metadata* metadata) uint8_t transport_headerType = ipv6Header->proto; uint16_t transport_headerOffset = metadata->network_headerOffset + sizeof(rte_ipv6_hdr); - unsigned int extension_i; + unsigned int extension_i = 0; for (extension_i = 0; extension_i < CONFIG_YADECAP_IPV6_EXTENSIONS_MAX + 1; extension_i++) diff --git a/dataplane/samples.h b/dataplane/samples.h index 8fbf09d7..f9cf132b 100644 --- a/dataplane/samples.h +++ b/dataplane/samples.h @@ -97,7 +97,7 @@ class Sampler return; } - sample_base_t* sample; + sample_base_t* sample = nullptr; if (metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { diff --git a/dataplane/slow_worker.cpp b/dataplane/slow_worker.cpp index 6354200f..1778d564 100644 --- a/dataplane/slow_worker.cpp +++ b/dataplane/slow_worker.cpp @@ -422,7 +422,7 @@ bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) return false; } - tAclId aclId; + tAclId aclId = 0; if (!slow_worker_->dataPlane->controlPlane->fw_state_multicast_acl_ids.apply([&](auto& fw_state_multicast_acl_ids) { auto it = fw_state_multicast_acl_ids.find(common::ipv6_address_t(ipv6Header->dst_addr)); if (it == fw_state_multicast_acl_ids.end()) @@ -520,8 +520,8 @@ bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) { (void)socketId; - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = globalBaseAtomic->fw6_state->lookup(key, lookup_value, locker); if (lookup_value) { @@ -601,8 +601,8 @@ bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) { (void)socketId; - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = globalBaseAtomic->fw4_state->lookup(key, lookup_value, locker); if (lookup_value) { @@ -636,7 +636,7 @@ void SlowWorker::BalancerICMPForwardCriticalSection( common::ip_address_t original_src_from_icmp_payload; common::ip_address_t src_from_ip_header; - uint16_t original_src_port_from_icmp_payload; + uint16_t original_src_port_from_icmp_payload = 0; uint32_t balancer_id = metadata->flow.data.balancer.id; diff --git a/dataplane/sock_dev.cpp b/dataplane/sock_dev.cpp index 14852e6d..5cd1f6d2 100644 --- a/dataplane/sock_dev.cpp +++ b/dataplane/sock_dev.cpp @@ -297,7 +297,7 @@ sock_dev_rx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) } } while (rc == 0); /// Repeat if there is no data yet - struct rte_mbuf* mbuf; + struct rte_mbuf* mbuf = nullptr; mbuf = rte_pktmbuf_alloc(sq->mb_pool); if (unlikely(mbuf == nullptr)) { diff --git a/dataplane/unittest/hashtable.cpp b/dataplane/unittest/hashtable.cpp index 94c1ee19..78381e00 100644 --- a/dataplane/unittest/hashtable.cpp +++ b/dataplane/unittest/hashtable.cpp @@ -10,7 +10,7 @@ TEST(HashtableTest, Basic) { dataplane::hashtable_chain_t t; - int* v; + int* v = nullptr; int k = 1; t.lookup(&k, &v, 1); EXPECT_EQ(nullptr, v); @@ -42,8 +42,8 @@ TEST(HashtableTest, Extended) for (int k = 0; k < 512; ++k) { - int* v; - dataplane::spinlock_t* locker; + int* v = nullptr; + dataplane::spinlock_t* locker = nullptr; t.lookup(k, v, locker); if ((k % 7) && (k % 11)) @@ -326,8 +326,8 @@ TEST(hashtable_mod_spinlock, basic) const uint32_t value1 = 12345u; const uint32_t value2 = 12345678u; - uint32_t* value; - dataplane::spinlock_nonrecursive_t* locker; + uint32_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; { const uint32_t hash = ht.lookup(key, value, locker); @@ -403,8 +403,8 @@ TEST(hashtable_mod_spinlock, collision) 32> ht; - uint32_t* value; - dataplane::spinlock_nonrecursive_t* locker; + uint32_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; for (unsigned int i = 0; i < 64; diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index a494c5ea..3bb517ca 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -2183,7 +2183,7 @@ inline void cWorker::route_handle4() key.address.mapped_ipv4_address.address = nexthop.neighbor_address.mapped_ipv4_address.address; } - dataplane::neighbor::value const* value; + dataplane::neighbor::value const* value = nullptr; base.neighbor_hashtable->lookup(key, value); if (value) { @@ -2307,7 +2307,7 @@ inline void cWorker::route_handle6() memcpy(key.address.bytes, nexthop.neighbor_address.bytes, 16); } - dataplane::neighbor::value const* value; + dataplane::neighbor::value const* value = nullptr; base.neighbor_hashtable->lookup(key, value); if (value) { @@ -2522,7 +2522,7 @@ inline void cWorker::route_tunnel_handle4() key.address.mapped_ipv4_address.address = nexthop.neighbor_address.mapped_ipv4_address.address; } - dataplane::neighbor::value const* value; + dataplane::neighbor::value const* value = nullptr; base.neighbor_hashtable->lookup(key, value); if (value) { @@ -2649,7 +2649,7 @@ inline void cWorker::route_tunnel_handle6() memcpy(key.address.bytes, nexthop.neighbor_address.bytes, 16); } - dataplane::neighbor::value const* value; + dataplane::neighbor::value const* value = nullptr; base.neighbor_hashtable->lookup(key, value); if (value) { @@ -2718,7 +2718,7 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, return; } - uint16_t payload_length; + uint16_t payload_length = 0; bool is_ipv4 = metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); if (is_ipv4 && !nexthop.is_ipv6) { @@ -2755,8 +2755,8 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, } else { - uint32_t vtc_flow; - uint16_t payload_len; + uint32_t vtc_flow = 0; + uint16_t payload_len = 0; if (is_ipv4) { rte_ipv4_hdr* ipv4HeaderInner = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); @@ -2969,8 +2969,8 @@ inline void cWorker::nat64stateful_lan_handle() const auto& nat64stateful = base.globalBase->nat64statefuls[metadata->flow.data.nat64stateful_id]; - dataplane::globalBase::nat64stateful_lan_value* value_lookup; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::nat64stateful_lan_value* value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = nat64stateful_lan_state->lookup(key, value_lookup, locker); if (value_lookup) { @@ -3018,9 +3018,9 @@ inline void cWorker::nat64stateful_lan_handle() wan_key.port_source = key.port_destination; wan_key.port_destination = key.port_source; - uint32_t wan_hash; - dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup; - dataplane::spinlock_nonrecursive_t* wan_locker; + uint32_t wan_hash = 0; + dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* wan_locker = nullptr; for (unsigned int try_i = 0; try_i < YANET_CONFIG_NAT64STATEFUL_INSERT_TRIES; try_i++) @@ -3260,8 +3260,8 @@ inline void cWorker::nat64stateful_wan_handle() const auto& nat64stateful = base.globalBase->nat64statefuls[metadata->flow.data.nat64stateful_id]; - dataplane::globalBase::nat64stateful_wan_value* value_lookup; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::nat64stateful_wan_value* value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; nat64stateful_wan_state->lookup(key, value_lookup, locker); if (!value_lookup) { @@ -4053,8 +4053,8 @@ inline void cWorker::balancer_handle() /// @todo: BALANCER TCP SYN - dataplane::globalBase::balancer_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::balancer_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = basePermanently.globalBaseAtomic->balancer_state->lookup(key, value, locker); bool rescheduleReal = false; if (value) @@ -4322,7 +4322,7 @@ inline void cWorker::balancer_ipv6_source(rte_ipv6_hdr* header, const rte_ipv4_hdr* ipv4HeaderInner, const rte_ipv6_hdr* ipv6HeaderInner) { - uint32_t random_src; + uint32_t random_src = 0; if (ipv4HeaderInner) { random_src = ipv4HeaderInner->src_addr; @@ -4666,8 +4666,8 @@ inline void cWorker::balancer_icmp_forward_handle() const balancer_service_id_t service_id = metadata->flow.data.atomic >> 8; const auto& service = base.globalBase->balancer_services[service_id]; - dataplane::globalBase::balancer_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::balancer_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; basePermanently.globalBaseAtomic->balancer_state->lookup(key, value, locker); if (value) @@ -4753,8 +4753,8 @@ inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf) key.dst_port = 0; } - dataplane::globalBase::fw_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; basePermanently.globalBaseAtomic->fw4_state->lookup(key, value, locker); return acl_checkstate(mbuf, value, locker); @@ -4789,8 +4789,8 @@ inline cWorker::FlowFromState cWorker::acl_checkstate(rte_mbuf* mbuf) key.dst_port = 0; } - dataplane::globalBase::fw_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; basePermanently.globalBaseAtomic->fw6_state->lookup(key, value, locker); return acl_checkstate(mbuf, value, locker); @@ -4895,8 +4895,8 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common break; } - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = atomic->fw4_state->lookup(key, lookup_value, locker); if (lookup_value) { @@ -4992,8 +4992,8 @@ inline void cWorker::acl_create_state(rte_mbuf* mbuf, tAclId aclId, const common break; } - dataplane::globalBase::fw_state_value_t* lookup_value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; const uint32_t hash = atomic->fw6_state->lookup(key, lookup_value, locker); if (lookup_value) { @@ -5382,7 +5382,7 @@ void cWorker::acl_log(rte_mbuf* mbuf, const common::globalBase::tFlow& flow, tAc const auto& base = bases[localBaseId & 1]; dataplane::metadata* metadata = YADECAP_METADATA(mbuf); - samples::sample_t* sample; + samples::sample_t* sample = nullptr; if (rte_mempool_get(dataPlane->mempool_log, (void**)&sample) != 0) { stats->logs_drops++; @@ -5480,8 +5480,8 @@ inline cWorker::FlowFromState cWorker::acl_egress_checkstate(rte_mbuf* mbuf) key.dst_port = 0; } - dataplane::globalBase::fw_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; basePermanently.globalBaseAtomic->fw4_state->lookup(key, value, locker); return acl_egress_checkstate(mbuf, value, locker); @@ -5516,8 +5516,8 @@ inline cWorker::FlowFromState cWorker::acl_egress_checkstate(rte_mbuf* mbuf) key.dst_port = 0; } - dataplane::globalBase::fw_state_value_t* value; - dataplane::spinlock_nonrecursive_t* locker; + dataplane::globalBase::fw_state_value_t* value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; basePermanently.globalBaseAtomic->fw6_state->lookup(key, value, locker); return acl_egress_checkstate(mbuf, value, locker); diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 50cc901e..e4eac656 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -257,8 +257,8 @@ void worker_gc_t::handle_nat64stateful_gc() break; } - dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup; - dataplane::spinlock_nonrecursive_t* wan_locker; + dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* wan_locker = nullptr; globalbase_atomic->nat64stateful_wan_state->lookup(wan_key, wan_value_lookup, wan_locker); if (wan_value_lookup) { @@ -286,8 +286,8 @@ void worker_gc_t::handle_nat64stateful_gc() break; } - dataplane::globalBase::nat64stateful_lan_value* lan_value_lookup; - dataplane::spinlock_nonrecursive_t* lan_locker; + dataplane::globalBase::nat64stateful_lan_value* lan_value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* lan_locker = nullptr; globalbase_atomic->nat64stateful_lan_state->lookup(lan_key, lan_value_lookup, lan_locker); if (lan_value_lookup) { @@ -440,9 +440,9 @@ void worker_gc_t::handle_balancer_gc() bool saved = true; bool updated = false; - dataplane::globalBase::balancer_state_value_t* ht_value; - dataplane::spinlock_nonrecursive_t* locker; - uint32_t old_real_id; + dataplane::globalBase::balancer_state_value_t* ht_value = nullptr; + dataplane::spinlock_nonrecursive_t* locker = nullptr; + uint32_t old_real_id = 0; uint32_t hash = globalbase_atomic_other->balancer_state->lookup(*iter.key(), ht_value, locker); if (ht_value) @@ -945,7 +945,7 @@ void worker_gc_t::handle_callbacks() void worker_gc_t::handle_free_mbuf() { rte_mbuf* mbufs[CONFIG_YADECAP_MBUFS_BURST_SIZE]; - unsigned int mbufs_count; + unsigned int mbufs_count = 0; for (auto& ring : toFree_) { @@ -1109,8 +1109,8 @@ void worker_gc_t::nat64stateful_state(const common::idp::nat64stateful_state::re break; } - dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup; - dataplane::spinlock_nonrecursive_t* wan_locker; + dataplane::globalBase::nat64stateful_wan_value* wan_value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* wan_locker = nullptr; globalbase_atomic->nat64stateful_wan_state->lookup(wan_key, wan_value_lookup, wan_locker); if (wan_value_lookup) { @@ -1137,8 +1137,8 @@ void worker_gc_t::nat64stateful_state(const common::idp::nat64stateful_state::re break; } - dataplane::globalBase::nat64stateful_lan_value* lan_value_lookup; - dataplane::spinlock_nonrecursive_t* lan_locker; + dataplane::globalBase::nat64stateful_lan_value* lan_value_lookup = nullptr; + dataplane::spinlock_nonrecursive_t* lan_locker = nullptr; globalbase_atomic->nat64stateful_lan_state->lookup(lan_key, lan_value_lookup, lan_locker); if (lan_value_lookup) { diff --git a/libfwparser/fw_lexer.cpp b/libfwparser/fw_lexer.cpp index cad85fed..e5773853 100644 --- a/libfwparser/fw_lexer.cpp +++ b/libfwparser/fw_lexer.cpp @@ -110,7 +110,7 @@ fw_lexer_t::make_IP6PRJID(const std::string& s, fw_parser_t::location_type& l) common::ipv6_address_t addr; std::string tmp = s; uint32_t prjid = 0; - int prefixlen, prjid_prefixlen = 32; + int prefixlen = 0, prjid_prefixlen = 32; // handle addresses with holes in masks 1407@2a02:6b8:c00::/40 auto pos = tmp.find("@"); diff --git a/librib/libyabird.cpp b/librib/libyabird.cpp index aed7c5e6..538c2efc 100644 --- a/librib/libyabird.cpp +++ b/librib/libyabird.cpp @@ -180,12 +180,12 @@ void libyabird_t::update(yanet_data_t* data) std::set attribute_communities; std::set attribute_large_communities; std::vector labels; - node* n; - yanet_prefix_t* p; - yanet_u32_t* uptr; + node* n = nullptr; + yanet_prefix_t* p = nullptr; + yanet_u32_t* uptr = nullptr; uint32_t attribute_local_preference = 0; uint32_t attribute_med = 0; - uint32_t i; + uint32_t i = 0; if (data->flags & YANET_ORIGIN) attribute_origin = std::string(data->origin); @@ -259,7 +259,7 @@ void libyabird_t::update(yanet_data_t* data) WALK_LIST(n, data->prefixes) { common::ip_prefix_t prefix; - size_t pos; + size_t pos = 0; p = reinterpret_cast(n); @@ -306,7 +306,7 @@ void libyabird_t::update(yanet_data_t* data) WALK_LIST(n, data->withdraw) { common::ip_prefix_t prefix; - size_t pos; + size_t pos = 0; p = reinterpret_cast(n); diff --git a/parser/main.cpp b/parser/main.cpp index 279558ff..d2acd485 100644 --- a/parser/main.cpp +++ b/parser/main.cpp @@ -36,9 +36,9 @@ int main(int argc, char* argv[]) { std::shared_ptr config; std::string dname, fname, mname; - bool cmd_mode, quiet_mode, test_mode, dump, success, sanity; + bool cmd_mode = false, quiet_mode = false, test_mode = false, dump = false, success = false, sanity = false; int verbose_level = 0; - char ch; + char ch = 0; cmd_mode = quiet_mode = test_mode = dump = sanity = false; while (!cmd_mode && (ch = getopt(argc, argv, "d:f:c:m:Dqsvnh")) != -1) diff --git a/unwind/unwind.cpp b/unwind/unwind.cpp index 1856b41f..0566628d 100644 --- a/unwind/unwind.cpp +++ b/unwind/unwind.cpp @@ -90,7 +90,7 @@ int main(int argc, char* argv[]) common::acl::iface_map_t ifmap; std::set oif, iif; std::string fname; - char ch; + char ch = 0; while ((ch = getopt(argc, argv, "f:o:i:hI")) != -1) { From 34b4a78f5ed6dc2c0db40e583da9a8cbe91d97e2 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:21:29 +0400 Subject: [PATCH 141/195] Some member functions should be marker [[nodiscard]] https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-nodiscard.html --- autotest/autotest.cpp | 12 +-- cli/influxdb_format.h | 2 +- common/acl.h | 8 +- common/btree.h | 2 +- common/refarray.h | 2 +- common/rpc_controller.h | 10 +- common/sdpcommon.h | 2 +- common/static_vector.h | 6 +- common/type.h | 132 +++++++++++++-------------- controlplane/acl/bitset.h | 12 +-- controlplane/acl/network.h | 4 +- controlplane/acl/rule.h | 30 +++--- controlplane/acl_filter.h | 2 +- controlplane/base.h | 2 +- controlplane/configconverter.h | 6 +- controlplane/configparser.h | 2 +- controlplane/dregress.h | 2 +- controlplane/errors.h | 2 +- controlplane/route.h | 8 +- controlplane/segment_allocator.h | 4 +- controlplane/telegraf.h | 4 +- dataplane/base.h | 10 +- dataplane/controlplane.h | 18 ++-- dataplane/fragmentation.h | 10 +- dataplane/hashtable.h | 22 ++--- dataplane/kernel_interface_handle.h | 6 +- dataplane/kernel_interface_handler.h | 12 +-- dataplane/lpm.h | 4 +- dataplane/samples.h | 4 +- dataplane/type.h | 4 +- dataplane/updater.h | 8 +- dataplane/worker.h | 4 +- libfwparser/fw_config.h | 6 +- 33 files changed, 181 insertions(+), 181 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 796f67f3..97096132 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -438,7 +438,7 @@ class PcapDumper pcap_dump((u_char*)dumper, header, data); } - std::string path() const + [[nodiscard]] std::string path() const { return tmpFilePath; } @@ -526,7 +526,7 @@ class pcap_expectation } } - bool has_unmatched_packets() const + [[nodiscard]] bool has_unmatched_packets() const { return has_packet; } @@ -538,22 +538,22 @@ class pcap_expectation !memcmp(buffer.data(), packet, packetSize); } - std::string location() const + [[nodiscard]] std::string location() const { return filename + ":" + std::to_string(packetsCount); } - int expected_len() const + [[nodiscard]] int expected_len() const { return header.len; } - const u_char* begin() const + [[nodiscard]] const u_char* begin() const { return buffer.data(); } - const u_char* end() const + [[nodiscard]] const u_char* end() const { return buffer.data() + header.len; } diff --git a/cli/influxdb_format.h b/cli/influxdb_format.h index 9b1a9bdc..99788e40 100644 --- a/cli/influxdb_format.h +++ b/cli/influxdb_format.h @@ -90,7 +90,7 @@ class base_t public: virtual ~base_t() = default; - const std::string& to_string() const + [[nodiscard]] const std::string& to_string() const { return string; } diff --git a/common/acl.h b/common/acl.h index fba42e72..a775ccc6 100644 --- a/common/acl.h +++ b/common/acl.h @@ -18,12 +18,12 @@ class tree_value_t return id < second.id; } - bool is_empty() const + [[nodiscard]] bool is_empty() const { return !id; } - uint32_t get_group_id() const + [[nodiscard]] uint32_t get_group_id() const { return id; } @@ -33,12 +33,12 @@ class tree_value_t id = group_id; } - bool is_chunk_id() const + [[nodiscard]] bool is_chunk_id() const { return id & 0x80000000u; } - uint32_t get_chunk_id() const + [[nodiscard]] uint32_t get_chunk_id() const { return id ^ 0x80000000u; } diff --git a/common/btree.h b/common/btree.h index fcaff50a..e11c8e76 100644 --- a/common/btree.h +++ b/common/btree.h @@ -457,7 +457,7 @@ class btree } } - std::vector get_all_top() const + [[nodiscard]] std::vector get_all_top() const { std::vector result; diff --git a/common/refarray.h b/common/refarray.h index a7b838ab..e73191be 100644 --- a/common/refarray.h +++ b/common/refarray.h @@ -185,7 +185,7 @@ class refarray_t ids.clear(); } - std::tuple stats() const + [[nodiscard]] std::tuple stats() const { return {size_T - ids_unused_size, size_T}; } diff --git a/common/rpc_controller.h b/common/rpc_controller.h index c65c5321..5b9c388c 100644 --- a/common/rpc_controller.h +++ b/common/rpc_controller.h @@ -18,16 +18,16 @@ class RpcController : public google::protobuf::RpcController _reset(); } - virtual bool Failed() const { return is_failed_; } + [[nodiscard]] virtual bool Failed() const { return is_failed_; } virtual void SetFailed(const std::string& reason) { is_failed_ = true; error_code_ = reason; } - virtual std::string ErrorText() const { return error_code_; } - virtual void StartCancel(){}; - virtual bool IsCanceled() const { return false; }; - virtual void NotifyOnCancel(::google::protobuf::Closure* /* callback */){}; + [[nodiscard]] virtual std::string ErrorText() const { return error_code_; } + virtual void StartCancel() {}; + [[nodiscard]] virtual bool IsCanceled() const { return false; }; + virtual void NotifyOnCancel(::google::protobuf::Closure* /* callback */) {}; private: bool is_failed_; diff --git a/common/sdpcommon.h b/common/sdpcommon.h index d3d7900c..059d9937 100644 --- a/common/sdpcommon.h +++ b/common/sdpcommon.h @@ -223,7 +223,7 @@ struct DataPlaneInSharedMemory return ((value + 63) / 64) * 64; } - std::tuple BuffersBus() const + [[nodiscard]] std::tuple BuffersBus() const { uint32_t count_errors = static_cast(common::idp::errorType::size); uint32_t count_requests = static_cast(common::idp::requestType::size); diff --git a/common/static_vector.h b/common/static_vector.h index b4642847..75234faa 100644 --- a/common/static_vector.h +++ b/common/static_vector.h @@ -210,7 +210,7 @@ class StaticVector return size() == 0; } - constexpr std::size_t capacity() const { return Cap; } + [[nodiscard]] constexpr std::size_t capacity() const { return Cap; } void clear() { @@ -227,8 +227,8 @@ class StaticVector } } - std::size_t size() const { return len_; } - bool Full() const { return size() == capacity(); } + [[nodiscard]] std::size_t size() const { return len_; } + [[nodiscard]] bool Full() const { return size() == capacity(); } }; } // namespace utils diff --git a/common/type.h b/common/type.h index dd7bc704..28f48d7d 100644 --- a/common/type.h +++ b/common/type.h @@ -215,12 +215,12 @@ class mac_address_t } public: - bool is_default() const + [[nodiscard]] bool is_default() const { return *this == mac_address_t(); } - std::string toString() const + [[nodiscard]] std::string toString() const { char buffer[64]; snprintf(buffer, 64, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", address[0], address[1], address[2], address[3], address[4], address[5]); @@ -232,7 +232,7 @@ class mac_address_t return address.data(); } - const uint8_t* data() const + [[nodiscard]] const uint8_t* data() const { return address.data(); } @@ -303,14 +303,14 @@ class ipv4_address_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { char buffer[64]; snprintf(buffer, 64, "%u.%u.%u.%u", (address >> 24) & 0xFF, (address >> 16) & 0xFF, (address >> 8) & 0xFF, address & 0xFF); return buffer; } - constexpr ipv4_address_t applyMask(const uint8_t& mask) const + [[nodiscard]] constexpr ipv4_address_t applyMask(const uint8_t& mask) const { if (mask == 0 || mask > 32) @@ -321,7 +321,7 @@ class ipv4_address_t return {address & (0xFFFFFFFFu << (32u - mask))}; } - constexpr std::tuple splitNetwork(const uint8_t& mask) const + [[nodiscard]] constexpr std::tuple splitNetwork(const uint8_t& mask) const { if (mask >= 32) { @@ -339,7 +339,7 @@ class ipv4_address_t address &= ~((!bit) << (31 - index)); } - uint8_t get_bit(const uint32_t& index) const + [[nodiscard]] uint8_t get_bit(const uint32_t& index) const { return (address >> (31 - index)) & 1; } @@ -438,7 +438,7 @@ class ipv6_address_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { char buffer[256]; inet_ntop(AF_INET6, address.data(), buffer, sizeof(buffer)); @@ -446,7 +446,7 @@ class ipv6_address_t return buffer; } - ipv6_address_t applyMask(const uint8_t& mask) const + [[nodiscard]] ipv6_address_t applyMask(const uint8_t& mask) const { if (mask == 0 || mask > 128) @@ -470,12 +470,12 @@ class ipv6_address_t return {address0, address64}; } - uint128_t getAddress128() const + [[nodiscard]] uint128_t getAddress128() const { return ((uint128_t)(getAddress64(0)) << 64) + ((uint128_t)(getAddress64(64))); } - uint64_t getAddress64(const uint8_t& offset) const + [[nodiscard]] uint64_t getAddress64(const uint8_t& offset) const { if (offset % 8 || offset > 128 - 64) @@ -486,7 +486,7 @@ class ipv6_address_t return be64toh(*(uint64_t*)&address[offset / 8]); } - uint32_t getAddress32(const uint8_t& offset) const + [[nodiscard]] uint32_t getAddress32(const uint8_t& offset) const { if (offset % 8 || offset > 128 - 32) @@ -497,12 +497,12 @@ class ipv6_address_t return be32toh(*(uint32_t*)&address[offset / 8]); } - ipv4_address_t get_mapped_ipv4_address() const + [[nodiscard]] ipv4_address_t get_mapped_ipv4_address() const { return ipv4_address_t(getAddress32(96)); } - constexpr const uint8_t* data() const + [[nodiscard]] constexpr const uint8_t* data() const { return address.data(); } @@ -519,7 +519,7 @@ class ipv6_address_t byte &= ~((!bit) << (7 - (index % 8))); } - uint8_t get_bit(const uint32_t& index) const + [[nodiscard]] uint8_t get_bit(const uint32_t& index) const { uint32_t address = getAddress32((index / 32) * 32); return (address >> (31 - (index % 32))) & 1; @@ -538,7 +538,7 @@ class ipv6_address_t /// Returns true if this is a multicast address (ff00::/8). /// /// This property is defined by IETF RFC 4291. - constexpr bool is_multicast() const + [[nodiscard]] constexpr bool is_multicast() const { return (address[0] & 0xff) == 0xff; } @@ -626,7 +626,7 @@ class ip_address_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { std::string string; @@ -638,12 +638,12 @@ class ip_address_t return string; } - constexpr bool is_ipv4() const + [[nodiscard]] constexpr bool is_ipv4() const { return std::holds_alternative(address); } - constexpr bool is_ipv6() const + [[nodiscard]] constexpr bool is_ipv6() const { return std::holds_alternative(address); } @@ -653,7 +653,7 @@ class ip_address_t return std::get(address); } - const ipv4_address_t& get_ipv4() const + [[nodiscard]] const ipv4_address_t& get_ipv4() const { return std::get(address); } @@ -663,12 +663,12 @@ class ip_address_t return std::get(address); } - const ipv6_address_t& get_ipv6() const + [[nodiscard]] const ipv6_address_t& get_ipv6() const { return std::get(address); } - bool is_default() const + [[nodiscard]] bool is_default() const { if (is_ipv4() && get_ipv4() == ipv4_address_t()) @@ -686,7 +686,7 @@ class ip_address_t } } - ip_address_t applyMask(const uint8_t& mask) const + [[nodiscard]] ip_address_t applyMask(const uint8_t& mask) const { if (is_ipv4()) { @@ -771,7 +771,7 @@ class ipv4_prefix_t } public: - constexpr const ipv4_address_t& address() const + [[nodiscard]] constexpr const ipv4_address_t& address() const { return std::get<0>(prefix); } @@ -781,7 +781,7 @@ class ipv4_prefix_t return std::get<0>(prefix); } - constexpr const uint8_t& mask() const + [[nodiscard]] constexpr const uint8_t& mask() const { return std::get<1>(prefix); } @@ -791,23 +791,23 @@ class ipv4_prefix_t return std::get<1>(prefix); } - std::string toString() const + [[nodiscard]] std::string toString() const { return address().toString() + "/" + std::to_string(mask()); } - constexpr bool isValid() const + [[nodiscard]] constexpr bool isValid() const { return mask() <= 32 && address().applyMask(mask()) == address(); } - constexpr ipv4_prefix_t applyMask(const uint8_t& mask) const + [[nodiscard]] constexpr ipv4_prefix_t applyMask(const uint8_t& mask) const { return {address().applyMask(mask), mask}; } - constexpr std::tuple splitNetwork() const + [[nodiscard]] constexpr std::tuple splitNetwork() const { if (mask() >= 32) { @@ -829,7 +829,7 @@ class ipv4_prefix_t stream.push(prefix); } - bool subnetOf(const ipv4_prefix_t& other) const + [[nodiscard]] bool subnetOf(const ipv4_prefix_t& other) const { if (mask() < other.mask()) { @@ -839,7 +839,7 @@ class ipv4_prefix_t return address().applyMask(other.mask()) == other.address(); } - bool subnetFor(const ipv4_address_t& other) const + [[nodiscard]] bool subnetFor(const ipv4_address_t& other) const { return other.applyMask(mask()) == address().applyMask(mask()); } @@ -984,7 +984,7 @@ class ipv6_prefix_t } public: - constexpr const ipv6_address_t& address() const + [[nodiscard]] constexpr const ipv6_address_t& address() const { return std::get<0>(prefix); } @@ -994,7 +994,7 @@ class ipv6_prefix_t return std::get<0>(prefix); } - constexpr const uint8_t& mask() const + [[nodiscard]] constexpr const uint8_t& mask() const { return std::get<1>(prefix); } @@ -1004,12 +1004,12 @@ class ipv6_prefix_t return std::get<1>(prefix); } - std::string toString() const + [[nodiscard]] std::string toString() const { return address().toString() + "/" + std::to_string(mask()); } - bool isValid() const + [[nodiscard]] bool isValid() const { if (mask() > 128) { @@ -1029,22 +1029,22 @@ class ipv6_prefix_t return true; } - ipv6_prefix_t applyMask(const uint8_t& mask) const + [[nodiscard]] ipv6_prefix_t applyMask(const uint8_t& mask) const { return {address().applyMask(mask), mask}; } - uint64_t getAddress64(const uint8_t& offset) const + [[nodiscard]] uint64_t getAddress64(const uint8_t& offset) const { return address().getAddress64(offset) & getAddressMask64(offset); } - uint32_t getAddress32(const uint8_t& offset) const + [[nodiscard]] uint32_t getAddress32(const uint8_t& offset) const { return address().getAddress32(offset) & getAddressMask32(offset); } - uint64_t getAddressMask64(const uint8_t& offset) const + [[nodiscard]] uint64_t getAddressMask64(const uint8_t& offset) const { if (offset > 128 - 64) { @@ -1064,7 +1064,7 @@ class ipv6_prefix_t return 0xFFFFFFFFFFFFFFFFull << (64ull + offset - mask()); } - uint32_t getAddressMask32(const uint8_t& offset) const + [[nodiscard]] uint32_t getAddressMask32(const uint8_t& offset) const { if (offset > 128 - 32) { @@ -1094,12 +1094,12 @@ class ipv6_prefix_t stream.push(prefix); } - bool subnetFor(const ipv6_address_t& other) const + [[nodiscard]] bool subnetFor(const ipv6_address_t& other) const { return other.applyMask(mask()) == address().applyMask(mask()); } - bool subnetOf(const ipv6_prefix_t& other) const + [[nodiscard]] bool subnetOf(const ipv6_prefix_t& other) const { if (mask() < other.mask()) { @@ -1263,7 +1263,7 @@ class ip_prefix_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { std::string string; @@ -1275,12 +1275,12 @@ class ip_prefix_t return string; } - bool is_ipv4() const + [[nodiscard]] bool is_ipv4() const { return std::holds_alternative(prefix); } - bool is_ipv6() const + [[nodiscard]] bool is_ipv6() const { return std::holds_alternative(prefix); } @@ -1290,7 +1290,7 @@ class ip_prefix_t return std::get(prefix); } - const ipv4_prefix_t& get_ipv4() const + [[nodiscard]] const ipv4_prefix_t& get_ipv4() const { return std::get(prefix); } @@ -1300,7 +1300,7 @@ class ip_prefix_t return std::get(prefix); } - const ipv6_prefix_t& get_ipv6() const + [[nodiscard]] const ipv6_prefix_t& get_ipv6() const { return std::get(prefix); } @@ -1317,7 +1317,7 @@ class ip_prefix_t } } - const uint8_t& mask() const + [[nodiscard]] const uint8_t& mask() const { if (is_ipv4()) { @@ -1329,7 +1329,7 @@ class ip_prefix_t } } - bool is_default() const + [[nodiscard]] bool is_default() const { if (is_ipv4() && get_ipv4() == ipv4_prefix_t()) @@ -1347,7 +1347,7 @@ class ip_prefix_t } } - bool is_host() const + [[nodiscard]] bool is_host() const { if (is_ipv4()) { @@ -1359,7 +1359,7 @@ class ip_prefix_t } } - ip_prefix_t get_default() const + [[nodiscard]] ip_prefix_t get_default() const { if (is_ipv4()) { @@ -1371,7 +1371,7 @@ class ip_prefix_t } } - ip_address_t address() const + [[nodiscard]] ip_address_t address() const { if (is_ipv4()) { @@ -1383,7 +1383,7 @@ class ip_prefix_t } } - ip_prefix_t applyMask(const uint8_t& mask) const + [[nodiscard]] ip_prefix_t applyMask(const uint8_t& mask) const { if (is_ipv4()) { @@ -1395,7 +1395,7 @@ class ip_prefix_t } } - bool subnetFor(const ip_address_t& other) const + [[nodiscard]] bool subnetFor(const ip_address_t& other) const { if (is_ipv4() && other.is_ipv4()) { @@ -1480,7 +1480,7 @@ class ip_prefix_with_announces_t } public: - ip_prefix_t get_prefix() const + [[nodiscard]] ip_prefix_t get_prefix() const { if (std::holds_alternative(prefix)) { @@ -1564,7 +1564,7 @@ class community_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { return std::to_string(value >> 16) + ":" + std::to_string(value & 0xFFFF); } @@ -1649,7 +1649,7 @@ class large_community_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { return std::to_string(value[0]) + ":" + std::to_string(value[1]) + ":" + std::to_string(value[2]); } @@ -1689,12 +1689,12 @@ class values_t return values; } - auto begin() const + [[nodiscard]] auto begin() const { return values.begin(); } - auto end() const + [[nodiscard]] auto end() const { return values.end(); } @@ -1777,7 +1777,7 @@ class range_t } public: - std::string toString() const + [[nodiscard]] std::string toString() const { return std::to_string(from()) + (from() == to() ? "" : "-" + std::to_string(to())); } @@ -1787,7 +1787,7 @@ class range_t return std::get<0>(range); } - const uint64_t& from() const + [[nodiscard]] const uint64_t& from() const { return std::get<0>(range); } @@ -1797,7 +1797,7 @@ class range_t return std::get<1>(range); } - const uint64_t& to() const + [[nodiscard]] const uint64_t& to() const { return std::get<1>(range); } @@ -1883,17 +1883,17 @@ class ranges_t ///< @todo: rename filter_t return ranges < second.ranges; } - auto begin() const + [[nodiscard]] auto begin() const { return ranges.begin(); } - auto end() const + [[nodiscard]] auto end() const { return ranges.end(); } - bool empty() const + [[nodiscard]] bool empty() const { return ranges.empty(); } @@ -1945,7 +1945,7 @@ class ranges_t ///< @todo: rename filter_t ranges = newRanges; } - bool isIntersect(const ranges_t& second) const + [[nodiscard]] bool isIntersect(const ranges_t& second) const { for (const auto& range : ranges) { diff --git a/controlplane/acl/bitset.h b/controlplane/acl/bitset.h index a0e9c042..2d9c6232 100644 --- a/controlplane/acl/bitset.h +++ b/controlplane/acl/bitset.h @@ -30,7 +30,7 @@ struct bitset_t return (vals[i / 64] & ((uint64_t)(1) << (i % 64))) != 0; } - bool empty() const + [[nodiscard]] bool empty() const { return first_one == size; } @@ -41,7 +41,7 @@ struct bitset_t printf("%s", to_string().c_str()); } - std::string to_string() const + [[nodiscard]] std::string to_string() const { std::string out; for (size_t i = 0; i < size; ++i) @@ -120,7 +120,7 @@ struct bitset_t return !(p1 == p2); } - std::tuple minAnd(const bitset_t& p) const + [[nodiscard]] std::tuple minAnd(const bitset_t& p) const { for (size_t i = std::max(first_one, p.first_one); i < size; ++i) { @@ -134,7 +134,7 @@ struct bitset_t return {0, false}; } - std::tuple minAnd(const bitset_t& p1, + [[nodiscard]] std::tuple minAnd(const bitset_t& p1, const bitset_t& p2) const { for (size_t i = std::max(std::max(first_one, p1.first_one), p2.first_one); i < size; ++i) @@ -149,7 +149,7 @@ struct bitset_t return {0, false}; } - bool emptyAnd(const bitset_t& p1) const + [[nodiscard]] bool emptyAnd(const bitset_t& p1) const { for (size_t i = std::max(first_one, p1.first_one); i < size; ++i) { @@ -163,7 +163,7 @@ struct bitset_t } private: - size_t start(const bitset_t& p1) const + [[nodiscard]] size_t start(const bitset_t& p1) const { return std::min(first_one, p1.first_one); } diff --git a/controlplane/acl/network.h b/controlplane/acl/network.h index d6a3aa7a..c5f87d98 100644 --- a/controlplane/acl/network.h +++ b/controlplane/acl/network.h @@ -157,7 +157,7 @@ struct network_t { } - std::string to_string() const + [[nodiscard]] std::string to_string() const { std::stringstream ret; if (family == 4) @@ -190,7 +190,7 @@ struct network_t return std::tie(family, mask, addr) < std::tie(second.family, second.mask, second.addr); } - network_t normalize() const + [[nodiscard]] network_t normalize() const { return {family, addr & mask, mask}; } diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 66c88029..7b5482fe 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -27,12 +27,12 @@ struct range_t : std::tuple inline range_t(unsigned int val) : std::tuple(val, val) {} - uint_t from() const + [[nodiscard]] uint_t from() const { return std::get<0>(*this); } - uint_t to() const + [[nodiscard]] uint_t to() const { return std::get<1>(*this); } @@ -43,9 +43,9 @@ struct filter_base_t unsigned long ref_count{}; inline constexpr filter_base_t() = default; - virtual bool is_none() const = 0; + [[nodiscard]] virtual bool is_none() const = 0; virtual ~filter_base_t() = default; - virtual std::string to_string() const = 0; + [[nodiscard]] virtual std::string to_string() const = 0; }; template @@ -145,7 +145,7 @@ struct ref_t return filter != nullptr; } - inline bool is_none() const + [[nodiscard]] inline bool is_none() const { return filter ? filter->is_none() : false; } @@ -199,12 +199,12 @@ struct filter_network_t : filter_base_t networks.emplace_back(std::move(string)); } - virtual bool is_none() const + [[nodiscard]] bool is_none() const { return networks.empty(); } - virtual std::string to_string() const + [[nodiscard]] virtual std::string to_string() const { if (networks.empty()) { @@ -335,12 +335,12 @@ struct filter_prm_t : filter_base_t } } - virtual bool is_none() const + [[nodiscard]] bool is_none() const { return ranges.empty(); } - virtual std::string to_string() const + [[nodiscard]] virtual std::string to_string() const { std::string ret; @@ -593,12 +593,12 @@ struct filter_id_t : filter_base_t inline filter_id_t(int _val) : val(_val) {} - virtual bool is_none() const + [[nodiscard]] virtual bool is_none() const { return val < 0; } - virtual std::string to_string() const + [[nodiscard]] virtual std::string to_string() const { return std::to_string(val); } @@ -742,12 +742,12 @@ struct filter_proto_t : filter_base_t } } - virtual bool is_none() const + [[nodiscard]] virtual bool is_none() const { return type.is_none() || prm1.is_none() || prm2.is_none(); } - virtual std::string to_string() const + [[nodiscard]] virtual std::string to_string() const { bool has_ports = false, has_icmptypes = false, has_icmp6types = false, has_flags = false; @@ -924,12 +924,12 @@ struct filter_t : filter_base_t } } - virtual bool is_none() const + [[nodiscard]] virtual bool is_none() const { return acl_id.is_none() || src.is_none() || dst.is_none() || proto.is_none() || dir.is_none() || recordstate.is_none(); } - virtual std::string to_string() const + [[nodiscard]] virtual std::string to_string() const { std::string ret; diff --git a/controlplane/acl_filter.h b/controlplane/acl_filter.h index 5352ac1b..07a34d33 100644 --- a/controlplane/acl_filter.h +++ b/controlplane/acl_filter.h @@ -34,7 +34,7 @@ class filter_transport second.icmpv6_identifier); } - inline bool protocol_contain(const uint8_t protocol_value) const + [[nodiscard]] inline bool protocol_contain(const uint8_t protocol_value) const { for (const auto& range : protocol.vector) { diff --git a/controlplane/base.h b/controlplane/base.h index e358c65b..96702b3b 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -41,7 +41,7 @@ class decap_t public: decap_t() = default; - std::set prefixes() const + [[nodiscard]] std::set prefixes() const { std::set prefixes; for (const auto& prefix : ipv6DestinationPrefixes) diff --git a/controlplane/configconverter.h b/controlplane/configconverter.h index 7be12d6a..443e3296 100644 --- a/controlplane/configconverter.h +++ b/controlplane/configconverter.h @@ -18,7 +18,7 @@ class config_converter_t [[nodiscard]] eResult process(uint32_t serial); - const controlplane::base_t& getBaseNext() const + [[nodiscard]] const controlplane::base_t& getBaseNext() const { return baseNext; } @@ -47,8 +47,8 @@ class config_converter_t std::string checkLimit(size_t count, const std::string& limit, size_t multiplier(size_t)); void convertToFlow(const std::string& nextModule, common::globalBase::tFlow& flow) const; - common::globalBase::tFlow convertToFlow(std::string nextModule) const; - common::globalBase::tFlow convertToFlow(std::string nextModule, const std::string& entryName) const; + [[nodiscard]] common::globalBase::tFlow convertToFlow(std::string nextModule) const; + [[nodiscard]] common::globalBase::tFlow convertToFlow(std::string nextModule, const std::string& entryName) const; void acl_rules_route_local(controlplane::base::acl_t& acl, const std::string& next_module) const; void acl_rules_route_forward(controlplane::base::acl_t& acl, const std::string& next_module) const; diff --git a/controlplane/configparser.h b/controlplane/configparser.h index a3c9b7d9..a24d4ebc 100644 --- a/controlplane/configparser.h +++ b/controlplane/configparser.h @@ -17,7 +17,7 @@ class config_parser_t controlplane::base_t loadConfig(const std::string& rootFilePath, const nlohmann::json& rootJson, const std::map& jsons = {}); protected: - tPortId getPhysicalPortId(const std::string& name) const; + [[nodiscard]] tPortId getPhysicalPortId(const std::string& name) const; void loadConfig_logicalPort(controlplane::base_t& baseNext, const std::string& moduleId, const nlohmann::json& moduleJson); void loadConfig_route(controlplane::base_t& baseNext, const std::string& moduleId, const nlohmann::json& moduleJson, const std::string& rootFilePath, const std::map& jsons); void loadConfig_route_peers(controlplane::base_t& baseNext, controlplane::route::config_t& route, const nlohmann::json& json, const std::string& rootFilePath, const std::map& jsons); diff --git a/controlplane/dregress.h b/controlplane/dregress.h index 55782c34..846b6352 100644 --- a/controlplane/dregress.h +++ b/controlplane/dregress.h @@ -45,7 +45,7 @@ class generation_t } } - std::optional get_peer_link_community(const std::set& communities) const + [[nodiscard]] std::optional get_peer_link_community(const std::set& communities) const { /// @todo: VRF for (const auto& [moduleName, dregress] : dregresses) diff --git a/controlplane/errors.h b/controlplane/errors.h index 2f0c64dd..468a3d3c 100644 --- a/controlplane/errors.h +++ b/controlplane/errors.h @@ -12,7 +12,7 @@ class error_result_t : public std::runtime_error std::runtime_error(error), code(result) {} - eResult result() const + [[nodiscard]] eResult result() const { return code; } diff --git a/controlplane/route.h b/controlplane/route.h index dca9f385..f75d7a3e 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -141,7 +141,7 @@ class generation_t socket_interfaces = base_next.socket_interfaces; } - std::optional*> get_interface_by_neighbor(const ip_address_t& address) const + [[nodiscard]] std::optional*> get_interface_by_neighbor(const ip_address_t& address) const { for (const auto& [prefix, interface] : interface_by_neighbors) { @@ -154,7 +154,7 @@ class generation_t return std::nullopt; } - std::optional get_vrf(const std::string& route_name) const + [[nodiscard]] std::optional get_vrf(const std::string& route_name) const { auto it = routes.find(route_name); if (it == routes.end()) @@ -165,7 +165,7 @@ class generation_t return &it->second.vrf; ///< read only after update } - const std::map* get_peers() const + [[nodiscard]] const std::map* get_peers() const { return &peers; } @@ -188,7 +188,7 @@ class generation_t class generation_neighbors_t { public: - std::optional get_mac_address(const std::string& route_name, const std::string& interface_name, const common::ip_address_t& neighbor) const + [[nodiscard]] std::optional get_mac_address(const std::string& route_name, const std::string& interface_name, const common::ip_address_t& neighbor) const { auto it = mac_addresses.find({route_name, interface_name, neighbor}); if (it == mac_addresses.end()) diff --git a/controlplane/segment_allocator.h b/controlplane/segment_allocator.h index 240fe11a..3ab06bad 100644 --- a/controlplane/segment_allocator.h +++ b/controlplane/segment_allocator.h @@ -149,7 +149,7 @@ class SegmentAllocator return true; } - uint32_t Size() const + [[nodiscard]] uint32_t Size() const { return free_cells_; } @@ -159,7 +159,7 @@ class SegmentAllocator return sizes_info_; } - std::pair GetErrors() const + [[nodiscard]] std::pair GetErrors() const { return {errors_external_, errors_internal_}; } diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index 99561cdc..8432b7de 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -41,12 +41,12 @@ class generation_t peers[0] = "unknown"; } - const std::map* get_communities() const + [[nodiscard]] const std::map* get_communities() const { return &communities; } - const std::map* get_peers() const + [[nodiscard]] const std::map* get_peers() const { return &peers; } diff --git a/dataplane/base.h b/dataplane/base.h index 6fbb4d0d..0fc9934b 100644 --- a/dataplane/base.h +++ b/dataplane/base.h @@ -47,7 +47,7 @@ class PortMapper return *this; } - uint16_t size() const { return ports_count_; } + [[nodiscard]] uint16_t size() const { return ports_count_; } [[nodiscard]] std::optional Register(tPortId dpdk_port) { @@ -72,10 +72,10 @@ class PortMapper } } - tPortId ToDpdk(tPortId logical) const { return dpdk_ports_[logical]; } - tPortId ToLogical(tPortId dpdk) const { return logical_ports_[dpdk]; } - bool ValidDpdk(tPortId dpdk) const { return logical_ports_[dpdk] != INVALID_PORT_ID; } - bool ValidLogical(tPortId logical) const { return logical < INVALID_PORT_ID; } + [[nodiscard]] tPortId ToDpdk(tPortId logical) const { return dpdk_ports_[logical]; } + [[nodiscard]] tPortId ToLogical(tPortId dpdk) const { return logical_ports_[dpdk]; } + [[nodiscard]] bool ValidDpdk(tPortId dpdk) const { return logical_ports_[dpdk] != INVALID_PORT_ID; } + [[nodiscard]] bool ValidLogical(tPortId logical) const { return logical < INVALID_PORT_ID; } }; class permanently diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 17bc2cfe..0949ee27 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -51,7 +51,7 @@ class cControlPlane ///< @todo: move to cDataPlane eResult updateGlobalBaseBalancer(const common::idp::updateGlobalBaseBalancer::request& request); common::idp::getGlobalBase::response getGlobalBase(const common::idp::getGlobalBase::request& request); common::idp::getWorkerStats::response getWorkerStats(const common::idp::getWorkerStats::request& request); - common::slowworker::stats_t SlowWorkerStats() const; + [[nodiscard]] common::slowworker::stats_t SlowWorkerStats() const; common::idp::getSlowWorkerStats::response SlowWorkerStatsResponse(); common::idp::get_worker_gc_stats::response get_worker_gc_stats(); common::idp::get_dregress_counters::response get_dregress_counters(); @@ -59,15 +59,15 @@ class cControlPlane ///< @todo: move to cDataPlane common::idp::get_ports_stats_extended::response get_ports_stats_extended(); common::idp::getControlPlanePortStats::response getControlPlanePortStats(const common::idp::getControlPlanePortStats::request& request); common::idp::getPortStatsEx::response getPortStatsEx(); - common::idp::getFragmentationStats::response getFragmentationStats() const; - common::dregress::stats_t DregressStats() const; - std::optional> KniStats(tPortId) const; - dataplane::hashtable_chain_spinlock_stats_t DregressConnectionsStats() const; - dregress::LimitsStats DregressLimitsStats() const; + [[nodiscard]] common::idp::getFragmentationStats::response getFragmentationStats() const; + [[nodiscard]] common::dregress::stats_t DregressStats() const; + [[nodiscard]] std::optional> KniStats(tPortId) const; + [[nodiscard]] dataplane::hashtable_chain_spinlock_stats_t DregressConnectionsStats() const; + [[nodiscard]] dregress::LimitsStats DregressLimitsStats() const; common::idp::getFWState::response getFWState(); common::idp::getFWStateStats::response getFWStateStats(); eResult clearFWState(); - common::idp::getConfig::response getConfig() const; + [[nodiscard]] common::idp::getConfig::response getConfig() const; common::idp::getErrors::response getErrors(); common::idp::getReport::response getReport(); common::idp::lpm4LookupAddress::response lpm4LookupAddress(const common::idp::lpm4LookupAddress::request& request); @@ -92,8 +92,8 @@ class cControlPlane ///< @todo: move to cDataPlane virtual void waitAllWorkers(); private: - const std::vector& workers_vector() const; - const std::map& slow_workers() const; + [[nodiscard]] const std::vector& workers_vector() const; + [[nodiscard]] const std::map& slow_workers() const; template // @brief returns sum of results of applying F to all cWorker*s diff --git a/dataplane/fragmentation.h b/dataplane/fragmentation.h index e25070e2..a6931f07 100644 --- a/dataplane/fragmentation.h +++ b/dataplane/fragmentation.h @@ -50,7 +50,7 @@ class Fragmentation Fragmentation& operator=(Fragmentation&& other) = default; public: - common::fragmentation::stats_t getStats() const; + [[nodiscard]] common::fragmentation::stats_t getStats() const; OnCollected& Callback() { return callback_; } void Configure(const FragmentationConfig& cfg) { config_ = cfg; } @@ -58,9 +58,9 @@ class Fragmentation void handle(); protected: - bool isTimeout(const value_t& value) const; - bool isCollected(const value_t& value) const; - bool isIntersect(const value_t& value, const uint32_t& range_from, const uint32_t& range_to) const; + [[nodiscard]] bool isTimeout(const value_t& value) const; + [[nodiscard]] bool isCollected(const value_t& value) const; + [[nodiscard]] bool isIntersect(const value_t& value, const uint32_t& range_from, const uint32_t& range_to) const; protected: OnCollected callback_; @@ -72,4 +72,4 @@ class Fragmentation std::map fragments_; }; -} // namespace fragmentation \ No newline at end of file +} // namespace fragmentation diff --git a/dataplane/hashtable.h b/dataplane/hashtable.h index 01b801fb..a41de272 100644 --- a/dataplane/hashtable.h +++ b/dataplane/hashtable.h @@ -409,7 +409,7 @@ class hashtable_chain_t } public: - uint32_t getNextExtendedChunkId() const + [[nodiscard]] uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -419,7 +419,7 @@ class hashtable_chain_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - bool isValid(const unsigned int& key_i) const + [[nodiscard]] bool isValid(const unsigned int& key_i) const { return keyValids & (1 << key_i); } @@ -485,7 +485,7 @@ class hashtable_chain_t } public: - uint32_t getNextExtendedChunkId() const + [[nodiscard]] uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -495,7 +495,7 @@ class hashtable_chain_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - bool isValid(const unsigned int& key_i) const + [[nodiscard]] bool isValid(const unsigned int& key_i) const { return keyValids & (1 << key_i); } @@ -1236,7 +1236,7 @@ class hashtable_chain_spinlock_t } public: - uint32_t getNextExtendedChunkId() const + [[nodiscard]] uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -1246,7 +1246,7 @@ class hashtable_chain_spinlock_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - bool isValid(const unsigned int& key_i) const + [[nodiscard]] bool isValid(const unsigned int& key_i) const { return keyValids & (1u << key_i); } @@ -1317,7 +1317,7 @@ class hashtable_chain_spinlock_t } public: - uint32_t getNextExtendedChunkId() const + [[nodiscard]] uint32_t getNextExtendedChunkId() const { return nextExtendedChunkId & 0x00FFFFFFu; } @@ -1327,7 +1327,7 @@ class hashtable_chain_spinlock_t nextExtendedChunkId = (nextExtendedChunkId & 0xFF000000u) | (extendedChunkId & 0x00FFFFFFu); } - bool isValid(const unsigned int& key_i) const + [[nodiscard]] bool isValid(const unsigned int& key_i) const { return keyValids & (1u << key_i); } @@ -1437,7 +1437,7 @@ class hashtable_chain_spinlock_t hashtable_chain_spinlock_stats_t stats_; public: - const hashtable_chain_spinlock_stats_t& stats() const + [[nodiscard]] const hashtable_chain_spinlock_stats_t& stats() const { return stats_; } @@ -1745,7 +1745,7 @@ class hashtable_mod_id32 } pairs[total_size]; protected: - bool is_valid(const uint32_t index) const + [[nodiscard]] bool is_valid(const uint32_t index) const { return (pairs[index].value >> shift_valid) & 1; } @@ -1982,7 +1982,7 @@ class hashtable_mod_id32_dynamic } protected: - bool is_valid(const uint32_t index) const + [[nodiscard]] bool is_valid(const uint32_t index) const { return (pairs[index].value >> shift_valid) & 1; } diff --git a/dataplane/kernel_interface_handle.h b/dataplane/kernel_interface_handle.h index 94569104..bad5ef26 100644 --- a/dataplane/kernel_interface_handle.h +++ b/dataplane/kernel_interface_handle.h @@ -27,8 +27,8 @@ class KernelInterfaceHandle tPortId port, tQueueId queue_count, uint16_t queue_size) noexcept; - const tPortId& Id() const noexcept { return kni_port_; } - bool Start() const noexcept; + [[nodiscard]] const tPortId& Id() const noexcept { return kni_port_; } + [[nodiscard]] bool Start() const noexcept; [[nodiscard]] bool SetUp() const noexcept; bool SetupRxQueue(tQueueId queue, tSocketId socket, rte_mempool* mempool) noexcept; bool SetupTxQueue(tQueueId queue, tSocketId socket) noexcept; @@ -45,4 +45,4 @@ class KernelInterfaceHandle [[nodiscard]] bool Valid() const { return kni_port_ != INVALID_PORT_ID; } }; -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/kernel_interface_handler.h b/dataplane/kernel_interface_handler.h index c3b43728..72f81766 100644 --- a/dataplane/kernel_interface_handler.h +++ b/dataplane/kernel_interface_handler.h @@ -40,8 +40,8 @@ class KernelInterface DirectionStats FlushTracked(); void Push(rte_mbuf* mbuf); DirectionStats PushTracked(rte_mbuf* mbuf); - const tPortId& port() const; - const tQueueId& queue() const; + [[nodiscard]] const tPortId& port() const; + [[nodiscard]] const tQueueId& queue() const; }; struct KernelInterfaceBundleConfig @@ -84,9 +84,9 @@ class KernelInterfaceWorker KernelInterfaceWorker(std::vector& config); KernelInterfaceWorker(KernelInterfaceWorker&& other); KernelInterfaceWorker& operator=(KernelInterfaceWorker&& other); - ConstPortArrayRange PortsIds() const; - ConstPortArrayRange PortsStats() const; - std::optional> PortStats(tPortId pid) const; + [[nodiscard]] ConstPortArrayRange PortsIds() const; + [[nodiscard]] ConstPortArrayRange PortsStats() const; + [[nodiscard]] std::optional> PortStats(tPortId pid) const; /// @brief Transmit accumulated packets. Those that could not be sent are freed void Flush(); @@ -97,4 +97,4 @@ class KernelInterfaceWorker void HandlePacketDump(rte_mbuf* mbuf); void HandlePacketFromForwardingPlane(rte_mbuf* mbuf); }; -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/lpm.h b/dataplane/lpm.h index d4d959b8..2aa36418 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -1499,12 +1499,12 @@ class lpm4_24bit_8bit_id32 return remap_chunks[from_chunk_id]; } - unsigned int get_extended_chunks_count() const + [[nodiscard]] unsigned int get_extended_chunks_count() const { return extended_chunks_count; } - unsigned int get_extended_chunks_size() const + [[nodiscard]] unsigned int get_extended_chunks_size() const { return extended_chunks_size; } diff --git a/dataplane/samples.h b/dataplane/samples.h index f9cf132b..cec8155a 100644 --- a/dataplane/samples.h +++ b/dataplane/samples.h @@ -160,7 +160,7 @@ class Sampler free4 = samples4 + sample4_size - 1; } - uint64_t get_drops() const + [[nodiscard]] uint64_t get_drops() const { return drops; } @@ -209,7 +209,7 @@ class Sampler return (tcpHeader->tcp_flags & (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG | RTE_TCP_FIN_FLAG | RTE_TCP_RST_FLAG)) == RTE_TCP_SYN_FLAG; } - bool is_full() const + [[nodiscard]] bool is_full() const { return (void*)(free6 + 1) > (void*)free4; } diff --git a/dataplane/type.h b/dataplane/type.h index 25e25bd5..07ee110c 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -191,7 +191,7 @@ struct ipv6_address_t return !(*this == second); } - bool empty() const ///< @todo: is_default() + [[nodiscard]] bool empty() const ///< @todo: is_default() { for (auto b : bytes) { @@ -644,7 +644,7 @@ struct fw_tcp_state_value_t uint8_t src_flags : 4; uint8_t dst_flags : 4; - uint8_t pack() const + [[nodiscard]] uint8_t pack() const { return src_flags | (dst_flags << 4); } diff --git a/dataplane/updater.h b/dataplane/updater.h index 06088de0..ca839215 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -181,22 +181,22 @@ class updater_lpm return eResult::success; } - bool NeedToGrow() const + [[nodiscard]] bool NeedToGrow() const { return stats_.extended_chunks_size - stats_.extended_chunks_count < ObjectType::extended_chunks_size_min; } - std::size_t GrowSize() const + [[nodiscard]] std::size_t GrowSize() const { return stats_.extended_chunks_size * 2; } - std::size_t ShrinkSize() const + [[nodiscard]] std::size_t ShrinkSize() const { return stats_.extended_chunks_size / 2; } - bool NeedToShrink() const + [[nodiscard]] bool NeedToShrink() const { return ShrinkSize() > std::max(ObjectType::extended_chunks_size_min, GrowSize()); } diff --git a/dataplane/worker.h b/dataplane/worker.h index 93b92742..546b06ff 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -72,7 +72,7 @@ class cWorker static void FillMetadataWorkerCounters(common::sdp::MetadataWorker& metadata); void SetBufferForCounters(void* buffer, const common::sdp::MetadataWorker& metadata); - const dataplane::base::generation& current_base() const { return bases[localBaseId & 1]; } + [[nodiscard]] const dataplane::base::generation& current_base() const { return bases[localBaseId & 1]; } protected: eResult sanityCheck(); @@ -235,7 +235,7 @@ class cWorker YANET_NEVER_INLINE void slowWorkerTranslation(rte_mbuf* mbuf, const dataplane::globalBase::tNat64stateless& nat64stateless, const dataplane::globalBase::nat64stateless_translation_t& translation, bool direction); /** true: ingress, false: egress */ const dataplane::base::generation& CurrentBase() { return bases[localBaseId & 1]; } void IncrementCounter(common::globalBase::static_counter_type type) { counters[(uint32_t)type]++; } - uint32_t CurrentTime() const { return basePermanently.globalBaseAtomic->currentTime; } + [[nodiscard]] uint32_t CurrentTime() const { return basePermanently.globalBaseAtomic->currentTime; } friend class cDataPlane; friend class cReport; diff --git a/libfwparser/fw_config.h b/libfwparser/fw_config.h index 6f6b002f..66ae9372 100644 --- a/libfwparser/fw_config.h +++ b/libfwparser/fw_config.h @@ -431,11 +431,11 @@ class fw_config_t void set_fqdn(const std::string&); void fill_fqdn(const common::ip_address_t&); - const auto& resolve_fqdn(const std::string& s) const + [[nodiscard]] const auto& resolve_fqdn(const std::string& s) const { return std::get<1>(m_dns_cache.at(s)); } - const auto& resolve_macro(const std::string& s) const + [[nodiscard]] const auto& resolve_macro(const std::string& s) const { return std::get<1>(m_macros.at(s)); } @@ -518,7 +518,7 @@ class fw_config_t void add_implicit_check_state_rule(); std::string format_location(const location_history_t& loc); - const auto& labels() const + [[nodiscard]] const auto& labels() const { return m_labels; } From 31b725cef2af1ffc8c0b9037a661f3d932a7d90f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:24:15 +0400 Subject: [PATCH 142/195] Use auto when initializing with a cast to avoid duplicating the type name --- autotest/autotest.cpp | 2 +- cli/influxdb_format.h | 2 +- common/sdpcommon.h | 4 ++-- common/type.h | 2 +- common/unittest/shared_memory.cpp | 4 ++-- controlplane/acl/dict.h | 2 +- controlplane/acl_transport.cpp | 2 +- dataplane/bus.cpp | 4 ++-- dataplane/icmp_translations.cpp | 20 ++++++++++---------- dataplane/neighbor.cpp | 4 ++-- dataplane/sharedmemory.cpp | 2 +- dataplane/sock_dev.cpp | 12 ++++++------ dataplane/unittest/sdp.cpp | 8 ++++---- dataplane/worker_gc.cpp | 2 +- 14 files changed, 35 insertions(+), 35 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 97096132..0c040a6c 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -1913,7 +1913,7 @@ common::bufferring::item_t* read_shm_packet(common::bufferring* buffer, uint64_t { return nullptr; } - common::bufferring::item_t* item = (common::bufferring::item_t*)((uintptr_t)buffer->ring->memory + (position * buffer->unit_size)); + auto* item = (common::bufferring::item_t*)((uintptr_t)buffer->ring->memory + (position * buffer->unit_size)); return item; } diff --git a/cli/influxdb_format.h b/cli/influxdb_format.h index 99788e40..544fec6b 100644 --- a/cli/influxdb_format.h +++ b/cli/influxdb_format.h @@ -181,7 +181,7 @@ void print_histogram(const char* name, const index_T start, const index_T end) { - for (unsigned int i = (unsigned int)start; + for (auto i = (unsigned int)start; i <= (unsigned int)end; i++) { diff --git a/common/sdpcommon.h b/common/sdpcommon.h index 059d9937..33e6cd29 100644 --- a/common/sdpcommon.h +++ b/common/sdpcommon.h @@ -225,8 +225,8 @@ struct DataPlaneInSharedMemory [[nodiscard]] std::tuple BuffersBus() const { - uint32_t count_errors = static_cast(common::idp::errorType::size); - uint32_t count_requests = static_cast(common::idp::requestType::size); + auto count_errors = static_cast(common::idp::errorType::size); + auto count_requests = static_cast(common::idp::requestType::size); uint64_t* requests = common::sdp::ShiftBuffer(dataplane_data, start_bus_section); uint64_t* errors = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + count_requests * sizeof(uint64_t)); uint64_t* durations = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + (count_requests + count_errors) * sizeof(uint64_t)); diff --git a/common/type.h b/common/type.h index 28f48d7d..a6b0b353 100644 --- a/common/type.h +++ b/common/type.h @@ -2634,7 +2634,7 @@ struct hash { std::size_t operator()(const common::ipv4_address_t& ip_addr) const { - const uint32_t ipv4 = static_cast(ip_addr); + const auto ipv4 = static_cast(ip_addr); return std::hash()(ipv4); } }; diff --git a/common/unittest/shared_memory.cpp b/common/unittest/shared_memory.cpp index 67e7c971..ce46728a 100644 --- a/common/unittest/shared_memory.cpp +++ b/common/unittest/shared_memory.cpp @@ -8,8 +8,8 @@ void TestForSize(void* buffer_writer, void* buffer_reader, size_t size, size_t s ASSERT_TRUE(buffer_reader != nullptr); ASSERT_EQ(size, size_reader); - uint8_t* buffer_writer8 = reinterpret_cast(buffer_writer); - uint8_t* buffer_reader8 = reinterpret_cast(buffer_reader); + auto* buffer_writer8 = reinterpret_cast(buffer_writer); + auto* buffer_reader8 = reinterpret_cast(buffer_reader); for (uint64_t index = 0; index < size; index++) { diff --git a/controlplane/acl/dict.h b/controlplane/acl/dict.h index e340ec1a..8e1da171 100644 --- a/controlplane/acl/dict.h +++ b/controlplane/acl/dict.h @@ -44,7 +44,7 @@ bool is_mask_simple(uint128_t mask) bool end_found = false; for (unsigned int i = 1; i <= 16; ++i) { - const uint8_t byte = uint8_t((mask >> (128 - i * 8)) & 0xff); + const auto byte = uint8_t((mask >> (128 - i * 8)) & 0xff); if (end_found) { if (byte > 0) diff --git a/controlplane/acl_transport.cpp b/controlplane/acl_transport.cpp index 82bf04e4..8eec12ed 100644 --- a/controlplane/acl_transport.cpp +++ b/controlplane/acl_transport.cpp @@ -67,7 +67,7 @@ void transport_t::distribute() (void)size; unsigned int best_layer_id = 0; - size_t best_filter_ids_count = (size_t)-1; + auto best_filter_ids_count = (size_t)-1; for (unsigned int layer_id = 0; layer_id < compiler->transport_layers_size_max; diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 57e70177..022ea4a0 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -57,8 +57,8 @@ void cBus::join() uint64_t cBus::GetSizeForCounters() { - uint32_t count_errors = static_cast(common::idp::errorType::size); - uint32_t count_requests = static_cast(common::idp::requestType::size); + auto count_errors = static_cast(common::idp::errorType::size); + auto count_requests = static_cast(common::idp::requestType::size); return (count_errors + 2 * count_requests) * sizeof(uint64_t); } diff --git a/dataplane/icmp_translations.cpp b/dataplane/icmp_translations.cpp index 25fe1ec1..789d3497 100644 --- a/dataplane/icmp_translations.cpp +++ b/dataplane/icmp_translations.cpp @@ -155,7 +155,7 @@ bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, { return false; } - tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + ipv6PayloadHeaderSize); + auto* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + ipv6PayloadHeaderSize); packet_id = static_cast(extension->identification >> 16); fragment_offset = rte_cpu_to_be_16(rte_be_to_cpu_16(extension->offsetFlagM) >> 3); fragment_offset |= (extension->offsetFlagM & 0x0100) >> 3; @@ -182,7 +182,7 @@ bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, nextPayloadHeader = IPPROTO_ICMP; } - rte_ipv4_hdr* ipv4PayloadHeader = (rte_ipv4_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr)); + auto* ipv4PayloadHeader = (rte_ipv4_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize - sizeof(rte_ipv4_hdr)); ipv4PayloadHeader->version_ihl = 0x45; ipv4PayloadHeader->type_of_service = (rte_be_to_cpu_32(ipv6PayloadHeader->vtc_flow) >> 20) & 0xFF; @@ -223,21 +223,21 @@ bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, { /// @todo: check packet size - rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + auto* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); yanet_tcp_checksum_v6_to_v4(tcpPayloadHeader, checksum6, checksum4); } else if (nextPayloadHeader == IPPROTO_UDP) { /// @todo: check packet size - rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + auto* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); yanet_udp_checksum_v6_to_v4(udpPayloadHeader, checksum6, checksum4); } else if (nextPayloadHeader == IPPROTO_ICMP) { /// @todo: check packet size - icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); + auto* icmpPayloadHeader = (icmp_header_t*)((char*)ipv4PayloadHeader + sizeof(rte_ipv4_hdr)); if ((fragment_offset & 0xFF3F) != 0 || !yanet_icmp_translate_v6_to_v4(icmpPayloadHeader, @@ -431,7 +431,7 @@ bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, if ((fragment_offset & 0xFF3F) != 0) { - tIPv6ExtensionFragment* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + sizeof(rte_ipv6_hdr)); + auto* extension = (tIPv6ExtensionFragment*)(((char*)ipv6PayloadHeader) + sizeof(rte_ipv6_hdr)); extension->nextHeader = nextPayloadHeader; extension->reserved = 0; extension->offsetFlagM = rte_cpu_to_be_16(rte_be_to_cpu_16(fragment_offset) << 3); @@ -470,21 +470,21 @@ bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, { /// @todo: check packet size - rte_tcp_hdr* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + auto* tcpPayloadHeader = (rte_tcp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); yanet_tcp_checksum_v4_to_v6(tcpPayloadHeader, checksum4, checksum6); } else if (nextPayloadHeader == IPPROTO_UDP) { /// @todo: check packet size - rte_udp_hdr* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + auto* udpPayloadHeader = (rte_udp_hdr*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); yanet_udp_checksum_v4_to_v6(udpPayloadHeader, checksum4, checksum6); } else if (nextPayloadHeader == IPPROTO_ICMPV6) { /// @todo: check packet size - icmp_header_t* icmpPayloadHeader = (icmp_header_t*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); + auto* icmpPayloadHeader = (icmp_header_t*)((char*)ipv6PayloadHeader + ipv6PayloadHeaderSize); if ((fragment_offset & 0xFF3F) != 0 || !yanet_icmp_translate_v4_to_v6(icmpPayloadHeader, @@ -513,4 +513,4 @@ bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, return true; } -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/neighbor.cpp b/dataplane/neighbor.cpp index c27856f6..d7685bb3 100644 --- a/dataplane/neighbor.cpp +++ b/dataplane/neighbor.cpp @@ -51,7 +51,7 @@ static void netlink_parse(const std::functionnlmsg_len; if (nl_message_header->nlmsg_type == NLMSG_DONE || @@ -63,7 +63,7 @@ static void netlink_parse(const std::functionnlmsg_type == RTM_NEWNEIGH || nl_message_header->nlmsg_type == RTM_GETNEIGH) { - ndmsg* nl_message = (ndmsg*)NLMSG_DATA(nl_message_header); + auto* nl_message = (ndmsg*)NLMSG_DATA(nl_message_header); parse_rt_attributes(rt_attributes, NDA_MAX, (rtattr*)(((char*)(nl_message)) + NLMSG_ALIGN(sizeof(ndmsg))), diff --git a/dataplane/sharedmemory.cpp b/dataplane/sharedmemory.cpp index 3168fba8..aec56f17 100644 --- a/dataplane/sharedmemory.cpp +++ b/dataplane/sharedmemory.cpp @@ -23,7 +23,7 @@ void cSharedMemory::write(rte_mbuf* mbuf, common::globalBase::eFlowType flow_typ uint64_t wpos = (buffer.ring->header.before) % buffer.units_number; buffer.ring->header.before++; - item_t* item = (item_t*)((uintptr_t)buffer.ring->memory + (wpos * buffer.unit_size)); + auto* item = (item_t*)((uintptr_t)buffer.ring->memory + (wpos * buffer.unit_size)); dataplane::metadata* metadata = YADECAP_METADATA(mbuf); diff --git a/dataplane/sock_dev.cpp b/dataplane/sock_dev.cpp index 5cd1f6d2..189257a4 100644 --- a/dataplane/sock_dev.cpp +++ b/dataplane/sock_dev.cpp @@ -98,7 +98,7 @@ sock_dev_stop(struct rte_eth_dev* dev) static int sock_dev_close(struct rte_eth_dev* dev) { - struct sock_internals* internals = + auto* internals = (struct sock_internals*)dev->data->dev_private; close(internals->fd); @@ -143,7 +143,7 @@ sock_dev_rx_queue_setup(struct rte_eth_dev* dev, const struct rte_eth_rxconf* rx_conf __rte_unused, struct rte_mempool* mb_pool) { - struct sock_internals* si = (struct sock_internals*)dev->data->dev_private; + auto* si = (struct sock_internals*)dev->data->dev_private; dev->data->rx_queues[rx_queue_id] = si->rx_queues + rx_queue_id; si->rx_queues[rx_queue_id].internals = si; si->rx_queues[rx_queue_id].mb_pool = mb_pool; @@ -257,7 +257,7 @@ sock_dev_rx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) return 0; } - struct sock_queue* sq = (struct sock_queue*)q; + auto* sq = (struct sock_queue*)q; if (sq->internals->conFd < 0) { @@ -365,7 +365,7 @@ sock_dev_tx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) return 0; } - struct sock_internals* si = (struct sock_internals*)q; + auto* si = (struct sock_internals*)q; if (si->conFd < 0) { si->eth_stats.oerrors++; @@ -406,14 +406,14 @@ sock_dev_tx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) int sock_dev_stats_get(struct rte_eth_dev* dev, struct rte_eth_stats* igb_stats) { - sock_internals* private_data = (struct sock_internals*)dev->data->dev_private; + auto* private_data = (struct sock_internals*)dev->data->dev_private; memcpy(igb_stats, &private_data->eth_stats, sizeof(rte_eth_stats)); return 0; } int sock_dev_create(const char* path, const char* name, uint8_t numa_node) { - struct sock_internals* internals = (struct sock_internals*) + auto* internals = (struct sock_internals*) rte_zmalloc_socket(path, sizeof(struct sock_internals), 0, numa_node); if (internals == nullptr) return ENOSPC; diff --git a/dataplane/unittest/sdp.cpp b/dataplane/unittest/sdp.cpp index 312e024f..5181d00a 100644 --- a/dataplane/unittest/sdp.cpp +++ b/dataplane/unittest/sdp.cpp @@ -9,8 +9,8 @@ class TestBus public: static uint64_t GetSizeForCounters() { - uint32_t count_errors = static_cast(common::idp::errorType::size); - uint32_t count_requests = static_cast(common::idp::requestType::size); + auto count_errors = static_cast(common::idp::errorType::size); + auto count_requests = static_cast(common::idp::requestType::size); return (count_errors + 2 * count_requests) * sizeof(uint64_t); } @@ -39,8 +39,8 @@ class TestBus void CompareWithClient(const common::sdp::DataPlaneInSharedMemory& sdp_data_client) { void* buffer = common::sdp::ShiftBuffer(sdp_data_client.dataplane_data, sdp_data_client.start_bus_section); - uint32_t count_errors = static_cast(common::idp::errorType::size); - uint32_t count_requests = static_cast(common::idp::requestType::size); + auto count_errors = static_cast(common::idp::errorType::size); + auto count_requests = static_cast(common::idp::requestType::size); uint64_t* requests = common::sdp::ShiftBuffer(buffer, 0); uint64_t* errors = common::sdp::ShiftBuffer(buffer, count_requests * sizeof(uint64_t)); uint64_t* durations = common::sdp::ShiftBuffer(buffer, (count_requests + count_errors) * sizeof(uint64_t)); diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index e4eac656..ea96e779 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -963,7 +963,7 @@ inline bool worker_gc_t::is_timeout(const uint32_t timestamp, inline void worker_gc_t::correct_timestamp(uint16_t& timestamp, const uint16_t last_seen_max) { - uint16_t last_seen = (uint16_t)(current_time - timestamp); + auto last_seen = (uint16_t)(current_time - timestamp); if (last_seen > last_seen_max) { timestamp = (uint16_t)(current_time - last_seen_max); From 6e2844088dffaea13a829f5021fa3fcc3160c046 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:25:50 +0400 Subject: [PATCH 143/195] Use auto when initializing with new to avoid duplicating the type name --- controlplane/acl.cpp | 4 ++-- controlplane/acl/rule.h | 6 +++--- controlplane/unittest/segment_allocator.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 2f02f414..2d3bc4d2 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -58,8 +58,8 @@ struct dispatcher_rules_t { const auto& network = *item.network; - filter_network_t* _src = new filter_network_t; - filter_network_t* _dst = new filter_network_t; + auto* _src = new filter_network_t; + auto* _dst = new filter_network_t; if (std::holds_alternative(network)) { diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 7b5482fe..1b66b807 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -233,7 +233,7 @@ struct filter_network_t : filter_base_t inline ref_t and_op(const ref_t& a, const ref_t& b) { - filter_network_t* result = new filter_network_t; + auto* result = new filter_network_t; for (const auto& a_item : a.filter->networks) { @@ -371,7 +371,7 @@ struct filter_prm_t : filter_base_t template ref_t> and_op(const ref_t>& a, const ref_t>& b) { - filter_prm_t* result = new filter_prm_t; + auto* result = new filter_prm_t; for (const auto& a_item : a.filter->ranges) { @@ -396,7 +396,7 @@ using filter_prm16_t = filter_prm_t; static inline ref_t icmp_prm1(const common::ranges_t& types, const common::ranges_t& codes) { - filter_prm16_t* filter = new filter_prm16_t; + auto* filter = new filter_prm16_t; if (types == ranges_t{common::range_t{0x00, 0xFF}} && codes == ranges_t{common::range_t{0x00, 0xFF}}) { diff --git a/controlplane/unittest/segment_allocator.cpp b/controlplane/unittest/segment_allocator.cpp index 0af3cf37..0e203663 100644 --- a/controlplane/unittest/segment_allocator.cpp +++ b/controlplane/unittest/segment_allocator.cpp @@ -179,7 +179,7 @@ TEST(SegmentAllocator, BigSize) uint8_t data[sizeof(AllocatorBig)]; memset((void*)data, -1, sizeof(AllocatorBig)); - AllocatorBig* allocator = new (data) AllocatorBig(); + auto* allocator = new (data) AllocatorBig(); uint16_t size = 4; uint32_t full_size = index_end - index_begin; From a9c52ab93162257fae68a01bdd8e1db008a33ae1 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:28:09 +0400 Subject: [PATCH 144/195] Use auto when initializing with a template cast to avoid duplicating the type name --- autotest/autotest.cpp | 10 +++++----- cli/telegraf.h | 4 ++-- common/sdpclient.h | 6 +++--- common/sdpcommon.h | 6 +++--- controlplane/configparser.cpp | 10 +++++----- controlplane/controlplane.cpp | 2 +- controlplane/telegraf.cpp | 2 +- dataplane/unittest/sdp.cpp | 16 ++++++++-------- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 0c040a6c..5fa3dddf 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -892,7 +892,7 @@ bool tAutotest::step_sendPackets(const YAML::Node& yamlStep, for (const auto& yamlPort : yamlStep) { - std::string interfaceName = yamlPort["port"].as(); + auto interfaceName = yamlPort["port"].as(); if (yamlPort["send"]) { @@ -1195,9 +1195,9 @@ bool tAutotest::step_rib_clear(const YAML::Node& yaml) if (yaml_attribute["peer"].IsDefined() && yaml_attribute["vrf"].IsDefined() && yaml_attribute["priority"].IsDefined()) { - std::string peer = yaml_attribute["peer"].as(); - std::string vrf = yaml_attribute["vrf"].as(); - uint32_t priority = yaml_attribute["priority"].as(); + auto peer = yaml_attribute["peer"].as(); + auto vrf = yaml_attribute["vrf"].as(); + auto priority = yaml_attribute["priority"].as(); std::tuple vrf_priority_tup(std::move(vrf), std::move(priority)); std::tuple> peer_vrf_priority_tup(std::move(peer), std::move(vrf_priority_tup)); @@ -1923,7 +1923,7 @@ bool tAutotest::step_dumpPackets(const YAML::Node& yamlStep, TextDumper dumper; for (const auto& yamlDump : yamlStep) { - std::string tag = yamlDump["ringTag"].as(); + auto tag = yamlDump["ringTag"].as(); std::string expectFilePath = path + "/" + yamlDump["expect"].as(); bool success = true; diff --git a/cli/telegraf.h b/cli/telegraf.h index f9e429a6..482d8daa 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -710,7 +710,7 @@ void main_counters() for (const auto& [coreId, worker_info] : sdp_data.workers) { std::vector values; - uint64_t* buffer = common::sdp::ShiftBuffer(worker_info.buffer, + auto* buffer = common::sdp::ShiftBuffer(worker_info.buffer, sdp_data.metadata_worker.start_counters); for (const auto& [name, index] : sdp_data.metadata_worker.counter_positions) { @@ -722,7 +722,7 @@ void main_counters() for (const auto& [coreId, worker_info] : sdp_data.workers_gc) { std::vector values; - uint64_t* buffer = common::sdp::ShiftBuffer(worker_info.buffer, + auto* buffer = common::sdp::ShiftBuffer(worker_info.buffer, sdp_data.metadata_worker.start_counters); for (const auto& [name, index] : sdp_data.metadata_worker_gc.counter_positions) { diff --git a/common/sdpclient.h b/common/sdpclient.h index f9abf909..7150199e 100644 --- a/common/sdpclient.h +++ b/common/sdpclient.h @@ -177,7 +177,7 @@ class SdpClient { if (!core_id.has_value() || worker_core_id == core_id) { - uint64_t* counters = common::sdp::ShiftBuffer(worker_info.buffer, + auto* counters = common::sdp::ShiftBuffer(worker_info.buffer, sdp_data.metadata_worker.start_counters); result[worker_core_id] = counters[index]; } @@ -193,7 +193,7 @@ class SdpClient { if (!core_id.has_value() || worker_core_id == core_id) { - uint64_t* counters = common::sdp::ShiftBuffer(worker_info.buffer, + auto* counters = common::sdp::ShiftBuffer(worker_info.buffer, sdp_data.metadata_worker.start_counters); result[worker_core_id] = counters[index]; } @@ -429,7 +429,7 @@ class SdpClient static uint64_t ReadValue(void* buffer, uint64_t index) { - uint8_t* data = common::sdp::ShiftBuffer(buffer, index * sizeof(uint64_t)); + auto* data = common::sdp::ShiftBuffer(buffer, index * sizeof(uint64_t)); uint64_t result = 0; for (int i = 0; i < 8; i++) { diff --git a/common/sdpcommon.h b/common/sdpcommon.h index 33e6cd29..9e2a9f35 100644 --- a/common/sdpcommon.h +++ b/common/sdpcommon.h @@ -227,9 +227,9 @@ struct DataPlaneInSharedMemory { auto count_errors = static_cast(common::idp::errorType::size); auto count_requests = static_cast(common::idp::requestType::size); - uint64_t* requests = common::sdp::ShiftBuffer(dataplane_data, start_bus_section); - uint64_t* errors = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + count_requests * sizeof(uint64_t)); - uint64_t* durations = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + (count_requests + count_errors) * sizeof(uint64_t)); + auto* requests = common::sdp::ShiftBuffer(dataplane_data, start_bus_section); + auto* errors = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + count_requests * sizeof(uint64_t)); + auto* durations = common::sdp::ShiftBuffer(dataplane_data, start_bus_section + (count_requests + count_errors) * sizeof(uint64_t)); return {requests, errors, durations}; } }; diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index cc6aa182..d46cbb0c 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -1136,7 +1136,7 @@ void config_parser_t::loadConfig_acl(controlplane::base_t& baseNext, if (exist(moduleJson, "macros")) { - std::string includePath = moduleJson["macros"].get(); + auto includePath = moduleJson["macros"].get(); if (includePath.find("/") != 0) ///< relative path { includePath = dirname(rootFilePath) + "/" + includePath; @@ -1149,7 +1149,7 @@ void config_parser_t::loadConfig_acl(controlplane::base_t& baseNext, if (exist(moduleJson, "dnscache")) { - std::string includePath = moduleJson["dnscache"].get(); + auto includePath = moduleJson["dnscache"].get(); if (includePath.find("/") != 0) ///< relative path { includePath = dirname(rootFilePath) + "/" + includePath; @@ -1213,7 +1213,7 @@ void config_parser_t::loadConfig_acl(controlplane::base_t& baseNext, for (const auto& ipJson : srcPrefixes) { - std::string prefix_str = ipJson.get(); + auto prefix_str = ipJson.get(); ip_prefix_t prefix(prefix_str); if (prefix.is_ipv4()) @@ -1231,7 +1231,7 @@ void config_parser_t::loadConfig_acl(controlplane::base_t& baseNext, { for (const auto& ipJson : earlyDecapJson["dstAddresses"]) { - std::string addr_str = ipJson.get(); + auto addr_str = ipJson.get(); ip_prefix_t addr(addr_str); if (addr.is_ipv4()) @@ -1919,7 +1919,7 @@ void config_parser_t::loadConfig_memory_group(common::memory_manager::memory_gro { auto memory_group_next = std::make_shared(); - std::string name = json_iter["name"].get(); + auto name = json_iter["name"].get(); std::string limit = "0"; if (exist(json_iter, "limit")) { diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index ea72defb..6d14ac62 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -1004,7 +1004,7 @@ std::vector cControlPlane::getAclCounters() uint64_t start_acl_counters = sdp_data.metadata_worker.start_acl_counters; for (const auto& iter : sdp_data.workers) { - uint64_t* aclCounters = common::sdp::ShiftBuffer(iter.second.buffer, start_acl_counters); + auto* aclCounters = common::sdp::ShiftBuffer(iter.second.buffer, start_acl_counters); for (size_t i = 0; i < YANET_CONFIG_ACL_COUNTERS_SIZE; i++) { response[i] += aclCounters[i]; diff --git a/controlplane/telegraf.cpp b/controlplane/telegraf.cpp index cff9f004..4574619e 100644 --- a/controlplane/telegraf.cpp +++ b/controlplane/telegraf.cpp @@ -306,7 +306,7 @@ common::icp::telegraf_other::response telegraf_t::telegraf_other() for (const auto& [coreId, worker_info] : sdp_data->workers) { std::array bursts; - uint64_t* worker_bursts = + auto* worker_bursts = common::sdp::ShiftBuffer(worker_info.buffer, sdp_data->metadata_worker.start_bursts); memcpy(&bursts[0], worker_bursts, sizeof(uint64_t) * (CONFIG_YADECAP_MBUFS_BURST_SIZE + 1)); currWorkers[coreId] = bursts; diff --git a/dataplane/unittest/sdp.cpp b/dataplane/unittest/sdp.cpp index 5181d00a..992cd7ff 100644 --- a/dataplane/unittest/sdp.cpp +++ b/dataplane/unittest/sdp.cpp @@ -41,9 +41,9 @@ class TestBus void* buffer = common::sdp::ShiftBuffer(sdp_data_client.dataplane_data, sdp_data_client.start_bus_section); auto count_errors = static_cast(common::idp::errorType::size); auto count_requests = static_cast(common::idp::requestType::size); - uint64_t* requests = common::sdp::ShiftBuffer(buffer, 0); - uint64_t* errors = common::sdp::ShiftBuffer(buffer, count_requests * sizeof(uint64_t)); - uint64_t* durations = common::sdp::ShiftBuffer(buffer, (count_requests + count_errors) * sizeof(uint64_t)); + auto* requests = common::sdp::ShiftBuffer(buffer, 0); + auto* errors = common::sdp::ShiftBuffer(buffer, count_requests * sizeof(uint64_t)); + auto* durations = common::sdp::ShiftBuffer(buffer, (count_requests + count_errors) * sizeof(uint64_t)); for (uint32_t index = 0; index < static_cast(common::idp::requestType::size); index++) { @@ -207,7 +207,7 @@ class TestWorker ASSERT_EQ(common::sdp::SdpClient::GetCounterByName(sdp_data_client, "dropPackets", coreId)[coreId], stats->dropPackets); // statsPorts - common::worker::stats::port* bufStatsPorts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_stats_ports); + auto* bufStatsPorts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_stats_ports); for (uint32_t index = 0; index < CONFIG_YADECAP_PORTS_SIZE + 1; index++) { ASSERT_EQ(statsPorts[index].controlPlane_drops, bufStatsPorts[index].controlPlane_drops); @@ -215,21 +215,21 @@ class TestWorker } // bursts - uint64_t* bufBursts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_bursts); + auto* bufBursts = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_bursts); for (uint32_t index = 0; index < CONFIG_YADECAP_MBUFS_BURST_SIZE + 1; index++) { ASSERT_EQ(bursts[index], bufBursts[index]); } // counters - uint64_t* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_counters); + auto* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_counters); for (uint32_t index = 0; index < YANET_CONFIG_COUNTERS_SIZE; index++) { ASSERT_EQ(counters[index], bufCounters[index]); } // aclCounters - uint64_t* bufAclCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_acl_counters); + auto* bufAclCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker.start_acl_counters); for (uint32_t index = 0; index < YANET_CONFIG_ACL_COUNTERS_SIZE; index++) { ASSERT_EQ(aclCounters[index], bufAclCounters[index]); @@ -302,7 +302,7 @@ class TestWorkerGc ASSERT_EQ(common::sdp::SdpClient::GetCounterByName(sdp_data_client, "drop_samples", coreId)[coreId], stats->drop_samples); // counters - uint64_t* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker_gc.start_counters); + auto* bufCounters = common::sdp::ShiftBuffer(buffer, sdp_data_client.metadata_worker_gc.start_counters); for (uint32_t index = 0; index < YANET_CONFIG_COUNTERS_SIZE; index++) { ASSERT_EQ(counters[index], bufCounters[index]); From 3a028f415719422701caf7a284251d87c9b101b6 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:30:23 +0400 Subject: [PATCH 145/195] Nested namespaces can be concatenated --- cli/develop.h | 7 +++---- common/icp.h | 7 +++---- common/tsc_deltas.h | 7 +++---- common/type.h | 7 +++---- controlplane/protobus.h | 7 +++---- dataplane/report.cpp | 9 ++++----- 6 files changed, 19 insertions(+), 25 deletions(-) diff --git a/cli/develop.h b/cli/develop.h index 1f736727..5b099137 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -14,10 +14,9 @@ #include "helper.h" -namespace develop -{ -namespace dataplane + +namespace develop::dataplane { static inline void printValue(const common::idp::value& value) @@ -369,4 +368,4 @@ void tsc_monitoring() } -} + diff --git a/common/icp.h b/common/icp.h index 8f377312..3b42b287 100644 --- a/common/icp.h +++ b/common/icp.h @@ -15,9 +15,8 @@ #include "result.h" #include "type.h" -namespace common -{ -namespace icp + +namespace common::icp { constexpr inline char socketPath[] = "/run/yanet/controlplane.sock"; @@ -1021,4 +1020,4 @@ using response = std::variant, convert::response, counters_stat::response>; } -} + diff --git a/common/tsc_deltas.h b/common/tsc_deltas.h index 9e503797..c4252601 100644 --- a/common/tsc_deltas.h +++ b/common/tsc_deltas.h @@ -13,10 +13,9 @@ #define YANET_TSC_BINS_SHIFT 2 #define YANET_TSC_BINS_N 4 -namespace dataplane -{ -namespace perf + +namespace dataplane::perf { struct tsc_base_values @@ -112,4 +111,4 @@ static_assert(std::is_pod_v == true, } -} + diff --git a/common/type.h b/common/type.h index a6b0b353..a4f61350 100644 --- a/common/type.h +++ b/common/type.h @@ -1984,9 +1984,8 @@ constexpr ipv6_prefix_t ipv6_prefix_default = {ipv6_address_default, 0}; // -namespace worker -{ -namespace stats + +namespace worker::stats { struct common { @@ -2033,7 +2032,7 @@ struct port uint64_t controlPlane_drops = 0; ///< @todo: DELETE }; } -} + namespace worker_gc { diff --git a/controlplane/protobus.h b/controlplane/protobus.h index 921e9bac..fe778de5 100644 --- a/controlplane/protobus.h +++ b/controlplane/protobus.h @@ -4,9 +4,8 @@ #include "module.h" -namespace controlplane -{ -namespace module + +namespace controlplane::module { class protoBus : public cModule @@ -27,4 +26,4 @@ class protoBus : public cModule }; } -} + diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 19ebf3e5..9b1e7192 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -35,9 +35,8 @@ nlohmann::json convertHashtable(const hashtable_mod_T& hashtable, const stats_T& } // namespace -namespace common -{ -namespace dregress + +namespace common::dregress { void to_json(nlohmann::json& j, const stats_t& stats) { @@ -57,8 +56,8 @@ void to_json(nlohmann::json& j, const stats_t& stats) {"tcp_timeout_sessions", stats.tcp_timeout_sessions}, {"tcp_unknown_sessions", stats.tcp_unknown_sessions}}; } -} // namespace dregress -} // namespace common +} // namespace common::dregress + cReport::cReport(cDataPlane* dataPlane) : dataPlane(dataPlane) From 71dbc8b23295e7e23f85e5cf4c52dfcde7c996e9 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 16:31:38 +0400 Subject: [PATCH 146/195] Use emplace_back instead of push_back No point in creating an object first to be pushed with push_back when we can just use emplace_back, i.e `response.push_back({id, name});` -> `response.emplace_back(id, name);` --- controlplane/acl.cpp | 2 +- controlplane/acl/dict.h | 2 +- controlplane/balancer.cpp | 4 ++-- controlplane/controlplane.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 2d3bc4d2..e486cc52 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -785,7 +785,7 @@ std::vector unwind_used_rules(const std::map ids_overflow; #ifdef ACL_DEBUG diff --git a/controlplane/acl/dict.h b/controlplane/acl/dict.h index 8e1da171..90e1a393 100644 --- a/controlplane/acl/dict.h +++ b/controlplane/acl/dict.h @@ -268,7 +268,7 @@ struct rdict_t vec.reserve(map.size()); for (auto& v : map) { - vec.push_back(v); + vec.emplace_back(v); } return vec; diff --git a/controlplane/balancer.cpp b/controlplane/balancer.cpp index f17855f4..88a2dc0e 100644 --- a/controlplane/balancer.cpp +++ b/controlplane/balancer.cpp @@ -159,14 +159,14 @@ void balancer_t::Real( request.reserve(req->reals().size()); for (const auto& real : req->reals()) { - request.push_back({real.module(), + request.emplace_back(real.module(), convert_to_ip_address(real.virtual_ip()), real.proto() == common::icp_proto::NetProto::tcp ? IPPROTO_TCP : IPPROTO_UDP, real.virtual_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::VirtualPortOptCase::kVirtualPort ? std::make_optional(real.virtual_port()) : std::nullopt, convert_to_ip_address(real.real_ip()), real.real_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::RealPortOptCase::kRealPort ? std::make_optional(real.real_port()) : std::nullopt, real.enable(), - real.weight_opt_case() == common::icp_proto::BalancerRealRequest_Real::WeightOptCase::kWeight ? std::make_optional(real.weight()) : std::nullopt}); + real.weight_opt_case() == common::icp_proto::BalancerRealRequest_Real::WeightOptCase::kWeight ? std::make_optional(real.weight()) : std::nullopt); } balancer_real(request); diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index 6d14ac62..3bd36d65 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -845,7 +845,7 @@ common::icp::convert::response cControlPlane::convert_logical_module() for (auto [id, name] : logicalport_id_to_name) { - response.push_back({id, name}); + response.emplace_back(id, name); } return response; From 1401ca4d2377b60c3596d0e7489153649e97deeb Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 17:52:25 +0400 Subject: [PATCH 147/195] Remove lpm unittest file Commit 8ff4da40df8aa8b50f1a9cb06f0a04ec86e8b990 disabled 'lpm.cpp' unittest. With it, this file file became useless --- dataplane/unittest/lpm.cpp | 890 ------------------------------------- 1 file changed, 890 deletions(-) delete mode 100644 dataplane/unittest/lpm.cpp diff --git a/dataplane/unittest/lpm.cpp b/dataplane/unittest/lpm.cpp deleted file mode 100644 index bd83afc7..00000000 --- a/dataplane/unittest/lpm.cpp +++ /dev/null @@ -1,890 +0,0 @@ -//! In this LPM insertion order matters! - -#include -#include -#include - -#include - -#include "../lpm.h" - -namespace -{ - -/// Non-functional extension of an LPM to provide nice dump methods. -template -class lpm6_8x16bit_atomic : public dataplane::lpm6_8x16bit_atomic -{ -public: - void print() const - { - auto envPtr = std::getenv("YANET_TEST_DEBUG"); - if (envPtr == nullptr) - { - return; - } - - std::string env(envPtr); - if (env == "plain") - { - print_table(); - return; - } - if (env == "graph") - { - print_digraph(); - return; - } - } - - void print_table() const - { - printf("==================================\n"); - print_chunk(this->rootChunk, -1, true); - for (unsigned int j = 0; j < TExtendedSize; j++) - { - print_chunk(this->extendedChunks[j], j); - } - } - - void print_digraph() const - { - printf("%s\n", digraph().data()); - } - - std::string digraph() const - { - std::ostringstream s; - s << "digraph G {\n"; - s << " nodesep=.05;\n"; - s << " rankdir=LR;\n"; - s << " node [shape=record fontname=\"Monospace\" fontsize=10];\n"; - s << " node [width = 0.5];\n"; - build_digraph_chunk(this->rootChunk, "R", s, true); - for (unsigned int j = 0; j < TExtendedSize; j++) - { - build_digraph_chunk(this->extendedChunks[j], j, s); - } - s << "}\n"; - - return s.str(); - } - -private: - struct entry_t - { - int from; - int to; - uint32_t flags; - uint32_t value; - }; - - template - void visit_chunk(const T& chunk, bool isRoot, const F& fn) const - { - if (!(chunk.entries[0].flags & this->flagExtendedChunkOccupied) && !isRoot) - { - return; - } - - int minDupIdx = 0; - for (int i = 1; i < 256 * 256; i++) - { - auto currEntry = chunk.entries[i]; - currEntry.flags &= ~(this->flagExtendedChunkOccupied); - auto prevEntry = chunk.entries[i - 1]; - prevEntry.flags &= ~(this->flagExtendedChunkOccupied); - auto minDupIdxEntry = chunk.entries[minDupIdx]; - minDupIdxEntry.flags &= ~(this->flagExtendedChunkOccupied); - - if (currEntry.atomic != prevEntry.atomic) - { - if (minDupIdxEntry.atomic != 0) - { - fn(entry_t{minDupIdx, i - 1, minDupIdxEntry.flags, minDupIdxEntry.valueId}); - } - minDupIdx = i; - } - } - if (chunk.entries[minDupIdx].atomic != 0) - { - fn(entry_t{minDupIdx, 0xffff, chunk.entries[minDupIdx].flags, chunk.entries[minDupIdx].valueId}); - } - } - - template - void print_chunk(const T& chunk, int chunkId, bool isRoot = false) const - { - visit_chunk(chunk, isRoot, [&](entry_t entry) { - if (entry.from == entry.to) - { - printf("%2d %04x : flags=0x%02x, value=%d\n", chunkId, entry.from, entry.flags, entry.value); - } - else - { - printf("%2d %04x..%04x: flags=0x%02x, value=%d\n", chunkId, entry.from, entry.to, entry.flags, entry.value); - } - }); - } - - template - void build_digraph_chunk(const T& chunk, N j, std::ostringstream& s, bool isRoot = false) const - { - std::vector entries; - visit_chunk(chunk, isRoot, [&](entry_t entry) { - entries.push_back(entry); - }); - - if (!entries.empty()) - { - s << " node" << j << "[label=\"[" << j << "]|{{"; - for (auto p = entries.begin(); p != entries.end(); ++p) - { - if (p->from == p->to) - { - char buf[16] = {}; - std::snprintf(buf, 8, "%04x", p->from); - s << buf; - } - else - { - char buf[16] = {}; - std::snprintf(buf, 12, "%04x-%04x", p->from, p->to); - s << buf; - } - if (p != entries.end() - 1) - { - s << "|"; - } - } - s << "}|{"; - for (unsigned int i = 0; i < entries.size(); ++i) - { - s << ""; - if (entries[i].flags & this->flagValid) - { - s << entries[i].value; - } - if (i != entries.size() - 1) - { - s << "|"; - } - } - s << "}}\"];\n"; - - for (unsigned int i = 0; i < entries.size(); ++i) - { - if (entries[i].flags & this->flagExtended) - { - s << " node" << j << ":f" << i << "->node" << entries[i].value << ":n\n"; - } - } - } - } -}; - -TEST(LPM, Lookup) -{ - auto t = std::make_unique>(); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::1"), &valueId)); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), 64, 4299)); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::1"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:ffff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, LookupUnalignedBitMask) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), 69, 4299)); - - uint32_t valueId{0}; - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:07ff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - // Out of range. - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:800:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(dataplane::lpmValueIdInvalid, valueId); - - t->print(); -} - -TEST(LPM, LookupOverlapped) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), 64, 4299)); - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234:4800::"), 69, 589)); - - uint32_t valueId{0}; - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:47ff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:4800::"), &valueId)); - EXPECT_EQ(589, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:4fff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(589, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:5000:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:ffff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, LookupOverlappedSimple) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"::", 0, 1}, - {"10:20::", 32, 2}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(net), mask, value)); - } - - uint32_t valueId{0}; - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("::1"), &valueId)); - EXPECT_EQ(1, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("10:20::1"), &valueId)); - EXPECT_EQ(2, valueId); - - t->print(); -} - -TEST(LPM, LookupExtMask) -{ - auto t = std::make_unique>(); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::1"), &valueId)); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), common::ipv6_address_t("ffff:ffff:ffff:ffff::"), 4299)); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::1"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:ffff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, LookupUnalignedBitExtMask) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), common::ipv6_address_t("ffff:ffff:ffff:ffff:f800::"), 4299)); - - uint32_t valueId{0}; - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:07ff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - // Out of range. - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:800:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(dataplane::lpmValueIdInvalid, valueId); - - t->print(); -} - -TEST(LPM, LookupOverlappedExt) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"2222:777:aabc:1234::", "ffff:ffff:ffff:ffff::", 4299}, - {"2222:777:aabc:1234:4800::", "ffff:ffff:ffff:ffff:f800::", 589}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value), eResult::success); - t->print(); - } - - uint32_t valueId{0}; - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:47ff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:4800::"), &valueId)); - EXPECT_EQ(589, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:4fff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(589, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:5000::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:ffff:ffff:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, LookupProjectIDExtMask) -{ - auto t = std::make_unique>(); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:0:1234:0:1"), &valueId)); - - // 1234@2222:777:aabc::/48 - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc::1234:0:0"), common::ipv6_address_t("ffff:ffff:ffff:0:ffff:ffff::"), 4299)); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:0:1234:0:1"), &valueId)); - EXPECT_EQ(4299, valueId); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:0:1234::"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:0:1234:ffff:ffff"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_FALSE(t->lookup(common::ipv6_address_t("2222:777:aabc:1234:0:1233::"), &valueId)); - EXPECT_EQ(dataplane::lpmValueIdInvalid, valueId); - - t->print(); -} - -TEST(LPM, LookupManyProjectIDsExtMask) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"2222:777:aabc::1234:0:0", "ffff:ffff:ffff:0:ffff:ffff::", 100}, - {"2222:777:aabc::1122:0:0", "ffff:ffff:ffff:0:ffff:ffff::", 101}, - {"2222:777:ff1d::", "ffff:ffff:ffff::", 102}, - {"2222:777:c00:0:add:8765::", "ffff:ffff:ff00:0:ffff:ffff::", 103}, - {"2222:777:c00:0:add:8005::", "ffff:ffff:ff00:0:ffff:ffff::", 104}, - {"2222:770:c00::f800:0:0", "ffff:ffff:ff00:0:ffff:f800::", 105}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value), eResult::success); - } - - const std::vector> cases{ - /// Value 100 - {"2222:777:aabc:1234:0:1234::", 100}, - {"2222:777:aabc:1234:0:1234:0:1", 100}, - {"2222:777:aabc:1234:0:1234::", 100}, - {"2222:777:aabc:1234:0:1234:0:ffff", 100}, - {"2222:777:aabc:1234:0:1234:ffff:ffff", 100}, - - /// Value 101 - {"2222:777:aabc::1122:0:0", 101}, - {"2222:777:aabc::1122:0:1", 101}, - {"2222:777:aabc:ff00:0:1122:0:1", 101}, - {"2222:777:aabc:ffff:0:1122:0:1", 101}, - - /// Value 102 - {"2222:777:ff1d::1", 102}, - {"2222:777:ff1d:ff00::1", 102}, - {"2222:777:ff1d:ff00:0:1234:0:1", 102}, - - /// Value 103 - {"2222:777:c00:0:add:8765::", 103}, - {"2222:777:c00:0:add:8765:0:1", 103}, - {"2222:777:c00:0:add:8765:0:2211", 103}, - {"2222:777:c00:0:add:8765:4433:0", 103}, - {"2222:777:c77:6655:add:8765:4433:2211", 103}, - - /// Value 104 - {"2222:777:c00:0:add:8005::", 104}, - {"2222:777:c00:0:add:8005:0:1", 104}, - {"2222:777:c00:0:add:8005:0:2211", 104}, - {"2222:777:c00:0:add:8005:4433:0", 104}, - {"2222:777:c77:6655:add:8005:4433:2211", 104}, - - /// Value 105 - {"2222:770:c00::f800:0:0", 105}, - {"2222:770:c00::f800:0:11", 105}, - {"2222:770:c00::f800:4433:2211", 105}, - {"2222:770:c00::f900:4433:2211", 105}, - {"2222:770:c00::ff00:4433:2211", 105}, - {"2222:770:c00::ff01:4433:2211", 105}, - {"2222:770:c00::fffe:4433:2211", 105}, - {"2222:770:c00::ffff:4433:2211", 105}, - {"2222:770:c00:8877:0:ffff:4433:2211", 105}, - {"2222:770:c99:8877:0:ffff:4433:2211", 105}, - - /// Invalid - {"2222:777:aabc::1134:0:1", dataplane::lpmValueIdInvalid}, - {"2222:777:ff1f::1234:0:1", dataplane::lpmValueIdInvalid}, - {"2222:770:c00::f7ff:4433:2211", dataplane::lpmValueIdInvalid}, - }; - - for (auto [addr, value] : cases) - { - uint32_t valueId{0}; - EXPECT_EQ(value != dataplane::lpmValueIdInvalid, t->lookup(common::ipv6_address_t(addr), &valueId)); - EXPECT_EQ(value, valueId); - } - - t->print(); -} - -TEST(LPM, LookupTrouble) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"2222:777:aabc:2030::", "ffff:ffff:ffff:fff0::", 589}, - {"2222:777:aabc:2030::", "ffff:ffff:ffff:ffff::", 42}, - {"2222:777:aabc:2030:0:1234::", "ffff:ffff:ffff:fff0:ffff:ffff::", 4299}, - {"2222:777:aabc:2030:0:5678::", "ffff:ffff:ffff:fff0:ffff:ffff::", 4298}, - {"2222:777:aabc:2030:aabb:5678::", "ffff:ffff:ffff:fff0:ffff:ffff::", 4297}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value), eResult::success); - t->print(); - } - - const std::vector> cases{ - {"2222:777:aabc:2030::1", 42}, - {"2222:777:aabc:2030:0:0:ffff:1", 42}, - {"2222:777:aabc:2030:0:ffff:0:1", 42}, - {"2222:777:aabc:2030:0:ffff:ffff:1", 42}, - {"2222:777:aabc:2030:aabb:ffff:ffff:1", 42}, - - {"2222:777:aabc:2031::1", 589}, - {"2222:777:aabc:2032::1", 589}, - {"2222:777:aabc:2033::1", 589}, - {"2222:777:aabc:2034::1", 589}, - {"2222:777:aabc:2035::1", 589}, - {"2222:777:aabc:2036::1", 589}, - {"2222:777:aabc:2037::1", 589}, - {"2222:777:aabc:2038::1", 589}, - {"2222:777:aabc:2039::1", 589}, - {"2222:777:aabc:203a::1", 589}, - {"2222:777:aabc:203b::1", 589}, - {"2222:777:aabc:203c::1", 589}, - {"2222:777:aabc:203d::1", 589}, - {"2222:777:aabc:203e::1", 589}, - {"2222:777:aabc:203f::1", 589}, - {"2222:777:aabc:2031:0:0:ffff:1", 589}, - {"2222:777:aabc:2032:0:ffff:0:1", 589}, - {"2222:777:aabc:2033:0:ffff:ffff:1", 589}, - {"2222:777:aabc:2034:aabb:ffff:ffff:1", 589}, - - {"2222:777:aabc:2030:0:1234:0:1", 4299}, - {"2222:777:aabc:2031:0:1234:0:1", 4299}, - {"2222:777:aabc:2032:0:1234:0:1", 4299}, - {"2222:777:aabc:2033:0:1234:0:1", 4299}, - {"2222:777:aabc:2034:0:1234:0:1", 4299}, - {"2222:777:aabc:2035:0:1234:0:1", 4299}, - {"2222:777:aabc:2036:0:1234:0:1", 4299}, - {"2222:777:aabc:2037:0:1234:0:1", 4299}, - {"2222:777:aabc:2038:0:1234:0:1", 4299}, - {"2222:777:aabc:2039:0:1234:0:1", 4299}, - {"2222:777:aabc:203a:0:1234:0:1", 4299}, - {"2222:777:aabc:203b:0:1234:0:1", 4299}, - {"2222:777:aabc:203c:0:1234:0:1", 4299}, - {"2222:777:aabc:203d:0:1234:0:1", 4299}, - {"2222:777:aabc:203e:0:1234:0:1", 4299}, - {"2222:777:aabc:203f:0:1234:0:1", 4299}, - - {"2222:777:aabc:2030:0:5678:0:1", 4298}, - {"2222:777:aabc:2031:0:5678:0:1", 4298}, - {"2222:777:aabc:2032:0:5678:0:1", 4298}, - {"2222:777:aabc:2033:0:5678:0:1", 4298}, - {"2222:777:aabc:2034:0:5678:0:1", 4298}, - {"2222:777:aabc:2035:0:5678:0:1", 4298}, - {"2222:777:aabc:2036:0:5678:0:1", 4298}, - {"2222:777:aabc:2037:0:5678:0:1", 4298}, - {"2222:777:aabc:2038:0:5678:0:1", 4298}, - {"2222:777:aabc:2039:0:5678:0:1", 4298}, - {"2222:777:aabc:203a:0:5678:0:1", 4298}, - {"2222:777:aabc:203b:0:5678:0:1", 4298}, - {"2222:777:aabc:203c:0:5678:0:1", 4298}, - {"2222:777:aabc:203d:0:5678:0:1", 4298}, - {"2222:777:aabc:203e:0:5678:0:1", 4298}, - {"2222:777:aabc:203f:0:5678:0:1", 4298}, - - {"2222:777:aabc:2030:aabb:5678::1", 4297}, - {"2222:777:aabc:2031:aabb:5678::1", 4297}, - {"2222:777:aabc:2032:aabb:5678::1", 4297}, - {"2222:777:aabc:2033:aabb:5678::1", 4297}, - {"2222:777:aabc:2034:aabb:5678::1", 4297}, - {"2222:777:aabc:2035:aabb:5678::1", 4297}, - {"2222:777:aabc:2036:aabb:5678::1", 4297}, - {"2222:777:aabc:2037:aabb:5678::1", 4297}, - {"2222:777:aabc:2038:aabb:5678::1", 4297}, - {"2222:777:aabc:2039:aabb:5678::1", 4297}, - {"2222:777:aabc:203a:aabb:5678::1", 4297}, - {"2222:777:aabc:203b:aabb:5678::1", 4297}, - {"2222:777:aabc:203c:aabb:5678::1", 4297}, - {"2222:777:aabc:203d:aabb:5678::1", 4297}, - {"2222:777:aabc:203e:aabb:5678::1", 4297}, - {"2222:777:aabc:203f:aabb:5678::1", 4297}, - }; - - for (auto [addr, value] : cases) - { - uint32_t valueId{0}; - EXPECT_EQ(value != dataplane::lpmValueIdInvalid, t->lookup(common::ipv6_address_t(addr), &valueId)); - EXPECT_EQ(value, valueId) << common::ipv6_address_t(addr).toString() << " -> " << value; - } - - t->print(); -} - -TEST(LPM, LookupMixedNetworksWithSamePrefix) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"2222:777:c00::", "ffff:ffff:ff00::", 589}, - {"2222:777:c00:0:add:8765::", "ffff:ffff:ff00:0:ffff:ffff::", 4299}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value), eResult::success); - } - - const std::vector> cases{ - {"2222:777:c00:0:add:8765:0:1", 4299}, - {"2222:777:c00:0:10d:4d60:0:1", 589}, - }; - - for (auto [addr, value] : cases) - { - uint32_t valueId{0}; - EXPECT_EQ(value != dataplane::lpmValueIdInvalid, t->lookup(common::ipv6_address_t(addr), &valueId)); - EXPECT_EQ(value, valueId); - } - - t->print(); -} - -TEST(LPM, LookupSummary) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"::", "::", 1001}, - {"1111:2222::", "ffff:ffff::", 1002}, - {"3333:4444:5555::", "ffff:ffff:ffff::", 1003}, - {"3333:4444:5555:0:aaaa:bbbb::", "ffff:ffff:ffff:0:ffff:ffff::", 1004}, - {"3333:4444:5555:6666::", "ffff:ffff:ffff:ffff::", 1005}, - {"3333:4444:5555:6666:aaaa:bbbb::", "ffff:ffff:ffff:ffff:ffff:ffff::", 1006}, - {"3333:4444:5555:6666:aaaa:bbbb:cccc:dddd", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 1007}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value)); - t->print(); - } - - const std::vector> cases{ - {"::1", 1001}, - {"1111:2222:c00::1", 1002}, - {"3333:4444:5555::1", 1003}, - {"3333:4444:5555:0:aaaa:bbbb:0:1", 1004}, - {"3333:4444:5555:1:aaaa:bbbb:0:1", 1004}, - {"3333:4444:5555:ffff:aaaa:bbbb:0:1", 1004}, - {"3333:4444:5555:6666::1", 1005}, - {"3333:4444:5555:6666:aaaa::1", 1005}, - {"3333:4444:5555:6666:0:bbbb:0:1", 1005}, - {"3333:4444:5555:6666:aaaa:bbbb:0:1", 1006}, - {"3333:4444:5555:6666:aaaa:bbbb:cccc:dddd", 1007}, - }; - - for (auto [addr, value] : cases) - { - uint32_t valueId{0}; - EXPECT_EQ(value != dataplane::lpmValueIdInvalid, t->lookup(common::ipv6_address_t(addr), &valueId)); - EXPECT_EQ(value, valueId); - } - - t->print(); -} - -TEST(LPM, LookupMerge) -{ - auto t = std::make_unique>(); - - for (int i = 65535; i >= 1; i--) - { - std::array addr{0x11, 0x11, 0x22, 0x22, uint8_t(i / 256), uint8_t(i % 256), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(addr), common::ipv6_address_t("ffff:ffff:ffff::"), 1000)); - } - - EXPECT_EQ(2, t->getStats().extendedChunksCount); - - std::array addr{0x11, 0x11, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(addr), common::ipv6_address_t("ffff:ffff:ffff::"), 1000)); - EXPECT_EQ(1, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, LookupCruelRealWorld) -{ - auto t = std::make_unique>(); - - std::ifstream stream("networks.txt"); - std::string line; - int counter = 1000000; // Easier to match by eyes. - std::vector> entries; - while (std::getline(stream, line)) - { - auto pos = line.find('/'); - auto addr = line.substr(0, pos); - auto mask = line.substr(pos + 1); - if (pos == std::string::npos) - { - mask = "128"; - } - - auto isNumber = !mask.empty() && std::all_of(mask.begin(), mask.end(), ::isdigit); - if (isNumber) - { - // Nevermind. The easiest way to convert ones set to proper IPv6 address. - mask = common::ipv6_address_t(t->createMask(std::stoi(mask, nullptr, 10))).toString(); - } - entries.emplace_back(addr, mask, counter++); - } - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value)) - << "Failed to insert " << value; - } - - t->print(); -} - -TEST(LPM, RemoveOne) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), 64, 4299)); - EXPECT_EQ(3, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("2222:777:aabc:1234::"), 64)); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, RemoveNotSame) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("::"), 0, 4299)); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("::1"), 128)); - EXPECT_EQ(7, t->getStats().extendedChunksCount); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("::1"), &valueId)); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("::2"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, RemoveNet) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("1111:2222::"), 32, 100)); - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("1111:2222:3333::"), 48, 101)); - EXPECT_EQ(2, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("1111:2222::"), 32)); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, RemoveOneWithMask) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("2222:777:aabc:1234::"), common::ipv6_address_t("ffff:ffff:ffff:ffff::"), 4299)); - EXPECT_EQ(3, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("2222:777:aabc:1234::"), common::ipv6_address_t("ffff:ffff:ffff:ffff::"))); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, RemoveNotSameWithMask) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("::"), common::ipv6_address_t("::"), 4299)); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("::1"), common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))); - EXPECT_EQ(7, t->getStats().extendedChunksCount); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("::1"), &valueId)); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("::2"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, RemoveNetWithMask) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("1111:2222::"), common::ipv6_address_t("ffff:ffff::"), 100)); - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("1111:2222:3333::"), common::ipv6_address_t("ffff:ffff:ffff::"), 101)); - EXPECT_EQ(2, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("1111:2222::"), common::ipv6_address_t("ffff:ffff::"))); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, RemoveGappedNetwork) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t("::"), common::ipv6_address_t("::"), 4299)); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("1111:2222:0:0:aaaa:bbbb::"), common::ipv6_address_t("ffff:ffff:0:0:ffff:ffff:0:0"))); - EXPECT_EQ(5, t->getStats().extendedChunksCount); - - uint32_t valueId{0}; - EXPECT_FALSE(t->lookup(common::ipv6_address_t("1111:2222:3333:4444:aaaa:bbbb::1"), &valueId)); - EXPECT_EQ(dataplane::lpmValueIdInvalid, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("1111:2222:3333:4444:aaaa:cccc::2"), &valueId)); - EXPECT_EQ(4299, valueId); - - t->print(); -} - -TEST(LPM, LookupSummaryWithClear) -{ - auto t = std::make_unique>(); - - const std::vector> entries{ - {"::", "::", 1001}, - {"1111:2222::", "ffff:ffff::", 1002}, - {"3333:4444:5555::", "ffff:ffff:ffff::", 1003}, - {"3333:4444:5555:0:aaaa:bbbb::", "ffff:ffff:ffff:0:ffff:ffff::", 1004}, - {"3333:4444:5555:6666::", "ffff:ffff:ffff:ffff::", 1005}, - {"3333:4444:5555:6666:aaaa:bbbb::", "ffff:ffff:ffff:ffff:ffff:ffff::", 1006}, - }; - - for (auto [net, mask, value] : entries) - { - EXPECT_EQ(eResult::success, t->insert(common::ipv6_address_t(net), common::ipv6_address_t(mask), value)); - } - - EXPECT_EQ(eResult::success, t->remove(common::ipv6_address_t("::"), common::ipv6_address_t("::"))); - EXPECT_EQ(0, t->getStats().extendedChunksCount); - - t->print(); -} - -TEST(LPM, InsertCorruption) -{ - auto t = std::make_unique>(); - - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777::00af"), - common::ipv6_address_t("ffff:ffff::ffff:ffff:ffff:ffff"), - 4299)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:1a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 589)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:2a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 105)); - - uint32_t valueId{0}; - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:1a::a1"), &valueId)); - EXPECT_EQ(589, valueId); - - t->print(); - - t->clear(); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777::00af"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 456)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:1a::00af"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 890)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:2a::00af"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 999)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777::00af"), - common::ipv6_address_t("ffff:ffff::ffff:ffff:ffff:ffff"), - 4299)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:1a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 589)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:2a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 105)); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777::af"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:1a::a1"), &valueId)); - EXPECT_EQ(589, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:2a::a1"), &valueId)); - EXPECT_EQ(105, valueId); - - t->print(); - - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:1a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 1112)); - EXPECT_EQ(eResult::success, - t->insert(common::ipv6_address_t("2222:777:2a::a1"), - common::ipv6_address_t("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), - 1221)); - - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777::af"), &valueId)); - EXPECT_EQ(4299, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:1a::a1"), &valueId)); - EXPECT_EQ(1112, valueId); - EXPECT_TRUE(t->lookup(common::ipv6_address_t("2222:777:2a::a1"), &valueId)); - EXPECT_EQ(1221, valueId); - - t->print(); -} - -} // namespace From 38dfde03a80617641535946c53b37aebf8b8b377 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 20 Sep 2024 18:54:18 +0400 Subject: [PATCH 148/195] Remove included headers that are not used directly Even though those includes are not used directly, the code could still use header that were inside the removed one. So we also need to add the exact includes that code needs (will be done later) --- autotest/autotest.cpp | 3 ++- autotest/autotest.h | 2 +- autotest/main.cpp | 1 - cli/balancer.h | 1 - cli/develop.h | 1 - common/acl.h | 2 -- common/config.autotest.h | 1 - common/define.h | 1 - common/icp_proto.h | 1 - common/idp.h | 1 - common/sdpcommon.h | 3 --- common/type.h | 2 +- controlplane/acl.cpp | 5 ----- controlplane/acl.h | 1 + controlplane/acl/dict.h | 1 - controlplane/acl/rule.h | 1 - controlplane/acl_base.h | 6 +----- controlplane/acl_flat.h | 1 - controlplane/acl_network_table.h | 6 +++++- controlplane/acl_table.h | 6 +----- controlplane/acl_transport.cpp | 1 - controlplane/acl_transport_table.h | 2 -- controlplane/acl_tree.h | 2 -- controlplane/balancer.h | 1 - controlplane/base.h | 3 +-- controlplane/bus.h | 1 - controlplane/configconverter.cpp | 4 +--- controlplane/configconverter.h | 2 ++ controlplane/configparser.h | 2 +- controlplane/controlplane.h | 8 -------- controlplane/counter.h | 9 ++------- controlplane/dregress.h | 1 + controlplane/durations.h | 2 -- controlplane/fqdn.h | 1 - controlplane/isystem.cpp | 1 - controlplane/main.cpp | 1 - controlplane/nat64stateful.h | 1 - controlplane/protobus.h | 1 - controlplane/rib.h | 18 ++---------------- controlplane/route.cpp | 2 ++ controlplane/route.h | 1 + controlplane/segment_allocator.h | 1 - controlplane/telegraf.h | 1 - controlplane/tun64.h | 1 - controlplane/type.h | 1 - controlplane/unittest/acl_flat.cpp | 2 -- controlplane/unittest/parser.cpp | 1 - dataplane/bus.h | 16 ++-------------- dataplane/checksum.h | 1 - dataplane/common.h | 2 +- dataplane/config_values.h | 2 +- dataplane/controlplane.cpp | 15 ++------------- dataplane/controlplane.h | 8 ++------ dataplane/dataplane.cpp | 4 +--- dataplane/dataplane.h | 1 - dataplane/dregress.cpp | 1 - dataplane/dregress.h | 1 - dataplane/dynamic_table.h | 4 +--- dataplane/flat.h | 1 - dataplane/fragmentation.h | 3 --- dataplane/icmp_translations.cpp | 3 +++ dataplane/icmp_translations.h | 5 ++--- dataplane/kernel_interface_handler.cpp | 3 ++- dataplane/kernel_interface_handler.h | 1 - dataplane/lpm.h | 3 --- dataplane/neighbor.h | 1 - dataplane/sdpserver.h | 4 +++- dataplane/slow_worker.cpp | 1 + dataplane/type.h | 2 -- dataplane/updater.h | 1 - dataplane/utils.h | 6 +----- dataplane/worker.cpp | 2 ++ dataplane/worker.h | 2 +- dataplane/worker_gc.cpp | 9 +++------ dataplane/worker_gc.h | 2 +- librib/libyabird.cpp | 1 - logger/main.cpp | 1 - unwind/unwind.cpp | 1 - 78 files changed, 54 insertions(+), 170 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 5fa3dddf..019ec4ae 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -20,6 +19,8 @@ #include "autotest.h" #include "common.h" +#include "common/sdpclient.h" + #define MAX_PACK_LEN 16384 #define SOCK_DEV_PREFIX "sock_dev:" diff --git a/autotest/autotest.h b/autotest/autotest.h index 40e26103..1725a16c 100644 --- a/autotest/autotest.h +++ b/autotest/autotest.h @@ -11,7 +11,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" #include "common/result.h" -#include "common/sdpclient.h" +#include "common/sdpcommon.h" namespace nAutotest { diff --git a/autotest/main.cpp b/autotest/main.cpp index eedeade2..c5bffded 100644 --- a/autotest/main.cpp +++ b/autotest/main.cpp @@ -1,6 +1,5 @@ #include -#include #include "common/result.h" diff --git a/cli/balancer.h b/cli/balancer.h index 5ca6b260..85b8af9a 100644 --- a/cli/balancer.h +++ b/cli/balancer.h @@ -1,7 +1,6 @@ #pragma once #include "common/icontrolplane.h" -#include "common/icp_proto.h" #include "common/idataplane.h" #include "common/iproto_controlplane.h" #include "common/type.h" diff --git a/cli/develop.h b/cli/develop.h index 5b099137..65dbd0ec 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -7,7 +7,6 @@ #include #include -#include "common/icontrolplane.h" #include "common/idataplane.h" #include "common/sdpclient.h" #include "common/tsc_deltas.h" diff --git a/common/acl.h b/common/acl.h index a775ccc6..ff959c42 100644 --- a/common/acl.h +++ b/common/acl.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "stream.h" #include "type.h" diff --git a/common/config.autotest.h b/common/config.autotest.h index 7a270049..5e87c725 100644 --- a/common/config.autotest.h +++ b/common/config.autotest.h @@ -1,3 +1,2 @@ -#include "config.release.h" #define CONFIG_YADECAP_AUTOTEST diff --git a/common/define.h b/common/define.h index 2f4986f2..48c0aa54 100644 --- a/common/define.h +++ b/common/define.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/common/icp_proto.h b/common/icp_proto.h index 0b68dd70..f8254b2b 100644 --- a/common/icp_proto.h +++ b/common/icp_proto.h @@ -1,6 +1,5 @@ #pragma once -#include "libprotobuf/controlplane.pb.h" namespace common::icp_proto { diff --git a/common/idp.h b/common/idp.h index aac44526..d07fe9b4 100644 --- a/common/idp.h +++ b/common/idp.h @@ -15,7 +15,6 @@ #include "acl.h" #include "balancer.h" #include "common/actions.h" -#include "config.h" #include "memory_manager.h" #include "neighbor.h" #include "result.h" diff --git a/common/sdpcommon.h b/common/sdpcommon.h index 9e2a9f35..0fda626d 100644 --- a/common/sdpcommon.h +++ b/common/sdpcommon.h @@ -6,9 +6,6 @@ #include "define.h" #include "idp.h" -#include "shared_memory.h" -#include "stream.h" -#include "type.h" // #define YANET_USE_POSIX_SHARED_MEMORY diff --git a/common/type.h b/common/type.h index a4f61350..23b0fab5 100644 --- a/common/type.h +++ b/common/type.h @@ -12,11 +12,11 @@ #include #include -#include "config.h" #include "ctree.h" #include "define.h" #include "stream.h" #include "uint128.h" +#include "config.release.h" using tCoreId = uint32_t; using tSocketId = uint32_t; diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index e486cc52..584307f4 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #ifdef ACL_DEBUG @@ -23,14 +22,10 @@ } #include "acl.h" -#include "acl/bitset.h" #include "acl/dict.h" -#include "acl/network.h" #include "acl/rule.h" #include "acl_compiler.h" -#include "common/acl.h" - namespace acl { diff --git a/controlplane/acl.h b/controlplane/acl.h index e3a73405..2822e3a0 100644 --- a/controlplane/acl.h +++ b/controlplane/acl.h @@ -3,6 +3,7 @@ #include #include "base.h" +#include "common/idp.h" namespace acl { diff --git a/controlplane/acl/dict.h b/controlplane/acl/dict.h index 90e1a393..ee023d79 100644 --- a/controlplane/acl/dict.h +++ b/controlplane/acl/dict.h @@ -1,6 +1,5 @@ #pragma once -#include "../acl.h" #include "bitset.h" #include "network.h" diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index 1b66b807..45a20c6f 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -8,7 +8,6 @@ #include #include "common/actions.h" -#include "libfwparser/fw_parser.h" #include "network.h" diff --git a/controlplane/acl_base.h b/controlplane/acl_base.h index 49931b13..b5446c36 100644 --- a/controlplane/acl_base.h +++ b/controlplane/acl_base.h @@ -1,10 +1,6 @@ #pragma once -#include -#include -#include - -#include +#include using tAclGroupId = uint32_t; diff --git a/controlplane/acl_flat.h b/controlplane/acl_flat.h index 9601bac3..de7e0bb8 100644 --- a/controlplane/acl_flat.h +++ b/controlplane/acl_flat.h @@ -1,6 +1,5 @@ #pragma once -#include "acl/bitset.h" #include "acl_base.h" #include "common/acl.h" diff --git a/controlplane/acl_network_table.h b/controlplane/acl_network_table.h index ac8a6470..b1e33695 100644 --- a/controlplane/acl_network_table.h +++ b/controlplane/acl_network_table.h @@ -1,6 +1,10 @@ #pragma once -#include "acl/bitset.h" +#include +#include +#include +#include + #include "acl_base.h" namespace acl::compiler diff --git a/controlplane/acl_table.h b/controlplane/acl_table.h index 281b712d..aa0d26e4 100644 --- a/controlplane/acl_table.h +++ b/controlplane/acl_table.h @@ -1,11 +1,7 @@ #pragma once -#include - -#include "acl/bitset.h" #include "acl_base.h" - -#include "common/acl.h" +#include "common/define.h" namespace acl::compiler { diff --git a/controlplane/acl_transport.cpp b/controlplane/acl_transport.cpp index 8eec12ed..6b2b159e 100644 --- a/controlplane/acl_transport.cpp +++ b/controlplane/acl_transport.cpp @@ -1,5 +1,4 @@ #include "acl_compiler.h" -#include "acl_network_table.h" using namespace acl::compiler; diff --git a/controlplane/acl_transport_table.h b/controlplane/acl_transport_table.h index caebf658..1064ec88 100644 --- a/controlplane/acl_transport_table.h +++ b/controlplane/acl_transport_table.h @@ -2,11 +2,9 @@ #include -#include "acl/bitset.h" #include "acl_base.h" #include "acl_table.h" -#include "common/acl.h" #include "common/idp.h" namespace acl::compiler diff --git a/controlplane/acl_tree.h b/controlplane/acl_tree.h index 8cb9a526..6d401740 100644 --- a/controlplane/acl_tree.h +++ b/controlplane/acl_tree.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "common/acl.h" namespace acl::compiler diff --git a/controlplane/balancer.h b/controlplane/balancer.h index f3bc4f2b..186cc26d 100644 --- a/controlplane/balancer.h +++ b/controlplane/balancer.h @@ -10,7 +10,6 @@ #include "common/generation.h" #include "common/icp.h" #include "common/idataplane.h" -#include "common/refarray.h" #include "libprotobuf/controlplane.pb.h" namespace balancer diff --git a/controlplane/base.h b/controlplane/base.h index 96702b3b..7f96a5e4 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -1,12 +1,11 @@ #pragma once -#include #include #include #include #include "common/controlplaneconfig.h" -#include "common/idp.h" +#include "common/memory_manager.h" #include "common/nat46clat.h" #include "common/type.h" #include "libfwparser/fw_parser.h" diff --git a/controlplane/bus.h b/controlplane/bus.h index e9c51494..5a458a9d 100644 --- a/controlplane/bus.h +++ b/controlplane/bus.h @@ -1,6 +1,5 @@ #pragma once -#include "common/icp.h" #include "module.h" diff --git a/controlplane/configconverter.cpp b/controlplane/configconverter.cpp index 4d32fe61..9a7c9987 100644 --- a/controlplane/configconverter.cpp +++ b/controlplane/configconverter.cpp @@ -6,10 +6,8 @@ #include #include "acl.h" -#include "configconverter.h" -#include "controlplane.h" #include "errors.h" -#include "isystem.h" +#include "configconverter.h" eResult config_converter_t::process(uint32_t serial) { diff --git a/controlplane/configconverter.h b/controlplane/configconverter.h index 443e3296..e1dc3467 100644 --- a/controlplane/configconverter.h +++ b/controlplane/configconverter.h @@ -3,6 +3,8 @@ #include #include "base.h" +#include "common/idp.h" +#include "common/result.h" class config_converter_t { diff --git a/controlplane/configparser.h b/controlplane/configparser.h index a24d4ebc..2b86dad8 100644 --- a/controlplane/configparser.h +++ b/controlplane/configparser.h @@ -1,11 +1,11 @@ #pragma once #include -#include #include "common/controlplaneconfig.h" #include "base.h" +#include "common/idp.h" class config_parser_t { diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index 9716cd88..a1abbdde 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -1,8 +1,5 @@ #pragma once -#include -#include -#include #include #include #include @@ -16,12 +13,7 @@ #include "common/idataplane.h" #include "common/idp.h" #include "common/result.h" -#include "common/sdpclient.h" -#include "libprotobuf/controlplane.pb.h" - #include "balancer.h" -#include "base.h" -#include "counter.h" #include "dregress.h" #include "durations.h" #include "fqdn.h" diff --git a/controlplane/counter.h b/controlplane/counter.h index 91d4770a..931dd55f 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -1,15 +1,10 @@ #pragma once #include -#include - -#include "segment_allocator.h" -#include "type.h" - #include "common/icp.h" -#include "common/idataplane.h" -#include "common/refarray.h" +#include "common/sdpcommon.h" #include "common/sdpclient.h" +#include "segment_allocator.h" class counter_manager_t { diff --git a/controlplane/dregress.h b/controlplane/dregress.h index 846b6352..96b62a5a 100644 --- a/controlplane/dregress.h +++ b/controlplane/dregress.h @@ -1,6 +1,7 @@ #pragma once #include "base.h" +#include "isystem.h" #include "module.h" #include "rib.h" #include "type.h" diff --git a/controlplane/durations.h b/controlplane/durations.h index a9df8bf9..8b64d3f6 100644 --- a/controlplane/durations.h +++ b/controlplane/durations.h @@ -2,9 +2,7 @@ #include -#include "base.h" #include "module.h" -#include "type.h" class durations_t : public module_t { diff --git a/controlplane/fqdn.h b/controlplane/fqdn.h index 373601a6..3b7f0071 100644 --- a/controlplane/fqdn.h +++ b/controlplane/fqdn.h @@ -1,7 +1,6 @@ #pragma once #include "base.h" -#include "counter.h" #include "module.h" #include "type.h" diff --git a/controlplane/isystem.cpp b/controlplane/isystem.cpp index e993f532..f96f5193 100644 --- a/controlplane/isystem.cpp +++ b/controlplane/isystem.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/controlplane/main.cpp b/controlplane/main.cpp index d5288f79..0928d401 100644 --- a/controlplane/main.cpp +++ b/controlplane/main.cpp @@ -1,7 +1,6 @@ #include #include -#include #include "controlplane.h" diff --git a/controlplane/nat64stateful.h b/controlplane/nat64stateful.h index c5be76c3..2b551200 100644 --- a/controlplane/nat64stateful.h +++ b/controlplane/nat64stateful.h @@ -10,7 +10,6 @@ #include "common/generation.h" #include "common/icp.h" #include "common/idataplane.h" -#include "common/refarray.h" namespace nat64stateful { diff --git a/controlplane/protobus.h b/controlplane/protobus.h index fe778de5..a9c2e100 100644 --- a/controlplane/protobus.h +++ b/controlplane/protobus.h @@ -1,6 +1,5 @@ #pragma once -#include "common/icp.h" #include "module.h" diff --git a/controlplane/rib.h b/controlplane/rib.h index 7bde0a4f..ccf5ea6a 100644 --- a/controlplane/rib.h +++ b/controlplane/rib.h @@ -1,22 +1,8 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/icp.h" -#include "common/idataplane.h" -#include "common/idp.h" - -#include "isystem.h" #include "module.h" -#include "type.h" +#include +#include namespace rib { diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 6b12cbc5..e7d3fd7c 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1,5 +1,7 @@ #include "route.h" +#include "common/icp.h" #include "controlplane.h" +#include "controlplane/route.h" uint32_t ExtractPeerIdFromPathInformation(const std::string& path_information) { diff --git a/controlplane/route.h b/controlplane/route.h index f75d7a3e..40b17dea 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -2,6 +2,7 @@ #include "base.h" #include "counter.h" +#include "isystem.h" #include "module.h" #include "rib.h" #include "type.h" diff --git a/controlplane/segment_allocator.h b/controlplane/segment_allocator.h index 3ab06bad..7000d473 100644 --- a/controlplane/segment_allocator.h +++ b/controlplane/segment_allocator.h @@ -4,7 +4,6 @@ #include #include -#include #define ENABLE_BIT(v, b) (v) |= ((uint64_t)1) << (b) #define GET_BIT(v, b) (((v) >> (b)) & 1) diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index 8432b7de..4b52a101 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "common/icp.h" #include "common/idataplane.h" diff --git a/controlplane/tun64.h b/controlplane/tun64.h index 9fd1bbe5..2ed76c07 100644 --- a/controlplane/tun64.h +++ b/controlplane/tun64.h @@ -9,7 +9,6 @@ #include "common/generation.h" #include "common/icp.h" #include "common/idataplane.h" -#include "common/refarray.h" namespace tun64 { diff --git a/controlplane/type.h b/controlplane/type.h index 1ba4e17e..11f00514 100644 --- a/controlplane/type.h +++ b/controlplane/type.h @@ -1,6 +1,5 @@ #pragma once -#include #include "common/type.h" diff --git a/controlplane/unittest/acl_flat.cpp b/controlplane/unittest/acl_flat.cpp index 13fdd65b..7f0072ea 100644 --- a/controlplane/unittest/acl_flat.cpp +++ b/controlplane/unittest/acl_flat.cpp @@ -1,5 +1,3 @@ -#include - #include #include diff --git a/controlplane/unittest/parser.cpp b/controlplane/unittest/parser.cpp index c07b9e62..4a2e1c71 100644 --- a/controlplane/unittest/parser.cpp +++ b/controlplane/unittest/parser.cpp @@ -1,6 +1,5 @@ #include -#include "common/type.h" #include "libfwparser/fw_parser.h" namespace diff --git a/dataplane/bus.h b/dataplane/bus.h index 1a43f223..acf699dc 100644 --- a/dataplane/bus.h +++ b/dataplane/bus.h @@ -1,19 +1,7 @@ #pragma once -#include - -#include -#include -#include -#include - -#include - -#include "common/idp.h" -#include "common/result.h" - -#include "sdpserver.h" -#include "type.h" +#include "common/sdpcommon.h" +#include "controlplane.h" class cBus { diff --git a/dataplane/checksum.h b/dataplane/checksum.h index caca7b9e..f9e9cae3 100644 --- a/dataplane/checksum.h +++ b/dataplane/checksum.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/dataplane/common.h b/dataplane/common.h index 2dca6b62..d38cb5e8 100644 --- a/dataplane/common.h +++ b/dataplane/common.h @@ -6,7 +6,7 @@ #include #include -#include "common/config.h" +#include "common/config.release.h" #include "common/define.h" #define YADECAP_UNUSED [[maybe_unused]] diff --git a/dataplane/config_values.h b/dataplane/config_values.h index 31711723..61256c4c 100644 --- a/dataplane/config_values.h +++ b/dataplane/config_values.h @@ -1,9 +1,9 @@ #pragma once +#include "common/config.release.h" #include #include -#include "common/config.h" struct FragmentationConfig { diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index d493091c..555c0e7d 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -9,22 +9,11 @@ #include #include -#include "common/fallback.h" -#include "common/idp.h" -#include "common/type.h" -#include "common/version.h" - -#include "checksum.h" #include "common.h" -#include "controlplane.h" +#include "common/version.h" #include "dataplane.h" +#include "dataplane/worker_gc.h" #include "debug_latch.h" -#include "icmp.h" -#include "icmp_translations.h" -#include "metadata.h" -#include "prepare.h" -#include "worker.h" -#include "worker_gc.h" cControlPlane::cControlPlane(cDataPlane* dataPlane) : dataPlane(dataPlane), diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 0949ee27..c981f5c7 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -15,14 +15,10 @@ #include "common/idp.h" #include "common/result.h" -#include "common/static_vector.h" -#include "common/type.h" -#include "dpdk.h" -#include "dregress.h" -#include "fragmentation.h" +#include "dataplane/dregress.h" +#include "dataplane/kernel_interface_handler.h" #include "kernel_interface_handle.h" -#include "slow_worker.h" #include "type.h" #include "utils.h" diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 6ff792b9..7d1c7d89 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -33,11 +33,9 @@ #include "common/idp.h" #include "common/result.h" #include "common/tsc_deltas.h" +#include "dataplane/sdpserver.h" #include "dataplane.h" -#include "debug_latch.h" #include "globalbase.h" -#include "lpm.h" -#include "report.h" #include "sock_dev.h" #include "work_runner.h" #include "worker.h" diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index e11b0f87..8b05af2d 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -26,7 +26,6 @@ #include "memory_manager.h" #include "neighbor.h" #include "report.h" -#include "sdpserver.h" #include "slow_worker.h" #include "type.h" diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index 0d04ec6f..b969ec15 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -1,7 +1,6 @@ #include #include -#include "common/fallback.h" #include "checksum.h" #include "dataplane.h" diff --git a/dataplane/dregress.h b/dataplane/dregress.h index 9a7b68ed..956f8aca 100644 --- a/dataplane/dregress.h +++ b/dataplane/dregress.h @@ -3,7 +3,6 @@ #include #include "common/btree.h" -#include "common/idp.h" #include "common/type.h" #include "hashtable.h" diff --git a/dataplane/dynamic_table.h b/dataplane/dynamic_table.h index a3eec75f..ce2e50e5 100644 --- a/dataplane/dynamic_table.h +++ b/dataplane/dynamic_table.h @@ -1,8 +1,6 @@ #pragma once -#include - -#include "common/config.h" +#include "common/config.release.h" #include "common/define.h" #include "common/result.h" diff --git a/dataplane/flat.h b/dataplane/flat.h index 5ff7c373..aba57ff1 100644 --- a/dataplane/flat.h +++ b/dataplane/flat.h @@ -1,6 +1,5 @@ #pragma once -#include #include diff --git a/dataplane/fragmentation.h b/dataplane/fragmentation.h index a6931f07..8c855a74 100644 --- a/dataplane/fragmentation.h +++ b/dataplane/fragmentation.h @@ -1,9 +1,6 @@ #pragma once -#include -#include -#include #include #include diff --git a/dataplane/icmp_translations.cpp b/dataplane/icmp_translations.cpp index 789d3497..b4ffb78a 100644 --- a/dataplane/icmp_translations.cpp +++ b/dataplane/icmp_translations.cpp @@ -1,4 +1,7 @@ +#include "checksum.h" +#include "dataplane/icmp.h" #include "icmp_translations.h" +#include "metadata.h" namespace dataplane { diff --git a/dataplane/icmp_translations.h b/dataplane/icmp_translations.h index 333701c5..f696d284 100644 --- a/dataplane/icmp_translations.h +++ b/dataplane/icmp_translations.h @@ -1,7 +1,6 @@ #include -#include "globalbase.h" -#include "icmp.h" +#include "type.h" namespace dataplane { @@ -10,4 +9,4 @@ bool do_icmp_translate_v6_to_v4(rte_mbuf* mbuf, bool do_icmp_translate_v4_to_v6(rte_mbuf* mbuf, const dataplane::globalBase::nat64stateless_translation_t& translation); -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/kernel_interface_handler.cpp b/dataplane/kernel_interface_handler.cpp index a8a06e4d..980f39a5 100644 --- a/dataplane/kernel_interface_handler.cpp +++ b/dataplane/kernel_interface_handler.cpp @@ -1,4 +1,5 @@ #include "kernel_interface_handler.h" +#include "metadata.h" namespace dataplane { @@ -251,4 +252,4 @@ void KernelInterfaceWorker::HandlePacketFromForwardingPlane(rte_mbuf* mbuf) stats_[i].odropped += delta.dropped; } -} // namespace dataplane \ No newline at end of file +} // namespace dataplane diff --git a/dataplane/kernel_interface_handler.h b/dataplane/kernel_interface_handler.h index 72f81766..c473983d 100644 --- a/dataplane/kernel_interface_handler.h +++ b/dataplane/kernel_interface_handler.h @@ -5,7 +5,6 @@ #include "base.h" #include "dpdk.h" -#include "metadata.h" namespace dataplane { diff --git a/dataplane/lpm.h b/dataplane/lpm.h index 2aa36418..f7ff96e3 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -1,9 +1,6 @@ #pragma once #include -#include -#include - #include #include #include diff --git a/dataplane/neighbor.h b/dataplane/neighbor.h index e163862b..554cda23 100644 --- a/dataplane/neighbor.h +++ b/dataplane/neighbor.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include diff --git a/dataplane/sdpserver.h b/dataplane/sdpserver.h index e224ee92..bebb8efa 100644 --- a/dataplane/sdpserver.h +++ b/dataplane/sdpserver.h @@ -1,8 +1,10 @@ #pragma once +#include + #include "common/result.h" #include "common/sdpcommon.h" -#include "type.h" +#include "common/shared_memory.h" namespace common::sdp { diff --git a/dataplane/slow_worker.cpp b/dataplane/slow_worker.cpp index 1778d564..1a3eccd8 100644 --- a/dataplane/slow_worker.cpp +++ b/dataplane/slow_worker.cpp @@ -1,5 +1,6 @@ #include "slow_worker.h" +#include "checksum.h" #include "common/fallback.h" #include "dataplane.h" #include "icmp_translations.h" diff --git a/dataplane/type.h b/dataplane/type.h index 07ee110c..e318eada 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -1,10 +1,8 @@ #pragma once -#include #include #include "common/balancer.h" -#include "common/config.h" #include "common/scheduler.h" #include "common/type.h" diff --git a/dataplane/updater.h b/dataplane/updater.h index ca839215..b3b0dc04 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/dataplane/utils.h b/dataplane/utils.h index d8e8afae..8b713712 100644 --- a/dataplane/utils.h +++ b/dataplane/utils.h @@ -3,10 +3,6 @@ #include -#include "common/config.h" -#include "common/define.h" -#include "common/type.h" -#include "dpdk.h" #include "metadata.h" namespace utils @@ -62,4 +58,4 @@ class Sequential } }; -} // namespace utils \ No newline at end of file +} // namespace utils diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 3bb517ca..88f3f720 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -21,6 +21,8 @@ #include "common/fallback.h" #include "common/nat46clat.h" +#include "dataplane/sdpserver.h" + #include "action_dispatcher.h" #include "checksum.h" #include "common.h" diff --git a/dataplane/worker.h b/dataplane/worker.h index 546b06ff..d75176a4 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -9,6 +9,7 @@ #include #include "common/result.h" +#include "common/sdpcommon.h" #include "common/tsc_deltas.h" #include "common/type.h" @@ -16,7 +17,6 @@ #include "common.h" #include "globalbase.h" #include "samples.h" -#include "sdpserver.h" #include "sharedmemory.h" namespace dataplane diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index ea96e779..936ccd64 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -1,14 +1,11 @@ -#include - #include #include #include "common/counters.h" #include "common/fallback.h" - -#include "dataplane.h" -#include "worker.h" -#include "worker_gc.h" +#include "dataplane/globalbase.h" +#include "dataplane/sdpserver.h" +#include "dataplane/worker_gc.h" worker_gc_t::worker_gc_t(const ConfigValues& cfg, const PortToSocketArray& pts, SamplersVector&& samplers) : mempool(nullptr), diff --git a/dataplane/worker_gc.h b/dataplane/worker_gc.h index 476eb699..074fb6df 100644 --- a/dataplane/worker_gc.h +++ b/dataplane/worker_gc.h @@ -5,6 +5,7 @@ #include "base.h" #include "common.h" +#include "common/sdpcommon.h" #include "config_values.h" #include "hashtable.h" #include "samples.h" @@ -14,7 +15,6 @@ #include "common/idp.h" #include "common/static_vector.h" #include "hashtable.h" -#include "sdpserver.h" class worker_gc_t { diff --git a/librib/libyabird.cpp b/librib/libyabird.cpp index 538c2efc..04767c88 100644 --- a/librib/libyabird.cpp +++ b/librib/libyabird.cpp @@ -7,7 +7,6 @@ #include "common/define.h" #include "common/icontrolplane.h" -#include "common/result.h" #include "common/type.h" #include "libyabird.h" diff --git a/logger/main.cpp b/logger/main.cpp index 564b0590..daee890e 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -11,7 +11,6 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" -#include "common/result.h" #include "common/type.h" #include "dataplane/samples.h" diff --git a/unwind/unwind.cpp b/unwind/unwind.cpp index 0566628d..8bac5586 100644 --- a/unwind/unwind.cpp +++ b/unwind/unwind.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include From 9ab9c52c8ed2f404ffc5ca7d897223f037193809 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 24 Sep 2024 20:40:58 +0400 Subject: [PATCH 149/195] Add 'config.h' to common/idp.h This include is not used in common/idp.h... I don't know what's going on, but without it checksum calculation breaks in the testsUpdate common/idp.h --- common/idp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/idp.h b/common/idp.h index d07fe9b4..aac44526 100644 --- a/common/idp.h +++ b/common/idp.h @@ -15,6 +15,7 @@ #include "acl.h" #include "balancer.h" #include "common/actions.h" +#include "config.h" #include "memory_manager.h" #include "neighbor.h" #include "result.h" From bf6bf72c8a5cb66b6b9d0ed0d7c19c551bcdce0b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 25 Sep 2024 13:48:28 +0400 Subject: [PATCH 150/195] Fix usage of deprecated C++ headers like 'signal.h' or 'stdio.h' One should consider using 'csignal'/'cstdio' instead. Also we should use cstdint instead of inttypes.h for fixed-size types --- autotest/autotest.cpp | 2 +- autotest/main.cpp | 2 +- common/balancer.h | 2 +- common/define.h | 2 +- common/idp.h | 1 - common/neighbor.h | 2 +- common/result.h | 3 ++- common/scheduler.h | 2 +- common/sendrecv.h | 2 +- common/shared_memory.h | 2 +- common/stream.h | 1 - common/type.h | 1 - controlplane/isystem.cpp | 6 +++--- controlplane/main.cpp | 2 +- controlplane/protobus.cpp | 1 - dataplane/dataplane.cpp | 6 +++--- dataplane/main.cpp | 2 +- logger/main.cpp | 2 +- 18 files changed, 19 insertions(+), 22 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 019ec4ae..d456c587 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/autotest/main.cpp b/autotest/main.cpp index c5bffded..2c8df810 100644 --- a/autotest/main.cpp +++ b/autotest/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include "common/result.h" diff --git a/common/balancer.h b/common/balancer.h index 132f5c1d..4b032527 100644 --- a/common/balancer.h +++ b/common/balancer.h @@ -1,7 +1,7 @@ #pragma once -#include +#include namespace balancer { diff --git a/common/define.h b/common/define.h index 48c0aa54..4cb9831b 100644 --- a/common/define.h +++ b/common/define.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -8,7 +9,6 @@ #include #include -#include #define YANET_UNUSED [[maybe_unused]] diff --git a/common/idp.h b/common/idp.h index aac44526..83831459 100644 --- a/common/idp.h +++ b/common/idp.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/common/neighbor.h b/common/neighbor.h index 01032091..d6e306ee 100644 --- a/common/neighbor.h +++ b/common/neighbor.h @@ -1,7 +1,7 @@ #pragma once -#include +#include namespace common::neighbor { diff --git a/common/result.h b/common/result.h index d4d5b1cc..0f932ec8 100644 --- a/common/result.h +++ b/common/result.h @@ -1,6 +1,7 @@ #pragma once -#include + +#include namespace common { diff --git a/common/scheduler.h b/common/scheduler.h index 6ef48956..f02c745f 100644 --- a/common/scheduler.h +++ b/common/scheduler.h @@ -1,7 +1,7 @@ #pragma once -#include +#include namespace balancer { diff --git a/common/sendrecv.h b/common/sendrecv.h index 6054d061..d2a4963a 100644 --- a/common/sendrecv.h +++ b/common/sendrecv.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/common/shared_memory.h b/common/shared_memory.h index 20f03f61..c465c4c6 100644 --- a/common/shared_memory.h +++ b/common/shared_memory.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/common/stream.h b/common/stream.h index 623dc503..4f882547 100644 --- a/common/stream.h +++ b/common/stream.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/common/type.h b/common/type.h index 23b0fab5..d147ad48 100644 --- a/common/type.h +++ b/common/type.h @@ -8,7 +8,6 @@ #include #include -#include #include #include diff --git a/controlplane/isystem.cpp b/controlplane/isystem.cpp index f96f5193..b0fc7e76 100644 --- a/controlplane/isystem.cpp +++ b/controlplane/isystem.cpp @@ -4,9 +4,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/controlplane/main.cpp b/controlplane/main.cpp index 0928d401..82af705d 100644 --- a/controlplane/main.cpp +++ b/controlplane/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include diff --git a/controlplane/protobus.cpp b/controlplane/protobus.cpp index 71b4d518..79b37f43 100644 --- a/controlplane/protobus.cpp +++ b/controlplane/protobus.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 7d1c7d89..6fbfa0c1 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #include #include "common.h" diff --git a/dataplane/main.cpp b/dataplane/main.cpp index af754505..ec0bba7f 100644 --- a/dataplane/main.cpp +++ b/dataplane/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/logger/main.cpp b/logger/main.cpp index daee890e..bb316421 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include From 7089c742c307a5918b0c25279a5e1d69fe935ba7 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 25 Sep 2024 13:58:09 +0400 Subject: [PATCH 151/195] Escaped string literal can be written as a raw string literal --- cli/show.h | 8 ++++---- logger/main.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cli/show.h b/cli/show.h index 6de4f7ca..9da7fb83 100644 --- a/cli/show.h +++ b/cli/show.h @@ -693,12 +693,12 @@ inline void samples_dump() } first = false; std::cout << "\n" - << "{\"in_iface\":\"" << in_iface << "\"," - << "\"out_iface\":\"" << out_iface << "\"," + << R"({"in_iface":")" << in_iface << "\"," + << R"("out_iface":")" << out_iface << "\"," << "\"proto\":" << (int)proto << "," - << "\"src_addr\":\"" << src_addr.toString() << "\"," + << R"("src_addr":")" << src_addr.toString() << "\"," << "\"src_port\":" << src_port << "," - << "\"dst_addr\":\"" << dst_addr.toString() << "\"," + << R"("dst_addr":")" << dst_addr.toString() << "\"," << "\"dst_port\":" << dst_port << "}"; } diff --git a/logger/main.cpp b/logger/main.cpp index bb316421..38b30422 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -168,14 +168,14 @@ int runLogger() } std::cout << "{" - << "\"action\":\"" << common::globalBase::eFlowType_toString(sample->action) << "\"," + << R"("action":")" << common::globalBase::eFlowType_toString(sample->action) << "\"," << "\"rule_ids\":[" << rule_ids << "]," << "\"direction\":" << (direction ? "\"in\"" : "\"out\"") << "," - << "\"iface\":\"" << iface << "\"," + << R"("iface":")" << iface << "\"," << "\"proto\":" << (int)sample->proto << "," - << "\"src_addr\":\"" << src_addr.toString() << "\"," + << R"("src_addr":")" << src_addr.toString() << "\"," << "\"src_port\":" << sample->src_port << "," - << "\"dst_addr\":\"" << dst_addr.toString() << "\"," + << R"("dst_addr":")" << dst_addr.toString() << "\"," << "\"dst_port\":" << sample->dst_port << "}\n"; rte_mempool_put(mempool, sample); From 07f3977441303ddf105604d1fd9a9c3734e682af Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 25 Sep 2024 14:04:29 +0400 Subject: [PATCH 152/195] Use [[maybe_unused]] instead of YANET_UNUSED This macro will be used to mark structured bindings due to bug in gcc (See next commit). For unused functions, we can just stick with a regular one --- common/controlplaneconfig.h | 4 ++-- controlplane/telegraf.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/controlplaneconfig.h b/common/controlplaneconfig.h index 0bcce0f7..0b2a9bab 100644 --- a/common/controlplaneconfig.h +++ b/common/controlplaneconfig.h @@ -250,7 +250,7 @@ class config_t namespace balancer { -YANET_UNUSED +[[maybe_unused]] static uint8_t to_proto(const std::string& string) { if (string == "tcp") @@ -265,7 +265,7 @@ static uint8_t to_proto(const std::string& string) return 0; } -YANET_UNUSED +[[maybe_unused]] constexpr const char* from_proto(const uint8_t& proto) { switch (proto) diff --git a/controlplane/telegraf.cpp b/controlplane/telegraf.cpp index 4574619e..f6c34799 100644 --- a/controlplane/telegraf.cpp +++ b/controlplane/telegraf.cpp @@ -4,7 +4,7 @@ using common::int64; using controlplane::module::telegraf; -YANET_UNUSED +[[maybe_unused]] static inline double perSecond(const int64_t& valueDiff, const uint64_t& timeDiff) { if (timeDiff == 0) From 01422b7a7fd6787dfb44288a08c17d6a74d70811 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Wed, 25 Sep 2024 18:54:52 +0400 Subject: [PATCH 153/195] Mark unused structured bindings with YANET_GCC_BUG_UNUSED instead of void cast GCC 7.5 version which we have to support for now due to Ubuntu 18 have a bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81767) where unused variables in structured bindings are incorrectly flagged as warnings, even though they "can't" be used, cause they are not a real variables. Current code uses `(void)var;` to suppress these warnings, but this approach is ugly and harder to grep. This commit removes `(void)var;` statements and replaces it with `YANET_GCC_BUG_UNUSED` Once we move to a newer GCC version where this bug is fixed, we can easily remove the that macro as it is much easier to grep and remove than those void(var) statements --- autotest/autotest.cpp | 6 +- cli/balancer.h | 10 +-- cli/bus.h | 6 +- cli/config.cpp | 4 +- cli/develop.h | 2 +- cli/main.cpp | 2 +- cli/memory_manager.h | 4 +- cli/rib.h | 2 +- cli/route.h | 4 +- cli/show.h | 2 +- cli/telegraf.h | 18 ++--- common/ctree.h | 8 +-- common/define.h | 17 ++++- common/refarray.h | 6 +- controlplane/acl.cpp | 4 +- controlplane/acl/rule.h | 8 +-- controlplane/acl_transport.cpp | 2 +- controlplane/acl_tree.h | 12 ++-- controlplane/balancer.cpp | 110 ++++++++++++++-------------- controlplane/configconverter.cpp | 118 +++++++++++++++---------------- controlplane/configparser.cpp | 18 ++--- controlplane/controlplane.cpp | 8 +-- controlplane/controlplane.h | 4 +- controlplane/counter.h | 8 +-- controlplane/dregress.cpp | 10 +-- controlplane/dregress.h | 4 +- controlplane/fqdn.h | 2 +- controlplane/nat46clat.cpp | 4 +- controlplane/nat64stateful.cpp | 4 +- controlplane/rib.cpp | 36 +++++----- controlplane/route.cpp | 116 +++++++++++++++--------------- controlplane/route.h | 2 +- controlplane/telegraf.cpp | 6 +- controlplane/telegraf.h | 4 +- controlplane/tun64.cpp | 6 +- dataplane/controlplane.cpp | 40 +++++------ dataplane/dataplane.cpp | 28 ++++---- dataplane/dregress.cpp | 20 +++--- dataplane/fragmentation.cpp | 18 ++--- dataplane/globalbase.cpp | 4 +- dataplane/lpm.h | 10 +-- dataplane/memory_manager.cpp | 4 +- dataplane/neighbor.cpp | 18 ++--- dataplane/report.cpp | 2 +- dataplane/slow_worker.cpp | 4 +- libfwparser/fw_config.cpp | 6 +- logger/main.cpp | 2 +- parser/fw_dump.cpp | 12 ++-- 48 files changed, 380 insertions(+), 365 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index d456c587..86eb3d6d 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -62,7 +62,7 @@ eResult tAutotest::init(const std::string& binaryPath, bool dumpPackets, const std::vector& configFilePaths) { - (void)binaryPath; + YANET_GCC_BUG_UNUSED(binaryPath); this->dumpPackets = dumpPackets; this->configFilePaths = configFilePaths; @@ -871,10 +871,10 @@ bool tAutotest::step_checkCounters(const YAML::Node& yamlStep) auto fwList = controlPlane.getFwList(common::icp::getFwList::requestType::static_rules_original); for (auto& [ruleno, rules] : fwList) { - (void)ruleno; + YANET_GCC_BUG_UNUSED(ruleno); for (auto& [id, counter, text] : rules) { - (void)text; + YANET_GCC_BUG_UNUSED(text); counters[id] = counter; } } diff --git a/cli/balancer.h b/cli/balancer.h index 85b8af9a..bbf3421b 100644 --- a/cli/balancer.h +++ b/cli/balancer.h @@ -85,7 +85,7 @@ void service(std::string module_string, { const auto& [virtual_ip, proto, virtual_port] = service_key; const auto& [scheduler, version, nap_connections, packets, bytes] = service_value; - (void)nap_connections; ///< @todo: DELETE + YANET_GCC_BUG_UNUSED(nap_connections); ///< @todo: DELETE auto proto_string = controlplane::balancer::from_proto(proto); @@ -97,7 +97,7 @@ void service(std::string module_string, uint32_t connections = 0; for (auto& [socket_id, service_connections] : balancer_service_connections) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); const auto& socket_connections = service_connections[key].value; if (socket_connections > connections) @@ -238,7 +238,7 @@ void real_find(std::string module_string, uint32_t connections = 0; for (auto& [socket_id, real_connections] : balancer_real_connections) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); const auto& socket_connections = real_connections[key].value; if (socket_connections > connections) @@ -320,7 +320,7 @@ void state(std::string module, /// @todo: OPT for (const auto& [socket_id, services_real_connections] : response) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); for (const auto& [services_real, connections] : services_real_connections) { @@ -330,7 +330,7 @@ void state(std::string module, for (const auto& [client_ip, client_port, timestamp_create, timestamp_last_packet, timestamp_gc] : connections) { - (void)timestamp_gc; + YANET_GCC_BUG_UNUSED(timestamp_gc); auto it = map.find({client_ip, client_port}); if (it != map.end()) diff --git a/cli/bus.h b/cli/bus.h index e26c2456..74480be8 100644 --- a/cli/bus.h +++ b/cli/bus.h @@ -11,7 +11,7 @@ using bus_request_info = std::tuple; inline std::vector get_bus_requests(common::sdp::DataPlaneInSharedMemory& sdp_data) { auto [requests, errors, durations] = sdp_data.BuffersBus(); - (void)errors; + YANET_GCC_BUG_UNUSED(errors); std::map names = { {common::idp::requestType::updateGlobalBase, "updateGlobalBase"}, @@ -94,8 +94,8 @@ inline void bus_requests() inline std::vector> get_bus_errors(const common::sdp::DataPlaneInSharedMemory& sdp_data) { auto [requests, errors, durations] = sdp_data.BuffersBus(); - (void)requests; - (void)durations; + YANET_GCC_BUG_UNUSED(requests); + YANET_GCC_BUG_UNUSED(durations); std::map names = { {common::idp::errorType::busRead, "busRead"}, diff --git a/cli/config.cpp b/cli/config.cpp index 5b4ffe6f..6e9aa403 100644 --- a/cli/config.cpp +++ b/cli/config.cpp @@ -366,7 +366,7 @@ void allow(const std::string& module, checkModuleType(decap, "decap"); const auto& [prefixes, inserted] = decap.emplace("ipv6DestinationPrefixes", nlohmann::json::array_t{}); - (void)inserted; + YANET_GCC_BUG_UNUSED(inserted); if (allowPrefix(*prefixes, prefixRaw, announceRaw)) { @@ -436,7 +436,7 @@ static void allowAny(const std::string& module, checkModuleType(nat64, "nat64stateless"); const auto& [prefixes, inserted] = nat64.emplace("nat64_prefixes", nlohmann::json::array_t{}); - (void)inserted; + YANET_GCC_BUG_UNUSED(inserted); if (allowPrefix(*prefixes, prefixRaw, announceRaw)) { diff --git a/cli/develop.h b/cli/develop.h index 65dbd0ec..beb7e46a 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -179,7 +179,7 @@ class tsc_monitoring_t for (const auto& [core, socket, ipc_key, offset] : response) { - (void)socket; + YANET_GCC_BUG_UNUSED(socket); if (ipc_cache.find(ipc_key) == ipc_cache.end()) { auto shmid = shmget(ipc_key, 0, 0); diff --git a/cli/main.cpp b/cli/main.cpp index 0cd2acb3..73a1cca8 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -153,7 +153,7 @@ void printUsage() printf("usage:\n"); for (const auto& [command, args, function] : commands) { - (void)function; + YANET_GCC_BUG_UNUSED(function); if (command.empty()) { diff --git a/cli/memory_manager.h b/cli/memory_manager.h index 95d4a677..7d6a33e0 100644 --- a/cli/memory_manager.h +++ b/cli/memory_manager.h @@ -12,7 +12,7 @@ void show() const auto response = dataplane.memory_manager_stats(); const auto& [response_memory_group, response_objects] = response; - (void)response_memory_group; + YANET_GCC_BUG_UNUSED(response_memory_group); table_t table; table.insert("name", @@ -55,7 +55,7 @@ void group() for (const auto& [name, socket_id, current] : response_objects) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); currents[name] = std::max(currents[name].value, current); diff --git a/cli/rib.h b/cli/rib.h index aeb8880c..3fdcf7d0 100644 --- a/cli/rib.h +++ b/cli/rib.h @@ -185,7 +185,7 @@ void get(const std::string& vrf, { const auto& [protocol, peer, table_name, path_information] = nexthop_key; const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = nexthop_value; - (void)prefix; + YANET_GCC_BUG_UNUSED(prefix); table.insert(vrf, priority, diff --git a/cli/route.h b/cli/route.h index c398db1d..d809351c 100644 --- a/cli/route.h +++ b/cli/route.h @@ -102,7 +102,7 @@ void get(const std::string& route_name, for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, egress_interface, labels] = item; - (void)prefix; + YANET_GCC_BUG_UNUSED(prefix); table.insert(ingress_physical_ports, nexthop.is_default() ? std::string("") : nexthop.toString(), @@ -190,7 +190,7 @@ void get(const std::string& route_name, for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, label, egress_interface, peer, weight_percent] = item; - (void)prefix; + YANET_GCC_BUG_UNUSED(prefix); double percent = (double)100.0 * weight_percent; diff --git a/cli/show.h b/cli/show.h index 9da7fb83..0717b0ea 100644 --- a/cli/show.h +++ b/cli/show.h @@ -578,7 +578,7 @@ static void list_fw_rules(unsigned int mask, bool list) { if (list) { - (void)counter; + YANET_GCC_BUG_UNUSED(counter); table.insert(id, ruleno, label, text); } else diff --git a/cli/telegraf.h b/cli/telegraf.h index 482d8daa..46520abd 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -27,8 +27,8 @@ void ports_stats() { interface::dataPlane dataplane; const auto [ports_cfg, cores_cfg, values] = dataplane.getConfig(); - (void)cores_cfg; - (void)values; + YANET_GCC_BUG_UNUSED(cores_cfg); + YANET_GCC_BUG_UNUSED(values); const std::vector> ports_stats_per_type{ {"port", dataplane.get_ports_stats()}, @@ -40,9 +40,9 @@ void ports_stats() for (const auto& [port_id, stats] : ports_stats) { const auto& [interface_name, socket_id, eth_addr, pci] = ports_cfg.at(port_id); - (void)socket_id; - (void)eth_addr; - (void)pci; + YANET_GCC_BUG_UNUSED(socket_id); + YANET_GCC_BUG_UNUSED(eth_addr); + YANET_GCC_BUG_UNUSED(pci); const auto& [rx_packets, rx_bytes, rx_errors, rx_drops, tx_packets, tx_bytes, tx_errors, tx_drops] = stats; printf("%s,physicalPortName=%s " @@ -453,7 +453,7 @@ void dregress() std::map communities; for (const auto& [community, peer_link_orig] : communities_orig) { - (void)peer_link_orig; + YANET_GCC_BUG_UNUSED(peer_link_orig); uint32_t link_id = 0; @@ -588,7 +588,7 @@ void other() const auto& [flagFirst, workers, ports] = controlPlane.telegraf_other(); const auto rib_summary = controlPlane.rib_summary(); const auto limit_summary = controlPlane.limit_summary(); - (void)flagFirst; + YANET_GCC_BUG_UNUSED(flagFirst); for (const auto& workerIter : workers) { @@ -667,7 +667,7 @@ void service() for (const auto& [virtual_ip, proto, virtual_port, nap_connections, packets, bytes, real_disabled_packets, real_disabled_bytes] : services) { - (void)nap_connections; + YANET_GCC_BUG_UNUSED(nap_connections); common::idp::balancer_service_connections::service_key_t key = {module_id, virtual_ip, @@ -677,7 +677,7 @@ void service() uint32_t connections = 0; for (auto& [socket_id, service_connections] : balancer_service_connections) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); const auto& socket_connections = service_connections[key].value; if (socket_connections > connections) diff --git a/common/ctree.h b/common/ctree.h index eeb8c975..61899b4e 100644 --- a/common/ctree.h +++ b/common/ctree.h @@ -146,8 +146,8 @@ struct ctree const std::vector& key_names, const std::function& callback) const { - (void)key_index; - (void)key_names; + YANET_GCC_BUG_UNUSED(key_index); + YANET_GCC_BUG_UNUSED(key_names); callback(key, values); } @@ -195,7 +195,7 @@ struct ctree { for (auto& [next_counter, next_node] : next) { - (void)next_counter; + YANET_GCC_BUG_UNUSED(next_counter); delete next_node; } } @@ -271,7 +271,7 @@ struct ctree { for (const auto& [next_counter, next_node] : next) { - (void)next_counter; + YANET_GCC_BUG_UNUSED(next_counter); static_cast*>(next_node)->convert_update(next_converts...); } } diff --git a/common/define.h b/common/define.h index 4cb9831b..337ccbcc 100644 --- a/common/define.h +++ b/common/define.h @@ -10,7 +10,22 @@ #include -#define YANET_UNUSED [[maybe_unused]] +/** + * GCC 7.5 version which we have to support for now due to Ubuntu 18 have a bug + * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81767) where unused variables + * in structured bindings are incorrectly flagged as warnings, even though + * they "can't" be used, cause they are not a real variables. + * + * Previously, code used `(void)var;` to suppress these warnings, but this + * approach was ugly and harder to grep. + * + * One should use this macro in structured bindings to mark unused bunding. + * + * Once we move to a newer GCC version where this bug is fixed, + * we can easily remove this macro as it is much easier to grep and remove + * than those void(var) statements. + */ +#define YANET_GCC_BUG_UNUSED(arg) (void)(arg) #define YANET_LOG_PRINT(msg, args...) fprintf(stdout, msg, ##args) diff --git a/common/refarray.h b/common/refarray.h index e73191be..ea779bb4 100644 --- a/common/refarray.h +++ b/common/refarray.h @@ -41,7 +41,7 @@ class refarray_t } auto& [refcount, id] = it->second; - (void)id; + YANET_GCC_BUG_UNUSED(id); refcount++; @@ -106,7 +106,7 @@ class refarray_t const auto& value = it->second; auto& [refcount, values_id] = values[value]; - (void)values_id; + YANET_GCC_BUG_UNUSED(values_id); refcount--; if (refcount) @@ -162,7 +162,7 @@ class refarray_t auto it = values.find(value); const auto& [refcount, id] = it->second; - (void)refcount; + YANET_GCC_BUG_UNUSED(refcount); return id; } diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 584307f4..43b1e449 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -527,10 +527,10 @@ iface_map_t ifaceMapping(std::mapruleid); for (const auto& [name, how] : rulep->ifaces) { - (void)how; // XXX: we can use in/out filters + YANET_GCC_BUG_UNUSED(how); // XXX: we can use in/out filters via.insert(name); } for (const auto& [direction, tables] : rulep->iface_tables) { - (void)direction; // XXX: we can use in/out filters + YANET_GCC_BUG_UNUSED(direction); // XXX: we can use in/out filters for (const auto& tablename : tables) { if (configp->m_tables.count(tablename) == 0) @@ -1133,7 +1133,7 @@ struct rule_t const auto& ifnames = std::get(table); for (const auto& [iface, label] : ifnames) { - (void)label; + YANET_GCC_BUG_UNUSED(label); via.insert(iface); } } @@ -1141,7 +1141,7 @@ struct rule_t { YANET_LOG_WARNING("wrong type for interface table %s\n", tablename.data()); } - (void)location; + YANET_GCC_BUG_UNUSED(location); } } } diff --git a/controlplane/acl_transport.cpp b/controlplane/acl_transport.cpp index 6b2b159e..840b074b 100644 --- a/controlplane/acl_transport.cpp +++ b/controlplane/acl_transport.cpp @@ -63,7 +63,7 @@ void transport_t::distribute() for (const auto& [key, network_table_group_ids] : variation) { const auto& [size, filter_ids] = key; - (void)size; + YANET_GCC_BUG_UNUSED(size); unsigned int best_layer_id = 0; auto best_filter_ids_count = (size_t)-1; diff --git a/controlplane/acl_tree.h b/controlplane/acl_tree.h index 6d401740..90c78b78 100644 --- a/controlplane/acl_tree.h +++ b/controlplane/acl_tree.h @@ -165,7 +165,7 @@ class tree_t { for (const auto& [gap_size, address, mask] : prefixes) { - (void)gap_size; + YANET_GCC_BUG_UNUSED(gap_size); if (is_mask_gapped(mask)) { @@ -176,7 +176,7 @@ class tree_t for (const auto& [gap_size, address, mask] : prefixes) { - (void)gap_size; + YANET_GCC_BUG_UNUSED(gap_size); if (!is_mask_gapped(mask)) { @@ -270,7 +270,7 @@ class tree_t { const auto& [warp_address, warp_mask] = map_key; const auto& [shift, warp_chunk_id] = map_value; - (void)shift; + YANET_GCC_BUG_UNUSED(shift); std::set last_multirefs_chunk_ids; get_last_gapped_chunks_step(warp_address, warp_mask, last_multirefs_chunk_ids, root_chunk_id); @@ -512,7 +512,7 @@ class tree_t { const auto& [prev_address, prev_mask] = key; const auto& [prev_shift, prev_warp_chunk_id] = value; - (void)prev_warp_chunk_id; + YANET_GCC_BUG_UNUSED(prev_warp_chunk_id); type_t shared_shadow_mask = warp_shadow_mask & (prev_mask & (prev_mask + 1)); @@ -569,8 +569,8 @@ class tree_t const auto& [warp_address, warp_mask] = map_key; const auto& [shift, warp_chunk_id] = map_value; - (void)shift; - (void)warp_chunk_id; + YANET_GCC_BUG_UNUSED(shift); + YANET_GCC_BUG_UNUSED(warp_chunk_id); type_t warp_shadow_mask = warp_mask & (warp_mask + 1); diff --git a/controlplane/balancer.cpp b/controlplane/balancer.cpp index 88a2dc0e..9073cb6b 100644 --- a/controlplane/balancer.cpp +++ b/controlplane/balancer.cpp @@ -241,21 +241,21 @@ void balancer_t::reload(const controlplane::base_t& base_prev, ipv6_outer_source_network, reals] : balancer.services) { - (void)service_id; - (void)version; - (void)scheduler; - (void)scheduler_params; - (void)reals; - (void)flags; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(service_id); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(reals); + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); service_counters.remove({module_name, {virtual_ip, proto, virtual_port}}); for (const auto& [real_ip, real_port, real_weight] : reals) { - (void)real_weight; + YANET_GCC_BUG_UNUSED(real_weight); const std::tuple filtered_reals; for (auto& [real_ip, real_port, enabled, weight, connections, packets, bytes] : response_reals) { - (void)connections; ///< @todo: DELETE - (void)packets; - (void)bytes; + YANET_GCC_BUG_UNUSED(connections); ///< @todo: DELETE + YANET_GCC_BUG_UNUSED(packets); + YANET_GCC_BUG_UNUSED(bytes); if (filter_real_ip && real_ip != *filter_real_ip) @@ -668,11 +668,11 @@ void balancer_t::update_service(const balancer::generation_config_t& generation_ ipv6_outer_source_network, reals] : balancer.services) { - (void)flags; - (void)scheduler_params; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (service_id >= YANET_CONFIG_BALANCER_SERVICES_SIZE) { @@ -684,9 +684,9 @@ void balancer_t::update_service(const balancer::generation_config_t& generation_ auto& [service_scheduler, service_version, service_connections, service_packets, service_bytes] = generation_services.services[{balancer.balancer_id, module_name}][{virtual_ip, proto, virtual_port}]; service_scheduler = to_string(scheduler); ///< @todo: OPT service_version = version; - (void)service_connections; ///< @todo: DELETE - (void)service_packets; ///< filled in request - (void)service_bytes; ///< filled in request + YANET_GCC_BUG_UNUSED(service_connections); ///< @todo: DELETE + YANET_GCC_BUG_UNUSED(service_packets); ///< filled in request + YANET_GCC_BUG_UNUSED(service_bytes); ///< filled in request auto& [reals_service_scheduler, reals_version, service_reals] = generation_services.reals[{balancer.balancer_id, module_name}][{virtual_ip, proto, virtual_port}]; reals_service_scheduler = service_scheduler; @@ -764,8 +764,8 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, ipv6_outer_source_network, reals] : balancer.services) { - (void)scheduler_params; - (void)version; + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(version); if (service_id >= YANET_CONFIG_BALANCER_SERVICES_SIZE) { @@ -776,7 +776,7 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, for (const auto& [real_ip, real_port, weight] : reals) { - (void)weight; + YANET_GCC_BUG_UNUSED(weight); balancer::real_key_global_t key = {module_name, {virtual_ip, proto, virtual_port}, {real_ip, real_port}}; @@ -849,13 +849,13 @@ void balancer_t::flush_reals(common::idp::updateGlobalBaseBalancer::request& bal ipv6_outer_source_network, reals] : balancer.services) { - (void)flags; - (void)scheduler; - (void)scheduler_params; - (void)version; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (service_id >= YANET_CONFIG_BALANCER_SERVICES_SIZE) { diff --git a/controlplane/configconverter.cpp b/controlplane/configconverter.cpp index 9a7c9987..c3bd76a1 100644 --- a/controlplane/configconverter.cpp +++ b/controlplane/configconverter.cpp @@ -337,7 +337,7 @@ void config_converter_t::processLogicalPorts() { for (auto& [moduleName, logicalPort] : baseNext.logicalPorts) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (logicalPort.logicalPortId >= CONFIG_YADECAP_LOGICALPORTS_SIZE) { @@ -365,7 +365,7 @@ void config_converter_t::serializeLogicalPorts() { for (auto& [moduleName, logicalPort] : baseNext.logicalPorts) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); globalbase.emplace_back(common::idp::updateGlobalBase::requestType::updateLogicalPort, common::idp::updateGlobalBase::updateLogicalPort::request{logicalPort.logicalPortId, @@ -381,7 +381,7 @@ void config_converter_t::processRoutes() { for (auto& [module_name, route] : baseNext.routes) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); if (route.routeId >= CONFIG_YADECAP_ROUTES_SIZE) { @@ -390,7 +390,7 @@ void config_converter_t::processRoutes() for (auto& [interface_name, interface] : route.interfaces) { - (void)interface_name; + YANET_GCC_BUG_UNUSED(interface_name); if (interface.interfaceId >= CONFIG_YADECAP_INTERFACES_SIZE) { @@ -425,7 +425,7 @@ void config_converter_t::serializeRoutes() { for (auto& [moduleName, route] : baseNext.routes) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); std::optional tunnel; if (route.tunnel_enabled) @@ -447,7 +447,7 @@ void config_converter_t::processDecap() { for (auto& [moduleName, decap] : baseNext.decaps) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (decap.decapId >= CONFIG_YADECAP_DECAPS_SIZE) { @@ -477,7 +477,7 @@ void config_converter_t::processNat64stateful() { for (auto& [name, nat64stateful] : baseNext.nat64statefuls) { - (void)name; + YANET_GCC_BUG_UNUSED(name); if (nat64stateful.nat64stateful_id >= YANET_CONFIG_NAT64STATEFULS_SIZE) { @@ -502,7 +502,7 @@ void config_converter_t::processTun64() { for (auto& [moduleName, tunnel] : baseNext.tunnels) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (tunnel.tun64Id >= CONFIG_YADECAP_TUN64_SIZE) { @@ -526,7 +526,7 @@ void config_converter_t::processNat64() { for (auto& [moduleName, nat64stateless] : baseNext.nat64statelesses) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (nat64stateless.nat64statelessId >= CONFIG_YADECAP_NAT64STATELESSES_SIZE) { @@ -585,7 +585,7 @@ void config_converter_t::processNat46clat() { for (auto& [module_name, nat46clat] : baseNext.nat46clats) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); if (nat46clat.nat46clat_id >= YANET_CONFIG_NAT46CLATS_SIZE) { @@ -612,7 +612,7 @@ void config_converter_t::processBalancer() for (auto& [moduleName, balancer] : baseNext.balancers) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (balancer.balancer_id >= YANET_CONFIG_BALANCERS_SIZE) { @@ -648,17 +648,17 @@ void config_converter_t::processBalancer() reals] : balancer.services) { /// @todo: - (void)vip; - (void)proto; - (void)vport; - (void)scheduler; - (void)scheduler_params; - (void)flags; - (void)reals; - (void)version; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(vip); + YANET_GCC_BUG_UNUSED(proto); + YANET_GCC_BUG_UNUSED(vport); + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(reals); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (service_id >= YANET_CONFIG_BALANCER_SERVICES_SIZE) { @@ -686,7 +686,7 @@ void config_converter_t::processDregress() { for (auto& [moduleName, dregress] : baseNext.dregresses) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (dregress.dregressId >= CONFIG_YADECAP_DREGRESS_SIZE) { @@ -717,7 +717,7 @@ void config_converter_t::processAcl() { for (auto& [moduleName, acl] : baseNext.acls) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (acl.synchronization) { @@ -870,7 +870,7 @@ void config_converter_t::acl_rules_route_local(controlplane::base::acl_t& acl, for (const auto& [interfaceName, interface] : route.interfaces) { - (void)interfaceName; + YANET_GCC_BUG_UNUSED(interfaceName); for (const auto& ipAddress : interface.ip_prefixes) { @@ -1111,8 +1111,8 @@ void config_converter_t::acl_rules_nat64stateless_ingress(controlplane::base::ac const auto& [ipv6Address, ipv6DestinationAddress, ingressPortRange] = key; const auto& [ipv4Address, egressPortRange, translationId] = value; - (void)ipv4Address; - (void)egressPortRange; + YANET_GCC_BUG_UNUSED(ipv4Address); + YANET_GCC_BUG_UNUSED(egressPortRange); flow.data.nat64stateless.translationId = translationId; flow_icmp.data.nat64stateless.translationId = translationId; @@ -1272,7 +1272,7 @@ void config_converter_t::acl_rules_nat64stateless_egress(controlplane::base::acl for (const auto& [key, value] : nat64stateless.translations) { - (void)key; + YANET_GCC_BUG_UNUSED(key); const auto& [ipv4Address, egressPortRange, translationId] = value; @@ -1607,13 +1607,13 @@ void config_converter_t::acl_rules_balancer(controlplane::base::acl_t& acl, ipv6_outer_source_network, reals] : balancer.services) { - (void)scheduler; - (void)scheduler_params; - (void)version; - (void)flags; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (reals.empty()) { @@ -1701,15 +1701,15 @@ void config_converter_t::acl_rules_balancer_icmp_reply(controlplane::base::acl_t ipv6_outer_source_network, reals] : balancer.services) { - (void)scheduler; - (void)scheduler_params; - (void)flags; - (void)proto; - (void)vport; - (void)version; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(proto); + YANET_GCC_BUG_UNUSED(vport); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (reals.empty()) { @@ -1770,15 +1770,15 @@ void config_converter_t::acl_rules_balancer_icmp_forward(controlplane::base::acl ipv6_outer_source_network, reals] : balancer.services) { - (void)scheduler; - (void)scheduler_params; - (void)flags; - (void)proto; - (void)vport; - (void)version; - (void)forwarding_method; - (void)ipv4_outer_source_network; - (void)ipv6_outer_source_network; + YANET_GCC_BUG_UNUSED(scheduler); + YANET_GCC_BUG_UNUSED(scheduler_params); + YANET_GCC_BUG_UNUSED(flags); + YANET_GCC_BUG_UNUSED(proto); + YANET_GCC_BUG_UNUSED(vport); + YANET_GCC_BUG_UNUSED(version); + YANET_GCC_BUG_UNUSED(forwarding_method); + YANET_GCC_BUG_UNUSED(ipv4_outer_source_network); + YANET_GCC_BUG_UNUSED(ipv6_outer_source_network); if (reals.empty()) { @@ -1810,8 +1810,8 @@ std::string config_converter_t::checkLimit(size_t count, const std::string& name uint64_t limit = 0; for (const auto& [limit_name, socket_id, current, maximum] : limits) { - (void)socket_id; - (void)current; + YANET_GCC_BUG_UNUSED(socket_id); + YANET_GCC_BUG_UNUSED(current); if (limit_name == name) { @@ -1857,10 +1857,10 @@ void config_converter_t::buildAcl() for (auto& [route_name, route] : baseNext.routes) { - (void)route_name; + YANET_GCC_BUG_UNUSED(route_name); for (auto& [name, iface] : route.interfaces) { - (void)name; + YANET_GCC_BUG_UNUSED(name); auto it = result.out_iface_map.find(iface.nextModule); if (it != result.out_iface_map.end()) { @@ -1897,7 +1897,7 @@ void config_converter_t::buildAcl() common::idp::updateGlobalBase::fwstate_synchronization_update::request fwstate_sync_request; for (const auto& [moduleName, acl] : baseNext.acls) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); if (acl.synchronization) { @@ -1929,7 +1929,7 @@ void config_converter_t::buildAcl() common::idp::updateGlobalBase::update_early_decap_flags::request early_decap_flags_request = false; for (const auto& [moduleName, acl] : baseNext.acls) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); // if at least one acl module has early_decap config section, early_decap feature is globally switched on if ((!acl.src4_early_decap.empty() && !acl.dst4_early_decap.empty()) || (!acl.src6_early_decap.empty() && !acl.dst6_early_decap.empty())) diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index d46cbb0c..ebef55eb 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -156,33 +156,33 @@ controlplane::base_t config_parser_t::loadConfig(const std::string& rootFilePath try { const auto& [dataplane_physicalports, dataplane_workers, dataplane_values] = dataPlaneConfig; - (void)dataplane_workers; - (void)dataplane_values; + YANET_GCC_BUG_UNUSED(dataplane_workers); + YANET_GCC_BUG_UNUSED(dataplane_values); for (const auto& [core_id, worker] : dataplane_workers) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); const auto& [ports, socket_id] = worker; - (void)ports; + YANET_GCC_BUG_UNUSED(ports); // add entry for sockets with workers, including slow worker baseNext.socket_interfaces[socket_id] = {}; } for (const auto& [route_name, route] : baseNext.routes) { - (void)route_name; + YANET_GCC_BUG_UNUSED(route_name); for (const auto& [interface_name, interface] : route.interfaces) { - (void)interface_name; + YANET_GCC_BUG_UNUSED(interface_name); if (exist(baseNext.logicalPorts, interface.nextModule)) { const auto& logicalport = baseNext.logicalPorts[interface.nextModule]; const auto& [physicalport_name, socket_id, mac_address, pci] = dataplane_physicalports.find(logicalport.physicalPortId)->second; - (void)physicalport_name; - (void)mac_address; - (void)pci; + YANET_GCC_BUG_UNUSED(physicalport_name); + YANET_GCC_BUG_UNUSED(mac_address); + YANET_GCC_BUG_UNUSED(pci); baseNext.socket_interfaces[socket_id].emplace(interface.interfaceId); } diff --git a/controlplane/controlplane.cpp b/controlplane/controlplane.cpp index 3bd36d65..ae31b56d 100644 --- a/controlplane/controlplane.cpp +++ b/controlplane/controlplane.cpp @@ -481,7 +481,7 @@ common::icp::acl_lookup::response cControlPlane::acl_lookup(const common::icp::a std::map labels; for (const auto& [module, acl] : acls) { - (void)module; + YANET_GCC_BUG_UNUSED(module); for (const auto& [label, info] : acl.firewall->labels()) { @@ -503,7 +503,7 @@ common::icp::acl_lookup::response cControlPlane::acl_lookup(const common::icp::a for (const auto& [id, gen_text, orig_text] : rules) { - (void)gen_text; + YANET_GCC_BUG_UNUSED(gen_text); if (ids.count(id)) { @@ -603,7 +603,7 @@ common::icp::getFwLabels::response cControlPlane::command_getFwLabels() for (const auto& [module, acl] : current.acls) { const auto& fw = acl.firewall; - (void)module; + YANET_GCC_BUG_UNUSED(module); for (const auto& [label, info] : fw->labels()) { auto ruleno = std::get(info); @@ -653,7 +653,7 @@ common::icp::getFwList::response cControlPlane::command_getFwList(const common:: for (const auto& [id, gen_text, unused_text] : current.dispatcher) { - (void)unused_text; + YANET_GCC_BUG_UNUSED(unused_text); // XXX: if we need accounting for dispatcher rules // we can prepare id mappings for them. response_rules.emplace_back(id, 0, gen_text); diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index a1abbdde..e69f7e1a 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -60,14 +60,14 @@ class cControlPlane else if constexpr (std::is_invocable_r_v) { commands[type] = [function](const common::icp::request& request) { - (void)request; + YANET_GCC_BUG_UNUSED(request); return function(); }; } else if constexpr (std::is_invocable_r_v) { commands[type] = [function](const common::icp::request& request) { - (void)request; + YANET_GCC_BUG_UNUSED(request); function(); return std::tuple<>{}; }; diff --git a/controlplane/counter.h b/controlplane/counter.h index 931dd55f..46ba3c7a 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -183,7 +183,7 @@ class counter_t if (counters_it != counters.end()) { auto& [counter_id, refcount] = counters_it->second; - (void)counter_id; + YANET_GCC_BUG_UNUSED(counter_id); if (!refcount) { @@ -265,7 +265,7 @@ class counter_t } const auto& [counter_id, refcount] = iter->second; - (void)refcount; + YANET_GCC_BUG_UNUSED(refcount); return counter_id; } @@ -278,7 +278,7 @@ class counter_t std::vector manager_counter_ids; for (const auto& [key, counter_id] : counters_allocated) { - (void)key; + YANET_GCC_BUG_UNUSED(key); for (size_t index = 0; index < size_T; index++) { @@ -293,7 +293,7 @@ class counter_t size_t i = 0; for (const auto& [key, counter_id] : counters_allocated) { - (void)counter_id; + YANET_GCC_BUG_UNUSED(counter_id); std::array array; for (size_t array_i = 0; diff --git a/controlplane/dregress.cpp b/controlplane/dregress.cpp index c5a10764..21156075 100644 --- a/controlplane/dregress.cpp +++ b/controlplane/dregress.cpp @@ -48,12 +48,12 @@ void dregress_t::prefix_insert(const std::tuple& vrf_prio for (const auto& [pptn_index, path_info_to_nh_ptr] : nexthops) { - (void)pptn_index; + YANET_GCC_BUG_UNUSED(pptn_index); for (const auto& [path_info, nexthop_stuff_ptr] : path_info_to_nh_ptr) { const auto& [nexthop, labels, origin, med, aspath, nexthop_communities, large_communities, local_preference] = *nexthop_stuff_ptr; - (void)large_communities; + YANET_GCC_BUG_UNUSED(large_communities); if ((prefix.is_ipv4() && nexthop.is_ipv4()) || (prefix.is_ipv6() && nexthop.is_ipv6())) @@ -232,7 +232,7 @@ void dregress_t::compile(common::idp::updateGlobalBase::request& globalbase, for (const auto& [config_module_name, config_module] : generation.dregresses) { - (void)config_module_name; + YANET_GCC_BUG_UNUSED(config_module_name); globalbase.emplace_back(common::idp::updateGlobalBase::requestType::dregress_local_prefix_update, config_module.localPrefixes); @@ -297,11 +297,11 @@ void dregress_t::value_compile(common::idp::updateGlobalBase::request& globalbas bool is_best = true; for (const auto& [attribute, destinations] : attribute_destinations) { - (void)attribute; + YANET_GCC_BUG_UNUSED(attribute); for (const auto& [nexthop, label, communities, peer_as, origin_as] : destinations) { - (void)vrf_priority; ///< @todo + YANET_GCC_BUG_UNUSED(vrf_priority); ///< @todo auto community = generation.get_peer_link_community(communities); if (community) { diff --git a/controlplane/dregress.h b/controlplane/dregress.h index 96b62a5a..de0b7864 100644 --- a/controlplane/dregress.h +++ b/controlplane/dregress.h @@ -40,7 +40,7 @@ class generation_t /// @todo: VRF for (const auto& [moduleName, dregress] : dregresses) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); our_as.insert(dregress.ourAs.begin(), dregress.ourAs.end()); } @@ -51,7 +51,7 @@ class generation_t /// @todo: VRF for (const auto& [moduleName, dregress] : dregresses) { - (void)moduleName; + YANET_GCC_BUG_UNUSED(moduleName); for (const auto& community : communities) { diff --git a/controlplane/fqdn.h b/controlplane/fqdn.h index 3b7f0071..26ebf043 100644 --- a/controlplane/fqdn.h +++ b/controlplane/fqdn.h @@ -17,7 +17,7 @@ class generation_t void update(const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; + YANET_GCC_BUG_UNUSED(base_prev); vrf_fqdns = base_next.vrf_fqdns; diff --git a/controlplane/nat46clat.cpp b/controlplane/nat46clat.cpp index 54f19af0..2096e579 100644 --- a/controlplane/nat46clat.cpp +++ b/controlplane/nat46clat.cpp @@ -55,14 +55,14 @@ void manager::reload(const controlplane::base_t& base_prev, for (const auto& [module_name, nat46clat] : base_next.nat46clats) { - (void)nat46clat; + YANET_GCC_BUG_UNUSED(nat46clat); module_counters.insert(module_name); } for (const auto& [module_name, nat46clat] : base_prev.nat46clats) { - (void)nat46clat; + YANET_GCC_BUG_UNUSED(nat46clat); module_counters.remove(module_name); } diff --git a/controlplane/nat64stateful.cpp b/controlplane/nat64stateful.cpp index 23e2c96e..f7f66d1a 100644 --- a/controlplane/nat64stateful.cpp +++ b/controlplane/nat64stateful.cpp @@ -33,14 +33,14 @@ void nat64stateful_t::reload(const controlplane::base_t& base_prev, for (const auto& [name, nat64stateful] : base_next.nat64statefuls) { - (void)nat64stateful; + YANET_GCC_BUG_UNUSED(nat64stateful); module_counters.insert(name); } for (const auto& [name, nat64stateful] : base_prev.nat64statefuls) { - (void)nat64stateful; + YANET_GCC_BUG_UNUSED(nat64stateful); module_counters.remove(name); } diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index 43b6c5f6..83182c63 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -176,7 +176,7 @@ void rib_t::rib_insert(const common::icp::rib_update::insert& request) for (const auto& [nexthop, nlris] : nexthops) { auto& [summary_prefixes, summary_paths, summary_eor] = this->summary[{vrf, priority, protocol, peer, table_name}]; - (void)summary_eor; + YANET_GCC_BUG_UNUSED(summary_eor); for (const auto& [prefix, path_information, labels] : nlris) { @@ -276,13 +276,13 @@ void rib_t::rib_remove(const common::icp::rib_update::remove& request) } auto& [summary_prefixes, summary_paths, summary_eor] = this->summary[{vrf, priority, protocol, peer, table_name}]; - (void)summary_eor; + YANET_GCC_BUG_UNUSED(summary_eor); rib::pptn_t current_pptn = {protocol, peer, table_name}; for (const auto& [prefix, path_information, labels] : nlris) { - (void)labels; + YANET_GCC_BUG_UNUSED(labels); unsigned int prefixes_diff = 0; unsigned int paths_diff = 0; @@ -371,9 +371,9 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) { const auto& [vrf, priority, protocol, peer, table_name] = summary_key; auto& [summary_prefixes, summary_paths, summary_eor] = summary_value; - (void)table_name; - (void)summary_prefixes; - (void)summary_paths; + YANET_GCC_BUG_UNUSED(table_name); + YANET_GCC_BUG_UNUSED(summary_prefixes); + YANET_GCC_BUG_UNUSED(summary_paths); if (protocol != request_protocol) { @@ -408,7 +408,7 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) if (request_attribute) { const auto& [request_peer, request_vrf_priority] = *request_attribute; - (void)request_peer; + YANET_GCC_BUG_UNUSED(request_peer); if (request_vrf_priority != vrf_priority) { @@ -423,7 +423,7 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) for (auto& [pptn_index, path_info_to_nh_ptr] : pptn_to_path_info_to_nh_ptr) { const auto& [protocol, peer, table_name] = proto_peer_table_name[pptn_index]; - (void)table_name; + YANET_GCC_BUG_UNUSED(table_name); if (request_protocol != protocol) { @@ -433,7 +433,7 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) if (request_attribute) { const auto& [request_peer, request_vrf_priority] = request_attribute.value(); - (void)request_vrf_priority; + YANET_GCC_BUG_UNUSED(request_vrf_priority); if (request_peer != peer) { @@ -443,7 +443,7 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) for (auto& [path_info, nh_ptr] : path_info_to_nh_ptr) { - (void)path_info; + YANET_GCC_BUG_UNUSED(path_info); --nh_to_ref_count[*nh_ptr]; // nexthop stuff is not referenced by any prefix anymore - remove it entirely @@ -505,8 +505,8 @@ void rib_t::rib_clear(const common::icp::rib_update::clear& request) for (auto& [summary_key, summary_value] : this->summary) { const auto& [vrf, priority, protocol, peer, table_name] = summary_key; - (void)summary_value; - (void)table_name; + YANET_GCC_BUG_UNUSED(summary_value); + YANET_GCC_BUG_UNUSED(table_name); if (protocol != request_protocol) { @@ -545,8 +545,8 @@ void rib_t::rib_eor(const common::icp::rib_update::eor& request) const auto& [protocol, vrf, priority, peer, table_name] = request; auto& [summary_prefixes, summary_paths, summary_eor] = this->summary[{vrf, priority, protocol, peer, table_name}]; - (void)summary_prefixes; - (void)summary_paths; + YANET_GCC_BUG_UNUSED(summary_prefixes); + YANET_GCC_BUG_UNUSED(summary_paths); summary_eor = true; } @@ -651,7 +651,7 @@ common::icp::rib_lookup::response rib_t::rib_lookup(const common::icp::rib_looku for (const auto& [vrf_priority, prefixes_to_pptn_to_path_info_to_nh_ptr] : prefixes_to_path_info_to_nh_ptr) { const auto& [vrf, priority] = vrf_priority; - (void)priority; + YANET_GCC_BUG_UNUSED(priority); if (request_vrf != vrf) { @@ -694,7 +694,7 @@ common::icp::rib_get::response rib_t::rib_get(const common::icp::rib_get::reques for (const auto& [vrf_priority, prefixes_to_pptn_to_path_info_to_nh_ptr] : prefixes_to_path_info_to_nh_ptr) { const auto& [vrf, priority] = vrf_priority; - (void)priority; + YANET_GCC_BUG_UNUSED(priority); if (request_vrf != vrf) { @@ -811,7 +811,7 @@ void rib_t::rib_load(const common::icp::rib_load::request& request) { for (const auto& [prefix, pptn_to_path_info_to_nh_ptr] : prefixes_to_pptn_to_path_info_to_nh_ptr) { - (void)pptn_to_path_info_to_nh_ptr; + YANET_GCC_BUG_UNUSED(pptn_to_path_info_to_nh_ptr); this->prefixes_reb[vrf_priority].insert(prefix); } } @@ -826,7 +826,7 @@ void rib_t::rib_load(const common::icp::rib_load::request& request) { const auto& [index, ref_count] = index_ref_count_pair; auto [nh_to_ref_count_it, insert_result] = this->nh_to_ref_count.insert({nh, ref_count}); - (void)insert_result; + YANET_GCC_BUG_UNUSED(insert_result); const rib::nexthop_stuff_t* nh_ptr = &(nh_to_ref_count_it->first); diff --git a/controlplane/route.cpp b/controlplane/route.cpp index e7d3fd7c..73e0380b 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -101,7 +101,7 @@ void route_t::prefix_update(const std::tuple& vrf_priorit auto current_guard = generations.current_lock_guard(); for (const auto& [name, module] : generations.current().routes) ///< @todo: DELETE { - (void)name; + YANET_GCC_BUG_UNUSED(name); if (exist(module.ignore_tables, table_name)) { @@ -120,8 +120,8 @@ void route_t::prefix_update(const std::tuple& vrf_priorit uint32_t peer_id = ExtractPeerIdFromPathInformation(path_info); const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = *nh_ptr; - (void)communities; - (void)large_communities; + YANET_GCC_BUG_UNUSED(communities); + YANET_GCC_BUG_UNUSED(large_communities); interface_destination_next[{std::numeric_limits::max() - local_preference, aspath.size(), @@ -215,12 +215,12 @@ void route_t::tunnel_prefix_update(const std::tuple& vrf_ for (const auto& [pptn_index, path_info_to_nh_ptr] : *nexthops) { - (void)pptn_index; + YANET_GCC_BUG_UNUSED(pptn_index); for (const auto& [path_information, nh_ptr] : path_info_to_nh_ptr) { const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = *nh_ptr; - (void)communities; + YANET_GCC_BUG_UNUSED(communities); if ((prefix.is_ipv4() && nexthop.is_ipv4()) || (prefix.is_ipv4() && nexthop.is_ipv6()) || @@ -459,7 +459,7 @@ common::icp::route_lookup::response route_t::route_lookup(const common::icp::rou if (exist(prefixes, vrf)) { const auto& [priority_current, update] = prefixes[vrf]; - (void)update; + YANET_GCC_BUG_UNUSED(update); for (auto it = priority_current.rbegin(); it != priority_current.rend(); @@ -519,7 +519,7 @@ common::icp::route_get::response route_t::route_get(const common::icp::route_get if (exist(prefixes, vrf)) { const auto& [priority_current, update] = prefixes[vrf]; - (void)update; + YANET_GCC_BUG_UNUSED(update); for (auto it = priority_current.rbegin(); it != priority_current.rend(); @@ -584,8 +584,8 @@ common::icp::route_tunnel_counters::response route_t::route_tunnel_counters() for (const auto& [key, counts] : counter_values) { const auto [is_ipv4, link_id, nexthop, origin_as] = key; - (void)is_ipv4; - (void)origin_as; + YANET_GCC_BUG_UNUSED(is_ipv4); + YANET_GCC_BUG_UNUSED(origin_as); if (counts[0] != 0 || counts[1] != 0) { result.emplace_back(link_id, nexthop, counts[0], counts[1]); @@ -667,7 +667,7 @@ common::icp::route_tunnel_lookup::response route_t::route_tunnel_lookup(const co if (exist(tunnel_prefixes, vrf)) { const auto& [priority_current, update] = tunnel_prefixes[vrf]; - (void)update; + YANET_GCC_BUG_UNUSED(update); for (auto it = priority_current.rbegin(); it != priority_current.rend(); @@ -686,7 +686,7 @@ common::icp::route_tunnel_lookup::response route_t::route_tunnel_lookup(const co for (const auto& [nexthop, egress_interface_name, label, peer_id, origin_as, weight_percent] : destinations) { - (void)origin_as; + YANET_GCC_BUG_UNUSED(origin_as); std::optional result_label; std::optional result_peer; @@ -745,7 +745,7 @@ common::icp::route_tunnel_get::response route_t::route_tunnel_get(const common:: if (exist(tunnel_prefixes, vrf)) { const auto& [priority_current, update] = tunnel_prefixes[vrf]; - (void)update; + YANET_GCC_BUG_UNUSED(update); for (auto it = priority_current.rbegin(); it != priority_current.rend(); @@ -764,7 +764,7 @@ common::icp::route_tunnel_get::response route_t::route_tunnel_get(const common:: for (const auto& [nexthop, egress_interface_name, label, peer_id, origin_as, weight_percent] : destinations) { - (void)origin_as; + YANET_GCC_BUG_UNUSED(origin_as); std::optional result_label; std::optional result_peer; @@ -896,7 +896,7 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [module_name, nat64stateless] : base_prev.nat64statelesses) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); for (const auto& prefix : nat64stateless.nat64_prefixes) { @@ -913,7 +913,7 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [module_name, nat64stateless] : base_next.nat64statelesses) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); for (const auto& prefix : nat64stateless.nat64_prefixes) { @@ -930,7 +930,7 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [config_module_name, config_module] : base_prev.routes) { - (void)config_module_name; + YANET_GCC_BUG_UNUSED(config_module_name); for (const auto& prefix : config_module.local_prefixes) { @@ -942,7 +942,7 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [config_module_name, config_module] : base_next.routes) { - (void)config_module_name; + YANET_GCC_BUG_UNUSED(config_module_name); for (const auto& prefix : config_module.local_prefixes) { @@ -954,11 +954,11 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [config_module_name, config_module] : base_prev.routes) { - (void)config_module_name; + YANET_GCC_BUG_UNUSED(config_module_name); for (const auto& [interface_name, interface] : config_module.interfaces) { - (void)interface_name; + YANET_GCC_BUG_UNUSED(interface_name); for (const auto& ip_prefix : interface.ip_prefixes) { @@ -975,7 +975,7 @@ void route_t::reload(const controlplane::base_t& base_prev, for (const auto& [config_module_name, config_module] : base_next.routes) { - (void)config_module_name; + YANET_GCC_BUG_UNUSED(config_module_name); for (const auto& [interface_name, interface] : config_module.interfaces) { @@ -1027,7 +1027,7 @@ void route_t::prefix_flush_prefixes(common::idp::updateGlobalBase::request& glob for (auto& [vrf, priority_current_update] : prefixes) { - (void)vrf; ///< @todo: VRF + YANET_GCC_BUG_UNUSED(vrf); ///< @todo: VRF auto& [priority_current, update] = priority_current_update; @@ -1053,7 +1053,7 @@ void route_t::prefix_flush_prefixes(common::idp::updateGlobalBase::request& glob for (const auto& [priority, current] : priority_current) { - (void)priority; + YANET_GCC_BUG_UNUSED(priority); for (const auto& update_prefix : update_prefixes) { @@ -1093,7 +1093,7 @@ void route_t::tunnel_prefix_flush_prefixes(common::idp::updateGlobalBase::reques for (auto& [vrf, priority_current_update] : tunnel_prefixes) { - (void)vrf; ///< @todo: VRF + YANET_GCC_BUG_UNUSED(vrf); ///< @todo: VRF auto& [priority_current, update] = priority_current_update; @@ -1119,7 +1119,7 @@ void route_t::tunnel_prefix_flush_prefixes(common::idp::updateGlobalBase::reques for (const auto& [priority, current] : priority_current) { - (void)priority; + YANET_GCC_BUG_UNUSED(priority); for (const auto& update_prefix : update_prefixes) { @@ -1173,15 +1173,15 @@ std::optional route_t::value_insert(const route::value_key_t& value_ke } const auto& [vrf_priority, destination, fallback] = value_key; - (void)vrf_priority; - (void)fallback; + YANET_GCC_BUG_UNUSED(vrf_priority); + YANET_GCC_BUG_UNUSED(fallback); /// counters if (const auto nexthops = std::get_if(&destination)) { for (const auto& [nexthop, peer_id, prefix, labels] : *nexthops) { - (void)labels; + YANET_GCC_BUG_UNUSED(labels); route_counter.insert({peer_id, nexthop, prefix}); } @@ -1196,15 +1196,15 @@ void route_t::value_remove(const uint32_t& value_id) if (value_key) { const auto& [vrf_priority, destination, fallback] = *value_key; - (void)vrf_priority; - (void)fallback; + YANET_GCC_BUG_UNUSED(vrf_priority); + YANET_GCC_BUG_UNUSED(fallback); /// counters if (const auto nexthops = std::get_if(&destination)) { for (const auto& [nexthop, peer_id, prefix, labels] : *nexthops) { - (void)labels; + YANET_GCC_BUG_UNUSED(labels); route_counter.remove({peer_id, nexthop, prefix}, 20); } @@ -1317,7 +1317,7 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, auto& [priority_current, update] = prefixes[vrf]; auto& current = priority_current[priority]; - (void)update; + YANET_GCC_BUG_UNUSED(update); const auto value_id_label = current.get(prefix_next); if (value_id_label) @@ -1340,7 +1340,7 @@ void route_t::value_compile(common::idp::updateGlobalBase::request& globalbase, { auto& [priority_current, update] = prefixes[vrf]; auto& current = priority_current[priority]; - (void)update; + YANET_GCC_BUG_UNUSED(update); const auto value_id_fallback = current.get(fallback); if (value_id_fallback) @@ -1449,9 +1449,9 @@ void route_t::value_compile_label(common::idp::updateGlobalBase::request& global { const auto& value_key = values.get_value(value_id); const auto& [vrf_priority, destination, fallback] = value_key; - (void)globalbase; - (void)vrf_priority; - (void)fallback; + YANET_GCC_BUG_UNUSED(globalbase); + YANET_GCC_BUG_UNUSED(vrf_priority); + YANET_GCC_BUG_UNUSED(fallback); if (const auto virtual_port_id = std::get_if(&destination)) { @@ -1502,9 +1502,9 @@ void route_t::value_compile_fallback(common::idp::updateGlobalBase::request& glo { const auto& value_key = values.get_value(value_id); const auto& [vrf_priority, destination, fallback] = value_key; - (void)globalbase; - (void)vrf_priority; - (void)fallback; + YANET_GCC_BUG_UNUSED(globalbase); + YANET_GCC_BUG_UNUSED(vrf_priority); + YANET_GCC_BUG_UNUSED(fallback); if (const auto virtual_port_id = std::get_if(&destination)) { @@ -1554,15 +1554,15 @@ std::optional route_t::tunnel_value_insert(const route::tunnel_value_k } const auto& [vrf_priority, destination, fallback] = value_key; - (void)vrf_priority; + YANET_GCC_BUG_UNUSED(vrf_priority); /// counters if (const auto nexthops = std::get_if(&destination)) { for (const auto& [nexthop, label, peer_id, origin_as, weight] : *nexthops) { - (void)label; - (void)weight; + YANET_GCC_BUG_UNUSED(label); + YANET_GCC_BUG_UNUSED(weight); tunnel_counter.insert({fallback.is_ipv4(), peer_id, nexthop, origin_as}); } @@ -1577,15 +1577,15 @@ void route_t::tunnel_value_remove(const uint32_t& value_id) if (value_key) { const auto& [vrf_priority, destination, fallback] = *value_key; - (void)vrf_priority; + YANET_GCC_BUG_UNUSED(vrf_priority); /// counters if (const auto nexthops = std::get_if(&destination)) { for (const auto& [nexthop, label, peer_id, origin_as, weight] : *nexthops) { - (void)label; - (void)weight; + YANET_GCC_BUG_UNUSED(label); + YANET_GCC_BUG_UNUSED(weight); tunnel_counter.remove({fallback.is_ipv4(), peer_id, nexthop, origin_as}, 20); } @@ -1601,7 +1601,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa std::vector request_interface; const auto& [vrf_priority, destination, fallback] = value_key; - (void)vrf_priority; ///< @todo: VRF + YANET_GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF tunnel_value_lookup[value_id].clear(); @@ -1812,7 +1812,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa for (const auto& item : request_interface) { const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; - (void)egress_interface_name; + YANET_GCC_BUG_UNUSED(egress_interface_name); if (exist(interfaces, egress_interface_id)) { @@ -1844,7 +1844,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa for (const auto& item : request_interface) { const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; - (void)egress_interface_name; + YANET_GCC_BUG_UNUSED(egress_interface_name); const auto counter_id = tunnel_counter.get_id({fallback.is_ipv4(), peer_id, nexthop, origin_as}); @@ -1880,12 +1880,12 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa for (auto& [nexthop, egress_interface_name, label, peer_id, origin_as, weight_percent] : tunnel_value_lookup[value_id][socket_id]) { - (void)socket_id; - (void)nexthop; - (void)egress_interface_name; - (void)label; - (void)peer_id; - (void)origin_as; + YANET_GCC_BUG_UNUSED(socket_id); + YANET_GCC_BUG_UNUSED(nexthop); + YANET_GCC_BUG_UNUSED(egress_interface_name); + YANET_GCC_BUG_UNUSED(label); + YANET_GCC_BUG_UNUSED(peer_id); + YANET_GCC_BUG_UNUSED(origin_as); if (weight_is_fallback) { @@ -1909,16 +1909,16 @@ std::set route_t::get_ingress_physical_ports(const tSocketId& socke /// @todo: use function const auto& [dataplane_physicalports, dataplane_workers, dataplane_values] = controlPlane->dataPlaneConfig; - (void)dataplane_workers; - (void)dataplane_values; + YANET_GCC_BUG_UNUSED(dataplane_workers); + YANET_GCC_BUG_UNUSED(dataplane_values); for (const auto& [dataplane_physicalport_id, dataplane_physicalport] : dataplane_physicalports) { - (void)dataplane_physicalport_id; + YANET_GCC_BUG_UNUSED(dataplane_physicalport_id); const auto& [physicalport_name, dataplane_socket_id, mac_address, pci] = dataplane_physicalport; - (void)mac_address; - (void)pci; + YANET_GCC_BUG_UNUSED(mac_address); + YANET_GCC_BUG_UNUSED(pci); if (socket_id != dataplane_socket_id) { diff --git a/controlplane/route.h b/controlplane/route.h index 40b17dea..43b479c5 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -109,7 +109,7 @@ class generation_t for (const auto& [module_name, route] : base_next.routes) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); for (const auto& [interface_name, interface] : route.interfaces) { diff --git a/controlplane/telegraf.cpp b/controlplane/telegraf.cpp index f6c34799..2066a0eb 100644 --- a/controlplane/telegraf.cpp +++ b/controlplane/telegraf.cpp @@ -141,7 +141,7 @@ common::icp::telegraf_unsafe::response telegraf_t::telegraf_unsafe() { const auto& [encap_packets, encap_bytes, encap_dropped, decap_packets, decap_bytes, decap_unknown] = tun64Stats.at(name); - (void)tunnel; + YANET_GCC_BUG_UNUSED(tunnel); responseTun64[name] = {encap_packets, encap_bytes, encap_dropped, decap_packets, decap_bytes, decap_unknown}; } } @@ -177,7 +177,7 @@ common::icp::telegraf_mappings::response telegraf_t::telegraf_mappings() const auto& [encap_packets, encap_bytes, decap_packets, decap_bytes] = counters.at({name, ipv4_address}); const common::tun64mapping::stats_t stats = {encap_packets, encap_bytes, decap_packets, decap_bytes}; - (void)location; + YANET_GCC_BUG_UNUSED(location); response.emplace_back(name, ipv4_address, ipv6_address, stats); } } @@ -220,7 +220,7 @@ common::icp::telegraf_dregress_traffic::response telegraf_t::telegraf_dregress_t { const auto& [is_ipv4, peer_id, nexthop, origin_as] = key; const auto& [packets, bytes] = value; - (void)origin_as; + YANET_GCC_BUG_UNUSED(origin_as); auto it = dregress_traffic_counters_prev.find(key); if (it != dregress_traffic_counters_prev.end()) diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index 4b52a101..ff44c287 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -25,7 +25,7 @@ class generation_t for (const auto& [module_name, dregress] : base_next.dregresses) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); communities.insert(dregress.communities.begin(), dregress.communities.end()); } @@ -33,7 +33,7 @@ class generation_t for (const auto& [module_name, route] : base_next.routes) { - (void)module_name; + YANET_GCC_BUG_UNUSED(module_name); peers.insert(route.peers.begin(), route.peers.end()); } diff --git a/controlplane/tun64.cpp b/controlplane/tun64.cpp index ed454867..142f9088 100644 --- a/controlplane/tun64.cpp +++ b/controlplane/tun64.cpp @@ -42,7 +42,7 @@ void tun64_t::reload(const controlplane::base_t& base_prev, for (const auto& [ipv4_address, mapping] : tunnel.mappings) { - (void)mapping; + YANET_GCC_BUG_UNUSED(mapping); mappings_counters.insert({name, ipv4_address}); } } @@ -53,7 +53,7 @@ void tun64_t::reload(const controlplane::base_t& base_prev, for (const auto& [ipv4_address, mapping] : tunnel.mappings) { - (void)mapping; + YANET_GCC_BUG_UNUSED(mapping); mappings_counters.remove({name, ipv4_address}); } } @@ -133,7 +133,7 @@ void tun64_t::compile(common::idp::updateGlobalBase::request& globalbase, const auto& [ipv6_address, location] = mapping; const auto counter_id = mappings_counters.get_id({name, ipv4_address}); - (void)location; + YANET_GCC_BUG_UNUSED(location); tun64mappings_update_request.emplace_back(tunnel.tun64Id, ipv4_address, ipv6_address, diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 555c0e7d..d464d10a 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -262,7 +262,7 @@ common::idp::getSlowWorkerStats::response cControlPlane::SlowWorkerStatsResponse for (const auto& [core_id, worker] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); hashtable_gc_stats.emplace_back(worker->socket_id, "nat64stateful.lan.state.ht", @@ -325,7 +325,7 @@ common::idp::get_ports_stats::response cControlPlane::get_ports_stats() for (const auto& [portId, port] : dataPlane->ports) { - (void)port; + YANET_GCC_BUG_UNUSED(port); rte_eth_stats stats; { @@ -359,7 +359,7 @@ common::idp::get_ports_stats_extended::response cControlPlane::get_ports_stats_e for (const auto& [portId, _] : dataPlane->ports) { - (void)_; + YANET_GCC_BUG_UNUSED(_); auto portStats = dataPlane->getPortStats(portId); response[portId] = portStats; @@ -476,7 +476,7 @@ common::idp::getFWState::response cControlPlane::getFWState() for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); worker_gc->fw_state_mutex.lock(); auto fw_state = worker_gc->fw_state; @@ -521,7 +521,7 @@ common::idp::getFWStateStats::response cControlPlane::getFWStateStats() ///< @to for (auto& [socket_id, globalbase_atomics] : dataPlane->globalBaseAtomics) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); stats.fwstate4_size = std::max(stats.fwstate4_size, (uint64_t)globalbase_atomics->updater.fw4_state.get_stats().keys_count); stats.fwstate6_size = std::max(stats.fwstate6_size, (uint64_t)globalbase_atomics->updater.fw6_state.get_stats().keys_count); @@ -534,7 +534,7 @@ eResult cControlPlane::clearFWState() { for (auto& [socketId, globalBaseAtomic] : dataPlane->globalBaseAtomics) { - (void)socketId; + YANET_GCC_BUG_UNUSED(socketId); globalBaseAtomic->fw4_state->clear(); globalBaseAtomic->fw6_state->clear(); @@ -585,9 +585,9 @@ common::idp::getConfig::response cControlPlane::getConfig() const for (const auto& [port_id, port] : dataPlane->ports) { const auto& [interface_name, rx_queues, tx_queues_count, mac_address, pci, symmetric_mode] = port; - (void)rx_queues; - (void)tx_queues_count; - (void)symmetric_mode; + YANET_GCC_BUG_UNUSED(rx_queues); + YANET_GCC_BUG_UNUSED(tx_queues_count); + YANET_GCC_BUG_UNUSED(symmetric_mode); response_ports[port_id] = {interface_name, rte_eth_dev_socket_id(port_id), @@ -757,7 +757,7 @@ common::idp::samples::response cControlPlane::samples() std::set samples; for (auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); std::lock_guard guard(worker_gc->samples_mutex); @@ -832,7 +832,7 @@ common::idp::limits::response cControlPlane::limits() for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); worker_gc->limits(response); } @@ -856,7 +856,7 @@ common::idp::balancer_connection::response cControlPlane::balancer_connection(co for (auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); auto& response_connections = response[worker_gc->socket_id]; @@ -920,7 +920,7 @@ common::idp::balancer_connection::response cControlPlane::balancer_connection(co } /// @todo: filter_real_port - (void)filter_real_port; + YANET_GCC_BUG_UNUSED(filter_real_port); auto& connections = response_connections[{balancer_id, virtual_ip, @@ -954,7 +954,7 @@ common::idp::balancer_service_connections::response cControlPlane::balancer_serv for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); auto current_guard = worker_gc->balancer_service_connections.current_lock_guard(); response[worker_gc->socket_id] = worker_gc->balancer_service_connections.current(); @@ -969,7 +969,7 @@ common::idp::balancer_real_connections::response cControlPlane::balancer_real_co for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); auto current_guard = worker_gc->balancer_real_connections.current_lock_guard(); response[worker_gc->socket_id] = worker_gc->balancer_real_connections.current(); @@ -1072,7 +1072,7 @@ eResult cControlPlane::dump_physical_port(const common::idp::dump_physical_port: /// start dump traffic to interface for (auto& [socket_id, globalbase_atomic] : dataPlane->globalBaseAtomics) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); __atomic_or_fetch(&globalbase_atomic->physicalPort_flags[*port_id], (uint8_t)(flag), @@ -1084,7 +1084,7 @@ eResult cControlPlane::dump_physical_port(const common::idp::dump_physical_port: /// stop dump traffic to interface for (auto& [socket_id, globalbase_atomic] : dataPlane->globalBaseAtomics) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); __atomic_and_fetch(&globalbase_atomic->physicalPort_flags[*port_id], (uint8_t)(~flag), @@ -1099,7 +1099,7 @@ eResult cControlPlane::balancer_state_clear() { for (auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); worker_gc->balancer_state_clear(); } @@ -1112,7 +1112,7 @@ common::idp::nat64stateful_state::response cControlPlane::nat64stateful_state(co for (auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); worker_gc->nat64stateful_state(request, response); } @@ -1194,7 +1194,7 @@ void cControlPlane::waitAllWorkers() for (const auto& [core_id, worker] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); uint64_t startIteration = worker->iteration; uint64_t nextIteration = startIteration; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 6fbfa0c1..06356ef0 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -231,7 +231,7 @@ eResult cDataPlane::init(const std::string& binaryPath, for (const auto& [core_id, worker_gc] : worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); gc_sockets_used.emplace(worker_gc->socket_id); } @@ -483,7 +483,7 @@ eResult cDataPlane::initPorts() { const std::string& interfaceName = configPortIter.first; const auto& [pci, name, symmetric_mode, rss_flags] = configPortIter.second; - (void)pci; + YANET_GCC_BUG_UNUSED(pci); tPortId portId = 0; @@ -936,8 +936,8 @@ eResult cDataPlane::initWorkers() for (const auto& [port_id, port] : ports) { const auto& [interface_name, rx_queues, tx_queues_count, mac_address, pci, symmetric_mode] = port; - (void)mac_address; - (void)pci; + YANET_GCC_BUG_UNUSED(mac_address); + YANET_GCC_BUG_UNUSED(pci); if (!basePermanently.ports.Register(port_id)) return eResult::invalidPortsCount; @@ -1035,7 +1035,7 @@ eResult cDataPlane::initWorkers() worker_gc_t::PortToSocketArray port_to_socket; for (const auto& [port_id, port] : ports) { - (void)port; + YANET_GCC_BUG_UNUSED(port); port_to_socket[port_id] = rte_eth_dev_socket_id(port_id); } @@ -1376,7 +1376,7 @@ void cDataPlane::init_worker_base() for (auto& [core_id, worker] : worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); auto* base = &worker->bases[worker->current_base_id]; auto* base_next = &worker->bases[worker->current_base_id ^ 1]; @@ -1399,7 +1399,7 @@ void cDataPlane::timestamp_thread() { for (const auto& [socket_id, globalbase_atomic] : globalBaseAtomics) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); globalbase_atomic->currentTime = current_time; } @@ -1896,7 +1896,7 @@ void cDataPlane::switch_worker_base() for (auto& [core_id, worker] : worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); auto* base_next = &worker->bases[worker->current_base_id ^ 1]; base_nexts.emplace_back(worker->socket_id, base_next); @@ -2286,9 +2286,9 @@ eResult cDataPlane::checkConfig() for (const auto& portIter : config.ports) { const auto& [pci, name, symmetric_mode, rss_flags] = portIter.second; - (void)pci; - (void)symmetric_mode; - (void)rss_flags; + YANET_GCC_BUG_UNUSED(pci); + YANET_GCC_BUG_UNUSED(symmetric_mode); + YANET_GCC_BUG_UNUSED(rss_flags); if (exist(names, name)) { @@ -2386,9 +2386,9 @@ eResult cDataPlane::initEal(const std::string& binaryPath, for (const auto& port : config.ports) { const auto& [pci, name, symmetric_mode, rss_flags] = port.second; - (void)name; - (void)symmetric_mode; - (void)rss_flags; + YANET_GCC_BUG_UNUSED(name); + YANET_GCC_BUG_UNUSED(symmetric_mode); + YANET_GCC_BUG_UNUSED(rss_flags); // Do not whitelist sock dev virtual devices if (StartsWith(name, SOCK_DEV_PREFIX)) diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index b969ec15..2bfefdb5 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -114,11 +114,11 @@ void dregress_t::insert(rte_mbuf* mbuf) } const auto& [prefix, nexthop, is_best, label, community, peer_as, origin_as] = *direction; - (void)prefix; - (void)is_best; - (void)community; - (void)peer_as; - (void)origin_as; + YANET_GCC_BUG_UNUSED(prefix); + YANET_GCC_BUG_UNUSED(is_best); + YANET_GCC_BUG_UNUSED(community); + YANET_GCC_BUG_UNUSED(peer_as); + YANET_GCC_BUG_UNUSED(origin_as); labelled_nexthop = ipv6_address_t::convert(nexthop); labelled_label = label; @@ -544,11 +544,11 @@ std::optional dregress_t::lookup(rte_mbuf* mbuf) auto direction = (*std::next(directions.begin(), rand() % directions.size())).second; { auto& [prefix, nexthop, is_best, label, community, peer_as, origin_as] = direction; - (void)nexthop; - (void)label; - (void)community; - (void)peer_as; - (void)origin_as; + YANET_GCC_BUG_UNUSED(nexthop); + YANET_GCC_BUG_UNUSED(label); + YANET_GCC_BUG_UNUSED(community); + YANET_GCC_BUG_UNUSED(peer_as); + YANET_GCC_BUG_UNUSED(origin_as); if (prefix.mask() != mask_max) { diff --git a/dataplane/fragmentation.cpp b/dataplane/fragmentation.cpp index 599b2a3c..8cf1ec65 100644 --- a/dataplane/fragmentation.cpp +++ b/dataplane/fragmentation.cpp @@ -25,14 +25,14 @@ Fragmentation::~Fragmentation() { for (const auto& [key, value] : fragments_) { - (void)key; + YANET_GCC_BUG_UNUSED(key); for (const auto& [range_from, range_value] : std::get<0>(value)) { - (void)range_from; + YANET_GCC_BUG_UNUSED(range_from); const auto& [range_to, mbuf] = range_value; - (void)range_to; + YANET_GCC_BUG_UNUSED(range_to); rte_pktmbuf_free(mbuf); } @@ -217,10 +217,10 @@ void Fragmentation::handle() for (auto& [range_from, range_value] : std::get<0>(value)) { - (void)range_from; + YANET_GCC_BUG_UNUSED(range_from); const auto& [range_to, mbuf] = range_value; - (void)range_to; + YANET_GCC_BUG_UNUSED(range_to); dataplane::metadata* metadata = YADECAP_METADATA(mbuf); metadata->flow.data = firstPacket_metadata->flow.data; @@ -238,10 +238,10 @@ void Fragmentation::handle() { for (auto& [range_from, range_value] : std::get<0>(fragments_[key])) { - (void)range_from; + YANET_GCC_BUG_UNUSED(range_from); const auto& [range_to, mbuf] = range_value; - (void)range_to; + YANET_GCC_BUG_UNUSED(range_to); stats_.timeout_packets++; rte_pktmbuf_free(mbuf); @@ -276,7 +276,7 @@ bool Fragmentation::isCollected(const fragmentation::value_t& value) const for (const auto& [range_from, range_value] : std::get<0>(value)) { const auto& [range_to, mbuf] = range_value; - (void)mbuf; + YANET_GCC_BUG_UNUSED(mbuf); if (range_from != next_range_from) { @@ -301,7 +301,7 @@ bool Fragmentation::isIntersect(const fragmentation::value_t& value, for (const auto& [range_from, range_value] : std::get<0>(value)) { const auto& [range_to, mbuf] = range_value; - (void)mbuf; + YANET_GCC_BUG_UNUSED(mbuf); if (second_range_to < range_from) { diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 1b3bc7ac..00bade2c 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -1518,7 +1518,7 @@ eResult generation::update_balancer_services(const common::idp::updateGlobalBase } for (const auto& [core_id, worker_gc] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); sum_gc += worker_gc->counters[counter_id + i]; } for (const auto& item : dataPlane->globalBaseAtomics) @@ -1610,7 +1610,7 @@ inline uint64_t generation::count_real_connections(uint32_t counter_id) uint64_t sessions_destroyed_gc = 0; for (const auto& [node_id, worker_gc] : dataPlane->worker_gcs) { - (void)node_id; + YANET_GCC_BUG_UNUSED(node_id); sessions_created_gc += worker_gc->counters[counter_id + (tCounterId)::balancer::gc_real_counter::sessions_created]; sessions_destroyed_gc += worker_gc->counters[counter_id + (tCounterId)::balancer::gc_real_counter::sessions_destroyed]; } diff --git a/dataplane/lpm.h b/dataplane/lpm.h index f7ff96e3..51f5090d 100644 --- a/dataplane/lpm.h +++ b/dataplane/lpm.h @@ -450,8 +450,8 @@ class lpm4_24bit_8bit_atomic const unsigned int& step, tChunk8& chunk) { - (void)needWait; - (void)step; + YANET_GCC_BUG_UNUSED(needWait); + YANET_GCC_BUG_UNUSED(step); for (unsigned int mask_i = 0; mask_i < (((unsigned int)1) << (8 - mask)); @@ -602,8 +602,8 @@ class lpm4_24bit_8bit_atomic const unsigned int& step, tChunk8& chunk) { - (void)needWait; - (void)step; + YANET_GCC_BUG_UNUSED(needWait); + YANET_GCC_BUG_UNUSED(step); for (unsigned int mask_i = 0; mask_i < (((unsigned int)1) << (8 - mask)); @@ -1687,7 +1687,7 @@ class lpm4_24bit_8bit_id32 const unsigned int from_chunk_id, const unsigned int extended_chunk_id) { - (void)updater; + YANET_GCC_BUG_UNUSED(updater); const auto& from_chunk = from_chunks[from_chunk_id]; auto& extended_chunk = extended_chunks[extended_chunk_id]; diff --git a/dataplane/memory_manager.cpp b/dataplane/memory_manager.cpp index f7c35b25..02cbec3e 100644 --- a/dataplane/memory_manager.cpp +++ b/dataplane/memory_manager.cpp @@ -68,7 +68,7 @@ common::idp::memory_manager_stats::response memory_manager::memory_manager_stats response_memory_group = root_memory_group; for (const auto& [pointer, memory_pointer] : pointers) { - (void)pointer; + YANET_GCC_BUG_UNUSED(pointer); response_objects.emplace_back(memory_pointer.name, memory_pointer.socket_id, memory_pointer.size); @@ -169,7 +169,7 @@ bool memory_manager::check_memory_limit(const std::string& name, for (const auto& [pointer, memory_pointer] : pointers) { - (void)pointer; + YANET_GCC_BUG_UNUSED(pointer); uint64_t object_size = memory_pointer.size; if (memory_pointer.name == name) diff --git a/dataplane/neighbor.cpp b/dataplane/neighbor.cpp index d7685bb3..cb20553e 100644 --- a/dataplane/neighbor.cpp +++ b/dataplane/neighbor.cpp @@ -286,7 +286,7 @@ common::idp::neighbor_show::response module::neighbor_show() const eResult module::neighbor_insert(const common::idp::neighbor_insert::request& request) { const auto& [route_name, interface_name, ip_address, mac_address] = request; - (void)route_name; ///< @todo + YANET_GCC_BUG_UNUSED(route_name); ///< @todo tInterfaceId interface_id = 0; { @@ -327,7 +327,7 @@ eResult module::neighbor_insert(const common::idp::neighbor_insert::request& req eResult result = eResult::success; for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); if (!hashtable_updater.get_pointer()->insert_or_update(key, value)) { result = eResult::isFull; @@ -347,7 +347,7 @@ eResult module::neighbor_insert(const common::idp::neighbor_insert::request& req eResult module::neighbor_remove(const common::idp::neighbor_remove::request& request) { const auto& [route_name, interface_name, ip_address] = request; - (void)route_name; ///< @todo + YANET_GCC_BUG_UNUSED(route_name); ///< @todo tInterfaceId interface_id = 0; { @@ -382,7 +382,7 @@ eResult module::neighbor_remove(const common::idp::neighbor_remove::request& req eResult result = eResult::success; for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); if (!hashtable_updater.get_pointer()->remove(key)) { result = eResult::invalidArguments; @@ -404,7 +404,7 @@ eResult module::neighbor_clear() auto response = generation_hashtable.update([](neighbor::generation_hashtable& hashtable) { for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); hashtable_updater.get_pointer()->clear(); } return eResult::success; @@ -483,7 +483,7 @@ eResult module::neighbor_update_interfaces(const common::idp::neighbor_update_in generation_hashtable.update([this, key, value](neighbor::generation_hashtable& hashtable) { for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); if (!hashtable_updater.get_pointer()->insert_or_update(key, value)) { stats.hashtable_insert_error++; @@ -614,7 +614,7 @@ void module::netlink_thread() generation_hashtable.update([this, key, value](neighbor::generation_hashtable& hashtable) { for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); if (!hashtable_updater.get_pointer()->insert_or_update(key, value)) { stats.hashtable_insert_error++; @@ -652,7 +652,7 @@ void module::resolve(const dataplane::neighbor::key& key) } const auto& [it_route_name, it_interface_name] = it->second; - (void)it_route_name; + YANET_GCC_BUG_UNUSED(it_route_name); interface_name = it_interface_name; } @@ -677,7 +677,7 @@ void module::resolve(const dataplane::neighbor::key& key) generation_hashtable.update([this, key, value](neighbor::generation_hashtable& hashtable) { for (auto& [socket_id, hashtable_updater] : hashtable.hashtable_updater) { - (void)socket_id; + YANET_GCC_BUG_UNUSED(socket_id); if (!hashtable_updater.get_pointer()->insert_or_update(key, value)) { stats.hashtable_insert_error++; diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 9b1e7192..de19e68b 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -75,7 +75,7 @@ nlohmann::json cReport::getReport() for (const auto& [core_id, worker] : dataPlane->worker_gcs) { - (void)core_id; + YANET_GCC_BUG_UNUSED(core_id); jsonReport["worker_gcs"].emplace_back(convertWorkerGC(worker)); } diff --git a/dataplane/slow_worker.cpp b/dataplane/slow_worker.cpp index 1a3eccd8..ccec4452 100644 --- a/dataplane/slow_worker.cpp +++ b/dataplane/slow_worker.cpp @@ -519,7 +519,7 @@ bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) for (auto& [socketId, globalBaseAtomic] : slow_worker_->dataPlane->globalBaseAtomics) { - (void)socketId; + YANET_GCC_BUG_UNUSED(socketId); dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; dataplane::spinlock_nonrecursive_t* locker = nullptr; @@ -600,7 +600,7 @@ bool SlowWorker::handlePacket_fw_state_sync_ingress(rte_mbuf* mbuf) for (auto& [socketId, globalBaseAtomic] : slow_worker_->dataPlane->globalBaseAtomics) { - (void)socketId; + YANET_GCC_BUG_UNUSED(socketId); dataplane::globalBase::fw_state_value_t* lookup_value = nullptr; dataplane::spinlock_nonrecursive_t* locker = nullptr; diff --git a/libfwparser/fw_config.cpp b/libfwparser/fw_config.cpp index 091e978f..c2459d40 100644 --- a/libfwparser/fw_config.cpp +++ b/libfwparser/fw_config.cpp @@ -269,7 +269,7 @@ void fw_config_t::set_fqdn(const std::string& s) location = {(unsigned int)l.begin.line, m_fileno.top()}; addresses.clear(); - (void)used; + YANET_GCC_BUG_UNUSED(used); } else { @@ -647,7 +647,7 @@ void fw_config_t::add_rule_table(const std::string& name) for (const auto& [prefix, label] : std::get(table)) { - (void)label; + YANET_GCC_BUG_UNUSED(label); add_rule_addr(prefix); } } @@ -1197,7 +1197,7 @@ bool fw_config_t::validate() } for (auto& [ruleno, rules] : m_rules) { - (void)ruleno; + YANET_GCC_BUG_UNUSED(ruleno); for (auto rulep : rules) { if (!validate_rule(rulep)) diff --git a/logger/main.cpp b/logger/main.cpp index 38b30422..19ba9f98 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -150,7 +150,7 @@ int runLogger() if (aclConfig != nullptr) { auto& [serial, ifaces, rules] = *aclConfig; - (void)serial; + YANET_GCC_BUG_UNUSED(serial); auto it = ifaces.find(sample->acl_id); if (it != ifaces.end()) diff --git a/parser/fw_dump.cpp b/parser/fw_dump.cpp index 1fcbf41d..c1c75c70 100644 --- a/parser/fw_dump.cpp +++ b/parser/fw_dump.cpp @@ -11,7 +11,7 @@ void fw_dump_t::dump_dnscache() const auto& [lh, addresses, actual] = values; bool comma = false; - (void)lh; + YANET_GCC_BUG_UNUSED(lh); std::cerr << fqdn << " "; for (const auto& addr : addresses) { @@ -33,7 +33,7 @@ void fw_dump_t::dump_tables() { const auto& [lh, table] = values; - (void)lh; + YANET_GCC_BUG_UNUSED(lh); std::cerr << "table " << name << " create type " << types[table.index()] << std::endl; if (std::holds_alternative(table)) { @@ -64,7 +64,7 @@ void fw_dump_t::dump_macros() const auto& [lh, prefixes, used] = values; bool comma = false; - (void)lh; + YANET_GCC_BUG_UNUSED(lh); if (!used) { // comment unused macros @@ -250,7 +250,7 @@ void fw_dump_t::dump_rule(rule_ptr_t rulep) std::cerr << "# via: "; for (const auto& [name, how] : rulep->ifaces) { - (void)how; + YANET_GCC_BUG_UNUSED(how); if (many) std::cerr << " or "; std::cerr << name; @@ -264,7 +264,7 @@ void fw_dump_t::dump_rule(rule_ptr_t rulep) std::cerr << "# via table: "; for (const auto& [how, tables] : rulep->iface_tables) { - (void)how; + YANET_GCC_BUG_UNUSED(how); for (const auto& name : tables) { if (comma) @@ -283,7 +283,7 @@ void fw_dump_t::dump_rules() std::cerr << "#----------------------------------------" << std::endl; for (auto& [ruleno, rules] : m_conf->m_rules) { - (void)ruleno; + YANET_GCC_BUG_UNUSED(ruleno); for (auto rulep : rules) { dump_rule(rulep); From 916427365a7e728cffd712e5e31bc9ffc07b3fdd Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 17:20:32 +0400 Subject: [PATCH 154/195] Use [[maybe_unused]] instead of void cast --- cli/converter.h | 6 ++---- cli/helper.h | 3 +-- controlplane/acl.cpp | 8 ++------ controlplane/balancer.h | 4 +--- controlplane/configconverter.cpp | 4 +--- controlplane/configparser.cpp | 14 ++++---------- controlplane/counter.h | 4 ++-- controlplane/dregress.h | 4 +--- controlplane/fqdn.cpp | 4 +--- controlplane/isystem.cpp | 10 +++------- controlplane/memory_manager.cpp | 6 ++---- controlplane/module.cpp | 15 +++++---------- controlplane/nat46clat.cpp | 4 +--- controlplane/nat64stateful.h | 4 +--- controlplane/rib.cpp | 7 ++----- controlplane/route.h | 4 +--- controlplane/telegraf.cpp | 4 +--- controlplane/telegraf.h | 4 +--- controlplane/tun64.h | 4 +--- dataplane/bus.h | 9 +++------ dataplane/memory_manager.cpp | 3 +-- 21 files changed, 37 insertions(+), 88 deletions(-) diff --git a/cli/converter.h b/cli/converter.h index 29043b32..5d235354 100644 --- a/cli/converter.h +++ b/cli/converter.h @@ -101,9 +101,8 @@ std::string to_string(const std::set& set, } std::string to_string(const bool& value, - const config_t config) + [[maybe_unused]] const config_t config) { - (void)config; if (value) { return "true"; @@ -129,9 +128,8 @@ std::string to_string(const std::string& string, template std::string to_string(const arg_T& value, - const config_t config) + [[maybe_unused]] const config_t config) { - (void)config; if constexpr (std::is_constructible_v) { return value; diff --git a/cli/helper.h b/cli/helper.h index 4d4ceea6..c2e0b8f2 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -153,9 +153,8 @@ void fillValue(std::optional& value) } template -void fillValue(TArg& value) +void fillValue([[maybe_unused]] TArg& value) { - (void)value; throw std::string("invalid arguments count"); } diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 43b1e449..61e1aa44 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -541,7 +541,7 @@ iface_map_t ifaceMapping(std::map& acls, const iface_map_t& ifaces, - const std::optional& module, + [[maybe_unused]] const std::optional& module, const std::optional& direction, const std::optional& network_source, const std::optional& network_destination, @@ -552,8 +552,6 @@ unwind_result unwind(const std::map& acl const std::optional& transport_flags, const std::optional& in_recordstate) { - (void)module; - unwind_result result; try @@ -1023,7 +1021,7 @@ uint8_t string_to_proto(const std::string& string) std::set lookup(const std::map& acls, const iface_map_t& ifaces, - const std::optional& module, + [[maybe_unused]] const std::optional& module, const std::optional& direction, const std::optional& network_source, const std::optional& network_destination, @@ -1032,8 +1030,6 @@ std::set lookup(const std::map const std::optional& transport_source, const std::optional& transport_destination) { - (void)module; - std::set result; try diff --git a/controlplane/balancer.h b/controlplane/balancer.h index 186cc26d..3bcba0cf 100644 --- a/controlplane/balancer.h +++ b/controlplane/balancer.h @@ -38,11 +38,9 @@ class generation_config_t public: generation_config_t() = default; - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - for (const auto& [name, balancer] : base_next.balancers) { name_id[name] = balancer.balancer_id; diff --git a/controlplane/configconverter.cpp b/controlplane/configconverter.cpp index c3bd76a1..a349d938 100644 --- a/controlplane/configconverter.cpp +++ b/controlplane/configconverter.cpp @@ -890,10 +890,8 @@ void config_converter_t::acl_rules_route_local(controlplane::base::acl_t& acl, } void config_converter_t::acl_rules_route_forward(controlplane::base::acl_t& acl, - const std::string& next_module) const + [[maybe_unused]] const std::string& next_module) const { - (void)next_module; - common::globalBase::tFlow flow = convertToFlow(next_module); acl.nextModuleRules.emplace_back(flow); } diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index ebef55eb..a1f373cc 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -501,12 +501,9 @@ void config_parser_t::loadConfig_decap(controlplane::base_t& baseNext, void config_parser_t::loadConfig_nat64stateful(controlplane::base_t& baseNext, const std::string& moduleId, const nlohmann::json& moduleJson, - const std::string& rootFilePath, - const std::map& jsons) + [[maybe_unused]] const std::string& rootFilePath, + [[maybe_unused]] const std::map& jsons) { - (void)rootFilePath; - (void)jsons; - auto& nat64stateful = baseNext.nat64statefuls[moduleId]; nat64stateful_id_t nat64stateful_id = baseNext.nat64statefuls.size(); @@ -1013,12 +1010,9 @@ void config_parser_t::loadConfig_nat64stateless_translations(controlplane::base_ void config_parser_t::loadConfig_nat46clat(controlplane::base_t& baseNext, const std::string& moduleId, const nlohmann::json& moduleJson, - const std::string& rootFilePath, - const std::map& jsons) + [[maybe_unused]] const std::string& rootFilePath, + [[maybe_unused]] const std::map& jsons) { - (void)rootFilePath; - (void)jsons; - auto& nat46clat = baseNext.nat46clats[moduleId]; nat46clat_id_t nat46clat_id = baseNext.nat46clats.size(); diff --git a/controlplane/counter.h b/controlplane/counter.h index 46ba3c7a..126930e3 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -152,7 +152,7 @@ class counter_t void allocate() { - allocate([](const key_T& key) { (void)key; }); + allocate([]([[maybe_unused]] const key_T& key) { }); } template @@ -172,7 +172,7 @@ class counter_t void release() { - release([](const key_T& key) { (void)key; }); + release([]([[maybe_unused]] const key_T& key) { }); } void insert(const key_T& key) diff --git a/controlplane/dregress.h b/controlplane/dregress.h index de0b7864..a512b1b8 100644 --- a/controlplane/dregress.h +++ b/controlplane/dregress.h @@ -29,11 +29,9 @@ class generation_t public: generation_t() = default; - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - routes = base_next.routes; dregresses = base_next.dregresses; diff --git a/controlplane/fqdn.cpp b/controlplane/fqdn.cpp index 0852ca39..503d1ce4 100644 --- a/controlplane/fqdn.cpp +++ b/controlplane/fqdn.cpp @@ -21,10 +21,8 @@ void fqdn_t::reload_before() void fqdn_t::reload(const controlplane::base_t& base_prev, const controlplane::base_t& base_next, - common::idp::updateGlobalBase::request& globalbase) + [[maybe_unused]] common::idp::updateGlobalBase::request& globalbase) { - (void)globalbase; - generations.next().update(base_prev, base_next); } diff --git a/controlplane/isystem.cpp b/controlplane/isystem.cpp index b0fc7e76..8bda05cd 100644 --- a/controlplane/isystem.cpp +++ b/controlplane/isystem.cpp @@ -178,8 +178,7 @@ void system::updateRoute(const uint32_t& network, snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), " nexthop via %s", ipv4_address_t(nexthop).toString().data()); } - int ret = ::system(buffer); - (void)ret; + [[maybe_unused]] int ret = ::system(buffer); } void system::updateRoute(const ip_prefix_t& prefix, @@ -220,8 +219,7 @@ void system::removeRoute(const uint32_t& network, char buffer[512]; snprintf(buffer, sizeof(buffer), "ip route del %s", prefix.toString().data()); - int ret = ::system(buffer); - (void)ret; + [[maybe_unused]] int ret = ::system(buffer); } void system::removeRoute(const ip_prefix_t& prefix) @@ -307,11 +305,9 @@ std::set> system::getLocalIPv6Addresses() return result; } -std::optional system::get_mac_address(const std::string& vrf, +std::optional system::get_mac_address([[maybe_unused]] const std::string& vrf, const ip_address_t& address) { - (void)vrf; ///< @todo: VRF - if (address.is_ipv4()) { std::array neighborMacAddress; diff --git a/controlplane/memory_manager.cpp b/controlplane/memory_manager.cpp index 4f2990d9..a41d1f15 100644 --- a/controlplane/memory_manager.cpp +++ b/controlplane/memory_manager.cpp @@ -2,11 +2,9 @@ using namespace controlplane::memory_manager; -void memory_manager::reload(const base_t& base_prev, +void memory_manager::reload([[maybe_unused]] const base_t& base_prev, const base_t& base_next, - common::idp::updateGlobalBase::request& globalbase) + [[maybe_unused]] common::idp::updateGlobalBase::request& globalbase) { - (void)base_prev; - (void)globalbase; dataplane.memory_manager_update(base_next.root_memory_group); } diff --git a/controlplane/module.cpp b/controlplane/module.cpp index cf4e23c7..2622ea41 100644 --- a/controlplane/module.cpp +++ b/controlplane/module.cpp @@ -62,27 +62,22 @@ void cModule::moduleJoin() join(); } -void cModule::limit(common::icp::limit_summary::response& limits) const +void cModule::limit([[maybe_unused]] common::icp::limit_summary::response& limits) const { - (void)limits; } -void cModule::controlplane_values(common::icp::controlplane_values::response& controlplane_values) const +void cModule::controlplane_values([[maybe_unused]] common::icp::controlplane_values::response& controlplane_values) const { - (void)controlplane_values; } void cModule::reload_before() { } -void cModule::reload(const controlplane::base_t& base_prev, - const controlplane::base_t& base_next, - common::idp::updateGlobalBase::request& globalbase) +void cModule::reload([[maybe_unused]] const controlplane::base_t& base_prev, + [[maybe_unused]] const controlplane::base_t& base_next, + [[maybe_unused]] common::idp::updateGlobalBase::request& globalbase) { - (void)base_prev; - (void)base_next; - (void)globalbase; } void cModule::reload_after() diff --git a/controlplane/nat46clat.cpp b/controlplane/nat46clat.cpp index 2096e579..cdbf0753 100644 --- a/controlplane/nat46clat.cpp +++ b/controlplane/nat46clat.cpp @@ -3,11 +3,9 @@ using namespace nat46clat; -void generation_config::update(const controlplane::base_t& base_prev, +void generation_config::update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - config_nat46clats = base_next.nat46clats; for (const auto& [module_name, nat46clat] : base_next.nat46clats) diff --git a/controlplane/nat64stateful.h b/controlplane/nat64stateful.h index 2b551200..41b5a4bd 100644 --- a/controlplane/nat64stateful.h +++ b/controlplane/nat64stateful.h @@ -19,11 +19,9 @@ using module_counter_key_t = std::string; ///< module_name class generation_config_t { public: - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - config_nat64statefuls = base_next.nat64statefuls; for (const auto& [name, nat64stateful] : base_next.nat64statefuls) diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index 83182c63..c6681376 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -64,13 +64,10 @@ eResult rib_t::init() return eResult::success; } -void rib_t::reload(const controlplane::base_t& base_prev, +void rib_t::reload([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next, - common::idp::updateGlobalBase::request& globalbase) + [[maybe_unused]] common::idp::updateGlobalBase::request& globalbase) { - (void)base_prev; - (void)globalbase; - common::icp::rib_update::request request; { diff --git a/controlplane/route.h b/controlplane/route.h index 43b479c5..890bb7e9 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -100,11 +100,9 @@ class generation_t public: generation_t() = default; - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - routes = base_next.routes; for (const auto& [module_name, route] : base_next.routes) diff --git a/controlplane/telegraf.cpp b/controlplane/telegraf.cpp index 2066a0eb..23fa46fe 100644 --- a/controlplane/telegraf.cpp +++ b/controlplane/telegraf.cpp @@ -88,10 +88,8 @@ void telegraf_t::reload_before() void telegraf_t::reload(const controlplane::base_t& base_prev, const controlplane::base_t& base_next, - common::idp::updateGlobalBase::request& globalbase) + [[maybe_unused]] common::idp::updateGlobalBase::request& globalbase) { - (void)globalbase; - generations.next().update(base_prev, base_next); } diff --git a/controlplane/telegraf.h b/controlplane/telegraf.h index ff44c287..34f9f3b4 100644 --- a/controlplane/telegraf.h +++ b/controlplane/telegraf.h @@ -18,11 +18,9 @@ class generation_t public: generation_t() = default; - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - for (const auto& [module_name, dregress] : base_next.dregresses) { YANET_GCC_BUG_UNUSED(module_name); diff --git a/controlplane/tun64.h b/controlplane/tun64.h index 2ed76c07..bd2a2b49 100644 --- a/controlplane/tun64.h +++ b/controlplane/tun64.h @@ -16,11 +16,9 @@ namespace tun64 class generation_config_t { public: - void update(const controlplane::base_t& base_prev, + void update([[maybe_unused]] const controlplane::base_t& base_prev, const controlplane::base_t& base_next) { - (void)base_prev; - config_tunnels = base_next.tunnels; } diff --git a/dataplane/bus.h b/dataplane/bus.h index acf699dc..450b1c47 100644 --- a/dataplane/bus.h +++ b/dataplane/bus.h @@ -21,9 +21,8 @@ class cBus void clientThread(int clientSocket); protected: - void call(void (cControlPlane::*function)(), const common::idp::request& request) + void call(void (cControlPlane::*function)(), [[maybe_unused]] const common::idp::request& request) { - (void)request; ///< @todo: [[maybe_unused]] (controlPlane->*function)(); } @@ -34,16 +33,14 @@ class cBus } template - TResult callWithResponse(TResult (cControlPlane::*function)(), const common::idp::request& request) + TResult callWithResponse(TResult (cControlPlane::*function)(), [[maybe_unused]] const common::idp::request& request) { - (void)request; ///< @todo: [[maybe_unused]] return (controlPlane->*function)(); } template - TResult callWithResponse(TResult (cControlPlane::*function)() const, const common::idp::request& request) const + TResult callWithResponse(TResult (cControlPlane::*function)() const, [[maybe_unused]] const common::idp::request& request) const { - (void)request; ///< @todo: [[maybe_unused]] return (controlPlane->*function)(); } diff --git a/dataplane/memory_manager.cpp b/dataplane/memory_manager.cpp index 02cbec3e..f59ffc45 100644 --- a/dataplane/memory_manager.cpp +++ b/dataplane/memory_manager.cpp @@ -218,7 +218,6 @@ bool memory_manager::check_memory_limit(const std::string& name, return result; } -void memory_manager::limits(common::idp::limits::response& response) +void memory_manager::limits([[maybe_unused]] common::idp::limits::response& response) { - (void)response; } From 43805ab8971520b0ddb9a30cb51c84a976463d27 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 17:42:38 +0400 Subject: [PATCH 155/195] Update clang-format version from 10 to 18 in GitHub workflow --- .github/workflows/docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index a884deb1..f4db89f5 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -14,7 +14,7 @@ jobs: - name: Run clang-format style check uses: jidicula/clang-format-action@v4.11.0 with: - clang-format-version: '10' + clang-format-version: '18' exclude-regex: .*\.proto build-unittest: From 0750f6225f169e6f3d3141de190433a5105bdccd Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 17:23:00 +0400 Subject: [PATCH 156/195] Apply clang-format-18 to all files changed so far --- autotest/autotest.cpp | 4 ++-- autotest/main.cpp | 3 +-- cli/develop.h | 4 ---- cli/telegraf.h | 4 ++-- common/balancer.h | 1 - common/controlplaneconfig.h | 6 ++--- common/define.h | 1 - common/generation.h | 4 ++-- common/icp.h | 2 -- common/icp_proto.h | 1 - common/idp.h | 1 - common/neighbor.h | 1 - common/result.h | 1 - common/rpc_controller.h | 2 +- common/scheduler.h | 1 - common/sdpclient.h | 4 ++-- common/sendrecv.h | 4 ++-- common/shared_memory.h | 2 +- common/stream.h | 1 - common/tsc_deltas.h | 4 ---- common/type.h | 40 +++++++++++++++----------------- controlplane/acl/bitset.h | 4 ++-- controlplane/acl/dict.h | 1 - controlplane/balancer.cpp | 14 +++++------ controlplane/bus.h | 1 - controlplane/configconverter.cpp | 2 +- controlplane/configconverter.h | 4 ++-- controlplane/controlplane.h | 2 +- controlplane/counter.h | 8 +++---- controlplane/isystem.cpp | 6 ++--- controlplane/main.cpp | 3 +-- controlplane/protobus.h | 3 --- controlplane/rib.cpp | 4 ++-- controlplane/rib.h | 2 +- controlplane/segment_allocator.h | 1 - controlplane/telegraf.cpp | 3 +-- controlplane/type.h | 1 - dataplane/checksum.h | 1 - dataplane/config_values.h | 1 - dataplane/dataplane.cpp | 4 ++-- dataplane/dregress.cpp | 1 - dataplane/flat.h | 1 - dataplane/fragmentation.h | 1 - dataplane/icmp_translations.cpp | 2 +- dataplane/neighbor.cpp | 3 +-- dataplane/report.cpp | 2 -- dataplane/samples.h | 2 +- dataplane/sock_dev.h | 2 +- dataplane/type.h | 6 ++--- dataplane/worker.h | 2 +- dataplane/worker_gc.cpp | 8 +++---- librib/libyabird.h | 2 +- logger/main.cpp | 2 +- parser/fw_dump.h | 2 +- parser/main.cpp | 12 +++++----- 55 files changed, 82 insertions(+), 122 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index 86eb3d6d..f983150a 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include #include @@ -409,7 +409,7 @@ class TextDumper class PcapDumper { public: - PcapDumper(std::string path, int capsize = MAX_PACK_LEN) : + PcapDumper(std::string path, int capsize = MAX_PACK_LEN) : tmpFilePath(std::move(path)), pcap(pcap_open_dead(DLT_EN10MB, capsize)) { diff --git a/autotest/main.cpp b/autotest/main.cpp index 2c8df810..f007132d 100644 --- a/autotest/main.cpp +++ b/autotest/main.cpp @@ -1,6 +1,5 @@ #include - #include "common/result.h" #include "autotest.h" @@ -44,7 +43,7 @@ int main(int argc, /** @todo if (signal(SIGINT, handleSignal) == SIG_ERR) { - return 3; + return 3; } */ diff --git a/cli/develop.h b/cli/develop.h index beb7e46a..8d961ed0 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -13,8 +13,6 @@ #include "helper.h" - - namespace develop::dataplane { @@ -366,5 +364,3 @@ void tsc_monitoring() } } - - diff --git a/cli/telegraf.h b/cli/telegraf.h index 46520abd..577d5f0a 100644 --- a/cli/telegraf.h +++ b/cli/telegraf.h @@ -711,7 +711,7 @@ void main_counters() { std::vector values; auto* buffer = common::sdp::ShiftBuffer(worker_info.buffer, - sdp_data.metadata_worker.start_counters); + sdp_data.metadata_worker.start_counters); for (const auto& [name, index] : sdp_data.metadata_worker.counter_positions) { values.emplace_back(name.data(), buffer[index]); @@ -723,7 +723,7 @@ void main_counters() { std::vector values; auto* buffer = common::sdp::ShiftBuffer(worker_info.buffer, - sdp_data.metadata_worker.start_counters); + sdp_data.metadata_worker.start_counters); for (const auto& [name, index] : sdp_data.metadata_worker_gc.counter_positions) { values.emplace_back(name.data(), buffer[index]); diff --git a/common/balancer.h b/common/balancer.h index 4b032527..ae308414 100644 --- a/common/balancer.h +++ b/common/balancer.h @@ -1,6 +1,5 @@ #pragma once - #include namespace balancer { diff --git a/common/controlplaneconfig.h b/common/controlplaneconfig.h index 0b2a9bab..0ee8ec01 100644 --- a/common/controlplaneconfig.h +++ b/common/controlplaneconfig.h @@ -250,8 +250,7 @@ class config_t namespace balancer { -[[maybe_unused]] -static uint8_t to_proto(const std::string& string) +[[maybe_unused]] static uint8_t to_proto(const std::string& string) { if (string == "tcp") { @@ -265,8 +264,7 @@ static uint8_t to_proto(const std::string& string) return 0; } -[[maybe_unused]] -constexpr const char* from_proto(const uint8_t& proto) +[[maybe_unused]] constexpr const char* from_proto(const uint8_t& proto) { switch (proto) { diff --git a/common/define.h b/common/define.h index 337ccbcc..130d9555 100644 --- a/common/define.h +++ b/common/define.h @@ -9,7 +9,6 @@ #include #include - /** * GCC 7.5 version which we have to support for now due to Ubuntu 18 have a bug * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81767) where unused variables diff --git a/common/generation.h b/common/generation.h index 26ab14e6..fd93a097 100644 --- a/common/generation.h +++ b/common/generation.h @@ -123,7 +123,7 @@ class generation_manager /** dangerous generation_shared current_shared() const { - return generation_shared(¤t_mutex, this); + return generation_shared(¤t_mutex, this); } */ @@ -145,7 +145,7 @@ class generation_manager /** dangerous generation_unique next_unique() { - return generation_unique(&next_mutex, this); + return generation_unique(&next_mutex, this); } */ diff --git a/common/icp.h b/common/icp.h index 3b42b287..d5103a29 100644 --- a/common/icp.h +++ b/common/icp.h @@ -15,7 +15,6 @@ #include "result.h" #include "type.h" - namespace common::icp { @@ -1020,4 +1019,3 @@ using response = std::variant, convert::response, counters_stat::response>; } - diff --git a/common/icp_proto.h b/common/icp_proto.h index f8254b2b..25bd18d2 100644 --- a/common/icp_proto.h +++ b/common/icp_proto.h @@ -1,6 +1,5 @@ #pragma once - namespace common::icp_proto { constexpr inline char socketPath[] = "/run/yanet/protocontrolplane.sock"; diff --git a/common/idp.h b/common/idp.h index 83831459..8719cd0d 100644 --- a/common/idp.h +++ b/common/idp.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include diff --git a/common/neighbor.h b/common/neighbor.h index d6e306ee..7037ae5f 100644 --- a/common/neighbor.h +++ b/common/neighbor.h @@ -1,6 +1,5 @@ #pragma once - #include namespace common::neighbor { diff --git a/common/result.h b/common/result.h index 0f932ec8..e60719bc 100644 --- a/common/result.h +++ b/common/result.h @@ -1,6 +1,5 @@ #pragma once - #include namespace common diff --git a/common/rpc_controller.h b/common/rpc_controller.h index 5b9c388c..2f383a1c 100644 --- a/common/rpc_controller.h +++ b/common/rpc_controller.h @@ -11,7 +11,7 @@ class RpcController : public google::protobuf::RpcController { public: RpcController() { _reset(); } - ~RpcController() override = default; + ~RpcController() override = default; virtual void Reset() { diff --git a/common/scheduler.h b/common/scheduler.h index f02c745f..6fe773ac 100644 --- a/common/scheduler.h +++ b/common/scheduler.h @@ -1,6 +1,5 @@ #pragma once - #include namespace balancer { diff --git a/common/sdpclient.h b/common/sdpclient.h index 7150199e..990cb31a 100644 --- a/common/sdpclient.h +++ b/common/sdpclient.h @@ -178,7 +178,7 @@ class SdpClient if (!core_id.has_value() || worker_core_id == core_id) { auto* counters = common::sdp::ShiftBuffer(worker_info.buffer, - sdp_data.metadata_worker.start_counters); + sdp_data.metadata_worker.start_counters); result[worker_core_id] = counters[index]; } } @@ -194,7 +194,7 @@ class SdpClient if (!core_id.has_value() || worker_core_id == core_id) { auto* counters = common::sdp::ShiftBuffer(worker_info.buffer, - sdp_data.metadata_worker.start_counters); + sdp_data.metadata_worker.start_counters); result[worker_core_id] = counters[index]; } } diff --git a/common/sendrecv.h b/common/sendrecv.h index d2a4963a..d2435214 100644 --- a/common/sendrecv.h +++ b/common/sendrecv.h @@ -2,8 +2,8 @@ #include -#include #include +#include #include #include #include @@ -118,7 +118,7 @@ static int send(int clientSocket, Req&& request) } template -static inline Resp recv(int clientSocket) //unsafe +static inline Resp recv(int clientSocket) // unsafe { std::vector buffer; diff --git a/common/shared_memory.h b/common/shared_memory.h index c465c4c6..e601c8be 100644 --- a/common/shared_memory.h +++ b/common/shared_memory.h @@ -1,10 +1,10 @@ #pragma once +#include #include #include #include #include -#include #include #include #include diff --git a/common/stream.h b/common/stream.h index 4f882547..b3254f1c 100644 --- a/common/stream.h +++ b/common/stream.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include diff --git a/common/tsc_deltas.h b/common/tsc_deltas.h index c4252601..bb108125 100644 --- a/common/tsc_deltas.h +++ b/common/tsc_deltas.h @@ -13,8 +13,6 @@ #define YANET_TSC_BINS_SHIFT 2 #define YANET_TSC_BINS_N 4 - - namespace dataplane::perf { @@ -110,5 +108,3 @@ static_assert(std::is_pod_v == true, "tsc structure is not pod"); } - - diff --git a/common/type.h b/common/type.h index d147ad48..488cc279 100644 --- a/common/type.h +++ b/common/type.h @@ -11,11 +11,11 @@ #include #include +#include "config.release.h" #include "ctree.h" #include "define.h" #include "stream.h" #include "uint128.h" -#include "config.release.h" using tCoreId = uint32_t; using tSocketId = uint32_t; @@ -198,12 +198,12 @@ class mac_address_t return address < second.address; } - constexpr operator const std::array &() const + constexpr operator const std::array&() const { return address; } - constexpr operator std::array &() + constexpr operator std::array&() { return address; } @@ -421,12 +421,12 @@ class ipv6_address_t return !memcmp(address.data(), second.address.data(), address.size()); } - constexpr operator const std::array &() const + constexpr operator const std::array&() const { return address; } - constexpr operator std::array &() + constexpr operator std::array&() { return address; } @@ -609,12 +609,12 @@ class ip_address_t return !(address == second.address); } - constexpr operator const std::variant &() const + constexpr operator const std::variant&() const { return address; } - constexpr operator std::variant &() + constexpr operator std::variant&() { return address; } @@ -754,12 +754,12 @@ class ipv4_prefix_t return prefix > second.prefix; } - constexpr operator const std::tuple &() const + constexpr operator const std::tuple&() const { return prefix; } - constexpr operator std::tuple &() + constexpr operator std::tuple&() { return prefix; } @@ -967,12 +967,12 @@ class ipv6_prefix_t return prefix > second.prefix; } - constexpr operator const std::tuple &() const + constexpr operator const std::tuple&() const { return prefix; } - constexpr operator std::tuple &() + constexpr operator std::tuple&() { return prefix; } @@ -1246,12 +1246,12 @@ class ip_prefix_t return prefix == second.prefix; } - constexpr operator const std::variant &() const + constexpr operator const std::variant&() const { return prefix; } - constexpr operator std::variant &() + constexpr operator std::variant&() { return prefix; } @@ -1632,12 +1632,12 @@ class large_community_t return value == second.value; } - constexpr operator const std::array &() const + constexpr operator const std::array&() const { return value; } - constexpr operator std::array &() + constexpr operator std::array&() { return value; } @@ -1678,12 +1678,12 @@ class values_t insertHelper(args...); } - operator const std::set &() const + operator const std::set&() const { return values; } - operator std::set &() + operator std::set&() { return values; } @@ -1760,12 +1760,12 @@ class range_t return range < second.range; } - constexpr operator const std::tuple &() const + constexpr operator const std::tuple&() const { return range; } - constexpr operator std::tuple &() + constexpr operator std::tuple&() { return range; } @@ -1983,7 +1983,6 @@ constexpr ipv6_prefix_t ipv6_prefix_default = {ipv6_address_default, 0}; // - namespace worker::stats { struct common @@ -2032,7 +2031,6 @@ struct port }; } - namespace worker_gc { struct stats_t diff --git a/controlplane/acl/bitset.h b/controlplane/acl/bitset.h index 2d9c6232..f4558a03 100644 --- a/controlplane/acl/bitset.h +++ b/controlplane/acl/bitset.h @@ -135,7 +135,7 @@ struct bitset_t } [[nodiscard]] std::tuple minAnd(const bitset_t& p1, - const bitset_t& p2) const + const bitset_t& p2) const { for (size_t i = std::max(std::max(first_one, p1.first_one), p2.first_one); i < size; ++i) { @@ -207,7 +207,7 @@ struct bitset_t } }; -} //namespace acl +} // namespace acl namespace std { diff --git a/controlplane/acl/dict.h b/controlplane/acl/dict.h index ee023d79..62d29e24 100644 --- a/controlplane/acl/dict.h +++ b/controlplane/acl/dict.h @@ -1,6 +1,5 @@ #pragma once - #include "bitset.h" #include "network.h" #include "rule.h" diff --git a/controlplane/balancer.cpp b/controlplane/balancer.cpp index 9073cb6b..a50aee80 100644 --- a/controlplane/balancer.cpp +++ b/controlplane/balancer.cpp @@ -160,13 +160,13 @@ void balancer_t::Real( for (const auto& real : req->reals()) { request.emplace_back(real.module(), - convert_to_ip_address(real.virtual_ip()), - real.proto() == common::icp_proto::NetProto::tcp ? IPPROTO_TCP : IPPROTO_UDP, - real.virtual_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::VirtualPortOptCase::kVirtualPort ? std::make_optional(real.virtual_port()) : std::nullopt, - convert_to_ip_address(real.real_ip()), - real.real_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::RealPortOptCase::kRealPort ? std::make_optional(real.real_port()) : std::nullopt, - real.enable(), - real.weight_opt_case() == common::icp_proto::BalancerRealRequest_Real::WeightOptCase::kWeight ? std::make_optional(real.weight()) : std::nullopt); + convert_to_ip_address(real.virtual_ip()), + real.proto() == common::icp_proto::NetProto::tcp ? IPPROTO_TCP : IPPROTO_UDP, + real.virtual_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::VirtualPortOptCase::kVirtualPort ? std::make_optional(real.virtual_port()) : std::nullopt, + convert_to_ip_address(real.real_ip()), + real.real_port_opt_case() == common::icp_proto::BalancerRealRequest_Real::RealPortOptCase::kRealPort ? std::make_optional(real.real_port()) : std::nullopt, + real.enable(), + real.weight_opt_case() == common::icp_proto::BalancerRealRequest_Real::WeightOptCase::kWeight ? std::make_optional(real.weight()) : std::nullopt); } balancer_real(request); diff --git a/controlplane/bus.h b/controlplane/bus.h index 5a458a9d..3f4f7aed 100644 --- a/controlplane/bus.h +++ b/controlplane/bus.h @@ -1,6 +1,5 @@ #pragma once - #include "module.h" namespace controlplane::module diff --git a/controlplane/configconverter.cpp b/controlplane/configconverter.cpp index a349d938..7062dcdb 100644 --- a/controlplane/configconverter.cpp +++ b/controlplane/configconverter.cpp @@ -6,8 +6,8 @@ #include #include "acl.h" -#include "errors.h" #include "configconverter.h" +#include "errors.h" eResult config_converter_t::process(uint32_t serial) { diff --git a/controlplane/configconverter.h b/controlplane/configconverter.h index e1dc3467..7b5751d9 100644 --- a/controlplane/configconverter.h +++ b/controlplane/configconverter.h @@ -10,8 +10,8 @@ class config_converter_t { public: config_converter_t(cControlPlane* controlplane, - controlplane::base_t baseNext, - common::idp::limits::response limits) : + controlplane::base_t baseNext, + common::idp::limits::response limits) : controlplane(controlplane), baseNext(std::move(baseNext)), limits(std::move(limits)) diff --git a/controlplane/controlplane.h b/controlplane/controlplane.h index e69f7e1a..7f98d1a6 100644 --- a/controlplane/controlplane.h +++ b/controlplane/controlplane.h @@ -8,12 +8,12 @@ #include +#include "balancer.h" #include "common/generation.h" #include "common/icp.h" #include "common/idataplane.h" #include "common/idp.h" #include "common/result.h" -#include "balancer.h" #include "dregress.h" #include "durations.h" #include "fqdn.h" diff --git a/controlplane/counter.h b/controlplane/counter.h index 126930e3..c0a8acd6 100644 --- a/controlplane/counter.h +++ b/controlplane/counter.h @@ -1,10 +1,10 @@ #pragma once -#include #include "common/icp.h" -#include "common/sdpcommon.h" #include "common/sdpclient.h" +#include "common/sdpcommon.h" #include "segment_allocator.h" +#include class counter_manager_t { @@ -152,7 +152,7 @@ class counter_t void allocate() { - allocate([]([[maybe_unused]] const key_T& key) { }); + allocate([]([[maybe_unused]] const key_T& key) {}); } template @@ -172,7 +172,7 @@ class counter_t void release() { - release([]([[maybe_unused]] const key_T& key) { }); + release([]([[maybe_unused]] const key_T& key) {}); } void insert(const key_T& key) diff --git a/controlplane/isystem.cpp b/controlplane/isystem.cpp index 8bda05cd..b3182d7d 100644 --- a/controlplane/isystem.cpp +++ b/controlplane/isystem.cpp @@ -1,12 +1,12 @@ +#include +#include +#include #include #include #include #include #include #include -#include -#include -#include #include #include #include diff --git a/controlplane/main.cpp b/controlplane/main.cpp index 82af705d..7abb8577 100644 --- a/controlplane/main.cpp +++ b/controlplane/main.cpp @@ -1,7 +1,6 @@ #include #include - #include "controlplane.h" cControlPlane application; @@ -48,7 +47,7 @@ int main(int argc, /** @todo if (signal(SIGINT, handleSignal) == SIG_ERR) { - return 3; + return 3; } */ diff --git a/controlplane/protobus.h b/controlplane/protobus.h index a9c2e100..e24b7c4f 100644 --- a/controlplane/protobus.h +++ b/controlplane/protobus.h @@ -1,9 +1,7 @@ #pragma once - #include "module.h" - namespace controlplane::module { @@ -25,4 +23,3 @@ class protoBus : public cModule }; } - diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index c6681376..2576a699 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -568,14 +568,14 @@ void rib_t::rib_flush(bool force_flush) controlPlane->route.prefix_update(vrf_priority, updated_prefix, proto_peer_table_name, destination); controlPlane->route.tunnel_prefix_update(vrf_priority, updated_prefix, destination); - //controlPlane->route.linux_prefix_update(vrf_priority, updated_prefix, destination); + // controlPlane->route.linux_prefix_update(vrf_priority, updated_prefix, destination); controlPlane->dregress.prefix_insert(vrf_priority, updated_prefix, destination); } else { controlPlane->route.prefix_update(vrf_priority, updated_prefix, {}, std::monostate()); // TODO: get rid of third parameter controlPlane->route.tunnel_prefix_update(vrf_priority, updated_prefix, std::monostate()); - //controlPlane->route.linux_prefix_update(vrf_priority, updated_prefix, std::monostate()); + // controlPlane->route.linux_prefix_update(vrf_priority, updated_prefix, std::monostate()); controlPlane->dregress.prefix_remove(vrf_priority, updated_prefix); } } diff --git a/controlplane/rib.h b/controlplane/rib.h index ccf5ea6a..5013421e 100644 --- a/controlplane/rib.h +++ b/controlplane/rib.h @@ -1,8 +1,8 @@ #pragma once #include "module.h" -#include #include +#include namespace rib { diff --git a/controlplane/segment_allocator.h b/controlplane/segment_allocator.h index 7000d473..5250ef12 100644 --- a/controlplane/segment_allocator.h +++ b/controlplane/segment_allocator.h @@ -4,7 +4,6 @@ #include #include - #define ENABLE_BIT(v, b) (v) |= ((uint64_t)1) << (b) #define GET_BIT(v, b) (((v) >> (b)) & 1) #define DISABLE_BIT(v, b) (v) &= ~(((uint64_t)1) << (b)) diff --git a/controlplane/telegraf.cpp b/controlplane/telegraf.cpp index 23fa46fe..05dc955f 100644 --- a/controlplane/telegraf.cpp +++ b/controlplane/telegraf.cpp @@ -4,8 +4,7 @@ using common::int64; using controlplane::module::telegraf; -[[maybe_unused]] -static inline double perSecond(const int64_t& valueDiff, const uint64_t& timeDiff) +[[maybe_unused]] static inline double perSecond(const int64_t& valueDiff, const uint64_t& timeDiff) { if (timeDiff == 0) { diff --git a/controlplane/type.h b/controlplane/type.h index 11f00514..ae408d95 100644 --- a/controlplane/type.h +++ b/controlplane/type.h @@ -1,6 +1,5 @@ #pragma once - #include "common/type.h" class cControlPlane; diff --git a/dataplane/checksum.h b/dataplane/checksum.h index f9e9cae3..6ed34cec 100644 --- a/dataplane/checksum.h +++ b/dataplane/checksum.h @@ -1,6 +1,5 @@ #pragma once - #include #include #include diff --git a/dataplane/config_values.h b/dataplane/config_values.h index 61256c4c..60103499 100644 --- a/dataplane/config_values.h +++ b/dataplane/config_values.h @@ -4,7 +4,6 @@ #include #include - struct FragmentationConfig { uint64_t size = 1024; diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 06356ef0..6ab8191e 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1,8 +1,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -33,8 +33,8 @@ #include "common/idp.h" #include "common/result.h" #include "common/tsc_deltas.h" -#include "dataplane/sdpserver.h" #include "dataplane.h" +#include "dataplane/sdpserver.h" #include "globalbase.h" #include "sock_dev.h" #include "work_runner.h" diff --git a/dataplane/dregress.cpp b/dataplane/dregress.cpp index 2bfefdb5..c833aa01 100644 --- a/dataplane/dregress.cpp +++ b/dataplane/dregress.cpp @@ -1,7 +1,6 @@ #include #include - #include "checksum.h" #include "dataplane.h" #include "dregress.h" diff --git a/dataplane/flat.h b/dataplane/flat.h index aba57ff1..42f8c2ea 100644 --- a/dataplane/flat.h +++ b/dataplane/flat.h @@ -1,6 +1,5 @@ #pragma once - #include #include "common/define.h" diff --git a/dataplane/fragmentation.h b/dataplane/fragmentation.h index 8c855a74..ec4459bd 100644 --- a/dataplane/fragmentation.h +++ b/dataplane/fragmentation.h @@ -1,6 +1,5 @@ #pragma once - #include #include diff --git a/dataplane/icmp_translations.cpp b/dataplane/icmp_translations.cpp index b4ffb78a..7151a525 100644 --- a/dataplane/icmp_translations.cpp +++ b/dataplane/icmp_translations.cpp @@ -1,6 +1,6 @@ +#include "icmp_translations.h" #include "checksum.h" #include "dataplane/icmp.h" -#include "icmp_translations.h" #include "metadata.h" namespace dataplane diff --git a/dataplane/neighbor.cpp b/dataplane/neighbor.cpp index cb20553e..d0b857b3 100644 --- a/dataplane/neighbor.cpp +++ b/dataplane/neighbor.cpp @@ -193,8 +193,7 @@ static void netlink_neighbor_dump(const std::function #include -//#define SOCK_DEV_PREFIX "sock_dev:" +// #define SOCK_DEV_PREFIX "sock_dev:" using namespace std::string_literals; const std::string SOCK_DEV_PREFIX = "sock_dev:"s; diff --git a/dataplane/type.h b/dataplane/type.h index e318eada..cf55b213 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -581,9 +581,9 @@ struct balancer_service_t uint32_t wlc_power; /* - outer_source_network_flag: - zero byte stores the state for ipv4_router_source_network - first byte stores the state for ipv6_router_source_network + outer_source_network_flag: + zero byte stores the state for ipv4_router_source_network + first byte stores the state for ipv6_router_source_network */ uint8_t outer_source_network_flag; ipv4_prefix_t ipv4_outer_source_network; diff --git a/dataplane/worker.h b/dataplane/worker.h index d75176a4..57e97976 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -32,7 +32,7 @@ template class tStack { public: - tStack() = default; + tStack() = default; inline void insert(rte_mbuf** mbufs, unsigned int mbufsCount) { diff --git a/dataplane/worker_gc.cpp b/dataplane/worker_gc.cpp index 936ccd64..2a645aa4 100644 --- a/dataplane/worker_gc.cpp +++ b/dataplane/worker_gc.cpp @@ -278,7 +278,7 @@ void worker_gc_t::handle_nat64stateful_gc() /// check lan tables for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - if (globalbase_atomic == nullptr) + if (globalbase_atomic == nullptr) { break; } @@ -424,7 +424,7 @@ void worker_gc_t::handle_balancer_gc() for (auto globalbase_atomic_other : base_permanently.globalBaseAtomics) { - if (globalbase_atomic_other == nullptr) + if (globalbase_atomic_other == nullptr) { break; } @@ -978,7 +978,7 @@ void worker_gc_t::nat64stateful_remove_state(const dataplane::globalBase::nat64s /// remove on other numas for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - if (globalbase_atomic == base_permanently.globalBaseAtomic) + if (globalbase_atomic == base_permanently.globalBaseAtomic) { continue; } @@ -1129,7 +1129,7 @@ void worker_gc_t::nat64stateful_state(const common::idp::nat64stateful_state::re /// check lan tables for (auto globalbase_atomic : base_permanently.globalBaseAtomics) { - if (globalbase_atomic == nullptr) + if (globalbase_atomic == nullptr) { break; } diff --git a/librib/libyabird.h b/librib/libyabird.h index 2df72c03..464794e0 100644 --- a/librib/libyabird.h +++ b/librib/libyabird.h @@ -97,7 +97,7 @@ extern "C" }; #else /* __cplusplus */ -//#define YANET_DEBUG +// #define YANET_DEBUG #ifdef YANET_DEBUG #include diff --git a/logger/main.cpp b/logger/main.cpp index 19ba9f98..ce2ba93d 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include diff --git a/parser/fw_dump.h b/parser/fw_dump.h index ea0598f4..1b74f5aa 100644 --- a/parser/fw_dump.h +++ b/parser/fw_dump.h @@ -1,7 +1,7 @@ #pragma once -#include "libfwparser/fw_parser.h" #include "libfwparser/fw_config.h" +#include "libfwparser/fw_parser.h" #include namespace ipfw diff --git a/parser/main.cpp b/parser/main.cpp index d2acd485..d06dc146 100644 --- a/parser/main.cpp +++ b/parser/main.cpp @@ -98,12 +98,12 @@ int main(int argc, char* argv[]) config->set_debug(verbose_level); /* - * For -c option we concatenate all remaining arguments into - * single spaces delimited string and pass it to the parser. - * - * NOTE: the order of scheduled files is matter. DNS cache - * should be scheduled last, then it will be processed first. - */ + * For -c option we concatenate all remaining arguments into + * single spaces delimited string and pass it to the parser. + * + * NOTE: the order of scheduled files is matter. DNS cache + * should be scheduled last, then it will be processed first. + */ if (cmd_mode) { /* Rule from command line arguments */ From c9cfb457c8df563a1952eac50a9a8110ba2faaa7 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 18:50:56 +0400 Subject: [PATCH 157/195] Replace it.second in loops with structured bindings with meaningful names Improves readability --- dataplane/controlplane.cpp | 15 +++++++++------ dataplane/dataplane.cpp | 16 ++++++++++------ dataplane/globalbase.cpp | 25 +++++++++++++++---------- logger/main.cpp | 9 +++++---- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index d464d10a..2165ac6f 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -305,9 +305,10 @@ common::idp::get_dregress_counters::response cControlPlane::get_dregress_counter { common::dregress::counters_t counters_v4; common::dregress::counters_t counters_v6; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + dregress_t& dregress = slow->Dregress(); auto guard = dregress.LockCounters(); counters_v4.merge(dregress.Counters4()); counters_v6.merge(dregress.Counters6()); @@ -403,9 +404,10 @@ common::idp::getControlPlanePortStats::response cControlPlane::getControlPlanePo else { /// all ports - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - const auto& kni_worker = it.second->KniWorker(); + YANET_GCC_BUG_UNUSED(core); + const auto& kni_worker = slow->KniWorker(); auto stats = kni_worker.PortsStats().first; for (auto [current, end] = kni_worker.PortsIds(); current != end; ++current, ++stats) @@ -444,9 +446,10 @@ common::dregress::stats_t cControlPlane::DregressStats() const std::optional> cControlPlane::KniStats(tPortId pid) const { // Dumb iteration over slow workers and their assigned ports, should not be a bottleneck - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - if (const auto& stats = it.second->KniWorker().PortStats(pid)) + YANET_GCC_BUG_UNUSED(core); + if (const auto& stats = slow->KniWorker().PortStats(pid)) { return stats; } diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 6ab8191e..9d572ff0 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -30,6 +30,7 @@ #include #include "common.h" +#include "common/define.h" #include "common/idp.h" #include "common/result.h" #include "common/tsc_deltas.h" @@ -65,9 +66,10 @@ cDataPlane::~cDataPlane() { rte_mempool_free(mempool_log); } - for (auto it : socket_cplane_mempools) + for (auto& [socket_id, rte_mempool] : socket_cplane_mempools) { - rte_mempool_free(it.second); + YANET_GCC_BUG_UNUSED(socket_id); + rte_mempool_free(rte_mempool); } } @@ -1429,9 +1431,10 @@ void cDataPlane::SWRateLimiterTimeTracker() __atomic_store_n(&worker->packetsToSWNPRemainder, config.SWNormalPriorityRateLimitPerWorker, __ATOMIC_RELAXED); } - for (auto it : slow_workers) + for (auto& [core, slow] : slow_workers) { - it.second->ResetIcmpOutRemainder(config.SWICMPOutRateLimit / config.rateLimitDivisor); + YANET_GCC_BUG_UNUSED(core); + slow->ResetIcmpOutRemainder(config.SWICMPOutRateLimit / config.rateLimitDivisor); } prevTimePointForSWRateLimiter = curTimePointForSWRateLimiter; @@ -2162,9 +2165,10 @@ nlohmann::json cDataPlane::makeLegacyControlPlaneWorkerConfig() const std::set cDataPlane::FastWorkerCores() const { std::set cores; - for (auto it : config.workers) + for (auto& [core, workers] : config.workers) { - if (!cores.insert(it.first).second) + YANET_GCC_BUG_UNUSED(workers); + if (!cores.insert(core).second) { YANET_LOG_ERROR("Same core specified in config for multiple workers\n"); } diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 00bade2c..e199c004 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -2316,9 +2316,10 @@ eResult generation::dregress_prefix_update(const common::idp::updateGlobalBase:: { eResult result = eResult::success; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - ::dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + ::dregress_t& dregress = slow->Dregress(); for (const auto& [prefix, value_id] : request) { std::lock_guard guard(dregress.prefixes_mutex); @@ -2333,9 +2334,10 @@ eResult generation::dregress_prefix_remove(const common::idp::updateGlobalBase:: { eResult result = eResult::success; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - ::dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + ::dregress_t& dregress = slow->Dregress(); for (const auto& prefix : request) { std::lock_guard guard(dregress.prefixes_mutex); @@ -2349,9 +2351,10 @@ eResult generation::dregress_prefix_clear() { eResult result = eResult::success; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - ::dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + ::dregress_t& dregress = slow->Dregress(); std::lock_guard guard(dregress.prefixes_mutex); dregress.prefixes.clear(); } @@ -2363,9 +2366,10 @@ eResult generation::dregress_local_prefix_update(const common::idp::updateGlobal { eResult result = eResult::success; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - ::dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + ::dregress_t& dregress = slow->Dregress(); std::lock_guard guard(dregress.prefixes_mutex); dregress.local_prefixes_v4.clear(); @@ -2390,9 +2394,10 @@ eResult generation::dregress_value_update(const common::idp::updateGlobalBase::d { eResult result = eResult::success; - for (auto it : dataPlane->slow_workers) + for (auto& [core, slow] : dataPlane->slow_workers) { - ::dregress_t& dregress = it.second->Dregress(); + YANET_GCC_BUG_UNUSED(core); + ::dregress_t& dregress = slow->Dregress(); std::lock_guard guard(dregress.prefixes_mutex); for (const auto& [value_id, value] : request) diff --git a/logger/main.cpp b/logger/main.cpp index ce2ba93d..8dd346e8 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -9,6 +9,7 @@ #include #include +#include "common/define.h" #include "common/icontrolplane.h" #include "common/idataplane.h" #include "common/type.h" @@ -41,13 +42,13 @@ int initLogger() auto response = dataplane.getConfig(); auto& workers = std::get<1>(response); - for (auto it : workers) + for (auto& [core, workers_vector] : workers) { - auto coreId = it.first; - auto ring = rte_ring_lookup(("r_log_" + std::to_string(coreId)).c_str()); + YANET_GCC_BUG_UNUSED(workers_vector); + auto ring = rte_ring_lookup(("r_log_" + std::to_string(core)).c_str()); if (ring != nullptr) { - YANET_LOG_DEBUG("found log ring on #%u core\n", coreId); + YANET_LOG_DEBUG("found log ring on #%u core\n", core); rings.push_back(ring); } From 7c1d5340f9b7558e83f504fb765ee655fc0b7560 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:03:17 +0400 Subject: [PATCH 158/195] Add missing braces around initialization of subobject --- dataplane/unittest/ip_address.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataplane/unittest/ip_address.cpp b/dataplane/unittest/ip_address.cpp index 0fcf9fec..aad01afa 100644 --- a/dataplane/unittest/ip_address.cpp +++ b/dataplane/unittest/ip_address.cpp @@ -21,7 +21,7 @@ TEST(IpAddress, Basic) { ipv6_address_t addr = ipv6_address_t::convert(commonAddr); - ipv6_address_t expected{0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}; + ipv6_address_t expected{{{0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}}}; EXPECT_EQ(addr, expected); addr.reset(); From 54a26e6e97dd20b4d667958dfdcf7ffd8e646bcc Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:06:30 +0400 Subject: [PATCH 159/195] Do not create unnecessary temporary object while calling emplace_back --- controlplane/acl.cpp | 4 ++-- controlplane/acl_compiler.cpp | 8 ++++---- controlplane/balancer.cpp | 10 +++------- controlplane/configparser.cpp | 2 +- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/controlplane/acl.cpp b/controlplane/acl.cpp index 61e1aa44..71258421 100644 --- a/controlplane/acl.cpp +++ b/controlplane/acl.cpp @@ -840,14 +840,14 @@ std::vector unwind_used_rules(const std::map& unwind_rules) } else { - network_ipv4_source_filter.emplace(network_t(4, 0, 0)); - network_ipv6_source_filter.emplace(network_t(6, 0, 0)); + network_ipv4_source_filter.emplace(4, 0, 0); + network_ipv6_source_filter.emplace(6, 0, 0); src_family[4] = true; src_family[6] = true; @@ -198,8 +198,8 @@ void compiler_t::collect(const std::vector& unwind_rules) } else { - network_ipv4_destination_filter.emplace(network_t(4, 0, 0)); - network_ipv6_destination_filter.emplace(network_t(6, 0, 0)); + network_ipv4_destination_filter.emplace(4, 0, 0); + network_ipv6_destination_filter.emplace(6, 0, 0); dst_family[4] = true; dst_family[6] = true; diff --git a/controlplane/balancer.cpp b/controlplane/balancer.cpp index a50aee80..4774ef76 100644 --- a/controlplane/balancer.cpp +++ b/controlplane/balancer.cpp @@ -797,15 +797,12 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, } } - req_reals.emplace_back(common::idp::updateGlobalBase::update_balancer_services::real{ - real_unordered_id, - real_ip, - counter_id}); + req_reals.emplace_back(real_unordered_id, real_ip, counter_id); req_binding.emplace_back(real_unordered_id); } const auto counter_id = service_counters.get_id({module_name, {virtual_ip, proto, virtual_port}}); - req_services.emplace_back(common::idp::updateGlobalBase::update_balancer_services::service{ + req_services.emplace_back( service_id, flags, counter_id, @@ -815,8 +812,7 @@ void balancer_t::compile(common::idp::updateGlobalBase::request& globalbase, (uint32_t)real_start, (uint32_t)(req_reals.size() - real_start), ipv4_outer_source_network, - ipv6_outer_source_network, - }); + ipv6_outer_source_network); } } diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index a1f373cc..92054e4c 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -631,7 +631,7 @@ void config_parser_t::loadConfig_tun64(controlplane::base_t& baseNext, } else { - tunnel.prefixes.emplace(common::ip_prefix_t(tunnel.ipv6SourceAddress, 128)); + tunnel.prefixes.emplace(tunnel.ipv6SourceAddress, 128); } if (exist(moduleJson, "mappings")) From 6a6b3bb3fa35b7038084215ef4f10ef26a9a3498 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:10:02 +0400 Subject: [PATCH 160/195] Add missing noexcept to Start and Configure definitions Noexcept was in the declaration, but missing in definition --- dataplane/kernel_interface_handle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dataplane/kernel_interface_handle.cpp b/dataplane/kernel_interface_handle.cpp index 7c57b7c5..34a10d89 100644 --- a/dataplane/kernel_interface_handle.cpp +++ b/dataplane/kernel_interface_handle.cpp @@ -42,7 +42,7 @@ KernelInterfaceHandle::KernelInterfaceHandle(KernelInterfaceHandle&& other) noex *this = std::move(other); } -bool KernelInterfaceHandle::Start() const +bool KernelInterfaceHandle::Start() const noexcept { auto rc = rte_eth_dev_start(kni_port_); if (rc) @@ -138,7 +138,7 @@ rte_eth_conf KernelInterfaceHandle::DefaultConfig() noexcept return rte_eth_conf{}; } -bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf, tQueueId queue_count) +bool KernelInterfaceHandle::Configure(const rte_eth_conf& eth_conf, tQueueId queue_count) noexcept { int ret = rte_eth_dev_configure(kni_port_, queue_count, From 37fabac7c6b3fcd53903356b19ee2a6a362980b0 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:12:50 +0400 Subject: [PATCH 161/195] Mark methods overriding a member function with 'override' --- common/rpc_channel.h | 12 ++++++------ common/rpc_controller.h | 14 +++++++------- controlplane/acl/rule.h | 20 ++++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/common/rpc_channel.h b/common/rpc_channel.h index 2f84875a..12949b38 100644 --- a/common/rpc_channel.h +++ b/common/rpc_channel.h @@ -21,7 +21,7 @@ class UnixProtobufRpcChannel : public google::protobuf::RpcChannel connectChannel(socketPath); } - ~UnixProtobufRpcChannel() + ~UnixProtobufRpcChannel() override { if (clientSocket != -1) { @@ -58,11 +58,11 @@ class UnixProtobufRpcChannel : public google::protobuf::RpcChannel } } - virtual void CallMethod(const ::google::protobuf::MethodDescriptor* method, - ::google::protobuf::RpcController* controller, - const ::google::protobuf::Message* request, - ::google::protobuf::Message* response, - ::google::protobuf::Closure*) + void CallMethod(const ::google::protobuf::MethodDescriptor* method, + ::google::protobuf::RpcController* controller, + const ::google::protobuf::Message* request, + ::google::protobuf::Message* response, + ::google::protobuf::Closure*) override { std::lock_guard guard(mutex); // Get the service name method name and fill it into rpc_meta diff --git a/common/rpc_controller.h b/common/rpc_controller.h index 2f383a1c..b11d247f 100644 --- a/common/rpc_controller.h +++ b/common/rpc_controller.h @@ -13,21 +13,21 @@ class RpcController : public google::protobuf::RpcController RpcController() { _reset(); } ~RpcController() override = default; - virtual void Reset() + void Reset() override { _reset(); } - [[nodiscard]] virtual bool Failed() const { return is_failed_; } - virtual void SetFailed(const std::string& reason) + [[nodiscard]] bool Failed() const override { return is_failed_; } + void SetFailed(const std::string& reason) override { is_failed_ = true; error_code_ = reason; } - [[nodiscard]] virtual std::string ErrorText() const { return error_code_; } - virtual void StartCancel() {}; - [[nodiscard]] virtual bool IsCanceled() const { return false; }; - virtual void NotifyOnCancel(::google::protobuf::Closure* /* callback */) {}; + [[nodiscard]] std::string ErrorText() const override { return error_code_; } + void StartCancel() override {}; + [[nodiscard]] bool IsCanceled() const override { return false; }; + void NotifyOnCancel(::google::protobuf::Closure* /* callback */) override {}; private: bool is_failed_; diff --git a/controlplane/acl/rule.h b/controlplane/acl/rule.h index ed6e3d9c..408aaee5 100644 --- a/controlplane/acl/rule.h +++ b/controlplane/acl/rule.h @@ -198,12 +198,12 @@ struct filter_network_t : filter_base_t networks.emplace_back(std::move(string)); } - [[nodiscard]] bool is_none() const + [[nodiscard]] bool is_none() const override { return networks.empty(); } - [[nodiscard]] virtual std::string to_string() const + [[nodiscard]] std::string to_string() const override { if (networks.empty()) { @@ -334,12 +334,12 @@ struct filter_prm_t : filter_base_t } } - [[nodiscard]] bool is_none() const + [[nodiscard]] bool is_none() const override { return ranges.empty(); } - [[nodiscard]] virtual std::string to_string() const + [[nodiscard]] std::string to_string() const override { std::string ret; @@ -592,12 +592,12 @@ struct filter_id_t : filter_base_t inline filter_id_t(int _val) : val(_val) {} - [[nodiscard]] virtual bool is_none() const + [[nodiscard]] bool is_none() const override { return val < 0; } - [[nodiscard]] virtual std::string to_string() const + [[nodiscard]] std::string to_string() const override { return std::to_string(val); } @@ -741,12 +741,12 @@ struct filter_proto_t : filter_base_t } } - [[nodiscard]] virtual bool is_none() const + [[nodiscard]] bool is_none() const override { return type.is_none() || prm1.is_none() || prm2.is_none(); } - [[nodiscard]] virtual std::string to_string() const + [[nodiscard]] std::string to_string() const override { bool has_ports = false, has_icmptypes = false, has_icmp6types = false, has_flags = false; @@ -923,12 +923,12 @@ struct filter_t : filter_base_t } } - [[nodiscard]] virtual bool is_none() const + [[nodiscard]] bool is_none() const override { return acl_id.is_none() || src.is_none() || dst.is_none() || proto.is_none() || dir.is_none() || recordstate.is_none(); } - [[nodiscard]] virtual std::string to_string() const + [[nodiscard]] std::string to_string() const override { std::string ret; From e444f0c872e5c031b3523f8b8abbff1c47524271 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:52:19 +0400 Subject: [PATCH 162/195] Do not use c-style casts to cast away constness --- dataplane/sock_dev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataplane/sock_dev.cpp b/dataplane/sock_dev.cpp index 189257a4..3b852c17 100644 --- a/dataplane/sock_dev.cpp +++ b/dataplane/sock_dev.cpp @@ -386,7 +386,7 @@ sock_dev_tx(void* q, struct rte_mbuf** bufs, uint16_t nb_bufs) iov[0].iov_base = &hdr; iov[0].iov_len = sizeof(hdr); - iov[1].iov_base = (void*)rte_pktmbuf_read(mbuf, 0, len, writeBuf); + iov[1].iov_base = const_cast(rte_pktmbuf_read(mbuf, 0, len, writeBuf)); iov[1].iov_len = len; if (writeIovCount(si->conFd, iov, 2) < 0) From 3a357be819b69d867ac1d7593ad5e5ede1839c30 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 19:52:28 +0400 Subject: [PATCH 163/195] Improve logger/main.cpp 'main' function - Replace C-style casts with const_cast - Switch to std::string for safer argument handling - Eliminate redundant C-style casting to char* - Use range-based loops - use std:: namespace with signal/strcmp --- logger/main.cpp | 56 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/logger/main.cpp b/logger/main.cpp index 8dd346e8..a6850d8f 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -232,82 +232,84 @@ int loadConfig(const std::string& path) return 0; } -int main(int argc, - char** argv) +int main(int argc, char** argv) { int config = argc; for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-d") == 0) + std::string_view arg{argv[i]}; + if (arg == "-d") { common::log::logPriority = common::log::TLOG_DEBUG; } - else if (strcmp(argv[i], "-c") == 0) + else if (arg == "-c") { config = i + 1; } } + if (config >= argc) { std::cout << "usage: " << argv[0] << " [-d] -c " << std::endl; return 1; } + int ret = loadConfig(argv[config]); if (ret != 0) { return ret; } - std::vector args; + std::vector args; args.push_back(argv[0]); - args.push_back("--proc-type=secondary"); + args.emplace_back("--proc-type=secondary"); std::string filePrefix = "--file-prefix="; + if (const char* pointer = std::getenv("YANET_FILEPREFIX")) { - char* pointer = getenv("YANET_FILEPREFIX"); - if (pointer) - { - filePrefix += pointer; - } - else - { - char* pointer = getenv("YANET_PREFIX"); - if (pointer) - { - filePrefix += pointer; - } - } + filePrefix += pointer; } + else if (const char* pointer = std::getenv("YANET_PREFIX")) + { + filePrefix += pointer; + } + if (filePrefix.size() > std::string("--file-prefix=").size()) { - args.push_back(filePrefix.data()); + args.push_back(filePrefix); } #if (RTE_VER_YEAR < 20) || (RTE_VER_YEAR == 20 && RTE_VER_MONT < 11) - const char masterLcore[] = "--master-lcore"; + const std::string masterLcore = "--master-lcore"; #else - const char masterLcore[] = "--main-lcore"; + const std::string masterLcore = "--main-lcore"; #endif std::string masterLcoreId = std::to_string(loggerCoreId); - args.push_back(masterLcore); - args.push_back(masterLcoreId.data()); + args.push_back(masterLcoreId); YANET_LOG_DEBUG("eal args:\n"); + for (const auto& arg : args) + { + YANET_LOG_DEBUG("%s\n", arg.c_str()); + } + + // Use std::vector and copy the data into it for passing to rte_eal_init + std::vector c_args; for (auto& arg : args) { - YANET_LOG_DEBUG("%s\n", arg); + c_args.push_back(const_cast(arg.c_str())); } - ret = rte_eal_init(args.size(), (char**)args.data()); + ret = rte_eal_init(static_cast(c_args.size()), c_args.data()); if (ret < 0) { YANET_LOG_ERROR("rte_eal_init() = %d\n", ret); return 2; } - if (signal(SIGPIPE, handleSignal) == SIG_ERR) + if (std::signal(SIGPIPE, handleSignal) == SIG_ERR) { return 3; } From 8a941187afcbba61b2d87189f3f522f28f1dca43 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 20:11:00 +0400 Subject: [PATCH 164/195] Do not use variable-length arrays as those are not supported by C++ --- logger/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/logger/main.cpp b/logger/main.cpp index a6850d8f..aef83344 100644 --- a/logger/main.cpp +++ b/logger/main.cpp @@ -90,8 +90,8 @@ int runLogger() interface::controlPlane controlplane; - uint32_t size = 1024; - samples::sample_t* samples[size]; + constexpr uint32_t size = 1024; + std::array samples; std::map configs; From d649a9411606faccd84a0af4219eed9cbc2875bc Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 21:23:59 +0400 Subject: [PATCH 165/195] Refactor StaticVector - Use `aligned_storage` with `std::array` instead of C-style array. - Due to that, remove now unnecessary `sizeof(T)` multiplication in `std::copy`. - Use `std::launder` to ensure compliance with [basic.life]/8 rule, Basically, [basic.life]/8 tells us that, if you allocate a new object in the storage of the old one, you cannot access the new object through pointers to the old. launder allows us to side-step that. - Refactor `push_back` to use make it accept both lvalues and rvalues. - Modify `PushBackUnsafe` to accept both lvalues and rvalues. - Squash `PerElementCopy`, `PerElementMove`, and `TrivialCopy` into a single `PerElementTransfer`, using `PushBackUnsafe` or `std::copy` based on `T` type traits. - Replace `#define`-based exception handling with a template boolean parameter - Add missing destructor to ensure proper cleanup. - Avoid assignment operator usage in constructors to prevent default object creation. - Add missing `clear` in move assignment operator. - Remove redundant `return` and `abort` statements after `HandleOutOfRange`. - Add missing `noexcept` specifier to move operations. --- common/static_vector.h | 159 ++++++++++++------------------ common/unittest/static_vector.cpp | 5 +- 2 files changed, 65 insertions(+), 99 deletions(-) diff --git a/common/static_vector.h b/common/static_vector.h index 75234faa..1e954a8b 100644 --- a/common/static_vector.h +++ b/common/static_vector.h @@ -1,62 +1,34 @@ #pragma once -#include +#include +#include #include +#include +#include namespace utils { -#ifdef STATIC_VECTOR_USE_EXCEPTIONS -static constexpr bool USE_EXCEPTIONS = true; -#else -static constexpr bool USE_EXCEPTIONS = false; -#endif - -template +template class StaticVector { - alignas(T) unsigned char buf_[sizeof(T[Cap])]; + using storage_t = std::aligned_storage_t; + std::array buf_; std::size_t len_ = 0; T* AddressOfIndex(std::size_t idx) { - return reinterpret_cast(buf_) + idx; + return std::launder(reinterpret_cast(&buf_[idx])); } const T* AddressOfIndex(std::size_t idx) const { - return reinterpret_cast(buf_) + idx; - } - - void TrivialCopy(const StaticVector& other) - { - std::copy(std::begin(other.buf_), - std::begin(other.buf_) + other.len_ * sizeof(T), - std::begin(buf_)); - len_ = other.len_; - } - - void PerElementCopy(const StaticVector& other) - { - clear(); - for (const auto& elem : other) - { - PushBackUnsafe(elem); - } - } - - void PerElementCopy(StaticVector&& other) - { - clear(); - for (auto& elem : other) - { - PushBackUnsafe(std::move(elem)); - } + return std::launder(reinterpret_cast(&buf_[idx])); } void HandleOutOfRange() { - if constexpr (USE_EXCEPTIONS) + if constexpr (UseExceptions) { throw std::out_of_range(""); } @@ -66,94 +38,98 @@ class StaticVector } } - void PushBackUnsafe(const T& elem) + template + void PushBackUnsafe(Args&&... args) { - new (AddressOfIndex(len_)) T(elem); + new (AddressOfIndex(len_)) T(std::forward(args)...); ++len_; } - void PushBackUnsafe(T&& elem) + template + void PerElementTransfer(OtherVector&& other) { - new (AddressOfIndex(len_)) T(std::move(elem)); - ++len_; + // If T is trivially copyable, use trivial copy + if constexpr (std::is_trivially_copyable_v) + { + std::copy(std::begin(other.buf_), std::begin(other.buf_) + other.len_, std::begin(buf_)); + len_ = other.len_; + } + else + { + clear(); + + for (auto&& elem : other) + { + PushBackUnsafe(std::forward(elem)); + } + + // If other is an rvalue, clear the original vector + if constexpr (std::is_rvalue_reference_v) + { + other.clear(); + } + } } public: using iterator = T*; using const_iterator = const T*; + StaticVector() = default; - StaticVector(StaticVector&& other) + ~StaticVector() { - *this = std::move(other); + clear(); } - StaticVector& operator=(StaticVector&& other) + StaticVector(const StaticVector& other) { - if (this == &other) - { - return *this; - } - - if constexpr (std::is_trivially_copyable_v) - { - TrivialCopy(other); - } - else - { - PerElementMove(other); - } - return *this; + PerElementTransfer(other); } - StaticVector(const StaticVector& other) + StaticVector(StaticVector&& other) noexcept { - *this = other; + PerElementTransfer(std::move(other)); } StaticVector& operator=(const StaticVector& other) { - if (this == &other) - { - return *this; - } - clear(); - if constexpr (std::is_trivially_copyable_v) - { - TrivialCopy(other); - } - else + if (this != &other) { - PerElementCopy(other); + clear(); + PerElementTransfer(other); } return *this; } - void push_back(const T& elem) + StaticVector& operator=(StaticVector&& other) noexcept { - if (Full()) + if (this != &other) { - HandleOutOfRange(); - return; + clear(); + PerElementTransfer(std::move(other)); } - PushBackUnsafe(elem); + return *this; } - void push_back(T&& elem) + template + void push_back(U&& elem) { if (Full()) { HandleOutOfRange(); - return; } - PushBackUnsafe(std::move(elem)); + PushBackUnsafe(std::forward(elem)); } template void emplace_back(Args&&... args) { - new (AddressOfIndex(len_)) T(std::forward(args)...); - ++len_; + if (Full()) + { + HandleOutOfRange(); + } + PushBackUnsafe(std::forward(args)...); } void pop_back() @@ -161,7 +137,6 @@ class StaticVector if (empty()) { HandleOutOfRange(); - return; } at(--len_).~T(); } @@ -169,7 +144,6 @@ class StaticVector T& operator[](std::size_t pos) { return *AddressOfIndex(pos); - // return reinterpret_cast(buf_[pos * sizeof(T)]); } const T& operator[](std::size_t pos) const @@ -182,10 +156,8 @@ class StaticVector if (pos >= size()) { HandleOutOfRange(); - abort(); } return *AddressOfIndex(pos); - // return reinterpret_cast(buf_[pos * sizeof(T)]); } const T& at(std::size_t pos) const @@ -193,7 +165,6 @@ class StaticVector if (pos >= size()) { HandleOutOfRange(); - abort(); } return *AddressOfIndex(pos); } @@ -205,13 +176,12 @@ class StaticVector const_iterator cbegin() const { return AddressOfIndex(0); } const_iterator cend() const { return AddressOfIndex(size()); } - [[nodiscard]] bool empty() const - { - return size() == 0; - } - + [[nodiscard]] bool empty() const { return size() == 0; } [[nodiscard]] constexpr std::size_t capacity() const { return Cap; } + [[nodiscard]] std::size_t size() const { return len_; } + [[nodiscard]] bool Full() const { return size() == capacity(); } + // Clear the vector and destruct elements void clear() { if constexpr (std::is_trivially_destructible_v) @@ -226,9 +196,6 @@ class StaticVector } } } - - [[nodiscard]] std::size_t size() const { return len_; } - [[nodiscard]] bool Full() const { return size() == capacity(); } }; } // namespace utils diff --git a/common/unittest/static_vector.cpp b/common/unittest/static_vector.cpp index bb4049ab..91033879 100644 --- a/common/unittest/static_vector.cpp +++ b/common/unittest/static_vector.cpp @@ -1,7 +1,6 @@ #include #include -#define STATIC_VECTOR_USE_EXCEPTIONS #include "../static_vector.h" namespace @@ -12,7 +11,7 @@ static constexpr std::string_view hw = "Hello World!"; TEST(StaticVector, 001_Basic_element_store) { - StaticVector v; + StaticVector v; // Enable exceptions ASSERT_TRUE(v.empty()); for (auto& c : hw) { @@ -47,4 +46,4 @@ TEST(StaticVector, 002_POD_copy_move) ASSERT_TRUE(std::mismatch(v.begin(), v.end(), moved.begin()).first == v.end()); } -} // namespace \ No newline at end of file +} // namespace From 18fd0bbbd328e5eb3ef5f89cc4a3b7cf3d48978b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 22:49:43 +0400 Subject: [PATCH 166/195] Replace args_T template type with Args Args is a common name for variadic templates, plus it adds consistency since other places in the code uses Args --- cli/converter.h | 8 ++++---- cli/helper.h | 4 ++-- common/type.h | 10 +++++----- controlplane/unittest/acl_flat.cpp | 10 +++++----- controlplane/unittest/acl_network.cpp | 20 ++++++++++---------- controlplane/unittest/acl_table.cpp | 14 +++++++------- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cli/converter.h b/cli/converter.h index 5d235354..ff549a29 100644 --- a/cli/converter.h +++ b/cli/converter.h @@ -20,8 +20,8 @@ struct config_t template std::string to_string(const std::optional& value, const config_t config = {}); -template -std::string to_string(const std::variant& value, const config_t config = {}); +template +std::string to_string(const std::variant& value, const config_t config = {}); template std::string to_string(const std::vector& vector, const config_t config = {}); template @@ -45,8 +45,8 @@ std::string to_string(const std::optional& value, } }; -template -std::string to_string(const std::variant& value, +template +std::string to_string(const std::variant& value, const config_t config) { return std::visit([&config](const auto& value) -> std::string { return to_string(value, config); }, value); diff --git a/cli/helper.h b/cli/helper.h index c2e0b8f2..8c896619 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -234,8 +234,8 @@ class table_t { } - template - void insert(const args_T&... args) + template + void insert(const Args&... args) { std::vector row = {converter::to_string(args, config)...}; diff --git a/common/type.h b/common/type.h index 488cc279..25ba7534 100644 --- a/common/type.h +++ b/common/type.h @@ -1672,8 +1672,8 @@ class values_t public: values_t() = default; - template - values_t(const args_T&... args) + template + values_t(const Args&... args) { insertHelper(args...); } @@ -1699,13 +1699,13 @@ class values_t } protected: - template + template void insertHelper(const arg0_T& arg0, - const args_T&... args) + const Args&... args) { values.emplace(arg0); - if constexpr (sizeof...(args_T)) + if constexpr (sizeof...(Args)) { insertHelper(args...); } diff --git a/controlplane/unittest/acl_flat.cpp b/controlplane/unittest/acl_flat.cpp index 7f0072ea..5af4c81c 100644 --- a/controlplane/unittest/acl_flat.cpp +++ b/controlplane/unittest/acl_flat.cpp @@ -6,21 +6,21 @@ namespace { -template +template void expect_group_ids_helper(std::vector& vector, const unsigned int group_id, - const args_T... group_ids) + const Args... group_ids) { vector.emplace_back(group_id); - if constexpr (sizeof...(args_T) != 0) + if constexpr (sizeof...(Args) != 0) { expect_group_ids_helper(vector, group_ids...); } } -template -std::vector expect_group_ids(const args_T... group_ids) +template +std::vector expect_group_ids(const Args... group_ids) { std::vector result; expect_group_ids_helper(result, group_ids...); diff --git a/controlplane/unittest/acl_network.cpp b/controlplane/unittest/acl_network.cpp index 71627e4f..4b70b732 100644 --- a/controlplane/unittest/acl_network.cpp +++ b/controlplane/unittest/acl_network.cpp @@ -13,21 +13,21 @@ uint128_t convert_to_uint128(const std::string& address) return acl::network_t(address).addr; } -template +template void make_filter_helper(acl::compiler::network_t::filter& filter, const std::string& prefix, - const args_T&... prefixes) + const Args&... prefixes) { filter.emplace(prefix); - if constexpr (sizeof...(args_T) != 0) + if constexpr (sizeof...(Args) != 0) { make_filter_helper(filter, prefixes...); } } -template -acl::compiler::network_t::filter make_filter(const args_T&... prefixes) +template +acl::compiler::network_t::filter make_filter(const Args&... prefixes) { acl::compiler::network_t::filter result; make_filter_helper(result, prefixes...); @@ -49,21 +49,21 @@ tAclGroupId get_by_address(acl::compiler::network_t& network, return network.get_group_ids_by_address(convert_to_uint128(address)); } -template +template void expect_group_ids_helper(std::vector& vector, const unsigned int group_id, - const args_T... group_ids) + const Args... group_ids) { vector.emplace_back(group_id); - if constexpr (sizeof...(args_T) != 0) + if constexpr (sizeof...(Args) != 0) { expect_group_ids_helper(vector, group_ids...); } } -template -std::vector expect_group_ids(const args_T... group_ids) +template +std::vector expect_group_ids(const Args... group_ids) { std::vector result; expect_group_ids_helper(result, group_ids...); diff --git a/controlplane/unittest/acl_table.cpp b/controlplane/unittest/acl_table.cpp index c98fdb7d..99d37d4f 100644 --- a/controlplane/unittest/acl_table.cpp +++ b/controlplane/unittest/acl_table.cpp @@ -6,29 +6,29 @@ namespace { -template +template void expect_group_ids_helper(std::vector& vector, const unsigned int group_id, - const args_T... group_ids) + const Args... group_ids) { vector.emplace_back(group_id); - if constexpr (sizeof...(args_T) != 0) + if constexpr (sizeof...(Args) != 0) { expect_group_ids_helper(vector, group_ids...); } } -template -std::vector expect_group_ids(const args_T... group_ids) +template +std::vector expect_group_ids(const Args... group_ids) { std::vector result; expect_group_ids_helper(result, group_ids...); return result; } -template -std::tuple expect_result(const args_T... args) +template +std::tuple expect_result(const Args... args) { return {args...}; } From 6b1859f98716a7aaf5938449f5b4beebd410f72b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 30 Sep 2024 19:24:33 +0400 Subject: [PATCH 167/195] Add some type traits to utils.h - is_optional_v for std::optional detection. - is_variant_v for std::variant detection. - is_container_v for general container detection. - is_vector_v for std::vector detection. - is_set_v for std::set detection. --- common/utils.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/common/utils.h b/common/utils.h index d979370f..9c07b7a0 100644 --- a/common/utils.h +++ b/common/utils.h @@ -1,7 +1,13 @@ #pragma once +#include +#include +#include +#include #include +#include +#include namespace utils { @@ -10,5 +16,70 @@ template struct always_false : std::false_type {}; +template +struct is_optional : std::false_type +{}; + +template +struct is_optional> : std::true_type +{}; + +template +inline constexpr bool is_optional_v = is_optional::value; + +template +struct is_variant : std::false_type +{}; + +template +struct is_variant> : std::true_type +{}; + +template +inline constexpr bool is_variant_v = is_variant::value; + +template +struct is_container : std::false_type +{}; + +/* + * Checks: + * Whether std::begin(T&), std::end(T&) and std::empty(T&) are valid expressions. + * Whether the result of std::begin(T&) can be dereferenced (i.e., *std::begin(T&) is valid) + */ +template +struct is_container())), + decltype(std::end(std::declval())), + decltype(std::empty(std::declval())), + decltype(*std::begin(std::declval()))>> : std::true_type +{}; + +template +inline constexpr bool is_container_v = is_container::value; + +template +struct is_vector : std::false_type +{}; + +template +struct is_vector> : std::true_type +{}; + +template +inline constexpr bool is_vector_v = is_vector::value; + +template +struct is_set : std::false_type +{}; + +template +struct is_set> : std::true_type +{}; + +template +inline constexpr bool is_set_v = is_set::value; + } // namespace utils From 0316b7441701af5501f8b4bc2a15b3d6a4697bd6 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Thu, 26 Sep 2024 23:15:40 +0400 Subject: [PATCH 168/195] Refactor cli/converter.h - Replace `arg_T` with `T`. More consistency this way. - Replace a lot of to_string functions with just one that uses if constexpr to determine a correct action on compile-time - Mark functions as `inline` to avoid violating ODR since they are defined in the header and not static - Avoid unnecessary copies of the `config_t` structure by passing it as a `const` reference. - std::ostringstream for container concatenation, simplifying `std::vector` and `std::set` implementations. - Replace `if-else` blocks with ternary operators for more concise return statements. - Add an ability to provide std::string_view --- cli/converter.h | 150 ++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 101 deletions(-) diff --git a/cli/converter.h b/cli/converter.h index ff549a29..3687ad30 100644 --- a/cli/converter.h +++ b/cli/converter.h @@ -1,12 +1,13 @@ #pragma once -#include #include #include #include #include #include +#include "common/utils.h" + namespace converter { @@ -18,126 +19,73 @@ struct config_t std::string set_empty = "n/s"; }; -template -std::string to_string(const std::optional& value, const config_t config = {}); -template -std::string to_string(const std::variant& value, const config_t config = {}); -template -std::string to_string(const std::vector& vector, const config_t config = {}); -template -std::string to_string(const std::set& set, const config_t config = {}); -std::string to_string(const bool& value, const config_t config = {}); -std::string to_string(const std::string& string, const config_t config = {}); -template -std::string to_string(const arg_T& value, const config_t config = {}); - -template -std::string to_string(const std::optional& value, - const config_t config) +template +std::string to_string(const T& value, const config_t& config = {}) { - if (value) + if constexpr (std::is_same_v) { - return to_string(*value, config); + return value.empty() ? config.string_empty : value; } - else + else if constexpr (std::is_same_v) { - return config.optional_null; + return value.empty() ? config.string_empty : std::string(value); } -}; - -template -std::string to_string(const std::variant& value, - const config_t config) -{ - return std::visit([&config](const auto& value) -> std::string { return to_string(value, config); }, value); -}; - -template -std::string to_string(const std::vector& vector, - const config_t config) -{ - if (vector.empty()) + else if constexpr (std::is_constructible_v) { - return config.vector_empty; + return value; } - - bool first = true; - std::ostringstream result; - for (const auto& item : vector) + else if constexpr (std::is_same_v) { - if (!first) - { - result << ","; ///< @todo: config - } - - result << to_string(item, config); - first = false; + return value ? "true" : "false"; } - return result.str(); -} - -template -std::string to_string(const std::set& set, - const config_t config) -{ - if (set.empty()) + else if constexpr (std::is_arithmetic_v) { - return config.set_empty; + return std::to_string(value); } - - bool first = true; - std::ostringstream result; - for (const auto& item : set) + else if constexpr (utils::is_variant_v) { - if (!first) - { - result << ","; ///< @todo: config - } - - result << to_string(item, config); - first = false; + return std::visit([&config](const auto& val) { return to_string(val, config); }, value); } - return result.str(); -} - -std::string to_string(const bool& value, - [[maybe_unused]] const config_t config) -{ - if (value) + else if constexpr (utils::is_optional_v) { - return "true"; + return value ? to_string(*value, config) : config.optional_null; } - else + else if constexpr (utils::is_container_v) { - return "false"; - } -}; + if (value.empty()) + { + if constexpr (utils::is_vector_v) + { + return config.vector_empty; + } + else if constexpr (utils::is_set_v) + { + return config.set_empty; + } + else + { + static_assert(utils::always_false::value, + "Container does not have default empty representation in struct config_t"); + } + } -std::string to_string(const std::string& string, - const config_t config) -{ - if (string.empty()) - { - return config.string_empty; - } - else - { - return string; - } -}; + std::ostringstream oss; + auto it = std::begin(value); + oss << to_string(*it, config); + ++it; -template -std::string to_string(const arg_T& value, - [[maybe_unused]] const config_t config) -{ - if constexpr (std::is_constructible_v) - { - return value; + for (; it != std::end(value); ++it) + { + oss << ',' << to_string(*it, config); + } + + return oss.str(); } else { - return std::to_string(value); + static_assert(std::is_constructible_v, + "Type is not convertible to std::string and no overload of to_string is provided"); } -}; - } + +} // namespace converter From b0a539ae9cf9e0b2646cc10913946faa30f55fbb Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 17:53:51 +0400 Subject: [PATCH 169/195] Add specialization for std::string conversion to default_value_t Otherwise we will be unable to use table_t which uses to_string function from converter.h since the default_value_t is not constructible with std::string. --- common/type.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/type.h b/common/type.h index 25ba7534..ac15ddea 100644 --- a/common/type.h +++ b/common/type.h @@ -100,6 +100,12 @@ class default_value_t return *this; } + template>> + operator std::string() const + { + return std::to_string(value); + } + public: type_t value; }; From 6f572cc2b435483a5b5de5b1bdbddd83f9ce94d2 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 17:25:24 +0400 Subject: [PATCH 170/195] Add utility to apply a function to multiple tuples element-wise Add functions zip_apply that applies function and zip_apply_collect that applies function and stores results in std::array. zip_apply_collect is actully unused now, but I've added it just in case --- common/tuple.h | 53 +++++++++++++++++++++++++ common/unittest/tuple.cpp | 82 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/common/tuple.h b/common/tuple.h index 68058c1c..488ebed7 100644 --- a/common/tuple.h +++ b/common/tuple.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -126,4 +127,56 @@ struct IndexOf> static constexpr std::size_t value = Helper<0>::value(); }; +/** + * @brief Helper to get the size of the first tuple in a parameter pack. + * + * This function extracts the size of the first tuple in the parameter pack `Tuples`. + * + * @tparam Tuples The types of the tuples. + * @return The size of the first tuple. + */ +template +constexpr std::size_t get_first_tuple_size() +{ + static_assert(sizeof...(Tuples) > 0, "At least one tuple is required."); + return std::tuple_size_v>>>; +} + +template +static void zip_apply_helper(Func&& f, Tuples&&... tuples) +{ + if constexpr (I < N) + { + f(std::get(std::forward(tuples))...); + zip_apply_helper(std::forward(f), std::forward(tuples)...); + } +} + +/** + * @brief Applies a function to corresponding elements of multiple tuples. + * + * The function `f` should be callable with the elements of the tuples at each index. + * This function works with any number of tuples, as long as they are all the same size. + * + * Example: + * ``` + * auto t1 = std::make_tuple(1, 2, 3); + * auto t2 = std::make_tuple(4, 5, 6); + * zip_apply([](auto a, auto b) { do something with a and b }, t1, t2); + * ``` + * + * @tparam Func The type of the function to apply. + * @tparam Tuples The types of the tuples. + * @param f The function to apply. + * @param tuples The tuples to iterate over. + */ +template +inline void zip_apply(Func&& f, Tuples&&... tuples) +{ + constexpr std::size_t tuple_size = get_first_tuple_size(); + static_assert((... && (std::tuple_size_v> == tuple_size)), "All tuples must have the same size."); + + zip_apply_helper<0, tuple_size>(std::forward(f), std::forward(tuples)...); +} + } // namespace utils diff --git a/common/unittest/tuple.cpp b/common/unittest/tuple.cpp index 906d2d3c..da3c0399 100644 --- a/common/unittest/tuple.cpp +++ b/common/unittest/tuple.cpp @@ -134,4 +134,86 @@ TEST(IndexOf, EmptyTuple) // constexpr std::size_t invalidIndex = IndexOf::value; } +using utils::get_first_tuple_size; + +TEST(TupleSize, GetFirstTupleSize) +{ + using Tuple1 = std::tuple; + constexpr std::size_t size1 = get_first_tuple_size(); + EXPECT_EQ(size1, 3); + + using Tuple2 = std::tuple; + constexpr std::size_t size2 = get_first_tuple_size(); + EXPECT_EQ(size2, 3); + + using EmptyTuple = std::tuple<>; + constexpr std::size_t size3 = get_first_tuple_size(); + EXPECT_EQ(size3, 0); +} + +using utils::zip_apply; + +TEST(ZipApply, BasicUsage) +{ + auto t1 = std::make_tuple(1, 2, 3); + auto t2 = std::make_tuple(4, 5, 6); + std::vector results; + + auto op = [&](int a, int b) { + results.push_back(a + b); + }; + + zip_apply(op, t1, t2); + + EXPECT_EQ(results.size(), 3u); + EXPECT_EQ(results[0], 5); + EXPECT_EQ(results[1], 7); + EXPECT_EQ(results[2], 9); + + results.clear(); + auto op2 = [&](int a, int b, int c, int d) { + results.push_back(a + b + c + d); + }; + + zip_apply(op2, t1, t2, t1, t2); + + EXPECT_EQ(results.size(), 3u); + EXPECT_EQ(results[0], 10); + EXPECT_EQ(results[1], 14); + EXPECT_EQ(results[2], 18); +} + +TEST(ZipApply, WorksWithSingleTuple) +{ + auto t1 = std::make_tuple(1, 2, 3); + std::vector results; + + auto op = [&](int a) { + results.push_back(a * 2); + }; + + zip_apply(op, t1); + + EXPECT_EQ(results.size(), 3u); + EXPECT_EQ(results[0], 2); + EXPECT_EQ(results[1], 4); + EXPECT_EQ(results[2], 6); +} + +TEST(ZipApply, DifferentSizesCompileError) +{ + // Expect a compile-time failure due to different tuple sizes + // Uncommenting the following lines should trigger a compile-time error: + /* auto t1 = std::make_tuple(1, 2); */ + /* auto t2 = std::make_tuple(3); */ + /* zip_apply([](int a, int b) {}, t1, t2); */ +} + +TEST(ZipApply, NoTuplesCompileError) +{ + // Expect a compile-time failure due to no tuples provided + // Uncommenting the following lines should trigger a compile-time error: + /* zip_apply([]() { }); */ +} + } // namespace From 2f11570b9c4ffdef00e44b7b07cef27eb965fb74 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 00:00:13 +0400 Subject: [PATCH 171/195] Refactor common/tsc_deltas.h - Replace #define with constexpr for YANET_TSC_BINS_N and YANET_TSC_BINS_SHIFT constants. - Use C++ standard alignas instead of __attribute__((aligned)). - Introduce CountersArray alias for std::array to avoid C-style arrays. - Use std::clamp instead of std::min and std::max for clarity. - Replace deprecated std::is_pod with std::is_trivially_copyable and std::is_standard_layout --- common/tsc_deltas.h | 89 +++++++++++++++++++++-------------------- dataplane/dataplane.cpp | 5 ++- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/common/tsc_deltas.h b/common/tsc_deltas.h index bb108125..5ef4403b 100644 --- a/common/tsc_deltas.h +++ b/common/tsc_deltas.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -10,13 +12,15 @@ #include "common/define.h" -#define YANET_TSC_BINS_SHIFT 2 -#define YANET_TSC_BINS_N 4 +constexpr auto YANET_TSC_BINS_SHIFT = 2; +constexpr auto YANET_TSC_BINS_N = 4; namespace dataplane::perf { -struct tsc_base_values +using CountersArray = std::array; + +struct alignas(2 * RTE_CACHE_LINE_SIZE) tsc_base_values { uint32_t logicalPort_ingress_handle = 18; uint32_t acl_ingress_handle4 = 0; @@ -43,39 +47,40 @@ struct tsc_base_values uint32_t acl_egress_handle6 = 0; uint32_t logicalPort_egress_handle = 0; uint32_t controlPlane_handle = 0; -} __attribute__((__aligned__(2 * RTE_CACHE_LINE_SIZE))); +}; -struct tsc_deltas +struct alignas(2 * RTE_CACHE_LINE_SIZE) tsc_deltas { uint64_t iter_num; - uint16_t logicalPort_ingress_handle[YANET_TSC_BINS_N]; - uint16_t acl_ingress_handle4[YANET_TSC_BINS_N]; - uint16_t acl_ingress_handle6[YANET_TSC_BINS_N]; - uint16_t tun64_ipv4_handle[YANET_TSC_BINS_N]; - uint16_t tun64_ipv6_handle[YANET_TSC_BINS_N]; - uint16_t route_handle4[YANET_TSC_BINS_N]; - uint16_t route_handle6[YANET_TSC_BINS_N]; - - uint16_t decap_handle[YANET_TSC_BINS_N]; - uint16_t nat64stateful_lan_handle[YANET_TSC_BINS_N]; - uint16_t nat64stateful_wan_handle[YANET_TSC_BINS_N]; - uint16_t nat64stateless_egress_handle[YANET_TSC_BINS_N]; - uint16_t nat64stateless_ingress_handle[YANET_TSC_BINS_N]; - uint16_t nat46clat_lan_handle[YANET_TSC_BINS_N]; - uint16_t nat46clat_wan_handle[YANET_TSC_BINS_N]; - uint16_t balancer_handle[YANET_TSC_BINS_N]; - - uint16_t balancer_icmp_reply_handle[YANET_TSC_BINS_N]; - uint16_t balancer_icmp_forward_handle[YANET_TSC_BINS_N]; - uint16_t route_tunnel_handle4[YANET_TSC_BINS_N]; - uint16_t route_tunnel_handle6[YANET_TSC_BINS_N]; - uint16_t acl_egress_handle4[YANET_TSC_BINS_N]; - uint16_t acl_egress_handle6[YANET_TSC_BINS_N]; - uint16_t logicalPort_egress_handle[YANET_TSC_BINS_N]; - - uint16_t controlPlane_handle[YANET_TSC_BINS_N]; - - YANET_ALWAYS_INLINE void write(uint64_t& tsc_start, uint32_t stack_size, uint16_t bins[YANET_TSC_BINS_N], uint32_t base) + CountersArray logicalPort_ingress_handle{}; + + CountersArray acl_ingress_handle4{}; + CountersArray acl_ingress_handle6{}; + CountersArray tun64_ipv4_handle{}; + CountersArray tun64_ipv6_handle{}; + CountersArray route_handle4{}; + CountersArray route_handle6{}; + + CountersArray decap_handle{}; + CountersArray nat64stateful_lan_handle{}; + CountersArray nat64stateful_wan_handle{}; + CountersArray nat64stateless_egress_handle{}; + CountersArray nat64stateless_ingress_handle{}; + CountersArray nat46clat_lan_handle{}; + CountersArray nat46clat_wan_handle{}; + CountersArray balancer_handle{}; + + CountersArray balancer_icmp_reply_handle{}; + CountersArray balancer_icmp_forward_handle{}; + CountersArray route_tunnel_handle4{}; + CountersArray route_tunnel_handle6{}; + CountersArray acl_egress_handle4{}; + CountersArray acl_egress_handle6{}; + CountersArray logicalPort_egress_handle{}; + + CountersArray controlPlane_handle{}; + + YANET_ALWAYS_INLINE void write(uint64_t& tsc_start, uint32_t stack_size, CountersArray& bins, uint32_t base) { if (!tsc_start || unlikely(stack_size == 0)) { @@ -83,12 +88,12 @@ struct tsc_deltas } auto tsc_end = rte_get_tsc_cycles(); - auto shifted_delta = (int64_t)((tsc_end - tsc_start) / stack_size) - base; + auto shifted_delta = static_cast((tsc_end - tsc_start) / stack_size) - base; if (shifted_delta > 0) { - int floor_log_4 = (sizeof(uint64_t) * CHAR_BIT - _lzcnt_u64(shifted_delta) - 1) >> 1; - int bin_idx = std::min(std::max(floor_log_4 - YANET_TSC_BINS_SHIFT, 0), 4 - 1); + uint16_t floor_log_4 = (sizeof(uint64_t) * CHAR_BIT - _lzcnt_u64(shifted_delta) - 1) >> 1; + uint16_t bin_idx = std::clamp(floor_log_4 - YANET_TSC_BINS_SHIFT, 0, YANET_TSC_BINS_N - 1); bins[bin_idx]++; } else @@ -98,13 +103,9 @@ struct tsc_deltas tsc_start = tsc_end; } +}; -} __attribute__((__aligned__(2 * RTE_CACHE_LINE_SIZE))); - -static_assert(sizeof(tsc_deltas) <= 8 * RTE_CACHE_LINE_SIZE, - "too many deltas"); - -static_assert(std::is_pod_v == true, - "tsc structure is not pod"); - +static_assert(sizeof(tsc_deltas) <= 8 * RTE_CACHE_LINE_SIZE, "tsc_deltas size exceeds cache line size"); +static_assert(std::is_trivially_copyable::value, "tsc_deltas should be trivially copyable"); +static_assert(std::is_standard_layout::value, "tsc_deltas should have a standard layout"); } diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 9d572ff0..b3d0c28b 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1768,8 +1768,9 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() const auto& [key, shm] = it->second; auto offset = offsets[shm]; - worker->tsc_deltas = (dataplane::perf::tsc_deltas*)((intptr_t)shm + offset); - memset(worker->tsc_deltas, 0, sizeof(dataplane::perf::tsc_deltas)); + worker->tsc_deltas = reinterpret_cast(reinterpret_cast(shm) + offset); + // Use value-initialization to reset the object + *worker->tsc_deltas = {}; offsets[shm] += sizeof(dataplane::perf::tsc_deltas); auto meta = common::idp::get_shm_tsc_info::tsc_meta(worker->coreId, socket_id, key, offset); From ef068347cfe58cd7901e6eb287b2ee36288fe0ef Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 14:54:35 +0400 Subject: [PATCH 172/195] Add `as_tuple` method to struct tsc_deltas This will help reduce boilerplate code later by utilizing fold expressions --- common/tsc_deltas.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/common/tsc_deltas.h b/common/tsc_deltas.h index 5ef4403b..0bbcf34e 100644 --- a/common/tsc_deltas.h +++ b/common/tsc_deltas.h @@ -103,6 +103,33 @@ struct alignas(2 * RTE_CACHE_LINE_SIZE) tsc_deltas tsc_start = tsc_end; } + + [[nodiscard]] auto as_tuple() const + { + return std::tie(logicalPort_ingress_handle, + acl_ingress_handle4, + acl_ingress_handle6, + tun64_ipv4_handle, + tun64_ipv6_handle, + route_handle4, + route_handle6, + decap_handle, + nat64stateful_lan_handle, + nat64stateful_wan_handle, + nat64stateless_egress_handle, + nat64stateless_ingress_handle, + nat46clat_lan_handle, + nat46clat_wan_handle, + balancer_handle, + balancer_icmp_reply_handle, + balancer_icmp_forward_handle, + route_tunnel_handle4, + route_tunnel_handle6, + acl_egress_handle4, + acl_egress_handle6, + logicalPort_egress_handle, + controlPlane_handle); + } }; static_assert(sizeof(tsc_deltas) <= 8 * RTE_CACHE_LINE_SIZE, "tsc_deltas size exceeds cache line size"); From da06f3784b246e507b0792785c78ab2e6a2b260d Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 30 Sep 2024 13:48:36 +0400 Subject: [PATCH 173/195] Add an overload for table_t::insert to support iterator ranges Enables insertion of values from containers --- cli/helper.h | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/cli/helper.h b/cli/helper.h index 8c896619..027482e0 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -230,31 +230,24 @@ class table_t { public: table_t(const converter::config_t config = {}) : - config(config) - { - } + config(config) {} template void insert(const Args&... args) { std::vector row = {converter::to_string(args, config)...}; + insert_row(row); + } - if (row.size() > columnLengths.size()) - { - columnLengths.resize(row.size(), 0); - } - - for (uint32_t string_i = 0; - string_i < row.size(); - string_i++) + template::iterator_category> + void insert(Iterator begin, Iterator end) + { + std::vector row; + for (auto it = begin; it != end; ++it) { - if (columnLengths[string_i] < row[string_i].size()) - { - columnLengths[string_i] = row[string_i].size(); - } + row.push_back(converter::to_string(*it, config)); } - - table.emplace_back(row); + insert_row(row); } void print_json() @@ -461,7 +454,25 @@ class table_t table.clear(); } -protected: +private: + void insert_row(const std::vector& row) + { + if (row.size() > columnLengths.size()) + { + columnLengths.resize(row.size(), 0); + } + + for (uint32_t string_i = 0; string_i < row.size(); ++string_i) + { + if (columnLengths[string_i] < row[string_i].size()) + { + columnLengths[string_i] = row[string_i].size(); + } + } + + table.emplace_back(row); + } + converter::config_t config; std::vector> table; std::vector columnLengths; From 45e925c0fa68792a0b4c0b54070ffd8b002e77e6 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 18:10:44 +0400 Subject: [PATCH 174/195] Refactor cli/develop.h - Mark functions as `inline` instead of `static` where appropriate. - Replace `printf` with `std::ostream` for safer and more idiomatic C++ code. - Use structured bindings to improve readability, replacing `std::get` usage. - Add a template function `lpmLookupAddress` to eliminate duplicated code between IPv4 and IPv6 lookups. - Use `auto&` instead of `auto` to prevent unnecessary copies of request objects. - Utilize `SharedMemory` class for managing shared memory instead of raw `shmget` and `shmat`. - Remove the use of `protected` since no inheritance is required; switch to `private`. - Remove unnecessary forward declaration of `overflow_store`. - Replace C-style arrays with `std::array`. - Use `utils::zip_apply` to reduce boilerplate code and improve maintainability. --- cli/develop.h | 398 ++++++++++++++++++++++++++------------------------ 1 file changed, 204 insertions(+), 194 deletions(-) diff --git a/cli/develop.h b/cli/develop.h index 8d961ed0..946c08c8 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,170 +10,162 @@ #include "common/idataplane.h" #include "common/sdpclient.h" +#include "common/shared_memory.h" #include "common/tsc_deltas.h" +#include "common/tuple.h" #include "helper.h" namespace develop::dataplane { -static inline void printValue(const common::idp::value& value) +static void printValue(const common::idp::value& value) { - const auto& type = std::get<0>(value); - if (type == common::globalBase::eNexthopType::drop) - { - printf(" drop\n"); - } - else if (type == common::globalBase::eNexthopType::interface) + const auto& [type, interface] = value; + std::ostringstream oss; + using common::globalBase::eNexthopType; + + switch (type) { - for (const auto& iter : std::get<1>(value)) - { - if (std::get<0>(std::get<1>(iter)) != common::unlabelled) + case eNexthopType::drop: + oss << " drop\n"; + break; + case eNexthopType::interface: + for (const auto& [interfaceId, transport, service] : interface) { - if (std::get<0>(std::get<2>(iter)) != common::unlabelled) + const auto& [transport_label, transport_exp] = transport; + const auto& [service_label, service_exp] = service; + + if (transport_label != common::unlabelled) { - printf(" interfaceId: %u,\ttransport: [label: %u, exp: %u],\tservice: [label: %u, exp: %u]\n", - std::get<0>(iter), - std::get<0>(std::get<1>(iter)), - std::get<1>(std::get<1>(iter)), - std::get<0>(std::get<2>(iter)), - std::get<1>(std::get<2>(iter))); + if (service_label != common::unlabelled) + { + oss << " interfaceId: " << interfaceId + << ",\ttransport: [label: " << transport_label + << ", exp: " << transport_exp + << "],\tservice: [label: " << service_label + << ", exp: " << service_exp << "]\n"; + } + else + { + oss << " interfaceId: " << interfaceId + << ",\ttransport: [label: " << transport_label + << ", exp: " << transport_exp << "]\n"; + } } else { - printf(" interfaceId: %u,\ttransport: [label: %u, exp: %u]\n", - std::get<0>(iter), - std::get<0>(std::get<1>(iter)), - std::get<1>(std::get<1>(iter))); + oss << " interfaceId: " << interfaceId << "\n"; } } - else - { - printf(" interfaceId: %u\n", - std::get<0>(iter)); - } - } - } - else if (type == common::globalBase::eNexthopType::controlPlane) - { - printf(" controlPlane\n"); - } - else - { - printf(" error\n"); + break; + case eNexthopType::controlPlane: + oss << " controlPlane\n"; + break; + default: + oss << " error\n"; } + + std::cout << oss.str(); } -void lpm4LookupAddress(const common::ipv4_address_t& address) +template +static void lpmLookupAddress(const T& address) { interface::dataPlane dataPlane; - const auto response = dataPlane.lpm4LookupAddress(address); - for (const auto& iter : response) - { - const auto& socketId = iter.first; - const auto& found = std::get<0>(iter.second); - const auto& valueId = std::get<1>(iter.second); - const auto& value = std::get<2>(iter.second); - printf("[socketId: %u] %s -> ", socketId, common::ipv4_address_t(address).toString().data()); - if (found) + const auto& response = [&]() { + if constexpr (std::is_same_v) { - printf("valueId: %u\n", valueId); - printValue(value); + return dataPlane.lpm4LookupAddress(address); + } + else if constexpr (std::is_same_v) + { + return dataPlane.lpm6LookupAddress(address); } else { - printf("not found\n"); + static_assert(utils::always_false::value, + "lpmLookupAddress cannot be used with types other than ipv4/6_address"); } - } -} + }(); -void lpm6LookupAddress(const common::ipv6_address_t& ipv6Address) -{ - interface::dataPlane dataPlane; - const auto response = dataPlane.lpm6LookupAddress(ipv6Address); - for (const auto& iter : response) + for (const auto& [socketId, entry] : response) { - const auto& socketId = iter.first; - const auto& found = std::get<0>(iter.second); - const auto& valueId = std::get<1>(iter.second); - const auto& value = std::get<2>(iter.second); + const auto& [found, valueId, value] = entry; + std::cout << "[socketId: " << socketId << "] " << address.toString() << " -> "; - printf("[socketId: %u] %s -> ", socketId, common::ipv6_address_t(ipv6Address).toString().data()); if (found) { - printf("valueId: %u\n", valueId); + std::cout << "valueId: " << valueId << '\n'; printValue(value); } else { - printf("not found\n"); + std::cout << "not found\n"; } } } -void getErrors() +inline void lpm4LookupAddress(const common::ipv4_address_t& address) +{ + lpmLookupAddress(address); +} + +inline void lpm6LookupAddress(const common::ipv6_address_t& address) +{ + lpmLookupAddress(address); +} + +inline void getErrors() { interface::dataPlane dataPlane; - const auto response = dataPlane.getErrors(); - printf("errors:\n"); - for (const auto& iter : response) + std::cout << "errors:\n"; + for (const auto& [name, counter] : dataPlane.getErrors()) { - printf(" (%lu) %s\n", - iter.second.value, - iter.first.data()); + std::cout << " (" << counter.value << ") " << name << '\n'; } } -void getReport() +inline void getReport() { interface::dataPlane dataPlane; - const auto response = dataPlane.getReport(); - printf("%s\n", response.data()); + std::cout << dataPlane.getReport() << '\n'; } -void counter(const uint32_t& counter_id, - const std::optional& range_size) +inline void counter(uint32_t counter_id, const std::optional& range_size) { - interface::dataPlane dataplane; + std::vector counter_ids{counter_id}; - std::vector counter_ids = {counter_id}; - if (range_size && (*range_size) > 0) + if (range_size.has_value() && range_size.value() > 0) { - for (uint32_t offset = 0; - offset < (*range_size) - 1; - offset++) + for (uint32_t offset = 0; offset < range_size.value() - 1; offset++) { counter_ids.emplace_back(counter_id + offset + 1); } } - const auto response = common::sdp::SdpClient::GetCounters(counter_ids); + const auto& response = common::sdp::SdpClient::GetCounters(counter_ids); table_t table; - table.insert("counter_id", - "value"); + table.insert("counter_id", "value"); - for (uint32_t i = 0; - i < counter_ids.size(); - i++) + for (uint32_t i = 0; i < counter_ids.size(); i++) { - table.insert(counter_ids[i], - response[i]); + table.insert(counter_ids[i], response[i]); } table.print(); } using namespace ::dataplane::perf; -class tsc_monitoring_t +struct tsc_monitoring_t { -public: void connect_shm() { interface::dataPlane dataplane; - const auto response = dataplane.get_shm_tsc_info(); + const auto& response = dataplane.get_shm_tsc_info(); std::map ipc_cache; for (const auto& [core, socket, ipc_key, offset] : response) @@ -180,21 +173,19 @@ class tsc_monitoring_t YANET_GCC_BUG_UNUSED(socket); if (ipc_cache.find(ipc_key) == ipc_cache.end()) { - auto shmid = shmget(ipc_key, 0, 0); - if (shmid == -1) - { - throw std::string("shmget(") + std::to_string(ipc_key) + ", 0, 0) = " + std::strerror(errno); - } - auto shmaddr = shmat(shmid, nullptr, SHM_RDONLY); - if (shmaddr == (void*)-1) + auto&& [shmaddr, size] = common::ipc::SharedMemory::OpenBufferKey(ipc_key, false); + YANET_GCC_BUG_UNUSED(size); + + if (shmaddr == nullptr) { - throw std::string("shmat(") + std::to_string(ipc_key) + ", nullptr, 0) = " + std::strerror(errno); + throw std::system_error(errno, std::generic_category(), "Opening an existing buffer in shared memory failed"); } ipc_cache[ipc_key] = shmaddr; } - auto counter_addr = (tsc_deltas*)((intptr_t)ipc_cache[ipc_key] + offset); + auto counter_addr = reinterpret_cast( + reinterpret_cast(ipc_cache[ipc_key]) + offset); worker_counters.emplace_back(core, counter_addr, tsc_deltas{}, overflow_store{}); } } @@ -202,9 +193,13 @@ class tsc_monitoring_t void monitor() { connect_shm(); - for (auto iter = 0;; iter++) + const int header_interval = 4; + + for (int iter = 0;; ++iter) { - if (iter % 4 == 0) + bool render_header = (iter % header_interval == 0); + + if (render_header) { insert_header(); } @@ -212,10 +207,11 @@ class tsc_monitoring_t for (auto& [core_id, counter, previous_value, overflow_store] : worker_counters) { const auto& counter_copy = *counter; - for (auto bin = 0; bin < YANET_TSC_BINS_N; bin++) + for (int bin = 0; bin < YANET_TSC_BINS_N; ++bin) { overflow_store.handle_overflow(counter_copy, previous_value, bin); - if (iter % 4 == 0) + + if (render_header) { insert_bin(counter_copy, overflow_store, bin, core_id); } @@ -224,16 +220,100 @@ class tsc_monitoring_t previous_value = counter_copy; } - if (iter % 4 == 0) + if (render_header) { table.render(); } + std::this_thread::sleep_for(std::chrono::milliseconds(250)); } } -protected: - struct overflow_store; +private: + struct overflow_store + { + template + static auto make_tuple(T& obj) + { + return std::tie(obj.logicalPort_ingress_handle, + obj.acl_ingress_handle4, + obj.acl_ingress_handle6, + obj.tun64_ipv4_handle, + obj.tun64_ipv6_handle, + obj.route_handle4, + obj.route_handle6, + obj.decap_handle, + obj.nat64stateful_lan_handle, + obj.nat64stateful_wan_handle, + obj.nat64stateless_egress_handle, + obj.nat64stateless_ingress_handle, + obj.nat46clat_lan_handle, + obj.nat46clat_wan_handle, + obj.balancer_handle, + obj.balancer_icmp_reply_handle, + obj.balancer_icmp_forward_handle, + obj.route_tunnel_handle4, + obj.route_tunnel_handle6, + obj.acl_egress_handle4, + obj.acl_egress_handle6, + obj.logicalPort_egress_handle, + obj.controlPlane_handle); + } + + using CountersArray = std::array; + + CountersArray logicalPort_ingress_handle{}; + CountersArray acl_ingress_handle4{}; + CountersArray acl_ingress_handle6{}; + CountersArray tun64_ipv4_handle{}; + CountersArray tun64_ipv6_handle{}; + CountersArray route_handle4{}; + CountersArray route_handle6{}; + + CountersArray decap_handle{}; + CountersArray nat64stateful_lan_handle{}; + CountersArray nat64stateful_wan_handle{}; + CountersArray nat64stateless_egress_handle{}; + CountersArray nat64stateless_ingress_handle{}; + CountersArray nat46clat_lan_handle{}; + CountersArray nat46clat_wan_handle{}; + CountersArray balancer_handle{}; + + CountersArray balancer_icmp_reply_handle{}; + CountersArray balancer_icmp_forward_handle{}; + CountersArray route_tunnel_handle4{}; + CountersArray route_tunnel_handle6{}; + CountersArray acl_egress_handle4{}; + CountersArray acl_egress_handle6{}; + CountersArray logicalPort_egress_handle{}; + CountersArray controlPlane_handle{}; + + auto as_tuple() + { + return make_tuple(*this); + } + + [[nodiscard]] auto as_tuple() const + { + return make_tuple(*this); + } + + void handle_overflow(const tsc_deltas& cnt, const tsc_deltas& prev, int bin) + { + auto this_tuple = as_tuple(); + auto cnt_tuple = cnt.as_tuple(); + auto prev_tuple = prev.as_tuple(); + + auto op = [&](auto& this_member, const auto& cnt_member, const auto& prev_member) { + this_member[bin] += (prev_member[bin] > cnt_member[bin]) << (sizeof(uint16_t) * CHAR_BIT); + }; + + utils::zip_apply(op, this_tuple, cnt_tuple, prev_tuple); + } + }; + + std::vector> worker_counters; + table_t table; void insert_header() { @@ -266,98 +346,28 @@ class tsc_monitoring_t void insert_bin(const tsc_deltas& cnt, const overflow_store& of_store, int bin, uint32_t core_id) { - table.insert(bin == 0 ? std::to_string(core_id) : std::string{}, - bin == 0 ? std::to_string(cnt.iter_num) : std::string{}, - of_store.logicalPort_ingress_handle[bin] + cnt.logicalPort_ingress_handle[bin], - of_store.acl_ingress_handle4[bin] + cnt.acl_ingress_handle4[bin], - of_store.acl_ingress_handle6[bin] + cnt.acl_ingress_handle6[bin], - of_store.tun64_ipv4_handle[bin] + cnt.tun64_ipv4_handle[bin], - of_store.tun64_ipv6_handle[bin] + cnt.tun64_ipv6_handle[bin], - of_store.route_handle4[bin] + cnt.route_handle4[bin], - of_store.route_handle6[bin] + cnt.route_handle6[bin], - - of_store.decap_handle[bin] + cnt.decap_handle[bin], - of_store.nat64stateful_lan_handle[bin] + cnt.nat64stateful_lan_handle[bin], - of_store.nat64stateful_wan_handle[bin] + cnt.nat64stateful_wan_handle[bin], - of_store.nat64stateless_egress_handle[bin] + cnt.nat64stateless_egress_handle[bin], - of_store.nat64stateless_ingress_handle[bin] + cnt.nat64stateless_ingress_handle[bin], - of_store.nat46clat_lan_handle[bin] + cnt.nat46clat_lan_handle[bin], - of_store.nat46clat_wan_handle[bin] + cnt.nat46clat_wan_handle[bin], - of_store.balancer_handle[bin] + cnt.balancer_handle[bin], - - of_store.balancer_icmp_reply_handle[bin] + cnt.balancer_icmp_reply_handle[bin], - of_store.balancer_icmp_forward_handle[bin] + cnt.balancer_icmp_forward_handle[bin], - of_store.route_tunnel_handle4[bin] + cnt.route_tunnel_handle4[bin], - of_store.route_tunnel_handle6[bin] + cnt.route_tunnel_handle6[bin], - of_store.acl_egress_handle4[bin] + cnt.acl_egress_handle4[bin], - of_store.acl_egress_handle6[bin] + cnt.acl_egress_handle6[bin], - of_store.logicalPort_egress_handle[bin] + cnt.logicalPort_egress_handle[bin], - of_store.controlPlane_handle[bin] + cnt.controlPlane_handle[bin]); - } + constexpr std::size_t tuple_size = std::tuple_size_v; + // The total size of the row will be 2 fixed elements (core_id and iter_num) plus tuple_size + std::array row; - struct overflow_store - { - uint64_t logicalPort_ingress_handle[YANET_TSC_BINS_N]; - uint64_t acl_ingress_handle4[YANET_TSC_BINS_N]; - uint64_t acl_ingress_handle6[YANET_TSC_BINS_N]; - uint64_t tun64_ipv4_handle[YANET_TSC_BINS_N]; - uint64_t tun64_ipv6_handle[YANET_TSC_BINS_N]; - uint64_t route_handle4[YANET_TSC_BINS_N]; - uint64_t route_handle6[YANET_TSC_BINS_N]; - - uint64_t decap_handle[YANET_TSC_BINS_N]; - uint64_t nat64stateful_lan_handle[YANET_TSC_BINS_N]; - uint64_t nat64stateful_wan_handle[YANET_TSC_BINS_N]; - uint64_t nat64stateless_egress_handle[YANET_TSC_BINS_N]; - uint64_t nat64stateless_ingress_handle[YANET_TSC_BINS_N]; - uint64_t nat46clat_lan_handle[YANET_TSC_BINS_N]; - uint64_t nat46clat_wan_handle[YANET_TSC_BINS_N]; - uint64_t balancer_handle[YANET_TSC_BINS_N]; - - uint64_t balancer_icmp_reply_handle[YANET_TSC_BINS_N]; - uint64_t balancer_icmp_forward_handle[YANET_TSC_BINS_N]; - uint64_t route_tunnel_handle4[YANET_TSC_BINS_N]; - uint64_t route_tunnel_handle6[YANET_TSC_BINS_N]; - uint64_t acl_egress_handle4[YANET_TSC_BINS_N]; - uint64_t acl_egress_handle6[YANET_TSC_BINS_N]; - uint64_t logicalPort_egress_handle[YANET_TSC_BINS_N]; - uint64_t controlPlane_handle[YANET_TSC_BINS_N]; + row[0] = (bin == 0) ? std::to_string(core_id) : std::string{}; + row[1] = (bin == 0) ? std::to_string(cnt.iter_num) : std::string{}; - void handle_overflow(const tsc_deltas& cnt, const tsc_deltas& prev, int bin) - { - logicalPort_ingress_handle[bin] += (prev.logicalPort_ingress_handle[bin] > cnt.logicalPort_ingress_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - acl_ingress_handle4[bin] += (prev.acl_ingress_handle4[bin] > cnt.acl_ingress_handle4[bin]) << sizeof(uint16_t) * CHAR_BIT; - acl_ingress_handle6[bin] += (prev.acl_ingress_handle6[bin] > cnt.acl_ingress_handle6[bin]) << sizeof(uint16_t) * CHAR_BIT; - tun64_ipv4_handle[bin] += (prev.tun64_ipv4_handle[bin] > cnt.tun64_ipv4_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - tun64_ipv6_handle[bin] += (prev.tun64_ipv6_handle[bin] > cnt.tun64_ipv6_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - route_handle4[bin] += (prev.route_handle4[bin] > cnt.route_handle4[bin]) << sizeof(uint16_t) * CHAR_BIT; - route_handle6[bin] += (prev.route_handle6[bin] > cnt.route_handle6[bin]) << sizeof(uint16_t) * CHAR_BIT; - - decap_handle[bin] += (prev.decap_handle[bin] > cnt.decap_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat64stateful_lan_handle[bin] += (prev.nat64stateful_lan_handle[bin] > cnt.nat64stateful_lan_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat64stateful_wan_handle[bin] += (prev.nat64stateful_wan_handle[bin] > cnt.nat64stateful_wan_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat64stateless_egress_handle[bin] += (prev.nat64stateless_egress_handle[bin] > cnt.nat64stateless_egress_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat64stateless_ingress_handle[bin] += (prev.nat64stateless_ingress_handle[bin] > cnt.nat64stateless_ingress_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat46clat_lan_handle[bin] += (prev.nat46clat_lan_handle[bin] > cnt.nat46clat_lan_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - nat46clat_wan_handle[bin] += (prev.nat46clat_wan_handle[bin] > cnt.nat46clat_wan_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - balancer_handle[bin] += (prev.balancer_handle[bin] > cnt.balancer_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - - balancer_icmp_reply_handle[bin] += (prev.balancer_icmp_reply_handle[bin] > cnt.balancer_icmp_reply_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - balancer_icmp_forward_handle[bin] += (prev.balancer_icmp_forward_handle[bin] > cnt.balancer_icmp_forward_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - route_tunnel_handle4[bin] += (prev.route_tunnel_handle4[bin] > cnt.route_tunnel_handle4[bin]) << sizeof(uint16_t) * CHAR_BIT; - route_tunnel_handle6[bin] += (prev.route_tunnel_handle6[bin] > cnt.route_tunnel_handle6[bin]) << sizeof(uint16_t) * CHAR_BIT; - acl_egress_handle4[bin] += (prev.acl_egress_handle4[bin] > cnt.acl_egress_handle4[bin]) << sizeof(uint16_t) * CHAR_BIT; - acl_egress_handle6[bin] += (prev.acl_egress_handle6[bin] > cnt.acl_egress_handle6[bin]) << sizeof(uint16_t) * CHAR_BIT; - logicalPort_egress_handle[bin] += (prev.logicalPort_egress_handle[bin] > cnt.logicalPort_egress_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - controlPlane_handle[bin] += (prev.controlPlane_handle[bin] > cnt.controlPlane_handle[bin]) << sizeof(uint16_t) * CHAR_BIT; - } - }; + auto cnt_tuple = cnt.as_tuple(); + auto of_store_tuple = of_store.as_tuple(); - std::vector> worker_counters; - table_t table; + std::size_t index = 2; // Start after core_id and iter_num + auto op = [&](const auto& of_store_member, const auto& cnt_member) mutable { + row[index++] = std::to_string(of_store_member[bin] + cnt_member[bin]); + }; + + utils::zip_apply(op, of_store_tuple, cnt_tuple); + + table.insert(row.begin(), row.end()); + } }; -void tsc_monitoring() +inline void tsc_monitoring() { tsc_monitoring_t monitoring{}; monitoring.monitor(); From a2d9d37d688903c69dc0297f544b03b1c20de59b Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 21:48:24 +0400 Subject: [PATCH 175/195] Move to_percent method to common/utils.h. This is a common utility function, so it has been relocated to utils.h. --- cli/helper.h | 15 --------------- cli/limit.h | 16 ++-------------- cli/memory_manager.h | 2 +- cli/route.h | 17 +++-------------- common/utils.h | 18 ++++++++++++++++++ 5 files changed, 24 insertions(+), 44 deletions(-) diff --git a/cli/helper.h b/cli/helper.h index 027482e0..98eb22df 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -15,20 +14,6 @@ #include "common/sdpclient.h" #include "converter.h" -template -static std::string to_percent(const type current, const type maximum) -{ - double percent = 0.0; - if (maximum) - { - percent = (double)current / (double)maximum; - percent *= (double)100; - } - - std::stringstream stream; - stream << std::fixed << std::setprecision(2) << percent; - return stream.str(); -} std::vector split(const char* string, const char delimiter) diff --git a/cli/limit.h b/cli/limit.h index 13f60db7..ba403a90 100644 --- a/cli/limit.h +++ b/cli/limit.h @@ -1,9 +1,8 @@ #pragma once -#include - #include "common/icontrolplane.h" +#include "common/utils.h" #include "helper.h" namespace limit @@ -23,22 +22,11 @@ void summary() for (const auto& [name, socket_id, current, maximum] : response) { - double percent = 0.0; - if (maximum) - { - percent = (double)current / (double)maximum; - percent *= (double)100; - } - - std::stringstream stream; - stream << std::fixed << std::setprecision(2) << percent; - std::string percent_string = stream.str(); - table.insert(name, socket_id, current, maximum, - percent_string); + utils::to_percent(current, maximum)); } table.print(); diff --git a/cli/memory_manager.h b/cli/memory_manager.h index 7d6a33e0..7e60650e 100644 --- a/cli/memory_manager.h +++ b/cli/memory_manager.h @@ -79,7 +79,7 @@ void group() if (memory_group.limit) { maximum = memory_group.limit; - percent = to_percent(group_total, memory_group.limit); + percent = utils::to_percent(group_total, memory_group.limit); } table.insert(memory_group.name, diff --git a/cli/route.h b/cli/route.h index d809351c..1bfde511 100644 --- a/cli/route.h +++ b/cli/route.h @@ -4,6 +4,7 @@ #include "common/icontrolplane.h" +#include "common/utils.h" #include "helper.h" namespace route @@ -155,19 +156,13 @@ void lookup(const std::string& route_name, { const auto& [ingress_physical_ports, prefix, nexthop, label, egress_interface, peer, weight_percent] = item; - double percent = (double)100.0 * weight_percent; - - std::stringstream stream; - stream << std::fixed << std::setprecision(2) << percent; - std::string percent_string = stream.str(); - table.insert(ingress_physical_ports, prefix, nexthop.is_default() ? std::string("") : nexthop.toString(), label, egress_interface, peer, - percent_string); + utils::to_percent(weight_percent)); } table.print(); @@ -192,18 +187,12 @@ void get(const std::string& route_name, const auto& [ingress_physical_ports, prefix, nexthop, label, egress_interface, peer, weight_percent] = item; YANET_GCC_BUG_UNUSED(prefix); - double percent = (double)100.0 * weight_percent; - - std::stringstream stream; - stream << std::fixed << std::setprecision(2) << percent; - std::string percent_string = stream.str(); - table.insert(ingress_physical_ports, nexthop.is_default() ? std::string("") : nexthop.toString(), label, egress_interface, peer, - percent_string); + utils::to_percent(weight_percent)); } table.print(); diff --git a/common/utils.h b/common/utils.h index 9c07b7a0..74b39639 100644 --- a/common/utils.h +++ b/common/utils.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -81,5 +82,22 @@ struct is_set> : std::true_type template inline constexpr bool is_set_v = is_set::value; +// Utility to calculate percentage +// TODO C++20: use std::type_identity_t to establish non-deduced context +// Will allow to do `to_percent(4.2, 1)` +template +inline std::string to_percent(T current, T maximum = 1) +{ + double percent = 0.0; + if (maximum != 0) + { + percent = static_cast(current) / static_cast(maximum) * 100.0; + } + + std::ostringstream stream; + stream << std::fixed << std::setprecision(2) << percent; + return stream.str(); +} + } // namespace utils From 8d9935d3863a733620d15ed387b2b5dc90797dd7 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 21:49:45 +0400 Subject: [PATCH 176/195] Move split function to common/utils.h. This is a common utility, and it was previously duplicated in three places. Also changed the input parameter from const char* to std::string_view ans use std::string_view::find for faster string splitting. --- autotest/autotest.cpp | 24 +++++------------------- cli/helper.h | 21 ++------------------- cli/rib.h | 17 +---------------- common/utils.h | 23 +++++++++++++++++++++++ 4 files changed, 31 insertions(+), 54 deletions(-) diff --git a/autotest/autotest.cpp b/autotest/autotest.cpp index f983150a..5a3cef86 100644 --- a/autotest/autotest.cpp +++ b/autotest/autotest.cpp @@ -20,6 +20,7 @@ #include "common.h" #include "common/sdpclient.h" +#include "common/utils.h" #define MAX_PACK_LEN 16384 #define SOCK_DEV_PREFIX "sock_dev:" @@ -741,21 +742,6 @@ void tAutotest::recvThread(std::string interfaceName, unlink(pcapDumper.path().data()); } -std::vector split(const std::string& string, - char delimiter = ' ') -{ - std::vector result; - - std::stringstream stream(string); - std::string item; - while (std::getline(stream, item, delimiter)) - { - result.emplace_back(item); - } - - return result; -} - bool tAutotest::step_ipv4Update(const YAML::Node& yamlStep) { if (yamlStep.IsScalar()) @@ -1535,7 +1521,7 @@ void tAutotest::convert_ipv4Update(const std::string& string) convert_ipv4Remove(prefix); - for (const auto& nexthop : split(nexthops)) + for (const auto& nexthop : utils::split(nexthops, ' ')) { common::icp::rib_update::insert request = {"autotest", "default", YANET_RIB_PRIORITY_DEFAULT, {}}; std::get<3>(request)[attribute_default]["ipv4"][nexthop].emplace_back(prefix, @@ -1572,7 +1558,7 @@ void tAutotest::convert_ipv4LabelledUpdate(const std::string& string) convert_ipv4LabelledRemove(prefix); - for (const auto& nexthop_label : split(nexthops)) + for (const auto& nexthop_label : utils::split(nexthops, ' ')) { std::string nexthop = nexthop_label.substr(0, nexthop_label.find(":")); std::string label = nexthop_label.substr(nexthop_label.find(":") + 1); @@ -1616,7 +1602,7 @@ void tAutotest::convert_ipv6Update(const std::string& string) std::string prefix = string.substr(0, string.find(" -> ")); std::string nexthops = string.substr(string.find(" -> ") + 4); - for (const auto& nexthop : split(nexthops)) + for (const auto& nexthop : utils::split(nexthops, ' ')) { common::icp::rib_update::insert request = {"autotest", "default", YANET_RIB_PRIORITY_DEFAULT, {}}; std::get<3>(request)[attribute_default]["ipv6"][nexthop].emplace_back(prefix, @@ -1633,7 +1619,7 @@ void tAutotest::convert_ipv6LabelledUpdate(const std::string& string) std::string prefix = string.substr(0, string.find(" -> ")); std::string nexthops = string.substr(string.find(" -> ") + 4); - for (const auto& nexthop_label : split(nexthops)) + for (const auto& nexthop_label : utils::split(nexthops, ' ')) { std::string nexthop = nexthop_label.substr(0, nexthop_label.find("|")); std::string label = nexthop_label.substr(nexthop_label.find("|") + 1); diff --git a/cli/helper.h b/cli/helper.h index 98eb22df..0f976917 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -14,22 +13,6 @@ #include "common/sdpclient.h" #include "converter.h" - -std::vector split(const char* string, - const char delimiter) -{ - std::vector result; - std::stringstream ss(string); - - std::string part; - while (std::getline(ss, part, delimiter)) - { - result.emplace_back(part); - } - - return result; -} - void fillValue(std::optional& value, const std::string& string) { if (string == "any") @@ -241,7 +224,7 @@ class table_t std::map format_keys_i; if (const char* format_keys_pointer = std::getenv("YANET_FORMAT_KEYS")) { - format_keys = split(format_keys_pointer, ','); + format_keys = utils::split(format_keys_pointer, ','); } std::vector keys; @@ -313,7 +296,7 @@ class table_t bool print_selected_cols_only = false; if (const char* columns_pointer = std::getenv("YANET_FORMAT_COLUMNS")) { - user_selected_col_names = split(columns_pointer, ','); + user_selected_col_names = utils::split(columns_pointer, ','); print_selected_cols_only = true; } diff --git a/cli/rib.h b/cli/rib.h index 3fdcf7d0..2a9d27f0 100644 --- a/cli/rib.h +++ b/cli/rib.h @@ -208,25 +208,10 @@ void get(const std::string& vrf, table.print(); } -std::vector split(const std::string& string, - char delimiter = ' ') -{ - std::vector result; - - std::stringstream stream(string); - std::string item; - while (std::getline(stream, item, delimiter)) - { - result.emplace_back(item); - } - - return result; -} - void convert(const std::string& string, std::tuple>& result) { - auto nexthop_label_string = split(string, '+'); + auto nexthop_label_string = utils::split(string, '+'); if (nexthop_label_string.size() == 1) { diff --git a/common/utils.h b/common/utils.h index 74b39639..604dbac7 100644 --- a/common/utils.h +++ b/common/utils.h @@ -99,5 +99,28 @@ inline std::string to_percent(T current, T maximum = 1) return stream.str(); } +// Split a string_view into a vector of strings based on a delimiter +inline std::vector split(const std::string_view str, char delimiter) +{ + std::vector result; + size_t start = 0; + size_t end = 0; + + while ((end = str.find(delimiter, start)) != std::string_view::npos) + { + result.emplace_back(str.substr(start, end - start)); + start = end + 1; + } + result.emplace_back(str.substr(start)); + return result; +} + +// Split for std::string but disabled for const char* to avoid ambiguity +template>> +inline std::vector split(const std::string& str, char delimiter) +{ + return split(std::string_view(str), delimiter); +} + } // namespace utils From 9c676703cb8b0120f2efb85b624adb30f400ae7f Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 21:52:37 +0400 Subject: [PATCH 177/195] Remove unused getDiff and getDiffTuple functions --- cli/helper.h | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/cli/helper.h b/cli/helper.h index 0f976917..b4ff8d1f 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -159,41 +159,6 @@ void call(void (*func)(TArgs... args), std::apply(func, tuple); } -template -void getDiffTuple(TDiffTuple& diff, - const TTuple& curr, - const TTuple& prev) -{ - if constexpr (TIndex < TSize) - { - std::get(diff) = std::get(curr) - std::get(prev); - getDiffTuple(diff, curr, prev); - } -} - -template -std::map> getDiff(const std::map>& curr, - const std::map>& prev) -{ - std::map> result; - - for (const auto& iter : curr) - { - if (prev.find(iter.first) != prev.end()) - { - std::array diff; - getDiffTuple<0, sizeof...(TSecondArgs)>(diff, iter.second, prev.find(iter.first)->second); - result[iter.first] = diff; - } - } - - return result; -} - class table_t { public: From 0e49073fe520079b9d00994ec330d1ef0b53efda Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 30 Sep 2024 16:34:00 +0400 Subject: [PATCH 178/195] Move table_t class from helper to it's own header and rename it table_t is bland and not so informative. The purpose of this class is to print it's content, so rename it to TablePrinter --- cli/acl.h | 6 +- cli/balancer.h | 12 +- cli/bus.h | 5 +- cli/convert.h | 4 +- cli/develop.h | 6 +- cli/dregress.h | 6 +- cli/helper.h | 257 ------------------------------------------ cli/limit.h | 4 +- cli/memory_manager.h | 6 +- cli/nat46clat.h | 6 +- cli/nat64stateful.h | 8 +- cli/neighbor.h | 4 +- cli/rib.h | 10 +- cli/route.h | 20 ++-- cli/show.h | 40 +++---- cli/table_printer.h | 259 +++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 327 insertions(+), 326 deletions(-) create mode 100644 cli/table_printer.h diff --git a/cli/acl.h b/cli/acl.h index 7579300f..89c1ea77 100644 --- a/cli/acl.h +++ b/cli/acl.h @@ -2,7 +2,7 @@ #include "common/icontrolplane.h" -#include "helper.h" +#include "table_printer.h" namespace acl { @@ -52,7 +52,7 @@ void unwind(const std::string& in_module, transport_flags, recordstate}); - table_t table({.optional_null = "any"}); + TablePrinter table({.optional_null = "any"}); table.insert("module", "direction", "network_source", @@ -113,7 +113,7 @@ void lookup(std::optional module, transport_source, transport_destination}); - table_t table; + TablePrinter table; table.insert("ruleno", "label", "rule"); diff --git a/cli/balancer.h b/cli/balancer.h index bbf3421b..3d64e42a 100644 --- a/cli/balancer.h +++ b/cli/balancer.h @@ -5,7 +5,7 @@ #include "common/iproto_controlplane.h" #include "common/type.h" -#include "helper.h" +#include "table_printer.h" namespace balancer { @@ -15,7 +15,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.balancer_summary(); - table_t table; + TablePrinter table; table.insert("module", "services", "reals_enabled", @@ -66,7 +66,7 @@ void service(std::string module_string, interface::dataPlane dataplane; auto balancer_service_connections = dataplane.balancer_service_connections(); - table_t table; + TablePrinter table; table.insert("module", "virtual_ip", "proto", @@ -201,7 +201,7 @@ void real_find(std::string module_string, interface::dataPlane dataplane; auto balancer_real_connections = dataplane.balancer_real_connections(); - table_t table; + TablePrinter table; table.insert("module", "virtual_ip", "proto", @@ -350,7 +350,7 @@ void state(std::string module, } } - table_t table; + TablePrinter table; table.insert("module", "virtual_ip", "proto", @@ -489,7 +489,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.balancer_announce(); - table_t table; + TablePrinter table; table.insert("module", "announces"); diff --git a/cli/bus.h b/cli/bus.h index 74480be8..59b554c5 100644 --- a/cli/bus.h +++ b/cli/bus.h @@ -1,6 +1,7 @@ #pragma once #include "helper.h" +#include "table_printer.h" #include "influxdb_format.h" namespace bus @@ -78,7 +79,7 @@ inline void bus_requests() OpenSharedMemoryDataplaneBuffers(sdp_data, false); auto requests = get_bus_requests(sdp_data); - table_t table; + TablePrinter table; table.insert("request", "count", "duration_ms"); for (const auto& [request, count, duration] : requests) { @@ -119,7 +120,7 @@ inline void bus_errors() OpenSharedMemoryDataplaneBuffers(sdp_data, false); auto errors = get_bus_errors(sdp_data); - table_t table; + TablePrinter table; table.insert("error", "count"); for (const auto& [error, count] : errors) { diff --git a/cli/convert.h b/cli/convert.h index 0c5795bb..32a91333 100644 --- a/cli/convert.h +++ b/cli/convert.h @@ -1,7 +1,7 @@ #pragma once #include "common/icontrolplane.h" -#include "helper.h" +#include "table_printer.h" namespace convert { @@ -11,7 +11,7 @@ inline void logical_module() interface::controlPlane controlPlane; const auto response = controlPlane.convert("logical_module"); - table_t table; + TablePrinter table; table.insert("id", "name"); diff --git a/cli/develop.h b/cli/develop.h index 946c08c8..2164e5c9 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -14,7 +14,7 @@ #include "common/tsc_deltas.h" #include "common/tuple.h" -#include "helper.h" +#include "table_printer.h" namespace develop::dataplane { @@ -148,7 +148,7 @@ inline void counter(uint32_t counter_id, const std::optional& range_si const auto& response = common::sdp::SdpClient::GetCounters(counter_ids); - table_t table; + TablePrinter table; table.insert("counter_id", "value"); for (uint32_t i = 0; i < counter_ids.size(); i++) @@ -313,7 +313,7 @@ struct tsc_monitoring_t }; std::vector> worker_counters; - table_t table; + TablePrinter table; void insert_header() { diff --git a/cli/dregress.h b/cli/dregress.h index e97b659b..0bb3f3e1 100644 --- a/cli/dregress.h +++ b/cli/dregress.h @@ -2,7 +2,7 @@ #include "common/icontrolplane.h" -#include "helper.h" +#include "table_printer.h" namespace dregress { @@ -12,7 +12,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.dregress_config(); - table_t table; + TablePrinter table; table.insert("module", "ipv6_sources", "ipv6_destination", @@ -42,7 +42,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.dregress_config(); - table_t table; + TablePrinter table; table.insert("module", "announces"); diff --git a/cli/helper.h b/cli/helper.h index b4ff8d1f..ee0b56b6 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -1,17 +1,12 @@ #pragma once -#include #include -#include #include #include #include #include -#include - #include "common/sdpclient.h" -#include "converter.h" void fillValue(std::optional& value, const std::string& string) { @@ -159,258 +154,6 @@ void call(void (*func)(TArgs... args), std::apply(func, tuple); } -class table_t -{ -public: - table_t(const converter::config_t config = {}) : - config(config) {} - - template - void insert(const Args&... args) - { - std::vector row = {converter::to_string(args, config)...}; - insert_row(row); - } - - template::iterator_category> - void insert(Iterator begin, Iterator end) - { - std::vector row; - for (auto it = begin; it != end; ++it) - { - row.push_back(converter::to_string(*it, config)); - } - insert_row(row); - } - - void print_json() - { - std::vector format_keys; - std::map format_keys_i; - if (const char* format_keys_pointer = std::getenv("YANET_FORMAT_KEYS")) - { - format_keys = utils::split(format_keys_pointer, ','); - } - - std::vector keys; - - bool header = true; - nlohmann::json json_root; - for (auto& row : table) - { - if (header) - { - for (uint32_t string_i = 0; - string_i < row.size(); - string_i++) - { - for (uint32_t format_i = 0; - format_i < format_keys.size(); - format_i++) - { - if (row[string_i] == format_keys[format_i]) - { - format_keys_i[string_i] = format_i; - } - } - } - - keys = row; - header = false; - continue; - } - - std::vector tree; - tree.resize(format_keys.size()); - - nlohmann::json json_row; - for (uint32_t string_i = 0; - string_i < row.size(); - string_i++) - { - if (format_keys_i.count(string_i)) - { - tree[format_keys_i[string_i]] = row[string_i]; - } - else - { - json_row[keys[string_i]] = row[string_i]; - } - } - - auto* json_current = &json_root; - for (const auto& key : tree) - { - json_current = &((*json_current)[key]); - } - (*json_current).emplace_back(json_row); - } - - printf("%s\n", json_root.dump(2).data()); - } - - void print_default() - { - if (table.size() == 0 || - columnLengths.size() == 0) - { - return; - } - - std::vector user_selected_col_names; - bool print_selected_cols_only = false; - if (const char* columns_pointer = std::getenv("YANET_FORMAT_COLUMNS")) - { - user_selected_col_names = utils::split(columns_pointer, ','); - print_selected_cols_only = true; - } - - /* header row contains table's column names */ - auto& header_row = table[0]; - - /* If the user listed only specific columns of the table to be printed in specific order, - need to build a relation between index of column in user-provided order and its index in the table (only if it does exist in the table): - This relation: columns_order[col_idx_in_user_selection] = col_idx_in_table - - Otherwise, when no custom columns' selection and/or order is provided by the user, - print all columns of the table in the table's order: - columns_order[col_idx_in_table] = col_idx_in_table */ - std::vector columns_order; - if (print_selected_cols_only) - { - uint32_t col_idx_in_user_selection = 0; - while (columns_order.size() < user_selected_col_names.size()) - { - bool selected_col_name_found = false; - for (uint32_t col_idx_in_table = 0; col_idx_in_table < header_row.size(); ++col_idx_in_table) - { - if (user_selected_col_names[col_idx_in_user_selection] == header_row[col_idx_in_table]) - { - // col_idx_in_user_selection must be equal to columns_order.size() prior to insertion (check?) - columns_order.push_back(col_idx_in_table); - selected_col_name_found = true; - ++col_idx_in_user_selection; - break; - } - } - - if (!selected_col_name_found) - { - // evidently, user provided such a column name, which does not exist in the table, cannot print it - // shifting tail of user_selected_col_names to the left by erasing non-existent user-provided column name - user_selected_col_names.erase(user_selected_col_names.begin() + col_idx_in_user_selection); - } - } - } - else - { - columns_order.resize(header_row.size()); - std::iota(columns_order.begin(), columns_order.end(), 0); - } - - if (columns_order.size() == 0) - { - /* column names provided by user do not match any column names of the table, - or the table does not have any columns at all (what?!) */ - return; - } - - bool header = true; - for (auto& row : table) - { - printf("%-*s", - columnLengths[columns_order[0]], - row[columns_order[0]].data()); - - for (uint32_t string_i = 1; - string_i < columns_order.size(); - string_i++) - { - if (string_i != columns_order.size() - 1) - { - printf(" %-*s", - columnLengths[columns_order[string_i]], - row[columns_order[string_i]].data()); - } - else - { - // Do not explode the last column with padding whitespace bytes. - printf(" %s", - row[columns_order[string_i]].data()); - } - } - - printf("\n"); - - if (header) - { - printf("%s", std::string(columnLengths[columns_order[0]], '-').data()); - - for (uint32_t string_i = 1; - string_i < columns_order.size(); - string_i++) - { - printf(" %s", std::string(columnLengths[columns_order[string_i]], '-').data()); - } - - printf("\n"); - - header = false; - } - } - } - - void print() - { - std::string format; - if (const char* format_pointer = std::getenv("YANET_FORMAT")) - { - format = format_pointer; - } - - if (format == "json") - { - print_json(); - } - else - { - print_default(); - } - } - - void render() - { - printf("\033[H\033[2J"); - fflush(stdout); - - print_default(); - table.clear(); - } - -private: - void insert_row(const std::vector& row) - { - if (row.size() > columnLengths.size()) - { - columnLengths.resize(row.size(), 0); - } - - for (uint32_t string_i = 0; string_i < row.size(); ++string_i) - { - if (columnLengths[string_i] < row[string_i].size()) - { - columnLengths[string_i] = row[string_i].size(); - } - } - - table.emplace_back(row); - } - - converter::config_t config; - std::vector> table; - std::vector columnLengths; -}; - void OpenSharedMemoryDataplaneBuffers(common::sdp::DataPlaneInSharedMemory& sdp_data, bool open_workers_data) { if (common::sdp::SdpClient::ReadSharedMemoryData(sdp_data, open_workers_data) != eResult::success) diff --git a/cli/limit.h b/cli/limit.h index ba403a90..38b7ee71 100644 --- a/cli/limit.h +++ b/cli/limit.h @@ -3,7 +3,7 @@ #include "common/icontrolplane.h" #include "common/utils.h" -#include "helper.h" +#include "table_printer.h" namespace limit { @@ -13,7 +13,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.limit_summary(); - table_t table; + TablePrinter table; table.insert("name", "socket_id", "current", diff --git a/cli/memory_manager.h b/cli/memory_manager.h index 7e60650e..bdce0f21 100644 --- a/cli/memory_manager.h +++ b/cli/memory_manager.h @@ -1,7 +1,7 @@ #pragma once #include "common/idataplane.h" -#include "helper.h" +#include "table_printer.h" namespace memory_manager { @@ -14,7 +14,7 @@ void show() const auto& [response_memory_group, response_objects] = response; YANET_GCC_BUG_UNUSED(response_memory_group); - table_t table; + TablePrinter table; table.insert("name", "socket_id", "current"); @@ -43,7 +43,7 @@ void group() const auto response = dataplane.memory_manager_stats(); const auto& [response_memory_group, response_objects] = response; - table_t table; + TablePrinter table; table.insert("group", "current", "maximum", diff --git a/cli/nat46clat.h b/cli/nat46clat.h index f9012005..850364a6 100644 --- a/cli/nat46clat.h +++ b/cli/nat46clat.h @@ -2,7 +2,7 @@ #include "common/icontrolplane.h" -#include "helper.h" +#include "table_printer.h" namespace nat46clat { @@ -12,7 +12,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.nat46clat_config(); - table_t table; + TablePrinter table; table.insert("module", "ipv6_source", "ipv6_destination", @@ -34,7 +34,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.nat46clat_announce(); - table_t table; + TablePrinter table; table.insert("module", "announces"); diff --git a/cli/nat64stateful.h b/cli/nat64stateful.h index 88e98e4a..45ce888e 100644 --- a/cli/nat64stateful.h +++ b/cli/nat64stateful.h @@ -3,7 +3,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" -#include "helper.h" +#include "table_printer.h" namespace nat64stateful { @@ -13,7 +13,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.nat64stateful_config(); - table_t table; + TablePrinter table; table.insert("module", "ipv4_pool_size", "next_module"); @@ -39,7 +39,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.nat64stateful_announce(); - table_t table; + TablePrinter table; table.insert("module", "announces"); @@ -152,7 +152,7 @@ void state(std::optional module) interface::dataPlane dataplane; const auto response = dataplane.nat64stateful_state({module_id}); - table_t table; + TablePrinter table; table.insert("module", "ipv6_source", "ipv4_source", diff --git a/cli/neighbor.h b/cli/neighbor.h index 2a961cbe..9ac10d22 100644 --- a/cli/neighbor.h +++ b/cli/neighbor.h @@ -2,7 +2,7 @@ #include "common/idataplane.h" -#include "helper.h" +#include "table_printer.h" namespace neighbor { @@ -12,7 +12,7 @@ void show() interface::dataPlane dataplane; const auto response = dataplane.neighbor_show(); - table_t table({.optional_null = "static"}); + TablePrinter table({.optional_null = "static"}); table.insert("route_name", "interface_name", "ip_address", diff --git a/cli/rib.h b/cli/rib.h index 2a9d27f0..b55243ff 100644 --- a/cli/rib.h +++ b/cli/rib.h @@ -4,7 +4,7 @@ #include "common/icontrolplane.h" -#include "helper.h" +#include "table_printer.h" namespace rib { @@ -14,7 +14,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.rib_summary(); - table_t table; + TablePrinter table; table.insert("vrf", "priority", "protocol", @@ -47,7 +47,7 @@ void prefixes() interface::controlPlane controlPlane; const auto response = controlPlane.rib_prefixes(); - table_t table; + TablePrinter table; table.insert("vrf", "priority", "prefix", @@ -103,7 +103,7 @@ void lookup(const std::string& vrf, interface::controlPlane controlPlane; const auto response = controlPlane.rib_lookup({vrf, address}); - table_t table; + TablePrinter table; table.insert("vrf", "priority", "prefix", @@ -159,7 +159,7 @@ void get(const std::string& vrf, interface::controlPlane controlPlane; const auto response = controlPlane.rib_get({vrf, prefix}); - table_t table; + TablePrinter table; table.insert("vrf", "priority", "protocol", diff --git a/cli/route.h b/cli/route.h index 1bfde511..28e32dc0 100644 --- a/cli/route.h +++ b/cli/route.h @@ -1,11 +1,9 @@ #pragma once -#include - #include "common/icontrolplane.h" #include "common/utils.h" -#include "helper.h" +#include "table_printer.h" namespace route { @@ -15,7 +13,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.route_summary(); - table_t table; + TablePrinter table; table.insert("module", "vrf"); @@ -33,7 +31,7 @@ void interface() interface::controlPlane controlplane; const auto response = controlplane.route_interface(); - table_t table; + TablePrinter table; table.insert("module", "interface", "address", @@ -67,7 +65,7 @@ void lookup(const std::string& route_name, interface::controlPlane controlplane; auto response = controlplane.route_lookup({route_name, address}); - table_t table; + TablePrinter table; table.insert("ingress_physical_ports", "prefix", "nexthop", @@ -94,7 +92,7 @@ void get(const std::string& route_name, interface::controlPlane controlplane; auto response = controlplane.route_get({route_name, prefix}); - table_t table; + TablePrinter table; table.insert("ingress_physical_ports", "nexthop", "egress_interface", @@ -119,7 +117,7 @@ void counters() interface::controlPlane controlplane; auto response = controlplane.route_counters(); - table_t table; + TablePrinter table; table.insert("link", "nexthop", "prefix", @@ -143,7 +141,7 @@ void lookup(const std::string& route_name, interface::controlPlane controlplane; auto response = controlplane.route_tunnel_lookup({route_name, address}); - table_t table; + TablePrinter table; table.insert("ingress_physical_ports", "prefix", "nexthop", @@ -174,7 +172,7 @@ void get(const std::string& route_name, interface::controlPlane controlplane; auto response = controlplane.route_tunnel_get({route_name, prefix}); - table_t table; + TablePrinter table; table.insert("ingress_physical_ports", "nexthop", "label", @@ -203,7 +201,7 @@ void counters() interface::controlPlane controlplane; auto response = controlplane.route_tunnel_counters(); - table_t table; + TablePrinter table; table.insert("link", "nexthop", "counts", diff --git a/cli/show.h b/cli/show.h index 0717b0ea..ffbdb494 100644 --- a/cli/show.h +++ b/cli/show.h @@ -10,7 +10,7 @@ #include "common/tsc_deltas.h" #include "common/version.h" -#include "helper.h" +#include "table_printer.h" namespace show { @@ -20,7 +20,7 @@ inline void physicalPort() interface::controlPlane controlPlane; const auto response = controlPlane.getPhysicalPorts(); - table_t table; + TablePrinter table; table.insert("moduleName", "link", "speed", @@ -75,7 +75,7 @@ inline void logicalPort() interface::controlPlane controlPlane; const auto response = controlPlane.getLogicalPorts(); - table_t table; + TablePrinter table; table.insert("moduleName", "physicalPortName", "vlanId", @@ -142,7 +142,7 @@ inline void summary(std::optional module) interface::controlPlane controlPlane; const auto response = controlPlane.tun64_tunnels(); - table_t table; + TablePrinter table; table.insert("module", "source_address", "prefixes", @@ -174,7 +174,7 @@ inline void announce(std::optional module) interface::controlPlane controlPlane; const auto response = controlPlane.tun64_prefixes(); - table_t table; + TablePrinter table; table.insert("module", "prefix", "announces"); @@ -201,7 +201,7 @@ inline void mappings(std::optional module) interface::controlPlane controlPlane; const auto response = controlPlane.tun64_mappings(); - table_t table; + TablePrinter table; table.insert("module", "ipv4Address", "ipv6Address", @@ -235,7 +235,7 @@ inline void summary() interface::controlPlane controlPlane; const auto response = controlPlane.getDecaps(); - table_t table; + TablePrinter table; table.insert("module", "prefixes", "DSCP", @@ -275,7 +275,7 @@ inline void announce() interface::controlPlane controlPlane; const auto response = controlPlane.getDecapPrefixes(); - table_t table; + TablePrinter table; table.insert("module", "prefix", "announces"); @@ -303,7 +303,7 @@ inline void summary() interface::controlPlane controlPlane; const auto response = controlPlane.getNat64statelesses(); - table_t table; + TablePrinter table; table.insert("module", "translations", "WKP", @@ -329,7 +329,7 @@ inline void translation() interface::controlPlane controlPlane; const auto response = controlPlane.getNat64statelessTranslations(); - table_t table; + TablePrinter table; table.insert("moduleName", "ipv6Address", "ipv6DestinationAddress", @@ -362,7 +362,7 @@ inline void announce() interface::controlPlane controlPlane; const auto response = controlPlane.getNat64statelessPrefixes(); - table_t table; + TablePrinter table; table.insert("module", "prefix", "announces"); @@ -509,7 +509,7 @@ static void list_fw_rules(unsigned int mask, bool list) common::icp::getFwLabels::response labels; interface::controlPlane controlPlane; - table_t table; + TablePrinter table; if (list) { table.insert("id", @@ -625,7 +625,7 @@ inline void fwlist(std::optional str) inline void errors() { - table_t table; + TablePrinter table; table.insert("name", "counter"); interface::dataPlane dataPlane; @@ -644,7 +644,7 @@ inline void samples() interface::controlPlane controlPlane; const auto response = controlPlane.getSamples(); - table_t table; + TablePrinter table; table.insert("in_iface", "out_iface", "proto", @@ -710,7 +710,7 @@ inline void values() interface::controlPlane controlplane; const auto controlplane_values = controlplane.controlplane_values(); - table_t table; + TablePrinter table; table.insert("application", "name", "value"); @@ -730,7 +730,7 @@ inline void durations() interface::controlPlane controlplane; const auto controlplane_durations = controlplane.controlplane_durations(); - table_t table; + TablePrinter table; table.insert("application", "name", "duration"); @@ -747,7 +747,7 @@ inline void durations() inline void version() { - table_t table; + TablePrinter table; table.insert("application", "version", "revision", @@ -815,7 +815,7 @@ inline void counter_by_name(std::string counter_name, } } - table_t table; + TablePrinter table; table.insert("core_id", "counter_value"); @@ -832,7 +832,7 @@ inline void shm_info() interface::dataPlane dataplane; const auto response = dataplane.get_shm_info(); - table_t table; + TablePrinter table; table.insert("ring name", "dump tag", "dump size", @@ -855,7 +855,7 @@ void shm_tsc_info() interface::dataPlane dataplane; const auto response = dataplane.get_shm_tsc_info(); - table_t table; + TablePrinter table; table.insert("core id", "socket id", "ipc key", diff --git a/cli/table_printer.h b/cli/table_printer.h new file mode 100644 index 00000000..511d0dd9 --- /dev/null +++ b/cli/table_printer.h @@ -0,0 +1,259 @@ +#pragma once + +#include +#include + +#include "common/utils.h" +#include "converter.h" + +class TablePrinter +{ +public: + TablePrinter(const converter::config_t config = {}) : + config(config) {} + + template + void insert(const Args&... args) + { + std::vector row = {converter::to_string(args, config)...}; + insert_row(row); + } + + template::iterator_category> + void insert(Iterator begin, Iterator end) + { + std::vector row; + for (auto it = begin; it != end; ++it) + { + row.push_back(converter::to_string(*it, config)); + } + insert_row(row); + } + + void print_json() + { + std::vector format_keys; + std::map format_keys_i; + if (const char* format_keys_pointer = std::getenv("YANET_FORMAT_KEYS")) + { + format_keys = utils::split(format_keys_pointer, ','); + } + + std::vector keys; + + bool header = true; + nlohmann::json json_root; + for (auto& row : table) + { + if (header) + { + for (uint32_t string_i = 0; + string_i < row.size(); + string_i++) + { + for (uint32_t format_i = 0; + format_i < format_keys.size(); + format_i++) + { + if (row[string_i] == format_keys[format_i]) + { + format_keys_i[string_i] = format_i; + } + } + } + + keys = row; + header = false; + continue; + } + + std::vector tree; + tree.resize(format_keys.size()); + + nlohmann::json json_row; + for (uint32_t string_i = 0; + string_i < row.size(); + string_i++) + { + if (format_keys_i.count(string_i)) + { + tree[format_keys_i[string_i]] = row[string_i]; + } + else + { + json_row[keys[string_i]] = row[string_i]; + } + } + + auto* json_current = &json_root; + for (const auto& key : tree) + { + json_current = &((*json_current)[key]); + } + (*json_current).emplace_back(json_row); + } + + printf("%s\n", json_root.dump(2).data()); + } + + void print_default() + { + if (table.size() == 0 || + columnLengths.size() == 0) + { + return; + } + + std::vector user_selected_col_names; + bool print_selected_cols_only = false; + if (const char* columns_pointer = std::getenv("YANET_FORMAT_COLUMNS")) + { + user_selected_col_names = utils::split(columns_pointer, ','); + print_selected_cols_only = true; + } + + /* header row contains table's column names */ + auto& header_row = table[0]; + + /* If the user listed only specific columns of the table to be printed in specific order, + need to build a relation between index of column in user-provided order and its index in the table (only if it does exist in the table): + This relation: columns_order[col_idx_in_user_selection] = col_idx_in_table + + Otherwise, when no custom columns' selection and/or order is provided by the user, + print all columns of the table in the table's order: + columns_order[col_idx_in_table] = col_idx_in_table */ + std::vector columns_order; + if (print_selected_cols_only) + { + uint32_t col_idx_in_user_selection = 0; + while (columns_order.size() < user_selected_col_names.size()) + { + bool selected_col_name_found = false; + for (uint32_t col_idx_in_table = 0; col_idx_in_table < header_row.size(); ++col_idx_in_table) + { + if (user_selected_col_names[col_idx_in_user_selection] == header_row[col_idx_in_table]) + { + // col_idx_in_user_selection must be equal to columns_order.size() prior to insertion (check?) + columns_order.push_back(col_idx_in_table); + selected_col_name_found = true; + ++col_idx_in_user_selection; + break; + } + } + + if (!selected_col_name_found) + { + // evidently, user provided such a column name, which does not exist in the table, cannot print it + // shifting tail of user_selected_col_names to the left by erasing non-existent user-provided column name + user_selected_col_names.erase(user_selected_col_names.begin() + col_idx_in_user_selection); + } + } + } + else + { + columns_order.resize(header_row.size()); + std::iota(columns_order.begin(), columns_order.end(), 0); + } + + if (columns_order.size() == 0) + { + /* column names provided by user do not match any column names of the table, + or the table does not have any columns at all (what?!) */ + return; + } + + bool header = true; + for (auto& row : table) + { + printf("%-*s", + columnLengths[columns_order[0]], + row[columns_order[0]].data()); + + for (uint32_t string_i = 1; + string_i < columns_order.size(); + string_i++) + { + if (string_i != columns_order.size() - 1) + { + printf(" %-*s", + columnLengths[columns_order[string_i]], + row[columns_order[string_i]].data()); + } + else + { + // Do not explode the last column with padding whitespace bytes. + printf(" %s", + row[columns_order[string_i]].data()); + } + } + + printf("\n"); + + if (header) + { + printf("%s", std::string(columnLengths[columns_order[0]], '-').data()); + + for (uint32_t string_i = 1; + string_i < columns_order.size(); + string_i++) + { + printf(" %s", std::string(columnLengths[columns_order[string_i]], '-').data()); + } + + printf("\n"); + + header = false; + } + } + } + + void print() + { + std::string format; + if (const char* format_pointer = std::getenv("YANET_FORMAT")) + { + format = format_pointer; + } + + if (format == "json") + { + print_json(); + } + else + { + print_default(); + } + } + + void render() + { + printf("\033[H\033[2J"); + fflush(stdout); + + print_default(); + table.clear(); + } + +private: + void insert_row(const std::vector& row) + { + if (row.size() > columnLengths.size()) + { + columnLengths.resize(row.size(), 0); + } + + for (uint32_t string_i = 0; string_i < row.size(); ++string_i) + { + if (columnLengths[string_i] < row[string_i].size()) + { + columnLengths[string_i] = row[string_i].size(); + } + } + + table.emplace_back(row); + } + + converter::config_t config; + std::vector> table; + std::vector columnLengths; +}; From 56d65f738a6ff40dc99ce1feb66a60363b84a406 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Mon, 30 Sep 2024 20:00:26 +0400 Subject: [PATCH 179/195] Refactor TablePrinter - Add perfect forwarding of arguments in insert_row - Introduce insert_row overloads for ranges and pairs - Renamed insert to insert_row for clarity - Added an insert_row method to directly handle tuples, avoiding unnecessary casting from tuples to vectors. - Simplified common code patterns such as: ```cpp TablePrinter table; table.insert("id", "name"); for (const auto& [id, name] : response) { table.insert(id, name); } table.print(); ``` by replacing them with a single helper function. - Rename private fields and public methos according to google codingstyle - Simplify print* methods by utilizing unordered_map for indices --- cli/acl.h | 63 ++----- cli/balancer.h | 173 +++++++++---------- cli/bus.h | 17 +- cli/convert.h | 12 +- cli/develop.h | 58 +++---- cli/dregress.h | 40 ++--- cli/helper.h | 11 ++ cli/limit.h | 13 +- cli/memory_manager.h | 30 +--- cli/nat46clat.h | 31 ++-- cli/nat64stateful.h | 77 ++++----- cli/neighbor.h | 31 +--- cli/rib.h | 216 ++++++++++++------------ cli/route.h | 170 ++++++++----------- cli/show.h | 388 ++++++++++++++++++++----------------------- cli/table_printer.h | 373 +++++++++++++++++++++++------------------ common/utils.h | 1 - 17 files changed, 792 insertions(+), 912 deletions(-) diff --git a/cli/acl.h b/cli/acl.h index 89c1ea77..5f143e0f 100644 --- a/cli/acl.h +++ b/cli/acl.h @@ -1,5 +1,6 @@ #pragma once +#include "cli/helper.h" #include "common/icontrolplane.h" #include "table_printer.h" @@ -52,39 +53,21 @@ void unwind(const std::string& in_module, transport_flags, recordstate}); - TablePrinter table({.optional_null = "any"}); - table.insert("module", - "direction", - "network_source", - "network_destination", - "fragment", - "protocol", - "transport_source", - "transport_destination", - "transport_flags", - "recordstate", - "next_module", - "ids", - "log"); - - for (const auto& [module, direction, network_source, network_destination, fragment, protocol, transport_source, transport_destination, transport_flags, recordstate, next_module, ids, log] : response) - { - table.insert(module, - direction, - network_source, - network_destination, - fragment, - protocol, - transport_source, - transport_destination, - transport_flags, - recordstate, - next_module, - ids, - log); - } - - table.print(); + FillAndPrintTable({"module", + "direction", + "network_source", + "network_destination", + "fragment", + "protocol", + "transport_source", + "transport_destination", + "transport_flags", + "recordstate", + "next_module", + "ids", + "log"}, + response, + {.optional_null = "any"}); } void lookup(std::optional module, @@ -113,19 +96,7 @@ void lookup(std::optional module, transport_source, transport_destination}); - TablePrinter table; - table.insert("ruleno", - "label", - "rule"); - - for (const auto& [ruleno, label, rule] : response) - { - table.insert(ruleno, - label, - rule); - } - - table.print(); + FillAndPrintTable({"ruleno", "label", "rule"}, response); } } diff --git a/cli/balancer.h b/cli/balancer.h index 3d64e42a..5d7acd71 100644 --- a/cli/balancer.h +++ b/cli/balancer.h @@ -1,5 +1,6 @@ #pragma once +#include "cli/helper.h" #include "common/icontrolplane.h" #include "common/idataplane.h" #include "common/iproto_controlplane.h" @@ -15,25 +16,13 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.balancer_summary(); - TablePrinter table; - table.insert("module", - "services", - "reals_enabled", - "reals", - "connections", - "next_module"); - - for (const auto& [module, services, reals_enabled, reals, connections, next_module] : response) - { - table.insert(module, - services, - reals_enabled, - reals, - connections, - next_module); - } - - table.print(); + FillAndPrintTable({"module", + "services", + "reals_enabled", + "reals", + "connections", + "next_module"}, + response); } void service(std::string module_string, @@ -67,15 +56,15 @@ void service(std::string module_string, auto balancer_service_connections = dataplane.balancer_service_connections(); TablePrinter table; - table.insert("module", - "virtual_ip", - "proto", - "virtual_port", - "scheduler", - "connections", - "packets", - "bytes", - "version"); + table.insert_row("module", + "virtual_ip", + "proto", + "virtual_port", + "scheduler", + "connections", + "packets", + "bytes", + "version"); for (const auto& [module, services] : response) { @@ -106,19 +95,19 @@ void service(std::string module_string, } } - table.insert(module_name, - virtual_ip, - proto_string, - virtual_port, - scheduler, - connections, - packets, - bytes, - version); + table.insert_row(module_name, + virtual_ip, + proto_string, + virtual_port, + scheduler, + connections, + packets, + bytes, + version); } } - table.print(); + table.Print(); } inline void setip(common::icp_proto::IPAddr* pAddr, const common::ip_address_t& value) @@ -202,19 +191,19 @@ void real_find(std::string module_string, auto balancer_real_connections = dataplane.balancer_real_connections(); TablePrinter table; - table.insert("module", - "virtual_ip", - "proto", - "virtual_port", - "scheduler", - "real_ip", - "real_port", - "enabled", - "weight", - "connections", - "packets", - "bytes", - "version"); + table.insert_row("module", + "virtual_ip", + "proto", + "virtual_port", + "scheduler", + "real_ip", + "real_port", + "enabled", + "weight", + "connections", + "packets", + "bytes", + "version"); for (const auto& balancer : response.balancers()) { @@ -247,24 +236,24 @@ void real_find(std::string module_string, } } - table.insert(balancer.module(), - virtual_ip, - proto_string, - service.key().port_opt_case() == common::icp_proto::BalancerRealFindResponse_ServiceKey::PortOptCase::kPort ? std::make_optional(service.key().port()) : std::nullopt, - service.scheduler(), - real_ip, - real.port_opt_case() == common::icp_proto::BalancerRealFindResponse_Real::PortOptCase::kPort ? std::make_optional(real.port()) : std::nullopt, - real.enabled(), - real.weight(), - connections, - real.packets(), - real.bytes(), - service.version_opt_case() == common::icp_proto::BalancerRealFindResponse_Service::VersionOptCase::kVersion ? std::make_optional(service.version()) : std::nullopt); + table.insert_row(balancer.module(), + virtual_ip, + proto_string, + service.key().port_opt_case() == common::icp_proto::BalancerRealFindResponse_ServiceKey::PortOptCase::kPort ? std::make_optional(service.key().port()) : std::nullopt, + service.scheduler(), + real_ip, + real.port_opt_case() == common::icp_proto::BalancerRealFindResponse_Real::PortOptCase::kPort ? std::make_optional(real.port()) : std::nullopt, + real.enabled(), + real.weight(), + connections, + real.packets(), + real.bytes(), + service.version_opt_case() == common::icp_proto::BalancerRealFindResponse_Service::VersionOptCase::kVersion ? std::make_optional(service.version()) : std::nullopt); } } } - table.print(); + table.Print(); } void state(std::string module, @@ -351,16 +340,16 @@ void state(std::string module, } TablePrinter table; - table.insert("module", - "virtual_ip", - "proto", - "virtual_port", - "real_ip", - "real_port", - "client_ip", - "client_port", - "created", - "last_seen"); + table.insert_row("module", + "virtual_ip", + "proto", + "virtual_port", + "real_ip", + "real_port", + "client_ip", + "client_port", + "created", + "last_seen"); uint32_t current_time = time(nullptr); @@ -387,22 +376,22 @@ void state(std::string module, const auto& [client_ip, client_port] = key; const auto& [timestamp_create, timestamp_last_packet] = value; - table.insert(module, - virtual_ip, - proto_string, - virtual_port, - real_ip, - real_port, - client_ip, - client_port, - (uint32_t)current_time - timestamp_create, - (uint16_t)current_time - timestamp_last_packet); + table.insert_row(module, + virtual_ip, + proto_string, + virtual_port, + real_ip, + real_port, + client_ip, + client_port, + (uint32_t)current_time - timestamp_create, + (uint16_t)current_time - timestamp_last_packet); } } } } - table.print(); + table.Print(); } namespace real @@ -489,17 +478,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.balancer_announce(); - TablePrinter table; - table.insert("module", - "announces"); - - for (const auto& [module, announces] : response) - { - table.insert(module, - announces); - } - - table.print(); + FillAndPrintTable({"module", "announces"}, response); } } diff --git a/cli/bus.h b/cli/bus.h index 59b554c5..ba8cefbb 100644 --- a/cli/bus.h +++ b/cli/bus.h @@ -1,8 +1,8 @@ #pragma once #include "helper.h" -#include "table_printer.h" #include "influxdb_format.h" +#include "table_printer.h" namespace bus { @@ -80,16 +80,16 @@ inline void bus_requests() auto requests = get_bus_requests(sdp_data); TablePrinter table; - table.insert("request", "count", "duration_ms"); + table.insert_row("request", "count", "duration_ms"); for (const auto& [request, count, duration] : requests) { if ((count != 0) || (duration != 0)) { - table.insert(request, count, duration); + table.insert_row(request, count, duration); } } - table.print(); + table.Print(); } inline std::vector> get_bus_errors(const common::sdp::DataPlaneInSharedMemory& sdp_data) @@ -120,14 +120,7 @@ inline void bus_errors() OpenSharedMemoryDataplaneBuffers(sdp_data, false); auto errors = get_bus_errors(sdp_data); - TablePrinter table; - table.insert("error", "count"); - for (const auto& [error, count] : errors) - { - table.insert(error, count); - } - - table.print(); + FillAndPrintTable({"error", "count"}, errors); } inline void bus_telegraf() diff --git a/cli/convert.h b/cli/convert.h index 32a91333..a10fc6f1 100644 --- a/cli/convert.h +++ b/cli/convert.h @@ -1,6 +1,7 @@ #pragma once #include "common/icontrolplane.h" +#include "helper.h" #include "table_printer.h" namespace convert @@ -11,16 +12,7 @@ inline void logical_module() interface::controlPlane controlPlane; const auto response = controlPlane.convert("logical_module"); - TablePrinter table; - table.insert("id", - "name"); - - for (const auto& [id, name] : response) - { - table.insert(id, name); - } - - table.print(); + FillAndPrintTable({"id", "name"}, response); } } /* namespace convert */ diff --git a/cli/develop.h b/cli/develop.h index 2164e5c9..10c0c7bf 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -153,10 +153,10 @@ inline void counter(uint32_t counter_id, const std::optional& range_si for (uint32_t i = 0; i < counter_ids.size(); i++) { - table.insert(counter_ids[i], response[i]); + table.insert_row(counter_ids[i], response[i]); } - table.print(); + table.Print(); } using namespace ::dataplane::perf; @@ -222,7 +222,7 @@ struct tsc_monitoring_t if (render_header) { - table.render(); + table.Render(); } std::this_thread::sleep_for(std::chrono::milliseconds(250)); @@ -317,31 +317,31 @@ struct tsc_monitoring_t void insert_header() { - table.insert("core_id", - "iter_num", - "logicalPort_ingress", - "acl_ingress4", - "acl_ingress6", - "tun64_ipv4", - "tun64_ipv6", - "route4", - "route6", - "decap", - "nat64stateful_lan", - "nat64stateful_wan", - "nat64stateless_egress", - "nat64stateless_ingress", - "nat46clat_lan", - "nat46clat_wan", - "balancer", - "balancer_icmp_reply", - "balancer_icmp_forward", - "route_tunnel4", - "route_tunnel6", - "acl_egress4", - "acl_egress6", - "logicalPort_egress", - "controlPlane"); + table.insert_row("core_id", + "iter_num", + "logicalPort_ingress", + "acl_ingress4", + "acl_ingress6", + "tun64_ipv4", + "tun64_ipv6", + "route4", + "route6", + "decap", + "nat64stateful_lan", + "nat64stateful_wan", + "nat64stateless_egress", + "nat64stateless_ingress", + "nat46clat_lan", + "nat46clat_wan", + "balancer", + "balancer_icmp_reply", + "balancer_icmp_forward", + "route_tunnel4", + "route_tunnel6", + "acl_egress4", + "acl_egress6", + "logicalPort_egress", + "controlPlane"); } void insert_bin(const tsc_deltas& cnt, const overflow_store& of_store, int bin, uint32_t core_id) @@ -363,7 +363,7 @@ struct tsc_monitoring_t utils::zip_apply(op, of_store_tuple, cnt_tuple); - table.insert(row.begin(), row.end()); + table.insert_row(row.begin(), row.end()); } }; diff --git a/cli/dregress.h b/cli/dregress.h index 0bb3f3e1..2aa2727e 100644 --- a/cli/dregress.h +++ b/cli/dregress.h @@ -13,28 +13,28 @@ void summary() const auto response = controlPlane.dregress_config(); TablePrinter table; - table.insert("module", - "ipv6_sources", - "ipv6_destination", - "ipv4_address", - "ipv6_address", - "udp_destination_port", - "only_longest", - "next_module"); + table.insert_row("module", + "ipv6_sources", + "ipv6_destination", + "ipv4_address", + "ipv6_address", + "udp_destination_port", + "only_longest", + "next_module"); for (const auto& [module_name, dregress] : response) { - table.insert(module_name, - dregress.ipv6SourcePrefixes, - dregress.ipv6DestinationPrefix, - dregress.ipv4SourceAddress, - dregress.ipv6SourceAddress, - dregress.udpDestinationPort, - dregress.onlyLongest, - dregress.nextModule); + table.insert_row(module_name, + dregress.ipv6SourcePrefixes, + dregress.ipv6DestinationPrefix, + dregress.ipv4SourceAddress, + dregress.ipv6SourceAddress, + dregress.udpDestinationPort, + dregress.onlyLongest, + dregress.nextModule); } - table.print(); + table.Print(); } void announce() @@ -48,11 +48,11 @@ void announce() for (const auto& [module_name, dregress] : response) { - table.insert(module_name, - dregress.announces); + table.insert_row(module_name, + dregress.announces); } - table.print(); + table.Print(); } /** @todo diff --git a/cli/helper.h b/cli/helper.h index ee0b56b6..924d143f 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -7,6 +7,7 @@ #include #include "common/sdpclient.h" +#include "table_printer.h" void fillValue(std::optional& value, const std::string& string) { @@ -162,3 +163,13 @@ void OpenSharedMemoryDataplaneBuffers(common::sdp::DataPlaneInSharedMemory& sdp_ std::exit(1); } } + +template +inline void FillAndPrintTable(const std::initializer_list& headers, const Container& data, const converter::config_t config = {}) +{ + TablePrinter table(config); + + table.insert_row(headers.begin(), headers.end()); + table.insert(data.begin(), data.end()); + table.Print(); +} diff --git a/cli/limit.h b/cli/limit.h index 38b7ee71..437c9976 100644 --- a/cli/limit.h +++ b/cli/limit.h @@ -14,22 +14,13 @@ void summary() const auto response = controlPlane.limit_summary(); TablePrinter table; - table.insert("name", - "socket_id", - "current", - "maximum", - "percent"); for (const auto& [name, socket_id, current, maximum] : response) { - table.insert(name, - socket_id, - current, - maximum, - utils::to_percent(current, maximum)); + table.insert_row(name, socket_id, current, maximum, utils::to_percent(current, maximum)); } - table.print(); + table.Print(); } } diff --git a/cli/memory_manager.h b/cli/memory_manager.h index bdce0f21..f92606e5 100644 --- a/cli/memory_manager.h +++ b/cli/memory_manager.h @@ -15,25 +15,19 @@ void show() YANET_GCC_BUG_UNUSED(response_memory_group); TablePrinter table; - table.insert("name", - "socket_id", - "current"); + table.insert_row("name", "socket_id", "current"); uint64_t total = 0; for (const auto& [name, socket_id, current] : response_objects) { total += current; - table.insert(name, - socket_id, - current); + table.insert_row(name, socket_id, current); } - table.insert("total", - "n/s", - total); + table.insert_row("total", "n/s", total); - table.print(); + table.Print(); } void group() @@ -44,10 +38,7 @@ void group() const auto& [response_memory_group, response_objects] = response; TablePrinter table; - table.insert("group", - "current", - "maximum", - "percent"); + table.insert_row("group", "current", "maximum", "percent"); std::map ///< current @@ -57,8 +48,7 @@ void group() { YANET_GCC_BUG_UNUSED(socket_id); - currents[name] = std::max(currents[name].value, - current); + currents[name] = std::max(currents[name].value, current); } response_memory_group.for_each([&](const auto& memory_group, @@ -82,13 +72,9 @@ void group() percent = utils::to_percent(group_total, memory_group.limit); } - table.insert(memory_group.name, - group_total, - maximum, - percent); + table.insert_row(memory_group.name, group_total, maximum, percent); }); - table.print(); + table.Print(); } - } diff --git a/cli/nat46clat.h b/cli/nat46clat.h index 850364a6..c62f218c 100644 --- a/cli/nat46clat.h +++ b/cli/nat46clat.h @@ -1,5 +1,6 @@ #pragma once +#include "cli/helper.h" #include "common/icontrolplane.h" #include "table_printer.h" @@ -13,20 +14,20 @@ void summary() const auto response = controlPlane.nat46clat_config(); TablePrinter table; - table.insert("module", - "ipv6_source", - "ipv6_destination", - "next_module"); + table.insert_row("module", + "ipv6_source", + "ipv6_destination", + "next_module"); for (const auto& [module_name, nat46clat] : response) { - table.insert(module_name, - nat46clat.ipv6_source, - nat46clat.ipv6_destination, - nat46clat.next_module); + table.insert_row(module_name, + nat46clat.ipv6_source, + nat46clat.ipv6_destination, + nat46clat.next_module); } - table.print(); + table.Print(); } void announce() @@ -34,17 +35,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.nat46clat_announce(); - TablePrinter table; - table.insert("module", - "announces"); - - for (const auto& [module_name, prefix] : response) - { - table.insert(module_name, - prefix); - } - - table.print(); + FillAndPrintTable({"module", "announces"}, response); } } diff --git a/cli/nat64stateful.h b/cli/nat64stateful.h index 45ce888e..ffe1412e 100644 --- a/cli/nat64stateful.h +++ b/cli/nat64stateful.h @@ -1,5 +1,6 @@ #pragma once +#include "cli/helper.h" #include "common/icontrolplane.h" #include "common/idataplane.h" @@ -14,9 +15,9 @@ void summary() const auto response = controlPlane.nat64stateful_config(); TablePrinter table; - table.insert("module", - "ipv4_pool_size", - "next_module"); + table.insert_row("module", + "ipv4_pool_size", + "next_module"); for (const auto& [name, nat64stateful] : response) { @@ -26,12 +27,12 @@ void summary() ipv4_pool_size += (1u << (32 - ipv4_prefix.mask())); } - table.insert(name, - ipv4_pool_size, - nat64stateful.next_module); + table.insert_row(name, + ipv4_pool_size, + nat64stateful.next_module); } - table.print(); + table.Print(); } void announce() @@ -39,17 +40,7 @@ void announce() interface::controlPlane controlPlane; const auto response = controlPlane.nat64stateful_announce(); - TablePrinter table; - table.insert("module", - "announces"); - - for (const auto& [module, announces] : response) - { - table.insert(module, - announces); - } - - table.print(); + FillAndPrintTable({"module", "announces"}, response); } /// @todo: move @@ -153,18 +144,18 @@ void state(std::optional module) const auto response = dataplane.nat64stateful_state({module_id}); TablePrinter table; - table.insert("module", - "ipv6_source", - "ipv4_source", - "ipv4_destination", - "proto", - "origin_port_source", - "port_source", - "port_destination", - "lan_flags", - "wan_flags", - "lan_last_seen", - "wan_last_seen"); + table.insert_row("module", + "ipv6_source", + "ipv4_source", + "ipv4_destination", + "proto", + "origin_port_source", + "port_source", + "port_destination", + "lan_flags", + "wan_flags", + "lan_last_seen", + "wan_last_seen"); for (const auto& [nat64stateful_id, proto, @@ -185,21 +176,21 @@ void state(std::optional module) it = modules.emplace_hint(it, nat64stateful_id, "unknown"); } - table.insert(it->second, - ipv6_source, - ipv4_source, - ipv6_destination.get_mapped_ipv4_address().toString().data(), - proto_to_string(proto).data(), - port_source, - wan_port_source, - port_destination, - tcp_flags_to_string(lan_flags), - tcp_flags_to_string(wan_flags), - lan_last_seen, - wan_last_seen); + table.insert_row(it->second, + ipv6_source, + ipv4_source, + ipv6_destination.get_mapped_ipv4_address().toString().data(), + proto_to_string(proto).data(), + port_source, + wan_port_source, + port_destination, + tcp_flags_to_string(lan_flags), + tcp_flags_to_string(wan_flags), + lan_last_seen, + wan_last_seen); } - table.print(); + table.Print(); } } diff --git a/cli/neighbor.h b/cli/neighbor.h index 9ac10d22..a68803de 100644 --- a/cli/neighbor.h +++ b/cli/neighbor.h @@ -1,9 +1,8 @@ #pragma once +#include "cli/helper.h" #include "common/idataplane.h" -#include "table_printer.h" - namespace neighbor { @@ -12,27 +11,13 @@ void show() interface::dataPlane dataplane; const auto response = dataplane.neighbor_show(); - TablePrinter table({.optional_null = "static"}); - table.insert("route_name", - "interface_name", - "ip_address", - "mac_address", - "last_update"); - - for (const auto& [route_name, - interface_name, - ip_address, - mac_address, - last_update] : response) - { - table.insert(route_name, - interface_name, - ip_address, - mac_address, - last_update); - } - - table.print(); + FillAndPrintTable({"route_name", + "interface_name", + "ip_address", + "mac_address", + "last_update"}, + response, + {.optional_null = "static"}); } void insert(const std::string& route_name, diff --git a/cli/rib.h b/cli/rib.h index b55243ff..0b83b248 100644 --- a/cli/rib.h +++ b/cli/rib.h @@ -15,31 +15,31 @@ void summary() const auto response = controlPlane.rib_summary(); TablePrinter table; - table.insert("vrf", - "priority", - "protocol", - "peer", - "table_name", - "prefixes", - "paths", - "eor"); + table.insert_row("vrf", + "priority", + "protocol", + "peer", + "table_name", + "prefixes", + "paths", + "eor"); for (const auto& [key, value] : response) { const auto& [vrf, priority, protocol, peer, table_name] = key; const auto& [prefixes, paths, eor] = value; - table.insert(vrf, - priority, - protocol, - peer, - table_name, - prefixes, - paths, - (bool)eor); + table.insert_row(vrf, + priority, + protocol, + peer, + table_name, + prefixes, + paths, + (bool)eor); } - table.print(); + table.Print(); } void prefixes() @@ -48,21 +48,21 @@ void prefixes() const auto response = controlPlane.rib_prefixes(); TablePrinter table; - table.insert("vrf", - "priority", - "prefix", - "protocol", - "peer", - "table_name", - "path_information", - "nexthop", - "labels", - "local_preference", - "aspath", - "origin", - "med", - "communities", - "large_communities"); + table.insert_row("vrf", + "priority", + "prefix", + "protocol", + "peer", + "table_name", + "path_information", + "nexthop", + "labels", + "local_preference", + "aspath", + "origin", + "med", + "communities", + "large_communities"); for (const auto& [vrf_priority, prefix_nexthops] : response) { @@ -75,26 +75,26 @@ void prefixes() const auto& [protocol, peer, table_name, path_information] = nexthop_key; const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = nexthop_value; - table.insert(vrf, - priority, - prefix, - protocol, - peer, - table_name, - path_information, - nexthop, - labels, - local_preference, - aspath, - origin, - med, - communities, - large_communities); + table.insert_row(vrf, + priority, + prefix, + protocol, + peer, + table_name, + path_information, + nexthop, + labels, + local_preference, + aspath, + origin, + med, + communities, + large_communities); } } } - table.print(); + table.Print(); } void lookup(const std::string& vrf, @@ -104,21 +104,21 @@ void lookup(const std::string& vrf, const auto response = controlPlane.rib_lookup({vrf, address}); TablePrinter table; - table.insert("vrf", - "priority", - "prefix", - "protocol", - "peer", - "table_name", - "path_information", - "nexthop", - "labels", - "local_preference", - "aspath", - "origin", - "med", - "communities", - "large_communities"); + table.insert_row("vrf", + "priority", + "prefix", + "protocol", + "peer", + "table_name", + "path_information", + "nexthop", + "labels", + "local_preference", + "aspath", + "origin", + "med", + "communities", + "large_communities"); for (const auto& [vrf_priority, prefix_nexthops] : response) { @@ -131,26 +131,26 @@ void lookup(const std::string& vrf, const auto& [protocol, peer, table_name, path_information] = nexthop_key; const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = nexthop_value; - table.insert(vrf, - priority, - prefix, - protocol, - peer, - table_name, - path_information, - nexthop, - labels, - local_preference, - aspath, - origin, - med, - communities, - large_communities); + table.insert_row(vrf, + priority, + prefix, + protocol, + peer, + table_name, + path_information, + nexthop, + labels, + local_preference, + aspath, + origin, + med, + communities, + large_communities); } } } - table.print(); + table.Print(); } void get(const std::string& vrf, @@ -160,20 +160,20 @@ void get(const std::string& vrf, const auto response = controlPlane.rib_get({vrf, prefix}); TablePrinter table; - table.insert("vrf", - "priority", - "protocol", - "peer", - "table_name", - "path_information", - "nexthop", - "labels", - "local_preference", - "aspath", - "origin", - "med", - "communities", - "large_communities"); + table.insert_row("vrf", + "priority", + "protocol", + "peer", + "table_name", + "path_information", + "nexthop", + "labels", + "local_preference", + "aspath", + "origin", + "med", + "communities", + "large_communities"); for (const auto& [vrf_priority, prefix_nexthops] : response) { @@ -187,25 +187,25 @@ void get(const std::string& vrf, const auto& [nexthop, labels, origin, med, aspath, communities, large_communities, local_preference] = nexthop_value; YANET_GCC_BUG_UNUSED(prefix); - table.insert(vrf, - priority, - protocol, - peer, - table_name, - path_information, - nexthop, - labels, - local_preference, - aspath, - origin, - med, - communities, - large_communities); + table.insert_row(vrf, + priority, + protocol, + peer, + table_name, + path_information, + nexthop, + labels, + local_preference, + aspath, + origin, + med, + communities, + large_communities); } } } - table.print(); + table.Print(); } void convert(const std::string& string, diff --git a/cli/route.h b/cli/route.h index 28e32dc0..034ffc0b 100644 --- a/cli/route.h +++ b/cli/route.h @@ -1,5 +1,6 @@ #pragma once +#include "cli/helper.h" #include "common/icontrolplane.h" #include "common/utils.h" @@ -13,17 +14,7 @@ void summary() interface::controlPlane controlPlane; const auto response = controlPlane.route_summary(); - TablePrinter table; - table.insert("module", - "vrf"); - - for (const auto& [route_name, vrf] : response) - { - table.insert(route_name, - vrf); - } - - table.print(); + FillAndPrintTable({"module", "vrf"}, response); } void interface() @@ -32,31 +23,31 @@ void interface() const auto response = controlplane.route_interface(); TablePrinter table; - table.insert("module", - "interface", - "address", - "neighbor_v4", - "neighbor_v6", - "neighbor_mac_address_v4", - "neighbor_mac_address_v6", - "next_module"); + table.insert_row("module", + "interface", + "address", + "neighbor_v4", + "neighbor_v6", + "neighbor_mac_address_v4", + "neighbor_mac_address_v6", + "next_module"); for (const auto& [key, value] : response) { const auto& [route_name, interface_name] = key; const auto& [address, neighbor_v4, neighbor_v6, neighbor_mac_address_v4, neighbor_mac_address_v6, next_module] = value; - table.insert(route_name, - interface_name, - address, - neighbor_v4, - neighbor_v6, - neighbor_mac_address_v4, - neighbor_mac_address_v6, - next_module == "controlPlane" ? std::string("linux") : next_module); + table.insert_row(route_name, + interface_name, + address, + neighbor_v4, + neighbor_v6, + neighbor_mac_address_v4, + neighbor_mac_address_v6, + next_module == "controlPlane" ? std::string("linux") : next_module); } - table.print(); + table.Print(); } void lookup(const std::string& route_name, @@ -66,24 +57,24 @@ void lookup(const std::string& route_name, auto response = controlplane.route_lookup({route_name, address}); TablePrinter table; - table.insert("ingress_physical_ports", - "prefix", - "nexthop", - "egress_interface", - "labels"); + table.insert_row("ingress_physical_ports", + "prefix", + "nexthop", + "egress_interface", + "labels"); for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, egress_interface, labels] = item; - table.insert(ingress_physical_ports, - prefix, - nexthop.is_default() ? std::string("") : nexthop.toString(), - egress_interface, - labels); + table.insert_row(ingress_physical_ports, + prefix, + nexthop.is_default() ? std::string("") : nexthop.toString(), + egress_interface, + labels); } - table.print(); + table.Print(); } void get(const std::string& route_name, @@ -93,23 +84,23 @@ void get(const std::string& route_name, auto response = controlplane.route_get({route_name, prefix}); TablePrinter table; - table.insert("ingress_physical_ports", - "nexthop", - "egress_interface", - "labels"); + table.insert_row("ingress_physical_ports", + "nexthop", + "egress_interface", + "labels"); for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, egress_interface, labels] = item; YANET_GCC_BUG_UNUSED(prefix); - table.insert(ingress_physical_ports, - nexthop.is_default() ? std::string("") : nexthop.toString(), - egress_interface, - labels); + table.insert_row(ingress_physical_ports, + nexthop.is_default() ? std::string("") : nexthop.toString(), + egress_interface, + labels); } - table.print(); + table.Print(); } void counters() @@ -117,19 +108,7 @@ void counters() interface::controlPlane controlplane; auto response = controlplane.route_counters(); - TablePrinter table; - table.insert("link", - "nexthop", - "prefix", - "counts", - "size"); - - for (const auto& [link, nexthop, prefix, counts, size] : response) - { - table.insert(link, nexthop, prefix, counts, size); - } - - table.print(); + FillAndPrintTable({"link", "nexthop", "prefix", "counts", "size"}, response); } namespace tunnel @@ -142,28 +121,28 @@ void lookup(const std::string& route_name, auto response = controlplane.route_tunnel_lookup({route_name, address}); TablePrinter table; - table.insert("ingress_physical_ports", - "prefix", - "nexthop", - "label", - "egress_interface", - "peer", - "weight (%)"); + table.insert_row("ingress_physical_ports", + "prefix", + "nexthop", + "label", + "egress_interface", + "peer", + "weight (%)"); for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, label, egress_interface, peer, weight_percent] = item; - table.insert(ingress_physical_ports, - prefix, - nexthop.is_default() ? std::string("") : nexthop.toString(), - label, - egress_interface, - peer, - utils::to_percent(weight_percent)); + table.insert_row(ingress_physical_ports, + prefix, + nexthop.is_default() ? std::string("") : nexthop.toString(), + label, + egress_interface, + peer, + utils::to_percent(weight_percent)); } - table.print(); + table.Print(); } void get(const std::string& route_name, @@ -173,27 +152,27 @@ void get(const std::string& route_name, auto response = controlplane.route_tunnel_get({route_name, prefix}); TablePrinter table; - table.insert("ingress_physical_ports", - "nexthop", - "label", - "egress_interface", - "peer", - "weight (%)"); + table.insert_row("ingress_physical_ports", + "nexthop", + "label", + "egress_interface", + "peer", + "weight (%)"); for (const auto& item : response) { const auto& [ingress_physical_ports, prefix, nexthop, label, egress_interface, peer, weight_percent] = item; YANET_GCC_BUG_UNUSED(prefix); - table.insert(ingress_physical_ports, - nexthop.is_default() ? std::string("") : nexthop.toString(), - label, - egress_interface, - peer, - utils::to_percent(weight_percent)); + table.insert_row(ingress_physical_ports, + nexthop.is_default() ? std::string("") : nexthop.toString(), + label, + egress_interface, + peer, + utils::to_percent(weight_percent)); } - table.print(); + table.Print(); } void counters() @@ -201,18 +180,7 @@ void counters() interface::controlPlane controlplane; auto response = controlplane.route_tunnel_counters(); - TablePrinter table; - table.insert("link", - "nexthop", - "counts", - "size"); - - for (const auto& [link, nexthop, counts, size] : response) - { - table.insert(link, nexthop, counts, size); - } - - table.print(); + FillAndPrintTable({"link", "nexthop", "counts", "size"}, response); } } diff --git a/cli/show.h b/cli/show.h index ffbdb494..41eafde2 100644 --- a/cli/show.h +++ b/cli/show.h @@ -10,6 +10,7 @@ #include "common/tsc_deltas.h" #include "common/version.h" +#include "helper.h" #include "table_printer.h" namespace show @@ -21,34 +22,34 @@ inline void physicalPort() const auto response = controlPlane.getPhysicalPorts(); TablePrinter table; - table.insert("moduleName", - "link", - "speed", - "rx_packets", - "rx_bytes", - "rx_errors", - "rx_drops", - "tx_packets", - "tx_bytes", - "tx_errors", - "tx_drops"); + table.insert_row("moduleName", + "link", + "speed", + "rx_packets", + "rx_bytes", + "rx_errors", + "rx_drops", + "tx_packets", + "tx_bytes", + "tx_errors", + "tx_drops"); for (const auto& [physicalPortName, physicalPort] : response) { - table.insert(physicalPortName, - std::get<8>(physicalPort) ? "up" : "down", - std::to_string(std::get<9>(physicalPort) / 1000) + "G", - std::get<0>(physicalPort), - std::get<1>(physicalPort), - std::get<2>(physicalPort), - std::get<3>(physicalPort), - std::get<4>(physicalPort), - std::get<5>(physicalPort), - std::get<6>(physicalPort), - std::get<7>(physicalPort)); + table.insert_row(physicalPortName, + std::get<8>(physicalPort) ? "up" : "down", + std::to_string(std::get<9>(physicalPort) / 1000) + "G", + std::get<0>(physicalPort), + std::get<1>(physicalPort), + std::get<2>(physicalPort), + std::get<3>(physicalPort), + std::get<4>(physicalPort), + std::get<5>(physicalPort), + std::get<6>(physicalPort), + std::get<7>(physicalPort)); } - table.print(); + table.Print(); } inline void physical_port_dump(const std::string& direction, @@ -76,22 +77,22 @@ inline void logicalPort() const auto response = controlPlane.getLogicalPorts(); TablePrinter table; - table.insert("moduleName", - "physicalPortName", - "vlanId", - "macAddress", - "promiscuousMode"); + table.insert_row("moduleName", + "physicalPortName", + "vlanId", + "macAddress", + "promiscuousMode"); for (const auto& [logicalPortName, logicalPort] : response) { - table.insert(logicalPortName, - std::get<0>(logicalPort), - std::get<1>(logicalPort), - std::get<2>(logicalPort), - std::get<3>(logicalPort) ? "true" : "false"); + table.insert_row(logicalPortName, + std::get<0>(logicalPort), + std::get<1>(logicalPort), + std::get<2>(logicalPort), + std::get<3>(logicalPort) ? "true" : "false"); } - table.print(); + table.Print(); } static inline std::string convertToString(const common::defender::status& status) @@ -143,11 +144,11 @@ inline void summary(std::optional module) const auto response = controlPlane.tun64_tunnels(); TablePrinter table; - table.insert("module", - "source_address", - "prefixes", - "randomization", - "next_module"); + table.insert_row("module", + "source_address", + "prefixes", + "randomization", + "next_module"); for (const auto& [tunnelName, tunnel] : response) { @@ -159,14 +160,14 @@ inline void summary(std::optional module) const auto& [ipv6Src, pfxCnt, rndFlag, nxtModule] = tunnel; - table.insert(tunnelName, - ipv6Src, - pfxCnt, - rndFlag ? "true" : "false", - nxtModule); + table.insert_row(tunnelName, + ipv6Src, + pfxCnt, + rndFlag ? "true" : "false", + nxtModule); } - table.print(); + table.Print(); } inline void announce(std::optional module) @@ -175,9 +176,9 @@ inline void announce(std::optional module) const auto response = controlPlane.tun64_prefixes(); TablePrinter table; - table.insert("module", - "prefix", - "announces"); + table.insert_row("module", + "prefix", + "announces"); for (const auto& [tunnelName, prefixes] : response) { @@ -189,11 +190,11 @@ inline void announce(std::optional module) for (const auto& prefix : prefixes) { - table.insert(tunnelName, prefix, prefix); + table.insert_row(tunnelName, prefix, prefix); } } - table.print(); + table.Print(); } inline void mappings(std::optional module) @@ -202,10 +203,10 @@ inline void mappings(std::optional module) const auto response = controlPlane.tun64_mappings(); TablePrinter table; - table.insert("module", - "ipv4Address", - "ipv6Address", - "location"); + table.insert_row("module", + "ipv4Address", + "ipv6Address", + "location"); for (const auto& v : response) { @@ -217,13 +218,13 @@ inline void mappings(std::optional module) continue; } - table.insert(tunnelName, - ipv4Address, - ipv6Address, - location); + table.insert_row(tunnelName, + ipv4Address, + ipv6Address, + location); } - table.print(); + table.Print(); } } /* namespace tun64 */ @@ -236,10 +237,10 @@ inline void summary() const auto response = controlPlane.getDecaps(); TablePrinter table; - table.insert("module", - "prefixes", - "DSCP", - "next_module"); + table.insert_row("module", + "prefixes", + "DSCP", + "next_module"); for (const auto& [decapName, decap] : response) { @@ -261,13 +262,13 @@ inline void summary() dscpString = "n/s"; } - table.insert(decapName, - std::get<0>(decap), - dscpString, - std::get<2>(decap)); + table.insert_row(decapName, + std::get<0>(decap), + dscpString, + std::get<2>(decap)); } - table.print(); + table.Print(); } inline void announce() @@ -276,21 +277,21 @@ inline void announce() const auto response = controlPlane.getDecapPrefixes(); TablePrinter table; - table.insert("module", - "prefix", - "announces"); + table.insert_row("module", + "prefix", + "announces"); for (const auto& [moduleName, prefixes] : response) { for (const auto& prefix : prefixes) { - table.insert(moduleName, - prefix.prefix, - prefix.announces); + table.insert_row(moduleName, + prefix.prefix, + prefix.announces); } } - table.print(); + table.Print(); } } @@ -304,24 +305,24 @@ inline void summary() const auto response = controlPlane.getNat64statelesses(); TablePrinter table; - table.insert("module", - "translations", - "WKP", - "SRC", - "prefixes", - "next_module"); + table.insert_row("module", + "translations", + "WKP", + "SRC", + "prefixes", + "next_module"); for (const auto& [nat64statelessName, nat64stateless] : response) { - table.insert(nat64statelessName, - std::get<0>(nat64stateless), - std::get<1>(nat64stateless), - std::get<2>(nat64stateless), - std::get<3>(nat64stateless), - std::get<4>(nat64stateless)); + table.insert_row(nat64statelessName, + std::get<0>(nat64stateless), + std::get<1>(nat64stateless), + std::get<2>(nat64stateless), + std::get<3>(nat64stateless), + std::get<4>(nat64stateless)); } - table.print(); + table.Print(); } inline void translation() @@ -330,12 +331,12 @@ inline void translation() const auto response = controlPlane.getNat64statelessTranslations(); TablePrinter table; - table.insert("moduleName", - "ipv6Address", - "ipv6DestinationAddress", - "fromRange", - "ipv4Address", - "toRange"); + table.insert_row("moduleName", + "ipv6Address", + "ipv6DestinationAddress", + "fromRange", + "ipv4Address", + "toRange"); for (const auto& [key, value] : response) { @@ -346,15 +347,15 @@ inline void translation() const auto& ipv4Address = std::get<0>(value); const auto& egressPorts = std::get<1>(value); - table.insert(moduleName, - ipv6Address, - ipv6DestinationAddress, - ingressPorts, - ipv4Address, - egressPorts); + table.insert_row(moduleName, + ipv6Address, + ipv6DestinationAddress, + ingressPorts, + ipv4Address, + egressPorts); } - table.print(); + table.Print(); } inline void announce() @@ -363,9 +364,9 @@ inline void announce() const auto response = controlPlane.getNat64statelessPrefixes(); TablePrinter table; - table.insert("module", - "prefix", - "announces"); + table.insert_row("module", + "prefix", + "announces"); for (const auto& [moduleName, prefixes] : response) { @@ -373,15 +374,15 @@ inline void announce() { std::visit( [&, &moduleName = moduleName](auto&& value) { - table.insert(moduleName, - value.prefix, - value.announces); + table.insert_row(moduleName, + value.prefix, + value.announces); }, (const common::ip_prefix_with_announces_t::variant_t&)prefix); } } - table.print(); + table.Print(); } } @@ -512,18 +513,18 @@ static void list_fw_rules(unsigned int mask, bool list) TablePrinter table; if (list) { - table.insert("id", - "ruleno", - "label", - "rule"); + table.insert_row("id", + "ruleno", + "label", + "rule"); } else { - table.insert("id", - "ruleno", - "label", - "counter", - "rule"); + table.insert_row("id", + "ruleno", + "label", + "counter", + "rule"); } if (need_labels & mask) @@ -579,16 +580,16 @@ static void list_fw_rules(unsigned int mask, bool list) if (list) { YANET_GCC_BUG_UNUSED(counter); - table.insert(id, ruleno, label, text); + table.insert_row(id, ruleno, label, text); } else { - table.insert(id, ruleno, label, counter, text); + table.insert_row(id, ruleno, label, counter, text); } } } } - table.print(); + table.Print(); } inline void fw(std::optional str) @@ -625,18 +626,10 @@ inline void fwlist(std::optional str) inline void errors() { - TablePrinter table; - table.insert("name", "counter"); - interface::dataPlane dataPlane; const auto response = dataPlane.getErrors(); - for (const auto& [name, counter] : response) - { - table.insert(name, counter); - } - - table.print(); + FillAndPrintTable({"name", "counter"}, response); } inline void samples() @@ -645,13 +638,13 @@ inline void samples() const auto response = controlPlane.getSamples(); TablePrinter table; - table.insert("in_iface", - "out_iface", - "proto", - "src_addr", - "src_port", - "dst_addr", - "dst_port"); + table.insert_row("in_iface", + "out_iface", + "proto", + "src_addr", + "src_port", + "dst_addr", + "dst_port"); // Cache the protocols we are interested in to prevent enormous number of reading of "/etc/protocols". std::unordered_map proto_cache; @@ -671,10 +664,10 @@ inline void samples() } const auto& protoName = it->second; - table.insert(in_iface, out_iface, protoName, src_addr, src_port, dst_addr, dst_port); + table.insert_row(in_iface, out_iface, protoName, src_addr, src_port, dst_addr, dst_port); } - table.print(); + table.Print(); } inline void samples_dump() @@ -711,18 +704,18 @@ inline void values() const auto controlplane_values = controlplane.controlplane_values(); TablePrinter table; - table.insert("application", - "name", - "value"); + table.insert_row("application", + "name", + "value"); for (const auto& [name, value] : controlplane_values) { - table.insert("controlplane", - name, - value); + table.insert_row("controlplane", + name, + value); } - table.print(); + table.Print(); } inline void durations() @@ -731,28 +724,28 @@ inline void durations() const auto controlplane_durations = controlplane.controlplane_durations(); TablePrinter table; - table.insert("application", - "name", - "duration"); + table.insert_row("application", + "name", + "duration"); for (const auto& [name, value] : controlplane_durations) { - table.insert("controlplane", - name, - value); + table.insert_row("controlplane", + name, + value); } - table.print(); + table.Print(); } inline void version() { TablePrinter table; - table.insert("application", - "version", - "revision", - "hash", - "custom"); + table.insert_row("application", + "version", + "revision", + "hash", + "custom"); /// dataplane try @@ -760,11 +753,11 @@ inline void version() interface::dataPlane dataplane; const auto [major, minor, revision, hash, custom] = dataplane.version(); - table.insert("dataplane", - version_to_string(major, minor), - version_revision_to_string(revision), - version_hash_to_string(hash), - version_custom_to_string(custom)); + table.insert_row("dataplane", + version_to_string(major, minor), + version_revision_to_string(revision), + version_hash_to_string(hash), + version_custom_to_string(custom)); } catch (...) { @@ -776,11 +769,11 @@ inline void version() interface::controlPlane controlplane; const auto [major, minor, revision, hash, custom] = controlplane.version(); - table.insert("controlplane", - version_to_string(major, minor), - version_revision_to_string(revision), - version_hash_to_string(hash), - version_custom_to_string(custom)); + table.insert_row("controlplane", + version_to_string(major, minor), + version_revision_to_string(revision), + version_hash_to_string(hash), + version_custom_to_string(custom)); } catch (...) { @@ -788,14 +781,14 @@ inline void version() /// cli { - table.insert("cli", - version_to_string(), - version_revision_to_string(), - version_hash_to_string(), - version_custom_to_string()); + table.insert_row("cli", + version_to_string(), + version_revision_to_string(), + version_hash_to_string(), + version_custom_to_string()); } - table.print(); + table.Print(); } inline void counter_by_name(std::string counter_name, @@ -815,16 +808,7 @@ inline void counter_by_name(std::string counter_name, } } - TablePrinter table; - table.insert("core_id", - "counter_value"); - - for (const auto& [core_id, counter_value] : response) - { - table.insert(core_id, counter_value); - } - - table.print(); + FillAndPrintTable({"core_id", "counter_value"}, response); } inline void shm_info() @@ -832,22 +816,15 @@ inline void shm_info() interface::dataPlane dataplane; const auto response = dataplane.get_shm_info(); - TablePrinter table; - table.insert("ring name", - "dump tag", - "dump size", - "dump count", - "core id", - "socket id", - "ipc key", - "offset"); - - for (const auto& [name, tag, size, count, core, socket, ipc_key, offset] : response) - { - table.insert(name, tag, size, count, core, socket, ipc_key, offset); - } - - table.print(); + FillAndPrintTable({"ring name", + "dump tag", + "dump size", + "dump count", + "core id", + "socket id", + "ipc key", + "offset"}, + response); } void shm_tsc_info() @@ -855,18 +832,7 @@ void shm_tsc_info() interface::dataPlane dataplane; const auto response = dataplane.get_shm_tsc_info(); - TablePrinter table; - table.insert("core id", - "socket id", - "ipc key", - "offset"); - - for (const auto& [core, socket, ipc_key, offset] : response) - { - table.insert(core, socket, ipc_key, offset); - } - - table.print(); + FillAndPrintTable({"core id", "socket id", "ipc key", "offset"}, response); } void shm_tsc_set_state(bool state) diff --git a/cli/table_printer.h b/cli/table_printer.h index 511d0dd9..9ef8d01f 100644 --- a/cli/table_printer.h +++ b/cli/table_printer.h @@ -1,7 +1,8 @@ #pragma once -#include +#include #include +#include #include "common/utils.h" #include "converter.h" @@ -10,142 +11,161 @@ class TablePrinter { public: TablePrinter(const converter::config_t config = {}) : - config(config) {} + config_(config) {} + // Insert arbitrary number of values as one row template - void insert(const Args&... args) + void insert_row(Args&&... args) { - std::vector row = {converter::to_string(args, config)...}; - insert_row(row); + insert_row({converter::to_string(std::forward(args), config_)...}); } + // Insert tuple as one row + template + void insert_row(const std::tuple& tuple) + { + std::vector row; + + std::apply([&row, this](const Args&... args) { + (row.push_back(converter::to_string(args, config_)), ...); + }, + tuple); + + insert_row(std::move(row)); + } + + // Insert pair as one row + template + void insert_row(const std::pair& pair) + { + std::vector row; + row.push_back(converter::to_string(pair.first, config_)); + row.push_back(converter::to_string(pair.second, config_)); + + insert_row(std::move(row)); + } + + // Insert values from a container as one row template::iterator_category> - void insert(Iterator begin, Iterator end) + void insert_row(Iterator begin, Iterator end) { std::vector row; for (auto it = begin; it != end; ++it) { - row.push_back(converter::to_string(*it, config)); + row.push_back(converter::to_string(*it, config_)); } - insert_row(row); + insert_row(std::move(row)); } - void print_json() + /** + * Insert values from a container as many rows + * + * Useful when we have a container of containers like the "responce" + * object obtained from controlplane + */ + template::iterator_category> + void insert(Iterator begin, Iterator end) { - std::vector format_keys; - std::map format_keys_i; - if (const char* format_keys_pointer = std::getenv("YANET_FORMAT_KEYS")) + for (auto it = begin; it != end; ++it) { - format_keys = utils::split(format_keys_pointer, ','); + insert_row(*it); } + } - std::vector keys; - - bool header = true; - nlohmann::json json_root; - for (auto& row : table) + void Print() + { + std::string format; + if (const char* format_pointer = std::getenv("YANET_FORMAT")) { - if (header) - { - for (uint32_t string_i = 0; - string_i < row.size(); - string_i++) - { - for (uint32_t format_i = 0; - format_i < format_keys.size(); - format_i++) - { - if (row[string_i] == format_keys[format_i]) - { - format_keys_i[string_i] = format_i; - } - } - } + format = format_pointer; + } - keys = row; - header = false; - continue; - } + (format == "json") ? print_json() : print_default(); + } - std::vector tree; - tree.resize(format_keys.size()); + void Render() + { + std::cout << "\033[H\033[2J" << std::flush; - nlohmann::json json_row; - for (uint32_t string_i = 0; - string_i < row.size(); - string_i++) - { - if (format_keys_i.count(string_i)) - { - tree[format_keys_i[string_i]] = row[string_i]; - } - else - { - json_row[keys[string_i]] = row[string_i]; - } - } + print_default(); + table_.clear(); + } - auto* json_current = &json_root; - for (const auto& key : tree) +private: + void insert_row(std::vector&& row) + { + if (row.size() > column_lengths_.size()) + { + column_lengths_.resize(row.size(), 0); + } + + for (uint32_t i = 0; i < row.size(); ++i) + { + if (column_lengths_[i] < row[i].size()) { - json_current = &((*json_current)[key]); + column_lengths_[i] = row[i].size(); } - (*json_current).emplace_back(json_row); } - printf("%s\n", json_root.dump(2).data()); + table_.push_back(std::move(row)); } void print_default() { - if (table.size() == 0 || - columnLengths.size() == 0) + if (table_.empty() || column_lengths_.empty()) { return; } std::vector user_selected_col_names; - bool print_selected_cols_only = false; if (const char* columns_pointer = std::getenv("YANET_FORMAT_COLUMNS")) { user_selected_col_names = utils::split(columns_pointer, ','); - print_selected_cols_only = true; } - /* header row contains table's column names */ - auto& header_row = table[0]; + bool print_selected_cols_only = !user_selected_col_names.empty(); - /* If the user listed only specific columns of the table to be printed in specific order, - need to build a relation between index of column in user-provided order and its index in the table (only if it does exist in the table): - This relation: columns_order[col_idx_in_user_selection] = col_idx_in_table + // The header row contains the table's column names + const auto& header_row = table_.front(); - Otherwise, when no custom columns' selection and/or order is provided by the user, - print all columns of the table in the table's order: - columns_order[col_idx_in_table] = col_idx_in_table */ - std::vector columns_order; + /* + * If the user has specified certain columns to be printed in a specific order, + * we need to map each column's index from the user-provided list to its corresponding + * index in the table. + * If no specific column selection or order is provided by the user, + * print all columns in the default table order: + */ + std::unordered_map header_indices; + for (size_t idx = 0; idx < header_row.size(); ++idx) + { + header_indices[header_row[idx]] = idx; + } + + std::vector columns_order; if (print_selected_cols_only) { - uint32_t col_idx_in_user_selection = 0; - while (columns_order.size() < user_selected_col_names.size()) + for (const auto& col_name : user_selected_col_names) { - bool selected_col_name_found = false; - for (uint32_t col_idx_in_table = 0; col_idx_in_table < header_row.size(); ++col_idx_in_table) + auto it = header_indices.find(col_name); + if (it != header_indices.end()) { - if (user_selected_col_names[col_idx_in_user_selection] == header_row[col_idx_in_table]) - { - // col_idx_in_user_selection must be equal to columns_order.size() prior to insertion (check?) - columns_order.push_back(col_idx_in_table); - selected_col_name_found = true; - ++col_idx_in_user_selection; - break; - } + columns_order.push_back(it->second); } - - if (!selected_col_name_found) + else { - // evidently, user provided such a column name, which does not exist in the table, cannot print it - // shifting tail of user_selected_col_names to the left by erasing non-existent user-provided column name - user_selected_col_names.erase(user_selected_col_names.begin() + col_idx_in_user_selection); + std::cerr << "The column name '" << col_name + << "' in YANET_FORMAT_COLUMNS does not match any " + << "available column name. Skipping it." << std::endl; + std::cerr << "Available column names are: "; + for (auto it = header_row.begin(); it != header_row.end(); ++it) + { + std::cerr << *it; + if (std::next(it) != header_row.end()) + { + std::cerr << ", "; + } + } + std::cerr << std::endl; } } } @@ -155,105 +175,142 @@ class TablePrinter std::iota(columns_order.begin(), columns_order.end(), 0); } - if (columns_order.size() == 0) + if (columns_order.empty()) + { + return; + } + + print_row(header_row, columns_order, true); + + for (size_t row_idx = 1; row_idx < table_.size(); ++row_idx) + { + const auto& row = table_[row_idx]; + print_row(row, columns_order, false); + } + } + + void print_json() + { + if (table_.empty()) { - /* column names provided by user do not match any column names of the table, - or the table does not have any columns at all (what?!) */ return; } - bool header = true; - for (auto& row : table) + std::vector format_keys; + if (const char* format_keys_pointer = std::getenv("YANET_FORMAT_KEYS")) { - printf("%-*s", - columnLengths[columns_order[0]], - row[columns_order[0]].data()); + format_keys = utils::split(format_keys_pointer, ','); + } + + // The header row contains the table's column names + const auto& header_row = table_.front(); - for (uint32_t string_i = 1; - string_i < columns_order.size(); - string_i++) + // Build a mapping from column indices to format_keys indices + std::unordered_map format_keys_i; + if (!format_keys.empty()) + { + for (size_t idx = 0; idx < header_row.size(); ++idx) { - if (string_i != columns_order.size() - 1) - { - printf(" %-*s", - columnLengths[columns_order[string_i]], - row[columns_order[string_i]].data()); - } - else + auto it = std::find(format_keys.begin(), format_keys.end(), header_row[idx]); + if (it != format_keys.end()) { - // Do not explode the last column with padding whitespace bytes. - printf(" %s", - row[columns_order[string_i]].data()); + size_t format_idx = std::distance(format_keys.begin(), it); + format_keys_i[idx] = format_idx; } } + } - printf("\n"); + nlohmann::json json_root; - if (header) - { - printf("%s", std::string(columnLengths[columns_order[0]], '-').data()); + // Process each data row + for (size_t row_idx = 1; row_idx < table_.size(); ++row_idx) + { + const auto& row = table_[row_idx]; + + std::vector tree(format_keys.size()); - for (uint32_t string_i = 1; - string_i < columns_order.size(); - string_i++) + nlohmann::json json_row; + for (size_t idx = 0; idx < row.size(); ++idx) + { + auto it = format_keys_i.find(idx); + if (it != format_keys_i.end()) { - printf(" %s", std::string(columnLengths[columns_order[string_i]], '-').data()); + // This column is part of the nested keys + size_t tree_idx = it->second; + tree[tree_idx] = row[idx]; + } + else if (idx < header_row.size()) + { + // Regular key-value pair in the row + json_row[header_row[idx]] = row[idx]; } - - printf("\n"); - - header = false; } - } - } - void print() - { - std::string format; - if (const char* format_pointer = std::getenv("YANET_FORMAT")) - { - format = format_pointer; - } + nlohmann::json* json_current = &json_root; + for (const auto& key : tree) + { + json_current = &((*json_current)[key]); + } - if (format == "json") - { - print_json(); + json_current->push_back(json_row); } - else - { - print_default(); - } - } - void render() - { - printf("\033[H\033[2J"); - fflush(stdout); - - print_default(); - table.clear(); + std::cout << json_root.dump(2) << std::endl; } -private: - void insert_row(const std::vector& row) + void print_row(const std::vector& row, + const std::vector& columns_order, + bool is_header) { - if (row.size() > columnLengths.size()) + for (size_t i = 0; i < columns_order.size(); ++i) { - columnLengths.resize(row.size(), 0); + size_t col_idx = columns_order[i]; + auto col_width = static_cast(column_lengths_[col_idx]); + const auto& cell = row[col_idx]; + + if (i == 0) + { + std::cout << std::left << std::setw(col_width) << cell; + } + else + { + std::cout << " "; // Add separation between columns + if (i != columns_order.size() - 1) + { + // For all but the last column, use setw + std::cout << std::left << std::setw(col_width) << cell; + } + else + { + // Do not pad the last column + std::cout << cell; + } + } } + std::cout << '\n'; - for (uint32_t string_i = 0; string_i < row.size(); ++string_i) + if (is_header) { - if (columnLengths[string_i] < row[string_i].size()) + // Print a separator line after the header + for (size_t i = 0; i < columns_order.size(); ++i) { - columnLengths[string_i] = row[string_i].size(); + size_t col_idx = columns_order[i]; + auto col_width = column_lengths_[col_idx]; + + if (i == 0) + { + std::cout << std::string(col_width, '-'); + } + else + { + std::cout << " " << std::string(col_width, '-'); + } } + std::cout << '\n'; } - - table.emplace_back(row); } - converter::config_t config; - std::vector> table; - std::vector columnLengths; + converter::config_t config_; + std::vector> table_; + std::vector column_lengths_; }; diff --git a/common/utils.h b/common/utils.h index 604dbac7..ee990ee6 100644 --- a/common/utils.h +++ b/common/utils.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include From 82308a4419e515264c4ace12e41418987237e9ca Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 1 Oct 2024 12:31:54 +0400 Subject: [PATCH 180/195] Add default constructor for class uint Otherwise the following refactoring of call method will fail --- common/type.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/type.h b/common/type.h index ac15ddea..5fec0263 100644 --- a/common/type.h +++ b/common/type.h @@ -126,6 +126,8 @@ constexpr inline uint32_t unlabelled = 3; class uint { public: + uint() = default; + uint(const std::string& string) : value(std::stoull(string, nullptr, 0)) { @@ -142,7 +144,7 @@ class uint return std::to_string(value); } - uint64_t value; + uint64_t value{}; }; class mac_address_t From 9121e5748b44842bc28673e7b3641a0aea89cbe4 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 1 Oct 2024 13:01:16 +0400 Subject: [PATCH 181/195] Move type traits from common/utils.h to new common/traits.h --- cli/converter.h | 14 ++++---- cli/develop.h | 2 +- common/actions.h | 12 +++---- common/traits.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ common/utils.h | 75 ----------------------------------------- 5 files changed, 100 insertions(+), 89 deletions(-) create mode 100644 common/traits.h diff --git a/cli/converter.h b/cli/converter.h index 3687ad30..b1db93eb 100644 --- a/cli/converter.h +++ b/cli/converter.h @@ -6,7 +6,7 @@ #include #include -#include "common/utils.h" +#include "common/traits.h" namespace converter { @@ -42,29 +42,29 @@ std::string to_string(const T& value, const config_t& config = {}) { return std::to_string(value); } - else if constexpr (utils::is_variant_v) + else if constexpr (traits::is_variant_v) { return std::visit([&config](const auto& val) { return to_string(val, config); }, value); } - else if constexpr (utils::is_optional_v) + else if constexpr (traits::is_optional_v) { return value ? to_string(*value, config) : config.optional_null; } - else if constexpr (utils::is_container_v) + else if constexpr (traits::is_container_v) { if (value.empty()) { - if constexpr (utils::is_vector_v) + if constexpr (traits::is_vector_v) { return config.vector_empty; } - else if constexpr (utils::is_set_v) + else if constexpr (traits::is_set_v) { return config.set_empty; } else { - static_assert(utils::always_false::value, + static_assert(traits::always_false_v, "Container does not have default empty representation in struct config_t"); } } diff --git a/cli/develop.h b/cli/develop.h index 10c0c7bf..b9c3ca67 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -85,7 +85,7 @@ static void lpmLookupAddress(const T& address) } else { - static_assert(utils::always_false::value, + static_assert(traits::always_false_v, "lpmLookupAddress cannot be used with types other than ipv4/6_address"); } }(); diff --git a/common/actions.h b/common/actions.h index 1eeee311..b354f11d 100644 --- a/common/actions.h +++ b/common/actions.h @@ -1,7 +1,7 @@ #pragma once +#include "common/traits.h" #include "common/type.h" -#include "common/utils.h" #include "common/variant_trait_map.h" namespace common @@ -470,11 +470,11 @@ struct IntermediateActions } else { - static_assert(utils::always_false::value, "Not all unique actions with MAX_COUNT = 1 are properly categorized. " - "Please add the missing actions to either `is_first_matters` or `is_last_matters` " - "to ensure their index is tracked. Tracking the index of such actions could " - "enhance dataplane performance if this information is utilized in " - "`value_t::compile()`."); + static_assert(traits::always_false_v, "Not all unique actions with MAX_COUNT = 1 are properly categorized. " + "Please add the missing actions to either `is_first_matters` or `is_last_matters` " + "to ensure their index is tracked. Tracking the index of such actions could " + "enhance dataplane performance if this information is utilized in " + "`value_t::compile()`."); } } diff --git a/common/traits.h b/common/traits.h new file mode 100644 index 00000000..a5275a20 --- /dev/null +++ b/common/traits.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace traits +{ + +template +struct always_false : std::false_type +{}; + +template +inline constexpr bool always_false_v = always_false::value; + +template +struct is_optional : std::false_type +{}; + +template +struct is_optional> : std::true_type +{}; + +template +inline constexpr bool is_optional_v = is_optional::value; + +template +struct is_variant : std::false_type +{}; + +template +struct is_variant> : std::true_type +{}; + +template +inline constexpr bool is_variant_v = is_variant::value; + +template +struct is_container : std::false_type +{}; + +/* + * Checks: + * Whether std::begin(T&), std::end(T&) and std::empty(T&) are valid expressions. + * Whether the result of std::begin(T&) can be dereferenced (i.e., *std::begin(T&) is valid) + */ +template +struct is_container())), + decltype(std::end(std::declval())), + decltype(std::empty(std::declval())), + decltype(*std::begin(std::declval()))>> : std::true_type +{}; + +template +inline constexpr bool is_container_v = is_container::value; + +template +struct is_vector : std::false_type +{}; + +template +struct is_vector> : std::true_type +{}; + +template +inline constexpr bool is_vector_v = is_vector::value; + +template +struct is_set : std::false_type +{}; + +template +struct is_set> : std::true_type +{}; + +template +inline constexpr bool is_set_v = is_set::value; + +} +// namespace utils diff --git a/common/utils.h b/common/utils.h index ee990ee6..20e20696 100644 --- a/common/utils.h +++ b/common/utils.h @@ -1,86 +1,11 @@ - #pragma once #include -#include -#include -#include -#include -#include #include namespace utils { -template -struct always_false : std::false_type -{}; - -template -struct is_optional : std::false_type -{}; - -template -struct is_optional> : std::true_type -{}; - -template -inline constexpr bool is_optional_v = is_optional::value; - -template -struct is_variant : std::false_type -{}; - -template -struct is_variant> : std::true_type -{}; - -template -inline constexpr bool is_variant_v = is_variant::value; - -template -struct is_container : std::false_type -{}; - -/* - * Checks: - * Whether std::begin(T&), std::end(T&) and std::empty(T&) are valid expressions. - * Whether the result of std::begin(T&) can be dereferenced (i.e., *std::begin(T&) is valid) - */ -template -struct is_container())), - decltype(std::end(std::declval())), - decltype(std::empty(std::declval())), - decltype(*std::begin(std::declval()))>> : std::true_type -{}; - -template -inline constexpr bool is_container_v = is_container::value; - -template -struct is_vector : std::false_type -{}; - -template -struct is_vector> : std::true_type -{}; - -template -inline constexpr bool is_vector_v = is_vector::value; - -template -struct is_set : std::false_type -{}; - -template -struct is_set> : std::true_type -{}; - -template -inline constexpr bool is_set_v = is_set::value; - // Utility to calculate percentage // TODO C++20: use std::type_identity_t to establish non-deduced context // Will allow to do `to_percent(4.2, 1)` From 0300d45784594257805cddc61682dbae8c2b6b7a Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 1 Oct 2024 13:29:21 +0400 Subject: [PATCH 182/195] Add utility to decay a tuple --- common/tuple.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/common/tuple.h b/common/tuple.h index 488ebed7..daef539c 100644 --- a/common/tuple.h +++ b/common/tuple.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -179,4 +178,26 @@ inline void zip_apply(Func&& f, Tuples&&... tuples) zip_apply_helper<0, tuple_size>(std::forward(f), std::forward(tuples)...); } +template +constexpr auto decay_types(std::tuple const&) -> std::tuple...>; + +/** + * @brief Decays the types of a tuple's elements. + * + * It removes any const, volatile, and reference qualifiers from the element + * types and performs array-to-pointer and function-to-pointer conversions. + * + * Example usage: + * ``` + * std::tuple t; + * using DecayedTuple = decay_tuple; + * // DecayedTuple is std::tuple + * ``` + * + * @tparam T The type of the tuple to decay. + * @return A tuple type with decayed element types. + */ +template +using decay_tuple = decltype(decay_types(std::declval())); + } // namespace utils From 05f800a30a54626bf0f3acb8f188096bfdeda2c2 Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Tue, 1 Oct 2024 13:31:34 +0400 Subject: [PATCH 183/195] Add trait to extract types from a function as a tuple --- common/traits.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/traits.h b/common/traits.h index a5275a20..d8503f53 100644 --- a/common/traits.h +++ b/common/traits.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -82,5 +83,14 @@ struct is_set> : std::true_type template inline constexpr bool is_set_v = is_set::value; +template +struct function +{ + template + static std::tuple pro_args(std::function); + + using args = decltype(pro_args(std::function{std::declval()})); +}; + } // namespace utils From f6a143dd214aee348c086476885f2bac1a341dcc Mon Sep 17 00:00:00 2001 From: Ivan Morozko Date: Fri, 27 Sep 2024 22:07:34 +0400 Subject: [PATCH 184/195] Refactor call method from cli/helper.h - Use a single template for both std::optional and non-optional types. - Replace std::stoull with std::from_chars or std::istringstream based on GCC version. We should support GCC 7.5, but unfortunately it supports not full set of C++17 features. #include is unsupported - Replaced recursive template functions with a single function utilizing std::index_sequence and fold expressions to iterate over tuple elements. - Add support for floating-point arguments - Remove casting of call argument to a function pointer. Now it can accept any callable which is more efficient and extensive - Rename it to Call (google codestyle) --- cli/helper.h | 177 +++++++++++++++------------------------------ cli/main.cpp | 198 +++++++++++++++++++++++++-------------------------- 2 files changed, 157 insertions(+), 218 deletions(-) diff --git a/cli/helper.h b/cli/helper.h index 924d143f..8d64ff6d 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -7,152 +7,91 @@ #include #include "common/sdpclient.h" +#include "common/traits.h" #include "table_printer.h" -void fillValue(std::optional& value, const std::string& string) -{ - if (string == "any") - { - value = std::nullopt; - } - else if (string != "") - { - value = std::stoull(string, nullptr, 0); - ; - } - else - { - value = std::nullopt; - } -} +#if __cpp_lib_charconv >= 201606L && !defined(__GNUC__) || __GNUC__ >= 8 +#define USE_FROM_CHARS +#endif -void fillValue(std::optional& value, const std::string& string) -{ - if (string == "any") - { - value = std::nullopt; - } - else if (string != "") - { - value = std::stoull(string, nullptr, 0); - ; - } - else - { - value = std::nullopt; - } -} +#if defined(USE_FROM_CHARS) +#include +#else +#include +#endif -void fillValue(std::optional& value, const std::string& string) +template +static void fill(T& value, const std::string& str) { - if (string == "any") - { - value = std::nullopt; - } - else if (string != "") + if constexpr (std::is_same_v) { - value = std::stoull(string, nullptr, 0); - ; - } - else - { - value = std::nullopt; - } -} - -template -void fillValue(std::optional& value, const std::string& string) -{ - if (string == "any") - { - value = std::nullopt; + if (str == "true") + value = true; + else if (str == "false") + value = false; + else + throw std::invalid_argument("Invalid boolean value"); } - else if (string != "") + else if constexpr (std::is_integral_v || std::is_floating_point_v) { - value = string; +#ifdef USE_FROM_CHARS + auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value); + if (ec != std::errc{}) + throw std::invalid_argument("Invalid numeric value: '" + str + "'"); +#else + std::istringstream iss(str); + if (!(iss >> value) || !iss.eof()) + throw std::invalid_argument("Invalid numeric value: '" + str + "'"); +#endif } - else + else if constexpr (traits::is_optional_v) { - value = std::nullopt; - } -} - -void fillValue(bool& value, const std::string& string) -{ - if (string == "false" || string == "true") - { - value = string == "true"; + if (str == "any" || str.empty()) + { + value.reset(); + } + else + { + typename T::value_type temp; + fill(temp, str); + value = std::move(temp); + } } else { - throw std::string("invalid argument, must be true or false"); + value = str; } } -void fillValue(uint8_t& value, const std::string& string) -{ - value = std::stoull(string, nullptr, 0); -} - -void fillValue(uint16_t& value, const std::string& string) -{ - value = std::stoull(string, nullptr, 0); -} - -void fillValue(uint32_t& value, const std::string& string) +// Fill a tuple with values from a vector of strings +template +static void fillTupleImpl(Tuple& tuple, const std::vector& args, std::index_sequence) { - value = std::stoull(string, nullptr, 0); + (..., fill(std::get(tuple), Is < args.size() ? args[Is] : std::string{})); } -template -void fillValue(TArg& value, const std::string& string) +template +static void fillTuple(std::tuple& tuple, const std::vector& args) { - value = string; + fillTupleImpl(tuple, args, std::index_sequence_for{}); } -template -void fillValue(std::optional& value) +// Call function using string arguments +template +inline void Call(F&& func, const std::vector& string_args) { - value = std::nullopt; -} - -template -void fillValue([[maybe_unused]] TArg& value) -{ - throw std::string("invalid arguments count"); -} + using ArgsTuple = typename traits::function::args; + constexpr auto arity = std::tuple_size_v; -template -void fillTuple(TTuple& tuple, const std::vector& stringArgs) -{ - if constexpr (TIndex < TSize) + if (string_args.size() > arity) { - if (TIndex < stringArgs.size()) - { - fillValue(std::get(tuple), stringArgs[TIndex]); - } - else - { - fillValue(std::get(tuple)); - } - - fillTuple(tuple, stringArgs); + throw std::invalid_argument("Invalid arguments count: '" + std::to_string(string_args.size()) + + "', expected at most: '" + std::to_string(arity) + "'"); } -} -template -void call(void (*func)(TArgs... args), - const std::vector& stringArgs) -{ - if (stringArgs.size() > sizeof...(TArgs)) - { - throw std::string("invalid arguments count: '") + std::to_string(stringArgs.size()) + "', need: '" + std::to_string(sizeof...(TArgs)) + "'"; - } - std::tuple...> tuple; - fillTuple<0, sizeof...(TArgs)>(tuple, stringArgs); - std::apply(func, tuple); + utils::decay_tuple args_tuple; + fillTuple(args_tuple, string_args); + std::apply(std::forward(func), args_tuple); } void OpenSharedMemoryDataplaneBuffers(common::sdp::DataPlaneInSharedMemory& sdp_data, bool open_workers_data) diff --git a/cli/main.cpp b/cli/main.cpp index 73a1cca8..c13d3577 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -36,117 +36,117 @@ void help() std::vector&)>>> - commands = {{"help", "", [](const auto& args) { call(help, args); }}, + commands = {{"help", "", [](const auto& args) { Call(help, args); }}, {}, - {"physicalPort", "", [](const auto& args) { call(show::physicalPort, args); }}, - {"logicalPort", "", [](const auto& args) { call(show::logicalPort, args); }}, - {"acl unwind", "[module] ", [](const auto& args) { call(acl::unwind, args); }}, - {"acl lookup", " ", [](const auto& args) { call(acl::lookup, args); }}, - {"decap", "", [](const auto& args) { call(show::decap::summary, args); }}, - {"decap announce", "", [](const auto& args) { call(show::decap::announce, args); }}, - {"decap prefix allow", "[module] [ipv6_prefix] [ipv6_prefix]", [](const auto& args) { call(config::decap::allow, args); }}, - {"decap prefix disallow", "[module] [ipv6_prefix] [ipv6_prefix]", [](const auto& args) { call(config::decap::disallow, args); }}, - {"decap prefix remove", "[module] [ipv6_prefix]", [](const auto& args) { call(config::decap::remove, args); }}, - {"tun64", "[module]", [](const auto& args) { call(show::tun64::summary, args); }}, - {"tun64 announce", "[module]", [](const auto& args) { call(show::tun64::announce, args); }}, - {"tun64 mappings list", "[module]", [](const auto& args) { call(show::tun64::mappings, args); }}, - {"nat64stateful", "", [](const auto& args) { call(nat64stateful::summary, args); }}, - {"nat64stateful state", "", [](const auto& args) { call(nat64stateful::state, args); }}, - {"nat64stateful announce", "", [](const auto& args) { call(nat64stateful::announce, args); }}, - {"nat64stateless", "", [](const auto& args) { call(show::nat64stateless::summary, args); }}, - {"nat64stateless translation", "", [](const auto& args) { call(show::nat64stateless::translation, args); }}, - {"nat64stateless announce", "", [](const auto& args) { call(show::nat64stateless::announce, args); }}, - {"nat64stateless prefix allow4", "[module] [ipv4_prefix] [ipv4_prefix]", [](const auto& args) { call(config::nat64stateless::allow4, args); }}, - {"nat64stateless prefix disallow4", "[module] [ipv4_prefix] [ipv4_prefix]", [](const auto& args) { call(config::nat64stateless::disallow4, args); }}, - {"nat64stateless prefix remove4", "[module] [ipv4_prefix]", [](const auto& args) { call(config::nat64stateless::remove4, args); }}, - {"nat64stateless prefix allow6", "[module] [ipv6_prefix] [ipv6_prefix]", [](const auto& args) { call(config::nat64stateless::allow6, args); }}, - {"nat64stateless prefix disallow6", "[module] [ipv6_prefix] [ipv6_prefix]", [](const auto& args) { call(config::nat64stateless::disallow6, args); }}, - {"nat64stateless prefix remove6", "[module] [ipv6_prefix]", [](const auto& args) { call(config::nat64stateless::remove6, args); }}, - {"nat46clat", "", [](const auto& args) { call(nat46clat::summary, args); }}, - {"nat46clat announce", "", [](const auto& args) { call(nat46clat::announce, args); }}, - {"balancer", "", [](const auto& args) { call(balancer::summary, args); }}, - {"balancer service", "[module] ", [](const auto& args) { call(balancer::service, args); }}, - {"balancer real", "[module] ", [](const auto& args) { call(balancer::real_find, args); }}, - {"balancer state", "[module] ", [](const auto& args) { call(balancer::state, args); }}, - {"balancer real enable", "[module] [virtual_ip] [proto] [virtual_port] [real_ip] [real_port] ", [](const auto& args) { call(balancer::real::enable, args); }}, - {"balancer real disable", "[module] [virtual_ip] [proto] [virtual_port] [real_ip] [real_port]", [](const auto& args) { call(balancer::real::disable, args); }}, - {"balancer real flush", "", [](const auto& args) { call(balancer::real::flush, args); }}, - {"balancer announce", "", [](const auto& args) { call(balancer::announce, args); }}, - {"route", "", [](const auto& args) { call(route::summary, args); }}, - {"route interface", "", [](const auto& args) { call(route::interface, args); }}, - {"route lookup", "[module] [ip_address]", [](const auto& args) { call(route::lookup, args); }}, - {"route get", "[module] [ip_prefix]", [](const auto& args) { call(route::get, args); }}, - {"route tunnel lookup", "[module] [ip_address]", [](const auto& args) { call(route::tunnel::lookup, args); }}, - {"route tunnel get", "[module] [ip_prefix]", [](const auto& args) { call(route::tunnel::get, args); }}, - {"route counters", "", [](const auto& args) { call(route::counters, args); }}, - {"route tunnel counters", "", [](const auto& args) { call(route::tunnel::counters, args); }}, - {"neighbor show", "", [](const auto& args) { call(neighbor::show, args); }}, - {"neighbor insert", "[route_name] [interface_name] [ip_address] [mac_address]", [](const auto& args) { call(neighbor::insert, args); }}, - {"neighbor remove", "[route_name] [interface_name] [ip_address]", [](const auto& args) { call(neighbor::remove, args); }}, - {"neighbor flush", "", [](const auto& args) { call(neighbor::flush, args); }}, - {"rib", "", [](const auto& args) { call(rib::summary, args); }}, - {"rib prefixes", "", [](const auto& args) { call(rib::prefixes, args); }}, - {"rib lookup", "[vrf] [ip_address]", [](const auto& args) { call(rib::lookup, args); }}, - {"rib get", "[vrf] [ip_prefix]", [](const auto& args) { call(rib::get, args); }}, - {"rib static insert", "[vrf] [ip_prefix] [nexthop]