From 22de5ccda6b129d6b0477a4b4c1fffa5eeea2d92 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 22 Dec 2024 18:25:26 +0300 Subject: [PATCH] Added forwarding of route information from controlplane to dataplane --- common/idp.h | 7 +- controlplane/route.cpp | 24 +++-- dataplane/controlplane.cpp | 4 + dataplane/globalbase.cpp | 184 ++++++++++++++++++++++++++++++++----- dataplane/globalbase.h | 13 +++ dataplane/report.cpp | 5 + dataplane/updater.h | 115 +++++++++++++++++++++++ dataplane/vrf.h | 40 ++++++++ 8 files changed, 360 insertions(+), 32 deletions(-) create mode 100644 dataplane/vrf.h diff --git a/common/idp.h b/common/idp.h index 3b0cf4fd..2270f007 100644 --- a/common/idp.h +++ b/common/idp.h @@ -111,9 +111,10 @@ using remove = std::vector; using clear = std::tuple<>; -using request = std::vector>; +using request = std::vector>>; } namespace updateGlobalBase diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 79bfbca0..c3c7f7f0 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -25,7 +25,7 @@ eResult route_t::init() { common::idp::updateGlobalBase::request globalbase; globalbase.emplace_back(common::idp::updateGlobalBase::requestType::route_lpm_update, - common::idp::lpm::request({common::idp::lpm::clear()})); + common::idp::lpm::request({{0, common::idp::lpm::clear()}})); dataplane.updateGlobalBase(std::move(globalbase)); } @@ -1015,7 +1015,12 @@ void route_t::prefix_flush_prefixes(common::idp::updateGlobalBase::request& glob for (auto& [vrf, priority_current_update] : prefixes) { - YANET_GCC_BUG_UNUSED(vrf); ///< @todo: VRF + std::optional vrfId = controlPlane->getVrfIdsStorage().GetOrCreate(vrf); + if (!vrfId.has_value()) + { + YANET_LOG_DEBUG("Can't get id for vrf: '%s'\n", vrf.c_str()); + continue; + } auto& [priority_current, update] = priority_current_update; @@ -1032,7 +1037,7 @@ void route_t::prefix_flush_prefixes(common::idp::updateGlobalBase::request& glob if (lpm_remove.size()) { - lpm_request.emplace_back(lpm_remove); + lpm_request.emplace_back(*vrfId, lpm_remove); } } @@ -1054,7 +1059,7 @@ void route_t::prefix_flush_prefixes(common::idp::updateGlobalBase::request& glob if (lpm_insert.size()) { - lpm_request.emplace_back(lpm_insert); + lpm_request.emplace_back(*vrfId, lpm_insert); } } } @@ -1081,7 +1086,12 @@ void route_t::tunnel_prefix_flush_prefixes(common::idp::updateGlobalBase::reques for (auto& [vrf, priority_current_update] : tunnel_prefixes) { - YANET_GCC_BUG_UNUSED(vrf); ///< @todo: VRF + std::optional vrfId = controlPlane->getVrfIdsStorage().GetOrCreate(vrf); + if (!vrfId.has_value()) + { + YANET_LOG_DEBUG("Can't get id for vrf: '%s'\n", vrf.c_str()); + continue; + } auto& [priority_current, update] = priority_current_update; @@ -1098,7 +1108,7 @@ void route_t::tunnel_prefix_flush_prefixes(common::idp::updateGlobalBase::reques if (lpm_remove.size()) { - lpm_request.emplace_back(lpm_remove); + lpm_request.emplace_back(*vrfId, lpm_remove); } } @@ -1120,7 +1130,7 @@ void route_t::tunnel_prefix_flush_prefixes(common::idp::updateGlobalBase::reques if (lpm_insert.size()) { - lpm_request.emplace_back(lpm_insert); + lpm_request.emplace_back(*vrfId, lpm_insert); } } } diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index 2165ac6f..6ae4d40f 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -810,6 +810,10 @@ common::idp::limits::response cControlPlane::limits() globalBase->updater.route_lpm6->limits(response); globalBase->updater.route_tunnel_lpm4->limits(response); globalBase->updater.route_tunnel_lpm6->limits(response); + globalBase->updater.vrf_route_lpm4->limits(response); + globalBase->updater.vrf_route_lpm6->limits(response); + globalBase->updater.vrf_route_tunnel_lpm4->limits(response); + globalBase->updater.vrf_route_tunnel_lpm6->limits(response); globalBase->updater.acl.network_table->limits(response); globalBase->updater.acl.transport_table->limits(response); diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index 89f0b87e..d7a913fc 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -232,6 +232,58 @@ eResult generation::init() route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer(); } + { + updater.vrf_route_lpm4 = std::make_unique>("vrf_route.v4.lpm", + &dataPlane->memory_manager, + socketId); + result = updater.vrf_route_lpm4->init(); + if (result != eResult::success) + { + return result; + } + + vrf_route_lpm4.Update(updater.vrf_route_lpm4->GetLpms()); + } + + { + updater.vrf_route_lpm6 = std::make_unique, vrf_lpm6>>("vrf_route.v6.lpm", + &dataPlane->memory_manager, + socketId); + result = updater.vrf_route_lpm6->init(); + if (result != eResult::success) + { + return result; + } + + vrf_route_lpm6.Update(updater.vrf_route_lpm6->GetLpms()); + } + + { + updater.vrf_route_tunnel_lpm4 = std::make_unique>("vrf_route.tunnel.v4.lpm", + &dataPlane->memory_manager, + socketId); + result = updater.vrf_route_tunnel_lpm4->init(); + if (result != eResult::success) + { + return result; + } + + vrf_route_tunnel_lpm4.Update(updater.vrf_route_tunnel_lpm4->GetLpms()); + } + + { + updater.vrf_route_tunnel_lpm6 = std::make_unique, vrf_lpm6>>("vrf_route.tunnel.v6.lpm", + &dataPlane->memory_manager, + socketId); + result = updater.vrf_route_tunnel_lpm6->init(); + if (result != eResult::success) + { + return result; + } + + vrf_route_tunnel_lpm6.Update(updater.vrf_route_tunnel_lpm6->GetLpms()); + } + return result; } @@ -1711,7 +1763,7 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ { eResult result = eResult::success; - for (const auto& action : request) + for (const auto& [vrfId, action] : request) { if (const auto update = std::get_if(&action)) { @@ -1719,15 +1771,35 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ { if (prefix.is_ipv4()) { - result = updater.route_lpm4->insert(prefix.get_ipv4().address(), - prefix.get_ipv4().mask(), - value_id); + if (vrfId == 0) + { + result = updater.route_lpm4->insert(prefix.get_ipv4().address(), + prefix.get_ipv4().mask(), + value_id); + } + else + { + result = updater.vrf_route_lpm4->insert(vrfId, + prefix.get_ipv4().address(), + prefix.get_ipv4().mask(), + value_id); + } } else { - result = updater.route_lpm6->insert(prefix.get_ipv6().address(), - prefix.get_ipv6().mask(), - value_id); + if (vrfId == 0) + { + result = updater.route_lpm6->insert(prefix.get_ipv6().address(), + prefix.get_ipv6().mask(), + value_id); + } + else + { + result = updater.vrf_route_lpm6->insert(vrfId, + prefix.get_ipv6().address(), + prefix.get_ipv6().mask(), + value_id); + } } if (result != eResult::success) @@ -1742,13 +1814,31 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ { if (prefix.is_ipv4()) { - result = updater.route_lpm4->remove(prefix.get_ipv4().address(), - prefix.get_ipv4().mask()); + if (vrfId == 0) + { + result = updater.route_lpm4->remove(prefix.get_ipv4().address(), + prefix.get_ipv4().mask()); + } + else + { + result = updater.vrf_route_lpm4->remove(vrfId, + prefix.get_ipv4().address(), + prefix.get_ipv4().mask()); + } } else { - result = updater.route_lpm6->remove(prefix.get_ipv6().address(), - prefix.get_ipv6().mask()); + if (vrfId == 0) + { + result = updater.route_lpm6->remove(prefix.get_ipv6().address(), + prefix.get_ipv6().mask()); + } + else + { + result = updater.vrf_route_lpm6->remove(vrfId, + prefix.get_ipv6().address(), + prefix.get_ipv6().mask()); + } } if (result != eResult::success) @@ -1764,6 +1854,9 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ updater.route_lpm4->clear(); updater.route_lpm6->clear(); + updater.vrf_route_lpm4->clear(); + updater.vrf_route_lpm6->clear(); + return eResult::success; } } @@ -1771,6 +1864,9 @@ eResult generation::route_lpm_update(const common::idp::updateGlobalBase::route_ route_lpm4 = updater.route_lpm4->pointer(); route_lpm6 = updater.route_lpm6->pointer(); + vrf_route_lpm4.Update(updater.vrf_route_lpm4->GetLpms()); + vrf_route_lpm6.Update(updater.vrf_route_lpm6->GetLpms()); + return result; } @@ -1877,7 +1973,7 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: { eResult result = eResult::success; - for (const auto& action : request) + for (const auto& [vrfId, action] : request) { if (const auto update = std::get_if(&action)) { @@ -1885,15 +1981,35 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: { if (prefix.is_ipv4()) { - result = updater.route_tunnel_lpm4->insert(prefix.get_ipv4().address(), - prefix.get_ipv4().mask(), - value_id); + if (vrfId == 0) + { + result = updater.route_tunnel_lpm4->insert(prefix.get_ipv4().address(), + prefix.get_ipv4().mask(), + value_id); + } + else + { + result = updater.vrf_route_tunnel_lpm4->insert(vrfId, + prefix.get_ipv4().address(), + prefix.get_ipv4().mask(), + value_id); + } } else { - result = updater.route_tunnel_lpm6->insert(prefix.get_ipv6().address(), - prefix.get_ipv6().mask(), - value_id); + if (vrfId == 0) + { + result = updater.route_tunnel_lpm6->insert(prefix.get_ipv6().address(), + prefix.get_ipv6().mask(), + value_id); + } + else + { + result = updater.vrf_route_tunnel_lpm6->insert(vrfId, + prefix.get_ipv6().address(), + prefix.get_ipv6().mask(), + value_id); + } } if (result != eResult::success) @@ -1908,13 +2024,31 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: { if (prefix.is_ipv4()) { - result = updater.route_tunnel_lpm4->remove(prefix.get_ipv4().address(), - prefix.get_ipv4().mask()); + if (vrfId == 0) + { + result = updater.route_tunnel_lpm4->remove(prefix.get_ipv4().address(), + prefix.get_ipv4().mask()); + } + else + { + result = updater.vrf_route_tunnel_lpm4->remove(vrfId, + prefix.get_ipv4().address(), + prefix.get_ipv4().mask()); + } } else { - result = updater.route_tunnel_lpm6->remove(prefix.get_ipv6().address(), - prefix.get_ipv6().mask()); + if (vrfId == 0) + { + result = updater.route_tunnel_lpm6->remove(prefix.get_ipv6().address(), + prefix.get_ipv6().mask()); + } + else + { + result = updater.vrf_route_tunnel_lpm6->remove(vrfId, + prefix.get_ipv6().address(), + prefix.get_ipv6().mask()); + } } if (result != eResult::success) @@ -1930,6 +2064,9 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: updater.route_tunnel_lpm4->clear(); updater.route_tunnel_lpm6->clear(); + updater.vrf_route_tunnel_lpm4->clear(); + updater.vrf_route_tunnel_lpm6->clear(); + return eResult::success; } } @@ -1937,6 +2074,9 @@ eResult generation::route_tunnel_lpm_update(const common::idp::updateGlobalBase: route_tunnel_lpm4 = updater.route_tunnel_lpm4->pointer(); route_tunnel_lpm6 = updater.route_tunnel_lpm6->pointer(); + vrf_route_tunnel_lpm4.Update(updater.vrf_route_tunnel_lpm4->GetLpms()); + vrf_route_tunnel_lpm6.Update(updater.vrf_route_tunnel_lpm6->GetLpms()); + return result; } diff --git a/dataplane/globalbase.h b/dataplane/globalbase.h index fbb38538..5ea908bc 100644 --- a/dataplane/globalbase.h +++ b/dataplane/globalbase.h @@ -17,6 +17,7 @@ #include "lpm.h" #include "type.h" #include "updater.h" +#include "vrf.h" /// @todo: move #define YADECAP_GB_DSCP_FLAG_MARK ((uint8_t)1) @@ -133,6 +134,9 @@ class atomic class generation { public: + using vrf_lpm4 = lpm4_24bit_8bit_atomic; + using vrf_lpm6 = lpm6_8x16bit_atomic; + generation(cDataPlane* dataPlane, const tSocketId& socketId); ~generation() = default; @@ -213,6 +217,11 @@ class generation std::unique_ptr route_lpm6; std::unique_ptr route_tunnel_lpm4; std::unique_ptr route_tunnel_lpm6; + + std::unique_ptr> vrf_route_lpm4; + std::unique_ptr, vrf_lpm6>> vrf_route_lpm6; + std::unique_ptr> vrf_route_tunnel_lpm4; + std::unique_ptr, vrf_lpm6>> vrf_route_tunnel_lpm6; } updater; /// variables above are not needed for cWorker::mainThread() @@ -248,12 +257,16 @@ class generation lpm4_24bit_8bit_atomic* route_lpm4; lpm6_8x16bit_atomic* route_lpm6; + dataplane::vrflpm::VrfLookuper vrf_route_lpm4; + dataplane::vrflpm::VrfLookuper vrf_route_lpm6; route_value_t route_values[YANET_CONFIG_ROUTE_VALUES_SIZE]; YADECAP_CACHE_ALIGNED(align3); lpm4_24bit_8bit_atomic* route_tunnel_lpm4; lpm6_8x16bit_atomic* route_tunnel_lpm6; + dataplane::vrflpm::VrfLookuper vrf_route_tunnel_lpm4; + dataplane::vrflpm::VrfLookuper vrf_route_tunnel_lpm6; uint8_t route_tunnel_weights[YANET_CONFIG_ROUTE_TUNNEL_WEIGHTS_SIZE]; route_tunnel_value_t route_tunnel_values[YANET_CONFIG_ROUTE_TUNNEL_VALUES_SIZE]; ipv4_address_t nat64stateful_pool[YANET_CONFIG_NAT64STATEFUL_POOL_SIZE]; diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 23617971..380de9b6 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -670,6 +670,11 @@ nlohmann::json cReport::convertGlobalBase(const dataplane::globalBase::generatio globalBase->updater.route_tunnel_lpm4->report(json["route_tunnel_lpm4"]); globalBase->updater.route_tunnel_lpm6->report(json["route_tunnel_lpm6"]); + globalBase->updater.vrf_route_lpm4->report(json["vrf_route_lpm4"]); + globalBase->updater.vrf_route_lpm6->report(json["vrf_route_lpm6"]); + globalBase->updater.vrf_route_tunnel_lpm4->report(json["vrf_route_tunnel_lpm4"]); + globalBase->updater.vrf_route_tunnel_lpm6->report(json["vrf_route_tunnel_lpm6"]); + globalBase->updater.acl.network_table->report(json["acl"]["network_table"]); globalBase->updater.acl.transport_table->report(json["acl"]["transport_table"]); globalBase->updater.acl.total_table->report(json["acl"]["total_table"]); diff --git a/dataplane/updater.h b/dataplane/updater.h index b3b0dc04..281769c5 100644 --- a/dataplane/updater.h +++ b/dataplane/updater.h @@ -9,6 +9,7 @@ #include "hashtable.h" #include "lpm.h" #include "memory_manager.h" +#include "vrf.h" namespace dataplane { @@ -669,4 +670,118 @@ class updater_array object_type* pointer; }; +template +class updater_vrf_lpm +{ +public: + using stats_t = typename InnerLpmType::stats_t; + using UpdaterType = updater_lpm; + + updater_vrf_lpm(const char* name, + dataplane::memory_manager* memory_manager, + tSocketId socket_id) : + name_(name), + memory_manager_(memory_manager), + socket_id_(socket_id) + { + } + + eResult init() + { + return eResult::success; + } + + eResult insert(tVrfId vrf, + const Address& ip_address, + const uint8_t& mask, + const uint32_t& value_id) + { + if (vrf >= YANET_RIB_VRF_MAX_NUMBER) + { + return eResult::invalidId; + } + if (updaters_[vrf] == nullptr) + { + std::string name = std::string(name_) + ".vrf" + std::to_string(vrf); + updaters_[vrf] = std::make_unique(name.c_str(), memory_manager_, socket_id_); + if (updaters_[vrf] == nullptr) + { + return eResult::errorAllocatingMemory; + } + eResult result = updaters_[vrf]->init(); + if (result != eResult::success) + { + return result; + } + } + + return updaters_[vrf]->insert(ip_address, mask, value_id); + } + + eResult remove(tVrfId vrf, + const Address& ip_address, + const uint8_t& mask) + { + if (vrf >= YANET_RIB_VRF_MAX_NUMBER) + { + return eResult::invalidId; + } + else if (updaters_[vrf] == nullptr) + { + return eResult::success; + } + return updaters_[vrf]->remove(ip_address, mask); + } + + void limits(common::idp::limits::response& limits) const + { + for (size_t index = 0; index < YANET_RIB_VRF_MAX_NUMBER; index++) + { + if (updaters_[index]) + { + updaters_[index]->limits(limits); + } + } + } + + void report(nlohmann::json& report) const + { + for (size_t index = 0; index < YANET_RIB_VRF_MAX_NUMBER; index++) + { + if (updaters_[index]) + { + updaters_[index]->report(report); + } + } + } + + void clear() + { + for (size_t index = 0; index < YANET_RIB_VRF_MAX_NUMBER; index++) + { + if (updaters_[index]) + { + updaters_[index]->clear(); + updaters_[index] = nullptr; + } + } + } + + std::array GetLpms() const + { + std::array result; + for (size_t index = 0; index < YANET_RIB_VRF_MAX_NUMBER; index++) + { + result[index] = (updaters_[index] == nullptr ? nullptr : updaters_[index]->pointer()); + } + return result; + } + +private: + std::string name_; + dataplane::memory_manager* memory_manager_; + tSocketId socket_id_; + std::array, YANET_RIB_VRF_MAX_NUMBER> updaters_; +}; + } diff --git a/dataplane/vrf.h b/dataplane/vrf.h new file mode 100644 index 00000000..eab0451d --- /dev/null +++ b/dataplane/vrf.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "lpm.h" +#include "type.h" + +namespace dataplane::vrflpm +{ + +template +class VrfLookuper +{ +public: + void Update(std::array lpms) + { + for (size_t index = 0; index < lpms_.size(); index++) + { + lpms_[index] = lpms[index]; + } + } + + void Lookup(const Address* ipAddresses, const tVrfId* vrfIds, uint32_t* valueIds, const unsigned int& count) const + { + for (unsigned int index = 0; index < count; index++) + { + valueIds[index] = lpmValueIdInvalid; + tVrfId vrf = vrfIds[index]; + if ((vrf < YANET_RIB_VRF_MAX_NUMBER) && (lpms_[vrf] != nullptr)) + { + lpms_[vrf]->lookup(ipAddresses + index, valueIds + index, 1); + } + } + } + +private: + std::array lpms_; +}; + +} // namespace dataplane