summaryrefslogtreecommitdiff
path: root/server/TetherController.cpp
diff options
context:
space:
mode:
authorMaciej Żenczykowski <maze@google.com>2020-05-13 17:08:10 -0700
committerMaciej Żenczykowski <maze@google.com>2020-05-23 13:32:44 -0700
commita1049cbacc39b12ca60ca8bba78b7ce329e55ed0 (patch)
tree81d524961bd0339220dc77e9162add2fd8784d07 /server/TetherController.cpp
parent9c52c282be3aa50d2f4dc90193960dc8cc920698 (diff)
ebpf tethering - add a map to store data limit, part 3
This actually starts enforcing the limit. Note: this requires netd to populate both stats & limit maps for offload to work. Bug: 150736748 Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: I13c21f455155480712fba9b1464b4392d5169a52
Diffstat (limited to 'server/TetherController.cpp')
-rw-r--r--server/TetherController.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 6f2ee099..560a01cf 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -1058,6 +1058,49 @@ StatusOr<TetherController::TetherStatsList> TetherController::getTetherStats() {
return statsList;
}
+// Use UINT64_MAX (~0uLL) for unlimited.
+Result<void> TetherController::setBpfLimit(uint32_t ifIndex, uint64_t limit) {
+ // The common case is an update, where the stats already exist,
+ // hence we read first, even though writing with BPF_NOEXIST
+ // first would make the code simpler.
+ uint64_t rxBytes, txBytes;
+ auto statsEntry = mBpfStatsMap.readValue(ifIndex);
+
+ if (statsEntry.ok()) {
+ // Ok, there was a stats entry.
+ rxBytes = statsEntry.value().rxBytes;
+ txBytes = statsEntry.value().txBytes;
+ } else if (statsEntry.error().code() == ENOENT) {
+ // No stats entry - create one with zeroes.
+ TetherStatsValue stats = {};
+ // This function is the *only* thing that can create entries.
+ auto ret = mBpfStatsMap.writeValue(ifIndex, stats, BPF_NOEXIST);
+ if (!ret.ok()) {
+ ALOGE("mBpfStatsMap.writeValue failure: %s", strerror(ret.error().code()));
+ return ret;
+ }
+ rxBytes = 0;
+ txBytes = 0;
+ } else {
+ // Other error while trying to get stats entry.
+ return statsEntry.error();
+ }
+
+ // rxBytes + txBytes won't overflow even at 5gbps for ~936 years.
+ uint64_t newLimit = rxBytes + txBytes + limit;
+
+ // if adding limit (e.g., if limit is UINT64_MAX) caused overflow: clamp to 'infinity'
+ if (newLimit < rxBytes + txBytes) newLimit = ~0uLL;
+
+ auto ret = mBpfLimitMap.writeValue(ifIndex, newLimit, BPF_ANY);
+ if (!ret.ok()) {
+ ALOGE("mBpfLimitMap.writeValue failure: %s", strerror(ret.error().code()));
+ return ret;
+ }
+
+ return {};
+}
+
void TetherController::maybeStartBpf(const char* extIface) {
if (!bpf::isBpfSupported()) return;
@@ -1088,6 +1131,9 @@ void TetherController::maybeStartBpf(const char* extIface) {
isEthernet.value(), strerror(-rv));
return;
}
+
+ // For now we just set data limit to 'infinity' ie. unlimited.
+ setBpfLimit(ifIndex, ~0uLL);
}
void TetherController::maybeStopBpf(const char* extIface) {