[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:
Abtin Keshavarzian
2024-12-18 20:35:58 -08:00
committed by GitHub
parent c34484d335
commit d1147d62b9
17 changed files with 547 additions and 41 deletions
+95 -9
View File
@@ -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