48 #include "lib/random.h"
51 #include "net/ip/uip-packetqueue.h"
55 #define DEBUG DEBUG_NONE
58 struct etimer uip_ds6_timer_periodic;
61 struct stimer uip_ds6_timer_ra;
63 static uint8_t racount;
64 static uint16_t rand_time;
68 static uint8_t rscount;
78 uint8_t uip_ds6_netif_addr_list_offset;
83 static uip_ipaddr_t loc_fipaddr;
96 uip_ds6_neighbors_init();
99 PRINTF(
"Init of IPv6 data structures\n");
100 PRINTF(
"%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n",
101 NBR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB,
102 UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB);
103 memset(uip_ds6_prefix_list, 0,
sizeof(uip_ds6_prefix_list));
104 memset(&uip_ds6_if, 0,
sizeof(uip_ds6_if));
106 uip_ds6_netif_addr_list_offset = offsetof(
struct uip_ds6_netif, addr_list);
110 uip_ds6_if.cur_hop_limit =
UIP_TTL;
111 uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
113 uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
117 uip_create_linklocal_prefix(&loc_fipaddr);
119 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
121 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
124 uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
127 uip_ds6_maddr_add(&loc_fipaddr);
130 uip_ds6_maddr_add(&loc_fipaddr);
136 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
151 for(locaddr = uip_ds6_if.addr_list;
152 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
153 if(locaddr->isused) {
154 if((!locaddr->isinfinite) && (
stimer_expired(&locaddr->vlifetime))) {
155 uip_ds6_addr_rm(locaddr);
156 #if UIP_ND6_DEF_MAXDADNS > 0
158 && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
161 uip_ds6_dad(locaddr);
168 uip_ds6_defrt_periodic();
179 for(locprefix = uip_ds6_prefix_list;
180 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
182 if(locprefix->isused && !locprefix->isinfinite
184 uip_ds6_prefix_rm(locprefix);
189 uip_ds6_neighbor_periodic();
191 #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA
194 uip_ds6_send_ra_periodic();
204 uint16_t elementsize, uip_ipaddr_t *ipaddr,
215 if(element->isused) {
216 if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
217 *out_element = element;
221 *out_element = element;
225 return *out_element !=
NULL ? FREESPACE : NOSPACE;
232 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
233 uint8_t advertise, uint8_t flags,
unsigned long vtime,
240 locprefix->isused = 1;
242 locprefix->length = ipaddrlen;
243 locprefix->advertise = advertise;
244 locprefix->l_a_reserved = flags;
245 locprefix->vlifetime = vtime;
246 locprefix->plifetime = ptime;
247 PRINTF(
"Adding prefix ");
248 PRINT6ADDR(&locprefix->ipaddr);
249 PRINTF(
"length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
250 ipaddrlen, flags, vtime, ptime);
253 PRINTF(
"No more space in Prefix list\n");
261 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
262 unsigned long interval)
268 locprefix->isused = 1;
270 locprefix->length = ipaddrlen;
272 stimer_set(&(locprefix->vlifetime), interval);
273 locprefix->isinfinite = 0;
275 locprefix->isinfinite = 1;
277 PRINTF(
"Adding prefix ");
278 PRINT6ADDR(&locprefix->ipaddr);
279 PRINTF(
"length %u, vlifetime%lu\n", ipaddrlen, interval);
296 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
309 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
311 for(locprefix = uip_ds6_prefix_list;
312 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
313 if(locprefix->isused &&
314 uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
323 uip_ds6_addr_add(uip_ipaddr_t *ipaddr,
unsigned long vlifetime, uint8_t type)
331 locaddr->type = type;
333 locaddr->isinfinite = 1;
335 locaddr->isinfinite = 0;
338 #if UIP_ND6_DEF_MAXDADNS > 0
341 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
343 locaddr->dadnscount = 0;
345 locaddr->state = ADDR_PREFERRED;
348 uip_ds6_maddr_add(&loc_fipaddr);
360 if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) !=
NULL) {
361 uip_ds6_maddr_rm(locmaddr);
370 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
388 uip_ds6_get_link_local(int8_t state)
390 for(locaddr = uip_ds6_if.addr_list;
391 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
392 if(locaddr->isused && (state == -1 || locaddr->state == state)
407 uip_ds6_get_global(int8_t state)
409 for(locaddr = uip_ds6_if.addr_list;
410 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
411 if(locaddr->isused && (state == -1 || locaddr->state == state)
421 uip_ds6_maddr_add(
const uip_ipaddr_t *ipaddr)
427 locmaddr->isused = 1;
446 uip_ds6_maddr_lookup(
const uip_ipaddr_t *ipaddr)
460 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
466 locaaddr->isused = 1;
485 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
505 for(locaddr = uip_ds6_if.addr_list;
506 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
508 if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
517 #if UIP_IPV6_MULTICAST
519 matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
522 matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
526 if(matchaddr ==
NULL) {
539 #if (UIP_LLADDR_LEN == 8)
540 memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
541 ipaddr->u8[8] ^= 0x02;
542 #elif (UIP_LLADDR_LEN == 6)
543 memcpy(ipaddr->u8 + 8, lladdr, 3);
544 ipaddr->u8[11] = 0xff;
545 ipaddr->u8[12] = 0xfe;
546 memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
547 ipaddr->u8[8] ^= 0x02;
549 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
560 for(j = 0; j < 16; j++) {
561 if(src->u8[j] == dst->u8[j]) {
564 x_or = src->u8[j] ^ dst->u8[j];
565 for(k = 0; k < 8; k++) {
566 if((x_or & 0x80) == 0) {
580 #if UIP_ND6_DEF_MAXDADNS > 0
585 if(addr->dadnscount < uip_ds6_if.maxdadns) {
596 PRINTF(
"DAD succeeded, ipaddr:");
597 PRINT6ADDR(&addr->ipaddr);
600 addr->state = ADDR_PREFERRED;
613 PRINTF(
"Contiki shutdown, DAD for link local address failed\n");
616 uip_ds6_addr_rm(addr);
625 uip_ds6_send_ra_sollicited(
void)
634 PRINTF(
"Solicited RA, random time %u\n", rand_time);
637 if(
stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
650 uip_ds6_send_ra_periodic(
void)
654 uip_nd6_ra_output(
NULL);
655 PRINTF(
"Sending periodic RA\n");
658 rand_time = UIP_ND6_MIN_RA_INTERVAL +
random_rand() %
659 (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
660 PRINTF(
"Random time 1 = %u\n", rand_time);
662 if(racount < UIP_ND6_MAX_INITIAL_RAS) {
663 if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
664 rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
665 PRINTF(
"Random time 2 = %u\n", rand_time);
669 PRINTF(
"Random time 3 = %u\n", rand_time);
679 if((uip_ds6_defrt_choose() ==
NULL)
680 && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
681 PRINTF(
"Sending RS %u\n", rscount);
687 PRINTF(
"Router found ? (boolean): %u\n",
688 (uip_ds6_defrt_choose() !=
NULL));
699 return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
700 (uip_ds6_if.base_reachable_time)) +
703 (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
704 UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
#define uip_create_unspecified(a)
set IP address a to unspecified
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
uip_len
The length of the packet in the uip_buf buffer.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
Neighbor discovery (RFC 4861)
int stimer_expired(struct stimer *t)
Check if a timer has expired.
#define uip_is_addr_link_local(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
#define UIP_DS6_PERIOD
General DS6 definitions.
Unicast address structure.
uint8_t uip_ds6_list_loop(uip_ds6_element_t *list, uint8_t size, uint16_t elementsize, uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, uip_ds6_element_t **out_element)
Generic loop routine on an abstract data structure, which generalizes all data structures used in DS6...
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
void uip_nd6_rs_output(void)
Send a Router Solicitation.
Network interface and stateless autoconfiguration (RFC 4862)
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
struct etimer uip_ds6_timer_rs
Timer for maintenance of data structures.
#define uip_is_addr_mcast_routable(a)
is address a routable multicast address.
void uip_ds6_periodic(void)
Periodic processing of data structures.
#define NULL
The null pointer.
#define uip_create_solicited_node(a, b)
put in b the solicited node address corresponding to address a both a and b are of type uip_ipaddr_t*...
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
The single interface.
#define UIP_ND6_DEF_MAXDADNS
Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8.2.
Generic type for a DS6, to use a common loop though all DS.
uint8_t uip_ds6_addr_size
Prefix list.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
void uip_ds6_send_rs(void)
Send periodic RS to find router.
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Interface structure (contains all the interface variables)
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define UIP_TTL
The IP TTL (time to live) of IP packets sent by uIP.
A set of debugging macros.
void uip_ds6_init(void)
Initialize data structures.
int timer_expired(struct timer *t)
Check if a timer has expired.
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
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.
unsigned long stimer_elapsed(struct stimer *t)
The time elapsed since the timer started.
uint8_t get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Get the number of matching bits of two addresses.
#define CLOCK_SECOND
A second, measured in system clock time.
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.