Skip to content

Commit

Permalink
Invalidate obsolete fabric-scoped event in circular event buffer (#18016
Browse files Browse the repository at this point in the history
)
  • Loading branch information
yunhanw-google authored May 5, 2022
1 parent c25e184 commit c438b89
Show file tree
Hide file tree
Showing 6 changed files with 397 additions and 4 deletions.
74 changes: 71 additions & 3 deletions src/app/EventManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ CHIP_ERROR EventManagement::ConstructEvent(EventLoadOutContext * apContext, Even

// The fabricIndex profile tag is internal use only for fabric filtering when retrieving event from circular event buffer,
// and would not go on the wire.
// Revisit FabricRemovedCB function should the encoding of fabricIndex change in the future.
if (apOptions->mFabricIndex != kUndefinedFabricIndex)
{
apContext->mWriter.Put(TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag), apOptions->mFabricIndex);
Expand Down Expand Up @@ -570,7 +571,9 @@ CHIP_ERROR EventManagement::CheckEventContext(EventLoadOutContext * eventLoadOut
return CHIP_ERROR_UNEXPECTED_EVENT;
}

if (event.mFabricIndex != kUndefinedFabricIndex && eventLoadOutContext->mSubjectDescriptor.fabricIndex != event.mFabricIndex)
if (event.mFabricIndex.HasValue() &&
(event.mFabricIndex.Value() == kUndefinedFabricIndex ||
eventLoadOutContext->mSubjectDescriptor.fabricIndex != event.mFabricIndex.Value()))
{
return CHIP_ERROR_UNEXPECTED_EVENT;
}
Expand Down Expand Up @@ -748,6 +751,69 @@ CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, const ObjectLi
return err;
}

CHIP_ERROR EventManagement::FabricRemovedCB(const TLV::TLVReader & aReader, size_t aDepth, void * apContext)
{
// the function does not actually remove the event, instead, it sets the fabric index to an invalid value.
FabricIndex * invalidFabricIndex = static_cast<FabricIndex *>(apContext);

TLVReader event;
TLVType tlvType;
TLVType tlvType1;
event.Init(aReader);
VerifyOrReturnError(event.EnterContainer(tlvType) == CHIP_NO_ERROR, CHIP_NO_ERROR);
VerifyOrReturnError(event.Next(TLV::ContextTag(to_underlying(EventReportIB::Tag::kEventData))) == CHIP_NO_ERROR, CHIP_NO_ERROR);
VerifyOrReturnError(event.EnterContainer(tlvType1) == CHIP_NO_ERROR, CHIP_NO_ERROR);

while (CHIP_NO_ERROR == event.Next())
{
if (event.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
{
uint8_t fabricIndex = 0;
VerifyOrReturnError(event.Get(fabricIndex) == CHIP_NO_ERROR, CHIP_NO_ERROR);
if (fabricIndex == *invalidFabricIndex)
{
CHIPCircularTLVBuffer * readBuffer = static_cast<CHIPCircularTLVBuffer *>(event.GetBackingStore());
// fabricIndex is encoded as an integer; the dataPtr will point to a location immediately after its encoding
// shift the dataPtr to point to the encoding of the fabric index, accounting for wraparound in backing storage
// we cannot get the actual encoding size from current container beginning to the fabric index because of several
// optional parameters, so we are assuming minimal encoding is used and the fabric index is 1 byte.
uint8_t * dataPtr;
if (event.GetReadPoint() != readBuffer->GetQueue())
{
dataPtr = readBuffer->GetQueue() + (event.GetReadPoint() - readBuffer->GetQueue() - 1);
}
else
{
dataPtr = readBuffer->GetQueue() + readBuffer->GetTotalDataLength() - 1;
}

*dataPtr = kUndefinedFabricIndex;
}
return CHIP_NO_ERROR;
}
}
return CHIP_NO_ERROR;
}

CHIP_ERROR EventManagement::FabricRemoved(FabricIndex aFabricIndex)
{
const bool recurse = false;
TLVReader reader;
CircularEventBufferWrapper bufWrapper;

#if !CHIP_SYSTEM_CONFIG_NO_LOCKING
ScopedLock lock(sInstance);
#endif // !CHIP_SYSTEM_CONFIG_NO_LOCKING

ReturnErrorOnFailure(GetEventReader(reader, PriorityLevel::Critical, &bufWrapper));
CHIP_ERROR err = TLV::Utilities::Iterate(reader, FabricRemovedCB, &aFabricIndex, recurse);
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
return err;
}

CHIP_ERROR EventManagement::GetEventReader(TLVReader & aReader, PriorityLevel aPriority, CircularEventBufferWrapper * apBufWrapper)
{
CircularEventBuffer * buffer = GetPriorityBuffer(aPriority);
Expand All @@ -761,7 +827,7 @@ CHIP_ERROR EventManagement::GetEventReader(TLVReader & aReader, PriorityLevel aP
return CHIP_NO_ERROR;
}

CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size_t aDepth, void * apContext)
CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size_t, void * apContext)
{
EventEnvelopeContext * const envelope = static_cast<EventEnvelopeContext *>(apContext);
TLVReader reader;
Expand Down Expand Up @@ -808,7 +874,9 @@ CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size

if (reader.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
{
ReturnErrorOnFailure(reader.Get(envelope->mFabricIndex));
uint8_t fabricIndex = kUndefinedFabricIndex;
ReturnErrorOnFailure(reader.Get(fabricIndex));
envelope->mFabricIndex.SetValue(fabricIndex);
}
return CHIP_NO_ERROR;
}
Expand Down
17 changes: 16 additions & 1 deletion src/app/EventManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ class EventManagement
CHIP_ERROR FetchEventsSince(chip::TLV::TLVWriter & aWriter, const ObjectList<EventPathParams> * apEventPathList,
EventNumber & aEventMin, size_t & aEventCount,
const Access::SubjectDescriptor & aSubjectDescriptor);
/**
* @brief brief Iterate all events and invalidate the fabric-sensitive events whose associated fabric has the given fabric
* index.
*/
CHIP_ERROR FabricRemoved(FabricIndex aFabricIndex);

/**
* @brief
Expand Down Expand Up @@ -378,7 +383,7 @@ class EventManagement
EndpointId mEndpointId = 0;
EventId mEventId = 0;
EventNumber mEventNumber = 0;
FabricIndex mFabricIndex = kUndefinedFabricIndex;
Optional<FabricIndex> mFabricIndex;
};

void VendEventNumber();
Expand Down Expand Up @@ -419,6 +424,16 @@ class EventManagement
*/
CHIP_ERROR EnsureSpaceInCircularBuffer(size_t aRequiredSpace);

/**
* @brief Iterate the event elements inside event tlv and mark the fabric index as kUndefinedFabricIndex if
* it matches the FabricIndex apFabricIndex points to.
*
* @param[in] aReader event tlv reader
* @param[in] apFabricIndex A FabricIndex* pointing to the fabric index for which we want to effectively evict events.
*
*/
static CHIP_ERROR FabricRemovedCB(const TLV::TLVReader & aReader, size_t, void * apFabricIndex);

/**
* @brief
* Internal API used to implement #FetchEventsSince
Expand Down
1 change: 1 addition & 0 deletions src/app/server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ class Server
}
}
}
app::EventManagement::GetInstance().FabricRemoved(fabricIndex);
};
void OnFabricRetrievedFromStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }

Expand Down
1 change: 1 addition & 0 deletions src/app/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ chip_test_suite("tests") {
"TestEventLogging.cpp",
"TestEventOverflow.cpp",
"TestEventPathParams.cpp",
"TestFabricScopedEventLogging.cpp",
"TestInteractionModelEngine.cpp",
"TestMessageDef.cpp",
"TestNumericAttributeTraits.cpp",
Expand Down
Loading

0 comments on commit c438b89

Please sign in to comment.