From 0ca91df5905111270a6ec1343be5c726c97fe571 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Nov 2018 14:17:48 +0200 Subject: [PATCH 01/12] Squashed 'features/frameworks/nanostack-libservice/' changes from 5eb2f3f..bb56e37 bb56e37 Merge pull request #76 from ARMmbed/compiler_warning_fixes a7b0de2 common_functions: remove use of "byte" as variable name fb84db0 ns_types.h: fix the GCC warning with "-Wundef" and missing __STDC_VER git-subtree-dir: features/frameworks/nanostack-libservice git-subtree-split: bb56e375bab77aa49dbddd4abb53b6832043aa99 --- mbed-client-libservice/common_functions.h | 38 +++++++++++------------ mbed-client-libservice/ns_types.h | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/mbed-client-libservice/common_functions.h b/mbed-client-libservice/common_functions.h index 54c8aa2c0cb..c2f529b8b27 100644 --- a/mbed-client-libservice/common_functions.h +++ b/mbed-client-libservice/common_functions.h @@ -186,31 +186,31 @@ NS_INLINE uint16_t common_read_16_bit_inverse(const uint8_t data_buf[__static 2] /* * Count bits in a byte * - * \param byte byte to inspect + * \param value byte to inspect * * \return number of 1-bits in byte */ -NS_INLINE uint_fast8_t common_count_bits(uint8_t byte); +NS_INLINE uint_fast8_t common_count_bits(uint8_t value); /* * Count leading zeros in a byte * * \deprecated Use common_count_leading_zeros_8 * - * \param byte byte to inspect + * \param value byte to inspect * * \return number of leading zeros in byte (0-8) */ -NS_INLINE uint_fast8_t common_count_leading_zeros(uint8_t byte); +NS_INLINE uint_fast8_t common_count_leading_zeros(uint8_t value); /* * Count leading zeros in a byte * - * \param byte byte to inspect + * \param value byte to inspect * * \return number of leading zeros in byte (0-8) */ -NS_INLINE uint_fast8_t common_count_leading_zeros_8(uint8_t byte); +NS_INLINE uint_fast8_t common_count_leading_zeros_8(uint8_t value); /* * Count leading zeros in a 16-bit value @@ -490,11 +490,11 @@ COMMON_FUNCTIONS_FN uint16_t common_read_16_bit_inverse(const uint8_t data_buf[_ return temp_16; } -COMMON_FUNCTIONS_FN uint_fast8_t common_count_bits(uint8_t byte) +COMMON_FUNCTIONS_FN uint_fast8_t common_count_bits(uint8_t value) { /* First step sets each bit pair to be count of bits (00,01,10) */ /* [00-00 = 00, 01-00 = 01, 10-01 = 01, 11-01 = 10] */ - uint_fast8_t count = byte - ((byte >> 1) & 0x55); + uint_fast8_t count = value - ((value >> 1) & 0x55); /* Add bit pairs to make each nibble contain count of bits (0-4) */ count = (count & 0x33) + ((count >> 2) & 0x33); /* Final result is sum of nibbles (0-8) */ @@ -502,31 +502,31 @@ COMMON_FUNCTIONS_FN uint_fast8_t common_count_bits(uint8_t byte) return count; } -COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros(uint8_t byte) +COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros(uint8_t value) { - return common_count_leading_zeros_8(byte); + return common_count_leading_zeros_8(value); } -COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t byte) +COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t value) { #ifdef __CC_ARM - return byte ? __clz((unsigned int) byte << 24) : 8; + return value ? __clz((unsigned int) value << 24) : 8; #elif defined __GNUC__ - return byte ? __builtin_clz((unsigned int) byte << 24) : 8; + return value ? __builtin_clz((unsigned int) value << 24) : 8; #else uint_fast8_t cnt = 0; - if (byte == 0) { + if (value == 0) { return 8; } - if ((byte & 0xF0) == 0) { - byte <<= 4; + if ((value & 0xF0) == 0) { + value <<= 4; cnt += 4; } - if ((byte & 0xC0) == 0) { - byte <<= 2; + if ((value & 0xC0) == 0) { + value <<= 2; cnt += 2; } - if ((byte & 0x80) == 0) { + if ((value & 0x80) == 0) { cnt += 1; } diff --git a/mbed-client-libservice/ns_types.h b/mbed-client-libservice/ns_types.h index 61b31f3dc06..296c2d03967 100644 --- a/mbed-client-libservice/ns_types.h +++ b/mbed-client-libservice/ns_types.h @@ -120,7 +120,7 @@ typedef int_fast32_t int_fast24_t; #if defined __CC_ARM || defined __TASKING__ #define alignas(n) __align(n) #define __alignas_is_defined 1 -#elif (__STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L) +#elif (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L) #include #elif defined __GNUC__ #define alignas(n) __attribute__((__aligned__(n))) From 7fab5abace6aa9d6fc6c335fa6fcab15a108d646 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Nov 2018 14:21:34 +0200 Subject: [PATCH 02/12] Squashed 'features/frameworks/mbed-trace/' changes from 6df2572..9eaf0d1 9eaf0d1 Add documentation on how to change trace level. (#85) git-subtree-dir: features/frameworks/mbed-trace git-subtree-split: 9eaf0d146f0804a700aafbbd896f02c1acaaae66 --- README.md | 37 +++++++++++++++++++++++++++++++++++++ mbed_lib.json | 6 ++++++ test/Test.cpp | 7 +++++++ 3 files changed, 50 insertions(+) diff --git a/README.md b/README.md index d798d01cab1..3f75420706e 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,43 @@ Set the output function, `printf` by default: mbed_trace_print_function_set(printf) ``` +### Tracing level + +Run time tracing level is set using `mbed_trace_set_config()` function. Possible levels and examples how to set them is presented below. + +```c +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL); +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_DEBUG); // (same as ALL) +mbed_trace_config_set(TRACE_ACTIVE_LEVEL_INFO); +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_WARN); +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ERROR); +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_CMD); +//mbed_trace_config_set(TRACE_ACTIVE_LEVEL_NONE); +``` + +Build time optimization can be done with `MBED_TRACE_MAX_LEVEL` definition. Setting max level to `TRACE_LEVEL_DEBUG` includes all traces to the build. Setting max level to `TRACE_LEVEL_INFO` includes all but `tr_debug()` traces to the build. Other maximum tracing levels follow the same behavior and no messages above the selected level are included in the build. + +```c +#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG +#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO +#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_WARN +#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_ERROR +#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_CMD +``` + +In Mbed OS, the build time maximum tracing level can be set through `mbed_app.json` as shown below. + +``` +{ + "target_overrides":{ + "*":{ + "mbed-trace.enable": true, + "mbed-trace.max-level": "TRACE_LEVEL_INFO" + } + } +} +``` + ### Helping functions The purpose of the helping functions is to provide simple conversions, for example from an array to C string, so that you can print everything to single trace line. They must be called inside the actual trace calls, for example: diff --git a/mbed_lib.json b/mbed_lib.json index f51343717f4..cb1dadf366c 100644 --- a/mbed_lib.json +++ b/mbed_lib.json @@ -5,6 +5,12 @@ "help": "Used to globally enable traces.", "value": null }, + "max-level": { + "help": "This flag is used to optimize the code size. For example, setting trace optimization level to TRACE_LEVEL_INFO will define all tr_debug() macros empty, which reduces the binary size. The possible optimization levels are TRACE_LEVEL_DEBUG, TRACE_LEVEL_INFO, TRACE_LEVEL_WARN, TRACE_LEVEL_ERROR and TRACE_LEVEL_CMD. To set the output tracing level, please use mbed_trace_config_set(TRACE_ACTIVE_LEVEL_INFO). The possible tracing levels for mbed_trace_config_set() are TRACE_ACTIVE_LEVEL_ALL, TRACE_ACTIVE_LEVEL_DEBUG (same as ALL), TRACE_ACTIVE_LEVEL_INFO, TRACE_ACTIVE_LEVEL_WARN, TRACE_ACTIVE_LEVEL_ERROR, TRACE_ACTIVE_LEVEL_CMD and TRACE_LEVEL_NONE.", + "value": null, + "macro_name": "MBED_TRACE_MAX_LEVEL" + + }, "fea-ipv6": { "help": "Used to globally disable ipv6 tracing features.", "value": null diff --git a/test/Test.cpp b/test/Test.cpp index bd0426130ee..845d9a49c67 100644 --- a/test/Test.cpp +++ b/test/Test.cpp @@ -239,6 +239,9 @@ TEST(trace, config_change) TEST(trace, active_level_all_color) { mbed_trace_config_set(TRACE_MODE_COLOR|TRACE_ACTIVE_LEVEL_ALL); + // unknown debug level + mbed_tracef(TRACE_LEVEL_DEBUG+1, "mygr", "hep"); + STRCMP_EQUAL(" hep", buf); mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "hello"); STRCMP_EQUAL("\x1b[90m[DBG ][mygr]: hello\x1b[0m", buf); mbed_tracef(TRACE_LEVEL_INFO, "mygr", "to one"); @@ -268,6 +271,10 @@ TEST(trace, change_levels) TEST(trace, active_level_debug) { mbed_trace_config_set(TRACE_ACTIVE_LEVEL_DEBUG); + + // unknown debug level + mbed_tracef(TRACE_LEVEL_DEBUG+1, "mygr", "hep"); + STRCMP_EQUAL(" hep", buf); mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "hep"); STRCMP_EQUAL("[DBG ][mygr]: hep", buf); From 6a6dc452aa482a87421de660b3c57590cd43d6fa Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Nov 2018 14:22:43 +0200 Subject: [PATCH 03/12] Squashed 'features/nanostack/coap-service/' changes from cbe656a..bc331ca bc331ca Delete transaction when handling response (#110) 0292600 Use callback function when deleting request (#109) 1edc4a8 New API to clear requests by service ID (#108) 61ecb6b Session cleanup timer fixes (#105) git-subtree-dir: features/nanostack/coap-service git-subtree-split: bc331cabb13e9b0e64a5ed74d712a3978aa270d6 --- coap-service/coap_service_api.h | 11 ++++- source/coap_connection_handler.c | 2 +- source/coap_message_handler.c | 47 +++++++++++++++++++ source/coap_service_api.c | 8 +++- source/include/coap_message_handler.h | 2 + .../coap_message_handlertest.cpp | 5 ++ .../test_coap_message_handler.c | 40 ++++++++++++++-- .../test_coap_message_handler.h | 1 + .../coap_service_api/coap_service_apitest.cpp | 5 ++ .../coap_service_api/test_coap_service_api.c | 6 +++ .../coap_service_api/test_coap_service_api.h | 2 + .../unittest/stub/coap_message_handler_stub.c | 6 +++ 12 files changed, 127 insertions(+), 8 deletions(-) diff --git a/coap-service/coap_service_api.h b/coap-service/coap_service_api.h index 623c381744a..4834acfb971 100644 --- a/coap-service/coap_service_api.h +++ b/coap-service/coap_service_api.h @@ -282,8 +282,6 @@ extern int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_ */ extern int8_t coap_service_response_send_by_msg_id(int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len); - - /** * \brief Delete CoAP request transaction * @@ -297,6 +295,15 @@ extern int8_t coap_service_response_send_by_msg_id(int8_t service_id, uint8_t op */ extern int8_t coap_service_request_delete(int8_t service_id, uint16_t msg_id); +/** + * \brief Delete CoAP requests from service id + * + * Removes pending CoAP requests from service specified by service_id. + * + * \param service_id Id number of the current service. + */ +extern void coap_service_request_delete_by_service_id(int8_t service_id); + /** * \brief Set DTLS handshake timeout values * diff --git a/source/coap_connection_handler.c b/source/coap_connection_handler.c index 8c6f094eb96..22348883b5a 100644 --- a/source/coap_connection_handler.c +++ b/source/coap_connection_handler.c @@ -1001,7 +1001,7 @@ void coap_connection_handler_exec(uint32_t time) { if(ns_list_count(&secure_session_list)){ // Seek & destroy old sessions where close notify have been sent - ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { + ns_list_foreach_safe(secure_session_t, cur_ptr, &secure_session_list) { if(cur_ptr->session_state == SECURE_SESSION_CLOSED) { if((cur_ptr->last_contact_time + CLOSED_SECURE_SESSION_TIMEOUT) <= time){ secure_session_delete(cur_ptr); diff --git a/source/coap_message_handler.c b/source/coap_message_handler.c index db2cc14ef66..be7055b822e 100644 --- a/source/coap_message_handler.c +++ b/source/coap_message_handler.c @@ -98,6 +98,18 @@ static coap_transaction_t *transaction_find_by_address(uint8_t *address_ptr, uin return this; } +static coap_transaction_t *transaction_find_by_service_id(int8_t service_id) +{ + coap_transaction_t *this = NULL; + ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { + if (cur_ptr->service_id == service_id) { + this = cur_ptr; + break; + } + } + return this; +} + /* retransmission valid time is calculated to be max. time that CoAP message sending can take: */ /* Number of retransmisisons, each retransmission is 2 * previous retransmisison time */ /* + random factor (max. 1.5) */ @@ -160,6 +172,21 @@ void transactions_delete_all(uint8_t *address_ptr, uint16_t port) } } +static void transactions_delete_all_by_service_id(int8_t service_id) +{ + coap_transaction_t *transaction = transaction_find_by_service_id(service_id); + + while (transaction) { + ns_list_remove(&request_list, transaction); + if (transaction->resp_cb) { + transaction->resp_cb(transaction->service_id, transaction->remote_address, transaction->remote_port, NULL); + } + sn_coap_protocol_delete_retransmission(coap_service_handle->coap, transaction->msg_id); + transaction_free(transaction); + transaction = transaction_find_by_service_id(service_id); + } +} + static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_ptr, void *param) { coap_transaction_t *this = NULL; @@ -322,6 +349,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t goto exit; /* Response received */ } else { + transaction_delete(transaction_ptr); // transaction_ptr not needed in response if (coap_message->token_ptr) { this = transaction_find_client_by_token(coap_message->token_ptr, coap_message->token_len, source_addr_ptr, port); } @@ -551,6 +579,7 @@ int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t se tr_error("invalid params"); return -1; } + sn_coap_protocol_delete_retransmission(handle->coap, msg_id); transaction_ptr = transaction_find_client(msg_id); @@ -558,10 +587,28 @@ int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t se tr_error("response transaction not found"); return -2; } + + if (transaction_ptr->resp_cb) { + transaction_ptr->resp_cb(transaction_ptr->service_id, transaction_ptr->remote_address, transaction_ptr->remote_port, NULL); + } transaction_delete(transaction_ptr); return 0; } +int8_t coap_message_handler_request_delete_by_service_id(coap_msg_handler_t *handle, int8_t service_id) +{ + tr_debug("Service %d, delete all CoAP requests", service_id); + + if (!handle) { + tr_error("invalid params"); + return -1; + } + + transactions_delete_all_by_service_id(service_id); + + return 0; +} + int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time){ if( !handle ){ diff --git a/source/coap_service_api.c b/source/coap_service_api.c index 16e646dda96..f5c4cc3913f 100644 --- a/source/coap_service_api.c +++ b/source/coap_service_api.c @@ -201,9 +201,10 @@ static void service_event_handler(arm_event_s *event) tr_debug("service tasklet initialised"); /*initialize coap service and listen socket*/ } + if (event->event_type == ARM_LIB_SYSTEM_TIMER_EVENT && event->event_id == COAP_TICK_TIMER) { coap_message_handler_exec(coap_service_handle, coap_ticks++); - if(coap_ticks && !coap_ticks % SECURE_SESSION_CLEAN_INTERVAL){ + if(coap_ticks && !(coap_ticks % SECURE_SESSION_CLEAN_INTERVAL)){ coap_connection_handler_exec(coap_ticks); } } @@ -541,6 +542,11 @@ int8_t coap_service_request_delete(int8_t service_id, uint16_t msg_id) return coap_message_handler_request_delete(coap_service_handle, service_id, msg_id); } +void coap_service_request_delete_by_service_id(int8_t service_id) +{ + coap_message_handler_request_delete_by_service_id(coap_service_handle, service_id); +} + int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint32_t max) { coap_service_t *this = service_find(service_id); diff --git a/source/include/coap_message_handler.h b/source/include/coap_message_handler.h index 9b54619ca79..377ca400c20 100644 --- a/source/include/coap_message_handler.h +++ b/source/include/coap_message_handler.h @@ -96,6 +96,8 @@ extern int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int extern int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t service_id, uint16_t msg_id); +extern int8_t coap_message_handler_request_delete_by_service_id(coap_msg_handler_t *handle, int8_t service_id); + extern int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time); extern void transaction_delete(coap_transaction_t *this); diff --git a/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp b/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp index e418ab375b3..1aed34f600b 100644 --- a/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp +++ b/test/coap-service/unittest/coap_message_handler/coap_message_handlertest.cpp @@ -63,6 +63,11 @@ TEST(coap_message_handler, test_coap_message_handler_request_delete) CHECK(test_coap_message_handler_request_delete()); } +TEST(coap_message_handler, test_coap_message_handler_request_delete_by_service_id) +{ + CHECK(test_coap_message_handler_request_delete_by_service_id()); +} + TEST(coap_message_handler, test_coap_message_handler_exec) { CHECK(test_coap_message_handler_exec()); diff --git a/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c b/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c index c00067fa49d..c4953c7e7a4 100644 --- a/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c +++ b/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c @@ -233,10 +233,8 @@ bool test_coap_message_handler_request_send() uint8_t buf[16]; memset(&buf, 1, 16); - char uri[3]; - uri[0] = "r"; - uri[1] = "s"; - uri[2] = "\0"; + char uri[3] = "rs"; + if( 0 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, NULL)) return false; @@ -330,6 +328,40 @@ bool test_coap_message_handler_request_delete() return true; } +bool test_coap_message_handler_request_delete_by_service_id() +{ + retCounter = 1; + sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s)); + memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s)); + nsdynmemlib_stub.returnCounter = 1; + coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function); + coap_service_handle = handle; + + uint8_t buf[16]; + memset(&buf, 1, 16); + char uri[3] = "rs"; + + if( 0 == coap_message_handler_request_delete_by_service_id(NULL, 1)) + return false; + + if( 0 != coap_message_handler_request_delete_by_service_id(handle, 1)) + return false; + + sn_coap_builder_stub.expectedUint16 = 1; + nsdynmemlib_stub.returnCounter = 3; + if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv)) + return false; + + if( 0 != coap_message_handler_request_delete_by_service_id(handle, 3)) + return false; + + free(sn_coap_protocol_stub.expectedCoap); + sn_coap_protocol_stub.expectedCoap = NULL; + coap_message_handler_destroy(handle); + coap_service_handle = NULL; + return true; +} + bool test_coap_message_handler_response_send() { if( -1 != coap_message_handler_response_send(NULL, 2, 0, NULL, 1,3,NULL, 0)) diff --git a/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h b/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h index fc3f2ae6bc9..18f5c0fca79 100644 --- a/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h +++ b/test/coap-service/unittest/coap_message_handler/test_coap_message_handler.h @@ -30,6 +30,7 @@ bool test_coap_message_handler_coap_msg_process(); bool test_coap_message_handler_request_send(); bool test_coap_message_handler_response_send(); bool test_coap_message_handler_request_delete(); +bool test_coap_message_handler_request_delete_by_service_id(); bool test_coap_message_handler_exec(); #ifdef __cplusplus diff --git a/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp b/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp index 377f486a61f..818680d0f23 100644 --- a/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp +++ b/test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp @@ -68,6 +68,11 @@ TEST(coap_service_api, test_coap_service_request_delete) CHECK(test_coap_service_request_delete()); } +TEST(coap_service_api, test_coap_service_request_delete_by_service_id) +{ + CHECK(test_coap_service_request_delete_by_service_id()); +} + TEST(coap_service_api, test_coap_service_response_send) { CHECK(test_coap_service_response_send()); diff --git a/test/coap-service/unittest/coap_service_api/test_coap_service_api.c b/test/coap-service/unittest/coap_service_api/test_coap_service_api.c index 00714a65b16..9d558ace7be 100644 --- a/test/coap-service/unittest/coap_service_api/test_coap_service_api.c +++ b/test/coap-service/unittest/coap_service_api/test_coap_service_api.c @@ -236,6 +236,12 @@ bool test_coap_service_request_delete() return true; } +bool test_coap_service_request_delete_by_service_id() +{ + coap_service_request_delete_by_service_id(0); + return true; +} + bool test_coap_service_response_send() { uint8_t buf[16]; diff --git a/test/coap-service/unittest/coap_service_api/test_coap_service_api.h b/test/coap-service/unittest/coap_service_api/test_coap_service_api.h index 9f83ca06a8e..ac148290ec9 100644 --- a/test/coap-service/unittest/coap_service_api/test_coap_service_api.h +++ b/test/coap-service/unittest/coap_service_api/test_coap_service_api.h @@ -39,6 +39,8 @@ bool test_coap_service_request_send(); bool test_coap_service_request_delete(); +bool test_coap_service_request_delete_by_service_id(); + bool test_coap_service_response_send(); bool test_coap_callbacks(); diff --git a/test/coap-service/unittest/stub/coap_message_handler_stub.c b/test/coap-service/unittest/stub/coap_message_handler_stub.c index 2116dd34709..33b4ba22b3f 100644 --- a/test/coap-service/unittest/stub/coap_message_handler_stub.c +++ b/test/coap-service/unittest/stub/coap_message_handler_stub.c @@ -39,6 +39,7 @@ void transactions_delete_all(uint8_t *address_ptr, uint16_t port) { } + int8_t coap_message_handler_destroy(coap_msg_handler_t *handle) { return coap_message_handler_stub.int8_value; @@ -78,6 +79,11 @@ int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t se return 0; } +int8_t coap_message_handler_request_delete_by_service_id(coap_msg_handler_t *handle, int8_t service_id) +{ + return 0; +} + int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time) { return coap_message_handler_stub.int8_value; From 6dd01c679db4deb0a4a2c55832f3abe7b19bc51b Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Nov 2018 17:08:28 +0200 Subject: [PATCH 04/12] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 2535a6c..ccd30a3 ccd30a3 Merge branch 'release_internal' into release_external a9d7c1b Use BSD3 license for Thread files (#1898) 2b1d298 Link request retransmission delay changed (#1895) 06bd60a Remove ws resources from Nanostack ad8577d Remove new test files 4453f82 Merge branch 'release_internal' into release_external acbf1ac Add missing function macros (#1897) dae82f6 implemented wisun routing cost calculation f919fd1 Fix warning found by PVS-studio (#1891) 399f02f Additional time for distribution of dataset added (#1892) dde9e61 Reverted commit #1888 and fixed thread_bbr_dua_entry_find (#1893) 628fa27 Merge pull request #1885 from ARMmbed/IOTTHD-2752 cfea7b2 BBR route for added with preference. Route info updated. (#1888) dc404c4 Fix issues found by coverity (#1889) c81e59c Fixes for Wi-SUN bbr behaviour c941fe6 Adjust COAP callback return values (#1886) 7ef4775 Fix for multicast ping forwarding before adding MPL header(#1883) 766e305 FHSS: fixed missing us convert ef38363 FHSS: Traces in set parent 296e455 FHSS: Time unit defines added 724696c FHSS: changed traces to use timestamp from MAC 3deb08c FHSS: use divider function in ufsi calculation 74c7f37 FHSS: function to check if remaining slots is negative 654dd44 Merge pull request #1879 from ARMmbed/IOTTHD-2752 1ef5062 Address registration fix (#1882) 4c74f96 FHSS unit tests: Fixed tr51 tests 4cf7fdf FHSS: fixed tr51 channel table size a1d8b3d FHSS unit tests: Fixed tr51 tests 7e622b3 FHSS: Allocate TR51 channel tables when FHSS enabled e7a8d45 link-local multicast group registration (#1880) d4c95f2 Clear COAP retransmissions in partition change (#1872) bf36b91 Added generation of mac address if not set 990f4f1 Merge pull request #1877 from ARMmbed/dhcpv6_server_fix 6cbe7c5 Fix wrong link type to correct one DHCPV6_DUID_HARDWARE_EUI64_TYPE -> DHCPV6_DUID_HARDWARE_EUI48_TYPE fd6c1c8 Merge pull request #1876 from ARMmbed/thread_dhcpv6_server_trace_fix 3f83bd1 Added trace about prefered timeout for fix CI test 4331ea1 added support for multicast forwarding 7327652 bbr start called after seq number updated. (#1875) 98be8b2 Merge pull request #1868 from ARMmbed/IOTTHD-2863 23296c1 Merge pull request #1871 from ARMmbed/ws_config_handler 2188fd2 FHSS: Fixed negative remaining time in ufsi calculation 5b70440 announce reattach fix (#1873) fc11a7a Merge pull request #1869 from ARMmbed/dhcpv6_server_update a156355 WS PAN config message handler update 5e45c40 Thread dhcpv6 server update fe9ba3b Wi-sun border router enable global prefix with DHCP address allocation. 6d2af0b Dhcpv6 server update ab1260a added possibility to set next sequence number on PBBR. (#1867) 6679db4 WS bootstrap: traces to hop calculation 1cc4aff Merge pull request #1865 from ARMmbed/dhcpv6_client_ws_integration c2d0e14 Enable wi-sun dhcp relay service. 70e56b1 Wi-sun DHCP client support and RPL prefix learn Callback 3389b46 Merge pull request #1866 from ARMmbed/dhcp_relay_fix 9aa6a95 Address registration changes for MED and SED (#1863) 16359eb Fix compile problem 1472b02 Removed duplcate line. 67ea075 Wi-SUN node init API change b906861 Fixed DHCP relay bugs bcffa5f FHSS: Fixed setting parent synch e0276f6 FHSS: Configure in critical state d74d5ff Merge pull request #1862 from ARMmbed/dhcp_client_generic_update 999bbc3 Copied memory fix from PR #1858 6500fcf DHCPv6 client Generic API for all stacks. 2ec9b6e Fix memory leak if dhcp renew send fails (#1858) cbf99e7 Merge pull request #1861 from ARMmbed/ws_dhcp_support 08155b1 DHCPv6 service relay support 62812ab Libdhcpv6 Relay support 0eea30d delay Join_ent.ntf sending by 50 ms (#1860) dac1d99 Merge pull request #1857 from ARMmbed/mac_enhanced_ack b819fa8 Fix bbr start 514bb58 Merge pull request #1836 from ARMmbed/IOTTHD-2828 b074d0e Merge pull request #1845 from ARMmbed/IOTTHD-2839 20b5e57 Enhanced ACK tx fix caf53d1 Merge pull request #1846 from ARMmbed/IOTTHD-2824 9b5e1c9 added payload length for Max child timeout tlv (#1856) 3c1864b address registration tlv check only for MTDs (#1855) 942d8e7 Diagnostic TLV added (#1854) f2b38cf Check for mandatory Address registration tlv (#1853) ce8d5b7 Valdations for Child update response added: (#1852) e373545 Added Wi-SUN border router implementation 1f7c040 Merge pull request #1849 from ARMmbed/mac_asynch_fix 33afc9c FHSS: Added force synch boolean in parent set 5ddf5fa FHSS: prevent unicast on broadcast channel in tx handle f17e6cd FHSS: Check TX/RX slot in tx handle 3082407 FHSS: implemented divide function cebdaf4 Update stoip6 prototype to tests (#1851) 279c708 Trig a new back off period for pending TX if ACK tx is active f1e7f06 Fix broken unit test. 1d8e3d7 MAC Asynch Data request update cca9879 Merge pull request #1848 from ARMmbed/iotthd-2788 fe84585 Merge pull request #1847 from ARMmbed/eAck_mac_timer_fix c1c5926 Dynamic parent selection delay based on trickle i_min. 68bad00 MAC: Stop active MAC timer before sending enhanced Ack 4a204bd MAC: set new MAC channel only if RF returns success 9d79ca9 FHSS: Added minimum synch interval a35b702 FHSS: Increased min random of tx poll db6dc6b MAC: Fixed enhanced ack TX time 5836b50 Merge pull request #1844 from ARMmbed/fix_ack_tx_fail_handling d9e2ea6 MAC: Fixed handling of the failed Ack transmission f43e285 Merge pull request #1843 from ARMmbed/address_reg_fix 0b4aa78 Parent Broadcast synch fix and TR51CF slot define fix d6b4111 fix for valgrind reported error. (#1842) 8160d86 Added support for wisun multicast 1f4625e Call ws_secondary_parent_update inside primary set for reduce code size. 35b39f4 Merge pull request #1840 from ARMmbed/address_register cfb2426 bbr memory leak during keep alive fixed. (#1839) a8aafe4 Stub update c244ad8 Enable 6-bit path control for give better compare between parent's. eac63d2 FHSS and address registration update c14343a valgrind and coverity reported errors fixed. (#1838) 9b14b83 additional thread prefixes in network data (#1833) fb07086 Merge pull request #1837 from ARMmbed/llc_parent_synch bf55180 Fixed failing unit test. 5e7a493 Update brodcast synch when here data from primary parent. 9e22831 Merge pull request #1834 from ARMmbed/enable_bt_ie_ulad 02af1a8 Thread extension commission updates (#1835) dd082a0 Fix ws_llc_data_send unit test validation with new bt-ie lement length. ae6554d Revert "Disable wi-sun features temporary". 927c329 Thread extension commissioning updates (#1828) 160ef0a Merge pull request #1829 from ARMmbed/IOTTHD-2821 576f2bf FHSS unit tests: Fixed channel function variable name f33d163 WS: Removed backward compatibility defines 9c88a7f WS: fixed overwriting fixed channel with random efd77f1 Clean thread_routing test stub (#1832) 2b8a011 Remove recursion from MAC layer #2 (#1830) 2f5a2ce Remove recursion from MAC layer (#1826) 06e3243 propagation of reserved bit in network data implemented. (#1827) e7fa605 Merge pull request #1823 from ARMmbed/IOTTHD-2782 89001d1 Merge pull request #1825 from ARMmbed/IOTTHD-2816 9c78a95 MAC: Static CSMA period when using FHSS 3d1c8a0 FHSS: Stop unicast schedule when fixed channel or no dwell interval d6086d0 Merge pull request #1818 from ARMmbed/nud_statemachine a2b8491 Wi-sun Border router and NUD process updates 60e1545 Disable wi-sun features temporary 7e3c16c Wi-sun LLC Data request IE update a27076f Fixed Pan informatio IE read bug bb1aeac Fixed Fragmentation init failure problem. 02fce65 Parent select and pan config handler update a2ef56a wi-sun update: ca9fd4f Disabled Wi-sun border router version number update. 231daf7 Wi-sun NUD State Machine update e7d551c Commissioner fixes (#1824) 62ffba3 keepalive for on mesh commissioner sent to leader aloc. (#1821) f846823 Coverity reported error fixes: (#1822) 708e8d3 Merge pull request #1820 from ARMmbed/IOTTHD-2735 b2e7efc FHSS WS: Get MAC channel from FHSS when starting RF interface fe2b448 Merge pull request #1819 from ARMmbed/fixed_bad_channel 7c13c3c commissioner updates. (#1812) 4c7d4f2 FHSS: Fixed bad channel check with fixed channel configuration 40b2eec Set global address flag to follow address state b46eacc updated channel plan settings 4a1d595 Merge pull request #1815 from ARMmbed/iotthd-2745 5a37354 Primary Parent Update Hook to Wi-sun for synch broadcast schedule. 98b0e23 Fix memory leak when advertising route (#1814) b5d276d refactored trickkle running checks 61ff793 Merge pull request #1807 from ARMmbed/rpl_parent_candidate a7a1ab3 Updated to NUD probability from 10% to 1%. 89b8eeb Merge pull request #1810 from ARMmbed/IOTTHD-2734 b99d497 Modify NUD operation propability. 4bb8b54 Wi-sun Probe update 2183869 FHSS Ack tx done fix fb4309d Mac Asynch and Ack validation update 2695601 FHSS parent synch fix. b50abb0 RPL, FHSS and Wisun Update a40e012 Check MAC status when purging indirect queue (#1811) b68f394 WS bootstrap: Updated channel function set apis 42b2e7c Unit tests: channel function tests updated b6236f9 WS bootstrap: Separated unicast and broadcast channel functions 6fe5ea5 Fix Thread DHCPv6-client memory leak (#1808) bbc0d77 WS bootstrap: renamed channel_function to uc_channel_function 7dbad5e Parent sends full network data in response to data request (#1806) cbe45b4 Merge pull request #1805 from ARMmbed/IOTTHD-2733 8956418 FHSS unit tests: Fixed broadcast handler tests e7aa893 FHSS: Define to make outdated application work 9fd804b FHSS: Separated broadcast schedule channel function 327c310 Merge pull request #1804 from ARMmbed/fhss_ws_cs e7ae8ce FHSS unit tests: Fixed missing platform stub 9cbd2b7 FHSS: added critical states 51f8328 Merge pull request #1803 from ARMmbed/IOTTHD-2736 537b60d FHSS unit tests: Fixed missing stub 43bc93d FHSS: Poll TX queue on every TX slot c6e2457 Merge pull request #1802 from ARMmbed/asynch_channel_plan_filter c851b07 Wi-sun bootstrap verify channel plan component against own configured ones. 1bdc4e6 Merge pull request #1800 from ARMmbed/IOTTHD-2504 6ed53e6 FHSS unit tests: Fixed timestamp stub return value f43b3af FHSS unit tests: Fixed missing timestamp read function f27a29c Merge pull request #1801 from ARMmbed/rf_driver_start_fix c2bc561 Add MAC TX active FLAG to active before write function return value. 08d3e12 Merge pull request #1799 from ARMmbed/several_bug_fixs 65d96c4 FHSS: Fixed calculating UFSI eedd746 FHSS: Compensate delay from platform driver when starting timeout 7d537ea FHSS: Read timestamp from MAC/PHY instead of using FHSS own timestamp 0206fc8 FHSS: Added callbacks for debugging purposes 63d8a41 Added Packet rebuild for extented driver after Driver Busy error. 607da3e Bug fixes: f39312b REED and FED links removed (#1796) b162d7b added support for modifying fhss configuration after initial startup 88e239d Merge pull request #1798 from ARMmbed/enhanced_ack_send 11fb5fa MAC Enhanced ACK TX fix: 08d5584 Merge pull request #1794 from ARMmbed/rpl_address_learn 5bbc86f fed advertisement fix (#1795) a48254c Wi-sun Address registration update: 5db8037 RPL Local Repair, SLAAC prefix update and Dodag Prefix proces update: b3139c8 Adjust Thread BBR neighbor/destination cache size (#1793) 21deb75 Registered neighbour cache entries are not reregistered. (#1792) d93b9e4 Added empty function for ws public api 1a09af7 Updated management api f52289f Merge pull request #1790 from ARMmbed/ws_llc_neigh_update_fix b954e56 WS neighbor refresh update 0b2736f Thread address registration improvements (#1779) 931a17d Merge pull request #1789 from ARMmbed/iotthd-2693 90c6a8a Removed unnecessary Decrypt Fail debug trace. b425f4b Adapatation neighbor validation update: 06255ee Merge pull request #1787 from ARMmbed/iottthd-2692 e98c182 MAC report unknow neighbour COMM status at Packet TX process not detetct destination. be0aa9c Merge pull request #1786 from ARMmbed/iotthd-2695 42122b7 Added support to report Driver if FHSS return unknow neighbor error. eb5ba30 Fixed Driver Tx done callback missing error return values. 1a9acbd Wi-SUN fhss refactor 0ca78d6 Merge pull request #1784 from ARMmbed/iotthd-2533 9b37c24 Fixed Unicast and Broadcast MAC packet request types. 0ddff57 Fix PAN-id read bug when received 2015 frame version's. git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: ccd30a3b7a718710090606b6d6add8dfd1c86159 --- nanostack/dhcp_service_api.h | 13 +- nanostack/fhss_api.h | 11 +- nanostack/fhss_config.h | 13 +- nanostack/fhss_ws_extension.h | 5 +- nanostack/mac_api.h | 3 +- nanostack/net_fhss.h | 3 +- nanostack/thread_bbr_api.h | 15 + nanostack/thread_commissioning_api.h | 14 + nanostack/thread_diagcop_lib.h | 3 +- .../Bootstraps/Generic/protocol_6lowpan.c | 15 +- .../Generic/protocol_6lowpan_bootstrap.c | 6 +- source/6LoWPAN/MAC/mpx_api.h | 3 +- source/6LoWPAN/Thread/thread_bbr_api.c | 65 ++-- .../6LoWPAN/Thread/thread_bbr_api_internal.h | 8 - source/6LoWPAN/Thread/thread_bootstrap.c | 84 +++-- source/6LoWPAN/Thread/thread_bootstrap.h | 4 +- .../6LoWPAN/Thread/thread_border_router_api.c | 38 ++- .../thread_border_router_api_internal.h | 9 + .../6LoWPAN/Thread/thread_commissioning_api.c | 276 +++++++++++++--- source/6LoWPAN/Thread/thread_common.c | 184 ++++++++++- source/6LoWPAN/Thread/thread_common.h | 10 +- source/6LoWPAN/Thread/thread_config.h | 11 + source/6LoWPAN/Thread/thread_constants.h | 1 + source/6LoWPAN/Thread/thread_dhcpv6_client.h | 98 ------ source/6LoWPAN/Thread/thread_dhcpv6_server.c | 114 +++++++ source/6LoWPAN/Thread/thread_dhcpv6_server.h | 39 +++ source/6LoWPAN/Thread/thread_diagnostic.c | 19 +- source/6LoWPAN/Thread/thread_extension.h | 44 ++- source/6LoWPAN/Thread/thread_extension_bbr.h | 4 + .../Thread/thread_extension_bootstrap.h | 2 + source/6LoWPAN/Thread/thread_host_bootstrap.c | 25 +- .../Thread/thread_joiner_application.c | 5 +- source/6LoWPAN/Thread/thread_leader_service.c | 13 +- source/6LoWPAN/Thread/thread_management_api.c | 1 - .../6LoWPAN/Thread/thread_management_client.c | 57 ++-- .../6LoWPAN/Thread/thread_management_client.h | 21 +- source/6LoWPAN/Thread/thread_management_if.c | 23 +- .../6LoWPAN/Thread/thread_management_server.c | 42 ++- .../6LoWPAN/Thread/thread_management_server.h | 7 + .../Thread/thread_mle_message_handler.c | 61 ++++ source/6LoWPAN/Thread/thread_nd.c | 5 +- .../Thread/thread_network_data_storage.c | 39 ++- .../Thread/thread_network_data_storage.h | 4 +- source/6LoWPAN/Thread/thread_nvm_store.c | 12 +- .../6LoWPAN/Thread/thread_resolution_client.c | 8 +- .../6LoWPAN/Thread/thread_resolution_server.c | 6 +- .../6LoWPAN/Thread/thread_router_bootstrap.c | 93 +++++- .../6LoWPAN/Thread/thread_router_bootstrap.h | 7 +- source/6LoWPAN/adaptation_interface.c | 94 +++--- source/6LoWPAN/ws/ws_bootstrap.h | 19 +- source/6LoWPAN/ws/ws_common.h | 33 +- source/6LoWPAN/ws/ws_common_defines.h | 26 +- source/6LoWPAN/ws/ws_neighbor_class.h | 5 + source/Common_Protocols/ipv6.c | 22 +- source/DHCPv6_Server/DHCPv6_Server_service.c | 197 +++--------- source/DHCPv6_Server/DHCPv6_server_service.h | 26 +- source/DHCPv6_client/dhcpv6_client_api.h | 88 ++++++ .../dhcpv6_client_service.c} | 111 +++---- source/MAC/IEEE802_15_4/mac_defines.h | 14 +- source/MAC/IEEE802_15_4/mac_fhss_callbacks.c | 13 +- source/MAC/IEEE802_15_4/mac_fhss_callbacks.h | 1 + .../mac_header_helper_functions.c | 49 ++- .../mac_header_helper_functions.h | 4 +- source/MAC/IEEE802_15_4/mac_indirect_data.c | 2 +- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 238 ++++++++------ source/MAC/IEEE802_15_4/mac_mcps_sap.h | 22 +- source/MAC/IEEE802_15_4/mac_mlme.c | 24 +- source/MAC/IEEE802_15_4/mac_mlme.h | 2 +- source/MAC/IEEE802_15_4/mac_pd_sap.c | 140 ++++++--- source/MAC/IEEE802_15_4/mac_pd_sap.h | 2 + source/MAC/IEEE802_15_4/sw_mac.c | 27 +- source/MPL/mpl.c | 58 ++-- source/RPL/rpl_control.c | 43 +-- source/RPL/rpl_control.h | 9 +- source/RPL/rpl_downward.c | 4 +- source/RPL/rpl_structures.h | 1 + source/RPL/rpl_upward.c | 43 ++- source/RPL/rpl_upward.h | 2 +- source/Service_Libs/etx/etx.c | 3 + source/Service_Libs/etx/etx.h | 1 + source/Service_Libs/fhss/channel_functions.h | 23 +- source/Service_Libs/fhss/channel_list.c | 13 + source/Service_Libs/fhss/channel_list.h | 10 + source/Service_Libs/fhss/fhss.c | 23 +- source/Service_Libs/fhss/fhss_common.c | 21 +- source/Service_Libs/fhss/fhss_common.h | 2 + .../fhss/fhss_configuration_interface.c | 4 +- source/Service_Libs/fhss/fhss_ws.h | 10 +- .../fhss/fhss_ws_empty_functions.c | 2 +- .../mac_neighbor_table/mac_neighbor_table.c | 12 + .../mac_neighbor_table/mac_neighbor_table.h | 2 + source/Service_Libs/mdns/ns_fnet_port.c | 3 +- source/ipv6_stack/ipv6_routing_table.c | 1 + source/ipv6_stack/protocol_ipv6.c | 14 +- source/libDHCPv6/dhcp_service_api.c | 296 +++++++++++++++++- source/libDHCPv6/libDHCPv6.c | 39 +++ source/libDHCPv6/libDHCPv6.h | 19 +- source/libDHCPv6/libDHCPv6_server.c | 16 +- source/libDHCPv6/libDHCPv6_server.h | 19 +- source/nsconfig.h | 6 + sources.mk | 3 +- 101 files changed, 2460 insertions(+), 944 deletions(-) delete mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_client.h create mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_server.c create mode 100644 source/6LoWPAN/Thread/thread_dhcpv6_server.h create mode 100644 source/DHCPv6_client/dhcpv6_client_api.h rename source/{6LoWPAN/Thread/thread_dhcpv6_client.c => DHCPv6_client/dhcpv6_client_service.c} (74%) diff --git a/nanostack/dhcp_service_api.h b/nanostack/dhcp_service_api.h index d8b9b5b1168..3efae996b45 100644 --- a/nanostack/dhcp_service_api.h +++ b/nanostack/dhcp_service_api.h @@ -69,7 +69,8 @@ typedef enum dhcp_instance_type { DHCP_INSTANCE_CLIENT, - DHCP_INSTANCE_SERVER + DHCP_INSTANCE_SERVER, + DHCP_INTANCE_RELAY_AGENT } dhcp_instance_type_e; /** @@ -124,6 +125,16 @@ typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb); +/** +* \brief Enable DHCPv6 Relay Agent to server. +* +* +* \param instance The instance ID of the registered server. +* \param server_address global server IPv6 address +*/ +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address); + + /** * \brief Deletes a server instance. * diff --git a/nanostack/fhss_api.h b/nanostack/fhss_api.h index 16820aeaaee..0f0774cd024 100644 --- a/nanostack/fhss_api.h +++ b/nanostack/fhss_api.h @@ -132,8 +132,9 @@ typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_ * @param api FHSS instance. * @param fhss_state FHSS state (FHSS states are defined by FHSS api). * @param pan_id PAN id of the network FHSS synchronizes with. + * @return -1 when failed, otherwise current MAC channel. */ -typedef void fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); +typedef int16_t fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); /** * @brief Read timestamp. @@ -215,6 +216,13 @@ typedef int mac_read_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_addres */ typedef uint32_t mac_read_datarate(const fhss_api_t *fhss_api); +/** + * @brief Read 32-bit timestamp. + * @param fhss_api FHSS instance. + * @return Timestamp. + */ +typedef uint32_t mac_read_timestamp(const fhss_api_t *fhss_api); + /** * @brief Change channel. * @param fhss_api FHSS instance. @@ -287,6 +295,7 @@ struct fhss_callback { mac_read_tx_queue_size *read_tx_queue_size; /**< Read MAC TX queue size. */ mac_read_mac_address *read_mac_address; /**< Read MAC address. */ mac_read_datarate *read_datarate; /**< Read PHY datarate. */ + mac_read_timestamp *read_timestamp; /**< Read timestamp. */ mac_change_channel *change_channel; /**< Change channel. */ mac_send_fhss_frame *send_fhss_frame; /**< Send FHSS frame. */ mac_synch_lost_notification *synch_lost_notification; /**< Send notification when FHSS synchronization is lost. */ diff --git a/nanostack/fhss_config.h b/nanostack/fhss_config.h index 5695367659f..6a1cf3507ab 100644 --- a/nanostack/fhss_config.h +++ b/nanostack/fhss_config.h @@ -96,8 +96,11 @@ typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uin */ typedef struct fhss_ws_configuration { - /** WS channel function. */ - fhss_ws_channel_functions ws_channel_function; + /** WS unicast channel function. */ + fhss_ws_channel_functions ws_uc_channel_function; + + /** WS broadcast channel function. */ + fhss_ws_channel_functions ws_bc_channel_function; /** Broadcast schedule identifier. */ uint16_t bsi; @@ -111,6 +114,12 @@ typedef struct fhss_ws_configuration /** Broadcast dwell interval. Range: 15-250 milliseconds. */ uint8_t fhss_bc_dwell_interval; + /** Unicast fixed channel */ + uint8_t unicast_fixed_channel; + + /** Broadcast fixed channel */ + uint8_t broadcast_fixed_channel; + /** Channel mask. */ uint32_t channel_mask[8]; diff --git a/nanostack/fhss_ws_extension.h b/nanostack/fhss_ws_extension.h index c440451204d..44d86d1f6d9 100644 --- a/nanostack/fhss_ws_extension.h +++ b/nanostack/fhss_ws_extension.h @@ -37,6 +37,7 @@ typedef struct unicast_timing_info { unsigned unicast_channel_function:3; /**< Unicast schedule channel function */ uint8_t unicast_dwell_interval; /**< Unicast dwell interval */ uint16_t unicast_number_of_channels; /**< Unicast number of channels */ + uint16_t fixed_channel; /**< Unicast fixed channel*/ uint_fast24_t ufsi; /**< Unicast fractional sequence interval */ uint32_t utt_rx_timestamp; /**< UTT-IE reception timestamp */ } unicast_timing_info_t; @@ -47,6 +48,7 @@ typedef struct unicast_timing_info { typedef struct broadcast_timing_info { unsigned broadcast_channel_function:3; /**< Broadcast schedule channel function */ uint8_t broadcast_dwell_interval; /**< Broadcast dwell interval */ + uint16_t fixed_channel; /**< Broadcast fixed channel*/ uint16_t broadcast_slot; /**< Broadcast slot number */ uint16_t broadcast_schedule_id; /**< Broadcast schedule identifier */ uint_fast24_t broadcast_interval_offset; /**< Broadcast interval offset */ @@ -78,9 +80,10 @@ typedef fhss_ws_neighbor_timing_info_t *fhss_get_neighbor_info(const fhss_api_t * @param fhss_api FHSS instance. * @param eui64 EUI-64 address of parent. * @param bc_timing_info Pointer to parent broadcast timing/hopping schedule info. + * @param force_synch If false, synchronization is done only if minimum (internal) synchronization interval is exceed. * @return 0 on success, -1 on fail. */ -extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); +extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch); /** * @brief Remove parent which was set by ns_fhss_ws_set_parent function. diff --git a/nanostack/mac_api.h b/nanostack/mac_api.h index b889ee25a73..33c954bf980 100644 --- a/nanostack/mac_api.h +++ b/nanostack/mac_api.h @@ -137,8 +137,9 @@ typedef void mcps_data_request_ext(const mac_api_t* api, const mcps_data_req_t * * @brief mcps_purge_request MCPS_PURGE request call * @param api API to handle the request * @param data MCPS-PURGE.request specific values + * @return 0 in case of success, non-zero otherwise */ -typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data); +typedef uint8_t mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data); //Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it) diff --git a/nanostack/net_fhss.h b/nanostack/net_fhss.h index 2223a5af3bf..b201420e14f 100644 --- a/nanostack/net_fhss.h +++ b/nanostack/net_fhss.h @@ -39,10 +39,9 @@ extern "C" { extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics); /** - * @brief TODO: description. + * @brief Creates FHSS WS API instance which will be registered to software MAC. * @param fhss_configuration Basic FHSS configuration. * @param fhss_timer FHSS platform timer interface and configuration. - * @param fhss_statistics FHSS statistics storage. * @return New FHSS instance if successful, NULL otherwise. */ extern fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); diff --git a/nanostack/thread_bbr_api.h b/nanostack/thread_bbr_api.h index 91e697baad5..55a8e9f97da 100644 --- a/nanostack/thread_bbr_api.h +++ b/nanostack/thread_bbr_api.h @@ -75,6 +75,7 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id); * */ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); + /** * Set prefix to be used as combining multiple thread networks on backbone. * @@ -89,6 +90,20 @@ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t tim */ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); +/** + * Set sequence number to be used by bbr + * + * update sequence number value + * + * \param interface_id interface ID of the Thread network. + * \param sequence_number value that needs to be set on bbr + * + * \return 0 on success + * \return <0 in case of errors + * + */ +int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number); + /** * Set the Thread validation interface destination address. * diff --git a/nanostack/thread_commissioning_api.h b/nanostack/thread_commissioning_api.h index 85923328c8e..6495786534b 100644 --- a/nanostack/thread_commissioning_api.h +++ b/nanostack/thread_commissioning_api.h @@ -189,8 +189,10 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh typedef struct thread_commissioning_link_configuration { uint8_t name[16]; /**< Name of the Thread network. utf8 string nul terminated if shorter than 16. */ + uint8_t destination_address[16]; /**index); // If primary parent has changed clears priority from previous parent if (entry->link_role != PRIORITY_PARENT_NEIGHBOUR) { + new_primary = true; protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST); } entry->link_role = PRIORITY_PARENT_NEIGHBOUR; @@ -501,6 +504,10 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t if (etx_entry) { protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4); } + + if (new_primary) { + ws_primary_parent_update(cur, entry); + } return 1; } else { return 0; @@ -519,9 +526,11 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type); if (entry) { + bool new_secondary = false; etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index); // If secondary parent has changed clears priority from previous parent if (entry->link_role != SECONDARY_PARENT_NEIGHBOUR) { + new_secondary = true; protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND); } entry->link_role = SECONDARY_PARENT_NEIGHBOUR; @@ -529,6 +538,9 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr if (etx_entry) { protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4); } + if (new_secondary) { + ws_secondary_parent_update(cur); + } return 1; } else { return 0; @@ -557,7 +569,6 @@ void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_ } } -#endif #endif #endif diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index e8f4fe95771..4e8cec5ba1b 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1786,7 +1786,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode */ if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) { //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } #endif cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED; @@ -2073,6 +2073,8 @@ static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *han tr_error("RPL Local repair fail-->interface to idle"); nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur); break; + default: + break; } } @@ -2179,7 +2181,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t * // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } // Send unicast DIS to coordinator nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); diff --git a/source/6LoWPAN/MAC/mpx_api.h b/source/6LoWPAN/MAC/mpx_api.h index a61e3e00537..739b07b3307 100644 --- a/source/6LoWPAN/MAC/mpx_api.h +++ b/source/6LoWPAN/MAC/mpx_api.h @@ -39,9 +39,10 @@ typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s * @param api API to handle the request * @param purge MCPS-purge request * @param user_id MPX user ID + * @return 0 if purge requst was OK, non-zero otherwise * */ -typedef void mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); +typedef uint8_t mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); /** * @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request diff --git a/source/6LoWPAN/Thread/thread_bbr_api.c b/source/6LoWPAN/Thread/thread_bbr_api.c index 6c0b09a2c0f..9064b890d29 100644 --- a/source/6LoWPAN/Thread/thread_bbr_api.c +++ b/source/6LoWPAN/Thread/thread_bbr_api.c @@ -40,12 +40,16 @@ #include "common_functions.h" #include "thread_border_router_api.h" #include "thread_bbr_api.h" +#include "net_ipv6_api.h" +#include "NWK_INTERFACE/Include/protocol.h" #include "Common_Protocols/ipv6_constants.h" #include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_dhcpv6_server.h" #include "thread_management_if.h" #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_common.h" +#include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_extension.h" #include "6LoWPAN/Thread/thread_extension_bbr.h" @@ -96,7 +100,6 @@ typedef struct { #define RFC6106_DNS_SEARCH_LIST_OPTION 31 static NS_LIST_DEFINE(bbr_instance_list, thread_bbr_t, link); - static thread_bbr_t *thread_bbr_find_by_interface(int8_t interface_id) { thread_bbr_t *this = NULL; @@ -579,7 +582,7 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], // delete old prefix memset(this->bbr_prefix,0,8); // create new prefix - if (DHCPv6_server_service_init(this->interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + if (thread_dhcp6_server_init(this->interface_id, prefix, eui64, THREAD_MIN_PREFIX_LIFETIME) != 0) { tr_warn("DHCP server alloc fail"); // set 20 seconds delay before next process this->br_delay_timer = 20; @@ -587,8 +590,6 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], } memcpy(this->bbr_prefix,prefix,8); - DHCPv6_server_service_set_address_validlifetime(this->interface_id, this->bbr_prefix, THREAD_MIN_PREFIX_LIFETIME); - br_info.P_default_route = true; br_info.P_dhcp = true; br_info.P_on_mesh = true; @@ -724,7 +725,7 @@ static bool thread_bbr_activated(thread_bbr_t *this, uint32_t seconds) return true; } - if (cur->thread_info->routerIdReqCoapID) { + if (cur->thread_info->routerIdRequested) { // Router id reguest pending we need to wait for response return false; } @@ -978,25 +979,31 @@ int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr) { thread_bbr_t *this = thread_bbr_find_by_interface(interface_id); + thread_pbbr_dua_info_t *map; if (!this || this->backbone_interface_id < 0) { return -1; } - thread_pbbr_dua_info_t *map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t)); - if (!map) { - goto error; + ipv6_route_t *route = ipv6_route_lookup_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, NULL, 0); + if (!route){ + map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t)); + if (!map) { + goto error; + } + // We are using route info field to store BBR MLEID map + route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0); + if (!route) { + // Direct route to host allows ND proxying to work + ns_dyn_mem_free(map); + goto error; + } + // Route info autofreed + route->info_autofree = true; } + map = route->info.info; memcpy(map->mleid_ptr, mleid_ptr, 8); map->last_contact_time = protocol_core_monotonic_time; + route->info.info = map; - // We are using route info field to store BBR MLEID map - ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0); - if (!route) { - // Direct route to host allows ND proxying to work - ns_dyn_mem_free(map); - goto error; - } - // Route info autofreed - route->info_autofree = true; // send NA thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr); @@ -1006,15 +1013,6 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, return -2; } -struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) { - ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL); - if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST ) { - //Not found - return NULL; - } - return route; -} - int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id); @@ -1099,7 +1097,11 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id) // By default multicast forwarding is not enabled as it causes multicast loops multicast_fwd_set_forwarding(this->interface_id, false); + // Adjust BBR neighbor and destination cache size + arm_nwk_ipv6_max_cache_entries(THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE); + thread_extension_bbr_init(interface_id,backbone_interface_id); + return 0; #else return -1; @@ -1131,6 +1133,17 @@ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix) #endif // HAVE_THREAD_BORDER_ROUTER } +int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number) +{ + (void) interface_id; + (void) sequence_number; +#ifdef HAVE_THREAD_BORDER_ROUTER + return thread_extension_bbr_sequence_number_set(interface_id, sequence_number); +#else + return -1; +#endif // HAVE_THREAD_BORDER_ROUTER +} + int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port) { (void) interface_id; diff --git a/source/6LoWPAN/Thread/thread_bbr_api_internal.h b/source/6LoWPAN/Thread/thread_bbr_api_internal.h index dd05ca7525b..9e434990331 100644 --- a/source/6LoWPAN/Thread/thread_bbr_api_internal.h +++ b/source/6LoWPAN/Thread/thread_bbr_api_internal.h @@ -67,7 +67,6 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t tics); */ int thread_bbr_commissioner_proxy_service_update(int8_t interface_id); - #else #define thread_bbr_init(interface_id, external_commisssioner_port) #define thread_bbr_delete(interface_id) @@ -118,12 +117,6 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, */ int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16]); -/** - * \brief Find if bbr has dua entry - * - * \param interface_id addr_data_ptr - */ -struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr); #else #define thread_bbr_proxy_state_update(caller_interface_id , handler_interface_id, status) (NULL) @@ -131,7 +124,6 @@ struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t #define thread_bbr_network_data_update_notify(cur) #define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info) (0) #define thread_bbr_dua_entry_add(interface_id, addr_data_ptr, lifetime, mleid_ptr) (0) -#define thread_bbr_dua_entry_find(interface_id, addr_data_ptr) (NULL) #define thread_bbr_na_send(interface_id, target) (0) #endif //HAVE_THREAD_BORDER_ROUTER diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 0e26b643edf..f16ece331a6 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -86,7 +86,7 @@ #include "MPL/mpl.h" #include "MLE/mle.h" #include "MLE/mle_tlv.h" -#include "thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "thread_config.h" #include "thread_meshcop_lib.h" #include "multicast_api.h" @@ -136,8 +136,6 @@ static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void * static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { - - // Sleepy host protocol_interface_info_entry_t *cur_interface = user_data; if (thread_am_router(cur_interface)) { @@ -676,8 +674,6 @@ static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t * // Generate new ML64 address thread_generate_ml64_address(cur); - // Generate new domain address - thread_extension_address_generate(cur); // Register multicast addresses thread_bootstrap_all_nodes_multicast_register(cur); @@ -698,8 +694,6 @@ int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, l //Define Default Contexts lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true); - thread_extension_activate(cur); - thread_extension_bbr_route_update(cur); blacklist_clear(); @@ -896,7 +890,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur) { thread_discovery_reset(cur->id); thread_routing_set_mesh_callbacks(cur); - thread_dhcp_client_init(cur->id); + dhcp_client_init(cur->id); thread_management_client_init(cur->id); thread_address_registration_init(); cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT; @@ -1069,9 +1063,7 @@ void thread_tasklet(arm_event_s *event) case THREAD_CHILD_UPDATE: tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); - if (thread_info(cur)->thread_endnode_parent) { - thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); - } + thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); break; case THREAD_ANNOUNCE_ACTIVE: { tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); @@ -1178,6 +1170,10 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur) thread_leader_service_generate_network_data(cur); } + if (thread_addresses_needs_to_be_registered(cur)) { + thread_info(cur)->childUpdateReqTimer = 1; + } + cur->bootsrap_state_machine_cnt = 0; mac_data_poll_protocol_poll_mode_decrement(cur); } @@ -1194,6 +1190,31 @@ void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur) } } +void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur) +{ + mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; + + if (thread_i_am_router(cur)) { + return; + } + + if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || + thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { + return; + } + + if (!thread_info(cur)->thread_endnode_parent) { + return; + } + ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { + // do not remove parent entry + if (memcmp(cur_entry->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) != 0) { + tr_debug("Free short addr: %x", cur_entry->mac16); + mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry); + } + } +} + void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur) { uint8_t static_address[16]; @@ -1612,7 +1633,6 @@ void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur) if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE || cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { thread_meshlocal_route_set(cur); - thread_extension_route_set(cur); // FEDs and routers (REEDs) perform their own address resolution thread_nd_service_activate(cur->id); } else { @@ -1627,7 +1647,7 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; cur->bootsrap_state_machine_cnt = 10; - cur->thread_info->routerIdReqCoapID = 0; + cur->thread_info->routerIdRequested = false; cur->thread_info->networkDataRequested = false; clear_power_state(ICMP_ACTIVE); @@ -1644,8 +1664,6 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur) thread_generate_ml16_address(cur); //GENERATE ML-EID64 thread_generate_ml64_address(cur); - // Generate new domain address - thread_extension_address_generate(cur); thread_bootstrap_routing_activate(cur); thread_bootstrap_network_data_update(cur); // After successful attach if there is announcement info present, send announcement back to previous channel @@ -1823,8 +1841,7 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[ tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); if (prefix && dhcp_addr) { tr_debug("Delete Current Server data"); - thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix); - //TODO shuold we try again or select new Server + dhcp_client_global_address_delete(interface, dhcp_addr, prefix); } } } @@ -1964,6 +1981,10 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_ config_ptr[n].rfChannel = cur_class->channel; memcpy(config_ptr[n].name, cur_class->network_name, 16); memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8); + memcpy(config_ptr[n].destination_address, ADDR_LINK_LOCAL_PREFIX, 8); + memcpy(&config_ptr[n].destination_address[8], cur_class->extented_mac, 8); + config_ptr[n].destination_address[8] ^= 2; + config_ptr[n].destination_port = cur_class->commissioner_port; n++; } @@ -2023,7 +2044,7 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_ interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; - interface->thread_info->routerIdReqCoapID = 0; + interface->thread_info->routerIdRequested = false; interface->thread_info->networkDataRequested = false; interface->bootsrap_state_machine_cnt = 10; @@ -2128,6 +2149,12 @@ static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entr uint16_t my_short_address; uint8_t parent_mac64[8]; + // link sync is allowed only once in bootstrap start and we might get here in other cases also + if (!cur->thread_info->link_sync_allowed) { + return false; + } + cur->thread_info->link_sync_allowed = false; + int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address); if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err); @@ -2136,7 +2163,7 @@ static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entr link_info_err = thread_nvm_store_link_info_clear(); if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { tr_warning("thread_nvm_store_link_info_clear returned %d", link_info_err); - } + } if (thread_is_router_addr(my_short_address)) { thread_info(cur)->routerShortAddress = my_short_address; thread_dynamic_storage_build_mle_table(cur->id); @@ -2278,7 +2305,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur) thread_leader_service_leader_data_free(cur->thread_info); thread_bootstrap_all_nodes_multicast_unregister(cur); thread_data_base_init(cur->thread_info, cur->id); - thread_dhcp_client_delete(cur->id); + dhcp_client_delete(cur->id); thread_nd_service_delete(cur->id); thread_child_id_request_entry_clean(cur); thread_registered_mcast_addr_entry_clean(cur); @@ -2356,6 +2383,7 @@ static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cu if (cid == 16) { return -1; } + context.cid = cid; context.compression = true; context.stableData = stableData; @@ -2499,6 +2527,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1); genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1); genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1); + genericService.P_res1 = ((flags >> THREAD_P_ND_RES_BIT_MOVE) & 1); if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) { if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) { if (!genericService.P_slaac) { @@ -2525,7 +2554,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); common_write_16_bit(genericService.routerID, &addr[14]); tr_debug("Delete DHCPv6 given address"); - thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); + dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); } } @@ -2702,6 +2731,8 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur) thread_border_router_network_data_update_notify(cur); thread_bbr_network_data_update_notify(cur); + thread_maintenance_timer_set(cur, THREAD_MAINTENANCE_TIMER_INTERVAL); + return 0; } @@ -2744,7 +2775,6 @@ int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thr return 0; } - void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur) { // Route prefix is variable-length, so need to zero pad for ip6tos @@ -2794,6 +2824,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) { // don't add tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); + } else if (curBorderRouter->P_res1) { + ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, 0xffffffff, 0); } else { //add tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); @@ -2818,8 +2850,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); /* Do not allow multiple DHCP solicits from one prefix => delete previous */ - thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); - if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { + dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); + if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { tr_debug("GP Address Requested"); } } @@ -2839,6 +2871,10 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t * icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); } } + // generate address based on res1 bit + if (curBorderRouter->P_res1) { + thread_extension_dua_address_generate(cur,curPrefix->servicesPrefix,64); + } } // for each borderRouterList diff --git a/source/6LoWPAN/Thread/thread_bootstrap.h b/source/6LoWPAN/Thread/thread_bootstrap.h index 212f1ca0449..e45bb99a6f4 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_bootstrap.h @@ -106,6 +106,9 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, void thread_bootstrap_ready(struct protocol_interface_info_entry *cur); int thread_bootstrap_reset(struct protocol_interface_info_entry *cur); void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur); + +/* Function to remove linked neighbours for REEDs and FEDs */ +void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur); bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address); bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mac_neighbor_table_entry *entry_temp); void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur); @@ -191,7 +194,6 @@ int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period); void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp); - #else #define thread_interface_up(cur) ((void) 0) #define thread_bootstrap_state_machine(cur) ((void)0) diff --git a/source/6LoWPAN/Thread/thread_border_router_api.c b/source/6LoWPAN/Thread/thread_border_router_api.c index 8ca402db62b..83385243ce2 100644 --- a/source/6LoWPAN/Thread/thread_border_router_api.c +++ b/source/6LoWPAN/Thread/thread_border_router_api.c @@ -42,6 +42,7 @@ #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_common.h" +#include "6LoWPAN/Thread/thread_extension_bbr.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_storage.h" #include "6LoWPAN/Thread/thread_management_client.h" @@ -591,6 +592,15 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent thread_border_router_network_data_appl_callback(cur); } + +void thread_border_router_old_partition_data_clean(int8_t interface_id) +{ + thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); + if (this) { + coap_service_request_delete_by_service_id(this->coap_service_id); + } + thread_extension_bbr_old_partition_data_clean(interface_id); +} #endif // HAVE_THREAD_ROUTER /*External APIs*/ @@ -837,7 +847,6 @@ int thread_border_router_dns_search_list_option_set(int8_t interface_id, uint8_t static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len) { protocol_interface_info_entry_t *cur; - (void) status; (void) data_len; (void) data_ptr; @@ -846,7 +855,7 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st return; } - cur->thread_info->localServerDataBase.publish_active = false; + cur->thread_info->localServerDataBase.publish_coap_req_id = 0; tr_debug("BR a/sd response status: %s, addr: %x",status?"Fail":"OK", cur->thread_info->localServerDataBase.registered_rloc16); @@ -855,9 +864,11 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st thread_border_router_publish(cur->id); } - // always update RLOC to new one. If COAP response fails then resubmit timer will trigger new a/sd - cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); - cur->thread_info->localServerDataBase.release_old_address = false; + if (status == 0) { + // If request was successful, then update RLOC to new one. + cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); + cur->thread_info->localServerDataBase.release_old_address = false; + } } #endif @@ -884,21 +895,20 @@ int thread_border_router_publish(int8_t interface_id) rloc16 = mac_helper_mac16_address_get(cur); tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16); - if (cur->thread_info->localServerDataBase.publish_active) { + if (cur->thread_info->localServerDataBase.publish_coap_req_id) { if (rloc16 != cur->thread_info->localServerDataBase.registered_rloc16) { /* - * Device short address has changed, cancel previous a/sd and a/as requests + * Device short address has changed, cancel previous a/sd requests * and start resubmit timer * */ - tr_debug("address changed, kill pending reuqests"); - thread_management_client_pending_coap_request_kill(cur->id); + tr_debug("RLOC changed, kill pending a/sd request"); + thread_management_client_coap_message_delete(cur->id, cur->thread_info->localServerDataBase.publish_coap_req_id); thread_border_router_resubmit_timer_set(interface_id, 5); - return 0; } else { cur->thread_info->localServerDataBase.publish_pending = true; tr_debug("Activate pending status for publish"); - return 0; } + return 0; } //Allocate Memory for Data @@ -926,8 +936,10 @@ int thread_border_router_publish(int8_t interface_id) if (payload_ptr) { ns_dyn_mem_free(payload_ptr); } - if (ret_val == 0) { - cur->thread_info->localServerDataBase.publish_active = true; + if (ret_val > 0) { + // a/sd request successful, save coap request id + cur->thread_info->localServerDataBase.publish_coap_req_id = (uint16_t)ret_val; + ret_val = 0 ; } thread_border_router_resubmit_timer_set(interface_id, -1); diff --git a/source/6LoWPAN/Thread/thread_border_router_api_internal.h b/source/6LoWPAN/Thread/thread_border_router_api_internal.h index 9d7694a23e2..c1227173dd7 100644 --- a/source/6LoWPAN/Thread/thread_border_router_api_internal.h +++ b/source/6LoWPAN/Thread/thread_border_router_api_internal.h @@ -85,6 +85,14 @@ void thread_border_router_network_data_appl_callback(protocol_interface_info_ent * */ void thread_border_router_network_data_update_notify(protocol_interface_info_entry_t *cur); + +/** + * \brief Clear data related to old partition. + * + * \param interface_id Network interface ID. + */ +void thread_border_router_old_partition_data_clean(int8_t interface_id); + #else #define thread_border_router_init(interface_id) #define thread_border_router_delete(interface_id) @@ -92,6 +100,7 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent #define thread_border_router_resubmit_timer_set(interface_id, seconds) #define thread_border_router_network_data_appl_callback(cur) #define thread_border_router_network_data_update_notify(cur) +#define thread_border_router_old_partition_data_clean(interface_id) #endif #endif /* THREAD_BORDER_ROUTER_API_INTERNAL_H_ */ diff --git a/source/6LoWPAN/Thread/thread_commissioning_api.c b/source/6LoWPAN/Thread/thread_commissioning_api.c index a80a5ad58f1..f5815360ac7 100644 --- a/source/6LoWPAN/Thread/thread_commissioning_api.c +++ b/source/6LoWPAN/Thread/thread_commissioning_api.c @@ -35,6 +35,7 @@ #include "ns_list.h" #include "ns_trace.h" #include "nsdynmemLIB.h" +#include "randLIB.h" #include "common_functions.h" #include "ns_sha256.h" @@ -74,6 +75,8 @@ typedef NS_LIST_HEAD(device_t, link) device_list_t; typedef struct commissioner_entry { device_list_t device_list; uint8_t destination_address[16]; + uint8_t final_dest_address[16]; // Relay message final destination + uint8_t leader_address[16]; // leader ALOC for contacting the leader uint8_t PSKc_ptr[16]; thread_commissioning_status_cb *status_cb_ptr; uint16_t destination_port; @@ -82,7 +85,8 @@ typedef struct commissioner_entry { int8_t interface_id; int8_t coap_service_id; int8_t coap_secure_service_id; - int8_t coap_virtual_service_id; + int8_t coap_secure_virtual_service_id; + int8_t coap_udp_proxy_service_id; bool registered: 1; bool native_commissioner: 1; @@ -167,7 +171,7 @@ static commissioner_t *commissioner_find_by_service(int8_t service_id) { commissioner_t *this = NULL; ns_list_foreach(commissioner_t, cur_ptr, &instance_list) { - if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id) { + if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_secure_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id || cur_ptr->coap_udp_proxy_service_id == service_id) { this = cur_ptr; break; } @@ -237,12 +241,46 @@ static int commission_finalisation_resp_send(int8_t coap_service_id, device_t *d * Callback functions */ +static int thread_commissioning_active_get_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) +{ + commissioner_t *this = commissioner_find_by_service(service_id); + commissioning_state_e state = COMMISSIONING_STATE_REJECT;// Default is accept if we get error it is rejected + uint8_t *ptr; + uint16_t len; + (void) source_address; + (void) source_port; + + /* Transaction failed */ + if (!response_ptr) { + return -1; + } + + tr_debug("management get response from comm module"); + if (!this) { + return -2; + } + + if ((len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr)) > 0) { + state = COMMISSIONING_STATE_ACCEPT; + tr_debug(" TLV ml prefix=%s\r\n", trace_array(ptr, len)); + memcpy(this->leader_address, ptr, 8); + memcpy(this->leader_address + 8, ADDR_SHORT_ADR_SUFFIC, 6); + common_write_16_bit(0xfc00, this->leader_address + 14); + } + + if (this->status_cb_ptr) { + this->status_cb_ptr(this->interface_id, this->session_id, state); + } + return 0; +} + static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) { commissioner_t *this = commissioner_find_by_service(service_id); commissioning_state_e state = COMMISSIONING_STATE_REJECT; uint16_t session_id = 0; - uint8_t *ptr; + uint8_t *ptr = NULL; + char *uri_ptr = THREAD_URI_ACTIVE_GET; (void) source_address; (void) source_port; @@ -267,6 +305,16 @@ static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t sour } tr_debug("petition response session_id: %d state:%d",session_id, state); + // if registered and native commissioner send ACTIVE_GET to BBR to get mesh parameters + // if not native set leader ALOC from stack + if (this->native_commissioner) { + coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb); + return 0; + } else { + thread_management_get_leader_aloc(this->interface_id, this->leader_address); + } + user_response: if (state == COMMISSIONING_STATE_REJECT) { thci_trace("commissionerPetitionRejected"); @@ -376,10 +424,54 @@ static int commission_dataset_changed_notify_recv_cb(int8_t service_id, uint8_t (void)source_port; tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address)); + commissioner_t *this = commissioner_find_by_service(service_id); + + if (!this) { + return -1; + } + + coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ACTIVE_GET, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb); + coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0); return 0; } +static int thread_commission_udp_proxy_receive_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) +{ + tr_debug("Recv UDP_RX.ntf"); + + commissioner_t *this = commissioner_find_by_service(service_id); + uint8_t *udp_encapsulation_ptr, *udp_tmf_ptr; + uint16_t udp_encapsulation_len, udp_tmf_len; + uint8_t *ipv6_addr_ptr; + uint16_t ipv6_addr_len; + uint16_t dest_port; + + (void) source_port; + + if (!this || !source_address || !request_ptr) { + return -1; // goto error response + } + + udp_encapsulation_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_UDP_ENCAPSULATION, &udp_encapsulation_ptr); + ipv6_addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_IPV6_ADDRESS, &ipv6_addr_ptr); + + if (udp_encapsulation_len == 0 || ipv6_addr_len < 16) { + tr_warn("Corrupted UDP_RX.ntf received (%d, %d)", udp_encapsulation_len, ipv6_addr_len); + return -1; + } + + dest_port = common_read_16_bit(udp_encapsulation_ptr + 2); + udp_tmf_len = udp_encapsulation_len - 4; + udp_tmf_ptr = udp_encapsulation_ptr + 4; + + tr_debug("UDP_RX tmf: %s", trace_array(udp_tmf_ptr, udp_tmf_len)); + + coap_service_virtual_socket_recv(this->coap_udp_proxy_service_id, ipv6_addr_ptr, dest_port, udp_tmf_ptr, udp_tmf_len); + + return -1; // no response sent +} static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t device_list, int *steering_tlv_max_length) { @@ -403,6 +495,35 @@ static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t d return bloom_filter_ptr; } +static int thread_commissioner_set_steering_data(commissioner_t *this, uint16_t session_id, uint8_t *steering_data_ptr, uint8_t steering_data_len) +{ + uint8_t payload[24];/* 4 + 16 + 4*/ + uint8_t *ptr; + int8_t coap_service_id; + if (!this || steering_data_len > 16) { + return -1; + } + + ptr = payload; + ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_STEERING_DATA, steering_data_len, steering_data_ptr); + ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id); + + tr_debug("thread commissioner set steering data %s", trace_array(steering_data_ptr, steering_data_len)); + memcpy(this->final_dest_address, this->leader_address,16); + //default uri for thread version 1.1 + char *uri = THREAD_URI_COMMISSIONER_SET; + + if (this->native_commissioner) { + coap_service_id = this->coap_udp_proxy_service_id; + } else { + coap_service_id = this->coap_service_id; + } + + coap_service_request_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL); + + return 0; +} static int commission_steering_data_update(commissioner_t *this) { @@ -414,7 +535,7 @@ static int commission_steering_data_update(commissioner_t *this) //bloom filter calculation function call bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length); tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16)); - ret = thread_management_set_steering_data(this->management_instance, this->session_id,bloom_filter_ptr, steering_tlv_length, NULL); + ret = thread_commissioner_set_steering_data(this, this->session_id,bloom_filter_ptr, steering_tlv_length); if (ret) { tr_warn("Steering data set failed %d", ret); return -1; @@ -475,7 +596,7 @@ static int commission_relay_rx_recv_cb(int8_t service_id, uint8_t source_address tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8)); } device_ptr->joiner_router_rloc = joiner_router_rloc; - coap_service_virtual_socket_recv(this->coap_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); + coap_service_virtual_socket_recv(this->coap_secure_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); return -1; // no response sent } @@ -616,20 +737,55 @@ static int commissioner_br_security_done_cb(int8_t service_id, uint8_t address[1 return 0; } -static int thread_commissioning_remote_addr_set(commissioner_t *this) +static int thread_commission_udp_proxy_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len) { - if (0 == thread_management_get_leader_address(this->interface_id, this->destination_address)) { - tr_debug("on-mesh commissioner"); - this->destination_port = THREAD_MANAGEMENT_PORT; - this->native_commissioner = false; - } else if (0 == thread_commissioning_native_commissioner_get_connection_info(this->interface_id, - this->destination_address, &this->destination_port)) { - tr_debug("native commissioner"); - this->native_commissioner = true; - } else { - tr_error("No remote address"); + (void) port; + uint8_t *payload_ptr; + uint8_t *ptr; + uint16_t payload_len; + uint16_t source_port; + + commissioner_t *this = commissioner_find_by_service(service_id); + if (!this) { + return -1; + } + + tr_debug("UDP_TX.ntf tmf: %s", trace_array(data_ptr, data_len)); + if (!this || !destination_addr_ptr || !data_ptr) { return -1; } + + payload_len = 2 + THREAD_IPV6_ADDRESS_TLV_LENGTH + 4 + 4 + data_len; // MESHCOP_TLV_IPV6_ADDRESS + MESHCOP_TLV_UDP_ENCAPSULATION + + payload_ptr = ns_dyn_mem_alloc(payload_len); + if (!payload_ptr) { + return -3; + } + + ptr = payload_ptr; + + tr_debug("br_address %s final dest_address %s and port %d", trace_ipv6(this->destination_address), + trace_ipv6(this->final_dest_address), this->destination_port); + + /* MESHCOP_TLV_IPV6_ADDRESS */ + ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_IPV6_ADDRESS, THREAD_IPV6_ADDRESS_TLV_LENGTH, this->final_dest_address); + + /* MESHCOP_TLV_UDP_ENCAPSULATION */ + *ptr++ = MESHCOP_TLV_UDP_ENCAPSULATION; + *ptr++ = 0xff; + ptr = common_write_16_bit(2 + 2 + data_len, ptr); // length (Port x 2 + TMF message) + source_port = randLIB_get_16bit(); // ephemeral port, 16-bit number + ptr = common_write_16_bit(source_port, ptr); // source port, + ptr = common_write_16_bit(THREAD_MANAGEMENT_PORT, ptr); // destination port + memcpy(ptr, data_ptr, data_len); + ptr += data_len; + + /* Send UDP_TX.ntf */ + coap_service_request_send(this->coap_secure_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, + COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_UDP_TRANSMIT_NOTIFICATION, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); + + ns_dyn_mem_free(payload_ptr); + return 0; } @@ -638,16 +794,17 @@ Public api functions */ int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) { - if (commissioner_find(interface_id)) { - return -1; + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + this = commissioner_create(interface_id); } - commissioner_t *this = commissioner_create(interface_id); if (!this) { return -2; } memcpy(this->PSKc_ptr,PSKc,16); - - this->management_instance = thread_management_register(interface_id); + if (this->registered) { + return 0; + } this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb); @@ -655,10 +812,15 @@ int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb); coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); + coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_UDP_RECVEIVE_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_commission_udp_proxy_receive_cb); + + this->coap_secure_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb); + coap_service_register_uri(this->coap_secure_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb); + coap_service_virtual_socket_set_cb(this->coap_secure_virtual_service_id, commission_virtual_socket_send_cb); + + this->coap_udp_proxy_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, NULL, NULL); + coap_service_virtual_socket_set_cb(this->coap_udp_proxy_service_id, thread_commission_udp_proxy_virtual_socket_send_cb); - this->coap_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb); - coap_service_register_uri(this->coap_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb); - coap_service_virtual_socket_set_cb(this->coap_virtual_service_id, commission_virtual_socket_send_cb); return 0; } @@ -672,11 +834,11 @@ int thread_commissioning_unregister(int8_t interface_id) // Unregister the commissioner thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT); } - thread_management_unregister(this->management_instance); coap_service_delete(this->coap_service_id); coap_service_delete(this->coap_secure_service_id); - coap_service_delete(this->coap_virtual_service_id); + coap_service_delete(this->coap_secure_virtual_service_id); + coap_service_delete(this->coap_udp_proxy_service_id); commissioner_delete(this); return 0; @@ -690,7 +852,6 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_ uint8_t service_id; uint8_t *ptr; char *uri_ptr; - this = commissioner_find(interface_id); if (!this) { @@ -705,16 +866,14 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_ return -3; } - if (thread_commissioning_remote_addr_set(this)) { - return -4; - } - if (this->native_commissioner) { uri_ptr = THREAD_URI_COMMISSIONER_PETITION; service_id = this->coap_secure_service_id; } else { uri_ptr = THREAD_URI_LEADER_PETITION; service_id = this->coap_service_id; + thread_management_get_leader_aloc(this->interface_id, this->destination_address); + this->destination_port = THREAD_MANAGEMENT_PORT; } this->status_cb_ptr = status_cb_ptr; @@ -747,16 +906,13 @@ int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_ return -1; } - if (thread_commissioning_remote_addr_set(this)) { - return -4; - } - if (this->native_commissioner) { uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE; service_id = this->coap_secure_service_id; } else { uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE; service_id = this->coap_service_id; + thread_management_get_leader_aloc(this->interface_id, this->destination_address); } ptr = payload; @@ -867,6 +1023,20 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh return cur_ptr; } +int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port) +{ + tr_debug("start ethernet commissioner attach"); + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + return -1; + } + memcpy(this->destination_address, destination_address,16); + this->destination_port = destination_port; + this->native_commissioner = true; + return 0; + +} + int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr) { protocol_interface_info_entry_t *cur; @@ -909,6 +1079,18 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread return -2; } *cur->thread_info->native_commissioner_link = *link_ptr; + + commissioner_t *this = commissioner_find(interface_id); + if (!this) { + this = commissioner_create(interface_id); + } + if (!this) { + return -3; + } + + this->native_commissioner = true; + memcpy(this->destination_address, link_ptr->destination_address,16); + this->destination_port = link_ptr->destination_port; //TODO check that we are scanning for networks and reset backup timers return 0; @@ -916,22 +1098,15 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port) { - protocol_interface_info_entry_t *cur; - cur = protocol_stack_interface_info_get_by_id(interface_id); + commissioner_t *this = commissioner_find(interface_id); tr_debug("get native connection info"); - if(!cur || !cur->thread_info) { + if (!this) { return -1; } - if (thread_attach_ready(cur) != 0) { - return -2; - } - if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, address_ptr) != 0) { - return -1; - } - if (port) { - *port = cur->thread_info->native_commissioner_port; - } + memcpy(address_ptr,this->destination_address,16); + + *port = this->destination_port; return 0; } @@ -1031,4 +1206,11 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread return -1; } +int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port) { + (void)interface_id; + (void)destination_address; + (void)destination_port; + return -1; +} + #endif diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index 0716d79cf7a..567851ecb4b 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -44,9 +44,11 @@ #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_beacon.h" +#include "6LoWPAN/Thread/thread_diagnostic.h" +#include "6LoWPAN/Thread/thread_extension_bbr.h" #include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_routing.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_router_bootstrap.h" @@ -60,6 +62,7 @@ #include "6LoWPAN/Thread/thread_management_internal.h" #include "6LoWPAN/Thread/thread_management_client.h" #include "6LoWPAN/Thread/thread_management_server.h" +#include "6LoWPAN/Thread/thread_resolution_server.h" #include "6LoWPAN/Thread/thread_resolution_client.h" #include "6LoWPAN/Thread/thread_address_registration_client.h" #include "6LoWPAN/Thread/thread_resolution_client.h" @@ -226,6 +229,7 @@ int8_t thread_bootstrap_up(protocol_interface_info_entry_t *cur) ret_val = nwk_6lowpan_up(cur); cur->nwk_nd_re_scan_count = 0; + cur->thread_info->link_sync_allowed = true; return ret_val; } @@ -258,9 +262,11 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur) thread_leader_mleid_rloc_map_to_nvm_write(cur); thread_bootstrap_stop(cur); mle_service_interface_unregister(cur->id); + thread_diagnostic_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id + thread_management_client_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id + thread_nd_service_disable(cur->id); // delete before thread_management_server_delete as they share same coap_service id thread_management_server_delete(cur->id); thread_joiner_application_deinit(cur->id); - thread_management_client_delete(cur->id); //free network Data thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage); //free local also here @@ -451,7 +457,7 @@ void thread_data_base_init(thread_info_t *thread_info, int8_t interfaceId) thread_leader_commissioner_create(thread_info); thread_info->rfc6775 = false; thread_info->threadPrivatePrefixInfo.ulaValid = false; - thread_info->routerIdReqCoapID = 0; + thread_info->routerIdRequested = false; thread_info->networkDataRequested = false; thread_info->proactive_an_timer = 0; @@ -905,6 +911,7 @@ static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur, if (cur->thread_info->childUpdateReqTimer == -1) { return; } + if (cur->thread_info->childUpdateReqTimer > seconds) { cur->thread_info->childUpdateReqTimer -= seconds; } else { @@ -945,6 +952,20 @@ static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16 } } +static void thread_maintenance_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) +{ + if (thread_info(cur)->thread_maintenance_timer) { + if (thread_info(cur)->thread_maintenance_timer > seconds) { + thread_info(cur)->thread_maintenance_timer -= seconds; + return; + } + } + + thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL ; + + thread_bootstrap_network_data_activate(cur); +} + void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) { uint8_t leader_address[16]; @@ -1003,6 +1024,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) } thread_router_bootstrap_timer(cur, ticks); + thread_maintenance_timer(cur, ticks); thread_border_router_seconds_timer(cur->id, ticks); thread_bbr_seconds_timer(cur->id, ticks); thread_lowpower_timer(cur, ticks); @@ -1720,9 +1742,105 @@ uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entr return ptr; } +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return false; + } + + // check for addresses + ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { + if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL + && !thread_addr_is_mesh_local_16(e->address, cur))) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (!ctx) { + return true; + } + if (ctx->cid != 0) { + return true; + + } + } + } + + // check for multicast groups + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); + ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) + { + if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) { + /* Skip solicited node multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { + /* Skip well-known realm-local all Thread nodes multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) { + /* Skip well-known link-local all Thread nodes multicast address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { + /* Skip All MPL Forwarders address */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_NODES)) { + /* Skip Mesh local all nodes */ + continue; + } + if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_ROUTERS)) { + /* Skip Mesh local all routers */ + continue; + } + return true; + } + return false; +} + +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) +{ + lowpan_context_t *ctx; + uint8_t *address_len_ptr; + + if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE && + thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) { + // No address registration for others than MED or SED + return ptr; + } + *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION; + address_len_ptr = ptr++; + + *address_len_ptr = 0; + + ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { + + if (*address_len_ptr > 148 ) { + // Maximum length of address registrations + continue; + } + if (!thread_addr_is_mesh_local_16(e->address, cur)) { + ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address); + if (ctx && ctx->cid == 0) { + //Write TLV to list + *ptr++ = (ctx->cid | 0x80); + memcpy(ptr, e->address + 8, 8); + ptr += 8; + *address_len_ptr += 9; + } + } + } + return ptr; +} + uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) { uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; lowpan_context_t *ctx; uint8_t *address_len_ptr; @@ -1738,7 +1856,6 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_ // Register all global addressess ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { - if (*address_len_ptr > 148 ) { // Maximum length of address registrations continue; @@ -1762,23 +1879,27 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_ } /* Registers multicast addresses to the parent */ - thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); - + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) { if (*address_len_ptr > 148) { // Maximum length of address registrations continue; } - if (addr_ipv6_multicast_scope(entry->group) < IPV6_SCOPE_REALM_LOCAL) { - /* Skip Link Local multicast address */ + + if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) { + /* Skip solicited node multicast address */ continue; } - if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { /* Skip well-known realm-local all Thread nodes multicast address */ continue; } + if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) { + /* Skip well-known link-local all Thread nodes multicast address */ + continue; + } if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { /* Skip All MPL Forwarders address */ continue; @@ -1935,9 +2056,34 @@ static void thread_address_notification_cb(struct protocol_interface_info_entry } } -void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added) +static bool thread_mcast_should_register_address(struct protocol_interface_info_entry *cur, uint8_t *addr) { + uint8_t thread_realm_local_mcast_addr[16]; + uint8_t thread_ll_unicast_prefix_based_mcast_addr[16]; + thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL); + thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL); + if (addr_ipv6_multicast_scope(addr) >= IPV6_SCOPE_LINK_LOCAL) { + if (memcmp(addr, ADDR_MULTICAST_SOLICITED, 13) == 0) { + return false; + } + if (memcmp(addr, thread_realm_local_mcast_addr, 16) == 0) { + return false; + } + if (memcmp(addr, thread_ll_unicast_prefix_based_mcast_addr, 16) == 0) { + return false; + } + if (memcmp(addr, ADDR_LINK_LOCAL_ALL_NODES, 16) == 0) { + return false; + } + if (memcmp(addr, ADDR_LINK_LOCAL_ALL_ROUTERS, 16) == 0) { + return false; + } + } + return true; +} +void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added) +{ if (thread_attach_ready(interface) != 0) { return; } @@ -1946,7 +2092,7 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if (thread_bootstrap_should_register_address(interface)) { /* Trigger Child Update Request only if MTD child's multicast address change */ - if (addr_ipv6_multicast_scope(group->group) > IPV6_SCOPE_LINK_LOCAL) { + if (thread_mcast_should_register_address(interface, group->group)) { interface->thread_info->childUpdateReqTimer = 1; } } else { @@ -1956,10 +2102,16 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface, } } +static void thread_old_partition_data_clean(int8_t interface_id) +{ + thread_management_client_old_partition_data_clean(interface_id); + thread_border_router_old_partition_data_clean(interface_id); +} + void thread_partition_data_purge(protocol_interface_info_entry_t *cur) { /* Partition has been changed. Wipe out data related to old partition */ - thread_management_client_pending_coap_request_kill(cur->id); + thread_old_partition_data_clean(cur->id); /* Reset previous routing information */ thread_routing_reset(&cur->thread_info->routing); @@ -1967,6 +2119,9 @@ void thread_partition_data_purge(protocol_interface_info_entry_t *cur) /* Flush address cache */ ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); + /* Remove linked neighbours for REEDs and FEDs */ + thread_reed_fed_neighbour_links_clean(cur); + } bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) @@ -1997,5 +2152,10 @@ void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index); } +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay) +{ + thread_info(cur)->thread_maintenance_timer = delay; +} + #endif diff --git a/source/6LoWPAN/Thread/thread_common.h b/source/6LoWPAN/Thread/thread_common.h index 09ffce3900f..6e849529875 100644 --- a/source/6LoWPAN/Thread/thread_common.h +++ b/source/6LoWPAN/Thread/thread_common.h @@ -309,10 +309,10 @@ typedef struct thread_info_s { uint16_t routerShortAddress; uint16_t reedJitterTimer; uint16_t reedMergeAdvTimer; - uint16_t routerIdReqCoapID; // COAP msg id of RouterID request int16_t childUpdateReqTimer; uint16_t childUpdateReqMsgId; uint16_t proactive_an_timer; + uint16_t thread_maintenance_timer; //uint8_t lastValidRouteMask[8]; int8_t interface_id; //Thread Interface ID uint8_t version; @@ -322,11 +322,13 @@ typedef struct thread_info_s { bool rfc6775: 1; bool requestFullNetworkData: 1; bool leaderCab: 1; + bool routerIdRequested: 1; bool releaseRouterId: 1; bool networkSynch: 1; bool networkDataRequested: 1; bool end_device_link_synch: 1; bool router_mc_addrs_registered: 1; + bool link_sync_allowed:1; bool leader_synced:1; // flag used by leader after restart } thread_info_t; @@ -397,6 +399,11 @@ void thread_child_mcast_entries_remove(protocol_interface_info_entry_t *cur, con uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur); uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); + +// returns true if SED/MED needs to register additional address to parent +bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur); +// write mesh local address tlv +uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64); thread_leader_info_t *thread_allocate_and_init_leader_private_data(void); thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality); @@ -441,6 +448,7 @@ bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_ void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index); bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf); +void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay); #else // HAVE_THREAD NS_DUMMY_DEFINITIONS_OK diff --git a/source/6LoWPAN/Thread/thread_config.h b/source/6LoWPAN/Thread/thread_config.h index 0db796cd5d9..cd7406d6eba 100644 --- a/source/6LoWPAN/Thread/thread_config.h +++ b/source/6LoWPAN/Thread/thread_config.h @@ -326,6 +326,17 @@ */ #define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST +/* + * Number of destination and neighbor cache entries assuming 250 thread devices (worst case) connecting to cloud service. + * Six entries reserved for backbone devices. + */ +#define THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE 256 + +/* + * Timeout to solicit address from DHCP if previous request fails. + */ +#define THREAD_MAINTENANCE_TIMER_INTERVAL 300 + /** * Build time flag to enable THCI special traces for test harness purposes */ diff --git a/source/6LoWPAN/Thread/thread_constants.h b/source/6LoWPAN/Thread/thread_constants.h index 4150f4cc237..971a1fa1c97 100644 --- a/source/6LoWPAN/Thread/thread_constants.h +++ b/source/6LoWPAN/Thread/thread_constants.h @@ -145,6 +145,7 @@ #define THREAD_DEFAULT_KEY_SWITCH_GUARD_TIME 624 // Hours #define THREAD_DEFAULT_KEY_ROTATION 672 // Hours #define THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL 50000 // Default thread commissioner keep-alive message interval (milliseconds) +#define THREAD_DELAY_JOIN_ENT 50 // Minimum delay for Joiner router before sending joiner entrust (milliseconds) #define THREAD_FAILED_CHILD_TRANSMISSIONS 4 #define THREAD_FAILED_ROUTER_TRANSMISSIONS 4 diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_client.h b/source/6LoWPAN/Thread/thread_dhcpv6_client.h deleted file mode 100644 index cc97006e05a..00000000000 --- a/source/6LoWPAN/Thread/thread_dhcpv6_client.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2014-2015, 2017, Arm Limited and affiliates. - * SPDX-License-Identifier: BSD-3-Clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ -#define SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ - -#include - -/* Thread DHCP client implementation. - * - * Responsibilities of this module are: - * - send router id address request and receive new router address and inform it to thread bootstrap. - * - handle Global address queries and refresh inside thread network. - * - */ - -/* Initialize dhcp thread dhcp client. - * - * This instance needs to bee initialized once for each thread network interface. - * if only one thread instance is supported this is needed to call only once. - * - * /param interface interface id of this thread instance. - * - */ - -void thread_dhcp_client_init(int8_t interface); - -/* Delete dhcp thread dhcp client. - * - * When this is called all addressed assigned by this module are removed from stack. - */ -void thread_dhcp_client_delete(int8_t interface); - -/* Global address handler. - * - * This module updates the addresses from dhcp server and sets them in stack. - * this module makes refresh of address when needed. - * - */ - - -/* give dhcp server and prefix for global address assignment - * - * /param interface interface where address is got - * /param dhcp_addr dhcp server ML16 address where address is registered. - * /param prefix dhcp server ML16 address where address is registered. - * /param mac64 64 bit mac address for identifieng client. - * /param error_cb error callback that is called if address cannot be created or becomes invalid. - * /param register_status true if address registered. - * - */ -typedef void (thread_dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status); - -int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb); - -/* Renew all leased adddresses might be used when short address changes - * - * /param interface interface where address is got - */ -void thread_dhcp_client_global_address_renew(int8_t interface); - -/* Delete address from device - * if prefix is NULL all are deleted - * - * /param interface interface where address is got - * /param prefix dhcp server ML16 address where address is registered. - * - */ -void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]); - -#endif /* SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ */ diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_server.c b/source/6LoWPAN/Thread/thread_dhcpv6_server.c new file mode 100644 index 00000000000..f0c8f6dafe2 --- /dev/null +++ b/source/6LoWPAN/Thread/thread_dhcpv6_server.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "nsconfig.h" +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) +#include +#include +#include "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "common_functions.h" +#include "ns_trace.h" +#include "NWK_INTERFACE/Include/protocol.h" +#include "ipv6_stack/protocol_ipv6.h" +#include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ipv6.h" +#include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_bbr_api_internal.h" + +#define TRACE_GROUP "thds" + +static void thread_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress) +{ + ipv6_neighbour_t *neighbour_entry; + + neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress); + if (neighbour_entry) { + tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress)); + ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); + } +} + +static void thread_dhcp_address_prefer_remove_cb(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info) +{ + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId); + if (!curPtr) { + return; + } + if (!targetAddress) { + //Clear All targets routes + ipv6_route_table_remove_info(interfaceId, ROUTE_THREAD_PROXIED_HOST,prefix_info); + } else { + tr_debug("Address Preferred Timeout"); + ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST); + thread_service_remove_GUA_from_neighcache(curPtr, targetAddress); + + } + +} + +static bool thread_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src) +{ + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId); + if (!curPtr) { + return false; + } + + // If this is solicit from existing address, flush ND cache. + if (address_info->allocatedNewAddress) { + // coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return + thread_service_remove_GUA_from_neighcache(curPtr, address_info->allocatedAddress); + } + + if (thread_bbr_nd_entry_add(interfaceId,address_info->allocatedAddress, address_info->validLifeTime, route_src) == -1) { + // No nanostack BBR present we will put entry for application implemented BBR + ipv6_route_t *route = ipv6_route_add_with_info(address_info->allocatedAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,route_src,0, address_info->validLifeTime, 0); + if (!route) { + return false; + } + + } + return true; +} + +int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne) +{ + if (DHCPv6_server_service_init(interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + return -1; + } + //Register Callbacks + DHCPv6_server_service_callback_set(interface_id, prefix, thread_dhcp_address_prefer_remove_cb, thread_dhcp_address_add_cb); + //SET Timeout + DHCPv6_server_service_set_address_validlifetime(interface_id, prefix, validLifeTimne); + + return 0; +} + +#endif diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_server.h b/source/6LoWPAN/Thread/thread_dhcpv6_server.h new file mode 100644 index 00000000000..b8e56a63f0b --- /dev/null +++ b/source/6LoWPAN/Thread/thread_dhcpv6_server.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREAD_DHCPV6_SERVER_H_ +#define THREAD_DHCPV6_SERVER_H_ +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) +int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne); +#else +#define thread_dhcp6_server_init(interface_id, prefix, eui64, validLifeTimne) (-1) +#endif + + +#endif /* THREAD_DHCPV6_SERVER_H_ */ diff --git a/source/6LoWPAN/Thread/thread_diagnostic.c b/source/6LoWPAN/Thread/thread_diagnostic.c index fdce83ece82..33e1b419c3d 100644 --- a/source/6LoWPAN/Thread/thread_diagnostic.c +++ b/source/6LoWPAN/Thread/thread_diagnostic.c @@ -35,6 +35,7 @@ #include "nsdynmemLIB.h" #include "net_interface.h" #include "thread_management_if.h" +#include "thread_management_server.h" #include "thread_common.h" #include "thread_joiner_application.h" #include "thread_leader_service.h" @@ -229,6 +230,10 @@ static int thread_diagnostic_configuration_calc(protocol_interface_info_entry_t payload_len += 2+1; break; + case DIAGCOP_TLV_MAX_CHILD_TIMEOUT: + payload_len += 2 + 4; + break; + default: // todo: Other TLV's not supported atm break; @@ -254,6 +259,7 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur uint8_t *ptr; int written_address_count = 0; uint16_t ipv6_address_count = 0; + uint32_t max_child_timeout = 0; uint8_t extended_address[8] = {0}; arm_net_interface_address_list_size(cur->id, &ipv6_address_count); @@ -352,6 +358,12 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_CHANNEL_PAGES, 0); break; + case DIAGCOP_TLV_MAX_CHILD_TIMEOUT: + if (thread_router_bootstrap_child_max_timeout_get(cur, &max_child_timeout) == 0) { + response_ptr = thread_diagcop_tlv_data_write_uint32(response_ptr, DIAGCOP_TLV_MAX_CHILD_TIMEOUT, max_child_timeout); + } + break; + default: break; @@ -532,7 +544,7 @@ int thread_diagnostic_init(int8_t interface_id) this->interface_id = interface_id; - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); if (this->coap_service_id < 0) { tr_error("Thread diagnostic init failed"); ns_dyn_mem_free(this); @@ -556,8 +568,9 @@ int thread_diagnostic_delete(int8_t interface_id) if (!this) { return -1; } - - coap_service_delete(this->coap_service_id); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_REQUEST); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_RESET); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_QUERY); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); return 0; diff --git a/source/6LoWPAN/Thread/thread_extension.h b/source/6LoWPAN/Thread/thread_extension.h index 671ea9823c8..b6f64d1e909 100644 --- a/source/6LoWPAN/Thread/thread_extension.h +++ b/source/6LoWPAN/Thread/thread_extension.h @@ -46,19 +46,15 @@ void thread_extension_allocate(protocol_interface_info_entry_t *cur); void thread_extension_free(protocol_interface_info_entry_t *cur); void thread_extension_init(int8_t interface_id, int8_t coap_service_id); void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur); -int thread_extension_network_prefix_get(int8_t interface_id, uint8_t *options_ptr, uint8_t *prefix_ptr, uint8_t *prefix_len); void thread_extension_network_data_process(struct protocol_interface_info_entry *cur); int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr); void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected); -void thread_extension_address_generate(protocol_interface_info_entry_t *cur); +void thread_extension_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len); void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur); bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16); void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t *interface); void thread_extension_address_registration_trigger(protocol_interface_info_entry_t *interface); -void thread_extension_route_set(protocol_interface_info_entry_t *cur); -void thread_extension_activate(protocol_interface_info_entry_t *cur); bool thread_extension_enabled(protocol_interface_info_entry_t *cur); -bool thread_extension_context_can_delete(int8_t id, uint8_t servicesPrefix[16], uint8_t context_prefix_length); bool thread_extension_version_check(uint8_t version); void thread_extension_discover_response_read(struct discovery_response_list *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len); void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy); @@ -70,35 +66,31 @@ uint8_t thread_extension_discover_response_len(protocol_interface_info_entry_t * uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr); #else -#define thread_extension_joining_enabled(interface_id) false -#define thread_extension_discover_response_len(cur) 0 +#define thread_extension_joining_enabled(interface_id) (false) +#define thread_extension_discover_response_len(cur) (0) #define thread_extension_discover_response_write(cur, ptr) (ptr) #endif //HAVE_THREAD_ROUTER #else -#define thread_extension_allocate(cur) -#define thread_extension_free(cur) -#define thread_extension_init(interface_id,coap_service_id) -#define thread_extension_network_prefix_get(interface_id,options_ptr,prefix_ptr,prefix_len) (-1) -#define thread_extension_network_data_process(cur) +#define thread_extension_allocate(cur) ((void) 0) +#define thread_extension_free(cur) ((void) 0) +#define thread_extension_init(interface_id,coap_service_id) ((void) 0) +#define thread_extension_network_data_process(cur) ((void) 0) #define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1) -#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) -#define thread_extension_address_generate(cur) -#define thread_extension_aloc_generate(cur) -#define thread_extension_aloc_map(cur, addr16) false -#define thread_extension_mcast_subscrition_change(interface) -#define thread_extension_route_set(cur) -#define thread_extension_activate(cur) +#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) ((void) 0) +#define thread_extension_aloc_generate(cur) ((void) 0) +#define thread_extension_aloc_map(cur, addr16) (false) +#define thread_extension_mcast_subscrition_change(interface) ((void) 0) #define thread_extension_enabled(cur) (false) #define thread_extension_version_check(version) (false) -#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) -#define thread_extension_discover_response_tlv_write(data, version, extension_bit) (data) -#define thread_extension_service_init(cur) 0 -#define thread_extension_joining_enabled(interface_id) false -#define thread_extension_discover_response_len(cur) 0 +#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) ((void) 0) +#define thread_extension_discover_response_tlv_write(data, version, securityPolicy) ((void) 0) +#define thread_extension_service_init(cur) (0) +#define thread_extension_joining_enabled(interface_id) (false) +#define thread_extension_discover_response_len(cur) (0) #define thread_extension_discover_response_write(cur, ptr) (ptr) -#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) -#define thread_extension_context_can_delete(id, servicesPrefix, context_prefix_length) false +#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) ((void) 0) +#define thread_extension_dua_address_generate(cur, domain_prefix, domain_prefix_len) ((void) 0) #endif #ifdef __cplusplus diff --git a/source/6LoWPAN/Thread/thread_extension_bbr.h b/source/6LoWPAN/Thread/thread_extension_bbr.h index cad08464b09..153a82bac22 100644 --- a/source/6LoWPAN/Thread/thread_extension_bbr.h +++ b/source/6LoWPAN/Thread/thread_extension_bbr.h @@ -52,10 +52,12 @@ int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_ void thread_extension_bbr_delete(int8_t interface_id); bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc); void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds); +int thread_extension_bbr_sequence_number_set(int8_t interface_id, uint8_t seq_number); int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port); void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur); int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); +void thread_extension_bbr_old_partition_data_clean(int8_t interface_id); #else @@ -67,7 +69,9 @@ int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); #define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay) #define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1) #define thread_extension_bbr_route_update(cur) +#define thread_extension_bbr_sequence_number_set(interface_id, seq_number) (-1) #define thread_extension_bbr_prefix_set(interface_id, prefix) 0 +#define thread_extension_bbr_old_partition_data_clean(interface_id) #endif #ifdef __cplusplus diff --git a/source/6LoWPAN/Thread/thread_extension_bootstrap.h b/source/6LoWPAN/Thread/thread_extension_bootstrap.h index e83b3d359cd..e6132ccdd99 100644 --- a/source/6LoWPAN/Thread/thread_extension_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_extension_bootstrap.h @@ -45,6 +45,8 @@ extern "C" { #define thread_extension_bootstrap_thread_name_length_get(cur) (0) #define thread_extension_bootstrap_thread_name_ptr_get(cur) (NULL) #define thread_extension_bootstrap_network_certificate_enable(cur, coap_service_id) (NULL) +#define thread_extension_bootstrap_reenrollment_start(cur, service_id, pbbr_addr) (-1) +#define thread_extension_bootstrap_network_reattach(interface_id, timeout) (-1) #ifdef __cplusplus } diff --git a/source/6LoWPAN/Thread/thread_host_bootstrap.c b/source/6LoWPAN/Thread/thread_host_bootstrap.c index 50366616120..a6cb6b5dbf4 100644 --- a/source/6LoWPAN/Thread/thread_host_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_host_bootstrap.c @@ -121,11 +121,11 @@ static void thread_network_data_clean(protocol_interface_info_entry_t *cur) static void thread_merge_prepare(protocol_interface_info_entry_t *cur) { + thread_partition_data_purge(cur); thread_clean_old_16_bit_address_based_addresses(cur); mpl_clear_realm_scope_seeds(cur); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL); - thread_partition_data_purge(cur); thread_network_data_clean(cur); cur->nwk_mode = ARM_NWK_GP_IP_MODE; } @@ -305,6 +305,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent uint16_t address16; uint32_t llFrameCounter; thread_leader_data_t leaderData; + mle_tlv_info_t addressRegisteredTlv; mac_neighbor_table_entry_t *entry_temp; bool new_entry_created; @@ -320,6 +321,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent // Address // MLE_TYPE_SRC_ADDRESS // MLE_TYPE_LEADER_DATA + // MLE_TYPE_ADDRESS_REGISTRATION if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) || @@ -329,6 +331,25 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent return -1; } + if (!(mode & THREAD_DEVICE_FED)) { + // check for presence of Address registration TLV for MTDs + if (!mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, ptr, data_length, &addressRegisteredTlv) || + (addressRegisteredTlv.tlvLen == 0)) { + tr_debug("MTD missed address registration TLV - reattach"); + return -1; + } + } + + // check if the source address is a router address + if (!thread_is_router_addr(srcAddress)) { + return -1; + } + + // check if the address16 is a valid child address + if (!thread_addr_is_child(srcAddress, address16)) { + return -1; + } + if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource)); // if learning key sequence from link sync actual guard timer value is not known @@ -1103,7 +1124,7 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t //Add ML-EID if ((mode & MLE_FFD_DEV) == 0) { - ptr = thread_address_registration_tlv_write(ptr, cur); + ptr = thread_ml_address_tlv_write(ptr,cur); } reqTlvCnt = 2; diff --git a/source/6LoWPAN/Thread/thread_joiner_application.c b/source/6LoWPAN/Thread/thread_joiner_application.c index 5bc1b784936..65ecc0af52c 100644 --- a/source/6LoWPAN/Thread/thread_joiner_application.c +++ b/source/6LoWPAN/Thread/thread_joiner_application.c @@ -54,6 +54,7 @@ #include "thread_management_if.h" #include "thread_common.h" #include "thread_bootstrap.h" +#include "thread_router_bootstrap.h" #include "thread_network_synch.h" #include "thread_network_data_lib.h" #include "thread_joiner_application.h" @@ -1140,7 +1141,7 @@ void thread_joiner_pending_config_activate(int8_t interface_id) this->active_configuration_ptr->timestamp = pending_active_timestamp; // All information is copied from old configuration so if configuration is corrupt we dont change anything. this->pending_configuration_ptr = NULL; - (void)thread_nvm_store_pending_configuration_remove(); + thread_nvm_store_pending_configuration_remove(); configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr); link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length); link_configuration_trace(this->configuration_ptr); @@ -1922,6 +1923,8 @@ int thread_joiner_application_update_configuration(uint8_t interface_id, uint8_t } thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); link_configuration_update(this->configuration_ptr,msg_ptr,msg_len); + // allow 5 seconds delay before state change for data response propagation + thread_router_bootstrap_delay_reed_jitter(interface_id, 5); ns_dyn_mem_free(configuration_ptr); thread_joiner_application_configuration_nvm_save(interface_id); diff --git a/source/6LoWPAN/Thread/thread_leader_service.c b/source/6LoWPAN/Thread/thread_leader_service.c index d2be5fd3ebf..a244c9cedcf 100644 --- a/source/6LoWPAN/Thread/thread_leader_service.c +++ b/source/6LoWPAN/Thread/thread_leader_service.c @@ -41,7 +41,7 @@ #include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_bootstrap.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" @@ -305,7 +305,6 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint protocol_interface_info_entry_t *cur; link_configuration_s *linkConfiguration; - tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address)); linkConfiguration = thread_joiner_application_get_config(interface_id); if (!linkConfiguration) { @@ -341,6 +340,13 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint *session_id = cur->thread_info->registered_commissioner.session_id; } + if (memcmp(border_router_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 && + memcmp(border_router_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0 && + border_router_address[14] == 0xfc) { + // source address is ALOC + common_write_16_bit(cur->thread_info->routerShortAddress, &border_router_address[14]); + } + tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address)); //SET Border Router Locator memcpy(cur->thread_info->registered_commissioner.border_router_address, border_router_address, 16); cur->thread_info->registered_commissioner.commissioner_valid = true; @@ -1295,7 +1301,7 @@ static int thread_leader_service_leader_init(protocol_interface_info_entry_t *cu thread_routing_free(&thread_info->routing); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); - thread_dhcp_client_delete(cur->id); + dhcp_client_delete(cur->id); thread_nd_service_delete(cur->id); mpl_clear_realm_scope_seeds(cur); ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); @@ -1352,7 +1358,6 @@ static void thread_leader_service_interface_setup_activate(protocol_interface_in cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS; thread_bootstrap_update_ml16_address(cur, cur->thread_info->routerShortAddress); thread_generate_ml64_address(cur); - thread_extension_address_generate(cur); thread_bootstrap_routing_activate(cur); thread_routing_update_id_set(cur, private->maskSeq, private->master_router_id_mask); thread_routing_activate(&cur->thread_info->routing); diff --git a/source/6LoWPAN/Thread/thread_management_api.c b/source/6LoWPAN/Thread/thread_management_api.c index ff364157b10..ac16c1f6066 100644 --- a/source/6LoWPAN/Thread/thread_management_api.c +++ b/source/6LoWPAN/Thread/thread_management_api.c @@ -287,7 +287,6 @@ int thread_management_register(int8_t interface_id) this->get_response_cb_ptr = NULL; if (thread_management_get_remote_addr(this)) { - ns_dyn_mem_free(this); return -1; } diff --git a/source/6LoWPAN/Thread/thread_management_client.c b/source/6LoWPAN/Thread/thread_management_client.c index 0ccae5a3ac3..a5d1646b3a0 100644 --- a/source/6LoWPAN/Thread/thread_management_client.c +++ b/source/6LoWPAN/Thread/thread_management_client.c @@ -45,6 +45,7 @@ #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_tmfcop_lib.h" #include "6LoWPAN/Thread/thread_management_internal.h" +#include "6LoWPAN/Thread/thread_management_server.h" #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_bootstrap.h" @@ -58,9 +59,8 @@ typedef struct thread_management { thread_management_client_router_id_cb *router_id_release_cb_ptr; thread_management_client_network_data_set_cb *network_data_set_cb_ptr; thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr; - uint16_t coap_asd_msg_id; // COAP msg id for a/sd int8_t interface_id; - int8_t coap_service_id; + int8_t coap_service_id; // COAP service ID from Management server ns_list_link_t link; } thread_management_t; @@ -150,9 +150,12 @@ void thread_management_client_init(int8_t interface_id) this->neighbor_discovery_cb_ptr = NULL; this->router_id_cb_ptr = NULL; this->interface_id = interface_id; - this->coap_asd_msg_id = 0; //TODO: Check if to use ephemeral port here - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + + this->coap_service_id = thread_management_server_service_id_get(interface_id); + if (this->coap_service_id < 0) { + tr_error("Failed to init COAP service"); + } ns_list_add_to_start(&instance_list, this); } return; @@ -165,19 +168,10 @@ void thread_management_client_delete(int8_t interface_id) return; } - coap_service_delete(this->coap_service_id); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); return; } -int8_t thread_management_client_service_id_get(int8_t interface_id) -{ - thread_management_t *this = thread_management_find(interface_id); - if (!this) { - return -1; - } - return this->coap_service_id; -} int thread_management_client_router_id_get(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb, uint8_t status) { @@ -251,8 +245,6 @@ static int thread_management_client_register_cb(int8_t service_id, uint8_t sourc return -1; } - this->coap_asd_msg_id = 0; //clear the coap message id - if (this->network_data_set_cb_ptr) { if (response_ptr) { // If we get response status is OK @@ -281,10 +273,8 @@ int thread_management_client_network_data_register(int8_t interface_id, uint8_t this->network_data_set_cb_ptr = set_cb; tr_debug("thread network data send to %s", trace_ipv6(destination)); - this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, - COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); - - return 0; + return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); } int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16) @@ -306,8 +296,8 @@ int thread_management_client_network_data_unregister(int8_t interface_id, uint16 tr_debug("thread network data unregister"); - this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, - COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); + coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, + COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); return 0; } @@ -616,26 +606,29 @@ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t ad payload, ptr - payload, thread_management_client_proactive_an_cb); } -void thread_management_client_pending_coap_request_kill(int8_t interface_id) +void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id) { thread_management_t *this = thread_management_find(interface_id); - protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!this || !cur) { + if (!this) { return; } - cur->thread_info->localServerDataBase.publish_active = false; + coap_service_request_delete(this->coap_service_id, coap_message_id); +} - if (this->coap_asd_msg_id != 0) { - coap_service_request_delete(this->coap_service_id, this->coap_asd_msg_id); - this->coap_asd_msg_id = 0; - } +void thread_management_client_old_partition_data_clean(int8_t interface_id) +{ + thread_management_t *this = thread_management_find(interface_id); + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (cur->thread_info->routerIdReqCoapID != 0) { - coap_service_request_delete(this->coap_service_id, cur->thread_info->routerIdReqCoapID); - cur->thread_info->routerIdReqCoapID = 0; + if (!this || !cur) { + return; } + + cur->thread_info->localServerDataBase.publish_coap_req_id = 0; + cur->thread_info->routerIdRequested = false; + coap_service_request_delete_by_service_id(this->coap_service_id); } #endif diff --git a/source/6LoWPAN/Thread/thread_management_client.h b/source/6LoWPAN/Thread/thread_management_client.h index 583b6fcec46..f2691278ab3 100644 --- a/source/6LoWPAN/Thread/thread_management_client.h +++ b/source/6LoWPAN/Thread/thread_management_client.h @@ -65,12 +65,6 @@ void thread_management_client_init(int8_t interface_id); */ void thread_management_client_delete(int8_t interface_id); -/** Get service id of management service. - * - * When using Coap Management port service this service is the only instance used to make client transactions. - */ -int8_t thread_management_client_service_id_get(int8_t interface_id); - /** Router id handler callback. * * callback to inform when new router id is received from leader. @@ -213,9 +207,20 @@ int thread_management_client_provision_request(int8_t interface_id, uint8_t *dst */ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t address[16], const uint16_t rloc, const uint8_t ml_eid[8], const uint8_t dst_addr[16]); -/** Kill pending COAP requests. +/** Delete COAP message . + * + * Delete COAP message that is sent to COAP service. + * + * \param interface_id interface id of this Thread instance. + * \param coap_message_id COAP message to be deleted. + */ +void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id); + +/** Clear old partition data. + * + * Clear data related to old partition, like pending COAP transactions. * * \param interface_id interface id of this Thread instance. */ -void thread_management_client_pending_coap_request_kill(int8_t interface_id); +void thread_management_client_old_partition_data_clean(int8_t interface_id); #endif /* THREAD_MANAGEMENT_CLIENT_H_ */ diff --git a/source/6LoWPAN/Thread/thread_management_if.c b/source/6LoWPAN/Thread/thread_management_if.c index 767bb355389..e22f94c9985 100644 --- a/source/6LoWPAN/Thread/thread_management_if.c +++ b/source/6LoWPAN/Thread/thread_management_if.c @@ -50,7 +50,7 @@ #include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_nd.h" #include "thread_diagnostic.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_network_synch.h" #include "6LoWPAN/Thread/thread_management_internal.h" @@ -63,6 +63,7 @@ #include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_extension_bootstrap.h" #include "6LoWPAN/Thread/thread_extension.h" +#include "6LoWPAN/Thread/thread_bbr_api_internal.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up #include "MLE/mle.h" @@ -71,9 +72,8 @@ #include "thread_commissioning_if.h" #include "shalib.h" #include "Common_Protocols/icmpv6.h" -#include "libDHCPv6/libDHCPv6.h" -#include "libDHCPv6/libDHCPv6_server.h" #include "DHCPv6_Server/DHCPv6_server_service.h" +#include "6LoWPAN/Thread/thread_dhcpv6_server.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/blacklist/blacklist.h" #include "6LoWPAN/MAC/mac_helper.h" @@ -606,7 +606,7 @@ int thread_management_get_ml_prefix_112(int8_t interface_id, uint8_t *prefix_ptr */ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_cnt, bool stableData) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) protocol_interface_info_entry_t *cur; thread_prefix_tlv_t prefixTlv; thread_border_router_tlv_entry_t service; @@ -622,7 +622,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t return -1; } - if (DHCPv6_server_service_init(interface_id, prefix_ptr, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { + if (thread_dhcp6_server_init(interface_id, prefix_ptr, cur->mac, THREAD_MIN_PREFIX_LIFETIME) != 0) { tr_warn("SerVER alloc fail"); return -1; } @@ -637,14 +637,9 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t service.P_on_mesh = true; service.stableData = stableData; - //SET Timeout - DHCPv6_server_service_set_address_validlifetime(interface_id, prefix_ptr, THREAD_MIN_PREFIX_LIFETIME); - // SET maximum number of accepted clients DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_cnt); - //Enable Mapping - //DHCPv6_server_service_set_gua_address_mapping(interface_id,prefix_ptr, true, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix); tr_debug("GUA server Generate OK"); memcpy(ptr, prefix_ptr, 8); memset(ptr + 8, 0, 8); @@ -665,7 +660,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -681,7 +676,7 @@ int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -697,7 +692,7 @@ int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) if (!prefix_ptr) { return -1; } @@ -715,7 +710,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t * int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr) { -#ifdef HAVE_DHCPV6_SERVER +#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER) uint8_t temp[16]; protocol_interface_info_entry_t *cur; thread_prefix_tlv_t prefixTlv; diff --git a/source/6LoWPAN/Thread/thread_management_server.c b/source/6LoWPAN/Thread/thread_management_server.c index 8a4ae139fd6..8f0bc4a59d5 100644 --- a/source/6LoWPAN/Thread/thread_management_server.c +++ b/source/6LoWPAN/Thread/thread_management_server.c @@ -100,6 +100,9 @@ typedef struct announce { typedef struct thread_management_server { scan_query_t *scan_ptr; announce_t *announce_ptr; + timeout_t *join_ent_timer; + uint8_t destination_address[16]; + uint8_t one_time_key[16]; uint16_t relay_port_joiner; uint16_t external_commissioner_port; int8_t interface_id; @@ -994,7 +997,6 @@ static int thread_management_server_energy_scan_cb(int8_t service_id, uint8_t so return -1; } - static void thread_announce_timeout_cb(void* arg) { link_configuration_s *linkConfiguration; @@ -1132,6 +1134,9 @@ int thread_management_server_init(int8_t interface_id) this->relay_port_joiner = 0; this->scan_ptr = NULL; this->announce_ptr = NULL; + this->join_ent_timer = NULL; + memset(this->destination_address,0,16); + memset(this->one_time_key,0,16); this->external_commissioner_port = THREAD_COMMISSIONING_PORT; #ifdef HAVE_THREAD_ROUTER @@ -1147,13 +1152,13 @@ int thread_management_server_init(int8_t interface_id) #endif this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); if (this->coap_service_id < 0) { - tr_warn("Thread management init failed"); + tr_error("Thread management init failed"); ns_dyn_mem_free(this); return -3; } #ifdef HAVE_THREAD_ROUTER if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { - tr_warn("Thread leader service init failed"); + tr_error("Thread leader service init failed"); ns_dyn_mem_free(this); return -3; } @@ -1191,6 +1196,7 @@ void thread_management_server_delete(int8_t interface_id) coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); coap_service_delete(this->coap_service_id); + ns_list_remove(&instance_list, this); if (this->announce_ptr) { if (this->announce_ptr->timer) { @@ -1215,6 +1221,15 @@ void thread_management_server_delete(int8_t interface_id) return; } +int8_t thread_management_server_service_id_get(int8_t interface_id) +{ + thread_management_server_t *this = thread_management_server_find(interface_id); + if (!this) { + return -1; + } + return this->coap_service_id; +} + int8_t thread_management_server_interface_id_get(int8_t coap_service_id) { thread_management_server_t *this = thread_management_find_by_service(coap_service_id); @@ -1312,6 +1327,19 @@ static int thread_management_server_entrust_send(thread_management_server_t *thi ns_dyn_mem_free(response_ptr); return 0; } + +static void thread_join_ent_timeout_cb(void *arg) +{ + thread_management_server_t *this = arg; + if(!this || !this->join_ent_timer) { + return; + } + + this->join_ent_timer = NULL; + thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); + return; +} + void joiner_router_recv_commission_msg(void *cb_res) { socket_callback_t *sckt_data = 0; @@ -1412,7 +1440,13 @@ static int thread_management_server_relay_tx_cb(int8_t service_id, uint8_t sourc if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { // KEK present in relay set pairwise key and send entrust tr_debug("Kek received"); - thread_management_server_entrust_send(this, destination_address.address, kek_ptr); + if (this->join_ent_timer) { + eventOS_timeout_cancel(this->join_ent_timer); + thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); + } + memcpy(this->destination_address, destination_address.address, 16); + memcpy(this->one_time_key, kek_ptr, 16); + this->join_ent_timer = eventOS_timeout_ms(thread_join_ent_timeout_cb, THREAD_DELAY_JOIN_ENT, this); } tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); thci_trace("joinerrouterJoinerDataRelayedOutbound"); diff --git a/source/6LoWPAN/Thread/thread_management_server.h b/source/6LoWPAN/Thread/thread_management_server.h index 88be72814a0..b7ca9fb5c1b 100644 --- a/source/6LoWPAN/Thread/thread_management_server.h +++ b/source/6LoWPAN/Thread/thread_management_server.h @@ -99,6 +99,13 @@ int thread_management_server_joiner_router_init(int8_t interface_id); * */ void thread_management_server_joiner_router_deinit(int8_t interface_id); + +/** Get service id of management service. + * + * When using Coap Management port service this service is the only instance used to make client transactions. + */ +int8_t thread_management_server_service_id_get(int8_t interface_id); + int8_t thread_management_server_interface_id_get(int8_t coap_service_id); int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data); diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 2c108ee6e88..4ff0a64038d 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -30,6 +30,7 @@ #ifdef HAVE_THREAD #include "ns_trace.h" +#include "string.h" #include "common_functions.h" #include "NWK_INTERFACE/Include/protocol.h" #include @@ -53,6 +54,7 @@ #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_data_poll.h" +#include "Common_Protocols/ipv6.h" #include "MLE/mle.h" #include "mac_api.h" #define TRACE_GROUP "thmh" @@ -699,6 +701,54 @@ static int thread_host_child_update_response_send(protocol_interface_info_entry_ return 0; } +static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info) +{ + uint8_t context; + uint16_t length = tlv_info->tlvLen; + uint8_t *ptr = tlv_info->dataPtr; + + while (length) { + context = *ptr++; + if (context & 0x80) { + if (memcmp(ptr, entry->address + 8, 8) == 0) { + return true; + } + ptr += 8; + length -= 9; + } else { + if (memcmp(ptr, entry->address, 16) == 0) { + return true; + } + ptr += 16; + length -= 17; + } + } + + return false; + +} + +static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info) +{ + bool ret_val = true; + + ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) { + if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL && + !thread_addr_is_mesh_local_16(e->address, cur))) { + + if (thread_address_registration_tlv_search(e, tlv_info) == false) { + tr_debug("Address %s registration to parent failed", trace_ipv6(e->address)); + addr_set_preferred_lifetime(cur, e, 0); // deprecate address + ret_val = false; + } else if (e->preferred_lifetime == 0) { + addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite + } + } + } + + return ret_val; +} + static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) { thread_leader_data_t leaderData; @@ -710,6 +760,7 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent uint64_t pending_timestamp = 0;// means no pending timestamp mac_neighbor_table_entry_t *entry_temp; bool data_request_needed = false; + mle_tlv_info_t tlv_info = {0}; tr_debug("Child update request"); entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); @@ -738,6 +789,11 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent thread_bootstrap_network_data_update(cur); } + // Check Address Registration TLV + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { // version numbers not in sync need to send data request @@ -776,6 +832,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * thread_leader_data_t leaderData = {0}; uint8_t status; bool leader_data_received; + mle_tlv_info_t tlv_info = {0}; if (cur->thread_info->thread_endnode_parent == NULL) { return; @@ -822,6 +879,10 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * tr_debug("Setting child timeout, value=%"PRIu32, timeout); } + if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) { + thread_address_registration_tlv_check(cur, &tlv_info); + } + tr_debug("Keep-Alive -->Respond from Parent"); mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); diff --git a/source/6LoWPAN/Thread/thread_nd.c b/source/6LoWPAN/Thread/thread_nd.c index 717e757bffd..85020a37705 100644 --- a/source/6LoWPAN/Thread/thread_nd.c +++ b/source/6LoWPAN/Thread/thread_nd.c @@ -294,7 +294,7 @@ static void thread_nd_address_error(int8_t interface_id, const uint8_t ip_addr[1 if_address_entry_t *addr_entry = addr_get_entry(cur, ip_addr); if (addr_entry && memcmp(ml_eid, cur->iid_slaac, 8)) { addr_duplicate_detected(cur, ip_addr); - thread_extension_address_generate(cur); + thread_extension_dua_address_generate(cur, ip_addr, 64); } /* Scan IPv6 neighbour cache for registered entries of children */ @@ -547,8 +547,7 @@ int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const u } uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh); - if (neigh->state != IP_NEIGHBOUR_NEW && memcmp(nce_eui64, mac64, 8) != 0) - { + if (neigh->type == IP_NEIGHBOUR_REGISTERED && memcmp(nce_eui64, mac64, 8) != 0) { return -2; } diff --git a/source/6LoWPAN/Thread/thread_network_data_storage.c b/source/6LoWPAN/Thread/thread_network_data_storage.c index 0947cf4564b..e5ef23aa26b 100755 --- a/source/6LoWPAN/Thread/thread_network_data_storage.c +++ b/source/6LoWPAN/Thread/thread_network_data_storage.c @@ -48,7 +48,7 @@ #include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_storage.h" -#include "6LoWPAN/Thread/thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "thread_management_if.h" #include "thread_meshcop_lib.h" @@ -193,6 +193,7 @@ static uint16_t thread_nd_service_border_router_flags_read(thread_network_server flags |= (cur->P_default_route << THREAD_P_DEF_ROUTE_BIT_MOVE); flags |= (cur->P_on_mesh << THREAD_P_ON_MESH_BIT_MOVE); flags |= (cur->P_nd_dns << THREAD_P_ND_DNS_BIT_MOVE); + flags |= (cur->P_res1 << THREAD_P_ND_RES_BIT_MOVE); return flags; } @@ -872,6 +873,7 @@ static int thread_service_data_delete_mark_by_router_id(thread_network_data_serv static int thread_server_context_clean(int8_t id, thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list) { + (void) id; int retVal = -1; (void) prefixEntry; ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { @@ -881,9 +883,7 @@ static int thread_server_context_clean(int8_t id, thread_network_data_cache_entr cachePtr->stableUpdatePushed = true; } // Set context lifetime to 0 to delete - if (thread_extension_context_can_delete(id, prefixEntry->servicesPrefix, cur->contextPrefixLength)) { - lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); - } + lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); ns_list_remove(listPtr, cur); ns_dyn_mem_free(cur); retVal = 0; @@ -930,11 +930,18 @@ static bool thread_server_data_clean_by_router_id(thread_network_data_cache_entr if (cur->P_dhcp) { tr_debug("Delete DHCPv6 given address"); - thread_dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix); - } else { + dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix); + } + + if (cur->P_slaac) { tr_debug("Delete SLAAC address"); addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_SLAAC); } + + if (cur->P_res1) { + tr_debug("Delete thread domain address"); + addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_THREAD_DOMAIN); + } } ns_list_remove(listPtr, cur); @@ -995,7 +1002,7 @@ void thread_network_local_server_data_base_init(thread_network_local_data_cache_ ns_list_init(&cachePtr->service_list); cachePtr->registered_rloc16 = 0xffff; cachePtr->release_old_address = false; - cachePtr->publish_active = false; + cachePtr->publish_coap_req_id = 0; cachePtr->publish_pending = false; } @@ -1077,6 +1084,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list) { + (void) id; ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList) { ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) { if (!curContext->compression) { @@ -1090,9 +1098,7 @@ void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_d cachePtr->temporaryUpdatePushed = true; } // Set context lifetime to 0 to delete - if (thread_extension_context_can_delete(id, cur->servicesPrefix,curContext->contextPrefixLength)) { - lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); - } + lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); ns_dyn_mem_free(curContext); } } @@ -1162,7 +1168,7 @@ void thread_network_local_data_free_and_clean(thread_network_local_data_cache_en } cachePtr->publish_pending = false; - cachePtr->publish_active = false; + cachePtr->publish_coap_req_id = 0; cachePtr->release_old_address = false; } @@ -1628,6 +1634,7 @@ int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *n server_entry->P_nd_dns = service->P_nd_dns; trigDataPropagate = true; } + } if (trigDataPropagate) { @@ -1707,9 +1714,9 @@ int thread_nd_local_list_del_on_mesh_server(thread_network_data_cache_entry_t *n int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) { int retVal = -1; - tr_debug("Add prefix: %s prf:%d %s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, + tr_debug("Add prefix: %s prf:%d %s%s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, service->P_default_route?"Default Route ":"",service->P_dhcp?"DHCPv6 Server ":"", service->P_configure?"DHCPv6 Configuration ":"", - service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":""); + service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":"",service->P_res1?"P_res1 ":""); if (networkDataList) { thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv); @@ -2341,7 +2348,9 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_ if (curService->S_id != S_id) { continue; } - ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) { + /* any server will do - take first from the list */ + thread_network_data_service_server_entry_t *curServiceServer = ns_list_get_first(&curService->server_list); + if (curServiceServer) { *rlocAddress = curServiceServer->router_id; return true; } @@ -2352,7 +2361,7 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_ bool thread_nd_on_mesh_address_valid(thread_network_server_data_entry_t *curRoute) { bool onMeshActive = false; - if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred) { + if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred || curRoute->P_on_mesh) { onMeshActive = true; } diff --git a/source/6LoWPAN/Thread/thread_network_data_storage.h b/source/6LoWPAN/Thread/thread_network_data_storage.h index 10dbd298f16..b5924535a62 100644 --- a/source/6LoWPAN/Thread/thread_network_data_storage.h +++ b/source/6LoWPAN/Thread/thread_network_data_storage.h @@ -187,8 +187,8 @@ typedef struct thread_network_local_data_cache_entry_s { thread_network_data_prefix_list_t prefix_list; /*!< Local parsed or generated service list */ thread_network_data_service_list_t service_list; uint16_t registered_rloc16;/*!< Address used for latest registration */ + uint16_t publish_coap_req_id;/*!< Non-zero when publish is active */ bool release_old_address:1;/*!< true if network data can be released from old address */ - bool publish_active:1;/*!< true when publish is active */ bool publish_pending:1;/*!< true when publish attempt made during active publish */ } thread_network_local_data_cache_entry_t; @@ -344,7 +344,7 @@ uint8_t *thread_network_data_prefix_set_write(thread_network_data_cache_entry_t uint8_t *thread_network_data_service_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr); bool thread_network_data_service_hosted_by_this_router_id(thread_network_data_service_cache_entry_t *dataList, uint16_t router_id); uint16_t thread_network_data_service_child_id_from_networkdata_get(thread_network_data_cache_entry_t *networkDataList, uint16_t router_short_addr); - +thread_network_data_prefix_cache_entry_t *thread_prefix_entry_find(thread_network_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv); uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_entry_t *serverDataList, uint8_t *ptr, uint16_t routerID); uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_entry_t *serverDataList); diff --git a/source/6LoWPAN/Thread/thread_nvm_store.c b/source/6LoWPAN/Thread/thread_nvm_store.c index 0aa4657f687..18a1918b04b 100644 --- a/source/6LoWPAN/Thread/thread_nvm_store.c +++ b/source/6LoWPAN/Thread/thread_nvm_store.c @@ -292,7 +292,11 @@ int thread_nvm_store_active_configuration_remove(void) } char ac_data_path[ACTIVE_CONF_STRING_LEN]; thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); - return remove(ac_data_path); + int status = remove(ac_data_path); + if (status != 0) { + return THREAD_NVM_FILE_REMOVE_ERROR; + } + return THREAD_NVM_FILE_SUCCESS; } int thread_nvm_store_pending_configuration_remove(void) @@ -302,7 +306,11 @@ int thread_nvm_store_pending_configuration_remove(void) } char ac_data_path[PENDING_CONF_STRING_LEN]; thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE); - return remove(ac_data_path); + int status = remove(ac_data_path); + if (status != 0) { + return THREAD_NVM_FILE_REMOVE_ERROR; + } + return THREAD_NVM_FILE_SUCCESS; } diff --git a/source/6LoWPAN/Thread/thread_resolution_client.c b/source/6LoWPAN/Thread/thread_resolution_client.c index 9ea5aeaa63c..58bb6cf3255 100644 --- a/source/6LoWPAN/Thread/thread_resolution_client.c +++ b/source/6LoWPAN/Thread/thread_resolution_client.c @@ -39,6 +39,7 @@ #include "coap_service_api.h" #include "thread_config.h" +#include "thread_management_server.h" #include "thread_resolution_client.h" #define TRACE_GROUP TRACE_GROUP_THREAD_RESOLUTION_CLIENT @@ -294,7 +295,7 @@ void thread_resolution_client_init(int8_t interface_id) this->error_cb_ptr = NULL; ns_list_init(&this->queries); //TODO: Check if to use ephemeral port here - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); ns_list_add_to_start(&instance_list, this); coap_service_register_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_resolution_client_notification_post_cb); @@ -309,7 +310,7 @@ void thread_resolution_client_delete(int8_t interface_id) } coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION); - coap_service_delete(this->coap_service_id); + coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_ERROR); ns_list_foreach_safe(address_query_t, query, &this->queries) { ns_list_remove(&this->queries, query); ns_dyn_mem_free(query); @@ -465,6 +466,7 @@ void thread_resolution_client_timer(int8_t interface_id, uint16_t seconds) } } } - } + #endif // HAVE_THREAD_NEIGHBOR_DISCOVERY + diff --git a/source/6LoWPAN/Thread/thread_resolution_server.c b/source/6LoWPAN/Thread/thread_resolution_server.c index 362f96aa7cd..e20541eb2bf 100644 --- a/source/6LoWPAN/Thread/thread_resolution_server.c +++ b/source/6LoWPAN/Thread/thread_resolution_server.c @@ -47,6 +47,7 @@ #include "thread_config.h" #include "thread_tmfcop_lib.h" #include "thread_management_if.h" +#include "thread_management_server.h" #include "thread_commissioning_if.h" @@ -170,9 +171,9 @@ int thread_resolution_server_init(int8_t interface_id, thread_resolution_server_ } this->interface_id = interface_id; - this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); + this->coap_service_id = thread_management_server_service_id_get(interface_id); if (this->coap_service_id < 0) { - tr_warn("Thread resolution init failed"); + tr_warn("Thread resolution srv init failed"); ns_dyn_mem_free(this); return -3; } @@ -193,7 +194,6 @@ void thread_resolution_server_delete(int8_t interface_id) coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_QUERY_REQUEST); - coap_service_delete(this->coap_service_id); ns_list_remove(&instance_list, this); ns_dyn_mem_free(this); } diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 0c00650f7fd..b16287a042a 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -78,7 +78,7 @@ #include "Service_Libs/nd_proxy/nd_proxy.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/blacklist/blacklist.h" -#include "thread_dhcpv6_client.h" +#include "DHCPv6_client/dhcpv6_client_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "mac_api.h" #include "6LoWPAN/MAC/mac_data_poll.h" @@ -1027,10 +1027,10 @@ static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t sta if (!cur) { return; } - if (!cur->thread_info->routerIdReqCoapID) { + if (!cur->thread_info->routerIdRequested) { return; } - cur->thread_info->routerIdReqCoapID = 0; + cur->thread_info->routerIdRequested = false; if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER || cur->thread_info->leader_private_data ) { @@ -1088,15 +1088,15 @@ void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t * { int router_id_req_status; tr_debug("Router ID Request"); - if (cur->thread_info->routerIdReqCoapID) { + if (cur->thread_info->routerIdRequested) { tr_warn("Router ID already requested"); return; } router_id_req_status = thread_management_client_router_id_get(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_cb, status); - tr_debug("Coap address req, ID=%d", router_id_req_status); + tr_debug("RouterIDReq COAP ID=%d", router_id_req_status); if (router_id_req_status > 0) { - cur->thread_info->routerIdReqCoapID = (uint16_t)router_id_req_status; + cur->thread_info->routerIdRequested = true; } } @@ -1196,6 +1196,32 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c } + +int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout) +{ + uint16_t router_address = thread_info(cur)->routerShortAddress; + uint32_t max_timeout = 0; + if (router_address >= 0xfffe) { + router_address = mac_helper_mac16_address_get(cur); + } + if (router_address & THREAD_CHILD_MASK) { + return -1; //I am child + } + if (router_address >= 0xfffe) { + return -1; + } + mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list; + + ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) { + if (thread_router_addr_from_addr(cur_entry->mac16) == router_address && + !cur_entry->ffd_device && cur_entry->lifetime > max_timeout) { + max_timeout = cur_entry->lifetime; + } + } + *max_child_timeout = max_timeout; + return 0; +} + uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur) { uint16_t child_count = 0; @@ -1277,7 +1303,7 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c bool new_neigbour = false; if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) { - if (!cur->thread_info->routerIdReqCoapID) { + if (!cur->thread_info->routerIdRequested) { tr_info("Upgrade REED to Router"); thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST); } @@ -1366,7 +1392,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le uint8_t tempIPv6Address[16]; uint8_t ctxId; bool new_neighbour_created; - + thread_child_mcast_entries_remove(cur,mac64); while (data_length) { //Read ctxId = *ptr++; @@ -1389,8 +1415,8 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le tr_debug("Register %s", trace_ipv6(ptr)); if (addr_is_ipv6_multicast(ptr)) { - // Register multicast address (higher scope than link-local) - if (addr_ipv6_multicast_scope(ptr) > IPV6_SCOPE_LINK_LOCAL) { + // Register multicast address (link-local & higher) + if (addr_ipv6_multicast_scope(ptr) >= IPV6_SCOPE_LINK_LOCAL) { addr_add_group(cur, ptr); if (thread_child_mcast_entry_get(cur, ptr, mac64)) { tr_debug("Added sleepy multicast registration entry."); @@ -1665,6 +1691,11 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t * } } + if (!(id_req->mode & MLE_FFD_DEV) && addressRegisteredTlv.tlvLen == 0) { + tr_debug("No address registration TLV in MTD child id request"); + thread_child_id_request_entry_remove(cur, id_req); + return; + } id_req->keyId = security_headers->KeyIndex; id_req->keySeq = common_read_32_bit(security_headers->Keysource); @@ -1991,10 +2022,22 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t * if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) { return; } + + uint8_t mode = mle_mode_write_from_mac_entry(entry_temp); + /* check if thread neighbor class is not initialized */ + if ((thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0) && + (thread_neighbor_last_communication_time_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0)) { + /* + * Thread neighbor class is not yet initialized and we receive data_request from such child. + * Always send full network data in this case + */ + mode |= MLE_THREAD_REQ_FULL_DATA_SET | MLE_THREAD_SECURED_DATA_REQUEST; + } else { + mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index); + } + thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false); thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index); - uint8_t mode = mle_mode_write_from_mac_entry(entry_temp); - mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index); mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode); } break; @@ -2026,8 +2069,9 @@ static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info tr_debug("Buffer overflow at message write"); } - timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; - timeout.timeout_init = 1; + // timeout set to two seconds, no retries + timeout.retrans_max = 1; + timeout.timeout_init = 2; timeout.timeout_max = 3; timeout.delay = MLE_NO_DELAY; @@ -2325,7 +2369,6 @@ static uint32_t thread_reed_timeout_calculate(thread_router_select_t *routerSele static int thread_reed_advertise (protocol_interface_info_entry_t *cur) { uint32_t keySequence; - tr_debug("MLE REED ADVERTISEMENT STARTED"); struct link_configuration *linkConfiguration; linkConfiguration = thread_joiner_application_get_config(cur->id); if (!linkConfiguration) { @@ -2336,11 +2379,17 @@ static int thread_reed_advertise (protocol_interface_info_entry_t *cur) return -1; } + // FED not allowed to send advertisements + if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) { + return -1; + } + uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT); if (bufId == 0) { return -1; } + tr_debug("MLE REED ADVERTISEMENT STARTED"); thread_management_get_current_keysequence(cur->id, &keySequence); mle_service_msg_update_security_params(bufId, 5, 2, keySequence); @@ -2734,4 +2783,18 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY; } +void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay) +{ + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return; + } + if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) { + return; + } + // delay reed jitter timer to allow for settings changes to distribute + thread_info(cur)->reedJitterTimer += delay; + return; +} + #endif /* HAVE_THREAD_ROUTER */ diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.h b/source/6LoWPAN/Thread/thread_router_bootstrap.h index 0143ce1e30c..6874a01b0bb 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.h +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.h @@ -52,6 +52,9 @@ int thread_router_bootstrap_mle_advertise(struct protocol_interface_info_entry * void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur); int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child); uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur); + +// max_child_timeout is longest MLE Timeout a router has registered for all of its active MTD children +int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout); void thread_router_bootstrap_child_id_handler(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_child_id_reject(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_router_id_request(struct protocol_interface_info_entry *cur, uint8_t status); @@ -73,6 +76,7 @@ void thread_router_bootstrap_anycast_address_register(protocol_interface_info_en void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur); bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur); +void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay); #else @@ -81,6 +85,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ #define thread_router_bootstrap_child_information_clear(cur) #define thread_router_bootstrap_child_count_get(cur) 0 +#define thread_router_bootstrap_child_max_timeout_get(cur, max_child_timeout) 0 #define thread_router_bootstrap_child_id_handler(cur) #define thread_router_bootstrap_child_id_reject(cur) #define thread_router_bootstrap_router_id_request(cur, status) @@ -104,7 +109,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_ #define thread_router_bootstrap_routing_allowed(cur) false #define thread_router_bootstrap_address_change_notify_send(cur) #define thread_router_bootstrap_reed_merge_advertisement(cur) - +#define thread_router_bootstrap_delay_reed_jitter(interface_id, delay) #endif/*HAVE_THREAD_ROUTER*/ #endif /* THREAD_ROUTER_BOOTSTRAP_H_ */ diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 226ed6f9642..4392f993ac1 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -43,7 +43,6 @@ #ifdef HAVE_RPL #include "RPL/rpl_data.h" #endif -#include "6LoWPAN/ws/ws_common.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/ws/ws_common.h" @@ -72,7 +71,7 @@ typedef struct { bool fragmented_data:1; bool first_fragment:1; bool indirect_data:1; - bool indirect_data_cached:1; /* Data cached for delayed transmission as mac request is already active */ + bool indirect_data_cached:1; /*!< Data cached for delayed transmission as mac request is already active */ buffer_t *buf; uint8_t *fragmenter_buf; ns_list_link_t link; /*!< List link entry */ @@ -132,7 +131,7 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr); /* Fragmentation local functions */ static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr); static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq); -static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); +static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); @@ -613,40 +612,35 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_ { mac_neighbor_table_entry_t *neigh_entry_ptr = NULL; + //Validate is link known and set indirect, datareq and security key id mode if (buf->dst_sa.addr_type == ADDR_NONE) { goto tx_error_handler; } - /* If MLE is enabled, we will talk if we have an MLE association */ - if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG ) { - neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); + if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK ) { + buf->dst_sa.addr_type = ADDR_802_15_4_SHORT; + buf->dst_sa.address[2] = 0xff; + buf->dst_sa.address[3] = 0xff; + buf->link_specific.ieee802_15_4.indirectTxProcess = false; + buf->link_specific.ieee802_15_4.requestAck = false; + } else { - } else if(buf->dst_sa.addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa.address + 2)) != 0xffff) { neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); - } - //Validate neighbour - if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) { + //Validate neighbour + if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) { - if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device) { + if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device) { - } else { - //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); + } else { + //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); + goto tx_error_handler; + } + } else if (ws_info(cur) && !neigh_entry_ptr) { + //Do not accept to send unknow device goto tx_error_handler; } - } - - //Check indirect - - - if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK) { - buf->dst_sa.addr_type = ADDR_802_15_4_SHORT; - buf->dst_sa.address[2] = 0xff; - buf->dst_sa.address[3] = 0xff; - buf->link_specific.ieee802_15_4.indirectTxProcess = false; - buf->link_specific.ieee802_15_4.requestAck = false; - } else { buf->link_specific.ieee802_15_4.requestAck = true; buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr); } @@ -755,7 +749,7 @@ static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_ent ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { if (fragmenter_tx_entry->indirect_data_cached) { if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { - tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); + tr_debug_extra("Pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); fragmenter_tx_entry->indirect_data_cached = false; lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr); return true; @@ -805,7 +799,12 @@ static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type); if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) { if (++count >= interface_ptr->max_indirect_small_packets_per_child) { - lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); + tr_debug_extra("Purge seq: %d", tx_entry->buf->seq); + if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) { + /* entry could not be purged from mac, try next entry */ + tr_debug_extra("Purge failed, try next"); + count--; + } } } } @@ -822,8 +821,12 @@ static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) { if (++count >= interface_ptr->max_indirect_big_packets_total) { - tr_debug_extra("free seq: %d", tx_entry->buf->seq); - lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); + tr_debug_extra("Purge seq: %d", tx_entry->buf->seq); + if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) { + tr_debug("Purge failed, try next entry"); + /* entry could not be purged from mac, try next entry */ + count--; + } } } } @@ -911,6 +914,8 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff if (indirect) { ns_dyn_mem_free(tx_ptr->fragmenter_buf); ns_dyn_mem_free(tx_ptr); + } else { + tx_ptr->buf = NULL; } goto tx_error_handler; } @@ -1281,29 +1286,44 @@ static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *addres return true; } -static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) +static bool lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) { mcps_purge_t purge_req; purge_req.msduHandle = msduhandle; + bool mac_purge_success = false; if (interface_ptr->mpx_api) { - interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id); + if (interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id) == 0) { + mac_purge_success = true; + } } else { if (cur->mac_api->mcps_purge_req) { - cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req); + if (cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req) == 0) { + mac_purge_success = true; + } } } + + return mac_purge_success; } -static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) +static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) { - tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq); - lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq); + tr_debug("Purge from indirect handle %u, cached %d", tx_ptr->buf->seq, tx_ptr->indirect_data_cached); + if (tx_ptr->indirect_data_cached == false) { + if (lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq) == false) { + // MAC purge failed + return false; + } + } + lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL); + + return true; } void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) { - //Free firts by defined short address + //Free first by defined short address if (entry_ptr->mac16 < 0xfffe) { uint8_t temp_address[2]; common_write_16_bit(entry_ptr->mac16, temp_address); @@ -1323,7 +1343,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr //Check first indirect queue ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) { - if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { //Purge from mac lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); @@ -1331,7 +1350,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr } return 0; - } int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child) diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 4cd3316e5a8..c967b1c86c5 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -35,6 +35,8 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode); void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur); +int ws_bootstrap_restart(int8_t interface_id); + /*State machine transactions*/ void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur); @@ -50,12 +52,27 @@ void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *c void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); -void ws_bootstrap_trigle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); +void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); + +void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor); + +void ws_secondary_parent_update(protocol_interface_info_entry_t *interface); + +void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor); + +void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); + +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local); + +void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix); #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) #define ws_bootstrap_state_machine(cur) +#define ws_bootstrap_restart(cur) +#define ws_primary_parent_update(interface, neighbor) +#define ws_secondary_parent_update(interface) #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index dc02f6938a8..70d48cb40a6 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -20,11 +20,13 @@ #include "ns_types.h" +#include "ns_list.h" #include "fhss_api.h" #include "fhss_config.h" #include "net_fhss.h" #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_neighbor_class.h" +#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" struct ws_pan_information_s; struct ws_neighbor_class_s; @@ -40,6 +42,17 @@ typedef struct parent_info_s { uint32_t timestamp; /**< Timestamp when packet was received */ }parent_info_t; +typedef struct ws_nud_table_entry { + void *neighbor_info; + uint16_t timer; /*!< Timer which resolution is 100ms*/ + unsigned retry_count:2; + bool wait_response:1; /*!< True when NS is sended and wait NA, False when random timer is active*/ + bool nud_process; + ns_list_link_t link; +} ws_nud_table_entry_t; + +typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; + typedef struct ws_info_s { char network_name[33]; // Network name max 32 octets + terminating 0. uint16_t network_pan_id; @@ -54,8 +67,24 @@ typedef struct ws_info_s { uint32_t pan_version_timer; /**< border router version udate timeout */ uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ uint8_t gtkhash[32]; + bool address_registration_event_active : 1; bool configuration_learned:1; - + bool trickle_pas_running:1; + bool trickle_pa_running:1; + bool trickle_pcs_running:1; + bool trickle_pc_running:1; + // default fhss parameters for this device + uint8_t fhss_uc_dwell_interval; + uint8_t fhss_bc_dwell_interval; + uint32_t fhss_bc_interval; + uint8_t fhss_uc_channel_function; + uint8_t fhss_bc_channel_function; + uint16_t fhss_uc_fixed_channel; + uint16_t fhss_bc_fixed_channel; + uint32_t fhss_channel_mask[8]; + ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX]; + ws_nud_table_list_t active_nud_process; + ws_nud_table_list_t free_nud_entries; struct ws_pan_information_s pan_information; ws_hopping_schedule_t hopping_schdule; struct ws_neighbor_class_s neighbor_storage; @@ -65,6 +94,8 @@ typedef struct ws_info_s { #ifdef HAVE_WS +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain); + int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 4b4c067f70f..ae6fb036146 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -73,12 +73,14 @@ typedef struct ws_hopping_schedule_s { uint8_t operating_class; /**< PHY operating class default to 1 */ uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */ uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */ - uint8_t channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ + uint8_t uc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ + uint8_t bc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ uint8_t channel_spacing; /**< derived from regulatory domain. 0:200k, 1:400k, 2:600k, 3:100k */ uint8_t number_of_channels; /**< derived from regulatory domain */ uint8_t clock_drift; uint8_t timing_accurancy; - uint16_t fixed_channel; + uint16_t uc_fixed_channel; + uint16_t bc_fixed_channel; uint16_t fhss_bsi; uint32_t fhss_broadcast_interval; uint32_t channel_mask[8]; @@ -182,9 +184,19 @@ typedef struct ws_bs_ie { #define WS_FAN_VERSION_1_0 1 -#define WS_NEIGHBOR_LINK_TIMEOUT 240 +#define WS_NEIGHBOR_LINK_TIMEOUT 2200 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 +#define WS_NEIGBOR_ETX_SAMPLE_MAX 3 + +#define WS_PROBE_INIT_BASE_SECONDS 8 + +#define WS_NUD_RAND_PROBABILITY 1 + +#define WS_NUD_RANDOM_SAMPLE_LENGTH WS_NEIGHBOR_NUD_TIMEOUT / 2 + +#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100 + /* * Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set */ @@ -203,4 +215,12 @@ typedef struct ws_bs_ie { */ #define WS_RPL_DIS_TIMEOUT 1800 +/* Default FHSS timing information + * + */ +#define WS_FHSS_UC_DWELL_INTERVAL 250; +#define WS_FHSS_BC_INTERVAL 800; +#define WS_FHSS_BC_DWELL_INTERVAL 200; + + #endif /* WS_COMMON_DEFINES_H_ */ diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index c05964f00b0..5be662f3a45 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -21,11 +21,16 @@ #include "fhss_ws_extension.h" #include "6LoWPAN/ws/ws_common_defines.h" +#define RSL_UNITITIALIZED 0x7fff + typedef struct ws_neighbor_class_entry { fhss_ws_neighbor_timing_info_t fhss_data; uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/ uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/ + uint16_t routing_cost; /*!< ETX to border Router. */ bool candidate_parent:1; + bool broadcast_timing_info_stored:1; + bool broadcast_shedule_info_stored:1; } ws_neighbor_class_entry_t; /** diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index af3ca814f49..ea441ea4490 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -583,6 +583,24 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_NO_ROUTE, 0); } + /* Consider multicast forwarding /before/ calling routing code to modify + * extension headers - if that actually decides to tunnel it will + * overwrite the buffer's src_sa and dst_sa, when we want to consider + * forwarding the inner packet. This ordering works out for our only + * header-modifying multicast case of MPL: + * 1) We never want to forward packets with MPL headers, which means the + * outer packet in a tunnel gets ignored anyway. + * 2) This also means we don't have to worry that we're forwarding packets + * with the extension header not filled in yet. + * If we ever do have a multicast system where we are working with + * extension headers and forwarding those across interfaces, ipv6_get_exthdrs + * system will need a rework - probably split the "try MODIFY" call from the + * subsequent "give me tunnel parameters" part. + */ + if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) { + buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true); + } + /* Allow routing code to update extension headers */ int16_t exthdr_result; buf = ipv6_get_exthdrs(buf, IPV6_EXTHDR_MODIFY, &exthdr_result); @@ -593,10 +611,6 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf) goto drop; } - if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) { - buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true); - } - /* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */ if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) { /* Avoid an infinite loop in the event of routing code failure - never diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index 26b7b3a7963..1049fe0cdd3 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -34,7 +34,6 @@ #include "DHCPv6_Server/DHCPv6_server_service.h" #include "common_functions.h" #include "NWK_INTERFACE/Include/protocol.h" -#include "6LoWPAN/Thread/thread_bbr_api_internal.h" #include "Common_Protocols/icmpv6.h" #include "dhcp_service_api.h" @@ -57,9 +56,6 @@ static int8_t dhcpv6_service_tasklet = -1; static arm_event_storage_t *dhcp_timer_storage = NULL; -static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress); - - static bool DHCP_server_service_timer_start(void) { if(!dhcp_timer_storage) { @@ -101,19 +97,16 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r nonTemporalAddress.validLifeTime = dhcp_allocated_address->lifetime; nonTemporalAddress.preferredLifeTime = dhcp_allocated_address->preferredLifetime; - // If this is solicit from existing address, flush ND cache. - if (allocateNew) { - // coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return - DHCPV6_server_service_remove_GUA_from_neighcache(protocol_stack_interface_info_get_by_id(serverBase->interfaceId), nonTemporalAddress.requestedAddress); - } - if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix) == -1) { - // No nanostack BBR present we will put entry for application implemented BBR - ipv6_route_t *route = ipv6_route_add_with_info(dhcp_allocated_address->nonTemporalAddress, 128, serverBase->interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,serverBase->guaPrefix,0, nonTemporalAddress.validLifeTime, 0); - if (!route) { + if (serverBase->addCb) { + dhcp_address_cache_update_t update_info; + update_info.allocatedAddress = dhcp_allocated_address->nonTemporalAddress; + update_info.allocatedNewAddress = allocateNew; + update_info.validLifeTime = nonTemporalAddress.validLifeTime; + + if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) { address_allocated = false; libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress); } - } } @@ -213,30 +206,6 @@ void DHCPv6_server_service_tasklet(arm_event_s *event) } } -static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress) -{ - ipv6_neighbour_t *neighbour_entry; - - neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress); - if (neighbour_entry) { - tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress)); - ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry); - } -} - -void DHCPv6_server_service_address_preferred_timeout_handler(int8_t interfaceId, uint8_t *targetAddress) -{ - tr_warn("Address Preferred Timeout"); - protocol_interface_info_entry_t *cur = 0; - //allocate Socket Service - - cur = protocol_stack_interface_info_get_by_id(interfaceId); - if (cur) { - ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST); - DHCPV6_server_service_remove_GUA_from_neighcache(cur, targetAddress); - } -} - static int8_t dhcpv6_server_service_tasklet_generated(void) { if (dhcpv6_service_tasklet == -1) { @@ -267,28 +236,21 @@ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], u //allocate Socket Service socketInstance = dhcp_service_init(interface, DHCP_INSTANCE_SERVER, DHCPV6_server_service_request_handler); cur = protocol_stack_interface_info_get_by_id(interface); - if (cur) { - if (dhcpv6_server_service_tasklet_generated() < 0) { - retVal = -2; - } else if (!DHCP_server_service_timer_start()) { - retVal = -2; - } else { - //allocate server - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE, DHCPv6_server_service_address_preferred_timeout_handler); - if (serverInfo) { - //if_address_entry_t *def_address = NULL; - uint8_t temp[16]; - uint8_t *ptr = temp; - //define address & Route advert's - memcpy(ptr, guaPrefix, 8); - ptr += 8; - memcpy(ptr, cur->iid_slaac, 8); - - serverInfo->socketInstance_id = socketInstance; - socketInstance = 0; - //Generate Address for current interface - retVal = 0; - } + if (!cur) { + return -1; + } + + if (dhcpv6_server_service_tasklet_generated() < 0) { + retVal = -2; + } else if (!DHCP_server_service_timer_start()) { + retVal = -2; + } else { + //allocate server + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE); + if (serverInfo) { + serverInfo->socketInstance_id = socketInstance; + socketInstance = 0; + retVal = 0; } } if (socketInstance > 0) { @@ -303,25 +265,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds) libdhcpv6_gua_servers_time_update(timeUpdateInSeconds); } -void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping) -{ - uint8_t ml64[16]; - uint8_t *ptr = ml64; - memcpy(ptr, meshLocalPrefix, 8); - ptr += 8; - memcpy(ptr, clientEUID64, 8); - *ptr ^= 2; - //Generate Route Info - if (deleteMapping) { - ipv6_route_delete(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC); - } else if (ipv6_route_add(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC, 0xffffffff, 0) == 0) { - tr_debug("Route ADD OK"); - } else { - tr_warn("Route Add fail"); - } - -} - /* Delete dhcp thread dhcp router ID server. * * When this is called it close selected service and free all allocated memory. @@ -332,30 +275,32 @@ void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAd */ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses) { - protocol_interface_info_entry_t *curPtr = 0; - //allocate Socket Service - - curPtr = protocol_stack_interface_info_get_by_id(interface); - if (curPtr) { - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { - //Delete Server data base - DHCPV6_server_service_remove_GUA_from_neighcache(curPtr, cur->nonTemporalAddress); + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (serverInfo) { + ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { + //Delete Server data base + if (serverInfo->removeCb) { + serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL); } + } + if (serverInfo->removeCb) { // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server - ipv6_route_table_remove_info(curPtr->id, ROUTE_THREAD_PROXIED_HOST,serverInfo->guaPrefix); - dhcp_service_delete(serverInfo->socketInstance_id); + serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix); } + dhcp_service_delete(serverInfo->socketInstance_id); + } - if (delete_gua_addresses) { + if (delete_gua_addresses) { + protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interface); + if (curPtr) { protocol_core_dhcpv6_allocated_address_remove(curPtr, guaPrefix); } + } - libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); + libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); + + DHCP_server_service_timer_stop(); - DHCP_server_service_timer_stop(); - } } /* Control GUA address for client by DUI.Default value is true @@ -379,33 +324,15 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu return retVal; } -/* Enable or disable GUA64 Address mapping to ML64 - * - * - * /param interface interface id of this thread instance. - * /param guaPrefix Prefix which will be removed - * /param mode - * /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64 - */ -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]) +void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb) { - int retVal = -1; - dhcpv6_gua_server_entry_s *serverInfo; - - serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); - if (serverInfo) { - if (mode == true && meshLocalPrefix == NULL) { - retVal = -2; - } else { - serverInfo->enableAddressMapping = mode; - if (meshLocalPrefix) { - memcpy(serverInfo->meshLocalPrefix, meshLocalPrefix, 8); - } - retVal = 0; - } + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return; } - return retVal; + serverInfo->addCb = add_cb; + serverInfo->removeCb = remove_cb; } /* SET max accepted clients to server, Default is 200 @@ -453,21 +380,6 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu } return retVal; } - -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64) -{ - dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, targetGUA); - if (serverInfo) { - dhcpv6_alloacted_address_entry_t *entry = libdhcpv6_address_get_from_allocated_list(serverInfo, targetGUA); - if (entry) { - if (entry->preferredLifetime && (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE)) { - memcpy(targetEUI64, entry->linkId, 8); - return 0; - } - } - } - return -1; -} #else int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) @@ -497,15 +409,6 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu return -1; } -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]) -{ - (void) interface; - (void) guaPrefix; - (void) mode; - (void) meshLocalPrefix; - - return -1; -} int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) { (void) interface; @@ -522,13 +425,5 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu return -1; } -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64) -{ - (void) interfaceId; - (void) targetGUA; - (void) targetEUI64; - - return -1; -} #endif diff --git a/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 50f535f7a74..d2ba01068f4 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/source/DHCPv6_Server/DHCPv6_server_service.h @@ -23,6 +23,10 @@ #ifndef DHCPV6_SERVER_SERVICE_H_ #define DHCPV6_SERVER_SERVICE_H_ +#ifdef HAVE_DHCPV6_SERVER +#include "libDHCPv6/libDHCPv6.h" +#include "libDHCPv6/libDHCPv6_server.h" + /* Initialize dhcp Global address server. * * This instance needs to bee initialized once for each thread network interface. @@ -38,6 +42,10 @@ */ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType); + +void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb); + + /* Delete dhcp thread dhcp router ID server. * * When this is called it close selected service and free all allocated memory. @@ -51,8 +59,6 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16] void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); -//void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping); - /* Control GUA address for client by DUI.Default value is true * * @@ -63,16 +69,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode); -/* Enable or disable GUA64 Address mapping to ML64 - * - * - * /param interface interface id of this thread instance. - * /param guaPrefix Prefix which will be removed - * /param mode - * /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64 - */ -int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]); - /* SET max accepted clients to server, Default is 200 * * @@ -91,7 +87,7 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ * /param validLifeTimne in seconds */ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne); - - -int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64); +#else +#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses) +#endif #endif /* DHCPV6_SERVER_SERVICE_H_ */ diff --git a/source/DHCPv6_client/dhcpv6_client_api.h b/source/DHCPv6_client/dhcpv6_client_api.h new file mode 100644 index 00000000000..69ae1ddd20d --- /dev/null +++ b/source/DHCPv6_client/dhcpv6_client_api.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * 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 DHCPV6_CLIENT_API_H_ +#define DHCPV6_CLIENT_API_H_ +#include + +/* DHCP client implementation. + * + * Responsibilities of this module are: + * - handle Global address queries and refresh inside network. + * + */ + +/* Initialize dhcp client. + * + * This instance needs to bee initialized once for each network interface. + * if only one thread instance is supported this is needed to call only once. + * + * /param interface interface id of this instance. + * + */ + +void dhcp_client_init(int8_t interface); + +/* Delete dhcp client. + * + * When this is called all addressed assigned by this module are removed from stack. + */ +void dhcp_client_delete(int8_t interface); + +/* Global address handler. + * + * This module updates the addresses from dhcp server and sets them in stack. + * this module makes refresh of address when needed. + * + */ + + +/* give dhcp server and prefix for global address assignment + * + * /param interface interface where address is got + * /param dhcp_addr dhcp server ML16 address where address is registered. + * /param prefix dhcp server ML16 address where address is registered. + * /param mac64 64 bit mac address for identifieng client. + * /param error_cb error callback that is called if address cannot be created or becomes invalid. + * /param register_status true if address registered. + * + */ +typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status); + +int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb); + +/* Renew all leased adddresses might be used when short address changes + * + * /param interface interface where address is got + */ +void dhcp_client_global_address_renew(int8_t interface); + +/* Delete address from device + * if prefix is NULL all are deleted + * + * /param interface interface where address is got + * /param prefix dhcp server ML16 address where address is registered. + * + */ +void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]); + + +void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]); + + + +#endif /* DHCPV6_CLIENT_API_H_ */ diff --git a/source/6LoWPAN/Thread/thread_dhcpv6_client.c b/source/DHCPv6_client/dhcpv6_client_service.c similarity index 74% rename from source/6LoWPAN/Thread/thread_dhcpv6_client.c rename to source/DHCPv6_client/dhcpv6_client_service.c index a49054e3ed0..06be8c8374c 100644 --- a/source/6LoWPAN/Thread/thread_dhcpv6_client.c +++ b/source/DHCPv6_client/dhcpv6_client_service.c @@ -1,34 +1,21 @@ /* - * Copyright (c) 2013-2018, Arm Limited and affiliates. - * SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * 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 * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * 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 "nsconfig.h" -#ifdef HAVE_THREAD #include #include #include @@ -36,31 +23,30 @@ #include "ns_list.h" #include "common_functions.h" - +#ifdef HAVE_DHCPV6 #include "dhcp_service_api.h" -#include "thread_dhcpv6_client.h" +#include "dhcpv6_client_api.h" #include "libDHCPv6/libDHCPv6.h" #include "NWK_INTERFACE/Include/protocol.h" -#include "6LoWPAN/Thread/thread_common.h" -#include "6LoWPAN/Thread/thread_bootstrap.h" -#define TRACE_GROUP "TDHP" +#define TRACE_GROUP "DHP" typedef struct { - thread_dhcp_client_global_adress_cb *global_address_cb; + dhcp_client_global_adress_cb *global_address_cb; uint16_t service_instance; + uint16_t relay_instance; uint8_t libDhcp_instance; int8_t interface; -} thread_dhcp_client_class_t; +} dhcp_client_class_t; -thread_dhcp_client_class_t dhcp_client; +static dhcp_client_class_t dhcp_client; -void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr); +void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr); -void thread_dhcp_client_init(int8_t interface) +void dhcp_client_init(int8_t interface) { - // No support for multible thread instances yet. + // No support for multible instances yet. dhcp_client.service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL); dhcp_client.interface = interface; dhcp_client.libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id(); @@ -68,7 +54,13 @@ void thread_dhcp_client_init(int8_t interface) return; } -void thread_dhcp_client_delete(int8_t interface) +void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]) +{ + dhcp_client.relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL); + dhcp_service_relay_instance_enable(dhcp_client.relay_instance, border_router_address); +} + +void dhcp_client_delete(int8_t interface) { protocol_interface_info_entry_t *cur = NULL; dhcpv6_client_server_data_t *srv_data_ptr; @@ -96,7 +88,7 @@ void thread_dhcp_client_delete(int8_t interface) } -void thread_dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) +void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) { if (srv_data_ptr != NULL) { @@ -159,12 +151,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime; memcpy(srv_data_ptr->serverLinkId, serverId.linkID, 8); srv_data_ptr->serverLinkType = serverId.linkType; - srv_data_ptr->serverLinkType = serverId.linkType; srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0; srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1; srv_data_ptr->iaNonTemporalStructValid = true; - thread_dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr); + dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr); if (dhcp_client.global_address_cb) { @@ -172,11 +163,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin } return RET_MSG_ACCEPTED; error_exit: - thread_dhcpv6_client_send_error_cb(srv_data_ptr); + dhcpv6_client_send_error_cb(srv_data_ptr); return RET_MSG_ACCEPTED; } -int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb) +int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb) { dhcpv6_solication_base_packet_s solPacket = {0}; dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; @@ -190,16 +181,19 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st } srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr); + if (!srv_data_ptr) { + tr_error("OOM srv_data_ptr"); + return -1; + } payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); - - if (payload_ptr == NULL || srv_data_ptr == NULL) { - ns_dyn_mem_free(payload_ptr); + if (!payload_ptr) { libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr); - tr_error("Out of memory"); + tr_error("OOM payload_ptr"); return -1; } + dhcp_client.global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code. srv_data_ptr->GlobalAddress = true; // Build solicit @@ -214,17 +208,22 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st // send solicit srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb); - return srv_data_ptr->transActionId ? 0 : -1; + if (srv_data_ptr->transActionId == 0) { + ns_dyn_mem_free(payload_ptr); + libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr); + return -1; + } + + return 0; } -void thread_dhcp_client_global_address_renew(int8_t interface) +void dhcp_client_global_address_renew(int8_t interface) { - // only prepared for changes in thread specifications (void)interface; return; } -void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]) +void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]) { protocol_interface_info_entry_t *cur; dhcpv6_client_server_data_t *srv_data_ptr; @@ -249,7 +248,7 @@ void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_add return; } -void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) +void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) { dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; dhcp_link_options_params_t serverLink; @@ -275,7 +274,7 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_ payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); if (payload_ptr == NULL) { - addr->state_timer = 200;//Retry after? should there be maximum 20 second retry + addr->state_timer = 200; //Retry after 20 seconds tr_error("Out of memory"); return ; } @@ -299,9 +298,14 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_ libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &serverLink); // send solicit srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, srv_data_ptr->server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb); + if (srv_data_ptr->transActionId == 0) { + ns_dyn_mem_free(payload_ptr); + addr->state_timer = 200; //Retry after 20 seconds + tr_error("DHCP renew send failed"); + } } -void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr) +void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr) { protocol_interface_info_entry_t *cur = NULL; if_address_entry_t *address_entry = NULL; @@ -335,6 +339,7 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_ } } address_entry->state_timer = renewTimer; - address_entry->cb = thread_dhcpv6_renew; + address_entry->cb = dhcpv6_renew; } + #endif diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 9315d36e95c..8a1c2edc9d6 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -37,7 +37,9 @@ typedef enum mac_event_t { MAC_TIMER_ACK, MAC_TIMER_CCA, MAC_TX_FAIL, - MAC_TX_TIMEOUT + MAC_TX_TIMEOUT, + MAC_UNKNOWN_DESTINATION, + MAC_TX_PRECOND_FAIL } mac_event_t; typedef enum mac_tx_status_type_t { @@ -89,8 +91,12 @@ typedef enum arm_nwk_mlme_event_type { ARM_NWK_MAC_MLME_INDIRECT_DATA_POLL_AFTER_DATA = 5, } arm_nwk_mlme_event_type_e; +#define ENHANCED_ACK_MAX_LENGTH 255 + typedef struct dev_driver_tx_buffer { uint8_t *buf; + uint8_t *enhanced_ack_buf; + uint16_t ack_len; uint16_t len; unsigned priority:2; } dev_driver_tx_buffer_s; @@ -134,6 +140,11 @@ typedef struct mac_tx_status_t { uint8_t retry; } mac_tx_status_t; +typedef struct mac_mcps_data_conf_fail_s { + uint8_t msduHandle; /**< Handle associated with MSDU */ + uint8_t status; /**< Status of the failing MSDU transmission */ +} mac_mcps_data_conf_fail_t; + typedef struct protocol_interface_rf_mac_setup { int8_t mac_interface_id; bool macUpState; @@ -229,6 +240,7 @@ typedef struct protocol_interface_rf_mac_setup { uint8_t max_ED; uint16_t mlme_ED_counter; mac_tx_status_t mac_tx_status; + mac_mcps_data_conf_fail_t mac_mcps_data_conf_fail; struct cca_structure_s *cca_structure; /* MAC Security components */ struct mlme_device_descriptor_s *device_description_table; diff --git a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c index d326aaa078a..3f09ca01baf 100644 --- a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c +++ b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.c @@ -65,13 +65,24 @@ uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api) return datarate; } +uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api) +{ + protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api); + if (!mac_setup) { + return 0; + } + uint32_t timestamp; + mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)×tamp); + return timestamp; +} + int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number) { protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api); if (!mac_setup) { return -1; } - if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && mac_setup->active_pd_data_request->asynch_request)) { + if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && (mac_setup->active_pd_data_request->asynch_request || mac_setup->timer_mac_event == MAC_TIMER_ACK))) { return -1; } return mac_mlme_rf_channel_change(mac_setup, channel_number); diff --git a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h index 431cd9cd1ae..364c94339f7 100644 --- a/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h +++ b/source/MAC/IEEE802_15_4/mac_fhss_callbacks.h @@ -21,6 +21,7 @@ uint16_t mac_read_tx_queue_sizes(const fhss_api_t *fhss_api, bool broadcast_queue); int mac_read_64bit_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address); uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api); +uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api); int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number); int mac_fhss_frame_tx(const fhss_api_t *fhss_api, int frame_type); int mac_synch_lost(const fhss_api_t *fhss_api); diff --git a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c index 2867513170f..39711c22b54 100644 --- a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c +++ b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c @@ -337,16 +337,16 @@ void mac_header_security_components_read(mac_pre_parsed_frame_t *buffer, mlme_se } -uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) +static bool mac_header_pan_full_compressed(const mac_fcf_sequence_t *header) { - - if (!header->SrcPanPresents) { - if (!header->DstPanPresents) { - return 0xffff; - } - return mac_header_get_dst_panid(header, ptr); + if (header->frameVersion == MAC_FRAME_VERSION_2015 && (!header->DstPanPresents && !header->SrcPanPresents) && header->intraPan) { + return true; } + return false; +} +static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) +{ ptr += mac_fcf_lenght(header);//Skip FCF + DSN ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address @@ -354,15 +354,42 @@ uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_ return common_read_16_bit_inverse(ptr); } -uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) +static uint16_t mac_header_read_dst_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) +{ + ptr += mac_fcf_lenght(header);//Skip FCF + DSN + + return common_read_16_bit_inverse(ptr); +} + +uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id) +{ + if (mac_header_pan_full_compressed(header)) { + return configured_pan_id; + } + + if (!header->SrcPanPresents) { + if (!header->DstPanPresents) { + return 0xffff; + } + return mac_header_read_dst_pan(header, ptr); + } + + return mac_header_read_src_pan(header, ptr); +} + +uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id) { + if (mac_header_pan_full_compressed(header)) { + return configured_pan_id; + } if (!header->DstPanPresents) { + if (header->SrcPanPresents && header->frameVersion == MAC_FRAME_VERSION_2015 && header->DstAddrMode == MAC_ADDR_MODE_NONE) { + return mac_header_read_src_pan(header, ptr); + } return 0xffff; } - ptr += mac_fcf_lenght(header);//Skip FCF + DSN - - return common_read_16_bit_inverse(ptr); + return mac_header_read_dst_pan(header, ptr); } void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr) diff --git a/source/MAC/IEEE802_15_4/mac_header_helper_functions.h b/source/MAC/IEEE802_15_4/mac_header_helper_functions.h index 4231f398209..5ce872323f8 100644 --- a/source/MAC/IEEE802_15_4/mac_header_helper_functions.h +++ b/source/MAC/IEEE802_15_4/mac_header_helper_functions.h @@ -59,8 +59,8 @@ uint16_t mac_buffer_total_payload_length(struct mac_pre_build_frame *buffer); /** * Next function should only call when address mode is not MAC_ADDR_MODE_NONE and parsed proper header! */ -uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); -uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); +uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id); +uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id); void mac_header_get_src_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); void mac_header_get_dst_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); uint8_t mac_address_length(uint8_t address_mode); diff --git a/source/MAC/IEEE802_15_4/mac_indirect_data.c b/source/MAC/IEEE802_15_4/mac_indirect_data.c index 3820c16e8d2..db09d73f1be 100644 --- a/source/MAC/IEEE802_15_4/mac_indirect_data.c +++ b/source/MAC/IEEE802_15_4/mac_indirect_data.c @@ -134,7 +134,7 @@ uint8_t mac_indirect_data_req_handle(mac_pre_parsed_frame_t *buf, protocol_inter comm_status.status = MLME_DATA_POLL_NOTIFICATION; //Call com status - comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), mac_ptr->pan_id); comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index cfe56837606..f118770c330 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -70,6 +70,7 @@ static void mac_set_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup static void mac_clear_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static bool mac_read_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer); +static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup); static int8_t mac_tasklet_event_handler = -1; @@ -87,47 +88,18 @@ static uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s return timestamp; } -static void mac_data_request_init(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) -{ - rf_mac_setup->active_pd_data_request = buffer; - if (buffer->asynch_request) { - buffer->asynch_channel = rf_mac_setup->mac_channel; //Store Original channel - uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list); - if (channel <= 0xff) { - uint8_t switch_channel = channel; - if (rf_mac_setup->mac_channel != switch_channel) { - mac_mlme_mac_radio_disabled(rf_mac_setup); - rf_mac_setup->mac_channel = channel; - mac_mlme_mac_radio_enable(rf_mac_setup); - } - } - } -} - static bool mac_data_request_confirmation_finnish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) { if (!buffer->asynch_request) { return true; } - uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list); - uint8_t switch_channel; - bool return_value; - - if (channel > 0x00ff) { - return_value = true; - switch_channel = buffer->asynch_channel; - } else { - switch_channel = channel; - return_value = false; - } - //Set original Channel back if channel is switched - if (rf_mac_setup->mac_channel != switch_channel) { - mac_mlme_mac_radio_disabled(rf_mac_setup); - rf_mac_setup->mac_channel = switch_channel; - mac_mlme_mac_radio_enable(rf_mac_setup); + if (mlme_scan_analyze_next_channel(&buffer->asynch_channel_list, false) > 0x00ff) { + mac_mlme_rf_channel_change(rf_mac_setup, buffer->asynch_channel); + return true; } - return return_value; + + return false; } @@ -145,7 +117,6 @@ static void mac_data_poll_radio_disable_check(protocol_interface_rf_mac_setup_s static void mcps_data_confirm_cb(protocol_interface_rf_mac_setup_s *rf_mac_setup, mcps_data_conf_t *confirm, mac_pre_parsed_frame_t *ack_buf) { - mac_data_poll_radio_disable_check(rf_mac_setup); if( get_sw_mac_api(rf_mac_setup) ) { @@ -363,13 +334,14 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set verify_status: if (status != MLME_SUCCESS){ - mcps_data_conf_t confirm; - memset(&confirm, 0, sizeof(mcps_data_conf_t)); - confirm.msduHandle = data_req->msduHandle; - confirm.status = status; tr_debug("DATA REQ Fail %u", status); + rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = data_req->msduHandle; + rf_mac_setup->mac_mcps_data_conf_fail.status = status; mcps_sap_prebuild_frame_buffer_free(buffer); - mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); + if (mcps_sap_pd_confirm_failure(rf_mac_setup) != 0) { + // event sending failed, calling handler directly + mac_pd_data_confirm_failure_handle(rf_mac_setup); + } } } @@ -568,7 +540,7 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme //READ SRC Address - uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b)); + uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b), rf_mac_setup->pan_id); mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address); neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode; neighbour_validation.keyId = security_params->KeyIndex; @@ -670,10 +642,11 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme static void mcps_comm_status_indication_generate(uint8_t status, mac_pre_parsed_frame_t *buf, mac_api_t * mac) { mlme_comm_status_t comm_status; + protocol_interface_rf_mac_setup_s *rf_ptr = buf->mac_class_ptr; memset(&comm_status,0 ,sizeof(mlme_comm_status_t) ); comm_status.status = status; //Call com status - comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_ptr->pan_id); comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; @@ -723,12 +696,14 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte //Parse data data_ind->DSN = buf->fcf_dsn.DSN; data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode; - data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr); data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode; - data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->SrcAddr); + data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); + data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); + data_ind->mpduLinkQuality = buf->LQI; data_ind->signal_dbm = buf->dbm; data_ind->timestamp = buf->timestamp; @@ -739,7 +714,6 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte if (buf->fcf_dsn.securityEnabled) { status = mac_data_interface_decrypt_packet(buf, &data_ind->Key); if (status != MLME_SUCCESS) { - tr_debug("Decrypt fail, %d", status); mcps_comm_status_indication_generate(status, buf, mac); goto DROP_PACKET; } @@ -772,6 +746,12 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte ie_list.payloadIeListLength = buf->payloadsIeLength; ie_list.headerIeList = buf->headerIePtr; ie_list.headerIeListLength = buf->headerIeLength; + //Swap compressed address to broadcast when dst Address is elided + if (buf->fcf_dsn.DstAddrMode == MAC_ADDR_MODE_NONE) { + data_ind->DstAddrMode = MAC_ADDR_MODE_16_BIT; + data_ind->DstAddr[0] = 0xff; + data_ind->DstAddr[1] = 0xff; + } mac->data_ind_ext_cb(mac, data_ind, &ie_list); } else { @@ -796,7 +776,7 @@ static void mac_lib_res_no_data_to_req(mac_pre_parsed_frame_t *buffer, protocol_ buf->fcf_dsn.SrcAddrMode = buffer->fcf_dsn.DstAddrMode; buf->fcf_dsn.DstAddrMode = buffer->fcf_dsn.SrcAddrMode; //SET PANID - buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer)); + buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), rf_mac_setup->pan_id); buf->DstPANId = buf->SrcPANId; mac_header_get_dst_address(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), buf->SrcAddr); @@ -910,7 +890,7 @@ static void mac_data_interface_parse_beacon(mac_pre_parsed_frame_t *buf, protoco uint8_t *pending_address_list = NULL; uint8_t SuperframeSpec[2]; - uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); + uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id); //validate beacon pan-id and filter other network out if (rf_mac_setup->pan_id < 0xffff && (rf_mac_setup->pan_id != src_pan_id && !rf_mac_setup->macAcceptAnyBeacon)) { @@ -1045,6 +1025,14 @@ static void mac_data_interface_frame_handler(mac_pre_parsed_frame_t *buf) } +static void mac_mcps_asynch_finish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) +{ + if (buffer->asynch_request && rf_mac_setup->fhss_api) { + // Must return to scheduled channel after asynch process by calling TX done + rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); + } +} + void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_setup) { if (!rf_mac_setup) { @@ -1064,9 +1052,10 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false); if (buffer) { - mac_data_request_init(rf_mac_setup, buffer); + rf_mac_setup->active_pd_data_request = buffer; if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { rf_mac_setup->active_pd_data_request = NULL; + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { return; @@ -1077,7 +1066,6 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s } } - static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_interface_rf_mac_setup_s *rf_mac_setup) { //allocate Data ind primitiv and parse packet to that @@ -1106,20 +1094,18 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter return 0; } -static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) { - +static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) +{ if (rf_mac_setup->active_pd_data_request) { mac_pre_build_frame_t *buffer = rf_mac_setup->active_pd_data_request; if (mac_data_request_confirmation_finnish(rf_mac_setup, buffer) ) { rf_mac_setup->active_pd_data_request = NULL; - if (buffer->asynch_request && rf_mac_setup->fhss_api) { - // Must return to scheduled channel after asynch process by calling TX done - rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); - } + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { rf_mac_setup->active_pd_data_request = NULL; + mac_mcps_asynch_finish(rf_mac_setup, buffer); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); } else { return; @@ -1130,9 +1116,17 @@ static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac mac_mcps_trig_buffer_from_queue(rf_mac_setup); } +static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) +{ + mcps_data_conf_t mcps_data_conf; + memset(&mcps_data_conf, 0, sizeof(mcps_data_conf_t)); + mcps_data_conf.msduHandle = rf_mac_setup->mac_mcps_data_conf_fail.msduHandle; + mcps_data_conf.status = rf_mac_setup->mac_mcps_data_conf_fail.status; + mcps_data_confirm_cb(rf_mac_setup, &mcps_data_conf, NULL); +} -static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { - +static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) +{ protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr; if (!rf_mac_setup->active_pd_data_request) { @@ -1147,10 +1141,6 @@ static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { } rf_mac_setup->active_pd_data_request = NULL; - if (buffer->asynch_request && rf_mac_setup->fhss_api) { - // Must return to scheduled channel after asynch process by calling TX done - rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle); - } mcps_data_confirm_handle(rf_mac_setup, buffer, buf); mcps_sap_pre_parsed_frame_buffer_free(buf); @@ -1177,6 +1167,10 @@ static void mac_mcps_sap_data_tasklet(arm_event_s *event) mac_pd_data_confirm_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr); break; + case MCPS_SAP_DATA_CNF_FAIL_EVENT: + mac_pd_data_confirm_failure_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr); + break; + case MCPS_SAP_DATA_ACK_CNF_EVENT: mac_pd_data_ack_handler((mac_pre_parsed_frame_t*)event->data_ptr); break; @@ -1277,14 +1271,8 @@ static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_ if (buffer->fcf_dsn.DstAddrMode && buffer->fcf_dsn.ackRequested) { device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode); if (!device_description) { - - if (rf_ptr->mac_security_bypass_unknow_device && (buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT - && buffer->aux_header.securityLevel > AES_SECURITY_LEVEL_ENC)) { - - } else { - buffer->status = MLME_UNAVAILABLE_KEY; - return false; - } + buffer->status = MLME_UNAVAILABLE_KEY; + return false; } } nonce_ext_64_ptr = rf_ptr->mac64; @@ -1350,7 +1338,11 @@ static void mac_common_data_confirmation_handle (protocol_interface_rf_mac_setup //Enable Radio mac_mlme_mac_radio_enable(rf_mac_setup); buf->status = MLME_TRANSACTION_EXPIRED; - } + } else if (m_event == MAC_UNKNOWN_DESTINATION) { + buf->status = MLME_UNAVAILABLE_KEY; + }/** else if (m_event == MAC_TX_PRECOND_FAIL) { + * Nothing to do, status already set to buf->status. + }**/ } } @@ -1419,7 +1411,7 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, sw_mac_stats_update(rf_ptr, STAT_MAC_TX_CCA_ATT, rf_ptr->mac_tx_status.cca_cnt); sw_mac_stats_update(rf_ptr, STAT_MAC_TX_RETRY, rf_ptr->mac_tx_status.retry); mcps_data_conf_t confirm; - if (rf_ptr->fhss_api) { + if (rf_ptr->fhss_api && !buffer->asynch_request) { // FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) { if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) { @@ -1615,6 +1607,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m buffer->fcf_dsn.frameVersion = fcf->frameVersion; buffer->fcf_dsn.framePending = rf_ptr->mac_frame_pending; buffer->fcf_dsn.DSN = fcf->DSN; + buffer->fcf_dsn.intraPan = fcf->intraPan; buffer->fcf_dsn.sequenceNumberSuppress = fcf->sequenceNumberSuppress; buffer->fcf_dsn.DstPanPresents = fcf->DstPanPresents; buffer->fcf_dsn.SrcAddrMode = fcf->DstAddrMode; @@ -1628,9 +1621,8 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn); - buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr); - buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr); - + buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr, rf_ptr->pan_id); + buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr, rf_ptr->pan_id); mac_header_get_src_address(fcf, data_ptr, buffer->DstAddr); mac_header_get_dst_address(fcf, data_ptr, buffer->SrcAddr); @@ -1696,7 +1688,15 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m //Add MHR length to total length frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len; - if ((frame_length) > dev_driver->phy_MTU - 2) { + uint16_t ack_mtu_size; + if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_MTU) { + ack_mtu_size = dev_driver->phy_MTU; + } else { + ack_mtu_size = ENHANCED_ACK_MAX_LENGTH; + } + + + if ((frame_length) > ack_mtu_size - 2) { buffer->status = MLME_FRAME_TOO_LONG; if (buffer->fcf_dsn.securityEnabled) { @@ -1708,14 +1708,14 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m } rf_ptr->mac_tx_status.length = frame_length; - uint8_t *ptr = tx_buf->buf; + uint8_t *ptr = tx_buf->enhanced_ack_buf; if (dev_driver->phy_header_length) { ptr += dev_driver->phy_header_length; } - tx_buf->len = frame_length; + tx_buf->ack_len = frame_length; uint8_t *mhr_start = ptr; - buffer->tx_time = rx_time + 196; //Send 196 us later + buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later ptr = mac_generic_packet_write(rf_ptr, ptr, buffer); @@ -1731,9 +1731,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m csma_params.cca_enabled = false; rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t*) &csma_params); if (rf_ptr->active_pd_data_request) { + timer_mac_stop(rf_ptr); mac_pd_sap_set_phy_tx_time(rf_ptr, 0, false); } - return mcps_pd_data_cca_trig(rf_ptr, buffer); } @@ -1803,6 +1803,7 @@ static int8_t mcps_generic_packet_rebuild(protocol_interface_rf_mac_setup_s *rf_ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer) { + platform_enter_critical(); mac_mlme_mac_radio_enable(rf_ptr); rf_ptr->macTxProcessActive = true; if (rf_ptr->rf_csma_extension_supported) { @@ -1810,18 +1811,35 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m bool cca_enabled; if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { cca_enabled = false; + rf_ptr->mac_ack_tx_active = true; } else { + if (rf_ptr->mac_ack_tx_active) { + mac_csma_backoff_start(rf_ptr); + platform_exit_critical(); + return -1; + } cca_enabled = true; } mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled); if (mac_plme_cca_req(rf_ptr) != 0) { - rf_ptr->macTxProcessActive = false; - return -1; + if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { + rf_ptr->mac_ack_tx_active = false; + // For Ack, stop the active TX process + rf_ptr->macTxProcessActive = false; + // If MAC had TX process active before Ack transmission, + // the TX process has to be restarted in case the Ack transmission failed. + if (rf_ptr->active_pd_data_request) { + mac_csma_backoff_start(rf_ptr); + } + platform_exit_critical(); + return -1; + } + mac_csma_backoff_start(rf_ptr); } } else { timer_mac_start(rf_ptr, MAC_TIMER_CCA, (uint16_t)(buffer->tx_time / 50)); } - + platform_exit_critical(); return 0; } @@ -1891,19 +1909,18 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup } } //Start TX process immediately - mac_data_request_init(rf_mac_setup, buffer); + rf_mac_setup->active_pd_data_request = buffer; if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { - rf_mac_setup->active_pd_data_request = NULL; - mcps_data_conf_t confirm; - memset(&confirm, 0, sizeof(mcps_data_conf_t)); - confirm.msduHandle = buffer->msduHandle; - confirm.status = buffer->status; - bool requested_from_up = buffer->upper_layer_request; - mcps_sap_prebuild_frame_buffer_free(buffer); - if (requested_from_up) { - mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); + rf_mac_setup->mac_tx_result = MAC_TX_PRECOND_FAIL; + rf_mac_setup->macTxRequestAck = false; + if (mcps_sap_pd_confirm(rf_mac_setup) != 0) { + // can't send event, try calling error handler directly + rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = buffer->msduHandle; + rf_mac_setup->mac_mcps_data_conf_fail.status = buffer->status; + mcps_sap_prebuild_frame_buffer_free(buffer); + rf_mac_setup->active_pd_data_request = NULL; + mac_pd_data_confirm_failure_handle(rf_mac_setup); } - //Call } return; @@ -1981,7 +1998,7 @@ static mac_pre_build_frame_t * mcps_sap_pd_req_queue_read(protocol_interface_rf_ // With FHSS, check TX conditions if (rf_mac_setup->fhss_api) { while (buffer) { - if ((flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer), + if (buffer->asynch_request || (flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer), buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length, rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true)) { break; @@ -2083,10 +2100,10 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer) return eventOS_event_send(&event); } -void mcps_sap_pd_confirm(void *mac_ptr) +int8_t mcps_sap_pd_confirm(void *mac_ptr) { if (mac_tasklet_event_handler < 0 || !mac_ptr) { - return; + return -2; } arm_event_s event = { .receiver = mac_tasklet_event_handler, @@ -2097,8 +2114,24 @@ void mcps_sap_pd_confirm(void *mac_ptr) .priority = ARM_LIB_HIGH_PRIORITY_EVENT, }; - eventOS_event_send(&event); + return eventOS_event_send(&event); +} +int8_t mcps_sap_pd_confirm_failure(void *mac_ptr) +{ + if (mac_tasklet_event_handler < 0 || !mac_ptr) { + return -2; + } + arm_event_s event = { + .receiver = mac_tasklet_event_handler, + .sender = 0, + .event_id = 0, + .data_ptr = mac_ptr, + .event_type = MCPS_SAP_DATA_CNF_FAIL_EVENT, + .priority = ARM_LIB_HIGH_PRIORITY_EVENT, + }; + + return eventOS_event_send(&event); } void mcps_sap_pd_ack(void *ack_ptr) @@ -2226,17 +2259,14 @@ static bool mcps_sap_purge_req_from_queue(protocol_interface_rf_mac_setup_s *rf_ uint8_t status = false; rf_mac_setup->pd_data_request_queue_to_go = mcps_sap_purge_from_list(rf_mac_setup->pd_data_request_queue_to_go, msduhandle, &status); - if (status) { - return true; + if (!status) { + rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status); } - rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status); - return status; - } -void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req) +uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req) { mcps_purge_conf_t confirmation; confirmation.msduHandle = purge_req->msduHandle; @@ -2250,4 +2280,6 @@ void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, if( get_sw_mac_api(rf_mac_setup) ) { get_sw_mac_api(rf_mac_setup)->purge_conf_cb(get_sw_mac_api(rf_mac_setup), &confirmation); } + + return confirmation.status; } diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.h b/source/MAC/IEEE802_15_4/mac_mcps_sap.h index 59d14cdbf76..2e88e69c53f 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.h +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.h @@ -48,14 +48,14 @@ typedef enum { #define MAC_PD_DATA_MEDIUM_PRIORITY 1 //Indirect Data which is polled #define MAC_PD_DATA_HIGH_PRIOTITY 2 //Beacon request Beacon response -#define MCPS_SAP_DATA_IND_EVENT 1 -#define MCPS_SAP_DATA_CNF_EVENT 2 -#define MAC_MLME_EVENT_HANDLER 3 -#define MAC_MCPS_INDIRECT_TIMER_CB 4 -#define MAC_MLME_SCAN_CONFIRM_HANDLER 5 -#define MAC_SAP_TRIG_TX 6 -#define MCPS_SAP_DATA_ACK_CNF_EVENT 7 - +#define MCPS_SAP_DATA_IND_EVENT 1 +#define MCPS_SAP_DATA_CNF_EVENT 2 +#define MCPS_SAP_DATA_CNF_FAIL_EVENT 3 +#define MAC_MLME_EVENT_HANDLER 4 +#define MAC_MCPS_INDIRECT_TIMER_CB 5 +#define MAC_MLME_SCAN_CONFIRM_HANDLER 6 +#define MAC_SAP_TRIG_TX 7 +#define MCPS_SAP_DATA_ACK_CNF_EVENT 8 /** * @brief struct mac_aux_security_header_t MAC auxiliarity security header structure @@ -180,7 +180,9 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer); /** * MAC MCPS SAP layer data confirmation event trig */ -void mcps_sap_pd_confirm(void *mac_ptr); +int8_t mcps_sap_pd_confirm(void *mac_ptr); + +int8_t mcps_sap_pd_confirm_failure(void *mac_ptr); void mcps_sap_pd_ack(void *ack_ptr); @@ -200,7 +202,7 @@ int mac_convert_frame_type_to_fhss(uint8_t frame_type); void mcps_sap_trig_tx(void *mac_ptr); -void mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req); +uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req); int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer); diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index bdf1c049690..51c63f329f0 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -85,7 +85,7 @@ static void mac_mlme_energy_scan_start(protocol_interface_rf_mac_setup_s *rf_mac rf_mac_setup->macRfRadioTxActive = false; } -uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list) +uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list, bool clear_channel) { uint8_t i, j = 0, k = 1; uint32_t mask = 1; @@ -101,7 +101,9 @@ uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list) { if (*channel_mask & mask) { - *channel_mask &= ~mask; + if (clear_channel) { + *channel_mask &= ~mask; + } return (i+j*32); } mask <<= 1; @@ -280,7 +282,7 @@ static void mac_mlme_scan_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) { uint8_t channel; - channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); + channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true); mac_mlme_scan_init(channel, rf_mac_setup); } @@ -400,14 +402,14 @@ int8_t mac_mlme_start_req(const mlme_start_t *s, struct protocol_interface_rf_ma tr_debug("MAC: Start network %u channel %x panid", s->LogicalChannel, s->PANId); mac_mlme_set_panid(rf_mac_setup, s->PANId); + // Synchronize FHSS if (rf_mac_setup->fhss_api) { - rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId); - } - - if (!rf_mac_setup->fhss_api) { + rf_mac_setup->mac_channel = rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId); + } else { rf_mac_setup->mac_channel = s->LogicalChannel; } + mac_mlme_start_request(rf_mac_setup); if (s->PANCoordinator) { //tr_debug("Cordinator"); @@ -795,7 +797,7 @@ static void mlme_scan_operation(protocol_interface_rf_mac_setup_s *rf_mac_setup) resp->ResultListSize++; } - channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); + channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true); if (channel > 0xff || rf_mac_setup->mac_mlme_scan_resp->ResultListSize == MLME_MAC_RES_SIZE_MAX) { resp->status = MLME_SUCCESS; tr_debug("Scan Complete..Halt MAC"); @@ -981,6 +983,7 @@ void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_ma eventOS_callback_timer_unregister(rf_mac->mac_mcps_timer); ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.buf); + ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.enhanced_ack_buf); ns_dyn_mem_free(rf_mac->mac_beacon_payload); mac_sec_mib_deinit(rf_mac); @@ -1510,8 +1513,9 @@ int8_t mac_mlme_rf_channel_change(protocol_interface_rf_mac_setup_s *rf_mac_setu return 0; } platform_enter_critical(); - rf_mac_setup->mac_channel = new_channel; - rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &rf_mac_setup->mac_channel); + if (rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &new_channel) == 0) { + rf_mac_setup->mac_channel = new_channel; + } platform_exit_critical(); return 0; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.h b/source/MAC/IEEE802_15_4/mac_mlme.h index 41f29601596..5878f702707 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.h +++ b/source/MAC/IEEE802_15_4/mac_mlme.h @@ -125,6 +125,6 @@ int8_t mac_mlme_beacon_tx(struct protocol_interface_rf_mac_setup *rf_ptr); uint8_t mac_mlme_beacon_req_tx(struct protocol_interface_rf_mac_setup *rf_ptr); int8_t mac_mlme_virtual_confirmation_handle(int8_t driver_id, const uint8_t *data_ptr, uint16_t length); -uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list); +uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list, bool clear_channel); #endif /* MAC_MLME_H_ */ diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 98586cf813a..8f71f73b309 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -38,8 +38,13 @@ /* Define TX Timeot Period */ // Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout #define NWKTX_TIMEOUT_PERIOD (1200*20) +// Measured 3750us with 1280 byte secured packet from calculating TX time to starting CSMA timer on PHY. +// Typically varies from 500us to several milliseconds depending on packet size and the platform. +// MAC should learn and make this dynamic by sending first few packets with predefined CSMA period. +#define MIN_FHSS_CSMA_PERIOD_US 4000 static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry); +static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr); void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup) { @@ -64,7 +69,7 @@ static uint16_t mac_csma_backoff_period_convert_to50us(uint8_t random, uint8_t b return (random * backoff_period_in_10us) / 5; } -static void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) +void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) { uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup); uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff, rf_mac_setup->backoff_period_in_10us); @@ -90,6 +95,13 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (backoff_in_us == 0) { backoff_in_us = 1; } + if (rf_mac_setup->fhss_api) { + // Synchronization error when backoff time is shorter than allowed. + // TODO: Make this dynamic. + if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) { + backoff_in_us += MIN_FHSS_CSMA_PERIOD_US; + } + } return backoff_in_us; } @@ -136,21 +148,31 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup) { dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer; phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver; - + rf_mac_setup->macRfRadioTxActive = true; if (dev_driver->arm_net_virtual_tx_cb) { if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { - rf_mac_setup->macRfRadioTxActive = true; timer_mac_start(rf_mac_setup, MAC_TX_TIMEOUT, NWKTX_TIMEOUT_PERIOD); /*Start Timeout timer for virtual packet loss*/ } else { + rf_mac_setup->macRfRadioTxActive = false; mac_data_interface_tx_to_cb(rf_mac_setup); } return 0; } - if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { - rf_mac_setup->macRfRadioTxActive = true; + uint8_t *buffer; + uint16_t length; + if (rf_mac_setup->mac_ack_tx_active) { + buffer = tx_buf->enhanced_ack_buf; + length = tx_buf->ack_len; + } else { + buffer = tx_buf->buf; + length = tx_buf->len; + } + if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) { return 0; } + + rf_mac_setup->macRfRadioTxActive = false; return -1; } @@ -219,6 +241,12 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (rf_mac_setup->macUpState && rf_mac_setup->macTxProcessActive) { if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) { + + if (rf_mac_setup->rf_csma_extension_supported) { + mac_sap_cca_fail_cb(rf_mac_setup); + return; + } + if (rf_mac_setup->fhss_api) { uint8_t *synch_info = NULL; mac_pre_build_frame_t *active_buf = rf_mac_setup->active_pd_data_request; @@ -254,6 +282,9 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) if (tx_handle_retval == -3) { mac_tx_done_state_set(rf_mac_setup, MAC_CCA_FAIL); return; + } else if (tx_handle_retval == -2) { + mac_tx_done_state_set(rf_mac_setup, MAC_UNKNOWN_DESTINATION); + return; } } if (mac_plme_cca_req(rf_mac_setup) != 0) { @@ -267,16 +298,24 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup) } } -static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) { - rf_ptr->macRfRadioTxActive = false; - if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { - //Send MAC_CCA_FAIL - mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); +static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) +{ + if (rf_ptr->mac_ack_tx_active) { + if (rf_ptr->active_pd_data_request) { + mac_csma_backoff_start(rf_ptr); + } } else { - timer_mac_stop(rf_ptr); - mac_csma_BE_update(rf_ptr); - if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request) ) { + + rf_ptr->macRfRadioTxActive = false; + if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { + //Send MAC_CCA_FAIL mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + } else { + timer_mac_stop(rf_ptr); + mac_csma_BE_update(rf_ptr); + if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request) ) { + mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + } } } } @@ -322,6 +361,20 @@ static bool mac_data_counter_too_small(uint32_t current_counter, uint32_t packet } +static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *active_buf) +{ + if (!active_buf || !active_buf->asynch_request) { + return false; + } + active_buf->asynch_channel = rf_ptr->mac_channel; //Store Original channel + uint16_t channel = mlme_scan_analyze_next_channel(&active_buf->asynch_channel_list, true); + if (channel <= 0xff) { + mac_mlme_rf_channel_change(rf_ptr, channel); + + } + return true; +} + static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry) { @@ -330,10 +383,16 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r } if (status == PHY_LINK_CCA_PREPARE) { + + if (rf_ptr->mac_ack_tx_active) { + return 0; + } + + if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request) ) { + return 0; + } + if (rf_ptr->fhss_api) { - if (rf_ptr->mac_ack_tx_active) { - return 0; - } mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request; if (!active_buf) { return -1; @@ -345,25 +404,28 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r uint8_t *synch_info = tx_buf->buf + rf_ptr->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH; rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, synch_info, 0, FHSS_SYNCH_FRAME, 0); } - if (active_buf->asynch_request == false) { - // Change to destination channel and write synchronization info to Beacon frames here - int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf), - active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype), - active_buf->mac_payload_length, rf_ptr->dev_driver->phy_driver->phy_header_length, - rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); - // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer - if (tx_handle_retval == -1) { - mac_sap_cca_fail_cb(rf_ptr); - return -2; - } - // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back - // to queue by using CCA fail event - if (tx_handle_retval == -3) { - mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); - return -3; - } + + // Change to destination channel and write synchronization info to Beacon frames here + int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf), + active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype), + active_buf->mac_payload_length, rf_ptr->dev_driver->phy_driver->phy_header_length, + rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); + // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer + if (tx_handle_retval == -1) { + mac_sap_cca_fail_cb(rf_ptr); + return -2; + } + // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back + // to queue by using CCA fail event + if (tx_handle_retval == -3) { + mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); + return -3; + } else if (tx_handle_retval == -2) { + mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION); + return -2; } } + return 0; } @@ -373,6 +435,10 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r if (rf_ptr->mac_ack_tx_active) { rf_ptr->mac_ack_tx_active = false; + if (rf_ptr->fhss_api) { + //SET tx completed false because ack isnot never queued + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff); + } if (rf_ptr->active_pd_data_request) { if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) { @@ -450,7 +516,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf) { - if (!rf_ptr->macRfRadioTxActive) { + if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) { return -1; } @@ -465,9 +531,7 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set mcps_sap_pd_ack(buf); if (rf_ptr->fhss_api) { - if (rf_ptr->active_pd_data_request->asynch_request == false) { - rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); - } + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); } return 0; } @@ -611,8 +675,6 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) if (mcps_generic_ack_build(rf_ptr, &fcf_read, pd_data_ind->data_ptr, &ack_payload, time_stamp) !=0) { return -1; } - - rf_ptr->mac_ack_tx_active = true; } } diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.h b/source/MAC/IEEE802_15_4/mac_pd_sap.h index f975f039522..d6364ba5274 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.h +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.h @@ -48,6 +48,8 @@ int8_t mac_pd_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *message); void mac_csma_param_init(struct protocol_interface_rf_mac_setup *rf_mac_setup); uint32_t mac_csma_backoff_get(struct protocol_interface_rf_mac_setup *rf_mac_setup); + +void mac_csma_backoff_start(struct protocol_interface_rf_mac_setup *rf_mac_setup); /** * Run Mac data interface state Machine. * diff --git a/source/MAC/IEEE802_15_4/sw_mac.c b/source/MAC/IEEE802_15_4/sw_mac.c index 45fbfc2ca06..3c8dee0721c 100644 --- a/source/MAC/IEEE802_15_4/sw_mac.c +++ b/source/MAC/IEEE802_15_4/sw_mac.c @@ -54,7 +54,7 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication static void mlme_req(const mac_api_t* api, mlme_primitive id, const void *data); static void mcps_req(const mac_api_t* api, const mcps_data_req_t *data); static void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list); -static void purge_req(const mac_api_t* api, const mcps_purge_t *data); +static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data); static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64); static int8_t macext_mac64_address_get( const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf); @@ -176,6 +176,7 @@ int ns_sw_mac_fhss_register(mac_api_t *mac_api, fhss_api_t *fhss_api) fhss_callback_t callbacks; callbacks.read_tx_queue_size = &mac_read_tx_queue_sizes; callbacks.read_datarate = &mac_read_phy_datarate; + callbacks.read_timestamp = &mac_read_phy_timestamp; callbacks.read_mac_address = &mac_read_64bit_mac_address; callbacks.change_channel = &mac_set_channel; callbacks.send_fhss_frame = &mac_fhss_frame_tx; @@ -251,6 +252,22 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication cur->data_ind_ext_cb = data_ind_cb; cur->enhanced_ack_data_req_cb = ack_data_req_cb; if (data_cnf_cb && data_ind_cb && ack_data_req_cb) { + arm_device_driver_list_s *dev_driver = mac_store.setup->dev_driver; + ns_dyn_mem_free(mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf); + + uint16_t total_length; + if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_driver->phy_MTU) { + total_length = dev_driver->phy_driver->phy_MTU; + } else { + total_length = ENHANCED_ACK_MAX_LENGTH; + } + + total_length += (dev_driver->phy_driver->phy_header_length + dev_driver->phy_driver->phy_tail_length); + mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf = ns_dyn_mem_alloc(total_length); + if (!mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf) { + return -2; + } + mac_store.setup->mac_extension_enabled = true; } else { mac_store.setup->mac_extension_enabled = false; @@ -509,11 +526,12 @@ void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_ } -static void purge_req(const mac_api_t* api, const mcps_purge_t *data) +static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data) { if (mac_store.mac_api == api) { - mcps_sap_purge_reg_handler(mac_store.setup , data ); + return mcps_sap_purge_reg_handler(mac_store.setup , data ); } + return MLME_INVALID_HANDLE; } static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64) @@ -587,8 +605,7 @@ static int8_t sw_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_li phy_msg.message.mac15_4_pd_sap_confirm.cca_retry = cca_retry; phy_msg.message.mac15_4_pd_sap_confirm.tx_retry = tx_retry; - mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg); - return 0; + return mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg); } static void bc_enable_timer_cb(int8_t timer_id, uint16_t slots) diff --git a/source/MPL/mpl.c b/source/MPL/mpl.c index 13ad35e10e6..f1c809fb9dd 100644 --- a/source/MPL/mpl.c +++ b/source/MPL/mpl.c @@ -1011,17 +1011,41 @@ void mpl_clear_realm_scope_seeds(protocol_interface_info_entry_t *cur) static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, int16_t *result) { mpl_domain_t *domain = mpl_domain_lookup_with_realm_check(buf->interface, buf->dst_sa.address); - if (!domain) { - // We need to tunnel - if (stage != IPV6_EXTHDR_MODIFY) { - *result = 0; + /* Deal with simpler modify-already-created-header case first. Note that no error returns. */ + if (stage == IPV6_EXTHDR_MODIFY) { + if (!domain) { + *result = IPV6_EXTHDR_MODIFY_TUNNEL; + memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16); + buf->src_sa.addr_type = ADDR_NONE; // force auto-selection return buf; } - *result = IPV6_EXTHDR_MODIFY_TUNNEL; - memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16); - buf->src_sa.addr_type = ADDR_NONE; // force auto-selection + if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) { + /* We assume we created this, therefore our option is in place + * in the expected place. Sequence is set now, AFTER + * fragmentation. + */ + uint8_t *iphdr = buffer_data_pointer(buf); + uint8_t *ext = iphdr + IPV6_HDRLEN; + if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) { + tr_err("modify"); + return buffer_free(buf); + } + /* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */ + ext[5] = domain->sequence++; + buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED; + buf->mpl_option_data_offset = IPV6_HDRLEN + 4; + mpl_forwarder_process_message(buf, domain, true); + } + *result = 0; + return buf; + } + + /* Rest of code deals with header insertion */ + if (!domain) { + // We will need to tunnel - do nothing on the inner packet + *result = 0; return buf; } @@ -1112,26 +1136,6 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i buf->options.ip_extflags |= IPEXT_HBH_MPL | IPEXT_HBH_MPL_UNFILLED; return buf; } - case IPV6_EXTHDR_MODIFY: - if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) { - /* We assume we created this, therefore our option is in place - * in the expected place. Sequence is set now, AFTER - * fragmentation. - */ - uint8_t *iphdr = buffer_data_pointer(buf); - uint8_t *ext = iphdr + IPV6_HDRLEN; - if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) { - tr_err("modify"); - return buffer_free(buf); - } - /* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */ - ext[5] = domain->sequence++; - buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED; - buf->mpl_option_data_offset = IPV6_HDRLEN + 4; - mpl_forwarder_process_message(buf, domain, true); - } - *result = 0; - return buf; default: return buffer_free(buf); } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index e95865bfad7..8239bc0fdd2 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -348,9 +348,10 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c } } -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle) +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle) { domain->callback = callback; + domain->prefix_cb = prefix_learn_cb; domain->cb_handle = cb_handle; } @@ -677,28 +678,22 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t * const uint8_t *prefix = ptr + 16; if (!pref_parent || neighbour == pref_parent) { - //Check is L Flag active - if (flags & PIO_L) { - //define ONLink Route Information - //tr_debug("Register On Link Prefix to routing table"); - ipv6_route_add(prefix, prefix_len, cur->id, NULL, ROUTE_RADV, valid, 0); - } - /* Check if A-Flag. - * A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC) - * from a prefix advertised by a parent. - */ - if (pref_parent && (flags & PIO_A)) { - if (icmpv6_slaac_prefix_update(cur, prefix, prefix_len, valid, preferred) != 0) { - ipv6_interface_slaac_handler(cur, prefix, prefix_len, valid, preferred); - } - } /* Store prefixes for possible forwarding */ /* XXX if leaf - don't bother? Or do we want to remember them for * when we switch DODAG, as mentioned above? */ - rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); + prefix_entry_t *prefix_entry = rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); + if (prefix_entry && pref_parent) { + rpl_control_process_prefix_option(prefix_entry, cur); + rpl_domain_t *domain = cur->rpl_domain; + if (domain && domain->prefix_cb) { + uint8_t ll_address[16]; + memcpy(ll_address, rpl_neighbour_ll_address(pref_parent), 16); + domain->prefix_cb(prefix_entry, domain->cb_handle,ll_address); + } + } } if ((flags & PIO_R) && !router_addr_set) { @@ -715,6 +710,18 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t * } } +void rpl_control_process_prefix_option(prefix_entry_t *prefix, protocol_interface_info_entry_t *cur) +{ + //Check is L Flag active + if (prefix->options & PIO_L) { + //define ONLink Route Information + //tr_debug("Register On Link Prefix to routing table"); + ipv6_route_add(prefix->prefix, prefix->prefix_len, cur->id, NULL, ROUTE_RADV, prefix->lifetime, 0); + } + +} + + /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -1004,7 +1011,7 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r rpl_instance_consistent_rx(instance); } - rpl_instance_neighbours_changed(instance); + rpl_instance_neighbours_changed(instance, dodag); return buffer_free(buf); diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 72f77885514..c924750d796 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -29,15 +29,19 @@ struct rpl_dodag; struct buffer; struct protocol_interface_info_entry; struct rpl_dodag_info_t; +struct prefix_entry_t; typedef enum rpl_event { RPL_EVENT_DAO_DONE, /* Simplistic trigger for bootstrap advance - a DAO registration completed */ RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/ RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */ + RPL_EVENT_DAO_PARENT_SWITCH, /* RPL indicate that DAO downward Parent state have been updated */ } rpl_event_t; typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); +typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local); + typedef struct rpl_domain { NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; @@ -50,6 +54,7 @@ typedef struct rpl_domain /* As part of shutdown, we can force entering leaf mode */ bool force_leaf; rpl_domain_callback_t *callback; + rpl_prefix_callback_t *prefix_cb; void *cb_handle; } rpl_domain_t; @@ -100,6 +105,7 @@ void rpl_control_transmit_dio(struct rpl_domain *domain, struct protocol_interfa bool rpl_control_transmit_dao(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, struct rpl_instance *instance, uint8_t instance_id, uint8_t dao_sequence, const uint8_t dodagid[16], const uint8_t *opts, uint16_t opts_size, const uint8_t *dst); void rpl_control_disable_ra_routes(struct rpl_domain *domain); void rpl_control_event(struct rpl_domain *domain, rpl_event_t event); +void rpl_control_process_prefix_option(struct prefix_entry_t *prefix, struct protocol_interface_info_entry *cur); /*********************** RPL control API to rest of system *******************/ @@ -138,7 +144,7 @@ rpl_domain_t *rpl_control_create_domain(void); void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle); +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); @@ -160,7 +166,6 @@ const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance * const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global); uint16_t rpl_control_current_rank(const struct rpl_instance *instance); - #else /* HAVE_RPL */ #define rpl_control_fast_timer(ticks) ((void) 0) diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 8e040e5c67e..d99c3e1c2fe 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -243,6 +243,8 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance) } } } + //GENERATE PARENT Update event + rpl_control_event(instance->domain, RPL_EVENT_DAO_PARENT_SWITCH); rpl_instance_dao_trigger(instance, 0); } } @@ -588,7 +590,7 @@ void rpl_instance_send_address_registration(protocol_interface_info_entry_t *int aro.status = ARO_SUCCESS; aro.present = true; - aro.lifetime = addr->preferred_lifetime; + aro.lifetime = addr->valid_lifetime; memcpy(aro.eui64, interface->mac, 8); // go through neighbour list, and send to all assigned parents. diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 0e518d029f9..4210442fdf8 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -134,6 +134,7 @@ typedef struct rpl_dao_non_root uint32_t refresh_timer; /* Refresh timer (seconds) - 0xFFFFFFFF = infinite, 0 = not yet set */ } rpl_dao_non_root_t; + /* Descriptor for a RPL DAO target */ struct rpl_dao_target { diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 126e195312e..fdc5f341bd4 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -427,7 +427,7 @@ void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour) } if (neighbour->dodag_parent) { rpl_instance_remove_system_routes_through_parent(instance, neighbour); - rpl_instance_neighbours_changed(instance); + rpl_instance_neighbours_changed(instance, NULL); } rpl_free(neighbour, sizeof *neighbour); @@ -1171,13 +1171,18 @@ bool rpl_instance_purge(rpl_instance_t *instance) return false; } -void rpl_instance_neighbours_changed(rpl_instance_t *instance) +void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag) { instance->neighbours_changed = true; - if (!rpl_instance_preferred_parent(instance)) { - rpl_instance_set_local_repair(instance, true); + uint16_t delay = rpl_policy_dio_parent_selection_delay(instance->domain); + if (dodag) { + //Convert imin 100ms tick to seconds + uint16_t i_min_delay = dodag->dio_timer_params.Imin / 10; + if (i_min_delay > delay) { + delay = i_min_delay; + } } - rpl_instance_trigger_parent_selection(instance, rpl_policy_dio_parent_selection_delay(instance->domain)); + rpl_instance_trigger_parent_selection(instance, delay); } static void rpl_instance_remove_parents(rpl_instance_t *instance) @@ -1366,7 +1371,18 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) } } - rpl_instance_set_local_repair(instance, preferred_parent == NULL); + //Control Local repair state + if (preferred_parent) { + // Always stop repair if we find a parent + rpl_instance_set_local_repair(instance, false); + } else if (original_preferred) { + // Only start repair if we just lost a parent + rpl_instance_set_local_repair(instance, true); + } else { + // !preferred_parent && !original_preferred - didn't have a parent, + // still don't. Leave repair flag as-is (would be off on initial start + // up, may be on if having problems mid-session). + } if (rpl_instance_mop(instance) != RPL_MODE_NO_DOWNWARD) { rpl_downward_process_dao_parent_changes(instance); @@ -1384,6 +1400,20 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) rpl_control_print(trace_info_print); /* Changing DODAG version is an inconsistency */ if (original_version != instance->current_dodag_version) { + //learn Routes an Prefixes + if (preferred_parent && instance->current_dodag_version) { + rpl_dodag_t *dodag = instance->current_dodag_version->dodag; + protocol_interface_info_entry_t *rpl_interface = protocol_stack_interface_info_get_by_id(preferred_parent->interface_id); + if (rpl_interface) { + ns_list_foreach(prefix_entry_t, prefix, &dodag->prefixes) { + rpl_control_process_prefix_option(prefix, rpl_interface); + if (instance->domain->prefix_cb) { + instance->domain->prefix_cb(prefix, rpl_interface, preferred_parent->ll_address); + } + } + } + } + rpl_instance_inconsistency(instance); return; } @@ -1536,6 +1566,7 @@ void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds) } } + void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) { rpl_dodag_version_t *dodag_version = instance->current_dodag_version; diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index 1718d753739..1225e285495 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -135,7 +135,7 @@ void rpl_neighbour_update_dodag_version(rpl_neighbour_t *neighbour, rpl_dodag_ve bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn); rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour); -void rpl_instance_neighbours_changed(rpl_instance_t *instance); +void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag); void rpl_instance_run_parent_selection(rpl_instance_t *instance); void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn); diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 981ab71ad8e..084ffaafed6 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -81,6 +81,9 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ if (!entry) { return; } + if (entry->etx_samples < 7) { + entry->etx_samples++; + } accumulated_failures = entry->accumulated_failures; diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index 12b1ee6117c..a0216b4a382 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -38,6 +38,7 @@ typedef struct etx_storage_s { unsigned accumulated_failures: 5; unsigned tmp_etx: 1; unsigned linkIdr: 4; + unsigned etx_samples: 3; } etx_storage_t; /** diff --git a/source/Service_Libs/fhss/channel_functions.h b/source/Service_Libs/fhss/channel_functions.h index 990a7ac90e6..f6ceab73bb8 100644 --- a/source/Service_Libs/fhss/channel_functions.h +++ b/source/Service_Libs/fhss/channel_functions.h @@ -17,25 +17,44 @@ #ifndef CHANNEL_FUNC_H_ #define CHANNEL_FUNC_H_ +/** + * @brief Function calculates nearest (higher) prime number for given start value. + * @param start_value Start value. + * @return Calculated prime number. + */ +uint16_t tr51_calc_nearest_prime_number(uint16_t start_value); + +/** + * @brief Initialize channel table for TR51 channel function. + * @param channel_table Channel table to be initialized. + * @param number_of_channels Number of channels. + * @return 0 Success, -1 Failure. + */ +int tr51_init_channel_table(int16_t *channel_table, int16_t number_of_channels); + /** * @brief Compute the unicast schedule channel index using tr51 channel function. + * @param channel_table Channel table. + * @param output_table Table used to generate output channel. * @param slot_number Current slot number. * @param mac MAC address of the node for which the index is calculated. * @param number_of_channels Number of channels. * @param excluded_channels Excluded channels. * @return Channel index. */ -int32_t tr51_get_uc_channel_index(uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels); +int32_t tr51_get_uc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels); /** * @brief Compute the broadcast schedule channel index using tr51 channel function. + * @param channel_table Channel table. + * @param output_table Table used to generate output channel. * @param slot_number Current slot number. * @param bsi Broadcast schedule identifier of the node for which the index is calculated. * @param number_of_channels Number of channels. * @param excluded_channels Excluded channels. * @return Channel index. */ -int32_t tr51_get_bc_channel_index(uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels); +int32_t tr51_get_bc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels); /** * @brief Compute the unicast schedule channel index using direct hash channel function. diff --git a/source/Service_Libs/fhss/channel_list.c b/source/Service_Libs/fhss/channel_list.c index 7d22696bd95..eab1e85c65d 100644 --- a/source/Service_Libs/fhss/channel_list.c +++ b/source/Service_Libs/fhss/channel_list.c @@ -88,6 +88,19 @@ uint8_t channel_list_get_channel(const uint32_t* list, int current_index) return found_index; } +void channel_list_set_channel(uint32_t* list, int channel, bool active) +{ + if (channel >= CHANNEL_LIST_SIZE_IN_BITS) { + return; + } + if (active) { + list[channel/32] |= (1 << channel % 32); + } else { + list[channel/32] &= ~(1 << channel % 32); + } + return; +} + // count the amount of channels enabled in a list int channel_list_count_channels(const uint32_t* list) { diff --git a/source/Service_Libs/fhss/channel_list.h b/source/Service_Libs/fhss/channel_list.h index 5e3a2139e0d..65a16c68089 100644 --- a/source/Service_Libs/fhss/channel_list.h +++ b/source/Service_Libs/fhss/channel_list.h @@ -31,6 +31,16 @@ extern "C" { * @return channel number */ uint8_t channel_list_get_channel(const uint32_t* list, int current_index); +/** + * set matching bit on in in channel mask. + * + * @param list channel mask + * @param channel channel number + * @param active set the channel on if true, disable channel if false. + * + * @return channel number + */ +void channel_list_set_channel(uint32_t* list, int channel, bool active); /** * Count the amount of channels enabled in a list. diff --git a/source/Service_Libs/fhss/fhss.c b/source/Service_Libs/fhss/fhss.c index 5e898153a46..bf4e763b038 100644 --- a/source/Service_Libs/fhss/fhss.c +++ b/source/Service_Libs/fhss/fhss.c @@ -34,6 +34,7 @@ #define TRACE_GROUP "fhss" +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); static int fhss_reset(fhss_structure_t *fhss_structure); static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure); static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length); @@ -67,6 +68,7 @@ fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t * } memset(fhss_struct->bs, 0, sizeof(fhss_bs_t)); + fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); fhss_struct->bs->fhss_configuration = *fhss_configuration; fhss_struct->bs->fhss_stats_ptr = fhss_statistics; fhss_struct->number_of_channels = channel_count; @@ -99,6 +101,15 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure) return true; } +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) +{ + (void) slots; + fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); + if (fhss_structure) { + fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); + } +} + static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) { if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) { @@ -689,16 +700,16 @@ static void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, } } -static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) +static int16_t fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { - return; + return -1; } // State is already set if (fhss_structure->fhss_state == fhss_state) { tr_debug("Synch same state %u", fhss_state); - return; + return -1; } if (fhss_state == FHSS_UNSYNCHRONIZED) { @@ -712,7 +723,7 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs // Do not synchronize to current pan if (fhss_structure->bs->synch_panid == pan_id) { tr_debug("Synch same panid %u", pan_id); - return; + return -1; } fhss_generate_scramble_table(fhss_structure); @@ -737,11 +748,11 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs fhss_start_timer(fhss_structure, fhss_structure->bs->synch_configuration.fhss_superframe_length, fhss_superframe_handler); } else { tr_error("Synch info not found"); - return; + return -1; } } fhss_structure->fhss_state = fhss_state; - return; + return fhss_structure->rx_channel; } static void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer) diff --git a/source/Service_Libs/fhss/fhss_common.c b/source/Service_Libs/fhss/fhss_common.c index 592a0b557da..583f87e241d 100644 --- a/source/Service_Libs/fhss/fhss_common.c +++ b/source/Service_Libs/fhss/fhss_common.c @@ -34,8 +34,6 @@ static fhss_structure_t *fhss_struct = NULL; -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); @@ -52,7 +50,6 @@ fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_ memset(fhss_struct, 0, sizeof(fhss_structure_t)); fhss_struct->fhss_api = fhss_api; fhss_struct->platform_functions = *fhss_timer; - fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); if (!fhss_struct->platform_functions.fhss_resolution_divider) { fhss_struct->platform_functions.fhss_resolution_divider = 1; } @@ -69,16 +66,7 @@ int8_t fhss_free_instance(fhss_api_t *fhss_api) return 0; } -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) -{ - (void) slots; - fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); - if (fhss_structure) { - fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); - } -} - -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) +fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) { if (timer_id < 0 || !fhss_struct) { return NULL; @@ -142,6 +130,13 @@ void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*ca } } +void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t)) +{ + if (callback){ + fhss_structure->platform_functions.fhss_timer_stop(callback, fhss_structure->fhss_api); + } +} + int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) { if (!fhss_structure) { diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h index 144e089019a..1c635d2062d 100644 --- a/source/Service_Libs/fhss/fhss_common.h +++ b/source/Service_Libs/fhss/fhss_common.h @@ -54,6 +54,7 @@ struct fhss_structure uint8_t synch_parent[8]; }; +fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_t *fhss_timer); int8_t fhss_free_instance(fhss_api_t *fhss_api); int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate); @@ -61,6 +62,7 @@ fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api); void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); int8_t fhss_disable(fhss_structure_t *fhss_structure); void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); +void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time); int fhss_timeout_stop(fhss_structure_t *fhss_structure); int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure); diff --git a/source/Service_Libs/fhss/fhss_configuration_interface.c b/source/Service_Libs/fhss/fhss_configuration_interface.c index 0c7567e5169..c1acfc38ac3 100644 --- a/source/Service_Libs/fhss/fhss_configuration_interface.c +++ b/source/Service_Libs/fhss/fhss_configuration_interface.c @@ -62,13 +62,13 @@ fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, return this; } -int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) +int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); if (!fhss_structure || !eui64 || !bc_timing_info) { return -1; } - return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info); + return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info, force_synch); } int ns_fhss_ws_remove_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8]) diff --git a/source/Service_Libs/fhss/fhss_ws.h b/source/Service_Libs/fhss/fhss_ws.h index 03befff9f8f..cf4af1040cb 100644 --- a/source/Service_Libs/fhss/fhss_ws.h +++ b/source/Service_Libs/fhss/fhss_ws.h @@ -23,6 +23,8 @@ #define WS_NUMBER_OF_CHANNEL_RETRIES 4 //TX/RX slot length in milliseconds #define WS_MAX_TXRX_SLOT_LEN_MS 100 +// Default minimum broadcast synchronization interval in seconds +#define DEFAULT_MIN_SYNCH_INTERVAL 60 typedef struct fhss_ws fhss_ws_t; struct fhss_ws @@ -30,6 +32,12 @@ struct fhss_ws uint8_t bc_channel; uint16_t uc_slot; uint16_t bc_slot; + uint16_t min_synch_interval; + uint32_t txrx_slot_length_ms; + uint32_t synchronization_time; + int16_t *tr51_channel_table; + uint8_t *tr51_output_table; + bool unicast_timer_running; bool is_on_bc_channel; struct fhss_ws_configuration fhss_configuration; const struct broadcast_timing_info *parent_bc_info; @@ -38,7 +46,7 @@ struct fhss_ws fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure); -int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); +int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch); int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]); int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration); int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count); diff --git a/source/Service_Libs/fhss/fhss_ws_empty_functions.c b/source/Service_Libs/fhss/fhss_ws_empty_functions.c index df6bc4813cf..07597662f93 100644 --- a/source/Service_Libs/fhss/fhss_ws_empty_functions.c +++ b/source/Service_Libs/fhss/fhss_ws_empty_functions.c @@ -46,7 +46,7 @@ int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure) return -1; } -int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) +int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch) { (void) fhss_structure; (void) eui64; diff --git a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c index 6b1e548212c..60352bec4fd 100644 --- a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c +++ b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c @@ -192,6 +192,9 @@ void mac_neighbor_table_neighbor_connected(mac_neighbor_table_t *table_class, ma void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device) { (void)table_class; + if (!neighbor_entry->trusted_device && trusted_device) { + neighbor_entry->lifetime = neighbor_entry->link_lifetime; + } neighbor_entry->trusted_device = trusted_device; } @@ -271,4 +274,13 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t return mac_neighbor_table_entry_allocate(table_class, mac64); } +mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class) +{ + ns_list_foreach(mac_neighbor_table_entry_t, entry, &table_class->neighbour_list) { + if (entry->link_role == PRIORITY_PARENT_NEIGHBOUR) { + return entry; + } + } + return NULL; +} diff --git a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h index edd10a974d9..c2bd7ef4f7a 100644 --- a/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h +++ b/source/Service_Libs/mac_neighbor_table/mac_neighbor_table.h @@ -202,4 +202,6 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_ll64(mac_neighbor_table_t mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t *table_class, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated); +mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class); + #endif /* MAC_NEIGHBOR_TABLE_H_ */ diff --git a/source/Service_Libs/mdns/ns_fnet_port.c b/source/Service_Libs/mdns/ns_fnet_port.c index 63e904b1911..346f6f3f8b4 100644 --- a/source/Service_Libs/mdns/ns_fnet_port.c +++ b/source/Service_Libs/mdns/ns_fnet_port.c @@ -72,10 +72,9 @@ fnet_bool_t fnet_netif_get_ip6_addr (fnet_netif_desc_t netif_desc, fnet_index_t addr_info->type = FNET_NETIF_IP_ADDR_TYPE_AUTOCONFIGURABLE; /* How the address was acquired.*/ result = FNET_TRUE; } + FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr)); } - FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr)); - return result; } diff --git a/source/ipv6_stack/ipv6_routing_table.c b/source/ipv6_stack/ipv6_routing_table.c index 0b47ed5b72c..484a41097b6 100644 --- a/source/ipv6_stack/ipv6_routing_table.c +++ b/source/ipv6_stack/ipv6_routing_table.c @@ -1589,6 +1589,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i route->metric = metric; changed_info = UPDATED; } + } if (changed_info != UNCHANGED) { diff --git a/source/ipv6_stack/protocol_ipv6.c b/source/ipv6_stack/protocol_ipv6.c index 7f01fbbe51f..59394310443 100644 --- a/source/ipv6_stack/protocol_ipv6.c +++ b/source/ipv6_stack/protocol_ipv6.c @@ -394,14 +394,14 @@ void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint return; } + if (addr_interface_gp_prefix_compare(cur, address) == 0) { + return; + } - - if (addr_interface_gp_prefix_compare(cur, address) != 0) { - ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) { - if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) { - cur_prefix->routePrefer = routePrefer; - return; - } + ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) { + if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) { + cur_prefix->routePrefer = routePrefer; + return; } } diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index 3027046fcc8..c000b581e17 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -53,6 +53,16 @@ typedef struct { } server_instance_t; typedef NS_LIST_HEAD(server_instance_t, link) server_instance_list_t; + +typedef struct { + uint16_t instance_id; + int8_t interface_id; + uint8_t server_address[16]; + bool relay_activated; + ns_list_link_t link; +} relay_instance_t; +typedef NS_LIST_HEAD(relay_instance_t, link) relay_instance_list_t; + typedef struct { ns_address_t addr; dhcp_service_receive_resp_cb *recv_resp_cb; @@ -71,6 +81,7 @@ typedef struct { uint8_t retrans; uint8_t *msg_ptr; uint16_t msg_len; + uint8_t *relay_start; ns_list_link_t link; } msg_tr_t; typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; @@ -78,9 +89,11 @@ typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; typedef struct { ns_address_t src_address; server_instance_list_t srv_list; + relay_instance_list_t relay_list; tr_list_t tr_list; int8_t dhcp_server_socket; int8_t dhcp_client_socket; + int8_t dhcp_relay_socket; int8_t dhcpv6_socket_service_tasklet; } dhcp_service_class_t; @@ -120,9 +133,11 @@ bool dhcp_service_allocate(void) dhcp_service = ns_dyn_mem_alloc(sizeof(dhcp_service_class_t)); if (dhcp_service) { ns_list_init(&dhcp_service->srv_list); + ns_list_init(&dhcp_service->relay_list); ns_list_init(&dhcp_service->tr_list); dhcp_service->dhcp_client_socket = -1; dhcp_service->dhcp_server_socket = -1; + dhcp_service->dhcp_relay_socket = -1; dhcp_service->dhcpv6_socket_service_tasklet = eventOS_event_handler_create(DHCPv6_socket_service_tasklet, DHCPV6_SOCKET_SERVICE_TASKLET_INIT); if (dhcp_service->dhcpv6_socket_service_tasklet < 0) { ns_dyn_mem_free(dhcp_service); @@ -229,13 +244,50 @@ server_instance_t *dhcp_service_client_find(uint16_t instance_id) } +static uint16_t dhcp_service_relay_interface_get(int8_t interface_id) +{ + ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) { + if (cur_ptr->interface_id == interface_id && cur_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) { + return cur_ptr->instance_id; + } + } + + return 0; +} + + + +static relay_instance_t *dhcp_service_relay_find(uint16_t instance_id) +{ + relay_instance_t *result = NULL; + ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) { + if (cur_ptr->instance_id == instance_id) { + result = cur_ptr; + } + } + return result; +} + +static relay_instance_t *dhcp_service_relay_interface(int8_t interface_id) +{ + relay_instance_t *result = NULL; + ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) { + if (cur_ptr->interface_id == interface_id) { + result = cur_ptr; + } + } + return result; +} + + void recv_dhcp_server_msg(void *cb_res) { socket_callback_t *sckt_data; server_instance_t *srv_ptr = NULL; msg_tr_t *msg_tr_ptr; - uint8_t *msg_ptr; + uint8_t *msg_ptr, *allocated_ptr; uint16_t msg_len; + dhcpv6_relay_msg_t relay_msg; sckt_data = cb_res; @@ -245,12 +297,33 @@ void recv_dhcp_server_msg(void *cb_res) tr_debug("dhcp Server recv request"); msg_tr_ptr = dhcp_tr_create(); msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len); + allocated_ptr = msg_ptr; if (msg_ptr == NULL || msg_tr_ptr == NULL) { // read actual message tr_error("Out of resources"); goto cleanup; } msg_len = socket_read(sckt_data->socket_id, &msg_tr_ptr->addr, msg_ptr, sckt_data->d_len); + + uint8_t msg_type = *msg_ptr; + if (msg_type == DHCPV6_RELAY_FORWARD) { + if ( !libdhcpv6_relay_msg_read(msg_ptr, msg_len, &relay_msg) ) { + tr_error("Relay forward not correct"); + goto cleanup; + } + //Update Source and data + msg_tr_ptr->relay_start = msg_ptr; + memcpy(msg_tr_ptr->addr.address,relay_msg.peer_address , 16); + msg_ptr = relay_msg.relay_options.msg_ptr; + msg_len = relay_msg.relay_options.len; + msg_type = *msg_ptr; + + + } else if (msg_type == DHCPV6_RELAY_REPLY) { + tr_error("Relay reply drop at server"); + goto cleanup; + } + //TODO use real function from lib also call validity check msg_tr_ptr->message_tr_id = common_read_24_bit(&msg_ptr[1]); @@ -265,7 +338,7 @@ void recv_dhcp_server_msg(void *cb_res) msg_tr_ptr->instance_id = cur_ptr->instance_id; msg_tr_ptr->interface_id = sckt_data->interface_id; if ((RET_MSG_ACCEPTED == - cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, *msg_ptr, msg_ptr + 4, msg_len - 4))) { + cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, msg_type, msg_ptr + 4, msg_len - 4))) { // should not modify pointers but library requires. msg_tr_ptr = NULL; srv_ptr = cur_ptr; @@ -276,7 +349,7 @@ void recv_dhcp_server_msg(void *cb_res) cleanup: dhcp_tr_delete(msg_tr_ptr); - ns_dyn_mem_free(msg_ptr); + ns_dyn_mem_free(allocated_ptr); if (srv_ptr == NULL) { //no owner found tr_warn("No handler for this message found"); @@ -285,6 +358,118 @@ void recv_dhcp_server_msg(void *cb_res) return; } +void recv_dhcp_relay_msg(void *cb_res) +{ + socket_callback_t *sckt_data; + uint16_t msg_len; + + sckt_data = cb_res; + + if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) { + return; + } + + protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(sckt_data->interface_id); + + relay_instance_t *relay_srv =dhcp_service_relay_interface(sckt_data->interface_id); + + if (!interface_ptr || !relay_srv || !relay_srv->relay_activated) { + return; + } + ns_address_t src_address; + + uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4]; + ns_iovec_t msg_iov[2]; + msg_iov[0].iov_base = relay_frame; + msg_iov[0].iov_len = 34; + msg_iov[1].iov_base = ns_dyn_mem_temporary_alloc(sckt_data->d_len); + msg_iov[1].iov_len = sckt_data->d_len; + if (msg_iov[1].iov_base == NULL ) { + // read actual message + tr_error("Out of resources"); + goto cleanup; + } + + ns_msghdr_t msghdr; + //Set messages name buffer + msghdr.msg_name = &src_address; + msghdr.msg_namelen = sizeof(src_address); + msghdr.msg_iov = &msg_iov[1]; + msghdr.msg_iovlen = 1; + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + + msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); + + + tr_debug("dhcp Relay recv msg"); + + //Parse type + uint8_t *ptr = msg_iov[1].iov_base; + uint8_t msg_type = *ptr; + + + if (msg_type == DHCPV6_RELAY_FORWARD) { + tr_error("Drop not supported DHCPv6 forward at Agent"); + goto cleanup; + + } else if (msg_type == DHCPV6_RELAY_REPLY) { + //Parse and validate Relay + dhcpv6_relay_msg_t relay_msg; + if (!libdhcpv6_relay_msg_read(ptr, msg_len, &relay_msg) ) { + tr_error("Not valid relay"); + goto cleanup; + } + if (0 != libdhcpv6_message_malformed_check(relay_msg.relay_options.msg_ptr, relay_msg.relay_options.len)) { + tr_error("Malformed packet"); + goto cleanup; + } + //Copy DST address + memcpy(src_address.address, relay_msg.peer_address, 16); + src_address.type = ADDRESS_IPV6; + src_address.identifier = DHCPV6_CLIENT_PORT; + msghdr.msg_iov = &msg_iov[0]; + msghdr.msg_iovlen = 1; + msg_iov[0].iov_base = relay_msg.relay_options.msg_ptr; + msg_iov[0].iov_len = relay_msg.relay_options.len; + tr_debug("Forward Original relay msg to client"); + + } else { + if (0 != libdhcpv6_message_malformed_check(ptr, msg_len)) { + tr_error("Malformed packet"); + goto cleanup; + } + uint8_t gp_address[16]; + //Get blobal address from interface + if (arm_net_address_get(sckt_data->interface_id, ADDR_IPV6_GP, gp_address) != 0) { + // No global prefix available + tr_error("No GP address"); + goto cleanup; + } + + //Build + libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address); + libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len); + + //Copy DST address + memcpy(src_address.address, relay_srv->server_address, 16); + src_address.type = ADDRESS_IPV6; + src_address.identifier = DHCPV6_SERVER_PORT; + //ADD relay frame vector front of original data + msghdr.msg_iov = &msg_iov[0]; + msghdr.msg_iovlen = 2; + msg_iov[0].iov_base = relay_frame; + msg_iov[0].iov_len = 38; + msg_iov[1].iov_len = msg_len; + tr_debug("Forward Client msg to server"); + } + socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); +cleanup: + ns_dyn_mem_free(msg_iov[1].iov_base); + + return; +} + void recv_dhcp_client_msg(void *cb_res) { ns_address_t address; @@ -351,8 +536,19 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty return 0; } if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) { + if (dhcp_service->dhcp_relay_socket >= 0) { + tr_error("dhcp Server socket can't open because Agent open already"); + } dhcp_service->dhcp_server_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_server_msg); } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT && dhcp_service->dhcp_relay_socket < 0) { + if (dhcp_service->dhcp_server_socket >= 0) { + tr_error("dhcp Relay agent can't open because server open already"); + } + dhcp_service->dhcp_relay_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_relay_msg); + } + if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) { dhcp_service->dhcp_client_socket = socket_open(SOCKET_UDP, DHCPV6_CLIENT_PORT, recv_dhcp_client_msg); } @@ -364,6 +560,18 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty tr_error("No sockets available for DHCP client"); return 0; } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT) { + if (dhcp_service->dhcp_relay_socket < 0) { + tr_error("No sockets available for DHCP server"); + } + + uint16_t temp_id = dhcp_service_relay_interface_get(interface_id); + if (temp_id) { + return temp_id; + } + } + for (; id < MAX_SERVERS; id++) { if (dhcp_service_client_find(id) == NULL) { break; @@ -375,6 +583,22 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty ns_dyn_mem_free(srv_ptr); return 0; } + + if (instance_type == DHCP_INTANCE_RELAY_AGENT) { + //Allocate Realay Agent + relay_instance_t *relay_srv = ns_dyn_mem_alloc(sizeof(relay_instance_t)); + if (!relay_srv) { + tr_error("Out of realy instances"); + ns_dyn_mem_free(srv_ptr); + return 0; + } + ns_list_add_to_start(&dhcp_service->relay_list, relay_srv); + relay_srv->instance_id = id; + relay_srv->interface_id = interface_id; + relay_srv->relay_activated = false; + + } + ns_list_add_to_start(&dhcp_service->srv_list, srv_ptr); srv_ptr->instance_id = id; srv_ptr->instance_type = instance_type; @@ -383,6 +607,15 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty return srv_ptr->instance_id; } +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address) +{ + relay_instance_t * realay_srv = dhcp_service_relay_find(instance); + if (realay_srv) { + realay_srv->relay_activated = true; + memcpy(realay_srv->server_address, server_address, 16); + } +} + void dhcp_service_delete(uint16_t instance) { server_instance_t *srv_ptr; @@ -393,7 +626,16 @@ void dhcp_service_delete(uint16_t instance) //TODO delete all transactions if (srv_ptr != NULL) { ns_list_remove(&dhcp_service->srv_list, srv_ptr); + if (srv_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) { + //Free relay service + relay_instance_t *relay = dhcp_service_relay_find(instance); + if (relay) { + ns_list_remove(&dhcp_service->relay_list, relay); + ns_dyn_mem_free(relay); + } + } ns_dyn_mem_free(srv_ptr); + } ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) { if (cur_ptr->instance_id == instance) { @@ -401,17 +643,19 @@ void dhcp_service_delete(uint16_t instance) } } - int8_t server_instances = 0, client_instances = 0; + int8_t server_instances = 0, client_instances = 0, relay_instances = 0; ns_list_foreach(server_instance_t, srv, &dhcp_service->srv_list) { if (srv->instance_type == DHCP_INSTANCE_SERVER) { ++server_instances; } else if (srv->instance_type == DHCP_INSTANCE_CLIENT) { ++client_instances; + } else if (srv->instance_type == DHCP_INTANCE_RELAY_AGENT) { + ++relay_instances; } } - if (server_instances == 0 && dhcp_service->dhcp_server_socket > -1) { + if ((server_instances == 0 && relay_instances == 0) && dhcp_service->dhcp_server_socket > -1) { socket_close(dhcp_service->dhcp_server_socket); dhcp_service->dhcp_server_socket = -1; } @@ -458,7 +702,7 @@ uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, msg_tr_ptr = dhcp_tr_create(); if (msg_tr_ptr == NULL || srv_ptr == NULL || msg_ptr == NULL || receive_resp_cb == NULL || msg_len < 5) { - tr_error("request sending failed"); + tr_error("Request sending failed"); return 0; } @@ -530,7 +774,38 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) } socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hop_limit, sizeof multicast_hop_limit); socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &msg_tr_ptr->interface_id, sizeof(int8_t)); - retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); + + if (msg_tr_ptr->relay_start) { + //Build Relay Reply only server do this + ns_iovec_t data_vector[2]; + ns_msghdr_t msghdr; + memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16); + msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT; + //SET IOV vectors + //Relay Reply + data_vector[0].iov_base = (void *) msg_tr_ptr->relay_start; + data_vector[0].iov_len = DHCPV6_RELAY_LENGTH + 4; + //DHCPV normal message vector + data_vector[1].iov_base = (void *) msg_tr_ptr->msg_ptr; + data_vector[1].iov_len = msg_tr_ptr->msg_len; + + //Set message name + msghdr.msg_name = (void *) &msg_tr_ptr->addr; + msghdr.msg_namelen = sizeof(ns_address_t); + msghdr.msg_iov = &data_vector[0]; + msghdr.msg_iovlen = 2; + //No ancillary data + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; + + uint8_t *ptr = msg_tr_ptr->relay_start; + *ptr = DHCPV6_RELAY_REPLY; + libdhcpv6_dhcp_option_header_write(ptr +34, msg_tr_ptr->msg_len); + retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0); + + } else { + retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); + } if (retval != 0) { tr_warn("dhcp service socket_sendto fails: %i", retval); } @@ -588,6 +863,12 @@ void dhcp_service_delete(uint16_t instance) (void)instance; } +void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address) +{ + (void)instance; + (void)server_address; +} + int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len) { (void)msg_tr_id; @@ -626,4 +907,5 @@ bool dhcp_service_timer_tick(uint16_t ticks) (void)ticks; return false; } + #endif diff --git a/source/libDHCPv6/libDHCPv6.c b/source/libDHCPv6/libDHCPv6.c index f89f66e5e3c..780d40afe8e 100644 --- a/source/libDHCPv6/libDHCPv6.c +++ b/source/libDHCPv6/libDHCPv6.c @@ -795,4 +795,43 @@ uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addre return length; } + +uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address) +{ + *ptr++ = type; + *ptr++ = hop_limit; + memcpy(ptr, link_address, 16); + ptr += 16; + memcpy(ptr, peer_addres, 16); + ptr += 16; + return ptr; +} + +uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length) +{ + ptr = common_write_16_bit(DHCPV6_OPTION_RELAY, ptr); + ptr = common_write_16_bit(length, ptr); + return ptr; +} + +bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg) +{ + if (length < DHCPV6_RELAY_LENGTH + 4) { + return false; + } + // Relay message base first + relay_msg->type = *ptr++; + relay_msg->hop_limit = *ptr++; + relay_msg->link_address = ptr; + relay_msg->peer_address = ptr + 16; + ptr += 32; + //Discover + if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_RELAY, &relay_msg->relay_options) != 0) { + return false; + } + + + return true; +} + #endif diff --git a/source/libDHCPv6/libDHCPv6.h b/source/libDHCPv6/libDHCPv6.h index f13a24887d5..d5a522a6cb5 100644 --- a/source/libDHCPv6/libDHCPv6.h +++ b/source/libDHCPv6/libDHCPv6.h @@ -112,6 +112,14 @@ typedef struct dhcpv6_client_server_entry_s { typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_entry_s; +typedef struct dhcpv6_relay_msg { + uint8_t type; + uint8_t hop_limit; + uint8_t *link_address; + uint8_t *peer_address; + dhcp_options_msg_t relay_options; +} dhcpv6_relay_msg_t; + /** UDP Port Number definition */ #define DHCPV6_SERVER_PORT 547 #define DHCPV6_CLIENT_PORT 546 @@ -123,6 +131,8 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent #define DHCPV6_RENEW_TYPE 5 #define DHCPV6_REPLY_TYPE 7 #define DHCPV6_RELEASE_TYPE 8 +#define DHCPV6_RELAY_FORWARD 12 +#define DHCPV6_RELAY_REPLY 13 #define DHCPV6_LEASEQUERY_TYPE 14 #define DHCPV6_LEASEQUERY_REPLY_TYPE 15 @@ -209,6 +219,11 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent #define DHCPV6_OPTION_CLT_TIME 0x002e +#define DHCPV6_RELAY_LENGTH 34 +#define DHCPV6_OPTION_RELAY 0x0009 + + + /** DHCPv6 client Nontemporal address and server data allocate, free and search */ dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address); void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry); @@ -259,7 +274,8 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t s uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink); uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData); - +uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address); +uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length); int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params); int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type , dhcp_link_options_params_t *params); @@ -347,5 +363,6 @@ int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_le int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length); bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length); bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length); +bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg); #endif /* LIBDHCPV6_H_ */ diff --git a/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index a70fd001da1..bac446af7a9 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/source/libDHCPv6/libDHCPv6_server.c @@ -43,11 +43,12 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s)); if (entry) { entry->clientIdSequence = 0; - entry->enableAddressMapping = false; entry->enableAddressAutonous = true; entry->clientIdDefaultSuffics = 0x0000000; entry->maxSuppertedClients = 200; entry->validLifetime = 7200; + entry->removeCb = NULL; + entry->addCb = NULL; ns_list_init(&entry->allocatedAddressList); } return entry; @@ -62,7 +63,7 @@ static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dh if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { memcpy(ptr, entry->linkId, 8); *ptr ^= 2; - } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { + } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) { *ptr++ = entry->linkId[0] ^ 2; *ptr++ = entry->linkId[1]; *ptr++ = entry->linkId[2]; @@ -96,7 +97,9 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds) //Stop use this address for leasequery and delete Route or address map address->preferredLifetime = 0; - cur->timeoutCb(cur->interfaceId, address->nonTemporalAddress); + if (cur->removeCb) { + cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix); + } } else { address->preferredLifetime -= timeUpdateInSeconds; } @@ -137,17 +140,16 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstanc } -dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb) +dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType) { - dhcpv6_gua_server_entry_s *entry = NULL; - if (libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix) == NULL) { + dhcpv6_gua_server_entry_s *entry = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix); + if (entry == NULL) { entry = libdhcpv6_server_entry_allocate(); if (entry) { memcpy(entry->guaPrefix, prefix, 8); memcpy(entry->serverDUID, serverDUID, 8); entry->serverLinkType = serverDUIDType; entry->interfaceId = interfaceId; - entry->timeoutCb = prefered_timeout_cb; ns_list_add_to_end(&dhcpv6_gua_server_list, entry); } } diff --git a/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index 9f47aff2437..6e9412e4789 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/source/libDHCPv6/libDHCPv6_server.h @@ -26,7 +26,7 @@ #ifdef HAVE_DHCPV6_SERVER #include "ns_list.h" -typedef void (dhcp_address_prefer_timeout_cb)(int8_t interfaceId, uint8_t *targetAddress); +typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info); typedef struct dhcpv6_alloacted_address_entry_s { uint8_t nonTemporalAddress[16]; @@ -50,10 +50,16 @@ typedef struct thread_dhcpv6_server_data_s { ns_list_link_t link; /*!< List link entry */ } dhcpv6_server_data_entry_t; +typedef struct dhcp_address_cache_update{ + uint8_t *allocatedAddress; + bool allocatedNewAddress; + uint32_t validLifeTime; +} dhcp_address_cache_update_t; + +typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src); + typedef struct dhcpv6_gua_server_entry_s { int8_t interfaceId; - bool enableAddressMapping; - uint8_t meshLocalPrefix[8]; bool enableAddressAutonous; uint16_t socketInstance_id; uint8_t guaPrefix[8]; @@ -63,13 +69,14 @@ typedef struct dhcpv6_gua_server_entry_s { uint32_t clientIdDefaultSuffics; uint32_t clientIdSequence; /*!< Define */ uint32_t validLifetime; - dhcp_address_prefer_timeout_cb *timeoutCb; + dhcp_address_prefer_remove_cb *removeCb; + dhcp_address_add_notify_cb *addCb; dhcpv6_alloacted_address_list_t allocatedAddressList; ns_list_link_t link; /*!< List link entry */ } dhcpv6_gua_server_entry_s; bool libdhcpv6_gua_server_list_empty(void); -dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb); +dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType); void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId); void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds); void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); @@ -81,7 +88,7 @@ dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_g #define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL #define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance, prefixPtr) NULL -#define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType, prefered_timeout_cb) NULL +#define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType) NULL #define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) ((void)0) #define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) ((void)0) #define libdhcpv6_gua_server_free_by_interfaceid(interfaceId) ((void)0) diff --git a/source/nsconfig.h b/source/nsconfig.h index bd7df30a632..59e3dc1a6fc 100644 --- a/source/nsconfig.h +++ b/source/nsconfig.h @@ -57,6 +57,12 @@ #endif #endif /* HAVE_THREAD */ +#if defined(HAVE_WS) +#ifndef HAVE_DHCPV6 +#define HAVE_DHCPV6 +#endif +#endif /* HAVE_WS */ + #endif // ifndef _NANOSTACK_SOURCE_CONFIG_H diff --git a/sources.mk b/sources.mk index 0217a539d46..e6461345da5 100644 --- a/sources.mk +++ b/sources.mk @@ -124,9 +124,9 @@ SRCS += \ source/6LoWPAN/Thread/thread_management_client.c \ source/6LoWPAN/Thread/thread_network_synch.c \ source/6LoWPAN/Thread/thread_bootstrap.c \ + source/6LoWPAN/Thread/thread_dhcpv6_server.c \ source/6LoWPAN/Thread/thread_host_bootstrap.c \ source/6LoWPAN/Thread/thread_router_bootstrap.c \ - source/6LoWPAN/Thread/thread_dhcpv6_client.c \ source/6LoWPAN/Thread/thread_discovery.c \ source/6LoWPAN/Thread/thread_commissioning_if.c \ source/6LoWPAN/Thread/thread_net_config_api.c \ @@ -143,6 +143,7 @@ SRCS += \ source/6LoWPAN/Thread/thread_lowpower_private_api.c \ source/6LoWPAN/Thread/thread_nvm_store.c \ source/DHCPv6_Server/DHCPv6_Server_service.c \ + source/DHCPv6_client/dhcpv6_client_service.c \ source/libDHCPv6/dhcp_service_api.c \ source/libDHCPv6/libDHCPv6.c \ source/libDHCPv6/libDHCPv6_server.c \ From 2457efc20a7967f6c9adb6c763810f7bca981881 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 9 Nov 2018 15:29:30 +0200 Subject: [PATCH 05/12] Remove sal-stack-nanostack-eventloop --- .../sal-stack-nanostack-eventloop/.cproject | 234 ---------- .../sal-stack-nanostack-eventloop/.gitignore | 6 - .../sal-stack-nanostack-eventloop/.project | 82 ---- .../org.eclipse.cdt.codan.core.prefs | 67 --- .../.settings/org.eclipse.cdt.core.prefs | 65 --- .../sal-stack-nanostack-eventloop/LICENSE | 2 - .../sal-stack-nanostack-eventloop/Makefile | 34 -- .../apache-2.0.txt | 56 --- .../mbed_lib.json | 13 - .../sal-stack-nanostack-eventloop/module.json | 25 -- .../eventOS_callback_timer.h | 32 -- .../nanostack-event-loop/eventOS_event.h | 169 -------- .../eventOS_event_timer.h | 255 ----------- .../nanostack-event-loop/eventOS_scheduler.h | 173 -------- .../platform/arm_hal_timer.h | 95 ----- .../platform/eventloop_config.h | 56 --- .../source/event.c | 401 ------------------ .../source/event.h | 34 -- .../source/minar_hal_timer.cpp | 71 ---- .../source/ns_timeout.c | 115 ----- .../source/ns_timer.c | 391 ----------------- .../source/ns_timer.h | 35 -- .../source/system_timer.c | 373 ---------------- .../source/timer_sys.h | 60 --- 24 files changed, 2844 deletions(-) delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/.cproject delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/.gitignore delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/.project delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.codan.core.prefs delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.core.prefs delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/LICENSE delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/Makefile delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/apache-2.0.txt delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/module.json delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/event.c delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/event.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/ns_timeout.c delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.c delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.h delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/system_timer.c delete mode 100644 features/nanostack/sal-stack-nanostack-eventloop/source/timer_sys.h diff --git a/features/nanostack/sal-stack-nanostack-eventloop/.cproject b/features/nanostack/sal-stack-nanostack-eventloop/.cproject deleted file mode 100644 index c41e8ee7466..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/.cproject +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/features/nanostack/sal-stack-nanostack-eventloop/.gitignore b/features/nanostack/sal-stack-nanostack-eventloop/.gitignore deleted file mode 100644 index cd8daf1ac81..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.a -output/* -build -yotta_modules -yotta_targets -*.lib diff --git a/features/nanostack/sal-stack-nanostack-eventloop/.project b/features/nanostack/sal-stack-nanostack-eventloop/.project deleted file mode 100644 index b2d4cf5ac4e..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/.project +++ /dev/null @@ -1,82 +0,0 @@ - - - eventOS - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - make - - - org.eclipse.cdt.make.core.buildLocation - ${workspace_loc:/event_loop/Debug} - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.codan.core.prefs b/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.codan.core.prefs deleted file mode 100644 index 77386c23cbe..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.codan.core.prefs +++ /dev/null @@ -1,67 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.cdt.codan.checkers.errnoreturn=Warning -org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} -org.eclipse.cdt.codan.checkers.errreturnvalue=Error -org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.checkers.noreturn=Error -org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} -org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning -org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error -org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error -org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} diff --git a/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.core.prefs b/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index 2eaccaf10b9..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,65 +0,0 @@ -eclipse.preferences.version=1 -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/delimiter=; -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/operation=append -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/value=gcc -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/delimiter=; -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/operation=append -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/value=1 -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/append=true -environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/appendContributed=true -environment/project/0.2056004298.141662914.2121498000.642060230/CPU/delimiter=; -environment/project/0.2056004298.141662914.2121498000.642060230/CPU/operation=replace -environment/project/0.2056004298.141662914.2121498000.642060230/CPU/value=Cortex-M0 -environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/delimiter=; -environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/operation=replace -environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/value=1 -environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/delimiter=; -environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/operation=append -environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/value=arm-unknown-linux-uclibcgnueabi- -environment/project/0.2056004298.141662914.2121498000.642060230/V/delimiter=; -environment/project/0.2056004298.141662914.2121498000.642060230/V/operation=append -environment/project/0.2056004298.141662914.2121498000.642060230/V/value=1 -environment/project/0.2056004298.141662914.2121498000.642060230/append=true -environment/project/0.2056004298.141662914.2121498000.642060230/appendContributed=true -environment/project/0.2056004298.141662914.2121498000/CPU/delimiter=; -environment/project/0.2056004298.141662914.2121498000/CPU/operation=append -environment/project/0.2056004298.141662914.2121498000/CPU/value=Cortex-M3 -environment/project/0.2056004298.141662914.2121498000/PLATFORM/delimiter=; -environment/project/0.2056004298.141662914.2121498000/PLATFORM/operation=append -environment/project/0.2056004298.141662914.2121498000/PLATFORM/value=arm-unknown-linux-uclibcgnueabi- -environment/project/0.2056004298.141662914.2121498000/V/delimiter=; -environment/project/0.2056004298.141662914.2121498000/V/operation=append -environment/project/0.2056004298.141662914.2121498000/V/value=1 -environment/project/0.2056004298.141662914.2121498000/append=true -environment/project/0.2056004298.141662914.2121498000/appendContributed=true -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/value=armcc -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/value=generic -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/value=Cortex-M0 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/value=1 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/operation=append -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/value=1 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/append=true -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/appendContributed=true -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/value=armcc -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/operation=append -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/value=Cortex-M3 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/operation=replace -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/value=1 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/operation=append -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/value=1 -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/append=true -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/appendContributed=true diff --git a/features/nanostack/sal-stack-nanostack-eventloop/LICENSE b/features/nanostack/sal-stack-nanostack-eventloop/LICENSE deleted file mode 100644 index 97df0e645d3..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/nanostack/sal-stack-nanostack-eventloop/Makefile b/features/nanostack/sal-stack-nanostack-eventloop/Makefile deleted file mode 100644 index ee2a9020b4c..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Define compiler toolchain with CC or PLATFORM variables -# Example (GCC toolchains) -# make PLATFORM=arm-linux-gnueabi- -# OR -# make CC=armcc AR=ArmAR -# OR -# make CC=iccarm - -LIB = libeventOS.a -SRCS += \ - source/event.c \ - source/ns_timer.c \ - source/system_timer.c\ - source/ns_timeout.c - -include ../libService/toolchain_rules.mk - -override CFLAGS += -I nanostack-event-loop - -# -# External sources from libService -# -SERVLIB_DIR := ../libService -override CFLAGS += -I$(SERVLIB_DIR)/libService - -$(eval $(call generate_rules,$(LIB),$(SRCS))) - -.PHONY: release -release: - 7z a edtls-lib_$(VERSION).zip *.a *.lib include - -.PHONY: deploy_to -deploy_to: all - tar --transform 's,^,event-loop/,' --append -f $(TO) *.a diff --git a/features/nanostack/sal-stack-nanostack-eventloop/apache-2.0.txt b/features/nanostack/sal-stack-nanostack-eventloop/apache-2.0.txt deleted file mode 100644 index 0e4cf3ee999..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/apache-2.0.txt +++ /dev/null @@ -1,56 +0,0 @@ - - -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. - -END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/features/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json b/features/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json deleted file mode 100644 index a56cdb50306..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "nanostack-eventloop", - "config": { - "use_platform_tick_timer": { - "help": "Use platform provided low resolution tick timer for eventloop", - "value": null - }, - "exclude_highres_timer": { - "help": "Exclude high resolution timer from build", - "value": null - } - } -} diff --git a/features/nanostack/sal-stack-nanostack-eventloop/module.json b/features/nanostack/sal-stack-nanostack-eventloop/module.json deleted file mode 100644 index ac6e4f00469..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/module.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "sal-stack-nanostack-eventloop", - "version": "1.1.0", - "description": "Event loop for 6LoWPAN stack", - "keywords": [], - "author": "Seppo Takalo ", - "repository": { - "url": "git@github.com:ARMmbed/sal-stack-nanostack-eventloop.git", - "type": "git" - }, - "homepage": "https://github.com/ARMmbed/sal-stack-nanostack-eventloop", - "license": "Apache-2.0", - "extraIncludes": [ - "nanostack-event-loop" - ], - "dependencies": { - "nanostack-libservice": "ARMmbed/nanostack-libservice#master" - }, - "targetDependencies": { - "mbed": { - "mbed-6lowpan-eventloop-adaptor": "^1.0.0", - "minar": "^1.0.0" - } - } -} diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h deleted file mode 100644 index 6b7d705811c..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 EVENTOS_CALLBACK_TIMER_H_ -#define EVENTOS_CALLBACK_TIMER_H_ -#ifdef __cplusplus -extern "C" { -#endif -#include "ns_types.h" - -extern int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)); -extern int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id); - -extern int8_t eventOS_callback_timer_stop(int8_t ns_timer_id); -extern int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots); -#ifdef __cplusplus -} -#endif - -#endif /* EVENTOS_CALLBACK_TIMER_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h deleted file mode 100644 index fdade478380..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 EVENTOS_EVENT_H_ -#define EVENTOS_EVENT_H_ -#ifdef __cplusplus -extern "C" { -#endif - -#include "ns_types.h" -#include "ns_list.h" - -/** - * \enum arm_library_event_priority_e - * \brief Event Priority level. - */ -typedef enum arm_library_event_priority_e { - ARM_LIB_HIGH_PRIORITY_EVENT = 0, /**< High Priority Event (Function CB) */ - ARM_LIB_MED_PRIORITY_EVENT = 1, /**< Medium Priority (Timer) */ - ARM_LIB_LOW_PRIORITY_EVENT = 2, /*!*< Normal Event and ECC / Security */ -} arm_library_event_priority_e; - -/** - * \struct arm_event_s - * \brief Event structure. - */ -typedef struct arm_event_s { - int8_t receiver; /**< Event handler Tasklet ID */ - int8_t sender; /**< Event sender Tasklet ID */ - uint8_t event_type; /**< This will be typecast arm_library_event_type_e, arm_internal_event_type_e or application specific define */ - uint8_t event_id; /**< Timer ID, NWK interface ID or application specific ID */ - void *data_ptr; /**< Application could share data pointer tasklet to tasklet */ - arm_library_event_priority_e priority; - uint32_t event_data; -} arm_event_t; - -/* Backwards compatibility */ -typedef arm_event_t arm_event_s; - -/** - * \struct arm_event_storage - * \brief Event structure storage, including list link. - -@startuml - -partition "Event loop" { -(*) -->[event created] "UNQUEUED" -"UNQUEUED" -->[event_core_write()] "QUEUED" -"QUEUED" -->[event_core_read()] "RUNNING" -"RUNNING" ->[event_core_free_push()] "UNQUEUED" -} - -partition "system_timer.c" { - "UNQUEUED:timer" -->[eventOS_event_send_timer_allocated()] "QUEUED" -} -@enduml - - */ -typedef struct arm_event_storage { - arm_event_s data; - enum { - ARM_LIB_EVENT_STARTUP_POOL, - ARM_LIB_EVENT_DYNAMIC, - ARM_LIB_EVENT_USER, - ARM_LIB_EVENT_TIMER, - } allocator; - enum { - ARM_LIB_EVENT_UNQUEUED, - ARM_LIB_EVENT_QUEUED, - ARM_LIB_EVENT_RUNNING, - } state; - ns_list_link_t link; -} arm_event_storage_t; - -/** - * \brief Send event to event scheduler. - * - * \param event pointer to pushed event. - * - * Event data is copied by the call, and this copy persists until the - * recipient's callback function returns. The callback function is passed - * a pointer to a copy of the data, not the original pointer. - * - * \return 0 Event push OK - * \return -1 Memory allocation Fail - */ -extern int8_t eventOS_event_send(const arm_event_t *event); - -/* Alternate names for timer function from eventOS_event_timer.h; - * implementations may one day merge */ -#define eventOS_event_send_at(event, at) eventOS_event_timer_request_at(event, at) -#define eventOS_event_send_in(event, in) eventOS_event_timer_request_in(event, in) -#define eventOS_event_send_after(event, after) eventOS_event_timer_request_after(event, after) -#define eventOS_event_send_every(event, every) eventOS_event_timer_request_every(event, every) - -/** - * \brief Send user-allocated event to event scheduler. - * - * \param event pointer to pushed event storage. - * - * The event structure is not copied by the call, the event system takes - * ownership and it is threaded directly into the event queue. This avoids the - * possibility of event sending failing due to memory exhaustion. - * - * event->data must be filled in on entry - the rest of the structure (link and - * allocator) need not be. - * - * The structure must remain valid until the recipient is called - the - * event system passes ownership to the receiving event handler, who may then - * invalidate it, or send it again. - * - * The recipient receives a pointer to the arm_event_t data member of the - * event - it can use NS_CONTAINER_OF() to get a pointer to the original - * event passed to this call, or to its outer container. - * - * It is a program error to send a user-allocated event to a non-existent task. - */ -extern void eventOS_event_send_user_allocated(arm_event_storage_t *event); - -/** - * \brief Event handler callback register - * - * Function will register and allocate unique event id handler - * - * \param handler_func_ptr function pointer for event handler - * \param init_event_type generated event type for init purpose - * - * \return >= 0 Unique event ID for this handler - * \return < 0 Register fail - * - * */ -extern int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_t *), uint8_t init_event_type); - -/** - * Cancel an event. - * - * Queued events are removed from the event-loop queue and/or the timer queue. - * - * Passing a NULL pointer is allowed, and does nothing. - * - * Event pointers are valid from the time they are queued until the event - * has finished running or is cancelled. - * - * Cancelling a currently-running event is only useful to stop scheduling - * it if it is on a periodic timer; it has no other effect. - * - * Cancelling an already-cancelled or already-run single-shot event - * is undefined behaviour. - * - * \param event Pointer to event handle or NULL. - */ -extern void eventOS_cancel(arm_event_storage_t *event); - -#ifdef __cplusplus -} -#endif -#endif /* EVENTOS_EVENT_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h deleted file mode 100644 index dec8efd9fbe..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 EVENTOS_EVENT_TIMER_H_ -#define EVENTOS_EVENT_TIMER_H_ -#ifdef __cplusplus -extern "C" { -#endif -#include "ns_types.h" -#include "eventOS_event.h" - -struct arm_event_s; -typedef struct sys_timer_struct_s sys_timer_struct_t; - -/* 100 Hz ticker, so 10 milliseconds per tick */ -#define EVENTOS_EVENT_TIMER_HZ 100 - -static inline uint32_t eventOS_event_timer_ticks_to_ms(uint32_t ticks) -{ - NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick") - return ticks * (1000 / EVENTOS_EVENT_TIMER_HZ); -} - -/* Convert ms to ticks, rounding up (so 9ms = 1 tick, 10ms = 1 tick, 11ms = 2 ticks) */ -static inline uint32_t eventOS_event_timer_ms_to_ticks(uint32_t ms) -{ - NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick") - return (ms + (1000 / EVENTOS_EVENT_TIMER_HZ) - 1) / (1000 / EVENTOS_EVENT_TIMER_HZ); -} - -/** - * Read current timer tick count. - * - * Can be used as a monotonic time source, and to schedule events with - * eventOS_event_timer_send. - * - * Note that the value will wrap, so take care on comparisons. - * - * \return tick count. - */ -extern uint32_t eventOS_event_timer_ticks(void); - -/* Comparison macros handling wrap efficiently (assuming a conventional compiler - * which converts 0x80000000 to 0xFFFFFFFF to negative when casting to int32_t). - */ -#define TICKS_AFTER(a, b) ((int32_t) ((a)-(b)) > 0) -#define TICKS_BEFORE(a, b) ((int32_t) ((a)-(b)) < 0) -#define TICKS_AFTER_OR_AT(a, b) ((int32_t) ((a)-(b)) >= 0) -#define TICKS_BEFORE_OR_AT(a, b) ((int32_t) ((a)-(b)) <= 0) - -/** - * Send an event after time expired (in milliseconds) - * - * Note that the current implementation has the "feature" that rounding - * varies depending on the precise timing requested: - * 0-20 ms => 2 x 10ms tick - * 21-29 ms => 3 x 10ms tick - * 30-39 ms => 4 x 10ms tick - * 40-49 ms => 5 x 10ms tick - * ... etc - * - * For improved flexibility on the event, and for more control of time, - * you should use eventOS_event_timer_request_at(). - * - * \param event_id event_id for event - * \param event_type event_type for event - * \param tasklet_id receiver for event - * \param time time to sleep in milliseconds - * - * \return 0 on success - * \return -1 on error (invalid tasklet_id or allocation failure) - * - * */ -extern int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time); - -/** - * Send an event at specified time - * - * The event will be sent when eventOS_event_timer_ticks() reaches the - * specified value. - * - * If the specified time is in the past (ie "at" is before or at the current - * tick value), the event will be sent immediately. - * - * Can also be invoked using the eventOS_event_send_at() macro in eventOS_event.h - * - * \param event event to send - * \param at absolute tick time to run event at - * - * \return pointer to timer structure on success - * \return NULL on error (invalid tasklet_id or allocation failure) - * - */ -extern arm_event_storage_t *eventOS_event_timer_request_at(const struct arm_event_s *event, uint32_t at); - -/** - * Send an event in a specified time - * - * The event will be sent in the specified number of ticks - to - * be precise, it is equivalent to requesting an event at - * - * eventOS_event_timer_ticks() + ticks - * - * Because of timer granularity, the elapsed time between issuing the request - * and it running may be up to 1 tick less than the specified time. - * - * eg requesting 2 ticks will cause the event to be sent on the second tick from - * now. If requested just after a tick, the delay will be nearly 2 ticks, but if - * requested just before a tick, the delay will be just over 1 tick. - * - * If `in` is <= 0, the event will be sent immediately. - * - * Can also be invoked using the eventOS_event_send_in() macro in eventOS_event.h - * - * \param event event to send - * \param in tick delay for event - * - * \return pointer to timer structure on success - * \return NULL on error (invalid tasklet_id or allocation failure) - * - */ -extern arm_event_storage_t *eventOS_event_timer_request_in(const struct arm_event_s *event, int32_t in); - -/** - * Send an event after a specified time - * - * The event will be sent after the specified number of ticks - to - * be precise, it is equivalent to requesting an event at - * - * eventOS_event_timer_ticks() + ticks + 1 - * - * Because of timer granularity, the elapsed time between issuing the request - * and it running may be up to 1 tick more than the specified time. - * - * eg requesting 2 ticks will cause the event to be sent on the third tick from - * now. If requested just after a tick, the delay will be nearly 3 ticks, but if - * requested just before a tick, the delay will be just over 2 ticks. - * - * If `after` is < 0, the event will be sent immediately. If it is 0, the event - * is sent on the next tick. - * - * Can also be invoked using the eventOS_event_send_after() macro in eventOS_event.h - * - * \param event event to send - * \param after tick delay for event - * - * \return pointer to timer structure on success - * \return NULL on error (invalid tasklet_id or allocation failure) - * - */ -#define eventOS_event_timer_request_after(event, after) \ - eventOS_event_timer_request_in(event, (after) + 1) - -/** - * Send an event periodically - * - * The event will be sent repeatedly using the specified ticks period. - * - * The first call is sent at - * - * eventOS_event_timer_ticks() + ticks - * - * Subsequent events will be sent at N*ticks from the initial time. - * - * Period will be maintained while the device is awake, regardless of delays to - * event scheduling. If an event has not been delivered and completed by the - * next scheduled time, the next event will be sent immediately when it - * finishes. This could cause a continuous stream of events if unable to keep - * up with the period. - * - * Can also be invoked using the eventOS_event_send_every() macro in eventOS_event.h - * - * \param event event to send - * \param period period for event - * - * \return pointer to timer structure on success - * \return NULL on error (invalid tasklet_id or allocation failure) - * - */ -extern arm_event_storage_t *eventOS_event_timer_request_every(const struct arm_event_s *event, int32_t period); - -/** - * Cancel an event timer - * - * This cancels a pending timed event, matched by event_id and tasklet_id. - * - * \param event_id event_id for event - * \param tasklet_id receiver for event - * - * \return 0 on success - * \return -1 on error (event not found) - * - * */ -extern int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id); - -/** - * System Timer shortest time in milli seconds - * - * \param ticks Time in 10 ms resolution - * - * \return none - * - * */ -extern uint32_t eventOS_event_timer_shortest_active_timer(void); - - -/** Timeout structure. Not to be modified by user */ -typedef struct timeout_entry_t timeout_t; - -/** Request timeout callback. - * - * Create timeout request for specific callback. - * - * \param ms timeout in milliseconds. Maximum range is same as for eventOS_event_timer_request(). - * \param callback function to call after timeout - * \param arg arquement to pass to callback - * \return pointer to timeout structure or NULL on errors - */ -timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg); - -/** Request periodic callback. - * - * Create timeout request for specific callback. Called periodically until eventOS_timeout_cancel() is called. - * - * \param every period in milliseconds. Maximum range is same as for eventOS_event_timer_request(). - * \param callback function to call after timeout - * \param arg arquement to pass to callback - * \return pointer to timeout structure or NULL on errors - */ -timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg); - -/** Cancell timeout request. - * - * \param t timeout request id. - */ -void eventOS_timeout_cancel(timeout_t *t); - - -#ifdef __cplusplus -} -#endif - -#endif /* EVENTOS_EVENT_TIMER_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h deleted file mode 100644 index 15d4f56008d..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 EVENTOS_SCHEDULER_H_ -#define EVENTOS_SCHEDULER_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#include "ns_types.h" - -/* Compatibility with older ns_types.h */ -#ifndef NS_NORETURN -#define NS_NORETURN -#endif - -/** - * \brief Initialise event scheduler. - * - */ -extern void eventOS_scheduler_init(void); - -/** - * Process one event from event queue. - * Do not call this directly from application. Requires to be public so that simulator can call this. - * Use eventOS_scheduler_run() or eventOS_scheduler_run_until_idle(). - * \return true If there was event processed, false if the event queue was empty. - */ -bool eventOS_scheduler_dispatch_event(void); - -/** - * \brief Process events until no more events to process. - */ -extern void eventOS_scheduler_run_until_idle(void); - -/** - * \brief Start Event scheduler. - * Loops forever processing events from the queue. - * Calls eventOS_scheduler_idle() whenever event queue is empty. - */ -NS_NORETURN extern void eventOS_scheduler_run(void); -/** - * \brief Disable Event scheduler Timers - * - * \return 0 Timer Stop OK - * \return -1 Timer Stop Fail - * - * */ -int eventOS_scheduler_timer_stop(void); - -/** - * \brief Synch Event scheduler timer after sleep - * - * \param sleep_ticks time in milli seconds - * - * \return 0 Timer Synch OK - * \return -1 Timer Synch & Start Fail - * - * */ -int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks); - -/** - * \brief Read current active Tasklet ID - * - * This function not return valid information called inside interrupt - * - * \return curret active tasklet id - * - * */ -extern int8_t eventOS_scheduler_get_active_tasklet(void); - -/** - * \brief Set manually Active Tasklet ID - * - * \param tasklet requested tasklet ID - * - * */ -extern void eventOS_scheduler_set_active_tasklet(int8_t tasklet); - -/** - * \brief Event scheduler loop idle Callback. - - * Note! This method is called only by eventOS_scheduler_run, needs to be - * ported for the platform only if you are using eventOS_scheduler_run(). - */ -extern void eventOS_scheduler_idle(void); - -/** - * \brief This function will be called when stack enter idle state and start - * waiting signal. - * - * Note! This method is called only by reference implementation of idle. Needs - * to be ported for the platform only if you are using reference implementation. - */ -extern void eventOS_scheduler_wait(void); - -/** - * \brief This function will be called when stack receives an event. - */ -extern void eventOS_scheduler_signal(void); - -/** - * \brief This function will be called when stack can enter deep sleep state in detected time. - * - * Note! This method is called only by reference implementation of idle. Needs to be - * ported for the platform only if you are using reference implementation. - * - * \param sleep_time_ms Time in milliseconds to sleep - * \return time slept in milliseconds - */ -extern uint32_t eventOS_scheduler_sleep(uint32_t sleep_time_ms); - -/** - * \brief Lock a thread against the event loop thread - * - * This method can be provided by multi-threaded platforms to allow - * mutual exclusion with the event loop thread, for cases where - * code wants to work with both the event loop and other threads. - * - * A typical platform implementation would claim the same mutex - * before calling eventOS_scheduler_run() or - * eventOS_scheduler_dispatch(), and release it during - * eventOS_scheduler_idle(). - * - * The mutex must count - nested calls from one thread return - * immediately. Thus calling this from inside an event callback - * is harmless. - */ -extern void eventOS_scheduler_mutex_wait(void); - -/** - * \brief Release the event loop mutex - * - * Release the mutex claimed with eventOS_scheduler_mutex_wait(), - * allowing the event loop to continue processing. - */ -extern void eventOS_scheduler_mutex_release(void); - -/** - * \brief Check if the current thread owns the event mutex - * - * Check if the calling thread owns the scheduler mutex. - * This allows the ownership to be asserted if a function - * requires the mutex to be locked externally. - * - * The function is only intended as a debugging aid for - * users of eventOS_scheduler_mutex_wait() - it is not - * used by the event loop core itself. - * - * If the underlying mutex system does not support it, - * this may be implemented to always return true. - * - * \return true if the current thread owns the mutex - */ -extern bool eventOS_scheduler_mutex_am_owner(void); - -#ifdef __cplusplus -} -#endif - -#endif /* EVENTOS_SCHEDULER_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h deleted file mode 100644 index 0a661abfa0c..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 ARM_HAL_TIMER_H_ -#define ARM_HAL_TIMER_H_ - -#include "eventloop_config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NS_EXCLUDE_HIGHRES_TIMER -/** - * \brief This function perform timer init. - */ -extern void platform_timer_enable(void); - -/** - * \brief This function is API for set Timer interrupt handler for stack - * - * \param new_fp Function pointer for stack giving timer handler - * - */ -typedef void (*platform_timer_cb)(void); -extern void platform_timer_set_cb(platform_timer_cb new_fp); - -/** - * \brief This function is API for stack timer start - * - * \param slots define how many 50us slot time period will be started - * - */ -extern void platform_timer_start(uint16_t slots); - -/** - * \brief This function is API for stack timer stop - * - */ -extern void platform_timer_disable(void); - -/** - * \brief This function is API for stack timer to read active timer remaining slot count - * - * \return 50us time slot remaining - */ -extern uint16_t platform_timer_get_remaining_slots(void); - -#endif // NS_EXCLUDE_HIGHRES_TIMER - -#ifdef NS_EVENTLOOP_USE_TICK_TIMER -/** - * \brief This function is API for registering low resolution tick timer callback. Also does - * any necessary initialization of the tick timer. - * - * \return -1 for failure, success otherwise - */ -extern int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void)); - -/** - * \brief This function is API for starting the low resolution tick timer. The callback - * set with platform_tick_timer_register gets called periodically until stopped - * by calling platform_tick_timer_stop. - * - * \param period_ms define how many milliseconds time period will be started - * \return -1 for failure, success otherwise - */ -extern int8_t platform_tick_timer_start(uint32_t period_ms); - -/** - * \brief This function is API for stopping the low resolution tick timer - * - * \return -1 for failure, success otherwise - */ -extern int8_t platform_tick_timer_stop(void); - -#endif // NS_EVENTLOOP_USE_TICK_TIMER - -#ifdef __cplusplus -} -#endif - -#endif /* ARM_HAL_TIMER_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h b/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h deleted file mode 100644 index 904eb242428..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 EVENTLOOP_CONFIG_H_ -#define EVENTLOOP_CONFIG_H_ - -/* - * Options can be picked up from mbed-cli JSON configuration, or from - * Yotta JSON configuration, or from a user configuration file - see below. - * - * Undefine all internal flags before evaluating the configuration. - */ - -/* Use platform-provided low-resolution tick timer for eventloop (requires "platform_tick_timer" API) */ -#undef NS_EVENTLOOP_USE_TICK_TIMER -/* Exclude high resolution timer from build (removes need for "platform_timer" API) */ -#undef NS_EXCLUDE_HIGHRES_TIMER - -/* - * mbedOS 5 specific configuration flag mapping to internal flags - */ -#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_USE_PLATFORM_TICK_TIMER -#define NS_EVENTLOOP_USE_TICK_TIMER 1 -#endif - -#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER -#define NS_EXCLUDE_HIGHRES_TIMER 1 -#endif - -/* - * For mbedOS 3 and minar use platform tick timer by default, highres timers should come from eventloop adaptor - */ -#ifdef YOTTA_CFG_MINAR -#define NS_EVENTLOOP_USE_TICK_TIMER 1 -#endif - -/* - * Include the user config file if defined - */ -#ifdef NS_EVENTLOOP_USER_CONFIG_FILE -#include NS_EVENTLOOP_USER_CONFIG_FILE -#endif - -#endif /* EVENTLOOP_CONFIG_H_ */ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/event.c b/features/nanostack/sal-stack-nanostack-eventloop/source/event.c deleted file mode 100644 index 77dec693c96..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/event.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 -#include "ns_types.h" -#include "ns_list.h" -#include "eventOS_event.h" -#include "eventOS_scheduler.h" -#include "timer_sys.h" -#include "nsdynmemLIB.h" -#include "ns_timer.h" -#include "event.h" -#include "platform/arm_hal_interrupt.h" - - -typedef struct arm_core_tasklet { - int8_t id; /**< Event handler Tasklet ID */ - void (*func_ptr)(arm_event_s *); - ns_list_link_t link; -} arm_core_tasklet_t; - -static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_t, link); -static NS_LIST_DEFINE(event_queue_active, arm_event_storage_t, link); -static NS_LIST_DEFINE(free_event_entry, arm_event_storage_t, link); - -// Statically allocate initial pool of events. -#define STARTUP_EVENT_POOL_SIZE 10 -static arm_event_storage_t startup_event_pool[STARTUP_EVENT_POOL_SIZE]; - -/** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */ -int8_t curr_tasklet = 0; - - -static arm_core_tasklet_t *tasklet_dynamically_allocate(void); -static arm_event_storage_t *event_dynamically_allocate(void); -static arm_event_storage_t *event_core_get(void); -static void event_core_write(arm_event_storage_t *event); - -static arm_core_tasklet_t *event_tasklet_handler_get(uint8_t tasklet_id) -{ - ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) { - if (cur->id == tasklet_id) { - return cur; - } - } - return NULL; -} - -bool event_tasklet_handler_id_valid(uint8_t tasklet_id) -{ - return event_tasklet_handler_get(tasklet_id); -} - -// XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least -// curr_tasklet is reset to 0 in various places. -static int8_t tasklet_get_free_id(void) -{ - /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ - for (uint8_t i = 0; i <= INT8_MAX; i++) { - if (!event_tasklet_handler_get(i)) { - return i; - } - } - return -1; -} - - -int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type) -{ - arm_event_storage_t *event_tmp; - - // XXX Do we really want to prevent multiple tasklets with same function? - ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) { - if (cur->func_ptr == handler_func_ptr) { - return -1; - } - } - - //Allocate new - arm_core_tasklet_t *new = tasklet_dynamically_allocate(); - if (!new) { - return -2; - } - - event_tmp = event_core_get(); - if (!event_tmp) { - ns_dyn_mem_free(new); - return -2; - } - - //Fill in tasklet; add to list - new->id = tasklet_get_free_id(); - new->func_ptr = handler_func_ptr; - ns_list_add_to_end(&arm_core_tasklet_list, new); - - //Queue "init" event for the new task - event_tmp->data.receiver = new->id; - event_tmp->data.sender = 0; - event_tmp->data.event_type = init_event_type; - event_tmp->data.event_data = 0; - event_core_write(event_tmp); - - return new->id; -} - -int8_t eventOS_event_send(const arm_event_t *event) -{ - if (event_tasklet_handler_get(event->receiver)) { - arm_event_storage_t *event_tmp = event_core_get(); - if (event_tmp) { - event_tmp->data = *event; - event_core_write(event_tmp); - return 0; - } - } - return -1; -} - -void eventOS_event_send_user_allocated(arm_event_storage_t *event) -{ - event->allocator = ARM_LIB_EVENT_USER; - event_core_write(event); -} - -void eventOS_event_send_timer_allocated(arm_event_storage_t *event) -{ - event->allocator = ARM_LIB_EVENT_TIMER; - event_core_write(event); -} - -void eventOS_event_cancel_critical(arm_event_storage_t *event) -{ - ns_list_remove(&event_queue_active, event); -} - -static arm_event_storage_t *event_dynamically_allocate(void) -{ - arm_event_storage_t *event = ns_dyn_mem_temporary_alloc(sizeof(arm_event_storage_t)); - if (event) { - event->allocator = ARM_LIB_EVENT_DYNAMIC; - } - return event; -} - -static arm_core_tasklet_t *tasklet_dynamically_allocate(void) -{ - return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_t)); -} - -arm_event_storage_t *event_core_get(void) -{ - arm_event_storage_t *event; - platform_enter_critical(); - event = ns_list_get_first(&free_event_entry); - if (event) { - ns_list_remove(&free_event_entry, event); - } else { - event = event_dynamically_allocate(); - } - if (event) { - event->data.data_ptr = NULL; - event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT; - } - platform_exit_critical(); - return event; -} - -void event_core_free_push(arm_event_storage_t *free) -{ - free->state = ARM_LIB_EVENT_UNQUEUED; - - switch (free->allocator) { - case ARM_LIB_EVENT_STARTUP_POOL: - platform_enter_critical(); - ns_list_add_to_start(&free_event_entry, free); - platform_exit_critical(); - break; - case ARM_LIB_EVENT_DYNAMIC: - // Free all dynamically allocated events. - ns_dyn_mem_free(free); - break; - case ARM_LIB_EVENT_TIMER: - // Hand it back to the timer system - timer_sys_event_free(free); - break; - case ARM_LIB_EVENT_USER: - default: - break; - } -} - - -static arm_event_storage_t *event_core_read(void) -{ - platform_enter_critical(); - arm_event_storage_t *event = ns_list_get_first(&event_queue_active); - if (event) { - event->state = ARM_LIB_EVENT_RUNNING; - ns_list_remove(&event_queue_active, event); - } - platform_exit_critical(); - return event; -} - -void event_core_write(arm_event_storage_t *event) -{ - platform_enter_critical(); - bool added = false; - ns_list_foreach(arm_event_storage_t, event_tmp, &event_queue_active) { - // note enum ordering means we're checking if event_tmp is LOWER priority than event - if (event_tmp->data.priority > event->data.priority) { - ns_list_add_before(&event_queue_active, event_tmp, event); - added = true; - break; - } - } - if (!added) { - ns_list_add_to_end(&event_queue_active, event); - } - event->state = ARM_LIB_EVENT_QUEUED; - - /* Wake From Idle */ - platform_exit_critical(); - eventOS_scheduler_signal(); -} - -// Requires lock to be held -arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id) -{ - ns_list_foreach(arm_event_storage_t, cur, &event_queue_active) { - if (cur->data.receiver == tasklet_id && cur->data.event_id == event_id) { - return cur; - } - } - - return NULL; -} - -/** - * - * \brief Initialize Nanostack Core. - * - * Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined. - * - */ -void eventOS_scheduler_init(void) -{ - /* Reset Event List variables */ - ns_list_init(&free_event_entry); - ns_list_init(&event_queue_active); - ns_list_init(&arm_core_tasklet_list); - - //Add first 10 entries to "free" list - for (unsigned i = 0; i < (sizeof(startup_event_pool) / sizeof(startup_event_pool[0])); i++) { - startup_event_pool[i].allocator = ARM_LIB_EVENT_STARTUP_POOL; - ns_list_add_to_start(&free_event_entry, &startup_event_pool[i]); - } - - /* Init Generic timer module */ - timer_sys_init(); //initialize timer - /* Set Tasklett switcher to Idle */ - curr_tasklet = 0; - -} - -int8_t eventOS_scheduler_get_active_tasklet(void) -{ - return curr_tasklet; -} - -void eventOS_scheduler_set_active_tasklet(int8_t tasklet) -{ - curr_tasklet = tasklet; -} - -int eventOS_scheduler_timer_stop(void) -{ - timer_sys_disable(); - if (ns_timer_sleep() != 0) { - return 1; - } - return 0; -} - -int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks) -{ - //Update MS to 10ms ticks - sleep_ticks /= 10; - sleep_ticks++; - system_timer_tick_update(sleep_ticks); - if (timer_sys_wakeup() == 0) { - return 0; - } - return -1; -} - -/** - * - * \brief Infinite Event Read Loop. - * - * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep - * - */ -bool eventOS_scheduler_dispatch_event(void) -{ - curr_tasklet = 0; - - arm_event_storage_t *cur_event = event_core_read(); - if (!cur_event) { - return false; - } - - curr_tasklet = cur_event->data.receiver; - - arm_core_tasklet_t *tasklet = event_tasklet_handler_get(curr_tasklet); - /* Do not bother with check for NULL - tasklets cannot be deleted, - * and user-facing API eventOS_event_send() has already checked the tasklet - * exists, so there is no possible issue there. - * - * For eventOS_event_send_user_allocated(), it would be a non-recoverable - * error to not deliver the message - we have to have a receiver to pass - * ownership to. If the lookup fails, let it crash. We want the send call - * itself to return void to simplify logic. - */ - - /* Tasklet Scheduler Call */ - tasklet->func_ptr(&cur_event->data); - event_core_free_push(cur_event); - - /* Set Current Tasklet to Idle state */ - curr_tasklet = 0; - - return true; -} - -void eventOS_scheduler_run_until_idle(void) -{ - while (eventOS_scheduler_dispatch_event()); -} - -/** - * - * \brief Infinite Event Read Loop. - * - * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep - * - */ -NS_NORETURN void eventOS_scheduler_run(void) -{ - while (1) { - if (!eventOS_scheduler_dispatch_event()) { - eventOS_scheduler_idle(); - } - } -} - -void eventOS_cancel(arm_event_storage_t *event) -{ - if (!event) { - return; - } - - platform_enter_critical(); - - /* - * Notify timer of cancellation. - */ - if (event->allocator == ARM_LIB_EVENT_TIMER) { - timer_sys_event_cancel_critical(event); - } - - /* - * Remove event from the list, - * Only queued can be removed, unqued are either timers or stale pointers - * RUNNING cannot be removed, we are currenly "in" that event. - */ - if (event->state == ARM_LIB_EVENT_QUEUED) { - eventOS_event_cancel_critical(event); - } - - /* - * Push back to "free" state - */ - if (event->state != ARM_LIB_EVENT_RUNNING) { - event_core_free_push(event); - } - - platform_exit_critical(); -} diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/event.h b/features/nanostack/sal-stack-nanostack-eventloop/source/event.h deleted file mode 100644 index 9efb685857e..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/event.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017 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 NS_EVENT_H_ -#define NS_EVENT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -bool event_tasklet_handler_id_valid(uint8_t tasklet_id); -void eventOS_event_send_timer_allocated(arm_event_storage_t *event); - -// This requires lock to be held -arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id); - -#ifdef __cplusplus -} -#endif - -#endif /*NS_EVENT_H_*/ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp b/features/nanostack/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp deleted file mode 100644 index 3d8a0a9ee8f..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016 ARM Limited, All Rights Reserved - */ - -// Include before mbed.h to properly get UINT*_C() - -#include "ns_types.h" - -#include "platform/arm_hal_timer.h" -#include "platform/arm_hal_interrupt.h" - -#if defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG_MINAR) - -#include "minar/minar.h" -#include "mbed-drivers/mbed.h" -#include "core-util/FunctionPointer.h" -#include "core-util/Event.h" - -#define TICK_TIMER_ID 1 - -using minar::Scheduler; -using minar::milliseconds; -using minar::callback_handle_t; -using namespace mbed::util; - -static callback_handle_t sys_timer_handle; -static void (*tick_timer_callback)(void); - -void timer_callback(void const *funcArgument) -{ - (void)funcArgument; - if (NULL != tick_timer_callback) { - tick_timer_callback(); - } -} - -// Low precision platform tick timer -int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void)) -{ - tick_timer_callback = tick_timer_cb_handler; - return TICK_TIMER_ID; -} - -int8_t platform_tick_timer_start(uint32_t period_ms) -{ - int8_t retval = -1; - if (sys_timer_handle != NULL) { - return 0; // Timer already started already so return success - } - Event e = FunctionPointer1(timer_callback).bind(NULL); - if (e != NULL) { - sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(period_ms)).getHandle(); - if (sys_timer_handle != NULL) { - retval = 0; - } - } - return retval; -} - -int8_t platform_tick_timer_stop(void) -{ - int8_t retval = -1; - if (sys_timer_handle != NULL) { - Scheduler::cancelCallback(sys_timer_handle); - sys_timer_handle = NULL; - retval = 0; - } - return retval; -} - -#endif // defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG) diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timeout.c b/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timeout.c deleted file mode 100644 index 62f131bd9db..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timeout.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 "eventOS_event.h" -#include "eventOS_event_timer.h" -#include "nsdynmemLIB.h" -#include "ns_list.h" -#include "timer_sys.h" - -#define STARTUP_EVENT 0 -#define TIMER_EVENT 1 - -// Timeout structure, already typedefed to timeout_t -struct timeout_entry_t { - void (*callback)(void *); - void *arg; - arm_event_storage_t *event; -}; - -static int8_t timeout_tasklet_id = -1; - -static void timeout_tasklet(arm_event_s *event) -{ - if (TIMER_EVENT != event->event_type) { - return; - } - - timeout_t *t = event->data_ptr; - arm_event_storage_t *storage = t->event; - sys_timer_struct_s *timer = NS_CONTAINER_OF(storage, sys_timer_struct_s, event); - - t->callback(t->arg); - - - // Check if this was periodic timer - if (timer->period == 0) { - ns_dyn_mem_free(event->data_ptr); - } -} - -static timeout_t *eventOS_timeout_at_(void (*callback)(void *), void *arg, uint32_t at, uint32_t period) -{ - arm_event_storage_t *storage; - - timeout_t *timeout = ns_dyn_mem_alloc(sizeof(timeout_t)); - if (!timeout) { - return NULL; - } - timeout->callback = callback; - timeout->arg = arg; - - // Start timeout taskled if it is not running - if (-1 == timeout_tasklet_id) { - timeout_tasklet_id = eventOS_event_handler_create(timeout_tasklet, STARTUP_EVENT); - if (timeout_tasklet_id < 0) { - timeout_tasklet_id = -1; - goto FAIL; - } - } - - arm_event_t event = { - .receiver = timeout_tasklet_id, - .sender = timeout_tasklet_id, - .event_type = TIMER_EVENT, - .event_id = TIMER_EVENT, - .data_ptr = timeout - }; - - if (period) - storage = eventOS_event_timer_request_every(&event, period); - else - storage = eventOS_event_timer_request_at(&event, at); - - timeout->event = storage; - if (storage) - return timeout; -FAIL: - ns_dyn_mem_free(timeout); - return NULL; -} - -timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg) -{ - return eventOS_timeout_at_(callback, arg, eventOS_event_timer_ms_to_ticks(ms)+eventOS_event_timer_ticks(), 0); -} - -timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg) -{ - return eventOS_timeout_at_(callback, arg, 0, eventOS_event_timer_ms_to_ticks(every)); -} - -void eventOS_timeout_cancel(timeout_t *t) -{ - if (!t) - return; - - eventOS_cancel(t->event); - - // Defer the freeing until returning from the callback - if (t->event->state != ARM_LIB_EVENT_RUNNING) { - ns_dyn_mem_free(t); - } -} diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.c b/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.c deleted file mode 100644 index f3affbdd248..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 "ns_types.h" -#include "ns_list.h" -#include "ns_timer.h" -#include "eventOS_callback_timer.h" -#include "platform/arm_hal_interrupt.h" -#include "platform/arm_hal_timer.h" -#include "nsdynmemLIB.h" - -#ifndef NS_EXCLUDE_HIGHRES_TIMER -typedef enum ns_timer_state_e { - NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt - NS_TIMER_HOLD, // Will run on a later HAL interrupt - NS_TIMER_RUN_INTERRUPT, // Running on the interrupt we're currently handling - NS_TIMER_STOP // Timer not scheduled ("start" not called since last callback) -} ns_timer_state_e; - -typedef struct ns_timer_struct { - int8_t ns_timer_id; - ns_timer_state_e timer_state; - uint16_t slots; - uint16_t remaining_slots; - void (*interrupt_handler)(int8_t, uint16_t); - ns_list_link_t link; -} ns_timer_struct; - -static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link); - -#define NS_TIMER_RUNNING 1 -static uint8_t ns_timer_state = 0; - -#ifdef ATMEGA256RFR2 -#define COMPENSATION 3 -#define COMPENSATION_TUNE 1 -#else -#define COMPENSATION 0 -#define COMPENSATION_TUNE 0 -#endif - -static void ns_timer_interrupt_handler(void); -static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id); -static bool ns_timer_initialized = 0; - -int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)) -{ - int8_t retval = -1; - - if (!ns_timer_initialized) { - /*Set interrupt handler in HAL driver*/ - platform_timer_set_cb(ns_timer_interrupt_handler); - ns_timer_initialized = 1; - } - - /*Find first free timer ID in timer list*/ - /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ - for (uint8_t i = 0; i <= INT8_MAX; i++) { - if (!ns_timer_get_pointer_to_timer_struct(i)) { - retval = i; - break; - } - } - - if (retval == -1) { - return -1; - } - - ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct)); - if (!new_timer) { - return -1; - } - - /*Initialise new timer*/ - new_timer->ns_timer_id = retval; - new_timer->timer_state = NS_TIMER_STOP; - new_timer->remaining_slots = 0; - new_timer->interrupt_handler = timer_interrupt_handler; - - // Critical section sufficient as long as list can't be reordered from - // interrupt, otherwise will need to cover whole routine - platform_enter_critical(); - ns_list_add_to_end(&ns_timer_list, new_timer); - platform_exit_critical(); - - /*Return timer ID*/ - return retval; -} - -int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id) -{ - ns_timer_struct *current_timer; - - current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); - if (!current_timer) { - return -1; - } - - // Critical section sufficient as long as list can't be reordered from - // interrupt, otherwise will need to cover whole routine - platform_enter_critical(); - ns_list_remove(&ns_timer_list, current_timer); - platform_exit_critical(); - - ns_dyn_mem_free(current_timer); - return 0; -} - - -static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots) -{ - /*Don't start timer with 0 slots*/ - if (!pl_timer_start_slots) { - pl_timer_start_slots = 1; - } - - /*Start HAL timer*/ - platform_timer_start(pl_timer_start_slots); - /*Set HAL timer state to running*/ - ns_timer_state |= NS_TIMER_RUNNING; - return 0; -} - -int8_t ns_timer_sleep(void) -{ - int8_t ret_val = -1; - if (ns_timer_state & NS_TIMER_RUNNING) { - /*Start HAL timer*/ - platform_timer_disable(); - /*Set HAL timer state to running*/ - ns_timer_state &= ~NS_TIMER_RUNNING; - ret_val = 0; - } - return ret_val; -} - -static int8_t ns_timer_get_next_running_to(void) -{ - uint8_t hold_count = 0; - ns_timer_struct *first_timer = NULL; - - /*Find hold-labelled timer with the least remaining slots*/ - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - if (current_timer->timer_state == NS_TIMER_HOLD) { - if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) { - first_timer = current_timer; - } - /*For optimisation, count the found timers*/ - hold_count++; - } - } - - if (!first_timer) { - return 0; - } - - /*If hold-labelled timer found, set it active and start the HAL driver*/ - hold_count--; - first_timer->timer_state = NS_TIMER_ACTIVE; - /*Compensate time spent in timer function*/ - if (first_timer->remaining_slots > COMPENSATION) { - first_timer->remaining_slots -= COMPENSATION; - } - /*Start HAL timer*/ - ns_timer_start_pl_timer(first_timer->remaining_slots); - - /*Update other hold-labelled timers*/ - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - if (hold_count == 0) { // early termination optimisation - break; - } - if (current_timer->timer_state == NS_TIMER_HOLD) { - if (current_timer->remaining_slots == first_timer->remaining_slots) { - current_timer->timer_state = NS_TIMER_ACTIVE; - } else { - current_timer->remaining_slots -= first_timer->remaining_slots; - /*Compensate time spent in timer function*/ - if (current_timer->remaining_slots > COMPENSATION) { - current_timer->remaining_slots -= COMPENSATION; - } - } - hold_count--; - } - } - - return 0; -} - - -static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id) -{ - /*Find timer with the given ID*/ - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - if (current_timer->ns_timer_id == timer_id) { - return current_timer; - } - } - return NULL; -} - -int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots) -{ - int8_t ret_val = 0; - uint16_t pl_timer_remaining_slots; - ns_timer_struct *timer; - platform_enter_critical(); - - /*Find timer to be activated*/ - timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); - if (!timer) { - ret_val = -1; - goto exit; - } - - // XXX this assumes the timer currently isn't running? - // Is event.c relying on this restarting HAL timer after ns_timer_sleep()? - - /*If any timers are active*/ - if (ns_timer_state & NS_TIMER_RUNNING) { - /*Get remaining slots of the currently activated timeout*/ - pl_timer_remaining_slots = platform_timer_get_remaining_slots(); - - /*New timeout is shorter than currently enabled timeout*/ - if (pl_timer_remaining_slots > slots) { - /*Start HAL timer*/ - ns_timer_start_pl_timer(slots - 0); - - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - /*Switch active timers to hold*/ - if (current_timer->timer_state == NS_TIMER_ACTIVE) { - current_timer->timer_state = NS_TIMER_HOLD; - current_timer->remaining_slots = 0; - } - /*Update hold-labelled timers*/ - if (current_timer->timer_state == NS_TIMER_HOLD) { - current_timer->remaining_slots += (pl_timer_remaining_slots - slots); - /*Compensate time spent in timer function*/ - if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) { - current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE); - } - } - } - /*Mark active and start the timer*/ - timer->timer_state = NS_TIMER_ACTIVE; - timer->slots = slots; - timer->remaining_slots = slots; - } - - /*New timeout is longer than currently enabled timeout*/ - else if (pl_timer_remaining_slots < slots) { - /*Mark hold and update remaining slots*/ - timer->timer_state = NS_TIMER_HOLD; - timer->slots = slots; - timer->remaining_slots = (slots - pl_timer_remaining_slots); - } - /*New timeout is equal to currently enabled timeout*/ - else { - /*Mark it active and it will be handled in next interrupt*/ - timer->timer_state = NS_TIMER_ACTIVE; - timer->slots = slots; - timer->remaining_slots = slots; - } - } else { - /*No timers running*/ - timer->timer_state = NS_TIMER_HOLD; - timer->slots = slots; - timer->remaining_slots = slots; - /*Start next timeout*/ - ns_timer_get_next_running_to(); - } -exit: - platform_exit_critical(); - return ret_val; -} - -static void ns_timer_interrupt_handler(void) -{ - uint8_t i = 0; - - platform_enter_critical(); - /*Clear timer running state*/ - ns_timer_state &= ~NS_TIMER_RUNNING; - /*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/ - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - if (current_timer->timer_state == NS_TIMER_ACTIVE) { - current_timer->timer_state = NS_TIMER_RUN_INTERRUPT; - /*For optimisation, count the found timers*/ - i++; - } - } - - /*Start next timeout*/ - ns_timer_get_next_running_to(); - - /*Call interrupt functions*/ - ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { - if (i == 0) { - break; - } - if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) { - current_timer->timer_state = NS_TIMER_STOP; - current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots); - i--; - } - } - - platform_exit_critical(); -} - -int8_t eventOS_callback_timer_stop(int8_t ns_timer_id) -{ - uint16_t pl_timer_remaining_slots; - bool active_timer_found = false; - ns_timer_struct *current_timer; - ns_timer_struct *first_timer = NULL; - int8_t retval = -1; - - platform_enter_critical(); - /*Find timer with given timer ID*/ - current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); - if (!current_timer) { - goto exit; - } - - retval = 0; - - /*Check if already stopped*/ - if (current_timer->timer_state == NS_TIMER_STOP) { - goto exit; - } - - current_timer->timer_state = NS_TIMER_STOP; - current_timer->remaining_slots = 0; - - /*Check if some timer is already active*/ - ns_list_foreach(ns_timer_struct, curr_timer, &ns_timer_list) { - if (curr_timer->timer_state == NS_TIMER_ACTIVE) { - active_timer_found = true; - break; - } - } - /*If no active timers found, start one*/ - if (!active_timer_found) { - pl_timer_remaining_slots = platform_timer_get_remaining_slots(); - /*Find hold-labelled timer with the least remaining slots*/ - ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { - if (cur_timer->timer_state == NS_TIMER_HOLD) { - cur_timer->remaining_slots += pl_timer_remaining_slots; - - if (!first_timer || cur_timer->remaining_slots < first_timer->remaining_slots) { - first_timer = cur_timer; - } - } - } - /*If hold-labelled timer found, set it active and start the HAL driver*/ - if (first_timer) { - first_timer->timer_state = NS_TIMER_ACTIVE; - /*Start HAL timer*/ - ns_timer_start_pl_timer(first_timer->remaining_slots); - /*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/ - ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { - if (cur_timer->timer_state == NS_TIMER_HOLD) { - if (cur_timer->remaining_slots == first_timer->remaining_slots) { - cur_timer->timer_state = NS_TIMER_ACTIVE; - } else { - cur_timer->remaining_slots -= first_timer->remaining_slots; - } - } - } - } - } - -exit: - platform_exit_critical(); - - return retval; -} -#endif // NS_EXCLUDE_HIGHRES_TIMER diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.h b/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.h deleted file mode 100644 index eac2f9d48bd..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/ns_timer.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 NS_TIMER_H_ -#define NS_TIMER_H_ - -#include "platform/eventloop_config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NS_EXCLUDE_HIGHRES_TIMER -extern int8_t ns_timer_sleep(void); -#else -#define ns_timer_sleep() ((int8_t) 0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /*NS_TIMER_H_*/ diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/system_timer.c b/features/nanostack/sal-stack-nanostack-eventloop/source/system_timer.c deleted file mode 100644 index 7535a4c5979..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/system_timer.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 "ns_types.h" -#include "ns_list.h" -#include "timer_sys.h" -#include "platform/arm_hal_interrupt.h" -#include "platform/arm_hal_timer.h" -#include "nsdynmemLIB.h" -#include "eventOS_event.h" -#include "eventOS_event_timer.h" -#include "event.h" -#include "eventOS_callback_timer.h" - -#include "ns_timer.h" - -#ifndef ST_MAX -#define ST_MAX 6 -#endif - -static sys_timer_struct_s startup_sys_timer_pool[ST_MAX]; - -#define TIMER_SLOTS_PER_MS 20 -NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Need whole number of ms per tick") -#define TIMER_SYS_TICK_PERIOD (1000 / EVENTOS_EVENT_TIMER_HZ) // milliseconds - -// timer_sys_ticks must be read in critical section to guarantee -// atomicity on 16-bit platforms -static volatile uint32_t timer_sys_ticks; - -static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, event.link); -static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, event.link); - - -static sys_timer_struct_s *sys_timer_dynamically_allocate(void); -static void timer_sys_interrupt(void); -static void timer_sys_add(sys_timer_struct_s *timer); - -#ifndef NS_EVENTLOOP_USE_TICK_TIMER -static int8_t platform_tick_timer_start(uint32_t period_ms); -/* Implement platform tick timer using eventOS timer */ -// platform tick timer callback function -static void (*tick_timer_callback)(void); -static int8_t tick_timer_id = -1; // eventOS timer id for tick timer - -// EventOS timer callback function -static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots) -{ - // Not interested in timer id or slots - (void)slots; - // Call the tick timer callback - if (tick_timer_callback != NULL && timer_id == tick_timer_id) { - platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); - tick_timer_callback(); - } -} - -static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void)) -{ - tick_timer_callback = tick_timer_cb; - tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback); - return tick_timer_id; -} - -static int8_t platform_tick_timer_start(uint32_t period_ms) -{ - return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms); -} - -static int8_t platform_tick_timer_stop(void) -{ - return eventOS_callback_timer_stop(tick_timer_id); -} -#endif // !NS_EVENTLOOP_USE_TICK_TIMER - -/* - * Initializes timers and starts system timer - */ -void timer_sys_init(void) -{ - for (uint8_t i = 0; i < ST_MAX; i++) { - ns_list_add_to_start(&system_timer_free, &startup_sys_timer_pool[i]); - } - - platform_tick_timer_register(timer_sys_interrupt); - platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); -} - - - -/*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ -void timer_sys_disable(void) -{ - platform_tick_timer_stop(); -} - -/* - * Starts ticking system timer interrupts every 10ms - */ -int8_t timer_sys_wakeup(void) -{ - return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); -} - - -static void timer_sys_interrupt(void) -{ - system_timer_tick_update(1); -} - - - -/* * * * * * * * * */ - -static sys_timer_struct_s *sys_timer_dynamically_allocate(void) -{ - return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); -} - -static sys_timer_struct_s *timer_struct_get(void) -{ - sys_timer_struct_s *timer; - platform_enter_critical(); - timer = ns_list_get_first(&system_timer_free); - if (timer) { - ns_list_remove(&system_timer_free, timer); - } else { - timer = sys_timer_dynamically_allocate(); - } - platform_exit_critical(); - return timer; -} - -void timer_sys_event_free(arm_event_storage_t *event) -{ - platform_enter_critical(); - sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); - if (timer->period == 0) { - // Non-periodic - return to free list - ns_list_add_to_start(&system_timer_free, timer); - } else { - // Periodic - check due time of next launch - timer->launch_time += timer->period; - if (TICKS_BEFORE_OR_AT(timer->launch_time, timer_sys_ticks)) { - // next event is overdue - queue event now - eventOS_event_send_timer_allocated(&timer->event); - } else { - // add back to timer queue for the future - timer_sys_add(timer); - } - } - platform_exit_critical(); -} - -void timer_sys_event_cancel_critical(struct arm_event_storage *event) -{ - sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); - timer->period = 0; - // If its unqueued it is on my timer list, otherwise it is in event-loop. - if (event->state == ARM_LIB_EVENT_UNQUEUED) { - ns_list_remove(&system_timer_list, timer); - } -} - -uint32_t eventOS_event_timer_ticks(void) -{ - uint32_t ret_val; - // Enter/exit critical is a bit clunky, but necessary on 16-bit platforms, - // which won't be able to do an atomic 32-bit read. - platform_enter_critical(); - ret_val = timer_sys_ticks; - platform_exit_critical(); - return ret_val; -} - -/* Called internally with lock held */ -static void timer_sys_add(sys_timer_struct_s *timer) -{ - uint32_t at = timer->launch_time; - - // Find first timer scheduled to run after us, and insert before it. - // (This means timers scheduled for same time run in order of request) - ns_list_foreach(sys_timer_struct_s, t, &system_timer_list) { - if (TICKS_BEFORE(at, t->launch_time)) { - ns_list_add_before(&system_timer_list, t, timer); - return; - } - } - - // Didn't insert before another timer, so must be last. - ns_list_add_to_end(&system_timer_list, timer); -} - -/* Called internally with lock held */ -static arm_event_storage_t *eventOS_event_timer_request_at_(const arm_event_t *event, uint32_t at, uint32_t period) -{ - // Because we use user-allocated events, they must get delivered to avoid - // a leak. Previously this call queued timers for invalid tasks, then they - // would go undelivered. Now it returns an error. - if (!event_tasklet_handler_id_valid(event->receiver)) { - return NULL; - } - - sys_timer_struct_s *timer = timer_struct_get(); - if (!timer) { - return NULL; - } - - timer->event.data = *event; - timer->event.allocator = ARM_LIB_EVENT_TIMER; - timer->event.state = ARM_LIB_EVENT_UNQUEUED; - timer->launch_time = at; - timer->period = period; - - if (TICKS_BEFORE_OR_AT(at, timer_sys_ticks)) { - eventOS_event_send_timer_allocated(&timer->event); - } else { - timer_sys_add(timer); - } - - return &timer->event; -} - -arm_event_storage_t *eventOS_event_timer_request_at(const arm_event_t *event, uint32_t at) -{ - platform_enter_critical(); - - arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, at, 0); - - platform_exit_critical(); - - return ret; -} - -arm_event_storage_t *eventOS_event_timer_request_in(const arm_event_t *event, int32_t in) -{ - platform_enter_critical(); - - arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + in, 0); - - platform_exit_critical(); - - return ret; - -} - -arm_event_storage_t *eventOS_event_timer_request_every(const arm_event_t *event, int32_t period) -{ - if (period <= 0) { - return NULL; - } - - platform_enter_critical(); - - arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + period, period); - - platform_exit_critical(); - - return ret; - -} - -int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time) -{ - const arm_event_t event = { - .event_id = event_id, - .event_type = event_type, - .receiver = tasklet_id, - .sender = 0, - .data_ptr = NULL, - .event_data = 0, - .priority = ARM_LIB_MED_PRIORITY_EVENT, - }; - - // Legacy time behaviour preserved - - // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. - // And why shouldn't they be able to get a 1-tick callback? - if (time > 2 * TIMER_SYS_TICK_PERIOD) { - time /= TIMER_SYS_TICK_PERIOD; - // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? - time++; - } else { - time = 2; - } - - platform_enter_critical(); - arm_event_storage_t *ret = eventOS_event_timer_request_at_(&event, timer_sys_ticks + time, 0); - platform_exit_critical(); - return ret?0:-1; -} - -int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id) -{ - platform_enter_critical(); - - /* First check pending timers */ - ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { - if (cur->event.data.receiver == tasklet_id && cur->event.data.event_id == event_id) { - eventOS_cancel(&cur->event); - goto done; - } - } - - /* No pending timer, so check for already-pending event */ - arm_event_storage_t *event = eventOS_event_find_by_id_critical(tasklet_id, event_id); - if (event && event->allocator == ARM_LIB_EVENT_TIMER) { - eventOS_cancel(event); - goto done; - } - - /* No match found */ - platform_exit_critical(); - return -1; - -done: - platform_exit_critical(); - return 0; -} - -uint32_t eventOS_event_timer_shortest_active_timer(void) -{ - uint32_t ret_val = 0; - - platform_enter_critical(); - sys_timer_struct_s *first = ns_list_get_first(&system_timer_list); - if (first == NULL) { - // Weird API has 0 for "no events" - ret_val = 0; - } else if (TICKS_BEFORE_OR_AT(first->launch_time, timer_sys_ticks)) { - // Which means an immediate/overdue event has to be 1 - ret_val = 1; - } else { - ret_val = first->launch_time - timer_sys_ticks; - } - - platform_exit_critical(); - return eventOS_event_timer_ticks_to_ms(ret_val); -} - -void system_timer_tick_update(uint32_t ticks) -{ - platform_enter_critical(); - //Keep runtime time - timer_sys_ticks += ticks; - ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { - if (TICKS_BEFORE_OR_AT(cur->launch_time, timer_sys_ticks)) { - // Unthread from our list - ns_list_remove(&system_timer_list, cur); - // Make it an event (can't fail - no allocation) - // event system will call our timer_sys_event_free on event delivery. - eventOS_event_send_timer_allocated(&cur->event); - } else { - // List is ordered, so as soon as we see a later event, we're done. - break; - } - } - - platform_exit_critical(); -} - diff --git a/features/nanostack/sal-stack-nanostack-eventloop/source/timer_sys.h b/features/nanostack/sal-stack-nanostack-eventloop/source/timer_sys.h deleted file mode 100644 index a29aec937af..00000000000 --- a/features/nanostack/sal-stack-nanostack-eventloop/source/timer_sys.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 _PL_NANO_TIMER_SYS_H_ -#define _PL_NANO_TIMER_SYS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "eventOS_event.h" - -/* We borrow base event storage, including its list link, and add a time field */ -typedef struct sys_timer_struct_s { - arm_event_storage_t event; - uint32_t launch_time; // tick value - uint32_t period; -} sys_timer_struct_s; - - -/** - * Initialize system timer - * */ -extern void timer_sys_init(void); - -extern uint32_t timer_get_runtime_ticks(void); -int8_t timer_sys_wakeup(void); -void timer_sys_disable(void); -void timer_sys_event_free(struct arm_event_storage *event); - -// This require lock to be held -void timer_sys_event_cancel_critical(struct arm_event_storage *event); - -/** - * System Timer update and synch after sleep - * - * \param ticks Time in 10 ms resolution - * - * \return none - * - * */ -void system_timer_tick_update(uint32_t ticks); - -#ifdef __cplusplus -} -#endif - -#endif /*_PL_NANO_TIMER_SYS_H_*/ From 623607c9da4ccd5cc1d3d75ff185b3f8d29a473b Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 9 Nov 2018 15:31:56 +0200 Subject: [PATCH 06/12] Squashed 'features/nanostack/sal-stack-nanostack-eventloop/' content from commit 778c4db git-subtree-dir: features/nanostack/sal-stack-nanostack-eventloop git-subtree-split: 778c4dba0f452ec87cabb0559dd1fa0f905818a1 --- .cproject | 234 ++++++++++ .gitignore | 6 + .project | 82 ++++ .settings/org.eclipse.cdt.codan.core.prefs | 67 +++ .settings/org.eclipse.cdt.core.prefs | 65 +++ LICENSE | 2 + Makefile | 34 ++ apache-2.0.txt | 56 +++ mbed_lib.json | 13 + module.json | 25 ++ nanostack-event-loop/eventOS_callback_timer.h | 32 ++ nanostack-event-loop/eventOS_event.h | 169 ++++++++ nanostack-event-loop/eventOS_event_timer.h | 255 +++++++++++ nanostack-event-loop/eventOS_scheduler.h | 173 ++++++++ nanostack-event-loop/platform/arm_hal_timer.h | 95 +++++ .../platform/eventloop_config.h | 56 +++ source/event.c | 401 ++++++++++++++++++ source/event.h | 34 ++ source/minar_hal_timer.cpp | 71 ++++ source/ns_timeout.c | 118 ++++++ source/ns_timer.c | 391 +++++++++++++++++ source/ns_timer.h | 35 ++ source/system_timer.c | 373 ++++++++++++++++ source/timer_sys.h | 60 +++ 24 files changed, 2847 insertions(+) create mode 100644 .cproject create mode 100644 .gitignore create mode 100644 .project create mode 100644 .settings/org.eclipse.cdt.codan.core.prefs create mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 apache-2.0.txt create mode 100644 mbed_lib.json create mode 100644 module.json create mode 100644 nanostack-event-loop/eventOS_callback_timer.h create mode 100644 nanostack-event-loop/eventOS_event.h create mode 100644 nanostack-event-loop/eventOS_event_timer.h create mode 100644 nanostack-event-loop/eventOS_scheduler.h create mode 100644 nanostack-event-loop/platform/arm_hal_timer.h create mode 100644 nanostack-event-loop/platform/eventloop_config.h create mode 100644 source/event.c create mode 100644 source/event.h create mode 100644 source/minar_hal_timer.cpp create mode 100644 source/ns_timeout.c create mode 100644 source/ns_timer.c create mode 100644 source/ns_timer.h create mode 100644 source/system_timer.c create mode 100644 source/timer_sys.h diff --git a/.cproject b/.cproject new file mode 100644 index 00000000000..c41e8ee7466 --- /dev/null +++ b/.cproject @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..cd8daf1ac81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.a +output/* +build +yotta_modules +yotta_targets +*.lib diff --git a/.project b/.project new file mode 100644 index 00000000000..b2d4cf5ac4e --- /dev/null +++ b/.project @@ -0,0 +1,82 @@ + + + eventOS + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/event_loop/Debug} + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 00000000000..77386c23cbe --- /dev/null +++ b/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,67 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 00000000000..2eaccaf10b9 --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,65 @@ +eclipse.preferences.version=1 +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/delimiter=; +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/operation=append +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/CC/value=gcc +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/delimiter=; +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/operation=append +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/V/value=1 +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/append=true +environment/project/0.2056004298.141662914.1517984773.801758434.1788862897/appendContributed=true +environment/project/0.2056004298.141662914.2121498000.642060230/CPU/delimiter=; +environment/project/0.2056004298.141662914.2121498000.642060230/CPU/operation=replace +environment/project/0.2056004298.141662914.2121498000.642060230/CPU/value=Cortex-M0 +environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/delimiter=; +environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/operation=replace +environment/project/0.2056004298.141662914.2121498000.642060230/DEBUG/value=1 +environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/delimiter=; +environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/operation=append +environment/project/0.2056004298.141662914.2121498000.642060230/PLATFORM/value=arm-unknown-linux-uclibcgnueabi- +environment/project/0.2056004298.141662914.2121498000.642060230/V/delimiter=; +environment/project/0.2056004298.141662914.2121498000.642060230/V/operation=append +environment/project/0.2056004298.141662914.2121498000.642060230/V/value=1 +environment/project/0.2056004298.141662914.2121498000.642060230/append=true +environment/project/0.2056004298.141662914.2121498000.642060230/appendContributed=true +environment/project/0.2056004298.141662914.2121498000/CPU/delimiter=; +environment/project/0.2056004298.141662914.2121498000/CPU/operation=append +environment/project/0.2056004298.141662914.2121498000/CPU/value=Cortex-M3 +environment/project/0.2056004298.141662914.2121498000/PLATFORM/delimiter=; +environment/project/0.2056004298.141662914.2121498000/PLATFORM/operation=append +environment/project/0.2056004298.141662914.2121498000/PLATFORM/value=arm-unknown-linux-uclibcgnueabi- +environment/project/0.2056004298.141662914.2121498000/V/delimiter=; +environment/project/0.2056004298.141662914.2121498000/V/operation=append +environment/project/0.2056004298.141662914.2121498000/V/value=1 +environment/project/0.2056004298.141662914.2121498000/append=true +environment/project/0.2056004298.141662914.2121498000/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CC/value=armcc +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CONFIG/value=generic +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/CPU/value=Cortex-M0 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/DEBUG/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/V/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/append=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176.535362087/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CC/value=armcc +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/CPU/value=Cortex-M3 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/DEBUG/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/V/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/append=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1189539176/appendContributed=true diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..97df0e645d3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..ee2a9020b4c --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +# Define compiler toolchain with CC or PLATFORM variables +# Example (GCC toolchains) +# make PLATFORM=arm-linux-gnueabi- +# OR +# make CC=armcc AR=ArmAR +# OR +# make CC=iccarm + +LIB = libeventOS.a +SRCS += \ + source/event.c \ + source/ns_timer.c \ + source/system_timer.c\ + source/ns_timeout.c + +include ../libService/toolchain_rules.mk + +override CFLAGS += -I nanostack-event-loop + +# +# External sources from libService +# +SERVLIB_DIR := ../libService +override CFLAGS += -I$(SERVLIB_DIR)/libService + +$(eval $(call generate_rules,$(LIB),$(SRCS))) + +.PHONY: release +release: + 7z a edtls-lib_$(VERSION).zip *.a *.lib include + +.PHONY: deploy_to +deploy_to: all + tar --transform 's,^,event-loop/,' --append -f $(TO) *.a diff --git a/apache-2.0.txt b/apache-2.0.txt new file mode 100644 index 00000000000..0e4cf3ee999 --- /dev/null +++ b/apache-2.0.txt @@ -0,0 +1,56 @@ + + +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. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/mbed_lib.json b/mbed_lib.json new file mode 100644 index 00000000000..a56cdb50306 --- /dev/null +++ b/mbed_lib.json @@ -0,0 +1,13 @@ +{ + "name": "nanostack-eventloop", + "config": { + "use_platform_tick_timer": { + "help": "Use platform provided low resolution tick timer for eventloop", + "value": null + }, + "exclude_highres_timer": { + "help": "Exclude high resolution timer from build", + "value": null + } + } +} diff --git a/module.json b/module.json new file mode 100644 index 00000000000..ac6e4f00469 --- /dev/null +++ b/module.json @@ -0,0 +1,25 @@ +{ + "name": "sal-stack-nanostack-eventloop", + "version": "1.1.0", + "description": "Event loop for 6LoWPAN stack", + "keywords": [], + "author": "Seppo Takalo ", + "repository": { + "url": "git@github.com:ARMmbed/sal-stack-nanostack-eventloop.git", + "type": "git" + }, + "homepage": "https://github.com/ARMmbed/sal-stack-nanostack-eventloop", + "license": "Apache-2.0", + "extraIncludes": [ + "nanostack-event-loop" + ], + "dependencies": { + "nanostack-libservice": "ARMmbed/nanostack-libservice#master" + }, + "targetDependencies": { + "mbed": { + "mbed-6lowpan-eventloop-adaptor": "^1.0.0", + "minar": "^1.0.0" + } + } +} diff --git a/nanostack-event-loop/eventOS_callback_timer.h b/nanostack-event-loop/eventOS_callback_timer.h new file mode 100644 index 00000000000..6b7d705811c --- /dev/null +++ b/nanostack-event-loop/eventOS_callback_timer.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014-2015 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 EVENTOS_CALLBACK_TIMER_H_ +#define EVENTOS_CALLBACK_TIMER_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include "ns_types.h" + +extern int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)); +extern int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id); + +extern int8_t eventOS_callback_timer_stop(int8_t ns_timer_id); +extern int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots); +#ifdef __cplusplus +} +#endif + +#endif /* EVENTOS_CALLBACK_TIMER_H_ */ diff --git a/nanostack-event-loop/eventOS_event.h b/nanostack-event-loop/eventOS_event.h new file mode 100644 index 00000000000..fdade478380 --- /dev/null +++ b/nanostack-event-loop/eventOS_event.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014-2015 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 EVENTOS_EVENT_H_ +#define EVENTOS_EVENT_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "ns_types.h" +#include "ns_list.h" + +/** + * \enum arm_library_event_priority_e + * \brief Event Priority level. + */ +typedef enum arm_library_event_priority_e { + ARM_LIB_HIGH_PRIORITY_EVENT = 0, /**< High Priority Event (Function CB) */ + ARM_LIB_MED_PRIORITY_EVENT = 1, /**< Medium Priority (Timer) */ + ARM_LIB_LOW_PRIORITY_EVENT = 2, /*!*< Normal Event and ECC / Security */ +} arm_library_event_priority_e; + +/** + * \struct arm_event_s + * \brief Event structure. + */ +typedef struct arm_event_s { + int8_t receiver; /**< Event handler Tasklet ID */ + int8_t sender; /**< Event sender Tasklet ID */ + uint8_t event_type; /**< This will be typecast arm_library_event_type_e, arm_internal_event_type_e or application specific define */ + uint8_t event_id; /**< Timer ID, NWK interface ID or application specific ID */ + void *data_ptr; /**< Application could share data pointer tasklet to tasklet */ + arm_library_event_priority_e priority; + uint32_t event_data; +} arm_event_t; + +/* Backwards compatibility */ +typedef arm_event_t arm_event_s; + +/** + * \struct arm_event_storage + * \brief Event structure storage, including list link. + +@startuml + +partition "Event loop" { +(*) -->[event created] "UNQUEUED" +"UNQUEUED" -->[event_core_write()] "QUEUED" +"QUEUED" -->[event_core_read()] "RUNNING" +"RUNNING" ->[event_core_free_push()] "UNQUEUED" +} + +partition "system_timer.c" { + "UNQUEUED:timer" -->[eventOS_event_send_timer_allocated()] "QUEUED" +} +@enduml + + */ +typedef struct arm_event_storage { + arm_event_s data; + enum { + ARM_LIB_EVENT_STARTUP_POOL, + ARM_LIB_EVENT_DYNAMIC, + ARM_LIB_EVENT_USER, + ARM_LIB_EVENT_TIMER, + } allocator; + enum { + ARM_LIB_EVENT_UNQUEUED, + ARM_LIB_EVENT_QUEUED, + ARM_LIB_EVENT_RUNNING, + } state; + ns_list_link_t link; +} arm_event_storage_t; + +/** + * \brief Send event to event scheduler. + * + * \param event pointer to pushed event. + * + * Event data is copied by the call, and this copy persists until the + * recipient's callback function returns. The callback function is passed + * a pointer to a copy of the data, not the original pointer. + * + * \return 0 Event push OK + * \return -1 Memory allocation Fail + */ +extern int8_t eventOS_event_send(const arm_event_t *event); + +/* Alternate names for timer function from eventOS_event_timer.h; + * implementations may one day merge */ +#define eventOS_event_send_at(event, at) eventOS_event_timer_request_at(event, at) +#define eventOS_event_send_in(event, in) eventOS_event_timer_request_in(event, in) +#define eventOS_event_send_after(event, after) eventOS_event_timer_request_after(event, after) +#define eventOS_event_send_every(event, every) eventOS_event_timer_request_every(event, every) + +/** + * \brief Send user-allocated event to event scheduler. + * + * \param event pointer to pushed event storage. + * + * The event structure is not copied by the call, the event system takes + * ownership and it is threaded directly into the event queue. This avoids the + * possibility of event sending failing due to memory exhaustion. + * + * event->data must be filled in on entry - the rest of the structure (link and + * allocator) need not be. + * + * The structure must remain valid until the recipient is called - the + * event system passes ownership to the receiving event handler, who may then + * invalidate it, or send it again. + * + * The recipient receives a pointer to the arm_event_t data member of the + * event - it can use NS_CONTAINER_OF() to get a pointer to the original + * event passed to this call, or to its outer container. + * + * It is a program error to send a user-allocated event to a non-existent task. + */ +extern void eventOS_event_send_user_allocated(arm_event_storage_t *event); + +/** + * \brief Event handler callback register + * + * Function will register and allocate unique event id handler + * + * \param handler_func_ptr function pointer for event handler + * \param init_event_type generated event type for init purpose + * + * \return >= 0 Unique event ID for this handler + * \return < 0 Register fail + * + * */ +extern int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_t *), uint8_t init_event_type); + +/** + * Cancel an event. + * + * Queued events are removed from the event-loop queue and/or the timer queue. + * + * Passing a NULL pointer is allowed, and does nothing. + * + * Event pointers are valid from the time they are queued until the event + * has finished running or is cancelled. + * + * Cancelling a currently-running event is only useful to stop scheduling + * it if it is on a periodic timer; it has no other effect. + * + * Cancelling an already-cancelled or already-run single-shot event + * is undefined behaviour. + * + * \param event Pointer to event handle or NULL. + */ +extern void eventOS_cancel(arm_event_storage_t *event); + +#ifdef __cplusplus +} +#endif +#endif /* EVENTOS_EVENT_H_ */ diff --git a/nanostack-event-loop/eventOS_event_timer.h b/nanostack-event-loop/eventOS_event_timer.h new file mode 100644 index 00000000000..dec8efd9fbe --- /dev/null +++ b/nanostack-event-loop/eventOS_event_timer.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2014-2015 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 EVENTOS_EVENT_TIMER_H_ +#define EVENTOS_EVENT_TIMER_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include "ns_types.h" +#include "eventOS_event.h" + +struct arm_event_s; +typedef struct sys_timer_struct_s sys_timer_struct_t; + +/* 100 Hz ticker, so 10 milliseconds per tick */ +#define EVENTOS_EVENT_TIMER_HZ 100 + +static inline uint32_t eventOS_event_timer_ticks_to_ms(uint32_t ticks) +{ + NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick") + return ticks * (1000 / EVENTOS_EVENT_TIMER_HZ); +} + +/* Convert ms to ticks, rounding up (so 9ms = 1 tick, 10ms = 1 tick, 11ms = 2 ticks) */ +static inline uint32_t eventOS_event_timer_ms_to_ticks(uint32_t ms) +{ + NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick") + return (ms + (1000 / EVENTOS_EVENT_TIMER_HZ) - 1) / (1000 / EVENTOS_EVENT_TIMER_HZ); +} + +/** + * Read current timer tick count. + * + * Can be used as a monotonic time source, and to schedule events with + * eventOS_event_timer_send. + * + * Note that the value will wrap, so take care on comparisons. + * + * \return tick count. + */ +extern uint32_t eventOS_event_timer_ticks(void); + +/* Comparison macros handling wrap efficiently (assuming a conventional compiler + * which converts 0x80000000 to 0xFFFFFFFF to negative when casting to int32_t). + */ +#define TICKS_AFTER(a, b) ((int32_t) ((a)-(b)) > 0) +#define TICKS_BEFORE(a, b) ((int32_t) ((a)-(b)) < 0) +#define TICKS_AFTER_OR_AT(a, b) ((int32_t) ((a)-(b)) >= 0) +#define TICKS_BEFORE_OR_AT(a, b) ((int32_t) ((a)-(b)) <= 0) + +/** + * Send an event after time expired (in milliseconds) + * + * Note that the current implementation has the "feature" that rounding + * varies depending on the precise timing requested: + * 0-20 ms => 2 x 10ms tick + * 21-29 ms => 3 x 10ms tick + * 30-39 ms => 4 x 10ms tick + * 40-49 ms => 5 x 10ms tick + * ... etc + * + * For improved flexibility on the event, and for more control of time, + * you should use eventOS_event_timer_request_at(). + * + * \param event_id event_id for event + * \param event_type event_type for event + * \param tasklet_id receiver for event + * \param time time to sleep in milliseconds + * + * \return 0 on success + * \return -1 on error (invalid tasklet_id or allocation failure) + * + * */ +extern int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time); + +/** + * Send an event at specified time + * + * The event will be sent when eventOS_event_timer_ticks() reaches the + * specified value. + * + * If the specified time is in the past (ie "at" is before or at the current + * tick value), the event will be sent immediately. + * + * Can also be invoked using the eventOS_event_send_at() macro in eventOS_event.h + * + * \param event event to send + * \param at absolute tick time to run event at + * + * \return pointer to timer structure on success + * \return NULL on error (invalid tasklet_id or allocation failure) + * + */ +extern arm_event_storage_t *eventOS_event_timer_request_at(const struct arm_event_s *event, uint32_t at); + +/** + * Send an event in a specified time + * + * The event will be sent in the specified number of ticks - to + * be precise, it is equivalent to requesting an event at + * + * eventOS_event_timer_ticks() + ticks + * + * Because of timer granularity, the elapsed time between issuing the request + * and it running may be up to 1 tick less than the specified time. + * + * eg requesting 2 ticks will cause the event to be sent on the second tick from + * now. If requested just after a tick, the delay will be nearly 2 ticks, but if + * requested just before a tick, the delay will be just over 1 tick. + * + * If `in` is <= 0, the event will be sent immediately. + * + * Can also be invoked using the eventOS_event_send_in() macro in eventOS_event.h + * + * \param event event to send + * \param in tick delay for event + * + * \return pointer to timer structure on success + * \return NULL on error (invalid tasklet_id or allocation failure) + * + */ +extern arm_event_storage_t *eventOS_event_timer_request_in(const struct arm_event_s *event, int32_t in); + +/** + * Send an event after a specified time + * + * The event will be sent after the specified number of ticks - to + * be precise, it is equivalent to requesting an event at + * + * eventOS_event_timer_ticks() + ticks + 1 + * + * Because of timer granularity, the elapsed time between issuing the request + * and it running may be up to 1 tick more than the specified time. + * + * eg requesting 2 ticks will cause the event to be sent on the third tick from + * now. If requested just after a tick, the delay will be nearly 3 ticks, but if + * requested just before a tick, the delay will be just over 2 ticks. + * + * If `after` is < 0, the event will be sent immediately. If it is 0, the event + * is sent on the next tick. + * + * Can also be invoked using the eventOS_event_send_after() macro in eventOS_event.h + * + * \param event event to send + * \param after tick delay for event + * + * \return pointer to timer structure on success + * \return NULL on error (invalid tasklet_id or allocation failure) + * + */ +#define eventOS_event_timer_request_after(event, after) \ + eventOS_event_timer_request_in(event, (after) + 1) + +/** + * Send an event periodically + * + * The event will be sent repeatedly using the specified ticks period. + * + * The first call is sent at + * + * eventOS_event_timer_ticks() + ticks + * + * Subsequent events will be sent at N*ticks from the initial time. + * + * Period will be maintained while the device is awake, regardless of delays to + * event scheduling. If an event has not been delivered and completed by the + * next scheduled time, the next event will be sent immediately when it + * finishes. This could cause a continuous stream of events if unable to keep + * up with the period. + * + * Can also be invoked using the eventOS_event_send_every() macro in eventOS_event.h + * + * \param event event to send + * \param period period for event + * + * \return pointer to timer structure on success + * \return NULL on error (invalid tasklet_id or allocation failure) + * + */ +extern arm_event_storage_t *eventOS_event_timer_request_every(const struct arm_event_s *event, int32_t period); + +/** + * Cancel an event timer + * + * This cancels a pending timed event, matched by event_id and tasklet_id. + * + * \param event_id event_id for event + * \param tasklet_id receiver for event + * + * \return 0 on success + * \return -1 on error (event not found) + * + * */ +extern int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id); + +/** + * System Timer shortest time in milli seconds + * + * \param ticks Time in 10 ms resolution + * + * \return none + * + * */ +extern uint32_t eventOS_event_timer_shortest_active_timer(void); + + +/** Timeout structure. Not to be modified by user */ +typedef struct timeout_entry_t timeout_t; + +/** Request timeout callback. + * + * Create timeout request for specific callback. + * + * \param ms timeout in milliseconds. Maximum range is same as for eventOS_event_timer_request(). + * \param callback function to call after timeout + * \param arg arquement to pass to callback + * \return pointer to timeout structure or NULL on errors + */ +timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg); + +/** Request periodic callback. + * + * Create timeout request for specific callback. Called periodically until eventOS_timeout_cancel() is called. + * + * \param every period in milliseconds. Maximum range is same as for eventOS_event_timer_request(). + * \param callback function to call after timeout + * \param arg arquement to pass to callback + * \return pointer to timeout structure or NULL on errors + */ +timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg); + +/** Cancell timeout request. + * + * \param t timeout request id. + */ +void eventOS_timeout_cancel(timeout_t *t); + + +#ifdef __cplusplus +} +#endif + +#endif /* EVENTOS_EVENT_TIMER_H_ */ diff --git a/nanostack-event-loop/eventOS_scheduler.h b/nanostack-event-loop/eventOS_scheduler.h new file mode 100644 index 00000000000..15d4f56008d --- /dev/null +++ b/nanostack-event-loop/eventOS_scheduler.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2014-2015 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 EVENTOS_SCHEDULER_H_ +#define EVENTOS_SCHEDULER_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "ns_types.h" + +/* Compatibility with older ns_types.h */ +#ifndef NS_NORETURN +#define NS_NORETURN +#endif + +/** + * \brief Initialise event scheduler. + * + */ +extern void eventOS_scheduler_init(void); + +/** + * Process one event from event queue. + * Do not call this directly from application. Requires to be public so that simulator can call this. + * Use eventOS_scheduler_run() or eventOS_scheduler_run_until_idle(). + * \return true If there was event processed, false if the event queue was empty. + */ +bool eventOS_scheduler_dispatch_event(void); + +/** + * \brief Process events until no more events to process. + */ +extern void eventOS_scheduler_run_until_idle(void); + +/** + * \brief Start Event scheduler. + * Loops forever processing events from the queue. + * Calls eventOS_scheduler_idle() whenever event queue is empty. + */ +NS_NORETURN extern void eventOS_scheduler_run(void); +/** + * \brief Disable Event scheduler Timers + * + * \return 0 Timer Stop OK + * \return -1 Timer Stop Fail + * + * */ +int eventOS_scheduler_timer_stop(void); + +/** + * \brief Synch Event scheduler timer after sleep + * + * \param sleep_ticks time in milli seconds + * + * \return 0 Timer Synch OK + * \return -1 Timer Synch & Start Fail + * + * */ +int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks); + +/** + * \brief Read current active Tasklet ID + * + * This function not return valid information called inside interrupt + * + * \return curret active tasklet id + * + * */ +extern int8_t eventOS_scheduler_get_active_tasklet(void); + +/** + * \brief Set manually Active Tasklet ID + * + * \param tasklet requested tasklet ID + * + * */ +extern void eventOS_scheduler_set_active_tasklet(int8_t tasklet); + +/** + * \brief Event scheduler loop idle Callback. + + * Note! This method is called only by eventOS_scheduler_run, needs to be + * ported for the platform only if you are using eventOS_scheduler_run(). + */ +extern void eventOS_scheduler_idle(void); + +/** + * \brief This function will be called when stack enter idle state and start + * waiting signal. + * + * Note! This method is called only by reference implementation of idle. Needs + * to be ported for the platform only if you are using reference implementation. + */ +extern void eventOS_scheduler_wait(void); + +/** + * \brief This function will be called when stack receives an event. + */ +extern void eventOS_scheduler_signal(void); + +/** + * \brief This function will be called when stack can enter deep sleep state in detected time. + * + * Note! This method is called only by reference implementation of idle. Needs to be + * ported for the platform only if you are using reference implementation. + * + * \param sleep_time_ms Time in milliseconds to sleep + * \return time slept in milliseconds + */ +extern uint32_t eventOS_scheduler_sleep(uint32_t sleep_time_ms); + +/** + * \brief Lock a thread against the event loop thread + * + * This method can be provided by multi-threaded platforms to allow + * mutual exclusion with the event loop thread, for cases where + * code wants to work with both the event loop and other threads. + * + * A typical platform implementation would claim the same mutex + * before calling eventOS_scheduler_run() or + * eventOS_scheduler_dispatch(), and release it during + * eventOS_scheduler_idle(). + * + * The mutex must count - nested calls from one thread return + * immediately. Thus calling this from inside an event callback + * is harmless. + */ +extern void eventOS_scheduler_mutex_wait(void); + +/** + * \brief Release the event loop mutex + * + * Release the mutex claimed with eventOS_scheduler_mutex_wait(), + * allowing the event loop to continue processing. + */ +extern void eventOS_scheduler_mutex_release(void); + +/** + * \brief Check if the current thread owns the event mutex + * + * Check if the calling thread owns the scheduler mutex. + * This allows the ownership to be asserted if a function + * requires the mutex to be locked externally. + * + * The function is only intended as a debugging aid for + * users of eventOS_scheduler_mutex_wait() - it is not + * used by the event loop core itself. + * + * If the underlying mutex system does not support it, + * this may be implemented to always return true. + * + * \return true if the current thread owns the mutex + */ +extern bool eventOS_scheduler_mutex_am_owner(void); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENTOS_SCHEDULER_H_ */ diff --git a/nanostack-event-loop/platform/arm_hal_timer.h b/nanostack-event-loop/platform/arm_hal_timer.h new file mode 100644 index 00000000000..0a661abfa0c --- /dev/null +++ b/nanostack-event-loop/platform/arm_hal_timer.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014-2015 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 ARM_HAL_TIMER_H_ +#define ARM_HAL_TIMER_H_ + +#include "eventloop_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NS_EXCLUDE_HIGHRES_TIMER +/** + * \brief This function perform timer init. + */ +extern void platform_timer_enable(void); + +/** + * \brief This function is API for set Timer interrupt handler for stack + * + * \param new_fp Function pointer for stack giving timer handler + * + */ +typedef void (*platform_timer_cb)(void); +extern void platform_timer_set_cb(platform_timer_cb new_fp); + +/** + * \brief This function is API for stack timer start + * + * \param slots define how many 50us slot time period will be started + * + */ +extern void platform_timer_start(uint16_t slots); + +/** + * \brief This function is API for stack timer stop + * + */ +extern void platform_timer_disable(void); + +/** + * \brief This function is API for stack timer to read active timer remaining slot count + * + * \return 50us time slot remaining + */ +extern uint16_t platform_timer_get_remaining_slots(void); + +#endif // NS_EXCLUDE_HIGHRES_TIMER + +#ifdef NS_EVENTLOOP_USE_TICK_TIMER +/** + * \brief This function is API for registering low resolution tick timer callback. Also does + * any necessary initialization of the tick timer. + * + * \return -1 for failure, success otherwise + */ +extern int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void)); + +/** + * \brief This function is API for starting the low resolution tick timer. The callback + * set with platform_tick_timer_register gets called periodically until stopped + * by calling platform_tick_timer_stop. + * + * \param period_ms define how many milliseconds time period will be started + * \return -1 for failure, success otherwise + */ +extern int8_t platform_tick_timer_start(uint32_t period_ms); + +/** + * \brief This function is API for stopping the low resolution tick timer + * + * \return -1 for failure, success otherwise + */ +extern int8_t platform_tick_timer_stop(void); + +#endif // NS_EVENTLOOP_USE_TICK_TIMER + +#ifdef __cplusplus +} +#endif + +#endif /* ARM_HAL_TIMER_H_ */ diff --git a/nanostack-event-loop/platform/eventloop_config.h b/nanostack-event-loop/platform/eventloop_config.h new file mode 100644 index 00000000000..904eb242428 --- /dev/null +++ b/nanostack-event-loop/platform/eventloop_config.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2015 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 EVENTLOOP_CONFIG_H_ +#define EVENTLOOP_CONFIG_H_ + +/* + * Options can be picked up from mbed-cli JSON configuration, or from + * Yotta JSON configuration, or from a user configuration file - see below. + * + * Undefine all internal flags before evaluating the configuration. + */ + +/* Use platform-provided low-resolution tick timer for eventloop (requires "platform_tick_timer" API) */ +#undef NS_EVENTLOOP_USE_TICK_TIMER +/* Exclude high resolution timer from build (removes need for "platform_timer" API) */ +#undef NS_EXCLUDE_HIGHRES_TIMER + +/* + * mbedOS 5 specific configuration flag mapping to internal flags + */ +#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_USE_PLATFORM_TICK_TIMER +#define NS_EVENTLOOP_USE_TICK_TIMER 1 +#endif + +#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER +#define NS_EXCLUDE_HIGHRES_TIMER 1 +#endif + +/* + * For mbedOS 3 and minar use platform tick timer by default, highres timers should come from eventloop adaptor + */ +#ifdef YOTTA_CFG_MINAR +#define NS_EVENTLOOP_USE_TICK_TIMER 1 +#endif + +/* + * Include the user config file if defined + */ +#ifdef NS_EVENTLOOP_USER_CONFIG_FILE +#include NS_EVENTLOOP_USER_CONFIG_FILE +#endif + +#endif /* EVENTLOOP_CONFIG_H_ */ diff --git a/source/event.c b/source/event.c new file mode 100644 index 00000000000..77dec693c96 --- /dev/null +++ b/source/event.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2014-2015 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 +#include "ns_types.h" +#include "ns_list.h" +#include "eventOS_event.h" +#include "eventOS_scheduler.h" +#include "timer_sys.h" +#include "nsdynmemLIB.h" +#include "ns_timer.h" +#include "event.h" +#include "platform/arm_hal_interrupt.h" + + +typedef struct arm_core_tasklet { + int8_t id; /**< Event handler Tasklet ID */ + void (*func_ptr)(arm_event_s *); + ns_list_link_t link; +} arm_core_tasklet_t; + +static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_t, link); +static NS_LIST_DEFINE(event_queue_active, arm_event_storage_t, link); +static NS_LIST_DEFINE(free_event_entry, arm_event_storage_t, link); + +// Statically allocate initial pool of events. +#define STARTUP_EVENT_POOL_SIZE 10 +static arm_event_storage_t startup_event_pool[STARTUP_EVENT_POOL_SIZE]; + +/** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */ +int8_t curr_tasklet = 0; + + +static arm_core_tasklet_t *tasklet_dynamically_allocate(void); +static arm_event_storage_t *event_dynamically_allocate(void); +static arm_event_storage_t *event_core_get(void); +static void event_core_write(arm_event_storage_t *event); + +static arm_core_tasklet_t *event_tasklet_handler_get(uint8_t tasklet_id) +{ + ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) { + if (cur->id == tasklet_id) { + return cur; + } + } + return NULL; +} + +bool event_tasklet_handler_id_valid(uint8_t tasklet_id) +{ + return event_tasklet_handler_get(tasklet_id); +} + +// XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least +// curr_tasklet is reset to 0 in various places. +static int8_t tasklet_get_free_id(void) +{ + /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ + for (uint8_t i = 0; i <= INT8_MAX; i++) { + if (!event_tasklet_handler_get(i)) { + return i; + } + } + return -1; +} + + +int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type) +{ + arm_event_storage_t *event_tmp; + + // XXX Do we really want to prevent multiple tasklets with same function? + ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) { + if (cur->func_ptr == handler_func_ptr) { + return -1; + } + } + + //Allocate new + arm_core_tasklet_t *new = tasklet_dynamically_allocate(); + if (!new) { + return -2; + } + + event_tmp = event_core_get(); + if (!event_tmp) { + ns_dyn_mem_free(new); + return -2; + } + + //Fill in tasklet; add to list + new->id = tasklet_get_free_id(); + new->func_ptr = handler_func_ptr; + ns_list_add_to_end(&arm_core_tasklet_list, new); + + //Queue "init" event for the new task + event_tmp->data.receiver = new->id; + event_tmp->data.sender = 0; + event_tmp->data.event_type = init_event_type; + event_tmp->data.event_data = 0; + event_core_write(event_tmp); + + return new->id; +} + +int8_t eventOS_event_send(const arm_event_t *event) +{ + if (event_tasklet_handler_get(event->receiver)) { + arm_event_storage_t *event_tmp = event_core_get(); + if (event_tmp) { + event_tmp->data = *event; + event_core_write(event_tmp); + return 0; + } + } + return -1; +} + +void eventOS_event_send_user_allocated(arm_event_storage_t *event) +{ + event->allocator = ARM_LIB_EVENT_USER; + event_core_write(event); +} + +void eventOS_event_send_timer_allocated(arm_event_storage_t *event) +{ + event->allocator = ARM_LIB_EVENT_TIMER; + event_core_write(event); +} + +void eventOS_event_cancel_critical(arm_event_storage_t *event) +{ + ns_list_remove(&event_queue_active, event); +} + +static arm_event_storage_t *event_dynamically_allocate(void) +{ + arm_event_storage_t *event = ns_dyn_mem_temporary_alloc(sizeof(arm_event_storage_t)); + if (event) { + event->allocator = ARM_LIB_EVENT_DYNAMIC; + } + return event; +} + +static arm_core_tasklet_t *tasklet_dynamically_allocate(void) +{ + return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_t)); +} + +arm_event_storage_t *event_core_get(void) +{ + arm_event_storage_t *event; + platform_enter_critical(); + event = ns_list_get_first(&free_event_entry); + if (event) { + ns_list_remove(&free_event_entry, event); + } else { + event = event_dynamically_allocate(); + } + if (event) { + event->data.data_ptr = NULL; + event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT; + } + platform_exit_critical(); + return event; +} + +void event_core_free_push(arm_event_storage_t *free) +{ + free->state = ARM_LIB_EVENT_UNQUEUED; + + switch (free->allocator) { + case ARM_LIB_EVENT_STARTUP_POOL: + platform_enter_critical(); + ns_list_add_to_start(&free_event_entry, free); + platform_exit_critical(); + break; + case ARM_LIB_EVENT_DYNAMIC: + // Free all dynamically allocated events. + ns_dyn_mem_free(free); + break; + case ARM_LIB_EVENT_TIMER: + // Hand it back to the timer system + timer_sys_event_free(free); + break; + case ARM_LIB_EVENT_USER: + default: + break; + } +} + + +static arm_event_storage_t *event_core_read(void) +{ + platform_enter_critical(); + arm_event_storage_t *event = ns_list_get_first(&event_queue_active); + if (event) { + event->state = ARM_LIB_EVENT_RUNNING; + ns_list_remove(&event_queue_active, event); + } + platform_exit_critical(); + return event; +} + +void event_core_write(arm_event_storage_t *event) +{ + platform_enter_critical(); + bool added = false; + ns_list_foreach(arm_event_storage_t, event_tmp, &event_queue_active) { + // note enum ordering means we're checking if event_tmp is LOWER priority than event + if (event_tmp->data.priority > event->data.priority) { + ns_list_add_before(&event_queue_active, event_tmp, event); + added = true; + break; + } + } + if (!added) { + ns_list_add_to_end(&event_queue_active, event); + } + event->state = ARM_LIB_EVENT_QUEUED; + + /* Wake From Idle */ + platform_exit_critical(); + eventOS_scheduler_signal(); +} + +// Requires lock to be held +arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id) +{ + ns_list_foreach(arm_event_storage_t, cur, &event_queue_active) { + if (cur->data.receiver == tasklet_id && cur->data.event_id == event_id) { + return cur; + } + } + + return NULL; +} + +/** + * + * \brief Initialize Nanostack Core. + * + * Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined. + * + */ +void eventOS_scheduler_init(void) +{ + /* Reset Event List variables */ + ns_list_init(&free_event_entry); + ns_list_init(&event_queue_active); + ns_list_init(&arm_core_tasklet_list); + + //Add first 10 entries to "free" list + for (unsigned i = 0; i < (sizeof(startup_event_pool) / sizeof(startup_event_pool[0])); i++) { + startup_event_pool[i].allocator = ARM_LIB_EVENT_STARTUP_POOL; + ns_list_add_to_start(&free_event_entry, &startup_event_pool[i]); + } + + /* Init Generic timer module */ + timer_sys_init(); //initialize timer + /* Set Tasklett switcher to Idle */ + curr_tasklet = 0; + +} + +int8_t eventOS_scheduler_get_active_tasklet(void) +{ + return curr_tasklet; +} + +void eventOS_scheduler_set_active_tasklet(int8_t tasklet) +{ + curr_tasklet = tasklet; +} + +int eventOS_scheduler_timer_stop(void) +{ + timer_sys_disable(); + if (ns_timer_sleep() != 0) { + return 1; + } + return 0; +} + +int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks) +{ + //Update MS to 10ms ticks + sleep_ticks /= 10; + sleep_ticks++; + system_timer_tick_update(sleep_ticks); + if (timer_sys_wakeup() == 0) { + return 0; + } + return -1; +} + +/** + * + * \brief Infinite Event Read Loop. + * + * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep + * + */ +bool eventOS_scheduler_dispatch_event(void) +{ + curr_tasklet = 0; + + arm_event_storage_t *cur_event = event_core_read(); + if (!cur_event) { + return false; + } + + curr_tasklet = cur_event->data.receiver; + + arm_core_tasklet_t *tasklet = event_tasklet_handler_get(curr_tasklet); + /* Do not bother with check for NULL - tasklets cannot be deleted, + * and user-facing API eventOS_event_send() has already checked the tasklet + * exists, so there is no possible issue there. + * + * For eventOS_event_send_user_allocated(), it would be a non-recoverable + * error to not deliver the message - we have to have a receiver to pass + * ownership to. If the lookup fails, let it crash. We want the send call + * itself to return void to simplify logic. + */ + + /* Tasklet Scheduler Call */ + tasklet->func_ptr(&cur_event->data); + event_core_free_push(cur_event); + + /* Set Current Tasklet to Idle state */ + curr_tasklet = 0; + + return true; +} + +void eventOS_scheduler_run_until_idle(void) +{ + while (eventOS_scheduler_dispatch_event()); +} + +/** + * + * \brief Infinite Event Read Loop. + * + * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep + * + */ +NS_NORETURN void eventOS_scheduler_run(void) +{ + while (1) { + if (!eventOS_scheduler_dispatch_event()) { + eventOS_scheduler_idle(); + } + } +} + +void eventOS_cancel(arm_event_storage_t *event) +{ + if (!event) { + return; + } + + platform_enter_critical(); + + /* + * Notify timer of cancellation. + */ + if (event->allocator == ARM_LIB_EVENT_TIMER) { + timer_sys_event_cancel_critical(event); + } + + /* + * Remove event from the list, + * Only queued can be removed, unqued are either timers or stale pointers + * RUNNING cannot be removed, we are currenly "in" that event. + */ + if (event->state == ARM_LIB_EVENT_QUEUED) { + eventOS_event_cancel_critical(event); + } + + /* + * Push back to "free" state + */ + if (event->state != ARM_LIB_EVENT_RUNNING) { + event_core_free_push(event); + } + + platform_exit_critical(); +} diff --git a/source/event.h b/source/event.h new file mode 100644 index 00000000000..9efb685857e --- /dev/null +++ b/source/event.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017 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 NS_EVENT_H_ +#define NS_EVENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +bool event_tasklet_handler_id_valid(uint8_t tasklet_id); +void eventOS_event_send_timer_allocated(arm_event_storage_t *event); + +// This requires lock to be held +arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id); + +#ifdef __cplusplus +} +#endif + +#endif /*NS_EVENT_H_*/ diff --git a/source/minar_hal_timer.cpp b/source/minar_hal_timer.cpp new file mode 100644 index 00000000000..3d8a0a9ee8f --- /dev/null +++ b/source/minar_hal_timer.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 ARM Limited, All Rights Reserved + */ + +// Include before mbed.h to properly get UINT*_C() + +#include "ns_types.h" + +#include "platform/arm_hal_timer.h" +#include "platform/arm_hal_interrupt.h" + +#if defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG_MINAR) + +#include "minar/minar.h" +#include "mbed-drivers/mbed.h" +#include "core-util/FunctionPointer.h" +#include "core-util/Event.h" + +#define TICK_TIMER_ID 1 + +using minar::Scheduler; +using minar::milliseconds; +using minar::callback_handle_t; +using namespace mbed::util; + +static callback_handle_t sys_timer_handle; +static void (*tick_timer_callback)(void); + +void timer_callback(void const *funcArgument) +{ + (void)funcArgument; + if (NULL != tick_timer_callback) { + tick_timer_callback(); + } +} + +// Low precision platform tick timer +int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void)) +{ + tick_timer_callback = tick_timer_cb_handler; + return TICK_TIMER_ID; +} + +int8_t platform_tick_timer_start(uint32_t period_ms) +{ + int8_t retval = -1; + if (sys_timer_handle != NULL) { + return 0; // Timer already started already so return success + } + Event e = FunctionPointer1(timer_callback).bind(NULL); + if (e != NULL) { + sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(period_ms)).getHandle(); + if (sys_timer_handle != NULL) { + retval = 0; + } + } + return retval; +} + +int8_t platform_tick_timer_stop(void) +{ + int8_t retval = -1; + if (sys_timer_handle != NULL) { + Scheduler::cancelCallback(sys_timer_handle); + sys_timer_handle = NULL; + retval = 0; + } + return retval; +} + +#endif // defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG) diff --git a/source/ns_timeout.c b/source/ns_timeout.c new file mode 100644 index 00000000000..4b3082f5015 --- /dev/null +++ b/source/ns_timeout.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014-2015 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 "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "nsdynmemLIB.h" +#include "ns_list.h" +#include "timer_sys.h" + +#define STARTUP_EVENT 0 +#define TIMER_EVENT 1 + +// Timeout structure, already typedefed to timeout_t +struct timeout_entry_t { + void (*callback)(void *); + void *arg; + arm_event_storage_t *event; +}; + +static int8_t timeout_tasklet_id = -1; + +static void timeout_tasklet(arm_event_s *event) +{ + if (TIMER_EVENT != event->event_type) { + return; + } + + timeout_t *t = event->data_ptr; + arm_event_storage_t *storage = t->event; + sys_timer_struct_s *timer = NS_CONTAINER_OF(storage, sys_timer_struct_s, event); + + t->callback(t->arg); + + + // Check if this was periodic timer + if (timer->period == 0) { + ns_dyn_mem_free(event->data_ptr); + } +} + +static timeout_t *eventOS_timeout_at_(void (*callback)(void *), void *arg, uint32_t at, uint32_t period) +{ + arm_event_storage_t *storage; + + timeout_t *timeout = ns_dyn_mem_alloc(sizeof(timeout_t)); + if (!timeout) { + return NULL; + } + timeout->callback = callback; + timeout->arg = arg; + + // Start timeout taskled if it is not running + if (-1 == timeout_tasklet_id) { + timeout_tasklet_id = eventOS_event_handler_create(timeout_tasklet, STARTUP_EVENT); + if (timeout_tasklet_id < 0) { + timeout_tasklet_id = -1; + goto FAIL; + } + } + + arm_event_t event = { + .receiver = timeout_tasklet_id, + .sender = timeout_tasklet_id, + .event_type = TIMER_EVENT, + .event_id = TIMER_EVENT, + .data_ptr = timeout + }; + + if (period) { + storage = eventOS_event_timer_request_every(&event, period); + } else { + storage = eventOS_event_timer_request_at(&event, at); + } + + timeout->event = storage; + if (storage) { + return timeout; + } +FAIL: + ns_dyn_mem_free(timeout); + return NULL; +} + +timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg) +{ + return eventOS_timeout_at_(callback, arg, eventOS_event_timer_ms_to_ticks(ms) + eventOS_event_timer_ticks(), 0); +} + +timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg) +{ + return eventOS_timeout_at_(callback, arg, 0, eventOS_event_timer_ms_to_ticks(every)); +} + +void eventOS_timeout_cancel(timeout_t *t) +{ + if (!t) { + return; + } + + eventOS_cancel(t->event); + + // Defer the freeing until returning from the callback + if (t->event->state != ARM_LIB_EVENT_RUNNING) { + ns_dyn_mem_free(t); + } +} diff --git a/source/ns_timer.c b/source/ns_timer.c new file mode 100644 index 00000000000..f3affbdd248 --- /dev/null +++ b/source/ns_timer.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2014-2015 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 "ns_types.h" +#include "ns_list.h" +#include "ns_timer.h" +#include "eventOS_callback_timer.h" +#include "platform/arm_hal_interrupt.h" +#include "platform/arm_hal_timer.h" +#include "nsdynmemLIB.h" + +#ifndef NS_EXCLUDE_HIGHRES_TIMER +typedef enum ns_timer_state_e { + NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt + NS_TIMER_HOLD, // Will run on a later HAL interrupt + NS_TIMER_RUN_INTERRUPT, // Running on the interrupt we're currently handling + NS_TIMER_STOP // Timer not scheduled ("start" not called since last callback) +} ns_timer_state_e; + +typedef struct ns_timer_struct { + int8_t ns_timer_id; + ns_timer_state_e timer_state; + uint16_t slots; + uint16_t remaining_slots; + void (*interrupt_handler)(int8_t, uint16_t); + ns_list_link_t link; +} ns_timer_struct; + +static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link); + +#define NS_TIMER_RUNNING 1 +static uint8_t ns_timer_state = 0; + +#ifdef ATMEGA256RFR2 +#define COMPENSATION 3 +#define COMPENSATION_TUNE 1 +#else +#define COMPENSATION 0 +#define COMPENSATION_TUNE 0 +#endif + +static void ns_timer_interrupt_handler(void); +static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id); +static bool ns_timer_initialized = 0; + +int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t)) +{ + int8_t retval = -1; + + if (!ns_timer_initialized) { + /*Set interrupt handler in HAL driver*/ + platform_timer_set_cb(ns_timer_interrupt_handler); + ns_timer_initialized = 1; + } + + /*Find first free timer ID in timer list*/ + /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ + for (uint8_t i = 0; i <= INT8_MAX; i++) { + if (!ns_timer_get_pointer_to_timer_struct(i)) { + retval = i; + break; + } + } + + if (retval == -1) { + return -1; + } + + ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct)); + if (!new_timer) { + return -1; + } + + /*Initialise new timer*/ + new_timer->ns_timer_id = retval; + new_timer->timer_state = NS_TIMER_STOP; + new_timer->remaining_slots = 0; + new_timer->interrupt_handler = timer_interrupt_handler; + + // Critical section sufficient as long as list can't be reordered from + // interrupt, otherwise will need to cover whole routine + platform_enter_critical(); + ns_list_add_to_end(&ns_timer_list, new_timer); + platform_exit_critical(); + + /*Return timer ID*/ + return retval; +} + +int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id) +{ + ns_timer_struct *current_timer; + + current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); + if (!current_timer) { + return -1; + } + + // Critical section sufficient as long as list can't be reordered from + // interrupt, otherwise will need to cover whole routine + platform_enter_critical(); + ns_list_remove(&ns_timer_list, current_timer); + platform_exit_critical(); + + ns_dyn_mem_free(current_timer); + return 0; +} + + +static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots) +{ + /*Don't start timer with 0 slots*/ + if (!pl_timer_start_slots) { + pl_timer_start_slots = 1; + } + + /*Start HAL timer*/ + platform_timer_start(pl_timer_start_slots); + /*Set HAL timer state to running*/ + ns_timer_state |= NS_TIMER_RUNNING; + return 0; +} + +int8_t ns_timer_sleep(void) +{ + int8_t ret_val = -1; + if (ns_timer_state & NS_TIMER_RUNNING) { + /*Start HAL timer*/ + platform_timer_disable(); + /*Set HAL timer state to running*/ + ns_timer_state &= ~NS_TIMER_RUNNING; + ret_val = 0; + } + return ret_val; +} + +static int8_t ns_timer_get_next_running_to(void) +{ + uint8_t hold_count = 0; + ns_timer_struct *first_timer = NULL; + + /*Find hold-labelled timer with the least remaining slots*/ + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + if (current_timer->timer_state == NS_TIMER_HOLD) { + if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) { + first_timer = current_timer; + } + /*For optimisation, count the found timers*/ + hold_count++; + } + } + + if (!first_timer) { + return 0; + } + + /*If hold-labelled timer found, set it active and start the HAL driver*/ + hold_count--; + first_timer->timer_state = NS_TIMER_ACTIVE; + /*Compensate time spent in timer function*/ + if (first_timer->remaining_slots > COMPENSATION) { + first_timer->remaining_slots -= COMPENSATION; + } + /*Start HAL timer*/ + ns_timer_start_pl_timer(first_timer->remaining_slots); + + /*Update other hold-labelled timers*/ + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + if (hold_count == 0) { // early termination optimisation + break; + } + if (current_timer->timer_state == NS_TIMER_HOLD) { + if (current_timer->remaining_slots == first_timer->remaining_slots) { + current_timer->timer_state = NS_TIMER_ACTIVE; + } else { + current_timer->remaining_slots -= first_timer->remaining_slots; + /*Compensate time spent in timer function*/ + if (current_timer->remaining_slots > COMPENSATION) { + current_timer->remaining_slots -= COMPENSATION; + } + } + hold_count--; + } + } + + return 0; +} + + +static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id) +{ + /*Find timer with the given ID*/ + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + if (current_timer->ns_timer_id == timer_id) { + return current_timer; + } + } + return NULL; +} + +int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots) +{ + int8_t ret_val = 0; + uint16_t pl_timer_remaining_slots; + ns_timer_struct *timer; + platform_enter_critical(); + + /*Find timer to be activated*/ + timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); + if (!timer) { + ret_val = -1; + goto exit; + } + + // XXX this assumes the timer currently isn't running? + // Is event.c relying on this restarting HAL timer after ns_timer_sleep()? + + /*If any timers are active*/ + if (ns_timer_state & NS_TIMER_RUNNING) { + /*Get remaining slots of the currently activated timeout*/ + pl_timer_remaining_slots = platform_timer_get_remaining_slots(); + + /*New timeout is shorter than currently enabled timeout*/ + if (pl_timer_remaining_slots > slots) { + /*Start HAL timer*/ + ns_timer_start_pl_timer(slots - 0); + + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + /*Switch active timers to hold*/ + if (current_timer->timer_state == NS_TIMER_ACTIVE) { + current_timer->timer_state = NS_TIMER_HOLD; + current_timer->remaining_slots = 0; + } + /*Update hold-labelled timers*/ + if (current_timer->timer_state == NS_TIMER_HOLD) { + current_timer->remaining_slots += (pl_timer_remaining_slots - slots); + /*Compensate time spent in timer function*/ + if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) { + current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE); + } + } + } + /*Mark active and start the timer*/ + timer->timer_state = NS_TIMER_ACTIVE; + timer->slots = slots; + timer->remaining_slots = slots; + } + + /*New timeout is longer than currently enabled timeout*/ + else if (pl_timer_remaining_slots < slots) { + /*Mark hold and update remaining slots*/ + timer->timer_state = NS_TIMER_HOLD; + timer->slots = slots; + timer->remaining_slots = (slots - pl_timer_remaining_slots); + } + /*New timeout is equal to currently enabled timeout*/ + else { + /*Mark it active and it will be handled in next interrupt*/ + timer->timer_state = NS_TIMER_ACTIVE; + timer->slots = slots; + timer->remaining_slots = slots; + } + } else { + /*No timers running*/ + timer->timer_state = NS_TIMER_HOLD; + timer->slots = slots; + timer->remaining_slots = slots; + /*Start next timeout*/ + ns_timer_get_next_running_to(); + } +exit: + platform_exit_critical(); + return ret_val; +} + +static void ns_timer_interrupt_handler(void) +{ + uint8_t i = 0; + + platform_enter_critical(); + /*Clear timer running state*/ + ns_timer_state &= ~NS_TIMER_RUNNING; + /*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/ + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + if (current_timer->timer_state == NS_TIMER_ACTIVE) { + current_timer->timer_state = NS_TIMER_RUN_INTERRUPT; + /*For optimisation, count the found timers*/ + i++; + } + } + + /*Start next timeout*/ + ns_timer_get_next_running_to(); + + /*Call interrupt functions*/ + ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) { + if (i == 0) { + break; + } + if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) { + current_timer->timer_state = NS_TIMER_STOP; + current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots); + i--; + } + } + + platform_exit_critical(); +} + +int8_t eventOS_callback_timer_stop(int8_t ns_timer_id) +{ + uint16_t pl_timer_remaining_slots; + bool active_timer_found = false; + ns_timer_struct *current_timer; + ns_timer_struct *first_timer = NULL; + int8_t retval = -1; + + platform_enter_critical(); + /*Find timer with given timer ID*/ + current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id); + if (!current_timer) { + goto exit; + } + + retval = 0; + + /*Check if already stopped*/ + if (current_timer->timer_state == NS_TIMER_STOP) { + goto exit; + } + + current_timer->timer_state = NS_TIMER_STOP; + current_timer->remaining_slots = 0; + + /*Check if some timer is already active*/ + ns_list_foreach(ns_timer_struct, curr_timer, &ns_timer_list) { + if (curr_timer->timer_state == NS_TIMER_ACTIVE) { + active_timer_found = true; + break; + } + } + /*If no active timers found, start one*/ + if (!active_timer_found) { + pl_timer_remaining_slots = platform_timer_get_remaining_slots(); + /*Find hold-labelled timer with the least remaining slots*/ + ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { + if (cur_timer->timer_state == NS_TIMER_HOLD) { + cur_timer->remaining_slots += pl_timer_remaining_slots; + + if (!first_timer || cur_timer->remaining_slots < first_timer->remaining_slots) { + first_timer = cur_timer; + } + } + } + /*If hold-labelled timer found, set it active and start the HAL driver*/ + if (first_timer) { + first_timer->timer_state = NS_TIMER_ACTIVE; + /*Start HAL timer*/ + ns_timer_start_pl_timer(first_timer->remaining_slots); + /*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/ + ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) { + if (cur_timer->timer_state == NS_TIMER_HOLD) { + if (cur_timer->remaining_slots == first_timer->remaining_slots) { + cur_timer->timer_state = NS_TIMER_ACTIVE; + } else { + cur_timer->remaining_slots -= first_timer->remaining_slots; + } + } + } + } + } + +exit: + platform_exit_critical(); + + return retval; +} +#endif // NS_EXCLUDE_HIGHRES_TIMER diff --git a/source/ns_timer.h b/source/ns_timer.h new file mode 100644 index 00000000000..eac2f9d48bd --- /dev/null +++ b/source/ns_timer.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015 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 NS_TIMER_H_ +#define NS_TIMER_H_ + +#include "platform/eventloop_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NS_EXCLUDE_HIGHRES_TIMER +extern int8_t ns_timer_sleep(void); +#else +#define ns_timer_sleep() ((int8_t) 0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*NS_TIMER_H_*/ diff --git a/source/system_timer.c b/source/system_timer.c new file mode 100644 index 00000000000..70d684b5908 --- /dev/null +++ b/source/system_timer.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2014-2015 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 "ns_types.h" +#include "ns_list.h" +#include "timer_sys.h" +#include "platform/arm_hal_interrupt.h" +#include "platform/arm_hal_timer.h" +#include "nsdynmemLIB.h" +#include "eventOS_event.h" +#include "eventOS_event_timer.h" +#include "event.h" +#include "eventOS_callback_timer.h" + +#include "ns_timer.h" + +#ifndef ST_MAX +#define ST_MAX 6 +#endif + +static sys_timer_struct_s startup_sys_timer_pool[ST_MAX]; + +#define TIMER_SLOTS_PER_MS 20 +NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Need whole number of ms per tick") +#define TIMER_SYS_TICK_PERIOD (1000 / EVENTOS_EVENT_TIMER_HZ) // milliseconds + +// timer_sys_ticks must be read in critical section to guarantee +// atomicity on 16-bit platforms +static volatile uint32_t timer_sys_ticks; + +static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, event.link); +static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, event.link); + + +static sys_timer_struct_s *sys_timer_dynamically_allocate(void); +static void timer_sys_interrupt(void); +static void timer_sys_add(sys_timer_struct_s *timer); + +#ifndef NS_EVENTLOOP_USE_TICK_TIMER +static int8_t platform_tick_timer_start(uint32_t period_ms); +/* Implement platform tick timer using eventOS timer */ +// platform tick timer callback function +static void (*tick_timer_callback)(void); +static int8_t tick_timer_id = -1; // eventOS timer id for tick timer + +// EventOS timer callback function +static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots) +{ + // Not interested in timer id or slots + (void)slots; + // Call the tick timer callback + if (tick_timer_callback != NULL && timer_id == tick_timer_id) { + platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); + tick_timer_callback(); + } +} + +static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void)) +{ + tick_timer_callback = tick_timer_cb; + tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback); + return tick_timer_id; +} + +static int8_t platform_tick_timer_start(uint32_t period_ms) +{ + return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms); +} + +static int8_t platform_tick_timer_stop(void) +{ + return eventOS_callback_timer_stop(tick_timer_id); +} +#endif // !NS_EVENTLOOP_USE_TICK_TIMER + +/* + * Initializes timers and starts system timer + */ +void timer_sys_init(void) +{ + for (uint8_t i = 0; i < ST_MAX; i++) { + ns_list_add_to_start(&system_timer_free, &startup_sys_timer_pool[i]); + } + + platform_tick_timer_register(timer_sys_interrupt); + platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); +} + + + +/*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/ +void timer_sys_disable(void) +{ + platform_tick_timer_stop(); +} + +/* + * Starts ticking system timer interrupts every 10ms + */ +int8_t timer_sys_wakeup(void) +{ + return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD); +} + + +static void timer_sys_interrupt(void) +{ + system_timer_tick_update(1); +} + + + +/* * * * * * * * * */ + +static sys_timer_struct_s *sys_timer_dynamically_allocate(void) +{ + return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s)); +} + +static sys_timer_struct_s *timer_struct_get(void) +{ + sys_timer_struct_s *timer; + platform_enter_critical(); + timer = ns_list_get_first(&system_timer_free); + if (timer) { + ns_list_remove(&system_timer_free, timer); + } else { + timer = sys_timer_dynamically_allocate(); + } + platform_exit_critical(); + return timer; +} + +void timer_sys_event_free(arm_event_storage_t *event) +{ + platform_enter_critical(); + sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); + if (timer->period == 0) { + // Non-periodic - return to free list + ns_list_add_to_start(&system_timer_free, timer); + } else { + // Periodic - check due time of next launch + timer->launch_time += timer->period; + if (TICKS_BEFORE_OR_AT(timer->launch_time, timer_sys_ticks)) { + // next event is overdue - queue event now + eventOS_event_send_timer_allocated(&timer->event); + } else { + // add back to timer queue for the future + timer_sys_add(timer); + } + } + platform_exit_critical(); +} + +void timer_sys_event_cancel_critical(struct arm_event_storage *event) +{ + sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event); + timer->period = 0; + // If its unqueued it is on my timer list, otherwise it is in event-loop. + if (event->state == ARM_LIB_EVENT_UNQUEUED) { + ns_list_remove(&system_timer_list, timer); + } +} + +uint32_t eventOS_event_timer_ticks(void) +{ + uint32_t ret_val; + // Enter/exit critical is a bit clunky, but necessary on 16-bit platforms, + // which won't be able to do an atomic 32-bit read. + platform_enter_critical(); + ret_val = timer_sys_ticks; + platform_exit_critical(); + return ret_val; +} + +/* Called internally with lock held */ +static void timer_sys_add(sys_timer_struct_s *timer) +{ + uint32_t at = timer->launch_time; + + // Find first timer scheduled to run after us, and insert before it. + // (This means timers scheduled for same time run in order of request) + ns_list_foreach(sys_timer_struct_s, t, &system_timer_list) { + if (TICKS_BEFORE(at, t->launch_time)) { + ns_list_add_before(&system_timer_list, t, timer); + return; + } + } + + // Didn't insert before another timer, so must be last. + ns_list_add_to_end(&system_timer_list, timer); +} + +/* Called internally with lock held */ +static arm_event_storage_t *eventOS_event_timer_request_at_(const arm_event_t *event, uint32_t at, uint32_t period) +{ + // Because we use user-allocated events, they must get delivered to avoid + // a leak. Previously this call queued timers for invalid tasks, then they + // would go undelivered. Now it returns an error. + if (!event_tasklet_handler_id_valid(event->receiver)) { + return NULL; + } + + sys_timer_struct_s *timer = timer_struct_get(); + if (!timer) { + return NULL; + } + + timer->event.data = *event; + timer->event.allocator = ARM_LIB_EVENT_TIMER; + timer->event.state = ARM_LIB_EVENT_UNQUEUED; + timer->launch_time = at; + timer->period = period; + + if (TICKS_BEFORE_OR_AT(at, timer_sys_ticks)) { + eventOS_event_send_timer_allocated(&timer->event); + } else { + timer_sys_add(timer); + } + + return &timer->event; +} + +arm_event_storage_t *eventOS_event_timer_request_at(const arm_event_t *event, uint32_t at) +{ + platform_enter_critical(); + + arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, at, 0); + + platform_exit_critical(); + + return ret; +} + +arm_event_storage_t *eventOS_event_timer_request_in(const arm_event_t *event, int32_t in) +{ + platform_enter_critical(); + + arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + in, 0); + + platform_exit_critical(); + + return ret; + +} + +arm_event_storage_t *eventOS_event_timer_request_every(const arm_event_t *event, int32_t period) +{ + if (period <= 0) { + return NULL; + } + + platform_enter_critical(); + + arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + period, period); + + platform_exit_critical(); + + return ret; + +} + +int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time) +{ + const arm_event_t event = { + .event_id = event_id, + .event_type = event_type, + .receiver = tasklet_id, + .sender = 0, + .data_ptr = NULL, + .event_data = 0, + .priority = ARM_LIB_MED_PRIORITY_EVENT, + }; + + // Legacy time behaviour preserved + + // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks. + // And why shouldn't they be able to get a 1-tick callback? + if (time > 2 * TIMER_SYS_TICK_PERIOD) { + time /= TIMER_SYS_TICK_PERIOD; + // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe? + time++; + } else { + time = 2; + } + + platform_enter_critical(); + arm_event_storage_t *ret = eventOS_event_timer_request_at_(&event, timer_sys_ticks + time, 0); + platform_exit_critical(); + return ret ? 0 : -1; +} + +int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id) +{ + platform_enter_critical(); + + /* First check pending timers */ + ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) { + if (cur->event.data.receiver == tasklet_id && cur->event.data.event_id == event_id) { + eventOS_cancel(&cur->event); + goto done; + } + } + + /* No pending timer, so check for already-pending event */ + arm_event_storage_t *event = eventOS_event_find_by_id_critical(tasklet_id, event_id); + if (event && event->allocator == ARM_LIB_EVENT_TIMER) { + eventOS_cancel(event); + goto done; + } + + /* No match found */ + platform_exit_critical(); + return -1; + +done: + platform_exit_critical(); + return 0; +} + +uint32_t eventOS_event_timer_shortest_active_timer(void) +{ + uint32_t ret_val = 0; + + platform_enter_critical(); + sys_timer_struct_s *first = ns_list_get_first(&system_timer_list); + if (first == NULL) { + // Weird API has 0 for "no events" + ret_val = 0; + } else if (TICKS_BEFORE_OR_AT(first->launch_time, timer_sys_ticks)) { + // Which means an immediate/overdue event has to be 1 + ret_val = 1; + } else { + ret_val = first->launch_time - timer_sys_ticks; + } + + platform_exit_critical(); + return eventOS_event_timer_ticks_to_ms(ret_val); +} + +void system_timer_tick_update(uint32_t ticks) +{ + platform_enter_critical(); + //Keep runtime time + timer_sys_ticks += ticks; + ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) { + if (TICKS_BEFORE_OR_AT(cur->launch_time, timer_sys_ticks)) { + // Unthread from our list + ns_list_remove(&system_timer_list, cur); + // Make it an event (can't fail - no allocation) + // event system will call our timer_sys_event_free on event delivery. + eventOS_event_send_timer_allocated(&cur->event); + } else { + // List is ordered, so as soon as we see a later event, we're done. + break; + } + } + + platform_exit_critical(); +} + diff --git a/source/timer_sys.h b/source/timer_sys.h new file mode 100644 index 00000000000..a29aec937af --- /dev/null +++ b/source/timer_sys.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014-2015 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 _PL_NANO_TIMER_SYS_H_ +#define _PL_NANO_TIMER_SYS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "eventOS_event.h" + +/* We borrow base event storage, including its list link, and add a time field */ +typedef struct sys_timer_struct_s { + arm_event_storage_t event; + uint32_t launch_time; // tick value + uint32_t period; +} sys_timer_struct_s; + + +/** + * Initialize system timer + * */ +extern void timer_sys_init(void); + +extern uint32_t timer_get_runtime_ticks(void); +int8_t timer_sys_wakeup(void); +void timer_sys_disable(void); +void timer_sys_event_free(struct arm_event_storage *event); + +// This require lock to be held +void timer_sys_event_cancel_critical(struct arm_event_storage *event); + +/** + * System Timer update and synch after sleep + * + * \param ticks Time in 10 ms resolution + * + * \return none + * + * */ +void system_timer_tick_update(uint32_t ticks); + +#ifdef __cplusplus +} +#endif + +#endif /*_PL_NANO_TIMER_SYS_H_*/ From 72fc5faab0351c9472c34a788525ac92b39c9132 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 9 Nov 2018 15:48:41 +0200 Subject: [PATCH 07/12] Remove mbed-client-randlib Remove mbed-client-randlib and add it later as git subtree --- .../frameworks/mbed-client-randlib/.gitignore | 1 - .../mbed-client-randlib/.mbedignore | 2 - .../frameworks/mbed-client-randlib/LICENSE | 2 - .../frameworks/mbed-client-randlib/Makefile | 5 - .../mbed-client-randlib/apache-2.0.txt | 56 -- .../platform/arm_hal_random.h | 37 -- .../mbed-client-randlib/randLIB.h | 149 ----- .../mbed-client-randlib/module.json | 13 - .../mbed-client-randlib/source/randLIB.c | 268 --------- .../mbed-client-randlib/unittest/Makefile | 23 - .../unittest/MakefileWorker.mk | 562 ------------------ .../unittest/makefile_defines.txt | 18 - .../unittest/randlib/Makefile | 18 - .../unittest/randlib/main.cpp | 15 - .../unittest/randlib/randlibtest.cpp | 56 -- .../unittest/randlib/test_randlib.c | 195 ------ .../unittest/randlib/test_randlib.h | 35 -- .../mbed-client-randlib/unittest/run_tests | 43 -- .../unittest/stubs/open_stub.c | 24 - .../unittest/stubs/random_stub.c | 27 - 20 files changed, 1549 deletions(-) delete mode 100644 features/frameworks/mbed-client-randlib/.gitignore delete mode 100644 features/frameworks/mbed-client-randlib/.mbedignore delete mode 100644 features/frameworks/mbed-client-randlib/LICENSE delete mode 100644 features/frameworks/mbed-client-randlib/Makefile delete mode 100644 features/frameworks/mbed-client-randlib/apache-2.0.txt delete mode 100644 features/frameworks/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h delete mode 100644 features/frameworks/mbed-client-randlib/mbed-client-randlib/randLIB.h delete mode 100644 features/frameworks/mbed-client-randlib/module.json delete mode 100644 features/frameworks/mbed-client-randlib/source/randLIB.c delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/Makefile delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/Makefile delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h delete mode 100755 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c delete mode 100644 features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c diff --git a/features/frameworks/mbed-client-randlib/.gitignore b/features/frameworks/mbed-client-randlib/.gitignore deleted file mode 100644 index 77320b339fe..00000000000 --- a/features/frameworks/mbed-client-randlib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -output/* diff --git a/features/frameworks/mbed-client-randlib/.mbedignore b/features/frameworks/mbed-client-randlib/.mbedignore deleted file mode 100644 index ba4eb1b31de..00000000000 --- a/features/frameworks/mbed-client-randlib/.mbedignore +++ /dev/null @@ -1,2 +0,0 @@ -linux/* -test/* diff --git a/features/frameworks/mbed-client-randlib/LICENSE b/features/frameworks/mbed-client-randlib/LICENSE deleted file mode 100644 index 97df0e645d3..00000000000 --- a/features/frameworks/mbed-client-randlib/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/features/frameworks/mbed-client-randlib/Makefile b/features/frameworks/mbed-client-randlib/Makefile deleted file mode 100644 index 9a40f3cd68a..00000000000 --- a/features/frameworks/mbed-client-randlib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -SRCS := $(wildcard source/*) -LIB := librand.a -EXPORT_HEADERS := mbed-client-randlib - -include ../exported_rules.mk diff --git a/features/frameworks/mbed-client-randlib/apache-2.0.txt b/features/frameworks/mbed-client-randlib/apache-2.0.txt deleted file mode 100644 index 0e4cf3ee999..00000000000 --- a/features/frameworks/mbed-client-randlib/apache-2.0.txt +++ /dev/null @@ -1,56 +0,0 @@ - - -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. - -END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/features/frameworks/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h b/features/frameworks/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h deleted file mode 100644 index 337486dedd6..00000000000 --- a/features/frameworks/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 ARM_HAL_RANDOM_H_ -#define ARM_HAL_RANDOM_H_ -#ifdef __cplusplus -extern "C" { -#endif -/** - * \brief This function performs Random number driver init. - */ -extern void arm_random_module_init(void); -/** - * \brief Get random library seed value. - * - * This function should return as random a value as possible, using - * hardware sources. Repeated calls should return different values if - * at all possible. - */ -extern uint32_t arm_random_seed_get(void); -#ifdef __cplusplus -} -#endif -#endif /* ARM_HAL_RANDOM_H_ */ diff --git a/features/frameworks/mbed-client-randlib/mbed-client-randlib/randLIB.h b/features/frameworks/mbed-client-randlib/mbed-client-randlib/randLIB.h deleted file mode 100644 index a58af013c80..00000000000 --- a/features/frameworks/mbed-client-randlib/mbed-client-randlib/randLIB.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2014-2015 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. - */ - -/** - * \file randLIB.h - * \brief Pseudo Random Library API: - * - * - * \section net-boot Network Bootstrap Control API: - * - randLIB_seed_random(), Set seed for pseudo random - * - randLIB_get_8bit(), Generate 8-bit random number - * - randLIB_get_16bit(),Generate 16-bit random number - * - randLIB_get_32bit(),Generate 32-bit random number - * - randLIB_get_n_bytes_random(), Generate n-bytes random numbers - * - */ - -#ifndef RANDLIB_H_ -#define RANDLIB_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * This library is made for getting random numbers for Timing needs in protocols. - * - * **not safe to use for security or cryptographic operations.** - * - */ - - -/** - * \brief Init seed for Pseudo Random. - * - * Makes call(s) to the platform's arm_random_seed_get() to seed the - * pseudo-random generator. - * - * \return None - * - */ -extern void randLIB_seed_random(void); - -/** - * \brief Update seed for pseudo-random generator - * - * Adds seed information to existing generator, to perturb the - * sequence. - * \param seed 64 bits of data to add to the seed. - */ -extern void randLIB_add_seed(uint64_t seed); - -/** - * \brief Generate 8-bit random number. - * - * \param None - * \return 8-bit random number - * - */ -extern uint8_t randLIB_get_8bit(void); - -/** - * \brief Generate 16-bit random number. - * - * \param None - * \return 16-bit random number - * - */ -extern uint16_t randLIB_get_16bit(void); - -/** - * \brief Generate 32-bit random number. - * - * \param None - * \return 32-bit random number - * - */ -extern uint32_t randLIB_get_32bit(void); - -/** - * \brief Generate 64-bit random number. - * - * \param None - * \return 64-bit random number - * - */ -extern uint64_t randLIB_get_64bit(void); - -/** - * \brief Generate n-bytes random numbers. - * - * \param data_ptr pointer where random will be stored - * \param count how many bytes need random - * - * \return data_ptr - */ -extern void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count); - -/** - * \brief Generate a random number within a range. - * - * The result is linearly distributed in the range [min..max], inclusive. - * - * \param min minimum value that can be generated - * \param max maximum value that can be generated - */ -uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max); - -/** - * \brief Randomise a base 32-bit number by a jitter factor - * - * The result is linearly distributed in the jitter range, which is expressed - * as fixed-point unsigned 1.15 values. For example, to produce a number in the - * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to - * 0xA000. - * - * Result is clamped to 0xFFFFFFFF if it overflows. - * - * \param base The base 32-bit value - * \param min_factor The minimum value for the random factor - * \param max_factor The maximum value for the random factor - */ -uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor); - -#ifdef RANDLIB_PRNG -/* \internal Reset the PRNG state to zero (invalid) */ -void randLIB_reset(void); -#endif - - -#ifdef __cplusplus -} -#endif -#endif /* RANDLIB_H_ */ diff --git a/features/frameworks/mbed-client-randlib/module.json b/features/frameworks/mbed-client-randlib/module.json deleted file mode 100644 index 863baaa504a..00000000000 --- a/features/frameworks/mbed-client-randlib/module.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "nanostack-randlib", - "version": "1.2.0", - "description": "Pseudo random library used by mbed-client and 6LoWPAN stack.", - "keywords": [], - "homepage": "https://github.com/ARMmbed/mbed-client-randlib", - "license": "Apache-2.0", - "extraIncludes": [ - "mbed-client-randlib" - ], - "dependencies": {}, - "targetDependencies": {} -} diff --git a/features/frameworks/mbed-client-randlib/source/randLIB.c b/features/frameworks/mbed-client-randlib/source/randLIB.c deleted file mode 100644 index b75d7edae8d..00000000000 --- a/features/frameworks/mbed-client-randlib/source/randLIB.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2014-2015 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 -#include -#include "randLIB.h" -#include "platform/arm_hal_random.h" - -/** - * This library is made for getting random numbers for timing needs in - * protocols, plus to generate dynamic ports, random IDs etc. - * - * **not safe to use for security or cryptographic operations.** - * - * Base implementation is a pseudo-RNG, but may also use a system RNG. - * Replay of sequence by reseeding is not possible. - * - * Base pseudo-RNG is the xoroshiro128+ generator by Marsaglia, Blackman and - * Vigna: - * - * http://xoroshiro.di.unimi.it/ - * - * Certainly not the fastest for 32-bit or smaller platforms, but speed - * is not critical. None of the long operations in the core are actually hard, - * unlike the divisions and multiplies in the utility functions below, where we - * do try to keep the operations narrow. - */ - -/* On some platforms, read from a system RNG, rather than use our own */ -/* RANDLIB_PRNG disables this and forces use of the PRNG (useful for test only?) */ -#ifndef RANDLIB_PRNG -#ifdef __linux -#define RANDOM_DEVICE "/dev/urandom" -#endif -#endif // RANDLIB_PRNG - -/* RAM usage - 16 bytes of state (or a FILE * pointer and underlying FILE, which - * will include a buffer) */ -#ifdef RANDOM_DEVICE -#include -static FILE *random_file; -#else -static uint64_t state[2]; -#endif - -#ifdef RANDLIB_PRNG -void randLIB_reset(void) -{ - state[0] = 0; - state[1] = 0; -} -#endif - -#ifndef RANDOM_DEVICE -static inline uint64_t rol(uint64_t n, int bits) -{ - return (n << bits) | (n >> (64 - bits)); -} - -/* Lower-quality generator used only for initial seeding, if platform - * isn't returning multiple seeds itself. Multiplies are rather heavy - * for lower-end platforms, but this is initialisation only. - */ -static uint64_t splitmix64(uint64_t *seed) -{ - uint64_t z = (*seed += UINT64_C(0x9E3779B97F4A7C15)); - z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); - z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); - return z ^ (z >> 31); -} -#endif // RANDOM_DEVICE - -void randLIB_seed_random(void) -{ -#ifdef RANDOM_DEVICE - if (!random_file) { - random_file = fopen(RANDOM_DEVICE, "rb"); - } -#else - arm_random_module_init(); - - /* We exclusive-OR with the current state, in case they make this call - * multiple times,or in case someone has called randLIB_add_seed before - * this. We don't want to potentially lose entropy. - */ - - /* Spell out expressions so we get known ordering of 4 seed calls */ - uint64_t s = (uint64_t) arm_random_seed_get() << 32; - state[0] ^= ( s | arm_random_seed_get()); - - s = (uint64_t) arm_random_seed_get() << 32; - state[1] ^= s | arm_random_seed_get(); - - /* This check serves to both to stir the state if the platform is returning - * constant seeding values, and to avoid the illegal all-zero state. - */ - if (state[0] == state[1]) { - randLIB_add_seed(state[0]); - } -#endif // RANDOM_DEVICE -} - -void randLIB_add_seed(uint64_t seed) -{ -#ifndef RANDOM_DEVICE - state[0] ^= splitmix64(&seed); - state[1] ^= splitmix64(&seed); - /* This is absolutely necessary, but I challenge you to add it to line coverage */ - if (state[1] == 0 && state[0] == 0) { - state[0] = 1; - } -#else - (void)seed; -#endif -} - -uint8_t randLIB_get_8bit(void) -{ - uint64_t r = randLIB_get_64bit(); - return (uint8_t) (r >> 56); -} - -uint16_t randLIB_get_16bit(void) -{ - uint64_t r = randLIB_get_64bit(); - return (uint16_t) (r >> 48); -} - -uint32_t randLIB_get_32bit(void) -{ - uint64_t r = randLIB_get_64bit(); - return (uint32_t) (r >> 32); -} - - -uint64_t randLIB_get_64bit(void) -{ -#ifdef RANDOM_DEVICE - if (!random_file) { - return 0; - } - uint64_t result; - if (fread(&result, sizeof result, 1, random_file) != 1) { - result = 0; - } - return result; -#else - const uint64_t s0 = state[0]; - uint64_t s1 = state[1]; - const uint64_t result = s0 + s1; - - s1 ^= s0; - state[0] = rol(s0, 55) ^ s1 ^ (s1 << 14); - state[1] = rol(s1, 36); - - return result; -#endif -} - -void *randLIB_get_n_bytes_random(void *ptr, uint8_t count) -{ - uint8_t *data_ptr = ptr; - uint64_t r = 0; - for (uint_fast8_t i = 0; i < count; i++) { - /* Take 8 bytes at a time */ - if (i % 8 == 0) { - r = randLIB_get_64bit(); - } else { - r >>= 8; - } - data_ptr[i] = (uint8_t) r; - } - return data_ptr; -} - -uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) -{ - /* This special case is potentially common, particularly in this routine's - * first user (Trickle), so worth catching immediately */ - if (min == max) { - return min; - } - -#if UINT_MAX >= 0xFFFFFFFF - const unsigned int rand_max = 0xFFFFFFFFu; // will use rand32 -#else - const unsigned int rand_max = 0xFFFFu; // will use rand16 - - /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ - if (max - min == 0xFFFF) { - return randLIB_get_16bit(); - } -#endif - - /* We get rand_max values from rand16 or 32() in the range [0..rand_max-1], and - * need to divvy them up into the number of values we need. And reroll any - * odd values off the end as we insist every value having equal chance. - * - * Using the range [0..rand_max-1] saves long division on the band - * calculation - it means rand_max ends up always being rerolled. - * - * Eg, range(1,2), rand_max = 0xFFFF: - * We have 2 bands of size 0x7FFF (0xFFFF/2). - * - * We roll: 0x0000..0x7FFE -> 1 - * 0x7FFF..0xFFFD -> 2 - * 0xFFFE..0xFFFF -> reroll - * (calculating band size as 0x10000/2 would have avoided the reroll cases) - * - * Eg, range(1,3), rand_max = 0xFFFFFFFF: - * We have 3 bands of size 0x55555555 (0xFFFFFFFF/3). - * - * We roll: 0x00000000..0x555555554 -> 1 - * 0x55555555..0xAAAAAAAA9 -> 2 - * 0xAAAAAAAA..0xFFFFFFFFE -> 3 - * 0xFFFFFFFF -> reroll - * - * (Bias problem clearly pretty insignificant there, but gets worse as - * range increases). - */ - const unsigned int values_needed = max + 1 - min; - /* Avoid the need for long division, at the expense of fractionally - * increasing reroll chance. */ - const unsigned int band_size = rand_max / values_needed; - const unsigned int top_of_bands = band_size * values_needed; - unsigned int result; - do { -#if UINT_MAX > 0xFFFF - result = randLIB_get_32bit(); -#else - result = randLIB_get_16bit(); -#endif - } while (result >= top_of_bands); - - return min + (uint16_t)(result / band_size); -} - -uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) -{ - uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); - - /* 32x16-bit long multiplication, to get 48-bit result */ - uint32_t hi = (base >> 16) * random_factor; - uint32_t lo = (base & 0xFFFF) * random_factor; - /* Add halves, and take top 32 bits of 48-bit result */ - uint32_t res = hi + (lo >> 16); - - /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ - if (res & 0x80000000) { - res = 0xFFFFFFFF; - } else { - res = (res << 1) | ((lo >> 15) & 1); - } - - return res; -} diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/Makefile b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/Makefile deleted file mode 100644 index b353517548f..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -#scan for folders having "Makefile" in them and remove 'this' to prevent loop -ifeq ($(OS),Windows_NT) -all: -clean: -else -DIRS := $(filter-out ./, $(sort $(dir $(shell find . -name 'Makefile')))) - -all: - for dir in $(DIRS); do \ - cd $$dir; make gcov; cd ..;\ - done - -clean: - for dir in $(DIRS); do \ - cd $$dir; make clean; cd ..;\ - done - rm -rf ../source/*gcov ../source/*gcda ../source/*o - rm -rf stubs/*gcov stubs/*gcda stubs/*o - rm -rf results/* - rm -rf coverages/* - rm -rf results - rm -rf coverages -endif diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk deleted file mode 100644 index 2096ced0367..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/MakefileWorker.mk +++ /dev/null @@ -1,562 +0,0 @@ -#--------- -# -# MakefileWorker.mk -# -# Include this helper file in your makefile -# It makes -# A static library -# A test executable -# -# See this example for parameter settings -# examples/Makefile -# -#---------- -# Inputs - these variables describe what to build -# -# INCLUDE_DIRS - Directories used to search for include files. -# This generates a -I for each directory -# SRC_DIRS - Directories containing source file to built into the library -# SRC_FILES - Specific source files to build into library. Helpful when not all code -# in a directory can be built for test (hopefully a temporary situation) -# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# TEST_SRC_FILES - Specific source files to build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner -# These do not go in a library. They are explicitly included in the test runner -#---------- -# You can adjust these variables to influence how to build the test target -# and where to put and name outputs -# See below to determine defaults -# COMPONENT_NAME - the name of the thing being built -# TEST_TARGET - name the test executable. By default it is -# $(COMPONENT_NAME)_tests -# Helpful if you want 1 > make files in the same directory with different -# executables as output. -# CPPUTEST_HOME - where CppUTest home dir found -# TARGET_PLATFORM - Influences how the outputs are generated by modifying the -# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the -# normal objs and lib directories. Also modifies where to search for the -# CPPUTEST_LIB to link against. -# CPPUTEST_OBJS_DIR - a directory where o and d files go -# CPPUTEST_LIB_DIR - a directory where libs go -# CPPUTEST_ENABLE_DEBUG - build for debug -# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete -# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out -# of the test harness -# CPPUTEST_USE_GCOV - Turn on coverage analysis -# Clean then build with this flag set to Y, then 'make gcov' -# CPPUTEST_MAPFILE - generate a map file -# CPPUTEST_WARNINGFLAGS - overly picky by default -# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make -# other targets. Like CSlim, which is part of fitnesse -# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user -# specification of source files and directories that aren't below -# the user's Makefile in the directory tree, like: -# SRC_DIRS += ../../lib/foo -# It defaults to N, and shouldn't be necessary except in the above case. -#---------- -# -# Other flags users can initialize to sneak in their settings -# CPPUTEST_CXXFLAGS - flags for the C++ compiler -# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor -# CPPUTEST_CFLAGS - flags for the C complier -# CPPUTEST_LDFLAGS - Linker flags -#---------- - -# Some behavior is weird on some platforms. Need to discover the platform. - -# Platforms -UNAME_OUTPUT = "$(shell uname -a)" -MACOSX_STR = Darwin -MINGW_STR = MINGW -CYGWIN_STR = CYGWIN -LINUX_STR = Linux -SUNOS_STR = SunOS -UNKNWOWN_OS_STR = Unknown - -# Compilers -CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" -CLANG_STR = clang -SUNSTUDIO_CXX_STR = SunStudio - -UNAME_OS = $(UNKNWOWN_OS_STR) - -ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) - UNAME_OS = $(MINGW_STR) -endif - -ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) - UNAME_OS = $(CYGWIN_STR) -endif - -ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) - UNAME_OS = $(LINUX_STR) -endif - -ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) - UNAME_OS = $(MACOSX_STR) -#lion has a problem with the 'v' part of -a - UNAME_OUTPUT = "$(shell uname -pmnrs)" -endif - -ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) - UNAME_OS = $(SUNOS_STR) - - SUNSTUDIO_CXX_ERR_STR = CC -flags -ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) - CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" - COMPILER_NAME = $(SUNSTUDIO_CXX_STR) -endif -endif - -ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) - COMPILER_NAME = $(CLANG_STR) -endif - -#Kludge for mingw, it does not have cc.exe, but gcc.exe will do -ifeq ($(UNAME_OS),$(MINGW_STR)) - CC := gcc -endif - -#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the -# Standard C++ library as a shared library. Unbelievable. -ifeq ($(UNAME_OS),$(MINGW_STR)) - CPPUTEST_LDFLAGS += -static -endif -ifeq ($(UNAME_OS),$(CYGWIN_STR)) - CPPUTEST_LDFLAGS += -static -endif - - -#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic -ifeq ($(UNAME_OS),$(MACOSX_STR)) -ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) - CPPUTEST_PEDANTIC_ERRORS = N -endif -endif - -ifndef COMPONENT_NAME - COMPONENT_NAME = name_this_in_the_makefile -endif - -# Debug on by default -ifndef CPPUTEST_ENABLE_DEBUG - CPPUTEST_ENABLE_DEBUG = Y -endif - -# new and delete for memory leak detection on by default -ifndef CPPUTEST_USE_MEM_LEAK_DETECTION - CPPUTEST_USE_MEM_LEAK_DETECTION = Y -endif - -# Use the standard C library -ifndef CPPUTEST_USE_STD_C_LIB - CPPUTEST_USE_STD_C_LIB = Y -endif - -# Use the standard C++ library -ifndef CPPUTEST_USE_STD_CPP_LIB - CPPUTEST_USE_STD_CPP_LIB = Y -endif - -# Use gcov, off by default -ifndef CPPUTEST_USE_GCOV - CPPUTEST_USE_GCOV = N -endif - -ifndef CPPUTEST_PEDANTIC_ERRORS - CPPUTEST_PEDANTIC_ERRORS = Y -endif - -# Default warnings -ifndef CPPUTEST_WARNINGFLAGS - CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion -ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) -# CPPUTEST_WARNINGFLAGS += -pedantic-errors - CPPUTEST_WARNINGFLAGS += -pedantic -endif -ifeq ($(UNAME_OS),$(LINUX_STR)) - CPPUTEST_WARNINGFLAGS += -Wsign-conversion -endif - CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual - CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes -endif - -#Wonderful extra compiler warnings with clang -ifeq ($(COMPILER_NAME),$(CLANG_STR)) -# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. -# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) -# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor -# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. - CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables - CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded -endif - -# Uhm. Maybe put some warning flags for SunStudio here? -ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) - CPPUTEST_CXX_WARNINGFLAGS = - CPPUTEST_C_WARNINGFLAGS = -endif - -# Default dir for temporary files (d, o) -ifndef CPPUTEST_OBJS_DIR -ifndef TARGET_PLATFORM - CPPUTEST_OBJS_DIR = objs -else - CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) -endif -endif - -# Default dir for the outout library -ifndef CPPUTEST_LIB_DIR -ifndef TARGET_PLATFORM - CPPUTEST_LIB_DIR = lib -else - CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) -endif -endif - -# No map by default -ifndef CPPUTEST_MAP_FILE - CPPUTEST_MAP_FILE = N -endif - -# No extentions is default -ifndef CPPUTEST_USE_EXTENSIONS - CPPUTEST_USE_EXTENSIONS = N -endif - -# No VPATH is default -ifndef CPPUTEST_USE_VPATH - CPPUTEST_USE_VPATH := N -endif -# Make empty, instead of 'N', for usage in $(if ) conditionals -ifneq ($(CPPUTEST_USE_VPATH), Y) - CPPUTEST_USE_VPATH := -endif - -ifndef TARGET_PLATFORM -#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib -CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu -else -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) -endif - -# -------------------------------------- -# derived flags in the following area -# -------------------------------------- - -# Without the C library, we'll need to disable the C++ library and ... -ifeq ($(CPPUTEST_USE_STD_C_LIB), N) - CPPUTEST_USE_STD_CPP_LIB = N - CPPUTEST_USE_MEM_LEAK_DETECTION = N - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED - CPPUTEST_CPPFLAGS += -nostdinc -endif - -CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION - -ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED -else - ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h - endif - ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h - endif -endif - -ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) - CPPUTEST_CXXFLAGS += -g - CPPUTEST_CFLAGS += -g - CPPUTEST_LDFLAGS += -g -endif - -ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED -ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) - CPPUTEST_CXXFLAGS += -nostdinc++ -endif -endif - -ifdef $(GMOCK_HOME) - GTEST_HOME = $(GMOCK_HOME)/gtest - CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include - GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a - LD_LIBRARIES += $(GMOCK_LIBRARY) - CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS - CPPUTEST_WARNINGFLAGS = - CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) - GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a - LD_LIBRARIES += $(GTEST_LIBRARY) -endif - - -ifeq ($(CPPUTEST_USE_GCOV), Y) - CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage - CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage -endif - -CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) -CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) -CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) -CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) -CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) - -TARGET_MAP = $(COMPONENT_NAME).map.txt -ifeq ($(CPPUTEST_MAP_FILE), Y) - CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) -endif - -# Link with CppUTest lib -CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a - -ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) -CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a -endif - -ifdef CPPUTEST_STATIC_REALTIME - LD_LIBRARIES += -lrt -endif - -TARGET_LIB = \ - $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a - -ifndef TEST_TARGET - ifndef TARGET_PLATFORM - TEST_TARGET = $(COMPONENT_NAME)_tests - else - TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests - endif -endif - -#Helper Functions -get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) -get_dirs_from_dirspec = $(wildcard $1) -get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) -__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) -src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) -src_to_o = $(call src_to,.o,$1) -src_to_d = $(call src_to,.d,$1) -src_to_gcda = $(call src_to,.gcda,$1) -src_to_gcno = $(call src_to,.gcno,$1) -time = $(shell date +%s) -delta_t = $(eval minus, $1, $2) -debug_print_list = $(foreach word,$1,echo " $(word)";) echo; - -#Derived -STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) - -SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) -OBJ = $(call src_to_o,$(SRC)) - -STUFF_TO_CLEAN += $(OBJ) - -TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) -TEST_OBJS = $(call src_to_o,$(TEST_SRC)) -STUFF_TO_CLEAN += $(TEST_OBJS) - - -MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) -MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) -STUFF_TO_CLEAN += $(MOCKS_OBJS) - -ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) - -# If we're using VPATH -ifeq ($(CPPUTEST_USE_VPATH), Y) -# gather all the source directories and add them - VPATH += $(sort $(dir $(ALL_SRC))) -# Add the component name to the objs dir path, to differentiate between same-name objects - CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) -endif - -#Test coverage with gcov -GCOV_OUTPUT = gcov_output.txt -GCOV_REPORT = gcov_report.txt -GCOV_ERROR = gcov_error.txt -GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) -GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) -TEST_OUTPUT = $(TEST_TARGET).txt -STUFF_TO_CLEAN += \ - $(GCOV_OUTPUT)\ - $(GCOV_REPORT)\ - $(GCOV_REPORT).html\ - $(GCOV_ERROR)\ - $(GCOV_GCDA_FILES)\ - $(GCOV_GCNO_FILES)\ - $(TEST_OUTPUT) - -#The gcda files for gcov need to be deleted before each run -#To avoid annoying messages. -GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) -RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit - -ifeq ($(CPPUTEST_USE_GCOV), Y) - - ifeq ($(COMPILER_NAME),$(CLANG_STR)) - LD_LIBRARIES += --coverage - else - LD_LIBRARIES += -lgcov - endif -endif - - -INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) -INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) -MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) -INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) - -CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) - -DEP_FILES = $(call src_to_d, $(ALL_SRC)) -STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) -STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output - -# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags -CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) -CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) -CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) -LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) - -# Don't consider creating the archive a warning condition that does STDERR output -ARFLAGS := $(ARFLAGS)c - -DEP_FLAGS=-MMD -MP - -# Some macros for programs to be overridden. For some reason, these are not in Make defaults -RANLIB = ranlib - -# Targets - -.PHONY: all -all: start $(TEST_TARGET) - $(RUN_TEST_TARGET) - -.PHONY: start -start: $(TEST_TARGET) - $(SILENCE)START_TIME=$(call time) - -.PHONY: all_no_tests -all_no_tests: $(TEST_TARGET) - -.PHONY: flags -flags: - @echo - @echo "OS ${UNAME_OS}" - @echo "Compile C and C++ source with CPPFLAGS:" - @$(call debug_print_list,$(CPPFLAGS)) - @echo "Compile C++ source with CXXFLAGS:" - @$(call debug_print_list,$(CXXFLAGS)) - @echo "Compile C source with CFLAGS:" - @$(call debug_print_list,$(CFLAGS)) - @echo "Link with LDFLAGS:" - @$(call debug_print_list,$(LDFLAGS)) - @echo "Link with LD_LIBRARIES:" - @$(call debug_print_list,$(LD_LIBRARIES)) - @echo "Create libraries with ARFLAGS:" - @$(call debug_print_list,$(ARFLAGS)) - -TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) -test-deps: $(TEST_DEPS) - -$(TEST_TARGET): $(TEST_DEPS) - @echo Linking $@ - $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) - -$(TARGET_LIB): $(OBJ) - @echo Building archive $@ - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(AR) $(ARFLAGS) $@ $^ - $(SILENCE)$(RANLIB) $@ - -test: $(TEST_TARGET) - $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) - -vtest: $(TEST_TARGET) - $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) - -$(CPPUTEST_OBJS_DIR)/%.o: %.cc - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.cpp - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.c - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -ifneq "$(MAKECMDGOALS)" "clean" --include $(DEP_FILES) -endif - -.PHONY: clean -clean: - @echo Making clean - $(SILENCE)$(RM) $(STUFF_TO_CLEAN) - $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) - $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) - $(SILENCE)find . -name "*.gcno" | xargs rm -f - $(SILENCE)find . -name "*.gcda" | xargs rm -f - -#realclean gets rid of all gcov, o and d files in the directory tree -#not just the ones made by this makefile -.PHONY: realclean -realclean: clean - $(SILENCE)rm -rf gcov - $(SILENCE)find . -name "*.gdcno" | xargs rm -f - $(SILENCE)find . -name "*.[do]" | xargs rm -f - -gcov: test -ifeq ($(CPPUTEST_USE_VPATH), Y) - $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) -else - $(SILENCE)for d in $(SRC_DIRS) ; do \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done - $(SILENCE)for f in $(SRC_FILES) ; do \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done -endif -# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) - /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) - $(SILENCE)cat $(GCOV_REPORT) - $(SILENCE)mkdir -p gcov - $(SILENCE)mv *.gcov gcov - $(SILENCE)mv gcov_* gcov - @echo "See gcov directory for details" - -.PHONEY: format -format: - $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) - -.PHONEY: debug -debug: - @echo - @echo "Target Source files:" - @$(call debug_print_list,$(SRC)) - @echo "Target Object files:" - @$(call debug_print_list,$(OBJ)) - @echo "Test Source files:" - @$(call debug_print_list,$(TEST_SRC)) - @echo "Test Object files:" - @$(call debug_print_list,$(TEST_OBJS)) - @echo "Mock Source files:" - @$(call debug_print_list,$(MOCKS_SRC)) - @echo "Mock Object files:" - @$(call debug_print_list,$(MOCKS_OBJS)) - @echo "All Input Dependency files:" - @$(call debug_print_list,$(DEP_FILES)) - @echo Stuff to clean: - @$(call debug_print_list,$(STUFF_TO_CLEAN)) - @echo Includes: - @$(call debug_print_list,$(INCLUDES)) - --include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt deleted file mode 100644 index 18691ee5431..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/makefile_defines.txt +++ /dev/null @@ -1,18 +0,0 @@ -#--- Inputs ----# -CPPUTEST_HOME = /usr -CPPUTEST_USE_EXTENSIONS = Y -CPPUTEST_USE_VPATH = Y -CPPUTEST_USE_GCOV = Y -CPP_PLATFORM = gcc -INCLUDE_DIRS =\ - .\ - ../common\ - ../stubs\ - ../../../..\ - ../../../../source\ - ../../../../mbed-client-randlib\ - /usr/include\ - $(CPPUTEST_HOME)/include\ - -CPPUTESTFLAGS = -D__thumb2__ -w -CPPUTEST_CFLAGS += -std=gnu99 diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/Makefile b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/Makefile deleted file mode 100644 index 12d97840f62..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -include ../makefile_defines.txt - -COMPONENT_NAME = randLIB_unit - -#This must be changed manually -SRC_FILES = \ - ../../../../source/randLIB.c - -TEST_SRC_FILES = \ - main.cpp \ - randlibtest.cpp \ - test_randlib.c \ - ../stubs/random_stub.c \ - -include ../MakefileWorker.mk - -CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -DRANDLIB_PRNG - diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp deleted file mode 100644 index d76b2f9173a..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2015 ARM. All rights reserved. - */ - -#include "CppUTest/CommandLineTestRunner.h" -#include "CppUTest/TestPlugin.h" -#include "CppUTest/TestRegistry.h" -#include "CppUTestExt/MockSupportPlugin.h" -int main(int ac, char** av) -{ - return CommandLineTestRunner::RunAllTests(ac, av); -} - -IMPORT_TEST_GROUP(randLIB); - diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp deleted file mode 100644 index 67b3cb59a01..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 ARM. All rights reserved. - */ -#include "CppUTest/TestHarness.h" -#include "test_randlib.h" - -TEST_GROUP(randLIB) -{ - void setup() - { - } - - void teardown() - { - } -}; - -TEST(randLIB, test_randLIB_seed_random) -{ - CHECK(test_randLIB_seed_random()); -} - -TEST(randLIB, test_randLIB_get_8bit) -{ - CHECK(test_randLIB_get_8bit()); -} - -TEST(randLIB, test_randLIB_get_16bit) -{ - CHECK(test_randLIB_get_16bit()); -} - -TEST(randLIB, test_randLIB_get_32bit) -{ - CHECK(test_randLIB_get_32bit()); -} - -TEST(randLIB, test_randLIB_get_64bit) -{ - CHECK(test_randLIB_get_64bit()); -} - -TEST(randLIB, test_randLIB_get_n_bytes_random) -{ - CHECK(test_randLIB_get_n_bytes_random()); -} - -TEST(randLIB, test_randLIB_get_random_in_range) -{ - CHECK(test_randLIB_get_random_in_range()); -} - -TEST(randLIB, test_randLIB_randomise_base) -{ - CHECK(test_randLIB_randomise_base()); -} diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c deleted file mode 100644 index d918d591083..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2016 ARM. All rights reserved. - */ -#include "test_randlib.h" -#include -#include -#include "randLIB.h" - -bool test_randLIB_seed_random() -{ - randLIB_reset(); - randLIB_seed_random(); - return true; -} - -bool test_randLIB_get_8bit() -{ - randLIB_reset(); - randLIB_seed_random(); - uint8_t test = randLIB_get_8bit(); - if( test == 0 ) { - test = randLIB_get_8bit(); - if( test == 0 ) { - return false; - } - } - return true; -} - -bool test_randLIB_get_16bit() -{ - randLIB_reset(); - randLIB_seed_random(); - uint16_t test = randLIB_get_16bit(); - if( test == 0 ) { - test = randLIB_get_16bit(); - if( test == 0 ) { - return false; - } - } - return true; -} - -bool test_randLIB_get_32bit() -{ - randLIB_reset(); - randLIB_seed_random(); - uint32_t test = randLIB_get_32bit(); - if( test == 0 ) { - test = randLIB_get_32bit(); - if( test == 0 ) { - return false; - } - } - return true; -} - -static bool test_output(uint32_t seed, bool seed_inc, const uint64_t expected[8]) -{ - random_stub_set_seed(seed, seed_inc); - randLIB_reset(); - randLIB_seed_random(); - for (int i = 0; i < 8; i++) { - if (randLIB_get_64bit() != expected[i]) { - return false; - } - } - - return true; -} - -bool test_randLIB_get_64bit() -{ - /* Initial 8 xoroshiro128+ values with initial seed of - * (0x0000000100000002, 0x00000003000000004). - */ - static const uint64_t expected1234[] = { - UINT64_C(0x0000000400000006), - UINT64_C(0x0100806200818026), - UINT64_C(0x2a30826271904706), - UINT64_C(0x918d7ea50109290d), - UINT64_C(0x5dcbd701c1e1c64c), - UINT64_C(0xaa129b152055f299), - UINT64_C(0x4c95c2b1e1038a4d), - UINT64_C(0x6479e7a3a75d865a) - }; - - if (!test_output(1, true, expected1234)) { - goto fail; - } - - /* If passed all zero seeds, seeding should detect this - * and use splitmix64 to create the actual seed - * (0xe220a8397b1dcdaf, 0x6e789e6aa1b965f4), - * and produce this output: - */ - static const uint64_t expected0000[] = { - UINT64_C(0x509946a41cd733a3), - UINT64_C(0x00885667b1934bfa), - UINT64_C(0x1061f9ad258fd5d5), - UINT64_C(0x3f8be44897a4317c), - UINT64_C(0x60da683bea50e6ab), - UINT64_C(0xd6b52f5379de1de0), - UINT64_C(0x2608bc9fedc5b750), - UINT64_C(0xb9fac9c7ec9de02a) - }; - - if (!test_output(0, false, expected0000)) { - goto fail; - } - - /* If passed all "4" seeds, seeding should detect this - * and use splitmix64 to create the actual seed - * (0x03910b0eab9b37e1, 0x0b309ab53d42b2a2), - * and produce this output: - */ - static const uint64_t expected4444[] = { - UINT64_C(0x0ec1a5c3e8ddea83), - UINT64_C(0x09e710b8faf5a491), - UINT64_C(0xd4102776f79448b4), - UINT64_C(0x5d61988b60091900), - UINT64_C(0xf6c8a72a9c72cb4b), - UINT64_C(0xb06923e0cf0f2fb1), - UINT64_C(0x24bbed475153f573), - UINT64_C(0xfff0b4bd08c5581f), - }; - - if (!test_output(4, false, expected4444)) { - goto fail; - } - - /* Last test used constant seed of 4, which is the default */ - return true; - -fail: - /* Put back the default seed of 4 (other tests might rely on it) */ - random_stub_set_seed(4, false); - return false; -} - -bool test_randLIB_get_n_bytes_random() -{ - randLIB_reset(); - randLIB_seed_random(); - - uint8_t dat[5]; - void *ret = randLIB_get_n_bytes_random(dat, 5); - if(ret != dat){ - return false; - } - - uint8_t dat2[5]; - randLIB_get_n_bytes_random(dat2, 5); - if (memcmp(dat, dat2, 5) == 0) { - return false; - } - - return true; -} - -bool test_randLIB_get_random_in_range() -{ - randLIB_reset(); - randLIB_seed_random(); - - uint16_t ret = randLIB_get_random_in_range(2, 2); - if( ret != 2 ){ - return false; - } - - ret = randLIB_get_random_in_range(2, 3); - if( ret != 2 && ret != 3){ - return false; - } - - ret = randLIB_get_random_in_range(0, 0xFFFF); - - return true; -} - -bool test_randLIB_randomise_base() -{ - randLIB_reset(); - randLIB_seed_random(); - - uint32_t ret = randLIB_randomise_base(0,0,0); - if( ret ){ - return false; - } - ret = randLIB_randomise_base(0xffff0000,0x8888,0x8888); - if( ret != 0xffffffff ){ - return false; - } - return true; -} diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h deleted file mode 100644 index a1949e6d05e..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/randlib/test_randlib.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2016 ARM. All rights reserved. - */ -#ifndef TEST_RANDLIB_H -#define TEST_RANDLIB_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -bool test_randLIB_seed_random(); - -bool test_randLIB_get_8bit(); - -bool test_randLIB_get_16bit(); - -bool test_randLIB_get_32bit(); - -bool test_randLIB_get_64bit(); - -bool test_randLIB_get_n_bytes_random(); - -bool test_randLIB_get_random_in_range(); - -bool test_randLIB_randomise_base(); - - -#ifdef __cplusplus -} -#endif - -#endif // TEST_RANDLIB_H - diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests deleted file mode 100755 index 87f2f504e67..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/run_tests +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -echo -echo Build mbed client randlib unit tests -echo - -# Remember to add new test folder to Makefile -make clean -make all - -echo -echo Create results -echo -mkdir results - -find ./ -name '*.xml' | xargs cp -t ./results/ - -echo -echo Create coverage document -echo -mkdir coverages -cd coverages - -#copy the .gcda & .gcno for all test projects (no need to modify -#cp ../../../source/*.gc* . -#find ../ -name '*.gcda' | xargs cp -t . -#find ../ -name '*.gcno' | xargs cp -t . -#find . -name "test*" -type f -delete -#find . -name "*test*" -type f -delete -#find . -name "*stub*" -type f -delete -#rm -rf main.* - -lcov -q -d ../. -c -o app.info -lcov -q -r app.info "/test*" -o app.info -lcov -q -r app.info "/usr*" -o app.info -genhtml --no-branch-coverage app.info -cd .. -echo -echo -echo -echo Have a nice bug hunt! -echo -echo -echo diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c deleted file mode 100644 index 588c12096e7..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/open_stub.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include -#include - -bool allow_open = true; -int __real_open(const char *path, int flags, ...); -int __wrap_open(const char *path, int flags, ...) -{ - if (allow_open) { - if (flags & O_CREAT) { - va_list vl; - va_start(vl,flags); - mode_t mode = va_arg(vl, mode_t); - va_end(vl); - return __real_open(path, flags, mode); - } else { - return __real_open(path, flags); - } - } else { - return -1; - } -} diff --git a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c b/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c deleted file mode 100644 index f480385da88..00000000000 --- a/features/frameworks/mbed-client-randlib/test/mbed-client-randlib/unittest/stubs/random_stub.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited, All Rights Reserved - */ -#include "random_stub.h" - -static uint32_t seed_value = 4; -static bool seed_inc = false; - -void arm_random_module_init(void) -{ - -} - -uint32_t arm_random_seed_get(void) -{ - uint32_t result = seed_value; - if (seed_inc) { - ++seed_value; - } - return result; -} - -void random_stub_set_seed(uint32_t value, bool increment) -{ - seed_value = value; - seed_inc = increment; -} From 5d162a08ffd383c97b49e35f3065fcd4638ac87c Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 9 Nov 2018 15:52:44 +0200 Subject: [PATCH 08/12] Squashed 'features/frameworks/mbed-client-randlib/' content from commit 3955b95 git-subtree-dir: features/frameworks/mbed-client-randlib git-subtree-split: 3955b95d01e97e821039460332b453b590592342 --- .gitignore | 1 + .mbedignore | 2 + .yotta_ignore | 1 + LICENSE | 2 + Makefile | 5 + apache-2.0.txt | 56 ++ mbed-client-randlib/platform/arm_hal_random.h | 37 ++ mbed-client-randlib/randLIB.h | 149 +++++ module.json | 13 + source/randLIB.c | 268 +++++++++ test/mbed-client-randlib/unittest/Makefile | 23 + .../unittest/MakefileWorker.mk | 562 ++++++++++++++++++ .../unittest/makefile_defines.txt | 19 + .../unittest/randlib/Makefile | 18 + .../unittest/randlib/main.cpp | 15 + .../unittest/randlib/randlibtest.cpp | 54 ++ .../unittest/randlib/test_randlib.c | 195 ++++++ .../unittest/randlib/test_randlib.h | 35 ++ test/mbed-client-randlib/unittest/run_tests | 43 ++ .../unittest/stubs/open_stub.c | 24 + .../unittest/stubs/random_stub.c | 28 + 21 files changed, 1550 insertions(+) create mode 100644 .gitignore create mode 100644 .mbedignore create mode 100644 .yotta_ignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 apache-2.0.txt create mode 100644 mbed-client-randlib/platform/arm_hal_random.h create mode 100644 mbed-client-randlib/randLIB.h create mode 100644 module.json create mode 100644 source/randLIB.c create mode 100644 test/mbed-client-randlib/unittest/Makefile create mode 100644 test/mbed-client-randlib/unittest/MakefileWorker.mk create mode 100644 test/mbed-client-randlib/unittest/makefile_defines.txt create mode 100644 test/mbed-client-randlib/unittest/randlib/Makefile create mode 100644 test/mbed-client-randlib/unittest/randlib/main.cpp create mode 100644 test/mbed-client-randlib/unittest/randlib/randlibtest.cpp create mode 100644 test/mbed-client-randlib/unittest/randlib/test_randlib.c create mode 100644 test/mbed-client-randlib/unittest/randlib/test_randlib.h create mode 100755 test/mbed-client-randlib/unittest/run_tests create mode 100644 test/mbed-client-randlib/unittest/stubs/open_stub.c create mode 100644 test/mbed-client-randlib/unittest/stubs/random_stub.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..77320b339fe --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +output/* diff --git a/.mbedignore b/.mbedignore new file mode 100644 index 00000000000..ba4eb1b31de --- /dev/null +++ b/.mbedignore @@ -0,0 +1,2 @@ +linux/* +test/* diff --git a/.yotta_ignore b/.yotta_ignore new file mode 100644 index 00000000000..ab1cfb4ef2c --- /dev/null +++ b/.yotta_ignore @@ -0,0 +1 @@ +test/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..97df0e645d3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..9a40f3cd68a --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +SRCS := $(wildcard source/*) +LIB := librand.a +EXPORT_HEADERS := mbed-client-randlib + +include ../exported_rules.mk diff --git a/apache-2.0.txt b/apache-2.0.txt new file mode 100644 index 00000000000..0e4cf3ee999 --- /dev/null +++ b/apache-2.0.txt @@ -0,0 +1,56 @@ + + +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. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/mbed-client-randlib/platform/arm_hal_random.h b/mbed-client-randlib/platform/arm_hal_random.h new file mode 100644 index 00000000000..337486dedd6 --- /dev/null +++ b/mbed-client-randlib/platform/arm_hal_random.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2015 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 ARM_HAL_RANDOM_H_ +#define ARM_HAL_RANDOM_H_ +#ifdef __cplusplus +extern "C" { +#endif +/** + * \brief This function performs Random number driver init. + */ +extern void arm_random_module_init(void); +/** + * \brief Get random library seed value. + * + * This function should return as random a value as possible, using + * hardware sources. Repeated calls should return different values if + * at all possible. + */ +extern uint32_t arm_random_seed_get(void); +#ifdef __cplusplus +} +#endif +#endif /* ARM_HAL_RANDOM_H_ */ diff --git a/mbed-client-randlib/randLIB.h b/mbed-client-randlib/randLIB.h new file mode 100644 index 00000000000..a58af013c80 --- /dev/null +++ b/mbed-client-randlib/randLIB.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014-2015 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. + */ + +/** + * \file randLIB.h + * \brief Pseudo Random Library API: + * + * + * \section net-boot Network Bootstrap Control API: + * - randLIB_seed_random(), Set seed for pseudo random + * - randLIB_get_8bit(), Generate 8-bit random number + * - randLIB_get_16bit(),Generate 16-bit random number + * - randLIB_get_32bit(),Generate 32-bit random number + * - randLIB_get_n_bytes_random(), Generate n-bytes random numbers + * + */ + +#ifndef RANDLIB_H_ +#define RANDLIB_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This library is made for getting random numbers for Timing needs in protocols. + * + * **not safe to use for security or cryptographic operations.** + * + */ + + +/** + * \brief Init seed for Pseudo Random. + * + * Makes call(s) to the platform's arm_random_seed_get() to seed the + * pseudo-random generator. + * + * \return None + * + */ +extern void randLIB_seed_random(void); + +/** + * \brief Update seed for pseudo-random generator + * + * Adds seed information to existing generator, to perturb the + * sequence. + * \param seed 64 bits of data to add to the seed. + */ +extern void randLIB_add_seed(uint64_t seed); + +/** + * \brief Generate 8-bit random number. + * + * \param None + * \return 8-bit random number + * + */ +extern uint8_t randLIB_get_8bit(void); + +/** + * \brief Generate 16-bit random number. + * + * \param None + * \return 16-bit random number + * + */ +extern uint16_t randLIB_get_16bit(void); + +/** + * \brief Generate 32-bit random number. + * + * \param None + * \return 32-bit random number + * + */ +extern uint32_t randLIB_get_32bit(void); + +/** + * \brief Generate 64-bit random number. + * + * \param None + * \return 64-bit random number + * + */ +extern uint64_t randLIB_get_64bit(void); + +/** + * \brief Generate n-bytes random numbers. + * + * \param data_ptr pointer where random will be stored + * \param count how many bytes need random + * + * \return data_ptr + */ +extern void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count); + +/** + * \brief Generate a random number within a range. + * + * The result is linearly distributed in the range [min..max], inclusive. + * + * \param min minimum value that can be generated + * \param max maximum value that can be generated + */ +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max); + +/** + * \brief Randomise a base 32-bit number by a jitter factor + * + * The result is linearly distributed in the jitter range, which is expressed + * as fixed-point unsigned 1.15 values. For example, to produce a number in the + * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to + * 0xA000. + * + * Result is clamped to 0xFFFFFFFF if it overflows. + * + * \param base The base 32-bit value + * \param min_factor The minimum value for the random factor + * \param max_factor The maximum value for the random factor + */ +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor); + +#ifdef RANDLIB_PRNG +/* \internal Reset the PRNG state to zero (invalid) */ +void randLIB_reset(void); +#endif + + +#ifdef __cplusplus +} +#endif +#endif /* RANDLIB_H_ */ diff --git a/module.json b/module.json new file mode 100644 index 00000000000..863baaa504a --- /dev/null +++ b/module.json @@ -0,0 +1,13 @@ +{ + "name": "nanostack-randlib", + "version": "1.2.0", + "description": "Pseudo random library used by mbed-client and 6LoWPAN stack.", + "keywords": [], + "homepage": "https://github.com/ARMmbed/mbed-client-randlib", + "license": "Apache-2.0", + "extraIncludes": [ + "mbed-client-randlib" + ], + "dependencies": {}, + "targetDependencies": {} +} diff --git a/source/randLIB.c b/source/randLIB.c new file mode 100644 index 00000000000..274e9bc39b8 --- /dev/null +++ b/source/randLIB.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2014-2015 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 +#include +#include "randLIB.h" +#include "platform/arm_hal_random.h" + +/** + * This library is made for getting random numbers for timing needs in + * protocols, plus to generate dynamic ports, random IDs etc. + * + * **not safe to use for security or cryptographic operations.** + * + * Base implementation is a pseudo-RNG, but may also use a system RNG. + * Replay of sequence by reseeding is not possible. + * + * Base pseudo-RNG is the xoroshiro128+ generator by Marsaglia, Blackman and + * Vigna: + * + * http://xoroshiro.di.unimi.it/ + * + * Certainly not the fastest for 32-bit or smaller platforms, but speed + * is not critical. None of the long operations in the core are actually hard, + * unlike the divisions and multiplies in the utility functions below, where we + * do try to keep the operations narrow. + */ + +/* On some platforms, read from a system RNG, rather than use our own */ +/* RANDLIB_PRNG disables this and forces use of the PRNG (useful for test only?) */ +#ifndef RANDLIB_PRNG +#ifdef __linux +#define RANDOM_DEVICE "/dev/urandom" +#endif +#endif // RANDLIB_PRNG + +/* RAM usage - 16 bytes of state (or a FILE * pointer and underlying FILE, which + * will include a buffer) */ +#ifdef RANDOM_DEVICE +#include +static FILE *random_file; +#else +static uint64_t state[2]; +#endif + +#ifdef RANDLIB_PRNG +void randLIB_reset(void) +{ + state[0] = 0; + state[1] = 0; +} +#endif + +#ifndef RANDOM_DEVICE +static inline uint64_t rol(uint64_t n, int bits) +{ + return (n << bits) | (n >> (64 - bits)); +} + +/* Lower-quality generator used only for initial seeding, if platform + * isn't returning multiple seeds itself. Multiplies are rather heavy + * for lower-end platforms, but this is initialisation only. + */ +static uint64_t splitmix64(uint64_t *seed) +{ + uint64_t z = (*seed += UINT64_C(0x9E3779B97F4A7C15)); + z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); + z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); + return z ^ (z >> 31); +} +#endif // RANDOM_DEVICE + +void randLIB_seed_random(void) +{ +#ifdef RANDOM_DEVICE + if (!random_file) { + random_file = fopen(RANDOM_DEVICE, "rb"); + } +#else + arm_random_module_init(); + + /* We exclusive-OR with the current state, in case they make this call + * multiple times,or in case someone has called randLIB_add_seed before + * this. We don't want to potentially lose entropy. + */ + + /* Spell out expressions so we get known ordering of 4 seed calls */ + uint64_t s = (uint64_t) arm_random_seed_get() << 32; + state[0] ^= (s | arm_random_seed_get()); + + s = (uint64_t) arm_random_seed_get() << 32; + state[1] ^= s | arm_random_seed_get(); + + /* This check serves to both to stir the state if the platform is returning + * constant seeding values, and to avoid the illegal all-zero state. + */ + if (state[0] == state[1]) { + randLIB_add_seed(state[0]); + } +#endif // RANDOM_DEVICE +} + +void randLIB_add_seed(uint64_t seed) +{ +#ifndef RANDOM_DEVICE + state[0] ^= splitmix64(&seed); + state[1] ^= splitmix64(&seed); + /* This is absolutely necessary, but I challenge you to add it to line coverage */ + if (state[1] == 0 && state[0] == 0) { + state[0] = 1; + } +#else + (void)seed; +#endif +} + +uint8_t randLIB_get_8bit(void) +{ + uint64_t r = randLIB_get_64bit(); + return (uint8_t)(r >> 56); +} + +uint16_t randLIB_get_16bit(void) +{ + uint64_t r = randLIB_get_64bit(); + return (uint16_t)(r >> 48); +} + +uint32_t randLIB_get_32bit(void) +{ + uint64_t r = randLIB_get_64bit(); + return (uint32_t)(r >> 32); +} + + +uint64_t randLIB_get_64bit(void) +{ +#ifdef RANDOM_DEVICE + if (!random_file) { + return 0; + } + uint64_t result; + if (fread(&result, sizeof result, 1, random_file) != 1) { + result = 0; + } + return result; +#else + const uint64_t s0 = state[0]; + uint64_t s1 = state[1]; + const uint64_t result = s0 + s1; + + s1 ^= s0; + state[0] = rol(s0, 55) ^ s1 ^ (s1 << 14); + state[1] = rol(s1, 36); + + return result; +#endif +} + +void *randLIB_get_n_bytes_random(void *ptr, uint8_t count) +{ + uint8_t *data_ptr = ptr; + uint64_t r = 0; + for (uint_fast8_t i = 0; i < count; i++) { + /* Take 8 bytes at a time */ + if (i % 8 == 0) { + r = randLIB_get_64bit(); + } else { + r >>= 8; + } + data_ptr[i] = (uint8_t) r; + } + return data_ptr; +} + +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) +{ + /* This special case is potentially common, particularly in this routine's + * first user (Trickle), so worth catching immediately */ + if (min == max) { + return min; + } + +#if UINT_MAX >= 0xFFFFFFFF + const unsigned int rand_max = 0xFFFFFFFFu; // will use rand32 +#else + const unsigned int rand_max = 0xFFFFu; // will use rand16 + + /* 16-bit arithmetic below fails in this extreme case; we can optimise it */ + if (max - min == 0xFFFF) { + return randLIB_get_16bit(); + } +#endif + + /* We get rand_max values from rand16 or 32() in the range [0..rand_max-1], and + * need to divvy them up into the number of values we need. And reroll any + * odd values off the end as we insist every value having equal chance. + * + * Using the range [0..rand_max-1] saves long division on the band + * calculation - it means rand_max ends up always being rerolled. + * + * Eg, range(1,2), rand_max = 0xFFFF: + * We have 2 bands of size 0x7FFF (0xFFFF/2). + * + * We roll: 0x0000..0x7FFE -> 1 + * 0x7FFF..0xFFFD -> 2 + * 0xFFFE..0xFFFF -> reroll + * (calculating band size as 0x10000/2 would have avoided the reroll cases) + * + * Eg, range(1,3), rand_max = 0xFFFFFFFF: + * We have 3 bands of size 0x55555555 (0xFFFFFFFF/3). + * + * We roll: 0x00000000..0x555555554 -> 1 + * 0x55555555..0xAAAAAAAA9 -> 2 + * 0xAAAAAAAA..0xFFFFFFFFE -> 3 + * 0xFFFFFFFF -> reroll + * + * (Bias problem clearly pretty insignificant there, but gets worse as + * range increases). + */ + const unsigned int values_needed = max + 1 - min; + /* Avoid the need for long division, at the expense of fractionally + * increasing reroll chance. */ + const unsigned int band_size = rand_max / values_needed; + const unsigned int top_of_bands = band_size * values_needed; + unsigned int result; + do { +#if UINT_MAX > 0xFFFF + result = randLIB_get_32bit(); +#else + result = randLIB_get_16bit(); +#endif + } while (result >= top_of_bands); + + return min + (uint16_t)(result / band_size); +} + +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) +{ + uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor); + + /* 32x16-bit long multiplication, to get 48-bit result */ + uint32_t hi = (base >> 16) * random_factor; + uint32_t lo = (base & 0xFFFF) * random_factor; + /* Add halves, and take top 32 bits of 48-bit result */ + uint32_t res = hi + (lo >> 16); + + /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */ + if (res & 0x80000000) { + res = 0xFFFFFFFF; + } else { + res = (res << 1) | ((lo >> 15) & 1); + } + + return res; +} diff --git a/test/mbed-client-randlib/unittest/Makefile b/test/mbed-client-randlib/unittest/Makefile new file mode 100644 index 00000000000..b353517548f --- /dev/null +++ b/test/mbed-client-randlib/unittest/Makefile @@ -0,0 +1,23 @@ +#scan for folders having "Makefile" in them and remove 'this' to prevent loop +ifeq ($(OS),Windows_NT) +all: +clean: +else +DIRS := $(filter-out ./, $(sort $(dir $(shell find . -name 'Makefile')))) + +all: + for dir in $(DIRS); do \ + cd $$dir; make gcov; cd ..;\ + done + +clean: + for dir in $(DIRS); do \ + cd $$dir; make clean; cd ..;\ + done + rm -rf ../source/*gcov ../source/*gcda ../source/*o + rm -rf stubs/*gcov stubs/*gcda stubs/*o + rm -rf results/* + rm -rf coverages/* + rm -rf results + rm -rf coverages +endif diff --git a/test/mbed-client-randlib/unittest/MakefileWorker.mk b/test/mbed-client-randlib/unittest/MakefileWorker.mk new file mode 100644 index 00000000000..2096ced0367 --- /dev/null +++ b/test/mbed-client-randlib/unittest/MakefileWorker.mk @@ -0,0 +1,562 @@ +#--------- +# +# MakefileWorker.mk +# +# Include this helper file in your makefile +# It makes +# A static library +# A test executable +# +# See this example for parameter settings +# examples/Makefile +# +#---------- +# Inputs - these variables describe what to build +# +# INCLUDE_DIRS - Directories used to search for include files. +# This generates a -I for each directory +# SRC_DIRS - Directories containing source file to built into the library +# SRC_FILES - Specific source files to build into library. Helpful when not all code +# in a directory can be built for test (hopefully a temporary situation) +# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# TEST_SRC_FILES - Specific source files to build into the unit test runner +# These do not go in a library. They are explicitly included in the test runner +# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner +# These do not go in a library. They are explicitly included in the test runner +#---------- +# You can adjust these variables to influence how to build the test target +# and where to put and name outputs +# See below to determine defaults +# COMPONENT_NAME - the name of the thing being built +# TEST_TARGET - name the test executable. By default it is +# $(COMPONENT_NAME)_tests +# Helpful if you want 1 > make files in the same directory with different +# executables as output. +# CPPUTEST_HOME - where CppUTest home dir found +# TARGET_PLATFORM - Influences how the outputs are generated by modifying the +# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the +# normal objs and lib directories. Also modifies where to search for the +# CPPUTEST_LIB to link against. +# CPPUTEST_OBJS_DIR - a directory where o and d files go +# CPPUTEST_LIB_DIR - a directory where libs go +# CPPUTEST_ENABLE_DEBUG - build for debug +# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete +# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out +# of the test harness +# CPPUTEST_USE_GCOV - Turn on coverage analysis +# Clean then build with this flag set to Y, then 'make gcov' +# CPPUTEST_MAPFILE - generate a map file +# CPPUTEST_WARNINGFLAGS - overly picky by default +# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make +# other targets. Like CSlim, which is part of fitnesse +# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user +# specification of source files and directories that aren't below +# the user's Makefile in the directory tree, like: +# SRC_DIRS += ../../lib/foo +# It defaults to N, and shouldn't be necessary except in the above case. +#---------- +# +# Other flags users can initialize to sneak in their settings +# CPPUTEST_CXXFLAGS - flags for the C++ compiler +# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor +# CPPUTEST_CFLAGS - flags for the C complier +# CPPUTEST_LDFLAGS - Linker flags +#---------- + +# Some behavior is weird on some platforms. Need to discover the platform. + +# Platforms +UNAME_OUTPUT = "$(shell uname -a)" +MACOSX_STR = Darwin +MINGW_STR = MINGW +CYGWIN_STR = CYGWIN +LINUX_STR = Linux +SUNOS_STR = SunOS +UNKNWOWN_OS_STR = Unknown + +# Compilers +CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" +CLANG_STR = clang +SUNSTUDIO_CXX_STR = SunStudio + +UNAME_OS = $(UNKNWOWN_OS_STR) + +ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) + UNAME_OS = $(MINGW_STR) +endif + +ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) + UNAME_OS = $(CYGWIN_STR) +endif + +ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) + UNAME_OS = $(LINUX_STR) +endif + +ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) + UNAME_OS = $(MACOSX_STR) +#lion has a problem with the 'v' part of -a + UNAME_OUTPUT = "$(shell uname -pmnrs)" +endif + +ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) + UNAME_OS = $(SUNOS_STR) + + SUNSTUDIO_CXX_ERR_STR = CC -flags +ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) + CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" + COMPILER_NAME = $(SUNSTUDIO_CXX_STR) +endif +endif + +ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) + COMPILER_NAME = $(CLANG_STR) +endif + +#Kludge for mingw, it does not have cc.exe, but gcc.exe will do +ifeq ($(UNAME_OS),$(MINGW_STR)) + CC := gcc +endif + +#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the +# Standard C++ library as a shared library. Unbelievable. +ifeq ($(UNAME_OS),$(MINGW_STR)) + CPPUTEST_LDFLAGS += -static +endif +ifeq ($(UNAME_OS),$(CYGWIN_STR)) + CPPUTEST_LDFLAGS += -static +endif + + +#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic +ifeq ($(UNAME_OS),$(MACOSX_STR)) +ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) + CPPUTEST_PEDANTIC_ERRORS = N +endif +endif + +ifndef COMPONENT_NAME + COMPONENT_NAME = name_this_in_the_makefile +endif + +# Debug on by default +ifndef CPPUTEST_ENABLE_DEBUG + CPPUTEST_ENABLE_DEBUG = Y +endif + +# new and delete for memory leak detection on by default +ifndef CPPUTEST_USE_MEM_LEAK_DETECTION + CPPUTEST_USE_MEM_LEAK_DETECTION = Y +endif + +# Use the standard C library +ifndef CPPUTEST_USE_STD_C_LIB + CPPUTEST_USE_STD_C_LIB = Y +endif + +# Use the standard C++ library +ifndef CPPUTEST_USE_STD_CPP_LIB + CPPUTEST_USE_STD_CPP_LIB = Y +endif + +# Use gcov, off by default +ifndef CPPUTEST_USE_GCOV + CPPUTEST_USE_GCOV = N +endif + +ifndef CPPUTEST_PEDANTIC_ERRORS + CPPUTEST_PEDANTIC_ERRORS = Y +endif + +# Default warnings +ifndef CPPUTEST_WARNINGFLAGS + CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion +ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) +# CPPUTEST_WARNINGFLAGS += -pedantic-errors + CPPUTEST_WARNINGFLAGS += -pedantic +endif +ifeq ($(UNAME_OS),$(LINUX_STR)) + CPPUTEST_WARNINGFLAGS += -Wsign-conversion +endif + CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual + CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes +endif + +#Wonderful extra compiler warnings with clang +ifeq ($(COMPILER_NAME),$(CLANG_STR)) +# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. +# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) +# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor +# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. + CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables + CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded +endif + +# Uhm. Maybe put some warning flags for SunStudio here? +ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) + CPPUTEST_CXX_WARNINGFLAGS = + CPPUTEST_C_WARNINGFLAGS = +endif + +# Default dir for temporary files (d, o) +ifndef CPPUTEST_OBJS_DIR +ifndef TARGET_PLATFORM + CPPUTEST_OBJS_DIR = objs +else + CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) +endif +endif + +# Default dir for the outout library +ifndef CPPUTEST_LIB_DIR +ifndef TARGET_PLATFORM + CPPUTEST_LIB_DIR = lib +else + CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM) +endif +endif + +# No map by default +ifndef CPPUTEST_MAP_FILE + CPPUTEST_MAP_FILE = N +endif + +# No extentions is default +ifndef CPPUTEST_USE_EXTENSIONS + CPPUTEST_USE_EXTENSIONS = N +endif + +# No VPATH is default +ifndef CPPUTEST_USE_VPATH + CPPUTEST_USE_VPATH := N +endif +# Make empty, instead of 'N', for usage in $(if ) conditionals +ifneq ($(CPPUTEST_USE_VPATH), Y) + CPPUTEST_USE_VPATH := +endif + +ifndef TARGET_PLATFORM +#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib +CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu +else +CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM) +endif + +# -------------------------------------- +# derived flags in the following area +# -------------------------------------- + +# Without the C library, we'll need to disable the C++ library and ... +ifeq ($(CPPUTEST_USE_STD_C_LIB), N) + CPPUTEST_USE_STD_CPP_LIB = N + CPPUTEST_USE_MEM_LEAK_DETECTION = N + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED + CPPUTEST_CPPFLAGS += -nostdinc +endif + +CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION + +ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED +else + ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h + endif + ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE + CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h + endif +endif + +ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) + CPPUTEST_CXXFLAGS += -g + CPPUTEST_CFLAGS += -g + CPPUTEST_LDFLAGS += -g +endif + +ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) + CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED +ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) + CPPUTEST_CXXFLAGS += -nostdinc++ +endif +endif + +ifdef $(GMOCK_HOME) + GTEST_HOME = $(GMOCK_HOME)/gtest + CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include + GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a + LD_LIBRARIES += $(GMOCK_LIBRARY) + CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS + CPPUTEST_WARNINGFLAGS = + CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) + GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a + LD_LIBRARIES += $(GTEST_LIBRARY) +endif + + +ifeq ($(CPPUTEST_USE_GCOV), Y) + CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage + CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage +endif + +CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) +CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) +CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) +CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) +CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) + +TARGET_MAP = $(COMPONENT_NAME).map.txt +ifeq ($(CPPUTEST_MAP_FILE), Y) + CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) +endif + +# Link with CppUTest lib +CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a + +ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) +CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a +endif + +ifdef CPPUTEST_STATIC_REALTIME + LD_LIBRARIES += -lrt +endif + +TARGET_LIB = \ + $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a + +ifndef TEST_TARGET + ifndef TARGET_PLATFORM + TEST_TARGET = $(COMPONENT_NAME)_tests + else + TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests + endif +endif + +#Helper Functions +get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) +get_dirs_from_dirspec = $(wildcard $1) +get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) +__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) +src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) +src_to_o = $(call src_to,.o,$1) +src_to_d = $(call src_to,.d,$1) +src_to_gcda = $(call src_to,.gcda,$1) +src_to_gcno = $(call src_to,.gcno,$1) +time = $(shell date +%s) +delta_t = $(eval minus, $1, $2) +debug_print_list = $(foreach word,$1,echo " $(word)";) echo; + +#Derived +STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) + +SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) +OBJ = $(call src_to_o,$(SRC)) + +STUFF_TO_CLEAN += $(OBJ) + +TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) +TEST_OBJS = $(call src_to_o,$(TEST_SRC)) +STUFF_TO_CLEAN += $(TEST_OBJS) + + +MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) +MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) +STUFF_TO_CLEAN += $(MOCKS_OBJS) + +ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) + +# If we're using VPATH +ifeq ($(CPPUTEST_USE_VPATH), Y) +# gather all the source directories and add them + VPATH += $(sort $(dir $(ALL_SRC))) +# Add the component name to the objs dir path, to differentiate between same-name objects + CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) +endif + +#Test coverage with gcov +GCOV_OUTPUT = gcov_output.txt +GCOV_REPORT = gcov_report.txt +GCOV_ERROR = gcov_error.txt +GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) +GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) +TEST_OUTPUT = $(TEST_TARGET).txt +STUFF_TO_CLEAN += \ + $(GCOV_OUTPUT)\ + $(GCOV_REPORT)\ + $(GCOV_REPORT).html\ + $(GCOV_ERROR)\ + $(GCOV_GCDA_FILES)\ + $(GCOV_GCNO_FILES)\ + $(TEST_OUTPUT) + +#The gcda files for gcov need to be deleted before each run +#To avoid annoying messages. +GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) +RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit + +ifeq ($(CPPUTEST_USE_GCOV), Y) + + ifeq ($(COMPILER_NAME),$(CLANG_STR)) + LD_LIBRARIES += --coverage + else + LD_LIBRARIES += -lgcov + endif +endif + + +INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) +INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) +MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) +INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) + +CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS) + +DEP_FILES = $(call src_to_d, $(ALL_SRC)) +STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) +STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output + +# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags +CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) +CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) +CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) +LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) + +# Don't consider creating the archive a warning condition that does STDERR output +ARFLAGS := $(ARFLAGS)c + +DEP_FLAGS=-MMD -MP + +# Some macros for programs to be overridden. For some reason, these are not in Make defaults +RANLIB = ranlib + +# Targets + +.PHONY: all +all: start $(TEST_TARGET) + $(RUN_TEST_TARGET) + +.PHONY: start +start: $(TEST_TARGET) + $(SILENCE)START_TIME=$(call time) + +.PHONY: all_no_tests +all_no_tests: $(TEST_TARGET) + +.PHONY: flags +flags: + @echo + @echo "OS ${UNAME_OS}" + @echo "Compile C and C++ source with CPPFLAGS:" + @$(call debug_print_list,$(CPPFLAGS)) + @echo "Compile C++ source with CXXFLAGS:" + @$(call debug_print_list,$(CXXFLAGS)) + @echo "Compile C source with CFLAGS:" + @$(call debug_print_list,$(CFLAGS)) + @echo "Link with LDFLAGS:" + @$(call debug_print_list,$(LDFLAGS)) + @echo "Link with LD_LIBRARIES:" + @$(call debug_print_list,$(LD_LIBRARIES)) + @echo "Create libraries with ARFLAGS:" + @$(call debug_print_list,$(ARFLAGS)) + +TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) +test-deps: $(TEST_DEPS) + +$(TEST_TARGET): $(TEST_DEPS) + @echo Linking $@ + $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) + +$(TARGET_LIB): $(OBJ) + @echo Building archive $@ + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(AR) $(ARFLAGS) $@ $^ + $(SILENCE)$(RANLIB) $@ + +test: $(TEST_TARGET) + $(RUN_TEST_TARGET) | tee $(TEST_OUTPUT) + +vtest: $(TEST_TARGET) + $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) + +$(CPPUTEST_OBJS_DIR)/%.o: %.cc + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.cpp + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +$(CPPUTEST_OBJS_DIR)/%.o: %.c + @echo compiling $(notdir $<) + $(SILENCE)mkdir -p $(dir $@) + $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< + +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEP_FILES) +endif + +.PHONY: clean +clean: + @echo Making clean + $(SILENCE)$(RM) $(STUFF_TO_CLEAN) + $(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR) + $(SILENCE)rm -rf $(CPPUTEST_LIB_DIR) + $(SILENCE)find . -name "*.gcno" | xargs rm -f + $(SILENCE)find . -name "*.gcda" | xargs rm -f + +#realclean gets rid of all gcov, o and d files in the directory tree +#not just the ones made by this makefile +.PHONY: realclean +realclean: clean + $(SILENCE)rm -rf gcov + $(SILENCE)find . -name "*.gdcno" | xargs rm -f + $(SILENCE)find . -name "*.[do]" | xargs rm -f + +gcov: test +ifeq ($(CPPUTEST_USE_VPATH), Y) + $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) +else + $(SILENCE)for d in $(SRC_DIRS) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done + $(SILENCE)for f in $(SRC_FILES) ; do \ + gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ + done +endif +# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + /usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) + $(SILENCE)cat $(GCOV_REPORT) + $(SILENCE)mkdir -p gcov + $(SILENCE)mv *.gcov gcov + $(SILENCE)mv gcov_* gcov + @echo "See gcov directory for details" + +.PHONEY: format +format: + $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) + +.PHONEY: debug +debug: + @echo + @echo "Target Source files:" + @$(call debug_print_list,$(SRC)) + @echo "Target Object files:" + @$(call debug_print_list,$(OBJ)) + @echo "Test Source files:" + @$(call debug_print_list,$(TEST_SRC)) + @echo "Test Object files:" + @$(call debug_print_list,$(TEST_OBJS)) + @echo "Mock Source files:" + @$(call debug_print_list,$(MOCKS_SRC)) + @echo "Mock Object files:" + @$(call debug_print_list,$(MOCKS_OBJS)) + @echo "All Input Dependency files:" + @$(call debug_print_list,$(DEP_FILES)) + @echo Stuff to clean: + @$(call debug_print_list,$(STUFF_TO_CLEAN)) + @echo Includes: + @$(call debug_print_list,$(INCLUDES)) + +-include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/test/mbed-client-randlib/unittest/makefile_defines.txt b/test/mbed-client-randlib/unittest/makefile_defines.txt new file mode 100644 index 00000000000..0a350ee9221 --- /dev/null +++ b/test/mbed-client-randlib/unittest/makefile_defines.txt @@ -0,0 +1,19 @@ +#--- Inputs ----# +CPPUTEST_HOME = /usr +CPPUTEST_USE_EXTENSIONS = Y +CPPUTEST_USE_VPATH = Y +CPPUTEST_USE_GCOV = Y +CPP_PLATFORM = gcc +INCLUDE_DIRS =\ + .\ + ../common\ + ../stubs\ + ../../../..\ + ../../../../source\ + ../../../../mbed-client-randlib\ + ../../../../../../../libService/libService\ + /usr/include\ + $(CPPUTEST_HOME)/include\ + +CPPUTESTFLAGS = -D__thumb2__ -w +CPPUTEST_CFLAGS += -std=gnu99 diff --git a/test/mbed-client-randlib/unittest/randlib/Makefile b/test/mbed-client-randlib/unittest/randlib/Makefile new file mode 100644 index 00000000000..12d97840f62 --- /dev/null +++ b/test/mbed-client-randlib/unittest/randlib/Makefile @@ -0,0 +1,18 @@ +include ../makefile_defines.txt + +COMPONENT_NAME = randLIB_unit + +#This must be changed manually +SRC_FILES = \ + ../../../../source/randLIB.c + +TEST_SRC_FILES = \ + main.cpp \ + randlibtest.cpp \ + test_randlib.c \ + ../stubs/random_stub.c \ + +include ../MakefileWorker.mk + +CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -DRANDLIB_PRNG + diff --git a/test/mbed-client-randlib/unittest/randlib/main.cpp b/test/mbed-client-randlib/unittest/randlib/main.cpp new file mode 100644 index 00000000000..becceb65ca9 --- /dev/null +++ b/test/mbed-client-randlib/unittest/randlib/main.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 ARM. All rights reserved. + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/TestPlugin.h" +#include "CppUTest/TestRegistry.h" +#include "CppUTestExt/MockSupportPlugin.h" +int main(int ac, char **av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} + +IMPORT_TEST_GROUP(randLIB); + diff --git a/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp b/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp new file mode 100644 index 00000000000..309896d81d4 --- /dev/null +++ b/test/mbed-client-randlib/unittest/randlib/randlibtest.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#include "CppUTest/TestHarness.h" +#include "test_randlib.h" + +TEST_GROUP(randLIB) +{ + void setup() { + } + + void teardown() { + } +}; + +TEST(randLIB, test_randLIB_seed_random) +{ + CHECK(test_randLIB_seed_random()); +} + +TEST(randLIB, test_randLIB_get_8bit) +{ + CHECK(test_randLIB_get_8bit()); +} + +TEST(randLIB, test_randLIB_get_16bit) +{ + CHECK(test_randLIB_get_16bit()); +} + +TEST(randLIB, test_randLIB_get_32bit) +{ + CHECK(test_randLIB_get_32bit()); +} + +TEST(randLIB, test_randLIB_get_64bit) +{ + CHECK(test_randLIB_get_64bit()); +} + +TEST(randLIB, test_randLIB_get_n_bytes_random) +{ + CHECK(test_randLIB_get_n_bytes_random()); +} + +TEST(randLIB, test_randLIB_get_random_in_range) +{ + CHECK(test_randLIB_get_random_in_range()); +} + +TEST(randLIB, test_randLIB_randomise_base) +{ + CHECK(test_randLIB_randomise_base()); +} diff --git a/test/mbed-client-randlib/unittest/randlib/test_randlib.c b/test/mbed-client-randlib/unittest/randlib/test_randlib.c new file mode 100644 index 00000000000..3a9639f7b7d --- /dev/null +++ b/test/mbed-client-randlib/unittest/randlib/test_randlib.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#include "test_randlib.h" +#include +#include +#include "randLIB.h" + +bool test_randLIB_seed_random() +{ + randLIB_reset(); + randLIB_seed_random(); + return true; +} + +bool test_randLIB_get_8bit() +{ + randLIB_reset(); + randLIB_seed_random(); + uint8_t test = randLIB_get_8bit(); + if (test == 0) { + test = randLIB_get_8bit(); + if (test == 0) { + return false; + } + } + return true; +} + +bool test_randLIB_get_16bit() +{ + randLIB_reset(); + randLIB_seed_random(); + uint16_t test = randLIB_get_16bit(); + if (test == 0) { + test = randLIB_get_16bit(); + if (test == 0) { + return false; + } + } + return true; +} + +bool test_randLIB_get_32bit() +{ + randLIB_reset(); + randLIB_seed_random(); + uint32_t test = randLIB_get_32bit(); + if (test == 0) { + test = randLIB_get_32bit(); + if (test == 0) { + return false; + } + } + return true; +} + +static bool test_output(uint32_t seed, bool seed_inc, const uint64_t expected[8]) +{ + random_stub_set_seed(seed, seed_inc); + randLIB_reset(); + randLIB_seed_random(); + for (int i = 0; i < 8; i++) { + if (randLIB_get_64bit() != expected[i]) { + return false; + } + } + + return true; +} + +bool test_randLIB_get_64bit() +{ + /* Initial 8 xoroshiro128+ values with initial seed of + * (0x0000000100000002, 0x00000003000000004). + */ + static const uint64_t expected1234[] = { + UINT64_C(0x0000000400000006), + UINT64_C(0x0100806200818026), + UINT64_C(0x2a30826271904706), + UINT64_C(0x918d7ea50109290d), + UINT64_C(0x5dcbd701c1e1c64c), + UINT64_C(0xaa129b152055f299), + UINT64_C(0x4c95c2b1e1038a4d), + UINT64_C(0x6479e7a3a75d865a) + }; + + if (!test_output(1, true, expected1234)) { + goto fail; + } + + /* If passed all zero seeds, seeding should detect this + * and use splitmix64 to create the actual seed + * (0xe220a8397b1dcdaf, 0x6e789e6aa1b965f4), + * and produce this output: + */ + static const uint64_t expected0000[] = { + UINT64_C(0x509946a41cd733a3), + UINT64_C(0x00885667b1934bfa), + UINT64_C(0x1061f9ad258fd5d5), + UINT64_C(0x3f8be44897a4317c), + UINT64_C(0x60da683bea50e6ab), + UINT64_C(0xd6b52f5379de1de0), + UINT64_C(0x2608bc9fedc5b750), + UINT64_C(0xb9fac9c7ec9de02a) + }; + + if (!test_output(0, false, expected0000)) { + goto fail; + } + + /* If passed all "4" seeds, seeding should detect this + * and use splitmix64 to create the actual seed + * (0x03910b0eab9b37e1, 0x0b309ab53d42b2a2), + * and produce this output: + */ + static const uint64_t expected4444[] = { + UINT64_C(0x0ec1a5c3e8ddea83), + UINT64_C(0x09e710b8faf5a491), + UINT64_C(0xd4102776f79448b4), + UINT64_C(0x5d61988b60091900), + UINT64_C(0xf6c8a72a9c72cb4b), + UINT64_C(0xb06923e0cf0f2fb1), + UINT64_C(0x24bbed475153f573), + UINT64_C(0xfff0b4bd08c5581f), + }; + + if (!test_output(4, false, expected4444)) { + goto fail; + } + + /* Last test used constant seed of 4, which is the default */ + return true; + +fail: + /* Put back the default seed of 4 (other tests might rely on it) */ + random_stub_set_seed(4, false); + return false; +} + +bool test_randLIB_get_n_bytes_random() +{ + randLIB_reset(); + randLIB_seed_random(); + + uint8_t dat[5]; + void *ret = randLIB_get_n_bytes_random(dat, 5); + if (ret != dat) { + return false; + } + + uint8_t dat2[5]; + randLIB_get_n_bytes_random(dat2, 5); + if (memcmp(dat, dat2, 5) == 0) { + return false; + } + + return true; +} + +bool test_randLIB_get_random_in_range() +{ + randLIB_reset(); + randLIB_seed_random(); + + uint16_t ret = randLIB_get_random_in_range(2, 2); + if (ret != 2) { + return false; + } + + ret = randLIB_get_random_in_range(2, 3); + if (ret != 2 && ret != 3) { + return false; + } + + ret = randLIB_get_random_in_range(0, 0xFFFF); + + return true; +} + +bool test_randLIB_randomise_base() +{ + randLIB_reset(); + randLIB_seed_random(); + + uint32_t ret = randLIB_randomise_base(0, 0, 0); + if (ret) { + return false; + } + ret = randLIB_randomise_base(0xffff0000, 0x8888, 0x8888); + if (ret != 0xffffffff) { + return false; + } + return true; +} diff --git a/test/mbed-client-randlib/unittest/randlib/test_randlib.h b/test/mbed-client-randlib/unittest/randlib/test_randlib.h new file mode 100644 index 00000000000..a1949e6d05e --- /dev/null +++ b/test/mbed-client-randlib/unittest/randlib/test_randlib.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 ARM. All rights reserved. + */ +#ifndef TEST_RANDLIB_H +#define TEST_RANDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool test_randLIB_seed_random(); + +bool test_randLIB_get_8bit(); + +bool test_randLIB_get_16bit(); + +bool test_randLIB_get_32bit(); + +bool test_randLIB_get_64bit(); + +bool test_randLIB_get_n_bytes_random(); + +bool test_randLIB_get_random_in_range(); + +bool test_randLIB_randomise_base(); + + +#ifdef __cplusplus +} +#endif + +#endif // TEST_RANDLIB_H + diff --git a/test/mbed-client-randlib/unittest/run_tests b/test/mbed-client-randlib/unittest/run_tests new file mode 100755 index 00000000000..87f2f504e67 --- /dev/null +++ b/test/mbed-client-randlib/unittest/run_tests @@ -0,0 +1,43 @@ +#!/bin/bash +echo +echo Build mbed client randlib unit tests +echo + +# Remember to add new test folder to Makefile +make clean +make all + +echo +echo Create results +echo +mkdir results + +find ./ -name '*.xml' | xargs cp -t ./results/ + +echo +echo Create coverage document +echo +mkdir coverages +cd coverages + +#copy the .gcda & .gcno for all test projects (no need to modify +#cp ../../../source/*.gc* . +#find ../ -name '*.gcda' | xargs cp -t . +#find ../ -name '*.gcno' | xargs cp -t . +#find . -name "test*" -type f -delete +#find . -name "*test*" -type f -delete +#find . -name "*stub*" -type f -delete +#rm -rf main.* + +lcov -q -d ../. -c -o app.info +lcov -q -r app.info "/test*" -o app.info +lcov -q -r app.info "/usr*" -o app.info +genhtml --no-branch-coverage app.info +cd .. +echo +echo +echo +echo Have a nice bug hunt! +echo +echo +echo diff --git a/test/mbed-client-randlib/unittest/stubs/open_stub.c b/test/mbed-client-randlib/unittest/stubs/open_stub.c new file mode 100644 index 00000000000..6fda589546a --- /dev/null +++ b/test/mbed-client-randlib/unittest/stubs/open_stub.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + +bool allow_open = true; +int __real_open(const char *path, int flags, ...); +int __wrap_open(const char *path, int flags, ...) +{ + if (allow_open) { + if (flags & O_CREAT) { + va_list vl; + va_start(vl, flags); + mode_t mode = va_arg(vl, mode_t); + va_end(vl); + return __real_open(path, flags, mode); + } else { + return __real_open(path, flags); + } + } else { + return -1; + } +} diff --git a/test/mbed-client-randlib/unittest/stubs/random_stub.c b/test/mbed-client-randlib/unittest/stubs/random_stub.c new file mode 100644 index 00000000000..c271839a6b8 --- /dev/null +++ b/test/mbed-client-randlib/unittest/stubs/random_stub.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited, All Rights Reserved + */ + +#include "ns_types.h" + +static uint32_t seed_value = 4; +static bool seed_inc = false; + +void arm_random_module_init(void) +{ + +} + +uint32_t arm_random_seed_get(void) +{ + uint32_t result = seed_value; + if (seed_inc) { + ++seed_value; + } + return result; +} + +void random_stub_set_seed(uint32_t value, bool increment) +{ + seed_value = value; + seed_inc = increment; +} From 1374a5e5e6775dd6db9533075f25b3112c984b22 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 9 Nov 2018 15:59:35 +0200 Subject: [PATCH 09/12] Squashed 'features/frameworks/mbed-trace/' changes from 9eaf0d1..7a1bd34 7a1bd34 Use Mbed OS coding style (#86) git-subtree-dir: features/frameworks/mbed-trace git-subtree-split: 7a1bd34be547f3aa9badfbeb1c9993ff4a9e1ded --- mbed-trace/mbed_trace.h | 36 +-- source/mbed_trace.c | 26 +-- test/Test.cpp | 487 ++++++++++++++++++++-------------------- 3 files changed, 278 insertions(+), 271 deletions(-) diff --git a/mbed-trace/mbed_trace.h b/mbed-trace/mbed_trace.h index eb4055b0c01..0562e4a898a 100644 --- a/mbed-trace/mbed_trace.h +++ b/mbed-trace/mbed_trace.h @@ -180,11 +180,11 @@ extern "C" { * Initialize trace functionality * @return 0 when all success, otherwise non zero */ -int mbed_trace_init( void ); +int mbed_trace_init(void); /** * Free trace memory */ -void mbed_trace_free( void ); +void mbed_trace_free(void); /** * Resize buffers (line / tmp ) sizes * @param lineLength new maximum length for trace line (0 = do no resize) @@ -226,7 +226,7 @@ uint8_t mbed_trace_config_get(void); * char* trace_time(){ return "rtc-time-in-string"; } * mbed_trace_prefix_function_set( &trace_time ); */ -void mbed_trace_prefix_function_set( char* (*pref_f)(size_t) ); +void mbed_trace_prefix_function_set(char *(*pref_f)(size_t)); /** * Set trace suffix function * suffix -function return string with null terminated @@ -235,18 +235,18 @@ void mbed_trace_prefix_function_set( char* (*pref_f)(size_t) ); * char* trace_suffix(){ return " END"; } * mbed_trace_suffix_function_set( &trace_suffix ); */ -void mbed_trace_suffix_function_set(char* (*suffix_f)(void) ); +void mbed_trace_suffix_function_set(char *(*suffix_f)(void)); /** * Set trace print function * By default, trace module print using printf() function, * but with this you can write own print function, * for e.g. to other IO device. */ -void mbed_trace_print_function_set( void (*print_f)(const char*) ); +void mbed_trace_print_function_set(void (*print_f)(const char *)); /** * Set trace print function for tr_cmdline() */ -void mbed_trace_cmdprint_function_set( void (*printf)(const char*) ); +void mbed_trace_cmdprint_function_set(void (*printf)(const char *)); /** * Set trace mutex wait function * By default, trace calls are not thread safe. @@ -270,10 +270,10 @@ void mbed_trace_mutex_release_function_set(void (*mutex_release_f)(void)); * mbed_trace_exclude_filters_set("mygr"); * mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "ougr", "This is not printed"); */ -void mbed_trace_exclude_filters_set(char* filters); +void mbed_trace_exclude_filters_set(char *filters); /** get trace exclude filters */ -const char* mbed_trace_exclude_filters_get(void); +const char *mbed_trace_exclude_filters_get(void); /** * When trace group contains text in filter, * trace will be printed. @@ -282,10 +282,10 @@ const char* mbed_trace_exclude_filters_get(void); * mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "mygr", "Hi There"); * mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "grp2", "This is not printed"); */ -void mbed_trace_include_filters_set(char* filters); +void mbed_trace_include_filters_set(char *filters); /** get trace include filters */ -const char* mbed_trace_include_filters_get(void); +const char *mbed_trace_include_filters_get(void); /** * General trace function * This should be used every time when user want to print out something important thing @@ -298,9 +298,9 @@ const char* mbed_trace_include_filters_get(void); * @param ... variable arguments related to fmt */ #if defined(__GNUC__) || defined(__CC_ARM) -void mbed_tracef(uint8_t dlevel, const char* grp, const char *fmt, ...) __attribute__ ((__format__(__printf__, 3, 4))); +void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...) __attribute__((__format__(__printf__, 3, 4))); #else -void mbed_tracef(uint8_t dlevel, const char* grp, const char *fmt, ...); +void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...); #endif /** * General trace function @@ -318,16 +318,16 @@ void mbed_tracef(uint8_t dlevel, const char* grp, const char *fmt, ...); * @param ap variable arguments list (like vprintf) */ #if defined(__GNUC__) || defined(__CC_ARM) -void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap) __attribute__ ((__format__(__printf__, 3, 0))); +void mbed_vtracef(uint8_t dlevel, const char *grp, const char *fmt, va_list ap) __attribute__((__format__(__printf__, 3, 0))); #else -void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap); +void mbed_vtracef(uint8_t dlevel, const char *grp, const char *fmt, va_list ap); #endif /** * Get last trace from buffer */ -const char* mbed_trace_last(void); +const char *mbed_trace_last(void); #if MBED_CONF_MBED_TRACE_FEA_IPV6 == 1 /** * mbed_tracef helping function for convert ipv6 @@ -339,7 +339,7 @@ const char* mbed_trace_last(void); * @param add_ptr IPv6 Address pointer * @return temporary buffer where ipv6 is in string format */ -char* mbed_trace_ipv6(const void *addr_ptr); +char *mbed_trace_ipv6(const void *addr_ptr); /** * mbed_tracef helping function for print ipv6 prefix * usage e.g. @@ -350,7 +350,7 @@ char* mbed_trace_ipv6(const void *addr_ptr); * @param prefix_len prefix length * @return temporary buffer where ipv6 is in string format */ -char* mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len); +char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len); #endif /** * mbed_tracef helping function for convert hex-array to string. @@ -364,7 +364,7 @@ char* mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len); * if array as string not fit to temp buffer, this function write '*' as last character, * which indicate that buffer is too small for array. */ -char* mbed_trace_array(const uint8_t* buf, uint16_t len); +char *mbed_trace_array(const uint8_t *buf, uint16_t len); #ifdef __cplusplus } diff --git a/source/mbed_trace.c b/source/mbed_trace.c index 5fdffd52c30..04dacbfaafc 100644 --- a/source/mbed_trace.c +++ b/source/mbed_trace.c @@ -93,7 +93,7 @@ #endif /** default print function, just redirect str to printf */ -static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length); +static void mbed_trace_realloc(char **buffer, int *length_ptr, int new_length); static void mbed_trace_default_print(const char *str); static void mbed_trace_reset_tmp(void); @@ -209,7 +209,7 @@ void mbed_trace_free(void) m_trace.mutex_release_f = 0; m_trace.mutex_lock_count = 0; } -static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length) +static void mbed_trace_realloc(char **buffer, int *length_ptr, int new_length) { MBED_TRACE_MEM_FREE(*buffer); *buffer = MBED_TRACE_MEM_ALLOC(new_length); @@ -217,11 +217,11 @@ static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length) } void mbed_trace_buffer_sizes(int lineLength, int tmpLength) { - if( lineLength > 0 ) { - mbed_trace_realloc( &(m_trace.line), &m_trace.line_length, lineLength ); + if (lineLength > 0) { + mbed_trace_realloc(&(m_trace.line), &m_trace.line_length, lineLength); } - if( tmpLength > 0 ) { - mbed_trace_realloc( &(m_trace.tmp_data), &m_trace.tmp_data_length, tmpLength); + if (tmpLength > 0) { + mbed_trace_realloc(&(m_trace.tmp_data), &m_trace.tmp_data_length, tmpLength); mbed_trace_reset_tmp(); } } @@ -311,9 +311,9 @@ void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...) mbed_vtracef(dlevel, grp, fmt, ap); va_end(ap); } -void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap) +void mbed_vtracef(uint8_t dlevel, const char *grp, const char *fmt, va_list ap) { - if ( m_trace.mutex_wait_f ) { + if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); m_trace.mutex_lock_count++; } @@ -476,7 +476,7 @@ void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap) } end: - if ( m_trace.mutex_release_f ) { + if (m_trace.mutex_release_f) { // Store the mutex lock count to temp variable so that it won't get // clobbered during last loop iteration when mutex gets released int count = m_trace.mutex_lock_count; @@ -507,7 +507,7 @@ const char *mbed_trace_last(void) char *mbed_trace_ipv6(const void *addr_ptr) { /** Acquire mutex. It is released before returning from mbed_vtracef. */ - if ( m_trace.mutex_wait_f ) { + if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); m_trace.mutex_lock_count++; } @@ -528,7 +528,7 @@ char *mbed_trace_ipv6(const void *addr_ptr) char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len) { /** Acquire mutex. It is released before returning from mbed_vtracef. */ - if ( m_trace.mutex_wait_f ) { + if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); m_trace.mutex_lock_count++; } @@ -551,7 +551,7 @@ char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len) char *mbed_trace_array(const uint8_t *buf, uint16_t len) { /** Acquire mutex. It is released before returning from mbed_vtracef. */ - if ( m_trace.mutex_wait_f ) { + if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); m_trace.mutex_lock_count++; } @@ -581,7 +581,7 @@ char *mbed_trace_array(const uint8_t *buf, uint16_t len) wptr += retval; } if (wptr > str) { - if( overflow ) { + if (overflow) { // replace last character as 'star', // which indicate buffer len is not enough *(wptr - 1) = '*'; diff --git a/test/Test.cpp b/test/Test.cpp index 845d9a49c67..4261d8172ea 100644 --- a/test/Test.cpp +++ b/test/Test.cpp @@ -30,101 +30,107 @@ static int mutex_release_count = 0; static bool check_mutex_lock_status = true; void my_mutex_wait() { - mutex_wait_count++; + mutex_wait_count++; } void my_mutex_release() { - mutex_release_count++; + mutex_release_count++; } char buf[1024]; #include -void myprint(const char* str) +void myprint(const char *str) { - if ( check_mutex_lock_status ) { - CHECK( (mutex_wait_count - mutex_release_count) > 0 ); - } - strcpy(buf, str); + if (check_mutex_lock_status) { + CHECK((mutex_wait_count - mutex_release_count) > 0); + } + strcpy(buf, str); } TEST_GROUP(trace) { - void setup() - { - - mbed_trace_init(); - mbed_trace_config_set(TRACE_MODE_PLAIN|TRACE_ACTIVE_LEVEL_ALL); - mbed_trace_print_function_set( myprint ); - mbed_trace_mutex_wait_function_set( my_mutex_wait ); - mbed_trace_mutex_release_function_set( my_mutex_release ); - } - void teardown() - { - CHECK(mutex_wait_count == mutex_release_count); // Check the mutex count with every test - mbed_trace_free(); - } + void setup() { + + mbed_trace_init(); + mbed_trace_config_set(TRACE_MODE_PLAIN | TRACE_ACTIVE_LEVEL_ALL); + mbed_trace_print_function_set(myprint); + mbed_trace_mutex_wait_function_set(my_mutex_wait); + mbed_trace_mutex_release_function_set(my_mutex_release); + } + void teardown() { + CHECK(mutex_wait_count == mutex_release_count); // Check the mutex count with every test + mbed_trace_free(); + } }; /* Unity test code starts */ TEST(trace, MutexNotSet) { - mbed_trace_mutex_wait_function_set( 0 ); - mbed_trace_mutex_release_function_set( 0 ); - int mutex_call_count_at_entry = mutex_wait_count; - check_mutex_lock_status = false; + mbed_trace_mutex_wait_function_set(0); + mbed_trace_mutex_release_function_set(0); + int mutex_call_count_at_entry = mutex_wait_count; + check_mutex_lock_status = false; - char expectedStr[] = "Hello hello!"; - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "Hello hello!"); - STRCMP_EQUAL(expectedStr, buf); + char expectedStr[] = "Hello hello!"; + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "Hello hello!"); + STRCMP_EQUAL(expectedStr, buf); - CHECK( mutex_call_count_at_entry == mutex_wait_count ); - CHECK( mutex_call_count_at_entry == mutex_release_count ); + CHECK(mutex_call_count_at_entry == mutex_wait_count); + CHECK(mutex_call_count_at_entry == mutex_release_count); - mbed_trace_mutex_wait_function_set( my_mutex_wait ); - mbed_trace_mutex_release_function_set( my_mutex_release ); - check_mutex_lock_status = true; + mbed_trace_mutex_wait_function_set(my_mutex_wait); + mbed_trace_mutex_release_function_set(my_mutex_release); + check_mutex_lock_status = true; } TEST(trace, Array) { - unsigned char longStr[200] = {0x66}; - for(int i=0;i<200;i++) {longStr[i] = 0x66; } - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(longStr, 200) ); + unsigned char longStr[200] = {0x66}; + for (int i = 0; i < 200; i++) { + longStr[i] = 0x66; + } + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(longStr, 200)); } TEST(trace, Null0Array) { - static const unsigned char array[2] = { 0x23, 0x45 }; - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 2)); - STRCMP_EQUAL("23:45", buf); - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 0)); - STRCMP_EQUAL("", buf); - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 0)); - STRCMP_EQUAL("", buf); - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 2)); - STRCMP_EQUAL("", buf); + static const unsigned char array[2] = { 0x23, 0x45 }; + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 2)); + STRCMP_EQUAL("23:45", buf); + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 0)); + STRCMP_EQUAL("", buf); + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 0)); + STRCMP_EQUAL("", buf); + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 2)); + STRCMP_EQUAL("", buf); } TEST(trace, LongString) { - char longStr[1000] = {0x36}; - for(int i=0;i<999;i++) {longStr[i] = 0x36; } - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", longStr ); + char longStr[1000] = {0x36}; + for (int i = 0; i < 999; i++) { + longStr[i] = 0x36; + } + mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", longStr); } TEST(trace, TooLong) { - #define TOO_LONG_SIZE 9400 - #define TRACE_LINE_SIZE 1024 - char longStr[TOO_LONG_SIZE] = {0}; - for(int i=0;i][DBG ][mygr]: test 1 2", buf); - //TEST_ASSERT_EQUAL_INT(4, time_length); - - mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL|TRACE_MODE_PLAIN); - mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "test"); - STRCMP_EQUAL("test", buf); - - mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL|TRACE_MODE_COLOR); - mbed_tracef(TRACE_LEVEL_ERROR, "mygr", "test"); - STRCMP_EQUAL("\x1b[31m[