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/bpfloader/bpf_kern.h b/bpfloader/bpf_kern.h
index ee818f8..2a2ef8c 100644
--- a/bpfloader/bpf_kern.h
+++ b/bpfloader/bpf_kern.h
@@ -16,6 +16,7 @@
 
 #include <linux/bpf.h>
 #include <stdint.h>
+#include "bpf_shared.h"
 
 #define ELF_SEC(NAME) __attribute__((section(NAME), used))
 
@@ -50,3 +51,27 @@
 
 #define BPF_PASS 1
 #define BPF_DROP 0
+#define BPF_EGRESS 0
+#define BPF_INGRESS 1
+
+static __always_inline int xt_bpf_count(struct __sk_buff* skb, int type) {
+    uint32_t key = skb->ifindex;
+    struct stats_value* value;
+
+    value = find_map_entry(IFACE_STATS_MAP, &key);
+    if (!value) {
+        struct stats_value newValue = {};
+        write_to_map_entry(IFACE_STATS_MAP, &key, &newValue, BPF_NOEXIST);
+        value = find_map_entry(IFACE_STATS_MAP, &key);
+    }
+    if (value) {
+        if (type == BPF_EGRESS) {
+            __sync_fetch_and_add(&value->txPackets, 1);
+            __sync_fetch_and_add(&value->txBytes, skb->len);
+        } else if (type == BPF_INGRESS) {
+            __sync_fetch_and_add(&value->rxPackets, 1);
+            __sync_fetch_and_add(&value->rxBytes, skb->len);
+        }
+    }
+    return BPF_PASS;
+}