Skip to content

Commit

Permalink
Merge pull request ARMmbed#1818 from ARMmbed/nud_statemachine
Browse files Browse the repository at this point in the history
Nud statemachine Update and some fix's
  • Loading branch information
Juha Heiskanen authored Sep 19, 2018
2 parents e7d551c + a2b8491 commit d6086d0
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 40 deletions.
2 changes: 2 additions & 0 deletions source/6LoWPAN/adaptation_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,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;
}
Expand Down
4 changes: 2 additions & 2 deletions source/6LoWPAN/ws/ws_bbr_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
// We update the RPL version in same time to allow nodes to reselect parent
// As configuration is made so that devices cant move downward in dodag this allows it
// TODO think the correct rate for this
if (cur->ws_info->pan_information.pan_version % 3 == 0) {
// Third the rate of configuration version change at default 12 minutes
if ( cur->ws_info->pan_information.pan_version && cur->ws_info->pan_information.pan_version % RPL_VERSION_LIFETIME / PAN_VERSION_LIFETIME == 0) {
// Third the rate of configuration version change at default 5 hours
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
}
}
Expand Down
222 changes: 194 additions & 28 deletions source/6LoWPAN/ws/ws_bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,134 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t
return eventOS_event_send(&event);
}

static void ws_nud_table_reset(protocol_interface_info_entry_t *cur)
{
//Empty active list
ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) {
ns_list_remove(&cur->ws_info->active_nud_process, entry);
}

//Empty free list
ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->free_nud_entries) {
ns_list_remove(&cur->ws_info->free_nud_entries, entry);
}
//Add to free list to full
for (int i=0; i< ACTIVE_NUD_PROCESS_MAX; i++) {
ns_list_add_to_end(&cur->ws_info->free_nud_entries, &cur->ws_info->nud_table_entrys[i]);
}
}

static ws_nud_table_entry_t *ws_nud_entry_get_free(protocol_interface_info_entry_t *cur)
{
ws_nud_table_entry_t *entry = ns_list_get_first(&cur->ws_info->free_nud_entries);
if (entry) {
entry->wait_response = false;
entry->retry_count = 0;
entry->nud_process = false;
entry->timer = randLIB_get_random_in_range(1, 900);
entry->neighbor_info = NULL;
ns_list_remove(&cur->ws_info->free_nud_entries, entry);
ns_list_add_to_end(&cur->ws_info->active_nud_process, entry);
}
return entry;
}


void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor)
{
ns_list_foreach(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) {
if (entry->neighbor_info == neighbor) {
mac_neighbor_table_entry_t *mac_neighbor = neighbor;
ns_list_remove(&cur->ws_info->active_nud_process, entry);
ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry);
if (mac_neighbor->nud_active) {
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_neighbor, mac_neighbor->link_lifetime);
}

mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor);
return;
}
}
}

static void ws_nud_state_clean(protocol_interface_info_entry_t *cur, ws_nud_table_entry_t *entry)
{
mac_neighbor_table_entry_t *neighbor = entry->neighbor_info;
ns_list_remove(&cur->ws_info->active_nud_process, entry);
ns_list_add_to_end(&cur->ws_info->free_nud_entries, entry);
if (neighbor->nud_active) {
neighbor->nud_active = false;
mac_neighbor_info(cur)->active_nud_process--;
}
}

static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor)
{
//Send NS
uint8_t ll_target[16];
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_target + 8, neighbor->mac64, 8);
ll_target[8] ^= 2;
tr_info("NUD generate NS %u", neighbor->index);
buffer_t * buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL);
if (buffer) {
protocol_push(buffer);
return true;
}
return false;
}

void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
{
//Convert TICKS to real milliseconds
if (ticks > 0xffff / 100) {
ticks = 0xffff;
} else {
ticks *= 100;
}

ns_list_foreach_safe(ws_nud_table_entry_t, entry, &cur->ws_info->active_nud_process) {
if (entry->timer <= ticks) {
//TX Process or timeout
if (entry->wait_response) {
//Timeout for NUD or Probe
if (entry->nud_process) {
tr_debug("NUD NA timeout");
if (entry->retry_count < 2) {
entry->timer = randLIB_get_random_in_range(1, 900);
entry->wait_response = false;
} else {
//Clear entry from active list
ws_nud_state_clean(cur, entry);
//Remove whole entry
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry->neighbor_info);
}
} else {
ws_nud_state_clean(cur, entry);
}

} else {
//Random TX wait period is over
entry->wait_response = ws_nud_message_build(cur, entry->neighbor_info);
if (!entry->wait_response) {
if (entry->nud_process && entry->retry_count < 2) {
entry->timer = randLIB_get_random_in_range(1, 900);
} else {
//Clear entry from active list
//Remove and try again later on
ws_nud_state_clean(cur, entry);
}
} else {
entry->retry_count++;
entry->timer = 5001;
}
}
} else {
entry->timer -= ticks;
}
}
}

static fhss_ws_neighbor_timing_info_t *ws_get_neighbor_info(const fhss_api_t *api, uint8_t eui64[8])
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_fhss_api(api);
Expand Down Expand Up @@ -331,26 +459,32 @@ static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry
{

fhss_ws_configuration_t fhss_configuration;
if (!neighbor_info->ws_neighbor->broadcast_timing_info_stored) {
tr_error("No BC timing info for set new parent");
return;
}

memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t));

ws_fhss_set_defaults(cur, &fhss_configuration);

// Learning broadcast network configuration
fhss_configuration.ws_bc_channel_function = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function;
if (fhss_configuration.ws_bc_channel_function == WS_FIXED_CHANNEL) {
cur->ws_info->hopping_schdule.bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel;
if (neighbor_info->ws_neighbor->broadcast_shedule_info_stored) {
fhss_configuration.ws_bc_channel_function = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function;
if (fhss_configuration.ws_bc_channel_function == WS_FIXED_CHANNEL) {
cur->ws_info->hopping_schdule.bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel;
}
fhss_configuration.bsi = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id;
fhss_configuration.fhss_bc_dwell_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval;
fhss_configuration.fhss_broadcast_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_interval;
fhss_configuration.broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel;

}
fhss_configuration.bsi = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id;
fhss_configuration.fhss_bc_dwell_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval;
fhss_configuration.fhss_broadcast_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_interval;
fhss_configuration.unicast_fixed_channel = cur->ws_info->fhss_uc_fixed_channel;
fhss_configuration.broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel;
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);

if (fhss_configuration.fhss_bc_dwell_interval && fhss_configuration.fhss_broadcast_interval) {
// We have broadcast schedule set up set the broadcast parent schedule
ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64, &neighbor_info->ws_neighbor->fhss_data.bc_timing_info);
}
// We have broadcast schedule set up set the broadcast parent schedule
ns_fhss_ws_set_parent(cur->ws_info->fhss_api, neighbor_info->neighbor->mac64, &neighbor_info->ws_neighbor->fhss_data.bc_timing_info);

// Update LLC to follow updated fhss settings
ws_bootstrap_llc_hopping_update(cur,&fhss_configuration);
Expand Down Expand Up @@ -380,11 +514,34 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr
ws_neighbor_class_entry_t *ws_neighbour = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, attribute_index);
etx_storage_t *etx_entry = etx_storage_entry_get(interface->id, attribute_index);

if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 ||
!ws_neighbour->candidate_parent) {
// if RSL value is not good enough candidate parent flag is removed and device not accepted as parent
//tr_debug("ws_etx_read not valid parent");
return 0xffff;
if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
if (!ws_neighbour || !etx_entry) {
return 0xffff;
}
} else {

if (!ws_neighbour || !etx_entry || etx_entry->etx_samples < 1 ||
!ws_neighbour->candidate_parent) {
// if RSL value is not good enough candidate parent flag is removed and device not accepted as parent
//tr_debug("ws_etx_read not valid parent");
return 0xffff;
}

#if 0
//If we are not following gbobal Broadcast synch
if (!interface->ws_info->pan_information.use_parent_bs) {
//We must know both information's here
if (!ws_neighbour->broadcast_shedule_info_stored ||
!ws_neighbour->broadcast_timing_info_stored) {
return 0xffff;
}
} else {
if (!ws_neighbour->broadcast_timing_info_stored) {
//Global shedule is stored already
return 0xffff;
}
}
#endif
}

etx = etx_local_etx_read(interface->id,attribute_index);
Expand Down Expand Up @@ -436,6 +593,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
/* Disable NUD Probes */
cur->ipv6_neighbour_cache.send_nud_probes = false;

ws_nud_table_reset(cur);

ws_bootstrap_event_discovery_start(cur);

return 0;
Expand All @@ -455,6 +614,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur)
// ws_common_reset(cur)
ws_llc_reset(cur);
nd_proxy_downstream_interface_unregister(cur->id);
ws_nud_table_reset(cur);

return nwk_6lowpan_down(cur);
}
Expand Down Expand Up @@ -746,12 +906,21 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
return;
}
}


}

if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
//Border router does not learn network information
return;
}

//Update synch to primary parent allways to update broadcast shedule and timing
if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
// RPL priority parent configuration we must update FHSS data
ws_bootstrap_primary_parent_set(cur, &neighbor_info);
}

if (cur->ws_info->configuration_learned &&
cur->ws_info->pan_information.pan_version == pan_version) {
// No new information
Expand All @@ -778,8 +947,8 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
// set neighbor as priority parent clear if there is others
protocol_6lowpan_neighbor_priority_clear_all(cur->id, PRIORITY_1ST);
neighbor_info.neighbor->link_role = PRIORITY_PARENT_NEIGHBOUR;
} else if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) {
// RPL priority parent configuration we must update FHSS data
} else if (neighbor_info.neighbor->link_role != PRIORITY_PARENT_NEIGHBOUR) {
//This cuold affect serious problem if BC parameters are changed
ws_bootstrap_primary_parent_set(cur, &neighbor_info);
}
}
Expand Down Expand Up @@ -1037,17 +1206,15 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
return false;
}


uint8_t ll_target[16];
memcpy(ll_target, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ll_target + 8, entry_ptr->mac64, 8);
ll_target[8] ^= 2;
tr_debug("NUD generate NS %u", entry_ptr->index);
buffer_t * buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL);
if (!buffer) {
ws_nud_table_entry_t *entry = ws_nud_entry_get_free(cur);
if (!entry) {
return false;
}
protocol_push(buffer);
entry->neighbor_info = entry_ptr;

if (etx_entry->etx_samples >= WS_NEIGBOR_ETX_SAMPLE_MAX) {
entry->nud_process = true;
}
return true;
}

Expand Down Expand Up @@ -1717,7 +1884,6 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur)
return;
}

ws_bootstrap_primary_parent_set(cur, &neighbor_info);
ws_bootstrap_network_information_learn(cur);
ws_bootstrap_fhss_activate(cur);
ws_bootstrap_event_authentication_start(cur);
Expand Down
4 changes: 4 additions & 0 deletions source/6LoWPAN/ws/ws_bootstrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t

void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);

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);

#else

#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
Expand Down
10 changes: 4 additions & 6 deletions source/6LoWPAN/ws/ws_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
}

memset(cur->ws_info,0, sizeof(ws_info_t));
ns_list_init(&cur->ws_info->active_nud_process);
ns_list_init(&cur->ws_info->free_nud_entries);

cur->ws_info->pan_information.use_parent_bs = true;
cur->ws_info->pan_information.rpl_routing_method = true;
Expand Down Expand Up @@ -172,6 +174,7 @@ void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seco
void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
{
ws_bootstrap_trickle_timer(cur, ticks);
ws_nud_active_timer(cur, ticks);
}


Expand All @@ -180,12 +183,7 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8
//Neighbor connectected update
mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL);
if (mac_neighbor) {
if (mac_neighbor->nud_active) {
tr_debug("NUD Response %u", mac_neighbor->index);
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_neighbor, mac_neighbor->link_lifetime);
}

mac_neighbor_table_neighbor_connected(mac_neighbor_info(cur), mac_neighbor);
ws_nud_entry_remove_active(cur, mac_neighbor);
}
}

Expand Down
Loading

0 comments on commit d6086d0

Please sign in to comment.