aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Sun <sunytt@google.com>2024-01-25 09:56:07 +0800
committerYang Sun <sunytt@google.com>2024-02-26 17:52:20 +0800
commitd41c1ff7e17f83eb6eae04268392d1069dc88d7d (patch)
treeb1d391f8b746783f7174e5cde3e6ad9485d33c4f
parent12a11b59a345e671a6832aee066f3244daef96ba (diff)
downloadot-br-posix-d41c1ff7e17f83eb6eae04268392d1069dc88d7d.tar.gz
[BBR] Send full list of multicast listening addresses
When there is an update in the multicast listening addresses or update with the BBR state, send the BBR state including full list of the listening addresses in the IOtDaemonCallback to system server. Bug: 321624274 Test: atest ThreadNetworkIntegrationTests Change-Id: I49f4f7bbd9c1e733e861b3518f0602dd96700ca8
-rw-r--r--src/android/aidl/com/android/server/thread/openthread/BackboneRouterState.aidl41
-rw-r--r--src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl11
-rw-r--r--src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl2
-rw-r--r--src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java26
-rw-r--r--src/android/otdaemon_server.cpp87
-rw-r--r--src/android/otdaemon_server.hpp26
-rw-r--r--tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java19
7 files changed, 144 insertions, 68 deletions
diff --git a/src/android/aidl/com/android/server/thread/openthread/BackboneRouterState.aidl b/src/android/aidl/com/android/server/thread/openthread/BackboneRouterState.aidl
new file mode 100644
index 00000000..22bb3ba5
--- /dev/null
+++ b/src/android/aidl/com/android/server/thread/openthread/BackboneRouterState.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server.thread.openthread;
+
+/**
+ * Contains all backbone router states which the system_server and/or client apps care about.
+ */
+parcelable BackboneRouterState {
+ // true when multicast forwarding should be enabled when BackboneRoute is primary, false
+ // otherwise.
+ boolean multicastForwardingEnabled;
+
+ // The list of multicast group address subscribed in Thread network
+ List<String> listeningAddresses;
+}
diff --git a/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl b/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl
index 28686b10..afc07959 100644
--- a/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl
+++ b/src/android/aidl/com/android/server/thread/openthread/IOtDaemonCallback.aidl
@@ -28,6 +28,7 @@
package com.android.server.thread.openthread;
+import com.android.server.thread.openthread.BackboneRouterState;
import com.android.server.thread.openthread.Ipv6AddressInfo;
import com.android.server.thread.openthread.OtDaemonState;
@@ -54,14 +55,12 @@ oneway interface IOtDaemonCallback {
void onAddressChanged(in Ipv6AddressInfo addressInfo, boolean isAdded);
/**
- * Called when multicast forwarding listening address has been changed.
+ * Called when backbone router state or multicast forwarding listening addresses has been
+ * changed.
*
- * @param address the IPv6 address in bytes which has been updated. This is a multicast
- * address registered by multicast listeners
- * @param isAdded {@code true} if this multicast address is being added;
- * Otherwise, this multicast address is being removed
+ * @param bbrState the backbone router state
*/
- void onMulticastForwardingAddressChanged(in byte[] ipv6Address, boolean isAdded);
+ void onBackboneRouterStateChanged(in BackboneRouterState bbrState);
/**
* Called when Thread enabled state has changed. Valid values are STATE_* defined in
diff --git a/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl b/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl
index 5d4fbb88..c13a9492 100644
--- a/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl
+++ b/src/android/aidl/com/android/server/thread/openthread/OtDaemonState.aidl
@@ -48,6 +48,4 @@ parcelable OtDaemonState {
// Active Oprational Dataset encoded as Thread TLVs. Empty array means the dataset doesn't
// exist
byte[] pendingDatasetTlvs;
-
- boolean multicastForwardingEnabled;
}
diff --git a/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java b/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java
index 6cfe8d95..96d5db07 100644
--- a/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java
+++ b/src/android/java/com/android/server/thread/openthread/testing/FakeOtDaemon.java
@@ -39,6 +39,7 @@ import android.os.IBinder.DeathRecipient;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import com.android.server.thread.openthread.BackboneRouterState;
import com.android.server.thread.openthread.BorderRouterConfigurationParcel;
import com.android.server.thread.openthread.IChannelMasksReceiver;
import com.android.server.thread.openthread.INsdPublisher;
@@ -48,6 +49,7 @@ import com.android.server.thread.openthread.IOtStatusReceiver;
import com.android.server.thread.openthread.OtDaemonState;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.NoSuchElementException;
/** A fake implementation of the {@link IOtDaemon} AIDL API for testing. */
@@ -66,6 +68,7 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
private final Handler mHandler;
private final OtDaemonState mState;
+ private final BackboneRouterState mBbrState;
private int mThreadEnabled = OT_STATE_ENABLED;
private int mChannelMasksReceiverOtError = OT_ERROR_NONE;
private int mSupportedChannelMask = 0x07FFF800; // from channel 11 to 26
@@ -90,7 +93,9 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
mState.deviceRole = OT_DEVICE_ROLE_DISABLED;
mState.activeDatasetTlvs = new byte[0];
mState.pendingDatasetTlvs = new byte[0];
- mState.multicastForwardingEnabled = false;
+ mBbrState = new BackboneRouterState();
+ mBbrState.multicastForwardingEnabled = false;
+ mBbrState.listeningAddresses = new ArrayList<>();
}
@Override
@@ -167,6 +172,7 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
mCallbackListenerId = listenerId;
mHandler.post(() -> onStateChanged(mState, mCallbackListenerId));
+ mHandler.post(() -> onBackboneRouterStateChanged(mBbrState));
}
@Nullable
@@ -191,9 +197,10 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
() -> {
mState.deviceRole = OT_DEVICE_ROLE_LEADER;
mState.activeDatasetTlvs = activeDataset.clone();
- mState.multicastForwardingEnabled = true;
+ mBbrState.multicastForwardingEnabled = true;
onStateChanged(mState, PROACTIVE_LISTENER_ID);
+ onBackboneRouterStateChanged(mBbrState);
try {
receiver.onSuccess();
} catch (RemoteException e) {
@@ -205,14 +212,13 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
private void onStateChanged(OtDaemonState state, long listenerId) {
try {
- // Make a copy of mState so that clients won't keep a direct reference to it
+ // Make a copy of state so that clients won't keep a direct reference to it
OtDaemonState copyState = new OtDaemonState();
copyState.isInterfaceUp = state.isInterfaceUp;
copyState.deviceRole = state.deviceRole;
copyState.partitionId = state.partitionId;
copyState.activeDatasetTlvs = state.activeDatasetTlvs.clone();
copyState.pendingDatasetTlvs = state.pendingDatasetTlvs.clone();
- copyState.multicastForwardingEnabled = state.multicastForwardingEnabled;
mCallback.onStateChanged(copyState, listenerId);
} catch (RemoteException e) {
@@ -220,6 +226,18 @@ public final class FakeOtDaemon extends IOtDaemon.Stub {
}
}
+ private void onBackboneRouterStateChanged(BackboneRouterState state) {
+ try {
+ // Make a copy of state so that clients won't keep a direct reference to it
+ BackboneRouterState copyState = new BackboneRouterState();
+ copyState.multicastForwardingEnabled = state.multicastForwardingEnabled;
+ copyState.listeningAddresses = new ArrayList<>(state.listeningAddresses);
+ mCallback.onBackboneRouterStateChanged(copyState);
+ } catch (RemoteException e) {
+ throw new AssertionError(e);
+ }
+ }
+
/** Sets the {@link RemoteException} which will be thrown from {@link #join}. */
public void setJoinException(RemoteException exception) {
mJoinException = exception;
diff --git a/src/android/otdaemon_server.cpp b/src/android/otdaemon_server.cpp
index 599e1c9f..005400b6 100644
--- a/src/android/otdaemon_server.cpp
+++ b/src/android/otdaemon_server.cpp
@@ -151,6 +151,10 @@ void OtDaemonServer::StateCallback(otChangedFlags aFlags)
mCallback->onStateChanged(mState, -1);
}
}
+ if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
+ {
+ mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
+ }
}
void OtDaemonServer::AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer)
@@ -257,41 +261,56 @@ exit:
}
}
-void OtDaemonServer::HandleBackboneMulticastListenerEvent(void *aBinderServer,
- otBackboneRouterMulticastListenerEvent aEvent,
- const otIp6Address *aAddress)
+BackboneRouterState OtDaemonServer::GetBackboneRouterState()
{
- OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
-
- bool isAdded;
- std::vector<uint8_t> addressBytes(aAddress->mFields.m8, BYTE_ARR_END(aAddress->mFields.m8));
- char addressString[OT_IP6_ADDRESS_STRING_SIZE];
+ BackboneRouterState state;
+ otBackboneRouterState bbrState = otBackboneRouterGetState(GetOtInstance());
+ otBackboneRouterMulticastListenerInfo info;
+ otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
+ state.listeningAddresses = std::vector<std::string>();
- otIp6AddressToString(aAddress, addressString, sizeof(addressString));
+ if (mCallback == nullptr)
+ {
+ otbrLogWarning("OT daemon callback is not set");
+ return state;
+ }
- switch (aEvent)
+ switch (bbrState)
{
- case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED:
- isAdded = true;
+ case OT_BACKBONE_ROUTER_STATE_DISABLED:
+ case OT_BACKBONE_ROUTER_STATE_SECONDARY:
+ state.multicastForwardingEnabled = false;
break;
- case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_REMOVED:
- isAdded = false;
+ case OT_BACKBONE_ROUTER_STATE_PRIMARY:
+ state.multicastForwardingEnabled = true;
break;
- default:
- otbrLogErr("Got BackboneMulticastListenerEvent with unsupported event: %d", aEvent);
- assert(false);
}
+ otbrLogInfo("Updating backbone router state (bbr state = %d)", bbrState);
- otbrLogDebug("Multicast forwarding address changed, %s is %s", addressString, isAdded ? "added" : "removed");
-
- if (thisServer->mCallback != nullptr)
+ while (otBackboneRouterMulticastListenerGetNext(GetOtInstance(), &iter, &info) == OT_ERROR_NONE)
{
- thisServer->mCallback->onMulticastForwardingAddressChanged(addressBytes, isAdded);
- }
- else
- {
- otbrLogWarning("OT daemon callback is not set");
+ char string[OT_IP6_ADDRESS_STRING_SIZE];
+
+ otIp6AddressToString(&info.mAddress, string, sizeof(string));
+ state.listeningAddresses.push_back(string);
}
+
+ return state;
+}
+
+void OtDaemonServer::HandleBackboneMulticastListenerEvent(void *aBinderServer,
+ otBackboneRouterMulticastListenerEvent aEvent,
+ const otIp6Address *aAddress)
+{
+ OtDaemonServer *thisServer = static_cast<OtDaemonServer *>(aBinderServer);
+ char addressString[OT_IP6_ADDRESS_STRING_SIZE];
+
+ otIp6AddressToString(aAddress, addressString, sizeof(addressString));
+
+ otbrLogDebug("Multicast forwarding address changed, %s is %s", addressString,
+ (aEvent == OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED) ? "added" : "removed");
+
+ thisServer->mCallback->onBackboneRouterStateChanged(thisServer->GetBackboneRouterState());
}
otInstance *OtDaemonServer::GetOtInstance()
@@ -439,6 +458,7 @@ Status OtDaemonServer::registerStateCallback(const std::shared_ptr<IOtDaemonCall
RefreshOtDaemonState(/* aFlags */ 0xffffffff);
mCallback->onStateChanged(mState, listenerId);
mCallback->onThreadEnabledChanged(mThreadEnabled);
+ mCallback->onBackboneRouterStateChanged(GetBackboneRouterState());
exit:
return Status::ok();
@@ -494,23 +514,6 @@ bool OtDaemonServer::RefreshOtDaemonState(otChangedFlags aFlags)
haveUpdates = true;
}
- if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
- {
- otBackboneRouterState state = otBackboneRouterGetState(GetOtInstance());
-
- switch (state)
- {
- case OT_BACKBONE_ROUTER_STATE_DISABLED:
- case OT_BACKBONE_ROUTER_STATE_SECONDARY:
- mState.multicastForwardingEnabled = false;
- break;
- case OT_BACKBONE_ROUTER_STATE_PRIMARY:
- mState.multicastForwardingEnabled = true;
- break;
- }
- haveUpdates = true;
- }
-
if (isAttached() && !mState.activeDatasetTlvs.empty() && mJoinReceiver != nullptr)
{
mJoinReceiver->onSuccess();
diff --git a/src/android/otdaemon_server.hpp b/src/android/otdaemon_server.hpp
index 70403b9a..ab1a50ea 100644
--- a/src/android/otdaemon_server.hpp
+++ b/src/android/otdaemon_server.hpp
@@ -51,6 +51,7 @@ namespace Android {
using BinderDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient;
using ScopedFileDescriptor = ::ndk::ScopedFileDescriptor;
using Status = ::ndk::ScopedAStatus;
+using aidl::com::android::server::thread::openthread::BackboneRouterState;
using aidl::com::android::server::thread::openthread::BnOtDaemon;
using aidl::com::android::server::thread::openthread::BorderRouterConfigurationParcel;
using aidl::com::android::server::thread::openthread::IChannelMasksReceiver;
@@ -112,18 +113,19 @@ private:
void DetachGracefullyCallback(void);
static void SendMgmtPendingSetCallback(otError aResult, void *aBinderServer);
- static void BinderDeathCallback(void *aBinderServer);
- void StateCallback(otChangedFlags aFlags);
- static void AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer);
- static void ReceiveCallback(otMessage *aMessage, void *aBinderServer);
- void ReceiveCallback(otMessage *aMessage);
- void TransmitCallback(void);
- static void HandleBackboneMulticastListenerEvent(void *aBinderServer,
- otBackboneRouterMulticastListenerEvent aEvent,
- const otIp6Address *aAddress);
- void PushTelemetryIfConditionMatch();
- void updateThreadEnabledState(const int aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver);
- void enableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver);
+ static void BinderDeathCallback(void *aBinderServer);
+ void StateCallback(otChangedFlags aFlags);
+ static void AddressCallback(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aBinderServer);
+ static void ReceiveCallback(otMessage *aMessage, void *aBinderServer);
+ void ReceiveCallback(otMessage *aMessage);
+ void TransmitCallback(void);
+ BackboneRouterState GetBackboneRouterState(void);
+ static void HandleBackboneMulticastListenerEvent(void *aBinderServer,
+ otBackboneRouterMulticastListenerEvent aEvent,
+ const otIp6Address *aAddress);
+ void PushTelemetryIfConditionMatch();
+ void updateThreadEnabledState(const int aEnabled, const std::shared_ptr<IOtStatusReceiver> &aReceiver);
+ void enableThread(const std::shared_ptr<IOtStatusReceiver> &aReceiver);
int mThreadEnabled = IOtDaemon::OT_STATE_DISABLED;
otbr::Ncp::ControllerOpenThread &mNcp;
diff --git a/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java b/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java
index e5fd72cc..adf16d20 100644
--- a/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java
+++ b/tests/android/java/com/android/server/thread/openthread/testing/FakeOtDaemonTest.java
@@ -45,6 +45,7 @@ import android.os.test.TestLooper;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.server.thread.openthread.BackboneRouterState;
import com.android.server.thread.openthread.IChannelMasksReceiver;
import com.android.server.thread.openthread.INsdPublisher;
import com.android.server.thread.openthread.IOtDaemonCallback;
@@ -120,6 +121,7 @@ public final class FakeOtDaemonTest {
mFakeOtDaemon.initialize(mMockTunFd, true, mMockNsdPublisher);
final AtomicReference<OtDaemonState> stateRef = new AtomicReference<>();
final AtomicLong listenerIdRef = new AtomicLong();
+ final AtomicReference<BackboneRouterState> bbrStateRef = new AtomicReference<>();
mFakeOtDaemon.registerStateCallback(
new IOtDaemonCallback.Default() {
@@ -128,6 +130,11 @@ public final class FakeOtDaemonTest {
stateRef.set(newState);
listenerIdRef.set(listenerId);
}
+
+ @Override
+ public void onBackboneRouterStateChanged(BackboneRouterState bbrState) {
+ bbrStateRef.set(bbrState);
+ }
},
7 /* listenerId */);
mTestLooper.dispatchAll();
@@ -138,8 +145,9 @@ public final class FakeOtDaemonTest {
assertThat(state.deviceRole).isEqualTo(FakeOtDaemon.OT_DEVICE_ROLE_DISABLED);
assertThat(state.activeDatasetTlvs).isEmpty();
assertThat(state.pendingDatasetTlvs).isEmpty();
- assertThat(state.multicastForwardingEnabled).isFalse();
assertThat(listenerIdRef.get()).isEqualTo(7);
+ BackboneRouterState bbrState = bbrStateRef.get();
+ assertThat(bbrState.multicastForwardingEnabled).isFalse();
}
@Test
@@ -162,12 +170,18 @@ public final class FakeOtDaemonTest {
public void join_succeed_statesAreSentBack() throws Exception {
final AtomicBoolean succeedRef = new AtomicBoolean(false);
final AtomicReference<OtDaemonState> stateRef = new AtomicReference<>();
+ final AtomicReference<BackboneRouterState> bbrStateRef = new AtomicReference<>();
mFakeOtDaemon.registerStateCallback(
new IOtDaemonCallback.Default() {
@Override
public void onStateChanged(OtDaemonState newState, long listenerId) {
stateRef.set(newState);
}
+
+ @Override
+ public void onBackboneRouterStateChanged(BackboneRouterState bbrState) {
+ bbrStateRef.set(bbrState);
+ }
},
11 /* listenerId */);
@@ -192,7 +206,8 @@ public final class FakeOtDaemonTest {
assertThat(state.isInterfaceUp).isTrue();
assertThat(state.deviceRole).isEqualTo(FakeOtDaemon.OT_DEVICE_ROLE_LEADER);
assertThat(state.activeDatasetTlvs).isEqualTo(DEFAULT_ACTIVE_DATASET_TLVS);
- assertThat(state.multicastForwardingEnabled).isTrue();
+ final BackboneRouterState bbrState = bbrStateRef.get();
+ assertThat(bbrState.multicastForwardingEnabled).isTrue();
}
@Test