[trel] implementing Thread Radio Encapsulation Link (TREL) (#4440)

This commit implements TREL protocol to encapsulate and exchange IEEE
802.15.4 frames over a packet switched network (e.g., a wireless LAN).
This commit also provides a TREL IPv6/UDP interface implementation
(using link-local IPv6 unicast/multicast addresses to communicate over
a subnet). It defines a platform abstraction (`otPlatTrelUdp6*`) for
TREL over IPv6/UDP.

This commit also provides an implementation of the TREL platform under
`examples/posix` focusing on simulating the behavior of the link.
This commit is contained in:
Abtin Keshavarzian
2020-12-10 11:46:07 -08:00
committed by Jonathan Hui
parent ffb3fdf9bd
commit 2d36853fe6
26 changed files with 2135 additions and 179 deletions
+3 -1
View File
@@ -251,7 +251,9 @@ LOCAL_SRC_FILES := \
src/core/radio/radio.cpp \
src/core/radio/radio_callbacks.cpp \
src/core/radio/radio_platform.cpp \
src/core/radio/trel.cpp \
src/core/radio/trel_interface.cpp \
src/core/radio/trel_link.cpp \
src/core/radio/trel_packet.cpp \
src/core/thread/address_resolver.cpp \
src/core/thread/announce_begin_server.cpp \
src/core/thread/announce_sender.cpp \
@@ -69,6 +69,7 @@ add_library(openthread-simulation
radio.c
spi-stubs.c
system.c
trel.c
uart.c
virtual_time/alarm-sim.c
virtual_time/platform-sim.c
@@ -52,6 +52,7 @@ PLATFORM_SOURCES = \
radio.c \
spi-stubs.c \
system.c \
trel.c \
uart.c \
virtual_time/alarm-sim.c \
virtual_time/platform-sim.c \
@@ -231,4 +231,43 @@ void otSimSendUartWriteEvent(const uint8_t *aData, uint16_t aLength);
*/
bool platformRadioIsTransmitPending(void);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
* This function initializes the TREL service.
*
* @param[in] aSpeedUpFactor The time speed-up factor.
*
*/
void platformTrelInit(uint32_t aSpeedUpFactor);
/**
* This function shuts down the TREL service.
*
*/
void platformTrelDeinit(void);
/**
* This function updates the file descriptor sets with file descriptors used by the TREL.
*
* @param[inout] aReadFdSet A pointer to the read file descriptors.
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
* @param[inout] aTimeout A pointer to the timeout.
* @param[inout] aMaxFd A pointer to the max file descriptor.
*
*/
void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd);
/**
* This function performs TREL processing.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aReadFdSet A pointer to the read file descriptors.
* @param[in] aWriteFdSet A pointer to the write file descriptors.
*
*/
void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet);
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
#endif // PLATFORM_SIMULATION_H_
+12
View File
@@ -116,6 +116,9 @@ void otSysInit(int aArgCount, char *aArgVector[])
platformAlarmInit(speedUpFactor);
platformRadioInit();
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelInit(speedUpFactor);
#endif
platformRandomInit();
}
@@ -127,6 +130,9 @@ bool otSysPseudoResetWasRequested(void)
void otSysDeinit(void)
{
platformRadioDeinit();
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelDeinit();
#endif
}
void otSysProcessDrivers(otInstance *aInstance)
@@ -145,6 +151,9 @@ void otSysProcessDrivers(otInstance *aInstance)
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
platformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
platformAlarmUpdateTimeout(&timeout);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
#endif
if (otTaskletsArePending(aInstance))
{
@@ -166,6 +175,9 @@ void otSysProcessDrivers(otInstance *aInstance)
}
platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelProcess(aInstance, &read_fds, &write_fds);
#endif
if (gTerminate)
{
+345
View File
@@ -0,0 +1,345 @@
/*
* Copyright (c) 2019, 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.
*/
#include "platform-simulation.h"
#include <openthread/random_noncrypto.h>
#include <openthread/platform/trel-udp6.h>
#include "utils/code_utils.h"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
// Change DEBUG_LOG to all extra logging
#define DEBUG_LOG 0
// The IPv4 group for receiving
#define TREL_SIM_GROUP "224.0.0.116"
#define TREL_SIM_PORT 9200
#define TREL_MAX_PACKET_SIZE 1800
#define TREL_MAX_PENDING_TX 5
typedef struct PendingTx
{
uint8_t mPacketBuffer[TREL_MAX_PACKET_SIZE];
uint16_t mPacketLength;
otIp6Address mDestIp6Address;
} PendingTx;
static uint8_t sNumPendingTx = 0;
static PendingTx sPendingTx[TREL_MAX_PENDING_TX];
static int sTxFd = -1;
static int sRxFd = -1;
static uint16_t sPortOffset = 0;
static bool sEnabled = true;
#if DEBUG_LOG
static void dumpBuffer(const uint8_t *aBuffer, uint16_t aLength)
{
fprintf(stderr, "[ (len:%d) ", aLength);
while (aLength--)
{
fprintf(stderr, "%02x ", *aBuffer++);
}
fprintf(stderr, "]");
}
#endif
static void initFds(void)
{
int fd;
int one = 1;
struct sockaddr_in sockaddr;
struct ip_mreqn mreq;
memset(&sockaddr, 0, sizeof(sockaddr));
otEXPECT_ACTION((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1, perror("socket(sTxFd)"));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons((uint16_t)(TREL_SIM_PORT + sPortOffset + gNodeId));
sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &sockaddr.sin_addr, sizeof(sockaddr.sin_addr)) != -1,
perror("setsockopt(sTxFd, IP_MULTICAST_IF)"));
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one)) != -1,
perror("setsockopt(sTxFd, IP_MULTICAST_LOOP)"));
otEXPECT_ACTION(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != -1, perror("bind(sTxFd)"));
// Tx fd is successfully initialized.
sTxFd = fd;
otEXPECT_ACTION((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1, perror("socket(sRxFd)"));
otEXPECT_ACTION(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != -1,
perror("setsockopt(sRxFd, SO_REUSEADDR)"));
otEXPECT_ACTION(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != -1,
perror("setsockopt(sRxFd, SO_REUSEPORT)"));
memset(&mreq, 0, sizeof(mreq));
inet_pton(AF_INET, TREL_SIM_GROUP, &mreq.imr_multiaddr);
// Always use loopback device to send simulation packets.
mreq.imr_address.s_addr = inet_addr("127.0.0.1");
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_address, sizeof(mreq.imr_address)) != -1,
perror("setsockopt(sRxFd, IP_MULTICAST_IF)"));
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != -1,
perror("setsockopt(sRxFd, IP_ADD_MEMBERSHIP)"));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons((uint16_t)(TREL_SIM_PORT + sPortOffset));
sockaddr.sin_addr.s_addr = inet_addr(TREL_SIM_GROUP);
otEXPECT_ACTION(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != -1, perror("bind(sRxFd)"));
// Rx fd is successfully initialized.
sRxFd = fd;
exit:
if (sRxFd == -1 || sTxFd == -1)
{
exit(EXIT_FAILURE);
}
}
static void deinitFds(void)
{
if (sRxFd != -1)
{
close(sRxFd);
}
if (sTxFd != -1)
{
close(sTxFd);
}
}
void sendPendingTxPackets(void)
{
ssize_t rval;
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
inet_pton(AF_INET, TREL_SIM_GROUP, &sockaddr.sin_addr);
sockaddr.sin_port = htons((uint16_t)(TREL_SIM_PORT + sPortOffset));
for (uint8_t i = 0; i < sNumPendingTx; i++)
{
#if DEBUG_LOG
fprintf(stderr, "\n[trel-udp] Sending packet (num:%d)", i);
dumpBuffer(sPendingTx[i].mPacketBuffer, sPendingTx[i].mPacketLength);
fprintf(stderr, "\n");
#endif
rval = sendto(sTxFd, sPendingTx[i].mPacketBuffer, sPendingTx[i].mPacketLength, 0, (struct sockaddr *)&sockaddr,
sizeof(sockaddr));
if (rval < 0)
{
perror("sendto(sTxFd)");
exit(EXIT_FAILURE);
}
}
sNumPendingTx = 0;
}
//---------------------------------------------------------------------------------------------------------------------
// otPlatTrel
void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aPort)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aUnicastAddress);
OT_UNUSED_VARIABLE(aPort);
}
void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aUnicastAddress);
}
void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aMulticastAddress);
}
otError otPlatTrelUdp6SendTo(otInstance * aInstance,
const uint8_t * aBuffer,
uint16_t aLength,
const otIp6Address *aDestAddress)
{
otError error = OT_ERROR_NONE;
OT_UNUSED_VARIABLE(aInstance);
otEXPECT(sEnabled);
otEXPECT_ACTION(sNumPendingTx < TREL_MAX_PENDING_TX, error = OT_ERROR_ABORT);
memcpy(sPendingTx[sNumPendingTx].mPacketBuffer, aBuffer, aLength);
sPendingTx[sNumPendingTx].mPacketLength = aLength;
memcpy(&sPendingTx[sNumPendingTx].mDestIp6Address, aDestAddress, sizeof(otIp6Address));
sNumPendingTx++;
exit:
return error;
}
otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
sEnabled = aEnable;
if (!sEnabled)
{
sNumPendingTx = 0;
}
return OT_ERROR_NONE;
}
//---------------------------------------------------------------------------------------------------------------------
// platformTrel system
void platformTrelInit(uint32_t aSpeedUpFactor)
{
char *str;
str = getenv("PORT_OFFSET");
if (str != NULL)
{
char *endptr;
sPortOffset = (uint16_t)strtol(str, &endptr, 0);
if (*endptr != '\0')
{
fprintf(stderr, "\nInvalid PORT_OFFSET: %s\n", str);
exit(EXIT_FAILURE);
}
sPortOffset *= (MAX_NETWORK_SIZE + 1);
}
initFds();
OT_UNUSED_VARIABLE(aSpeedUpFactor);
}
void platformTrelDeinit(void)
{
deinitFds();
}
void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd)
{
OT_UNUSED_VARIABLE(aTimeout);
// Always ready to receive
if (aReadFdSet != NULL)
{
FD_SET(sRxFd, aReadFdSet);
if (aMaxFd != NULL && *aMaxFd < sRxFd)
{
*aMaxFd = sRxFd;
}
}
if ((aWriteFdSet != NULL) && (sNumPendingTx > 0))
{
FD_SET(sTxFd, aWriteFdSet);
if (aMaxFd != NULL && *aMaxFd < sTxFd)
{
*aMaxFd = sTxFd;
}
}
}
void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
{
if (FD_ISSET(sTxFd, aWriteFdSet) && (sNumPendingTx > 0))
{
sendPendingTxPackets();
}
if (FD_ISSET(sRxFd, aReadFdSet))
{
uint8_t rxPacketBuffer[TREL_MAX_PACKET_SIZE];
uint16_t rxPacketLength;
ssize_t rval;
rval = recvfrom(sRxFd, (char *)rxPacketBuffer, sizeof(rxPacketBuffer), 0, NULL, NULL);
if (rval < 0)
{
perror("recvfrom(sRxFd)");
exit(EXIT_FAILURE);
}
rxPacketLength = (uint16_t)(rval);
#if DEBUG_LOG
fprintf(stderr, "\n[trel-udp6] recvdPacket()");
dumpBuffer(rxPacketBuffer, rxPacketLength);
fprintf(stderr, "\n");
#endif
if (sEnabled)
{
otPlatTrelUdp6HandleReceived(aInstance, rxPacketBuffer, rxPacketLength);
}
}
}
// This is added for RCP build to be built ok
OT_TOOL_WEAK void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aBuffer);
OT_UNUSED_VARIABLE(aLength);
assert(false);
}
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+1
View File
@@ -100,6 +100,7 @@ ot_platform_headers = \
openthread/platform/settings.h \
openthread/platform/messagepool.h \
openthread/platform/toolchain.h \
openthread/platform/trel-udp6.h \
$(NULL)
ot_platformdir = $(includedir)/openthread/platform
+1
View File
@@ -105,6 +105,7 @@ source_set("openthread") {
"platform/spi-slave.h",
"platform/time.h",
"platform/toolchain.h",
"platform/trel-udp6.h",
"platform/uart.h",
"platform/udp.h",
"random_crypto.h",
+154
View File
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* @brief
* This file includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using an IPv6/UDP interface.
*
*/
#ifndef OPENTHREAD_PLATFORM_TREL_UDP6_H_
#define OPENTHREAD_PLATFORM_TREL_UDP6_H_
#include <stdint.h>
#include <openthread/error.h>
#include <openthread/instance.h>
#include <openthread/ip6.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup plat-trel
*
* @brief
* This module includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using an IPv6/UDP
* interface.
*
* @{
*
*/
/**
* This function initializes the TREL IPv6/UDP interface.
*
* This function is called before any other TREL platform functions.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aUnicastAddress The unicast address to add to interface and use as tx source and rx destination.
* @param[in] aUdpPort A UDP port number to use.
*
*/
void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort);
/**
* This function updates the unicast IPv6 address for TREL IPv6/UDP interface.
*
* The interface should only have one unicast IPv6 address. Calling this function replaces any previously set unicast
* IPv6 address (during initialization from `otPlatTrelUdp6Init` or earlier calls to `otPlatTrelUdp6UpdateAddress()`).
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aUnicastAddress The unicast address to add to interface and use for as tx source and rx destination.
*
*/
void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress);
/**
* This function subscribes the TREL IPv6/UDP interface to a new multicast address.
*
* This function may be called multiple times to subscribe to different addresses. The interface should accept/receive
* packets destined to any previously subscribed multicast address in addition to the unicast address added from the
* `otPlatTrelUdp6Init()` function when interface was initialized.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aMulticastAddress A multicast IPv6 address.
*
*/
void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress);
/**
* This function requests a packet to be sent to a given destination.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aBuffer A pointer to buffer containing the packet to send.
* @param[in] aLength Packet length (number of bytes).
* @param[in] aDestAddress The destination IPv6 address (can be a unicast or a multicast IPv6 address).
*
* @retval OT_ERROR_NONE The tx request was handled successfully.
* @retval OT_ERROR_ABORT The interface is not ready and tx was aborted
*
*/
otError otPlatTrelUdp6SendTo(otInstance * aInstance,
const uint8_t * aBuffer,
uint16_t aLength,
const otIp6Address *aDestAddress);
/**
* This function is a callback from platform to notify of a received packet.
*
* @note The buffer content (up to its specified length) may get changed during processing by OpenThread core (e.g.,
* decrypted in place), so the platform implementation should expect that after returning from this function the
* packet @p aBuffer content may have been altered.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aBuffer A buffer containing the received packet.
* @param[in] aLength Packet length (number of bytes).
*
*/
extern void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
/**
* This optional function is intended for testing only. It changes the test mode status for TREL interface.
*
* This function requests TREL interface to be temporarily disabled or enabled. When disabled all traffic flow through
* the TREL interface should be silently dropped.
*
* A default weak implementation of this method is provided by OpenThread (returning NOT_IMPLEMENTED).
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aEnable Indicates whether to enable/disable the TREL interface.
*
* @retval OT_ERROR_NONE Successfully changed the TREL interface test status (enabled/disabled).
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not provided by the platform.
*
*/
otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable);
/**
* @}
*
*/
#ifdef __cplusplus
} // end of extern "C"
#endif
#endif // OPENTHREAD_PLATFORM_TREL_UDP6_H_
+6 -2
View File
@@ -496,8 +496,12 @@ openthread_core_files = [
"radio/radio.hpp",
"radio/radio_callbacks.cpp",
"radio/radio_platform.cpp",
"radio/trel.cpp",
"radio/trel.hpp",
"radio/trel_interface.cpp",
"radio/trel_interface.hpp",
"radio/trel_link.cpp",
"radio/trel_link.hpp",
"radio/trel_packet.cpp",
"radio/trel_packet.hpp",
"thread/address_resolver.cpp",
"thread/address_resolver.hpp",
"thread/announce_begin_server.cpp",
+3 -1
View File
@@ -144,7 +144,9 @@ set(COMMON_SOURCES
radio/radio.cpp
radio/radio_callbacks.cpp
radio/radio_platform.cpp
radio/trel.cpp
radio/trel_interface.cpp
radio/trel_link.cpp
radio/trel_packet.cpp
thread/address_resolver.cpp
thread/announce_begin_server.cpp
thread/announce_sender.cpp
+6 -2
View File
@@ -221,7 +221,9 @@ SOURCES_COMMON = \
radio/radio.cpp \
radio/radio_callbacks.cpp \
radio/radio_platform.cpp \
radio/trel.cpp \
radio/trel_interface.cpp \
radio/trel_link.cpp \
radio/trel_packet.cpp \
thread/address_resolver.cpp \
thread/announce_begin_server.cpp \
thread/announce_sender.cpp \
@@ -457,7 +459,9 @@ HEADERS_COMMON = \
net/tcp.hpp \
net/udp6.hpp \
radio/radio.hpp \
radio/trel.hpp \
radio/trel_interface.hpp \
radio/trel_link.hpp \
radio/trel_packet.hpp \
thread/address_resolver.hpp \
thread/announce_begin_server.hpp \
thread/announce_sender.hpp \
+5
View File
@@ -515,6 +515,11 @@ template <> inline Trel::Link &Instance::Get(void)
{
return mThreadNetif.mMac.mLinks.mTrel;
}
template <> inline Trel::Interface &Instance::Get(void)
{
return mThreadNetif.mMac.mLinks.mTrel.mInterface;
}
#endif
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+1 -1
View File
@@ -50,7 +50,7 @@
#include "mac/mac_links.hpp"
#include "mac/mac_types.hpp"
#include "mac/sub_mac.hpp"
#include "radio/trel.hpp"
#include "radio/trel_link.hpp"
#include "thread/key_manager.hpp"
#include "thread/link_quality.hpp"
+1 -1
View File
@@ -37,7 +37,7 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "radio/trel.hpp"
#include "radio/trel_link.hpp"
#if !OPENTHREAD_RADIO || OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
#include "crypto/aes_ccm.hpp"
#endif
+4 -1
View File
@@ -41,7 +41,7 @@
#include "mac/mac_frame.hpp"
#include "mac/mac_types.hpp"
#include "mac/sub_mac.hpp"
#include "radio/trel.hpp"
#include "radio/trel_link.hpp"
namespace ot {
namespace Mac {
@@ -377,6 +377,9 @@ public:
mSubMac.SetExtAddress(aExtAddress);
#else
mExtAddress = aExtAddress;
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
mTrel.HandleExtAddressChange();
#endif
#endif
}
-64
View File
@@ -1,64 +0,0 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file implements Thread Radio Encapsulation Link (TREL).
*/
#include "trel.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
Link::Link(Instance &aInstance)
: InstanceLocator(aInstance)
{
memset(&mTxFrame, 0, sizeof(mTxFrame));
mTxFrame.mPsdu = &mFrameBuffer[kHeaderSize];
mTxFrame.SetLength(0);
#if OPENTHREAD_CONFIG_MULTI_RADIO
mTxFrame.SetRadioType(Mac::kRadioTypeTrel);
#endif
}
void Link::Send(void)
{
Get<Mac::Mac>().RecordFrameTransmitStatus(mTxFrame, NULL, OT_ERROR_ABORT, 0, false);
Get<Mac::Mac>().HandleTransmitDone(mTxFrame, NULL, OT_ERROR_ABORT);
}
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file includes definitions for Thread Radio Encapsulation Link (TREL).
*/
#ifndef TREL_HPP_
#define TREL_HPP_
#include "openthread-core-config.h"
#include "common/locator.hpp"
#include "mac/mac_frame.hpp"
#include "mac/mac_types.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
/**
* @addtogroup core-trel
*
* @brief
* This module includes definitions for Thread Radio Encapsulation Link (TREL)
*
* @{
*
*/
/**
* This class represents a Thread Radio Encapsulation Link (TREL).
*
*/
class Link : public InstanceLocator
{
friend class Instance;
public:
enum
{
kMtuSize = 1600,
kFcsSize = 0,
};
explicit Link(Instance &aInstance);
void SetPanId(Mac::PanId) {}
void Enable(void) {}
void Disable(void) {}
void Sleep(void) {}
void Receive(uint8_t) {}
void Send(void);
Mac::TxFrame &GetTransmitFrame(void) { return mTxFrame; }
private:
enum
{
kHeaderSize = 10,
};
Mac::TxFrame mTxFrame;
uint8_t mFrameBuffer[kHeaderSize + kMtuSize];
};
/**
* @}
*
*/
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
#endif // TREL_HPP_
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file implements Thread Radio Encapsulation Link (TREL) interface.
*/
#include "trel_interface.hpp"
#include <openthread/platform/trel-udp6.h>
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
Interface::Interface(Instance &aInstance)
: InstanceLocator(aInstance)
, mInitialized(false)
{
}
void Interface::Init(void)
{
Ip6::Address ip6Address;
VerifyOrExit(!mInitialized);
ip6Address.SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());
otPlatTrelUdp6Init(&GetInstance(), &ip6Address, kUdpPort);
CreateMulticastIp6Address(ip6Address);
otPlatTrelUdp6SubscribeMulticastAddress(&GetInstance(), &ip6Address);
mInitialized = true;
exit:
return;
}
void Interface::HandleExtAddressChange(void)
{
Ip6::Address ip6Address;
VerifyOrExit(mInitialized);
ip6Address.SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());
otPlatTrelUdp6UpdateAddress(&GetInstance(), &ip6Address);
exit:
return;
}
otError Interface::Send(const Packet &aPacket)
{
Ip6::Address destIp6Address;
switch (aPacket.GetHeader().GetType())
{
case Header::kTypeBroadcast:
CreateMulticastIp6Address(destIp6Address);
break;
case Header::kTypeUnicast:
case Header::kTypeAck:
destIp6Address.SetToLinkLocalAddress(aPacket.GetHeader().GetDestination());
break;
}
return otPlatTrelUdp6SendTo(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &destIp6Address);
}
void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength)
{
mRxPacket.Init(aBuffer, aLength);
Get<Link>().ProcessReceivedPacket(mRxPacket);
}
void Interface::CreateMulticastIp6Address(Ip6::Address &aIp6Address)
{
// Use ff02::1 (Link-local All Nodes multicast address).
aIp6Address.SetToLinkLocalAllNodesMulticast();
}
} // namespace Trel
} // namespace ot
extern "C" void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
{
ot::Instance &instance = *static_cast<ot::Instance *>(aInstance);
VerifyOrExit(instance.IsInitialized());
instance.Get<ot::Trel::Interface>().HandleReceived(aBuffer, aLength);
exit:
return;
}
extern "C" OT_TOOL_WEAK otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NOT_IMPLEMENTED;
}
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file includes definitions for Thread Radio Encapsulation Link (TREL) interface.
*/
#ifndef TREL_INTERFACE_HPP_
#define TREL_INTERFACE_HPP_
#include "openthread-core-config.h"
#include "common/locator.hpp"
#include "mac/mac_types.hpp"
#include "net/ip6_address.hpp"
#include "radio/trel_packet.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
/**
* This class represents a TREL link interface.
*
*/
class Interface : public InstanceLocator
{
public:
/**
* This method initializes an `Interface` object
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Interface(Instance &aInstance);
/**
* This method initializes the interface.
*
* This method should be called after OpenThread instance itself is fully initialized, allowing the `Init()` method
* to use method from `Instance` and any of its containing objects.
*
*/
void Init(void);
/**
* This method indicates whether the interface is initialized or not.
*
* @returns TRUE if the interface is initialized, FALSE otherwise.
*
*/
bool IsInitialized(void) const { return mInitialized; }
/**
* This method notifies the interface that device's extended MAC address has changed for it to update any
* internal address/state.
*
*/
void HandleExtAddressChange(void);
/**
* This method sends a packet over the interface.
*
* @note There is no expected callback from the interface to notify completion of send.
*
* @param[in] aPacket A packet to send.
*
* @retval OT_ERROR_NONE The frame was sent successfully.
* @retval OT_ERROR_ABORT The interface is not ready and send was aborted.
*
*/
otError Send(const Packet &aPacket);
/**
* This method is a callback from platform layer to handle a received packet over the interface.
*
* @param[in] aBuffer A pointer to buffer containing the received packet.
* @param[in] aLength The length (number of bytes) in the received packet.
*
*/
void HandleReceived(uint8_t *aBuffer, uint16_t aLength);
private:
enum
{
kUdpPort = 19788, // UDP port (same as MLE port).
};
void CreateMulticastIp6Address(Ip6::Address &aIp6Address);
bool mInitialized;
Packet mRxPacket;
};
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
#endif // TREL_INTERFACE_HPP_
+475
View File
@@ -0,0 +1,475 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file implements Thread Radio Encapsulation Link (TREL).
*/
#include "trel_link.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
Link::Link(Instance &aInstance)
: InstanceLocator(aInstance)
, mState(kStateDisabled)
, mRxChannel(0)
, mPanId(Mac::kPanIdBroadcast)
, mTxPacketNumber(0)
, mTxTasklet(aInstance, HandleTxTasklet, this)
, mTimer(aInstance, HandleTimer, this)
, mInterface(aInstance)
{
memset(&mTxFrame, 0, sizeof(mTxFrame));
memset(&mRxFrame, 0, sizeof(mRxFrame));
memset(mAckFrameBuffer, 0, sizeof(mAckFrameBuffer));
mTxFrame.mPsdu = &mTxPacketBuffer[kMaxHeaderSize];
mTxFrame.SetLength(0);
#if OPENTHREAD_CONFIG_MULTI_RADIO
mTxFrame.SetRadioType(Mac::kRadioTypeTrel);
mRxFrame.SetRadioType(Mac::kRadioTypeTrel);
#endif
// `mTxTasklet` is used for initializing the interface (in addition
// to handling `Send()` requests). Invoking `Interface::Init()` from
// a tasklet ensures that it happens after the constructors for
// `Instance` and all its objects are done, allowing the interface
// to safely use any of the core object methods (e.g., get the
// randomly generated MAC address).
mTxTasklet.Post();
mTimer.Start(kAckWaitWindow);
}
void Link::Enable(void)
{
if (mState == kStateDisabled)
{
SetState(kStateSleep);
}
}
void Link::Disable(void)
{
if (mState != kStateDisabled)
{
SetState(kStateDisabled);
}
}
void Link::Sleep(void)
{
OT_ASSERT(mState != kStateDisabled);
SetState(kStateSleep);
}
void Link::Receive(uint8_t aChannel)
{
OT_ASSERT(mState != kStateDisabled);
mRxChannel = aChannel;
SetState(kStateReceive);
}
void Link::Send(void)
{
OT_ASSERT(mState != kStateDisabled);
SetState(kStateTransmit);
mTxTasklet.Post();
}
void Link::HandleTxTasklet(Tasklet &aTasklet)
{
aTasklet.GetOwner<Link>().HandleTxTasklet();
}
void Link::HandleTxTasklet(void)
{
if (!mInterface.IsInitialized())
{
mInterface.Init();
}
BeginTransmit();
}
void Link::BeginTransmit(void)
{
Mac::Address destAddr;
Mac::PanId destPanId;
Header::Type type;
Packet txPacket;
Neighbor * neighbor = nullptr;
Mac::RxFrame *ackFrame = nullptr;
VerifyOrExit(mState == kStateTransmit);
// After sending a frame on a given channel we should
// continue to rx on same channel
mRxChannel = mTxFrame.GetChannel();
VerifyOrExit(!mTxFrame.IsEmpty(), InvokeSendDone(OT_ERROR_ABORT));
IgnoreError(mTxFrame.GetDstAddr(destAddr));
if (destAddr.IsNone() || destAddr.IsBroadcast())
{
type = Header::kTypeBroadcast;
}
else
{
type = Header::kTypeUnicast;
neighbor = Get<NeighborTable>().FindNeighbor(destAddr, Neighbor::kInStateAnyExceptInvalid);
if (destAddr.IsShort())
{
if (neighbor != nullptr)
{
destAddr.SetExtended(neighbor->GetExtAddress());
}
else
{
// Send as a broadcast since we don't know the dest
// ext address to include in the packet header.
type = Header::kTypeBroadcast;
}
}
}
if (mTxFrame.GetDstPanId(destPanId) != OT_ERROR_NONE)
{
destPanId = Mac::kPanIdBroadcast;
}
txPacket.Init(type, mTxFrame.GetPsdu(), mTxFrame.GetLength());
if (neighbor == nullptr)
{
txPacket.GetHeader().SetAckMode(Header::kNoAck);
txPacket.GetHeader().SetPacketNumber(mTxPacketNumber++);
}
else
{
txPacket.GetHeader().SetAckMode(Header::kAckRequested);
txPacket.GetHeader().SetPacketNumber(neighbor->mTrelTxPacketNumber++);
neighbor->mTrelCurrentPendingAcks++;
}
txPacket.GetHeader().SetChannel(mTxFrame.GetChannel());
txPacket.GetHeader().SetPanId(destPanId);
txPacket.GetHeader().SetSource(Get<Mac::Mac>().GetExtAddress());
if (type == Header::kTypeUnicast)
{
OT_ASSERT(destAddr.IsExtended());
txPacket.GetHeader().SetDestination(destAddr.GetExtended());
}
otLogDebgMac("Trel: BeginTransmit() [%s] plen:%d", txPacket.GetHeader().ToString().AsCString(),
txPacket.GetPayloadLength());
VerifyOrExit(mInterface.Send(txPacket) == OT_ERROR_NONE, InvokeSendDone(OT_ERROR_ABORT));
if (mTxFrame.GetAckRequest())
{
uint16_t fcf = Mac::Frame::kFcfFrameAck;
if (!Get<Mle::MleRouter>().IsRxOnWhenIdle())
{
fcf |= Mac::Frame::kFcfFramePending;
}
// Prepare the ack frame (FCF followed by sequence number)
Encoding::LittleEndian::WriteUint16(fcf, mAckFrameBuffer);
mAckFrameBuffer[sizeof(fcf)] = mTxFrame.GetSequence();
mRxFrame.mPsdu = mAckFrameBuffer;
mRxFrame.mLength = k154AckFrameSize;
mRxFrame.mChannel = mTxFrame.GetChannel();
#if OPENTHREAD_CONFIG_MULTI_RADIO
mRxFrame.mRadioType = Mac::kRadioTypeTrel;
#endif
mRxFrame.mInfo.mRxInfo.mTimestamp = 0;
mRxFrame.mInfo.mRxInfo.mRssi = OT_RADIO_RSSI_INVALID;
mRxFrame.mInfo.mRxInfo.mLqi = OT_RADIO_LQI_NONE;
mRxFrame.mInfo.mRxInfo.mAckedWithFramePending = false;
ackFrame = &mRxFrame;
}
InvokeSendDone(OT_ERROR_NONE, ackFrame);
exit:
return;
}
void Link::InvokeSendDone(otError aError, Mac::RxFrame *aAckFrame)
{
SetState(kStateReceive);
Get<Mac::Mac>().RecordFrameTransmitStatus(mTxFrame, aAckFrame, aError, /* aRetryCount */ 0, /* aWillRetx */ false);
Get<Mac::Mac>().HandleTransmitDone(mTxFrame, aAckFrame, aError);
}
void Link::HandleTimer(Timer &aTimer)
{
aTimer.GetOwner<Link>().HandleTimer();
}
void Link::HandleTimer(void)
{
mTimer.Start(kAckWaitWindow);
#if OPENTHREAD_FTD
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
{
HandleTimer(child);
}
for (Router &router : Get<RouterTable>().Iterate())
{
HandleTimer(router);
}
#endif
// Parent and ParentCandidate should also be updated as neighbors.
// Parent is considered only when the device is detached or child.
// When device becomes a router/leader the parent entry is copied
// into the router table but the MLE parent may still stay in
// valid state. Note that "Parent Candidate" may be in use on a
// router/leader during a partition merge, so it is always treated
// as a neighbor.
switch (Get<Mle::MleRouter>().GetRole())
{
case Mle::kRoleDisabled:
break;
case Mle::kRoleDetached:
case Mle::kRoleChild:
HandleTimer(Get<Mle::MleRouter>().GetParent());
// Fall through
case Mle::kRoleRouter:
case Mle::kRoleLeader:
HandleTimer(Get<Mle::MleRouter>().GetParentCandidate());
break;
}
}
void Link::HandleTimer(Neighbor &aNeighbor)
{
VerifyOrExit(!aNeighbor.IsStateInvalid());
// Any remaining previous pending ack has timed out.
while (aNeighbor.mTrelPreviousPendingAcks > 0)
{
aNeighbor.mTrelPreviousPendingAcks--;
ReportDeferredAckStatus(aNeighbor, OT_ERROR_NO_ACK);
VerifyOrExit(!aNeighbor.IsStateInvalid());
}
aNeighbor.mTrelPreviousPendingAcks = aNeighbor.mTrelCurrentPendingAcks;
aNeighbor.mTrelCurrentPendingAcks = 0;
exit:
return;
}
void Link::ProcessReceivedPacket(Packet &aPacket)
{
Header::Type type;
VerifyOrExit(aPacket.IsHeaderValid());
type = aPacket.GetHeader().GetType();
if (type != Header::kTypeAck)
{
// No need to check state or channel for a TREL ack packet.
// Note that TREL ack may be received much later than the tx
// and device can be on a different rx channel.
VerifyOrExit((mState == kStateReceive) || (mState == kStateTransmit));
VerifyOrExit(aPacket.GetHeader().GetChannel() == mRxChannel);
}
if (mPanId != Mac::kPanIdBroadcast)
{
Mac::PanId rxPanId = aPacket.GetHeader().GetPanId();
VerifyOrExit((rxPanId == mPanId) || (rxPanId == Mac::kPanIdBroadcast));
}
// Drop packets originating from same device.
VerifyOrExit(aPacket.GetHeader().GetSource() != Get<Mac::Mac>().GetExtAddress());
if (type != Header::kTypeBroadcast)
{
VerifyOrExit(aPacket.GetHeader().GetDestination() == Get<Mac::Mac>().GetExtAddress());
if (type == Header::kTypeAck)
{
HandleAck(aPacket);
ExitNow();
}
}
otLogDebgMac("Trel: ReceivedPacket() [%s] plen:%d", aPacket.GetHeader().ToString().AsCString(),
aPacket.GetPayloadLength());
if (aPacket.GetHeader().GetAckMode() == Header::kAckRequested)
{
SendAck(aPacket);
}
mRxFrame.mPsdu = aPacket.GetPayload();
mRxFrame.mLength = aPacket.GetPayloadLength();
mRxFrame.mChannel = aPacket.GetHeader().GetChannel();
#if OPENTHREAD_CONFIG_MULTI_RADIO
mRxFrame.mRadioType = Mac::kRadioTypeTrel;
#endif
mRxFrame.mInfo.mRxInfo.mTimestamp = 0;
mRxFrame.mInfo.mRxInfo.mRssi = kRxRssi;
mRxFrame.mInfo.mRxInfo.mLqi = OT_RADIO_LQI_NONE;
mRxFrame.mInfo.mRxInfo.mAckedWithFramePending = true;
Get<Mac::Mac>().HandleReceivedFrame(&mRxFrame, OT_ERROR_NONE);
exit:
return;
}
void Link::HandleAck(Packet &aAckPacket)
{
otError ackError;
Mac::Address srcAddress;
Neighbor * neighbor;
uint32_t ackNumber;
otLogDebgMac("Trel: HandleAck() [%s]", aAckPacket.GetHeader().ToString().AsCString());
srcAddress.SetExtended(aAckPacket.GetHeader().GetSource());
neighbor = Get<NeighborTable>().FindNeighbor(srcAddress, Neighbor::kInStateAnyExceptInvalid);
VerifyOrExit(neighbor != nullptr);
ackNumber = aAckPacket.GetHeader().GetPacketNumber();
// Verify that neighbor is waiting for acks and the received ack
// number is within the range of expected ack numbers.
VerifyOrExit(neighbor->IsRxAckNumberValid(ackNumber));
do
{
// Check whether the received ack number matches the next
// expected one. If it does not, it indicates that some of
// packets missed their acks.
ackError = (ackNumber == neighbor->GetExpectedTrelAckNumber()) ? OT_ERROR_NONE : OT_ERROR_NO_ACK;
neighbor->DecrementPendingTrelAckCount();
ReportDeferredAckStatus(*neighbor, ackError);
VerifyOrExit(!neighbor->IsStateInvalid());
} while (ackError == OT_ERROR_NO_ACK);
exit:
return;
}
void Link::SendAck(Packet &aRxPacket)
{
Packet ackPacket;
ackPacket.Init(mAckPacketBuffer, sizeof(mAckPacketBuffer));
ackPacket.GetHeader().Init(Header::kTypeAck);
ackPacket.GetHeader().SetAckMode(Header::kNoAck);
ackPacket.GetHeader().SetChannel(aRxPacket.GetHeader().GetChannel());
ackPacket.GetHeader().SetPanId(aRxPacket.GetHeader().GetPanId());
ackPacket.GetHeader().SetPacketNumber(aRxPacket.GetHeader().GetPacketNumber());
ackPacket.GetHeader().SetSource(Get<Mac::Mac>().GetExtAddress());
ackPacket.GetHeader().SetDestination(aRxPacket.GetHeader().GetSource());
otLogDebgMac("Trel: SendAck [%s]", ackPacket.GetHeader().ToString().AsCString());
IgnoreError(mInterface.Send(ackPacket));
}
void Link::ReportDeferredAckStatus(Neighbor &aNeighbor, otError aError)
{
otLogDebgMac("Trel: ReportDeferredAckStatus(): %s for %s", aNeighbor.GetExtAddress().ToString().AsCString(),
otThreadErrorToString(aError));
Get<MeshForwarder>().HandleDeferredAck(aNeighbor, aError);
}
void Link::SetState(State aState)
{
if (mState != aState)
{
otLogDebgMac("Trel: State: %s -> %s", StateToString(mState), StateToString(aState));
mState = aState;
}
}
// LCOV_EXCL_START
const char *Link::StateToString(State aState)
{
static const char *kStateStrings[] = {
"Disabled", // kStateDisabled
"Sleep", // kStateSleep
"Receive", // kStateReceive
"Transmit", // kStateTransmit
};
return (static_cast<uint8_t>(aState) < OT_ARRAY_LENGTH(kStateStrings)) ? kStateStrings[aState] : "Unknown";
}
// LCOV_EXCL_STOP
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+252
View File
@@ -0,0 +1,252 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file includes definitions for Thread Radio Encapsulation Link (TREL).
*/
#ifndef TREL_LINK_HPP_
#define TREL_LINK_HPP_
#include "openthread-core-config.h"
#include "common/encoding.hpp"
#include "common/locator.hpp"
#include "common/tasklet.hpp"
#include "common/timer.hpp"
#include "mac/mac_frame.hpp"
#include "mac/mac_types.hpp"
#include "radio/trel_interface.hpp"
#include "radio/trel_packet.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
class Neighbor;
namespace Trel {
/**
* @addtogroup core-trel
*
* @brief
* This module includes definitions for Thread Radio Encapsulation Link (TREL)
*
* @{
*
*/
/**
* This class represents a Thread Radio Encapsulation Link (TREL).
*
*/
class Link : public InstanceLocator
{
friend class ot::Instance;
friend class Interface;
public:
enum
{
kMtuSize = OT_RADIO_FRAME_MAX_SIZE, ///< MTU size for TREL frame.
kFcsSize = 2, ///< FCS size for TREL frame.
};
/**
* This constructor initializes the `Link` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Link(Instance &aInstance);
/**
* This method sets the PAN Identifier.
*
* @param[in] aPanId A PAN Identifier.
*
*/
void SetPanId(Mac::PanId aPanId) { mPanId = aPanId; }
/**
* This method notifies TREL radio link that device's extended MAC address has changed for it to update any
* internal address/state.
*
*/
void HandleExtAddressChange(void) { mInterface.HandleExtAddressChange(); }
/**
* This method enables the TREL radio link.
*
*/
void Enable(void);
/**
* This method disables the TREL radio link.
*
*/
void Disable(void);
/**
* This method requests TREL radio link to transition to Sleep mode
*
*/
void Sleep(void);
/**
* This method requests TREL radio link to transition to Receive mode on a given channel.
*
* `Mac::HandleReceivedFrame()` is used to notify MAC layer upon receiving a frame.
*
* @param[in] aChannel The channel to receive on.
*
*/
void Receive(uint8_t aChannel);
/**
* This method gets the radio transmit frame for TREL radio link.
*
* @returns The transmit frame.
*
*/
Mac::TxFrame &GetTransmitFrame(void) { return mTxFrame; }
/**
* This method requests a frame to be sent over TREL radio link.
*
* The frame should be already placed in `GetTransmitFrame()` frame.
*
* `Mac::RecordFrameTransmitStatus()` and `Mac::HandleTransmitDone()` are used to notify the success or error status
* of frame transmission upon completion of send.
*
*/
void Send(void);
private:
enum
{
kMaxHeaderSize = sizeof(Header),
k154AckFrameSize = 3 + kFcsSize,
kRxRssi = -20, // The RSSI value used for received frames on TREL radio link.
kAckWaitWindow = 750, // (in msec)
};
enum State : uint8_t
{
kStateDisabled,
kStateSleep,
kStateReceive,
kStateTransmit,
};
void SetState(State aState);
void BeginTransmit(void);
void InvokeSendDone(otError aError) { InvokeSendDone(aError, nullptr); }
void InvokeSendDone(otError aError, Mac::RxFrame *aAckFrame);
void ProcessReceivedPacket(Packet &aPacket);
void HandleAck(Packet &aAckPacket);
void SendAck(Packet &aRxPacket);
void ReportDeferredAckStatus(Neighbor &aNeighbor, otError aError);
void HandleTimer(Neighbor &aNeighbor);
static void HandleTxTasklet(Tasklet &aTasklet);
void HandleTxTasklet(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
static const char *StateToString(State aState);
State mState;
uint8_t mRxChannel;
Mac::PanId mPanId;
uint32_t mTxPacketNumber;
Tasklet mTxTasklet;
TimerMilli mTimer;
Interface mInterface;
Mac::RxFrame mRxFrame;
Mac::TxFrame mTxFrame;
uint8_t mTxPacketBuffer[kMaxHeaderSize + kMtuSize];
uint8_t mAckPacketBuffer[kMaxHeaderSize];
uint8_t mAckFrameBuffer[k154AckFrameSize];
};
/**
* This class defines all the neighbor info required for TREL link.
*
* `Neighbor` class publicly inherits from this class.
*
*/
class NeighborInfo
{
friend class Link;
private:
uint32_t GetPendingTrelAckCount(void) const { return (mTrelPreviousPendingAcks + mTrelCurrentPendingAcks); }
void DecrementPendingTrelAckCount(void)
{
if (mTrelPreviousPendingAcks != 0)
{
mTrelPreviousPendingAcks--;
}
else if (mTrelCurrentPendingAcks != 0)
{
mTrelCurrentPendingAcks--;
}
}
uint32_t GetExpectedTrelAckNumber(void) const { return mTrelTxPacketNumber - GetPendingTrelAckCount(); }
bool IsRxAckNumberValid(uint32_t aAckNumber) const
{
// Note that calculating the difference between `aAckNumber`
// and `GetExpectedTrelAckNumber` will correctly handle the
// roll-over of packet number value.
return (GetPendingTrelAckCount() != 0) && (aAckNumber - GetExpectedTrelAckNumber() < GetPendingTrelAckCount());
}
uint32_t mTrelTxPacketNumber; // Next packet number to use for tx
uint16_t mTrelCurrentPendingAcks; // Number of pending acks for current interval.
uint16_t mTrelPreviousPendingAcks; // Number of pending acks for previous interval.
};
/**
* @}
*
*/
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
#endif // TREL_LINK_HPP_
+140
View File
@@ -0,0 +1,140 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file implements Thread Radio Encapsulation Link (TREL) packet.
*/
#include "trel_packet.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
void Header::SetAckMode(AckMode aAckMode)
{
switch (aAckMode)
{
case kNoAck:
mControl &= ~kAckModeFlag;
break;
case kAckRequested:
mControl |= kAckModeFlag;
break;
}
}
uint16_t Header::GetSize(Type aType)
{
uint16_t size = sizeof(Header);
switch (aType)
{
case kTypeBroadcast:
size -= sizeof(Mac::ExtAddress); // Exclude mDestination field.
break;
case kTypeUnicast:
case kTypeAck:
break;
}
return size;
}
Header::InfoString Header::ToString(void) const
{
Type type = GetType();
InfoString string;
switch (type)
{
case kTypeBroadcast:
IgnoreError(string.Set("broadcast ch:%d", GetChannel()));
break;
case kTypeUnicast:
IgnoreError(string.Set("unicast ch:%d", GetChannel()));
break;
case kTypeAck:
IgnoreError(string.Set("ack"));
break;
}
IgnoreError(
string.Append(" panid:%04x num:%lu src:%s", GetPanId(), GetPacketNumber(), GetSource().ToString().AsCString()));
if ((type == kTypeUnicast) || (type == kTypeAck))
{
IgnoreError(string.Append(" dst:%s", GetDestination().ToString().AsCString()));
}
if ((type == kTypeUnicast) || (type == kTypeBroadcast))
{
IgnoreError(string.Append(GetAckMode() == kNoAck ? " no-ack" : " ack-req"));
}
return string;
}
void Packet::Init(uint8_t *aBuffer, uint16_t aLength)
{
mBuffer = aBuffer;
mLength = aLength;
}
void Packet::Init(Header::Type aType, uint8_t *mPayload, uint16_t mPayloadLength)
{
uint16_t headerSize = Header::GetSize(aType);
// The payload buffer should reserve enough bytes for
// header (depending on type) before the payload.
Init(mPayload - headerSize, mPayloadLength + headerSize);
GetHeader().Init(aType);
}
bool Packet::IsHeaderValid(void) const
{
return ((mBuffer != nullptr) && (mLength > 0) && GetHeader().IsVersionValid() &&
(mLength >= GetHeader().GetLength()));
}
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+373
View File
@@ -0,0 +1,373 @@
/*
* Copyright (c) 2019, 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.
*/
/**
* @file
* This file includes definitions for Thread Radio Encapsulation Link (TREL) Packet
*/
#ifndef TREL_PACKET_HPP_
#define TREL_PACKET_HPP_
#include "openthread-core-config.h"
#include "common/encoding.hpp"
#include "common/locator.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
namespace ot {
namespace Trel {
/**
* This class represents a TREL radio link packet encapsulation header.
*
*/
OT_TOOL_PACKED_BEGIN
class Header
{
public:
/**
* This enumeration defines packet types.
*
*/
enum Type
{
kTypeBroadcast = 0, ///< A TREL broadcast packet.
kTypeUnicast = 1, ///< A TREL unicast packet.
kTypeAck = 2, ///< A TREL Ack packet.
};
/**
* This enumeration represents Ack Mode field in TREL header.
*
*/
enum AckMode
{
kNoAck, ///< No TREL Ack is requested.
kAckRequested, ///< A TREL Ack is requested.
};
enum
{
kInfoStringSize = 128, ///< Max chars needed for the info string representation (@sa ToInfoString()).
};
/**
* This type defines the fixed-length `String` object returned from `ToString()` method.
*
*/
typedef String<kInfoStringSize> InfoString;
/**
* This method initializes the header.
*
* @param[in] aType The header type.
*
*/
void Init(Type aType) { mControl = aType + kVersion; }
/**
* This method checks whether the version field in header is valid or not
*
* @returns TRUE if the version field is valid, FALSE otherwise.
*
*/
bool IsVersionValid(void) const { return (mControl & kVersionMask) == kVersion; }
/**
* This method gets the packet type.
*
* @returns The packet type.
*
*/
Type GetType(void) const { return static_cast<Type>(mControl & kTypeMask); }
/**
* This method gets the header length based on its type.
*
* @returns the header length (number of bytes).
*
*/
uint16_t GetLength(void) const { return GetSize(GetType()); }
/**
* This method gets the Ack Mode field from the header.
*
* @returns The Ack Mode field.
*
*/
AckMode GetAckMode(void) const { return (mControl & kAckModeFlag) ? kAckRequested : kNoAck; }
/**
* This method sets the Ack Mode field in the header.
*
* @param[in] aAckMode The Ack Mode field
*
*/
void SetAckMode(AckMode aAckMode);
/**
* This method gets the channel field from the header.
*
* @returns The channel field.
*
*/
uint8_t GetChannel(void) const { return mChannel; }
/**
* This method sets the channel field in the header.
*
* @param[in] aChannel A channel.
*
*/
void SetChannel(uint8_t aChannel) { mChannel = aChannel; }
/**
* This method gets the PAN Identifier field from the header.
*
* @returns The PAN Identifier field.
*
*/
Mac::PanId GetPanId(void) const { return Encoding::BigEndian::HostSwap16(mPanId); }
/**
* This method sets the PAN Identifier field in the header.
*
* @param[in] aPanId A PAN Identifier.
*
*/
void SetPanId(Mac::PanId aPanId) { mPanId = Encoding::BigEndian::HostSwap16(aPanId); }
/**
* This method gets the packet number field from the header.
*
* @returns The packet number field.
*
*/
uint32_t GetPacketNumber(void) const { return Encoding::BigEndian::HostSwap32(mPacketNumber); }
/**
* This method sets the packet number field in the header.
*
* @param[in] aPacketNumber The packet number.
*
*/
void SetPacketNumber(uint32_t aPacketNumber) { mPacketNumber = Encoding::BigEndian::HostSwap32(aPacketNumber); }
/**
* This method gets the source MAC address field from the header.
*
* @returns The source MAC address field.
*
*/
const Mac::ExtAddress &GetSource(void) const { return mSource; }
/**
* This method sets the source MAC address filed in the header.
*
* @param[in] aSource A MAC extended address to set as source.
*
*/
void SetSource(const Mac::ExtAddress &aSource) { mSource = aSource; }
/**
* This method gets the destination MAC address field from the header.
*
* This method MUST be used with a unicast of ack type packet, otherwise its behavior is undefined.
*
* @returns The destination MAC address field.
*
*/
const Mac::ExtAddress &GetDestination(void) const { return mDestination; }
/**
* This method sets the destination MAC address field in the header.
*
* This method MUST be used with a unicast of ack type packet, otherwise its behavior is undefined.
*
* @param[in] aDest A MAC extended address to set as destination.
*
*/
void SetDestination(const Mac::ExtAddress &aDest) { mDestination = aDest; }
/**
* This static method gets the size (number of bytes) in header of given packet type.
*
* @param[in] aType The packet type.
*
* @returns The fixed header size (number of bytes) for @p aType packet.
*
*/
static uint16_t GetSize(Type aType);
/**
* This method returns a string representation of header.
*
* @returns An `InfoString` representation of header.
*
*/
InfoString ToString(void) const;
private:
enum
{
kTypeMask = (3 << 0), // Bits 0-1 specify packet `Type`
kAckModeFlag = (1 << 2), // Bit 2 indicate "ack mode" (TREL ack requested or not).
kVersionMask = (7 << 5), // Bits 5-7 specify the version.
kVersion = (0 << 5), // Current TREL header version.
};
// All header fields are big-endian.
uint8_t mControl;
uint8_t mChannel;
uint16_t mPanId;
uint32_t mPacketNumber;
Mac::ExtAddress mSource;
Mac::ExtAddress mDestination; // Present in `kTypeAck` or `kTypeUnicast` packet types.
} OT_TOOL_PACKED_END;
/**
* This class represent a TREL radio link packet.
*
*/
class Packet
{
public:
/**
* This method initializes the `Packet` with a given buffer and length.
*
* @param[in] aBuffer A pointer to a buffer containing the entire packet (header and payload).
* @param[in] aLength Length (number of bytes) of the packet (including header and payload).
*
*/
void Init(uint8_t *aBuffer, uint16_t aLength);
/**
* This method initializes the `Packet` with a specified header type and given a payload.
*
* The payload buffer @p aPayload should have space reserved before the start of payload for the packet header.
* This method will initialize the header with the given type @p aType. Rest of header fields can be updated after
* initializing the packet.
*
* @param[in] aType The packet type.
* @param[in] aPayload A pointer to a buffer containing the packet payload. Buffer should have space reserved
* for header before the payload.
* @param[in] aPayloadLength The length (number of bytes) in the payload only (not including the header).
*
*/
void Init(Header::Type aType, uint8_t *aPayload, uint16_t aPayloadLength);
/**
* This method gets a pointer to buffer containing the packet.
*
* @returns A pointer to buffer containing the packet.
*
*/
uint8_t *GetBuffer(void) { return mBuffer; }
/**
* This method gets a pointer to buffer containing the packet.
*
* @returns A pointer to buffer containing the packet.
*
*/
const uint8_t *GetBuffer(void) const { return mBuffer; }
/**
* This method gets the length of packet.
*
* @returns The length (number of bytes) of packet (header and payload).
*
*/
uint16_t GetLength(void) const { return mLength; }
/**
* This method checks whether or not the packet header is valid.
*
* @retval TRUE The packet header is valid and well-formed.
* @retval FALSE The packet header is not valid.
*
*/
bool IsHeaderValid(void) const;
/**
* This method gets the packet header.
*
* @returns A reference to the packet header as `Header`.
*
*/
Header &GetHeader(void) { return *reinterpret_cast<Header *>(mBuffer); }
/**
* This method gets the packet header.
*
* @returns A reference to the packet header as `Header`.
*
*/
const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mBuffer); }
/**
* This method gets a pointer to start of packet payload.
*
* @returns A pointer to start of packet payload (after header).
*
*/
uint8_t *GetPayload(void) { return mBuffer + GetHeader().GetLength(); }
/**
* This method gets a pointer to start of packet payload.
*
* @returns A pointer to start of packet payload (after header).
*
*/
const uint8_t *GetPayload(void) const { return mBuffer + GetHeader().GetLength(); }
/**
* This method gets the payload length.
*
* @returns The packet payload length (number of bytes).
*
*/
uint16_t GetPayloadLength(void) const { return mLength - GetHeader().GetLength(); }
private:
uint8_t *mBuffer;
uint16_t mLength;
};
} // namespace Trel
} // namespace ot
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
#endif // TREL_PACKET_HPP_
+5
View File
@@ -46,6 +46,7 @@
#include "common/timer.hpp"
#include "mac/mac_types.hpp"
#include "net/ip6.hpp"
#include "radio/trel_link.hpp"
#include "thread/csl_tx_scheduler.hpp"
#include "thread/indirect_sender.hpp"
#include "thread/link_metrics.hpp"
@@ -69,6 +70,10 @@ class Neighbor : public InstanceLocatorInit
,
public RadioSelector::NeighborInfo
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
,
public Trel::NeighborInfo
#endif
{
public:
/**
+43
View File
@@ -610,4 +610,47 @@ void otPlatOtnsStatus(const char *aStatus)
}
#endif // OPENTHREAD_CONFIG_OTNS_ENABLE
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aUnicastAddress);
OT_UNUSED_VARIABLE(aUdpPort);
}
void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aUnicastAddress);
}
void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aMulticastAddress);
}
otError otPlatTrelUdp6SendTo(otInstance * aInstance,
const uint8_t * aBuffer,
uint16_t aLength,
const otIp6Address *aDestAddress)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aBuffer);
OT_UNUSED_VARIABLE(aLength);
OT_UNUSED_VARIABLE(aDestAddress);
return OT_ERROR_ABORT;
}
otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
return OT_ERROR_NOT_IMPLEMENTED;
}
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
} // extern "C"