Skip to content

Commit 67e8110

Browse files
Add DeviceController deleteFromFabricTableOnShutdown option (project-chip#32846)
* Add DeviceController deleteFromFabricTableOnShutdown option This is analogous to removeFromFabricTableOnShutdown but does an actual Delete(), i.e. affects storage, rather than just a Forget(). Use this to simplify controller shutdown on Darwin. * Address review comments
1 parent 9080cd3 commit 67e8110

7 files changed

+62
-59
lines changed

src/controller/CHIPDeviceController.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ CHIP_ERROR DeviceController::Init(ControllerInitParams params)
136136
mState = State::Initialized;
137137

138138
mRemoveFromFabricTableOnShutdown = params.removeFromFabricTableOnShutdown;
139+
mDeleteFromFabricTableOnShutdown = params.deleteFromFabricTableOnShutdown;
139140

140141
if (GetFabricIndex() != kUndefinedFabricIndex)
141142
{
@@ -382,8 +383,9 @@ void DeviceController::Shutdown()
382383

383384
VerifyOrReturn(mState != State::NotInitialized);
384385

386+
// If our state is initialialized it means mSystemState is valid,
387+
// and we can use it below before we release our reference to it.
385388
ChipLogDetail(Controller, "Shutting down the controller");
386-
387389
mState = State::NotInitialized;
388390

389391
if (mFabricIndex != kUndefinedFabricIndex)
@@ -401,13 +403,13 @@ void DeviceController::Shutdown()
401403
// existing sessions too?
402404
mSystemState->SessionMgr()->ExpireAllSessionsForFabric(mFabricIndex);
403405

404-
if (mRemoveFromFabricTableOnShutdown)
406+
if (mDeleteFromFabricTableOnShutdown)
405407
{
406-
FabricTable * fabricTable = mSystemState->Fabrics();
407-
if (fabricTable != nullptr)
408-
{
409-
fabricTable->Forget(mFabricIndex);
410-
}
408+
mSystemState->Fabrics()->Delete(mFabricIndex);
409+
}
410+
else if (mRemoveFromFabricTableOnShutdown)
411+
{
412+
mSystemState->Fabrics()->Forget(mFabricIndex);
411413
}
412414
}
413415

src/controller/CHIPDeviceController.h

+19-6
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,27 @@ struct ControllerInitParams
126126

127127
/**
128128
* Controls whether shutdown of the controller removes the corresponding
129-
* entry from the fabric table. For now the removal is just from the
130-
* in-memory table, not from storage, which means that after controller
131-
* shutdown the storage and the in-memory fabric table will be out of sync.
132-
* This is acceptable for implementations that don't actually store any of
133-
* the fabric table information, but if someone wants a true removal at some
134-
* point another option will need to be added here.
129+
* entry from the in-memory fabric table, but NOT from storage.
130+
*
131+
* Note that this means that after controller shutdown the storage and
132+
* in-memory versions of the fabric table will be out of sync.
133+
* For compatibility reasons this is the default behavior.
134+
*
135+
* @see deleteFromFabricTableOnShutdown
135136
*/
136137
bool removeFromFabricTableOnShutdown = true;
137138

139+
/**
140+
* Controls whether shutdown of the controller deletes the corresponding
141+
* entry from the fabric table (both in-memory and storage).
142+
*
143+
* If both `removeFromFabricTableOnShutdown` and this setting are true,
144+
* this setting will take precedence.
145+
*
146+
* @see removeFromFabricTableOnShutdown
147+
*/
148+
bool deleteFromFabricTableOnShutdown = false;
149+
138150
/**
139151
* Specifies whether to utilize the fabric table entry for the given FabricIndex
140152
* for initialization. If provided and neither the operational key pair nor the NOC
@@ -394,6 +406,7 @@ class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController
394406
FabricIndex mFabricIndex = kUndefinedFabricIndex;
395407

396408
bool mRemoveFromFabricTableOnShutdown = true;
409+
bool mDeleteFromFabricTableOnShutdown = false;
397410

398411
FabricTable::AdvertiseIdentity mAdvertiseIdentity = FabricTable::AdvertiseIdentity::Yes;
399412

src/controller/CHIPDeviceControllerFactory.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ void DeviceControllerFactory::PopulateInitParams(ControllerInitParams & controll
305305
controllerParams.controllerRCAC = params.controllerRCAC;
306306
controllerParams.permitMultiControllerFabrics = params.permitMultiControllerFabrics;
307307
controllerParams.removeFromFabricTableOnShutdown = params.removeFromFabricTableOnShutdown;
308+
controllerParams.deleteFromFabricTableOnShutdown = params.deleteFromFabricTableOnShutdown;
308309

309310
controllerParams.systemState = mSystemState;
310311
controllerParams.controllerVendorId = params.controllerVendorId;

src/controller/CHIPDeviceControllerFactory.h

+18-6
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,27 @@ struct SetupParams
9393

9494
/**
9595
* Controls whether shutdown of the controller removes the corresponding
96-
* entry from the fabric table. For now the removal is just from the
97-
* in-memory table, not from storage, which means that after controller
98-
* shutdown the storage and the in-memory fabric table will be out of sync.
99-
* This is acceptable for implementations that don't actually store any of
100-
* the fabric table information, but if someone wants a true removal at some
101-
* point another option will need to be added here.
96+
* entry from the in-memory fabric table, but NOT from storage.
97+
*
98+
* Note that this means that after controller shutdown the storage and
99+
* in-memory versions of the fabric table will be out of sync.
100+
* For compatibility reasons this is the default behavior.
101+
*
102+
* @see deleteFromFabricTableOnShutdown
102103
*/
103104
bool removeFromFabricTableOnShutdown = true;
104105

106+
/**
107+
* Controls whether shutdown of the controller deletes the corresponding
108+
* entry from the fabric table (both in-memory and storage).
109+
*
110+
* If both `removeFromFabricTableOnShutdown` and this setting are true,
111+
* this setting will take precedence.
112+
*
113+
* @see removeFromFabricTableOnShutdown
114+
*/
115+
bool deleteFromFabricTableOnShutdown = false;
116+
105117
/**
106118
* Specifies whether to utilize the fabric table entry for the given FabricIndex
107119
* for initialization. If provided and neither the operational key pair nor the NOC

src/darwin/Framework/CHIP/MTRDeviceController.mm

+8-4
Original file line numberDiff line numberDiff line change
@@ -509,11 +509,15 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
509509
}
510510
commissionerParams.controllerVendorId = static_cast<chip::VendorId>([startupParams.vendorID unsignedShortValue]);
511511
commissionerParams.enableServerInteractions = startupParams.advertiseOperational;
512-
// We don't want to remove things from the fabric table on controller
513-
// shutdown, since our controller setup depends on being able to fetch
514-
// fabric information for the relevant fabric indices on controller
515-
// bring-up.
512+
513+
// We never want plain "removal" from the fabric table since this leaves
514+
// the in-memory state out of sync with what's in storage. In per-controller
515+
// storage mode, have the controller delete itself from the fabric table on shutdown.
516+
// In factory storage mode we need to keep fabric information around so we can
517+
// start another controller on that existing fabric at a later time.
516518
commissionerParams.removeFromFabricTableOnShutdown = false;
519+
commissionerParams.deleteFromFabricTableOnShutdown = (startupParams.storageDelegate != nil);
520+
517521
commissionerParams.permitMultiControllerFabrics = startupParams.allowMultipleControllersPerFabric;
518522

519523
// Set up our attestation verifier. Assume we want to use the default

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm

-28
Original file line numberDiff line numberDiff line change
@@ -1082,22 +1082,6 @@ - (void)controllerShuttingDown:(MTRDeviceController *)controller
10821082
}
10831083

10841084
sharedCleanupBlock();
1085-
1086-
// Now that our per-controller storage for the controller being shut
1087-
// down is guaranteed to be disconnected, go ahead and clean up the
1088-
// fabric table entry for the controller if we're in per-controller
1089-
// storage mode.
1090-
if (self->_usingPerControllerStorage) {
1091-
// We have to use a new fabric table to do this cleanup, because
1092-
// our system state is gone now.
1093-
FabricTable fabricTable;
1094-
CHIP_ERROR err = [self _initFabricTable:fabricTable];
1095-
if (err != CHIP_NO_ERROR) {
1096-
MTR_LOG_ERROR("Failed to clean up fabric entries. Expect things to act oddly: %" CHIP_ERROR_FORMAT, err.Format());
1097-
} else {
1098-
fabricTable.Delete(controllerFabricIndex);
1099-
}
1100-
}
11011085
} else {
11021086
// Do the controller shutdown on the Matter work queue.
11031087
dispatch_sync(_chipWorkQueue, ^{
@@ -1106,18 +1090,6 @@ - (void)controllerShuttingDown:(MTRDeviceController *)controller
11061090
}
11071091

11081092
sharedCleanupBlock();
1109-
1110-
// Now that our per-controller storage for the controller being shut
1111-
// down is guaranteed to be disconnected, go ahead and clean up the
1112-
// fabric table entry for the controller if we're in per-controller
1113-
// storage mode.
1114-
if (self->_usingPerControllerStorage) {
1115-
// Make sure to delete controllerFabricIndex from the system state's
1116-
// fabric table. We know there's a system state here, because we
1117-
// still have a running controller.
1118-
auto * systemState = _controllerFactory->GetSystemState();
1119-
systemState->Fabrics()->Delete(controllerFabricIndex);
1120-
}
11211093
});
11221094
}
11231095

src/darwin/Framework/CHIP/MTRSessionResumptionStorageBridge.mm

+7-8
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,19 @@
104104
{
105105
assertChipStackLockedByCurrentThread();
106106

107-
// NOTE: During controller startup, the Matter SDK thinks that the cert for
108-
// a fabric index is changing and hence that it must remove session
109-
// resumption data for that fabric index. For us that does not matter,
110-
// since we don't key that data on fabric index anyway. But we do want to
111-
// avoid doing this delete-on-startup so we can actually store session
112-
// resumption data persistently.
107+
// NOTE: During controller startup and shutdown, the SDK DeviceControllerFactory
108+
// calls this method from ClearCASEResumptionStateOnFabricChange() due to fabric
109+
// update or removal. For us that does not matter, since we don't key resumption
110+
// data on fabric index anyway. But we do want to avoid executing the DeleteAll
111+
// so we can actually store session resumption data persistently.
113112

114113
// And that is the only use of DeleteAll for controllers in practice, in the
115114
// situations where we are using MTRSessionResumptionStorageBridge at all.
116115
// So just no-op this function, but verify that our assumptions hold.
117116
auto * controller = [mFactory runningControllerForFabricIndex:fabricIndex
118117
includeControllerStartingUp:NO
119-
includeControllerShuttingDown:YES];
120-
VerifyOrDieWithMsg(controller == nil, Controller, "Deleting resumption storage for controller outside startup");
118+
includeControllerShuttingDown:NO];
119+
VerifyOrDieWithMsg(controller == nil, Controller, "ResumptionStorage::DeleteAll called for running controller");
121120
return CHIP_NO_ERROR;
122121
}
123122

0 commit comments

Comments
 (0)