Get bpf level when check bpf support
Instead of return boolean, bpf support check now returns a integer
represent the current bpf level on device. This level is used to decide
if the device support some advanced bpf feature such as map_in_map and
bpf cgroup socket filter. Delete the binder call for bpf status check
since no one is using it.
Bug: 111441138
Test: libnetdbpf_test, netd_integration_test
Change-Id: Ib70c07647ffe491d493b4582b4b4b0eba7caf3a9
diff --git a/server/Controllers.cpp b/server/Controllers.cpp
index 8f0dad2..a5c9eba 100644
--- a/server/Controllers.cpp
+++ b/server/Controllers.cpp
@@ -282,7 +282,7 @@
}
gLog.info("Initializing traffic control: %.1fms", s.getTimeAndReset());
- bandwidthCtrl.setBpfEnabled(trafficCtrl.checkBpfStatsEnable());
+ bandwidthCtrl.setBpfEnabled(trafficCtrl.getBpfLevel() != android::bpf::BpfLevel::NONE);
bandwidthCtrl.enableBandwidthControl();
gLog.info("Enabling bandwidth control: %.1fms", s.getTimeAndReset());
diff --git a/server/FirewallController.cpp b/server/FirewallController.cpp
index 890ab5b..7512c09 100644
--- a/server/FirewallController.cpp
+++ b/server/FirewallController.cpp
@@ -41,6 +41,7 @@
using android::base::Split;
using android::base::StringAppendF;
using android::base::StringPrintf;
+using android::bpf::BpfLevel;
using android::net::gCtls;
namespace {
@@ -53,8 +54,8 @@
// Proc file containing the uid mapping for the user namespace of the current process.
const char kUidMapProcFile[] = "/proc/self/uid_map";
-bool getBpfOwnerStatus() {
- return gCtls->trafficCtrl.checkBpfStatsEnable();
+android::bpf::BpfLevel getBpfOwnerStatus() {
+ return gCtls->trafficCtrl.getBpfLevel();
}
} // namespace
@@ -95,7 +96,7 @@
int FirewallController::setupIptablesHooks(void) {
int res = 0;
mUseBpfOwnerMatch = getBpfOwnerStatus();
- if (mUseBpfOwnerMatch) {
+ if (mUseBpfOwnerMatch != BpfLevel::NONE) {
return res;
}
res |= createChain(LOCAL_DOZABLE, getFirewallType(DOZABLE));
@@ -159,7 +160,7 @@
return res;
}
- if (mUseBpfOwnerMatch) {
+ if (mUseBpfOwnerMatch != BpfLevel::NONE) {
return gCtls->trafficCtrl.toggleUidOwnerMap(chain, enable);
}
@@ -258,7 +259,7 @@
ALOGW("Unknown child chain: %d", chain);
return -EINVAL;
}
- if (mUseBpfOwnerMatch) {
+ if (mUseBpfOwnerMatch != BpfLevel::NONE) {
return gCtls->trafficCtrl.changeUidOwnerRule(chain, uid, rule, firewallType);
}
@@ -346,8 +347,8 @@
int FirewallController::replaceUidChain(
const std::string &name, bool isWhitelist, const std::vector<int32_t>& uids) {
- if (mUseBpfOwnerMatch) {
- return gCtls->trafficCtrl.replaceUidOwnerMap(name, isWhitelist, uids);
+ if (mUseBpfOwnerMatch != BpfLevel::NONE) {
+ return gCtls->trafficCtrl.replaceUidOwnerMap(name, isWhitelist, uids);
}
std::string commands4 = makeUidRules(V4, name.c_str(), isWhitelist, uids);
std::string commands6 = makeUidRules(V6, name.c_str(), isWhitelist, uids);
diff --git a/server/FirewallController.h b/server/FirewallController.h
index a7082da..43da322 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -26,6 +26,7 @@
#include "android/net/INetd.h"
#include "NetdConstants.h"
+#include "bpf/BpfUtils.h"
namespace android {
namespace net {
@@ -103,7 +104,7 @@
// fails with EPERM. Netd can therefore assumes the max valid uid to be const.
const uid_t mMaxUid;
FirewallType mFirewallType;
- bool mUseBpfOwnerMatch;
+ android::bpf::BpfLevel mUseBpfOwnerMatch;
std::set<std::string> mIfaceRules;
int attachChain(const char*, const char*);
int detachChain(const char*, const char*);
diff --git a/server/FirewallControllerTest.cpp b/server/FirewallControllerTest.cpp
index 71cc532..bd933b4 100644
--- a/server/FirewallControllerTest.cpp
+++ b/server/FirewallControllerTest.cpp
@@ -39,7 +39,10 @@
protected:
FirewallControllerTest() {
FirewallController::execIptablesRestore = fakeExecIptablesRestore;
- mFw.mUseBpfOwnerMatch = false;
+ // This unit test currently doesn't cover the eBPF owner match case so
+ // we have to manually turn eBPF support off.
+ // TODO: find a way to unit test the eBPF code path.
+ mFw.mUseBpfOwnerMatch = android::bpf::BpfLevel::NONE;
}
FirewallController mFw;
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 5b213b4..f607069 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -911,12 +911,6 @@
return asBinderStatus(gCtls->wakeupCtrl.delInterface(ifName, prefix, mark, mask));
}
-binder::Status NetdNativeService::trafficCheckBpfStatsEnable(bool* ret) {
- ENFORCE_PERMISSION(NETWORK_STACK);
- *ret = gCtls->trafficCtrl.checkBpfStatsEnable();
- return binder::Status::ok();
-}
-
binder::Status NetdNativeService::idletimerAddInterface(const std::string& ifName, int32_t timeout,
const std::string& classLabel) {
NETD_LOCKING_RPC(NETWORK_STACK, gCtls->idletimerCtrl.lock);
diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
index e399fac..607bec8 100644
--- a/server/NetdNativeService.h
+++ b/server/NetdNativeService.h
@@ -205,8 +205,6 @@
int32_t direction, int32_t markValue, int32_t markMask,
int32_t interfaceId);
- binder::Status trafficCheckBpfStatsEnable(bool* ret) override;
-
binder::Status ipSecAddTunnelInterface(const std::string& deviceName,
const std::string& localAddress,
const std::string& remoteAddress, int32_t iKey,
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index e3b950c..677f32c 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -157,9 +157,7 @@
return netdutils::status::ok;
}
-TrafficController::TrafficController() {
- ebpfSupported = hasBpfSupport();
-}
+TrafficController::TrafficController() : mBpfLevel(getBpfSupportLevel()) {}
Status TrafficController::initMaps() {
std::lock_guard ownerMapGuard(mOwnerMatchMutex);
@@ -260,8 +258,7 @@
}
Status TrafficController::start() {
-
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
return netdutils::status::ok;
}
@@ -326,7 +323,7 @@
return -EPERM;
}
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
if (legacy_tagSocket(sockFd, tag, uid)) return -errno;
return 0;
}
@@ -349,7 +346,7 @@
}
int TrafficController::untagSocket(int sockFd) {
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
if (legacy_untagSocket(sockFd)) return -errno;
return 0;
}
@@ -368,7 +365,7 @@
if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
if (legacy_setCounterSet(counterSetNum, uid)) return -errno;
return 0;
}
@@ -400,7 +397,7 @@
int TrafficController::deleteTagData(uint32_t tag, uid_t uid, uid_t callingUid) {
if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
if (legacy_deleteTagData(tag, uid)) return -errno;
return 0;
}
@@ -462,7 +459,7 @@
}
int TrafficController::addInterface(const char* name, uint32_t ifaceIndex) {
- if (!ebpfSupported) return 0;
+ if (mBpfLevel == BpfLevel::NONE) return 0;
IfaceValue iface;
if (ifaceIndex == 0) {
@@ -563,7 +560,7 @@
int TrafficController::changeUidOwnerRule(ChildChain chain, uid_t uid, FirewallRule rule,
FirewallType type) {
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
ALOGE("bpf is not set up, should use iptables rule");
return -ENOSYS;
}
@@ -677,8 +674,8 @@
return -res.code();
}
-bool TrafficController::checkBpfStatsEnable() {
- return ebpfSupported;
+BpfLevel TrafficController::getBpfLevel() {
+ return mBpfLevel;
}
void TrafficController::setPermissionForUids(int permission, const std::vector<uid_t>& uids) {
@@ -746,9 +743,9 @@
dw.println("TrafficController");
ScopedIndent indentPreBpfModule(dw);
- dw.println("BPF module status: %s", ebpfSupported? "ON" : "OFF");
+ dw.println("BPF module status: %s", BpfLevelToString(mBpfLevel).c_str());
- if (!ebpfSupported) {
+ if (mBpfLevel == BpfLevel::NONE) {
return;
}
diff --git a/server/TrafficController.h b/server/TrafficController.h
index 35bea4a..1576882 100644
--- a/server/TrafficController.h
+++ b/server/TrafficController.h
@@ -86,7 +86,7 @@
* Check if the current device have the bpf traffic stats accounting service
* running.
*/
- bool checkBpfStatsEnable();
+ bpf::BpfLevel getBpfLevel();
/*
* Add the interface name and index pair into the eBPF map.
@@ -204,7 +204,7 @@
netdutils::Status addMatch(BpfMap<uint32_t, uint8_t>& map, uint32_t uid,
UidOwnerMatchType match) REQUIRES(mOwnerMatchMutex);
- bool ebpfSupported;
+ bpf::BpfLevel mBpfLevel;
std::mutex mOwnerMatchMutex;
diff --git a/server/TrafficControllerTest.cpp b/server/TrafficControllerTest.cpp
index 31d3b6b..05702e2 100644
--- a/server/TrafficControllerTest.cpp
+++ b/server/TrafficControllerTest.cpp
@@ -102,8 +102,6 @@
mFakeUidPermissionMap.reset(
createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), TEST_MAP_SIZE, 0));
ASSERT_TRUE(mFakeUidPermissionMap.isValid());
- // Make sure trafficController use the eBPF code path.
- mTc.ebpfSupported = true;
mTc.mCookieTagMap.reset(mFakeCookieTagMap.getMap());
mTc.mUidCounterSetMap.reset(mFakeUidCounterSetMap.getMap());
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index c198aa6..1b6c988 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -569,12 +569,6 @@
void setIPv6AddrGenMode(in @utf8InCpp String ifName, int mode);
/**
- * Query the netd service to know if the eBPF traffic stats accounting service is currently
- * running on the device.
- */
- boolean trafficCheckBpfStatsEnable();
-
- /**
* Add idletimer for specific interface
*
* @param ifName Name of target interface