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