Use c program as the eBPF kernel program

With proper Clang and LLVM support. The eBPF program can be compiled and
generated from simplified C program. The original c program is
bpf_ingress.c and bpf_egress.c and the corresponding .o file the output
containing the BPF bytecode that need to be loaded into the kernel at
runtime.

Bug: 30950746
Test: run cts -m CtsNetTestCases -t android.net.cts.TrafficStatsTest
Change-Id: Iedff82bf759c979bbe8e698570eabba436b56d80
diff --git a/bpfloader/bpf_ingress.c b/bpfloader/bpf_ingress.c
new file mode 100644
index 0000000..0a5c5b8
--- /dev/null
+++ b/bpfloader/bpf_ingress.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <linux/bpf.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/ip.h>
+#include "bpf_kern.h"
+#include "bpf_shared.h"
+
+ELF_SEC(BPF_PROG_SEC_NAME)
+int bpf_cgroup_ingress(struct __sk_buff* skb) {
+    uint64_t cookie = get_socket_cookie(skb);
+    struct uid_tag* utag = find_map_entry(COOKIE_TAG_MAP, &cookie);
+    uint32_t uid, tag;
+    if (utag) {
+        uid = utag->uid;
+        tag = utag->tag;
+    } else {
+        uid = get_socket_uid(skb);
+        tag = 0;
+    }
+
+    struct stats_key key = {.uid = uid, .tag = tag, .counterSet = 0, .ifaceIndex = skb->ifindex};
+
+    uint32_t* counterSet;
+    counterSet = find_map_entry(UID_COUNTERSET_MAP, &uid);
+    if (counterSet) key.counterSet = *counterSet;
+
+    int ret;
+    if (tag) {
+        struct stats_value* tagValue;
+        tagValue = find_map_entry(TAG_STATS_MAP, &key);
+        if (!tagValue) {
+            struct stats_value newValue = {};
+            write_to_map_entry(TAG_STATS_MAP, &key, &newValue, BPF_NOEXIST);
+            tagValue = find_map_entry(TAG_STATS_MAP, &key);
+        }
+        if (tagValue) {
+            __sync_fetch_and_add(&tagValue->rxPackets, 1);
+            __sync_fetch_and_add(&tagValue->rxBytes, skb->len);
+        }
+    }
+
+    key.tag = 0;
+    struct stats_value* value;
+    value = find_map_entry(UID_STATS_MAP, &key);
+    if (!value) {
+        struct stats_value newValue = {};
+        write_to_map_entry(UID_STATS_MAP, &key, &newValue, BPF_NOEXIST);
+        value = find_map_entry(UID_STATS_MAP, &key);
+    }
+    if (value) {
+        __sync_fetch_and_add(&value->rxPackets, 1);
+        __sync_fetch_and_add(&value->rxBytes, skb->len);
+    }
+    return BPF_PASS;
+}