ohmu
·
2026-10-15
1#include "netio.h"
2#include "common/debug.h"
3#include "common/netif.h"
4#include "common/strutil.h"
5
6#include <kstat.h>
7
8static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
9 assert(pkc);
10 if (*pkc) {
11 kstat_close(*pkc);
12 }
13}
14
15const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) {
16 [[gnu::cleanup(kstatFreeWrap)]] kstat_ctl_t* kc = kstat_open();
17 if (!kc) {
18 FF_DEBUG("kstat_open() failed");
19 return "kstat_open() failed";
20 }
21
22 const char* defaultRouteIfName = ffNetifGetDefaultRouteV4()->ifName;
23
24 for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) {
25 if (!ffStrEquals(ks->ks_class, "net") || !ffStrEquals(ks->ks_module, "link")) {
26 continue;
27 }
28
29 if (options->namePrefix.length && strncmp(ks->ks_name, options->namePrefix.chars, options->namePrefix.length) != 0) {
30 continue;
31 }
32
33 bool isDefaultRoute = ffStrEquals(ks->ks_name, defaultRouteIfName);
34 if (options->defaultRouteOnly && !isDefaultRoute) {
35 continue;
36 }
37
38 if (kstat_read(kc, ks, nullptr) < 0) {
39 continue;
40 }
41
42 FFNetIOResult* counters = FF_LIST_ADD(FFNetIOResult, *result);
43
44 kstat_named_t* wbytes = (kstat_named_t*) kstat_data_lookup(ks, "obytes64");
45 kstat_named_t* rbytes = (kstat_named_t*) kstat_data_lookup(ks, "rbytes64");
46 kstat_named_t* wpkts = (kstat_named_t*) kstat_data_lookup(ks, "opackets64");
47 kstat_named_t* rpkts = (kstat_named_t*) kstat_data_lookup(ks, "ipackets64");
48 kstat_named_t* werrs = (kstat_named_t*) kstat_data_lookup(ks, "oerrors");
49 kstat_named_t* rerrs = (kstat_named_t*) kstat_data_lookup(ks, "ierrors");
50
51 *counters = (FFNetIOResult) {
52 .name = ffStrbufCreateS(ks->ks_name),
53 .txBytes = wbytes->value.ui64,
54 .rxBytes = rbytes->value.ui64,
55 .txPackets = wpkts->value.ui64,
56 .rxPackets = rpkts->value.ui64,
57 .txErrors = werrs->value.ui64,
58 .rxErrors = rerrs->value.ui64,
59 .txDrops = 0, // unsupported
60 .rxDrops = 0,
61 .defaultRoute = isDefaultRoute,
62 };
63
64 if (options->defaultRouteOnly) {
65 break;
66 }
67 }
68
69 return nullptr;
70}