mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 09:29:51 +00:00
[trel] detect and handle socket addr discrepancy for TREL peers (#10869)
This commit introduces a new mechanism for the TREL link to detect and handle discrepancies between the IPv6 address and port used by a TREL peer in a received TREL packet, and the information previously reported by the platform layer (through DNS-SD discovery) for the same peer. Ideally, the platform underlying DNS-SD should detect changes to advertised ports and addresses by peers. However, there are situations where this is not detected reliably. As a received frame over the TREL radio link is processed by the MAC or MLE layers, if the frame passes receive security checks at either layer (indicating it is a secure and authenticated/fresh frame from a valid neighbor), the TREL peer socket address is automatically updated from the received TREL packet info. This ensures the TREL peer table is updated correctly if there are changes to TREL peer addresses of valid Thread neighbors upon rx from such neighbor, increasing the robustness of the TREL link. This commit also introduces a new `otPlatTrel` platform API, `otPlatTrelNotifyPeerSocketAddressDifference()`. The TREL implementation now notifies the platform layer whenever it detects a discrepancy in a TREL peer's socket address, regardless of whether the peer table is automatically updated. This allows the platform layer to take any appropriate action, such as restarting or confirming DNS-SD service resolution query for the peer service instance and/or address resolution query for its associated host name. This commit also adds a new test that validates the newly added behavior, including the auto-update of peer table information and notification of the platform through the new API, triggered by either MLE or MAC messages over the TREL radio link.
This commit is contained in:
@@ -72,6 +72,9 @@ static otError ProcessExit(void *aContext, uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
#if OPENTHREAD_EXAMPLES_SIMULATION
|
||||
extern otError ProcessNodeIdFilter(void *aContext, uint8_t aArgsLength, char *aArgs[]);
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
extern otError ProcessTrelTest(void *aContext, uint8_t aArgsLength, char *aArgs[]);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const otCliCommand kCommands[] = {
|
||||
@@ -92,6 +95,9 @@ static const otCliCommand kCommands[] = {
|
||||
* - `nodeidfilter` : Outputs filter mode (allow-list or deny-list) and filtered node IDs.
|
||||
*/
|
||||
{"nodeidfilter", ProcessNodeIdFilter},
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
{"treltest", ProcessTrelTest},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#endif // OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/random_noncrypto.h>
|
||||
#include <openthread/platform/trel.h>
|
||||
|
||||
@@ -60,6 +61,7 @@ typedef struct Message
|
||||
{
|
||||
MessageType mType;
|
||||
otSockAddr mSockAddr; // Destination (when TREL_DATA_MESSAGE), or peer addr (when DNS-SD service)
|
||||
otSockAddr mSourceAddr; // Source address (used when TREL_DATA_MESSAGE)
|
||||
uint16_t mDataLength; // mData length
|
||||
uint8_t mData[TREL_MAX_PACKET_SIZE]; // TREL UDP packet (when TREL_DATA_MESSAGE), or service TXT data.
|
||||
} Message;
|
||||
@@ -70,12 +72,13 @@ static Message sPendingTx[TREL_MAX_PENDING_TX];
|
||||
static utilsSocket sSocket;
|
||||
static uint16_t sPortOffset = 0;
|
||||
static bool sEnabled = false;
|
||||
static otSockAddr sSockAddr;
|
||||
|
||||
static bool sServiceRegistered = false;
|
||||
static uint16_t sServicePort;
|
||||
static uint8_t sServiceTxtLength;
|
||||
static char sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
|
||||
static otPlatTrelCounters sCounters;
|
||||
static uint16_t sNotifyAddressDiffCounter = 0;
|
||||
|
||||
#if DEBUG_LOG
|
||||
static void dumpBuffer(const void *aBuffer, uint16_t aLength)
|
||||
@@ -158,15 +161,14 @@ static void sendServiceMessage(MessageType aType)
|
||||
assert(sNumPendingTx < TREL_MAX_PENDING_TX);
|
||||
message = &sPendingTx[sNumPendingTx++];
|
||||
|
||||
message->mType = aType;
|
||||
memset(&message->mSockAddr, 0, sizeof(otSockAddr));
|
||||
message->mSockAddr.mPort = sServicePort;
|
||||
message->mDataLength = sServiceTxtLength;
|
||||
message->mType = aType;
|
||||
message->mSockAddr = sSockAddr;
|
||||
message->mDataLength = sServiceTxtLength;
|
||||
memcpy(message->mData, sServiceTxtData, sServiceTxtLength);
|
||||
|
||||
#if DEBUG_LOG
|
||||
fprintf(stderr, "\r\n[trel-sim] sendServiceMessage(%s): service-port:%u, txt-len:%u\r\n",
|
||||
aType == TREL_DNSSD_ADD_SERVICE_MESSAGE ? "add" : "remove", sServicePort, sServiceTxtLength);
|
||||
aType == TREL_DNSSD_ADD_SERVICE_MESSAGE ? "add" : "remove", sSockAddr.mPort, sServiceTxtLength);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -186,7 +188,8 @@ static void processMessage(otInstance *aInstance, Message *aMessage, uint16_t aL
|
||||
{
|
||||
case TREL_DATA_MESSAGE:
|
||||
otEXPECT(aMessage->mSockAddr.mPort == sSocket.mPort);
|
||||
otPlatTrelHandleReceived(aInstance, aMessage->mData, aMessage->mDataLength);
|
||||
otEXPECT(otIp6IsAddressEqual(&aMessage->mSockAddr.mAddress, &sSockAddr.mAddress));
|
||||
otPlatTrelHandleReceived(aInstance, aMessage->mData, aMessage->mDataLength, &aMessage->mSourceAddr);
|
||||
break;
|
||||
|
||||
case TREL_DNSSD_BROWSE_MESSAGE:
|
||||
@@ -248,6 +251,21 @@ void otPlatTrelDisable(otInstance *aInstance)
|
||||
}
|
||||
}
|
||||
|
||||
void otPlatTrelNotifyPeerSocketAddressDifference(otInstance *aInstance,
|
||||
const otSockAddr *aPeerSockAddr,
|
||||
const otSockAddr *aRxSockAddr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aPeerSockAddr);
|
||||
OT_UNUSED_VARIABLE(aRxSockAddr);
|
||||
|
||||
sNotifyAddressDiffCounter++;
|
||||
|
||||
#if DEBUG_LOG
|
||||
fprintf(stderr, "\r\n[trel-sim] otPlatTrelNotifyPeerSocketAddressDifference()\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
@@ -260,7 +278,7 @@ void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint
|
||||
}
|
||||
|
||||
sServiceRegistered = true;
|
||||
sServicePort = aPort;
|
||||
sSockAddr.mPort = aPort;
|
||||
sServiceTxtLength = aTxtLength;
|
||||
memcpy(sServiceTxtData, aTxtData, aTxtLength);
|
||||
|
||||
@@ -289,6 +307,7 @@ void otPlatTrelSend(otInstance *aInstance,
|
||||
|
||||
message->mType = TREL_DATA_MESSAGE;
|
||||
message->mSockAddr = *aDestSockAddr;
|
||||
message->mSourceAddr = sSockAddr;
|
||||
message->mDataLength = aUdpPayloadLen;
|
||||
memcpy(message->mData, aUdpPayload, aUdpPayloadLen);
|
||||
|
||||
@@ -325,6 +344,10 @@ void platformTrelInit(uint32_t aSpeedUpFactor)
|
||||
|
||||
utilsInitSocket(&sSocket, TREL_SIM_PORT + sPortOffset);
|
||||
|
||||
memset(&sSockAddr, 0, sizeof(otSockAddr));
|
||||
sSockAddr.mAddress.mFields.m32[3] = gNodeId;
|
||||
sSockAddr.mPort = sSocket.mPort;
|
||||
|
||||
OT_UNUSED_VARIABLE(aSpeedUpFactor);
|
||||
}
|
||||
|
||||
@@ -378,14 +401,59 @@ void otPlatTrelResetCounters(otInstance *aInstance)
|
||||
memset(&sCounters, 0, sizeof(sCounters));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// CLI `treltest` command
|
||||
|
||||
OT_TOOL_WEAK void otCliOutputFormat(const char *aFmt, ...) { OT_UNUSED_VARIABLE(aFmt); }
|
||||
|
||||
otError ProcessTrelTest(void *aContext, uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aContext);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
if (!strcmp(aArgs[0], "sockaddr"))
|
||||
{
|
||||
char string[OT_IP6_SOCK_ADDR_STRING_SIZE];
|
||||
|
||||
otIp6SockAddrToString(&sSockAddr, string, sizeof(string));
|
||||
otCliOutputFormat("%s\r\n", string);
|
||||
}
|
||||
else if (!strcmp(aArgs[0], "changesockaddr"))
|
||||
{
|
||||
sSockAddr.mAddress.mFields.m32[2]++;
|
||||
}
|
||||
else if (!strcmp(aArgs[0], "changesockport"))
|
||||
{
|
||||
sSockAddr.mPort++;
|
||||
}
|
||||
else if (!strcmp(aArgs[0], "notifyaddrcounter"))
|
||||
{
|
||||
otCliOutputFormat("%u\r\n", sNotifyAddressDiffCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// This is added for RCP build to be built ok
|
||||
OT_TOOL_WEAK void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
|
||||
OT_TOOL_WEAK void otPlatTrelHandleReceived(otInstance *aInstance,
|
||||
uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
const otSockAddr *aSenderAddr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aBuffer);
|
||||
OT_UNUSED_VARIABLE(aLength);
|
||||
OT_UNUSED_VARIABLE(aSenderAddr);
|
||||
|
||||
assert(false);
|
||||
}
|
||||
@@ -398,4 +466,22 @@ OT_TOOL_WEAK void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, cons
|
||||
assert(false);
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK void otIp6SockAddrToString(const otSockAddr *aSockAddr, char *aBuffer, uint16_t aSize)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSockAddr);
|
||||
OT_UNUSED_VARIABLE(aBuffer);
|
||||
OT_UNUSED_VARIABLE(aSize);
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK bool otIp6IsAddressEqual(const otIp6Address *aFirst, const otIp6Address *aSecond)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aFirst);
|
||||
OT_UNUSED_VARIABLE(aSecond);
|
||||
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (467)
|
||||
#define OPENTHREAD_API_VERSION (468)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -135,6 +135,23 @@ typedef struct otPlatTrelPeerInfo
|
||||
*/
|
||||
extern void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
|
||||
|
||||
/**
|
||||
* Notifies platform that a TREL packet is received from a peer using a different socket address than the one reported
|
||||
* earlier from `otPlatTrelHandleDiscoveredPeerInfo()`.
|
||||
*
|
||||
* Ideally the platform underlying DNS-SD should detect changes to advertised port and addresses by peers, however,
|
||||
* there are situations where this is not detected reliably. This function signals to the platform layer than we
|
||||
* received a packet from a peer with it using a different port or address. This can be used by the playroom layer to
|
||||
* restart/confirm the DNS-SD service/address resolution for the peer service and/or take any other relevant actions.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[in] aPeerSockAddr The address of the peer, reported from `otPlatTrelHandleDiscoveredPeerInfo()` call.
|
||||
* @param[in] aRxSockAddr The address of received packet from the same peer (differs from @p aPeerSockAddr).
|
||||
*/
|
||||
void otPlatTrelNotifyPeerSocketAddressDifference(otInstance *aInstance,
|
||||
const otSockAddr *aPeerSockAddr,
|
||||
const otSockAddr *aRxSockAddr);
|
||||
|
||||
/**
|
||||
* Registers a new service to be advertised using DNS-SD [RFC6763].
|
||||
*
|
||||
@@ -181,8 +198,12 @@ void otPlatTrelSend(otInstance *aInstance,
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aBuffer A buffer containing the received UDP payload.
|
||||
* @param[in] aLength UDP payload length (number of bytes).
|
||||
* @param[in] aSockAddr The sender address.
|
||||
*/
|
||||
extern void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
|
||||
extern void otPlatTrelHandleReceived(otInstance *aInstance,
|
||||
uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
const otSockAddr *aSenderAddr);
|
||||
|
||||
/**
|
||||
* Represents a group of TREL related counters in the platform layer.
|
||||
|
||||
@@ -2139,6 +2139,30 @@ exit:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
if (aFrame->GetRadioType() == kRadioTypeTrel)
|
||||
#endif
|
||||
{
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
// If the received frame is using TREL and is successfully
|
||||
// processed, check for any discrepancy between the socket
|
||||
// address of the received TREL packet and the information
|
||||
// saved in the corresponding TREL peer, and signal this to
|
||||
// the platform layer.
|
||||
//
|
||||
// If the frame used link security and was successfully
|
||||
// processed, we allow the `Peer` entry socket information
|
||||
// to be updated directly.
|
||||
|
||||
Get<Trel::Link>().CheckPeerAddrOnRxSuccess(aFrame->GetSecurityEnabled()
|
||||
? Trel::Link::kAllowPeerSockAddrUpdate
|
||||
: Trel::Link::kDisallowPeerSockAddrUpdate);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
}
|
||||
|
||||
void Mac::UpdateNeighborLinkInfo(Neighbor &aNeighbor, const RxFrame &aRxFrame)
|
||||
|
||||
@@ -109,6 +109,16 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Interface::Peer *Interface::FindPeer(const Mac::ExtAddress &aExtAddress)
|
||||
{
|
||||
return mPeerTable.FindMatching(aExtAddress);
|
||||
}
|
||||
|
||||
void Interface::NotifyPeerSocketAddressDifference(const Ip6::SockAddr &aPeerSockAddr, const Ip6::SockAddr &aRxSockAddr)
|
||||
{
|
||||
otPlatTrelNotifyPeerSocketAddressDifference(&GetInstance(), &aPeerSockAddr, &aRxSockAddr);
|
||||
}
|
||||
|
||||
void Interface::HandleExtAddressChange(void)
|
||||
{
|
||||
VerifyOrExit(mInitialized && mEnabled);
|
||||
@@ -188,7 +198,7 @@ void Interface::HandleDiscoveredPeerInfo(const Peer::Info &aInfo)
|
||||
|
||||
if (aInfo.IsRemoved())
|
||||
{
|
||||
entry = mPeerTable.FindMatching(extAddress);
|
||||
entry = FindPeer(extAddress);
|
||||
VerifyOrExit(entry != nullptr);
|
||||
RemovePeerEntry(*entry);
|
||||
ExitNow();
|
||||
@@ -380,25 +390,28 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
|
||||
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance,
|
||||
uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
const otSockAddr *aSenderAddress)
|
||||
{
|
||||
Instance &instance = AsCoreType(aInstance);
|
||||
|
||||
VerifyOrExit(instance.IsInitialized());
|
||||
instance.Get<Interface>().HandleReceived(aBuffer, aLength);
|
||||
instance.Get<Interface>().HandleReceived(aBuffer, aLength, AsCoreType(aSenderAddress));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength)
|
||||
void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength, const Ip6::SockAddr &aSenderAddr)
|
||||
{
|
||||
LogDebg("HandleReceived(aLength:%u)", aLength);
|
||||
|
||||
VerifyOrExit(mInitialized && mEnabled && !mFiltered);
|
||||
|
||||
mRxPacket.Init(aBuffer, aLength);
|
||||
Get<Link>().ProcessReceivedPacket(mRxPacket);
|
||||
Get<Link>().ProcessReceivedPacket(mRxPacket, aSenderAddr);
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
@@ -56,7 +56,10 @@ namespace Trel {
|
||||
|
||||
class Link;
|
||||
|
||||
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
|
||||
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance,
|
||||
uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
const otSockAddr *aSenderAddr);
|
||||
extern "C" void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
|
||||
|
||||
/**
|
||||
@@ -70,7 +73,10 @@ typedef otTrelCounters Counters;
|
||||
class Interface : public InstanceLocator
|
||||
{
|
||||
friend class Link;
|
||||
friend void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
|
||||
friend void otPlatTrelHandleReceived(otInstance *aInstance,
|
||||
uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
const otSockAddr *aSenderAddr);
|
||||
friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
|
||||
|
||||
public:
|
||||
@@ -103,10 +109,17 @@ public:
|
||||
/**
|
||||
* Returns the IPv6 socket address of the discovered TREL peer.
|
||||
*
|
||||
* @returns The IPv6 socket address of the TREP peer.
|
||||
* @returns The IPv6 socket address of the TREL peer.
|
||||
*/
|
||||
const Ip6::SockAddr &GetSockAddr(void) const { return static_cast<const Ip6::SockAddr &>(mSockAddr); }
|
||||
|
||||
/**
|
||||
* Set the IPv6 socket address of the discovered TREL peer.
|
||||
*
|
||||
* @param[in] aSockAddr The IPv6 socket address.
|
||||
*/
|
||||
void SetSockAddr(const Ip6::SockAddr &aSockAddr) { mSockAddr = aSockAddr; }
|
||||
|
||||
/**
|
||||
* Indicates whether the peer matches a given Extended Address.
|
||||
*
|
||||
@@ -139,7 +152,6 @@ public:
|
||||
|
||||
void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
|
||||
void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; }
|
||||
void SetSockAddr(const Ip6::SockAddr &aSockAddr) { mSockAddr = aSockAddr; }
|
||||
void Log(const char *aAction) const;
|
||||
};
|
||||
|
||||
@@ -244,6 +256,24 @@ public:
|
||||
*/
|
||||
uint16_t GetUdpPort(void) const { return mUdpPort; }
|
||||
|
||||
/**
|
||||
* Finds the TREL peer associated with a given Extended Address.
|
||||
*
|
||||
* @param[in] aExtAddress The extended address.
|
||||
*
|
||||
* @returns The peer associated with @ aExtAddress, or `nullptr` if not found.
|
||||
*/
|
||||
Peer *FindPeer(const Mac::ExtAddress &aExtAddress);
|
||||
|
||||
/**
|
||||
* Notifies platform that a TREL packet is received from a peer using a different socket address than the one
|
||||
* reported earlier.
|
||||
*
|
||||
* @param[in] aPeerSockAddr The previously reported peer sock addr.
|
||||
* @param[in] aRxSockAddr The address of received packet from the same peer.
|
||||
*/
|
||||
void NotifyPeerSocketAddressDifference(const Ip6::SockAddr &aPeerSockAddr, const Ip6::SockAddr &aRxSockAddr);
|
||||
|
||||
private:
|
||||
#if OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE != 0
|
||||
static constexpr uint16_t kPeerTableSize = OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE;
|
||||
@@ -265,7 +295,7 @@ private:
|
||||
Error Send(const Packet &aPacket, bool aIsDiscovery = false);
|
||||
|
||||
// Callbacks from `otPlatTrel`.
|
||||
void HandleReceived(uint8_t *aBuffer, uint16_t aLength);
|
||||
void HandleReceived(uint8_t *aBuffer, uint16_t aLength, const Ip6::SockAddr &aSenderAddr);
|
||||
void HandleDiscoveredPeerInfo(const Peer::Info &aInfo);
|
||||
|
||||
void RegisterService(void);
|
||||
|
||||
@@ -314,7 +314,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Link::ProcessReceivedPacket(Packet &aPacket)
|
||||
void Link::ProcessReceivedPacket(Packet &aPacket, const Ip6::SockAddr &aSockAddr)
|
||||
{
|
||||
Header::Type type;
|
||||
|
||||
@@ -342,6 +342,9 @@ void Link::ProcessReceivedPacket(Packet &aPacket)
|
||||
// Drop packets originating from same device.
|
||||
VerifyOrExit(aPacket.GetHeader().GetSource() != Get<Mac::Mac>().GetExtAddress());
|
||||
|
||||
mRxPacketSenderAddr = aSockAddr;
|
||||
mRxPacketPeer = Get<Interface>().FindPeer(aPacket.GetHeader().GetSource());
|
||||
|
||||
if (type != Header::kTypeBroadcast)
|
||||
{
|
||||
VerifyOrExit(aPacket.GetHeader().GetDestination() == Get<Mac::Mac>().GetExtAddress());
|
||||
@@ -371,10 +374,44 @@ void Link::ProcessReceivedPacket(Packet &aPacket)
|
||||
mRxFrame.mInfo.mRxInfo.mLqi = OT_RADIO_LQI_NONE;
|
||||
mRxFrame.mInfo.mRxInfo.mAckedWithFramePending = true;
|
||||
|
||||
// As the received frame is processed by the MAC or MLE layers,
|
||||
// `CheckPeerAddrOnRxSuccess()` may be called with different modes,
|
||||
// depending on whether the frame passes receive security checks
|
||||
// at either the MAC or MLE layers, allowing or disallowing peer
|
||||
// socket address to be updated from received TREL packet info.
|
||||
|
||||
Get<Mac::Mac>().HandleReceivedFrame(&mRxFrame, kErrorNone);
|
||||
|
||||
exit:
|
||||
return;
|
||||
mRxPacketPeer = nullptr;
|
||||
}
|
||||
|
||||
void Link::CheckPeerAddrOnRxSuccess(PeerSockAddrUpdateMode aMode)
|
||||
{
|
||||
Ip6::SockAddr prevSockAddr;
|
||||
|
||||
VerifyOrExit(mState != kStateDisabled);
|
||||
|
||||
VerifyOrExit(mRxPacketPeer != nullptr);
|
||||
|
||||
prevSockAddr = mRxPacketPeer->GetSockAddr();
|
||||
VerifyOrExit(prevSockAddr != mRxPacketSenderAddr);
|
||||
|
||||
LogNote("Peer %s rx sock-addr differs the previously saved one",
|
||||
mRxPacketPeer->GetExtAddress().ToString().AsCString());
|
||||
LogNote(" Rcvd sock-addr:%s", mRxPacketSenderAddr.ToString().AsCString());
|
||||
LogNote(" Prev sock-addr:%s", prevSockAddr.ToString().AsCString());
|
||||
|
||||
if (aMode == kAllowPeerSockAddrUpdate)
|
||||
{
|
||||
LogNote("Updating the peer sock-addr to the newly received");
|
||||
mRxPacketPeer->SetSockAddr(mRxPacketSenderAddr);
|
||||
}
|
||||
|
||||
Get<Interface>().NotifyPeerSocketAddressDifference(prevSockAddr, mRxPacketSenderAddr);
|
||||
|
||||
exit:
|
||||
mRxPacketPeer = nullptr;
|
||||
}
|
||||
|
||||
void Link::HandleAck(Packet &aAckPacket)
|
||||
@@ -412,6 +449,8 @@ void Link::HandleAck(Packet &aAckPacket)
|
||||
|
||||
} while (ackError == kErrorNoAck);
|
||||
|
||||
CheckPeerAddrOnRxSuccess(kDisallowPeerSockAddrUpdate);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,16 @@ public:
|
||||
static constexpr uint16_t kMtuSize = 1280 - 48 - sizeof(Header); ///< MTU size for TREL frame.
|
||||
static constexpr uint8_t kFcsSize = 0; ///< FCS size for TREL frame.
|
||||
|
||||
/**
|
||||
* Used as input by `CheckPeerAddrOnRxSuccess()` to determine whether the peer socket address can be updated based
|
||||
* on a received TREL packet from the peer if there is a discrepancy.
|
||||
*/
|
||||
enum PeerSockAddrUpdateMode : uint8_t
|
||||
{
|
||||
kAllowPeerSockAddrUpdate, ///< Peer socket address can be updated.
|
||||
kDisallowPeerSockAddrUpdate, ///< Peer socket address cannot be updated.
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the `Link` object.
|
||||
*
|
||||
@@ -137,6 +147,17 @@ public:
|
||||
*/
|
||||
void Send(void);
|
||||
|
||||
/**
|
||||
* Checks the address/port from the last received TREL packet against the ones recorded in the corresponding `Peer`
|
||||
* entry and acts if there is a discrepancy.
|
||||
*
|
||||
* This method signals to the platform about the discrepancy. Based on @p aMode, it may also update the `Peer`
|
||||
* entry information directly to match the new address/port information.
|
||||
*
|
||||
* @param[in] aMode Determines whether to update the `Peer` entry if there is a discrepancy.
|
||||
*/
|
||||
void CheckPeerAddrOnRxSuccess(PeerSockAddrUpdateMode aMode);
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxHeaderSize = sizeof(Header);
|
||||
static constexpr uint16_t k154AckFrameSize = 3 + kFcsSize;
|
||||
@@ -144,6 +165,8 @@ private:
|
||||
static constexpr uint32_t kAckWaitWindow = 750; // (in msec)
|
||||
static constexpr uint16_t kFcfFramePending = 1 << 4;
|
||||
|
||||
typedef Interface::Peer Peer;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisabled,
|
||||
@@ -157,7 +180,7 @@ private:
|
||||
void BeginTransmit(void);
|
||||
void InvokeSendDone(Error aError) { InvokeSendDone(aError, nullptr); }
|
||||
void InvokeSendDone(Error aError, Mac::RxFrame *aAckFrame);
|
||||
void ProcessReceivedPacket(Packet &aPacket);
|
||||
void ProcessReceivedPacket(Packet &aPacket, const Ip6::SockAddr &aSockAddr);
|
||||
void HandleAck(Packet &aAckPacket);
|
||||
void SendAck(Packet &aRxPacket);
|
||||
void ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError);
|
||||
@@ -171,18 +194,20 @@ private:
|
||||
using TxTasklet = TaskletIn<Link, &Link::HandleTxTasklet>;
|
||||
using TimeoutTimer = TimerMilliIn<Link, &Link::HandleTimer>;
|
||||
|
||||
State mState;
|
||||
uint8_t mRxChannel;
|
||||
Mac::PanId mPanId;
|
||||
uint32_t mTxPacketNumber;
|
||||
TxTasklet mTxTasklet;
|
||||
TimeoutTimer mTimer;
|
||||
Interface mInterface;
|
||||
Mac::RxFrame mRxFrame;
|
||||
Mac::TxFrame mTxFrame;
|
||||
uint8_t mTxPacketBuffer[kMaxHeaderSize + kMtuSize];
|
||||
uint8_t mAckPacketBuffer[kMaxHeaderSize];
|
||||
uint8_t mAckFrameBuffer[k154AckFrameSize];
|
||||
State mState;
|
||||
uint8_t mRxChannel;
|
||||
Mac::PanId mPanId;
|
||||
uint32_t mTxPacketNumber;
|
||||
TxTasklet mTxTasklet;
|
||||
TimeoutTimer mTimer;
|
||||
Interface mInterface;
|
||||
Ip6::SockAddr mRxPacketSenderAddr;
|
||||
Peer *mRxPacketPeer;
|
||||
Mac::RxFrame mRxFrame;
|
||||
Mac::TxFrame mTxFrame;
|
||||
uint8_t mTxPacketBuffer[kMaxHeaderSize + kMtuSize];
|
||||
uint8_t mAckPacketBuffer[kMaxHeaderSize];
|
||||
uint8_t mAckFrameBuffer[k154AckFrameSize];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2441,12 +2441,17 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
OT_ASSERT(aMessage.IsRadioTypeSet());
|
||||
Get<RadioSelector>().UpdateOnReceive(*neighbor, aMessage.GetRadioType(), /* IsDuplicate */ true);
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
CheckTrelPeerAddrOnSecureMleRx(aMessage);
|
||||
#endif
|
||||
|
||||
// We intentionally exit without setting the error to
|
||||
// skip logging "Failed to process UDP" at the exit
|
||||
// label. Note that in multi-radio mode, receiving
|
||||
// duplicate MLE message (with one-off counter) would
|
||||
// be common and ok for broadcast MLE messages (e.g.
|
||||
// MLE Link Advertisements).
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
#endif
|
||||
@@ -2463,6 +2468,10 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
neighbor->SetMleFrameCounter(frameCounter + 1);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
CheckTrelPeerAddrOnSecureMleRx(aMessage);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
if (neighbor != nullptr)
|
||||
{
|
||||
@@ -2673,6 +2682,20 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
void Mle::CheckTrelPeerAddrOnSecureMleRx(const Message &aMessage)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
if (aMessage.IsRadioTypeSet() && aMessage.GetRadioType() == Mac::kRadioTypeTrel)
|
||||
#endif
|
||||
{
|
||||
Get<Trel::Link>().CheckPeerAddrOnRxSuccess(Trel::Link::kAllowPeerSockAddrUpdate);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Mle::ReestablishLinkWithNeighbor(Neighbor &aNeighbor)
|
||||
{
|
||||
VerifyOrExit(IsAttached() && aNeighbor.IsStateValid());
|
||||
|
||||
@@ -1383,6 +1383,10 @@ private:
|
||||
void UpdateServiceAlocs(void);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
void CheckTrelPeerAddrOnSecureMleRx(const Message &aMessage);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
void HandleTimeSync(RxInfo &aRxInfo);
|
||||
#endif
|
||||
|
||||
@@ -285,9 +285,15 @@ static void ReceivePacket(int aSocket, otInstance *aInstance)
|
||||
|
||||
if (sEnabled)
|
||||
{
|
||||
otSockAddr senderAddr;
|
||||
|
||||
++sCounters.mRxPackets;
|
||||
sCounters.mRxBytes += sRxPacketLength;
|
||||
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength);
|
||||
|
||||
memcpy(&senderAddr.mAddress, &sockAddr.sin6_addr, sizeof(otIp6Address));
|
||||
senderAddr.mPort = ntohs(sockAddr.sin6_port);
|
||||
|
||||
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength, &senderAddr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +429,25 @@ OT_TOOL_WEAK void trelDnssdStopBrowse(void)
|
||||
// earlier call to `trelDnssdStartBrowse()`.
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK void trelDnssdNotifyPeerSocketAddressDifference(const otSockAddr *aPeerSockAddr,
|
||||
const otSockAddr *aRxSockAddr)
|
||||
{
|
||||
// Notifies platform that a TREL packet was received from a previously
|
||||
// discovered peer with `aPeerSockAddr` now using a different socket
|
||||
// address `aRxSockAddr` compared to the one reported earlier by DNS-SD
|
||||
// using the `otPlatTrelHandleDiscoveredPeerInfo()` callback.
|
||||
//
|
||||
// Ideally the platform DNS-SD should detect changes to advertised port
|
||||
// and addresses by peers, however, there are situations where this is
|
||||
// not detected reliably. This function signals to that we received a
|
||||
// packet from a peer with it using a different port or address. This can
|
||||
// be used to restart/confirm the DNS-SD service/address resolution for
|
||||
// the peer service and/or take any other relevant actions.
|
||||
|
||||
OT_UNUSED_VARIABLE(aPeerSockAddr);
|
||||
OT_UNUSED_VARIABLE(aRxSockAddr);
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK void trelDnssdRegisterService(uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
|
||||
{
|
||||
// This function registers a new service to be advertised using
|
||||
@@ -542,6 +567,15 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void otPlatTrelNotifyPeerSocketAddressDifference(otInstance *aInstance,
|
||||
const otSockAddr *aPeerSockAddr,
|
||||
const otSockAddr *aRxSockAddr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
trelDnssdNotifyPeerSocketAddressDifference(aPeerSockAddr, aRxSockAddr);
|
||||
}
|
||||
|
||||
void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
@@ -554,10 +554,11 @@ void otPlatFlashWrite(otInstance *, uint8_t aSwapIndex, uint32_t aOffset, const
|
||||
FakePlatform::CurrentPlatform().FlashWrite(aSwapIndex, aOffset, aData, aSize);
|
||||
}
|
||||
|
||||
void otPlatTrelEnable(otInstance *, uint16_t *) {}
|
||||
void otPlatTrelDisable(otInstance *) {}
|
||||
void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t) {}
|
||||
void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *) {}
|
||||
void otPlatTrelEnable(otInstance *, uint16_t *) {}
|
||||
void otPlatTrelDisable(otInstance *) {}
|
||||
void otPlatTrelNotifyPeerSocketAddressDifference(otInstance *, const otSockAddr *, const otSockAddr *) {}
|
||||
void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t) {}
|
||||
void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *) {}
|
||||
const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *) { return nullptr; }
|
||||
void otPlatTrelResetCounters(otInstance *) {}
|
||||
|
||||
|
||||
@@ -844,6 +844,25 @@ class Node(object):
|
||||
def br_count_peers(self):
|
||||
return self._cli_single_output('br peers count')
|
||||
|
||||
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# trel
|
||||
|
||||
def trel_get_peers(self):
|
||||
peers = self.cli('trel peers ')
|
||||
return Node.parse_table(peers)
|
||||
|
||||
def trel_test_get_sock_addr(self):
|
||||
return self._cli_single_output('treltest sockaddr')
|
||||
|
||||
def trel_test_change_sock_addr(self):
|
||||
return self._cli_no_output('treltest changesockaddr')
|
||||
|
||||
def trel_test_change_sock_port(self):
|
||||
return self._cli_no_output('treltest changesockport')
|
||||
|
||||
def trel_test_get_notify_addr_counter(self):
|
||||
return self._cli_single_output('treltest notifyaddrcounter')
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
# Helper methods
|
||||
|
||||
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from cli import verify
|
||||
from cli import verify_within
|
||||
import cli
|
||||
import time
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test description: This test validates the mechanism to discover and update the TREL peer info when processing
|
||||
# a received TREL packet from a peer (when peer IPv6 address or port number gets changes).
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
print('Starting \'{}\''.format(test_name))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Creating `cli.Node` instances
|
||||
|
||||
speedup = 10
|
||||
cli.Node.set_time_speedup_factor(speedup)
|
||||
|
||||
r1 = cli.Node(cli.RADIO_15_4_TREL)
|
||||
r2 = cli.Node(cli.RADIO_15_4_TREL)
|
||||
c1 = cli.Node(cli.RADIO_15_4_TREL)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Build network topology
|
||||
|
||||
r1.form("trel-peer-disc")
|
||||
c1.join(r1, cli.JOIN_TYPE_REED)
|
||||
r2.join(r1)
|
||||
|
||||
verify(r1.get_state() == 'leader')
|
||||
verify(r2.get_state() == 'router')
|
||||
verify(c1.get_state() == 'child')
|
||||
|
||||
verify(r1.multiradio_get_radios() == '[15.4, TREL]')
|
||||
verify(r2.multiradio_get_radios() == '[15.4, TREL]')
|
||||
verify(c1.multiradio_get_radios() == '[15.4, TREL]')
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test Implementation
|
||||
|
||||
|
||||
def check_trel_peers(node, peer_nodes):
|
||||
# Validate that `node` has discovered `peer_nodes` as its TREL peers
|
||||
# and validate that the correct TREL socket address is discovered
|
||||
# and used for each.
|
||||
peers = node.trel_get_peers()
|
||||
verify(len(peers) == len(peer_nodes))
|
||||
peers_ext_addrs = [nd.get_ext_addr() for nd in peer_nodes]
|
||||
for peer in peers:
|
||||
for peer_node in peer_nodes:
|
||||
if peer['Ext MAC Address'] == peer_node.get_ext_addr():
|
||||
verify(peer_node.trel_test_get_sock_addr() == peer['IPv6 Socket Address'])
|
||||
break
|
||||
else:
|
||||
verify(False) # Did not find peer in `peer_nodes`
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Check that all nodes see each other as TREL peers with the correct
|
||||
# TREL socket address.
|
||||
|
||||
check_trel_peers(r1, [r2, c1])
|
||||
check_trel_peers(r2, [r1, c1])
|
||||
check_trel_peers(c1, [r1, r2])
|
||||
|
||||
verify(int(r1.trel_test_get_notify_addr_counter()) == 0)
|
||||
verify(int(r2.trel_test_get_notify_addr_counter()) == 0)
|
||||
verify(int(c1.trel_test_get_notify_addr_counter()) == 0)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Use test CLI command to force `r2` to change its TREL socket
|
||||
# address (IPv6 address only).
|
||||
|
||||
time.sleep(10 / speedup)
|
||||
|
||||
old_sock_addr = r2.trel_test_get_sock_addr()
|
||||
r2.trel_test_change_sock_addr()
|
||||
verify(r2.trel_test_get_sock_addr() != old_sock_addr)
|
||||
|
||||
# Wait for longer than the Link Advertisement interval for `r2` to
|
||||
# send an advertisement. Other nodes that receive and process this
|
||||
# adv should then update the socket address of `r2` in their TREL
|
||||
# peer table.
|
||||
|
||||
time.sleep(35 / speedup)
|
||||
|
||||
check_trel_peers(r1, [r2, c1])
|
||||
check_trel_peers(r2, [r1, c1])
|
||||
check_trel_peers(c1, [r1, r2])
|
||||
|
||||
# Validate that the platform is notified of the socket address
|
||||
# discrepancy on `r1` and `c1`.
|
||||
|
||||
verify(int(r1.trel_test_get_notify_addr_counter()) == 1)
|
||||
verify(int(r2.trel_test_get_notify_addr_counter()) == 0)
|
||||
verify(int(c1.trel_test_get_notify_addr_counter()) == 1)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Use test CLI command to force `r2` to change its TREL socket
|
||||
# address port.
|
||||
|
||||
time.sleep(10 / speedup)
|
||||
|
||||
old_sock_addr = r2.trel_test_get_sock_addr()
|
||||
r2.trel_test_change_sock_port()
|
||||
verify(r2.trel_test_get_sock_addr() != old_sock_addr)
|
||||
|
||||
# Wait for longer than the Link Advertisement interval for `r2` to
|
||||
# send an advertisement. Other nodes that receive and process this
|
||||
# adv should then update the socket address of `r2` in their TREL
|
||||
# peer table.
|
||||
|
||||
time.sleep(35 / speedup)
|
||||
|
||||
check_trel_peers(r1, [r2, c1])
|
||||
check_trel_peers(r2, [r1, c1])
|
||||
check_trel_peers(c1, [r1, r2])
|
||||
|
||||
# Validate that the platform is notified of the socket address
|
||||
# discrepancy on `r1` and `c1`.
|
||||
|
||||
verify(int(r1.trel_test_get_notify_addr_counter()) == 2)
|
||||
verify(int(r2.trel_test_get_notify_addr_counter()) == 0)
|
||||
verify(int(c1.trel_test_get_notify_addr_counter()) == 2)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Use test CLI command to force `c1` to change its TREL socket
|
||||
# address (IPv6 address only).
|
||||
|
||||
old_sock_addr = c1.trel_test_get_sock_addr()
|
||||
c1.trel_test_change_sock_addr()
|
||||
verify(c1.trel_test_get_sock_addr() != old_sock_addr)
|
||||
|
||||
# Send a ping from `c1` to `r1` to trigger communication
|
||||
# between `r1` and `c1`. The receipt of a secure data frame
|
||||
# from `c1` should update the TREL socket address on `r1`
|
||||
|
||||
c1.ping(r1.get_rloc_ip_addr())
|
||||
|
||||
check_trel_peers(r1, [r2, c1])
|
||||
verify(int(r1.trel_test_get_notify_addr_counter()) == 3)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
cli.Node.finalize_all_nodes()
|
||||
|
||||
print('\'{}\' passed.'.format(test_name))
|
||||
@@ -161,6 +161,7 @@ if [ "$TORANJ_CLI" = 1 ]; then
|
||||
run cli/test-703-multi-radio-mesh-header-msg.py
|
||||
run cli/test-704-multi-radio-scan.py
|
||||
run cli/test-705-multi-radio-discover-scan.py
|
||||
run cli/test-706-multi-radio-trel-peer-addr-port-change-discovery.py
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -450,6 +450,8 @@ OT_TOOL_WEAK void otPlatTrelDisable(otInstance *) {}
|
||||
|
||||
OT_TOOL_WEAK void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *) {}
|
||||
|
||||
OT_TOOL_WEAK void otPlatTrelNotifyPeerSocketAddressDifference(otInstance *, const otSockAddr *, const otSockAddr *) {}
|
||||
|
||||
OT_TOOL_WEAK void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t) {}
|
||||
|
||||
OT_TOOL_WEAK const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *) { return nullptr; }
|
||||
|
||||
Reference in New Issue
Block a user