Contiki 3.x
uip-ds6-route.c
1 /*
2  * Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 #include "net/ipv6/uip-ds6.h"
33 #include "net/ip/uip.h"
34 
35 #include "lib/list.h"
36 #include "lib/memb.h"
37 #include "net/nbr-table.h"
38 
39 #if UIP_CONF_IPV6
40 
41 #include <string.h>
42 
43 /* The nbr_routes holds a neighbor table to be able to maintain
44  information about what routes go through what neighbor. This
45  neighbor table is registered with the central nbr-table repository
46  so that it will be maintained along with the rest of the neighbor
47  tables in the system. */
48 NBR_TABLE(struct uip_ds6_route_neighbor_routes, nbr_routes);
49 MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
50 
51 /* Each route is repressented by a uip_ds6_route_t structure and
52  memory for each route is allocated from the routememb memory
53  block. These routes are maintained on the routelist. */
54 LIST(routelist);
55 MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB);
56 
57 /* Default routes are held on the defaultrouterlist and their
58  structures are allocated from the defaultroutermemb memory block.*/
59 LIST(defaultrouterlist);
60 MEMB(defaultroutermemb, uip_ds6_defrt_t, UIP_DS6_DEFRT_NB);
61 
62 #if UIP_DS6_NOTIFICATIONS
63 LIST(notificationlist);
64 #endif
65 
66 static int num_routes = 0;
67 
68 #undef DEBUG
69 #define DEBUG DEBUG_NONE
70 #include "net/ip/uip-debug.h"
71 
72 static void rm_routelist_callback(nbr_table_item_t *ptr);
73 /*---------------------------------------------------------------------------*/
74 #if DEBUG != DEBUG_NONE
75 static void
76 assert_nbr_routes_list_sane(void)
77 {
78  uip_ds6_route_t *r;
79  int count;
80 
81  /* Check if the route list has an infinite loop. */
82  for(r = uip_ds6_route_head(),
83  count = 0;
84  r != NULL &&
85  count < UIP_DS6_ROUTE_NB * 2;
86  r = uip_ds6_route_next(r),
87  count++);
88 
89  if(count > UIP_DS6_ROUTE_NB) {
90  printf("uip-ds6-route.c: assert_nbr_routes_list_sane route list is in infinite loop\n");
91  }
92 
93  /* Make sure that the route list has as many entries as the
94  num_routes vairable. */
95  if(count < num_routes) {
96  printf("uip-ds6-route.c: assert_nbr_routes_list_sane too few entries on route list: should be %d, is %d, max %d\n",
97  num_routes, count, UIP_CONF_MAX_ROUTES);
98  }
99 }
100 #endif /* DEBUG != DEBUG_NONE */
101 /*---------------------------------------------------------------------------*/
102 #if UIP_DS6_NOTIFICATIONS
103 static void
104 call_route_callback(int event, uip_ipaddr_t *route,
105  uip_ipaddr_t *nexthop)
106 {
107  int num;
108  struct uip_ds6_notification *n;
109  for(n = list_head(notificationlist);
110  n != NULL;
111  n = list_item_next(n)) {
112  if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD ||
113  event == UIP_DS6_NOTIFICATION_DEFRT_RM) {
114  num = list_length(defaultrouterlist);
115  } else {
116  num = num_routes;
117  }
118  n->callback(event, route, nexthop, num);
119  }
120 }
121 /*---------------------------------------------------------------------------*/
122 void
123 uip_ds6_notification_add(struct uip_ds6_notification *n,
124  uip_ds6_notification_callback c)
125 {
126  if(n != NULL && c != NULL) {
127  n->callback = c;
128  list_add(notificationlist, n);
129  }
130 }
131 /*---------------------------------------------------------------------------*/
132 void
133 uip_ds6_notification_rm(struct uip_ds6_notification *n)
134 {
135  list_remove(notificationlist, n);
136 }
137 #endif
138 /*---------------------------------------------------------------------------*/
139 void
140 uip_ds6_route_init(void)
141 {
142  memb_init(&routememb);
143  list_init(routelist);
144  nbr_table_register(nbr_routes,
145  (nbr_table_callback *)rm_routelist_callback);
146 
147  memb_init(&defaultroutermemb);
148  list_init(defaultrouterlist);
149 
150 #if UIP_DS6_NOTIFICATIONS
151  list_init(notificationlist);
152 #endif
153 }
154 /*---------------------------------------------------------------------------*/
155 static uip_lladdr_t *
156 uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route)
157 {
158  if(route != NULL) {
159  return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
160  route->neighbor_routes);
161  } else {
162  return NULL;
163  }
164 }
165 /*---------------------------------------------------------------------------*/
166 uip_ipaddr_t *
167 uip_ds6_route_nexthop(uip_ds6_route_t *route)
168 {
169  if(route != NULL) {
170  return uip_ds6_nbr_ipaddr_from_lladdr(uip_ds6_route_nexthop_lladdr(route));
171  } else {
172  return NULL;
173  }
174 }
175 /*---------------------------------------------------------------------------*/
177 uip_ds6_route_head(void)
178 {
179  return list_head(routelist);
180 }
181 /*---------------------------------------------------------------------------*/
183 uip_ds6_route_next(uip_ds6_route_t *r)
184 {
185  if(r != NULL) {
187  return n;
188  }
189  return NULL;
190 }
191 /*---------------------------------------------------------------------------*/
192 int
193 uip_ds6_route_num_routes(void)
194 {
195  return num_routes;
196 }
197 /*---------------------------------------------------------------------------*/
199 uip_ds6_route_lookup(uip_ipaddr_t *addr)
200 {
201  uip_ds6_route_t *r;
202  uip_ds6_route_t *found_route;
203  uint8_t longestmatch;
204 
205  PRINTF("uip-ds6-route: Looking up route for ");
206  PRINT6ADDR(addr);
207  PRINTF("\n");
208 
209 
210  found_route = NULL;
211  longestmatch = 0;
212  for(r = uip_ds6_route_head();
213  r != NULL;
214  r = uip_ds6_route_next(r)) {
215  if(r->length >= longestmatch &&
216  uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) {
217  longestmatch = r->length;
218  found_route = r;
219  }
220  }
221 
222  if(found_route != NULL) {
223  PRINTF("uip-ds6-route: Found route: ");
224  PRINT6ADDR(addr);
225  PRINTF(" via ");
226  PRINT6ADDR(uip_ds6_route_nexthop(found_route));
227  PRINTF("\n");
228  } else {
229  PRINTF("uip-ds6-route: No route found\n");
230  }
231 
232  if(found_route != NULL) {
233  /* If we found a route, we put it at the end of the routeslist
234  list. The list is ordered by how recently we looked them up:
235  the least recently used route will be at the start of the
236  list. */
237  list_remove(routelist, found_route);
238  list_add(routelist, found_route);
239  }
240 
241  return found_route;
242 }
243 /*---------------------------------------------------------------------------*/
245 uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
246  uip_ipaddr_t *nexthop)
247 {
248  uip_ds6_route_t *r;
249  struct uip_ds6_route_neighbor_route *nbrr;
250 
251 #if DEBUG != DEBUG_NONE
252  assert_nbr_routes_list_sane();
253 #endif /* DEBUG != DEBUG_NONE */
254 
255  /* Get link-layer address of next hop, make sure it is in neighbor table */
256  const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
257  if(nexthop_lladdr == NULL) {
258  PRINTF("uip_ds6_route_add: neighbor link-local address unknown for ");
259  PRINT6ADDR(nexthop);
260  PRINTF("\n");
261  return NULL;
262  }
263 
264  /* First make sure that we don't add a route twice. If we find an
265  existing route for our destination, we'll delete the old
266  one first. */
267  r = uip_ds6_route_lookup(ipaddr);
268  if(r != NULL) {
269  PRINTF("uip_ds6_route_add: old route for ");
270  PRINT6ADDR(ipaddr);
271  PRINTF(" found, deleting it\n");
272  uip_ds6_route_rm(r);
273  }
274  {
275  struct uip_ds6_route_neighbor_routes *routes;
276  /* If there is no routing entry, create one. We first need to
277  check if we have room for this route. If not, we remove the
278  least recently used one we have. */
279 
280  if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
281  /* Removing the oldest route entry from the route table. The
282  least recently used route is the first route on the list. */
283  uip_ds6_route_t *oldest;
284 
285  oldest = uip_ds6_route_head();
286  PRINTF("uip_ds6_route_add: dropping route to ");
287  PRINT6ADDR(&oldest->ipaddr);
288  PRINTF("\n");
289  uip_ds6_route_rm(oldest);
290  }
291 
292 
293  /* Every neighbor on our neighbor table holds a struct
294  uip_ds6_route_neighbor_routes which holds a list of routes that
295  go through the neighbor. We add our route entry to this list.
296 
297  We first check to see if we already have this neighbor in our
298  nbr_route table. If so, the neighbor already has a route entry
299  list.
300  */
301  routes = nbr_table_get_from_lladdr(nbr_routes,
302  (linkaddr_t *)nexthop_lladdr);
303 
304  if(routes == NULL) {
305  /* If the neighbor did not have an entry in our neighbor table,
306  we create one. The nbr_table_add_lladdr() function returns a
307  pointer to a pointer that we may use for our own purposes. We
308  initialize this pointer with the list of routing entries that
309  are attached to this neighbor. */
310  routes = nbr_table_add_lladdr(nbr_routes,
311  (linkaddr_t *)nexthop_lladdr);
312  if(routes == NULL) {
313  /* This should not happen, as we explicitly deallocated one
314  route table entry above. */
315  PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n");
316  return NULL;
317  }
318  LIST_STRUCT_INIT(routes, route_list);
319  }
320 
321  /* Allocate a routing entry and populate it. */
322  r = memb_alloc(&routememb);
323 
324  if(r == NULL) {
325  /* This should not happen, as we explicitly deallocated one
326  route table entry above. */
327  PRINTF("uip_ds6_route_add: could not allocate route\n");
328  return NULL;
329  }
330 
331  list_add(routelist, r);
332 
333  nbrr = memb_alloc(&neighborroutememb);
334  if(nbrr == NULL) {
335  /* This should not happen, as we explicitly deallocated one
336  route table entry above. */
337  PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n");
338  memb_free(&routememb, r);
339  return NULL;
340  }
341 
342  nbrr->route = r;
343  /* Add the route to this neighbor */
344  list_add(routes->route_list, nbrr);
345  r->neighbor_routes = routes;
346  num_routes++;
347 
348  PRINTF("uip_ds6_route_add num %d\n", num_routes);
349  }
350 
351  uip_ipaddr_copy(&(r->ipaddr), ipaddr);
352  r->length = length;
353 
354 #ifdef UIP_DS6_ROUTE_STATE_TYPE
355  memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
356 #endif
357 
358  PRINTF("uip_ds6_route_add: adding route: ");
359  PRINT6ADDR(ipaddr);
360  PRINTF(" via ");
361  PRINT6ADDR(nexthop);
362  PRINTF("\n");
363  ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
364 
365 #if UIP_DS6_NOTIFICATIONS
366  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
367 #endif
368 
369 #if DEBUG != DEBUG_NONE
370  assert_nbr_routes_list_sane();
371 #endif /* DEBUG != DEBUG_NONE */
372  return r;
373 }
374 
375 /*---------------------------------------------------------------------------*/
376 void
377 uip_ds6_route_rm(uip_ds6_route_t *route)
378 {
379  struct uip_ds6_route_neighbor_route *neighbor_route;
380 #if DEBUG != DEBUG_NONE
381  assert_nbr_routes_list_sane();
382 #endif /* DEBUG != DEBUG_NONE */
383  if(route != NULL && route->neighbor_routes != NULL) {
384 
385  PRINTF("uip_ds6_route_rm: removing route: ");
386  PRINT6ADDR(&route->ipaddr);
387  PRINTF("\n");
388 
389  /* Remove the neighbor from the route list */
390  list_remove(routelist, route);
391 
392  /* Find the corresponding neighbor_route and remove it. */
393  for(neighbor_route = list_head(route->neighbor_routes->route_list);
394  neighbor_route != NULL && neighbor_route->route != route;
395  neighbor_route = list_item_next(neighbor_route));
396 
397  if(neighbor_route == NULL) {
398  PRINTF("uip_ds6_route_rm: neighbor_route was NULL for ");
399  uip_debug_ipaddr_print(&route->ipaddr);
400  PRINTF("\n");
401  }
402  list_remove(route->neighbor_routes->route_list, neighbor_route);
403  if(list_head(route->neighbor_routes->route_list) == NULL) {
404  /* If this was the only route using this neighbor, remove the
405  neibhor from the table */
406  PRINTF("uip_ds6_route_rm: removing neighbor too\n");
407  nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
408  }
409  memb_free(&routememb, route);
410  memb_free(&neighborroutememb, neighbor_route);
411 
412  num_routes--;
413 
414  PRINTF("uip_ds6_route_rm num %d\n", num_routes);
415 
416 #if UIP_DS6_NOTIFICATIONS
417  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
418  &route->ipaddr, uip_ds6_route_nexthop(route));
419 #endif
420 #if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE
421  /* we need to check if this was the last route towards "nexthop" */
422  /* if so - remove that link (annotation) */
423  uip_ds6_route_t *r;
424  for(r = uip_ds6_route_head();
425  r != NULL;
426  r = uip_ds6_route_next(r)) {
427  uip_ipaddr_t *nextr, *nextroute;
428  nextr = uip_ds6_route_nexthop(r);
429  nextroute = uip_ds6_route_nexthop(route);
430  if(nextr != NULL &&
431  nextroute != NULL &&
432  uip_ipaddr_cmp(nextr, nextroute)) {
433  /* we found another link using the specific nexthop, so keep the #L */
434  return;
435  }
436  }
437  ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]);
438 #endif
439  }
440 
441 #if DEBUG != DEBUG_NONE
442  assert_nbr_routes_list_sane();
443 #endif /* DEBUG != DEBUG_NONE */
444  return;
445 }
446 /*---------------------------------------------------------------------------*/
447 static void
448 rm_routelist(struct uip_ds6_route_neighbor_routes *routes)
449 {
450 #if DEBUG != DEBUG_NONE
451  assert_nbr_routes_list_sane();
452 #endif /* DEBUG != DEBUG_NONE */
453  PRINTF("uip_ds6_route_rm_routelist\n");
454  if(routes != NULL && routes->route_list != NULL) {
456  r = list_head(routes->route_list);
457  while(r != NULL) {
458  uip_ds6_route_rm(r->route);
459  r = list_head(routes->route_list);
460  }
461  nbr_table_remove(nbr_routes, routes);
462  }
463 #if DEBUG != DEBUG_NONE
464  assert_nbr_routes_list_sane();
465 #endif /* DEBUG != DEBUG_NONE */
466 }
467 /*---------------------------------------------------------------------------*/
468 static void
469 rm_routelist_callback(nbr_table_item_t *ptr)
470 {
471  rm_routelist((struct uip_ds6_route_neighbor_routes *)ptr);
472 }
473 /*---------------------------------------------------------------------------*/
474 void
475 uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
476 {
477  /* Get routing entry list of this neighbor */
478  const uip_lladdr_t *nexthop_lladdr;
479  struct uip_ds6_route_neighbor_routes *routes;
480 
481  nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
482  routes = nbr_table_get_from_lladdr(nbr_routes,
483  (linkaddr_t *)nexthop_lladdr);
484  rm_routelist(routes);
485 }
486 /*---------------------------------------------------------------------------*/
488 uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
489 {
490  uip_ds6_defrt_t *d;
491 
492 #if DEBUG != DEBUG_NONE
493  assert_nbr_routes_list_sane();
494 #endif /* DEBUG != DEBUG_NONE */
495 
496  PRINTF("uip_ds6_defrt_add\n");
497  d = uip_ds6_defrt_lookup(ipaddr);
498  if(d == NULL) {
499  d = memb_alloc(&defaultroutermemb);
500  if(d == NULL) {
501  PRINTF("uip_ds6_defrt_add: could not add default route to ");
502  PRINT6ADDR(ipaddr);
503  PRINTF(", out of memory\n");
504  return NULL;
505  } else {
506  PRINTF("uip_ds6_defrt_add: adding default route to ");
507  PRINT6ADDR(ipaddr);
508  PRINTF("\n");
509  }
510 
511  list_push(defaultrouterlist, d);
512  }
513 
514  uip_ipaddr_copy(&d->ipaddr, ipaddr);
515  if(interval != 0) {
516  stimer_set(&d->lifetime, interval);
517  d->isinfinite = 0;
518  } else {
519  d->isinfinite = 1;
520  }
521 
522  ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]);
523 
524 #if UIP_DS6_NOTIFICATIONS
525  call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr);
526 #endif
527 
528 #if DEBUG != DEBUG_NONE
529  assert_nbr_routes_list_sane();
530 #endif /* DEBUG != DEBUG_NONE */
531 
532  return d;
533 }
534 /*---------------------------------------------------------------------------*/
535 void
536 uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt)
537 {
538  uip_ds6_defrt_t *d;
539 
540 #if DEBUG != DEBUG_NONE
541  assert_nbr_routes_list_sane();
542 #endif /* DEBUG != DEBUG_NONE */
543 
544  /* Make sure that the defrt is in the list before we remove it. */
545  for(d = list_head(defaultrouterlist);
546  d != NULL;
547  d = list_item_next(d)) {
548  if(d == defrt) {
549  PRINTF("Removing default route\n");
550  list_remove(defaultrouterlist, defrt);
551  memb_free(&defaultroutermemb, defrt);
552  ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]);
553 #if UIP_DS6_NOTIFICATIONS
554  call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_RM,
555  &defrt->ipaddr, &defrt->ipaddr);
556 #endif
557  return;
558  }
559  }
560 #if DEBUG != DEBUG_NONE
561  assert_nbr_routes_list_sane();
562 #endif /* DEBUG != DEBUG_NONE */
563 
564 }
565 /*---------------------------------------------------------------------------*/
567 uip_ds6_defrt_lookup(uip_ipaddr_t *ipaddr)
568 {
569  uip_ds6_defrt_t *d;
570  for(d = list_head(defaultrouterlist);
571  d != NULL;
572  d = list_item_next(d)) {
573  if(uip_ipaddr_cmp(&d->ipaddr, ipaddr)) {
574  return d;
575  }
576  }
577  return NULL;
578 }
579 /*---------------------------------------------------------------------------*/
580 uip_ipaddr_t *
581 uip_ds6_defrt_choose(void)
582 {
583  uip_ds6_defrt_t *d;
584  uip_ds6_nbr_t *bestnbr;
585  uip_ipaddr_t *addr;
586 
587  addr = NULL;
588  for(d = list_head(defaultrouterlist);
589  d != NULL;
590  d = list_item_next(d)) {
591  PRINTF("Defrt, IP address ");
592  PRINT6ADDR(&d->ipaddr);
593  PRINTF("\n");
594  bestnbr = uip_ds6_nbr_lookup(&d->ipaddr);
595  if(bestnbr != NULL && bestnbr->state != NBR_INCOMPLETE) {
596  PRINTF("Defrt found, IP address ");
597  PRINT6ADDR(&d->ipaddr);
598  PRINTF("\n");
599  return &d->ipaddr;
600  } else {
601  addr = &d->ipaddr;
602  PRINTF("Defrt INCOMPLETE found, IP address ");
603  PRINT6ADDR(&d->ipaddr);
604  PRINTF("\n");
605  }
606  }
607  return addr;
608 }
609 /*---------------------------------------------------------------------------*/
610 void
611 uip_ds6_defrt_periodic(void)
612 {
613  uip_ds6_defrt_t *d;
614  d = list_head(defaultrouterlist);
615  while(d != NULL) {
616  if(!d->isinfinite &&
617  stimer_expired(&d->lifetime)) {
618  PRINTF("uip_ds6_defrt_periodic: defrt lifetime expired\n");
619  uip_ds6_defrt_rm(d);
620  d = list_head(defaultrouterlist);
621  } else {
622  d = list_item_next(d);
623  }
624  }
625 }
626 /*---------------------------------------------------------------------------*/
627 
628 #endif /* UIP_CONF_IPV6 */
Linked list manipulation routines.
An entry in the routing table.
int stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition: stimer.c:124
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
void list_push(list_t list, void *item)
Add an item to the start of the list.
Definition: list.c:165
Header file for the uIP TCP/IP stack.
Network interface and stateless autoconfiguration (RFC 4862)
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:325
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:79
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
#define NULL
The null pointer.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:61
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:240
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
The neighbor routes hold a list of routing table entries that are attached to a specific neihbor...
Definition: uip-ds6-route.h:98
int list_length(list_t list)
Get the length of a list.
Definition: list.c:275
void list_init(list_t list)
Initialize a list.
Definition: list.c:66
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1026
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:83
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:89
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:143
802.3 address
Definition: uip.h:135
A neighbor route list entry, used on the uip_ds6_route-&gt;neighbor_routes-&gt;route_list list...
#define LIST(name)
Declare a linked list.
Definition: list.h:86
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:122
A set of debugging macros.
Memory block allocation routines.
An entry in the default router list.
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:70