diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h index 972810fa6a..51d4ca1431 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h @@ -82,6 +82,8 @@ protected: }; class Nanostack::MeshInterface : public Nanostack::Interface { +public: + char *get_interface_name(char *buf); protected: MeshInterface(NanostackRfPhy &phy) : Interface(phy) { } NanostackRfPhy &get_phy() const diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackEthernetInterface.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackEthernetInterface.h index f58b5393ad..da2c9d4881 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackEthernetInterface.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackEthernetInterface.h @@ -29,6 +29,7 @@ public: bool blocking = true); virtual nsapi_error_t bringdown(); + char *get_interface_name(char *buf); private: friend class Nanostack; friend class NanostackEthernetInterface; diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackPPPInterface.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackPPPInterface.h index f60f45ae3c..735ef52d14 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackPPPInterface.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackPPPInterface.h @@ -32,6 +32,7 @@ public: typedef mbed::Callback link_state_cb_t; virtual void set_link_state_changed_callback(link_state_cb_t link_state_cb); + char *get_interface_name(char *buf); private: friend class Nanostack; PPPInterface(NanostackPhy &phy) : Interface(phy), link_state_up(false), enet_tasklet_connected(false) {} diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h new file mode 100644 index 0000000000..600e8d8d98 --- /dev/null +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WISUNBORDERROUTER_H +#define WISUNBORDERROUTER_H + +/** Wi-SUN Border Router class + * + * Class can be used to start, stop and configure Wi-SUN Border Router. + */ +class WisunBorderRouter { +public: + + /** Create WisunBorderRouter + * + * */ + WisunBorderRouter() { } + + /** + * \brief Start Wi-SUN Border Router + * + * Starts Wi-SUN Border Router and routing between the mesh and backbone interfaces. Network interfaces + * must be initialized and connected before calling the start. Backbone interface can be either Ethernet + * (EMAC) or Cellular. + * + * \param mesh_if Wi-SUN mesh network interface + * \param backbone_if Backbone network interface + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t start(NetworkInterface *mesh_if, NetworkInterface *backbone_if); + + /** + * \brief Start Wi-SUN Border Router + * + * Starts Wi-SUN Border Router and routing between the mesh and backbone interfaces. Mesh network interface + * must be initialized and connected before calling the start. Backbone OnboardNetworkStack::Interface must + * be brought up before calling the start. Backbone interface can be either Ethernet (EMAC) or Cellular (PPP). + * + * \param mesh_if Wi-SUN mesh network interface + * \param backbone_if Backbone OnboardNetworkStack::Interface interface + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t start(NetworkInterface *mesh_if, OnboardNetworkStack::Interface *backbone_if); + + /** + * \brief Stop Wi-SUN Border Router + * + * Stops Wi-SUN Border Router. + * + * */ + void stop(); + + /** + * \brief Set Wi-SUN RPL DIO trickle parameters. + * + * Function stores new parameters to Border Router and uses them when mesh interface connect() is called + * next time. If device is already connected to the Wi-SUN network then device will restart Wi-SUN network after + * changing the RPL DIO trickle parameters. Mesh interface must be initialized before calling this + * function. + * + * \param dio_interval_min DIO trickle timer Imin parameter. Use 0x00 to use leave parameter unchanged. + * \param dio_interval_doublings DIO trickle timer Imax parameter as doublings of Imin. Use 0x00 to use leave parameter unchanged. + * \param dio_redundancy_constant DIO trickle timer redundancy constant. Use 0xff to use leave parameter unchanged. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t set_rpl_parameters(uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant); + + /** + * \brief Get Wi-SUN RPL DIO trickle parameters. + * + * Function reads DIO trickle timer Imin, DIO trickle timer Imax and DIO trickle timer redundancy + * constant from Border Router. Mesh interface must be initialized before calling this function. + * + * \param dio_interval_min DIO trickle timer Imin parameter. + * \param dio_interval_doublings DIO trickle timer Imax parameter as doublings of Imin. + * \param dio_redundancy_constant DIO trickle timer redundancy constant. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t get_rpl_parameters(uint8_t *dio_interval_min, uint8_t *dio_interval_doublings, uint8_t *dio_redundancy_constant); + + /** + * \brief Validate Wi-SUN RPL DIO trickle parameters. + * + * Function validates DIO trickle timer Imin, DIO trickle timer Imax and DIO trickle timer redundancy + * constant. Function can be used to test that values that will be used on set function are valid. + * Mesh interface must be initialized before the calling this function. + * + * \param dio_interval_min DIO trickle timer Imin parameter. + * \param dio_interval_doublings DIO trickle timer Imax parameter as doublings of Imin. + * \param dio_redundancy_constant DIO trickle timer redundancy constant. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t validate_rpl_parameters(uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant); + + /** + * \brief Set Wi-SUN PAN configuration parameters. + * + * Function stores new parameters to Border Router and uses them when mesh interface connect() is called + * next time. If device is already connected to the Wi-SUN network then device will restart Wi-SUN network after + * changing the PAN configuration parameters. Mesh interface must be initialized before calling this + * function. + * + * \param pan_id PAN ID. 0xffff will generate the PAN ID on the mesh interface connect() call if not already generated. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t set_pan_configuration(uint16_t pan_id); + + /** + * \brief Get Wi-SUN PAN configuration parameters. + * + * Function reads PAN ID from Border Router. Mesh interface must be initialized before calling this function. + * + * \param pan_id PAN ID. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t get_pan_configuration(uint16_t *pan_id); + + /** + * \brief Validate Wi-SUN PAN configuration parameters. + * + * Function validates PAN ID. Function can be used to test that values that will be used on set function are valid. + * Mesh interface must be initialized before calling this function. + * + * \param pan_id PAN ID. + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t validate_pan_configuration(uint16_t pan_id); + +private: + int8_t _mesh_if_id = -1; + +}; + +#endif diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/mesh_interface_types.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/mesh_interface_types.h index 64c753945c..b63c25713b 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/mesh_interface_types.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/mesh_interface_types.h @@ -66,10 +66,10 @@ typedef enum { * Mesh channel function */ typedef enum { - MESH_CHANNEL_FUNCTION_FIXED = 0x00, - MESH_CHANNEL_FUNCTION_TR51CF, - MESH_CHANNEL_FUNCTION_DH1CF, - MESH_CHANNEL_FUNCTION_VENDOR_DEFINED + MESH_CHANNEL_FUNCTION_FIXED = 0x00, + MESH_CHANNEL_FUNCTION_TR51CF, + MESH_CHANNEL_FUNCTION_DH1CF, + MESH_CHANNEL_FUNCTION_VENDOR_DEFINED } mesh_channel_function_t; /** diff --git a/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp b/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp index af919a39e3..015828265b 100644 --- a/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp +++ b/features/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp @@ -124,6 +124,15 @@ int InterfaceNanostack::disconnect() return _interface->bringdown(); } +char *Nanostack::MeshInterface::get_interface_name(char *buf) +{ + if (interface_id < 0) { + return NULL; + } + sprintf(buf, "MES%d", interface_id); + return buf; +}; + nsapi_error_t MeshInterfaceNanostack::initialize(NanostackRfPhy *phy) { if (_phy && phy && _phy != phy) { diff --git a/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp b/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp index 83c5af5d0d..3ad3e3fa39 100644 --- a/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp @@ -120,3 +120,12 @@ nsapi_error_t Nanostack::EthernetInterface::bringdown() } return NSAPI_ERROR_OK; } + +char *Nanostack::EthernetInterface::get_interface_name(char *buf) +{ + if (interface_id < 0) { + return NULL; + } + sprintf(buf, "ETH%d", interface_id); + return buf; +}; diff --git a/features/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp b/features/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp index 85c2b3a3f9..8a19090cd8 100644 --- a/features/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp @@ -181,6 +181,15 @@ void Nanostack::PPPInterface::set_link_state_changed_callback(link_state_cb_t ne link_state_cb = new_link_state_cb; } +char *Nanostack::PPPInterface::get_interface_name(char *buf) +{ + if (interface_id < 0) { + return NULL; + } + sprintf(buf, "PPP%d", interface_id); + return buf; +}; + // GAH! no handles on the callback. Force a single interface static PPPPhy *single_phy; diff --git a/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp new file mode 100644 index 0000000000..d5fcf624ea --- /dev/null +++ b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WisunInterface.h" +#include "ns_trace.h" +#include "WisunBorderRouter.h" +#include "MeshInterfaceNanostack.h" + +extern "C" { +#include "ws_bbr_api.h" +} + +#define TRACE_GROUP "WSBR" + +mesh_error_t WisunBorderRouter::start(NetworkInterface *mesh_if, NetworkInterface *backbone_if) +{ + if (mesh_if == NULL || backbone_if == NULL) { + return MESH_ERROR_PARAM; + } + + InterfaceNanostack *nano_mesh_if = reinterpret_cast(mesh_if); + int8_t mesh_if_id = nano_mesh_if->get_interface_id(); + if (mesh_if_id < 0) { + return MESH_ERROR_UNKNOWN; + } + _mesh_if_id = mesh_if_id; + + char backbone_if_name[7] = {0}; + if (backbone_if->get_interface_name(backbone_if_name) == NULL) { + return MESH_ERROR_UNKNOWN; + } + + if (strlen((char *) &backbone_if_name) < 4) { + return MESH_ERROR_UNKNOWN; + } + + int backbone_if_id = atoi(&backbone_if_name[3]); + if (backbone_if_id < 0) { + return MESH_ERROR_UNKNOWN; + } + + int ret = ws_bbr_start(mesh_if_id, backbone_if_id); + if (ret < 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::start(NetworkInterface *mesh_if, OnboardNetworkStack::Interface *backbone_if) +{ + InterfaceNanostack *nano_mesh_if = reinterpret_cast(mesh_if); + int8_t mesh_if_id = nano_mesh_if->get_interface_id(); + if (mesh_if_id < 0) { + return MESH_ERROR_UNKNOWN; + } + _mesh_if_id = mesh_if_id; + + Nanostack::Interface *nano_backbone_if = static_cast(backbone_if); + int8_t backbone_if_id = nano_backbone_if->get_interface_id(); + if (backbone_if_id < 0) { + return MESH_ERROR_UNKNOWN; + } + + int ret = ws_bbr_start(mesh_if_id, backbone_if_id); + if (ret < 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +void WisunBorderRouter::stop() +{ + if (_mesh_if_id < 0) { + return; + } + + ws_bbr_stop(_mesh_if_id); + + _mesh_if_id = -1; +} + +mesh_error_t WisunBorderRouter::set_rpl_parameters(uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant) +{ + int status = ws_bbr_rpl_parameters_set(_mesh_if_id, dio_interval_min, dio_interval_doublings, dio_redundancy_constant); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::get_rpl_parameters(uint8_t *dio_interval_min, uint8_t *dio_interval_doublings, uint8_t *dio_redundancy_constant) +{ + int status = ws_bbr_rpl_parameters_get(_mesh_if_id, dio_interval_min, dio_interval_doublings, dio_redundancy_constant); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::validate_rpl_parameters(uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant) +{ + int status = ws_bbr_rpl_parameters_validate(_mesh_if_id, dio_interval_min, dio_interval_doublings, dio_redundancy_constant); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::set_pan_configuration(uint16_t pan_id) +{ + int status = ws_bbr_pan_configuration_set(_mesh_if_id, pan_id); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::get_pan_configuration(uint16_t *pan_id) +{ + int status = ws_bbr_pan_configuration_get(_mesh_if_id, pan_id); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::validate_pan_configuration(uint16_t pan_id) +{ + int status = ws_bbr_pan_configuration_validate(_mesh_if_id, pan_id); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +}