Clean up dependency between NetlinkListener and TrafficController
Bug: 209935649
Test: m; flash; boot
Test: atest netd_integration_test
Change-Id: I779050cd4472395adbef06d8921884c194fd0b32
diff --git a/server/Android.bp b/server/Android.bp
index 49445db..071f467 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -29,7 +29,6 @@
"NetdConstants.cpp",
"InterfaceController.cpp",
"NetlinkCommands.cpp",
- "NetlinkListener.cpp",
"TcUtils.cpp",
"SockDiag.cpp",
"XfrmController.cpp",
@@ -57,7 +56,6 @@
"IptablesRestoreController.cpp",
"NFLogListener.cpp",
"NetlinkCommands.cpp",
- "NetlinkListener.cpp",
"NetlinkManager.cpp",
"TcUtils.cpp",
"RouteController.cpp",
diff --git a/server/NFLogListener.cpp b/server/NFLogListener.cpp
index 76972b6..62ac19d 100644
--- a/server/NFLogListener.cpp
+++ b/server/NFLogListener.cpp
@@ -35,6 +35,8 @@
using netdutils::extract;
using netdutils::findWithDefault;
using netdutils::makeSlice;
+using netdutils::NetlinkListener;
+using netdutils::NetlinkListenerInterface;
using netdutils::Slice;
using netdutils::sSyscalls;
using netdutils::Status;
diff --git a/server/NFLogListener.h b/server/NFLogListener.h
index 459b5cf..722fdd0 100644
--- a/server/NFLogListener.h
+++ b/server/NFLogListener.h
@@ -19,7 +19,7 @@
#include <netdutils/Netfilter.h>
-#include "NetlinkListener.h"
+#include "netdutils/NetlinkListener.h"
#include "netdutils/StatusOr.h"
namespace android {
@@ -64,7 +64,7 @@
// Do not invoke this constructor directly outside of tests. Use
// makeNFLogListener() instead.
- NFLogListener(std::shared_ptr<NetlinkListenerInterface> listener);
+ NFLogListener(std::shared_ptr<netdutils::NetlinkListenerInterface> listener);
~NFLogListener() override;
@@ -76,7 +76,7 @@
netdutils::Status unsubscribe(uint16_t nfLogGroup) override;
private:
- std::shared_ptr<NetlinkListenerInterface> mListener;
+ std::shared_ptr<netdutils::NetlinkListenerInterface> mListener;
std::mutex mMutex;
std::map<uint16_t, DispatchFn> mDispatchMap; // guarded by mMutex
};
diff --git a/server/NFLogListenerTest.cpp b/server/NFLogListenerTest.cpp
index f3bd810..88ab2c6 100644
--- a/server/NFLogListenerTest.cpp
+++ b/server/NFLogListenerTest.cpp
@@ -38,9 +38,10 @@
namespace android {
namespace net {
+using netdutils::makeSlice;
+using netdutils::NetlinkListenerInterface;
using netdutils::Slice;
using netdutils::StatusOr;
-using netdutils::makeSlice;
using netdutils::status::ok;
constexpr int kNFLogPacketMsgType = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET;
diff --git a/server/NetlinkListener.cpp b/server/NetlinkListener.cpp
deleted file mode 100644
index a6e427d..0000000
--- a/server/NetlinkListener.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "NetlinkListener"
-
-#include "NetlinkListener.h"
-
-#include <sstream>
-#include <vector>
-
-#include <linux/netfilter/nfnetlink.h>
-
-#include <log/log.h>
-#include <netdutils/Misc.h>
-#include <netdutils/Syscalls.h>
-
-namespace android {
-namespace net {
-
-using netdutils::Fd;
-using netdutils::Slice;
-using netdutils::Status;
-using netdutils::UniqueFd;
-using netdutils::findWithDefault;
-using netdutils::forEachNetlinkMessage;
-using netdutils::makeSlice;
-using netdutils::sSyscalls;
-using netdutils::status::ok;
-using netdutils::statusFromErrno;
-
-namespace {
-
-constexpr int kNetlinkMsgErrorType = (NFNL_SUBSYS_NONE << 8) | NLMSG_ERROR;
-
-constexpr sockaddr_nl kKernelAddr = {
- .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = 0,
-};
-
-const NetlinkListener::DispatchFn kDefaultDispatchFn = [](const nlmsghdr& nlmsg, const Slice) {
- std::stringstream ss;
- ss << nlmsg;
- ALOGE("unhandled netlink message: %s", ss.str().c_str());
-};
-
-} // namespace
-
-NetlinkListener::NetlinkListener(UniqueFd event, UniqueFd sock, const std::string& name)
- : mEvent(std::move(event)), mSock(std::move(sock)), mThreadName(name) {
- const auto rxErrorHandler = [](const nlmsghdr& nlmsg, const Slice msg) {
- std::stringstream ss;
- ss << nlmsg << " " << msg << " " << netdutils::toHex(msg, 32);
- ALOGE("unhandled netlink message: %s", ss.str().c_str());
- };
- expectOk(NetlinkListener::subscribe(kNetlinkMsgErrorType, rxErrorHandler));
-
- mErrorHandler = [& name = mThreadName](const int fd, const int err) {
- ALOGE("Error on NetlinkListener(%s) fd=%d: %s", name.c_str(), fd, strerror(err));
- };
-
- // Start the thread
- mWorker = std::thread([this]() { run().ignoreError(); });
-}
-
-NetlinkListener::~NetlinkListener() {
- const auto& sys = sSyscalls.get();
- const uint64_t data = 1;
- // eventfd should never enter an error state unexpectedly
- expectOk(sys.write(mEvent, makeSlice(data)).status());
- mWorker.join();
-}
-
-Status NetlinkListener::send(const Slice msg) {
- const auto& sys = sSyscalls.get();
- ASSIGN_OR_RETURN(auto sent, sys.sendto(mSock, msg, 0, kKernelAddr));
- if (sent != msg.size()) {
- return statusFromErrno(EMSGSIZE, "unexpect message size");
- }
- return ok;
-}
-
-Status NetlinkListener::subscribe(uint16_t type, const DispatchFn& fn) {
- std::lock_guard guard(mMutex);
- mDispatchMap[type] = fn;
- return ok;
-}
-
-Status NetlinkListener::unsubscribe(uint16_t type) {
- std::lock_guard guard(mMutex);
- mDispatchMap.erase(type);
- return ok;
-}
-
-void NetlinkListener::registerSkErrorHandler(const SkErrorHandler& handler) {
- mErrorHandler = handler;
-}
-
-Status NetlinkListener::run() {
- std::vector<char> rxbuf(4096);
-
- const auto rxHandler = [this](const nlmsghdr& nlmsg, const Slice& buf) {
- std::lock_guard guard(mMutex);
- const auto& fn = findWithDefault(mDispatchMap, nlmsg.nlmsg_type, kDefaultDispatchFn);
- fn(nlmsg, buf);
- };
-
- if (mThreadName.length() > 0) {
- int ret = pthread_setname_np(pthread_self(), mThreadName.c_str());
- if (ret) {
- ALOGE("thread name set failed, name: %s, ret: %s", mThreadName.c_str(), strerror(ret));
- }
- }
- const auto& sys = sSyscalls.get();
- const std::array<Fd, 2> fds{{{mEvent}, {mSock}}};
- const int events = POLLIN;
- const double timeout = 3600;
- while (true) {
- ASSIGN_OR_RETURN(auto revents, sys.ppoll(fds, events, timeout));
- // After mEvent becomes readable, we should stop servicing mSock and return
- if (revents[0] & POLLIN) {
- break;
- }
- if (revents[1] & (POLLIN|POLLERR)) {
- auto rx = sys.recvfrom(mSock, makeSlice(rxbuf), 0);
- int err = rx.status().code();
- if (err) {
- // Ignore errors. The only error we expect to see here is ENOBUFS, and there's
- // nothing we can do about that. The recvfrom above will already have cleared the
- // error indication and ensured we won't get EPOLLERR again.
- // TODO: Consider using NETLINK_NO_ENOBUFS.
- mErrorHandler(((Fd) mSock).get(), err);
- continue;
- }
- forEachNetlinkMessage(rx.value(), rxHandler);
- }
- }
- return ok;
-}
-
-} // namespace net
-} // namespace android
diff --git a/server/NetlinkListener.h b/server/NetlinkListener.h
deleted file mode 100644
index 6f38829..0000000
--- a/server/NetlinkListener.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef NETLINK_LISTENER_H
-#define NETLINK_LISTENER_H
-
-#include <functional>
-#include <map>
-#include <mutex>
-#include <thread>
-
-#include <android-base/thread_annotations.h>
-#include <netdutils/Netlink.h>
-#include <netdutils/Slice.h>
-#include <netdutils/Status.h>
-#include <netdutils/UniqueFd.h>
-
-namespace android {
-namespace net {
-
-class NetlinkListenerInterface {
- public:
- using DispatchFn = std::function<void(const nlmsghdr& nlmsg, const netdutils::Slice msg)>;
-
- using SkErrorHandler = std::function<void(const int fd, const int err)>;
-
- virtual ~NetlinkListenerInterface() = default;
-
- // Send message to the kernel using the underlying netlink socket
- virtual netdutils::Status send(const netdutils::Slice msg) = 0;
-
- // Deliver future messages with nlmsghdr.nlmsg_type == type to fn.
- //
- // Threadsafe.
- // All dispatch functions invoked on a single service thread.
- // subscribe() and join() must not be called from the stack of fn().
- virtual netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) = 0;
-
- // Halt delivery of future messages with nlmsghdr.nlmsg_type == type.
- // Threadsafe.
- virtual netdutils::Status unsubscribe(uint16_t type) = 0;
-
- virtual void registerSkErrorHandler(const SkErrorHandler& handler) = 0;
-};
-
-// NetlinkListener manages a netlink socket and associated blocking
-// service thread.
-//
-// This class is written in a generic way to allow multiple different
-// netlink subsystems to share this common infrastructure. If multiple
-// subsystems share the same message delivery requirements (drops ok,
-// no drops) they may share a single listener by calling subscribe()
-// with multiple types.
-//
-// This class is suitable for moderate performance message
-// processing. In particular it avoids extra copies of received
-// message data and allows client code to control which message
-// attributes are processed.
-//
-// Note that NetlinkListener is capable of processing multiple batched
-// netlink messages in a single system call. This is useful to
-// netfilter extensions that allow batching of events like NFLOG.
-class NetlinkListener : public NetlinkListenerInterface {
- public:
- NetlinkListener(netdutils::UniqueFd event, netdutils::UniqueFd sock, const std::string& name);
-
- ~NetlinkListener() override;
-
- netdutils::Status send(const netdutils::Slice msg) override;
-
- netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) override EXCLUDES(mMutex);
-
- netdutils::Status unsubscribe(uint16_t type) override EXCLUDES(mMutex);
-
- void registerSkErrorHandler(const SkErrorHandler& handler) override;
-
- private:
- netdutils::Status run();
-
- const netdutils::UniqueFd mEvent;
- const netdutils::UniqueFd mSock;
- const std::string mThreadName;
- std::mutex mMutex;
- std::map<uint16_t, DispatchFn> mDispatchMap GUARDED_BY(mMutex);
- std::thread mWorker;
- SkErrorHandler mErrorHandler;
-};
-
-} // namespace net
-} // namespace android
-
-#endif /* NETLINK_LISTENER_H */
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index 5a12d9c..2b4ecb6 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -41,13 +41,13 @@
#include <netdutils/StatusOr.h>
#include <netdutils/Misc.h>
+#include <netdutils/NetlinkListener.h>
#include <netdutils/Syscalls.h>
#include <netdutils/Utils.h>
#include <processgroup/processgroup.h>
#include "TrafficController.h"
#include "bpf/BpfMap.h"
-#include "NetlinkListener.h"
#include "netdutils/DumpWriter.h"
namespace android {
@@ -55,6 +55,7 @@
using base::StringPrintf;
using base::unique_fd;
+using bpf::BpfMap;
using bpf::getSocketCookie;
using bpf::NONEXISTENT_COOKIE;
using bpf::OVERFLOW_COUNTERSET;
@@ -63,6 +64,8 @@
using netdutils::DumpWriter;
using netdutils::extract;
using netdutils::getIfaceList;
+using netdutils::NetlinkListener;
+using netdutils::NetlinkListenerInterface;
using netdutils::ScopedIndent;
using netdutils::Slice;
using netdutils::sSyscalls;
diff --git a/server/TrafficController.h b/server/TrafficController.h
index 13a1a80..2f38f6c 100644
--- a/server/TrafficController.h
+++ b/server/TrafficController.h
@@ -19,18 +19,16 @@
#include <linux/bpf.h>
-#include "NetlinkListener.h"
#include "Network.h"
#include "android-base/thread_annotations.h"
#include "android-base/unique_fd.h"
#include "bpf/BpfMap.h"
#include "bpf_shared.h"
#include "netdutils/DumpWriter.h"
+#include "netdutils/NetlinkListener.h"
#include "netdutils/StatusOr.h"
#include "utils/String16.h"
-using android::bpf::BpfMap;
-
namespace android {
namespace net {
@@ -117,7 +115,8 @@
int toggleUidOwnerMap(ChildChain chain, bool enable) EXCLUDES(mMutex);
- static netdutils::StatusOr<std::unique_ptr<NetlinkListenerInterface>> makeSkDestroyListener();
+ static netdutils::StatusOr<std::unique_ptr<netdutils::NetlinkListenerInterface>>
+ makeSkDestroyListener();
void setPermissionForUids(int permission, const std::vector<uid_t>& uids) EXCLUDES(mMutex);
@@ -139,7 +138,7 @@
* Map Key: uint64_t socket cookie
* Map Value: UidTagValue, contains a uint32 uid and a uint32 tag.
*/
- BpfMap<uint64_t, UidTagValue> mCookieTagMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint64_t, UidTagValue> mCookieTagMap GUARDED_BY(mMutex);
/*
* mUidCounterSetMap: Store the counterSet of a specific uid.
@@ -147,14 +146,14 @@
* Map Value: uint32 counterSet specifies if the traffic is a background
* or foreground traffic.
*/
- BpfMap<uint32_t, uint8_t> mUidCounterSetMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint32_t, uint8_t> mUidCounterSetMap GUARDED_BY(mMutex);
/*
* mAppUidStatsMap: Store the total traffic stats for a uid regardless of
* tag, counterSet and iface. The stats is used by TrafficStats.getUidStats
* API to return persistent stats for a specific uid since device boot.
*/
- BpfMap<uint32_t, StatsValue> mAppUidStatsMap;
+ bpf::BpfMap<uint32_t, StatsValue> mAppUidStatsMap;
/*
* mStatsMapA/mStatsMapB: Store the traffic statistics for a specific
@@ -165,22 +164,22 @@
* Map Value: Stats, contains packet count and byte count of each
* transport protocol on egress and ingress direction.
*/
- BpfMap<StatsKey, StatsValue> mStatsMapA GUARDED_BY(mMutex);
+ bpf::BpfMap<StatsKey, StatsValue> mStatsMapA GUARDED_BY(mMutex);
- BpfMap<StatsKey, StatsValue> mStatsMapB GUARDED_BY(mMutex);
+ bpf::BpfMap<StatsKey, StatsValue> mStatsMapB GUARDED_BY(mMutex);
/*
* mIfaceIndexNameMap: Store the index name pair of each interface show up
* on the device since boot. The interface index is used by the eBPF program
* to correctly match the iface name when receiving a packet.
*/
- BpfMap<uint32_t, IfaceValue> mIfaceIndexNameMap;
+ bpf::BpfMap<uint32_t, IfaceValue> mIfaceIndexNameMap;
/*
* mIfaceStataMap: Store per iface traffic stats gathered from xt_bpf
* filter.
*/
- BpfMap<uint32_t, StatsValue> mIfaceStatsMap;
+ bpf::BpfMap<uint32_t, StatsValue> mIfaceStatsMap;
/*
* mConfigurationMap: Store the current network policy about uid filtering
@@ -194,19 +193,19 @@
* Userspace can do scraping and cleaning job on the other one depending on the
* current configs.
*/
- BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mMutex);
/*
* mUidOwnerMap: Store uids that are used for bandwidth control uid match.
*/
- BpfMap<uint32_t, UidOwnerValue> mUidOwnerMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint32_t, UidOwnerValue> mUidOwnerMap GUARDED_BY(mMutex);
/*
* mUidOwnerMap: Store uids that are used for INTERNET permission check.
*/
- BpfMap<uint32_t, uint8_t> mUidPermissionMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint32_t, uint8_t> mUidPermissionMap GUARDED_BY(mMutex);
- std::unique_ptr<NetlinkListenerInterface> mSkDestroyListener;
+ std::unique_ptr<netdutils::NetlinkListenerInterface> mSkDestroyListener;
netdutils::Status removeRule(uint32_t uid, UidOwnerMatchType match) REQUIRES(mMutex);
diff --git a/tests/netlink_listener_test.cpp b/tests/netlink_listener_test.cpp
index 18315e8..31cd7fb 100644
--- a/tests/netlink_listener_test.cpp
+++ b/tests/netlink_listener_test.cpp
@@ -34,11 +34,11 @@
#include <netdutils/Misc.h>
#include <netdutils/Syscalls.h>
-#include "NetlinkListener.h"
#include "TrafficController.h"
#include "bpf/BpfMap.h"
#include "bpf/BpfUtils.h"
#include "netdutils/Netlink.h"
+#include "netdutils/NetlinkListener.h"
// A test uid that is large enough so normal apps are not likely to take,
constexpr uid_t TEST_UID = UID_MAX - 2;
@@ -50,6 +50,7 @@
using android::base::Error;
using android::base::Result;
+using android::bpf::BpfMap;
// This test set up a SkDestroyListener that is runing parallel with the production
// SkDestroyListener. The test will create thousands of sockets and tag them on the
@@ -100,7 +101,7 @@
}
bool checkMassiveSocketDestroy(int totalNumber, bool expectError) {
- std::unique_ptr<android::net::NetlinkListenerInterface> skDestroyListener;
+ std::unique_ptr<android::netdutils::NetlinkListenerInterface> skDestroyListener;
auto result = android::net::TrafficController::makeSkDestroyListener();
if (!isOk(result)) {
ALOGE("Unable to create SkDestroyListener: %s", toString(result).c_str());