From ec609b49eb5300b6c21c0fe1d962092c7d15b87c Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Wed, 3 Jul 2013 19:32:26 +0200 Subject: [PATCH] Make DS6 neighbors use neighbor-table, and move all DS6 neighbor management from uip-ds6 to a new uip-ds6-neighbor module. --- core/net/Makefile.uip | 1 + core/net/rpl/rpl.c | 37 ++---- core/net/tcpip.c | 12 +- core/net/uip-ds6-neighbor.c | 248 ++++++++++++++++++++++++++++++++++++ core/net/uip-ds6-neighbor.h | 97 ++++++++++++++ core/net/uip-ds6.c | 206 +----------------------------- core/net/uip-ds6.h | 46 +------ core/net/uip-nd6.c | 29 +++-- 8 files changed, 386 insertions(+), 290 deletions(-) create mode 100644 core/net/uip-ds6-neighbor.c create mode 100644 core/net/uip-ds6-neighbor.h diff --git a/core/net/Makefile.uip b/core/net/Makefile.uip index c675bfe74..66ca1d0ec 100644 --- a/core/net/Makefile.uip +++ b/core/net/Makefile.uip @@ -18,6 +18,7 @@ uaodv-rt.c \ uaodv.c \ uip-debug.c \ uip-ds6-route.c \ +uip-ds6-neighbor.c \ uip-ds6.c \ uip-fw-drv.c \ uip-fw.c \ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 2e9a10e5a..a5cabef91 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -142,21 +142,6 @@ rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) } } ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); - -#if 0 - uip_ds6_route_t *locroute; - - for(locroute = uip_ds6_routing_table; - locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; - locroute++) { - if(locroute->isused - && uip_ipaddr_cmp(&locroute->nexthop, nexthop) - && locroute->state.dag == dag) { - locroute->isused = 0; - } - } - ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); -#endif /* 0 */ } /*---------------------------------------------------------------------------*/ uip_ds6_route_t * @@ -242,18 +227,16 @@ rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) rpl_instance_t *instance; rpl_instance_t *end; - if(!nbr->isused) { - PRINTF("RPL: Removing neighbor "); - PRINT6ADDR(&nbr->ipaddr); - PRINTF("\n"); - for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { - if(instance->used == 1 ) { - p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); - if(p != NULL) { - p->rank = INFINITE_RANK; - /* Trigger DAG rank recalculation. */ - p->updated = 1; - } + PRINTF("RPL: Removing neighbor "); + PRINT6ADDR(&nbr->ipaddr); + PRINTF("\n"); + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 1 ) { + p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); + if(p != NULL) { + p->rank = INFINITE_RANK; + /* Trigger DAG rank recalculation. */ + p->updated = 1; } } } diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 20e504bc7..81a2f2e60 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -567,6 +567,7 @@ tcpip_ipv6_output(void) uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { + PRINTF("tcpip_ipv6_output: no route found, using default route\n"); if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", @@ -588,11 +589,14 @@ tcpip_ipv6_output(void) } else { nexthop = &locrt->nexthop; } -#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { + PRINTF("tcpip_ipv6_output: next hop "); + PRINT6ADDR(nexthop); + PRINTF("\n"); +#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); - } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ + } } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL @@ -655,7 +659,7 @@ tcpip_ipv6_output(void) } #endif /* UIP_ND6_SEND_NA */ - tcpip_output(&nbr->lladdr); + tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* @@ -668,7 +672,7 @@ tcpip_ipv6_output(void) uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); - tcpip_output(&nbr->lladdr); + tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ diff --git a/core/net/uip-ds6-neighbor.c b/core/net/uip-ds6-neighbor.c new file mode 100644 index 000000000..e5dd36897 --- /dev/null +++ b/core/net/uip-ds6-neighbor.c @@ -0,0 +1,248 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/* + * Copyright (c) 2013, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * + */ + +/** + * \file + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * \author Mathilde Durvy + * \author Julien Abeille + * \author Simon Duquennoy + * + */ + +#include +#include +#include +#include "lib/list.h" +#include "net/rime/rimeaddr.h" +#include "net/packetbuf.h" +#include "net/uip-ds6-neighbor.h" + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +#ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED +#define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n) +void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n); +#else +#define NEIGHBOR_STATE_CHANGED(n) +#endif /* UIP_DS6_CONF_NEIGHBOR_STATE_CHANGED */ + +NEIGHBOR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors); + +/*---------------------------------------------------------------------------*/ +void +uip_ds6_neighbors_init(void) +{ + nbr_table_register(ds6_neighbors, (remove_callback_func *)uip_ds6_nbr_rm); +} +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, + uint8_t isrouter, uint8_t state) +{ + uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (rimeaddr_t*)lladdr); + if(nbr) { + uip_ipaddr_copy(&nbr->ipaddr, ipaddr); + nbr->isrouter = isrouter; + nbr->state = state; + #if UIP_CONF_IPV6_QUEUE_PKT + uip_packetqueue_new(&nbr->packethandle); + #endif /* UIP_CONF_IPV6_QUEUE_PKT */ + /* timers are set separately, for now we put them in expired state */ + stimer_set(&nbr->reachable, 0); + stimer_set(&nbr->sendns, 0); + nbr->nscount = 0; + PRINTF("Adding neighbor with ip addr "); + PRINT6ADDR(ipaddr); + PRINTF(" link addr "); + PRINTLLADDR(lladdr); + PRINTF(" state %u\n", state); + NEIGHBOR_STATE_CHANGED(nbr); + return nbr; + } else { + PRINTF("uip_ds6_nbr_add drop ip addr "); + PRINT6ADDR(ipaddr); + PRINTF(" link addr (%p) ", lladdr); + PRINTLLADDR(lladdr); + PRINTF(" state %u\n", state); + return NULL; + } +} + +/*---------------------------------------------------------------------------*/ +void +uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) +{ + if(nbr != NULL) { +#if UIP_CONF_IPV6_QUEUE_PKT + uip_packetqueue_free(&nbr->packethandle); +#endif /* UIP_CONF_IPV6_QUEUE_PKT */ + NEIGHBOR_STATE_CHANGED(nbr); + nbr_table_remove(ds6_neighbors, nbr); + } + return; +} + +/*---------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_ds6_nbr_get_ipaddr(uip_ds6_nbr_t *nbr) +{ + return (nbr != NULL) ? &nbr->ipaddr : NULL; +} + +/*---------------------------------------------------------------------------*/ +uip_lladdr_t * +uip_ds6_nbr_get_ll(uip_ds6_nbr_t *nbr) +{ + return (uip_lladdr_t *)nbr_table_get_lladdr(ds6_neighbors, nbr); +} + +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr) +{ + uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + if(uip_ipaddr_cmp(&nbr->ipaddr, ipaddr)) { + return nbr; + } + nbr = nbr_table_next(ds6_neighbors, nbr); + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr) +{ + return nbr_table_get_from_lladdr(ds6_neighbors, (rimeaddr_t*)lladdr); +} + +/*---------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_ds6_nbr_ipaddr_from_lladdr(uip_lladdr_t *lladdr) +{ + uip_ds6_nbr_t *nbr = uip_ds6_nbr_ll_lookup(lladdr); + return nbr ? &nbr->ipaddr : NULL; +} + +/*---------------------------------------------------------------------------*/ +uip_lladdr_t * +uip_ds6_nbr_lladdr_from_ipaddr(uip_ipaddr_t *ipaddr) +{ + uip_ds6_nbr_t *nbr = uip_ds6_nbr_lookup(ipaddr); + return nbr ? uip_ds6_nbr_get_ll(nbr) : NULL; +} + +/*---------------------------------------------------------------------------*/ +void +uip_ds6_neighbor_periodic() +{ + /* Periodic processing on neighbors */ + uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + switch(nbr->state) { + case NBR_REACHABLE: + if(stimer_expired(&nbr->reachable)) { + PRINTF("REACHABLE: moving to STALE ("); + PRINT6ADDR(&nbr->ipaddr); + PRINTF(")\n"); + nbr->state = NBR_STALE; + } + break; +#if UIP_ND6_SEND_NA + case NBR_INCOMPLETE: + if(nbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { + uip_ds6_nbr_rm(nbr); + } else if(stimer_expired(&nbr->sendns) && (uip_len == 0)) { + nbr->nscount++; + PRINTF("NBR_INCOMPLETE: NS %u\n", nbr->nscount); + uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); + stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); + } + break; + case NBR_DELAY: + if(stimer_expired(&nbr->reachable)) { + nbr->state = NBR_PROBE; + nbr->nscount = 0; + PRINTF("DELAY: moving to PROBE\n"); + stimer_set(&nbr->sendns, 0); + } + break; + case NBR_PROBE: + if(nbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) { + uip_ds6_defrt_t *locdefrt; + PRINTF("PROBE END\n"); + if((locdefrt = uip_ds6_defrt_lookup(&nbr->ipaddr)) != NULL) { + if (!locdefrt->isinfinite) { + uip_ds6_defrt_rm(locdefrt); + } + } + uip_ds6_nbr_rm(nbr); + } else if(stimer_expired(&nbr->sendns) && (uip_len == 0)) { + nbr->nscount++; + PRINTF("PROBE: NS %u\n", nbr->nscount); + uip_nd6_ns_output(NULL, &nbr->ipaddr, &nbr->ipaddr); + stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); + } + break; +#endif /* UIP_ND6_SEND_NA */ + default: + break; + } + nbr = nbr_table_next(ds6_neighbors, nbr); + } +} + +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +uip_ds6_get_least_lifetime_neighbor(void) +{ + uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors); + uip_ds6_nbr_t *nbr_expiring = NULL; + while(nbr != NULL) { + if(nbr_expiring != NULL) { + clock_time_t curr = stimer_remaining(&nbr->reachable); + if(curr < stimer_remaining(&nbr->reachable)) { + nbr_expiring = nbr; + } + } else { + nbr_expiring = nbr; + } + nbr = nbr_table_next(ds6_neighbors, nbr); + } + return nbr_expiring; +} diff --git a/core/net/uip-ds6-neighbor.h b/core/net/uip-ds6-neighbor.h new file mode 100644 index 000000000..686fb6abd --- /dev/null +++ b/core/net/uip-ds6-neighbor.h @@ -0,0 +1,97 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/* + * Copyright (c) 2013, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * + */ + +/** + * \file + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * \author Mathilde Durvy + * \author Julien Abeille + * \author Simon Duquennoy + * + */ + +#ifndef __UIP_DS6_NEIGHBOR_H__ +#define __UIP_DS6_NEIGHBOR_H__ + +#include "net/uip-ds6.h" +#include "net/neighbor-table.h" + +#if UIP_CONF_IPV6_QUEUE_PKT +#include "net/uip-packetqueue.h" +#endif /*UIP_CONF_QUEUE_PKT */ + +NEIGHBOR_TABLE_DECLARE(ds6_neighbors); + +/** \brief An entry in the nbr cache */ +typedef struct uip_ds6_nbr { + uip_ipaddr_t ipaddr; + struct stimer reachable; + struct stimer sendns; + uint8_t nscount; + uint8_t isrouter; + uint8_t state; +#if UIP_CONF_IPV6_QUEUE_PKT + struct uip_packetqueue_handle packethandle; +#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 +#endif /*UIP_CONF_QUEUE_PKT */ +} uip_ds6_nbr_t; + +void uip_ds6_neighbors_init(void); + +/** \brief Neighbor Cache basic routines */ +uip_ds6_nbr_t *uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, + uint8_t isrouter, uint8_t state); +void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); +uip_lladdr_t *uip_ds6_nbr_get_ll(uip_ds6_nbr_t *nbr); +uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(uip_ds6_nbr_t *nbr); +uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); +uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr); +uip_ipaddr_t *uip_ds6_nbr_ipaddr_from_lladdr(uip_lladdr_t *lladdr); +uip_lladdr_t *uip_ds6_nbr_lladdr_from_ipaddr(uip_ipaddr_t *ipaddr); +void uip_ds6_neighbor_periodic(); + +/** + * \brief + * This searches inside the neighbor table for the neighbor that is about to + * expire the next. + * + * \return + * A reference to the neighbor about to expire the next or NULL if + * table is empty. + */ +uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void); + +#endif /* __UIP_DS6_NEIGHBOR_H__ */ diff --git a/core/net/uip-ds6.c b/core/net/uip-ds6.c index 354583d5a..41e97bfd6 100644 --- a/core/net/uip-ds6.c +++ b/core/net/uip-ds6.c @@ -53,13 +53,6 @@ #define DEBUG DEBUG_NONE #include "net/uip-debug.h" -#ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED -#define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n) -void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n); -#else -#define NEIGHBOR_STATE_CHANGED(n) -#endif /* UIP_DS6_CONF_NEIGHBOR_STATE_CHANGED */ - struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */ #if UIP_CONF_ROUTER @@ -76,10 +69,7 @@ static uint8_t rscount; /** \brief numbe /** \name "DS6" Data structures */ /** @{ */ uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */ -uip_ds6_nbr_t uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; /** \brief Neighor cache */ -//uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; /** \brief Default rt list */ uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */ -//uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; /** \brief Routing table */ /* Used by Cooja to enable extraction of addresses from memory.*/ uint8_t uip_ds6_addr_size; @@ -95,25 +85,21 @@ static uip_ds6_addr_t *locaddr; static uip_ds6_maddr_t *locmaddr; static uip_ds6_aaddr_t *locaaddr; static uip_ds6_prefix_t *locprefix; -static uip_ds6_nbr_t *locnbr; -static uip_ds6_defrt_t *locdefrt; /*---------------------------------------------------------------------------*/ void uip_ds6_init(void) { + uip_ds6_neighbors_init(); uip_ds6_route_init(); PRINTF("Init of IPv6 data structures\n"); PRINTF("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n", - UIP_DS6_NBR_NB, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB, + NEIGHBOR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB, UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB); - memset(uip_ds6_nbr_cache, 0, sizeof(uip_ds6_nbr_cache)); - // memset(uip_ds6_defrt_list, 0, sizeof(uip_ds6_defrt_list)); memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list)); memset(&uip_ds6_if, 0, sizeof(uip_ds6_if)); - // memset(uip_ds6_routing_table, 0, sizeof(uip_ds6_routing_table)); uip_ds6_addr_size = sizeof(struct uip_ds6_addr); uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list); @@ -198,61 +184,7 @@ uip_ds6_periodic(void) } #endif /* !UIP_CONF_ROUTER */ - /* Periodic processing on neighbors */ - for(locnbr = uip_ds6_nbr_cache; - locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; - locnbr++) { - if(locnbr->isused) { - switch(locnbr->state) { - case NBR_REACHABLE: - if(stimer_expired(&locnbr->reachable)) { - PRINTF("REACHABLE: moving to STALE ("); - PRINT6ADDR(&locnbr->ipaddr); - PRINTF(")\n"); - locnbr->state = NBR_STALE; - } - break; -#if UIP_ND6_SEND_NA - case NBR_INCOMPLETE: - if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { - uip_ds6_nbr_rm(locnbr); - } else if(stimer_expired(&locnbr->sendns) && (uip_len == 0)) { - locnbr->nscount++; - PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount); - uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr); - stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000); - } - break; - case NBR_DELAY: - if(stimer_expired(&locnbr->reachable)) { - locnbr->state = NBR_PROBE; - locnbr->nscount = 0; - PRINTF("DELAY: moving to PROBE\n"); - stimer_set(&locnbr->sendns, 0); - } - break; - case NBR_PROBE: - if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) { - PRINTF("PROBE END\n"); - if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) { - if (!locdefrt->isinfinite) { - uip_ds6_defrt_rm(locdefrt); - } - } - uip_ds6_nbr_rm(locnbr); - } else if(stimer_expired(&locnbr->sendns) && (uip_len == 0)) { - locnbr->nscount++; - PRINTF("PROBE: NS %u\n", locnbr->nscount); - uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr); - stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000); - } - break; -#endif /* UIP_ND6_SEND_NA */ - default: - break; - } - } - } + uip_ds6_neighbor_periodic(); #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA /* Periodic RA sending */ @@ -291,118 +223,6 @@ uip_ds6_list_loop(uip_ds6_element_t *list, uint8_t size, return *out_element != NULL ? FREESPACE : NOSPACE; } -/*---------------------------------------------------------------------------*/ -uip_ds6_nbr_t * -uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state) -{ - int r; - - r = uip_ds6_list_loop - ((uip_ds6_element_t *)uip_ds6_nbr_cache, UIP_DS6_NBR_NB, - sizeof(uip_ds6_nbr_t), ipaddr, 128, - (uip_ds6_element_t **)&locnbr); - - if(r == FREESPACE) { - locnbr->isused = 1; - uip_ipaddr_copy(&locnbr->ipaddr, ipaddr); - if(lladdr != NULL) { - memcpy(&locnbr->lladdr, lladdr, UIP_LLADDR_LEN); - } else { - memset(&locnbr->lladdr, 0, UIP_LLADDR_LEN); - } - locnbr->isrouter = isrouter; - locnbr->state = state; -#if UIP_CONF_IPV6_QUEUE_PKT - uip_packetqueue_new(&locnbr->packethandle); -#endif /* UIP_CONF_IPV6_QUEUE_PKT */ - /* timers are set separately, for now we put them in expired state */ - stimer_set(&locnbr->reachable, 0); - stimer_set(&locnbr->sendns, 0); - locnbr->nscount = 0; - PRINTF("Adding neighbor with ip addr "); - PRINT6ADDR(ipaddr); - PRINTF("link addr "); - PRINTLLADDR((&(locnbr->lladdr))); - PRINTF("state %u\n", state); - NEIGHBOR_STATE_CHANGED(locnbr); - - locnbr->last_lookup = clock_time(); - return locnbr; - } else if(r == NOSPACE) { - /* We did not find any empty slot on the neighbor list, so we need - to remove one old entry to make room. */ - uip_ds6_nbr_t *n, *oldest; - clock_time_t oldest_time; - - oldest = NULL; - oldest_time = clock_time(); - - for(n = uip_ds6_nbr_cache; - n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; - n++) { - if(n->isused && !uip_ds6_defrt_lookup(&n->ipaddr)) { - if(n->last_lookup < oldest_time) { - oldest = n; - oldest_time = n->last_lookup; - } - } - } - if(oldest != NULL) { - uip_ds6_nbr_rm(oldest); - return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state); - } - } - PRINTF("uip_ds6_nbr_add drop\n"); - return NULL; -} - -/*---------------------------------------------------------------------------*/ -void -uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) -{ - if(nbr != NULL) { - nbr->isused = 0; -#if UIP_CONF_IPV6_QUEUE_PKT - uip_packetqueue_free(&nbr->packethandle); -#endif /* UIP_CONF_IPV6_QUEUE_PKT */ - NEIGHBOR_STATE_CHANGED(nbr); - } - return; -} - -/*---------------------------------------------------------------------------*/ -uip_ds6_nbr_t * -uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr) -{ - if(uip_ds6_list_loop - ((uip_ds6_element_t *)uip_ds6_nbr_cache, UIP_DS6_NBR_NB, - sizeof(uip_ds6_nbr_t), ipaddr, 128, - (uip_ds6_element_t **)&locnbr) == FOUND) { - locnbr->last_lookup = clock_time(); - return locnbr; - } - return NULL; -} - -/*---------------------------------------------------------------------------*/ -uip_ds6_nbr_t * -uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr) -{ - uip_ds6_nbr_t *fin; - - for(locnbr = uip_ds6_nbr_cache, fin = locnbr + UIP_DS6_NBR_NB; - locnbr < fin; - ++locnbr) { - if(locnbr->isused) { - if(!memcmp(lladdr, &locnbr->lladdr, UIP_LLADDR_LEN)) { - return locnbr; - } - } - } - return NULL; -} - /*---------------------------------------------------------------------------*/ #if UIP_CONF_ROUTER /*---------------------------------------------------------------------------*/ @@ -878,25 +698,5 @@ uip_ds6_compute_reachable_time(void) UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time)); } /*---------------------------------------------------------------------------*/ -uip_ds6_nbr_t * -uip_ds6_get_least_lifetime_neighbor(void) -{ - uip_ds6_nbr_t *nbr_expiring = NULL; - uint8_t i; - for(i = 0; i < UIP_DS6_NBR_NB; i++) { - if(uip_ds6_nbr_cache[i].isused) { - if(nbr_expiring != NULL) { - clock_time_t curr = stimer_remaining(&uip_ds6_nbr_cache[i].reachable); - if(curr < stimer_remaining(&nbr_expiring->reachable)) { - nbr_expiring = &uip_ds6_nbr_cache[i]; - } - } else { - nbr_expiring = &uip_ds6_nbr_cache[i]; - } - } - } - return nbr_expiring; -} -/*---------------------------------------------------------------------------*/ /** @} */ #endif /* UIP_CONF_IPV6 */ diff --git a/core/net/uip-ds6.h b/core/net/uip-ds6.h index 556dc8629..e0d032c96 100644 --- a/core/net/uip-ds6.h +++ b/core/net/uip-ds6.h @@ -47,6 +47,7 @@ /* The size of uip_ds6_addr_t depends on UIP_ND6_DEF_MAXDADNS. Include uip-nd6.h to define it. */ #include "net/uip-nd6.h" #include "net/uip-ds6-route.h" +#include "net/uip-ds6-neighbor.h" /*--------------------------------------------------*/ /** Configuration. For all tables (Neighbor cache, Prefix List, Routing Table, @@ -56,14 +57,6 @@ * - the number of elements assigned by the system (name suffixed by _NBS) * - the total number of elements is the sum (name suffixed by _NB) */ -/* Neighbor cache */ -#define UIP_DS6_NBR_NBS 0 -#ifndef UIP_CONF_DS6_NBR_NBU -#define UIP_DS6_NBR_NBU 4 -#else -#define UIP_DS6_NBR_NBU UIP_CONF_DS6_NBR_NBU -#endif -#define UIP_DS6_NBR_NB UIP_DS6_NBR_NBS + UIP_DS6_NBR_NBU /* Default router list */ #define UIP_DS6_DEFRT_NBS 0 @@ -155,22 +148,6 @@ #if UIP_CONF_IPV6_QUEUE_PKT #include "net/uip-packetqueue.h" #endif /*UIP_CONF_QUEUE_PKT */ -/** \brief An entry in the nbr cache */ -typedef struct uip_ds6_nbr { - uint8_t isused; - uip_ipaddr_t ipaddr; - uip_lladdr_t lladdr; - struct stimer reachable; - struct stimer sendns; - clock_time_t last_lookup; - uint8_t nscount; - uint8_t isrouter; - uint8_t state; -#if UIP_CONF_IPV6_QUEUE_PKT - struct uip_packetqueue_handle packethandle; -#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 -#endif /*UIP_CONF_QUEUE_PKT */ -} uip_ds6_nbr_t; /** \brief A prefix list entry */ #if UIP_CONF_ROUTER @@ -226,8 +203,6 @@ typedef struct uip_ds6_maddr { #endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ #endif /* UIP_CONF_IPV6_RPL */ - - /** \brief Interface structure (contains all the interface variables) */ typedef struct uip_ds6_netif { uint32_t link_mtu; @@ -273,14 +248,6 @@ uint8_t uip_ds6_list_loop(uip_ds6_element_t *list, uint8_t size, uint8_t ipaddrlen, uip_ds6_element_t **out_element); -/** \name Neighbor Cache basic routines */ -/** @{ */ -uip_ds6_nbr_t *uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state); -void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); -uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); -uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr); - /** @} */ @@ -371,15 +338,4 @@ uint32_t uip_ds6_compute_reachable_time(void); /** \brief compute random reachab /** @} */ /** @} */ -/** - * \brief - * This searches inside the neighbor table for the neighbor that is about to - * expire the next. - * - * \return - * A reference to the neighbor about to expire the next or NULL if - * table is empty. - */ -uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void); - #endif /* __UIP_DS6_H__ */ diff --git a/core/net/uip-nd6.c b/core/net/uip-nd6.c index 868032872..30424713a 100644 --- a/core/net/uip-nd6.c +++ b/core/net/uip-nd6.c @@ -191,9 +191,10 @@ uip_nd6_ns_input(void) (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); } else { + uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - &nbr->lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(&nbr->lladdr, &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); nbr->state = NBR_STALE; } else { @@ -460,20 +461,22 @@ uip_nd6_na_input(void) PRINTF("NA received is bad\n"); goto discard; } else { + uip_lladdr_t *lladdr; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); + lladdr = uip_ds6_nbr_get_ll(nbr); if(nbr == NULL) { goto discard; } if(nd6_opt_llao != 0) { is_llchange = - memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)(&nbr->lladdr), + memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr, UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { if(nd6_opt_llao == NULL) { goto discard; } - memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], + memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); if(is_solicited) { nbr->state = NBR_REACHABLE; @@ -496,7 +499,7 @@ uip_nd6_na_input(void) if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) || nd6_opt_llao == 0) { if(nd6_opt_llao != 0) { - memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], + memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); } if(is_solicited) { @@ -583,7 +586,7 @@ uip_nd6_rs_input(void) #endif /*UIP_CONF_IPV6_CHECKS */ switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: - nd6_opt_llao = UIP_ND6_OPT_HDR_BUF; + nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF; break; default: PRINTF("ND option not supported in RS\n"); @@ -602,14 +605,18 @@ uip_nd6_rs_input(void) 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, - &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); + (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); } else { /* If LL address changed, set neighbor state to stale */ if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - &nbr->lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); - nbr->state = NBR_STALE; + uip_ds6_nbr_get_ll(nbr), 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, + (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); + nbr->reachable = nbr_data.reachable; + nbr->sendns = nbr_data.sendns; + nbr->nscount = nbr_data.nscount; } nbr->isrouter = 0; }