[DRUEL04] Implement unsolicited NAT64 prefix event
Implement unsolicited NAT64 prefix event that will report to the
listener when change NAT64 prefix.
Bug: 173485754
Test: atest resolv_integration_test resolv_unit_test\
resolv_stress_test resolv_stats_test_utils_test
Change-Id: If20353529969ffa956b56d19345519f286046e25
diff --git a/ResolverController.cpp b/ResolverController.cpp
index 7b181e2..b193af1 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -35,6 +35,8 @@
#include "stats.h"
using aidl::android::net::ResolverParamsParcel;
+using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
+using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
namespace android {
@@ -45,14 +47,30 @@
namespace {
void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) {
+ LOG(DEBUG) << "Sending Nat64Prefix " << (args.added ? "added" : "removed") << " event on netId "
+ << args.netId << " with address {" << args.prefixString << "(" << args.prefixLength
+ << ")}";
+ // Send a nat64 prefix event to NetdEventListenerService.
const auto& listeners = ResolverEventReporter::getInstance().getListeners();
- if (listeners.size() == 0) {
- LOG(ERROR) << __func__ << ": No available listener. dropping NAT64 prefix event";
- return;
+ if (listeners.empty()) {
+ LOG(ERROR) << __func__ << ": No available listener. Skipping NAT64 prefix event";
}
for (const auto& it : listeners) {
it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength);
}
+
+ const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners();
+ const Nat64PrefixEventParcel nat64PrefixEvent = {
+ .netId = static_cast<int32_t>(args.netId),
+ .prefixOperation =
+ args.added ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED
+ : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED,
+ .prefixAddress = args.prefixString,
+ .prefixLength = args.prefixLength,
+ };
+ for (const auto& it : unsolEventListeners) {
+ it->onNat64PrefixEvent(nat64PrefixEvent);
+ }
}
int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains,
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index 714b2db..890c599 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -96,6 +96,7 @@
using aidl::android::net::ResolverParamsParcel;
using aidl::android::net::metrics::INetdEventListener;
using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
+using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
using android::base::Error;
using android::base::ParseInt;
@@ -258,7 +259,12 @@
bool WaitForNat64Prefix(ExpectNat64PrefixStatus status,
std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) {
- return sDnsMetricsListener->waitForNat64Prefix(status, timeout);
+ return sDnsMetricsListener->waitForNat64Prefix(status, timeout) &&
+ sUnsolicitedEventListener->waitForNat64Prefix(
+ status == EXPECT_FOUND
+ ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED
+ : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED,
+ timeout);
}
bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated) {
@@ -4031,6 +4037,7 @@
EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND));
EXPECT_EQ(0, sDnsMetricsListener->getUnexpectedNat64PrefixUpdates());
+ EXPECT_EQ(0, sUnsolicitedEventListener->getUnexpectedNat64PrefixUpdates());
}
namespace {
diff --git a/tests/unsolicited_listener/unsolicited_event_listener.cpp b/tests/unsolicited_listener/unsolicited_event_listener.cpp
index f5ebb0b..8cf7505 100644
--- a/tests/unsolicited_listener/unsolicited_event_listener.cpp
+++ b/tests/unsolicited_listener/unsolicited_event_listener.cpp
@@ -23,11 +23,14 @@
namespace android::net::resolv::aidl {
+using ::aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
+using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel;
using android::base::ScopedLockAssertion;
using std::chrono::milliseconds;
constexpr milliseconds kEventTimeoutMs{5000};
+constexpr milliseconds kRetryIntervalMs{20};
::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent(
const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) {
@@ -36,8 +39,15 @@
}
::ndk::ScopedAStatus UnsolicitedEventListener::onNat64PrefixEvent(
- const ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel&) {
- // default no-op
+ const Nat64PrefixEventParcel& event) {
+ std::lock_guard lock(mMutex);
+ mUnexpectedNat64PrefixUpdates++;
+ if (event.netId == mNetId) {
+ mNat64PrefixAddress = (event.prefixOperation ==
+ IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED)
+ ? event.prefixAddress
+ : "";
+ }
return ::ndk::ScopedAStatus::ok();
}
@@ -77,4 +87,22 @@
return false;
}
+bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseconds& timeout) {
+ android::base::Timer t;
+ while (t.duration() < timeout) {
+ {
+ std::lock_guard lock(mMutex);
+ if ((operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED &&
+ !mNat64PrefixAddress.empty()) ||
+ (operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED &&
+ mNat64PrefixAddress.empty())) {
+ mUnexpectedNat64PrefixUpdates--;
+ return true;
+ }
+ }
+ std::this_thread::sleep_for(kRetryIntervalMs);
+ }
+ return false;
+}
+
} // namespace android::net::resolv::aidl
diff --git a/tests/unsolicited_listener/unsolicited_event_listener.h b/tests/unsolicited_listener/unsolicited_event_listener.h
index 5615f24..e8fce1d 100644
--- a/tests/unsolicited_listener/unsolicited_event_listener.h
+++ b/tests/unsolicited_listener/unsolicited_event_listener.h
@@ -44,15 +44,26 @@
// Wait for the expected private DNS validation result until timeout.
bool waitForPrivateDnsValidation(const std::string& serverAddr, int validation);
+ // Wait for expected NAT64 prefix operation until timeout.
+ bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout)
+ EXCLUDES(mMutex);
+
// Return true if a validation result for |serverAddr| is found; otherwise, return false.
bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) {
std::lock_guard lock(mMutex);
return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end();
}
+ // Returns the number of updates to the NAT64 prefix that have not yet been waited for.
+ int getUnexpectedNat64PrefixUpdates() const EXCLUDES(mMutex) {
+ std::lock_guard lock(mMutex);
+ return mUnexpectedNat64PrefixUpdates;
+ }
+
void reset() EXCLUDES(mMutex) {
std::lock_guard lock(mMutex);
mValidationRecords.clear();
+ mUnexpectedNat64PrefixUpdates = 0;
}
private:
@@ -68,6 +79,16 @@
// Used to store the data from onPrivateDnsValidationEvent.
std::map<ServerKey, int> mValidationRecords GUARDED_BY(mMutex);
+ // The NAT64 prefix address of the network |mNetId|. It is updated by onNat64PrefixEvent().
+ std::string mNat64PrefixAddress GUARDED_BY(mMutex);
+
+ // The number of updates to the NAT64 prefix of network |mNetId| that have not yet been waited
+ // for. Increases by 1 every time onNat64PrefixEvent is called, and decreases by 1 every time
+ // waitForNat64Prefix returns true.
+ // This allows tests to check that no unexpected events have been received without having to
+ // resort to timeouts that make the tests slower and flakier.
+ int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex);
+
mutable std::mutex mMutex;
std::condition_variable mCv;
};