Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loopback filtering #30

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading