From 15584dcda3cee6658ebf2bf3b70d42724168a9d0 Mon Sep 17 00:00:00 2001 From: Simon Lin Date: Tue, 10 Aug 2021 10:49:18 +0800 Subject: [PATCH] [cli] allow binding CLI udp socket to unspecified interface (#6761) --- include/openthread/instance.h | 2 +- include/openthread/platform/udp.h | 11 ----------- include/openthread/udp.h | 14 +++++++++++++- src/cli/README_UDP.md | 12 ++++++++++-- src/cli/cli_udp.cpp | 18 +++++++++++++++--- src/core/api/udp_api.cpp | 4 ++-- tools/otci/otci/__init__.py | 5 +++-- tools/otci/otci/otci.py | 12 +++++++++--- tools/otci/otci/types.py | 7 +++++++ tools/otci/tests/test_otci.py | 16 +++++++++------- 10 files changed, 69 insertions(+), 32 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 9bb79e623..498ba5c54 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (143) +#define OPENTHREAD_API_VERSION (144) /** * @addtogroup api-instance diff --git a/include/openthread/platform/udp.h b/include/openthread/platform/udp.h index 936b0c71e..345f15962 100644 --- a/include/openthread/platform/udp.h +++ b/include/openthread/platform/udp.h @@ -41,17 +41,6 @@ extern "C" { #endif -/** - * This enumeration defines the OpenThread network interface identifiers. - * - */ -typedef enum otNetifIdentifier -{ - OT_NETIF_UNSPECIFIED = 0, ///< Unspecified network interface. - OT_NETIF_THREAD, ///< The Thread interface. - OT_NETIF_BACKBONE, ///< The Backbone interface. -} otNetifIdentifier; - /** * This function initializes the UDP socket by platform. * diff --git a/include/openthread/udp.h b/include/openthread/udp.h index 344373aea..3b2ffceba 100644 --- a/include/openthread/udp.h +++ b/include/openthread/udp.h @@ -130,6 +130,17 @@ typedef struct otUdpSocket struct otUdpSocket *mNext; ///< A pointer to the next UDP socket (internal use only). } otUdpSocket; +/** + * This enumeration defines the OpenThread network interface identifiers. + * + */ +typedef enum otNetifIdentifier +{ + OT_NETIF_UNSPECIFIED = 0, ///< Unspecified network interface. + OT_NETIF_THREAD, ///< The Thread interface. + OT_NETIF_BACKBONE, ///< The Backbone interface. +} otNetifIdentifier; + /** * Allocate a new message buffer for sending a UDP message. * @@ -189,12 +200,13 @@ otError otUdpClose(otInstance *aInstance, otUdpSocket *aSocket); * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aSocket A pointer to a UDP socket structure. * @param[in] aSockName A pointer to an IPv6 socket address structure. + * @param[in] aNetif The network interface to bind. * * @retval OT_ERROR_NONE Bind operation was successful. * @retval OT_ERROR_FAILED Failed to bind UDP socket. * */ -otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName); +otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName, otNetifIdentifier aNetif); /** * Connect a UDP/IPv6 socket. diff --git a/src/cli/README_UDP.md b/src/cli/README_UDP.md index b47393574..51cd8cc5b 100644 --- a/src/cli/README_UDP.md +++ b/src/cli/README_UDP.md @@ -39,7 +39,7 @@ On node 1, you should see a print out similar to below: ## Command List - [help](#help) -- [bind](#bind-ip-port) +- [bind](#bind-netif-ip-port) - [close](#close) - [connect](#connect-ip-port) - [linksecurity](#linksecurity) @@ -63,16 +63,24 @@ send Done ``` -### bind \ \ +### bind [netif] \ \ Assigns a name (i.e. IPv6 address and port) to the example socket. +- netif: the network interface to bind to. + - not specified: Thread network interface. + - `-u`: unspecified network interface. + - `-b`: Backbone network interface. - ip: the IPv6 address or the unspecified IPv6 address (`::`). - port: the UDP port ```bash > udp bind :: 1234 Done +> udp bind -u :: 1234 +Done +> udp bind -b :: 1234 +Done ``` ### close diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp index 8e0a4737a..a53d5b498 100644 --- a/src/cli/cli_udp.cpp +++ b/src/cli/cli_udp.cpp @@ -65,14 +65,26 @@ otError UdpExample::ProcessHelp(Arg aArgs[]) otError UdpExample::ProcessBind(Arg aArgs[]) { - otError error; - otSockAddr sockaddr; + otError error; + otSockAddr sockaddr; + otNetifIdentifier netif = OT_NETIF_THREAD; + + if (aArgs[0] == "-u") + { + netif = OT_NETIF_UNSPECIFIED; + aArgs++; + } + else if (aArgs[0] == "-b") + { + netif = OT_NETIF_BACKBONE; + aArgs++; + } SuccessOrExit(error = aArgs[0].ParseAsIp6Address(sockaddr.mAddress)); SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort)); VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS); - error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr); + error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr, netif); exit: return error; diff --git a/src/core/api/udp_api.cpp b/src/core/api/udp_api.cpp index deaaf8940..d060ec56f 100644 --- a/src/core/api/udp_api.cpp +++ b/src/core/api/udp_api.cpp @@ -70,12 +70,12 @@ otError otUdpClose(otInstance *aInstance, otUdpSocket *aSocket) return instance.Get().Close(*static_cast(aSocket)); } -otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName) +otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName, otNetifIdentifier aNetif) { Instance &instance = *static_cast(aInstance); return instance.Get().Bind(*static_cast(aSocket), - *static_cast(aSockName), OT_NETIF_THREAD); + *static_cast(aSockName), aNetif); } otError otUdpConnect(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName) diff --git a/tools/otci/otci/__init__.py b/tools/otci/otci/__init__.py index 8c3a1e5e8..3e97e8959 100644 --- a/tools/otci/otci/__init__.py +++ b/tools/otci/otci/__init__.py @@ -36,7 +36,7 @@ from .otci import \ connect_ncp_sim, \ connect_cmd_handler, \ connect_otbr_ssh -from .types import Rloc16, ChildId +from .types import Rloc16, ChildId, NetifIdentifier _connectors = [ 'connect_cli_sim', @@ -46,4 +46,5 @@ _connectors = [ 'connect_cmd_handler', ] -__all__ = ['OTCI', 'errors', 'Rloc16', 'ChildId', 'THREAD_VERSION_1_1', 'THREAD_VERSION_1_2'] + _connectors +__all__ = ['OTCI', 'errors', 'Rloc16', 'ChildId', 'NetifIdentifer', 'THREAD_VERSION_1_1', 'THREAD_VERSION_1_2' + ] + _connectors diff --git a/tools/otci/otci/otci.py b/tools/otci/otci/otci.py index 86b6446d9..990a737f9 100644 --- a/tools/otci/otci/otci.py +++ b/tools/otci/otci/otci.py @@ -37,7 +37,7 @@ from .command_handlers import OTCommandHandler, OtCliCommandRunner, OtbrSshComma from .connectors import Simulator from .errors import UnexpectedCommandOutput, ExpectLineTimeoutError, CommandError, InvalidArgumentsError from .types import ChildId, Rloc16, Ip6Addr, ThreadState, PartitionId, DeviceMode, RouterId, SecurityPolicy, Ip6Prefix, \ - RouterTableEntry + RouterTableEntry, NetifIdentifier from .utils import match_line, constant_property @@ -2121,13 +2121,19 @@ class OTCI(object): """Opens the example socket.""" self.execute_command('udp close') - def udp_bind(self, ip: str, port: int): + def udp_bind(self, ip: str, port: int, netif: NetifIdentifier = NetifIdentifier.THERAD): """Assigns a name (i.e. IPv6 address and port) to the example socket. :param ip: the IPv6 address or the unspecified IPv6 address (::). :param port: the UDP port """ - self.execute_command(f'udp bind {ip} {port}') + bindarg = '' + if netif == NetifIdentifier.UNSPECIFIED: + bindarg += ' -u' + elif netif == NetifIdentifier.BACKBONE: + bindarg += ' -b' + + self.execute_command(f'udp bind{bindarg} {ip} {port}') def udp_connect(self, ip: str, port: int): """Specifies the peer with which the socket is to be associated. diff --git a/tools/otci/otci/types.py b/tools/otci/otci/types.py index f5d39a1de..222955233 100644 --- a/tools/otci/otci/types.py +++ b/tools/otci/otci/types.py @@ -52,6 +52,13 @@ class PartitionId(int): pass +class NetifIdentifier(int): + """Represents a network interface identifier.""" + UNSPECIFIED = 0 + THERAD = 1 + BACKBONE = 2 + + class DeviceMode(str): """Represents a device mode.""" diff --git a/tools/otci/tests/test_otci.py b/tools/otci/tests/test_otci.py index ee027f506..d0519fb53 100644 --- a/tools/otci/tests/test_otci.py +++ b/tools/otci/tests/test_otci.py @@ -36,6 +36,7 @@ import unittest import otci from otci import OTCI from otci.errors import CommandError +from otci import NetifIdentifier logging.basicConfig(level=logging.DEBUG) @@ -303,13 +304,14 @@ class TestOTCI(unittest.TestCase): leader.wait(1) leader.coap_stop() - leader.udp_open() - leader.udp_bind("::", 1234) - leader.udp_send(leader.get_ipaddr_rloc(), 1234, text='hello') - leader.udp_send(leader.get_ipaddr_rloc(), 1234, random_bytes=3) - leader.udp_send(leader.get_ipaddr_rloc(), 1234, hex='112233') - leader.wait(1) - leader.udp_close() + for netif in (NetifIdentifier.THERAD, NetifIdentifier.UNSPECIFIED, NetifIdentifier.BACKBONE): + leader.udp_open() + leader.udp_bind("::", 1234, netif=netif) + leader.udp_send(leader.get_ipaddr_rloc(), 1234, text='hello') + leader.udp_send(leader.get_ipaddr_rloc(), 1234, random_bytes=3) + leader.udp_send(leader.get_ipaddr_rloc(), 1234, hex='112233') + leader.wait(1) + leader.udp_close() logging.info('dataset: %r', leader.get_dataset()) logging.info('dataset active: %r', leader.get_dataset('active'))