Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Group] Fabric removal sync #15874

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint
err = mSessions.Init(&DeviceLayer::SystemLayer(), &mTransports, &mMessageCounterManager, &mDeviceStorage, &GetFabricTable());
SuccessOrExit(err);

err = mFabricDelegate.Init(&mSessions);
SuccessOrExit(err);
mFabrics.AddFabricDelegate(&mFabricDelegate);

err = mExchangeMgr.Init(&mSessions);
SuccessOrExit(err);
err = mMessageCounterManager.Init(&mExchangeMgr);
Expand Down
35 changes: 35 additions & 0 deletions src/app/server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,40 @@ class Server
ServerTransportMgr * mTransports;
};

class ServerFabricDelegate final : public FabricTableDelegate
{
public:
ServerFabricDelegate() {}

CHIP_ERROR Init(SessionManager * sessionManager)
{
VerifyOrReturnError(sessionManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

mSessionManager = sessionManager;
return CHIP_NO_ERROR;
};

void OnFabricDeletedFromStorage(CompressedFabricId compressedId, FabricIndex fabricIndex) override
{
(void) compressedId;
if (mSessionManager != nullptr)
{
mSessionManager->FabricRemoved(fabricIndex);
}
Credentials::GroupDataProvider * groupDataProvider = Credentials::GetGroupDataProvider();
if (groupDataProvider != nullptr)
{
groupDataProvider->RemoveFabric(fabricIndex);
}
};
void OnFabricRetrievedFromStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }

void OnFabricPersistedToStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }

private:
SessionManager * mSessionManager = nullptr;
};

#if CONFIG_NETWORK_LAYER_BLE
Ble::BleLayer * mBleLayer = nullptr;
#endif
Expand Down Expand Up @@ -198,6 +232,7 @@ class Server
Credentials::GroupDataProviderImpl mGroupsProvider;
app::DefaultAttributePersistenceProvider mAttributePersister;
GroupDataProviderListener mListener;
ServerFabricDelegate mFabricDelegate;

Access::AccessControl mAccessControl;

Expand Down
4 changes: 4 additions & 0 deletions src/controller/CHIPDeviceControllerFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)

ReturnErrorOnFailure(stateParams.fabricTable->Init(params.fabricIndependentStorage));

auto delegate = chip::Platform::MakeUnique<ControllerFabricDelegate>(stateParams.sessionMgr);
ReturnErrorOnFailure(stateParams.fabricTable->AddFabricDelegate(delegate.get()));
delegate.release();

ReturnErrorOnFailure(stateParams.sessionMgr->Init(stateParams.systemLayer, stateParams.transportMgr,
stateParams.messageCounterManager, params.fabricIndependentStorage,
stateParams.fabricTable));
Expand Down
36 changes: 36 additions & 0 deletions src/controller/CHIPDeviceControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <controller/CHIPDeviceController.h>
#include <controller/CHIPDeviceControllerSystemState.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>

namespace chip {
Expand Down Expand Up @@ -137,6 +138,41 @@ class DeviceControllerFactory
//
void ReleaseSystemState() { mSystemState->Release(); }

class ControllerFabricDelegate final : public FabricTableDelegate
{
public:
ControllerFabricDelegate() {}
ControllerFabricDelegate(SessionManager * sessionManager) : FabricTableDelegate(true), mSessionManager(sessionManager) {}

CHIP_ERROR Init(SessionManager * sessionManager)
{
VerifyOrReturnError(sessionManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

mSessionManager = sessionManager;
return CHIP_NO_ERROR;
};

void OnFabricDeletedFromStorage(CompressedFabricId compressedId, FabricIndex fabricIndex) override
{
if (mSessionManager != nullptr)
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
{
mSessionManager->FabricRemoved(fabricIndex);
}
Credentials::GroupDataProvider * groupDataProvider = Credentials::GetGroupDataProvider();
if (groupDataProvider != nullptr)
{
groupDataProvider->RemoveFabric(fabricIndex);
}
};

void OnFabricRetrievedFromStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }

void OnFabricPersistedToStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }

private:
SessionManager * mSessionManager = nullptr;
};

private:
DeviceControllerFactory(){};
void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params);
Expand Down
16 changes: 16 additions & 0 deletions src/credentials/FabricTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,20 @@ CHIP_ERROR FabricInfo::MatchDestinationID(const ByteSpan & targetDestinationId,
return CHIP_ERROR_CERT_NOT_TRUSTED;
}

FabricTable::~FabricTable()
{
FabricTableDelegate * delegate = mDelegate;
while (delegate)
{
FabricTableDelegate * temp = delegate->mNext;
if (delegate->mOwnedByFabricTable)
{
chip::Platform::Delete(delegate);
}
delegate = temp;
}
}

void FabricTable::ReleaseFabricIndex(FabricIndex fabricIndex)
{
FabricInfo * fabric = FindFabricWithIndex(fabricIndex);
Expand Down Expand Up @@ -629,6 +643,7 @@ CHIP_ERROR FabricTable::Delete(FabricIndex index)
mFabricCount--;
}
ChipLogProgress(Discovery, "Fabric (%d) deleted. Calling OnFabricDeletedFromStorage", index);

FabricTableDelegate * delegate = mDelegate;
while (delegate)
{
Expand All @@ -651,6 +666,7 @@ void FabricTable::DeleteAllFabrics()
CHIP_ERROR FabricTable::Init(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

mStorage = storage;
ChipLogDetail(Discovery, "Init fabric pairing table with server storage");

Expand Down
4 changes: 4 additions & 0 deletions src/credentials/FabricTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ class DLL_EXPORT FabricTableDelegate
friend class FabricTable;

public:
FabricTableDelegate(bool ownedByFabricTable = false) : mOwnedByFabricTable(ownedByFabricTable) {}
virtual ~FabricTableDelegate() {}
/**
* Gets called when a fabric is deleted from KVS store.
Expand All @@ -292,6 +293,7 @@ class DLL_EXPORT FabricTableDelegate

private:
FabricTableDelegate * mNext = nullptr;
bool mOwnedByFabricTable = false;
};

/**
Expand Down Expand Up @@ -365,6 +367,8 @@ class DLL_EXPORT FabricTable
{
public:
FabricTable() { Reset(); }
~FabricTable();

CHIP_ERROR Store(FabricIndex index);
CHIP_ERROR LoadFromStorage(FabricInfo * info);

Expand Down
2 changes: 1 addition & 1 deletion src/credentials/GroupDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ class GroupDataProvider
/**
* Callback invoked when an existing group is removed.
*
* @param[in] removed_state GroupInfo structure of the removed group.
* @param[in] old_group GroupInfo structure of the removed group.
*/
virtual void OnGroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group) = 0;
};
Expand Down
59 changes: 45 additions & 14 deletions src/transport/GroupPeerMessageCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,27 +151,36 @@ CHIP_ERROR GroupPeerTable::RemovePeer(FabricIndex fabricIndex, NodeId nodeId, bo
{
if (mGroupFabrics[fabricIt].mDataPeerCount == 0 && mGroupFabrics[fabricIt].mControlPeerCount == 0)
{
mGroupFabrics[fabricIt].mFabricIndex = kUndefinedFabricIndex;
// To maintain logic integrity Fabric array cannot have empty slot in between data
// Find the last non empty element
for (uint32_t i = CHIP_CONFIG_MAX_FABRICS - 1; i > fabricIt; i--)
{
if (mGroupFabrics[i].mFabricIndex != kUndefinedFabricIndex)
{
// Logic works since all buffer are static
// move it up front
new (&mGroupFabrics[fabricIt]) GroupFabric(mGroupFabrics[i]);
new (&mGroupFabrics[i]) GroupFabric();
break;
}
}
RemoveAndCompactFabric(fabricIt);
}
}

// Cannot find Peer to remove
return err;
}

CHIP_ERROR GroupPeerTable::FabricRemoved(FabricIndex fabricIndex)
{
CHIP_ERROR err = CHIP_ERROR_NOT_FOUND;

if (fabricIndex == kUndefinedFabricIndex)
{
return CHIP_ERROR_INVALID_ARGUMENT;
}

for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
{
if (fabricIndex == mGroupFabrics[it].mFabricIndex)
{
RemoveAndCompactFabric(it);
return CHIP_NO_ERROR;
}
}

// Cannot find Fabric to remove
return err;
}

bool GroupPeerTable::RemoveSpecificPeer(GroupSender * list, NodeId nodeId, uint32_t size)
{
bool removed = false;
Expand Down Expand Up @@ -222,6 +231,28 @@ void GroupPeerTable::CompactPeers(GroupSender * list, uint32_t size)
}
}

void GroupPeerTable::RemoveAndCompactFabric(uint32_t tableIndex)
{
if (tableIndex >= CHIP_CONFIG_MAX_FABRICS)
{
return;
}
mGroupFabrics[tableIndex].mFabricIndex = kUndefinedFabricIndex;
// To maintain logic integrity Fabric array cannot have empty slot in between data
// Find the last non empty element
for (uint32_t i = CHIP_CONFIG_MAX_FABRICS - 1; i > tableIndex; i--)
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved
{
if (mGroupFabrics[i].mFabricIndex != kUndefinedFabricIndex)
{
// Logic works since all buffer are static
// move it up front
new (&mGroupFabrics[tableIndex]) GroupFabric(mGroupFabrics[i]);
new (&mGroupFabrics[i]) GroupFabric();
break;
}
}
}

GroupOutgoingCounters::GroupOutgoingCounters(chip::PersistentStorageDelegate * storage_delegate)
{
Init(storage_delegate);
Expand Down
3 changes: 3 additions & 0 deletions src/transport/GroupPeerMessageCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ class GroupPeerTable
// Used in case of MCSP failure
CHIP_ERROR RemovePeer(FabricIndex fabricIndex, NodeId nodeId, bool isControl);

CHIP_ERROR FabricRemoved(FabricIndex fabricIndex);

// Protected for Unit Tests inheritance
protected:
bool RemoveSpecificPeer(GroupSender * list, NodeId nodeId, uint32_t size);
void CompactPeers(GroupSender * list, uint32_t size);
void RemoveAndCompactFabric(uint32_t tableIndex);

GroupFabric mGroupFabrics[CHIP_CONFIG_MAX_FABRICS];
};
Expand Down
11 changes: 11 additions & 0 deletions src/transport/SessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ void SessionManager::Shutdown()
mCB = nullptr;
}

/**
* @brief Notification that a fabric was removed.
* This function doesn't call ExpireAllPairingsForFabric
* since the CASE session might still be open to send a response
* on the removed fabric.
*/
void SessionManager::FabricRemoved(FabricIndex fabricIndex)
{
mGroupPeerMsgCounter.FabricRemoved(fabricIndex);
}

CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
{
Expand Down
5 changes: 5 additions & 0 deletions src/transport/SessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate
*/
void Shutdown();

/**
* @brief Notification that a fabric was removed.
*/
void FabricRemoved(FabricIndex fabricIndex);

TransportMgrBase * GetTransportManager() const { return mTransportMgr; }

/**
Expand Down
24 changes: 23 additions & 1 deletion src/transport/tests/TestGroupMessageCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void RemovePeerTest(nlTestSuite * inSuite, void * inContext)
FabricIndex fabricIndex = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
chip::Transport::GroupPeerTable mGroupPeerMsgCounter;
TestGroupPeerTable mGroupPeerMsgCounter;

// Fill table up (max fabric and mac peer)
for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
Expand Down Expand Up @@ -165,6 +165,28 @@ void RemovePeerTest(nlTestSuite * inSuite, void * inContext)
// Try re-adding the previous peer without any error
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = mGroupPeerMsgCounter.FindOrAddPeer(104, 99, true, counter);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = mGroupPeerMsgCounter.FindOrAddPeer(105, 99, true, counter);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = mGroupPeerMsgCounter.FindOrAddPeer(106, 99, true, counter);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

// Fabric removal test
err = mGroupPeerMsgCounter.FabricRemoved(123);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NOT_FOUND);

err = mGroupPeerMsgCounter.FabricRemoved(99);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = mGroupPeerMsgCounter.FabricRemoved(99);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NOT_FOUND);
jepenven-silabs marked this conversation as resolved.
Show resolved Hide resolved

// Verify that the Fabric List was compacted.
NL_TEST_ASSERT(inSuite, 106 == mGroupPeerMsgCounter.GetFabricIndexAt(0));
}

void PeerRetrievalTest(nlTestSuite * inSuite, void * inContext)
Expand Down