Nanostack Border Router is a generic mbed border router implementation that provides the 6LoWPAN ND or Thread border router initialization logic.

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Thu Mar 09 17:47:03 2017 +0000
Child:
1:db6e7986719f
Commit message:
Initial commit.
Commit copied from https://github.com/ARMmbed/nanostack-border-router

Changed in this revision

Jenkinsfile Show annotated file Show diff for this revision Revisions of this file
LICENSE Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
configs/6lowpan_Atmel_RF.json Show annotated file Show diff for this revision Revisions of this file
configs/6lowpan_Spirit1_RF.json Show annotated file Show diff for this revision Revisions of this file
configs/Thread_Atmel_RF.json Show annotated file Show diff for this revision Revisions of this file
configs/Thread_SLIP_Atmel_RF.json Show annotated file Show diff for this revision Revisions of this file
drivers/.gitignore Show annotated file Show diff for this revision Revisions of this file
drivers/TARGET_K64F/sal-nanostack-driver-k64f-eth.lib Show annotated file Show diff for this revision Revisions of this file
drivers/TARGET_NUCLEO_F429ZI/.gitignore Show annotated file Show diff for this revision Revisions of this file
drivers/TARGET_NUCLEO_F429ZI/sal-nanostack-driver-stm32-eth.lib Show annotated file Show diff for this revision Revisions of this file
drivers/atmel-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
drivers/eth_driver.h Show annotated file Show diff for this revision Revisions of this file
drivers/mcr20a-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
drivers/rf_wrapper.cpp Show annotated file Show diff for this revision Revisions of this file
drivers/rf_wrapper.h Show annotated file Show diff for this revision Revisions of this file
drivers/sal-stack-nanostack-slip.lib Show annotated file Show diff for this revision Revisions of this file
drivers/stm-spirit1-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
images/BorderRouter.png Show annotated file Show diff for this revision Revisions of this file
images/br_role.png Show annotated file Show diff for this revision Revisions of this file
images/structure.png Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
source/border_router_main.cpp Show annotated file Show diff for this revision Revisions of this file
source/borderrouter_helpers.c Show annotated file Show diff for this revision Revisions of this file
source/borderrouter_helpers.h Show annotated file Show diff for this revision Revisions of this file
source/borderrouter_tasklet.c Show annotated file Show diff for this revision Revisions of this file
source/borderrouter_tasklet.h Show annotated file Show diff for this revision Revisions of this file
source/borderrouter_thread_tasklet.c Show annotated file Show diff for this revision Revisions of this file
source/cfg_parser.c Show annotated file Show diff for this revision Revisions of this file
source/cfg_parser.h Show annotated file Show diff for this revision Revisions of this file
source/mbedtls_thread_config.h Show annotated file Show diff for this revision Revisions of this file
source/static_6lowpan_config.h Show annotated file Show diff for this revision Revisions of this file
source/thread_bbr_ext.h Show annotated file Show diff for this revision Revisions of this file
source/thread_br_conn_handler.c Show annotated file Show diff for this revision Revisions of this file
source/thread_br_conn_handler.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jenkinsfile	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,55 @@
+// List of targets to compile
+def targets = [
+  "K64F"
+  ]
+
+// Map toolchains to compilers
+def toolchains = [
+  ARM: "armcc",
+  GCC_ARM: "arm-none-eabi-gcc",
+  IAR: "iar_arm"
+  ]
+
+// Configurations
+def configurations = [
+  LOWPAN: "6lowpan_Atmel_RF.json",
+  THREAD: "Thread_Atmel_RF.json",
+  THREAD_SLIP: "Thread_SLIP_Atmel_RF.json"
+  ]
+
+def stepsForParallel = [:]
+
+// Jenkins pipeline does not support map.each, we need to use oldschool for loop
+for (int i = 0; i < targets.size(); i++) {
+  for(int j = 0; j < toolchains.size(); j++) {
+    for(int k = 0; k < configurations.size(); k++) {
+      def target = targets.get(i)
+      def toolchain = toolchains.keySet().asList().get(j)
+      def compilerLabel = toolchains.get(toolchain)
+      def configurationLabel = configurations.keySet().asList().get(k)
+      def configurationFile = configurations.get(configurationLabel)
+      def stepName = "${target} ${configurationLabel} ${toolchain}"
+      stepsForParallel[stepName] = buildStep(target, compilerLabel, configurationFile, configurationLabel, toolchain)
+    }
+  }
+}
+
+timestamps {
+  parallel stepsForParallel
+}
+
+def buildStep(target, compilerLabel, configurationFile, configurationLabel, toolchain) {
+  return {
+    stage ("${target}_${compilerLabel}_${configurationLabel}") {
+      node ("${compilerLabel}") {
+        deleteDir()
+        dir("nanostack-border-router") {
+          checkout scm
+          execute("mbed deploy --protocol ssh")
+          execute("mbed compile --build out/${configurationLabel}/${target}/${compilerLabel}/ -m ${target} -t ${toolchain} --app-config ./configs/${configurationFile}")
+        }
+        archive '**/nanostack-border-router.bin'
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,291 @@
+# Nanostack Border Router
+
+Nanostack Border Router is a generic mbed border router implementation that provides the 6LoWPAN ND or Thread border router initialization logic.
+
+Border router is a network gateway between a wireless 6LoWPAN mesh network and a backhaul network. It controls and relays traffic between the two networks. In a typical setup, a 6LoWPAN border router is connected to another router in the backhaul network (over Ethernet or a serial line) which in turn forwards traffic to/from the internet or a private company LAN, for instance.
+
+![](images/br_role.png)
+
+## Structure
+
+This application runs on mbed OS and utilizes PHY drivers and Nanostack to form a border router.
+
+![](images/structure.png)
+
+The code layout is organized like this:
+
+```
+configs/                  Contains example configuration files
+drivers/                  Contains PHY drivers
+mbed-os/                  Contains mbed OS itself
+source/                   Contains the application code
+mbed_app.json             Build time configuration file
+```
+
+## Building
+
+1. Clone this repository.
+1. Run `mbed deploy`.
+1. Select target platform.
+1. Select toolchain.
+1. Configure.
+1. Build.
+
+For example:
+
+```
+$ mbed deploy
+
+$ mbed target K64F
+ OR
+$ mbed target NUCLEO_F429ZI
+
+$ mbed toolchain GCC_ARM
+
+$ mbed compile
+```
+
+## Selecting the target platform
+
+The target platform is the hardware on which the border router runs. There are number of target platforms already available for you in the mbed OS 5.
+
+If you wish to write your own target, follow the instructions in [Adding target support to mbed OS 5](https://docs.mbed.com/docs/mbed-os-handbook/en/5.3/advanced/porting_guide/).
+
+The border router requires backhaul and RF drivers to be provided for Nanostack. The backhaul is either SLIP or Ethernet. Currently, there are drivers for the following backhauls:
+
+* [K64F Ethernet](https://github.com/ARMmbed/sal-nanostack-driver-k64f-eth)
+* [NUCLEO_F429ZI Ethernet](https://github.com/ARMmbed/sal-nanostack-driver-stm32-eth)
+* [SLIP driver](https://github.com/ARMmbed/sal-stack-nanostack-slip)
+
+And following RF drivers:
+
+* [Atmel AT86RF233](https://github.com/ARMmbed/atmel-rf-driver)
+* [Atmel AT86RF212B](https://github.com/ARMmbed/atmel-rf-driver)
+* [STM Spirit1](https://github.com/ARMmbed/stm-spirit1-rf-driver)
+* [NXP MCR20A](https://github.com/ARMmbed/mcr20a-rf-driver)
+
+The existing drivers are found in the `drivers/` folder. More drivers can be linked in.
+
+See [Notes on different hardware](https://github.com/ARMmbed/mbed-os-example-mesh-minimal/blob/master/Hardware.md) to see known combinations that work.
+
+## Configuring Nanostack Border Router
+
+Applications using Nanostack Border Router need to use a `.json` file for the configuration. The example configurations can be found in the `configs/` folder.
+
+### The backhaul configuration options
+
+| Field                               | Description                                                   |
+|-------------------------------------|---------------------------------------------------------------|
+| `backhaul-dynamic-bootstrap`          | Defines whether the manually configured backhaul prefix and default route are used, or whether they are learnt automatically via the IPv6 neighbor discovery. False means static and true means automatic configuration. |
+| `backhaul-prefix`                     | The IPv6 prefix (64 bits) assigned to and advertised on the backhaul interface. Example format: `fd00:1:2::` |
+| `backhaul-default-route`              | The default route (prefix and prefix length) where packets should be forwarded on the backhaul device, default: `::/0`. Example format: `fd00:a1::/10` |
+| `backhaul-next-hop`                   | The next-hop value for the backhaul default route; should be a link-local address of a neighboring router, default: empty (on-link prefix). Example format: `fe80::1` |
+
+### 6LoWPAN ND border router options
+
+| Field                               | Description                                                   |
+|-------------------------------------|---------------------------------------------------------------|
+| `security-mode`                       | The 6LoWPAN mesh network traffic (link layer) can be protected with the Private Shared Key (PSK) security mode, allowed values: `NONE` and `PSK`. |
+| `psk-key`                             | A 16-bytes long private shared key to be used when the security mode is PSK. Example format (hexadecimal byte values separated by commas inside brackets): `{0x00, ..., 0x0f}` |
+| `multicast-addr`                      | Multicast forwarding is supported by default. This defines the multicast address to which the border router application forwards multicast packets (on the backhaul and RF interface). Example format: `ff05::5` |
+|`ra-router-lifetime`|Defines the router advertisement interval in seconds (default 1024 if left out).|
+|`beacon-protocol-id`|Is used to identify beacons. This should not be changed (default 4 if left out).|
+|`nanostack.configuration`|Is needed when building the 6LoWPAN ND border router from the Nanostack sources.|
+
+The `LOWPAN_BORDER_ROUTER` feature is the Nanostack library, which implements the 6LoWPAN ND border router networking stack.
+
+To learn more about 6LoWPAN and the configuration parameters, read the [6LoWPAN overview] (https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/quick_start_intro/index.html).
+
+See [configs/6lowpan_Atmel_RF.json](configs/6lowpan_Atmel_RF.json) for an example configuration file.
+
+#### The routing protocol RPL (6LoWPAN ND)
+
+Nanostack Border Router uses [RPL](https://tools.ietf.org/html/rfc6550) as the routing protocol on the mesh network side (RF interface) when in 6LoWPAN-ND mode. Currently, only the `grounded/non-storing` operation mode is supported.
+
+Nanostack Border Router offers the following configuration options for RPL:
+
+| Field                               | Description                                                   |
+|-------------------------------------|---------------------------------------------------------------|
+| rpl-instance-id                     | The RPL instance ID value that identifies the RPL instance, default: 1 |
+| rpl-idoublings                      | RPL Trickle parameter: DIOIntervalDoublings value, default: 12 |
+| rpl-imin                            | RPL Trickle parameter: DIOIntervalMin value, default: 9 |
+| rpl-k                               | RPL Trickle parameter: the redundacy constant k, default: 10 |
+| rpl-max-rank-inc                    | Maximum rank increase value, default: 2048|
+| rpl-min-hop-rank-inc                | Minimum rank increase value, default: 128 |
+| rpl-default-lifetime                | Default lifetime for the RPL routes, default: 64 |
+| rpl-lifetime-unit                   | The value of the unit that describes the lifetime (in seconds), default: 60 |
+| rpl-pcs                             | The number of bits that may be allocated to the path control field. |
+| rpl-ocp                             | The Objective Function (OF) to use, values: 1=OF0 (default), 2=MRHOF |
+
+### Thread configuration
+
+The Thread-specific parameters are listed below.
+
+| Field                               | Description                                                   |
+|-------------------------------------|---------------------------------------------------------------|
+| `commissioning-dataset-timestamp`   | Used for updating the Thread network parameters. The device with the highest value propagates the parameters to the network (in the same Realm-Local scope). |
+| `pan-id`                            | 2-byte Personal Area Network ID. |
+| `extended-pan-id`                   | 8-byte value used to identify Thread networks in range. |
+| `mesh-local-prefix`                 | ULA prefix used for communication within the Thread network. |
+| `network-name`                      | A human-readable name for the network. |
+| `pskc`                              | Pre-Shared Key for the Commissioner. |
+| `pskd`                              | Pre-Shared Key for the device. |
+| `thread-master-key`                 | A key used to derive security material for MAC and MLE protection. |
+| `nanostack.configuration`           | Is needed when building the Thread border router from the Nanostack sources. |
+
+
+The `THREAD_BORDER_ROUTER` feature is the Nanostack library, which implements the Thread border router networking stack.
+
+For the Thread Border Router, there are example configuration files for `SLIP` and `ETH` backhaul connectivity:
+
+ * [configs/Thread_Atmel_RF.json](configs/Thread_Atmel_RF.json)
+ * [configs/Thread_SLIP_Atmel_RF.json](configs/Thread_SLIP_Atmel_RF.json)
+
+The [mbedtls_thread_config.h](source/mbedtls_thread_config.h) file configures mbed TLS for Thread use.
+
+<span class="notes">**Note:** The configuration examples are for testing purposes only; do not use them for production or expose them.</span>
+
+
+#### Backhaul connectivity
+
+The Nanostack border router application can be connected to a backhaul network. This enables you to connect the devices in a 6LoWPAN mesh network to the internet or a private LAN. Currently, the application supports SLIP (IPv6 encapsulation over a serial line) and Ethernet backhaul connectivity.
+
+```
+"config": {
+    "backhaul-driver": {
+        "help": "options are ETH, SLIP",
+        "value": "ETH"
+    },
+    "backhaul-mac-src": {
+        "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+        "value": "BOARD"
+    },
+    "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+    "backhaul-dynamic-bootstrap": true,
+    "backhaul-prefix": "\"fd00:300::\"",
+    "backhaul-next-hop": "\"fe80::1\"",
+    "backhaul-default-route": "\"::/0\"",
+    .............
+}
+```
+
+You can select your preferred option through the configuration file (field `backhaul-driver` in the `config` section). The value `SLIP` includes the SLIP driver, while the value `ETH` compiles the border router application with Ethernet backhaul support. You can define the MAC address on the backhaul interface manually (field `backhaul-mac-src` value `CONFIG`). Alternatively, you can use the MAC address provided by the development board (field `backhaul-mac-src` value `BOARD`). By default, the backhaul driver is set to `ETH` and the MAC address source is `BOARD`.
+
+You can also set the backhaul bootstrap mode (field `backhaul-dynamic-bootstrap`). By default, the bootstrap mode is set to true, which means the autonomous mode. With the autonomous mode, the border router learns the prefix information automatically from an IPv6 gateway in the Ethernet/SLIP segment. When the parameter is set to false, it enables you to set up a manual configuration of `backhaul-prefix` and `backhaul-default-route`.
+
+If you use the static bootstrap mode, you need to configure a default route on the backhaul interface to properly forward packets between the backhaul and the 6LoWPAN mesh network. In addition to this, you need to set a backhaul prefix. The static mode creates a site-local IPv6 network from which packets cannot be routed outside.
+
+When using the autonomous mode in the 6LoWPAN ND configuration, you can set the `prefix-from-backhaul` option to `true` to use the same backhaul prefix on the mesh network side as well. This allows the mesh nodes to be directly connectable from the outside of the mesh network. In the Thread network, it is enough that `backhaul-dynamic-bootstrap` is set to true.
+
+For more details on how to set the backhaul prefix and default route, read the [Nanostack Border Router](https://github.com/ARMmbed/nanostack-border-router-private) documentation.
+
+#### Note on the SLIP backhaul driver
+
+If you are using a K64F board, you need to use the UART1 serial line of the board with the SLIP driver. See the `pins` section in the [mbed_app.json](./mbed_app.json) configuration file. To use a different UART line, replace the `SERIAL_TX` and `SERIAL_RX` values with correct TX/RX pin names.
+
+If you wish to use the hardware flow control, set the configuration field `slip_hw_flow_control` to true. By default, it is set to false. Before using hardware flow control, make sure that the other end of your SLIP interface can handle the flow control.
+
+For the pin names of your desired UART line, refer to your development board's documentation.
+
+An example configuration for the SLIP driver:
+
+```
+"target_overrides": {
+    "K64F": {
+        "SERIAL_TX": "PTE0",
+        "SERIAL_RX": "PTE1",
+        "SERIAL_CTS": "PTE2",
+        "SERIAL_RTS": "PTE3"
+    }
+```
+
+### Switching the RF shield
+
+By default, the application uses an Atmel AT86RF233/212B RF driver. You can alternatively use any RF driver provided in the `drivers/` folder or link in your own driver. You can set the configuration for the RF driver in the `json` file.
+
+To select the Atmel radio shield, use the following:
+
+```
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "ATMEL"
+        },
+```
+
+To select the NXP radio shield, use the following:
+
+```
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "MCR20"
+        },
+```
+
+To select the STM Spirit1 radio shield, use the following:
+
+```
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "SPIRIT1"
+        },
+```
+
+In case you have choosen the STM Spirit1 Sub-1 GHz RF expansion board [X-NUCLEO-IDS01A4](https://github.com/ARMmbed/stm-spirit1-rf-driver), you need also to configure its MAC address in the `mbed_app.json` file, for example:
+
+```json
+    "target_overrides": {
+        "*": {
+            "spirit1.mac-address": "{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}"
+        },
+    }
+```
+
+<span class="notes">**Not**: This MAC address must be unique within the 6LoWPAN mesh network.</span>
+
+After changing the radio shield, you need to recompile the application.
+
+## Running the border router application
+
+1. Find the  binary file `nanostack-border-router.bin` in the `BUILD` folder.
+2. Copy the binary to the USB mass storage root of the development board. It is automatically flashed to the target MCU. When the flashing is complete, the board restarts itself. Press the **Reset** button of the development board if it does not restart automatically.
+3. The program begins execution.
+4. Open the [serial connection](#serial-connection-settings), for example PuTTY.
+
+## Serial connection settings
+
+Serial connection settings for the Nanorouter are as follows:
+
+* Baud-rate = 115200
+* Data bits = 8
+* Stop bits = 1
+
+If there is no input from the serial terminal, press the **Reset** button of the development board.
+
+In the PuTTY main screen, save the session and click **Open**. This opens a console window showing debug messages from the application. If the console screen is blank, you may need to press the **Reset** button of the board to see the debug information. The serial output from the 6LoWPAN border router looks something like this in the console:
+
+```
+[INFO][app ]: Starting Nanostack border router...
+[INFO][brro]: NET_IPV6_BOOTSTRAP_AUTONOMOUS
+[INFO][app ]: Using ETH backhaul driver...
+[INFO][Eth ]: Ethernet cable is connected.
+[INFO][addr]: Tentative Address added to IF 1: fe80::ac41:dcff:fe37:72c4
+[INFO][addr]: DAD passed on IF 1: fe80::ac41:dcff:fe37:72c4
+[INFO][addr]: Tentative Address added to IF 1: 2001:999:21:9ce:ac41:dcff:fe37:72c4
+[INFO][addr]: DAD passed on IF 1: 2001:999:21:9ce:ac41:dcff:fe37:72c4
+[INFO][brro]: Backhaul bootstrap ready, IPv6 = 2001:999:21:9ce:ac41:dcff:fe37:72c4
+[INFO][brro]: Backhaul interface addresses:
+[INFO][brro]:    [0] fe80::ac41:dcff:fe37:72c4
+[INFO][brro]:    [1] 2001:999:21:9ce:ac41:dcff:fe37:72c4
+[INFO][addr]: Address added to IF 0: fe80::ff:fe00:face
+[INFO][br  ]: BR nwk base ready for start
+[INFO][br  ]: Refresh Contexts
+[INFO][br  ]: Refresh Prefixs
+[INFO][addr]: Address added to IF 0: 2001:999:21:9ce:0:ff:fe00:face
+[INFO][addr]: Address added to IF 0: fe80::fec2:3d00:4:a0cd
+[INFO][brro]: RF bootstrap ready, IPv6 = 2001:999:21:9ce:0:ff:fe00:face
+[INFO][brro]: RF interface addresses:
+[INFO][brro]:    [0] fe80::ff:fe00:face
+[INFO][brro]:    [1] fe80::fec2:3d00:4:a0cd
+[INFO][brro]:    [2] 2001:999:21:9ce:0:ff:fe00:face
+[INFO][brro]: 6LoWPAN Border Router Bootstrap Complete.
+```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/6lowpan_Atmel_RF.json	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,82 @@
+{
+    "config": {
+        "heap-size": {
+             "help": "The amount of static RAM to reserve for nsdynmemlib heap",
+             "value": 50000
+        },
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "ATMEL"
+        },
+        "backhaul-driver": {
+            "help": "options are ETH, SLIP",
+            "value": "ETH"
+        },
+        "mesh-mode": {
+            "help": "Mesh networking mode. Options are LOWPAN_ND and THREAD",
+            "value": "LOWPAN_ND"
+        },
+        "backhaul-mac-src": {
+            "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+            "value": "BOARD"
+        },
+        "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+        "slip_hw_flow_control": "false",
+        "slip_serial_baud_rate": "921600",
+        "debug-trace": "false",
+        "defined-BR-config": "true",
+        "security-mode": "NONE",
+        "psk-key-id": 1,
+        "psk-key": "{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}",
+        "pana-mode": "",
+        "tls-psk-key": "{0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0}",
+        "tls-psk-key-id": 1,
+        "pan-id": "0x0691",
+        "network-id": "network000000000",
+        "beacon-protocol-id": 4,
+        "prefix": "fd00:db8::",
+        "prefix-from-backhaul": true,
+        "rf-channel": 12,
+        "rf-channel-page": 0,
+        "rf-channel-mask": "0x07fff800",
+        "short-mac-address": "0xface",
+        "backhaul-dynamic-bootstrap": true,
+        "backhaul-prefix": "fd00:db8:ff1::",
+        "backhaul-default-route": "::/0",
+        "backhaul-next-hop": "fe80::1",
+        "ra-router-lifetime": 1024,
+        "rpl-instance-id": 1,
+        "rpl-idoublings": 9,
+        "rpl-imin": 12,
+        "rpl-k": 10,
+        "rpl-max-rank-inc": 2048,
+        "rpl-min-hop-rank-inc": 128,
+        "rpl-default-lifetime": 64,
+        "rpl-lifetime-unit": 60,
+        "rpl-pcs": 1,
+        "rpl-ocp": 1,
+        "multicast-addr": "ff05::7",
+        "LED": "NC",
+        "SERIAL_TX": "NC",
+        "SERIAL_RX": "NC",
+        "SERIAL_CTS": "NC",
+        "SERIAL_RTS": "NC"
+    },
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "LOWPAN_BORDER_ROUTER", "COMMON_PAL"],
+            "target.features_remove": ["LWIP"],
+            "mbed-trace.enable": 1,
+            "nanostack.configuration": "lowpan_border_router",
+            "platform.stdio-convert-newlines": true,
+            "platform.stdio-baud-rate": 115200
+        },
+        "K64F": {
+            "LED": "LED_GREEN",
+            "SERIAL_TX": "PTE0",
+            "SERIAL_RX": "PTE1",
+            "SERIAL_CTS": "PTE2",
+            "SERIAL_RTS": "PTE3"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/6lowpan_Spirit1_RF.json	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,84 @@
+{
+    "config": {
+        "heap-size": {
+             "help": "The amount of static RAM to reserve for nsdynmemlib heap",
+             "value": 50000
+        },
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "SPIRIT1"
+        },
+        "backhaul-driver": {
+            "help": "options are ETH, SLIP",
+            "value": "ETH"
+        },
+        "mesh-mode": {
+            "help": "Mesh networking mode. Options are LOWPAN_ND and THREAD",
+            "value": "LOWPAN_ND"
+        },
+        "backhaul-mac-src": {
+            "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+            "value": "BOARD"
+        },
+        "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+        "slip_hw_flow_control": "false",
+        "slip_serial_baud_rate": "921600",
+        "debug-trace": "false",
+        "defined-BR-config": "true",
+        "security-mode": "PSK",
+        "psk-key-id": 1,
+        "psk-key": "{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}",
+        "pana-mode": "",
+        "tls-psk-key": "{0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0}",
+        "tls-psk-key-id": 1,
+        "pan-id": "0x0691",
+        "network-id": "network000000000",
+        "beacon-protocol-id": 4,
+        "prefix": "fd00:db8::",
+        "prefix-from-backhaul": true,
+	"rf-channel": 1,
+	"rf-channel-page": 2,
+	"rf-channel-mask": "(1<<1)",
+        "short-mac-address": "0xface",
+        "backhaul-dynamic-bootstrap": true,
+        "backhaul-prefix": "fd00:db8:ff1::",
+        "backhaul-default-route": "::/0",
+        "backhaul-next-hop": "fe80::1",
+        "ra-router-lifetime": 1024,
+        "rpl-instance-id": 1,
+        "rpl-idoublings": 9,
+        "rpl-imin": 12,
+        "rpl-k": 10,
+        "rpl-max-rank-inc": 2048,
+        "rpl-min-hop-rank-inc": 128,
+        "rpl-default-lifetime": 64,
+        "rpl-lifetime-unit": 60,
+        "rpl-pcs": 1,
+        "rpl-ocp": 1,
+        "multicast-addr": "ff05::7",
+        "LED": "NC",
+        "SERIAL_TX": "NC",
+        "SERIAL_RX": "NC",
+        "SERIAL_CTS": "NC",
+        "SERIAL_RTS": "NC"
+    },
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "LOWPAN_BORDER_ROUTER", "COMMON_PAL"],
+            "target.features_remove": ["LWIP"],
+            "spirit1.mac-address": "{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}",
+            "mbed-trace.enable": 1,
+            "nanostack.configuration": "lowpan_border_router",
+            "platform.stdio-convert-newlines": true,
+            "platform.stdio-baud-rate": 115200
+        },
+        "NUCLEO_F429ZI": {
+    	    "LED": "LED1",
+   	    "SERIAL_TX": "SERIAL_TX",
+    	    "SERIAL_RX": "SERIAL_RX",
+    	    "SERIAL_CTS": "PD_11",
+    	    "SERIAL_RTS": "PD_12"
+        }
+    },
+    "macros": ["PB5_ETH_PATCH"]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/Thread_Atmel_RF.json	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,64 @@
+{
+    "config": {
+        "heap-size": {
+             "help": "The amount of static RAM to reserve for nsdynmemlib heap",
+             "value": 50000
+        },
+        "radio-type":{
+            "help": "options are ATMEL, MCR20",
+            "value": "ATMEL"
+        },
+        "backhaul-driver": {
+            "help": "options are ETH, SLIP",
+            "value": "ETH"
+        },
+        "mesh-mode": {
+            "help": "Mesh networking mode. Options are LOWPAN_ND and THREAD",
+            "value": "THREAD"
+        },
+        "backhaul-mac-src": {
+            "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+            "value": "BOARD"
+        },
+        "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+        "rf-channel": 22,
+        "rf-channel-page": 0,
+        "rf-channel-mask": "0x07fff800",
+        "debug-trace":  1,
+        "backhaul-dynamic-bootstrap": true,
+        "backhaul-prefix": "\"fd00:300::\"",
+        "backhaul-next-hop": "\"fe80::1\"",
+        "backhaul-default-route": "\"::/0\"",
+        "commissioning-dataset-timestamp": "0x00010000",
+        "pan-id": "0x0700",
+        "extended-pan-id": "{0xf1, 0xb5, 0xa1, 0xb2,0xc4, 0xd5, 0xa1, 0xbd }",
+        "mesh-local-prefix": "{0xfd, 0x0, 0x0d, 0xb8, 0x0,0x0, 0x0, 0x0}",
+        "network-name": "\"Thread Network\"",
+        "pskd": "\"abcdefghijklmno\"",
+        "pskc": "{0xc8, 0xa6, 0x2e, 0xae, 0xf3, 0x68, 0xf3, 0x46, 0xa9, 0x9e, 0x57, 0x85, 0x98, 0x9d, 0x1c, 0xd0}",
+        "thread-master-key": "{0x10, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}",
+        "LED": "NC",
+        "SERIAL_TX": "NC",
+        "SERIAL_RX": "NC",
+        "SERIAL_CTS": "NC",
+        "SERIAL_RTS": "NC"
+    },
+    "macros": ["MBEDTLS_USER_CONFIG_FILE=\"source/mbedtls_thread_config.h\""],
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "COMMON_PAL", "THREAD_BORDER_ROUTER"],
+            "target.features_remove": ["LWIP"],
+            "mbed-trace.enable": 1,
+            "nanostack.configuration": "thread_border_router",
+            "platform.stdio-convert-newlines": true,
+            "platform.stdio-baud-rate": 115200
+        },
+        "K64F": {
+            "LED": "LED_GREEN",
+            "SERIAL_TX": "PTE0",
+            "SERIAL_RX": "PTE1",
+            "SERIAL_CTS": "PTE2",
+            "SERIAL_RTS": "PTE3"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/Thread_SLIP_Atmel_RF.json	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,66 @@
+{
+    "config": {
+        "heap-size": {
+             "help": "The amount of static RAM to reserve for nsdynmemlib heap",
+             "value": 50000
+        },
+        "radio-type":{
+            "help": "options are ATMEL, MCR20",
+            "value": "ATMEL"
+        },
+        "backhaul-driver": {
+            "help": "options are ETH, SLIP",
+            "value": "SLIP"
+        },
+        "mesh-mode": {
+            "help": "Mesh networking mode. Options are LOWPAN_ND and THREAD",
+            "value": "THREAD"
+        },
+        "backhaul-mac-src": {
+            "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+            "value": "BOARD"
+        },
+        "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+        "slip_hw_flow_control": "true",
+        "slip_serial_baud_rate": "921600",
+        "rf-channel": 22,
+        "rf-channel-page": 0,
+        "rf-channel-mask": "0x07fff800",
+        "debug-trace":  1,
+        "backhaul-dynamic-bootstrap": true,
+        "backhaul-prefix": "\"fd00:300::\"",
+        "backhaul-next-hop": "\"fe80::1\"",
+        "backhaul-default-route": "\"::/0\"",
+        "commissioning-dataset-timestamp": "0x00000001",
+        "pan-id": "0x0700",
+        "extended-pan-id": "{0xf1, 0xb5, 0xa1, 0xb2,0xc4, 0xd5, 0xa1, 0xbd }",
+        "mesh-local-prefix": "{0xfd, 0x0, 0x0d, 0xb8, 0x0, 0x0, 0x0, 0x0}",
+        "network-name": "\"Thread Network\"",
+        "pskd": "\"abcdefghijklmno\"",
+        "pskc": "{0xc8, 0xa6, 0x2e, 0xae, 0xf3, 0x68, 0xf3, 0x46, 0xa9, 0x9e, 0x57, 0x85, 0x98, 0x9d, 0x1c, 0xd0}",
+        "thread-master-key": "{0x10, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}",
+        "LED": "NC",
+        "SERIAL_TX": "NC",
+        "SERIAL_RX": "NC",
+        "SERIAL_CTS": "NC",
+        "SERIAL_RTS": "NC"
+    },
+    "macros": ["MBEDTLS_USER_CONFIG_FILE=\"source/mbedtls_thread_config.h\"", "ATMEL_SPI_RST = PTD4"],
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "COMMON_PAL", "THREAD_BORDER_ROUTER"],
+            "target.features_remove": ["LWIP"],
+            "mbed-trace.enable": 1,
+            "nanostack.configuration": "thread_border_router",
+            "platform.stdio-convert-newlines": true,
+            "platform.stdio-baud-rate": 115200
+        },
+        "K64F": {
+            "LED": "LED_GREEN",
+            "SERIAL_TX": "PTE0",
+            "SERIAL_RX": "PTE1",
+            "SERIAL_CTS": "PTE2",
+            "SERIAL_RTS": "PTE3"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/.gitignore	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,2 @@
+stm-spirit1-rf-driver
+stm-spirit1-rf-driver/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/TARGET_K64F/sal-nanostack-driver-k64f-eth.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/sal-nanostack-driver-k64f-eth/#dafa84646b48287273c57d0f677ccc39e33c4cb3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/TARGET_NUCLEO_F429ZI/.gitignore	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,2 @@
+sal-nanostack-driver-stm32-eth
+sal-nanostack-driver-stm32-eth/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/TARGET_NUCLEO_F429ZI/sal-nanostack-driver-stm32-eth.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/sal-nanostack-driver-stm32-eth/#1369c4a6a4546ca8ce8e51d7827621db2a2ad3c7
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/atmel-rf-driver.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/atmel-rf-driver/#57f22763f4d3649d4ac0b1df1f568f4cc45e491a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/eth_driver.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,16 @@
+#ifndef ETH_DRIVER_H
+#define ETH_DRIVER_H
+
+/**
+ * Initialize Ethernet PHY driver and register itself to MAC.
+ *
+ * Must follow C calling conventions.
+ *
+ * \param mac_ptr Pointer to EIU-48 address
+ * \param app_ipv6_init_cb Callback to receive link status and interface id
+ */
+
+
+extern "C" void arm_eth_phy_device_register(uint8_t *mac_ptr, void (*app_ipv6_init_cb)(uint8_t, int8_t));
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/mcr20a-rf-driver.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mcr20a-rf-driver/#d8810e105d7d35315aa708ec51d821156cad45e9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/rf_wrapper.cpp	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include "rf_wrapper.h"
+
+// Must be defined for next preprocessor tests to work
+#define ATMEL       0
+#define MCR20       1
+#define NCS36510    2
+#define SPIRIT1     3 
+
+#if MBED_CONF_APP_RADIO_TYPE == ATMEL
+#include "NanostackRfPhyAtmel.h"
+NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS,
+                           ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL);
+#elif MBED_CONF_APP_RADIO_TYPE == MCR20
+#include "NanostackRfPhyMcr20a.h"
+NanostackRfPhyMcr20a rf_phy(MCR20A_SPI_MOSI, MCR20A_SPI_MISO, MCR20A_SPI_SCLK, MCR20A_SPI_CS, MCR20A_SPI_RST, MCR20A_SPI_IRQ);
+#elif MBED_CONF_APP_RADIO_TYPE == SPIRIT1
+#include "NanostackRfPhySpirit1.h"
+NanostackRfPhySpirit1 rf_phy(SPIRIT1_SPI_MOSI, SPIRIT1_SPI_MISO, SPIRIT1_SPI_SCLK,
+			     SPIRIT1_DEV_IRQ, SPIRIT1_DEV_CS, SPIRIT1_DEV_SDN, SPIRIT1_BRD_LED);
+#endif //MBED_CONF_APP_RADIO_TYPE
+
+extern "C" int8_t rf_device_register()
+{
+    return rf_phy.rf_register();
+}
+
+extern "C" void rf_read_mac_address(uint8_t *mac)
+{
+    rf_phy.get_mac_address(mac);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/rf_wrapper.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int8_t rf_device_register(void);
+void rf_read_mac_address(uint8_t *mac);
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/sal-stack-nanostack-slip.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/sal-stack-nanostack-slip/#4a600894da858c0082fdae987b529e67c363dd4c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/stm-spirit1-rf-driver.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/stm-spirit1-rf-driver/#ac7a4f4772228d856b9c88709ad54066f396c5d2
\ No newline at end of file
Binary file images/BorderRouter.png has changed
Binary file images/br_role.png has changed
Binary file images/structure.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#305f5c491e34d86098e9da91b322017549c189ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,82 @@
+{
+    "config": {
+        "heap-size": {
+             "help": "The amount of static RAM to reserve for nsdynmemlib heap",
+             "value": 50000
+        },
+        "radio-type":{
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "ATMEL"
+        },
+        "backhaul-driver": {
+            "help": "options are ETH, SLIP",
+            "value": "ETH"
+        },
+        "mesh-mode": {
+            "help": "Mesh networking mode. Options are LOWPAN_ND and THREAD",
+            "value": "LOWPAN_ND"
+        },
+        "backhaul-mac-src": {
+            "help": "Where to get EUI48 address. Options are BOARD, CONFIG",
+            "value": "BOARD"
+        },
+        "backhaul-mac": "{0x02, 0x00, 0x00, 0x00, 0x00, 0x01}",
+        "slip_hw_flow_control": "false",
+        "slip_serial_baud_rate": "921600",
+        "debug-trace": "false",
+        "defined-BR-config": "true",
+        "security-mode": "NONE",
+        "psk-key-id": 1,
+        "psk-key": "{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}",
+        "pana-mode": "",
+        "tls-psk-key": "{0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0}",
+        "tls-psk-key-id": 1,
+        "pan-id": "0x0691",
+        "network-id": "network000000000",
+        "beacon-protocol-id": 4,
+        "prefix": "fd00:db8::",
+        "prefix-from-backhaul": true,
+        "rf-channel": 12,
+        "rf-channel-page": 0,
+        "rf-channel-mask": "0x07fff800",
+        "short-mac-address": "0xface",
+        "backhaul-dynamic-bootstrap": true,
+        "backhaul-prefix": "fd00:db8:ff1::",
+        "backhaul-default-route": "::/0",
+        "backhaul-next-hop": "fe80::1",
+        "ra-router-lifetime": 1024,
+        "rpl-instance-id": 1,
+        "rpl-idoublings": 9,
+        "rpl-imin": 12,
+        "rpl-k": 10,
+        "rpl-max-rank-inc": 2048,
+        "rpl-min-hop-rank-inc": 128,
+        "rpl-default-lifetime": 64,
+        "rpl-lifetime-unit": 60,
+        "rpl-pcs": 1,
+        "rpl-ocp": 1,
+        "multicast-addr": "ff05::7",
+        "LED": "NC",
+        "SERIAL_TX": "NC",
+        "SERIAL_RX": "NC",
+        "SERIAL_CTS": "NC",
+        "SERIAL_RTS": "NC"
+    },
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "LOWPAN_BORDER_ROUTER", "COMMON_PAL"],
+            "target.features_remove": ["LWIP"],
+            "mbed-trace.enable": 1,
+            "nanostack.configuration": "lowpan_border_router",
+            "platform.stdio-convert-newlines": true,
+            "platform.stdio-baud-rate": 115200
+        },
+        "K64F": {
+            "LED": "LED_GREEN",
+            "SERIAL_TX": "PTE0",
+            "SERIAL_RX": "PTE1",
+            "SERIAL_CTS": "PTE2",
+            "SERIAL_RTS": "PTE3"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/border_router_main.cpp	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <string.h>
+
+
+#include "mbed.h"
+#include "borderrouter_tasklet.h"
+#include "drivers/eth_driver.h"
+#include "sal-stack-nanostack-slip/Slip.h"
+
+#ifdef  MBED_CONF_APP_DEBUG_TRACE
+#if MBED_CONF_APP_DEBUG_TRACE == 1
+#define APP_TRACE_LEVEL TRACE_ACTIVE_LEVEL_DEBUG
+#else
+#define APP_TRACE_LEVEL TRACE_ACTIVE_LEVEL_INFO
+#endif
+#endif //MBED_CONF_APP_DEBUG_TRACE
+
+#include "ns_hal_init.h"
+#include "cmsis_os.h"
+#include "arm_hal_interrupt.h"
+
+
+#include "ns_trace.h"
+#define TRACE_GROUP "app"
+
+#define APP_DEFINED_HEAP_SIZE MBED_CONF_APP_HEAP_SIZE
+static uint8_t app_stack_heap[APP_DEFINED_HEAP_SIZE];
+static uint8_t mac[6] = {0};
+
+static DigitalOut led1(MBED_CONF_APP_LED);
+
+static Ticker led_ticker;
+
+static void app_heap_error_handler(heap_fail_t event);
+
+static void toggle_led1()
+{
+    led1 = !led1;
+}
+
+/**
+ * \brief Prints string to serial (adds CRLF).
+ */
+static void trace_printer(const char *str)
+{
+    printf("%s\n", str);
+}
+
+/**
+ * \brief Initializes the SLIP MAC backhaul driver.
+ * This function is called by the border router module.
+ */
+void backhaul_driver_init(void (*backhaul_driver_status_cb)(uint8_t, int8_t))
+{
+// Values allowed in "backhaul-driver" option
+#define ETH 0
+#define SLIP 1
+#if MBED_CONF_APP_BACKHAUL_DRIVER == SLIP
+    SlipMACDriver *pslipmacdriver;
+    int8_t slipdrv_id = -1;
+#if defined(MBED_CONF_APP_SLIP_HW_FLOW_CONTROL)
+    pslipmacdriver = new SlipMACDriver(SERIAL_TX, SERIAL_RX, SERIAL_RTS, SERIAL_CTS);
+#else
+    pslipmacdriver = new SlipMACDriver(SERIAL_TX, SERIAL_RX);
+#endif
+
+    if (pslipmacdriver == NULL) {
+        tr_error("Unable to create SLIP driver");
+        return;
+    }
+
+    tr_info("Using SLIP backhaul driver...");
+
+#ifdef MBED_CONF_APP_SLIP_SERIAL_BAUD_RATE
+    slipdrv_id = pslipmacdriver->Slip_Init(mac, MBED_CONF_APP_SLIP_SERIAL_BAUD_RATE);
+#else
+    tr_warning("baud rate for slip not defined");
+#endif
+
+    if (slipdrv_id >= 0) {
+        backhaul_driver_status_cb(1, slipdrv_id);
+        return;
+    }
+
+    tr_error("Backhaul driver init failed, retval = %d", slipdrv_id);
+#elif MBED_CONF_APP_BACKHAUL_DRIVER == ETH
+    tr_info("Using ETH backhaul driver...");
+    arm_eth_phy_device_register(mac, backhaul_driver_status_cb);
+    return;
+#else
+#error "Unsupported backhaul driver"
+#endif
+
+}
+
+/**
+ * \brief The entry point for this application.
+ * Sets up the application and starts the border router module.
+ */
+
+int main(int argc, char **argv)
+{
+    ns_hal_init(app_stack_heap, APP_DEFINED_HEAP_SIZE, app_heap_error_handler, 0);
+
+    trace_init(); // set up the tracing library
+    set_trace_print_function(trace_printer);
+    set_trace_config(TRACE_MODE_COLOR | APP_TRACE_LEVEL | TRACE_CARRIAGE_RETURN);
+
+
+#define BOARD 0
+#define CONFIG 1
+#if MBED_CONF_APP_BACKHAUL_MAC_SRC == BOARD
+    /* Setting the MAC Address from UID.
+     * Takes UID Mid low and UID low and shuffles them around. */
+    mbed_mac_address((char *)mac);
+#elif MBED_CONF_APP_BACKHAUL_MAC_SRC == CONFIG
+    const uint8_t mac48[] = MBED_CONF_APP_BACKHAUL_MAC;
+    for (uint32_t i = 0; i < sizeof(mac); ++i) {
+        mac[i] = mac48[i];
+    }
+#else
+    #error "MAC address not defined"
+#endif
+
+    led_ticker.attach_us(toggle_led1, 500000);
+    border_router_start();
+}
+
+/**
+ * \brief Error handler for errors in dynamic memory handling.
+ */
+static void app_heap_error_handler(heap_fail_t event)
+{
+    tr_error("Dyn mem error %x", (int8_t)event);
+
+    switch (event) {
+        case NS_DYN_MEM_NULL_FREE:
+            break;
+        case NS_DYN_MEM_DOUBLE_FREE:
+            break;
+        case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID:
+            break;
+        case NS_DYN_MEM_POINTER_NOT_VALID:
+            break;
+        case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED:
+            break;
+        case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED:
+            break;
+        default:
+            break;
+    }
+
+    while (1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_helpers.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "ip6string.h"
+#include "ns_types.h"
+#include "common_functions.h"
+#include "ns_trace.h"
+#define TRACE_GROUP "app"
+
+static char tmp_print_buffer[128] = {0};
+
+char *print_ipv6(const void *addr_ptr)
+{
+    ip6tos(addr_ptr, tmp_print_buffer);
+    return tmp_print_buffer;
+}
+
+char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len)
+{
+    char *str = tmp_print_buffer;
+    int retval;
+    char tmp[40];
+    uint8_t addr[16] = {0};
+
+    if (prefix_len != 0) {
+        if (prefix == NULL || prefix_len > 128) {
+            return "<err>";
+        }
+        bitcopy(addr, prefix, prefix_len);
+    }
+
+    ip6tos(addr, tmp);
+    retval = snprintf(str, 128, "%s/%u", tmp, prefix_len);
+    if (retval <= 0) {
+        return "";
+    }
+    return str;
+}
+
+void print_appl_info(void)
+{
+    tr_info("Starting NanoStack Border Router...");
+    tr_info("Build date: %s %s", __DATE__, __TIME__);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_helpers.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+
+#ifndef BORDERROUTER_HELPERS_H
+#define BORDERROUTER_HELPERS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+char *print_ipv6(const void *addr_ptr);
+char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len);
+void print_appl_info(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BORDERROUTER_HELPERS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_tasklet.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#define LOWPAN_ND 0
+#define THREAD 1
+#if MBED_CONF_APP_MESH_MODE == LOWPAN_ND
+
+#include <string.h>
+#include <stdlib.h>
+#include "ns_types.h"
+#include "eventOS_event.h"
+#include "eventOS_event_timer.h"
+#include "eventOS_scheduler.h"
+#include "multicast_api.h"
+#include "whiteboard_api.h"
+#include "platform/arm_hal_timer.h"
+#include "borderrouter_tasklet.h"
+#include "borderrouter_helpers.h"
+#include "net_interface.h"
+#include "cfg_parser.h"
+#include "rf_wrapper.h"
+#include "nwk_stats_api.h"
+#include "net_interface.h"
+#include "ip6string.h"
+#include "net_rpl.h"
+#include "mac_api.h"
+#include "ethernet_mac_api.h"
+#include "sw_mac.h"
+
+#include "static_6lowpan_config.h"
+
+#include "ns_trace.h"
+#define TRACE_GROUP "brro"
+
+#define NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY 2
+#define NR_BACKHAUL_INTERFACE_PHY_DOWN  3
+
+static mac_api_t *api;
+static eth_mac_api_t *eth_mac_api;
+
+/* The border router tasklet runs in grounded/non-storing mode */
+#define RPL_FLAGS RPL_GROUNDED | BR_DODAG_MOP_NON_STORING | RPL_DODAG_PREF(0)
+
+typedef enum interface_bootstrap_state {
+    INTERFACE_IDLE_PHY_NOT_READY,
+    INTERFACE_IDLE_STATE,
+    INTERFACE_BOOTSTRAP_ACTIVE,
+    INTERFACE_CONNECTED
+} interface_bootstrap_state_e;
+
+typedef struct {
+    uint8_t DODAG_ID[16];
+    uint8_t rpl_instance_id;
+    uint8_t rpl_setups;
+} rpl_setup_info_t;
+
+typedef struct {
+    int8_t prefix_len;
+    uint8_t prefix[16];
+    uint8_t next_hop[16];
+} route_info_t;
+
+/* Border router channel list */
+static channel_list_s channel_list;
+
+/* Channel masks for different RF types */
+static const uint32_t channel_mask_0_2_4ghz = 0x07fff800;
+
+/* Border router settings */
+static border_router_setup_s br;
+
+/* RPL routing settings */
+static rpl_setup_info_t rpl_setup_info;
+
+/* DODAG configuration */
+static dodag_config_t dodag_config;
+
+/* Backhaul prefix */
+static uint8_t backhaul_prefix[16] = {0};
+
+/* Backhaul default route information */
+static route_info_t backhaul_route;
+
+/* Should prefix on the backhaul used for PAN as well? */
+static uint8_t rf_prefix_from_backhaul = 0;
+
+static net_6lowpan_mode_e operating_mode = NET_6LOWPAN_BORDER_ROUTER;
+static net_6lowpan_mode_extension_e operating_mode_extension = NET_6LOWPAN_ND_WITH_MLE;
+static interface_bootstrap_state_e net_6lowpan_state = INTERFACE_IDLE_PHY_NOT_READY;
+static interface_bootstrap_state_e net_backhaul_state = INTERFACE_IDLE_PHY_NOT_READY;
+static net_ipv6_mode_e backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+
+static const uint8_t gp16_address_suffix[6] = {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00};
+
+static int8_t br_tasklet_id = -1;
+static int8_t net_6lowpan_id = -1;
+static int8_t backhaul_if_id = -1;
+
+/* Network statistics */
+static nwk_stats_t nwk_stats;
+
+/* Link layer security information */
+static net_6lowpan_link_layer_sec_mode_e link_security_mode;
+static net_link_layer_psk_security_info_s link_layer_psk;
+static net_tls_cipher_e pana_security_suite;
+
+static uint8_t multicast_addr[16] = {0};
+
+/* Function forward declarations */
+static void app_parse_network_event(arm_event_s *event);
+static void borderrouter_tasklet(arm_event_s *event);
+static void initialize_channel_list(uint32_t channel);
+static void start_6lowpan(const uint8_t *backhaul_address);
+static int8_t rf_interface_init(void);
+static void load_config(void);
+
+void border_router_start(void)
+{
+    load_config();
+    net_init_core();
+    /* initialize Radio module*/
+    net_6lowpan_id = rf_interface_init();
+
+    protocol_stats_start(&nwk_stats);
+
+    eventOS_event_handler_create(
+        &borderrouter_tasklet,
+        ARM_LIB_TASKLET_INIT_EVENT);
+}
+
+static void print_interface_addr(int id)
+{
+    uint8_t address_buf[128];
+    int address_count = 0;
+    char buf[128];
+
+    if (arm_net_address_list_get(id, 128, address_buf, &address_count) == 0) {
+        uint8_t *t_buf = address_buf;
+        for (int i = 0; i < address_count; ++i) {
+            ip6tos(t_buf, buf);
+            tr_info("   [%d] %s", i, buf);
+            t_buf += 16;
+        }
+    }
+}
+
+static void initialize_channel_list(uint32_t channel)
+{
+    const int_fast8_t word_index = channel / 32;
+    const int_fast8_t bit_index = channel % 32;
+
+    if (channel > 0) {
+        /* Zero channel value means listen all channels */
+        memset(&channel_list.channel_mask, 0, sizeof(channel_list.channel_mask));
+        channel_list.channel_mask[word_index] |= ((uint32_t) 1 << bit_index);
+    }
+}
+
+static void load_config(void)
+{
+    const char *prefix, *psk;
+    uint8_t nd_prefix[16];
+
+    prefix = cfg_string(global_config, "PREFIX", NULL);
+
+    if (!prefix) {
+        tr_error("No RF prefix in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), nd_prefix);
+
+    prefix = cfg_string(global_config, "BACKHAUL_PREFIX", NULL);
+    if (!prefix) {
+        tr_error("No backhaul prefix in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), backhaul_prefix);
+    memset(&backhaul_prefix[8], 0, 8);
+
+    prefix = cfg_string(global_config, "MULTICAST_ADDR", NULL);
+    if (!prefix) {
+        tr_error("No multicast address in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), multicast_addr);
+
+    /* Set up channel page and channgel mask */
+    memset(&channel_list, 0, sizeof(channel_list));
+    channel_list.channel_page = (channel_page_e)cfg_int(global_config, "RF_CHANNEL_PAGE", CHANNEL_PAGE_0);
+    channel_list.channel_mask[0] = cfg_int(global_config, "RF_CHANNEL_MASK", channel_mask_0_2_4ghz);
+
+    prefix = cfg_string(global_config, "NETWORK_ID", "NETWORK000000000");
+    memcpy(br.network_id, prefix, 16);
+
+    br.mac_panid = cfg_int(global_config, "PAN_ID", 0x0691);
+    tr_info("PANID: %x", br.mac_panid);
+    br.mac_short_adr = cfg_int(global_config, "SHORT_MAC_ADDRESS", 0xffff);
+    br.ra_life_time = cfg_int(global_config, "RA_ROUTER_LIFETIME", 1024);
+    br.beacon_protocol_id = cfg_int(global_config, "BEACON_PROTOCOL_ID", 4);
+
+    memcpy(br.lowpan_nd_prefix, nd_prefix, 8);
+    br.abro_version_num = 0;
+
+    /* RPL routing setup */
+    rpl_setup_info.rpl_instance_id = cfg_int(global_config, "RPL_INSTANCE_ID", 1);
+    rpl_setup_info.rpl_setups = RPL_FLAGS;
+
+    /* generate DODAG ID */
+    memcpy(rpl_setup_info.DODAG_ID, nd_prefix, 8);
+    memcpy(&rpl_setup_info.DODAG_ID[8], gp16_address_suffix, 6);
+    rpl_setup_info.DODAG_ID[14] = (br.mac_short_adr >> 8);
+    rpl_setup_info.DODAG_ID[15] = br.mac_short_adr;
+
+    /* DODAG configuration */
+    dodag_config.DAG_DIO_INT_DOUB = cfg_int(global_config, "RPL_IDOUBLINGS", 12);
+    dodag_config.DAG_DIO_INT_MIN = cfg_int(global_config, "RPL_IMIN", 9);
+    dodag_config.DAG_DIO_REDU = cfg_int(global_config, "RPL_K", 10);
+    dodag_config.DAG_MAX_RANK_INC = cfg_int(global_config, "RPL_MAX_RANK_INC", 2048);
+    dodag_config.DAG_MIN_HOP_RANK_INC = cfg_int(global_config, "RPL_MIN_HOP_RANK_INC", 128);
+    dodag_config.LIFE_IN_SECONDS = cfg_int(global_config, "RPL_LIFETIME_UNIT", 64);
+    dodag_config.LIFETIME_UNIT = cfg_int(global_config, "RPL_DEFAULT_LIFETIME", 60);
+    dodag_config.DAG_SEC_PCS = cfg_int(global_config, "RPL_PCS", 1);
+    dodag_config.DAG_OCP = cfg_int(global_config, "RPL_OCP", 1);
+
+    bool dynamic_bootstrap = (net_ipv6_mode_e)cfg_int(global_config, "BACKHAUL_DYNAMIC_BOOTSTRAP", 0);
+
+    if (dynamic_bootstrap == 1) {
+        backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_AUTONOMOUS;
+        tr_info("NET_IPV6_BOOTSTRAP_AUTONOMOUS");
+    } else {
+        tr_info("NET_IPV6_BOOTSTRAP_STATIC");
+        backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+    }
+
+    /* Bootstrap mode for the backhaul interface */
+    rf_prefix_from_backhaul = cfg_int(global_config, "PREFIX_FROM_BACKHAUL", 0);
+
+    /* Backhaul default route */
+    memset(&backhaul_route, 0, sizeof(backhaul_route));
+    psk = cfg_string(global_config, "BACKHAUL_NEXT_HOP", NULL);
+
+    if (psk) {
+        stoip6(psk, strlen(psk), backhaul_route.next_hop);
+    }
+
+    psk = cfg_string(global_config, "BACKHAUL_DEFAULT_ROUTE", NULL);
+
+    if (psk) {
+        char *prefix, route_buf[255] = {0};
+
+        /* copy the config value to a non-const buffer */
+        strncpy(route_buf, psk, sizeof(route_buf) - 1);
+        prefix = strtok(route_buf, "/");
+        backhaul_route.prefix_len = atoi(strtok(NULL, "/"));
+
+        stoip6(prefix, strlen(prefix), backhaul_route.prefix);
+    }
+
+    prefix = cfg_string(global_config, "SECURITY_MODE", "NONE");
+
+    if (strcmp(prefix, "NONE") == 0) {
+        link_security_mode = NET_SEC_MODE_NO_LINK_SECURITY;
+        tr_warn("Security NOT enabled");
+        return;
+    }
+
+    psk = cfg_string(global_config, "PSK_KEY", NULL);
+
+    if (!psk) {
+        tr_error("No PSK set in configuration!");
+        return;
+    }
+
+    link_layer_psk.key_id = cfg_int(global_config, "PSK_KEY_ID", 1);
+    memcpy(link_layer_psk.security_key, psk, 16);
+
+    if (strcmp(prefix, "PSK") == 0) {
+        tr_debug("Using PSK security mode, key ID = %d", link_layer_psk.key_id);
+        link_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY;
+    } else if (strcmp(prefix, "PANA") == 0) {
+        const char *mode = cfg_string(global_config, "PANA_MODE", "PSK");
+        link_security_mode = NET_SEC_MODE_PANA_LINK_SECURITY;
+        if (strcmp(mode, "ECC") == 0) {
+            pana_security_suite = NET_TLS_ECC_CIPHER;
+        } else if (strcmp(mode, "ECC+PSK") == 0) {
+            pana_security_suite = NET_TLS_PSK_AND_ECC_CIPHER;
+        } else {
+            pana_security_suite = NET_TLS_PSK_CIPHER;
+        }
+    }
+}
+
+static int8_t rf_interface_init(void)
+{
+    static char phy_name[] = "mesh0";
+    int8_t rfid = -1;
+    int8_t rf_phy_device_register_id = rf_device_register();
+    tr_debug("RF device ID: %d", rf_phy_device_register_id);
+
+    if (rf_phy_device_register_id >= 0) {
+        mac_description_storage_size_t storage_sizes;
+        storage_sizes.device_decription_table_size = 32;
+        storage_sizes.key_description_table_size = 3;
+        storage_sizes.key_lookup_size = 1;
+        storage_sizes.key_usage_size = 3;
+        if (!api) {
+            api = ns_sw_mac_create(rf_phy_device_register_id, &storage_sizes);
+        }
+        rfid = arm_nwk_interface_lowpan_init(api, phy_name);
+        tr_debug("RF interface ID: %d", rfid);
+    }
+
+    return rfid;
+}
+
+static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id)
+{
+    arm_event_s event = {
+        .sender = br_tasklet_id,
+        .receiver = br_tasklet_id,
+        .priority = ARM_LIB_MED_PRIORITY_EVENT,
+        .event_type = APPLICATION_EVENT,
+        .event_data = driver_id
+    };
+
+    if (link_up) {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY;
+    } else {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DOWN;
+    }
+
+    tr_debug("Backhaul driver ID: %d", driver_id);
+
+    eventOS_event_send(&event);
+}
+
+static int backhaul_interface_up(int8_t driver_id)
+{
+    int retval = -1;
+    if (backhaul_if_id != -1) {
+        tr_debug("Border RouterInterface already at active state\n");
+    } else {
+        if (!eth_mac_api) {
+            eth_mac_api = ethernet_mac_create(driver_id);
+        }
+
+        backhaul_if_id = arm_nwk_interface_ethernet_init(eth_mac_api, "bh0");
+
+        if (backhaul_if_id >= 0) {
+            tr_debug("Backhaul interface ID: %d", backhaul_if_id);
+            if (memcmp(backhaul_prefix, (const uint8_t[8]) { 0 }, 8) == 0) {
+                memcpy(backhaul_prefix, rpl_setup_info.DODAG_ID, 8);
+            }
+            arm_nwk_interface_configure_ipv6_bootstrap_set(
+                backhaul_if_id, backhaul_bootstrap_mode, backhaul_prefix);
+            arm_nwk_interface_up(backhaul_if_id);
+            retval = 0;
+        }
+    }
+    return retval;
+}
+
+static int backhaul_interface_down(void)
+{
+    int retval = -1;
+    if (backhaul_if_id != -1) {
+        arm_nwk_interface_down(backhaul_if_id);
+        backhaul_if_id = -1;
+        retval = 0;
+    }
+    return retval;
+}
+
+/**
+  * \brief Border Router Main Tasklet
+  *
+  *  Tasklet Handle next items:
+  *
+  *  - EV_INIT event: Set Certificate Chain, RF Interface Boot UP, multicast Init
+  *  - SYSTEM_TIMER event: For RF interface Handshake purpose
+  *
+  */
+static void borderrouter_tasklet(arm_event_s *event)
+{
+    arm_library_event_type_e event_type;
+    event_type = (arm_library_event_type_e)event->event_type;
+
+    switch (event_type) {
+        case ARM_LIB_NWK_INTERFACE_EVENT:
+            app_parse_network_event(event);
+            break;
+
+        case APPLICATION_EVENT:
+            if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY) {
+                int8_t net_backhaul_id = (int8_t) event->event_data;
+                if (net_backhaul_state == INTERFACE_IDLE_PHY_NOT_READY) {
+                    net_backhaul_state = INTERFACE_IDLE_STATE;
+                }
+
+                if (backhaul_interface_up(net_backhaul_id) != 0) {
+                    tr_debug("Backhaul bootstrap start failed");
+                } else {
+                    tr_debug("Backhaul bootstrap started");
+                    net_backhaul_state = INTERFACE_BOOTSTRAP_ACTIVE;
+                }
+            } else if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DOWN) {
+                if (backhaul_interface_down() != 0) {
+                    tr_error("Backhaul interface down failed");
+                } else {
+                    tr_debug("Backhaul interface is down");
+                    backhaul_if_id = -1;
+                    net_backhaul_state = INTERFACE_IDLE_STATE;
+                }
+            }
+            break;
+
+        case ARM_LIB_TASKLET_INIT_EVENT:
+            print_appl_info();
+            br_tasklet_id = event->receiver;
+
+            /* initialize the backhaul interface */
+            backhaul_driver_init(borderrouter_backhaul_phy_status_cb);
+
+            if (net_6lowpan_id < 0) {
+                tr_error("RF interface initialization failed");
+                return;
+            }
+            net_6lowpan_state = INTERFACE_IDLE_STATE;
+            eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            break;
+
+        case ARM_LIB_SYSTEM_TIMER_EVENT:
+            eventOS_event_timer_cancel(event->event_id, event->receiver);
+
+            if (event->event_id == 9) {
+#ifdef MBED_CONF_APP_DEBUG_TRACE
+#if MBED_CONF_APP_DEBUG_TRACE == 1
+                arm_print_routing_table();
+                arm_print_neigh_cache();
+#endif
+#endif
+                eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void start_6lowpan(const uint8_t *backhaul_address)
+{
+    uint8_t p[16] = {0};
+
+    if (arm_net_address_get(backhaul_if_id, ADDR_IPV6_GP, p) == 0) {
+        uint32_t lifetime = 0xffffffff; // infinite
+        uint8_t prefix_len = 0;
+        uint8_t t_flags = 0;
+        int8_t retval = -1;
+
+        /* Channel list: listen to a channel (default: all channels) */
+        uint32_t channel = cfg_int(global_config, "RF_CHANNEL", 0);
+        tr_info("RF channel: %d", channel);
+        initialize_channel_list(channel);
+
+        // configure as border router and set the operation mode
+        retval = arm_nwk_interface_configure_6lowpan_bootstrap_set(net_6lowpan_id,
+                 operating_mode, operating_mode_extension);
+
+        if (retval < 0) {
+            tr_error("Configuring 6LoWPAN bootstrap failed, retval = %d", retval);
+            return;
+        }
+
+        retval = arm_nwk_link_layer_security_mode(net_6lowpan_id, link_security_mode, 5, &link_layer_psk);
+
+        if (retval < 0) {
+            tr_error("Failed to set link layer security mode, retval = %d", retval);
+            return;
+        }
+
+        /* Should we use the backhaul prefix on the PAN as well? */
+        if (backhaul_address && rf_prefix_from_backhaul) {
+            memcpy(br.lowpan_nd_prefix, p, 8);
+            memcpy(rpl_setup_info.DODAG_ID, br.lowpan_nd_prefix, 8);
+        }
+
+        retval = arm_nwk_6lowpan_border_router_init(net_6lowpan_id, &br);
+
+        if (retval < 0) {
+            tr_error("Initializing 6LoWPAN border router failed, retval = %d", retval);
+            return;
+        }
+
+        /* configure both /64 and /128 context prefixes */
+        retval = arm_nwk_6lowpan_border_router_context_update(net_6lowpan_id, ((1 << 4) | 0x03),
+                 128, 0xffff, rpl_setup_info.DODAG_ID);
+
+        if (retval < 0) {
+            tr_error("Setting ND context failed, retval = %d", retval);
+            return;
+        }
+
+        // configure the RPL routing protocol for the 6LoWPAN mesh network
+        if (arm_nwk_6lowpan_rpl_dodag_init(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                           &dodag_config, rpl_setup_info.rpl_instance_id,
+                                           rpl_setup_info.rpl_setups) == 0) {
+            prefix_len = 64;
+            t_flags = RPL_PREFIX_ROUTER_ADDRESS_FLAG;
+            /* add "/64" prefix with the full BR address (DODAG ID) */
+            arm_nwk_6lowpan_rpl_dodag_prefix_update(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                                    prefix_len, t_flags, lifetime);
+
+            t_flags = 0;
+            prefix_len = 0;
+            /* add default route "::/0" */
+            arm_nwk_6lowpan_rpl_dodag_route_update(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                                   prefix_len, t_flags, lifetime);
+        }
+
+        if (link_security_mode == NET_SEC_MODE_PANA_LINK_SECURITY) {
+            uint8_t *psk = (uint8_t *)cfg_string(global_config, "TLS_PSK_KEY", NULL);
+
+            if (!psk) {
+                tr_error("No TLS PSK key set in configuration");
+                return;
+            }
+
+            if (arm_tls_add_psk_key(psk, cfg_int(global_config, "TLS_PSK_KEY_ID", 0)) != 0) {
+                tr_error("No TLS PSK key ID set in configuration");
+                return;
+            }
+
+            retval = arm_pana_server_library_init(net_6lowpan_id, pana_security_suite, NULL, 120);
+
+            if (retval) {
+                tr_error("Failed to initialize PANA server library, retval = %d", retval);
+                return;
+            }
+        }
+
+        retval = arm_nwk_set_channel_list(net_6lowpan_id, &channel_list);
+
+        if (retval) {
+            tr_error("Failed to set channel list, retval = %d", retval);
+            return;
+        }
+
+        retval = arm_nwk_interface_up(net_6lowpan_id);
+
+        if (retval < 0) {
+            tr_error("Failed to bring up the RF interface, retval = %d", retval);
+            return;
+        }
+
+        /* mark the RF interface active */
+        net_6lowpan_state = INTERFACE_BOOTSTRAP_ACTIVE;
+
+        multicast_set_parameters(10, 0, 20, 3, 75);
+        multicast_add_address(multicast_addr, 1);
+    }
+}
+
+/**
+  * \brief Network state event handler.
+  * \param event show network start response or current network state.
+  *
+  */
+static void app_parse_network_event(arm_event_s *event)
+{
+    switch ((arm_nwk_interface_status_type_e)event->event_data) {
+        case ARM_NWK_BOOTSTRAP_READY: {
+            bool gp_address_available;
+            uint8_t p[16];
+            char buf[128];
+            if (0 == arm_net_address_get(event->event_id, ADDR_IPV6_GP, p)) {
+                ip6tos(p, buf);
+                gp_address_available = true;
+            } else {
+                gp_address_available = false;
+            }
+
+            if (backhaul_if_id == event->event_id) {
+
+                if (gp_address_available) {
+                    tr_info("Backhaul bootstrap ready, IPv6 = %s", buf);
+                } else {
+                    tr_info("Backhaul interface in ULA Mode");
+                }
+
+                if (backhaul_bootstrap_mode == NET_IPV6_BOOTSTRAP_STATIC) {
+                    int8_t retval;
+                    uint8_t *next_hop_ptr;
+
+                    if (memcmp(backhaul_route.next_hop, (const uint8_t[16]) {0}, 16) == 0) {
+                        tr_info("Next hop not defined");
+                        next_hop_ptr = NULL;
+                    }
+                    else {
+                        next_hop_ptr = backhaul_route.next_hop;
+                    }
+
+                    tr_info("Backhaul default route:");
+                    tr_info("   prefix:   %s", print_ipv6_prefix(backhaul_route.prefix, backhaul_route.prefix_len));
+                    tr_info("   next hop: %s", next_hop_ptr ? print_ipv6(backhaul_route.next_hop) : "on-link");
+
+                    retval = arm_net_route_add(backhaul_route.prefix, backhaul_route.prefix_len,
+                                               next_hop_ptr, 0xffffffff, 128, backhaul_if_id);
+
+                    if (retval < 0) {
+                        tr_error("Failed to add backhaul default route, retval = %d", retval);
+                    }
+                }
+
+                tr_info("Backhaul interface addresses:");
+                print_interface_addr(backhaul_if_id);
+
+                net_backhaul_state = INTERFACE_CONNECTED;
+                if (net_6lowpan_state == INTERFACE_IDLE_STATE) {
+                    //Start 6lowpan
+                    start_6lowpan(p);
+                }
+            } else {
+                tr_info("RF bootstrap ready, IPv6 = %s", buf);
+                arm_nwk_6lowpan_rpl_dodag_start(net_6lowpan_id);
+                net_6lowpan_state = INTERFACE_CONNECTED;
+                tr_info("RF interface addresses:");
+                print_interface_addr(net_6lowpan_id);
+                tr_info("6LoWPAN Border Router Bootstrap Complete.");
+            }
+        }
+            /* Network connection Ready */
+        break;
+        case ARM_NWK_NWK_SCAN_FAIL:
+            /* Link Layer Active Scan Fail, Stack is Already in Idle state */
+            break;
+        case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
+            /* No ND Router at current Channel Stack is Already at Idle state */
+            break;
+        case ARM_NWK_NWK_CONNECTION_DOWN:
+            /* Connection to Access point is lost wait for Scan Result */
+            break;
+        case ARM_NWK_NWK_PARENT_POLL_FAIL:
+            break;
+        case ARM_NWK_AUHTENTICATION_FAIL:
+            /* Network authentication fail */
+            break;
+        case ARM_NWK_DUPLICATE_ADDRESS_DETECTED:
+            if (backhaul_if_id == event->event_id) {
+                tr_error("Backhaul DAD failed.");
+            }
+            break;
+        default:
+            /* Unknow event */
+            break;
+    }
+}
+
+#endif // MBED_CONF_APP_MESH_MODE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_tasklet.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+
+#ifndef BORDERROUTER_TASKLET_H
+#define BORDERROUTER_TASKLET_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Initializes the backhaul driver. MUST be implemented by the application.
+ */
+void backhaul_driver_init(void (*backhaul_driver_status_cb)(uint8_t, int8_t));
+
+/**
+ * Initializes the border router module: loads configuration and
+ * initiates bootstrap for the RF 6LoWPAN and backhaul interfaces.
+ */
+void border_router_start(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BORDERROUTER_TASKLET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_thread_tasklet.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#define LOWPAN_ND 0
+#define THREAD 1
+#if MBED_CONF_APP_MESH_MODE == THREAD
+
+#include <string.h>
+#include <stdlib.h>
+#include <mbed_assert.h>
+#include "ns_types.h"
+#include "eventOS_event.h"
+#include "eventOS_event_timer.h"
+#include "eventOS_scheduler.h"
+#include "platform/arm_hal_timer.h"
+#include "borderrouter_tasklet.h"
+#include "borderrouter_helpers.h"
+#include "net_interface.h"
+#include "rf_wrapper.h"
+#include "nwk_stats_api.h"
+#include "ip6string.h"
+#include "ethernet_mac_api.h"
+#include "mac_api.h"
+#include "sw_mac.h"
+#include "mbed_interface.h"
+#include "common_functions.h"
+#include "thread_management_if.h"
+#include "thread_br_conn_handler.h"
+#include "randLIB.h"
+
+#include "ns_trace.h"
+#define TRACE_GROUP "brro"
+
+#define NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY 2
+#define NR_BACKHAUL_INTERFACE_PHY_DOWN  3
+#define MESH_LINK_TIMEOUT 100
+#define MESH_METRIC 1000
+#define THREAD_MAX_CHILD_COUNT 32
+
+static mac_api_t *api;
+static eth_mac_api_t *eth_mac_api;
+
+typedef enum {
+    STATE_UNKNOWN,
+    STATE_DISCONNECTED,
+    STATE_LINK_READY,
+    STATE_BOOTSTRAP,
+    STATE_CONNECTED,
+    STATE_MAX_VALUE
+} connection_state_e;
+
+typedef struct {
+    int8_t prefix_len;
+    uint8_t prefix[16];
+    uint8_t next_hop[16];
+} route_info_t;
+
+/* Border router channel list */
+static channel_list_s channel_list;
+
+/* Backhaul prefix */
+static uint8_t backhaul_prefix[16] = {0};
+
+/* Backhaul default route information */
+static route_info_t backhaul_route;
+static int8_t br_tasklet_id = -1;
+
+/* Network statistics */
+static nwk_stats_t nwk_stats;
+
+/* Function forward declarations */
+
+static void thread_link_configuration_get(link_configuration_s *link_configuration);
+static void network_interface_event_handler(arm_event_s *event);
+static void mesh_network_up(void);
+static void eth_network_data_init(void);
+static net_ipv6_mode_e backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+static void borderrouter_tasklet(arm_event_s *event);
+
+static void print_interface_addr(int id)
+{
+    uint8_t address_buf[128];
+    int address_count = 0;
+    char buf[128];
+
+    if (arm_net_address_list_get(id, 128, address_buf, &address_count) == 0) {
+        uint8_t *t_buf = address_buf;
+        for (int i = 0; i < address_count; ++i) {
+            ip6tos(t_buf, buf);
+            tr_info(" [%d] %s", i, buf);
+            t_buf += 16;
+        }
+    }
+}
+
+static void eth_network_data_init()
+{
+    memset(&backhaul_prefix[8], 0, 8);
+
+    /* Bootstrap mode for the backhaul interface */
+#if MBED_CONF_APP_BACKHAUL_DYNAMIC_BOOTSTRAP == 1
+    backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_AUTONOMOUS;
+    tr_info("NET_IPV6_BOOTSTRAP_AUTONOMOUS");
+
+#else
+    tr_info("NET_IPV6_BOOTSTRAP_STATIC");
+    backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+    // done like this so that prefix can be left out in the dynamic case.
+    const char *param = MBED_CONF_APP_BACKHAUL_PREFIX;
+    stoip6(param, strlen(param), backhaul_prefix);
+    tr_info("backhaul_prefix: %s", print_ipv6(backhaul_prefix));
+
+    /* Backhaul route configuration*/
+    memset(&backhaul_route, 0, sizeof(backhaul_route));
+#ifdef MBED_CONF_APP_BACKHAUL_NEXT_HOP
+    param = MBED_CONF_APP_BACKHAUL_NEXT_HOP;
+    stoip6(param, strlen(param), backhaul_route.next_hop);
+    tr_info("next hop: %s", print_ipv6(backhaul_route.next_hop));
+#endif
+    param = MBED_CONF_APP_BACKHAUL_DEFAULT_ROUTE;
+    char *prefix, route_buf[255] = {0};
+    /* copy the config value to a non-const buffer */
+    strncpy(route_buf, param, sizeof(route_buf) - 1);
+    prefix = strtok(route_buf, "/");
+    backhaul_route.prefix_len = atoi(strtok(NULL, "/"));
+    stoip6(prefix, strlen(prefix), backhaul_route.prefix);
+    tr_info("backhaul route prefix: %s", print_ipv6(backhaul_route.prefix));
+#endif
+}
+
+static int thread_interface_up(void)
+{
+    int32_t val;
+    device_configuration_s device_config;
+    link_configuration_s link_setup;
+    int8_t thread_if_id = thread_br_conn_handler_thread_interface_id_get();
+
+    tr_info("thread_interface_up");
+    memset(&device_config, 0, sizeof(device_config));
+
+    const char *param = MBED_CONF_APP_PSKD;
+    uint16_t len = strlen(param);
+    MBED_ASSERT(len > 5 && len < 33);
+
+    device_config.PSKd_ptr = malloc(len + 1);
+    device_config.PSKd_len = len;
+    memset(device_config.PSKd_ptr, 0, len + 1);
+    memcpy(device_config.PSKd_ptr, param, len);
+
+    thread_link_configuration_get(&link_setup);
+
+    val = thread_management_node_init(thread_if_id, &channel_list, &device_config, &link_setup);
+
+    if (val) {
+        tr_error("Thread init error with code: %is\r\n", (int)val);
+        return val;
+    }
+
+    // Additional thread configurations
+    thread_management_set_link_timeout(thread_if_id, MESH_LINK_TIMEOUT);
+    thread_management_max_child_count(thread_if_id, THREAD_MAX_CHILD_COUNT);
+
+    val = arm_nwk_interface_up(thread_if_id);
+    if (val != 0) {
+        tr_error("mesh0 up Fail with code: %i\r\n", (int)val);
+        return -1;
+    } else {
+        tr_info("mesh0 bootstrap ongoing...");
+    }
+    return 0;
+}
+
+static void thread_link_configuration_get(link_configuration_s *link_configuration)
+{
+    memset(link_configuration, 0, sizeof(link_configuration_s));
+
+    MBED_ASSERT(strlen(MBED_CONF_APP_NETWORK_NAME) > 0 && strlen(MBED_CONF_APP_NETWORK_NAME) < 17);
+    const uint8_t master_key[] = MBED_CONF_APP_THREAD_MASTER_KEY;
+    MBED_ASSERT(sizeof(master_key) == 16);
+    const uint8_t pskc[] = MBED_CONF_APP_PSKC;
+    MBED_ASSERT(sizeof(pskc) == 16);
+
+    const uint8_t extented_panid[] = MBED_CONF_APP_EXTENDED_PAN_ID;
+    MBED_ASSERT(sizeof(extented_panid) == 8);
+    const uint8_t mesh_local_prefix[] = MBED_CONF_APP_MESH_LOCAL_PREFIX;
+    MBED_ASSERT(sizeof(mesh_local_prefix) == 8);
+
+    memcpy(link_configuration->extented_pan_id, extented_panid, sizeof(extented_panid));
+    memcpy(link_configuration->mesh_local_ula_prefix, mesh_local_prefix, sizeof(mesh_local_prefix));
+
+    link_configuration->panId = MBED_CONF_APP_PAN_ID;
+    tr_info("PAN ID %x", link_configuration->panId);
+    memcpy(link_configuration->name, MBED_CONF_APP_NETWORK_NAME, strlen(MBED_CONF_APP_NETWORK_NAME));
+    link_configuration->timestamp = MBED_CONF_APP_COMMISSIONING_DATASET_TIMESTAMP;
+
+    memcpy(link_configuration->PSKc, pskc, sizeof(pskc));
+    memcpy(link_configuration->master_key, master_key, sizeof(master_key));
+    link_configuration->securityPolicy = SECURITY_POLICY_ALL_SECURITY;
+
+    link_configuration->rfChannel = MBED_CONF_APP_RF_CHANNEL;
+    tr_info("RF channel %d", link_configuration->rfChannel);
+    link_configuration->channel_page = MBED_CONF_APP_RF_CHANNEL_PAGE;
+    uint32_t channel_mask = MBED_CONF_APP_RF_CHANNEL_MASK;
+    common_write_32_bit(channel_mask, link_configuration->channel_mask);
+
+    link_configuration->key_rotation = 3600;
+    link_configuration->key_sequence = 0;
+}
+
+// ethernet interface
+static void network_interface_event_handler(arm_event_s *event)
+{
+    bool connectStatus = false;
+    arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
+    switch (status) {
+        case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
+
+            connectStatus = true;
+            tr_info("BR interface_id: %d", thread_br_conn_handler_eth_interface_id_get());
+            if (-1 != thread_br_conn_handler_eth_interface_id_get()) {
+                // metric set to high priority
+                if (0 != arm_net_interface_set_metric(thread_br_conn_handler_eth_interface_id_get(), 0)) {
+                    tr_warn("Failed to set metric for eth0.");
+                }
+
+                if (backhaul_bootstrap_mode == NET_IPV6_BOOTSTRAP_STATIC) {
+                    uint8_t *next_hop_ptr;
+
+                    if (memcmp(backhaul_route.next_hop, (const uint8_t[16]) {0}, 16) == 0) {
+                        next_hop_ptr = NULL;
+                    }
+                    else {
+                        next_hop_ptr = backhaul_route.next_hop;
+                    }
+                    tr_debug("Default route prefix: %s/%d", print_ipv6(backhaul_route.prefix),
+                             backhaul_route.prefix_len);
+                    tr_debug("Default route next hop: %s", print_ipv6(backhaul_route.next_hop));
+                    arm_net_route_add(backhaul_route.prefix,
+                                      backhaul_route.prefix_len,
+                                      next_hop_ptr, 0xffffffff, 128,
+                                      thread_br_conn_handler_eth_interface_id_get());
+                }
+                thread_br_conn_handler_eth_ready();
+                tr_info("Backhaul interface addresses:");
+                print_interface_addr(thread_br_conn_handler_eth_interface_id_get());
+                thread_br_conn_handler_ethernet_connection_update(connectStatus);
+            }
+            break;
+        }
+        case (ARM_NWK_RPL_INSTANCE_FLOODING_READY): // RPL instance have been flooded
+            tr_info("\rRPL instance have been flooded\r\n");
+            break;
+        case (ARM_NWK_SET_DOWN_COMPLETE): // Interface DOWN command successfully
+            break;
+        case (ARM_NWK_NWK_SCAN_FAIL):   // Interface have not detect any valid network
+            tr_warning("\rmesh0 haven't detect any valid nw\r\n");
+            break;
+        case (ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL): // IP address allocation fail(ND, DHCPv4 or DHCPv6)
+            tr_error("\rNO GP address detected");
+            break;
+        case (ARM_NWK_DUPLICATE_ADDRESS_DETECTED): // User specific GP16 was not valid
+            tr_error("\rEthernet IPv6 Duplicate addr detected!\r\n");
+            break;
+        case (ARM_NWK_AUHTENTICATION_START_FAIL): // No valid Authentication server detected behind access point ;
+            tr_error("\rNo valid ath server detected behind AP\r\n");
+            break;
+        case (ARM_NWK_AUHTENTICATION_FAIL): // Network authentication fail by Handshake
+            tr_error("\rNetwork authentication fail");
+            break;
+        case (ARM_NWK_NWK_CONNECTION_DOWN): // No connection between Access point or Default Router
+            tr_warning("\rPrefix timeout\r\n");
+            break;
+        case (ARM_NWK_NWK_PARENT_POLL_FAIL): // Sleepy host poll fail 3 time
+            tr_warning("\rParent poll fail\r\n");
+            break;
+        case (ARM_NWK_PHY_CONNECTION_DOWN): // Interface PHY cable off or serial port interface not respond anymore
+            tr_error("\reth0 down\r\n");
+            break;
+        default:
+            tr_warning("\rUnkown nw if event (type: %02x, id: %02x, data: %02x)\r\n", event->event_type, event->event_id, (unsigned int)event->event_data);
+            break;
+    }
+}
+
+void thread_interface_event_handler(arm_event_s *event)
+{
+    bool connectStatus = false;
+    arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
+    switch (status) {
+        case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
+            connectStatus = true;
+            tr_info("Thread bootstrap ready");
+
+            if (arm_net_interface_set_metric(thread_br_conn_handler_thread_interface_id_get(), MESH_METRIC) != 0) {
+                tr_warn("Failed to set metric for mesh0.");
+            }
+
+            tr_info("RF interface addresses:");
+            print_interface_addr(thread_br_conn_handler_thread_interface_id_get());
+
+            break;
+        }
+        case (ARM_NWK_SET_DOWN_COMPLETE):
+            tr_info("Thread interface down");
+            break;
+        default:
+            tr_warning("Unkown nw if event (type: %02x, id: %02x, data: %02x)\r\n", event->event_type, event->event_id, (unsigned int)event->event_data);
+            break;
+    }
+
+    thread_br_conn_handler_thread_connection_update(connectStatus);
+}
+
+static void mesh_network_up()
+{
+    tr_debug("Create Mesh Interface");
+
+    int status;
+    int8_t thread_if_id;
+
+    thread_if_id = arm_nwk_interface_lowpan_init(api, "ThreadInterface");
+    tr_info("thread_if_id: %d", thread_if_id);
+    MBED_ASSERT(thread_if_id>=0);
+
+    if (thread_if_id < 0) {
+        tr_error("arm_nwk_interface_lowpan_init() failed");
+        return;
+    }
+
+    status = arm_nwk_interface_configure_6lowpan_bootstrap_set(
+                thread_if_id,
+                NET_6LOWPAN_ROUTER,
+                NET_6LOWPAN_THREAD);
+
+    if (status < 0) {
+        tr_error("arm_nwk_interface_configure_6lowpan_bootstrap_set() failed");
+        return;
+    }
+
+    thread_br_conn_handler_thread_interface_id_set(thread_if_id);
+
+    status = thread_interface_up();
+    MBED_ASSERT(!status);
+    if (status) {
+        tr_error("thread_interface_up() failed: %d", status);
+    }
+}
+
+void thread_rf_init()
+{
+    mac_description_storage_size_t storage_sizes;
+    storage_sizes.key_lookup_size = 1;
+    storage_sizes.key_usage_size = 1;
+    storage_sizes.device_decription_table_size = 32;
+    storage_sizes.key_description_table_size = 6;
+
+    int8_t rf_driver_id = rf_device_register();
+    MBED_ASSERT(rf_driver_id>=0);
+    if (rf_driver_id>=0) {
+        randLIB_seed_random();
+
+        if (!api) {
+            api = ns_sw_mac_create(rf_driver_id, &storage_sizes);
+        }
+    }
+}
+
+void border_router_start(void)
+{
+    net_init_core();
+    thread_rf_init();
+    protocol_stats_start(&nwk_stats);
+
+    eventOS_event_handler_create(
+        &borderrouter_tasklet,
+        ARM_LIB_TASKLET_INIT_EVENT);
+}
+
+
+static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id)
+{
+    arm_event_s event = {
+        .sender = br_tasklet_id,
+        .receiver = br_tasklet_id,
+        .priority = ARM_LIB_MED_PRIORITY_EVENT,
+        .event_type = APPLICATION_EVENT,
+        .event_data = driver_id
+    };
+
+    if (link_up) {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY;
+    } else {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DOWN;
+    }
+
+    tr_debug("Backhaul driver ID: %d", driver_id);
+
+    eventOS_event_send(&event);
+}
+
+static int backhaul_interface_up(int8_t driver_id)
+{
+    int retval = -1;
+    tr_debug("backhaul_interface_up: %i\n", driver_id);
+    int8_t backhaul_if_id = thread_br_conn_handler_eth_interface_id_get();
+    if (backhaul_if_id != -1) {
+        tr_debug("Border RouterInterface already at active state\n");
+    } else {
+
+        if (!eth_mac_api) {
+            eth_mac_api = ethernet_mac_create(driver_id);
+        }
+
+        backhaul_if_id = arm_nwk_interface_ethernet_init(eth_mac_api, "bh0");
+
+        MBED_ASSERT(backhaul_if_id >= 0);
+        if (backhaul_if_id >= 0) {
+            tr_debug("Backhaul interface ID: %d", backhaul_if_id);
+            thread_br_conn_handler_eth_interface_id_set(backhaul_if_id);
+            arm_nwk_interface_configure_ipv6_bootstrap_set(
+                backhaul_if_id, backhaul_bootstrap_mode, backhaul_prefix);
+            arm_nwk_interface_up(backhaul_if_id);
+            retval = 0;
+        }
+        else {
+            tr_debug("Could not init ethernet");
+        }
+    }
+    return retval;
+}
+
+static int backhaul_interface_down(void)
+{
+    int retval = -1;
+    if (thread_br_conn_handler_eth_interface_id_get() != -1) {
+        arm_nwk_interface_down(thread_br_conn_handler_eth_interface_id_get());
+        thread_br_conn_handler_eth_interface_id_set(-1);
+        thread_br_conn_handler_ethernet_connection_update(false);
+        retval = 0;
+    }
+    else {
+        tr_debug("Could not set eth down");
+    }
+    return retval;
+}
+
+/**
+  * \brief Border Router Main Tasklet
+  *
+  *  Tasklet Handle next items:
+  *
+  *  - EV_INIT event: Set Certificate Chain, RF Interface Boot UP, multicast Init
+  *  - SYSTEM_TIMER event: For RF interface Handshake purpose
+  *
+  */
+static void borderrouter_tasklet(arm_event_s *event)
+{
+    arm_library_event_type_e event_type;
+    event_type = (arm_library_event_type_e)event->event_type;
+
+    switch (event_type) {
+        case ARM_LIB_NWK_INTERFACE_EVENT:
+
+            if (event->event_id == thread_br_conn_handler_eth_interface_id_get()) {
+                network_interface_event_handler(event);
+            } else {
+                thread_interface_event_handler(event);
+            }
+
+            break;
+        // comes from the backhaul_driver_init.
+        case APPLICATION_EVENT:
+            if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY) {
+                int8_t net_backhaul_id = (int8_t) event->event_data;
+
+                if (backhaul_interface_up(net_backhaul_id) != 0) {
+                    tr_debug("Backhaul bootstrap start failed");
+                } else {
+                    tr_debug("Backhaul bootstrap started");
+                }
+            } else if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DOWN) {
+                if (backhaul_interface_down() != 0) {
+                    // may happend when booting first time.
+                    tr_warning("Backhaul interface down failed");
+                } else {
+                    tr_debug("Backhaul interface is down");
+                }
+            }
+            break;
+
+        case ARM_LIB_TASKLET_INIT_EVENT:
+            print_appl_info();
+            br_tasklet_id = event->receiver;
+            thread_br_conn_handler_init();
+            eth_network_data_init();
+            backhaul_driver_init(borderrouter_backhaul_phy_status_cb);
+            mesh_network_up();
+            eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            break;
+
+        case ARM_LIB_SYSTEM_TIMER_EVENT:
+            eventOS_event_timer_cancel(event->event_id, event->receiver);
+
+            if (event->event_id == 9) {
+#ifdef MBED_CONF_APP_DEBUG_TRACE
+#if MBED_CONF_APP_DEBUG_TRACE == 1
+                arm_print_routing_table();
+                arm_print_neigh_cache();
+#endif
+#endif
+                eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+#endif // MBED_CONF_APP_MESH_MODE
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/cfg_parser.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <string.h>
+#include "cfg_parser.h"
+
+const char *cfg_string(conf_t *conf, const char *key, const char *default_value)
+{
+    for (; (conf && conf->name); conf++) {
+        if (0 == strcmp(conf->name, key)) {
+            return conf->svalue;
+        }
+    }
+    return default_value;
+}
+
+int cfg_int(conf_t *conf, const char *key, int default_value)
+{
+    for (; (conf && conf->name); conf++) {
+        if (0 == strcmp(conf->name, key)) {
+            return conf->ivalue;
+        }
+    }
+    return default_value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/cfg_parser.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+#ifndef CFG_PARSER_H
+#define CFG_PARSER_H
+
+typedef struct conf_t {
+    const char *name;
+    const char *svalue;
+    const int ivalue;
+} conf_t;
+
+#define STR_HELPER(x) #x
+#define STR(x) STR_HELPER(x)
+
+extern conf_t *global_config;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+const char *cfg_string(conf_t *conf, const char *key, const char *default_value);
+int cfg_int(conf_t *conf, const char *key, int default_value);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* CFG_PARSER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/mbedtls_thread_config.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#ifndef MBEDTLS_THREAD_CONFIG_H_
+#define MBEDTLS_THREAD_CONFIG_H_
+
+/* System support */
+#undef MBEDTLS_HAVE_ASM
+
+/* mbed TLS feature support */
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NIST_OPTIM
+#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#define MBEDTLS_SSL_EXPORT_KEYS
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+
+#define MBEDTLS_SHA256_SMALLER //reduce ROM usage ~1,4kB, perf hit 30%
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECJPAKE_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+
+/* Undef these when building to embedded platform */
+#undef MBEDTLS_NET_C
+#undef MBEDTLS_TIMING_C
+#undef MBEDTLS_HAVE_TIME
+#undef MBEDTLS_HAVE_TIME_DATE
+#undef MBEDTLS_FS_IO
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/* Save RAM at the expense of ROM */
+#define MBEDTLS_AES_ROM_TABLES
+
+/* Save RAM by adjusting to our exact needs */
+#define MBEDTLS_ECP_MAX_BITS             256
+#define MBEDTLS_MPI_MAX_SIZE              32 // 256 bits is 32 bytes
+
+/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
+
+/* Optimization. Remove all not needed stuff */
+/* For type TYPE_THREAD_SLEEPY_END_DEVICE
+#undef MBEDTLS_X509_USE_C
+#undef MBEDTLS_X509_CRT_PARSE_C
+#undef MBEDTLS_ASN1_PARSE_C
+#undef MBEDTLS_ASN1_WRITE_C
+#undef MBEDTLS_ECDH_C
+#undef MBEDTLS_PK_PARSE_C
+#undef MBEDTLS_PK_WRITE_C
+#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+#undef MBEDTLS_X509_CREATE_C
+#undef MBEDTLS_X509_CRT_WRITE_C
+*/
+
+/* For TYPE_THREAD_BORDER_ROUTER */
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+#define MBEDTLS_X509_CREATE_C
+#define MBEDTLS_X509_CRT_WRITE_C
+
+#undef MBEDTLS_X509_CRL_PARSE_C
+#undef MBEDTLS_SSL_SERVER_NAME_INDICATION
+#undef MBEDTLS_SELF_TEST
+#undef MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#undef MBEDTLS_BASE64_C
+#undef MBEDTLS_DEBUG_C
+#undef MBEDTLS_ECDSA_C
+#undef MBEDTLS_ERROR_C
+#undef MBEDTLS_GCM_C
+#undef MBEDTLS_PEM_PARSE_C
+#undef MBEDTLS_RSA_C
+#undef MBEDTLS_VERSION_C
+#undef MBEDTLS_CERTS_C
+#undef MBEDTLS_HMAC_DRBG_C
+#undef MBEDTLS_CIPHER_MODE_CBC
+#undef MBEDTLS_CIPHER_PADDING_PKCS7
+#undef MBEDTLS_ECDSA_DETERMINISTIC
+#undef MBEDTLS_SSL_SESSION_TICKETS
+#undef MBEDTLS_VERSION_FEATURES
+#undef MBEDTLS_X509_CHECK_KEY_USAGE
+#undef MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+#undef MBEDTLS_ERROR_STRERROR_DUMMY
+#undef MBEDTLS_SSL_ALPN
+#undef MBEDTLS_SSL_TICKET_C
+#undef MBEDTLS_HAVE_SSE2
+#undef MBEDTLS_PLATFORM_MEMORY
+#undef MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#undef MBEDTLS_DEPRECATED_WARNING
+#undef MBEDTLS_DEPRECATED_REMOVED
+#undef MBEDTLS_CAMELLIA_SMALL_MEMORY
+#undef MBEDTLS_CIPHER_MODE_CFB
+#undef MBEDTLS_CIPHER_MODE_CTR
+#undef MBEDTLS_CIPHER_NULL_CIPHER
+#undef MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#undef MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#undef MBEDTLS_CIPHER_PADDING_ZEROS
+#undef MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#undef MBEDTLS_PK_PARSE_EC_EXTENDED
+#undef MBEDTLS_GENPRIME
+#undef MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+#undef MBEDTLS_MEMORY_DEBUG
+#undef MBEDTLS_MEMORY_BACKTRACE
+#undef MBEDTLS_PK_RSA_ALT_SUPPORT
+#undef MBEDTLS_PKCS1_V15
+#undef MBEDTLS_PKCS1_V21
+#undef MBEDTLS_RSA_NO_CRT
+#undef MBEDTLS_SSL_AEAD_RANDOM_IV
+#undef MBEDTLS_RSA_NO_CRT
+#undef MBEDTLS_SSL_DEBUG_ALL
+#undef MBEDTLS_SSL_FALLBACK_SCSV
+#undef MBEDTLS_SSL_HW_RECORD_ACCEL
+#undef MBEDTLS_SSL_CBC_RECORD_SPLITTING
+#undef MBEDTLS_SSL_RENEGOTIATION
+#undef MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+#undef MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+#undef MBEDTLS_SSL_PROTO_TLS1
+#undef MBEDTLS_SSL_PROTO_TLS1_1
+#undef MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+#undef MBEDTLS_SSL_TRUNCATED_HMAC
+#undef MBEDTLS_THREADING_ALT
+#undef MBEDTLS_THREADING_PTHREAD
+#undef MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+#undef MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#undef MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#undef MBEDTLS_ZLIB_SUPPORT
+#undef MBEDTLS_AESNI_C
+#undef MBEDTLS_ARC4_C
+#undef MBEDTLS_BLOWFISH_C
+#undef MBEDTLS_CAMELLIA_C
+#undef MBEDTLS_DES_C
+#undef MBEDTLS_DHM_C
+#undef MBEDTLS_HAVEGE_C
+#undef MBEDTLS_MD2_C
+#undef MBEDTLS_MD4_C
+#undef MBEDTLS_MD5_C
+#undef MBEDTLS_MEMORY_BUFFER_ALLOC_C
+#undef MBEDTLS_PADLOCK_C
+#undef MBEDTLS_PEM_WRITE_C
+#undef MBEDTLS_PKCS5_C
+#undef MBEDTLS_PKCS11_C
+#undef MBEDTLS_PKCS12_C
+#undef MBEDTLS_PLATFORM_C
+#undef MBEDTLS_RIPEMD160_C
+#undef MBEDTLS_SHA1_C
+#undef MBEDTLS_SHA512_C
+#undef MBEDTLS_SSL_CACHE_C
+#undef MBEDTLS_THREADING_C
+#undef MBEDTLS_X509_CSR_PARSE_C
+#undef MBEDTLS_X509_CSR_WRITE_C
+#undef MBEDTLS_XTEA_C
+
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/static_6lowpan_config.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+
+#ifndef STATIC_6LOWPAN_CONFIG
+#define STATIC_6LOWPAN_CONFIG
+
+#include "cfg_parser.h"
+
+static const char psk_key[16] = MBED_CONF_APP_PSK_KEY;
+static const char tls_psk_key[16] = MBED_CONF_APP_TLS_PSK_KEY;
+
+static conf_t mbed_config[] = {
+    /* NAME, STRING_VALUE, INT_VALUE */
+    {"SECURITY_MODE", STR(MBED_CONF_APP_SECURITY_MODE), 0},
+    {"PANA_MODE", STR(MBED_CONF_APP_PANA_MODE), 0},
+    {"PSK_KEY", psk_key, 0},
+    {"PSK_KEY_ID", NULL, MBED_CONF_APP_PSK_KEY_ID},
+    {"PAN_ID", NULL, MBED_CONF_APP_PAN_ID},
+    {"NETWORK_ID", STR(MBED_CONF_APP_NETWORK_ID), 0},
+    {"PREFIX", STR(MBED_CONF_APP_PREFIX), 0},
+    {"BACKHAUL_PREFIX", STR(MBED_CONF_APP_BACKHAUL_PREFIX), 0},
+    {"BACKHAUL_DEFAULT_ROUTE", STR(MBED_CONF_APP_BACKHAUL_DEFAULT_ROUTE), 0},
+    {"BACKHAUL_NEXT_HOP", STR(MBED_CONF_APP_BACKHAUL_NEXT_HOP), 0},
+    {"RF_CHANNEL", NULL, MBED_CONF_APP_RF_CHANNEL},
+    {"RF_CHANNEL_PAGE", NULL, MBED_CONF_APP_RF_CHANNEL_PAGE},
+    {"RF_CHANNEL_MASK", NULL, MBED_CONF_APP_RF_CHANNEL_MASK},
+    {"RPL_INSTANCE_ID", NULL, MBED_CONF_APP_RPL_INSTANCE_ID},
+    {"RPL_IDOUBLINGS", NULL, MBED_CONF_APP_RPL_IDOUBLINGS},
+    {"RPL_K", NULL, MBED_CONF_APP_RPL_K},
+    {"RPL_MAX_RANK_INC", NULL, MBED_CONF_APP_RPL_MAX_RANK_INC},
+    {"RPL_MIN_HOP_RANK_INC", NULL, MBED_CONF_APP_RPL_MIN_HOP_RANK_INC},
+    {"RPL_IMIN", NULL, MBED_CONF_APP_RPL_IMIN},
+    {"RPL_DEFAULT_LIFETIME", NULL, MBED_CONF_APP_RPL_DEFAULT_LIFETIME},
+    {"RPL_LIFETIME_UNIT", NULL, MBED_CONF_APP_RPL_LIFETIME_UNIT},
+    {"RPL_PCS", NULL, MBED_CONF_APP_RPL_PCS},
+    {"RPL_OCP", NULL, MBED_CONF_APP_RPL_OCP},
+    {"RA_ROUTER_LIFETIME", NULL, MBED_CONF_APP_RA_ROUTER_LIFETIME},
+    {"BEACON_PROTOCOL_ID", NULL, MBED_CONF_APP_BEACON_PROTOCOL_ID},
+    {"TLS_PSK_KEY", tls_psk_key, 0},
+    {"TLS_PSK_KEY_ID", NULL, MBED_CONF_APP_TLS_PSK_KEY_ID},
+    {"BACKHAUL_DYNAMIC_BOOTSTRAP", NULL, MBED_CONF_APP_BACKHAUL_DYNAMIC_BOOTSTRAP},
+    {"SHORT_MAC_ADDRESS", NULL, MBED_CONF_APP_SHORT_MAC_ADDRESS},
+    {"MULTICAST_ADDR", STR(MBED_CONF_APP_MULTICAST_ADDR), 0},
+    {"PREFIX_FROM_BACKHAUL", NULL, MBED_CONF_APP_PREFIX_FROM_BACKHAUL},
+    /* Array must end on {NULL, NULL, 0} field */
+    {NULL, NULL, 0}
+};
+conf_t *global_config = mbed_config;
+
+#endif //STATIC_6LOWPAN_CONFIG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/thread_bbr_ext.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ */
+
+#ifndef _THREAD_BBR_EXT_
+#define _THREAD_BBR_EXT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if MBED_CONF_APP_THREAD_BBR_EXTENSION == 1
+
+#include "../../thread_bbr_extension/thread_bbr_extension.h"
+
+#else
+
+#define thread_bbr_extension_mesh_interface_updated_ntf(thread_interface_id);
+#define thread_bbr_extension_bb_interface_updated_ntf(bb_interface_id);
+#define thread_bbr_extension_start(thread_interface_id, bb_interface_id);
+
+#endif // MBED_CONF_APP_THREAD_BBR_EXTENSION
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _THREAD_BBR_EXT_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/thread_br_conn_handler.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <string.h>
+#include "net_interface.h"
+#include "mbed-trace/mbed_trace.h"
+#include "thread_border_router_api.h"
+#include "thread_br_conn_handler.h"
+#include "thread_dhcpv6_server.h"
+#include "borderrouter_helpers.h"
+#include "common_functions.h"
+#include "eventOS_event_timer.h"
+#include "thread_bbr_ext.h"
+
+#define TRACE_GROUP "TBRH"
+#define DHCP_SERVER_SHUTDOWN_TIMEOUT (100)
+
+typedef struct {
+    
+    uint8_t dhcp_prefix[16];
+    timeout_t *thread_dhcp_shutdown_timer;
+    uint8_t dhcp_prefix_len;
+    int8_t  thread_interface_id;
+    int8_t  eth_interface_id;
+    bool    eth_connection_ready;
+    bool    thread_connection_ready;
+    bool    dhcp_server_running;
+} thread_br_handler_t;
+
+static thread_br_handler_t thread_br_handler;
+static void thread_br_conn_handler_border_router_startup_attempt(void);
+static bool thread_br_conn_handler_default_route_enable(void);
+static void thread_br_conn_handler_dhcp_server_stop_cb(void *arg);
+static void thread_br_conn_handler_border_router_shutdown_request(void);
+
+
+void thread_br_conn_handler_init(void)
+{
+    thread_br_handler.eth_connection_ready = false;
+    thread_br_handler.thread_connection_ready = false;    
+    thread_br_handler.dhcp_server_running = false;
+    thread_br_handler.dhcp_prefix_len = 0;
+    thread_br_handler.thread_interface_id = -1;
+    thread_br_handler.eth_interface_id = -1;    
+    thread_br_handler.thread_dhcp_shutdown_timer = NULL;
+    memset(thread_br_handler.dhcp_prefix, 0, 16);
+}
+
+static void thread_br_conn_handler_border_router_startup_attempt(void)
+{
+    if (thread_br_handler.thread_dhcp_shutdown_timer != NULL) {
+        tr_debug("DHCP server already running, enable default_route");
+        eventOS_timeout_cancel(thread_br_handler.thread_dhcp_shutdown_timer);
+        thread_br_handler.thread_dhcp_shutdown_timer = NULL;
+    }
+
+    if (!thread_br_handler.eth_connection_ready) {
+        tr_debug("eth0 is down");
+        return;
+    } else if (!thread_br_handler.thread_connection_ready) {
+        tr_debug("mesh0 is down");
+        return;
+    }
+
+    if (thread_br_handler.dhcp_prefix_len == 0) {
+        //No prefix/prefix_len to start DHCP server
+        tr_error("DHCP server prefix length = 0");
+        return;
+    }
+
+    if (thread_br_handler.thread_interface_id == -1) {
+        tr_error("Thread interface ID not set");
+        return;
+    }
+
+    if (thread_br_handler.dhcp_server_running == true) {
+        // DHCP server is already running, enable default route
+        tr_debug("DHCP server already running, enable default_route");
+        thread_br_conn_handler_default_route_enable();
+        return;
+    }
+
+    int retcode = thread_dhcpv6_server_add(thread_br_handler.thread_interface_id, thread_br_handler.dhcp_prefix, 200, true);
+    if (retcode == 0) {
+        tr_debug("DHCP server started ");
+        if (thread_br_conn_handler_default_route_enable()) {
+            thread_br_handler.dhcp_server_running = true;
+            thread_bbr_extension_start(thread_br_handler.thread_interface_id, thread_br_handler.eth_interface_id);
+        } else {
+            tr_error("Failed to update DHCP default route");
+        }
+    } else {
+        tr_error("DHCP server start failed");
+    }
+}
+
+void thread_br_conn_handler_thread_connection_update(bool status)
+{
+    thread_br_handler.thread_connection_ready = status;
+    if (status) {
+        tr_debug("mesh0 connected");
+        thread_br_conn_handler_border_router_startup_attempt();
+    } else {
+        // Thread network down. Reset DHCP server back to original state
+        thread_br_handler.dhcp_server_running = false;
+        if (thread_br_handler.thread_dhcp_shutdown_timer != NULL) {
+            // cancel active shutdown timer
+            eventOS_timeout_cancel(thread_br_handler.thread_dhcp_shutdown_timer);
+            thread_br_handler.thread_dhcp_shutdown_timer = NULL;
+        }
+    }
+}
+
+
+void thread_br_conn_handler_ethernet_connection_update(bool status)
+{
+    thread_br_handler.eth_connection_ready = status;
+    if (status) {
+        tr_debug("Eth0 connected");
+        thread_br_conn_handler_border_router_startup_attempt();
+    } else {
+        // Ethernet connection down, request DHCP server shutdown
+        thread_br_conn_handler_border_router_shutdown_request();
+        tr_debug("Eth0 disconnected");
+    }
+}
+
+void thread_br_conn_handler_eth_ready()
+{    
+    uint8_t prefix_len = 64;
+    uint8_t global_address[16];
+    
+    if (0 == arm_net_address_get(thread_br_conn_handler_eth_interface_id_get(), ADDR_IPV6_GP, global_address)) {
+        tr_info("Ethernet (eth0) bootstrap ready. IP: %s", print_ipv6(global_address));
+    } else {
+        tr_warn("arm_net_address_get fail");
+    }
+    thread_br_handler.dhcp_prefix_len = prefix_len;
+    memset(thread_br_handler.dhcp_prefix, 0, 16);
+    memcpy(thread_br_handler.dhcp_prefix, global_address, prefix_len / 8);
+}
+
+static bool thread_br_conn_handler_default_route_enable(void)
+{
+    thread_border_router_info_t thread_border_router_info;
+    thread_border_router_info.Prf = 1;
+    thread_border_router_info.P_preferred = false;
+    thread_border_router_info.P_slaac = false;
+    thread_border_router_info.P_dhcp = true;
+    thread_border_router_info.P_configure = false;
+    thread_border_router_info.P_default_route = true;
+    thread_border_router_info.P_on_mesh = false;
+    thread_border_router_info.P_nd_dns = false;
+    thread_border_router_info.stableData = true;
+
+    if (thread_border_router_prefix_add(thread_br_handler.thread_interface_id, thread_br_handler.dhcp_prefix, thread_br_handler.dhcp_prefix_len, &thread_border_router_info) == 0) {
+        thread_border_router_publish(thread_br_handler.thread_interface_id);
+        tr_debug("Updated %s prefix", print_ipv6_prefix(thread_br_handler.dhcp_prefix, thread_br_handler.dhcp_prefix_len));
+        return true;
+    } else {
+        tr_error("Failed to enable default_route flag to prefix");
+        return false;
+    }
+}
+
+static void thread_br_conn_handler_dhcp_server_stop_cb(void *arg)
+{
+    (void)arg;
+    thread_br_handler.thread_dhcp_shutdown_timer = NULL;
+    thread_br_handler.dhcp_server_running = false;
+    thread_dhcpv6_server_delete(thread_br_handler.thread_interface_id, thread_br_handler.dhcp_prefix);
+    thread_border_router_publish(thread_br_handler.thread_interface_id);
+
+    tr_debug("DHCP server stop cb");
+    thread_br_handler.dhcp_prefix_len = 0;
+    memset(thread_br_handler.dhcp_prefix, 0, 16);
+}
+
+static void thread_br_conn_handler_border_router_shutdown_request(void)
+{
+    if (thread_br_handler.dhcp_server_running && thread_br_handler.thread_dhcp_shutdown_timer == NULL) {
+        tr_debug("DHCP server shutdown timer started");
+        thread_br_handler.thread_dhcp_shutdown_timer = eventOS_timeout_ms(thread_br_conn_handler_dhcp_server_stop_cb, DHCP_SERVER_SHUTDOWN_TIMEOUT, NULL);
+    }
+}
+
+void thread_br_conn_handler_thread_interface_id_set(int8_t interfaceId)
+{
+    thread_br_handler.thread_interface_id = interfaceId;
+    thread_bbr_extension_mesh_interface_updated_ntf(thread_br_handler.thread_interface_id);
+}
+
+int8_t thread_br_conn_handler_thread_interface_id_get(void)
+{
+    return thread_br_handler.thread_interface_id;
+}
+
+bool thread_br_conn_handler_eth_connection_status_get(void)
+{
+    return thread_br_handler.eth_connection_ready;
+}
+
+bool thread_br_conn_handler_thread_connection_status_get(void)
+{
+    return thread_br_handler.thread_connection_ready;
+}
+
+void thread_br_conn_handler_eth_interface_id_set(int8_t interfaceId)
+{
+    thread_br_handler.eth_interface_id = interfaceId;
+    thread_bbr_extension_bb_interface_updated_ntf(thread_br_handler.eth_interface_id);
+}
+
+int8_t thread_br_conn_handler_eth_interface_id_get(void)
+{
+    return thread_br_handler.eth_interface_id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/thread_br_conn_handler.h	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#ifndef thread_br_conn_handler_H_
+#define thread_br_conn_handler_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+
+void thread_br_conn_handler_init(void);
+void thread_br_conn_handler_thread_connection_update(bool status);
+void thread_br_conn_handler_ethernet_connection_update(bool status);
+
+// Tells that ethernet connection is ready and the prefix can be read and set.
+void thread_br_conn_handler_eth_ready(void);
+// Setters
+void   thread_br_conn_handler_thread_interface_id_set(int8_t interfaceId);
+void   thread_br_conn_handler_eth_interface_id_set(int8_t interfaceId);
+
+// Getters thread_br_conn_handler       
+bool   thread_br_conn_handler_eth_connection_status_get(void);
+bool   thread_br_conn_handler_thread_connection_status_get(void);
+int8_t thread_br_conn_handler_thread_interface_id_get(void);
+int8_t thread_br_conn_handler_eth_interface_id_get(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* thread_br_conn_handler_H_ */
+