Skip to content

Commit

Permalink
Add a FabricTable API to get the next available fabric index. (#28391)
Browse files Browse the repository at this point in the history
* Add a FabricTable API to get the next available fabric index.

This can be used during controller startup to map the fabric index (which is
allocated to the controller partway through startup and then used immediately
for storage keys) to the controller instance being started.

* Address review comments.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Aug 21, 2023
1 parent 887d106 commit 3b12679
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/credentials/FabricTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2080,4 +2080,19 @@ CHIP_ERROR FabricTable::GetFabricLabel(FabricIndex fabricIndex, CharSpan & outFa
return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::PeekFabricIndexForNextAddition(FabricIndex & outIndex)
{
EnsureNextAvailableFabricIndexUpdated();
if (!mNextAvailableFabricIndex.HasValue())
{
return CHIP_ERROR_NO_MEMORY;
}

FabricIndex index = mNextAvailableFabricIndex.Value();
VerifyOrReturnError(IsValidFabricIndex(index), CHIP_ERROR_INVALID_FABRIC_INDEX);

outIndex = index;
return CHIP_NO_ERROR;
}

} // namespace chip
8 changes: 8 additions & 0 deletions src/credentials/FabricTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,14 @@ class DLL_EXPORT FabricTable
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

/**
* Get the fabric index that will be used for the next fabric that will be
* added. Returns error if no more fabrics can be added, otherwise writes
* the fabric index that will be used for the next addition into the
* outparam.
*/
CHIP_ERROR PeekFabricIndexForNextAddition(FabricIndex & outIndex);

private:
enum class StateFlags : uint16_t
{
Expand Down
89 changes: 89 additions & 0 deletions src/credentials/tests/TestFabricTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,12 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)

NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 0);

{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 1);
}

size_t numFabricsIterated = 0;

size_t numStorageKeysAtStart = storage.GetNumKeys();
Expand Down Expand Up @@ -588,6 +594,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
// No storage yet
NL_TEST_ASSERT(inSuite, storage.GetNumKeys() == numStorageKeysAtStart);

// Next fabric index has not been updated yet.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 1);
}

// Validate iterator sees pending
{
numFabricsIterated = 0;
Expand All @@ -612,6 +625,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)

NL_TEST_ASSERT(inSuite, storage.GetNumKeys() == (numStorageKeysAtStart + 4)); // 2 opcerts + fabric metadata + index

// Next fabric index has been updated.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 2);
}

// Validate contents
const auto * fabricInfo = fabricTable.FindFabricWithIndex(1);
NL_TEST_ASSERT(inSuite, fabricInfo != nullptr);
Expand Down Expand Up @@ -679,6 +699,14 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
ByteSpan noc = fabric44CertAuthority.GetNoc();

NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 1);

// Next fabric index should still be the same as before.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 2);
}

NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AddNewPendingTrustedRootCert(rcac));
FabricIndex newFabricIndex = kUndefinedFabricIndex;

Expand All @@ -689,6 +717,12 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, newFabricIndex == 2);
// No storage yet
NL_TEST_ASSERT(inSuite, storage.GetNumKeys() == numStorageAfterFirstAdd);
// Next fabric index has not been updated yet.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 2);
}

// Commit, now storage should have keys
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.CommitPendingFabricData());
Expand All @@ -697,6 +731,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(),
(numStorageAfterFirstAdd + 5)); // 3 opcerts + fabric metadata + 1 operational key

// Next fabric index has been updated.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}

// Validate contents
const auto * fabricInfo = fabricTable.FindFabricWithIndex(2);
NL_TEST_ASSERT(inSuite, fabricInfo != nullptr);
Expand Down Expand Up @@ -879,6 +920,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, saw1 == true);
NL_TEST_ASSERT(inSuite, saw2 == true);
}

// Next fabric index has stayed the same.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}
}

size_t numStorageAfterUpdate = storage.GetNumKeys();
Expand All @@ -904,6 +952,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, fabricInfo->GetFabricLabel().data_equal(CharSpan{ "roboto", strlen("roboto") }));
}
}

// Next fabric index has stayed the same.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}
}

// Sequence 5: Remove FabricIndex 1 (FabricId 11, NodeId 55), make sure FabricIndex 2 (FabricId 44, NodeId 1000) still exists
Expand All @@ -917,6 +972,13 @@ void TestBasicAddNocUpdateNocFlow(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT_EQUALS(inSuite, storage.GetNumKeys(), (numStorageAfterUpdate - 3)); // Deleted NOC, RCAC, Metadata
}

// Next fabric index has stayed the same.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}

// Validate contents of Fabric Index 2 is still OK
const auto * fabricInfo = fabricTable.FindFabricWithIndex(2);
NL_TEST_ASSERT(inSuite, fabricInfo != nullptr);
Expand Down Expand Up @@ -1374,6 +1436,13 @@ void TestPersistence(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, saw1 == true);
NL_TEST_ASSERT(inSuite, saw2 == true);
}

// Next fabric index should now be 3, since we added 1 and 2 above.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}
}

// Global: Last known good time + fabric index = 2
Expand Down Expand Up @@ -1501,6 +1570,13 @@ void TestPersistence(nlTestSuite * inSuite, void * inContext)
CHIP_ERROR_INVALID_SIGNATURE);
}
}

// Validate that next fabric index is still 3;
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 3);
}
}
}

Expand Down Expand Up @@ -1544,6 +1620,12 @@ void TestAddNocFailSafe(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT_SUCCESS(inSuite, fabricTable.AddNewPendingTrustedRootCert(rcac));
FabricIndex newFabricIndex = kUndefinedFabricIndex;

{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 1);
}

NL_TEST_ASSERT_EQUALS(inSuite, fabricTable.FabricCount(), 0);
NL_TEST_ASSERT_SUCCESS(inSuite,
fabricTable.AddNewPendingFabricWithOperationalKeystore(noc, ByteSpan{}, kVendorId, &newFabricIndex));
Expand Down Expand Up @@ -1596,6 +1678,13 @@ void TestAddNocFailSafe(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, numFabricsIterated == 0);
NL_TEST_ASSERT(inSuite, saw1 == false);
}

// Validate next fabric index has not changed.
{
FabricIndex nextFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, fabricTable.PeekFabricIndexForNextAddition(nextFabricIndex) == CHIP_NO_ERROR);
NL_TEST_ASSERT_EQUALS(inSuite, nextFabricIndex, 1);
}
}

size_t numStorageAfterRevert = storage.GetNumKeys();
Expand Down

0 comments on commit 3b12679

Please sign in to comment.