48 #include "lib/random.h" 53 #include "net/ipv6/uip-packetqueue.h" 57 #define LOG_MODULE "IPv6 DS" 58 #define LOG_LEVEL LOG_LEVEL_IPV6 63 struct stimer uip_ds6_timer_ra;
65 static uint8_t racount;
66 static uint16_t rand_time;
79 uint8_t uip_ds6_addr_size;
80 uint8_t uip_ds6_netif_addr_list_offset;
85 static uip_ipaddr_t loc_fipaddr;
94 #if (UIP_LLADDR_LEN == 2) 95 static const uint8_t iid_prefix[] = { 0x00, 0x00 , 0x00 , 0xff , 0xfe , 0x00 };
99 static uip_ip6addr_t default_prefix = {
100 .u16 = { 0, 0, 0, 0, 0, 0, 0, 0 }
103 const uip_ip6addr_t *
106 return &default_prefix;
112 uip_ip6addr_copy(&default_prefix, prefix);
119 uip_ip6addr(&default_prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
122 uip_ds6_neighbors_init();
123 uip_ds6_route_init();
125 LOG_INFO(
"Init: %u neighbors\n", NBR_TABLE_MAX_NEIGHBORS);
126 LOG_INFO(
"%u default routers\n", UIP_DS6_DEFRT_NB);
127 LOG_INFO(
"%u prefixes\n", UIP_DS6_PREFIX_NB);
128 LOG_INFO(
"%u routes\n", UIP_DS6_ROUTE_NB);
129 LOG_INFO(
"%u unicast addresses\n", UIP_DS6_ADDR_NB);
130 LOG_INFO(
"%u multicast addresses\n", UIP_DS6_MADDR_NB);
131 LOG_INFO(
"%u anycast addresses\n", UIP_DS6_AADDR_NB);
133 memset(uip_ds6_prefix_list, 0,
sizeof(uip_ds6_prefix_list));
134 memset(&uip_ds6_if, 0,
sizeof(uip_ds6_if));
136 uip_ds6_netif_addr_list_offset = offsetof(
struct uip_ds6_netif, addr_list);
140 uip_ds6_if.cur_hop_limit =
UIP_TTL;
141 uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
143 uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
147 uip_create_linklocal_prefix(&loc_fipaddr);
149 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
151 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
157 uip_ds6_maddr_add(&loc_fipaddr);
160 uip_ds6_maddr_add(&loc_fipaddr);
181 for(locaddr = uip_ds6_if.addr_list;
182 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
183 if(locaddr->isused) {
184 if((!locaddr->isinfinite) && (
stimer_expired(&locaddr->vlifetime))) {
185 uip_ds6_addr_rm(locaddr);
186 #if UIP_ND6_DEF_MAXDADNS > 0 188 && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
198 uip_ds6_defrt_periodic();
209 for(locprefix = uip_ds6_prefix_list;
210 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
212 if(locprefix->isused && !locprefix->isinfinite
214 uip_ds6_prefix_rm(locprefix);
223 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA 226 uip_ds6_send_ra_periodic();
236 uint16_t elementsize, uip_ipaddr_t *
ipaddr,
241 if(list == NULL || ipaddr == NULL || out_element == NULL) {
251 if(element->isused) {
252 if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
253 *out_element = element;
257 *out_element = element;
261 return *out_element != NULL ? FREESPACE : NOSPACE;
268 uip_ds6_prefix_add(uip_ipaddr_t *
ipaddr, uint8_t ipaddrlen,
269 uint8_t advertise, uint8_t flags,
unsigned long vtime,
276 locprefix->isused = 1;
278 locprefix->length = ipaddrlen;
279 locprefix->advertise = advertise;
280 locprefix->l_a_reserved = flags;
281 locprefix->vlifetime = vtime;
282 locprefix->plifetime = ptime;
283 LOG_INFO(
"Adding prefix ");
284 LOG_INFO_6ADDR(&locprefix->ipaddr);
285 LOG_INFO_(
"length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
286 ipaddrlen, flags, vtime, ptime);
289 LOG_INFO(
"No more space in Prefix list\n");
297 uip_ds6_prefix_add(uip_ipaddr_t *
ipaddr, uint8_t ipaddrlen,
298 unsigned long interval)
304 locprefix->isused = 1;
306 locprefix->length = ipaddrlen;
308 stimer_set(&(locprefix->vlifetime), interval);
309 locprefix->isinfinite = 0;
311 locprefix->isinfinite = 1;
313 LOG_INFO(
"Adding prefix ");
314 LOG_INFO_6ADDR(&locprefix->ipaddr);
315 LOG_INFO_(
"length %u, vlifetime %lu\n", ipaddrlen, interval);
333 uip_ds6_prefix_lookup(uip_ipaddr_t *
ipaddr, uint8_t ipaddrlen)
346 uip_ds6_is_addr_onlink(uip_ipaddr_t *
ipaddr)
348 for(locprefix = uip_ds6_prefix_list;
349 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
350 if(locprefix->isused &&
351 uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
368 locaddr->type = type;
370 locaddr->isinfinite = 1;
372 locaddr->isinfinite = 0;
375 #if UIP_ND6_DEF_MAXDADNS > 0 380 locaddr->dadnscount = 0;
382 locaddr->state = ADDR_PREFERRED;
385 uip_ds6_maddr_add(&loc_fipaddr);
397 if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
398 uip_ds6_maddr_rm(locmaddr);
407 uip_ds6_addr_lookup(uip_ipaddr_t *
ipaddr)
425 uip_ds6_get_link_local(int8_t state)
427 for(locaddr = uip_ds6_if.addr_list;
428 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
429 if(locaddr->isused && (state == -1 || locaddr->state == state)
444 uip_ds6_get_global(int8_t state)
446 for(locaddr = uip_ds6_if.addr_list;
447 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
448 if(locaddr->isused && (state == -1 || locaddr->state == state)
458 uip_ds6_maddr_add(
const uip_ipaddr_t *
ipaddr)
464 locmaddr->isused = 1;
483 uip_ds6_maddr_lookup(
const uip_ipaddr_t *
ipaddr)
497 uip_ds6_aaddr_add(uip_ipaddr_t *
ipaddr)
504 locaaddr->isused = 1;
524 uip_ds6_aaddr_lookup(uip_ipaddr_t *
ipaddr)
546 for(locaddr = uip_ds6_if.addr_list;
547 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
549 if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
558 #if UIP_IPV6_MULTICAST 560 matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
563 matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
567 if(matchaddr == NULL) {
578 #if (UIP_LLADDR_LEN == 8) 580 ipaddr->u8[8] ^= 0x02;
581 #elif (UIP_LLADDR_LEN == 6) 582 memcpy(ipaddr->u8 + 8, lladdr, 3);
583 ipaddr->u8[11] = 0xff;
584 ipaddr->u8[12] = 0xfe;
585 memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
586 ipaddr->u8[8] ^= 0x02;
587 #elif (UIP_LLADDR_LEN == 2) 589 memcpy(ipaddr->u8 + 8, iid_prefix, 6);
592 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6, 8, or 2 599 #if (UIP_LLADDR_LEN == 8) 601 lladdr->addr[0] ^= 0x02;
602 #elif (UIP_LLADDR_LEN == 2) 605 #error uip-ds6.c cannot build lladdr address when UIP_LLADDR_LEN is not 8 or 2 616 for(j = 0; j < 16; j++) {
617 if(src->u8[j] == dst->u8[j]) {
620 x_or = src->u8[j] ^ dst->u8[j];
621 for(k = 0; k < 8; k++) {
622 if((x_or & 0x80) == 0) {
636 #if UIP_ND6_DEF_MAXDADNS > 0 641 if(addr->dadnscount < uip_ds6_if.maxdadns) {
652 LOG_INFO(
"DAD succeeded, ipaddr: ");
653 LOG_INFO_6ADDR(&addr->ipaddr);
656 addr->state = ADDR_PREFERRED;
669 LOG_ERR(
"Contiki shutdown, DAD for link local address failed\n");
672 uip_ds6_addr_rm(addr);
681 uip_ds6_send_ra_sollicited(
void)
690 LOG_INFO(
"Solicited RA, random time %u\n", rand_time);
693 if(
stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
706 uip_ds6_send_ra_periodic(
void)
710 uip_nd6_ra_output(NULL);
711 LOG_INFO(
"Sending periodic RA\n");
714 rand_time = UIP_ND6_MIN_RA_INTERVAL +
random_rand() %
715 (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
716 LOG_DBG(
"Random time 1 = %u\n", rand_time);
718 if(racount < UIP_ND6_MAX_INITIAL_RAS) {
719 if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
720 rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
721 LOG_DBG(
"Random time 2 = %u\n", rand_time);
725 LOG_DBG(
"Random time 3 = %u\n", rand_time);
735 if((uip_ds6_defrt_choose() == NULL)
737 LOG_INFO(
"Sending RS %u\n",
rscount);
743 LOG_INFO(
"Router found ? (boolean): %u\n",
744 (uip_ds6_defrt_choose() != NULL));
755 return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
756 (uip_ds6_if.base_reachable_time)) +
759 (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
760 UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
uip_lladdr_t uip_lladdr
Host L2 address.
void etimer_stop(struct etimer *et)
Stop a pending event timer.
#define uip_is_addr_mcast_routable(a)
is address a routable multicast address.
void uip_ds6_send_rs(void)
Send periodic RS to find router.
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.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
void uip_ds6_init(void)
Initialize data structures.
#define UIP_ND6_RTR_SOLICITATION_INTERVAL
Router solicitation interval.
Generic type for a DS6, to use a common loop though all DS.
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
int stimer_expired(struct stimer *t)
Check if a timer has expired.
void uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
Build a link-layer address from an IPv6 address based on its UUID64.
uint8_t get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Get the number of matching bits of two addresses.
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_ds6_dad(uip_ds6_addr_t *addr)
Perform Duplicate Address Selection on one address.
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
Prefix list.
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Header file for IPv6-related data structures.
int uip_ds6_dad_failed(uip_ds6_addr_t *addr)
Callback when DAD failed.
#define UIP_LLADDR_LEN
802.15.4 address
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.
This header file contains configuration directives for uIPv6 multicast support.
unsigned long stimer_elapsed(struct stimer *t)
The time elapsed since the timer started.
#define CLOCK_SECOND
A second, measured in system clock time.
void uip_ds6_set_default_prefix(const uip_ip6addr_t *prefix)
Set the Default IPv6 prefix.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
const uip_ip6addr_t * uip_ds6_default_prefix()
Retrieve the Default IPv6 prefix.
void uip_ds6_neighbor_periodic(void)
The housekeeping function called periodically.
static uint8_t rscount
number of rs already sent
struct etimer uip_ds6_timer_periodic
Timer for maintenance of data structures.
#define UIP_ND6_MAX_RTR_SOLICITATIONS
Maximum router solicitations.
#define UIP_ND6_DEF_MAXDADNS
Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8.2.
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Unicast address structure.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY
Maximum router solicitation delay.
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
Add a unicast address to the interface.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
void uip_ds6_periodic(void)
Periodic processing of data structures.
struct etimer uip_ds6_timer_rs
RS timer, to schedule RS sending.
#define uip_create_unspecified(a)
set IP address a to unspecified
Header file for IPv6 Neighbor discovery (RFC 4861)
uip_ds6_netif_t uip_ds6_if
The single interface.
Interface structure (contains all the interface variables)
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...
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Header file for the logging system
#define UIP_TTL
The IP TTL (time to live) of IP packets sent by uIP.
void uip_nd6_rs_output(void)
Neighbor Solicitation Processing.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define UIP_DS6_PERIOD
General DS6 definitions.
#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*...
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.