void ng_ndp_netif_add(ng_ipv6_netif_t *iface) { uint32_t reach_time = _rand(NG_NDP_MIN_RAND, NG_NDP_MAX_RAND); /* set default values */ mutex_lock(&iface->mutex); iface->reach_time_base = NG_NDP_REACH_TIME; reach_time = (reach_time * iface->reach_time_base) / 10; iface->reach_time = timex_set(0, reach_time); timex_normalize(&iface->reach_time); iface->retrans_timer = timex_set(0, NG_NDP_RETRANS_TIMER); timex_normalize(&iface->retrans_timer); mutex_unlock(&iface->mutex); }
static int set_timeout(vtimer_t *timeout, timex_t val, void *args) { vtimer_remove(timeout); timex_normalize(&val); return vtimer_set_msg(timeout, val, sending_slot_pid, args); }
void reset_trickletimer(void) { I = Imin; c = 0; /* start timer */ t = (I / 2) + (rand() % (I - (I / 2) + 1)); t_time = timex_set(0, t * 1000); I_time = timex_set(0, I * 1000); timex_normalize(&t_time); timex_normalize(&I_time); vtimer_remove(&trickle_t_timer); vtimer_remove(&trickle_I_timer); vtimer_set_wakeup(&trickle_t_timer, t_time, timer_over_pid); vtimer_set_wakeup(&trickle_I_timer, I_time, interval_over_pid); }
bool ccnl_is_timed_out(struct timeval *now, struct timeval *last_used, uint32_t timeout_s, uint32_t timeout_us) { timex_t time = timex_set(timeout_s, timeout_us); timex_normalize(&time); struct timeval abs_timeout = { last_used->tv_sec + time.seconds, last_used->tv_usec + time.microseconds }; return timevaldelta(now, &abs_timeout) > 0; }
int usleep(useconds_t useconds) { timex_t time = timex_set(0, useconds); timex_normalize(&time); vtimer_sleep(time); return 0; }
static void *trickle_interval_over(void *arg) { (void) arg; while (1) { thread_sleep(); I = I * 2; DEBUG("TRICKLE new Interval %" PRIu32 "\n", I); if (I == 0) { puts("[WARNING] Interval was 0"); if (Imax == 0) { puts("[WARNING] Imax == 0"); } I = (Imin << Imax); } if (I > (Imin << Imax)) { I = (Imin << Imax); } c = 0; t = (I / 2) + (rand() % (I - (I / 2) + 1)); /* start timer */ t_time = timex_set(0, t * 1000); timex_normalize(&t_time); I_time = timex_set(0, I * 1000); timex_normalize(&I_time); vtimer_remove(&trickle_t_timer); if (vtimer_set_wakeup(&trickle_t_timer, t_time, timer_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } vtimer_remove(&trickle_I_timer); if (vtimer_set_wakeup(&trickle_I_timer, I_time, interval_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } } return NULL; }
static gnrc_nettest_res_t _pkt_test(uint16_t cmd_type, kernel_pid_t pid, gnrc_pktsnip_t *in, unsigned int exp_pkts, const kernel_pid_t *exp_senders, const gnrc_pktsnip_t **exp_out) { msg_t msg; timex_t t = { 0, GNRC_NETTEST_TIMEOUT }; gnrc_nettest_res_t res = GNRC_NETTEST_SUCCESS; msg.type = cmd_type; msg.content.ptr = (char *)in; msg_send(&msg, pid); timex_normalize(&t); if (exp_pkts == 0) { thread_yield(); } for (unsigned int i = 0; i < exp_pkts; i++) { gnrc_pktsnip_t *out; const gnrc_pktsnip_t *exp = exp_out[i]; if (vtimer_msg_receive_timeout(&msg, t) < 0) { return GNRC_NETTEST_TIMED_OUT; } if (msg.type != cmd_type) { return GNRC_NETTEST_WRONG_MSG; } if (msg.sender_pid != exp_senders[i]) { return GNRC_NETTEST_WRONG_SENDER; } out = (gnrc_pktsnip_t *)msg.content.ptr; if (out == NULL) { return GNRC_NETTEST_FAIL; } while (out && exp) { if ((out->users != exp->users) || (out->size != exp->size) || (out->type != exp->type) || (memcmp(out->data, exp->data, out->size) != 0)) { return GNRC_NETTEST_FAIL; } out = out->next; exp = exp->next; } gnrc_pktbuf_release((gnrc_pktsnip_t *)msg.content.ptr); } return res; }
static inline void _set_reach_time(gnrc_ipv6_netif_t *if_entry, uint32_t mean) { uint32_t reach_time = genrand_uint32_range(GNRC_NDP_MIN_RAND, GNRC_NDP_MAX_RAND); if_entry->reach_time_base = mean; /* to avoid floating point number computation and have higher value entropy, the * boundaries for the random value are multiplied by 10 and we need to account for that */ reach_time = (reach_time * if_entry->reach_time_base) / 10; if_entry->reach_time = timex_set(0, reach_time); timex_normalize(&if_entry->reach_time); }
void start_trickle(uint8_t DIOIntMin, uint8_t DIOIntDoubl, uint8_t DIORedundancyConstant) { c = 0; k = DIORedundancyConstant; Imin = (1 << DIOIntMin); Imax = DIOIntDoubl; /* Eigentlich laut Spezifikation erste Bestimmung von I wie auskommentiert: */ /* I = Imin + ( rand() % ( (Imin << Imax) - Imin + 1 ) ); */ I = Imin + (rand() % (4 * Imin)) ; t = (I / 2) + (rand() % (I - (I / 2) + 1)); t_time = timex_set(0, t * 1000); timex_normalize(&t_time); I_time = timex_set(0, I * 1000); timex_normalize(&I_time); vtimer_remove(&trickle_t_timer); vtimer_remove(&trickle_I_timer); vtimer_set_wakeup(&trickle_t_timer, t_time, timer_over_pid); vtimer_set_wakeup(&trickle_I_timer, I_time, interval_over_pid); }
void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t *ipv6, ndp_rtr_adv_t *rtr_adv, size_t icmpv6_size) { uint8_t *buf = (uint8_t *)(rtr_adv + 1); gnrc_ipv6_nc_t *nc_entry = NULL; gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface); uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX]; #ifdef MODULE_GNRC_SIXLOWPAN_ND uint32_t next_rtr_sol = 0; #endif int sicmpv6_size = (int)icmpv6_size, l2src_len = 0; uint16_t opt_offset = 0; if (!ipv6_addr_is_link_local(&ipv6->src) || ipv6_addr_is_multicast(&ipv6->src) || (ipv6->hl != 255) || (rtr_adv->code != 0) || (icmpv6_size < sizeof(ndp_rtr_adv_t))) { DEBUG("ndp: router advertisement was invalid\n"); /* ipv6 releases */ return; } /* get source from default router list */ nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src); if (nc_entry == NULL) { /* not in default router list */ /* create default router list entry */ nc_entry = gnrc_ipv6_nc_add(iface, &ipv6->src, NULL, 0, GNRC_IPV6_NC_IS_ROUTER); if (nc_entry == NULL) { DEBUG("ndp: error on default router list entry creation\n"); return; } } else if ((nc_entry->flags & GNRC_IPV6_NC_IS_ROUTER) && (byteorder_ntohs(rtr_adv->ltime) == 0)) { nc_entry->flags &= ~GNRC_IPV6_NC_IS_ROUTER; } else { nc_entry->flags |= GNRC_IPV6_NC_IS_ROUTER; } /* set router life timer */ if (rtr_adv->ltime.u16 != 0) { uint16_t ltime = byteorder_ntohs(rtr_adv->ltime); #ifdef MODULE_GNRC_SIXLOWPAN_ND next_rtr_sol = ltime; #endif xtimer_set_msg(&nc_entry->rtr_timeout, (ltime * SEC_IN_USEC), &nc_entry->rtr_timeout_msg, thread_getpid()); } /* set current hop limit from message if available */ if (rtr_adv->cur_hl != 0) { if_entry->cur_hl = rtr_adv->cur_hl; } /* set flags from message */ if_entry->flags &= ~GNRC_IPV6_NETIF_FLAGS_RTR_ADV_MASK; if_entry->flags |= (rtr_adv->flags << GNRC_IPV6_NETIF_FLAGS_RTR_ADV_POS) & GNRC_IPV6_NETIF_FLAGS_RTR_ADV_MASK; /* set reachable time from message if it is not the same as the random base * value */ if ((rtr_adv->reach_time.u32 != 0) && (if_entry->reach_time_base != byteorder_ntohl(rtr_adv->reach_time))) { _set_reach_time(if_entry, byteorder_ntohl(rtr_adv->reach_time)); } /* set retransmission timer from message */ if (rtr_adv->retrans_timer.u32 != 0) { if_entry->retrans_timer = timex_set(0, byteorder_ntohl(rtr_adv->retrans_timer)); timex_normalize(&if_entry->retrans_timer); } mutex_unlock(&if_entry->mutex); sicmpv6_size -= sizeof(ndp_rtr_adv_t); /* parse options */ while (sicmpv6_size > 0) { ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset); switch (opt->type) { case NDP_OPT_SL2A: if ((l2src_len = gnrc_ndp_internal_sl2a_opt_handle(pkt, ipv6, rtr_adv->type, opt, l2src)) < 0) { /* -ENOTSUP can not happen */ /* invalid source link-layer address option */ return; } break; case NDP_OPT_MTU: if (!gnrc_ndp_internal_mtu_opt_handle(iface, rtr_adv->type, (ndp_opt_mtu_t *)opt)) { /* invalid MTU option */ return; } break; case NDP_OPT_PI: if (!gnrc_ndp_internal_pi_opt_handle(iface, rtr_adv->type, (ndp_opt_pi_t *)opt)) { /* invalid prefix information option */ return; } #ifdef MODULE_GNRC_SIXLOWPAN_ND uint32_t valid_ltime = byteorder_ntohl(((ndp_opt_pi_t *)opt)->valid_ltime); if ((valid_ltime != 0) && (valid_ltime < next_rtr_sol)) { next_rtr_sol = valid_ltime; } #endif break; #ifdef MODULE_GNRC_SIXLOWPAN_ND case NDP_OPT_6CTX: if (!gnrc_sixlowpan_nd_opt_6ctx_handle(rtr_adv->type, (sixlowpan_nd_opt_6ctx_t *)opt)) { /* invalid 6LoWPAN context option */ return; } uint16_t ltime = byteorder_ntohs(((sixlowpan_nd_opt_6ctx_t *)opt)->ltime); if ((ltime != 0) && (ltime < (next_rtr_sol / 60))) { next_rtr_sol = ltime * 60; } break; #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER case NDP_OPT_ABR: gnrc_sixlowpan_nd_opt_abr_handle(iface, rtr_adv, icmpv6_size, (sixlowpan_nd_opt_abr_t *)opt); break; #endif } opt_offset += (opt->len * 8); sicmpv6_size -= (opt->len * 8); #if ENABLE_DEBUG if (sicmpv6_size < 0) { DEBUG("ndp: Option parsing out of sync.\n"); } #endif } #if ENABLE_DEBUG && defined(MODULE_GNRC_SIXLOWPAN_ND) if ((if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && (l2src_len <= 0)) { DEBUG("ndp: Router advertisement did not contain any source address information\n"); } #endif _stale_nc(iface, &ipv6->src, l2src, l2src_len); /* stop multicast router solicitation retransmission timer */ xtimer_remove(&if_entry->rtr_sol_timer); #ifdef MODULE_GNRC_SIXLOWPAN_ND if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { /* 3/4 of the time should be "well before" enough the respective timeout * not to run out; see https://tools.ietf.org/html/rfc6775#section-5.4.3 */ next_rtr_sol *= 3; next_rtr_sol = (next_rtr_sol > 4) ? (next_rtr_sol >> 2) : 1; /* according to https://tools.ietf.org/html/rfc6775#section-5.3: * "In all cases, the RS retransmissions are terminated when an RA is * received." * Hence, reset router solicitation counter and reset timer. */ if_entry->rtr_sol_count = 0; gnrc_sixlowpan_nd_rtr_sol_reschedule(nc_entry, next_rtr_sol); gnrc_ndp_internal_send_nbr_sol(nc_entry->iface, NULL, &nc_entry->ipv6_addr, &nc_entry->ipv6_addr); if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) { gnrc_ipv6_netif_set_rtr_adv(if_entry, true); } }
int nhdp_register_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type, uint16_t max_pl_size, uint16_t hello_int_ms, uint16_t val_time_ms) { nhdp_if_entry_t *if_entry = NULL; nhdp_addr_t *nhdp_addr; msg_t signal_msg; if (nhdp_rcv_pid != KERNEL_PID_UNDEF) { return -2; } for (int i = 0; i < GNRC_NETIF_NUMOF; i++) { if (nhdp_if_table[i].if_pid == KERNEL_PID_UNDEF) { if_entry = &nhdp_if_table[i]; break; } } if (!if_entry) { /* Maximum number of registerable interfaces reached */ return -2; } uint16_t payload_size = max_pl_size > NHDP_MAX_RFC5444_PACKET_SZ ? NHDP_MAX_RFC5444_PACKET_SZ : max_pl_size; if_entry->wr_target.packet_buffer = (uint8_t *) calloc(payload_size, sizeof(uint8_t)); if (!if_entry->wr_target.packet_buffer) { /* Insufficient memory */ return -1; } if_entry->wr_target.packet_size = payload_size; if_entry->wr_target.sendPacket = write_packet; /* Get NHDP address entry for the given address */ nhdp_addr = nhdp_addr_db_get_address(addr, addr_size, addr_type); if (!nhdp_addr) { /* Insufficient memory */ free(if_entry->wr_target.packet_buffer); return -1; } /* Add the interface to the LIB */ if (lib_add_if_addr(if_pid, nhdp_addr) != 0) { free(if_entry->wr_target.packet_buffer); nhdp_decrement_addr_usage(nhdp_addr); return -1; } /* Create new IIB for the interface */ if (iib_register_if(if_pid) != 0) { /* TODO: Cleanup lib entry */ free(if_entry->wr_target.packet_buffer); nhdp_decrement_addr_usage(nhdp_addr); return -1; } /* Set Interface's PID */ if_entry->if_pid = if_pid; /* Set HELLO_INTERVAL and H_HOLD_TIME (validity time) */ if_entry->hello_interval.seconds = 0; if_entry->hello_interval.microseconds = MS_IN_USEC * hello_int_ms; if_entry->validity_time.seconds = 0; if_entry->validity_time.microseconds = MS_IN_USEC * val_time_ms; timex_normalize(&if_entry->hello_interval); timex_normalize(&if_entry->validity_time); /* Reset sequence number */ if_entry->seq_no = 0; /* Everything went well */ nhdp_decrement_addr_usage(nhdp_addr); nhdp_writer_register_if(&if_entry->wr_target); helper_pid = if_pid; /* Start the receiving thread */ nhdp_rcv_pid = thread_create(nhdp_rcv_stack, sizeof(nhdp_rcv_stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _nhdp_receiver, NULL, "nhdp_rcv_thread"); /* Start sending periodic HELLO */ signal_msg.type = HELLO_TIMER; signal_msg.content.ptr = if_entry; /* TODO: msg_send or msg_try_send? */ msg_try_send(&signal_msg, nhdp_pid); return 0; }
void ng_ndp_internal_send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst, bool supply_tl2a) { ng_pktsnip_t *hdr, *pkt = NULL; uint8_t adv_flags = 0; DEBUG("ndp internal: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) { adv_flags |= NG_NDP_NBR_ADV_FLAGS_R; } if (ng_ipv6_addr_is_unspecified(dst)) { ng_ipv6_addr_set_all_nodes_multicast(dst, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NG_NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; uint16_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp internal: error allocating Target Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NG_NDP_NBR_ADV_FLAGS_O; } hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor advertisement.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp internal: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp internal: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); if (ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ timex_t delay = { 0, genrand_uint32_range(0, NG_NDP_MAX_AC_TGT_DELAY * SEC_IN_USEC) }; timex_normalize(&delay); ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt); DEBUG("ndp internal: delay neighbor advertisement for %" PRIu32 " sec.", delay.seconds); /* nc_entry must be set so no need to check it */ _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt); } else { ng_netapi_send(ng_ipv6_pid, pkt); } }
void gnrc_ndp_internal_send_nbr_adv(kernel_pid_t iface, ipv6_addr_t *tgt, ipv6_addr_t *dst, bool supply_tl2a, gnrc_pktsnip_t *ext_opts) { gnrc_pktsnip_t *hdr, *pkt = ext_opts; uint8_t adv_flags = 0; DEBUG("ndp internal: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) && (gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { adv_flags |= NDP_NBR_ADV_FLAGS_R; } if (ipv6_addr_is_unspecified(dst)) { ipv6_addr_set_all_nodes_multicast(dst, IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; size_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = gnrc_ndp_opt_tl2a_build(l2src, l2src_len, pkt); if (pkt == NULL) { DEBUG("ndp internal: error allocating Target Link-layer address option.\n"); gnrc_pktbuf_release(ext_opts); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !gnrc_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NDP_NBR_ADV_FLAGS_O; } hdr = gnrc_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor advertisement.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, NULL); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } if (gnrc_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ timex_t delay = { 0, genrand_uint32_range(0, GNRC_NDP_MAX_AC_TGT_DELAY * SEC_IN_USEC) }; timex_normalize(&delay); gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, tgt); DEBUG("ndp internal: delay neighbor advertisement for %" PRIu32 " sec.", delay.seconds); /* nc_entry must be set so no need to check it */ _send_delayed(&nc_entry->nbr_adv_timer, delay, hdr); } else { gnrc_netapi_send(gnrc_ipv6_pid, hdr); } }