From e4bf2ffe3480f8df34bbe9fde36a1a8747e7742d Mon Sep 17 00:00:00 2001 From: Zang MingJie Date: Tue, 25 Oct 2022 05:57:48 +0800 Subject: [PATCH] [netif-posix] add an option to persistent interface (#8033) --- src/posix/main.c | 13 +++- .../include/openthread/openthread-system.h | 1 + src/posix/platform/netif.cpp | 71 ++++++++++++------- src/posix/platform/platform-posix.h | 2 +- src/posix/platform/system.cpp | 2 +- 5 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/posix/main.c b/src/posix/main.c index d6de188a4..bfd14a435 100644 --- a/src/posix/main.c +++ b/src/posix/main.c @@ -141,6 +141,7 @@ enum OT_POSIX_OPT_DRY_RUN = 'n', OT_POSIX_OPT_HELP = 'h', OT_POSIX_OPT_INTERFACE_NAME = 'I', + OT_POSIX_OPT_PERSISTENT_INTERFACE = 'p', OT_POSIX_OPT_TIME_SPEED = 's', OT_POSIX_OPT_VERBOSE = 'v', @@ -156,6 +157,7 @@ static const struct option kOptions[] = { {"dry-run", no_argument, NULL, OT_POSIX_OPT_DRY_RUN}, {"help", no_argument, NULL, OT_POSIX_OPT_HELP}, {"interface-name", required_argument, NULL, OT_POSIX_OPT_INTERFACE_NAME}, + {"persistent-interface", no_argument, NULL, OT_POSIX_OPT_PERSISTENT_INTERFACE}, {"radio-version", no_argument, NULL, OT_POSIX_OPT_RADIO_VERSION}, {"real-time-signal", required_argument, NULL, OT_POSIX_OPT_REAL_TIME_SIGNAL}, {"time-speed", required_argument, NULL, OT_POSIX_OPT_TIME_SPEED}, @@ -174,6 +176,7 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) " -I --interface-name name Thread network interface name.\n" " -n --dry-run Just verify if arguments is valid and radio spinel is compatible.\n" " --radio-version Print radio firmware version.\n" + " -p --persistent-interface Persistent the created thread network interface\n" " -s --time-speed factor Time speed up factor.\n" " -v --verbose Also log to stderr.\n", aProgramName); @@ -191,8 +194,9 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) { memset(aConfig, 0, sizeof(*aConfig)); - aConfig->mPlatformConfig.mSpeedUpFactor = 1; - aConfig->mLogLevel = OT_LOG_LEVEL_CRIT; + aConfig->mPlatformConfig.mPersistentInterface = false; + aConfig->mPlatformConfig.mSpeedUpFactor = 1; + aConfig->mLogLevel = OT_LOG_LEVEL_CRIT; #ifdef __linux__ aConfig->mPlatformConfig.mRealTimeSignal = SIGRTMIN; #endif @@ -202,7 +206,7 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) while (true) { int index = 0; - int option = getopt_long(aArgCount, aArgVector, "B:d:hI:ns:v", kOptions, &index); + int option = getopt_long(aArgCount, aArgVector, "B:d:hI:nps:v", kOptions, &index); if (option == -1) { @@ -220,6 +224,9 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) case OT_POSIX_OPT_INTERFACE_NAME: aConfig->mPlatformConfig.mInterfaceName = optarg; break; + case OT_POSIX_OPT_PERSISTENT_INTERFACE: + aConfig->mPlatformConfig.mPersistentInterface = true; + break; case OT_POSIX_OPT_BACKBONE_INTERFACE_NAME: aConfig->mPlatformConfig.mBackboneInterfaceName = optarg; break; diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h index 9a1a666bd..e8a09dcb8 100644 --- a/src/posix/platform/include/openthread/openthread-system.h +++ b/src/posix/platform/include/openthread/openthread-system.h @@ -80,6 +80,7 @@ typedef struct otPlatformConfig uint8_t mRadioUrlNum; ///< Number of Radio URLs. int mRealTimeSignal; ///< The real-time signal for microsecond timer. uint32_t mSpeedUpFactor; ///< Speed up factor. + bool mPersistentInterface; ///< Whether persistent the interface bool mDryRun; ///< If 'DryRun' is set, the posix daemon will exit ///< directly after initialization. } otPlatformConfig; diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp index f93cfa2d9..ec7fbcfde 100644 --- a/src/posix/platform/netif.cpp +++ b/src/posix/platform/netif.cpp @@ -533,12 +533,13 @@ exit: SuccessOrDie(error); } -static void UpdateLink(otInstance *aInstance) +static void SetLinkState(otInstance *aInstance, bool aState) { + OT_UNUSED_VARIABLE(aInstance); + otError error = OT_ERROR_NONE; struct ifreq ifr; bool ifState = false; - bool otState = false; assert(gInstance == aInstance); @@ -548,14 +549,13 @@ static void UpdateLink(otInstance *aInstance) VerifyOrExit(ioctl(sIpFd, SIOCGIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED); ifState = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? true : false; - otState = otIp6IsEnabled(aInstance); - otLogNotePlat("[netif] Changing interface state to %s%s.", otState ? "up" : "down", - (ifState == otState) ? " (already done, ignoring)" : ""); + otLogNotePlat("[netif] Changing interface state to %s%s.", aState ? "up" : "down", + (ifState == aState) ? " (already done, ignoring)" : ""); - if (ifState != otState) + if (ifState != aState) { - ifr.ifr_flags = otState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP); + ifr.ifr_flags = aState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP); VerifyOrExit(ioctl(sIpFd, SIOCSIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED); #if defined(RTM_NEWLINK) && defined(RTM_DELLINK) // wait for RTM_NEWLINK event before processing notification from kernel to avoid infinite loop @@ -570,6 +570,12 @@ exit: } } +static void UpdateLink(otInstance *aInstance) +{ + assert(gInstance == aInstance); + SetLinkState(aInstance, otIp6IsEnabled(aInstance)); +} + #if defined(__linux__) template otError AddRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen, uint32_t aPriority) { @@ -1597,21 +1603,27 @@ exit: #if defined(__linux__) // set up the tun device -static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceName, size_t deviceNameLen) +static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig) { struct ifreq ifr; + const char * interfaceName; sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK); VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO); memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TUN | IFF_NO_PI | static_cast(IFF_TUN_EXCL); - - if (aInterfaceName) + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + if (!aPlatformConfig->mPersistentInterface) { - VerifyOrDie(strlen(aInterfaceName) < IFNAMSIZ, OT_EXIT_INVALID_ARGUMENTS); + ifr.ifr_flags |= static_cast(IFF_TUN_EXCL); + } - strncpy(ifr.ifr_name, aInterfaceName, IFNAMSIZ); + interfaceName = aPlatformConfig->mInterfaceName; + if (interfaceName) + { + VerifyOrDie(strlen(interfaceName) < IFNAMSIZ, OT_EXIT_INVALID_ARGUMENTS); + + strncpy(ifr.ifr_name, interfaceName, IFNAMSIZ); } else { @@ -1619,9 +1631,18 @@ static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceN } VerifyOrDie(ioctl(sTunFd, TUNSETIFF, static_cast(&ifr)) == 0, OT_EXIT_ERROR_ERRNO); - VerifyOrDie(ioctl(sTunFd, TUNSETLINK, ARPHRD_VOID) == 0, OT_EXIT_ERROR_ERRNO); - strncpy(deviceName, ifr.ifr_name, deviceNameLen); + strncpy(gNetifName, ifr.ifr_name, sizeof(gNetifName)); + + if (aPlatformConfig->mPersistentInterface) + { + VerifyOrDie(ioctl(sTunFd, TUNSETPERSIST, 1) == 0, OT_EXIT_ERROR_ERRNO); + // Set link down to reset the tun configuration. + // This will drop all existing IP addresses on the interface. + SetLinkState(gInstance, false); + } + + VerifyOrDie(ioctl(sTunFd, TUNSETLINK, ARPHRD_VOID) == 0, OT_EXIT_ERROR_ERRNO); ifr.ifr_mtu = static_cast(kMaxIp6Size); VerifyOrDie(ioctl(sIpFd, SIOCSIFMTU, static_cast(&ifr)) == 0, OT_EXIT_ERROR_ERRNO); @@ -1629,9 +1650,9 @@ static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceN #endif #if defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN) -static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceName, size_t deviceNameLen) +static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig) { - (void)aInterfaceName; + (void)aPlatformConfig; int err = 0; struct sockaddr_ctl addr; struct ctl_info info; @@ -1654,11 +1675,11 @@ static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceN VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO); socklen_t devNameLen; - devNameLen = (socklen_t)deviceNameLen; - err = getsockopt(sTunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, deviceName, &devNameLen); + devNameLen = (socklen_t)sizeof(gNetifName); + err = getsockopt(sTunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gNetifName, &devNameLen); VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO); - otLogInfoPlat("[netif] Tunnel device name = '%s'", deviceName); + otLogInfoPlat("[netif] Tunnel device name = '%s'", gNetifName); } #endif @@ -1681,14 +1702,14 @@ exit: #if defined(__NetBSD__) || \ (defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN)) || \ defined(__FreeBSD__) -static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceName, size_t deviceNameLen) +static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig) { int flags = IFF_BROADCAST | IFF_MULTICAST; int err; const char *last_slash; const char *path; - (void)aInterfaceName; + (void)aPlatformConfig; path = OPENTHREAD_POSIX_TUN_DEVICE; @@ -1708,7 +1729,7 @@ static void platformConfigureTunDevice(const char *aInterfaceName, char *deviceN VerifyOrDie(last_slash != nullptr, OT_EXIT_ERROR_ERRNO); last_slash++; - strncpy(deviceName, last_slash, deviceNameLen); + strncpy(gNetifName, last_slash, sizeof(gNetifName)); } #endif @@ -1760,13 +1781,13 @@ static void platformConfigureNetLink(void) #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) } -void platformNetifInit(const char *aInterfaceName) +void platformNetifInit(otPlatformConfig *aPlatformConfig) { sIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock); VerifyOrDie(sIpFd >= 0, OT_EXIT_ERROR_ERRNO); platformConfigureNetLink(); - platformConfigureTunDevice(aInterfaceName, gNetifName, sizeof(gNetifName)); + platformConfigureTunDevice(aPlatformConfig); gNetifIndex = if_nametoindex(gNetifName); VerifyOrDie(gNetifIndex > 0, OT_EXIT_FAILURE); diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index b23b77c1f..a3b21722d 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -244,7 +244,7 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co * @param[in] aInterfaceName A pointer to Thread network interface name. * */ -void platformNetifInit(const char *aInterfaceName); +void platformNetifInit(otPlatformConfig *aPlatformConfig); /** * This function sets up platform netif. diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp index 7aa6c9b90..6d836c094 100644 --- a/src/posix/platform/system.cpp +++ b/src/posix/platform/system.cpp @@ -154,7 +154,7 @@ void platformInit(otPlatformConfig *aPlatformConfig) #endif #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE - platformNetifInit(aPlatformConfig->mInterfaceName); + platformNetifInit(aPlatformConfig); #endif #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE