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 UIP_DS6_NBR_MULTI_IPV6_ADDRS
75 uip_ds6_nbr_entry_t *nbr_entry);
87static void remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry);
99static void callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry);
101NBR_TABLE(uip_ds6_nbr_entry_t, uip_ds6_nbr_entries);
109uip_ds6_neighbors_init(
void)
112#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
114 nbr_table_register(uip_ds6_nbr_entries,
115 (nbr_table_callback *)callback_nbr_entry_removal);
117 nbr_table_register(ds6_neighbors, (nbr_table_callback *)
uip_ds6_nbr_rm);
123 uint8_t isrouter, uint8_t state, nbr_table_reason_t reason,
128#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
129 uip_ds6_nbr_entry_t *nbr_entry;
133 LOG_ERR(
"%s: uip_ds6_nbr for ", __func__);
135 LOG_ERR_(
"has already existed\n");
141 LOG_ERR(
"%s: cannot allocate a new uip_ds6_nbr\n", __func__);
146 nbr_entry = nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
147 (
const linkaddr_t *)lladdr);
148 if(nbr_entry == NULL) {
150 nbr_table_add_lladdr(uip_ds6_nbr_entries,
151 (linkaddr_t*)lladdr, reason, data)) == NULL) {
152 LOG_ERR(
"%s: cannot allocate a new uip_ds6_nbr_entry\n", __func__);
160 if((nbr_entry == NULL) ||
167 LOG_ERR(
"%s: no room in nbr_entry for ", __func__);
168 LOG_ERR_LLADDR((
const linkaddr_t *)lladdr);
177 add_uip_ds6_nbr_to_nbr_entry(
nbr, nbr_entry);
180 nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr, reason, data);
185#if UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
186 nbr->isrouter = isrouter;
189#if UIP_CONF_IPV6_QUEUE_PKT
190 uip_packetqueue_new(&
nbr->packethandle);
193 if(
nbr->state == NBR_REACHABLE) {
202 LOG_INFO(
"Adding neighbor with ip addr ");
204 LOG_INFO_(
" link addr ");
205 LOG_INFO_LLADDR((linkaddr_t*)lladdr);
206 LOG_INFO_(
" state %u\n", state);
210 LOG_INFO(
"Add drop ip addr ");
212 LOG_INFO_(
" link addr (%p) ", lladdr);
213 LOG_INFO_LLADDR((linkaddr_t*)lladdr);
214 LOG_INFO_(
" state %u\n", state);
219#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
223 uip_ds6_nbr_entry_t *nbr_entry)
225 LOG_DBG(
"%s: add nbr(%p) to nbr_entry (%p)\n",
226 __func__,
nbr, nbr_entry);
227 nbr->nbr_entry = nbr_entry;
237 LOG_DBG(
"%s: remove nbr(%p) from nbr_entry (%p)\n",
238 __func__,
nbr,
nbr->nbr_entry);
243remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry)
245 if(nbr_entry == NULL) {
248 LOG_DBG(
"%s: remove nbr_entry (%p) from nbr_table\n",
249 __func__, nbr_entry);
250 (void)nbr_table_remove(uip_ds6_nbr_entries, nbr_entry);
259#if UIP_CONF_IPV6_QUEUE_PKT
260 uip_packetqueue_free(&
nbr->packethandle);
263 assert(
nbr->nbr_entry != NULL);
264 if(
nbr->nbr_entry == NULL) {
265 LOG_ERR(
"%s: unexpected error nbr->nbr_entry is NULL\n", __func__);
267 remove_uip_ds6_nbr_from_nbr_entry(
nbr);
269 remove_nbr_entry(
nbr->nbr_entry);
272 LOG_DBG(
"%s: free memory for nbr(%p)\n", __func__,
nbr);
277callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry)
281 if(nbr_entry == NULL) {
288 free_uip_ds6_nbr(
nbr);
296#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
300 free_uip_ds6_nbr(
nbr);
305#if UIP_CONF_IPV6_QUEUE_PKT
306 uip_packetqueue_free(&
nbr->packethandle);
309 return nbr_table_remove(ds6_neighbors,
nbr);
319#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
320 uip_ds6_nbr_entry_t *nbr_entry;
326 if(nbr_pp == NULL || new_ll_addr == NULL) {
327 LOG_ERR(
"%s: invalid argument\n", __func__);
331#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
334 nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
335 (
const linkaddr_t *)new_ll_addr)) == NULL) {
337 nbr_table_add_lladdr(uip_ds6_nbr_entries,
338 (
const linkaddr_t*)new_ll_addr,
339 NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
340 LOG_ERR(
"%s: cannot allocate a nbr_entry for", __func__);
341 LOG_ERR_LLADDR((
const linkaddr_t *)new_ll_addr);
350 remove_uip_ds6_nbr_from_nbr_entry(
nbr);
352 remove_nbr_entry(
nbr->nbr_entry);
354 add_uip_ds6_nbr_to_nbr_entry(
nbr, nbr_entry);
360 LOG_ERR(
"%s: new_ll_addr, ", __func__);
361 LOG_ERR_LLADDR((
const linkaddr_t *)new_ll_addr);
362 LOG_ERR_(
", is already used in another nbr\n");
368 LOG_ERR(
"%s: input nbr cannot be removed\n", __func__);
373 nbr_backup.isrouter, nbr_backup.state,
374 NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
375 LOG_ERR(
"%s: cannot allocate a new nbr for new_ll_addr\n", __func__);
387 return (
nbr != NULL) ? &
nbr->ipaddr : NULL;
394#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
398 return (
const uip_lladdr_t *)nbr_table_get_lladdr(uip_ds6_nbr_entries,
401 return (
const uip_lladdr_t *)nbr_table_get_lladdr(ds6_neighbors,
nbr);
410#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
411 uip_ds6_nbr_entry_t *nbr_entry;
412 for(nbr_entry = nbr_table_head(uip_ds6_nbr_entries);
414 nbr_entry = nbr_table_next(uip_ds6_nbr_entries, nbr_entry)) {
419 for(
nbr = nbr_table_head(ds6_neighbors);
421 nbr = nbr_table_next(ds6_neighbors,
nbr)) {
431#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
432 uip_ds6_nbr_entry_t *nbr_entry;
433 if((nbr_entry = nbr_table_head(uip_ds6_nbr_entries)) == NULL) {
436 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
439 return nbr_table_head(ds6_neighbors);
446#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
447 uip_ds6_nbr_entry_t *nbr_entry;
454 nbr_entry = nbr_table_next(uip_ds6_nbr_entries,
nbr->nbr_entry);
455 if(nbr_entry == NULL) {
458 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
462 return nbr_table_next(ds6_neighbors,
nbr);
474 if(uip_ipaddr_cmp(&
nbr->ipaddr,
ipaddr)) {
484#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
485 uip_ds6_nbr_entry_t *nbr_entry;
491 (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
492 (linkaddr_t*)lladdr);
493 if(nbr_entry == NULL) {
496 assert(
list_head(nbr_entry->uip_ds6_nbrs) != NULL);
499 return nbr_table_get_from_lladdr(ds6_neighbors, (linkaddr_t*)lladdr);
508 return nbr ? &
nbr->ipaddr : NULL;
521update_nbr_reachable_state_by_ack(
uip_ds6_nbr_t *
nbr,
const linkaddr_t *lladdr)
524 nbr->state = NBR_REACHABLE;
526 LOG_INFO(
"received a link layer ACK : ");
527 LOG_INFO_LLADDR(lladdr);
528 LOG_INFO_(
" is reachable.\n");
537 const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
559#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
560 uip_ds6_nbr_entry_t *nbr_entry;
562 (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
569 update_nbr_reachable_state_by_ack(
nbr, dest);
573 update_nbr_reachable_state_by_ack(
nbr, dest);
596 if(uip_ds6_defrt_lookup(&
nbr->ipaddr) != NULL) {
597 LOG_INFO(
"REACHABLE: defrt moving to DELAY (");
598 LOG_INFO_6ADDR(&
nbr->ipaddr);
600 nbr->state = NBR_DELAY;
604 LOG_INFO(
"REACHABLE: moving to STALE (");
605 LOG_INFO_6ADDR(&
nbr->ipaddr);
607 nbr->state = NBR_STALE;
610 LOG_INFO(
"REACHABLE: moving to STALE (");
611 LOG_INFO_6ADDR(&
nbr->ipaddr);
613 nbr->state = NBR_STALE;
618 if(
nbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) {
622 LOG_INFO(
"NBR_INCOMPLETE: NS %u\n",
nbr->nscount);
629 nbr->state = NBR_PROBE;
631 LOG_INFO(
"DELAY: moving to PROBE\n");
636 if(
nbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) {
638 LOG_INFO(
"PROBE END\n");
639 if((locdefrt = uip_ds6_defrt_lookup(&
nbr->ipaddr)) != NULL) {
640 if (!locdefrt->isinfinite) {
641 uip_ds6_defrt_rm(locdefrt);
647 LOG_INFO(
"PROBE: NS %u\n",
nbr->nscount);
660uip_ds6_nbr_refresh_reachable_state(
const uip_ipaddr_t *
ipaddr)
665 nbr->state = NBR_REACHABLE;
const linkaddr_t linkaddr_null
The null link-layer address.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void * list_head(const list_t list)
Get a pointer to the first element of a list.
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.
#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)