From 97200b3bfbdfa3a9cfe72089c34976bdc5712695 Mon Sep 17 00:00:00 2001 From: Mika Tervonen Date: Fri, 6 Apr 2018 12:03:46 +0300 Subject: [PATCH] Added version number increase in border router Version number is learned and distributed to the network Device will notice if version number does not change in correct time still left todo to proper handling of RPL parent lost --- source/6LoWPAN/ws/ws_bootstrap.c | 177 ++++++++++++------ source/6LoWPAN/ws/ws_common.h | 2 + source/6LoWPAN/ws/ws_config.h | 19 ++ source/6LoWPAN/ws/ws_neighbor_class.c | 8 + source/6LoWPAN/ws/ws_neighbor_class.h | 12 ++ .../unittest/stub/ws_neighbour_class_stub.c | 6 + 6 files changed, 168 insertions(+), 56 deletions(-) diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index dbb6463bb9b..72194c82cef 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -35,6 +35,7 @@ #include "6LoWPAN/MAC/mpx_api.h" #include "6LoWPAN/MAC/mac_ie_lib.h" #include "6LoWPAN/ws/ws_common_defines.h" +#include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" #include "RPL/rpl_protocol.h" @@ -80,22 +81,50 @@ static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur) static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur); static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur); static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data); -static mac_neighbor_table_entry_t * ws_bootstrap_add_neighbor(struct protocol_interface_info_entry *interface, const uint8_t *src64) + +static mac_neighbor_table_entry_t * ws_bootstrap_mac_neighbor_add(struct protocol_interface_info_entry *interface, const uint8_t *src64) { mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(interface->mac_parameters->mac_neighbor_table, src64, MAC_ADDR_MODE_64_BIT); if (!neighbor) { neighbor = mac_neighbor_table_entry_allocate(interface->mac_parameters->mac_neighbor_table, src64); - if (neighbor) { - mlme_device_descriptor_t device_desc; - tr_debug("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index); - mac_helper_device_description_write(interface, &device_desc, neighbor->mac64, neighbor->mac16,0, false); - mac_helper_devicetable_set(&device_desc, interface,neighbor->index, interface->mac_parameters->mac_default_key_index, true); - } } + if (!neighbor) { + return NULL; + } + mlme_device_descriptor_t device_desc; + tr_debug("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index); + mac_helper_device_description_write(interface, &device_desc, neighbor->mac64, neighbor->mac16,0, false); + mac_helper_devicetable_set(&device_desc, interface,neighbor->index, interface->mac_parameters->mac_default_key_index, true); return neighbor; } +static ws_neighbor_class_entry_t * ws_bootstrap_neighbor_add(struct protocol_interface_info_entry *interface, const uint8_t *src64) +{ + mac_neighbor_table_entry_t *neighbor = ws_bootstrap_mac_neighbor_add(interface, src64); + if (!neighbor) { + return NULL; + } + ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index); + if (!ws_neighbor) { + mac_neighbor_table_neighbor_remove(interface->mac_parameters->mac_neighbor_table, neighbor); + return NULL; + } + return ws_neighbor; +} + +static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, uint8_t attribute_index) +{ + mac_helper_devicetable_remove(interface->mac_api, attribute_index); + etx_neighbor_remove(interface->id, attribute_index); + ws_neighbor_class_entry_remove(&interface->ws_info->neighbor_storage, attribute_index); +} + +static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface) +{ + + mac_neighbor_table_neighbor_list_clean(interface->mac_parameters->mac_neighbor_table); +} static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason) { @@ -334,19 +363,14 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf } //TODO smarter Neighbor allocate system - mac_neighbor_table_entry_t *neighbor = ws_bootstrap_add_neighbor(cur, data->SrcAddr); + ws_neighbor_class_entry_t *neighbor = ws_bootstrap_neighbor_add(cur, data->SrcAddr); if (!neighbor) { return; } - ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, neighbor->index); - if (!ws_neighbor) { - return; - } - - etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor->index); - ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor, ws_utt, data->timestamp); - ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor, ws_us); + etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, ws_neighbor_class_entry_index_get(&cur->ws_info->neighbor_storage,neighbor)); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor, ws_us); // Save the best network parent @@ -388,16 +412,13 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) { - mac_neighbor_table_entry_t *neighbor = ws_bootstrap_add_neighbor(cur, data->SrcAddr); + ws_neighbor_class_entry_t *neighbor = ws_bootstrap_neighbor_add(cur, data->SrcAddr); if (!neighbor) { return; } - ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, neighbor->index); - if (!ws_neighbor) { - return; - } - ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor, ws_utt, data->timestamp); - ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor, ws_us); + + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor, ws_us); /* * An inconsistent transmission is defined as: @@ -463,20 +484,17 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry return; } - mac_neighbor_table_entry_t *neighbor = ws_bootstrap_add_neighbor(cur, data->SrcAddr); + ws_neighbor_class_entry_t *neighbor = ws_bootstrap_neighbor_add(cur, data->SrcAddr); if (!neighbor) { return; } - ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, neighbor->index); - if (!ws_neighbor) { - return; - } - etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor->index); + + etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, ws_neighbor_class_entry_index_get(&cur->ws_info->neighbor_storage,neighbor)); //Update Neighbor Broadcast and Unicast Parameters - ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor, ws_utt, data->timestamp); - ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor, ws_us); - ws_neighbor_class_neighbor_broadcast_time_info_update(ws_neighbor, &ws_bt_ie, data->timestamp); - ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor, &ws_bs_ie); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor, ws_us); + ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor, &ws_bt_ie, data->timestamp); + ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor, &ws_bs_ie); if (cur->ws_info->configuration_learned && @@ -504,6 +522,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry */ tr_info("Updated PAN configuration heard"); + cur->ws_info->pan_version_timeout_timer = PAN_VERSION_TIMEOUT; cur->ws_info->pan_configuration.pan_version = pan_version; memcpy(cur->ws_info->gtkhash,gtkhash_ptr,32); @@ -531,17 +550,13 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in return; } - mac_neighbor_table_entry_t *neighbor = ws_bootstrap_add_neighbor(cur, data->SrcAddr); + ws_neighbor_class_entry_t *neighbor = ws_bootstrap_neighbor_add(cur, data->SrcAddr); if (!neighbor) { return; } - ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, neighbor->index); - if (!ws_neighbor) { - return; - } - ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor, ws_utt, data->timestamp); - ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor, ws_us); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor, ws_us); /* * A consistent transmission is defined as a PAN Configuration Solicit with @@ -643,6 +658,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt protocol_interface_info_entry_t *cur = user_data; + topo_trace(TOPOLOGY_MLE, entry_ptr->ext64, TOPO_REMOVE); // Sleepy host if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) { mac_data_poll_protocol_poll_mode_decrement(cur); @@ -654,14 +670,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_ptr->mac16); protocol_6lowpan_release_long_link_address_from_neighcache(cur, entry_ptr->mac64); } - mac_helper_devicetable_remove(cur->mac_api, entry_ptr->index); - - //Remove WS neighbor data - ws_neighbor_class_entry_remove(&cur->ws_info->neighbor_storage, entry_ptr->index); - topo_trace(TOPOLOGY_MLE, entry_ptr->ext64, TOPO_REMOVE); - - //SET ETX to infinity - etx_neighbor_remove(cur->id, entry_ptr->index); + ws_bootstrap_neighbor_delete(cur,entry_ptr->index); } @@ -850,6 +859,8 @@ static void ws_bootstrap_ip_stack_activate(protocol_interface_info_entry_t *cur) tr_debug("ip stack init"); clear_power_state(ICMP_ACTIVE); cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; + ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); + } static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) { @@ -865,7 +876,11 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) } else if(event == RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS) { // RPL gave up so we need to re-trigger network scan. // TODO is this correct? + // TODO no! ws_bootstrap_event_configuration_start(cur); causes failure to + // We could send solicit for configuration and then select new parent when those arrive + /* This is done after address deletion, so RPL can act on them */ ws_bootstrap_event_configuration_start(cur); + } cur->ws_info->rpl_state = event; tr_info("RPL event %d", event); @@ -917,12 +932,40 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) tr_debug("router discovery start"); ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); cur->nwk_nd_re_scan_count = 0; + cur->ws_info->configuration_learned = false; + cur->ws_info->pan_version_timeout_timer = 0; + // Clear parent info + memset(cur->ws_info->parent_info.addr,0,8); + + // Clear learned neighbours + ws_bootstrap_neighbor_list_clean(cur); + // Reset advertisement solicit trickle to start discovering network trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &trickle_params_pan_configuration); trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &trickle_params_pan_configuration); + +} +// Start configuration learning +static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur) +{ + tr_debug("router configuration learn start"); + ws_bootstrap_state_change(cur, ER_SCAN); + + cur->ws_info->configuration_learned = false; + cur->ws_info->pan_version_timeout_timer = 0; + rpl_control_remove_domain_from_interface(cur); + ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); // Clear parent info memset(cur->ws_info->parent_info.addr,0,8); + // Clear learned neighbours + ws_bootstrap_neighbor_list_clean(cur); + + // Reset advertisement solicit trickle to start discovering network + trickle_start(&cur->ws_info->trickle_pan_config_solicit, &trickle_params_pan_configuration); + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config_solicit, &trickle_params_pan_configuration); + + } /* @@ -1070,6 +1113,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->pan_configuration.version = WS_FAN_VERSION_1_0; cur->ws_info->hopping_schdule.channel_function = WS_FIXED_CHANNEL; ws_llc_set_gtkhash(cur, cur->ws_info->gtkhash); + cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME; ws_bootstrap_fhss_activate(cur); ws_bootstrap_event_operation_start(cur); break; @@ -1087,13 +1131,12 @@ static void ws_bootstrap_event_handler(arm_event_s *event) break; case WS_CONFIGURATION_START: tr_info("Configuration start"); - // TODO temporary learn from parent - // Start solicit tricklle - // TODO process state after first Config go to operation - trickle_start(&cur->ws_info->trickle_pan_config_solicit, &trickle_params_pan_configuration); - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config_solicit, &trickle_params_pan_configuration); - ws_bootstrap_state_change(cur, ER_SCAN); - cur->ws_info->configuration_learned = false; + trickle_stop(&cur->ws_info->trickle_pan_advertisement); + trickle_stop(&cur->ws_info->trickle_pan_config); + + // Build list of possible neighbours and learn first broadcast schedule + + ws_bootstrap_start_configuration_learn(cur); break; case WS_OPERATION_START: tr_info("operation start"); @@ -1253,7 +1296,29 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s tr_info("Send PAN configuration"); ws_bootstrap_pan_config(cur); } + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + // update version number + if (cur->ws_info->pan_version_timer > seconds ) { + cur->ws_info->pan_version_timer -= seconds; + } else { + // Border router has timed out + tr_debug("Border router version number update"); + cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME; + cur->ws_info->pan_configuration.pan_version++; + // Inconsistent for border router to make information distribute faster + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config,&trickle_params_pan_configuration); + } + } + if (cur->ws_info->pan_version_timeout_timer){ + // PAN version timer running + if (cur->ws_info->pan_version_timeout_timer > seconds ) { + cur->ws_info->pan_version_timeout_timer -= seconds; + } else { + // Border router has timed out + tr_warn("Border router has timed out"); + ws_bootstrap_event_discovery_start(cur); + } + } } - #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 669ceaf8825..f968d1d1175 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -49,6 +49,8 @@ typedef struct ws_info_s { trickle_t trickle_pan_advertisement; uint8_t rpl_state; // state from rpl_event_t parent_info_t parent_info; + 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 configuration_learned:1; diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index f362448c97d..80973c4b785 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -30,4 +30,23 @@ #define WS_RPL_DIO_DOUBLING 2 #define WS_RPL_DIO_REDUDANCY 1 + +/* Border router version change interval + * + * Minimum interval at which a Border Router shall increment its PAN Version value. + */ + +#define PAN_VERSION_LIFETIME 240 + +/* Border router connection lost timeout + * + * Interval within which a node expects to detect a change in PAN Version + * (delivered via a PAN Configuration frame / PAN-IE). + * + * the maximum Trickle interval specified for DISC_IMAX (32 minutes). + * + */ + +#define PAN_VERSION_TIMEOUT 1920 + #endif /* WS_CONFIG_H_ */ diff --git a/source/6LoWPAN/ws/ws_neighbor_class.c b/source/6LoWPAN/ws/ws_neighbor_class.c index b6ab720d95e..a132167bbf0 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/source/6LoWPAN/ws/ws_neighbor_class.c @@ -59,6 +59,14 @@ ws_neighbor_class_entry_t * ws_neighbor_class_entry_get(ws_neighbor_class_t *cla return entry; } +uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry) +{ + if (!class_data->neigh_info_list) { + return 0xff; + } + return entry - class_data->neigh_info_list; +} + void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t attribute_index) { ws_neighbor_class_entry_t *entry = ws_neighbor_class_entry_get(class_data, attribute_index); diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index 10612aa4d5f..4ed281df9f1 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -64,6 +64,18 @@ void ws_neighbor_class_dealloc(ws_neighbor_class_t *class_data); * */ ws_neighbor_class_entry_t * ws_neighbor_class_entry_get(ws_neighbor_class_t *class_data, uint8_t attribute_index); + +/** + * ws_neighbor_class_entry_t a function for search hopping info for giving neighbor attribute index + * + * \param class_data pointer to structure which will be initialized by this function + * \param entry which attribute index is counted. + * + * \return Attribute index of entry + * + */ +uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry); + /** * ws_neighbor_class_entry_remove a function for clean information should be call when neighbor is removed * diff --git a/test/nanostack/unittest/stub/ws_neighbour_class_stub.c b/test/nanostack/unittest/stub/ws_neighbour_class_stub.c index 53657941437..4b44e265c4e 100644 --- a/test/nanostack/unittest/stub/ws_neighbour_class_stub.c +++ b/test/nanostack/unittest/stub/ws_neighbour_class_stub.c @@ -58,6 +58,12 @@ ws_neighbor_class_entry_t * ws_neighbor_class_entry_get(ws_neighbor_class_t *cla return ws_neighbor_stub.neigh_entry; } +uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry) +{ + return 0; +} + + void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t attribute_index) {