From 22df1b463b9e4dcfc99dce5cec60e03d810f9b41 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 15:02:19 +0300 Subject: [PATCH 1/9] Separate route_tunnel request creation for each socket --- common/type.h | 17 +++++++++ controlplane/route.cpp | 81 +++++++++++------------------------------- 2 files changed, 38 insertions(+), 60 deletions(-) diff --git a/common/type.h b/common/type.h index 807392da..2e6bdf6c 100644 --- a/common/type.h +++ b/common/type.h @@ -1998,6 +1998,23 @@ enum class eNexthopType : unsigned int repeat, }; +inline std::string InterfaceName(eNexthopType nh) +{ + switch (nh) + { + case eNexthopType::controlPlane: + return "linux"; + case eNexthopType::repeat: + return "repeat"; + default: +#if __cpp_exceptions + throw std::invalid_argument{"No valid conversion from eNexthopType to interface name string"}; +#else + std::exit(EXIT_FAILURE); +#endif + } +} + enum class eFlowType : uint8_t { drop, diff --git a/controlplane/route.cpp b/controlplane/route.cpp index d69f87cb..ebc611ca 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1620,27 +1620,30 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa tunnel_value_lookup[value_id].clear(); + auto request_for_each_socket = [this, &globalbase, value_id](common::globalBase::eNexthopType nexthop) { + controlPlane->forEachSocket([this, value_id, nexthop, &globalbase](const tSocketId& socket_id) { + tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), + common::globalBase::InterfaceName(nexthop), + 3, ///< @todo: DEFINE + 0, + 0, + 1.00); + + globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, + common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, + socket_id, + nexthop, + {})); + }); + }; + if (const auto nexthops = std::get_if(&destination)) { for (const auto& [nexthop, label, peer_id, origin_as, weight] : *nexthops) { if (nexthop.is_default()) { - controlPlane->forEachSocket([this, &value_id, &globalbase](const tSocketId& socket_id) { - tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), - "linux", - 3, ///< @todo: DEFINE - 0, - 0, - 1.00); - - globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, - common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, - socket_id, - common::globalBase::eNexthopType::controlPlane, - {})); - }); - + request_for_each_socket(common::globalBase::eNexthopType::controlPlane); return; } @@ -1692,21 +1695,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { if (nexthop.is_default()) { - controlPlane->forEachSocket([this, &value_id, &globalbase](const tSocketId& socket_id) { - tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), - "linux", - 3, ///< @todo: DEFINE - 0, - 0, - 1.00); - - globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, - common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, - socket_id, - common::globalBase::eNexthopType::controlPlane, - {})); - }); - + request_for_each_socket(common::globalBase::eNexthopType::controlPlane); return; } @@ -1741,21 +1730,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa } else if (const auto virtual_port_id = std::get_if(&destination)) { - controlPlane->forEachSocket([this, &value_id, &globalbase](const tSocketId& socket_id) { - tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), - "repeat", - 3, ///< @todo: DEFINE - 0, - 0, - 1.00); - - globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, - common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, - socket_id, - common::globalBase::eNexthopType::repeat, - {})); ///< @todo: VIRTUAL_PORT - }); - + request_for_each_socket(common::globalBase::eNexthopType::repeat); return; } else if (std::get_if(&destination)) @@ -1811,21 +1786,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa if (request_interface.empty()) { - controlPlane->forEachSocket([this, &value_id, &globalbase](const tSocketId& socket_id) { - tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), - "linux", - 3, ///< @todo: DEFINE - 0, - 0, - 1.00); - - globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, - common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, - socket_id, - common::globalBase::eNexthopType::controlPlane, - {})); - }); - + request_for_each_socket(common::globalBase::eNexthopType::controlPlane); return; } From 56bf131b26907b7b1300db0f30da6fe6edd43ded Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 15:04:14 +0300 Subject: [PATCH 2/9] Add log error when truncating route_tunnel request size --- controlplane/route.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controlplane/route.cpp b/controlplane/route.cpp index ebc611ca..373e7114 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1780,7 +1780,9 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa if (request_interface.size() > YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE) { /// @todo: stats - + YANET_LOG_ERROR("YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE exceeded, truncated from %ld to %d", + request_interface.size(), + YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE); request_interface.resize(YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE); } From d3542bc3f99ec5d6965cf81333d3a79305193080 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 15:09:37 +0300 Subject: [PATCH 3/9] Replace manual looping with accumulate --- common/weight.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/common/weight.h b/common/weight.h index 20c1fb84..ff000483 100644 --- a/common/weight.h +++ b/common/weight.h @@ -38,11 +38,7 @@ class weight_t } else { - uint32_t weight_total = 0; - for (const auto& weight : weights) - { - weight_total += weight; - } + uint32_t weight_total = std::accumulate(weights.begin(), weights.end(), uint32_t{}); if (size + weight_total > size_T) { YANET_LOG_WARNING("not enough weights\n"); From ba22f642a53c3da1fadd485738e8fe960c639038 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 15:37:10 +0300 Subject: [PATCH 4/9] Separate route tunnel default request creation --- controlplane/route.cpp | 84 ++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 56 deletions(-) diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 373e7114..7496ef93 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1615,6 +1615,30 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { std::vector request_interface; + auto request_default = [&generation, + &request_interface]( + const auto& default_nexthop, + const ip_address_t& nexthop, + uint32_t label, + uint32_t peer_id, + uint32_t origin_as, + uint32_t weight) { + auto interface = generation.get_interface_by_neighbor(default_nexthop); + if (interface) + { + const auto& [interface_id, interface_name] = **interface; + + request_interface.emplace_back(nexthop, + interface_id, + label, + interface_name, + peer_id, + origin_as, + weight, + default_nexthop); + } + }; + const auto& [vrf_priority, destination, fallback] = value_key; GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF @@ -1651,40 +1675,14 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { for (const auto& default_nexthop : tunnel_defaults_v4) { - auto interface = generation.get_interface_by_neighbor(default_nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(nexthop, - interface_id, - label, - interface_name, - peer_id, - origin_as, - weight, - default_nexthop); - } + request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); } } else { for (const auto& default_nexthop : tunnel_defaults_v6) { - auto interface = generation.get_interface_by_neighbor(default_nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(nexthop, - interface_id, - label, - interface_name, - peer_id, - origin_as, - weight, - default_nexthop); - } + request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); } } } @@ -1739,40 +1737,14 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { for (const auto& default_nexthop : tunnel_defaults_v4) { - auto interface = generation.get_interface_by_neighbor(default_nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(default_nexthop, - interface_id, - 3, ///< @todo: DEFINE - interface_name, - 0, - 0, - 1, - default_nexthop); - } + request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); } } else { for (const auto& default_nexthop : tunnel_defaults_v6) { - auto interface = generation.get_interface_by_neighbor(default_nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(default_nexthop, - interface_id, - 3, ///< @todo: DEFINE - interface_name, - 0, - 0, - 1, - default_nexthop); - } + request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); } } } From b5d85897639b193a68d220f7c06246d43d085317 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 16:13:14 +0300 Subject: [PATCH 5/9] Replace if chain with variant visitor --- common/utils.h | 10 +++ controlplane/route.cpp | 180 +++++++++++++++++++++-------------------- 2 files changed, 103 insertions(+), 87 deletions(-) diff --git a/common/utils.h b/common/utils.h index c6373fa8..f747c126 100644 --- a/common/utils.h +++ b/common/utils.h @@ -169,5 +169,15 @@ class Job } }; +// helper type for the variant visitor +template +struct Visitor : Ts... +{ + using Ts::operator()...; +}; +// explicit deduction guide (not needed as of C++20) +template +Visitor(Ts...) -> Visitor; + } // namespace utils diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 7496ef93..9cba3509 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1,5 +1,6 @@ #include "route.h" #include "common/icp.h" +#include "common/utils.h" #include "controlplane.h" #include "controlplane/route.h" @@ -1639,11 +1640,6 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa } }; - const auto& [vrf_priority, destination, fallback] = value_key; - GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF - - tunnel_value_lookup[value_id].clear(); - auto request_for_each_socket = [this, &globalbase, value_id](common::globalBase::eNexthopType nexthop) { controlPlane->forEachSocket([this, value_id, nexthop, &globalbase](const tSocketId& socket_id) { tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), @@ -1661,93 +1657,103 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa }); }; - if (const auto nexthops = std::get_if(&destination)) - { - for (const auto& [nexthop, label, peer_id, origin_as, weight] : *nexthops) - { - if (nexthop.is_default()) - { - request_for_each_socket(common::globalBase::eNexthopType::controlPlane); - return; - } - - if (nexthop.is_ipv4()) - { - for (const auto& default_nexthop : tunnel_defaults_v4) - { - request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); - } - } - else - { - for (const auto& default_nexthop : tunnel_defaults_v6) - { - request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); - } - } - } - } - else if (const auto nexthops = std::get_if(&destination)) - { - for (const auto& nexthop : *nexthops) - { - if (nexthop.is_default()) - { - request_for_each_socket(common::globalBase::eNexthopType::controlPlane); - return; - } - - auto interface = generation.get_interface_by_neighbor(nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; + const auto& [vrf_priority, destination, fallback] = value_key; + GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF - request_interface.emplace_back(nexthop, - interface_id, - 3, ///< @todo: DEFINE - interface_name, - 0, - 0, - 1, - nexthop); - } - } - } - else if (const auto directly_connected = std::get_if(&destination)) - { - const auto& [interface_id, interface_name] = *directly_connected; + tunnel_value_lookup[value_id].clear(); - request_interface.emplace_back(ipv4_address_t(), ///< default - interface_id, - 3, ///< @todo: DEFINE - interface_name, - 0, - 0, - 1, - ipv4_address_t()); ///< default - } - else if (const auto virtual_port_id = std::get_if(&destination)) + const auto& visitor = utils::Visitor{ + [&](const route::tunnel_destination_interface_t& nexthops) { + for (const auto& [nexthop, label, peer_id, origin_as, weight] : nexthops) + { + if (nexthop.is_default()) + { + request_for_each_socket(common::globalBase::eNexthopType::controlPlane); + return true; + } + + if (nexthop.is_ipv4()) + { + for (const auto& default_nexthop : tunnel_defaults_v4) + { + request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); + } + } + else + { + for (const auto& default_nexthop : tunnel_defaults_v6) + { + request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); + } + } + } + return false; + }, + [&](const route::tunnel_destination_legacy_t& nexthops) { + for (const auto& nexthop : nexthops) + { + if (nexthop.is_default()) + { + request_for_each_socket(common::globalBase::eNexthopType::controlPlane); + return true; + } + + auto interface = generation.get_interface_by_neighbor(nexthop); + if (interface) + { + const auto& [interface_id, interface_name] = **interface; + + request_interface.emplace_back(nexthop, + interface_id, + 3, ///< @todo: DEFINE + interface_name, + 0, + 0, + 1, + nexthop); + } + } + return false; + }, + [&](const route::directly_connected_destination_t& directly_connected) { + const auto& [interface_id, interface_name] = directly_connected; + + request_interface.emplace_back(ipv4_address_t(), ///< default + interface_id, + 3, ///< @todo: DEFINE + interface_name, + 0, + 0, + 1, + ipv4_address_t()); ///< default + return false; + }, + [&](uint32_t virtual_port_id) { + request_for_each_socket(common::globalBase::eNexthopType::repeat); + return true; + }, + [&](route::tunnel_destination_default_t) { + if (fallback.is_ipv4()) + { + for (const auto& default_nexthop : tunnel_defaults_v4) + { + request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); + } + } + else + { + for (const auto& default_nexthop : tunnel_defaults_v6) + { + request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); + } + } + return false; + }}; + + if (bool finished = std::visit(visitor, destination); finished) { - request_for_each_socket(common::globalBase::eNexthopType::repeat); return; } - else if (std::get_if(&destination)) - { - if (fallback.is_ipv4()) - { - for (const auto& default_nexthop : tunnel_defaults_v4) - { - request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); - } - } - else - { - for (const auto& default_nexthop : tunnel_defaults_v6) - { - request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); - } - } - } if (request_interface.size() > YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE) { From 9aa2914f1b8478a482e4b6c219fc16ca709efce5 Mon Sep 17 00:00:00 2001 From: vimes Date: Wed, 19 Mar 2025 18:47:24 +0300 Subject: [PATCH 6/9] Append requests without lambdas --- controlplane/route.cpp | 118 +++++++++++++++++++---------------------- controlplane/route.h | 3 ++ 2 files changed, 58 insertions(+), 63 deletions(-) diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 9cba3509..83e13099 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1609,6 +1609,52 @@ void route_t::tunnel_value_remove(const uint32_t& value_id) } } +void route_t::AddRequestForEachSocket(common::idp::updateGlobalBase::request& globalbase, + uint32_t value_id, + common::globalBase::eNexthopType nexthop) +{ + controlPlane->forEachSocket([this, value_id, nexthop, &globalbase](const tSocketId& socket_id) { + tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), + common::globalBase::InterfaceName(nexthop), + 3, ///< @todo: DEFINE + 0, + 0, + 1.00); + + globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, + common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, + socket_id, + nexthop, + {})); + }); +} + +void AddRequestInterface( + std::vector& request_interface, + const route::generation_t& generation, + const ip_address_t& default_nexthop, + const ip_address_t& nexthop, + uint32_t label, + uint32_t peer_id, + uint32_t origin_as, + uint32_t weight) +{ + auto interface = generation.get_interface_by_neighbor(default_nexthop); + if (interface) + { + const auto& [interface_id, interface_name] = **interface; + + request_interface.emplace_back(nexthop, + interface_id, + label, + interface_name, + peer_id, + origin_as, + weight, + default_nexthop); + } +} + void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, @@ -1616,47 +1662,6 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { std::vector request_interface; - auto request_default = [&generation, - &request_interface]( - const auto& default_nexthop, - const ip_address_t& nexthop, - uint32_t label, - uint32_t peer_id, - uint32_t origin_as, - uint32_t weight) { - auto interface = generation.get_interface_by_neighbor(default_nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(nexthop, - interface_id, - label, - interface_name, - peer_id, - origin_as, - weight, - default_nexthop); - } - }; - - auto request_for_each_socket = [this, &globalbase, value_id](common::globalBase::eNexthopType nexthop) { - controlPlane->forEachSocket([this, value_id, nexthop, &globalbase](const tSocketId& socket_id) { - tunnel_value_lookup[value_id][socket_id].emplace_back(ip_address_t(), - common::globalBase::InterfaceName(nexthop), - 3, ///< @todo: DEFINE - 0, - 0, - 1.00); - - globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_tunnel_value_update, - common::idp::updateGlobalBase::route_tunnel_value_update::request(value_id, - socket_id, - nexthop, - {})); - }); - }; - const auto& [vrf_priority, destination, fallback] = value_key; GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF @@ -1668,7 +1673,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { if (nexthop.is_default()) { - request_for_each_socket(common::globalBase::eNexthopType::controlPlane); + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); return true; } @@ -1676,14 +1681,14 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { for (const auto& default_nexthop : tunnel_defaults_v4) { - request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); + AddRequestInterface(request_interface, generation, default_nexthop, nexthop, label, peer_id, origin_as, weight); } } else { for (const auto& default_nexthop : tunnel_defaults_v6) { - request_default(default_nexthop, nexthop, label, peer_id, origin_as, weight); + AddRequestInterface(request_interface, generation, default_nexthop, nexthop, label, peer_id, origin_as, weight); } } } @@ -1694,24 +1699,11 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { if (nexthop.is_default()) { - request_for_each_socket(common::globalBase::eNexthopType::controlPlane); + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); return true; } - auto interface = generation.get_interface_by_neighbor(nexthop); - if (interface) - { - const auto& [interface_id, interface_name] = **interface; - - request_interface.emplace_back(nexthop, - interface_id, - 3, ///< @todo: DEFINE - interface_name, - 0, - 0, - 1, - nexthop); - } + AddRequestInterface(request_interface, generation, nexthop, nexthop, 3, 0, 0, 1); } return false; }, @@ -1729,7 +1721,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa return false; }, [&](uint32_t virtual_port_id) { - request_for_each_socket(common::globalBase::eNexthopType::repeat); + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::repeat); return true; }, [&](route::tunnel_destination_default_t) { @@ -1737,14 +1729,14 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa { for (const auto& default_nexthop : tunnel_defaults_v4) { - request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); + AddRequestInterface(request_interface, generation, default_nexthop, default_nexthop, 3, 0, 0, 1); } } else { for (const auto& default_nexthop : tunnel_defaults_v6) { - request_default(default_nexthop, default_nexthop, 3, 0, 0, 1); + AddRequestInterface(request_interface, generation, default_nexthop, default_nexthop, 3, 0, 0, 1); } } return false; @@ -1766,7 +1758,7 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa if (request_interface.empty()) { - request_for_each_socket(common::globalBase::eNexthopType::controlPlane); + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); return; } diff --git a/controlplane/route.h b/controlplane/route.h index 619da422..b49c8237 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -280,6 +280,9 @@ class route_t : public module_t std::optional tunnel_value_insert(const route::tunnel_value_key_t& value_key); void tunnel_value_remove(const uint32_t& value_id); + void AddRequestForEachSocket(common::idp::updateGlobalBase::request& globalbase, + uint32_t value_id, + common::globalBase::eNexthopType nexthop); void tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, From dd56283d913caac87adb66e07b1123fa53657fba Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 20 Mar 2025 16:29:04 +0300 Subject: [PATCH 7/9] Split filling request_interface from per socket requests --- controlplane/route.cpp | 98 ++++++++++++++++++++++++++++-------------- controlplane/route.h | 10 +++++ 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 83e13099..ecea00f5 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1655,28 +1655,57 @@ void AddRequestInterface( } } -void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, - const route::generation_t& generation, - const uint32_t& value_id, - const route::tunnel_value_key_t& value_key) +bool route_t::MakePerSocketRequest( + common::idp::updateGlobalBase::request& globalbase, + uint32_t value_id, + const route::tunnel_value_key_t& value_key) { - std::vector request_interface; - - const auto& [vrf_priority, destination, fallback] = value_key; - GCC_BUG_UNUSED(vrf_priority); ///< @todo: VRF - - tunnel_value_lookup[value_id].clear(); - const auto& visitor = utils::Visitor{ [&](const route::tunnel_destination_interface_t& nexthops) { - for (const auto& [nexthop, label, peer_id, origin_as, weight] : nexthops) + for (const auto& nexthop : nexthops) + { + if (std::get(nexthop).is_default()) + { + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); + return true; + } + } + return false; + }, + [&](const route::tunnel_destination_legacy_t& nexthops) { + for (const auto& nexthop : nexthops) { if (nexthop.is_default()) { AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); return true; } + } + return false; + }, + [](const route::directly_connected_destination_t&) { return false; }, + [&](uint32_t virtual_port_id) { + AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::repeat); + return true; + }, + [](route::tunnel_destination_default_t) { return false; }}; + return std::visit(visitor, std::get(value_key)); +} + +std::vector route_t::MakeTunnelValueRequestInterface( + common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + uint32_t value_id, + const route::tunnel_value_key_t& value_key) +{ + std::vector request_interface; + tunnel_value_lookup[value_id].clear(); + + const auto& visitor = utils::Visitor{ + [&](const route::tunnel_destination_interface_t& nexthops) { + for (const auto& [nexthop, label, peer_id, origin_as, weight] : nexthops) + { if (nexthop.is_ipv4()) { for (const auto& default_nexthop : tunnel_defaults_v4) @@ -1692,20 +1721,12 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa } } } - return false; }, [&](const route::tunnel_destination_legacy_t& nexthops) { for (const auto& nexthop : nexthops) { - if (nexthop.is_default()) - { - AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); - return true; - } - AddRequestInterface(request_interface, generation, nexthop, nexthop, 3, 0, 0, 1); } - return false; }, [&](const route::directly_connected_destination_t& directly_connected) { const auto& [interface_id, interface_name] = directly_connected; @@ -1718,13 +1739,9 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa 0, 1, ipv4_address_t()); ///< default - return false; - }, - [&](uint32_t virtual_port_id) { - AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::repeat); - return true; }, - [&](route::tunnel_destination_default_t) { + [](uint32_t virtual_port_id) {}, + [&, &fallback = std::get(value_key)](route::tunnel_destination_default_t) { if (fallback.is_ipv4()) { for (const auto& default_nexthop : tunnel_defaults_v4) @@ -1739,13 +1756,9 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa AddRequestInterface(request_interface, generation, default_nexthop, default_nexthop, 3, 0, 0, 1); } } - return false; }}; - if (bool finished = std::visit(visitor, destination); finished) - { - return; - } + std::visit(visitor, std::get(value_key)); if (request_interface.size() > YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE) { @@ -1756,13 +1769,34 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa request_interface.resize(YANET_CONFIG_ROUTE_TUNNEL_ECMP_SIZE); } + return request_interface; +} + +void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + const uint32_t& value_id, + const route::tunnel_value_key_t& value_key) +{ + if (MakePerSocketRequest(globalbase, value_id, value_key)) + { + return; + } + std::vector request_interface = + MakeTunnelValueRequestInterface(globalbase, generation, value_id, value_key); + if (request_interface.empty()) { AddRequestForEachSocket(globalbase, value_id, common::globalBase::eNexthopType::controlPlane); return; } - generation.for_each_socket([this, &value_id, &request_interface, &fallback = fallback, &globalbase](const tSocketId& socket_id, const std::set& interfaces) { + generation.for_each_socket([this, + &value_id, + &request_interface, + &fallback = std::get(value_key), + &globalbase]( + const tSocketId& socket_id, + const std::set& interfaces) { common::idp::updateGlobalBase::route_tunnel_value_update::interface update_interface; auto& [update_weight_start, update_weight_size, update_nexthops] = update_interface; diff --git a/controlplane/route.h b/controlplane/route.h index b49c8237..b63ac689 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -283,6 +283,16 @@ class route_t : public module_t void AddRequestForEachSocket(common::idp::updateGlobalBase::request& globalbase, uint32_t value_id, common::globalBase::eNexthopType nexthop); + bool MakePerSocketRequest( + common::idp::updateGlobalBase::request& globalbase, + uint32_t value_id, + const route::tunnel_value_key_t& value_key); + std::vector + MakeTunnelValueRequestInterface( + common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + uint32_t value_id, + const route::tunnel_value_key_t& value_key); void tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, From 76b4cf1ff75a806aa9bc14db5ed1e45d1b3240cc Mon Sep 17 00:00:00 2001 From: vimes Date: Thu, 20 Mar 2025 19:32:08 +0300 Subject: [PATCH 8/9] Split tunnel_value compilation logic to a lambda --- controlplane/route.cpp | 82 +++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 50 deletions(-) diff --git a/controlplane/route.cpp b/controlplane/route.cpp index ecea00f5..d66bf9a9 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1700,8 +1700,6 @@ std::vector route_t::MakeTunnelValueRequestInte { std::vector request_interface; - tunnel_value_lookup[value_id].clear(); - const auto& visitor = utils::Visitor{ [&](const route::tunnel_destination_interface_t& nexthops) { for (const auto& [nexthop, label, peer_id, origin_as, weight] : nexthops) @@ -1790,6 +1788,8 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa return; } + tunnel_value_lookup[value_id].clear(); + generation.for_each_socket([this, &value_id, &request_interface, @@ -1803,64 +1803,47 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa std::vector weights; uint64_t weight_total = 0; - /// same numa - for (const auto& item : request_interface) - { - const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; - GCC_BUG_UNUSED(egress_interface_name); - - if (exist(interfaces, egress_interface_id)) + auto collect = [&](auto filter) { + for (const auto& item : request_interface) { - const auto counter_id = tunnel_counter.get_id({fallback.is_ipv4(), peer_id, nexthop, origin_as}); + const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; - uint16_t flags = 0; - if (neighbor_address.is_default()) + if (filter(item)) { - flags |= YANET_NEXTHOP_FLAG_DIRECTLY; - } + 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()) + { + flags |= YANET_NEXTHOP_FLAG_DIRECTLY; + } - update_nexthops.emplace_back(egress_interface_id, counter_id, label, nexthop, neighbor_address, flags); - weights.emplace_back(weight); + 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, - egress_interface_name, - label, - peer_id, - origin_as, - weight); + tunnel_value_lookup[value_id][socket_id].emplace_back(nexthop, + egress_interface_name, + label, + peer_id, + origin_as, + weight); - weight_total += weight; + weight_total += weight; + } } - } + }; + + // same numa + collect([&](const route::tunnel_value_interface_t& e) { + return exist(interfaces, std::get<1>(e)); + }); /// all numa if (update_nexthops.empty()) { - for (const auto& item : request_interface) - { - const auto& [nexthop, egress_interface_id, label, egress_interface_name, peer_id, origin_as, weight, neighbor_address] = item; - GCC_BUG_UNUSED(egress_interface_name); - - 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()) - { - flags |= YANET_NEXTHOP_FLAG_DIRECTLY; - } - - 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, - egress_interface_name, - label, - peer_id, - origin_as, - weight); - - weight_total += weight; - } + collect([](const route::tunnel_value_interface_t&) { + return true; + }); } const auto& [weight_start, weight_size, weight_is_fallback] = tunnel_weights.insert(weights); @@ -1875,7 +1858,6 @@ 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]) { - GCC_BUG_UNUSED(socket_id); GCC_BUG_UNUSED(nexthop); GCC_BUG_UNUSED(egress_interface_name); GCC_BUG_UNUSED(label); From e23bd7dfc61e238535fd51a1819f21f743d87d75 Mon Sep 17 00:00:00 2001 From: vimes Date: Fri, 12 Sep 2025 17:57:32 +0300 Subject: [PATCH 9/9] Replace some tuples with structs --- common/weight.h | 24 ++++++++++++++++++------ controlplane/route.cpp | 15 ++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/common/weight.h b/common/weight.h index ff000483..8844de4b 100644 --- a/common/weight.h +++ b/common/weight.h @@ -28,7 +28,19 @@ class weight_t } public: - std::tuple insert(const std::vector& weights) + struct Range + { + uint32_t start; + uint32_t size; + }; + + struct InsertResult + { + Range range; + bool is_fallback; + }; + + InsertResult insert(const std::vector& weights) { /// @todo: check weights.size() @@ -51,9 +63,9 @@ class weight_t return {0, std::min((uint32_t)weights.size(), (uint32_t)256), true}; ///< fallback } - auto& [range_start, range_size] = ranges[*id]; + Range& range = ranges[*id]; - range_start = size; + range.start = size; index_type_T item_i = 0; for (const auto& weight : weights) @@ -64,10 +76,10 @@ class weight_t size += weight; } - range_size = size - range_start; + range.size = size - range.start; } - return std::tuple_cat(ranges[values.get_id(weights)], std::make_tuple(false)); + return {ranges[values.get_id(weights)], false}; } void clear() @@ -104,7 +116,7 @@ class weight_t values; std::map> + Range> ranges; mutable std::vector base; diff --git a/controlplane/route.cpp b/controlplane/route.cpp index d66bf9a9..ad14aaa6 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -1629,6 +1629,9 @@ void route_t::AddRequestForEachSocket(common::idp::updateGlobalBase::request& gl }); } +namespace +{ + void AddRequestInterface( std::vector& request_interface, const route::generation_t& generation, @@ -1655,6 +1658,8 @@ void AddRequestInterface( } } +} // namespace + bool route_t::MakePerSocketRequest( common::idp::updateGlobalBase::request& globalbase, uint32_t value_id, @@ -1846,14 +1851,14 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa }); } - const auto& [weight_start, weight_size, weight_is_fallback] = tunnel_weights.insert(weights); - update_weight_start = weight_start; - update_weight_size = weight_size; + const auto& [weight, weight_is_fallback] = tunnel_weights.insert(weights); + update_weight_start = weight.start; + update_weight_size = weight.size; if (weight_is_fallback) { - tunnel_value_lookup[value_id][socket_id].resize(weight_size); - weight_total = weight_size; + tunnel_value_lookup[value_id][socket_id].resize(weight.size); + weight_total = weight.size; } for (auto& [nexthop, egress_interface_name, label, peer_id, origin_as, weight_percent] : tunnel_value_lookup[value_id][socket_id])