50#include "net/link-stats.h"
58#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
64#define LOG_MODULE "IPv6 Nbr"
65#define LOG_LEVEL LOG_LEVEL_IPV6
67#if BUILD_WITH_ORCHESTRA
70#ifndef NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK
71#define NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK orchestra_callback_neighbor_updated
73void NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK(
const linkaddr_t *, uint8_t is_added);
77#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
85 uip_ds6_nbr_entry_t *nbr_entry);
97static void remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry);
109static void callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry);
111NBR_TABLE(uip_ds6_nbr_entry_t, uip_ds6_nbr_entries);
119uip_ds6_neighbors_init(
void)
122#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
124 nbr_table_register(uip_ds6_nbr_entries,
125 (nbr_table_callback *)callback_nbr_entry_removal);
127 nbr_table_register(ds6_neighbors, (nbr_table_callback *)
uip_ds6_nbr_rm);
133 uint8_t isrouter, uint8_t state, nbr_table_reason_t reason,
138#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
139 uip_ds6_nbr_entry_t *nbr_entry;
143 LOG_ERR(
"%s: uip_ds6_nbr for ", __func__);
145 LOG_ERR_(
"has already existed\n");
151 LOG_ERR(
"%s: cannot allocate a new uip_ds6_nbr\n", __func__);
156 nbr_entry = nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
157 (
const linkaddr_t *)lladdr);
158 if(nbr_entry == NULL) {
160 nbr_table_add_lladdr(uip_ds6_nbr_entries,
161 (linkaddr_t*)lladdr, reason, data)) == NULL) {
162 LOG_ERR(
"%s: cannot allocate a new uip_ds6_nbr_entry\n", __func__);
170 if((nbr_entry == NULL) ||
177 LOG_ERR(
"%s: no room in nbr_entry for ", __func__);
178 LOG_ERR_LLADDR((
const linkaddr_t *)lladdr);
187 add_uip_ds6_nbr_to_nbr_entry(
nbr, nbr_entry);
190 nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr, reason, data);
194#ifdef NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK
195 NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK((
const linkaddr_t *)lladdr, 1);
198#if UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
199 nbr->isrouter = isrouter;
202#if UIP_CONF_IPV6_QUEUE_PKT
203 uip_packetqueue_new(&
nbr->packethandle);
206 if(
nbr->state == NBR_REACHABLE) {
215 LOG_INFO(
"Adding neighbor with ip addr ");
217 LOG_INFO_(
" link addr ");
218 LOG_INFO_LLADDR((linkaddr_t*)lladdr);
219 LOG_INFO_(
" state %u\n", state);
223 LOG_INFO(
"Add drop ip addr ");
225 LOG_INFO_(
" link addr (%p) ", lladdr);
226 LOG_INFO_LLADDR((linkaddr_t*)lladdr);
227 LOG_INFO_(
" state %u\n", state);
232#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
236 uip_ds6_nbr_entry_t *nbr_entry)
238 LOG_DBG(
"%s: add nbr(%p) to nbr_entry (%p)\n",
239 __func__,
nbr, nbr_entry);
240 nbr->nbr_entry = nbr_entry;
250 LOG_DBG(
"%s: remove nbr(%p) from nbr_entry (%p)\n",
251 __func__,
nbr,
nbr->nbr_entry);
256remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry)
258 if(nbr_entry == NULL) {
261 LOG_DBG(
"%s: remove nbr_entry (%p) from nbr_table\n",
262 __func__, nbr_entry);
263 (void)nbr_table_remove(uip_ds6_nbr_entries, nbr_entry);
272#if UIP_CONF_IPV6_QUEUE_PKT
273 uip_packetqueue_free(&
nbr->packethandle);
276 assert(
nbr->nbr_entry != NULL);
277 if(
nbr->nbr_entry == NULL) {
278 LOG_ERR(
"%s: unexpected error nbr->nbr_entry is NULL\n", __func__);
280 remove_uip_ds6_nbr_from_nbr_entry(
nbr);
282 remove_nbr_entry(
nbr->nbr_entry);
285 LOG_DBG(
"%s: free memory for nbr(%p)\n", __func__,
nbr);
290callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry)
294 if(nbr_entry == NULL) {
301 free_uip_ds6_nbr(
nbr);
314#ifdef NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK
315 linkaddr_t lladdr = {0};
318 if(plladdr != NULL) {
319 memcpy(&lladdr, plladdr,
sizeof(lladdr));
323#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
325 free_uip_ds6_nbr(
nbr);
330#if UIP_CONF_IPV6_QUEUE_PKT
331 uip_packetqueue_free(&
nbr->packethandle);
335 ret = nbr_table_remove(ds6_neighbors,
nbr);
338#ifdef NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK
339 NETSTACK_CONF_DS6_NEIGHBOR_UPDATED_CALLBACK(&lladdr, 0);
349#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
350 uip_ds6_nbr_entry_t *nbr_entry;
356 if(nbr_pp == NULL || new_ll_addr == NULL) {
357 LOG_ERR(
"%s: invalid argument\n", __func__);
361#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
364 nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
365 (
const linkaddr_t *)new_ll_addr)) == NULL) {
367 nbr_table_add_lladdr(uip_ds6_nbr_entries,
368 (
const linkaddr_t*)new_ll_addr,
369 NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
370 LOG_ERR(
"%s: cannot allocate a nbr_entry for", __func__);
371 LOG_ERR_LLADDR((
const linkaddr_t *)new_ll_addr);
380 remove_uip_ds6_nbr_from_nbr_entry(
nbr);
382 remove_nbr_entry(
nbr->nbr_entry);
384 add_uip_ds6_nbr_to_nbr_entry(
nbr, nbr_entry);
390 LOG_ERR(
"%s: new_ll_addr, ", __func__);
391 LOG_ERR_LLADDR((
const linkaddr_t *)new_ll_addr);
392 LOG_ERR_(
", is already used in another nbr\n");
398 LOG_ERR(
"%s: input nbr cannot be removed\n", __func__);
403 nbr_backup.isrouter, nbr_backup.state,
404 NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
405 LOG_ERR(
"%s: cannot allocate a new nbr for new_ll_addr\n", __func__);
417 return (
nbr != NULL) ? &
nbr->ipaddr : NULL;
424#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
428 return (
const uip_lladdr_t *)nbr_table_get_lladdr(uip_ds6_nbr_entries,
431 return (
const uip_lladdr_t *)nbr_table_get_lladdr(ds6_neighbors,
nbr);
440#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
441 uip_ds6_nbr_entry_t *nbr_entry;
442 for(nbr_entry = nbr_table_head(uip_ds6_nbr_entries);
444 nbr_entry = nbr_table_next(uip_ds6_nbr_entries, nbr_entry)) {
449 for(
nbr = nbr_table_head(ds6_neighbors);
451 nbr = nbr_table_next(ds6_neighbors,
nbr)) {
461#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
462 uip_ds6_nbr_entry_t *nbr_entry;
463 if((nbr_entry = nbr_table_head(uip_ds6_nbr_entries)) == NULL) {
466 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
469 return nbr_table_head(ds6_neighbors);
476#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
477 uip_ds6_nbr_entry_t *nbr_entry;
484 nbr_entry = nbr_table_next(uip_ds6_nbr_entries,
nbr->nbr_entry);
485 if(nbr_entry == NULL) {
488 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
492 return nbr_table_next(ds6_neighbors,
nbr);
504 if(uip_ipaddr_cmp(&
nbr->ipaddr,
ipaddr)) {
514#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
515 uip_ds6_nbr_entry_t *nbr_entry;
521 (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
522 (linkaddr_t*)lladdr);
523 if(nbr_entry == NULL) {
526 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
529 return nbr_table_get_from_lladdr(ds6_neighbors, (linkaddr_t*)lladdr);
538 return nbr ? &
nbr->ipaddr : NULL;
551update_nbr_reachable_state_by_ack(
uip_ds6_nbr_t *
nbr,
const linkaddr_t *lladdr)
554 nbr->state = NBR_REACHABLE;
556 LOG_INFO(
"received a link layer ACK : ");
557 LOG_INFO_LLADDR(lladdr);
558 LOG_INFO_(
" is reachable.\n");
567 const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
589#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
590 uip_ds6_nbr_entry_t *nbr_entry;
592 (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
599 update_nbr_reachable_state_by_ack(
nbr, dest);
603 update_nbr_reachable_state_by_ack(
nbr, dest);
626 if(uip_ds6_defrt_lookup(&
nbr->ipaddr) != NULL) {
627 LOG_INFO(
"REACHABLE: defrt moving to DELAY (");
628 LOG_INFO_6ADDR(&
nbr->ipaddr);
630 nbr->state = NBR_DELAY;
634 LOG_INFO(
"REACHABLE: moving to STALE (");
635 LOG_INFO_6ADDR(&
nbr->ipaddr);
637 nbr->state = NBR_STALE;
640 LOG_INFO(
"REACHABLE: moving to STALE (");
641 LOG_INFO_6ADDR(&
nbr->ipaddr);
643 nbr->state = NBR_STALE;
648 if(
nbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) {
652 LOG_INFO(
"NBR_INCOMPLETE: NS %u\n",
nbr->nscount);
659 nbr->state = NBR_PROBE;
661 LOG_INFO(
"DELAY: moving to PROBE\n");
666 if(
nbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) {
668 LOG_INFO(
"PROBE END\n");
669 if((locdefrt = uip_ds6_defrt_lookup(&
nbr->ipaddr)) != NULL) {
670 if (!locdefrt->isinfinite) {
671 uip_ds6_defrt_rm(locdefrt);
677 LOG_INFO(
"PROBE: NS %u\n",
nbr->nscount);
690uip_ds6_nbr_refresh_reachable_state(
const uip_ipaddr_t *
ipaddr)
695 nbr->state = NBR_REACHABLE;
bool linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
const linkaddr_t linkaddr_null
The null link-layer address.
int list_length(const_list_t list)
Get the length of a list.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
void * list_item_next(const void *item)
Get the next item following this item.
void * list_head(const_list_t list)
Get a pointer to the first element of a list.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
#define MEMB(name, structure, num)
Declare a memory block.
int stimer_expired(struct stimer *t)
Check if a timer has expired.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
void uip_nd6_ns_output(const uip_ipaddr_t *src, const uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
Get the link-layer address associated with a specified nbr cache.
#define UIP_DS6_NBR_MAX_6ADDRS_PER_NBR
Set the maximum number of IPv6 addresses per link-layer address.
uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state, nbr_table_reason_t reason, void *data)
Add a neighbor cache for a specified IPv6 address, which is associated with a specified link-layer ad...
uip_ds6_nbr_t * uip_ds6_nbr_head(void)
Get the first neighbor cache in nbr_table.
uip_ds6_nbr_t * uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr)
Get the neighbor cache associated with a specified link-layer address.
int uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr_pp, const uip_lladdr_t *new_ll_addr)
Update the link-layer address associated with an IPv6 address.
#define UIP_DS6_NBR_MAX_NEIGHBOR_CACHES
Set the maximum number of neighbor cache entries.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
Remove a neighbor cache.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
void uip_ds6_neighbor_periodic(void)
The housekeeping function called periodically.
const uip_ipaddr_t * uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr)
Get an IPv6 address of a neighbor cache.
int uip_ds6_nbr_num(void)
Return the number of neighbor caches.
void uip_ds6_link_callback(int status, int numtx)
The callback function to update link-layer stats in a neighbor cache.
uip_ds6_netif_t uip_ds6_if
The single interface.
const uip_lladdr_t * uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr)
Get the link-layer address associated with a specified IPv6 address.
uip_ds6_nbr_t * uip_ds6_nbr_next(uip_ds6_nbr_t *nbr)
Get the next neighbor cache of a specified one.
uip_ipaddr_t * uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr)
Get an IPv6 address associated with a specified link-layer address.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Header file for the link-layer address representation.
Linked list manipulation routines.
Header file for the logging system.
@ MAC_TX_OK
The MAC layer transmission was OK.
Memory block allocation routines.
Header file for the Packet buffer (packetbuf) management.
Routing driver header file.
void(* neighbor_state_changed)(uip_ds6_nbr_t *nbr)
Called by uIP to notify addition/removal of IPv6 neighbor entries.
An entry in the default router list.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
Header file for IPv6-related data structures.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Header file for IPv6 Neighbor discovery (RFC 4861)