[simulation] allow specify local host (#9925)

This commit adds a argument `-L`/`--local-host` to simulation platform
to specify the source IP address for packets simulating 15.4
frames. This allows the simulation packets being transmitted over
different network interfaces, so that the simulation can run on
different hosts.

This can be used to enable multiple emulation devices(e.g. Android
Virtual Device) communicating to each other over emulated Thread
radio.

The argument accepts either an IPv4 address or a network interface
name. In the latter case, the first found IPv4 address on that
interface will be used will be used.
This commit is contained in:
Yakun Xu
2024-03-13 11:42:53 -07:00
committed by GitHub
parent cf6dcc5bc7
commit 3ebc3d3a06
4 changed files with 116 additions and 4 deletions
+4 -2
View File
@@ -36,6 +36,8 @@
#define UTILS_SOCKET_LOCAL_HOST_ADDR "127.0.0.1"
#define UTILS_SOCKET_GROUP_ADDR "224.0.0.116"
const char *gLocalHost = UTILS_SOCKET_LOCAL_HOST_ADDR;
void utilsAddFdToFdSet(int aFd, fd_set *aFdSet, int *aMaxFd)
{
otEXPECT(aFd >= 0);
@@ -75,7 +77,7 @@ void utilsInitSocket(utilsSocket *aSocket, uint16_t aPortBase)
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(aSocket->mPort);
sockaddr.sin_addr.s_addr = inet_addr(UTILS_SOCKET_LOCAL_HOST_ADDR);
sockaddr.sin_addr.s_addr = inet_addr(gLocalHost);
rval = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &sockaddr.sin_addr, sizeof(sockaddr.sin_addr));
otEXPECT_ACTION(rval != -1, perror("setsockopt(TxFd, IP_MULTICAST_IF)"));
@@ -103,7 +105,7 @@ void utilsInitSocket(utilsSocket *aSocket, uint16_t aPortBase)
memset(&mreq, 0, sizeof(mreq));
inet_pton(AF_INET, UTILS_SOCKET_GROUP_ADDR, &mreq.imr_multiaddr);
mreq.imr_address.s_addr = inet_addr(UTILS_SOCKET_LOCAL_HOST_ADDR);
mreq.imr_address.s_addr = inet_addr(gLocalHost);
rval = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_address, sizeof(mreq.imr_address));
otEXPECT_ACTION(rval != -1, perror("setsockopt(RxFd, IP_MULTICAST_IF)"));
@@ -46,6 +46,8 @@ typedef struct utilsSocket
uint16_t mPort; ///< The port number used by this node
} utilsSocket;
extern const char *gLocalHost; ///< Local host address to use for sockets
/**
* Adds a file descriptor (FD) to a given FD set.
*
+66 -2
View File
@@ -36,19 +36,27 @@
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <ifaddrs.h>
#include <libgen.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include "simul_utils.h"
#include "utils/code_utils.h"
uint32_t gNodeId = 1;
extern bool gPlatformPseudoResetWasRequested;
@@ -71,6 +79,7 @@ enum
{
OT_SIM_OPT_HELP = 'h',
OT_SIM_OPT_ENABLE_ENERGY_SCAN = 'E',
OT_SIM_OPT_LOCAL_HOST = 'L',
OT_SIM_OPT_SLEEP_TO_TX = 't',
OT_SIM_OPT_TIME_SPEED = 's',
OT_SIM_OPT_LOG_FILE = 'l',
@@ -96,6 +105,56 @@ static void PrintUsage(const char *aProgramName, int aExitCode)
exit(aExitCode);
}
static const char *GetLocalHostAddress(const char *aLocalHost)
{
struct ifaddrs *ifaddr;
static char ipstr[INET_ADDRSTRLEN] = {0};
const char *rval = NULL;
{
struct in_addr addr;
otEXPECT_ACTION(inet_aton(aLocalHost, &addr) == 0, rval = aLocalHost);
}
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
{
continue;
}
if (strcmp(ifa->ifa_name, aLocalHost) == 0)
{
struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
if (inet_ntop(AF_INET, &addr->sin_addr, ipstr, sizeof(ipstr)))
{
break;
}
}
}
freeifaddrs(ifaddr);
if (ipstr[0] == '\0')
{
fprintf(stderr, "Local host address not found!\n");
exit(EXIT_FAILURE);
}
rval = ipstr;
exit:
return rval;
}
void otSysInit(int aArgCount, char *aArgVector[])
{
char *endptr;
@@ -106,6 +165,7 @@ void otSysInit(int aArgCount, char *aArgVector[])
{"enable-energy-scan", no_argument, 0, OT_SIM_OPT_ENABLE_ENERGY_SCAN},
{"sleep-to-tx", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
{"time-speed", required_argument, 0, OT_SIM_OPT_TIME_SPEED},
{"local-host", required_argument, 0, OT_SIM_OPT_LOCAL_HOST},
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
{"log-file", required_argument, 0, OT_SIM_OPT_LOG_FILE},
#endif
@@ -113,9 +173,9 @@ void otSysInit(int aArgCount, char *aArgVector[])
};
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
static const char options[] = "Ehts:l:";
static const char options[] = "Ehts:L:l:";
#else
static const char options[] = "Ehts:";
static const char options[] = "Ehts:L:";
#endif
if (gPlatformPseudoResetWasRequested)
@@ -149,6 +209,10 @@ void otSysInit(int aArgCount, char *aArgVector[])
case OT_SIM_OPT_SLEEP_TO_TX:
gRadioCaps |= OT_RADIO_CAPS_SLEEP_TO_TX;
break;
case OT_SIM_OPT_LOCAL_HOST:
gLocalHost = GetLocalHostAddress(optarg);
fprintf(stderr, "Simulate on %s\n", gLocalHost);
break;
case OT_SIM_OPT_TIME_SPEED:
speedUpFactor = (uint32_t)strtol(optarg, &endptr, 10);
if (*endptr != '\0' || speedUpFactor == 0)