/*---------------------------------------------------------------------------*/ static void check_prefix(rpl_prefix_t *last_prefix, rpl_prefix_t *new_prefix) { uip_ipaddr_t ipaddr; uip_ds6_addr_t *rep; if(last_prefix != NULL && new_prefix != NULL && last_prefix->length == new_prefix->length && uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length) && last_prefix->flags == new_prefix->flags) { /* Nothing has changed. */ return; } if(last_prefix != NULL) { set_ip_from_prefix(&ipaddr, last_prefix); rep = uip_ds6_addr_lookup(&ipaddr); if(rep != NULL) { PRINTF("RPL: removing global IP address "); PRINT6ADDR(&ipaddr); PRINTF("\n"); uip_ds6_addr_rm(rep); } } if(new_prefix != NULL) { set_ip_from_prefix(&ipaddr, new_prefix); if(uip_ds6_addr_lookup(&ipaddr) == NULL) { PRINTF("RPL: adding global IP address "); PRINT6ADDR(&ipaddr); PRINTF("\n"); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } } }
/*---------------------------------------------------------------------------*/ void uip_ds6_set_lladdr(uip_lladdr_t *lladdr) { /* First remove the current address from system as this function * can be called many times. */ uip_ds6_addr_rm(uip_ds6_addr_lookup(&loc_fipaddr)); /* Create link local address, prefix, multicast addresses, * anycast addresses */ uip_create_linklocal_prefix(&loc_fipaddr); #if UIP_CONF_ROUTER uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); #else /* UIP_CONF_ROUTER */ uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0); #endif /* UIP_CONF_ROUTER */ memcpy(&uip_lladdr, lladdr, sizeof(uip_lladdr)); uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr); uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF); uip_create_linklocal_allnodes_mcast(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); #if UIP_CONF_ROUTER uip_create_linklocal_allrouters_mcast(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); #endif /* UIP_CONF_ROUTER */ }
/* * Calling code must handle when this returns 0 (e.g. link local * address can not be used). */ int uip_ds6_dad_failed(uip_ds6_addr_t *addr) { if(uip_is_addr_link_local(&addr->ipaddr)) { PRINTF("Contiki shutdown, DAD for link local address failed\n"); return 0; } uip_ds6_addr_rm(addr); return 1; }
/*---------------------------------------------------------------------------*/ void uip_ds6_periodic(struct net_buf *buf) { uip_ds6_addr_t *locaddr; uip_ds6_prefix_t *locprefix; /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); #if UIP_ND6_DEF_MAXDADNS > 0 } else if((locaddr->state == ADDR_TENTATIVE) && (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (timer_expired(&locaddr->dadtimer))) { uip_ds6_dad(NULL, locaddr); #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } } } /* Periodic processing on default routers */ uip_ds6_defrt_periodic(); /* for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (!locdefrt->isinfinite) && (stimer_expired(&(locdefrt->lifetime)))) { uip_ds6_defrt_rm(locdefrt); } }*/ #if !UIP_CONF_ROUTER /* Periodic processing on prefixes */ for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && !locprefix->isinfinite && stimer_expired(&(locprefix->vlifetime))) { uip_ds6_prefix_rm(locprefix); } } #endif /* !UIP_CONF_ROUTER */ uip_ds6_neighbor_periodic(buf); #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA /* Periodic RA sending */ if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) { uip_ds6_send_ra_periodic(); } #endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */ etimer_reset(&uip_ds6_timer_periodic); return; }
/*---------------------------------------------------------------------------*/ uip_ds6_addr_t * uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr) { if(uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB, sizeof(uip_ds6_addr_t), ipaddr, 128, (uip_ds6_element_t **)&locaddr) == FOUND) { if((!locaddr->isinfinite) && (stimestamp_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); return NULL; } return locaddr; } return NULL; }
/*---------------------------------------------------------------------------*/ uip_ds6_maddr_t * uip_ds6_maddr_solicited_node_verify(uip_ds6_maddr_t * maddr) { for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimestamp_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); } else if ((locaddr->ipaddr.u8[13] == maddr->ipaddr.u8[13]) && (locaddr->ipaddr.u16[7] == maddr->ipaddr.u16[7])){ return maddr; } } } return NULL; }
/* * get a global address - * state = -1 => any address is ok. Otherwise state = desired state of addr. * (TENTATIVE, PREFERRED, DEPRECATED) */ uip_ds6_addr_t * uip_ds6_get_global(int8_t state) { for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused && (state == -1 || locaddr->state == state) && !(uip_is_addr_link_local(&locaddr->ipaddr))) { if((!locaddr->isinfinite) && (stimestamp_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); } else { return locaddr; } } } return NULL; }
/*---------------------------------------------------------------------------*/ inline void uip_ds6_addr_clean(void) { uip_ds6_addr_t *element; for(element = uip_ds6_if.addr_list; element < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; ++element) { if(!element->isinfinite && stimestamp_expired(&(element->vlifetime))) { uip_ds6_addr_rm(element); locaddr = element; loc_loop_state = FREESPACE; return; } } }
/*---------------------------------------------------------------------------*/ static void slip_input_callback(void) { unsigned char i; unsigned short chek_summ,chek_summ_recv; if (strncmp(uip_buf, "AdressTarget", 12) == 0){ chek_summ =chksum(chek_summ,(uint8_t*)uip_buf,16); chek_summ_recv = uip_buf[16]; chek_summ_recv |= ((uint16_t)uip_buf[17])<<8; if (chek_summ_recv==chek_summ){ //set new IPv6 addres uip_ipaddr_t ipaddr; uip_lladdr_t lladdr; lladdr.addr[0] = 0x00; lladdr.addr[1] = 0x12; lladdr.addr[2] = 0x4b; lladdr.addr[3] = 0x00; lladdr.addr[4] = uip_buf[12]; lladdr.addr[5] = uip_buf[13]; lladdr.addr[6] = uip_buf[14]; lladdr.addr[7] = uip_buf[15]; for (i=0;i<4;i++){ if (uip_buf[12+i]!= uip_ds6_if.addr_list[0].ipaddr.u8[12+i]) break; } if (i<4){ uip_ds6_addr_rm(&uip_ds6_if.addr_list[0]); uip_ip6addr(&ipaddr, 0x2001, 0x0db8, 0, 0x0212, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); uip_buf[12] = uip_ds6_if.addr_list[0].ipaddr.u8[12]; uip_buf[13] = uip_ds6_if.addr_list[0].ipaddr.u8[13]; uip_buf[14] = uip_ds6_if.addr_list[0].ipaddr.u8[14]; uip_buf[15] = uip_ds6_if.addr_list[0].ipaddr.u8[15]; slip_write(uip_buf, 16); print_local_addresses(); } } } // PRINTF("SIN: %u\n", uip_len); }
/*---------------------------------------------------------------------------*/ void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst) { uint8_t best = 0; /* number of bit in common with best match */ uint8_t n = 0; uip_ds6_addr_t *matchaddr = NULL; if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) { /* find longest match */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { /* Only preferred global (not link-local) addresses */ PRINTF("PReff %i ",locaddr->isused && locaddr->state); PRINT6ADDR(&locaddr->ipaddr); PRINTF("\n"); if(locaddr->isused && locaddr->state == ADDR_PREFERRED && !uip_is_addr_link_local(&locaddr->ipaddr)) { if((!locaddr->isinfinite) && (stimestamp_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); } else { n = get_match_length(dst, &locaddr->ipaddr); if(n >= best) { best = n; matchaddr = locaddr; } } } } } else { matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED); } /* use the :: (unspecified address) as source if no match found */ if(matchaddr == NULL) { uip_create_unspecified(src); } else { uip_ipaddr_copy(src, &matchaddr->ipaddr); } }
/*---------------------------------------------------------------------------*/ void uip_ds6_periodic(void) { /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); #if UIP_ND6_DEF_MAXDADNS > 0 } else if((locaddr->state == ADDR_TENTATIVE) && (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (timer_expired(&locaddr->dadtimer)) && (uip_len == 0)) { uip_ds6_dad(locaddr); #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } } } /* Periodic processing on default routers */ for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (!locdefrt->isinfinite) && (stimer_expired(&(locdefrt->lifetime)))) { uip_ds6_defrt_rm(locdefrt); } } #if !UIP_CONF_ROUTER /* Periodic processing on prefixes */ for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && !locprefix->isinfinite && stimer_expired(&(locprefix->vlifetime))) { uip_ds6_prefix_rm(locprefix); } } #endif /* !UIP_CONF_ROUTER */ /* Periodic processing on neighbors */ for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; locnbr++) { if(locnbr->isused) { switch(locnbr->state) { case NBR_INCOMPLETE: if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&locnbr->sendns) && (uip_len == 0)) { locnbr->nscount++; PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr); stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000); } break; case NBR_REACHABLE: if(stimer_expired(&locnbr->reachable)) { PRINTF("REACHABLE: moving to STALE ("); PRINT6ADDR(&locnbr->ipaddr); PRINTF(")\n"); locnbr->state = NBR_STALE; } break; case NBR_DELAY: if(stimer_expired(&locnbr->reachable)) { locnbr->state = NBR_PROBE; locnbr->nscount = 0; PRINTF("DELAY: moving to PROBE\n"); stimer_set(&locnbr->sendns, 0); } break; case NBR_PROBE: if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) { PRINTF("PROBE END\n"); if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) { if (!locdefrt->isinfinite) { uip_ds6_defrt_rm(locdefrt); } } uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&locnbr->sendns) && (uip_len == 0)) { locnbr->nscount++; PRINTF("PROBE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr); stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000); } break; default: break; } } } #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA /* Periodic RA sending */ if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) { uip_ds6_send_ra_periodic(); } #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */ etimer_reset(&uip_ds6_timer_periodic); return; }
/*---------------------------------------------------------------------------*/ void cetic_6lbr_init(void) { uip_ds6_addr_t *local = uip_ds6_get_link_local(-1); uip_ipaddr_copy(&wsn_ip_local_addr, &local->ipaddr); LOG6LBR_6ADDR(INFO, &wsn_ip_local_addr, "Tentative local IPv6 address "); eth_mac64_addr.addr[0] = eth_mac_addr[0]; eth_mac64_addr.addr[1] = eth_mac_addr[1]; eth_mac64_addr.addr[2] = eth_mac_addr[2]; eth_mac64_addr.addr[3] = CETIC_6LBR_ETH_EXT_A; eth_mac64_addr.addr[4] = CETIC_6LBR_ETH_EXT_B; eth_mac64_addr.addr[5] = eth_mac_addr[3]; eth_mac64_addr.addr[6] = eth_mac_addr[4]; eth_mac64_addr.addr[7] = eth_mac_addr[5]; #if CETIC_6LBR_SMARTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) //Manual configuration { memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); wsn_net_prefix_len = nvm_data.wsn_net_prefix_len; if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address "); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } uip_ipaddr_t dns; memcpy(dns.u8, &nvm_data.dns_server, sizeof(nvm_data.dns_server)); uip_nameserver_update(&dns, UIP_NAMESERVER_INFINITE_LIFETIME); } else { //End manual configuration uip_create_unspecified(&wsn_net_prefix); wsn_net_prefix_len = 0; uip_create_unspecified(&wsn_ip_addr); } #endif #if CETIC_6LBR_ROUTER //WSN network configuration memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); wsn_net_prefix_len = nvm_data.wsn_net_prefix_len; if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address (WSN) "); uip_ipaddr_t dns; memcpy(dns.u8, &nvm_data.dns_server, sizeof(nvm_data.dns_server)); uip_nameserver_update(&dns, UIP_NAMESERVER_INFINITE_LIFETIME); //Ethernet network configuration memcpy(eth_net_prefix.u8, &nvm_data.eth_net_prefix, sizeof(nvm_data.eth_net_prefix)); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } if((nvm_data.mode & CETIC_MODE_ETH_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(ð_ip_addr, ð_net_prefix); uip_ds6_set_addr_iid(ð_ip_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(eth_ip_addr.u8, &nvm_data.eth_ip_addr, sizeof(nvm_data.eth_ip_addr)); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, ð_ip_addr, "Tentative global IPv6 address (ETH) "); //Ugly hack : in order to set WSN local address as the default address //We must add it afterwards as uip_ds6_addr_add allocates addr from the end of the list uip_ds6_addr_rm(local); uip_create_linklocal_prefix(ð_ip_local_addr); uip_ds6_set_addr_iid(ð_ip_local_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_addr_add(&wsn_ip_local_addr, 0, ADDR_AUTOCONF); //Prefix and RA configuration #if CETIC_6LBR_WITH_RPL uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #else uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, 0, 0, 0, 0); uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #endif #if CETIC_6LBR_WITH_RPL if ((nvm_data.ra_rio_flags & CETIC_6LBR_MODE_SEND_RIO) != 0 ) { uip_ds6_route_info_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, nvm_data.ra_rio_flags, nvm_data.ra_rio_lifetime); } #endif if ((nvm_data.mode & CETIC_MODE_ROUTER_RA_DAEMON) != 0 ) { LOG6LBR_INFO("RA Daemon enabled\n"); } else { LOG6LBR_INFO("RA Daemon disabled\n"); } #endif }
/*---------------------------------------------------------------------------*/ void uip_ds6_periodic(void) { /* This flag signals whether we allow or not to send a packet in the current * invocation. */ u8_t allow_output = 1; /* minimum lifetime */ min_lifetime = 0xFFFFFFFF; /* router with minimum lifetime */ min_defrt = NULL; /* Periodic processing on registrations */ for(locreg = uip_ds6_reg_list; locreg < uip_ds6_reg_list + UIP_DS6_REG_LIST_SIZE; locreg++) { if (locreg->isused) { if (stimer_expired(&locreg->reg_lifetime)) { uip_ds6_reg_rm(locreg); } else if (allow_output) { /* If no output is allowed, it is pointless to enter here in this invocation */ if (uip_ds6_if.registration_in_progress) { /* There is a registration in progress */ if ((locreg == uip_ds6_if.registration_in_progress) && (timer_expired(&locreg->registration_timer))) { /* We already sent a NS message for this address but there has been no response */ if(locreg->reg_count >= UIP_ND6_MAX_UNICAST_SOLICIT) { /* NUD failed. Signal the need for next-hop determination by deleting the * NCE (RFC 4861) */ uip_ds6_reg_rm(locreg); /* And then, delete neighbor and corresponding router (as hosts only keep * NCEs for routers in 6lowpan-nd) */ locnbr = uip_ds6_nbr_lookup(&locreg->defrt->ipaddr); uip_ds6_nbr_rm(locnbr); uip_ds6_defrt_rm(locreg->defrt); /* Since we are deleting a default router, we must delete also all * registrations with that router. * Be careful here, uip_ds6_reg_cleanup_defrt() modifies the value of locreg!*/ uip_ds6_reg_cleanup_defrt(locreg->defrt); /* We will also need to start sending RS, as specified in I-D.ietf-6lowpan-nd * for NUD failure case */ uip_ds6_send_rs(NULL); uip_ds6_if.registration_in_progress = NULL; } else { locreg->reg_count++; timer_restart(&locreg->registration_timer); uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME); } allow_output = 0; /* Prevent this invocation from sending anything else */ } } else { /* There are no registrations in progress, let's see this entry needs (re)registration * or deletion */ if ((locreg->state == REG_GARBAGE_COLLECTIBLE) || (locreg->state == REG_TO_BE_UNREGISTERED) || ((locreg->state == REG_REGISTERED) && (stimer_remaining(&locreg->reg_lifetime) < stimer_elapsed(&locreg->reg_lifetime)))) { /* Issue (re)registration */ uip_ds6_if.registration_in_progress = locreg; locreg->reg_count++; timer_set(&locreg->registration_timer, (uip_ds6_if.retrans_timer / 1000) * (CLOCK_SECOND /* FIXME @@@jwg!!!!*/+250)); if (locreg->state == REG_TO_BE_UNREGISTERED) { uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, 0); } else { uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME); } allow_output = 0; /* Prevent this invocation from sending anything else */ } } } } } /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); } else if (allow_output) { if (stimer_remaining(&locaddr->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locaddr->vlifetime); min_defrt = locaddr->defrt; } } } } /* Periodic processing on default routers */ if (uip_ds6_defrt_choose() == NULL) { if (allow_output) { /* If default router list is empty, start sending RS */ uip_ds6_send_rs(NULL); allow_output = 0; /* Prevent this invocation from sending anything else */ } } else { for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (!locdefrt->isinfinite)) { if (stimer_expired(&(locdefrt->lifetime))) { uip_ds6_defrt_rm(locdefrt); /* If default router list is empty, we will start sending RS in * the next invocation of ds6_periodic() */ } else { if (allow_output) { if (stimer_remaining(&locdefrt->lifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locdefrt->lifetime); min_defrt = locdefrt; } } } } } } #if !UIP_CONF_ROUTER /* Periodic processing on prefixes */ for (locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if((locprefix->isused) && (!locprefix->isinfinite)) { if (stimer_expired(&locprefix->vlifetime)) { uip_ds6_prefix_rm(locprefix); } else if (allow_output) { if (stimer_remaining(&locprefix->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locprefix->vlifetime); min_defrt = locprefix->defrt; } } } } #endif /* !UIP_CONF_ROUTER */ #if CONF_6LOWPAN_ND_6CO /* Periodic processing on contexts */ for(loccontext = uip_ds6_addr_context_table; loccontext < uip_ds6_addr_context_table + SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; loccontext++) { if(loccontext->state != NOT_IN_USE) { if (stimer_expired(&loccontext->vlifetime)) { if (loccontext->state != EXPIRED) { loccontext->state = IN_USE_UNCOMPRESS_ONLY; stimer_set(&loccontext->vlifetime, 2 * loccontext->defrt_lifetime); } else { uip_ds6_context_rm(loccontext); } } else if (allow_output) { if (stimer_remaining(&loccontext->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&loccontext->vlifetime); min_defrt = loccontext->defrt; } } } } #endif /* CONF_6LOWPAN_ND_6CO */ /* Start sending RS well before the minimum of the lifetimes (def. router, * context, or prefix) expires */ if ((allow_output) && (min_lifetime < UIP_DS6_LIFETIME_THRESHOLD)) { /* Start sending RSs to the router with minimum lifetime (if possible) */ uip_ds6_send_rs(min_defrt); allow_output = 0; } /* Periodic processing on neighbors */ for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; locnbr++) { if(locnbr->isused) { switch (locnbr->state) { #if UIP_CONF_ROUTER /* There can not be INCOMPLETE NCEs in a host in 6lowpan-nd */ case NBR_INCOMPLETE: if (allow_output) { if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&(locnbr->sendns))) { locnbr->nscount++; PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; #endif /* UIP_CONF_ROUTER */ case NBR_REACHABLE: if(stimer_expired(&(locnbr->reachable))) { PRINTF("REACHABLE: moving to STALE ("); PRINT6ADDR(&locnbr->ipaddr); PRINTF(")\n"); locnbr->state = NBR_STALE; NEIGHBOR_STATE_CHANGED(locnbr); } break; case NBR_DELAY: if (allow_output) { if(stimer_expired(&(locnbr->reachable))) { locnbr->state = NBR_PROBE; locnbr->nscount = 1; NEIGHBOR_STATE_CHANGED(locnbr); PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; case NBR_PROBE: if (allow_output) { if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) { PRINTF("PROBE END \n"); if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) { uip_ds6_defrt_rm(locdefrt); } uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&(locnbr->sendns))) { locnbr->nscount++; PRINTF("PROBE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; default: break; } } } #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA /* Periodic RA sending */ if(stimer_expired(&uip_ds6_timer_ra)) { uip_ds6_send_ra_periodic(); } #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */ etimer_reset(&uip_ds6_timer_periodic); return; }
void cetic_6lbr_init(void) { uip_ds6_addr_t *local = uip_ds6_get_link_local(-1); uip_ipaddr_copy(&wsn_ip_local_addr, &local->ipaddr); LOG6LBR_6ADDR(INFO, &wsn_ip_local_addr, "Tentative local IPv6 address "); #if CETIC_6LBR_SMARTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) //Manual configuration { memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address "); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } } //End manual configuration #endif #if CETIC_6LBR_ROUTER //WSN network configuration memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); wsn_net_prefix_len = nvm_data.wsn_net_prefix_len; if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address (WSN) "); //Ethernet network configuration memcpy(eth_net_prefix.u8, &nvm_data.eth_net_prefix, sizeof(nvm_data.eth_net_prefix)); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); if ( !uip_is_addr_unspecified(ð_dft_router) ) { uip_ds6_defrt_add(ð_dft_router, 0); } eth_mac64_addr.addr[0] = eth_mac_addr[0]; eth_mac64_addr.addr[1] = eth_mac_addr[1]; eth_mac64_addr.addr[2] = eth_mac_addr[2]; eth_mac64_addr.addr[3] = CETIC_6LBR_ETH_EXT_A; eth_mac64_addr.addr[4] = CETIC_6LBR_ETH_EXT_B; eth_mac64_addr.addr[5] = eth_mac_addr[3]; eth_mac64_addr.addr[6] = eth_mac_addr[4]; eth_mac64_addr.addr[7] = eth_mac_addr[5]; if((nvm_data.mode & CETIC_MODE_ETH_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(ð_ip_addr, ð_net_prefix); uip_ds6_set_addr_iid(ð_ip_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(eth_ip_addr.u8, &nvm_data.eth_ip_addr, sizeof(nvm_data.eth_ip_addr)); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_MANUAL); } LOG6LBR_6ADDR(INFO, ð_ip_addr, "Tentative global IPv6 address (ETH) "); //Ugly hack : in order to set WSN local address as the default address //We must add it afterwards as uip_ds6_addr_add allocates addr from the end of the list uip_ds6_addr_rm(local); uip_create_linklocal_prefix(ð_ip_local_addr); uip_ds6_set_addr_iid(ð_ip_local_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_addr_add(&wsn_ip_local_addr, 0, ADDR_AUTOCONF); //Prefix and RA configuration #if UIP_CONF_IPV6_RPL uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #else uip_ds6_prefix_add(ð_net_prefix, nvm_data.eth_net_prefix_len, 0, 0, 0, 0); uint8_t publish = (nvm_data.ra_prefix_flags & CETIC_6LBR_MODE_SEND_PIO) != 0; uip_ds6_prefix_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, publish, nvm_data.ra_prefix_flags, nvm_data.ra_prefix_vtime, nvm_data.ra_prefix_ptime); #endif #if UIP_CONF_IPV6_RPL if ((nvm_data.ra_rio_flags & CETIC_6LBR_MODE_SEND_RIO) != 0 ) { uip_ds6_route_info_add(&wsn_net_prefix, nvm_data.wsn_net_prefix_len, nvm_data.ra_rio_flags, nvm_data.ra_rio_lifetime); } #endif #endif #if UIP_CONF_IPV6_RPL && CETIC_6LBR_DODAG_ROOT //DODAGID = link-local address used ! cetic_dag = rpl_set_root(nvm_data.rpl_instance_id, &wsn_ip_local_addr); #if CETIC_6LBR_SMARTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { rpl_set_prefix(cetic_dag, &wsn_net_prefix, nvm_data.wsn_net_prefix_len); } #else rpl_set_prefix(cetic_dag, &wsn_net_prefix, nvm_data.wsn_net_prefix_len); #endif LOG6LBR_INFO("Configured as DODAG Root\n"); #endif #if CETIC_6LBR_TRANSPARENTBRIDGE #if CETIC_6LBR_LEARN_RPL_MAC LOG6LBR_INFO("Starting as RPL Relay\n"); #else LOG6LBR_INFO("Starting as Full TRANSPARENT-BRIDGE\n"); #endif #elif CETIC_6LBR_SMARTBRIDGE LOG6LBR_INFO("Starting as SMART-BRIDGE\n"); #elif CETIC_6LBR_ROUTER #if UIP_CONF_IPV6_RPL LOG6LBR_INFO("Starting as RPL ROUTER\n"); #else LOG6LBR_INFO("Starting as NDP ROUTER\n"); #endif #elif CETIC_6LBR_6LR LOG6LBR_INFO("Starting as 6LR\n"); #else LOG6LBR_INFO("Starting in UNKNOWN mode\n"); #endif #if CONTIKI_TARGET_NATIVE if (ip_config_file_name) { char str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, (struct sockaddr_in6 *)ð_ip_addr, str, INET6_ADDRSTRLEN); FILE *ip_config_file = fopen(ip_config_file_name, "w"); fprintf(ip_config_file, "%s\n", str); fclose(ip_config_file); } #endif }
void cetic_6lbr_init(void) { #if !CETIC_6LBR_TRANSPARENTBRIDGE uip_ipaddr_t loc_fipaddr; //DODAGID = link-local address used ! uip_create_linklocal_prefix(&loc_fipaddr); uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr); cetic_dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &loc_fipaddr); #endif uip_ds6_addr_t *local = uip_ds6_get_link_local(-1); uip_ipaddr_copy(&wsn_ip_local_addr, &local->ipaddr); PRINTF("Tentative local IPv6 address "); PRINT6ADDR(&wsn_ip_local_addr); PRINTF("\n"); #if CETIC_6LBR_SMARTBRIDGE || CETIC_6LBR_TRANSPARENTBRIDGE if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) //Manual configuration { memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address "); PRINT6ADDR(&wsn_ip_addr.u8); PRINTF("\n"); memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); uip_ds6_defrt_add(ð_dft_router, 0); #if CETIC_6LBR_SMARTBRIDGE rpl_set_prefix(cetic_dag, &wsn_net_prefix, 64); #endif } //End manual configuration #if CETIC_6LBR_TRANSPARENTBRIDGE printf("Starting as Transparent-BRIDGE\n"); #else printf("Starting as Smart-BRIDGE\n"); #endif #else /* ROUTER */ //WSN network configuration memcpy(wsn_net_prefix.u8, &nvm_data.wsn_net_prefix, sizeof(nvm_data.wsn_net_prefix)); if((nvm_data.mode & CETIC_MODE_WSN_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(&wsn_ip_addr, &wsn_net_prefix); uip_ds6_set_addr_iid(&wsn_ip_addr, &uip_lladdr); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(wsn_ip_addr.u8, &nvm_data.wsn_ip_addr, sizeof(nvm_data.wsn_ip_addr)); uip_ds6_addr_add(&wsn_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address (WSN) "); PRINT6ADDR(&wsn_ip_addr.u8); PRINTF("\n"); //Ethernet network configuration memcpy(eth_net_prefix.u8, &nvm_data.eth_net_prefix, sizeof(nvm_data.eth_net_prefix)); if((nvm_data.mode & CETIC_MODE_ROUTER_SEND_CONFIG) != 0) { PRINTF("RA with autoconfig\n"); uip_ds6_prefix_add(ð_net_prefix, 64, 1, UIP_ND6_RA_FLAG_ONLINK | UIP_ND6_RA_FLAG_AUTONOMOUS, 30000, 30000); } else { PRINTF("RA without autoconfig\n"); uip_ds6_prefix_add(ð_net_prefix, 64, 0, 0, 0, 0); } memcpy(eth_dft_router.u8, &nvm_data.eth_dft_router, sizeof(nvm_data.eth_dft_router)); uip_ds6_defrt_add(ð_dft_router, 0); eth_mac64_addr.addr[0] = eth_mac_addr[0]; eth_mac64_addr.addr[1] = eth_mac_addr[1]; eth_mac64_addr.addr[2] = eth_mac_addr[2]; eth_mac64_addr.addr[3] = CETIC_6LBR_ETH_EXT_A; eth_mac64_addr.addr[4] = CETIC_6LBR_ETH_EXT_B; eth_mac64_addr.addr[5] = eth_mac_addr[3]; eth_mac64_addr.addr[6] = eth_mac_addr[4]; eth_mac64_addr.addr[7] = eth_mac_addr[5]; if((nvm_data.mode & CETIC_MODE_ETH_AUTOCONF) != 0) //Address auto configuration { uip_ipaddr_copy(ð_ip_addr, ð_net_prefix); uip_ds6_set_addr_iid(ð_ip_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_AUTOCONF); } else { memcpy(eth_ip_addr.u8, &nvm_data.eth_ip_addr, sizeof(nvm_data.eth_ip_addr)); uip_ds6_addr_add(ð_ip_addr, 0, ADDR_MANUAL); } PRINTF("Tentative global IPv6 address (ETH) "); PRINT6ADDR(ð_ip_addr.u8); PRINTF("\n"); rpl_set_prefix(cetic_dag, &wsn_net_prefix, 64); //Ugly hack : in order to set WSN local address as the default address //We must add it afterwards as uip_ds6_addr_add allocates addr from the end of the list uip_ds6_addr_rm(local); uip_create_linklocal_prefix(ð_ip_local_addr); uip_ds6_set_addr_iid(ð_ip_local_addr, ð_mac64_addr); uip_ds6_addr_add(ð_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_addr_add(&wsn_ip_local_addr, 0, ADDR_AUTOCONF); uip_ds6_route_info_add(&wsn_net_prefix, 64, 0, 600); printf("Starting as ROUTER\n"); #endif }
/*---------------------------------------------------------------------------*/ void uip_ds6_periodic(void) { #if CONF_6LOWPAN_ND_OPTI_START && UIP_CONF_6L_ROUTER /* Start RPL only when the device has global IPv6 */ if(!rpl_started && uip_ds6_get_global(ADDR_PREFERRED)) { rpl_init(); rpl_started = 1; } #endif /* CONF_6LOWPAN_ND_OPTI_START && UIP_CONF_6L_ROUTER */ /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); #if UIP_ND6_DEF_MAXDADNS > 0 } else if((locaddr->state == ADDR_TENTATIVE) && (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (timer_expired(&locaddr->dadtimer)) && (uip_len == 0)) { uip_ds6_dad(locaddr); #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } } } /* Periodic processing on default routers */ uip_ds6_defrt_periodic(); /* for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (!locdefrt->isinfinite) && (stimer_expired(&(locdefrt->lifetime)))) { uip_ds6_defrt_rm(locdefrt); } }*/ #if CONF_6LOWPAN_ND /* Periodic processing on context prefixes */ for(loccontext = uip_ds6_context_pref_list; loccontext < uip_ds6_context_pref_list + UIP_DS6_CONTEXT_PREF_NB; loccontext++) { if(loccontext->state != CONTEXT_PREF_ST_FREE) { #if UIP_CONF_6LBR if(stimer_expired(&loccontext->lifetime) && loccontext->br->state != BR_ST_NEW_VERSION) { switch(loccontext->state) { case CONTEXT_PREF_ST_RM: /* Valid lifetime expired, so remove */ loccontext->state = CONTEXT_PREF_ST_FREE; break; case CONTEXT_PREF_ST_ADD: /* before c=0, now c=1 */ loccontext->state = CONTEXT_PREF_ST_COMPRESS; stimer_set(&loccontext->lifetime, loccontext->vlifetime * 60); break; } } #else /* UIP_CONF_6LBR */ if(stimer_expired(&loccontext->lifetime)) { switch(loccontext->state) { case CONTEXT_PREF_ST_UNCOMPRESSONLY: case CONTEXT_PREF_ST_RM: /* Valid lifetime expired, so remove */ loccontext->state = CONTEXT_PREF_ST_FREE; break; case CONTEXT_PREF_ST_SENDING: /* receive-only mode for a period of twice the default Router Lifetime */ loccontext->state = CONTEXT_PREF_ST_UNCOMPRESSONLY; stimer_set(&loccontext->lifetime, loccontext->router_lifetime * 2); break; case CONTEXT_PREF_ST_ADD: /* before c=0, now c=1 */ loccontext->state = CONTEXT_PREF_ST_COMPRESS; stimer_set(&loccontext->lifetime, loccontext->vlifetime * 60); break; } } else if(is_timeout_percent(&loccontext->lifetime, UIP_DS6_RS_PERCENT_LIFETIME_RETRAN, UIP_DS6_RS_MINLIFETIME_RETRAN) && loccontext->state == CONTEXT_PREF_ST_COMPRESS) { if(loccontext->br->state != BR_ST_SENDING_RS) { loccontext->br->state = BR_ST_MUST_SEND_RS; } loccontext->state = CONTEXT_PREF_ST_SENDING; } #endif /* UIP_CONF_6LBR */ } } #endif /* CONF_6LOWPAN_ND */ #if !UIP_CONF_ROUTER /* Periodic processing on prefixes */ for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && !locprefix->isinfinite) { if(stimer_expired(&(locprefix->vlifetime))) { uip_ds6_prefix_rm(locprefix); #if UIP_CONF_6LR || UIP_CONF_6LN } else if(is_timeout_percent(&locprefix->vlifetime, UIP_DS6_RS_PERCENT_LIFETIME_RETRAN, UIP_DS6_RS_MINLIFETIME_RETRAN)) { if(locprefix->br->state != BR_ST_SENDING_RS) { locprefix->br->state = BR_ST_MUST_SEND_RS; } #endif /* UIP_CONF_6LR || UIP_CONF_6LN */ } } } #endif /* !UIP_CONF_ROUTER */ /* Periodic processing on border router */ #if CONF_6LOWPAN_ND uip_ds6_br_periodic(); #endif /* CONF_6LOWPAN_ND */ /* Periodic processing on Duplication Address*/ #if UIP_CONF_6LBR for(locdad = uip_ds6_dup_addr_list; locdad < uip_ds6_dup_addr_list + UIP_DS6_DUPADDR_NB; locdad++) { if(locdad->isused && stimer_expired(&locdad->lifetime)) { uip_ds6_dup_addr_rm(locdad); } } #endif /* UIP_CONF_6LBR */ uip_ds6_neighbor_periodic(); #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA #if !CONF_6LOWPAN_ND || UIP_ND6_RA_PERIODIC /* Periodic RA sending */ if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) { uip_ds6_send_ra_periodic(); } #endif /* !CONF_6LOWPAN_ND || UIP_ND6_RA_PERIODIC */ #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */ etimer_reset(&uip_ds6_timer_periodic); return; }