Skip to content

Commit f7536b6

Browse files
NetworkCommissioning: Disconnect previous network when trying a new (project-chip#35256)
* NetworkCommissioning: disconnect previous network when attepmting a new connection on other endpoint * use linked list and disconnect driver when no connected network config * Add DisconnectFromNetwork for OpenThread and ESP32 platform * Update src/app/clusters/network-commissioning/network-commissioning.cpp Co-authored-by: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> * resolve comments * Use IntrusiveList and other minor tweaks * fix CI --------- Co-authored-by: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Co-authored-by: Karsten Sperling <ksperling@apple.com>
1 parent 60d6c6b commit f7536b6

7 files changed

+121
-1
lines changed

src/app/clusters/network-commissioning/network-commissioning.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,10 @@ CHIP_ERROR ThreadScanResponseToTLV::EncodeTo(TLV::TLVWriter & writer, TLV::Tag t
336336

337337
} // namespace
338338

339+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
340+
Instance::NetworkInstanceList Instance::sInstances;
341+
#endif
342+
339343
Instance::Instance(EndpointId aEndpointId, WiFiDriver * apDelegate) :
340344
CommandHandlerInterface(Optional<EndpointId>(aEndpointId), Id), AttributeAccessInterface(Optional<EndpointId>(aEndpointId), Id),
341345
mEndpointId(aEndpointId), mFeatureFlags(WiFiFeatures(apDelegate)), mpWirelessDriver(apDelegate), mpBaseDriver(apDelegate)
@@ -365,11 +369,23 @@ CHIP_ERROR Instance::Init()
365369
mLastNetworkingStatusValue.SetNull();
366370
mLastConnectErrorValue.SetNull();
367371
mLastNetworkIDLen = 0;
372+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
373+
if (!sInstances.Contains(this))
374+
{
375+
sInstances.PushBack(this);
376+
}
377+
#endif
368378
return CHIP_NO_ERROR;
369379
}
370380

371381
void Instance::Shutdown()
372382
{
383+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
384+
if (sInstances.Contains(this))
385+
{
386+
sInstances.Remove(this);
387+
}
388+
#endif
373389
mpBaseDriver->Shutdown();
374390
}
375391

@@ -1031,6 +1047,16 @@ void Instance::HandleConnectNetwork(HandlerContext & ctx, const Commands::Connec
10311047
mCurrentOperationBreadcrumb = req.breadcrumb;
10321048

10331049
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
1050+
// Per spec, lingering connections on any other interfaces need to be disconnected at this point.
1051+
for (auto & node : sInstances)
1052+
{
1053+
Instance * instance = static_cast<Instance *>(&node);
1054+
if (instance != this)
1055+
{
1056+
instance->DisconnectLingeringConnection();
1057+
}
1058+
}
1059+
10341060
mpWirelessDriver->ConnectNetwork(req.networkID, this);
10351061
#else
10361062
// In Non-concurrent mode postpone the final execution of ConnectNetwork until the operational
@@ -1150,6 +1176,29 @@ void Instance::HandleQueryIdentity(HandlerContext & ctx, const Commands::QueryId
11501176
}
11511177
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC
11521178

1179+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
1180+
void Instance::DisconnectLingeringConnection()
1181+
{
1182+
bool haveConnectedNetwork = false;
1183+
EnumerateAndRelease(mpBaseDriver->GetNetworks(), [&](const Network & network) {
1184+
if (network.connected)
1185+
{
1186+
haveConnectedNetwork = true;
1187+
return Loop::Break;
1188+
}
1189+
return Loop::Continue;
1190+
});
1191+
1192+
// If none of the configured networks is `connected`, we may have a
1193+
// lingering connection to a different network that we need to disconnect.
1194+
// Note: The driver may or may not be actually connected
1195+
if (!haveConnectedNetwork)
1196+
{
1197+
LogErrorOnFailure(mpWirelessDriver->DisconnectFromNetwork());
1198+
}
1199+
}
1200+
#endif
1201+
11531202
void Instance::OnResult(Status commissioningError, CharSpan debugText, int32_t interfaceStatus)
11541203
{
11551204
auto commandHandleRef = std::move(mAsyncCommandHandle);

src/app/clusters/network-commissioning/network-commissioning.h

+34-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <app/AttributeAccessInterface.h>
2323
#include <app/CommandHandlerInterface.h>
2424
#include <app/data-model/Nullable.h>
25+
#include <lib/support/IntrusiveList.h>
2526
#include <lib/support/ThreadOperationalDataset.h>
2627
#include <lib/support/Variant.h>
2728
#include <platform/NetworkCommissioning.h>
@@ -33,9 +34,17 @@ namespace app {
3334
namespace Clusters {
3435
namespace NetworkCommissioning {
3536

37+
// Instance inherits privately from this class to participate in Instance::sInstances
38+
class InstanceListNode : public IntrusiveListNodeBase<>
39+
{
40+
};
41+
3642
// TODO: Use macro to disable some wifi or thread
3743
class Instance : public CommandHandlerInterface,
3844
public AttributeAccessInterface,
45+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
46+
private InstanceListNode,
47+
#endif
3948
public DeviceLayer::NetworkCommissioning::Internal::BaseDriver::NetworkStatusChangeCallback,
4049
public DeviceLayer::NetworkCommissioning::Internal::WirelessDriver::ConnectCallback,
4150
public DeviceLayer::NetworkCommissioning::WiFiDriver::ScanCallback,
@@ -81,6 +90,17 @@ class Instance : public CommandHandlerInterface,
8190
void SendNonConcurrentConnectNetworkResponse();
8291
#endif
8392

93+
// TODO: This could be guarded by a separate multi-interface condition instead
94+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
95+
class NetworkInstanceList : public IntrusiveList<InstanceListNode>
96+
{
97+
public:
98+
~NetworkInstanceList() { this->Clear(); }
99+
};
100+
101+
static NetworkInstanceList sInstances;
102+
#endif
103+
84104
EndpointId mEndpointId = kInvalidEndpointId;
85105
const BitFlags<Feature> mFeatureFlags;
86106

@@ -111,6 +131,11 @@ class Instance : public CommandHandlerInterface,
111131
void SetLastNetworkId(ByteSpan lastNetworkId);
112132
void ReportNetworksListChanged() const;
113133

134+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
135+
// Disconnect if the current connection is not in the Networks list
136+
void DisconnectLingeringConnection();
137+
#endif
138+
114139
// Commits the breadcrumb value saved in mCurrentOperationBreadcrumb to the breadcrumb attribute in GeneralCommissioning
115140
// cluster. Will set mCurrentOperationBreadcrumb to NullOptional.
116141
void CommitSavedBreadcrumb();
@@ -133,7 +158,15 @@ class Instance : public CommandHandlerInterface,
133158
Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::WiFiDriver * apDelegate);
134159
Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::ThreadDriver * apDelegate);
135160
Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::EthernetDriver * apDelegate);
136-
virtual ~Instance() = default;
161+
virtual ~Instance()
162+
{
163+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
164+
if (IsInList())
165+
{
166+
sInstances.Remove(this);
167+
}
168+
#endif
169+
}
137170
};
138171

139172
// NetworkDriver for the devices that don't have / don't need a real network driver.

src/include/platform/NetworkCommissioning.h

+7
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,13 @@ class WirelessDriver : public Internal::BaseDriver
247247
* called inside ConnectNetwork.
248248
*/
249249
virtual void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) = 0;
250+
251+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
252+
/**
253+
* @brief Disconnect from network, if currently connected.
254+
*/
255+
virtual CHIP_ERROR DisconnectFromNetwork() { return CHIP_ERROR_NOT_IMPLEMENTED; }
256+
#endif
250257
};
251258
} // namespace Internal
252259

src/platform/ESP32/NetworkCommissioningDriver.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,18 @@ CHIP_ERROR ESPWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen,
264264
return ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled);
265265
}
266266

267+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
268+
CHIP_ERROR ESPWiFiDriver::DisconnectFromNetwork()
269+
{
270+
if (chip::DeviceLayer::Internal::ESP32Utils::IsStationProvisioned())
271+
{
272+
// Attaching to an empty network will disconnect the network.
273+
ReturnErrorOnFailure(ConnectWiFiNetwork(nullptr, 0, nullptr, 0));
274+
}
275+
return CHIP_NO_ERROR;
276+
}
277+
#endif
278+
267279
void ESPWiFiDriver::OnConnectWiFiNetwork()
268280
{
269281
if (mpConnectCallback)

src/platform/ESP32/NetworkCommissioningDriver.h

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ class ESPWiFiDriver final : public WiFiDriver
107107
Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override;
108108
Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override;
109109
void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override;
110+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
111+
CHIP_ERROR DisconnectFromNetwork() override;
112+
#endif
110113

111114
// WiFiDriver
112115
Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText,

src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,19 @@ void GenericThreadDriver::CheckInterfaceEnabled()
277277
#endif
278278
}
279279

280+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
281+
CHIP_ERROR GenericThreadDriver::DisconnectFromNetwork()
282+
{
283+
if (ThreadStackMgrImpl().IsThreadProvisioned())
284+
{
285+
Thread::OperationalDataset emptyNetwork = {};
286+
// Attach to an empty network will disconnect the driver.
287+
ReturnErrorOnFailure(ThreadStackMgrImpl().AttachToThreadNetwork(emptyNetwork, nullptr));
288+
}
289+
return CHIP_NO_ERROR;
290+
}
291+
#endif
292+
280293
size_t GenericThreadDriver::ThreadNetworkIterator::Count()
281294
{
282295
return driver->mStagingNetwork.IsCommissioned() ? 1 : 0;

src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h

+3
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class GenericThreadDriver final : public ThreadDriver
110110
Status RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override;
111111
Status ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) override;
112112
void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override;
113+
#if CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
114+
CHIP_ERROR DisconnectFromNetwork() override;
115+
#endif
113116

114117
// ThreadDriver
115118
Status AddOrUpdateNetwork(ByteSpan operationalDataset, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override;

0 commit comments

Comments
 (0)