From e9e31e9fd11070d04cec5e37fd47c3c145bb82df Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 26 Nov 2015 20:26:10 +0100 Subject: [PATCH] replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information --- core/net/ipv6/uip-nd6.c | 77 ++++++++++++++++++++++++++--------------- core/net/nbr-table.c | 69 ++++++++++++++++++++++++++++-------- core/net/nbr-table.h | 1 + 3 files changed, 104 insertions(+), 43 deletions(-) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 62b3a64cb..d160392ed 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -136,7 +136,7 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ /*------------------------------------------------------------------*/ /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */ static void -extract_lladdr_aligned(uip_lladdr_t *dest) { +extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) { if(dest != NULL && nd6_opt_llao != NULL) { memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); } @@ -199,17 +199,29 @@ ns_input(void) goto discard; } else { #endif /*UIP_CONF_IPV6_CHECKS */ + uip_lladdr_t lladdr_aligned; + extract_lladdr_from_llao_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { +<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a uip_lladdr_t lladdr_aligned; extract_lladdr_aligned(&lladdr_aligned); uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); +======= + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); +>>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } else { if(nbr->state == NBR_INCOMPLETE) { @@ -495,10 +507,12 @@ na_input(void) if(nbr == NULL) { goto discard; } - lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(nd6_opt_llao != NULL) { - is_llchange = lladdr == NULL || + is_llchange = memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN); } @@ -507,17 +521,13 @@ na_input(void) if(nd6_opt_llao == NULL) { goto discard; } - extract_lladdr_aligned(&lladdr_aligned); - /* Remove this neighbor - since it has a NULL MAC address */ - uip_ds6_nbr_rm(nbr); - /* Re-add this neighbor - now with a correct MAC address */ - nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, - &lladdr_aligned, - is_router, NBR_STALE); - if(nbr == NULL) { + extract_lladdr_from_llao_aligned(&lladdr_aligned); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ goto discard; } + if(is_solicited) { nbr->state = NBR_REACHABLE; nbr->nscount = 0; @@ -529,7 +539,7 @@ na_input(void) nbr->state = NBR_STALE; } nbr->isrouter = is_router; - } else { + } else { /* NBR is not INCOMPLETE */ if(!is_override && is_llchange) { if(nbr->state == NBR_REACHABLE) { nbr->state = NBR_STALE; @@ -543,15 +553,9 @@ na_input(void) if(is_override || !is_llchange || nd6_opt_llao == NULL) { if(nd6_opt_llao != NULL && is_llchange) { uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); - - /* Remove this neighbor - since it has updated its MAC address */ - uip_ds6_nbr_rm(nbr); - /* Re-add this neighbor - now with a correct (new) MAC address */ - nbr = uip_ds6_nbr_add(&UIP_ND6_NA_BUF->tgtipaddr, - &lladdr_aligned, - is_router, NBR_STALE); - if(nbr == NULL) { + extract_lladdr_from_llao_aligned(&lladdr_aligned); + if(nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ goto discard; } } @@ -652,15 +656,19 @@ rs_input(void) } else { #endif /*UIP_CONF_IPV6_CHECKS */ uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); + extract_lladdr_from_llao_aligned(&lladdr_aligned); if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { /* we need to add the neighbor */ uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { /* If LL address changed, set neighbor state to stale */ + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) { + lladdr, UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_t nbr_data = *nbr; uip_ds6_nbr_rm(nbr); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, @@ -892,18 +900,31 @@ ra_input(void) nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { uip_lladdr_t lladdr_aligned; +<<<<<<< 2e852f758b3fbc18ad30ec75d8c62b5d5238e70a extract_lladdr_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); +======= + extract_lladdr_from_llao_aligned(&lladdr_aligned); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE); +>>>>>>> replaced add/remove ds6-nbr with an nbr-module controlled update of lladdress to avoid loss of other state information } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + uip_lladdr_t lladdr_aligned; + extract_lladdr_from_llao_aligned(&lladdr_aligned); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + /* change of link layer address */ + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } nbr->isrouter = 1; diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index ddae06fca..4a3518475 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -178,6 +178,26 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val return 0; } /*---------------------------------------------------------------------------*/ +static void +remove_key(nbr_table_key_t *least_used_key) +{ + int i; + for(i = 0; i < MAX_NUM_TABLES; i++) { + if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { + /* Call table callback for each table that uses this item */ + nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); + if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { + all_tables[i]->callback(removed_item); + } + } + } + /* Empty used map */ + used_map[index_from_key(least_used_key)] = 0; + /* Remove neighbor from list */ + list_remove(nbr_table_keys, least_used_key); + /* Return associated key */ +} + static nbr_table_key_t * nbr_table_allocate(nbr_table_reason_t reason, void *data) { @@ -253,21 +273,7 @@ nbr_table_allocate(nbr_table_reason_t reason, void *data) return NULL; } else { /* Reuse least used item */ - int i; - for(i = 0; icallback != NULL) { - /* Call table callback for each table that uses this item */ - nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); - if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { - all_tables[i]->callback(removed_item); - } - } - } - /* Empty used map */ - used_map[index_from_key(least_used_key)] = 0; - /* Remove neighbor from list */ - list_remove(nbr_table_keys, least_used_key); - /* Return associated key */ + remove_key(least_used_key); return least_used_key; } } @@ -416,6 +422,39 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item) return key != NULL ? &key->lladdr : NULL; } /*---------------------------------------------------------------------------*/ +/* Update link-layer address of an item */ +int +nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, + int remove_if_duplicate) +{ + int index; + int new_index; + nbr_table_key_t *key; + index = index_from_lladdr(old_addr); + if(index == -1) { + /* Failure to change since there is nothing to change. */ + return 0; + } + if((new_index = index_from_lladdr(new_addr)) != -1) { + /* check if it is a change or not - do not remove / fail if same */ + if(new_index == index) { + return 1; + } + /* This new entry already exists - failure! - remove if requested. */ + if(remove_if_duplicate) { + remove_key(key_from_index(index)); + } + return 0; + } + key = key_from_index(index); + /** + * Copy the new lladdr into the key - since we know that there is no + * conflicting entry. + */ + memcpy(&key->lladdr, new_addr, sizeof(linkaddr_t)); + return 1; +} +/*---------------------------------------------------------------------------*/ #if DEBUG static void print_table() diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index 88a90a46c..c797a44ec 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -109,6 +109,7 @@ int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item); /** \name Neighbor tables: address manipulation */ /** @{ */ linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item); +int nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, int remove_if_duplicate); /** @} */ #endif /* NBR_TABLE_H_ */