Skip to content

Commit

Permalink
Merge pull request #30 from dynatrace-oss/loopback_filtering
Browse files Browse the repository at this point in the history
Loopback filtering
  • Loading branch information
pawsten authored Jun 3, 2024
2 parents 4121e6c + 67b590a commit 089db1b
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 45 deletions.
8 changes: 2 additions & 6 deletions conanfile.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[requires]
fmt/8.0.1
spdlog/1.9.2
boost/1.70.0
boost/1.85.0
elfutils/0.180
gtest/1.11.0
gtest/1.13.0

[generators]
cmake
Expand All @@ -20,12 +20,8 @@ boost:without_fiber=True
boost:without_type_erasure=True
boost:without_stacktrace=True
boost:without_chrono=True
boost:without_system=True
boost:without_date_time=True
boost:without_atomic=True
boost:without_container=True
boost:without_coroutine=True
boost:without_filesystem=True
boost:without_log=True
boost:without_math=True
boost:without_random=True
Expand Down
54 changes: 48 additions & 6 deletions libnettracer/src/netstat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
#include "bpf_generic/src/bpf_wrapper.h"
#include "bpf_generic/src/log.h"
#include "proc_tcp.h"
#include <sys/ioctl.h>
#include <iomanip>
#include <iostream>
#include <poll.h>
#include <sys/ioctl.h>
#include <unistd.h>

namespace netstat {
Expand Down Expand Up @@ -91,9 +91,11 @@ void NetStat::map_loop(const bpf_fds& fdsIPv4, const bpf_fds& fdsIPv6) {
unsigned counter = 0;
unsigned factor = exitCtrl.wait_time * INTERVAL_DIVIDER;
printHeader();

while (exitCtrl.running) {
update<ipv4_tuple_t>(fdsIPv4);
update<ipv6_tuple_t>(fdsIPv6);

clean_bpf<ipv4_tuple_t>(fdsIPv4);
clean_bpf<ipv6_tuple_t>(fdsIPv6);

Expand Down Expand Up @@ -226,16 +228,50 @@ void NetStat::flush() {
*os << " " << std::endl;
}

static bool shouldFilter(const uint32_t key) {
constexpr uint32_t loopback = 0x0000007f;
return ((key & loopback) == loopback);
}

static bool shouldFilter(const ipv4_tuple_t key) {
return shouldFilter(key.saddr);
}

static bool isIpv4MappedIpv6(uint64_t addr_l) {
uint64_t mask = 0x00000000ff00;
return (addr_l && mask) == mask;
}

static bool shouldFilter(const ipv6_tuple_t key) {
if (key.saddr_h != 0) {
return false;
}
if (isIpv4MappedIpv6(key.saddr_l)) {
uint32_t ipv4 = static_cast<uint32_t>(key.saddr_l);
return shouldFilter(ipv4);
}
constexpr uint64_t loopback = 0xffffffff00000000;
return ((key.saddr_l & loopback) == key.saddr_l);
}

template<typename IPTYPE>
void NetStat::print() {
std::unique_lock<std::mutex> l(mx);
auto& aggr{connections<IPTYPE>()};
std::stringstream buf;

for (auto it = aggr.begin(); it != aggr.end(); ++it) {

if (filter_loopback && shouldFilter(it->first)) {
continue;
}

buf.str("");
auto wall_now = getCurrentTimeFromSystemClock();
uint64_t pkts_sent = subtract(it->second.pkts_sent, it->second.pkts_sent_prev, 2, incremental);
uint64_t pkts_received = subtract(it->second.pkts_received, it->second.pkts_received_prev, 3, incremental);

*os << std::right
buf << std::right
<< std::setw(12) << duration_cast<seconds>(wall_now.time_since_epoch()).count()
<< it->first
<< std::setw(12) << it->second.pid
Expand All @@ -251,10 +287,11 @@ void NetStat::print() {
if (it->second.state.Established) {
auto end = (it->second.end != system_clock::time_point{}) ? it->second.end : getCurrentTimeFromSystemClock();
auto duration = duration_cast<seconds>(end - it->second.start);
*os << std::setw(16) << duration_cast<seconds>(it->second.start.time_since_epoch()).count() << std::setw(9)
buf << std::setw(16) << duration_cast<seconds>(it->second.start.time_since_epoch()).count() << std::setw(9)
<< duration.count();
}
*os << "\n";
*os << buf.str() << std::endl;
LOG_DEBUG(buf.str());
}
}

Expand All @@ -272,6 +309,11 @@ void NetStat::print_human_readable() {
std::unique_lock<std::mutex> l(mx);
auto& aggr{connections<IPTYPE>()};
for (const auto& it : aggr) {

if (filter_loopback && shouldFilter(it.first)) {
continue;
}

printAddr(*os, it.first, field_width);
*os << std::setw(field_width) << it.second.pid << std::setw(field_width) << it.second.bytes_sent
<< std::setw(field_width) << it.second.bytes_received << std::setw(field_width) << it.second.rtt << "\n";
Expand Down Expand Up @@ -313,8 +355,8 @@ steady_clock::time_point NetStat::getCurrentTimeFromSteadyClock() const {
return steady_clock::now();
}

NetStat::NetStat(ExitCtrl& e, bool deltaMode, bool headerMode, bool nonInteractive)
: exitCtrl(e), incremental(deltaMode), add_header_mode_(headerMode), os(&std::cout) {
NetStat::NetStat(ExitCtrl& e, bool deltaMode, bool headerMode, bool nonInteractive, bool filterLoopback)
: exitCtrl(e), incremental(deltaMode), add_header_mode_(headerMode), os(&std::cout), filter_loopback(filterLoopback) {
interactive = ((isatty(STDIN_FILENO) == 1) && !nonInteractive);
if (interactive) {
int window_width = getWindowWidth();
Expand Down
3 changes: 2 additions & 1 deletion libnettracer/src/netstat.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class NetStat {
std::ostream* os;
int field_width;
bool interactive;
bool filter_loopback;

template <typename IPTYPE>
inline auto& connections(); // no default instantiation
Expand Down Expand Up @@ -88,7 +89,7 @@ class NetStat {
virtual steady_clock::time_point getCurrentTimeFromSteadyClock() const;

public:
explicit NetStat(ExitCtrl& e, bool deltaMode, bool headerMode, bool nonInteractive);
explicit NetStat(ExitCtrl& e, bool deltaMode, bool headerMode, bool nonInteractive, bool filterLoopback = true);
virtual ~NetStat();
void set_kbhit();
void init();
Expand Down
56 changes: 26 additions & 30 deletions libnettracer/src/proc_tcp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,40 +106,36 @@ std::optional<std::pair<ipv6_tuple_t, ConnectionDetails>> parseProcIPv6Connectio
iss >> hex >> remoteAddress[0] >> remoteAddress[1];

if (state == TCP_ESTABLISHED) {
ipv6_tuple_t conn{
localAddress[0],
localAddress[1],
remoteAddress[0],
remoteAddress[1],
localPort,
remotePort,
0
};
ConnectionDetails details{
ipv6_tuple_t conn{
swap_uint32_t(localAddress[0]),
swap_uint32_t(localAddress[1]),
swap_uint32_t(remoteAddress[0]),
swap_uint32_t(remoteAddress[1]),
localPort,
remotePort,
0};
ConnectionDetails details{
0,
ConnectionDirection::Outgoing
};
return {std::make_pair(conn, details)};
}
else if (state == TCP_LISTEN) {
ipv6_tuple_t conn{
remoteAddress[0],
remoteAddress[1],
localAddress[0],
localAddress[1],
remotePort,
localPort,
0
};
ConnectionDetails details{
} else if (state == TCP_LISTEN) {
ipv6_tuple_t conn{
swap_uint32_t(remoteAddress[0]),
swap_uint32_t(remoteAddress[1]),
swap_uint32_t(localAddress[0]),
swap_uint32_t(localAddress[1]),
remotePort,
localPort,
0};
ConnectionDetails details{
0,
ConnectionDirection::Incoming
};
return {std::make_pair(conn, details)};
}
else { // connection is probably closing
return std::nullopt;
}
} else { // connection is probably closing
return std::nullopt;
}
}

namespace {
Expand Down Expand Up @@ -273,10 +269,10 @@ std::pair<iNode, Connection<ipv6_tuple_t>> parseLine(const std::string& line, ui
localIp2[16] = 0;
remoteIp2[16] = 0;
remoteIp2[16] = 0;
localAddress[0] = std::strtoull(localIp1, nullptr, 16);
localAddress[1] = std::strtoull(localIp2, nullptr, 16);
remoteAddress[0] = std::strtoull(remoteIp1, nullptr, 16);
remoteAddress[1] = std::strtoull(remoteIp2, nullptr, 16);
localAddress[0] = swap_uint32_t(std::strtoull(localIp1, nullptr, 16));
localAddress[1] = swap_uint32_t(std::strtoull(localIp2, nullptr, 16));
remoteAddress[0] = swap_uint32_t(std::strtoull(remoteIp1, nullptr, 16));
remoteAddress[1] = swap_uint32_t(std::strtoull(remoteIp2, nullptr, 16));

Connection<ipv6_tuple_t> conn;
conn.ep = ipv6_tuple_t{localAddress[0], localAddress[1], remoteAddress[0], remoteAddress[1], localPort, remotePort, ns};
Expand Down
6 changes: 6 additions & 0 deletions libnettracer/src/tuple_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,9 @@ ipv6_tuple_t eventToTuple(const tcp_ipv6_event_t& evt) {
tup.netns = evt.netns;
return tup;
}

uint64_t swap_uint32_t(uint64_t addrpart) {
uint64_t hpart = static_cast<uint32_t>(addrpart >> 32);
uint64_t lpart = static_cast<uint32_t>(addrpart);
return uint64_t{(hpart) | (lpart << 32)};
}
2 changes: 2 additions & 0 deletions libnettracer/src/tuple_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ std::string ipv4_to_string(uint32_t addr);
std::string to_string(const std::pair<ipv4_tuple_t, ConnectionDirection>& tupleWithDirection);
std::string to_string(const std::pair<ipv6_tuple_t, ConnectionDirection>& tupleWithDirection);

uint64_t swap_uint32_t(uint64_t addrpart);

inline std::string to_string(const ipv4_tuple_t& tuple) {
return to_string(std::make_pair(tuple, ConnectionDirection::Unknown));
}
Expand Down
3 changes: 2 additions & 1 deletion nettracersrv/nettracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ po::variables_map parseOptions(int argc, char* argv[]) {
("time_interval,t", po::value<unsigned>()->default_value(30), "Time interval of printing metrics data")
("incremental,i", "Enable incremental data")
("noninteractive,r", "Hex output")
("with_loopback,f", "With loopback")
("program,p", po::value<std::string>()->default_value("nettracer-bpf.o"), "BPF program path")
("header,s", "Add average header size to traffic")
("map_size,m", po::value<uint32_t>()->default_value(4096), "Number of entries in BPF maps")
Expand Down Expand Up @@ -216,7 +217,7 @@ int main(int argc, char* argv[]) {

bool monitorIPv6 = isIPv6MonitoringPossible(status_fd, mapsWrapper);

netstat::NetStat netst(exitCtrl, vm.count("incremental"), vm.count("header"), vm.count("noninteractive"));
netstat::NetStat netst(exitCtrl, vm.count("incremental"), vm.count("header"), vm.count("noninteractive"), vm.count("with_loopback") == 0);
netst.init();
bpf_events bevents;
bevents.set_kbhit_observer( std::bind(&netstat::NetStat::set_kbhit, &netst));
Expand Down
2 changes: 1 addition & 1 deletion version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=1.1.7
version=1.1.8

0 comments on commit 089db1b

Please sign in to comment.