diff --git a/cli/develop.h b/cli/develop.h index dc99a1e4..c45a39de 100644 --- a/cli/develop.h +++ b/cli/develop.h @@ -1,7 +1,15 @@ #pragma once +#include +#include +#include +#include +#include +#include + #include "common/icontrolplane.h" #include "common/idataplane.h" +#include "common/tsc_deltas.h" #include "helper.h" @@ -160,6 +168,196 @@ void counter(const uint32_t& counter_id, table.print(); } +using namespace ::dataplane::perf; +class tsc_monitoring_t +{ +public: + void connect_shm() + { + interface::dataPlane dataplane; + const auto response = dataplane.get_shm_tsc_info(); + std::map ipc_cache; + + for (const auto& [core, socket, ipc_key, offset] : response) + { + (void)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, NULL, SHM_RDONLY); + if (shmaddr == (void*)-1) + { + throw std::string("shmat(") + std::to_string(ipc_key) + ", NULL, 0) = " + std::strerror(errno); + } + + ipc_cache[ipc_key] = shmaddr; + } + + auto counter_addr = (tsc_deltas*)((intptr_t)ipc_cache[ipc_key] + offset); + worker_counters.emplace_back(core, counter_addr, tsc_deltas{}, overflow_store{}); + } + } + + void monitor() + { + connect_shm(); + for (auto iter = 0;; iter++) + { + if (iter % 4 == 0) + { + insert_header(); + } + + 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++) + { + overflow_store.handle_overflow(counter_copy, previous_value, bin); + if (iter % 4 == 0) + { + insert_bin(counter_copy, overflow_store, bin, core_id); + } + } + + previous_value = counter_copy; + } + + if (iter % 4 == 0) + { + table.render(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } + } + +protected: + struct overflow_store; + + 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", + "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) + { + 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.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]); + } + + 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 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]; + + 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; + 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; + } + }; + + std::vector> worker_counters; + table_t table; +}; + +void tsc_monitoring() +{ + tsc_monitoring_t monitoring{}; + monitoring.monitor(); +} + } } diff --git a/cli/helper.h b/cli/helper.h index f16aad7d..88b9b146 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -97,6 +97,18 @@ void fillValue(std::optional& value, const std::string& string) } } +void fillValue(bool& value, const std::string& string) +{ + if (string == "false" || string == "true") + { + value = string == "true"; + } + else + { + throw std::string("invalid argument, must be true or false"); + } +} + void fillValue(uint8_t& value, const std::string& string) { value = std::stoull(string, nullptr, 0); @@ -427,6 +439,13 @@ class table_t } } + void render() + { + printf("\033[2J\033[H"); + print_default(); + table.clear(); + } + protected: converter::config_t config; std::vector> table; diff --git a/cli/main.cpp b/cli/main.cpp index 5f76c32c..0ed1855d 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -100,6 +100,10 @@ std::vector ", [](const auto& args) { call(rib::clear, args); }}, + {"dontdoit podumoi tsc monitoring", "", [](const auto& args) { call(develop::dataplane::tsc_monitoring, args); }}, {}, {"telegraf unsafe", "", [](const auto& args) { call(telegraf::unsafe, args); }}, {"telegraf ports", "", [](const auto& args) { call(telegraf::ports_stats, args); }}, diff --git a/cli/show.h b/cli/show.h index f7c6f2c7..637af1cd 100644 --- a/cli/show.h +++ b/cli/show.h @@ -6,6 +6,7 @@ #include "common/icontrolplane.h" #include "common/idataplane.h" +#include "common/tsc_deltas.h" #include "common/version.h" #include "helper.h" @@ -850,4 +851,75 @@ inline void shm_info() table.print(); } +void shm_tsc_info() +{ + interface::dataPlane dataplane; + const auto response = dataplane.get_shm_tsc_info(); + + table_t 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(); +} + +void shm_tsc_set_state(bool state) +{ + interface::dataPlane dataplane; + common::idp::updateGlobalBase::request globalbase; + globalbase.emplace_back(common::idp::updateGlobalBase::requestType::tsc_state_update, + state); + dataplane.updateGlobalBase(globalbase); +} + +using dataplane::perf::tsc_base_values; +static const std::map counter_name_to_offset = { + {"logicalPort_ingress_handle", offsetof(tsc_base_values, logicalPort_ingress_handle)}, + {"acl_ingress_handle4", offsetof(tsc_base_values, acl_ingress_handle4)}, + {"acl_ingress_handle6", offsetof(tsc_base_values, acl_ingress_handle6)}, + {"tun64_ipv4_handle", offsetof(tsc_base_values, tun64_ipv4_handle)}, + {"tun64_ipv6_handle", offsetof(tsc_base_values, tun64_ipv6_handle)}, + {"route_handle4", offsetof(tsc_base_values, route_handle4)}, + {"route_handle6", offsetof(tsc_base_values, route_handle6)}, + {"decap_handle", offsetof(tsc_base_values, decap_handle)}, + {"nat64stateful_lan_handle", offsetof(tsc_base_values, nat64stateful_lan_handle)}, + {"nat64stateful_wan_handle", offsetof(tsc_base_values, nat64stateful_wan_handle)}, + {"nat64stateless_egress_handle", offsetof(tsc_base_values, nat64stateless_egress_handle)}, + {"nat64stateless_ingress_handle", offsetof(tsc_base_values, nat64stateless_ingress_handle)}, + {"balancer_handle", offsetof(tsc_base_values, balancer_handle)}, + {"balancer_icmp_reply_handle", offsetof(tsc_base_values, balancer_icmp_reply_handle)}, + {"balancer_icmp_forward_handle", offsetof(tsc_base_values, balancer_icmp_forward_handle)}, + {"route_tunnel_handle4", offsetof(tsc_base_values, route_tunnel_handle4)}, + {"route_tunnel_handle6", offsetof(tsc_base_values, route_tunnel_handle6)}, + {"acl_egress_handle4", offsetof(tsc_base_values, acl_egress_handle4)}, + {"acl_egress_handle6", offsetof(tsc_base_values, acl_egress_handle6)}, + {"logicalPort_egress_handle", offsetof(tsc_base_values, logicalPort_egress_handle)}, + {"controlPlane_handle", offsetof(tsc_base_values, controlPlane_handle)}, +}; + +void shm_tsc_set_base_value(std::string counter_name, uint32_t value) +{ + if (counter_name_to_offset.count(counter_name) != 0) + { + interface::dataPlane dataplane; + common::idp::updateGlobalBase::request globalbase; + globalbase.emplace_back(common::idp::updateGlobalBase::requestType::tscs_base_value_update, + common::idp::updateGlobalBase::tscs_base_value_update::request{counter_name_to_offset.at(counter_name), value}); + dataplane.updateGlobalBase(globalbase); + } + else + { + std::string args; + std::for_each(counter_name_to_offset.cbegin(), counter_name_to_offset.cend(), [&](const auto& e) { args += " " + e.first; }); + throw std::string("invalid argument: ") + counter_name + ", supported types:" + args; + } +} + } diff --git a/common/config.release.h b/common/config.release.h index 2fdeb45e..c32619f3 100644 --- a/common/config.release.h +++ b/common/config.release.h @@ -73,4 +73,5 @@ #define YANET_CONFIG_SHARED_RINGS_NUMBER (32) #define YANET_DEFAULT_IPC_SHMKEY (12345) #define YANET_CONFIG_KERNEL_INTERFACE_QUEUE_SIZE (4096) +#define YANET_CONFIG_TSC_ACTIVE_STATE (0) #define YANET_CONFIG_NAT46CLATS_SIZE (32) diff --git a/common/idataplane.h b/common/idataplane.h index 227196da..aeeb26d7 100644 --- a/common/idataplane.h +++ b/common/idataplane.h @@ -208,6 +208,11 @@ class dataPlane return get(); } + auto get_shm_tsc_info() const + { + return get(); + } + auto dump_physical_port(const common::idp::dump_physical_port::request& request) const { return get(request); diff --git a/common/idp.h b/common/idp.h index e68f8bff..cee29adb 100644 --- a/common/idp.h +++ b/common/idp.h @@ -71,6 +71,8 @@ enum class requestType : uint32_t version, get_counter_by_name, get_shm_info, + get_shm_tsc_info, + set_shm_tsc_state, dump_physical_port, balancer_state_clear, neighbor_show, @@ -161,6 +163,8 @@ enum class requestType : uint32_t tun64_update, tun64mappings_update, serial_update, + tsc_state_update, + tscs_base_value_update, nat46clat_update, dump_tags_ids }; @@ -488,6 +492,16 @@ namespace serial_update using request = uint32_t; ///< serial } +namespace tsc_state_update +{ +using request = bool; +} + +namespace tscs_base_value_update +{ +using request = std::tuple; +} + using requestVariant = std::variant, updateLogicalPort::request, updateDecap::request, @@ -520,7 +534,8 @@ using requestVariant = std::variant, dregress_neighbor_update::request, dregress_value_update::request, fwstate_synchronization_update::request, - sampler_update::request, /// + update_early_decap_flags::request + sampler_update::request, /// + update_early_decap_flags::request, tsc_state_update::request + tscs_base_value_update::request, serial_update::request, nat46clat_update::request>; @@ -875,6 +890,16 @@ using dump_meta = std::tuple; } +namespace get_shm_tsc_info +{ +using tsc_meta = std::tuple; /// offset + +using response = std::vector; +} + namespace dump_physical_port { using request = std::tuple, samples::response, get_counter_by_name::response, get_shm_info::response, + get_shm_tsc_info::response, neighbor_show::response, neighbor_stats::response>; } diff --git a/common/tsc_deltas.h b/common/tsc_deltas.h new file mode 100644 index 00000000..b12910f5 --- /dev/null +++ b/common/tsc_deltas.h @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "common/define.h" + +#define YANET_TSC_BINS_SHIFT 2 +#define YANET_TSC_BINS_N 4 + +namespace dataplane +{ + +namespace perf +{ + +struct tsc_base_values +{ + uint32_t logicalPort_ingress_handle = 18; + uint32_t acl_ingress_handle4 = 0; + uint32_t acl_ingress_handle6 = 124; + uint32_t tun64_ipv4_handle = 0; + uint32_t tun64_ipv6_handle = 0; + uint32_t route_handle4 = 0; + uint32_t route_handle6 = 81; + uint32_t decap_handle = 0; + + uint32_t nat64stateful_lan_handle = 0; + uint32_t nat64stateful_wan_handle = 0; + uint32_t nat64stateless_egress_handle = 0; + uint32_t nat64stateless_ingress_handle = 0; + uint32_t balancer_handle = 259; + uint32_t balancer_icmp_reply_handle = 0; + uint32_t balancer_icmp_forward_handle = 0; + uint32_t route_tunnel_handle4 = 0; + + uint32_t route_tunnel_handle6 = 0; + uint32_t acl_egress_handle4 = 0; + 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 +{ + 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 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) + { + if (!tsc_start || unlikely(stack_size == 0)) + { + return; + } + + auto tsc_end = rte_get_tsc_cycles(); + auto shifted_delta = (int64_t)((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); + bins[bin_idx]++; + } + else + { + bins[0]++; + } + + 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"); + +} + +} diff --git a/dataplane/bus.cpp b/dataplane/bus.cpp index 169843cc..c72d7831 100644 --- a/dataplane/bus.cpp +++ b/dataplane/bus.cpp @@ -338,6 +338,10 @@ void cBus::clientThread(int clientSocket) { response = callWithResponse(&cControlPlane::get_shm_info, request); } + else if (type == common::idp::requestType::get_shm_tsc_info) + { + response = callWithResponse(&cControlPlane::get_shm_tsc_info, request); + } else if (type == common::idp::requestType::dump_physical_port) { response = callWithResponse(&cControlPlane::dump_physical_port, request); diff --git a/dataplane/controlplane.cpp b/dataplane/controlplane.cpp index a2386bfc..de372df6 100644 --- a/dataplane/controlplane.cpp +++ b/dataplane/controlplane.cpp @@ -9,6 +9,7 @@ #include #include "common/fallback.h" +#include "common/idp.h" #include "common/version.h" #include "checksum.h" @@ -1229,6 +1230,17 @@ common::idp::get_shm_info::response cControlPlane::get_shm_info() return response; } +common::idp::get_shm_tsc_info::response cControlPlane::get_shm_tsc_info() +{ + common::idp::get_shm_tsc_info::response response; + for (const auto& key : dataPlane->getShmTscInfo()) + { + response.emplace_back(key); + } + + return response; +} + eResult cControlPlane::dump_physical_port(const common::idp::dump_physical_port::request& request) { const auto& [interface_name, direction, state] = request; diff --git a/dataplane/controlplane.h b/dataplane/controlplane.h index 3c5b33b4..e1885c52 100644 --- a/dataplane/controlplane.h +++ b/dataplane/controlplane.h @@ -68,6 +68,7 @@ class cControlPlane ///< @todo: move to cDataPlane 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(); eResult dump_physical_port(const common::idp::dump_physical_port::request& request); eResult balancer_state_clear(); diff --git a/dataplane/dataplane.cpp b/dataplane/dataplane.cpp index 1182a6d0..75116fca 100644 --- a/dataplane/dataplane.cpp +++ b/dataplane/dataplane.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -27,6 +28,9 @@ #include #include "common.h" +#include "common/idp.h" +#include "common/result.h" +#include "common/tsc_deltas.h" #include "dataplane.h" #include "globalbase.h" #include "report.h" @@ -87,6 +91,7 @@ cDataPlane::cDataPlane() : {eConfigType::master_mempool_size, 8192}, {eConfigType::nat64stateful_states_size, YANET_CONFIG_NAT64STATEFUL_HT_SIZE}, {eConfigType::kernel_interface_queue_size, YANET_CONFIG_KERNEL_INTERFACE_QUEUE_SIZE}, + {eConfigType::tsc_active_state, YANET_CONFIG_TSC_ACTIVE_STATE}, {eConfigType::balancer_state_ttl, 60}, {eConfigType::balancer_state_ht_size, YANET_CONFIG_BALANCER_STATE_HT_SIZE}}; } @@ -1365,6 +1370,17 @@ eResult cDataPlane::allocateSharedMemory() } } + for (const auto& [socket_id, num] : number_of_workers_per_socket) + { + auto it = shm_size_per_socket.find(socket_id); + if (it == shm_size_per_socket.end()) + { + 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))); + } + /// allocating IPC shared memory key_t key = YANET_DEFAULT_IPC_SHMKEY; for (const auto& [socket_id, size] : shm_size_per_socket) @@ -1474,6 +1490,25 @@ eResult cDataPlane::splitSharedMemoryPerWorkers() } } + for (auto& [core_id, worker] : workers) + { + const auto& socket_id = worker->socketId; + const auto& it = shm_by_socket_id.find(socket_id); + if (it == shm_by_socket_id.end()) + { + continue; + } + 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)); + offsets[shm] += sizeof(dataplane::perf::tsc_deltas); + + auto meta = common::idp::get_shm_tsc_info::tsc_meta(core_id, socket_id, key, offset); + tscs_meta.emplace_back(meta); + } + return eResult::success; } @@ -1487,6 +1522,16 @@ common::idp::get_shm_info::response cDataPlane::getShmInfo() return result; } +common::idp::get_shm_tsc_info::response cDataPlane::getShmTscInfo() +{ + common::idp::get_shm_tsc_info::response result; + result.reserve(tscs_meta.size()); + + std::copy(tscs_meta.begin(), tscs_meta.end(), std::back_inserter(result)); + + return result; +} + std::map cDataPlane::getPortStats(const tPortId& portId) const { /// unsafe @@ -1890,6 +1935,11 @@ eResult cDataPlane::parseConfigValues(const nlohmann::json& json) configValues[eConfigType::kernel_interface_queue_size] = json["kernel_interface_queue_size"]; } + if (exist(json, "tsc_active_state")) + { + configValues[eConfigType::tsc_active_state] = json["tsc_active_state"]; + } + if (exist(json, "balancer_state_ttl")) { configValues[eConfigType::balancer_state_ttl] = json["balancer_state_ttl"]; diff --git a/dataplane/dataplane.h b/dataplane/dataplane.h index 0a700e3b..466fe757 100644 --- a/dataplane/dataplane.h +++ b/dataplane/dataplane.h @@ -58,6 +58,7 @@ enum class eConfigType master_mempool_size, nat64stateful_states_size, kernel_interface_queue_size, + tsc_active_state, balancer_state_ttl, balancer_state_ht_size, }; @@ -295,6 +296,7 @@ class cDataPlane 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(); static int lcoreThread(void* args); void timestamp_thread(); @@ -344,6 +346,8 @@ class cDataPlane common::idp::get_shm_info::response dumps_meta; std::map tag_to_id; + common::idp::get_shm_tsc_info::response tscs_meta; + /// modules cReport report; std::unique_ptr controlPlane; diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index baf6b420..5688c5f6 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -27,6 +27,8 @@ 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->getConfigValue(eConfigType::tsc_active_state); } atomic::~atomic() @@ -232,6 +234,14 @@ eResult generation::update(const common::idp::updateGlobalBase::request& request result = eResult::success; serial = std::get(data); } + else if (type == common::idp::updateGlobalBase::requestType::tsc_state_update) + { + result = tsc_state_update(std::get(data)); + } + else if (type == common::idp::updateGlobalBase::requestType::tscs_base_value_update) + { + result = tscs_base_value_update(std::get(data)); + } else { YADECAP_LOG_ERROR("invalid request type\n"); @@ -740,6 +750,20 @@ eResult generation::tun64mappings_update(const common::idp::updateGlobalBase::tu return eResult::success; } +eResult generation::tsc_state_update(const common::idp::updateGlobalBase::tsc_state_update::request& request) +{ + tscs_active = request; + return eResult::success; +} + +eResult generation::tscs_base_value_update(const common::idp::updateGlobalBase::tscs_base_value_update::request& request) +{ + const auto& [offset, value] = request; + *(uint32_t*)((uintptr_t)(&tsc_base_values) + offset) = value; + + return eResult::success; +} + eResult generation::updateDecap(const common::idp::updateGlobalBase::updateDecap::request& request) { using common::eDscpMarkType; diff --git a/dataplane/globalbase.h b/dataplane/globalbase.h index 54578e97..332694c7 100644 --- a/dataplane/globalbase.h +++ b/dataplane/globalbase.h @@ -9,6 +9,7 @@ #include "common/idp.h" #include "common/result.h" +#include "common/tsc_deltas.h" #include "common.h" #include "dynamic_table.h" @@ -51,9 +52,9 @@ struct transport_layer_t struct { /** @todo: - flat type; - flat code; - */ + flat type; + flat code; + */ flat type_code; flat identifier; } icmp; @@ -121,6 +122,8 @@ class atomic nat64stateful::lan_ht* nat64stateful_lan_state; nat64stateful::wan_ht* nat64stateful_wan_state; balancer::state_ht* balancer_state; + + bool tsc_active_state; }; // @@ -177,6 +180,8 @@ class generation eResult fwstate_synchronization_update(const common::idp::updateGlobalBase::fwstate_synchronization_update::request& request); eResult tun64_update(const common::idp::updateGlobalBase::tun64_update::request& request); eResult tun64mappings_update(const common::idp::updateGlobalBase::tun64mappings_update::request& request); + eResult tsc_state_update(const common::idp::updateGlobalBase::tsc_state_update::request& request); + eResult tscs_base_value_update(const common::idp::updateGlobalBase::tscs_base_value_update::request& request); void evaluate_service_ring(uint32_t next_balancer_reals_id); inline uint64_t count_real_connections(uint32_t counter_id); @@ -298,6 +303,9 @@ class generation balancer_service_ring_t balancer_service_rings[2]; int64_t dump_id_to_tag[YANET_CONFIG_DUMP_ID_TO_TAG_SIZE]; + + bool tscs_active; + dataplane::perf::tsc_base_values tsc_base_values; }; } diff --git a/dataplane/meson.build b/dataplane/meson.build index d886657e..1a8d0712 100644 --- a/dataplane/meson.build +++ b/dataplane/meson.build @@ -29,7 +29,8 @@ foreach arch : archs endif cpp_args_append = ['-march=' + arch, - '-DYANET_CONFIG_SUFFIX=' + yanet_config] + '-DYANET_CONFIG_SUFFIX=' + yanet_config, + '-mlzcnt'] executable(bin, sources, diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 8782d50a..a7e48ec0 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -856,10 +857,25 @@ inline void cWorker::handlePackets() const auto& base = bases[localBaseId & 1]; const auto& globalbase = *base.globalBase; + auto& base_values = globalbase.tsc_base_values; + auto tsc_start = globalbase.tscs_active || basePermanently.globalBaseAtomic->tsc_active_state ? rte_get_tsc_cycles() : 0; + + if (tsc_start) + { + tsc_deltas->iter_num++; + } + + auto stack_size = logicalPort_ingress_stack.mbufsCount; logicalPort_ingress_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->logicalPort_ingress_handle, base_values.logicalPort_ingress_handle); + stack_size = acl_ingress_stack4.mbufsCount; acl_ingress_handle4(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_ingress_handle4, base_values.acl_ingress_handle4); + + stack_size = acl_ingress_stack6.mbufsCount; acl_ingress_handle6(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_ingress_handle6, base_values.acl_ingress_handle6); if (globalbase.early_decap_enabled) { @@ -867,38 +883,61 @@ inline void cWorker::handlePackets() { acl_ingress_stack4 = after_early_decap_stack4; after_early_decap_stack4.clear(); + + stack_size = acl_ingress_stack4.mbufsCount; acl_ingress_handle4(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_ingress_handle4, base_values.acl_ingress_handle4); } if (after_early_decap_stack6.mbufsCount > 0) { acl_ingress_stack6 = after_early_decap_stack6; after_early_decap_stack6.clear(); + + stack_size = acl_ingress_stack6.mbufsCount; acl_ingress_handle6(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_ingress_handle6, base_values.acl_ingress_handle6); } } if (globalbase.tun64_enabled) { + stack_size = tun64_stack4.mbufsCount; tun64_ipv4_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->tun64_ipv4_handle, base_values.tun64_ipv4_handle); + + stack_size = tun64_stack6.mbufsCount; tun64_ipv6_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->tun64_ipv6_handle, base_values.tun64_ipv6_handle); } if (globalbase.decap_enabled) { + stack_size = decap_stack.mbufsCount; decap_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->decap_handle, base_values.decap_handle); } if (globalbase.nat64stateful_enabled) { + stack_size = nat64stateful_lan_stack.mbufsCount; nat64stateful_lan_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->nat64stateful_lan_handle, base_values.nat64stateful_lan_handle); + + stack_size = nat64stateful_wan_stack.mbufsCount; nat64stateful_wan_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->nat64stateful_wan_handle, base_values.nat64stateful_wan_handle); } if (globalbase.nat64stateless_enabled) { + stack_size = nat64stateless_ingress_stack.mbufsCount; nat64stateless_ingress_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->nat64stateless_ingress_handle, base_values.nat64stateless_ingress_handle); + + stack_size = nat64stateless_egress_stack.mbufsCount; nat64stateless_egress_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->nat64stateless_egress_handle, base_values.nat64stateless_egress_handle); } if (globalbase.nat46clat_enabled) @@ -909,25 +948,54 @@ inline void cWorker::handlePackets() if (globalbase.balancer_enabled) { + stack_size = balancer_stack.mbufsCount; balancer_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->balancer_handle, base_values.balancer_handle); + stack_size = balancer_icmp_reply_stack.mbufsCount; balancer_icmp_reply_handle(); // balancer replies instead of real (when client pings VS) + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->balancer_icmp_reply_handle, base_values.balancer_icmp_reply_handle); + + stack_size = balancer_icmp_forward_stack.mbufsCount; balancer_icmp_forward_handle(); // forward icmp message to other balancers (if not sent to one of this balancer's reals) + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->balancer_icmp_forward_handle, base_values.balancer_icmp_forward_handle); } + stack_size = route_stack4.mbufsCount; route_handle4(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->route_handle4, base_values.route_handle4); + + stack_size = route_stack6.mbufsCount; route_handle6(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->route_handle6, base_values.route_handle6); + + stack_size = route_tunnel_stack4.mbufsCount; route_tunnel_handle4(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->route_tunnel_handle4, base_values.route_tunnel_handle4); + + stack_size = route_tunnel_stack6.mbufsCount; route_tunnel_handle6(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->route_tunnel_handle6, base_values.route_tunnel_handle6); if (globalbase.acl_egress_enabled) { + stack_size = acl_egress_stack4.mbufsCount; acl_egress_handle4(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_egress_handle4, base_values.acl_egress_handle4); + + stack_size = acl_egress_stack6.mbufsCount; acl_egress_handle6(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->acl_egress_handle6, base_values.acl_egress_handle6); } + stack_size = logicalPort_egress_stack.mbufsCount; logicalPort_egress_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->logicalPort_egress_handle, base_values.logicalPort_egress_handle); + + stack_size = controlPlane_stack.mbufsCount; controlPlane_handle(); + tsc_deltas->write(tsc_start, stack_size, tsc_deltas->controlPlane_handle, base_values.controlPlane_handle); + physicalPort_egress_handle(); } diff --git a/dataplane/worker.h b/dataplane/worker.h index 6410262d..6b2a1688 100644 --- a/dataplane/worker.h +++ b/dataplane/worker.h @@ -9,6 +9,7 @@ #include #include "common/result.h" +#include "common/tsc_deltas.h" #include "common/type.h" #include "base.h" @@ -316,7 +317,7 @@ class cWorker rte_ring* ring_highPriority; rte_ring* ring_normalPriority; rte_ring* ring_lowPriority; - + dataplane::perf::tsc_deltas* tsc_deltas; rte_ring* ring_toFreePackets; rte_ring* ring_log;