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);
87 static void remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry);
99 static void callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry);
101 NBR_TABLE(uip_ds6_nbr_entry_t, uip_ds6_nbr_entries);
109 uip_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__);
134 LOG_ERR_6ADDR(ipaddr);
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) {
194 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
202 LOG_INFO(
"Adding neighbor with ip addr ");
203 LOG_INFO_6ADDR(ipaddr);
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 ");
211 LOG_INFO_6ADDR(ipaddr);
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;
228 list_add(nbr_entry->uip_ds6_nbrs, nbr);
237 LOG_DBG(
"%s: remove nbr(%p) from nbr_entry (%p)\n",
238 __func__, nbr, nbr->nbr_entry);
243 remove_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);
268 if(
list_length(nbr->nbr_entry->uip_ds6_nbrs) == 0) {
269 remove_nbr_entry(nbr->nbr_entry);
272 LOG_DBG(
"%s: free memory for nbr(%p)\n", __func__, nbr);
277 callback_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);
351 if(
list_length(nbr->nbr_entry->uip_ds6_nbrs) == 0) {
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;
521 update_nbr_reachable_state_by_ack(
uip_ds6_nbr_t *nbr,
const linkaddr_t *lladdr)
524 nbr->state = NBR_REACHABLE;
525 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
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;
601 stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
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);
660 uip_ds6_nbr_refresh_reachable_state(
const uip_ipaddr_t *
ipaddr)
665 nbr->state = NBR_REACHABLE;
667 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
677 if(nbr_expiring != NULL) {
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
An entry in the default router list.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
uip_ds6_nbr_t * uip_ds6_nbr_head(void)
Get the first neighbor cache in nbr_table.
Header file for the link-layer address representation
uip_ds6_nbr_t * uip_ds6_get_least_lifetime_neighbor(void)
This searches inside the neighbor table for the neighbor that is about to expire the next...
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
int stimer_expired(struct stimer *t)
Check if a timer has expired.
void uip_ds6_link_callback(int status, int numtx)
The callback function to update link-layer stats in a neighbor cache.
const linkaddr_t linkaddr_null
The null link-layer address.
int uip_ds6_nbr_num(void)
Return the number of neighbor caches.
Header file for IPv6-related data structures.
void(* neighbor_state_changed)(uip_ds6_nbr_t *nbr)
Called by uIP to notify addition/removal of IPv6 neighbor entries.
void uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
void uip_ds6_neighbor_periodic(void)
The housekeeping function called periodically.
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.
Linked list manipulation routines.
#define UIP_DS6_NBR_MAX_6ADDRS_PER_NBR
Set the maximum number of IPv6 addresses per link-layer address.
const uip_ipaddr_t * uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr)
Get an IPv6 address of a neighbor cache.
void * list_head(list_t list)
Get a pointer to the first element of a list.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
The MAC layer transmission was OK.
Routing driver header file
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
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.
Memory block allocation routines.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
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...
Header file for IPv6 Neighbor discovery (RFC 4861)
uip_ds6_netif_t uip_ds6_if
The single interface.
uip_ds6_nbr_t * uip_ds6_nbr_next(uip_ds6_nbr_t *nbr)
Get the next neighbor cache of a specified one.
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.
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
Remove a neighbor cache.
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.
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.
Header file for the Packet buffer (packetbuf) management
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Header file for the logging system
#define UIP_DS6_NBR_MAX_NEIGHBOR_CACHES
Set the maximum number of neighbor cache entries.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
#define MEMB(name, structure, num)
Declare a memory block.
int list_length(list_t list)
Get the length of a list.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...