Use xt_bpf module to record the iface stats
To make interface packet accounting more accurately and persistent, the
xt_bpf module is implemented to record the total packets and bytes
tx/rx through each interface. The netd will load the bpf program and
set up iptable rules for the xt_bpf module at boot time and the
framework service will use them to get per interface networks stats on
supported devices. Add logcat support to bpfloader program.
Test: iface stats show up in maps. Iptable rules show up after boot.
Bug: 72111305
Change-Id: Ib33d2b165b64e130999931302dd67891c35a12e9
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index 10d0cf4..25142ee 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -181,6 +181,20 @@
addInterface(ifacePair.first.c_str(), ifacePair.second);
}
+ ASSIGN_OR_RETURN(mIfaceStatsMap,
+ setUpBPFMap(sizeof(uint32_t), sizeof(struct StatsValue), IFACE_STATS_MAP_SIZE,
+ IFACE_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
+ // Change the file mode of pinned map so both netd and system server can get the map fd
+ // from the path.
+ ret = chown(IFACE_STATS_MAP_PATH, AID_ROOT, AID_NET_BW_STATS);
+ if (ret) {
+ return statusFromErrno(errno, "change ifaceStatsMap group failed.");
+ }
+ ret = chmod(IFACE_STATS_MAP_PATH, S_IRWXU | S_IRGRP);
+ if (ret) {
+ return statusFromErrno(errno, "change ifaceStatsMap mode failed.");
+ }
+
auto result = makeSkDestroyListener();
if (!isOk(result)) {
ALOGE("Unable to create SkDestroyListener: %s", toString(result).c_str());
@@ -223,9 +237,17 @@
if (ret != 0 && errno == ENOENT) {
prog_args.push_back((char*)"-e");
}
+ ret = access(XT_BPF_INGRESS_PROG_PATH, R_OK);
+ if (ret != 0 && errno == ENOENT) {
+ prog_args.push_back((char*)"-p");
+ }
+ ret = access(XT_BPF_EGRESS_PROG_PATH, R_OK);
+ if (ret != 0 && errno == ENOENT) {
+ prog_args.push_back((char*)"-m");
+ }
if (prog_args.size() == 1) {
- // both program are loaded already.
+ // all program are loaded already.
return netdutils::status::ok;
}