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

Add intelligence to the ExchangeContext to determine if a peer is active #29549

Merged
merged 12 commits into from
Oct 19, 2023
4 changes: 3 additions & 1 deletion src/messaging/ExchangeContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ CHIP_ERROR ExchangeContext::HandleMessage(uint32_t messageCounter, const Payload
if (payloadHeader.NeedsAck())
{
// An acknowledgment needs to be sent back to the peer for this message on this exchange,

HandleNeedsAck(messageCounter, msgFlags);
}
}
Expand Down Expand Up @@ -590,6 +589,9 @@ CHIP_ERROR ExchangeContext::HandleMessage(uint32_t messageCounter, const Payload
app::ICDNotifier::GetInstance().BroadcastNetworkActivityNotification();
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

// Set kFlagReceivedAtLeastOneMessage to true since we have received at least one new application level message
SetHasReceivedAtLeastOneMessage(true);

if (IsResponseExpected())
{
// Since we got the response, cancel the response timer.
Expand Down
45 changes: 15 additions & 30 deletions src/messaging/ExchangeContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ class DLL_EXPORT ExchangeContext : public ReliableMessageContext,
*/
bool IsSendExpected() const { return mFlags.Has(Flags::kFlagWillSendMessage); }

/**
* Tracks whether we have received at least one application level message
* during the life-time of this exchange
*
* @return Returns 'true' if we have received at least one message, else 'false'
*/
inline bool HasReceivedAtLeastOneMessage() { return mFlags.Has(Flags::kFlagReceivedAtLeastOneMessage); }

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
SessionHolder & GetSessionHolder() { return mSession; }

Expand Down Expand Up @@ -292,42 +300,19 @@ class DLL_EXPORT ExchangeContext : public ReliableMessageContext,
*/
void MessageHandled();

/**
* Updates Sleepy End Device intervals mode in the following way:
* - does nothing for exchanges over Bluetooth LE
* - requests active mode if there are more messages,
* including MRP acknowledgements, expected to be sent or received on
* this exchange.
* - withdraws the request for active mode, otherwise.
*/
void UpdateSEDIntervalMode();

/**
* Requests or withdraws the request for Sleepy End Device active mode
* based on the argument value.
*
* Note that the device switches to the idle mode if no
* exchange nor other component requests the active mode.
*/
void UpdateSEDIntervalMode(bool activeMode);

static ExchangeMessageDispatch & GetMessageDispatch(bool isEphemeralExchange, ExchangeDelegate * delegate);

// If SetAutoReleaseSession() is called, this exchange must be using a SecureSession, and should
// evict it when the exchange is done with all its work (including any MRP traffic).
inline void SetIgnoreSessionRelease(bool ignore);
inline bool ShouldIgnoreSessionRelease();
};
inline void SetIgnoreSessionRelease(bool ignore) { mFlags.Set(Flags::kFlagIgnoreSessionRelease, ignore); }

inline void ExchangeContext::SetIgnoreSessionRelease(bool ignore)
{
mFlags.Set(Flags::kFlagIgnoreSessionRelease, ignore);
}
inline bool ShouldIgnoreSessionRelease() { return mFlags.Has(Flags::kFlagIgnoreSessionRelease); }

inline bool ExchangeContext::ShouldIgnoreSessionRelease()
{
return mFlags.Has(Flags::kFlagIgnoreSessionRelease);
}
inline void SetHasReceivedAtLeastOneMessage(bool hasReceivedMessage)
{
mFlags.Set(Flags::kFlagReceivedAtLeastOneMessage, hasReceivedMessage);
}
};

} // namespace Messaging
} // namespace chip
1 change: 0 additions & 1 deletion src/messaging/ReliableMessageContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ void ReliableMessageContext::HandleRcvdAck(uint32_t ackMessageCounter)
}

CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags)

{
CHIP_ERROR err = HandleNeedsAckInner(messageCounter, messageFlags);

Expand Down
26 changes: 8 additions & 18 deletions src/messaging/ReliableMessageContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,6 @@ class ReliableMessageContext
/// Set if this exchange is requesting Sleepy End Device active mode
void SetRequestingActiveMode(bool activeMode);

/// Determine whether this exchange is requesting Sleepy End Device active mode
bool IsRequestingActiveMode() const;

/// Determine whether this exchange is a EphemeralExchange for replying a StandaloneAck
bool IsEphemeralExchange() const;

Expand Down Expand Up @@ -169,14 +166,17 @@ class ReliableMessageContext
/// When set, we have had Close() or Abort() called on us already.
kFlagClosed = (1u << 7),

/// When set, signifies that the exchange is requesting Sleepy End Device active mode.
kFlagActiveMode = (1u << 8),

/// When set, signifies that the exchange created sorely for replying a StandaloneAck
kFlagEphemeralExchange = (1u << 9),
kFlagEphemeralExchange = (1u << 8),

/// When set, ignore session being released, because we are releasing it ourselves.
kFlagIgnoreSessionRelease = (1u << 10),
kFlagIgnoreSessionRelease = (1u << 9),

// This flag is used to determine if the peer (receiver) should be considered active or not.
// When set, sender knows it has received at least one application-level message
// from the peer and can assume the peer (receiver) is active.
// If the flag is not set, we don't know if the peer (receiver) is active or not.
kFlagReceivedAtLeastOneMessage = (1u << 10),

/// When set:
///
Expand Down Expand Up @@ -238,11 +238,6 @@ inline bool ReliableMessageContext::HasPiggybackAckPending() const
return mFlags.Has(Flags::kFlagAckMessageCounterIsValid);
}

inline bool ReliableMessageContext::IsRequestingActiveMode() const
{
return mFlags.Has(Flags::kFlagActiveMode);
mkardous-silabs marked this conversation as resolved.
Show resolved Hide resolved
}

inline void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck)
{
mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck);
Expand All @@ -253,11 +248,6 @@ inline void ReliableMessageContext::SetAckPending(bool inAckPending)
mFlags.Set(Flags::kFlagAckPending, inAckPending);
}

inline void ReliableMessageContext::SetRequestingActiveMode(bool activeMode)
{
mFlags.Set(Flags::kFlagActiveMode, activeMode);
}

inline bool ReliableMessageContext::IsEphemeralExchange() const
{
return mFlags.Has(Flags::kFlagEphemeralExchange);
Expand Down
31 changes: 23 additions & 8 deletions src/messaging/ReliableMessageMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,7 @@ void ReliableMessageMgr::ExecuteActions()
" Send Cnt %d",
messageCounter, ChipLogValueExchange(&entry->ec.Get()), entry->sendCount);

// Choose active/idle timeout from PeerActiveMode of session per 4.11.2.1. Retransmissions.
System::Clock::Timestamp baseTimeout = entry->ec->GetSessionHandle()->GetMRPBaseTimeout();
System::Clock::Timestamp backoff = ReliableMessageMgr::GetBackoff(baseTimeout, entry->sendCount);
entry->nextRetransTime = System::SystemClock().GetMonotonicTimestamp() + backoff;
CalculateNextRetransTime(*entry);
SendFromRetransTable(entry);

return Loop::Continue;
Expand Down Expand Up @@ -272,10 +269,7 @@ System::Clock::Timestamp ReliableMessageMgr::GetBackoff(System::Clock::Timestamp

void ReliableMessageMgr::StartRetransmision(RetransTableEntry * entry)
{
// Choose active/idle timeout from PeerActiveMode of session per 4.11.2.1. Retransmissions.
System::Clock::Timestamp baseTimeout = entry->ec->GetSessionHandle()->GetMRPBaseTimeout();
System::Clock::Timestamp backoff = ReliableMessageMgr::GetBackoff(baseTimeout, entry->sendCount);
entry->nextRetransTime = System::SystemClock().GetMonotonicTimestamp() + backoff;
CalculateNextRetransTime(*entry);
StartTimer();
}

Expand Down Expand Up @@ -456,6 +450,27 @@ CHIP_ERROR ReliableMessageMgr::MapSendError(CHIP_ERROR error, uint16_t exchangeI
return error;
}

void ReliableMessageMgr::CalculateNextRetransTime(RetransTableEntry & entry)
{
System::Clock::Timestamp baseTimeout = System::Clock::Milliseconds64(0);

// Check if we have received at least one application-level message
if (entry.ec->HasReceivedAtLeastOneMessage())
{
// If we have received at least one message, assume peer is active and use ActiveRetransTimeout
baseTimeout = entry.ec->GetSessionHandle()->GetRemoteMRPConfig().mActiveRetransTimeout;
}
else
{
// If we haven't received at least one message
// Choose active/idle timeout from PeerActiveMode of session per 4.11.2.1. Retransmissions.
baseTimeout = entry.ec->GetSessionHandle()->GetMRPBaseTimeout();
}

System::Clock::Timestamp backoff = ReliableMessageMgr::GetBackoff(baseTimeout, entry.sendCount);
entry.nextRetransTime = System::SystemClock().GetMonotonicTimestamp() + backoff;
}

#if CHIP_CONFIG_TEST
int ReliableMessageMgr::TestGetCountRetransTable()
{
Expand Down
8 changes: 8 additions & 0 deletions src/messaging/ReliableMessageMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ class ReliableMessageMgr
#endif // CHIP_CONFIG_TEST

private:
/**
* Calculates the next retransmission time for the entry
* Function sets the nextRetransTime of the entry
*
* @param[in,out] entry RetransTableEntry for which we need to calculate the nextRetransTime
*/
void CalculateNextRetransTime(RetransTableEntry & entry);

ObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool;
chip::System::Layer * mSystemLayer;

Expand Down
Loading