blob: 0268f9b0cfe6b5e6de0d11ed90771e2a15a7287f [file] [log] [blame]
Chenbo Fengf2759682017-10-10 17:31:57 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Chenbo Fengc10a8a42017-12-15 13:56:33 -080017#define LOG_TAG "TrafficController"
Chenbo Feng33cc1032017-10-23 15:16:37 -070018#include <inttypes.h>
Chenbo Fengf2759682017-10-10 17:31:57 -070019#include <linux/bpf.h>
20#include <linux/if_ether.h>
21#include <linux/in.h>
22#include <linux/inet_diag.h>
Chenbo Feng116d0552017-12-04 17:25:19 -080023#include <linux/netlink.h>
24#include <linux/sock_diag.h>
Chenbo Fengf2759682017-10-10 17:31:57 -070025#include <linux/unistd.h>
Chenbo Fengc10a8a42017-12-15 13:56:33 -080026#include <net/if.h>
Chenbo Fengf2759682017-10-10 17:31:57 -070027#include <stdlib.h>
28#include <string.h>
29#include <sys/socket.h>
Chenbo Fengc10a8a42017-12-15 13:56:33 -080030#include <sys/stat.h>
Chenbo Feng05393d82018-01-09 15:18:43 -080031#include <sys/types.h>
Chenbo Feng33cc1032017-10-23 15:16:37 -070032#include <sys/utsname.h>
Chenbo Feng05393d82018-01-09 15:18:43 -080033#include <sys/wait.h>
Chenbo Feng64af7042018-03-21 10:29:18 -070034#include <mutex>
Chenbo Fengc10a8a42017-12-15 13:56:33 -080035#include <unordered_set>
36#include <vector>
37
38#include <android-base/stringprintf.h>
Chenbo Feng132065d2018-03-26 10:53:33 -070039#include <android-base/strings.h>
Chenbo Fengc10a8a42017-12-15 13:56:33 -080040#include <android-base/unique_fd.h>
Chenbo Feng05393d82018-01-09 15:18:43 -080041#include <logwrap/logwrap.h>
Chenbo Fengc10a8a42017-12-15 13:56:33 -080042#include <netdutils/StatusOr.h>
Chenbo Fengf2759682017-10-10 17:31:57 -070043
Chenbo Feng116d0552017-12-04 17:25:19 -080044#include <netdutils/Misc.h>
45#include <netdutils/Syscalls.h>
Chenbo Fengf2759682017-10-10 17:31:57 -070046#include "TrafficController.h"
Chenbo Feng2c67f262018-04-26 10:37:55 -070047#include "bpf/BpfMap.h"
Chenbo Feng64af7042018-03-21 10:29:18 -070048#include "bpf/bpf_shared.h"
Chenbo Feng116d0552017-12-04 17:25:19 -080049
Chenbo Feng132065d2018-03-26 10:53:33 -070050#include "DumpWriter.h"
Chenbo Feng64af7042018-03-21 10:29:18 -070051#include "FirewallController.h"
Chenbo Feng8cc480c2018-02-28 22:57:21 -080052#include "InterfaceController.h"
Chenbo Feng116d0552017-12-04 17:25:19 -080053#include "NetlinkListener.h"
Chenbo Feng33cc1032017-10-23 15:16:37 -070054#include "qtaguid/qtaguid.h"
Chenbo Fengf2759682017-10-10 17:31:57 -070055
Chenbo Fengc10a8a42017-12-15 13:56:33 -080056using namespace android::bpf;
Chenbo Fengf2759682017-10-10 17:31:57 -070057
58namespace android {
59namespace net {
60
Chenbo Fengc10a8a42017-12-15 13:56:33 -080061using base::StringPrintf;
62using base::unique_fd;
Chenbo Feng132065d2018-03-26 10:53:33 -070063using base::Join;
Chenbo Feng116d0552017-12-04 17:25:19 -080064using netdutils::extract;
65using netdutils::Slice;
66using netdutils::sSyscalls;
Chenbo Fengc10a8a42017-12-15 13:56:33 -080067using netdutils::Status;
68using netdutils::statusFromErrno;
69using netdutils::StatusOr;
Chenbo Feng116d0552017-12-04 17:25:19 -080070using netdutils::status::ok;
Chenbo Fengc10a8a42017-12-15 13:56:33 -080071
Chenbo Feng116d0552017-12-04 17:25:19 -080072constexpr int kSockDiagMsgType = SOCK_DIAG_BY_FAMILY;
73constexpr int kSockDiagDoneMsgType = NLMSG_DONE;
74
75StatusOr<std::unique_ptr<NetlinkListenerInterface>> makeSkDestroyListener() {
76 const auto& sys = sSyscalls.get();
77 ASSIGN_OR_RETURN(auto event, sys.eventfd(0, EFD_CLOEXEC));
78 const int domain = AF_NETLINK;
79 const int type = SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
80 const int protocol = NETLINK_INET_DIAG;
81 ASSIGN_OR_RETURN(auto sock, sys.socket(domain, type, protocol));
82
Lorenzo Colitti75057f02018-07-26 17:20:57 +090083 // TODO: if too many sockets are closed too quickly, we can overflow the socket buffer, and
84 // some entries in mCookieTagMap will not be freed. In order to fix this we would need to
85 // periodically dump all sockets and remove the tag entries for sockets that have been closed.
86 // For now, set a large-enough buffer that we can close hundreds of sockets without getting
87 // ENOBUFS and leaking mCookieTagMap entries.
88 int rcvbuf = 512 * 1024;
89 auto ret = sys.setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
90 if (!ret.ok()) {
91 ALOGW("Failed to set SkDestroyListener buffer size to %d: %s", rcvbuf, ret.msg().c_str());
92 }
93
Chenbo Feng116d0552017-12-04 17:25:19 -080094 sockaddr_nl addr = {
95 .nl_family = AF_NETLINK,
96 .nl_groups = 1 << (SKNLGRP_INET_TCP_DESTROY - 1) | 1 << (SKNLGRP_INET_UDP_DESTROY - 1) |
97 1 << (SKNLGRP_INET6_TCP_DESTROY - 1) | 1 << (SKNLGRP_INET6_UDP_DESTROY - 1)};
98 RETURN_IF_NOT_OK(sys.bind(sock, addr));
99
100 const sockaddr_nl kernel = {.nl_family = AF_NETLINK};
101 RETURN_IF_NOT_OK(sys.connect(sock, kernel));
102
103 std::unique_ptr<NetlinkListenerInterface> listener =
104 std::make_unique<NetlinkListener>(std::move(event), std::move(sock));
105
106 return listener;
107}
108
Chenbo Feng64af7042018-03-21 10:29:18 -0700109Status changeOwnerAndMode(const char* path, gid_t group, const char* debugName, bool netdOnly) {
110 int ret = chown(path, AID_ROOT, group);
111 if (ret != 0) return statusFromErrno(errno, StringPrintf("change %s group failed", debugName));
112
113 if (netdOnly) {
114 ret = chmod(path, S_IRWXU);
115 } else {
116 // Allow both netd and system server to obtain map fd from the path.
117 // chmod doesn't grant permission to all processes in that group to
118 // read/write the bpf map. They still need correct sepolicy to
119 // read/write the map.
120 ret = chmod(path, S_IRWXU | S_IRGRP);
121 }
122 if (ret != 0) return statusFromErrno(errno, StringPrintf("change %s mode failed", debugName));
123 return netdutils::status::ok;
124}
125
126TrafficController::TrafficController() {
Chenbo Fengf43bf812017-12-15 18:27:22 -0800127 ebpfSupported = hasBpfSupport();
Chenbo Feng64af7042018-03-21 10:29:18 -0700128}
129
Chenbo Feng2c67f262018-04-26 10:37:55 -0700130Status initialOwnerMap(BpfMap<uint32_t, uint8_t>& map) {
131 // Check and delete all the entries from the map in case it is a runtime
132 // restart
133 const auto deleteAllEntries = [](const uint32_t& key, BpfMap<uint32_t, uint8_t>& map) {
134 Status res = map.deleteValue(key);
135 if (!isOk(res) && (res.code() == ENOENT)) {
136 ALOGE("Failed to delete data(uid=%u): %s\n", key, strerror(res.code()));
137 }
138 return netdutils::status::ok;
139 };
140 // It is safe to delete from this map because nothing will concurrently iterate over it:
141 // - Nothing in netd will iterate over it because we're holding mOwnerMatchMutex.
142 // - Nothing outside netd iterates over it.
143 map.iterate(deleteAllEntries);
Chenbo Feng64af7042018-03-21 10:29:18 -0700144 uint32_t mapSettingKey = UID_MAP_ENABLED;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700145 uint8_t defaultMapState = 0;
146 return map.writeValue(mapSettingKey, defaultMapState, BPF_NOEXIST);
Chenbo Feng64af7042018-03-21 10:29:18 -0700147}
148
149Status TrafficController::initMaps() {
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700150 std::lock_guard<std::mutex> ownerMapGuard(mOwnerMatchMutex);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700151 RETURN_IF_NOT_OK(
152 mCookieTagMap.getOrCreate(COOKIE_UID_MAP_SIZE, COOKIE_TAG_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700153
154 RETURN_IF_NOT_OK(changeOwnerAndMode(COOKIE_TAG_MAP_PATH, AID_NET_BW_ACCT, "CookieTagMap",
155 false));
156
Chenbo Feng2c67f262018-04-26 10:37:55 -0700157 RETURN_IF_NOT_OK(mUidCounterSetMap.getOrCreate(UID_COUNTERSET_MAP_SIZE, UID_COUNTERSET_MAP_PATH,
158 BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700159 RETURN_IF_NOT_OK(changeOwnerAndMode(UID_COUNTERSET_MAP_PATH, AID_NET_BW_ACCT,
160 "UidCounterSetMap", false));
161
Chenbo Feng2c67f262018-04-26 10:37:55 -0700162 RETURN_IF_NOT_OK(
Chenbo Feng58a09b52018-05-11 19:15:15 -0700163 mAppUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, APP_UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
164 RETURN_IF_NOT_OK(
165 changeOwnerAndMode(APP_UID_STATS_MAP_PATH, AID_NET_BW_STATS, "AppUidStatsMap", false));
166
167 RETURN_IF_NOT_OK(
Chenbo Feng2c67f262018-04-26 10:37:55 -0700168 mUidStatsMap.getOrCreate(UID_STATS_MAP_SIZE, UID_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700169 RETURN_IF_NOT_OK(changeOwnerAndMode(UID_STATS_MAP_PATH, AID_NET_BW_STATS, "UidStatsMap",
170 false));
171
Chenbo Feng2c67f262018-04-26 10:37:55 -0700172 RETURN_IF_NOT_OK(
173 mTagStatsMap.getOrCreate(TAG_STATS_MAP_SIZE, TAG_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700174 RETURN_IF_NOT_OK(changeOwnerAndMode(TAG_STATS_MAP_PATH, AID_NET_BW_STATS, "TagStatsMap",
175 false));
176
Chenbo Feng2c67f262018-04-26 10:37:55 -0700177 RETURN_IF_NOT_OK(mIfaceIndexNameMap.getOrCreate(IFACE_INDEX_NAME_MAP_SIZE,
178 IFACE_INDEX_NAME_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700179 RETURN_IF_NOT_OK(changeOwnerAndMode(IFACE_INDEX_NAME_MAP_PATH, AID_NET_BW_STATS,
180 "IfaceIndexNameMap", false));
181
Chenbo Feng2c67f262018-04-26 10:37:55 -0700182 RETURN_IF_NOT_OK(
183 mDozableUidMap.getOrCreate(UID_OWNER_MAP_SIZE, DOZABLE_UID_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700184 RETURN_IF_NOT_OK(changeOwnerAndMode(DOZABLE_UID_MAP_PATH, AID_ROOT, "DozableUidMap", true));
Chenbo Feng2c67f262018-04-26 10:37:55 -0700185 RETURN_IF_NOT_OK(initialOwnerMap(mDozableUidMap));
Chenbo Feng64af7042018-03-21 10:29:18 -0700186
Chenbo Feng2c67f262018-04-26 10:37:55 -0700187 RETURN_IF_NOT_OK(
188 mStandbyUidMap.getOrCreate(UID_OWNER_MAP_SIZE, STANDBY_UID_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700189 RETURN_IF_NOT_OK(changeOwnerAndMode(STANDBY_UID_MAP_PATH, AID_ROOT, "StandbyUidMap", true));
Chenbo Feng2c67f262018-04-26 10:37:55 -0700190 RETURN_IF_NOT_OK(initialOwnerMap(mStandbyUidMap));
Chenbo Feng64af7042018-03-21 10:29:18 -0700191
Chenbo Feng2c67f262018-04-26 10:37:55 -0700192 RETURN_IF_NOT_OK(mPowerSaveUidMap.getOrCreate(UID_OWNER_MAP_SIZE, POWERSAVE_UID_MAP_PATH,
193 BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700194 RETURN_IF_NOT_OK(changeOwnerAndMode(POWERSAVE_UID_MAP_PATH, AID_ROOT, "PowerSaveUidMap", true));
Chenbo Feng2c67f262018-04-26 10:37:55 -0700195 RETURN_IF_NOT_OK(initialOwnerMap(mPowerSaveUidMap));
Chenbo Feng64af7042018-03-21 10:29:18 -0700196
Chenbo Feng2c67f262018-04-26 10:37:55 -0700197 RETURN_IF_NOT_OK(
198 mIfaceStatsMap.getOrCreate(IFACE_STATS_MAP_SIZE, IFACE_STATS_MAP_PATH, BPF_MAP_TYPE_HASH));
Chenbo Feng64af7042018-03-21 10:29:18 -0700199 RETURN_IF_NOT_OK(changeOwnerAndMode(IFACE_STATS_MAP_PATH, AID_NET_BW_STATS, "IfaceStatsMap",
200 false));
201 return netdutils::status::ok;
202}
203
204Status TrafficController::start() {
205
Chenbo Fengf43bf812017-12-15 18:27:22 -0800206 if (!ebpfSupported) {
Chenbo Fengc10a8a42017-12-15 13:56:33 -0800207 return netdutils::status::ok;
Chenbo Fengf2759682017-10-10 17:31:57 -0700208 }
209
210 /* When netd restart from a crash without total system reboot, the program
211 * is still attached to the cgroup, detach it so the program can be freed
212 * and we can load and attach new program into the target cgroup.
213 *
214 * TODO: Scrape existing socket when run-time restart and clean up the map
215 * if the socket no longer exist
216 */
217
Chenbo Feng64af7042018-03-21 10:29:18 -0700218 RETURN_IF_NOT_OK(initMaps());
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800219
220 // Fetch the list of currently-existing interfaces. At this point NetlinkHandler is
221 // already running, so it will call addInterface() when any new interface appears.
222 std::map<std::string, uint32_t> ifacePairs;
223 ASSIGN_OR_RETURN(ifacePairs, InterfaceController::getIfaceList());
224 for (const auto& ifacePair:ifacePairs) {
225 addInterface(ifacePair.first.c_str(), ifacePair.second);
226 }
227
Chenbo Fengd425ec82018-03-13 21:30:49 -0700228
Chenbo Feng116d0552017-12-04 17:25:19 -0800229 auto result = makeSkDestroyListener();
230 if (!isOk(result)) {
231 ALOGE("Unable to create SkDestroyListener: %s", toString(result).c_str());
232 } else {
233 mSkDestroyListener = std::move(result.value());
234 }
235 // Rx handler extracts nfgenmsg looks up and invokes registered dispatch function.
236 const auto rxHandler = [this](const nlmsghdr&, const Slice msg) {
237 inet_diag_msg diagmsg = {};
238 if (extract(msg, diagmsg) < sizeof(inet_diag_msg)) {
239 ALOGE("unrecognized netlink message: %s", toString(msg).c_str());
240 return;
241 }
242 uint64_t sock_cookie = static_cast<uint64_t>(diagmsg.id.idiag_cookie[0]) |
243 (static_cast<uint64_t>(diagmsg.id.idiag_cookie[1]) << 32);
244
Chenbo Feng2c67f262018-04-26 10:37:55 -0700245 mCookieTagMap.deleteValue(sock_cookie);
Chenbo Feng116d0552017-12-04 17:25:19 -0800246 };
247 expectOk(mSkDestroyListener->subscribe(kSockDiagMsgType, rxHandler));
248
249 // In case multiple netlink message comes in as a stream, we need to handle the rxDone message
250 // properly.
251 const auto rxDoneHandler = [](const nlmsghdr&, const Slice msg) {
252 // Ignore NLMSG_DONE messages
253 inet_diag_msg diagmsg = {};
254 extract(msg, diagmsg);
255 };
256 expectOk(mSkDestroyListener->subscribe(kSockDiagDoneMsgType, rxDoneHandler));
257
Chenbo Feng05393d82018-01-09 15:18:43 -0800258 int* status = nullptr;
259
260 std::vector<const char*> prog_args{
261 "/system/bin/bpfloader",
262 };
Chenbo Feng64af7042018-03-21 10:29:18 -0700263 int ret = access(BPF_INGRESS_PROG_PATH, R_OK);
Chenbo Feng05393d82018-01-09 15:18:43 -0800264 if (ret != 0 && errno == ENOENT) {
265 prog_args.push_back((char*)"-i");
266 }
267 ret = access(BPF_EGRESS_PROG_PATH, R_OK);
268 if (ret != 0 && errno == ENOENT) {
269 prog_args.push_back((char*)"-e");
270 }
Chenbo Fengd425ec82018-03-13 21:30:49 -0700271 ret = access(XT_BPF_INGRESS_PROG_PATH, R_OK);
272 if (ret != 0 && errno == ENOENT) {
273 prog_args.push_back((char*)"-p");
274 }
275 ret = access(XT_BPF_EGRESS_PROG_PATH, R_OK);
276 if (ret != 0 && errno == ENOENT) {
277 prog_args.push_back((char*)"-m");
278 }
Chenbo Feng05393d82018-01-09 15:18:43 -0800279
280 if (prog_args.size() == 1) {
Chenbo Fengd425ec82018-03-13 21:30:49 -0700281 // all program are loaded already.
Chenbo Feng05393d82018-01-09 15:18:43 -0800282 return netdutils::status::ok;
283 }
284
285 prog_args.push_back(nullptr);
286 ret = android_fork_execvp(prog_args.size(), (char**)prog_args.data(), status, false, true);
287 if (ret) {
288 ret = errno;
289 ALOGE("failed to execute %s: %s", prog_args[0], strerror(errno));
290 return statusFromErrno(ret, "run bpf loader failed");
291 }
292 return netdutils::status::ok;
Chenbo Fengf2759682017-10-10 17:31:57 -0700293}
294
Chenbo Fengf2759682017-10-10 17:31:57 -0700295int TrafficController::tagSocket(int sockFd, uint32_t tag, uid_t uid) {
Chenbo Feng883abce2018-04-11 18:27:19 -0700296 if (!ebpfSupported) {
297 if (legacy_tagSocket(sockFd, tag, uid)) return -errno;
298 return 0;
299 }
Chenbo Feng33cc1032017-10-23 15:16:37 -0700300
Chenbo Fengf2759682017-10-10 17:31:57 -0700301 uint64_t sock_cookie = getSocketCookie(sockFd);
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700302 if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
Chenbo Fengf2759682017-10-10 17:31:57 -0700303 UidTag newKey = {.uid = (uint32_t)uid, .tag = tag};
304
305 // Update the tag information of a socket to the cookieUidMap. Use BPF_ANY
306 // flag so it will insert a new entry to the map if that value doesn't exist
307 // yet. And update the tag if there is already a tag stored. Since the eBPF
308 // program in kernel only read this map, and is protected by rcu read lock. It
309 // should be fine to cocurrently update the map while eBPF program is running.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700310 Status res = mCookieTagMap.writeValue(sock_cookie, newKey, BPF_ANY);
311 if (!isOk(res)) {
312 ALOGE("Failed to tag the socket: %s, fd: %d", strerror(res.code()),
313 mCookieTagMap.getMap().get());
Chenbo Fengf2759682017-10-10 17:31:57 -0700314 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700315 return -res.code();
Chenbo Fengf2759682017-10-10 17:31:57 -0700316}
317
318int TrafficController::untagSocket(int sockFd) {
Chenbo Feng883abce2018-04-11 18:27:19 -0700319 if (!ebpfSupported) {
320 if (legacy_untagSocket(sockFd)) return -errno;
321 return 0;
322 }
Chenbo Fengf2759682017-10-10 17:31:57 -0700323 uint64_t sock_cookie = getSocketCookie(sockFd);
324
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700325 if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700326 Status res = mCookieTagMap.deleteValue(sock_cookie);
327 if (!isOk(res)) {
328 ALOGE("Failed to untag socket: %s\n", strerror(res.code()));
Chenbo Fengf2759682017-10-10 17:31:57 -0700329 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700330 return -res.code();
Chenbo Fengf2759682017-10-10 17:31:57 -0700331}
332
333int TrafficController::setCounterSet(int counterSetNum, uid_t uid) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700334 if (counterSetNum < 0 || counterSetNum >= OVERFLOW_COUNTERSET) return -EINVAL;
335 Status res;
Chenbo Feng883abce2018-04-11 18:27:19 -0700336 if (!ebpfSupported) {
337 if (legacy_setCounterSet(counterSetNum, uid)) return -errno;
338 return 0;
339 }
Chenbo Fengc10a8a42017-12-15 13:56:33 -0800340
341 // The default counter set for all uid is 0, so deleting the current counterset for that uid
342 // will automatically set it to 0.
Chenbo Fengf2759682017-10-10 17:31:57 -0700343 if (counterSetNum == 0) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700344 Status res = mUidCounterSetMap.deleteValue(uid);
345 if (isOk(res) || (!isOk(res) && res.code() == ENOENT)) {
Chenbo Fengf2759682017-10-10 17:31:57 -0700346 return 0;
347 } else {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700348 ALOGE("Failed to delete the counterSet: %s\n", strerror(res.code()));
349 return -res.code();
Chenbo Fengf2759682017-10-10 17:31:57 -0700350 }
351 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700352 uint8_t tmpCounterSetNum = (uint8_t)counterSetNum;
353 res = mUidCounterSetMap.writeValue(uid, tmpCounterSetNum, BPF_ANY);
354 if (!isOk(res)) {
355 ALOGE("Failed to set the counterSet: %s, fd: %d", strerror(res.code()),
356 mUidCounterSetMap.getMap().get());
357 return -res.code();
Chenbo Fengf2759682017-10-10 17:31:57 -0700358 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700359 return 0;
Chenbo Fengf2759682017-10-10 17:31:57 -0700360}
361
362int TrafficController::deleteTagData(uint32_t tag, uid_t uid) {
Chenbo Feng33cc1032017-10-23 15:16:37 -0700363
Chenbo Feng883abce2018-04-11 18:27:19 -0700364 if (!ebpfSupported) {
365 if (legacy_deleteTagData(tag, uid)) return -errno;
366 return 0;
367 }
Chenbo Feng33cc1032017-10-23 15:16:37 -0700368
Chenbo Fengc10a8a42017-12-15 13:56:33 -0800369 // First we go through the cookieTagMap to delete the target uid tag combination. Or delete all
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700370 // the tags related to the uid if the tag is 0.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700371 const auto deleteMatchedCookieEntries = [uid, tag](const uint64_t& key, const UidTag& value,
372 BpfMap<uint64_t, UidTag>& map) {
373 if (value.uid == uid && (value.tag == tag || tag == 0)) {
374 Status res = map.deleteValue(key);
375 if (isOk(res) || (res.code() == ENOENT)) {
376 return netdutils::status::ok;
Chenbo Fengf2759682017-10-10 17:31:57 -0700377 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700378 ALOGE("Failed to delete data(cookie = %" PRIu64 "): %s\n", key, strerror(res.code()));
Chenbo Fengf2759682017-10-10 17:31:57 -0700379 }
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700380 // Move forward to next cookie in the map.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700381 return netdutils::status::ok;
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700382 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700383 mCookieTagMap.iterateWithValue(deleteMatchedCookieEntries);
Chenbo Fengf2759682017-10-10 17:31:57 -0700384 // Now we go through the Tag stats map and delete the data entry with correct uid and tag
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700385 // combination. Or all tag stats under that uid if the target tag is 0.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700386 const auto deleteMatchedUidTagEntries = [uid, tag](const StatsKey& key,
387 BpfMap<StatsKey, StatsValue>& map) {
388 if (key.uid == uid && (key.tag == tag || tag == 0)) {
389 Status res = map.deleteValue(key);
390 if (isOk(res) || (res.code() == ENOENT)) {
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700391 //Entry is deleted, use the current key to get a new nextKey;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700392 return netdutils::status::ok;
Chenbo Fengf2759682017-10-10 17:31:57 -0700393 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700394 ALOGE("Failed to delete data(uid=%u, tag=%u): %s\n", key.uid, key.tag,
395 strerror(res.code()));
Chenbo Fengf2759682017-10-10 17:31:57 -0700396 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700397 return netdutils::status::ok;
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700398 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700399 mTagStatsMap.iterate(deleteMatchedUidTagEntries);
Chenbo Fengf2759682017-10-10 17:31:57 -0700400 // If the tag is not zero, we already deleted all the data entry required. If tag is 0, we also
Chenbo Fenged37fea2017-12-13 19:35:01 -0800401 // need to delete the stats stored in uidStatsMap and counterSet map.
Chenbo Fengc10a8a42017-12-15 13:56:33 -0800402 if (tag != 0) return 0;
403
Chenbo Feng2c67f262018-04-26 10:37:55 -0700404 Status res = mUidCounterSetMap.deleteValue(uid);
405 if (!isOk(res) && res.code() != ENOENT) {
406 ALOGE("Failed to delete counterSet data(uid=%u, tag=%u): %s\n", uid, tag,
407 strerror(res.code()));
Chenbo Fengc10a8a42017-12-15 13:56:33 -0800408 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700409 mUidStatsMap.iterate(deleteMatchedUidTagEntries);
Chenbo Feng58a09b52018-05-11 19:15:15 -0700410
411 auto deleteAppUidStatsEntry = [uid](const uint32_t& key, BpfMap<uint32_t, StatsValue>& map) {
412 if (key == uid) {
413 Status res = map.deleteValue(key);
414 if (isOk(res) || (res.code() == ENOENT)) {
415 return netdutils::status::ok;
416 }
417 ALOGE("Failed to delete data(uid=%u): %s", key, strerror(res.code()));
418 }
419 return netdutils::status::ok;
420 };
421 mAppUidStatsMap.iterate(deleteAppUidStatsEntry);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700422 return 0;
Chenbo Fengf2759682017-10-10 17:31:57 -0700423}
424
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800425int TrafficController::addInterface(const char* name, uint32_t ifaceIndex) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700426 if (!ebpfSupported) return 0;
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800427
Chenbo Feng2c67f262018-04-26 10:37:55 -0700428 IfaceValue iface;
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800429 if (ifaceIndex == 0) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700430 ALOGE("Unknown interface %s(%d)", name, ifaceIndex);
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800431 return -1;
432 }
433
Chenbo Feng2c67f262018-04-26 10:37:55 -0700434 strlcpy(iface.name, name, sizeof(IfaceValue));
435 Status res = mIfaceIndexNameMap.writeValue(ifaceIndex, iface, BPF_ANY);
436 if (!isOk(res)) {
437 ALOGE("Failed to add iface %s(%d): %s", name, ifaceIndex, strerror(res.code()));
438 return -res.code();
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800439 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700440 return 0;
Chenbo Feng8cc480c2018-02-28 22:57:21 -0800441}
442
Chenbo Feng2c67f262018-04-26 10:37:55 -0700443Status TrafficController::updateOwnerMapEntry(BpfMap<uint32_t, uint8_t>& map, uid_t uid,
444 FirewallRule rule, FirewallType type) {
Chenbo Feng64af7042018-03-21 10:29:18 -0700445 if (uid == UID_MAP_ENABLED) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700446 return statusFromErrno(-EINVAL, "This uid is reserved for map state");
Chenbo Feng64af7042018-03-21 10:29:18 -0700447 }
448
449 if ((rule == ALLOW && type == WHITELIST) || (rule == DENY && type == BLACKLIST)) {
450 uint8_t flag = (type == WHITELIST) ? BPF_PASS : BPF_DROP;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700451 RETURN_IF_NOT_OK(map.writeValue(uid, flag, BPF_ANY));
Chenbo Feng64af7042018-03-21 10:29:18 -0700452 } else if ((rule == ALLOW && type == BLACKLIST) || (rule == DENY && type == WHITELIST)) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700453 RETURN_IF_NOT_OK(map.deleteValue(uid));
Chenbo Feng64af7042018-03-21 10:29:18 -0700454 } else {
455 //Cannot happen.
Chenbo Feng2c67f262018-04-26 10:37:55 -0700456 return statusFromErrno(-EINVAL, "");
Chenbo Feng64af7042018-03-21 10:29:18 -0700457 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700458 return netdutils::status::ok;
Chenbo Feng64af7042018-03-21 10:29:18 -0700459}
460
461int TrafficController::changeUidOwnerRule(ChildChain chain, uid_t uid, FirewallRule rule,
462 FirewallType type) {
463 std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
464 if (!ebpfSupported) {
465 ALOGE("bpf is not set up, should use iptables rule");
466 return -ENOSYS;
467 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700468 Status res;
Chenbo Feng64af7042018-03-21 10:29:18 -0700469 switch (chain) {
470 case DOZABLE:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700471 res = updateOwnerMapEntry(mDozableUidMap, uid, rule, type);
472 break;
Chenbo Feng64af7042018-03-21 10:29:18 -0700473 case STANDBY:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700474 res = updateOwnerMapEntry(mStandbyUidMap, uid, rule, type);
475 break;
Chenbo Feng64af7042018-03-21 10:29:18 -0700476 case POWERSAVE:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700477 res = updateOwnerMapEntry(mPowerSaveUidMap, uid, rule, type);
478 break;
Chenbo Feng64af7042018-03-21 10:29:18 -0700479 case NONE:
480 default:
481 return -EINVAL;
482 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700483 if (!isOk(res)) {
484 ALOGE("change uid(%u) rule of %d failed: %s, rule: %d, type: %d", uid, chain,
485 res.msg().c_str(), rule, type);
486 return -res.code();
487 }
488 return 0;
Chenbo Feng64af7042018-03-21 10:29:18 -0700489}
490
Chenbo Feng2c67f262018-04-26 10:37:55 -0700491Status TrafficController::replaceUidsInMap(BpfMap<uint32_t, uint8_t>& map,
492 const std::vector<int32_t>& uids, FirewallRule rule,
493 FirewallType type) {
Chenbo Feng64af7042018-03-21 10:29:18 -0700494 std::set<int32_t> uidSet(uids.begin(), uids.end());
495 std::vector<uint32_t> uidsToDelete;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700496 auto getUidsToDelete = [&uidsToDelete, &uidSet](const uint32_t& key,
497 const BpfMap<uint32_t, uint8_t>&) {
498 if (key != UID_MAP_ENABLED && uidSet.find((int32_t)key) == uidSet.end()) {
499 uidsToDelete.push_back(key);
Chenbo Feng64af7042018-03-21 10:29:18 -0700500 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700501 return netdutils::status::ok;
Chenbo Feng64af7042018-03-21 10:29:18 -0700502 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700503 RETURN_IF_NOT_OK(map.iterate(getUidsToDelete));
Chenbo Feng64af7042018-03-21 10:29:18 -0700504
505 for(auto uid : uidsToDelete) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700506 RETURN_IF_NOT_OK(map.deleteValue(uid));
Chenbo Feng64af7042018-03-21 10:29:18 -0700507 }
508
509 for (auto uid : uids) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700510 RETURN_IF_NOT_OK(updateOwnerMapEntry(map, uid, rule, type));
Chenbo Feng64af7042018-03-21 10:29:18 -0700511 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700512 return netdutils::status::ok;
Chenbo Feng64af7042018-03-21 10:29:18 -0700513}
514
515int TrafficController::replaceUidOwnerMap(const std::string& name, bool isWhitelist,
516 const std::vector<int32_t>& uids) {
517 std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
518 FirewallRule rule;
519 FirewallType type;
520 if (isWhitelist) {
521 type = WHITELIST;
522 rule = ALLOW;
523 } else {
524 type = BLACKLIST;
525 rule = DENY;
526 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700527 Status res;
Chenbo Feng64af7042018-03-21 10:29:18 -0700528 if (!name.compare(FirewallController::LOCAL_DOZABLE)) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700529 res = replaceUidsInMap(mDozableUidMap, uids, rule, type);
Chenbo Feng64af7042018-03-21 10:29:18 -0700530 } else if (!name.compare(FirewallController::LOCAL_STANDBY)) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700531 res = replaceUidsInMap(mStandbyUidMap, uids, rule, type);
Chenbo Feng64af7042018-03-21 10:29:18 -0700532 } else if (!name.compare(FirewallController::LOCAL_POWERSAVE)) {
Chenbo Feng2c67f262018-04-26 10:37:55 -0700533 res = replaceUidsInMap(mPowerSaveUidMap, uids, rule, type);
Chenbo Feng64af7042018-03-21 10:29:18 -0700534 } else {
535 ALOGE("unknown chain name: %s", name.c_str());
536 return -EINVAL;
537 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700538 if (!isOk(res)) {
539 ALOGE("Failed to clean up chain: %s: %s", name.c_str(), res.msg().c_str());
540 return -res.code();
Chenbo Feng64af7042018-03-21 10:29:18 -0700541 }
542 return 0;
543}
544
545int TrafficController::toggleUidOwnerMap(ChildChain chain, bool enable) {
546 std::lock_guard<std::mutex> guard(mOwnerMatchMutex);
547 uint32_t keyUid = UID_MAP_ENABLED;
548 uint8_t mapState = enable ? 1 : 0;
Chenbo Feng2c67f262018-04-26 10:37:55 -0700549 Status res;
Chenbo Feng64af7042018-03-21 10:29:18 -0700550 switch (chain) {
551 case DOZABLE:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700552 res = mDozableUidMap.writeValue(keyUid, mapState, BPF_EXIST);
Chenbo Feng64af7042018-03-21 10:29:18 -0700553 break;
554 case STANDBY:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700555 res = mStandbyUidMap.writeValue(keyUid, mapState, BPF_EXIST);
Chenbo Feng64af7042018-03-21 10:29:18 -0700556 break;
557 case POWERSAVE:
Chenbo Feng2c67f262018-04-26 10:37:55 -0700558 res = mPowerSaveUidMap.writeValue(keyUid, mapState, BPF_EXIST);
Chenbo Feng64af7042018-03-21 10:29:18 -0700559 break;
560 default:
561 return -EINVAL;
562 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700563 if (!isOk(res)) {
564 ALOGE("Failed to toggleUidOwnerMap(%d): %s", chain, res.msg().c_str());
Chenbo Feng64af7042018-03-21 10:29:18 -0700565 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700566 return -res.code();
Chenbo Feng64af7042018-03-21 10:29:18 -0700567}
568
Chenbo Feng07d43fe2017-12-21 14:38:51 -0800569bool TrafficController::checkBpfStatsEnable() {
570 return ebpfSupported;
571}
572
Chenbo Feng132065d2018-03-26 10:53:33 -0700573std::string getProgramStatus(const char *path) {
574 int ret = access(path, R_OK);
575 if (ret == 0) {
576 return StringPrintf("OK");
577 }
578 if (ret != 0 && errno == ENOENT) {
579 return StringPrintf("program is missing at: %s", path);
580 }
581 return StringPrintf("check Program %s error: %s", path, strerror(errno));
582}
583
Chenbo Feng2c67f262018-04-26 10:37:55 -0700584std::string getMapStatus(const base::unique_fd& map_fd, const char* path) {
Chenbo Feng132065d2018-03-26 10:53:33 -0700585 if (map_fd.get() < 0) {
586 return StringPrintf("map fd lost");
587 }
588 if (access(path, F_OK) != 0) {
589 return StringPrintf("map not pinned to location: %s", path);
590 }
591 return StringPrintf("OK");
592}
593
594void dumpBpfMap(std::string mapName, DumpWriter& dw, const std::string& header) {
595 dw.blankline();
596 dw.println("%s:", mapName.c_str());
597 if(!header.empty()) {
598 dw.println(header.c_str());
599 }
600}
601
602const String16 TrafficController::DUMP_KEYWORD = String16("trafficcontroller");
603
604void TrafficController::dump(DumpWriter& dw, bool verbose) {
Chenbo Feng0cef0cd2018-04-13 19:50:49 -0700605 std::lock_guard<std::mutex> ownerMapGuard(mOwnerMatchMutex);
Chenbo Feng132065d2018-03-26 10:53:33 -0700606 dw.incIndent();
607 dw.println("TrafficController");
608
609 dw.incIndent();
610 dw.println("BPF module status: %s", ebpfSupported? "ON" : "OFF");
611
612 if (!ebpfSupported)
613 return;
614
615 dw.blankline();
616 dw.println("mCookieTagMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700617 getMapStatus(mCookieTagMap.getMap(), COOKIE_TAG_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700618 dw.println("mUidCounterSetMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700619 getMapStatus(mUidCounterSetMap.getMap(), UID_COUNTERSET_MAP_PATH).c_str());
Chenbo Feng58a09b52018-05-11 19:15:15 -0700620 dw.println("mAppUidStatsMap status: %s",
621 getMapStatus(mAppUidStatsMap.getMap(), APP_UID_STATS_MAP_PATH).c_str());
Chenbo Feng2c67f262018-04-26 10:37:55 -0700622 dw.println("mUidStatsMap status: %s",
623 getMapStatus(mUidStatsMap.getMap(), UID_STATS_MAP_PATH).c_str());
624 dw.println("mTagStatsMap status: %s",
625 getMapStatus(mTagStatsMap.getMap(), TAG_STATS_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700626 dw.println("mIfaceIndexNameMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700627 getMapStatus(mIfaceIndexNameMap.getMap(), IFACE_INDEX_NAME_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700628 dw.println("mIfaceStatsMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700629 getMapStatus(mIfaceStatsMap.getMap(), IFACE_STATS_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700630 dw.println("mDozableUidMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700631 getMapStatus(mDozableUidMap.getMap(), DOZABLE_UID_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700632 dw.println("mStandbyUidMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700633 getMapStatus(mStandbyUidMap.getMap(), STANDBY_UID_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700634 dw.println("mPowerSaveUidMap status: %s",
Chenbo Feng2c67f262018-04-26 10:37:55 -0700635 getMapStatus(mPowerSaveUidMap.getMap(), POWERSAVE_UID_MAP_PATH).c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700636
637 dw.blankline();
638 dw.println("Cgroup ingress program status: %s",
639 getProgramStatus(BPF_INGRESS_PROG_PATH).c_str());
640 dw.println("Cgroup egress program status: %s", getProgramStatus(BPF_EGRESS_PROG_PATH).c_str());
641 dw.println("xt_bpf ingress program status: %s",
642 getProgramStatus(XT_BPF_INGRESS_PROG_PATH).c_str());
643 dw.println("xt_bpf egress program status: %s",
644 getProgramStatus(XT_BPF_EGRESS_PROG_PATH).c_str());
645
646 if(!verbose) return;
647
648 dw.blankline();
649 dw.println("BPF map content:");
650
651 dw.incIndent();
652
653 // Print CookieTagMap content.
654 dumpBpfMap("mCookieTagMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700655 const auto printCookieTagInfo = [&dw](const uint64_t& key, const UidTag& value,
656 const BpfMap<uint64_t, UidTag>&) {
657 dw.println("cookie=%" PRIu64 " tag=0x%x uid=%u", key, value.tag, value.uid);
658 return netdutils::status::ok;
Chenbo Feng132065d2018-03-26 10:53:33 -0700659 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700660 Status res = mCookieTagMap.iterateWithValue(printCookieTagInfo);
661 if (!isOk(res)) {
662 dw.println("mCookieTagMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700663 }
664
665 // Print UidCounterSetMap Content
666 dumpBpfMap("mUidCounterSetMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700667 const auto printUidInfo = [&dw](const uint32_t& key, const uint8_t& value,
668 const BpfMap<uint32_t, uint8_t>&) {
669 dw.println("%u %u", key, value);
670 return netdutils::status::ok;
Chenbo Feng132065d2018-03-26 10:53:33 -0700671 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700672 res = mUidCounterSetMap.iterateWithValue(printUidInfo);
673 if (!isOk(res)) {
674 dw.println("mUidCounterSetMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700675 }
676
Chenbo Feng58a09b52018-05-11 19:15:15 -0700677 // Print AppUidStatsMap content
678 std::string appUidStatsHeader = StringPrintf("uid rxBytes rxPackets txBytes txPackets");
679 dumpBpfMap("mAppUidStatsMap:", dw, appUidStatsHeader);
680 auto printAppUidStatsInfo = [&dw](const uint32_t& key, const StatsValue& value,
681 const BpfMap<uint32_t, StatsValue>&) {
682 dw.println("%u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, key, value.rxBytes,
683 value.rxPackets, value.txBytes, value.txPackets);
684 return netdutils::status::ok;
685 };
686 res = mAppUidStatsMap.iterateWithValue(printAppUidStatsInfo);
687 if (!res.ok()) {
688 dw.println("mAppUidStatsMap print end with error: %s", res.msg().c_str());
689 }
690
Chenbo Feng132065d2018-03-26 10:53:33 -0700691 // Print uidStatsMap content
692 std::string statsHeader = StringPrintf("ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes"
693 " rxPackets txBytes txPackets");
694 dumpBpfMap("mUidStatsMap", dw, statsHeader);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700695 const auto printStatsInfo = [&dw, this](const StatsKey& key, const StatsValue& value,
696 const BpfMap<StatsKey, StatsValue>&) {
697 uint32_t ifIndex = key.ifaceIndex;
698 auto ifname = mIfaceIndexNameMap.readValue(ifIndex);
699 if (!isOk(ifname)) {
700 strlcpy(ifname.value().name, "unknown", sizeof(IfaceValue));
Chenbo Feng132065d2018-03-26 10:53:33 -0700701 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700702 dw.println("%u %s 0x%x %u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, ifIndex,
703 ifname.value().name, key.tag, key.uid, key.counterSet, value.rxBytes,
704 value.rxPackets, value.txBytes, value.txPackets);
705 return netdutils::status::ok;
Chenbo Feng132065d2018-03-26 10:53:33 -0700706 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700707 res = mUidStatsMap.iterateWithValue(printStatsInfo);
708 if (!isOk(res)) {
709 dw.println("mUidStatsMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700710 }
711
712 // Print TagStatsMap content.
713 dumpBpfMap("mTagStatsMap", dw, statsHeader);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700714 res = mTagStatsMap.iterateWithValue(printStatsInfo);
715 if (!isOk(res)) {
716 dw.println("mTagStatsMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700717 }
718
719 // Print ifaceIndexToNameMap content.
720 dumpBpfMap("mIfaceIndexNameMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700721 const auto printIfaceNameInfo = [&dw](const uint32_t& key, const IfaceValue& value,
722 const BpfMap<uint32_t, IfaceValue>&) {
723 const char* ifname = value.name;
724 dw.println("ifaceIndex=%u ifaceName=%s", key, ifname);
725 return netdutils::status::ok;
Chenbo Feng132065d2018-03-26 10:53:33 -0700726 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700727 res = mIfaceIndexNameMap.iterateWithValue(printIfaceNameInfo);
728 if (!isOk(res)) {
729 dw.println("mIfaceIndexNameMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700730 }
731
732 // Print ifaceStatsMap content
733 std::string ifaceStatsHeader = StringPrintf("ifaceIndex ifaceName rxBytes rxPackets txBytes"
734 " txPackets");
735 dumpBpfMap("mIfaceStatsMap:", dw, ifaceStatsHeader);
Chenbo Feng2c67f262018-04-26 10:37:55 -0700736 const auto printIfaceStatsInfo = [&dw, this](const uint32_t& key, const StatsValue& value,
737 const BpfMap<uint32_t, StatsValue>&) {
738 auto ifname = mIfaceIndexNameMap.readValue(key);
739 if (!isOk(ifname)) {
740 strlcpy(ifname.value().name, "unknown", sizeof(IfaceValue));
Chenbo Feng132065d2018-03-26 10:53:33 -0700741 }
Chenbo Feng2c67f262018-04-26 10:37:55 -0700742 dw.println("%u %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, key, ifname.value().name,
743 value.rxBytes, value.rxPackets, value.txBytes, value.txPackets);
744 return netdutils::status::ok;
Chenbo Feng132065d2018-03-26 10:53:33 -0700745 };
Chenbo Feng2c67f262018-04-26 10:37:55 -0700746 res = mIfaceStatsMap.iterateWithValue(printIfaceStatsInfo);
747 if (!isOk(res)) {
748 dw.println("mIfaceStatsMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700749 }
750
751 // Print owner match uid maps
Chenbo Feng132065d2018-03-26 10:53:33 -0700752 dumpBpfMap("mDozableUidMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700753 res = mDozableUidMap.iterateWithValue(printUidInfo);
754 if (!isOk(res)) {
755 dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700756 }
757
758 dumpBpfMap("mStandbyUidMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700759 res = mStandbyUidMap.iterateWithValue(printUidInfo);
760 if (!isOk(res)) {
761 dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700762 }
763
764 dumpBpfMap("mPowerSaveUidMap", dw, "");
Chenbo Feng2c67f262018-04-26 10:37:55 -0700765 res = mPowerSaveUidMap.iterateWithValue(printUidInfo);
766 if (!isOk(res)) {
767 dw.println("mDozableUidMap print end with error: %s", res.msg().c_str());
Chenbo Feng132065d2018-03-26 10:53:33 -0700768 }
769
770 dw.decIndent();
771
772 dw.decIndent();
773
774 dw.decIndent();
775
776}
777
Chenbo Fengf2759682017-10-10 17:31:57 -0700778} // namespace net
779} // namespace android