uIP ND6: added option to automatically fill the neighbor cache assuming autoconfigured IPv6 addresses

This commit is contained in:
Simon Duquennoy 2017-06-16 15:57:24 +02:00
parent 30bb899f7c
commit 0d0e065456
5 changed files with 54 additions and 2 deletions

View File

@ -173,16 +173,25 @@
/* UIP_CONF_ND6_SEND_NS enables standard IPv6 Neighbor Discovery Protocol.
We enable it by default when IPv6 is used without RPL.
With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping)
is fed whenever receiving DIO and DAO messages. This is always sufficient
is fed whenever receiving DIO. This is often sufficient
for RPL routing, i.e. to send to the preferred parent or any child.
Link-local unicast to other neighbors may, however, not be possible if
we never receive any DIO from them. This may happen if the link from the
neighbor to us is weak, if DIO transmissions are suppressed (Trickle
timer) or if the neighbor chooses not to transmit DIOs because it is
a leaf node or for any reason. */
a leaf node or for any reason.*/
#ifndef UIP_CONF_ND6_SEND_NS
#define UIP_CONF_ND6_SEND_NS (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
#endif /* UIP_CONF_ND6_SEND_NS */
/* To speed up the neighbor cache construction,
enable UIP_CONF_ND6_AUTOFILL_NBR_CACHE. When a node does not the link-layer
address of a neighbor, it will infer it from the link-local IPv6, assuming
the node used autoconfiguration. Note that RPL uses its own freshness
mechanism to select whether neighbors are sitll usable as a parent
or not, regardless of the neighbor cache. */
#ifndef UIP_CONF_ND6_AUTOFILL_NBR_CACHE
#define UIP_CONF_ND6_AUTOFILL_NBR_CACHE (!UIP_CONF_ND6_SEND_NS)
#endif /* UIP_CONF_ND6_AUTOFILL_NBR_CACHE */
/* UIP_CONF_ND6_SEND_NA allows to still comply with NDP even if the host does
not perform NUD or DAD processes. By default it is activated so the host
can still communicate with a full NDP peer. */

View File

@ -668,6 +668,25 @@ tcpip_ipv6_output(void)
annotate_transmission(nexthop);
nbr = uip_ds6_nbr_lookup(nexthop);
#if UIP_ND6_AUTOFILL_NBR_CACHE
if(nbr == NULL) {
/* Neighbor not found in cache? Derive its link-layer address from it's
link-local IPv6, assuming it used autoconfiguration. This is not
standard-compliant but this is a convenient way to keep the
neighbor cache out of the way in cases ND is not used */
uip_lladdr_t lladdr;
uip_ds6_set_lladdr_from_iid(&lladdr, nexthop);
if((nbr = uip_ds6_nbr_add(nexthop, &lladdr,
0, NBR_REACHABLE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
PRINTF("tcpip_ipv6_output: failed to autofill neighbor cache for host ");
PRINT6ADDR(nexthop);
PRINTF("\n");
goto exit;
}
}
#endif /* UIP_ND6_AUTOFILL_NBR_CACHE */
if(nbr == NULL) {
if(send_nd6_ns(nexthop)) {
PRINTF("tcpip_ipv6_output: failed to add neighbor to cache\n");

View File

@ -558,6 +558,18 @@ uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
#endif
}
/*---------------------------------------------------------------------------*/
void
uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
{
#if (UIP_LLADDR_LEN == 8)
memcpy(lladdr, ipaddr->u8 + 8, UIP_LLADDR_LEN);
lladdr->addr[0] ^= 0x02;
#else
#error uip-ds6.c cannot build lladdr address when UIP_LLADDR_LEN is not 8
#endif
}
/*---------------------------------------------------------------------------*/
uint8_t
get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)

View File

@ -344,6 +344,9 @@ uip_ds6_aaddr_t *uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr);
/** \brief set the last 64 bits of an IP address based on the MAC address */
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr);
/** \brief Build a link-layer address from an IPv6 address based on its UUID64 */
void uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr);
/** \brief Get the number of matching bits of two addresses */
uint8_t get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst);

View File

@ -96,6 +96,15 @@
#else
#define UIP_ND6_SEND_NA UIP_CONF_ND6_SEND_NA
#endif
#ifndef UIP_CONF_ND6_AUTOFILL_NBR_CACHE
/* Neighbor not found in cache? Derive its link-layer address from it's
link-local IPv6, assuming it used autoconfiguration. This is not
standard-compliant but this is a convenient way to keep the
neighbor cache out of the way in cases ND is not used */
#define UIP_ND6_AUTOFILL_NBR_CACHE 0
#else
#define UIP_ND6_AUTOFILL_NBR_CACHE UIP_CONF_ND6_AUTOFILL_NBR_CACHE
#endif
#ifndef UIP_CONF_ND6_MAX_RA_INTERVAL
#define UIP_ND6_MAX_RA_INTERVAL 600
#else