summaryrefslogtreecommitdiff
path: root/server/TetherController.cpp
diff options
context:
space:
mode:
authorHungming Chen <nuccachen@google.com>2020-04-17 20:00:27 +0800
committerHungming Chen <nuccachen@google.com>2020-06-05 16:24:56 +0800
commit468a20c532eb13e7af0ebaeaa742be05e76e2be5 (patch)
treeb79c00ef41314f123653fe2d2eb4f614b4e2e968 /server/TetherController.cpp
parent0c47671990d1b1e8672f38209faa76d184089b96 (diff)
Add binder call tetherOffloadGetAndClearStats
Provide binder calls for getting tethering statistics and clear the stats for the given upstream. Bug: 150736748 Test: None Change-Id: I7bb635ee39d658961cd9515cc37e23bc3f0cd38f
Diffstat (limited to 'server/TetherController.cpp')
-rw-r--r--server/TetherController.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 1844ca9e..ad6e8a97 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -1165,6 +1165,46 @@ int TetherController::setTetherOffloadInterfaceQuota(int ifIndex, int64_t maxByt
return 0;
}
+Result<TetherController::TetherOffloadStats> TetherController::getAndClearTetherOffloadStats(
+ int ifIndex) {
+ if (!mBpfStatsMap.isValid() || !mBpfLimitMap.isValid()) return Error(ENOTSUP);
+
+ if (ifIndex <= 0) {
+ return Error(ENODEV) << "Invalid interface " << ifIndex;
+ }
+
+ // getAndClearTetherOffloadStats is called after all offload rules have already been deleted
+ // for the given upstream interface. Before starting to do cleanup stuff in this function, use
+ // synchronizeKernelRCU to make sure that all the current running eBPF programs are finished
+ // on all CPUs, especially the unfinished packet processing. After synchronizeKernelRCU
+ // returned, we can safely read or delete on the stats map or the limit map.
+ if (int res = bpf::synchronizeKernelRCU()) {
+ // Error log but don't return error. Do as much cleanup as possible.
+ ALOGE("synchronize_rcu() failed: %s", strerror(-res));
+ }
+
+ const auto stats = mBpfStatsMap.readValue(ifIndex);
+ if (!stats.ok()) {
+ return Error(stats.error().code()) << "Fail to get stats for interface index " << ifIndex;
+ }
+
+ auto res = mBpfStatsMap.deleteValue(ifIndex);
+ if (!res.ok()) {
+ return Error(res.error().code()) << "Fail to delete stats for interface index " << ifIndex;
+ }
+
+ res = mBpfLimitMap.deleteValue(ifIndex);
+ if (!res.ok()) {
+ return Error(res.error().code()) << "Fail to delete limit for interface index " << ifIndex;
+ }
+
+ return TetherOffloadStats{.ifIndex = static_cast<int>(ifIndex),
+ .rxBytes = static_cast<int64_t>(stats.value().rxBytes),
+ .rxPackets = static_cast<int64_t>(stats.value().rxPackets),
+ .txBytes = static_cast<int64_t>(stats.value().txBytes),
+ .txPackets = static_cast<int64_t>(stats.value().txPackets)};
+}
+
void TetherController::dumpIfaces(DumpWriter& dw) {
dw.println("Interface pairs:");