Skip to content

Commit

Permalink
fixup! Add external ip connections counters for each service
Browse files Browse the repository at this point in the history
  • Loading branch information
lnarolski committed Nov 14, 2024
1 parent e0efd7c commit 5335b25
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 46 deletions.
2 changes: 1 addition & 1 deletion ebpfdiscoverysrv/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ int main(int argc, char** argv) {
if(featchAndHandleEventsFuture.valid()) {
featchAndHandleEventsFuture.wait();
}
if(!enableNetworkCounters && networkCountersCleaningFuture.valid()) {
if(enableNetworkCounters && networkCountersCleaningFuture.valid()) {
networkCountersCleaningFuture.wait();
}

Expand Down
4 changes: 2 additions & 2 deletions libebpfdiscoveryproto/src/Translator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ std::pair<ServicesList, bool> internalToProto(const std::vector<std::reference_w
protoService->set_internalclientsnumber(service.internalClientsNumber);
protoService->set_externalclientsnumber(service.externalClientsNumber);
if (enableNetworkCounters) {
protoService->set_externalipv4_16clientnets(service.detectedExternalIPv416Networks.size());
protoService->set_externalipv4_24clientnets(service.detectedExternalIPv424Networks.size());
protoService->set_externalipv4_16clientnets(service.detectedExternalIPv4_16Networks.size());
protoService->set_externalipv4_24clientnets(service.detectedExternalIPv4_24Networks.size());
protoService->set_externalipv6clientsnets(service.detectedExternalIPv6Networks.size());
}

Expand Down
6 changes: 3 additions & 3 deletions libebpfdiscoveryproto/test/TranslatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ TEST_F(ProtobufTranslatorTest, successfulTranslationToJsonNetworkCounters) {
};

std::vector<std::reference_wrapper<service::Service>> internalServices;
service::Service service1{.pid = 1, .endpoint = "/endpoint/1", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv416Networks = detectedExternalIPv416Networks, .detectedExternalIPv424Networks = detectedExternalIPv424Networks};
service::Service service2{.pid = 2, .endpoint = "/endpoint/1", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv416Networks = detectedExternalIPv416Networks, .detectedExternalIPv424Networks = detectedExternalIPv424Networks};
service::Service service3{.pid = 3, .endpoint = "/endpoint/2", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv416Networks = detectedExternalIPv416Networks, .detectedExternalIPv424Networks = detectedExternalIPv424Networks};
service::Service service1{.pid = 1, .endpoint = "/endpoint/1", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv4_16Networks = detectedExternalIPv416Networks, .detectedExternalIPv4_24Networks = detectedExternalIPv424Networks};
service::Service service2{.pid = 2, .endpoint = "/endpoint/1", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv4_16Networks = detectedExternalIPv416Networks, .detectedExternalIPv4_24Networks = detectedExternalIPv424Networks};
service::Service service3{.pid = 3, .endpoint = "/endpoint/2", .internalClientsNumber = 1, .externalClientsNumber = 3, .detectedExternalIPv4_16Networks = detectedExternalIPv416Networks, .detectedExternalIPv4_24Networks = detectedExternalIPv424Networks};

service::Service service4{.pid = 4, .endpoint = "google.com/endpoint/3", .domain = "google.com", .scheme = "http", .internalClientsNumber = 1, .externalClientsNumber = 2, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};
service::Service service5{.pid = 5, .endpoint = "dynatrace.com/endpoint/4", .domain = "dynatrace.com", .scheme = "https", .internalClientsNumber = 1, .externalClientsNumber = 2, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};
Expand Down
12 changes: 7 additions & 5 deletions libservice/headers/service/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ struct ArrayHasher {
std::size_t operator()(const std::array<uint8_t, N>& array) const {
std::size_t hash = 0;
for (auto element : array) {
hash ^= std::hash<int>{}(element) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
// The golden ratio hash is used to mix the bits to reduce collisions in std::unordered_map
hash ^= std::hash<size_t>{}(element) + 0x9e3779b97f4a7c15ULL + (hash << 12) + (hash >> 4);
}
return hash;
}
Expand All @@ -45,14 +46,15 @@ struct Service {
uint32_t internalClientsNumber{0u};
uint32_t externalClientsNumber{0u};

std::unordered_map<uint32_t, std::chrono::time_point<std::chrono::steady_clock>> detectedExternalIPv416Networks;
std::unordered_map<uint32_t, std::chrono::time_point<std::chrono::steady_clock>> detectedExternalIPv424Networks;
std::unordered_map<uint32_t, std::chrono::time_point<std::chrono::steady_clock>> detectedExternalIPv4_16Networks;
std::unordered_map<uint32_t, std::chrono::time_point<std::chrono::steady_clock>> detectedExternalIPv4_24Networks;
std::unordered_map<std::array<uint8_t, ipv6NetworkPrefixBytesLen>, std::chrono::time_point<std::chrono::steady_clock>, ArrayHasher> detectedExternalIPv6Networks;

bool operator==(const Service& other) const {
return pid == other.pid && endpoint == other.endpoint && domain == other.domain && scheme == other.scheme && internalClientsNumber == other.internalClientsNumber &&
externalClientsNumber == other.externalClientsNumber && detectedExternalIPv416Networks == other.detectedExternalIPv416Networks &&
detectedExternalIPv424Networks == other.detectedExternalIPv424Networks && detectedExternalIPv6Networks == other.detectedExternalIPv6Networks;
externalClientsNumber == other.externalClientsNumber &&
detectedExternalIPv4_16Networks == other.detectedExternalIPv4_16Networks &&
detectedExternalIPv4_24Networks == other.detectedExternalIPv4_24Networks && detectedExternalIPv6Networks == other.detectedExternalIPv6Networks;
}
};

Expand Down
48 changes: 18 additions & 30 deletions libservice/src/Aggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ static std::string getEndpoint(const std::string& host, const std::string& url)
return host + url;
}

static bool isIpv4ClientExternal(const IpAddressChecker& ipChecker, const std::variant<in_addr, in6_addr>& clientAddrBinary) {
return ipChecker.isV4AddressExternal(std::get<in_addr>(clientAddrBinary).s_addr);
static bool isIpv4ClientExternal(const IpAddressChecker& ipChecker, const in_addr& clientAddrBinary) {
return ipChecker.isV4AddressExternal(clientAddrBinary.s_addr);
}

static bool isIpv6ClientExternal(const IpAddressChecker& ipChecker, const std::variant<in_addr, in6_addr>& clientAddrBinary) {
return ipChecker.isV6AddressExternal(std::get<in6_addr>(clientAddrBinary));
static bool isIpv6ClientExternal(const IpAddressChecker& ipChecker, const in6_addr& clientAddrBinary) {
return ipChecker.isV6AddressExternal(clientAddrBinary);
}

static bool isClientExternal(const IpAddressChecker& ipChecker, const std::variant<in_addr, in6_addr>& clientAddrBinary, bool isIpv6) {
return isIpv6 ? isIpv6ClientExternal(ipChecker, clientAddrBinary) : isIpv4ClientExternal(ipChecker, clientAddrBinary);
return isIpv6 ? isIpv6ClientExternal(ipChecker, std::get<in6_addr>(clientAddrBinary)) : isIpv4ClientExternal(ipChecker, std::get<in_addr>(clientAddrBinary));
}

static bool enableNetworkCounters;
Expand Down Expand Up @@ -91,26 +91,13 @@ static void incrementServiceClientsNumber(
if (isIpv6) {
std::array<uint8_t, service::ipv6NetworkPrefixBytesLen> networkIPv6{};
std::memcpy(networkIPv6.data(), std::get<in6_addr>(clientAddrBinary).s6_addr, service::ipv6NetworkPrefixBytesLen);

if (auto it = service.detectedExternalIPv6Networks.find(networkIPv6); it != service.detectedExternalIPv6Networks.end()) {
it->second = currentTime;
} else {
service.detectedExternalIPv6Networks[networkIPv6] = currentTime;
}
service.detectedExternalIPv6Networks[networkIPv6] = currentTime;
} else {
uint32_t network24 = (std::get<in_addr>(clientAddrBinary).s_addr & 0xFFFFFF);
if (auto it = service.detectedExternalIPv424Networks.find(network24); it != service.detectedExternalIPv424Networks.end()) {
it->second = currentTime;
} else {
service.detectedExternalIPv424Networks[network24] = currentTime;
}
service.detectedExternalIPv4_24Networks[network24] = currentTime;

uint32_t network16 = (std::get<in_addr>(clientAddrBinary).s_addr & 0xFFFF);
if (auto it = service.detectedExternalIPv416Networks.find(network16); it != service.detectedExternalIPv416Networks.end()) {
it->second = currentTime;
} else {
service.detectedExternalIPv416Networks[network16] = currentTime;
}
service.detectedExternalIPv4_16Networks[network16] = currentTime;
}
} catch (const std::bad_variant_access& e) {
LOG_TRACE("Bad variant access during network counters processing: {} (client address: {})", e.what(), clientAddr);
Expand Down Expand Up @@ -150,8 +137,8 @@ void Aggregator::clear() {
std::lock_guard<std::mutex> lock(servicesMutex);
if (enableNetworkCounters) {
for (auto it = services.begin(); it != services.end();) {
if (it->second.detectedExternalIPv416Networks.empty() &&
it->second.detectedExternalIPv424Networks.empty() &&
if (it->second.detectedExternalIPv4_16Networks.empty() &&
it->second.detectedExternalIPv4_24Networks.empty() &&
it->second.detectedExternalIPv6Networks.empty()) {
it = services.erase(it);
} else {
Expand Down Expand Up @@ -192,25 +179,26 @@ std::vector<std::reference_wrapper<Service>> Aggregator::collectServices() {
return servicesVec;
}
void Aggregator::networkCountersCleaning() {
const auto retentionTime = std::chrono::hours(1);
std::lock_guard<std::mutex> lock(servicesMutex);
for (auto& service : services) {
auto currentTime = getCurrentTime();
for (auto detectedExternalIPv416NetworksIt = service.second.detectedExternalIPv416Networks.begin(); detectedExternalIPv416NetworksIt != service.second.detectedExternalIPv416Networks.end();) {
if (currentTime - detectedExternalIPv416NetworksIt->second >= std::chrono::hours(1)) {
detectedExternalIPv416NetworksIt = service.second.detectedExternalIPv416Networks.erase(detectedExternalIPv416NetworksIt);
for (auto detectedExternalIPv416NetworksIt = service.second.detectedExternalIPv4_16Networks.begin(); detectedExternalIPv416NetworksIt != service.second.detectedExternalIPv4_16Networks.end();) {
if (currentTime - detectedExternalIPv416NetworksIt->second >= retentionTime) {
detectedExternalIPv416NetworksIt = service.second.detectedExternalIPv4_16Networks.erase(detectedExternalIPv416NetworksIt);
} else {
++detectedExternalIPv416NetworksIt;
}
}
for (auto detectedExternalIPv424NetworksIt = service.second.detectedExternalIPv424Networks.begin(); detectedExternalIPv424NetworksIt != service.second.detectedExternalIPv424Networks.end();) {
if (currentTime - detectedExternalIPv424NetworksIt->second >= std::chrono::hours(1)) {
detectedExternalIPv424NetworksIt = service.second.detectedExternalIPv424Networks.erase(detectedExternalIPv424NetworksIt);
for (auto detectedExternalIPv424NetworksIt = service.second.detectedExternalIPv4_24Networks.begin(); detectedExternalIPv424NetworksIt != service.second.detectedExternalIPv4_24Networks.end();) {
if (currentTime - detectedExternalIPv424NetworksIt->second >= retentionTime) {
detectedExternalIPv424NetworksIt = service.second.detectedExternalIPv4_24Networks.erase(detectedExternalIPv424NetworksIt);
} else {
++detectedExternalIPv424NetworksIt;
}
}
for (auto detectedExternalIPv6NetworksIt = service.second.detectedExternalIPv6Networks.begin(); detectedExternalIPv6NetworksIt != service.second.detectedExternalIPv6Networks.end();) {
if (currentTime - detectedExternalIPv6NetworksIt->second >= std::chrono::hours(1)) {
if (currentTime - detectedExternalIPv6NetworksIt->second >= retentionTime) {
detectedExternalIPv6NetworksIt = service.second.detectedExternalIPv6Networks.erase(detectedExternalIPv6NetworksIt);
} else {
++detectedExternalIPv6NetworksIt;
Expand Down
10 changes: 5 additions & 5 deletions libservice/test/AggregatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ using namespace service;
namespace service {
void PrintTo(const Service& service, std::ostream* os) {
*os << "(" << service.pid << ", " << service.endpoint << ", " << service.internalClientsNumber << ", " << service.externalClientsNumber
<< ", " << service.detectedExternalIPv416Networks.size() << ", " << service.detectedExternalIPv424Networks.size() << ", " << service.detectedExternalIPv6Networks.size()
<< ", " << service.detectedExternalIPv4_16Networks.size() << ", " << service.detectedExternalIPv4_24Networks.size() << ", " << service.detectedExternalIPv6Networks.size()
<< ")";
}
} // namespace service
Expand Down Expand Up @@ -249,8 +249,8 @@ TEST_F(ServiceAggregatorTest, aggregateNetworkCounters) {
auto services{aggregator.collectServices()};
EXPECT_EQ(services.size(), 2);

Service expectedService{.pid = 100, .endpoint{"host/url"}, .domain = "host", .scheme = "http", .internalClientsNumber = 0, .externalClientsNumber = 5, .detectedExternalIPv416Networks = detectedExternalIPv416Networks, .detectedExternalIPv424Networks = detectedExternalIPv424Networks, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};
Service expectedService2{.pid = 200, .endpoint{"host/url"}, .domain = "host", .scheme = "https", .internalClientsNumber = 0, .externalClientsNumber = 5, .detectedExternalIPv416Networks = detectedExternalIPv416Networks, .detectedExternalIPv424Networks = detectedExternalIPv424Networks, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};
Service expectedService{.pid = 100, .endpoint{"host/url"}, .domain = "host", .scheme = "http", .internalClientsNumber = 0, .externalClientsNumber = 5, .detectedExternalIPv4_16Networks = detectedExternalIPv416Networks, .detectedExternalIPv4_24Networks = detectedExternalIPv424Networks, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};
Service expectedService2{.pid = 200, .endpoint{"host/url"}, .domain = "host", .scheme = "https", .internalClientsNumber = 0, .externalClientsNumber = 5, .detectedExternalIPv4_16Networks = detectedExternalIPv416Networks, .detectedExternalIPv4_24Networks = detectedExternalIPv424Networks, .detectedExternalIPv6Networks = detectedExternalIPv6Networks};

std::vector<Service> servicesCopy;
std::transform(services.begin(), services.end(), std::back_inserter(servicesCopy), [](const auto& ref) { return ref.get(); });
Expand All @@ -269,8 +269,8 @@ TEST_F(ServiceAggregatorTest, aggregateNetworkCounters) {

for (const auto& service : collectedServices) {
EXPECT_EQ(service.get().externalClientsNumber, 0);
EXPECT_EQ(service.get().detectedExternalIPv416Networks.size(), 2);
EXPECT_EQ(service.get().detectedExternalIPv424Networks.size(), 3);
EXPECT_EQ(service.get().detectedExternalIPv4_16Networks.size(), 2);
EXPECT_EQ(service.get().detectedExternalIPv4_24Networks.size(), 3);
EXPECT_EQ(service.get().detectedExternalIPv6Networks.size(), 2);
}
}
Expand Down

0 comments on commit 5335b25

Please sign in to comment.