Microchip® Advanced Software Framework

nd6.c File Reference

Neighbor discovery and stateless address autoconfiguration for IPv6.

Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 (Address autoconfiguration).

#include "lwip/opt.h"
#include "lwip/nd6.h"
#include "lwip/pbuf.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/icmp6.h"
#include "lwip/mld6.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
#include <string.h>

Macros

#define ND6_SEND_FLAG_ALLNODES_DEST   0x02
 
#define ND6_SEND_FLAG_MULTICAST_DEST   0x01
 

Functions

static s8_t nd6_find_destination_cache_entry (ip6_addr_t *ip6addr)
 Search for a destination cache entry. More...
 
static s8_t nd6_find_neighbor_cache_entry (ip6_addr_t *ip6addr)
 Search for a neighbor cache entry. More...
 
static void nd6_free_neighbor_cache_entry (s8_t i)
 Will free any resources associated with a neighbor cache entry, and will mark it as unused. More...
 
static void nd6_free_q (struct nd6_q_entry *q)
 Free a complete queue of nd6 q entries. More...
 
u16_t nd6_get_destination_mtu (ip6_addr_t *ip6addr, struct netif *netif)
 Get the Path MTU for a destination. More...
 
s8_t nd6_get_next_hop_entry (ip6_addr_t *ip6addr, struct netif *netif)
 Determine the next hop for a destination. More...
 
static s8_t nd6_get_onlink_prefix (ip6_addr_t *prefix, struct netif *netif)
 Find the cached entry for an on-link prefix. More...
 
static s8_t nd6_get_router (ip6_addr_t *router_addr, struct netif *netif)
 Find an entry for a default router. More...
 
void nd6_input (struct pbuf *p, struct netif *inp)
 Process an incoming neighbor discovery message. More...
 
static s8_t nd6_is_prefix_in_netif (ip6_addr_t *ip6addr, struct netif *netif)
 Determine whether an address matches an on-link prefix. More...
 
static s8_t nd6_new_destination_cache_entry (void)
 Create a new destination cache entry. More...
 
static s8_t nd6_new_neighbor_cache_entry (void)
 Create a new neighbor cache entry. More...
 
static s8_t nd6_new_onlink_prefix (ip6_addr_t *prefix, struct netif *netif)
 Creates a new entry for an on-link prefix. More...
 
static s8_t nd6_new_router (ip6_addr_t *router_addr, struct netif *netif)
 Create a new entry for a default router. More...
 
err_t nd6_queue_packet (s8_t neighbor_index, struct pbuf *q)
 Queue a packet for a neighbor. More...
 
void nd6_reachability_hint (ip6_addr_t *ip6addr)
 Provide the Neighbor discovery process with a hint that a destination is reachable. More...
 
s8_t nd6_select_router (ip6_addr_t *ip6addr, struct netif *netif)
 Select a default router for a destination. More...
 
static void nd6_send_na (struct netif *netif, ip6_addr_t *target_addr, u8_t flags)
 Send a neighbor advertisement message. More...
 
static void nd6_send_ns (struct netif *netif, ip6_addr_t *target_addr, u8_t flags)
 Send a neighbor solicitation message. More...
 
static void nd6_send_q (s8_t i)
 Send queued packets for a neighbor. More...
 
static void nd6_send_rs (struct netif *netif)
 Send a router solicitation message. More...
 
void nd6_tmr (void)
 Periodic timer for Neighbor discovery functions: More...
 

Variables

struct nd6_router_list_entry default_router_list [LWIP_ND6_NUM_ROUTERS]
 
struct nd6_destination_cache_entry destination_cache [LWIP_ND6_NUM_DESTINATIONS]
 
static ip6_addr_t multicast_address
 
static u8_t nd6_cached_destination_index
 
static u8_t nd6_cached_neighbor_index
 
static u8_t nd6_ra_buffer [sizeof(struct prefix_option)]
 
struct nd6_neighbor_cache_entry neighbor_cache [LWIP_ND6_NUM_NEIGHBORS]
 
struct nd6_prefix_list_entry prefix_list [LWIP_ND6_NUM_PREFIXES]
 
u32_t reachable_time = LWIP_ND6_REACHABLE_TIME
 
u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER
 

#define ND6_SEND_FLAG_ALLNODES_DEST   0x02

Referenced by nd6_input(), and nd6_send_na().

#define ND6_SEND_FLAG_MULTICAST_DEST   0x01

Referenced by nd6_send_na(), nd6_send_ns(), and nd6_tmr().

static s8_t nd6_find_destination_cache_entry ( ip6_addr_t ip6addr)
static

Search for a destination cache entry.

Parameters
ip6addrthe IPv6 address of the destination
Returns
The destination cache entry index that matched, -1 if no entry is found

References destination_cache, and ip6_addr_cmp.

Referenced by nd6_get_destination_mtu(), nd6_get_next_hop_entry(), nd6_input(), and nd6_reachability_hint().

static s8_t nd6_find_neighbor_cache_entry ( ip6_addr_t ip6addr)
static

Search for a neighbor cache entry.

Parameters
ip6addrthe IPv6 address of the neighbor
Returns
The neighbor cache entry index that matched, -1 if no entry is found

References ip6_addr_cmp, and neighbor_cache.

Referenced by nd6_get_next_hop_entry(), nd6_input(), nd6_new_router(), and nd6_reachability_hint().

static void nd6_free_neighbor_cache_entry ( s8_t  i)
static

Will free any resources associated with a neighbor cache entry, and will mark it as unused.

Parameters
ithe neighbor cache entry index to free

References nd6_neighbor_cache_entry::counter, ip6_addr_set_zero, nd6_neighbor_cache_entry::isrouter, nd6_free_q(), ND6_NO_ENTRY, neighbor_cache, nd6_neighbor_cache_entry::netif, NULL, nd6_neighbor_cache_entry::q, nd6_neighbor_cache_entry::reachable_time, and nd6_neighbor_cache_entry::state.

Referenced by nd6_new_neighbor_cache_entry(), and nd6_tmr().

static void nd6_free_q ( struct nd6_q_entry q)
static

Free a complete queue of nd6 q entries.

Parameters
qa queue of nd6_q_entry to free

References LWIP_ASSERT, memp_free(), nd6_q_entry::next, NULL, nd6_q_entry::p, and pbuf_free().

Referenced by nd6_free_neighbor_cache_entry(), and nd6_queue_packet().

u16_t nd6_get_destination_mtu ( ip6_addr_t ip6addr,
struct netif netif 
)

Get the Path MTU for a destination.

Parameters
ip6addrthe destination address
netifthe netif on which the packet will be sent
Returns
the Path MTU, if known, or the netif default MTU

References destination_cache, netif::mtu, nd6_find_destination_cache_entry(), NULL, and nd6_destination_cache_entry::pmtu.

Referenced by ip6_output_if_src(), and tcp_eff_send_mss_impl().

s8_t nd6_get_next_hop_entry ( ip6_addr_t ip6addr,
struct netif netif 
)

Determine the next hop for a destination.

Will determine if the destination is on-link, else a suitable on-link router is selected.

The last entry index is cached for fast entry search.

Parameters
ip6addrthe destination address
netifthe netif on which the packet will be sent
Returns
the neighbor cache entry for the next hop, ERR_RTE if no suitable next hop was found, ERR_MEM if no cache entry could be created

References nd6_destination_cache_entry::age, nd6_neighbor_cache_entry::counter, default_router_list, destination_cache, ERR_MEM, ERR_RTE, ip6_addr_cmp, ip6_addr_copy, ip6_addr_islinklocal, ip6_addr_set, ip6_addr_set_any, nd6_neighbor_cache_entry::isrouter, netif::mtu, nd6_cached_destination_index, nd6_cached_neighbor_index, nd6_find_destination_cache_entry(), nd6_find_neighbor_cache_entry(), ND6_INCOMPLETE, nd6_is_prefix_in_netif(), nd6_new_destination_cache_entry(), nd6_new_neighbor_cache_entry(), nd6_select_router(), ND6_STATS_INC, neighbor_cache, nd6_neighbor_cache_entry::netif, NULL, nd6_destination_cache_entry::pmtu, nd6_neighbor_cache_entry::probes_sent, and nd6_neighbor_cache_entry::state.

Referenced by ethip6_output().

static s8_t nd6_get_onlink_prefix ( ip6_addr_t prefix,
struct netif netif 
)
static

Find the cached entry for an on-link prefix.

Parameters
prefixthe IPv6 prefix that is on-link
netifthe netif on which the prefix is on-link
Returns
the index on the prefix table, or -1 if not found

References ip6_addr_netcmp, and prefix_list.

Referenced by nd6_input().

static s8_t nd6_get_router ( ip6_addr_t router_addr,
struct netif netif 
)
static

Find an entry for a default router.

Parameters
router_addrthe IPv6 address of the router
netifthe netif on which the router is found, if known
Returns
the index of the router entry, or -1 if not found

References default_router_list, ip6_addr_cmp, and NULL.

Referenced by nd6_input().

void nd6_input ( struct pbuf p,
struct netif inp 
)

Process an incoming neighbor discovery message.

Parameters
pthe nd packet, p->payload pointing to the icmpv6 header
inpthe netif on which this packet was received

References buffer, nd6_neighbor_cache_entry::counter, default_router_list, nd6_neighbor_cache_entry::delay_time, destination_cache, nd6_prefix_list_entry::flags, nd6_router_list_entry::flags, netif::hwaddr_len, ICMP6_TYPE_NA, ICMP6_TYPE_NS, ICMP6_TYPE_PTB, ICMP6_TYPE_RA, ICMP6_TYPE_RD, if(), nd6_prefix_list_entry::invalidation_timer, nd6_router_list_entry::invalidation_timer, ip6_addr_cmp, IP6_ADDR_INVALID, ip6_addr_isany, ip6_addr_islinklocal, ip6_addr_ismulticast, ip6_addr_istentative, ip6_addr_isvalid, ip6_addr_set, ip6_addr_set_solicitednode, ip6_current_dest_addr, ip6_current_src_addr, IP6_HLEN, pbuf::len, mld6_leavegroup(), netif::mtu, multicast_address, ND6_DELAY, nd6_find_destination_cache_entry(), nd6_find_neighbor_cache_entry(), ND6_FLAG_OVERRIDE, ND6_FLAG_SOLICITED, nd6_get_onlink_prefix(), nd6_get_router(), ND6_INCOMPLETE, nd6_new_neighbor_cache_entry(), nd6_new_onlink_prefix(), nd6_new_router(), ND6_OPTION_TYPE_MTU, ND6_OPTION_TYPE_PREFIX_INFO, ND6_OPTION_TYPE_ROUTE_INFO, ND6_OPTION_TYPE_SOURCE_LLADDR, ND6_OPTION_TYPE_TARGET_LLADDR, ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE, ND6_PREFIX_AUTOCONFIG_AUTONOMOUS, ND6_PREFIX_FLAG_AUTONOMOUS, ND6_PREFIX_FLAG_ON_LINK, nd6_ra_buffer, ND6_REACHABLE, ND6_SEND_FLAG_ALLNODES_DEST, nd6_send_na(), nd6_send_q(), ND6_STATS_INC, neighbor_cache, nd6_router_list_entry::neighbor_entry, nd6_neighbor_cache_entry::netif, netif_ip6_addr, netif_ip6_addr_set_state, netif_ip6_addr_state, NULL, pbuf::payload, pbuf_copy_partial(), pbuf_free(), nd6_destination_cache_entry::pmtu, prefix_list, reachable_time, nd6_neighbor_cache_entry::reachable_time, retrans_timer, netif::rs_count, nd6_neighbor_cache_entry::state, and pbuf::tot_len.

Referenced by icmp6_input().

static s8_t nd6_is_prefix_in_netif ( ip6_addr_t ip6addr,
struct netif netif 
)
static

Determine whether an address matches an on-link prefix.

Parameters
ip6addrthe IPv6 address to match
Returns
1 if the address is on-link, 0 otherwise

References ip6_addr_isvalid, ip6_addr_netcmp, netif_ip6_addr, netif_ip6_addr_state, and prefix_list.

Referenced by nd6_get_next_hop_entry().

static s8_t nd6_new_destination_cache_entry ( void  )
static

Create a new destination cache entry.

If no unused entry is found, will recycle oldest entry.

Returns
The destination cache entry index that was created, -1 if no entry was created

References destination_cache, and ip6_addr_isany.

Referenced by nd6_get_next_hop_entry().

static s8_t nd6_new_neighbor_cache_entry ( void  )
static

Create a new neighbor cache entry.

If no unused entry is found, will try to recycle an old entry according to ad-hoc "age" heuristic.

Returns
The neighbor cache entry index that was created, -1 if no entry could be created

References nd6_neighbor_cache_entry::counter, ND6_DELAY, nd6_free_neighbor_cache_entry(), ND6_INCOMPLETE, ND6_NO_ENTRY, ND6_PROBE, ND6_REACHABLE, ND6_STALE, neighbor_cache, NULL, nd6_neighbor_cache_entry::probes_sent, nd6_neighbor_cache_entry::reachable_time, and time.

Referenced by nd6_get_next_hop_entry(), nd6_input(), and nd6_new_router().

static s8_t nd6_new_onlink_prefix ( ip6_addr_t prefix,
struct netif netif 
)
static

Creates a new entry for an on-link prefix.

Parameters
prefixthe IPv6 prefix that is on-link
netifthe netif on which the prefix is on-link
Returns
the index on the prefix table, or -1 if not created

References nd6_prefix_list_entry::flags, ip6_addr_set, nd6_prefix_list_entry::netif, NULL, and prefix_list.

Referenced by nd6_input().

static s8_t nd6_new_router ( ip6_addr_t router_addr,
struct netif netif 
)
static

Create a new entry for a default router.

Parameters
router_addrthe IPv6 address of the router
netifthe netif on which the router is connected, if known
Returns
the index on the router table, or -1 if could not be created

References nd6_neighbor_cache_entry::counter, default_router_list, ip6_addr_set, nd6_neighbor_cache_entry::isrouter, nd6_find_neighbor_cache_entry(), ND6_INCOMPLETE, nd6_new_neighbor_cache_entry(), neighbor_cache, nd6_router_list_entry::neighbor_entry, nd6_neighbor_cache_entry::netif, NULL, nd6_neighbor_cache_entry::probes_sent, nd6_neighbor_cache_entry::q, and nd6_neighbor_cache_entry::state.

Referenced by nd6_input().

err_t nd6_queue_packet ( s8_t  neighbor_index,
struct pbuf q 
)

Queue a packet for a neighbor.

Parameters
neighbor_indexthe index in the neighbor cache table
qpacket to be queued
Returns
ERR_OK if succeeded, ERR_MEM if out of memory

References ERR_ARG, ERR_MEM, ERR_OK, LWIP_DBG_TRACE, LWIP_DEBUGF, memp_malloc(), nd6_free_q(), neighbor_cache, pbuf::next, nd6_q_entry::next, NULL, nd6_q_entry::p, pbuf_alloc(), pbuf_copy(), pbuf_free(), PBUF_LINK, PBUF_RAM, pbuf_ref(), PBUF_ROM, nd6_neighbor_cache_entry::q, S16_F, pbuf::tot_len, and pbuf::type.

Referenced by ethip6_output().

void nd6_reachability_hint ( ip6_addr_t ip6addr)

Provide the Neighbor discovery process with a hint that a destination is reachable.

Called by tcp_receive when ACKs are received or sent (as per RFC). This is useful to avoid sending NS messages every 30 seconds.

Parameters
ip6addrthe destination address which is know to be reachable by an upper layer protocol (TCP)

References nd6_neighbor_cache_entry::counter, destination_cache, ip6_addr_cmp, nd6_cached_destination_index, nd6_cached_neighbor_index, nd6_find_destination_cache_entry(), nd6_find_neighbor_cache_entry(), ND6_REACHABLE, ND6_STATS_INC, neighbor_cache, reachable_time, nd6_neighbor_cache_entry::reachable_time, and nd6_neighbor_cache_entry::state.

Referenced by tcp_receive().

s8_t nd6_select_router ( ip6_addr_t ip6addr,
struct netif netif 
)

Select a default router for a destination.

Parameters
ip6addrthe destination address
netifthe netif for the outgoing packet, if known
Returns
the default router entry index, or -1 if no suitable router is found

References default_router_list, ND6_REACHABLE, nd6_router_list_entry::neighbor_entry, nd6_neighbor_cache_entry::netif, NULL, nd6_neighbor_cache_entry::state, and void.

Referenced by ip6_route(), and nd6_get_next_hop_entry().

static void nd6_send_na ( struct netif netif,
ip6_addr_t target_addr,
u8_t  flags 
)
static

Send a neighbor advertisement message.

Parameters
netifthe netif on which to send the message
target_addrthe IPv6 target address for the ND message
flagsone of ND6_SEND_FLAG_*

References netif::hwaddr, netif::hwaddr_len, ICMP6_TYPE_NA, ip6_addr_set, ip6_addr_set_allnodes_linklocal, ip6_addr_set_solicitednode, ip6_chksum_pseudo(), ip6_current_src_addr, IP6_NEXTH_ICMP6, ip6_output_if(), pbuf::len, multicast_address, ND6_OPTION_TYPE_TARGET_LLADDR, ND6_SEND_FLAG_ALLNODES_DEST, ND6_SEND_FLAG_MULTICAST_DEST, ND6_STATS_INC, NULL, pbuf::payload, pbuf_alloc(), pbuf_free(), PBUF_IP, and PBUF_RAM.

Referenced by nd6_input().

static void nd6_send_ns ( struct netif netif,
ip6_addr_t target_addr,
u8_t  flags 
)
static

Send a neighbor solicitation message.

Parameters
netifthe netif on which to send the message
target_addrthe IPv6 target address for the ND message
flagsone of ND6_SEND_FLAG_*

References netif::hwaddr, netif::hwaddr_len, ICMP6_TYPE_NS, IP6_ADDR_ANY, ip6_addr_isvalid, ip6_addr_set, ip6_addr_set_solicitednode, ip6_chksum_pseudo(), IP6_NEXTH_ICMP6, ip6_output_if(), pbuf::len, multicast_address, ND6_OPTION_TYPE_SOURCE_LLADDR, ND6_SEND_FLAG_MULTICAST_DEST, ND6_STATS_INC, netif_ip6_addr, netif_ip6_addr_state, NULL, pbuf::payload, pbuf_alloc(), pbuf_free(), PBUF_IP, and PBUF_RAM.

Referenced by nd6_tmr().

static void nd6_send_q ( s8_t  i)
static

Send queued packets for a neighbor.

Parameters
ithe neighbor to send packets to

References ip6_addr_set, ip6_current_dest_addr, memp_free(), neighbor_cache, nd6_neighbor_cache_entry::netif, nd6_q_entry::next, NULL, nd6_q_entry::p, pbuf::payload, pbuf_free(), and nd6_neighbor_cache_entry::q.

Referenced by nd6_input(), and nd6_tmr().

void nd6_tmr ( void  )

Periodic timer for Neighbor discovery functions:

  • Update neighbor reachability states
  • Update destination cache entries age
  • Update invalidation timers of default routers and on-link prefixes
  • Perform duplicate address detection (DAD) for our addresses
  • Send router solicitations

References nd6_destination_cache_entry::age, nd6_neighbor_cache_entry::counter, default_router_list, nd6_neighbor_cache_entry::delay_time, destination_cache, nd6_prefix_list_entry::flags, nd6_router_list_entry::flags, netif::flags, nd6_prefix_list_entry::invalidation_timer, nd6_router_list_entry::invalidation_timer, netif::ip6_addr, IP6_ADDR_INVALID, ip6_addr_istentative, IP6_ADDR_PREFERRED, ip6_addr_set_solicitednode, netif::ip6_addr_state, IP6_ADDR_TENTATIVE, netif::ip6_autoconfig_enabled, nd6_neighbor_cache_entry::isrouter, mld6_joingroup(), multicast_address, ND6_DELAY, nd6_free_neighbor_cache_entry(), ND6_INCOMPLETE, ND6_NO_ENTRY, ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED, ND6_PREFIX_AUTOCONFIG_AUTONOMOUS, ND6_PROBE, ND6_REACHABLE, ND6_SEND_FLAG_MULTICAST_DEST, nd6_send_ns(), nd6_send_q(), nd6_send_rs(), ND6_STALE, ND6_TMR_INTERVAL, neighbor_cache, nd6_router_list_entry::neighbor_entry, nd6_prefix_list_entry::netif, NETIF_FLAG_UP, netif_ip6_addr, netif_ip6_addr_set_state, netif_ip6_addr_state, netif_list, netif::next, NULL, nd6_prefix_list_entry::prefix, prefix_list, nd6_neighbor_cache_entry::probes_sent, nd6_neighbor_cache_entry::reachable_time, netif::rs_count, nd6_neighbor_cache_entry::stale_time, nd6_neighbor_cache_entry::state, and netif::state.

Referenced by nd6_timer().

ip6_addr_t multicast_address
static
u8_t nd6_cached_destination_index
static
u8_t nd6_cached_neighbor_index
static
u8_t nd6_ra_buffer[sizeof(struct prefix_option)]
static

Referenced by nd6_input().

u32_t reachable_time = LWIP_ND6_REACHABLE_TIME

Referenced by nd6_input(), and nd6_reachability_hint().

u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER

Referenced by nd6_input().