Make DS6 neighbors use neighbor-table, and move all DS6 neighbor management from uip-ds6 to a new uip-ds6-neighbor module.

This commit is contained in:
Simon Duquennoy 2013-07-03 19:32:26 +02:00
parent 5a1d8d8006
commit ec609b49eb
8 changed files with 386 additions and 290 deletions

View file

@ -18,6 +18,7 @@ uaodv-rt.c \
uaodv.c \ uaodv.c \
uip-debug.c \ uip-debug.c \
uip-ds6-route.c \ uip-ds6-route.c \
uip-ds6-neighbor.c \
uip-ds6.c \ uip-ds6.c \
uip-fw-drv.c \ uip-fw-drv.c \
uip-fw.c \ uip-fw.c \

View file

@ -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]); 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 * uip_ds6_route_t *
@ -242,18 +227,16 @@ rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
rpl_instance_t *instance; rpl_instance_t *instance;
rpl_instance_t *end; rpl_instance_t *end;
if(!nbr->isused) { PRINTF("RPL: Removing neighbor ");
PRINTF("RPL: Removing neighbor "); PRINT6ADDR(&nbr->ipaddr);
PRINT6ADDR(&nbr->ipaddr); PRINTF("\n");
PRINTF("\n"); for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { if(instance->used == 1 ) {
if(instance->used == 1 ) { p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); if(p != NULL) {
if(p != NULL) { p->rank = INFINITE_RANK;
p->rank = INFINITE_RANK; /* Trigger DAG rank recalculation. */
/* Trigger DAG rank recalculation. */ p->updated = 1;
p->updated = 1;
}
} }
} }
} }

View file

@ -567,6 +567,7 @@ tcpip_ipv6_output(void)
uip_ds6_route_t* locrt; uip_ds6_route_t* locrt;
locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
if(locrt == NULL) { if(locrt == NULL) {
PRINTF("tcpip_ipv6_output: no route found, using default route\n");
if((nexthop = uip_ds6_defrt_choose()) == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) {
#ifdef UIP_FALLBACK_INTERFACE #ifdef UIP_FALLBACK_INTERFACE
PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n",
@ -588,11 +589,14 @@ tcpip_ipv6_output(void)
} else { } else {
nexthop = &locrt->nexthop; nexthop = &locrt->nexthop;
} }
#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
if(nexthop != NULL) { 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]); printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
}
#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
}
} }
/* End of next hop determination */ /* End of next hop determination */
#if UIP_CONF_IPV6_RPL #if UIP_CONF_IPV6_RPL
@ -655,7 +659,7 @@ tcpip_ipv6_output(void)
} }
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NA */
tcpip_output(&nbr->lladdr); tcpip_output(uip_ds6_nbr_get_ll(nbr));
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* /*
@ -668,7 +672,7 @@ tcpip_ipv6_output(void)
uip_len = uip_packetqueue_buflen(&nbr->packethandle); uip_len = uip_packetqueue_buflen(&nbr->packethandle);
memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
uip_packetqueue_free(&nbr->packethandle); uip_packetqueue_free(&nbr->packethandle);
tcpip_output(&nbr->lladdr); tcpip_output(uip_ds6_nbr_get_ll(nbr));
} }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ #endif /*UIP_CONF_IPV6_QUEUE_PKT*/

248
core/net/uip-ds6-neighbor.c Normal file
View file

@ -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 <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
* \author Simon Duquennoy <simonduq@sics.se>
*
*/
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#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;
}

View file

@ -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 <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
* \author Simon Duquennoy <simonduq@sics.se>
*
*/
#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__ */

View file

@ -53,13 +53,6 @@
#define DEBUG DEBUG_NONE #define DEBUG DEBUG_NONE
#include "net/uip-debug.h" #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 */ struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
@ -76,10 +69,7 @@ static uint8_t rscount; /** \brief numbe
/** \name "DS6" Data structures */ /** \name "DS6" Data structures */
/** @{ */ /** @{ */
uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */ 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_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.*/ /* Used by Cooja to enable extraction of addresses from memory.*/
uint8_t uip_ds6_addr_size; 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_maddr_t *locmaddr;
static uip_ds6_aaddr_t *locaaddr; static uip_ds6_aaddr_t *locaaddr;
static uip_ds6_prefix_t *locprefix; static uip_ds6_prefix_t *locprefix;
static uip_ds6_nbr_t *locnbr;
static uip_ds6_defrt_t *locdefrt;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_init(void) uip_ds6_init(void)
{ {
uip_ds6_neighbors_init();
uip_ds6_route_init(); uip_ds6_route_init();
PRINTF("Init of IPv6 data structures\n"); 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", 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); 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_prefix_list, 0, sizeof(uip_ds6_prefix_list));
memset(&uip_ds6_if, 0, sizeof(uip_ds6_if)); 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_addr_size = sizeof(struct uip_ds6_addr);
uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list); 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 */ #endif /* !UIP_CONF_ROUTER */
/* Periodic processing on neighbors */ uip_ds6_neighbor_periodic();
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;
}
}
}
#if UIP_CONF_ROUTER & UIP_ND6_SEND_RA #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA
/* Periodic RA sending */ /* 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; 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 #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_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 */ #endif /* UIP_CONF_IPV6 */

View file

@ -47,6 +47,7 @@
/* The size of uip_ds6_addr_t depends on UIP_ND6_DEF_MAXDADNS. Include uip-nd6.h to define it. */ /* 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-nd6.h"
#include "net/uip-ds6-route.h" #include "net/uip-ds6-route.h"
#include "net/uip-ds6-neighbor.h"
/*--------------------------------------------------*/ /*--------------------------------------------------*/
/** Configuration. For all tables (Neighbor cache, Prefix List, Routing Table, /** 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 number of elements assigned by the system (name suffixed by _NBS)
* - the total number of elements is the sum (name suffixed by _NB) * - 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 */ /* Default router list */
#define UIP_DS6_DEFRT_NBS 0 #define UIP_DS6_DEFRT_NBS 0
@ -155,22 +148,6 @@
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
#include "net/uip-packetqueue.h" #include "net/uip-packetqueue.h"
#endif /*UIP_CONF_QUEUE_PKT */ #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 */ /** \brief A prefix list entry */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
@ -226,8 +203,6 @@ typedef struct uip_ds6_maddr {
#endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ #endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */
#endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6_RPL */
/** \brief Interface structure (contains all the interface variables) */ /** \brief Interface structure (contains all the interface variables) */
typedef struct uip_ds6_netif { typedef struct uip_ds6_netif {
uint32_t link_mtu; 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, uint8_t ipaddrlen,
uip_ds6_element_t **out_element); 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__ */ #endif /* __UIP_DS6_H__ */

View file

@ -191,9 +191,10 @@ uip_nd6_ns_input(void)
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
0, NBR_STALE); 0, NBR_STALE);
} else { } else {
uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
&nbr->lladdr, UIP_LLADDR_LEN) != 0) { lladdr, UIP_LLADDR_LEN) != 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); UIP_LLADDR_LEN);
nbr->state = NBR_STALE; nbr->state = NBR_STALE;
} else { } else {
@ -460,20 +461,22 @@ uip_nd6_na_input(void)
PRINTF("NA received is bad\n"); PRINTF("NA received is bad\n");
goto discard; goto discard;
} else { } else {
uip_lladdr_t *lladdr;
nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
lladdr = uip_ds6_nbr_get_ll(nbr);
if(nbr == NULL) { if(nbr == NULL) {
goto discard; goto discard;
} }
if(nd6_opt_llao != 0) { if(nd6_opt_llao != 0) {
is_llchange = 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); UIP_LLADDR_LEN);
} }
if(nbr->state == NBR_INCOMPLETE) { if(nbr->state == NBR_INCOMPLETE) {
if(nd6_opt_llao == NULL) { if(nd6_opt_llao == NULL) {
goto discard; 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); UIP_LLADDR_LEN);
if(is_solicited) { if(is_solicited) {
nbr->state = NBR_REACHABLE; nbr->state = NBR_REACHABLE;
@ -496,7 +499,7 @@ uip_nd6_na_input(void)
if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange)
|| nd6_opt_llao == 0) { || nd6_opt_llao == 0) {
if(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); UIP_LLADDR_LEN);
} }
if(is_solicited) { if(is_solicited) {
@ -583,7 +586,7 @@ uip_nd6_rs_input(void)
#endif /*UIP_CONF_IPV6_CHECKS */ #endif /*UIP_CONF_IPV6_CHECKS */
switch (UIP_ND6_OPT_HDR_BUF->type) { switch (UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_SLLAO: case UIP_ND6_OPT_SLLAO:
nd6_opt_llao = UIP_ND6_OPT_HDR_BUF; nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
break; break;
default: default:
PRINTF("ND option not supported in RS\n"); 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) { if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
/* we need to add the neighbor */ /* we need to add the neighbor */
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 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 { } else {
/* If LL address changed, set neighbor state to stale */ /* If LL address changed, set neighbor state to stale */
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
&nbr->lladdr, UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) {
memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], uip_ds6_nbr_t nbr_data = *nbr;
UIP_LLADDR_LEN); uip_ds6_nbr_rm(nbr);
nbr->state = NBR_STALE; 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; nbr->isrouter = 0;
} }