diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h index 600e8d8d98..8280167ad7 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h @@ -17,6 +17,37 @@ #ifndef WISUNBORDERROUTER_H #define WISUNBORDERROUTER_H +/** + * \brief Struct br_information Border router dynamic information. + */ +typedef struct ws_br_info { + /** Address prefix given to devices in network set to 0 if not available*/ + uint8_t ipv6_prefix[8]; + /** IID of Border router */ + uint8_t ipv6_iid[8]; + /** Border router dodag id */ + uint8_t rpl_dodag_id[16]; + /** Border router instance identifier defined in RPL */ + uint8_t instance_id; + /** RPL version number */ + uint8_t version; + /** Timestamp of the the device. Can be used as version number*/ + uint64_t host_timestamp; + /** Amount of devices in the network. */ + uint16_t device_count; +} ws_br_info_t; + +/** + * \brief Struct br_route_info is parent child relation structure. + */ +typedef struct ws_br_route_info { + /** IID of target device + * Public IPv6 address can be formed by combining prefix + IID*/ + uint8_t target[8]; + /** IID of parent*/ + uint8_t parent[8]; +} ws_br_route_info_t; + /** Wi-SUN Border Router class * * Class can be used to start, stop and configure Wi-SUN Border Router. @@ -147,6 +178,35 @@ public: * */ mesh_error_t validate_pan_configuration(uint16_t pan_id); + /** + * \brief Get Wi-SUN Border Router information. + * + * Function reads RPL information from Border Router. + * Mesh interface must be initialized before calling this function. + * + * \param info_ptr Structure given to stack where information will be stored + * + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t info_get(ws_br_info_t *info_ptr); + + /** + * \brief Get Wi-SUN neighbor table information. + * + * Function reads Routing Table information from Border Router. + * Table is Parent child relation using the Global address IID of the devices. + * To get the full IPv6 address of the device, IPv6 = Global Prefix + IID. + * Mesh interface must be initialized before calling this function. + * + * \param table_ptr Application allocated memory block where routing table is written. + * \param table_len Length of the table allocated by application given as amount of entries. + * + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t routing_table_get(ws_br_route_info_t *table_ptr, uint16_t table_len); + private: int8_t _mesh_if_id = -1; diff --git a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunInterface.h b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunInterface.h index d23efc6bfb..ee203498e5 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunInterface.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunInterface.h @@ -19,6 +19,22 @@ #include "MeshInterfaceNanostack.h" +/** + * \brief Struct ws_rpl_info Wi-SUN router RPL information. + */ +typedef struct ws_rpl_info { + /** Address prefix given to devices in network set to 0 if not available*/ + uint8_t ipv6_prefix[8]; + /** IID of router */ + uint8_t ipv6_iid[8]; + /** Router dodag id */ + uint8_t rpl_dodag_id[16]; + /** Router instance identifier */ + uint8_t instance_id; + /** RPL version number */ + uint8_t version; +} ws_rpl_info_t; + /** Wi-SUN mesh network interface class * * Configure Nanostack to use Wi-SUN protocol. @@ -433,6 +449,19 @@ public: * */ mesh_error_t read_mac_statistics(mesh_mac_statistics_t *statistics); + /** + * \brief Get Wi-SUN Router information. + * + * Function reads RPL information from nanostack. + * Mesh interface must be initialized before calling this function. + * + * \param info_ptr Structure given to stack where information will be stored + * + * \return MESH_ERROR_NONE on success. + * \return MESH_ERROR_UNKNOWN in case of failure. + * */ + mesh_error_t info_get(ws_rpl_info_t *info_ptr); + protected: Nanostack::WisunInterface *get_interface() const; virtual nsapi_error_t do_initialize(); diff --git a/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp index d5fcf624ea..4d05308763 100644 --- a/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp +++ b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp @@ -153,3 +153,41 @@ mesh_error_t WisunBorderRouter::validate_pan_configuration(uint16_t pan_id) return MESH_ERROR_NONE; } + +mesh_error_t WisunBorderRouter::info_get(ws_br_info_t *info_ptr) +{ + bbr_information_t bbr_info = {0}; + + if (info_ptr == NULL) { + return MESH_ERROR_PARAM; + } + + int status = ws_bbr_info_get(_mesh_if_id, &bbr_info); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + info_ptr->device_count = bbr_info.devices_in_network; + info_ptr->host_timestamp = bbr_info.timestamp; + info_ptr->instance_id = bbr_info.instance_id; + info_ptr->version = bbr_info.version; + memcpy(info_ptr->rpl_dodag_id, bbr_info.dodag_id, 16); + memcpy(info_ptr->ipv6_prefix, bbr_info.prefix, 8); + memcpy(info_ptr->ipv6_iid, bbr_info.IID, 8); + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::routing_table_get(ws_br_route_info_t *table_ptr, uint16_t table_len) +{ + if (table_ptr == NULL) { + return MESH_ERROR_PARAM; + } + + int status = ws_bbr_routing_table_get(_mesh_if_id, (bbr_route_info_t *)table_ptr, table_len); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} diff --git a/features/nanostack/mbed-mesh-api/source/WisunInterface.cpp b/features/nanostack/mbed-mesh-api/source/WisunInterface.cpp index b130131423..1190fdf408 100644 --- a/features/nanostack/mbed-mesh-api/source/WisunInterface.cpp +++ b/features/nanostack/mbed-mesh-api/source/WisunInterface.cpp @@ -24,6 +24,8 @@ #include "fhss_api.h" #include "fhss_config.h" #include "ws_management_api.h" +#include "net_rpl.h" +#include "net_interface.h" #include "ns_trace.h" #define TRACE_GROUP "WSIn" @@ -542,6 +544,60 @@ mesh_error_t WisunInterface::read_mac_statistics(mesh_mac_statistics_t *statisti return ret_val; } +mesh_error_t WisunInterface::info_get(ws_rpl_info_t *info_ptr) +{ + if (info_ptr == NULL) { + return MESH_ERROR_PARAM; + } + + rpl_dodag_info_t dodag_ptr = {0}; + uint8_t global_address[16] = {0}; + uint8_t rpl_instance_count; + uint8_t instance_id_list[10]; + uint8_t instance_id = RPL_INSTANCE_LOCAL; + uint8_t instance_id_new; + uint8_t instance_index; + rpl_instance_count = rpl_instance_list_read(&instance_id_list[0], sizeof(instance_id_list)); + + if (rpl_instance_count > 10) { + return MESH_ERROR_UNKNOWN; + } + + /* Find lowest global instance ID (assumption: RPL instance with lowest instance ID has + most generic routing rule and its rank should be indicated in beacon) */ + for (instance_index = 0; instance_index < rpl_instance_count; instance_index++) { + instance_id_new = instance_id_list[instance_index]; + + if ((instance_id_new & RPL_INSTANCE_LOCAL) == RPL_INSTANCE_LOCAL) { + break; + } else { + if (instance_id_new < instance_id) { + instance_id = instance_id_new; + } + } + } + + if (instance_id == RPL_INSTANCE_LOCAL) { + return MESH_ERROR_UNKNOWN; + } + + if (!rpl_read_dodag_info(&dodag_ptr, instance_id)) { + return MESH_ERROR_UNKNOWN; + } + + if (arm_net_address_get(get_interface_id(), ADDR_IPV6_GP, global_address) != 0) { + // No global prefix available, Nothing to do. + } + + info_ptr->instance_id = dodag_ptr.instance_id; + info_ptr->version = dodag_ptr.version_num; + memcpy(info_ptr->rpl_dodag_id, dodag_ptr.dodag_id, 16); + memcpy(info_ptr->ipv6_prefix, global_address, 8); + memcpy(info_ptr->ipv6_iid, global_address + 8, 8); + + return MESH_ERROR_NONE; +} + #define WISUN 0x2345 #if MBED_CONF_NSAPI_DEFAULT_MESH_TYPE == WISUN && DEVICE_802_15_4_PHY MBED_WEAK MeshInterface *MeshInterface::get_target_default_instance()