From 4f828cc55427f7b1e0a04438ff21d9467472059d Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Tue, 19 Feb 2019 17:55:54 +0200 Subject: [PATCH 1/8] Clarify network state changes. --- .../api/networkinterfaces/networkinterface.md | 28 ++++++++++++++++-- docs/images/NetworkinterfaceStates.png | Bin 20867 -> 14198 bytes 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index deaa31ae79..bc9ad22e9b 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -15,11 +15,11 @@ NetworkInterface is also the controlling API that the application uses to specif When you create a network interface, it starts from the disconnected state. When you call `NetworkInteface::connect()`, the interface stays connected until you call `NetworkInterface::disconnect()`. The following diagram illustrates the state changes: -![](https://s3-us-west-2.amazonaws.com/mbed-os-docs-images/NetworkinterfaceStates.png)Network states +![](../../images/NetworkinterfaceStates.png)Network states -The interface handles all state changes itself between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. 6LoWPAN-ND returns when it connects to a border router that provides global connection. The thread returns when you create a local mesh network and may later get global connection when it finds a border router. +The interface handles all state changes itself between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. 6LoWPAN-ND returns when it connects to a border router that provides global connection. The Thread returns when you create a local mesh network and may later get global connection when it finds a border router. -When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal back off periods, and not all interfaces implement the reconnection logic. +When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface usually reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal back off periods, and not all interfaces implement the reconnection logic at all. Refer to table below on how different interfaces behave. An application may check the connection status by calling `nsapi_connection_status_t get_connection_status()` or register a callback to monitoring status changes. The following table lists defined network states with actions that applictions should take on the state change: @@ -35,6 +35,17 @@ Use the following API to register status callbacks: - [Network status](network-status.html): API for monitoring network status changes. +Error handling and reconnection logic depends on the network interface used. Use following table to determine what actions your application needs to do on each network type. + +| `NetworkInterface` sub class | Does it reconnect automatically? | Possible states | +|------------------------------|---------------------------------|-----------------| +| `EthernetInterface` | Yes | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
3.`NSAPI_STATUS_GLOBAL_UP`| +| `WiFiInterface` | Yes, when onboard network stack is used.
For external modules, it depends on the driver.
See examples below. | - | +| `OdinWiFiInterface` or
`RTWInterface` | Yes | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
3.`NSAPI_STATUS_GLOBAL_UP`| +| `ESP8266Interface` | Yes | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
3.`NSAPI_STATUS_GLOBAL_UP`| +| `CellularInterface` | Mostly no | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
3.`NSAPI_STATUS_GLOBAL_UP`
`CellularInterface` may also send Cellular specific states specified in `CellularCommon.h` | +| `LoWPANNDInterface` or
`ThreadInterface` or
`WisunInterface` | Yes | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
4.`NSAPI_STATUS_LOCAL_UP`
4.`NSAPI_STATUS_GLOBAL_UP`| + ### Default network interface In Mbed OS, targets that provide network connectivity also provide a default network interface. This can be Ethernet, Wi-Fi, mesh or cellular. Using a default interface allows you to port applications to different targets and connectivity options. @@ -97,6 +108,17 @@ if (wifi) { } ``` +### Notes on portable applications + +When application is expected to be portable between different network interfaces, following guidelines should be used: + +1. Use only `NetworkInterface::get_default_instance()` for getting the interface. +2. Register network status handler and implement reconnection logic. + +See previous section [Default network interface](#default-network-interface) on how to use the portable API for network interface. + +For network status changes, the API is specified in [Network status](network-status.html) section. Being portable means that your application only communicates after `NSAPI_STATUS_GLOBAL_UP` is received and tries to reconnect the network if `NSAPI_STATUS_DISCONNECTED` is received without calling `NetworkInterface::disconnect()`. + ### Related content - [Configuring the default network interface](../reference/configuration-connectivity.html#selecting-the-default-network-interface). diff --git a/docs/images/NetworkinterfaceStates.png b/docs/images/NetworkinterfaceStates.png index cebacc1e3be381fdfc3c080939f1490b3c1fe338..a3dd04ae936d32c425253ad0e78c6dddc5cac17d 100644 GIT binary patch literal 14198 zcmZvDbwE??+rNsUf)dh5NRQDi4YElKgV7}*4I(AYK%_Q8q+15a= zjpzBk@B97Zcl~pA?sMN~=bYW=zCLj+O#O}gQ#@+CJ9q9pRa5|J+_`fPa_7!nn@2d< z7KC|38MfhET?Gop?&9L&;^X5#eforefPj>Qgq)n5ikg~+l7fbYhT#PrBO@a#D=Uzh z5eNiwaB_2TbMXLK`S|(yg~jU%nI<JSJ7`Wg&{LbbKE zb)oXQCOUfhhS)GtRWUL)GWN+edHeRQzT#WU52nE?=H})WP)!SK3rkZC8yg!t2RnNg zU;D_G_t@}w?`Wg@!O-vnHllyHU?W}M%_qdo-_70K-NVDf)6>(-;+>bPskgVcPl&g# zudkn|$zvJFP|hJ=KKhK7cHa)8If z5eP&?-cTeq5_6*5-M)PJ5*;1=_3PIdY<&9~8~!oQ+bb?EE+Ho&F)=YI+ABFZIi)=) zH8nLY&Mz&uI;|izJv}`m0ro9a<{LIjzJ05i%2a%v861?Q^g1i$Q&v`1PDS?jvew+( zTvSFd3Wdt6&CAcvFX&Gx!p4u8;v7VA-LI19s8VdSmXvm3%1{yI<>eI>6_u5hRjtF- zh0)brRW*t6HR$|WsCsQ}ZCy!hy^dzRo>oI@azj~MV}^3$ )Srsm4TW^4>LwSG%) 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 Date: Wed, 20 Feb 2019 12:16:53 +0200 Subject: [PATCH 2/8] Clarify Asyncronous operation of NetworkInterface --- docs/api/networkinterfaces/networkinterface.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index bc9ad22e9b..bef722410e 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -119,6 +119,16 @@ See previous section [Default network interface](#default-network-interface) on For network status changes, the API is specified in [Network status](network-status.html) section. Being portable means that your application only communicates after `NSAPI_STATUS_GLOBAL_UP` is received and tries to reconnect the network if `NSAPI_STATUS_DISCONNECTED` is received without calling `NetworkInterface::disconnect()`. + +### Asynchronous operation + +`NetworkInterface::connect()` and `NetworkInterface::disconnect()` are blocking by default. When application prefers asyncronous operation +it can set the interface into non-blocking mode by calling `NetworkInterface::set_blocking(false)`. This has to be done for each interface separately. + +When interface is operating in asyncronous mode, the return values of `connect()` and `disconnect()` have slightly different meaning. Basically calling `connect()` starts the asyncronous operation which aims to have the device in `GLOBAL_UP` state. Calling `disconnect()` has the target state being `DISCONNECTED`. Return codes in asyncronous mode do not anymore reflect the connection status. Most common return codes in asyncronous mode is `NSAPI_ERROR_OK` which means that operation just started. Refer to Doxygen documentation of [NetworkInterface::connect()](https://os.mbed.com/docs/mbed-os/v5.11/mbed-os-api-doxy/class_network_interface.html#aaf6bf1dfffbe6a5626b7b52eaa542b6e) and [NetworkInterface::disconnect()](https://os.mbed.com/docs/mbed-os/v5.11/mbed-os-api-doxy/class_network_interface.html#afdda3f62c7d73df183ee2d352e8cd146) for return values of these functions. + +For checking the whether the interface is connected, application needs to register the status callback for the interface. Refer to [Network status API](network-status.html) how to do it. + ### Related content - [Configuring the default network interface](../reference/configuration-connectivity.html#selecting-the-default-network-interface). From dfed8fe909a0ed9bdf4690507dbca186b429f225 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 20 Feb 2019 15:55:55 +0200 Subject: [PATCH 3/8] ONME-4184: Document multihoming limitations --- docs/api/networkinterfaces/networkinterface.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index bef722410e..25a7dd859b 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -119,6 +119,18 @@ See previous section [Default network interface](#default-network-interface) on For network status changes, the API is specified in [Network status](network-status.html) section. Being portable means that your application only communicates after `NSAPI_STATUS_GLOBAL_UP` is received and tries to reconnect the network if `NSAPI_STATUS_DISCONNECTED` is received without calling `NetworkInterface::disconnect()`. +### Using multiple network interfaces + +In Mbed OS, applications usually use just one network interface at a time, and most APIs are designed to work with such assumption. +With few limitations, applications are able to operate more than one NetworkInterface. In Mbed OS, there are two build in IP stacks and numerous external IP stacks provided by modules. Refer to [Architecture:IP networking](reference/ip-networking.html) section for explanation of how different stacks are integrated into Mbed OS. + +When using two network interfaces where both are operating on different IP stacks, they can work independently, as there is no common data paths. Such example can be application that uses on-board Ethernet interface and any of the external WiFi modules. + +When using two network interfaces where both use the same IP stacks, there are limitations. Both IP stacks, LwIP and Nanostack, are build using assumption that there is only one active interface. +For the Mbed OS 5.12, the LwIP routing core was modified to support multiple active interfaces, but it has its own limitations as well. When you have more than one active interfaces in LwIP, only one is the default, which all the outgoing traffic flows through. +If you need to force the traffic to only one of the interface, you need to use `Socket::setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, , )` to bind the socket into one interface. Interface name can get fetched from `NetworkInterface::get_interface_name()` call. + +Another, more common, case is where only one of the interface is active at a time. In this case, there is no need for `Socket::setsockopt()` if another interface is brought down as there is only one route option. This works when LwIP is used, but not verified with Nanostack as it is used only on specific use cases. like mesh routing. ### Asynchronous operation From 180163eac11c124fb0745d25b5c627566f3ae17f Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 20 Feb 2019 15:56:54 +0200 Subject: [PATCH 4/8] ONME-4168: Clarify how the network interface behaves for 6LoWPAN networks. --- docs/api/networkinterfaces/networkinterface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index 25a7dd859b..ee2227348c 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -17,7 +17,7 @@ When you create a network interface, it starts from the disconnected state. When ![](../../images/NetworkinterfaceStates.png)Network states -The interface handles all state changes itself between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. 6LoWPAN-ND returns when it connects to a border router that provides global connection. The Thread returns when you create a local mesh network and may later get global connection when it finds a border router. +The interface handles all state changes itself between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. The `LoWPANNDInterface` returns from `connect()` call when it connects to a border router that provides global connection. The `ThreadInterface` returns from `connect()` call when it joins a local mesh network. It may later get global connection when it finds a border router. When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface usually reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal back off periods, and not all interfaces implement the reconnection logic at all. Refer to table below on how different interfaces behave. From dc23bbeb898e070902c3a2b338835a0c6fba4847 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 20 Feb 2019 16:26:51 +0200 Subject: [PATCH 5/8] Document NetworkInterface::add_event_listener() --- docs/api/networkinterfaces/NetworkStatus.md | 36 ++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/api/networkinterfaces/NetworkStatus.md b/docs/api/networkinterfaces/NetworkStatus.md index d182635ab9..240759c5e4 100644 --- a/docs/api/networkinterfaces/NetworkStatus.md +++ b/docs/api/networkinterfaces/NetworkStatus.md @@ -2,7 +2,7 @@ This interface informs you about connection state changes asynchronously. Providing a method to register a callback function to a socket accomplishes this. Each time the network interface's state changes, it triggers the callback. -![](https://s3-us-west-2.amazonaws.com/mbed-os-docs-images/NetworkinterfaceStates.png)Network states +![](../../images/NetworkinterfaceStates.png)Network states #### Usage @@ -74,6 +74,40 @@ Optionally, the application might want to set the `connect()` method to nonblock By default, the `connect()` call blocks until `NSAPI_STATUS_GLOBAL_UP` state is reached. Some applications might require only link-local connectivity and therefore do not need to block that long. In those case monitoring the state changes is the preferred behavior. +### Using multiple connection status callbacks + +In Mbed OS 5.12, the NetworkInterface API is extended with two new functions regarding status callbacks. Applications now have possibility to use these new APIs to register more than one callback per network interface. New APIs is as follows: + +``` + /** Add event listener for interface. + * + * This API allows multiple callback to be registered for a single interface. + * When first called, internal list of event handlers are created and registered to + * interface through attach() API. + * + * Application may only use attach() or add_event_listener() interface. Mixing usage + * of both leads to undefined behavior. + * + * @param status_cb The callback for status changes. + */ + void add_event_listener(mbed::Callback status_cb); + + /** Remove event listener from interface. + * + * Remove previously added callback from the handler list. + * + * @param status_cb The callback to unregister. + */ + void remove_event_listener(mbed::Callback status_cb); +``` + +The callback prototype is exactly same as for the `NetworkInterface::attach()`, so it makes easy for applications to be refactored. + +The `NetworkInterface::attach()` is still functional, and it is a porting API that each interface should provide. The new API uses internally `NetworkInterface::attach()` so application cannot use both APIs at the same time. +Application should either be completely refactored to new API by replacing `NetworkInterface::attach()` calls with `NetworkInterface::add_event_listener()` or remain using the `NetworkInterface::attach()`. + +The new API is completely optional and has small RAM and ROM impact, so applications are not required to use it. Both APIs are still supported but usage is limited to either one of these. + ### Example Registering a status callback that connection state changes trigger depends on whether the network interface provides this functionality. From 850048103e7b5d48f82fa59cfa014cf2400490ac Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Tue, 26 Feb 2019 15:54:57 -0600 Subject: [PATCH 6/8] Edit NetworkStatus.md Edit file, mostly to remove references to "new" for easier maintenance and to update example to latest version. --- docs/api/networkinterfaces/NetworkStatus.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/api/networkinterfaces/NetworkStatus.md b/docs/api/networkinterfaces/NetworkStatus.md index 240759c5e4..031cafaba2 100644 --- a/docs/api/networkinterfaces/NetworkStatus.md +++ b/docs/api/networkinterfaces/NetworkStatus.md @@ -76,16 +76,16 @@ By default, the `connect()` call blocks until `NSAPI_STATUS_GLOBAL_UP` state is ### Using multiple connection status callbacks -In Mbed OS 5.12, the NetworkInterface API is extended with two new functions regarding status callbacks. Applications now have possibility to use these new APIs to register more than one callback per network interface. New APIs is as follows: +The NetworkInterface API includes two functions that the applications can use to register more than one status callback for each network interface: ``` /** Add event listener for interface. * * This API allows multiple callback to be registered for a single interface. - * When first called, internal list of event handlers are created and registered to + * When first called, an internal list of event handlers is created and registered to * interface through attach() API. * - * Application may only use attach() or add_event_listener() interface. Mixing usage + * The application may only use the attach() or add_event_listener() interface. Mixing use * of both leads to undefined behavior. * * @param status_cb The callback for status changes. @@ -101,18 +101,19 @@ In Mbed OS 5.12, the NetworkInterface API is extended with two new functions reg void remove_event_listener(mbed::Callback status_cb); ``` -The callback prototype is exactly same as for the `NetworkInterface::attach()`, so it makes easy for applications to be refactored. +The callback prototype is the same as that for the `NetworkInterface::attach()`. -The `NetworkInterface::attach()` is still functional, and it is a porting API that each interface should provide. The new API uses internally `NetworkInterface::attach()` so application cannot use both APIs at the same time. -Application should either be completely refactored to new API by replacing `NetworkInterface::attach()` calls with `NetworkInterface::add_event_listener()` or remain using the `NetworkInterface::attach()`. +The `NetworkInterface::attach()` is still functional, and it is a porting API that each interface should provide. The functions above use `NetworkInterface::attach()` internally, so the application cannot use both at the same time. -The new API is completely optional and has small RAM and ROM impact, so applications are not required to use it. Both APIs are still supported but usage is limited to either one of these. +You must either refactor the application by replacing `NetworkInterface::attach()` calls with `NetworkInterface::add_event_listener()`, or the application must remain using the `NetworkInterface::attach()`. + +This optional and has a small RAM and ROM increase, so applications are not required to use it. Both APIs are still supported, but use is limited to one at a time. ### Example Registering a status callback that connection state changes trigger depends on whether the network interface provides this functionality. -[![View code](https://www.mbed.com/embed/?url=https://os.mbed.com/teams/mbed_example/code/TCPSocket_ConnStateCb_Example/)](https://os.mbed.com/teams/mbed_example/code/TCPSocket_ConnStateCb_Example/file/8a8191e3d305/main.cpp) +[![View code](https://www.mbed.com/embed/?url=https://os.mbed.com/teams/mbed_example/code/TCPSocket_ConnStateCb_Example/)](https://os.mbed.com/teams/mbed_example/code/TCPSocket_ConnStateCb_Example/file/c66df92cf71b/main.cpp) ### Related content From 4b1aefa0af58d9d5543267d742593f17108590e1 Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Tue, 26 Feb 2019 16:44:21 -0600 Subject: [PATCH 7/8] Edit networkinterface.md Edit file, mostly for active voice and minor wording changes. --- .../api/networkinterfaces/networkinterface.md | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index ee2227348c..4b82b6810f 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -17,9 +17,9 @@ When you create a network interface, it starts from the disconnected state. When ![](../../images/NetworkinterfaceStates.png)Network states -The interface handles all state changes itself between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. The `LoWPANNDInterface` returns from `connect()` call when it connects to a border router that provides global connection. The `ThreadInterface` returns from `connect()` call when it joins a local mesh network. It may later get global connection when it finds a border router. +The interface handles all state changes between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. The `LoWPANNDInterface` returns from `connect()` call when it connects to a border router that provides a global connection. The `ThreadInterface` returns from `connect()` call when it joins a local mesh network. It may later get a global connection when it finds a border router. -When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface usually reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal back off periods, and not all interfaces implement the reconnection logic at all. Refer to table below on how different interfaces behave. +When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface usually reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal backoff periods, and not all interfaces implement the reconnection logic at all. Please refer to table below for information on how different interfaces behave. An application may check the connection status by calling `nsapi_connection_status_t get_connection_status()` or register a callback to monitoring status changes. The following table lists defined network states with actions that applictions should take on the state change: @@ -30,14 +30,13 @@ An application may check the connection status by calling `nsapi_connection_stat | Local connectivity | `NSAPI_STATUS_LOCAL_UP` | You can create sockets and communicate with local devices in the same network. | | Global route found | `NSAPI_STATUS_GLOBAL_UP` | You can create sockets and communicate with all hosts. | - Use the following API to register status callbacks: - [Network status](network-status.html): API for monitoring network status changes. -Error handling and reconnection logic depends on the network interface used. Use following table to determine what actions your application needs to do on each network type. +Error handling and reconnection logic depends on the network interface. Please use the following table to determine what actions your application needs to do on each network type. -| `NetworkInterface` sub class | Does it reconnect automatically? | Possible states | +| `NetworkInterface` subclass | Does it reconnect automatically? | Possible states | |------------------------------|---------------------------------|-----------------| | `EthernetInterface` | Yes | 1.`NSAPI_STATUS_DISCONNECTED`
2.`NSAPI_STATUS_CONNECTING`
3.`NSAPI_STATUS_GLOBAL_UP`| | `WiFiInterface` | Yes, when onboard network stack is used.
For external modules, it depends on the driver.
See examples below. | - | @@ -110,36 +109,36 @@ if (wifi) { ### Notes on portable applications -When application is expected to be portable between different network interfaces, following guidelines should be used: +When you expect an application to be portable between different network interfaces, please use the following guidelines: 1. Use only `NetworkInterface::get_default_instance()` for getting the interface. -2. Register network status handler and implement reconnection logic. +1. Register the network status handler, and implement reconnection logic. -See previous section [Default network interface](#default-network-interface) on how to use the portable API for network interface. +Please see the previous section, [Default network interface](#default-network-interface), on how to use the portable API for the network interface. For network status changes, the API is specified in [Network status](network-status.html) section. Being portable means that your application only communicates after `NSAPI_STATUS_GLOBAL_UP` is received and tries to reconnect the network if `NSAPI_STATUS_DISCONNECTED` is received without calling `NetworkInterface::disconnect()`. ### Using multiple network interfaces -In Mbed OS, applications usually use just one network interface at a time, and most APIs are designed to work with such assumption. -With few limitations, applications are able to operate more than one NetworkInterface. In Mbed OS, there are two build in IP stacks and numerous external IP stacks provided by modules. Refer to [Architecture:IP networking](reference/ip-networking.html) section for explanation of how different stacks are integrated into Mbed OS. +In Mbed OS, applications usually use one network interface at a time, and most APIs are designed this way. With few limitations, applications are able to operate more than one NetworkInterface. In Mbed OS, there are two built-in IP stacks and many external IP stacks provided by modules. Please refer to the [Architecture:IP networking](reference/ip-networking.html) section for an explanation of how different stacks are integrated into Mbed OS. + +When you use two network interfaces and both are operating on different IP stacks, the interfaces can work independently because there is no common data path, for example an application that uses an on-board Ethernet interface and any of the external Wi-Fi modules. + +When you use two network interfaces and both use the same IP stacks, there are limitations. -When using two network interfaces where both are operating on different IP stacks, they can work independently, as there is no common data paths. Such example can be application that uses on-board Ethernet interface and any of the external WiFi modules. +We have modified the LwIP routing core to support multiple active interfaces, but when more than one active interface is active in LwIP, only one is the default. All the outgoing traffic flows through it. -When using two network interfaces where both use the same IP stacks, there are limitations. Both IP stacks, LwIP and Nanostack, are build using assumption that there is only one active interface. -For the Mbed OS 5.12, the LwIP routing core was modified to support multiple active interfaces, but it has its own limitations as well. When you have more than one active interfaces in LwIP, only one is the default, which all the outgoing traffic flows through. -If you need to force the traffic to only one of the interface, you need to use `Socket::setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, , )` to bind the socket into one interface. Interface name can get fetched from `NetworkInterface::get_interface_name()` call. +If you need to force the traffic to only one of the interfaces, you need to use `Socket::setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, , )` to bind the socket into one interface. You can fetch the interface name from the `NetworkInterface::get_interface_name()` call. -Another, more common, case is where only one of the interface is active at a time. In this case, there is no need for `Socket::setsockopt()` if another interface is brought down as there is only one route option. This works when LwIP is used, but not verified with Nanostack as it is used only on specific use cases. like mesh routing. +Another, more common, case is where only one of the interface is active at a time. In this case, there is no need for `Socket::setsockopt()` if another interface is brought down because there is only one route option. This works with LwIP but is not verified with Nanostack because it is used only on specific use cases, such as mesh routing. ### Asynchronous operation -`NetworkInterface::connect()` and `NetworkInterface::disconnect()` are blocking by default. When application prefers asyncronous operation -it can set the interface into non-blocking mode by calling `NetworkInterface::set_blocking(false)`. This has to be done for each interface separately. +`NetworkInterface::connect()` and `NetworkInterface::disconnect()` are blocking by default. When an application prefers asynchronous operation, it can set the interface into nonblocking mode by calling `NetworkInterface::set_blocking(false)`. This has to be done for each interface separately. -When interface is operating in asyncronous mode, the return values of `connect()` and `disconnect()` have slightly different meaning. Basically calling `connect()` starts the asyncronous operation which aims to have the device in `GLOBAL_UP` state. Calling `disconnect()` has the target state being `DISCONNECTED`. Return codes in asyncronous mode do not anymore reflect the connection status. Most common return codes in asyncronous mode is `NSAPI_ERROR_OK` which means that operation just started. Refer to Doxygen documentation of [NetworkInterface::connect()](https://os.mbed.com/docs/mbed-os/v5.11/mbed-os-api-doxy/class_network_interface.html#aaf6bf1dfffbe6a5626b7b52eaa542b6e) and [NetworkInterface::disconnect()](https://os.mbed.com/docs/mbed-os/v5.11/mbed-os-api-doxy/class_network_interface.html#afdda3f62c7d73df183ee2d352e8cd146) for return values of these functions. +When an interface operates in asynchronous mode, the return values of `connect()` and `disconnect()` have slightly different meanings. Calling `connect()` starts the asynchronous operation, which puts the device in the `GLOBAL_UP` state. Calling `disconnect()` puts the target in the `DISCONNECTED` state. Return code in asynchronous mode does not reflect the connection status. The most common return codes in asynchronous mode is `NSAPI_ERROR_OK`, which means that operation just started. Please refer to the Doxygen documentation of [NetworkInterface::connect()](https://os.mbed.com/docs/mbed-os/development/mbed-os-api-doxy/class_network_interface.html#aaf6bf1dfffbe6a5626b7b52eaa542b6e) and [NetworkInterface::disconnect()](https://os.mbed.com/docs/mbed-os/development/mbed-os-api-doxy/class_network_interface.html#afdda3f62c7d73df183ee2d352e8cd146) for return values of these functions. -For checking the whether the interface is connected, application needs to register the status callback for the interface. Refer to [Network status API](network-status.html) how to do it. +To check whether the interface is connected, the application needs to register the status callback for the interface. Please refer to the [Network status API](network-status.html) for information on how to do so. ### Related content From 5c2073a0d2b521133ad2355cf1bc429716827408 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 27 Feb 2019 14:26:46 +0200 Subject: [PATCH 8/8] Add small changes to two sentences "usually reconnects" -> "reconnects" because it is not optional. "active interface is active in ..." -> "interface is active in.." --- docs/api/networkinterfaces/networkinterface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/networkinterfaces/networkinterface.md b/docs/api/networkinterfaces/networkinterface.md index 4b82b6810f..a117cb2ded 100644 --- a/docs/api/networkinterfaces/networkinterface.md +++ b/docs/api/networkinterfaces/networkinterface.md @@ -19,7 +19,7 @@ When you create a network interface, it starts from the disconnected state. When The interface handles all state changes between `Connecting`, `Local connectivity` and `Global route found`. Calling `NetworkInterface::connect()` might return when either local or global connectivity states are reached. This depends on the connectivity. For example, Ethernet and Wi-Fi interfaces return when global connectivity is reached. 6LoWPAN-based mesh networks depend on the standard you're using. The `LoWPANNDInterface` returns from `connect()` call when it connects to a border router that provides a global connection. The `ThreadInterface` returns from `connect()` call when it joins a local mesh network. It may later get a global connection when it finds a border router. -When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface usually reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal backoff periods, and not all interfaces implement the reconnection logic at all. Please refer to table below for information on how different interfaces behave. +When a network or route is lost or any other cause limits the connectivity, the interface may change its state back to `Connecting`, `Local connectivity` or `Disconnected`. In the `Connecting` and `Local connectivity` states, the interface reconnects until the application chooses to call `NetworkInterface::disconnect()`. Depending on the network, this reconnection might have internal backoff periods, and not all interfaces implement the reconnection logic at all. Please refer to table below for information on how different interfaces behave. An application may check the connection status by calling `nsapi_connection_status_t get_connection_status()` or register a callback to monitoring status changes. The following table lists defined network states with actions that applictions should take on the state change: @@ -126,7 +126,7 @@ When you use two network interfaces and both are operating on different IP stack When you use two network interfaces and both use the same IP stacks, there are limitations. -We have modified the LwIP routing core to support multiple active interfaces, but when more than one active interface is active in LwIP, only one is the default. All the outgoing traffic flows through it. +We have modified the LwIP routing core to support multiple active interfaces, but when more than one interface is active in LwIP, only one is the default. All the outgoing traffic flows through it. If you need to force the traffic to only one of the interfaces, you need to use `Socket::setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, , )` to bind the socket into one interface. You can fetch the interface name from the `NetworkInterface::get_interface_name()` call.