diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h index 321dd2eab..713c97fe5 100644 --- a/src/posix/platform/openthread-posix-config.h +++ b/src/posix/platform/openthread-posix-config.h @@ -57,6 +57,25 @@ #define OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME "" #endif +/** + * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET + * + * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()` + * command. + * + * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif. + * + * Use of netlink is enabled by default on linux-based platforms. + * + */ +#ifndef OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET +#ifdef __linux__ +#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1 +#else +#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0 +#endif +#endif + /** * @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME * diff --git a/src/posix/platform/trel_udp6.cpp b/src/posix/platform/trel_udp6.cpp index 1b3ff0ce9..5b224b667 100644 --- a/src/posix/platform/trel_udp6.cpp +++ b/src/posix/platform/trel_udp6.cpp @@ -35,6 +35,10 @@ #include "platform-posix.h" +#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET && !defined(__linux__) +#error "netlink socket use is only supported on linux platform" +#endif + #include #include #include @@ -43,6 +47,11 @@ #include #include #include +#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET +#include +#include +#include +#endif #include @@ -57,6 +66,9 @@ #define USEC_PER_MSEC 1000u #define TREL_SOCKET_BIND_MAX_WAIT_TIME_MSEC 4000u +#define TREL_UNICAST_ADDRESS_PREFIX_LEN 64 +#define TREL_UNICAST_ADDRESS_SCOPE 2 // The unicast address is link-local + typedef struct TxPacket { struct TxPacket *mNext; @@ -126,6 +138,66 @@ exit: #endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG) #endif // OPENTHREAD_CONFIG_LOG_PLATFORM +#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET + +static void UpdateUnicastAddress(const otIp6Address *aUnicastAddress, bool aToAdd) +{ + int netlinkSocket; + int ret; + struct rtattr *rta; + + struct + { + struct nlmsghdr nh; + struct ifaddrmsg ifa; + char buf[64]; + } request; + + netlinkSocket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + VerifyOrDie(netlinkSocket >= 0, OT_EXIT_ERROR_ERRNO); + + memset(&request, 0, sizeof(request)); + + request.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + request.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; + request.nh.nlmsg_type = aToAdd ? RTM_NEWADDR : RTM_DELADDR; + request.nh.nlmsg_pid = 0; + request.nh.nlmsg_seq = 0; + + request.ifa.ifa_family = AF_INET6; + request.ifa.ifa_prefixlen = TREL_UNICAST_ADDRESS_PREFIX_LEN; + request.ifa.ifa_flags = IFA_F_NODAD; + request.ifa.ifa_scope = TREL_UNICAST_ADDRESS_SCOPE; + request.ifa.ifa_index = sInterfaceIndex; + + rta = reinterpret_cast((reinterpret_cast(&request)) + NLMSG_ALIGN(request.nh.nlmsg_len)); + rta->rta_type = IFA_LOCAL; + rta->rta_len = RTA_LENGTH(sizeof(otIp6Address)); + + memcpy(RTA_DATA(rta), aUnicastAddress, sizeof(otIp6Address)); + + request.nh.nlmsg_len = NLMSG_ALIGN(request.nh.nlmsg_len) + rta->rta_len; + + ret = send(netlinkSocket, &request, request.nh.nlmsg_len, 0); + VerifyOrDie(ret != -1, OT_EXIT_ERROR_ERRNO); + + close(netlinkSocket); +} + +static void AddUnicastAddress(const otIp6Address *aUnicastAddress) +{ + otLogDebgPlat("[trel] AddUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress)); + UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ true); +} + +static void RemoveUnicastAddress(const otIp6Address *aUnicastAddress) +{ + otLogDebgPlat("[trel] RemoveUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress)); + UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ false); +} + +#else // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET + static void AddUnicastAddress(const otIp6Address *aUnicastAddress) { int mgmtFd; @@ -185,6 +257,8 @@ static void RemoveUnicastAddress(const otIp6Address *aUnicastAddress) close(mgmtFd); } +#endif // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET + static void PrepareSocket(void) { int val; diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h index fae209594..fb411377b 100644 --- a/tests/toranj/openthread-core-toranj-config-posix.h +++ b/tests/toranj/openthread-core-toranj-config-posix.h @@ -61,6 +61,21 @@ */ #define OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME "trel" +/** + * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET + * + * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()` + * command. + * + * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif. + * + */ +#ifdef __linux__ +#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1 +#else +#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0 +#endif + /** * @def OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE *