Skip to content

Commit f4bbb34

Browse files
authored
Instruct Collector to not aggregate some subnets (#1739)
ROX_NON_AGGREGATED_NETWORKS can list subnets that should not be aggregated. This is very similar to private network subnets.
1 parent 88d9628 commit f4bbb34

File tree

7 files changed

+76
-14
lines changed

7 files changed

+76
-14
lines changed

collector/lib/CollectorConfig.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ BoolEnvVar network_drop_ignored("ROX_NETWORK_DROP_IGNORED", true);
2828
// The default value contains link-local addresses for IPv4 (RFC3927) and IPv6 (RFC2462)
2929
StringListEnvVar ignored_networks("ROX_IGNORE_NETWORKS", std::vector<std::string>({"169.254.0.0/16", "fe80::/10"}));
3030

31+
// Connection endpoints matching a network prefix listed here will never be aggregated.
32+
StringListEnvVar non_aggregated_networks("ROX_NON_AGGREGATED_NETWORKS", std::vector<std::string>());
33+
3134
// If true, set curl to be verbose, adding further logging that might be useful for debugging.
3235
BoolEnvVar set_curl_verbose("ROX_COLLECTOR_SET_CURL_VERBOSE", false);
3336

@@ -172,20 +175,33 @@ void CollectorConfig::InitCollectorConfig(CollectorArgs* args) {
172175
ignored_l4proto_port_pairs_ = kIgnoredL4ProtoPortPairs;
173176
}
174177

175-
std::for_each(ignored_networks.value().begin(), ignored_networks.value().end(),
176-
[&ignored_networks = this->ignored_networks_](const std::string& str) {
177-
if (str.empty())
178-
return;
178+
for (const std::string& str : ignored_networks.value()) {
179+
if (str.empty())
180+
continue;
181+
182+
std::optional<IPNet> net = IPNet::parse(str);
183+
184+
if (net) {
185+
CLOG(INFO) << "Ignore network : " << *net;
186+
ignored_networks_.emplace_back(std::move(*net));
187+
} else {
188+
CLOG(ERROR) << "Invalid network in ROX_IGNORE_NETWORKS : " << str;
189+
}
190+
}
191+
192+
for (const std::string& str : non_aggregated_networks.value()) {
193+
if (str.empty())
194+
continue;
179195

180-
std::optional<IPNet> net = IPNet::parse(str);
196+
std::optional<IPNet> net = IPNet::parse(str);
181197

182-
if (net) {
183-
CLOG(INFO) << "Ignore network : " << *net;
184-
ignored_networks.emplace_back(std::move(*net));
185-
} else {
186-
CLOG(ERROR) << "Invalid network in ROX_IGNORE_NETWORKS : " << str;
187-
}
188-
});
198+
if (net) {
199+
CLOG(INFO) << "Non-aggregated network : " << *net;
200+
non_aggregated_networks_.emplace_back(std::move(*net));
201+
} else {
202+
CLOG(ERROR) << "Invalid network in ROX_NON_AGGREGATED_NETWORKS : " << str;
203+
}
204+
}
189205

190206
if (set_curl_verbose) {
191207
curl_verbose_ = true;

collector/lib/CollectorConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class CollectorConfig {
6565
bool DisableNetworkFlows() const { return disable_network_flows_; }
6666
const UnorderedSet<L4ProtoPortPair>& IgnoredL4ProtoPortPairs() const { return ignored_l4proto_port_pairs_; }
6767
const std::vector<IPNet>& IgnoredNetworks() const { return ignored_networks_; }
68+
const std::vector<IPNet>& NonAggregatedNetworks() const { return non_aggregated_networks_; }
6869
bool CurlVerbose() const { return curl_verbose_; }
6970
bool EnableAfterglow() const { return enable_afterglow_; }
7071
bool IsCoreDumpEnabled() const;
@@ -100,6 +101,7 @@ class CollectorConfig {
100101
bool scrape_listen_endpoints_ = false;
101102
UnorderedSet<L4ProtoPortPair> ignored_l4proto_port_pairs_;
102103
std::vector<IPNet> ignored_networks_;
104+
std::vector<IPNet> non_aggregated_networks_;
103105
bool curl_verbose_ = false;
104106

105107
HostConfig host_config_;

collector/lib/CollectorService.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ void CollectorService::RunForever() {
8888
UnorderedSet<L4ProtoPortPair> ignored_l4proto_port_pairs(config_.IgnoredL4ProtoPortPairs());
8989
conn_tracker->UpdateIgnoredL4ProtoPortPairs(std::move(ignored_l4proto_port_pairs));
9090
conn_tracker->UpdateIgnoredNetworks(config_.IgnoredNetworks());
91+
conn_tracker->UpdateNonAggregatedNetworks(config_.NonAggregatedNetworks());
9192
conn_tracker->EnableExternalIPs(config_.EnableExternalIPs());
9293

9394
auto network_connection_info_service_comm = std::make_shared<NetworkConnectionInfoServiceComm>(config_.Hostname(), config_.grpc_channel);

collector/lib/ConnTracker.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,18 @@ IPNet ConnectionTracker::NormalizeAddressNoLock(const Address& address) const {
7777
}
7878

7979
bool private_addr = !address.IsPublic();
80+
bool do_not_aggregate_addr = !non_aggregated_networks_.Find(address).IsNull();
81+
82+
// We want to keep private addresses and explicitely requested ones.
83+
bool keep_addr = private_addr || do_not_aggregate_addr;
84+
8085
const bool* known_private_networks_exists = Lookup(known_private_networks_exists_, address.family());
81-
if (private_addr && (known_private_networks_exists && !*known_private_networks_exists)) {
86+
if (keep_addr && (known_private_networks_exists && !*known_private_networks_exists)) {
8287
return IPNet(address, 0, true);
8388
}
8489

8590
const auto& network = known_ip_networks_.Find(address);
86-
if (private_addr || Contains(known_public_ips_, address)) {
91+
if (keep_addr || Contains(known_public_ips_, address)) {
8792
return IPNet(address, network.bits(), true);
8893
}
8994

@@ -330,6 +335,12 @@ void ConnectionTracker::UpdateIgnoredNetworks(const std::vector<IPNet>& network_
330335
}
331336
}
332337

338+
void ConnectionTracker::UpdateNonAggregatedNetworks(const std::vector<IPNet>& network_list) {
339+
WITH_LOCK(mutex_) {
340+
non_aggregated_networks_ = NRadixTree(network_list);
341+
}
342+
}
343+
333344
// Increment the stat counter matching the connection's characteristics
334345
inline void ConnectionTracker::IncrementConnectionStats(Connection conn, ConnectionTracker::Stats& stats) const {
335346
auto& direction = conn.is_server() ? stats.inbound : stats.outbound;

collector/lib/ConnTracker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class ConnectionTracker {
130130
void EnableExternalIPs(bool enable) { enable_external_ips_ = enable; }
131131
void UpdateIgnoredL4ProtoPortPairs(UnorderedSet<L4ProtoPortPair>&& ignored_l4proto_port_pairs);
132132
void UpdateIgnoredNetworks(const std::vector<IPNet>& network_list);
133+
void UpdateNonAggregatedNetworks(const std::vector<IPNet>& network_list);
133134

134135
// Emplace a connection into the state ConnMap, or update its timestamp if the supplied timestamp is more recent
135136
// than the stored one.
@@ -200,6 +201,7 @@ class ConnectionTracker {
200201
UnorderedMap<Address::Family, bool> known_private_networks_exists_;
201202
UnorderedSet<L4ProtoPortPair> ignored_l4proto_port_pairs_;
202203
NRadixTree ignored_networks_;
204+
NRadixTree non_aggregated_networks_;
203205

204206
Stats inserted_connections_counters_ = {};
205207
};

collector/test/ConnTrackerTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,30 @@ TEST(ConnTrackerTest, TestUpdateIgnoredNetworks) {
171171
EXPECT_TRUE(tracker.FetchConnState().empty());
172172
}
173173

174+
TEST(ConnTrackerTest, TestUpdateNonAggregatedNetworks) {
175+
Endpoint a(Address(192, 168, 1, 10), 9999);
176+
Endpoint b(Address(245, 1, 1, 1), 80);
177+
178+
Connection conn1("xyz", a, b, L4Proto::TCP, false);
179+
180+
int64_t time_micros = 1000;
181+
182+
Connection conn_aggregated("xyz", Endpoint(IPNet(Address(), 0, true), 0), Endpoint(IPNet(Address(255, 255, 255, 255), 0), 80), L4Proto::TCP, false);
183+
Connection conn_detailed("xyz", Endpoint(IPNet(Address(), 0, true), 0), Endpoint(IPNet(Address(245, 1, 1, 1), 0, true), 80), L4Proto::TCP, false);
184+
185+
ConnectionTracker tracker;
186+
187+
tracker.Update({conn1}, {}, time_micros);
188+
189+
auto state = tracker.FetchConnState(true);
190+
EXPECT_THAT(state, UnorderedElementsAre(std::make_pair(conn_aggregated, ConnStatus(time_micros, true))));
191+
192+
tracker.UpdateNonAggregatedNetworks({IPNet(Address(240, 0, 0, 0), 4)});
193+
194+
state = tracker.FetchConnState(true);
195+
EXPECT_THAT(state, UnorderedElementsAre(std::make_pair(conn_detailed, ConnStatus(time_micros, true))));
196+
}
197+
174198
TEST(ConnTrackerTest, TestUpdateNormalized) {
175199
Endpoint a(Address(192, 168, 0, 1), 80);
176200
Endpoint b(Address(192, 168, 1, 10), 9999);

docs/references.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ port pairs (at the moment only `udp/9`). The default is true.
2121
Any connection with a remote peer matching this list will not be reported.
2222
The default is `169.254.0.0/16,fe80::/10`
2323

24+
* `ROX_NON_AGGREGATED_NETWORKS`: A coma-separated list of network prefixes
25+
indicating endpoints which should never be considered for aggregation.
26+
This option can be useful when the CIDR blocks used for services or PODs are
27+
not standard private subnets, as it will prevent Collector from handling them
28+
as public IPs.
29+
2430
* `ROX_NETWORK_GRAPH_PORTS`: Controls whether to retrieve TCP listening
2531
sockets, while reading connection information from procfs. The default is true.
2632

0 commit comments

Comments
 (0)