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;
     }