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 cc1eb4c629..bd6e340050 100644 --- a/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h +++ b/features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h @@ -50,6 +50,18 @@ typedef struct ws_br_route_info { uint8_t parent[8]; } ws_br_route_info_t; +/** + * \brief Struct ws_br_radius_timing_t is RADIUS timing configuration structure. + */ +typedef struct ws_br_radius_timing { + /** RADIUS retry trickle timer Imin; in 100ms units; range 1-1200; default 20 (2 seconds) */ + uint16_t radius_retry_imin; + /** RADIUS retry trickle timer Imax; in 100ms units; range 1-1200; default 30 (3 seconds) */ + uint16_t radius_retry_imax; + /** RADIUS retry trickle count; default 3 */ + uint8_t radius_retry_count; +} ws_br_radius_timing_t; + /** Wi-SUN Border Router class * * Class can be used to start, stop and configure Wi-SUN Border Router. @@ -273,17 +285,55 @@ public: * */ mesh_error_t set_dns_query_result(SocketAddress *address, char *domain_name); + /** + * \brief Set Wi-SUN RADIUS timing parameters. + * + * Function sets RADIUS timing parameters to Border Router. For RADIUS retry trickle timer default + * settings are that the first retry is done between 1 to 3 seconds after the initial attempt and + * all retries are done in maximum in 9 seconds. + * + * \param timing Timing parameters. + * \return MESH_ERROR_NONE on success. + * \return error value in case of failure. + * */ + mesh_error_t set_radius_timing(ws_br_radius_timing_t *timing); + + /** + * \brief Get Wi-SUN RADIUS timing parameters. + * + * Function gets RADIUS timing parameters from Border Router. + * + * \param timing Timing parameters. + * \return MESH_ERROR_NONE on success. + * \return error value in case of failure. + * */ + mesh_error_t get_radius_timing(ws_br_radius_timing_t *timing); + + /** + * \brief Validate Wi-SUN RADIUS timing parameters. + * + * Function validates RADIUS timing parameters on Border Router. + * + * \param timing Timing parameters. + * \return MESH_ERROR_NONE on success. + * \return error value in case of failure. + * */ + mesh_error_t validate_radius_timing(ws_br_radius_timing_t *timing); + private: mesh_error_t configure(); mesh_error_t apply_configuration(int8_t mesh_if_id); mesh_error_t set_bbr_radius_address(void); - mesh_error_t set_bbr_radius_shared_secret(); + mesh_error_t set_bbr_radius_shared_secret(void); + mesh_error_t set_bbr_radius_timing(void); char _radius_ipv6_addr[40]; + ws_br_radius_timing_t _radius_timing; char *_shared_secret = NULL; uint16_t _shared_secret_len = 0; int8_t _mesh_if_id = -1; bool _radius_ipv6_addr_set = false; bool _configured = false; + bool _radius_timing_set = false; }; #endif diff --git a/features/nanostack/mbed-mesh-api/mbed_lib.json b/features/nanostack/mbed-mesh-api/mbed_lib.json index 7d14d85833..2bc76a35fd 100644 --- a/features/nanostack/mbed-mesh-api/mbed_lib.json +++ b/features/nanostack/mbed-mesh-api/mbed_lib.json @@ -207,7 +207,19 @@ "radius-shared-secret-len": { "help": "RADIUS shared secret length; If length is not defined, strlen() is used to determine RADIUS shared secret length", "value": null - } + }, + "radius-retry-imin": { + "help": "RADIUS retry trickle timer Imin; in 100ms units; range 1-1200; default 20 (2 seconds)", + "value": 20 + }, + "radius-retry-imax": { + "help": "RADIUS retry trickle timer Imax; in 100ms units; range 1-1200; default 30 (3 seconds)", + "value": 30 + }, + "radius-retry-count": { + "help": "RADIUS retry trickle count; default 3", + "value": 3 + } }, "target_overrides": { "KW24D": { diff --git a/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp index 2e5e381f30..3b98c9cfc4 100644 --- a/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp +++ b/features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp @@ -109,7 +109,7 @@ void WisunBorderRouter::stop() mesh_error_t WisunBorderRouter::configure() { -#if defined(MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET) || defined(MBED_CONF_MBED_MESH_API_RADIUS_SERVER_IPV6_ADDRESS) +#if defined(MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET) || defined(MBED_CONF_MBED_MESH_API_RADIUS_SERVER_IPV6_ADDRESS) || defined(MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMIN) mesh_error_t status; #endif @@ -139,23 +139,40 @@ mesh_error_t WisunBorderRouter::configure() if (status != MESH_ERROR_NONE) { tr_error("Failed to set RADIUS server IPv6 address!"); } + +#if defined(MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMIN) || defined(MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMAX) || defined(MBED_CONF_MBED_MESH_API_RADIUS_RETRY_COUNT) + ws_br_radius_timing_t timing { + .radius_retry_imin = MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMIN, + .radius_retry_imax = MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMAX, + .radius_retry_count = MBED_CONF_MBED_MESH_API_RADIUS_RETRY_COUNT + }; + status = set_radius_timing(&timing); + if (status != MESH_ERROR_NONE) { + tr_error("Failed to set RADIUS timing parameters!"); + } #endif +#endif return MESH_ERROR_NONE; } mesh_error_t WisunBorderRouter::apply_configuration(int8_t mesh_if_id) { + configure(); + mesh_error_t status = set_bbr_radius_address(); if (status != MESH_ERROR_NONE) { tr_error("Failed to apply RADIUS server IPv6 address!"); - return MESH_ERROR_PARAM; } status = set_bbr_radius_shared_secret(); if (status != MESH_ERROR_NONE) { tr_error("Failed to apply RADIUS server IPv6 address!"); - return MESH_ERROR_PARAM; + } + + status = set_bbr_radius_timing(); + if (status != MESH_ERROR_NONE) { + tr_error("Failed to apply RADIUS timing parameters!"); } return MESH_ERROR_NONE; @@ -328,7 +345,7 @@ mesh_error_t WisunBorderRouter::set_radius_shared_secret(uint16_t shared_secret_ return set_bbr_radius_shared_secret(); } -mesh_error_t WisunBorderRouter::set_bbr_radius_shared_secret() +mesh_error_t WisunBorderRouter::set_bbr_radius_shared_secret(void) { if (_shared_secret_len == 0 || _shared_secret == NULL) { return MESH_ERROR_UNKNOWN; @@ -372,3 +389,83 @@ mesh_error_t WisunBorderRouter::set_dns_query_result(SocketAddress *address, cha return MESH_ERROR_UNKNOWN; } + +mesh_error_t WisunBorderRouter::set_radius_timing(ws_br_radius_timing_t *timing) +{ + if (timing == NULL) { + return MESH_ERROR_PARAM; + } + + if (validate_radius_timing(timing) != MESH_ERROR_NONE) { + return MESH_ERROR_PARAM; + } + + _radius_timing = *timing; + _radius_timing_set = true; + + return set_bbr_radius_timing(); +} + +mesh_error_t WisunBorderRouter::set_bbr_radius_timing(void) +{ + if (!_radius_timing_set) { + return MESH_ERROR_NONE; + } + + bbr_radius_timing_t bbr_timing = { + .radius_retry_imin = _radius_timing.radius_retry_imin, + .radius_retry_imax = _radius_timing.radius_retry_imax, + .radius_retry_count = _radius_timing.radius_retry_count + }; + + int status = ws_bbr_radius_timing_set(_mesh_if_id, &bbr_timing); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::get_radius_timing(ws_br_radius_timing_t *timing) +{ + if (timing == NULL) { + return MESH_ERROR_PARAM; + } + + if (_radius_timing_set) { + *timing = _radius_timing; + return MESH_ERROR_NONE; + } + + bbr_radius_timing_t bbr_timing; + int status = ws_bbr_radius_timing_get(_mesh_if_id, &bbr_timing); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + timing->radius_retry_imin = bbr_timing.radius_retry_imin; + timing->radius_retry_imax = bbr_timing.radius_retry_imax; + timing->radius_retry_count = bbr_timing.radius_retry_count; + + return MESH_ERROR_NONE; +} + +mesh_error_t WisunBorderRouter::validate_radius_timing(ws_br_radius_timing_t *timing) +{ + if (timing == NULL) { + return MESH_ERROR_PARAM; + } + + bbr_radius_timing_t bbr_timing = { + .radius_retry_imin = timing->radius_retry_imin, + .radius_retry_imax = timing->radius_retry_imax, + .radius_retry_count = timing->radius_retry_count + }; + + int status = ws_bbr_radius_timing_validate(_mesh_if_id, &bbr_timing); + if (status != 0) { + return MESH_ERROR_UNKNOWN; + } + + return MESH_ERROR_NONE; +}