Skip to content

Commit

Permalink
Fix subscription liveness check
Browse files Browse the repository at this point in the history
-- Send sync report with max interval, after min interval passed, send report immediately if there is any attribute change.
-- Add additionam margin for MRP upon max interval when doing liveness check
  • Loading branch information
yunhanw-google committed Nov 19, 2021
1 parent ef6455d commit 5529e57
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 21 deletions.
14 changes: 12 additions & 2 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,19 @@ CHIP_ERROR ReadClient::ProcessEventReportIBs(TLV::TLVReader & aEventReportIBsRea
CHIP_ERROR ReadClient::RefreshLivenessCheckTimer()
{
CancelLivenessCheckTimer();
ChipLogProgress(DataManagement, "Refresh LivenessCheckTime with %d seconds", mMaxIntervalCeilingSeconds);
System::Clock::Timeout timeout = System::Clock::Seconds16(mMaxIntervalCeilingSeconds);
if (mpExchangeCtx != nullptr && mpExchangeCtx->IsUDPTransport())
{
auto margin = System::Clock::Milliseconds32(
(CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS + 1) *
(mpExchangeCtx->GetIdleRetransmitTimeoutTick() << CHIP_CONFIG_RMP_TIMER_DEFAULT_PERIOD_SHIFT));
timeout = timeout + margin;
}

//EFR32/MBED/INFINION/K32W's chrono count return long unsinged, but other platform returns unsigned
ChipLogProgress(DataManagement, "Refresh LivenessCheckTime with %lu milliseconds", static_cast<long unsigned>(timeout.count()));
CHIP_ERROR err = InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer(
System::Clock::Seconds16(mMaxIntervalCeilingSeconds), OnLivenessTimeoutCallback, this);
timeout, OnLivenessTimeoutCallback, this);

if (err != CHIP_NO_ERROR)
{
Expand Down
29 changes: 24 additions & 5 deletions src/app/ReadHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,21 +590,40 @@ CHIP_ERROR ReadHandler::ProcessSubscribeRequest(System::PacketBufferHandle && aP
return CHIP_NO_ERROR;
}

void ReadHandler::OnUnblockHoldReportCallback(System::Layer * apSystemLayer, void * apAppState)
{
VerifyOrReturn(apAppState != nullptr);
ReadHandler * readHandler = static_cast<ReadHandler *>(apAppState);
ChipLogProgress(DataManagement, "Unblock report hold after min %d seconds", readHandler->mMinIntervalFloorSeconds);
readHandler->mHoldReport = false;
if (readHandler->mDirty)
{
InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
}
InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer(
System::Clock::Seconds16(readHandler->mMaxIntervalCeilingSeconds - readHandler->mMinIntervalFloorSeconds),
OnRefreshSubscribeTimerSyncCallback, readHandler);
}

void ReadHandler::OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState)
{
ReadHandler * aReadHandler = static_cast<ReadHandler *>(apAppState);
aReadHandler->mHoldReport = false;
VerifyOrReturn(apAppState != nullptr);
InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
}

CHIP_ERROR ReadHandler::RefreshSubscribeSyncTimer()
{
ChipLogProgress(DataManagement, "ReadHandler::Refresh Subscribe Sync Timer with %d seconds", mMinIntervalFloorSeconds);
ChipLogProgress(DataManagement, "ReadHandler::Refresh Subscribe Sync Timer with %d seconds", mMaxIntervalCeilingSeconds);
InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer(
OnUnblockHoldReportCallback, this);
InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->CancelTimer(
OnRefreshSubscribeTimerSyncCallback, this);
mHoldReport = true;
return InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer(
System::Clock::Seconds16(mMinIntervalFloorSeconds), OnRefreshSubscribeTimerSyncCallback, this);
ReturnErrorOnFailure(
InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer(
System::Clock::Seconds16(mMinIntervalFloorSeconds), OnUnblockHoldReportCallback, this));

return CHIP_NO_ERROR;
}
} // namespace app
} // namespace chip
1 change: 1 addition & 0 deletions src/app/ReadHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ class ReadHandler : public Messaging::ExchangeDelegate
AwaitingReportResponse, ///< The handler has sent the report to the client and is awaiting a status response.
};

static void OnUnblockHoldReportCallback(System::Layer * apSystemLayer, void * apAppState);
static void OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState);
CHIP_ERROR RefreshSubscribeSyncTimer();
CHIP_ERROR SendSubscribeResponse();
Expand Down
26 changes: 18 additions & 8 deletions src/app/reporting/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,15 @@ CHIP_ERROR Engine::SetDirty(ClusterInfo & aClusterInfo)
// chunk for read interactions.
if (handler.IsGeneratingReports() || handler.IsAwaitingReportResponse())
{
handler.SetDirty();
for (auto clusterInfo = handler.GetAttributeClusterInfolist(); clusterInfo != nullptr;
clusterInfo = clusterInfo->mpNext)
{
if (aClusterInfo.IsAttributePathSupersetOf(*clusterInfo) || clusterInfo->IsAttributePathSupersetOf(aClusterInfo))
{
handler.SetDirty();
break;
}
}
}
}
if (!InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(mpGlobalDirtySet, aClusterInfo) &&
Expand All @@ -460,20 +468,22 @@ void Engine::UpdateReadHandlerDirty(ReadHandler & aReadHandler)
{
return;
}

bool intersected = false;
for (auto clusterInfo = aReadHandler.GetAttributeClusterInfolist(); clusterInfo != nullptr; clusterInfo = clusterInfo->mpNext)
{
bool intersected = false;
for (auto path = mpGlobalDirtySet; path != nullptr; path = path->mpNext)
{
if (path->IsAttributePathSupersetOf(*clusterInfo) || clusterInfo->IsAttributePathSupersetOf(*path))
{
intersected = true;
break;
}
}
if (!intersected)
{
aReadHandler.ClearDirty();
}
}
if (!intersected)
{
aReadHandler.ClearDirty();
}
}

Expand All @@ -496,8 +506,8 @@ void Engine::OnReportConfirm()
}

}; // namespace reporting
}; // namespace app
}; // namespace chip
} // namespace app
} // namespace chip

void __attribute__((weak)) MatterPreAttributeReadCallback(const chip::app::ConcreteAttributePath & attributePath) {}
void __attribute__((weak)) MatterPostAttributeReadCallback(const chip::app::ConcreteAttributePath & attributePath) {}
17 changes: 11 additions & 6 deletions src/messaging/ExchangeContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,7 @@ CHIP_ERROR ExchangeContext::SendMessage(Protocols::Id protocolId, uint8_t msgTyp
// an error arising below. at the end, we have to close it.
ExchangeHandle ref(*this);

// If sending via UDP and NoAutoRequestAck send flag is not specificed,
// request reliable transmission.
const Transport::PeerAddress * peerAddress = GetSessionHandle().GetPeerAddress(mExchangeMgr->GetSessionManager());
// Treat unknown peer address as "not UDP", because we have no idea whether
// it's safe to do MRP there.
bool isUDPTransport = peerAddress && peerAddress->GetTransportType() == Transport::Type::kUdp;
bool isUDPTransport = IsUDPTransport();

// this check is ignored by the ExchangeMsgDispatch if !AutoRequestAck()
bool reliableTransmissionRequested = isUDPTransport && !sendFlags.Has(SendMessageFlags::kNoAutoRequestAck);
Expand Down Expand Up @@ -501,5 +496,15 @@ void ExchangeContext::MessageHandled()
Close();
}

bool ExchangeContext::IsUDPTransport()
{
// If sending via UDP and NoAutoRequestAck send flag is not specificed,
// request reliable transmission.
const Transport::PeerAddress * peerAddress = GetSessionHandle().GetPeerAddress(mExchangeMgr->GetSessionManager());
// Treat unknown peer address as "not UDP", because we have no idea whether
// it's safe to do MRP there.
return peerAddress && peerAddress->GetTransportType() == Transport::Type::kUdp;
}

} // namespace Messaging
} // namespace chip
1 change: 1 addition & 0 deletions src/messaging/ExchangeContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ class DLL_EXPORT ExchangeContext : public ReliableMessageContext, public Referen
void Abort();

void SetResponseTimeout(Timeout timeout);
bool IsUDPTransport();

private:
Timeout mResponseTimeout{ 0 }; // Maximum time to wait for response (in milliseconds); 0 disables response timeout.
Expand Down

0 comments on commit 5529e57

Please sign in to comment.