Add a eBPF map to store iface name and index

Since the kernel bpf program can only get the iface index instead of
iface name, we need a seperate map to store the iface index and name
pair in userspace so the kernel program can know what iface each
received packet is and account against the correct name.

Test: run cts -m TrafficStatsTest
Bug: 30950746
Bug: 73137611
Change-Id: I6638dc4b03db6fd18b6b38b4524ec89e25a55bc0
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index e099845..10d0cf4 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -15,7 +15,6 @@
  */
 
 #define LOG_TAG "TrafficController"
-
 #include <inttypes.h>
 #include <linux/bpf.h>
 #include <linux/if_ether.h>
@@ -45,6 +44,7 @@
 #include "TrafficController.h"
 #include "bpf/BpfUtils.h"
 
+#include "InterfaceController.h"
 #include "NetlinkListener.h"
 #include "qtaguid/qtaguid.h"
 
@@ -159,6 +159,28 @@
         return statusFromErrno(errno, "change tagStatsMap mode failed.");
     }
 
+    ASSIGN_OR_RETURN(mIfaceIndexNameMap,
+                     setUpBPFMap(sizeof(uint32_t), IFNAMSIZ, IFACE_INDEX_NAME_MAP_SIZE,
+                                 IFACE_INDEX_NAME_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_INDEX_NAME_MAP_PATH, AID_ROOT, AID_NET_BW_STATS);
+    if (ret) {
+        return statusFromErrno(errno, "change ifaceIndexNameMap group failed.");
+    }
+    ret = chmod(IFACE_INDEX_NAME_MAP_PATH, S_IRWXU | S_IRGRP | S_IWGRP);
+    if (ret) {
+        return statusFromErrno(errno, "change ifaceIndexNameMap mode failed.");
+    }
+
+    // Fetch the list of currently-existing interfaces. At this point NetlinkHandler is
+    // already running, so it will call addInterface() when any new interface appears.
+    std::map<std::string, uint32_t> ifacePairs;
+    ASSIGN_OR_RETURN(ifacePairs, InterfaceController::getIfaceList());
+    for (const auto& ifacePair:ifacePairs) {
+        addInterface(ifacePair.first.c_str(), ifacePair.second);
+    }
+
     auto result = makeSkDestroyListener();
     if (!isOk(result)) {
         ALOGE("Unable to create SkDestroyListener: %s", toString(result).c_str());
@@ -393,6 +415,25 @@
     return res;
 }
 
+int TrafficController::addInterface(const char* name, uint32_t ifaceIndex) {
+    int res = 0;
+    if (!ebpfSupported) return res;
+
+    char ifaceName[IFNAMSIZ];
+    if (ifaceIndex == 0) {
+        ALOGE("Unknow interface %s(%d)", name, ifaceIndex);
+        return -1;
+    }
+
+    strlcpy(ifaceName, name, sizeof(ifaceName));
+    res = writeToMapEntry(mIfaceIndexNameMap, &ifaceIndex, ifaceName, BPF_ANY);
+    if (res) {
+        res = -errno;
+        ALOGE("Failed to add iface %s(%d): %s", name, ifaceIndex, strerror(errno));
+    }
+    return res;
+}
+
 bool TrafficController::checkBpfStatsEnable() {
     return ebpfSupported;
 }