[border-agent] add epskc journey statistics (#11530)

This commit adds some new statistics for ePSKc to show the time
duration of various sub process during the credential sharing.

A Nexus unit test is added to verify the stats are counted correctly.

A few small points to be noted:
* The `StopReason` which was used internally in `EphemeralKeyManager`
  is renamed as `DeactivationReason`, defined as public and is mapped
  to the public enum `otHistoryTrackerEpskcDeactivationReason`.
* The original reason `Timeout` is renamed to `SessionTimeout` to
  indicate this is a timeout of the secure session. This is to
  differentiate with the epskc mode timeout.
* A new reason `EpskcTimeout` to indicate the timeout is due to epskc
  mode timeout.
This commit is contained in:
Li Cao
2025-06-02 22:23:07 -07:00
committed by GitHub
parent f9be8f76ee
commit ea3a3da0ee
11 changed files with 588 additions and 38 deletions
+1
View File
@@ -76,6 +76,7 @@ typedef enum otCoapSecureConnectEvent
OT_COAP_SECURE_DISCONNECTED_LOCAL_CLOSED, ///< Disconnected locally
OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS, ///< Disconnected due to reaching the max connection attempts
OT_COAP_SECURE_DISCONNECTED_ERROR, ///< Disconnected due to an error
OT_COAP_SECURE_DISCONNECTED_TIMEOUT, ///< Disconnected locally due to session timeout
} otCoapSecureConnectEvent;
/**
+37
View File
@@ -235,6 +235,26 @@ typedef struct otHistoryTrackerExternalRouteInfo
otHistoryTrackerNetDataEvent mEvent; ///< Indicates the event (added/removed).
} otHistoryTrackerExternalRouteInfo;
/**
* Represents events during the Border Agent's ePSKc journey.
*/
typedef enum
{
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED, ///< ePSKc mode is activated.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED, ///< Secure session is connected.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED, ///< Commissioner petition is received.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_ACTIVE_DATASET, ///< Active dataset is retrieved.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_PENDING_DATASET, ///< Pending dataset is retrieved.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_KEEP_ALIVE, ///< Keep alive message is received.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_LOCAL_CLOSE, ///< Deactivated by a call to the API.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_REMOTE_CLOSE, ///< Disconnected by the peer.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_SESSION_ERROR, ///< Disconnected due to some error.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_SESSION_TIMEOUT, ///< Disconnected due to timeout.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_MAX_ATTEMPTS, ///< Max allowed attempts reached.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_EPSKC_TIMEOUT, ///< ePSKc mode timed out.
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_UNKNOWN, ///< Deactivated for an unknown reason.
} otHistoryTrackerBorderAgentEpskcEvent;
/**
* Initializes an `otHistoryTrackerIterator`.
*
@@ -397,6 +417,23 @@ const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHis
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* Iterates over the entries in the Border Agent ePSKc history list.
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[in,out] aIterator A pointer to an iterator. MUST be initialized or the behavior is undefined.
* @param[out] aEntryAge A pointer to a variable to output the entry's age. MUST NOT be NULL.
* Age is provided as the duration (in milliseconds) from when entry was recorded to
* @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
* older than max age.
*
* @returns The `otHistoryTrackerBorderAgentEpskcEvent` entry or `NULL` if no more entries in the list.
*/
const otHistoryTrackerBorderAgentEpskcEvent *otHistoryTrackerIterateBorderAgentEpskcEventHistory(
otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* Converts a given entry age to a human-readable string.
*
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (510)
#define OPENTHREAD_API_VERSION (511)
/**
* @addtogroup api-instance
+13
View File
@@ -129,6 +129,19 @@ const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHis
*aEntryAge);
}
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
const otHistoryTrackerBorderAgentEpskcEvent *otHistoryTrackerIterateBorderAgentEpskcEventHistory(
otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge)
{
AssertPointerIsNotNull(aEntryAge);
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateEpskcEventHistory(AsCoreType(aIterator),
*aEntryAge);
}
#endif
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
{
Utils::HistoryTracker::EntryAgeToString(aEntryAge, aBuffer, aSize);
+11
View File
@@ -160,6 +160,17 @@
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE 32
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE
*
* Specifies the maximum number of entries in Border Agent ePSKc history list.
*
* Can be set to zero to configure History Tracker module not to collect any ePSKc journey info.
*/
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE 64
#endif
/**
* @}
*/
+96 -31
View File
@@ -746,6 +746,9 @@ exit:
{
case kErrorNone:
Get<BorderAgent>().mCounters.mEpskcActivations++;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcActivated);
#endif
break;
case kErrorInvalidState:
Get<BorderAgent>().mCounters.mEpskcInvalidBaStateErrors++;
@@ -763,7 +766,7 @@ exit:
void BorderAgent::EphemeralKeyManager::Stop(void) { Stop(kReasonLocalDisconnect); }
void BorderAgent::EphemeralKeyManager::Stop(StopReason aReason)
void BorderAgent::EphemeralKeyManager::Stop(DeactivationReason aReason)
{
switch (mState)
{
@@ -776,37 +779,71 @@ void BorderAgent::EphemeralKeyManager::Stop(StopReason aReason)
ExitNow();
}
LogInfo("Stopping ephemeral key use - reason: %s", StopReasonToString(aReason));
LogInfo("Stopping ephemeral key use - reason: %s", DeactivationReasonToString(aReason));
SetState(kStateStopped);
mTimer.Stop();
mDtlsTransport.Close();
switch (aReason)
{
case kReasonLocalDisconnect:
Get<BorderAgent>().mCounters.mEpskcDeactivationClears++;
break;
case kReasonPeerDisconnect:
Get<BorderAgent>().mCounters.mEpskcDeactivationDisconnects++;
break;
case kReasonSessionError:
Get<BorderAgent>().mCounters.mEpskcStartSecureSessionErrors++;
break;
case kReasonMaxFailedAttempts:
Get<BorderAgent>().mCounters.mEpskcDeactivationMaxAttempts++;
break;
case kReasonTimeout:
Get<BorderAgent>().mCounters.mEpskcDeactivationTimeouts++;
break;
case kReasonUnknown:
break;
}
UpdateCountersAndRecordEvent(aReason);
exit:
return;
}
void BorderAgent::EphemeralKeyManager::UpdateCountersAndRecordEvent(DeactivationReason aReason)
{
struct ReasonToCounterEventEntry
{
DeactivationReason mReason;
uint8_t mEvent; // Raw values of `Utils::HistoryTracker::Epskc` enum.
uint32_t Counters::*mCounterPtr;
};
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
#define ReasonEntry(kReason, kCounter, kEvent) \
{ \
kReason, Utils::HistoryTracker::kEvent, &Counters::kCounter, \
}
#else
#define ReasonEntry(kReason, kCounter, kEvent) \
{ \
kReason, 0, &Counters::kCounter \
}
#endif
static const ReasonToCounterEventEntry kReasonToCounterEventEntries[] = {
ReasonEntry(kReasonLocalDisconnect, mEpskcDeactivationClears, kEpskcDeactivatedLocalClose),
ReasonEntry(kReasonSessionTimeout, mEpskcDeactivationClears, kEpskcDeactivatedSessionTimeout),
ReasonEntry(kReasonPeerDisconnect, mEpskcDeactivationDisconnects, kEpskcDeactivatedRemoteClose),
ReasonEntry(kReasonSessionError, mEpskcStartSecureSessionErrors, kEpskcDeactivatedSessionError),
ReasonEntry(kReasonMaxFailedAttempts, mEpskcDeactivationMaxAttempts, kEpskcDeactivatedMaxAttempts),
ReasonEntry(kReasonEpskcTimeout, mEpskcDeactivationTimeouts, kEpskcDeactivatedEpskcTimeout),
};
#undef ReasonEntry
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Utils::HistoryTracker::EpskcEvent event = Utils::HistoryTracker::kEpskcDeactivatedUnknown;
#endif
for (const ReasonToCounterEventEntry &entry : kReasonToCounterEventEntries)
{
if (aReason == entry.mReason)
{
(Get<BorderAgent>().mCounters.*(entry.mCounterPtr))++;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
event = static_cast<Utils::HistoryTracker::EpskcEvent>(entry.mEvent);
#endif
break;
}
}
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordEpskcEvent(event);
#endif
}
void BorderAgent::EphemeralKeyManager::SetState(State aState)
{
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
@@ -868,14 +905,16 @@ void BorderAgent::EphemeralKeyManager::HandleSessionConnected(void)
{
SetState(kStateConnected);
Get<BorderAgent>().mCounters.mEpskcSecureSessionSuccesses++;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcConnected);
#endif
}
void BorderAgent::EphemeralKeyManager::HandleSessionDisconnected(SecureSession::ConnectEvent aEvent)
{
StopReason reason = kReasonUnknown;
DeactivationReason reason = kReasonUnknown;
// The ephemeral key can be used once
VerifyOrExit((mState == kStateConnected) || (mState == kStateAccepted));
switch (aEvent)
@@ -889,6 +928,9 @@ void BorderAgent::EphemeralKeyManager::HandleSessionDisconnected(SecureSession::
case SecureSession::kDisconnectedMaxAttempts:
reason = kReasonMaxFailedAttempts;
break;
case SecureSession::kDisconnectedTimeout:
reason = kReasonSessionTimeout;
break;
default:
break;
}
@@ -903,9 +945,12 @@ void BorderAgent::EphemeralKeyManager::HandleCommissionerPetitionAccepted(void)
{
SetState(kStateAccepted);
Get<BorderAgent>().mCounters.mEpskcCommissionerPetitions++;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcPetitioned);
#endif
}
void BorderAgent::EphemeralKeyManager::HandleTimer(void) { Stop(kReasonTimeout); }
void BorderAgent::EphemeralKeyManager::HandleTimer(void) { Stop(kReasonEpskcTimeout); }
void BorderAgent::EphemeralKeyManager::HandleTask(void) { mCallback.InvokeIfSet(); }
@@ -992,15 +1037,16 @@ const char *BorderAgent::EphemeralKeyManager::StateToString(State aState)
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
const char *BorderAgent::EphemeralKeyManager::StopReasonToString(StopReason aReason)
const char *BorderAgent::EphemeralKeyManager::DeactivationReasonToString(DeactivationReason aReason)
{
static const char *const kReasonStrings[] = {
"LocalDisconnect", // (0) kReasonLocalDisconnect
"PeerDisconnect", // (1) kReasonPeerDisconnect
"SessionError", // (2) kReasonSessionError
"MaxFailedAttempts", // (3) kReasonMaxFailedAttempts
"Timeout", // (4) kReasonTimeout
"Unknown", // (5) kReasonUnknown
"SessionTimeout", // (3) kReasonSessionTimeout
"MaxFailedAttempts", // (4) kReasonMaxFailedAttempts
"EpskcTimeout", // (5) kReasonTimeout
"Unknown", // (6) kReasonUnknown
};
struct EnumCheck
@@ -1009,8 +1055,9 @@ const char *BorderAgent::EphemeralKeyManager::StopReasonToString(StopReason aRea
ValidateNextEnum(kReasonLocalDisconnect);
ValidateNextEnum(kReasonPeerDisconnect);
ValidateNextEnum(kReasonSessionError);
ValidateNextEnum(kReasonSessionTimeout);
ValidateNextEnum(kReasonMaxFailedAttempts);
ValidateNextEnum(kReasonTimeout);
ValidateNextEnum(kReasonEpskcTimeout);
ValidateNextEnum(kReasonUnknown);
};
@@ -1124,6 +1171,12 @@ void BorderAgent::CoapDtlsSession::HandleTmfCommissionerKeepAlive(Coap::Message
VerifyOrExit(mIsActiveCommissioner);
SuccessOrExit(ForwardToLeader(aMessage, aMessageInfo, kUriLeaderKeepAlive));
mTimer.Start(kKeepAliveTimeout);
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE && OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
if (Get<EphemeralKeyManager>().OwnsSession(*this))
{
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcKeepAlive);
}
#endif
exit:
return;
@@ -1454,11 +1507,23 @@ void BorderAgent::CoapDtlsSession::HandleTmfDatasetGet(Coap::Message &aMessage,
case kUriActiveGet:
response = Get<ActiveDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
Get<BorderAgent>().mCounters.mMgmtActiveGets++;
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE && OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
if (Get<EphemeralKeyManager>().OwnsSession(*this))
{
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcRetrievedActiveDataset);
}
#endif
break;
case kUriPendingGet:
response = Get<PendingDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
Get<BorderAgent>().mCounters.mMgmtPendingGets++;
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE && OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
if (Get<EphemeralKeyManager>().OwnsSession(*this))
{
Get<Utils::HistoryTracker>().RecordEpskcEvent(Utils::HistoryTracker::kEpskcRetrievedPendingDataset);
}
#endif
break;
case kUriCommissionerGet:
@@ -1490,7 +1555,7 @@ void BorderAgent::CoapDtlsSession::HandleTimer(void)
if (IsConnected())
{
LogInfo("Session timed out - disconnecting");
Disconnect();
DisconnectTimeout();
}
}
+7 -4
View File
@@ -39,6 +39,7 @@
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#include <openthread/border_agent.h>
#include <openthread/history_tracker.h>
#include "border_router/routing_manager.hpp"
#include "common/appender.hpp"
@@ -389,26 +390,28 @@ public:
static_assert(kMaxKeyLength <= Dtls::Transport::kPskMaxLength, "Max e-key len is larger than max PSK len");
enum StopReason : uint8_t
enum DeactivationReason : uint8_t
{
kReasonLocalDisconnect,
kReasonPeerDisconnect,
kReasonSessionError,
kReasonSessionTimeout,
kReasonMaxFailedAttempts,
kReasonTimeout,
kReasonEpskcTimeout,
kReasonUnknown,
};
explicit EphemeralKeyManager(Instance &aInstance);
void SetState(State aState);
void Stop(StopReason aReason);
void Stop(DeactivationReason aReason);
void HandleTimer(void);
void HandleTask(void);
bool OwnsSession(CoapDtlsSession &aSession) const { return mCoapDtlsSession == &aSession; }
void HandleSessionConnected(void);
void HandleSessionDisconnected(SecureSession::ConnectEvent aEvent);
void HandleCommissionerPetitionAccepted(void);
void UpdateCountersAndRecordEvent(DeactivationReason aReason);
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
bool ShouldRegisterService(void) const;
void RegisterOrUnregisterService(void);
@@ -423,7 +426,7 @@ public:
void HandleTransportClosed(void);
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
static const char *StopReasonToString(StopReason aReason);
static const char *DeactivationReasonToString(DeactivationReason aReason);
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
+6
View File
@@ -118,6 +118,7 @@ public:
static constexpr ConnectEvent kDisconnectedLocalClosed = OT_COAP_SECURE_DISCONNECTED_LOCAL_CLOSED;
static constexpr ConnectEvent kDisconnectedMaxAttempts = OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS;
static constexpr ConnectEvent kDisconnectedError = OT_COAP_SECURE_DISCONNECTED_ERROR;
static constexpr ConnectEvent kDisconnectedTimeout = OT_COAP_SECURE_DISCONNECTED_TIMEOUT;
/**
* Function pointer which is called reporting a session connection event.
@@ -176,6 +177,11 @@ public:
*/
void Disconnect(void) { Disconnect(kDisconnectedLocalClosed); }
/**
* Disconnects the session due to timeout.
*/
void DisconnectTimeout(void) { Disconnect(kDisconnectedTimeout); }
/**
* Sends message to the secure session.
*
+16 -1
View File
@@ -425,6 +425,19 @@ exit:
#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
void HistoryTracker::RecordEpskcEvent(EpskcEvent aEvent)
{
EpskcEvent *entry = mEpskcEventHistory.AddNewEntry();
VerifyOrExit(entry != nullptr);
*entry = aEvent;
exit:
return;
}
#endif
void HistoryTracker::HandleNotifierEvents(Events aEvents)
{
if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadRlocAdded | kEventThreadRlocRemoved |
@@ -451,7 +464,9 @@ void HistoryTracker::HandleTimer(void)
mNeighborHistory.UpdateAgedEntries();
mOnMeshPrefixHistory.UpdateAgedEntries();
mExternalRouteHistory.UpdateAgedEntries();
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
mEpskcEventHistory.UpdateAgedEntries();
#endif
mTimer.Start(kAgeCheckPeriod);
}
+44
View File
@@ -47,6 +47,7 @@
#include "common/non_copyable.hpp"
#include "common/notifier.hpp"
#include "common/timer.hpp"
#include "meshcop/border_agent.hpp"
#include "net/netif.hpp"
#include "net/socket.hpp"
#include "thread/mesh_forwarder.hpp"
@@ -57,6 +58,7 @@
#include "thread/router_table.hpp"
namespace ot {
namespace Utils {
#ifdef OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
@@ -81,6 +83,10 @@ class HistoryTracker : public InstanceLocator, private NonCopyable
#if OPENTHREAD_FTD
friend class ot::RouterTable;
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
friend class ot::MeshCoP::BorderAgent;
friend class ot::MeshCoP::BorderAgent::EphemeralKeyManager;
#endif
public:
/**
@@ -134,6 +140,9 @@ public:
typedef otHistoryTrackerRouterInfo RouterInfo; ///< Router info.
typedef otHistoryTrackerOnMeshPrefixInfo OnMeshPrefixInfo; ///< Network Data on mesh prefix info.
typedef otHistoryTrackerExternalRouteInfo ExternalRouteInfo; ///< Network Data external route info
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
typedef otHistoryTrackerBorderAgentEpskcEvent EpskcEvent; ///< Border Agent ePSKc Event.
#endif
/**
* Initializes the `HistoryTracker`.
@@ -242,6 +251,13 @@ public:
return mExternalRouteHistory.Iterate(aIterator, aEntryAge);
}
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
const EpskcEvent *IterateEpskcEventHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mEpskcEventHistory.Iterate(aIterator, aEntryAge);
}
#endif
/**
* Converts a given entry age to a human-readable string.
*
@@ -273,6 +289,7 @@ private:
static constexpr uint16_t kRouterListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE;
static constexpr uint16_t kOnMeshPrefixListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE;
static constexpr uint16_t kExternalRouteListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE;
static constexpr uint16_t kEpskcEventListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE;
typedef otHistoryTrackerAddressEvent AddressEvent;
@@ -300,6 +317,27 @@ private:
static constexpr NetDataEvent kNetDataEntryAdded = OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED;
static constexpr NetDataEvent kNetDataEntryRemoved = OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED;
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
#define DefineEpskcEvent(aName, aPublicEnumName) \
static constexpr EpskcEvent kEpskc##aName = OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_##aPublicEnumName
DefineEpskcEvent(Activated, ACTIVATED);
DefineEpskcEvent(Connected, CONNECTED);
DefineEpskcEvent(Petitioned, PETITIONED);
DefineEpskcEvent(RetrievedActiveDataset, RETRIEVED_ACTIVE_DATASET);
DefineEpskcEvent(RetrievedPendingDataset, RETRIEVED_PENDING_DATASET);
DefineEpskcEvent(KeepAlive, KEEP_ALIVE);
DefineEpskcEvent(DeactivatedLocalClose, DEACTIVATED_LOCAL_CLOSE);
DefineEpskcEvent(DeactivatedRemoteClose, DEACTIVATED_REMOTE_CLOSE);
DefineEpskcEvent(DeactivatedSessionError, DEACTIVATED_SESSION_ERROR);
DefineEpskcEvent(DeactivatedSessionTimeout, DEACTIVATED_SESSION_TIMEOUT);
DefineEpskcEvent(DeactivatedMaxAttempts, DEACTIVATED_MAX_ATTEMPTS);
DefineEpskcEvent(DeactivatedEpskcTimeout, DEACTIVATED_EPSKC_TIMEOUT);
DefineEpskcEvent(DeactivatedUnknown, DEACTIVATED_UNKNOWN);
#undef DefineEpskcEvent
#endif
class Timestamp
{
public:
@@ -408,6 +446,9 @@ private:
void RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix);
void RecordExternalRouteEvent(NetDataEvent aEvent, const NetworkData::ExternalRouteConfig &aRoute);
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
void RecordEpskcEvent(EpskcEvent aEvent);
#endif
using TrackerTimer = TimerMilliIn<HistoryTracker, &HistoryTracker::HandleTimer>;
@@ -420,6 +461,9 @@ private:
EntryList<RouterInfo, kRouterListSize> mRouterHistory;
EntryList<OnMeshPrefixInfo, kOnMeshPrefixListSize> mOnMeshPrefixHistory;
EntryList<ExternalRouteInfo, kExternalRouteListSize> mExternalRouteHistory;
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
EntryList<EpskcEvent, kEpskcEventListSize> mEpskcEventHistory;
#endif
TrackerTimer mTimer;
+356 -1
View File
@@ -38,7 +38,10 @@ namespace Nexus {
using ActiveDatasetManager = MeshCoP::ActiveDatasetManager;
using BorderAgent = MeshCoP::BorderAgent;
using EphemeralKeyManager = ot::MeshCoP::BorderAgent::EphemeralKeyManager;
using EphemeralKeyManager = MeshCoP::BorderAgent::EphemeralKeyManager;
using HistoryTracker = Utils::HistoryTracker;
using EpskcEvent = HistoryTracker::EpskcEvent;
using Iterator = HistoryTracker::Iterator;
using ExtendedPanIdManager = MeshCoP::ExtendedPanIdManager;
using NameData = MeshCoP::NameData;
using NetworkNameManager = MeshCoP::NetworkNameManager;
@@ -754,6 +757,357 @@ void TestBorderAgentEphemeralKey(void)
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcInvalidArgsErrors == 2);
}
EpskcEvent GetNewestEpskcEvent(Node &aNode)
{
const EpskcEvent *epskcEvent = nullptr;
Iterator iter;
uint32_t age;
iter.Init();
epskcEvent = aNode.Get<HistoryTracker>().IterateEpskcEventHistory(iter, age);
VerifyOrQuit(epskcEvent != nullptr);
return *epskcEvent;
}
void TestHistoryTrackerBorderAgentEpskcEvent(void)
{
static const char kEphemeralKey[] = "nexus1234";
static constexpr uint16_t kEphemeralKeySize = sizeof(kEphemeralKey) - 1;
static constexpr uint16_t kUdpPort = 49155;
Core nexus;
Node &node0 = nexus.CreateNode();
Node &node1 = nexus.CreateNode();
Ip6::SockAddr sockAddr;
Coap::Message *message;
EpskcEvent epskcEvent;
Log("------------------------------------------------------------------------------------------------------");
Log("TestHistoryTrackerBorderAgentEpskcEvent");
nexus.AdvanceTime(0);
// Form the topology:
// - node0 leader acting as Border Agent.
// - node1 acting as candidate
node0.Form();
nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<Mle::Mle>().IsLeader());
sockAddr.SetAddress(node0.Get<Mle::Mle>().GetLinkLocalAddress());
sockAddr.SetPort(kUdpPort);
SuccessOrQuit(node1.Get<Mac::Mac>().SetPanChannel(node0.Get<Mac::Mac>().GetPanChannel()));
node1.Get<Mac::Mac>().SetPanId(node0.Get<Mac::Mac>().GetPanId());
node1.Get<ThreadNetif>().Up();
// Enable the Ephemeral Key feature.
node0.Get<EphemeralKeyManager>().SetEnabled(true);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 1: Epskc Mode is activated, then deactivated");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
node0.Get<EphemeralKeyManager>().Stop();
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_LOCAL_CLOSE);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 2: Epskc Mode is activated, then deactivated after max failed connection "
"attempts");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
SuccessOrQuit(node0.Get<Ip6::Filter>().AddUnsecurePort(kUdpPort));
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
nexus.AdvanceTime(0);
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Open());
SuccessOrQuit(
node1.Get<Tmf::SecureAgent>().SetPsk(reinterpret_cast<const uint8_t *>(kEphemeralKey), kEphemeralKeySize - 2));
for (uint8_t numAttempts = 1; numAttempts < 10; numAttempts++)
{
Log(" Attempt %u to connect with the wrong key", numAttempts);
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
}
Log(" Attempt 10 (final attempt) to connect with the wrong key, check that ephemeral key use is stopped");
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_MAX_ATTEMPTS);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 3: The session is connected successfully, then disconnected by API");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
SuccessOrQuit(
node1.Get<Tmf::SecureAgent>().SetPsk(reinterpret_cast<const uint8_t *>(kEphemeralKey), kEphemeralKeySize));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
node0.Get<EphemeralKeyManager>().Stop();
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_LOCAL_CLOSE);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 4: The session is connected successfully. And the candidate petitioned as an "
"active commissioner. The session is disconnected by the remote.");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED);
node1.Get<Tmf::SecureAgent>().Disconnect();
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_REMOTE_CLOSE);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 5: The session is connected successfully. And the active dataset is fetched. "
"The session is disconnected by the remote.");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriActiveGet);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_ACTIVE_DATASET);
node1.Get<Tmf::SecureAgent>().Disconnect();
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_REMOTE_CLOSE);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 6: The session is connected successfully. And the pending dataset is fetched. "
"The session is disconnected by the remote.");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriActiveGet);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_ACTIVE_DATASET);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriPendingGet);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_PENDING_DATASET);
node1.Get<Tmf::SecureAgent>().Disconnect();
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_REMOTE_CLOSE);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 7: The session is connected successfully. And the pending dataset is fetched. "
"The session is due to session timeout.");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriActiveGet);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_ACTIVE_DATASET);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriPendingGet);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_RETRIEVED_PENDING_DATASET);
static constexpr uint32_t kKeepAliveTimeout = 50 * 1000; // Timeout to reject a commissioner (in msec)
nexus.AdvanceTime(kKeepAliveTimeout); // Wait for the session timeout
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_SESSION_TIMEOUT);
Log("------------------------------------------------------------------------------------------------------");
Log(" Check Ephemeral Key Journey 8: The session is connected successfully. The epskc mode is deactivated due to "
"timeout.");
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_ACTIVATED);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_CONNECTED);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_PETITIONED);
// Send a KeepAlive message every 30s until ePSKc mode timed out
for (uint8_t i = 0; i < EphemeralKeyManager::kDefaultTimeout / (30 * Time::kOneSecondInMsec) - 1; i++)
{
if (!node1.Get<Tmf::SecureAgent>().IsConnected())
{
break;
}
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerKeepAlive);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::StateTlv>(*message, MeshCoP::StateTlv::kAccept));
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(30 * Time::kOneSecondInMsec);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_KEEP_ALIVE);
}
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerKeepAlive);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::StateTlv>(*message, MeshCoP::StateTlv::kAccept));
SuccessOrQuit(Tlv::Append<MeshCoP::CommissionerIdTlv>(*message, "node1"));
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().SendMessage(*message));
nexus.AdvanceTime(30 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
epskcEvent = GetNewestEpskcEvent(node0);
VerifyOrQuit(epskcEvent == OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_EPSKC_TIMEOUT);
}
//----------------------------------------------------------------------------------------------------------------------
struct TxtData
@@ -1547,6 +1901,7 @@ int main(void)
{
ot::Nexus::TestBorderAgent();
ot::Nexus::TestBorderAgentEphemeralKey();
ot::Nexus::TestHistoryTrackerBorderAgentEpskcEvent();
ot::Nexus::TestBorderAgentTxtDataCallback();
ot::Nexus::TestBorderAgentServiceRegistration();
printf("All tests passed\n");