static void test_fib_15_get_lifetime(void) { timex_t lifetime, now; kernel_pid_t iface_id = 1; char addr_dst[] = "Test address151"; char addr_nxt[] = "Test address152"; size_t add_buf_size = 16; uint32_t addr_dst_flags = 0x77777777; uint32_t addr_nxt_flags = 0x77777777; TEST_ASSERT_EQUAL_INT(0, fib_add_entry(iface_id, (uint8_t *)addr_dst, add_buf_size - 1, addr_dst_flags, (uint8_t *)addr_nxt, add_buf_size - 1, addr_nxt_flags, 1000)); TEST_ASSERT_EQUAL_INT(0, fib_devel_get_lifetime(&lifetime, (uint8_t *)addr_dst, add_buf_size - 1)); /* assuming some ms passed during these operations... */ vtimer_now(&now); timex_t cmp_lifetime = timex_add(now, timex_set(0, 900000)); timex_t cmp_max_lifetime = timex_add(now, timex_set(1,1)); TEST_ASSERT_EQUAL_INT(1, timex_cmp(lifetime, cmp_lifetime)); /* make sure lifetime hasn't grown magically either */ TEST_ASSERT_EQUAL_INT(-1, timex_cmp(lifetime, cmp_max_lifetime)); fib_deinit(); }
static void test_timex_sub(void) { timex_t time; time = timex_sub(timex_set(100, 100), timex_set(40, 10)); TEST_ASSERT_EQUAL_INT(0, timex_cmp(time, timex_set(60, 90))); time = timex_sub(timex_set(100, 100), timex_set(40, 200)); TEST_ASSERT_EQUAL_INT(0, timex_cmp(time, timex_set(59, 999900))); }
static void test_timex_add(void) { timex_t time; time = timex_add(timex_set(100, 100), timex_set(40, 10)); TEST_ASSERT_EQUAL_INT(0, timex_cmp(time, timex_set(140, 110))); time = timex_add(timex_set(100, 700000), timex_set(40, 800000)); TEST_ASSERT_EQUAL_INT(0, timex_cmp(time, timex_set(141, 500000))); }
static void calc_rtt(void) { timex_t rtt = timex_sub(end, start); rtt_sum = timex_add(rtt_sum, rtt); l2_ping_stats.last_rtt = rtt; l2_ping_stats.avg_rtt = timex_from_uint64(timex_uint64(rtt_sum) / l2_ping_stats.pong_count); if (timex_cmp(rtt, l2_ping_stats.max_rtt) > 0) { l2_ping_stats.max_rtt = rtt; } if (timex_cmp(rtt, l2_ping_stats.min_rtt) < 0) { l2_ping_stats.min_rtt = rtt; } }
/* * Check if entry at index i is stale and clear the struct it fills if it is */ static void _reset_entry_if_stale(uint8_t i) { vtimer_now(&now); if (timex_cmp(rreq_table[i].timestamp, null_time) == 0) { return; } timex_t expiration_time = timex_add(rreq_table[i].timestamp, _max_idletime); if (timex_cmp(expiration_time, now) < 0) { /* timestamp+expiration time is in the past: this entry is stale */ DEBUG("\treset rreq table entry %s\n", netaddr_to_string(&nbuf, &rreq_table[i].origNode)); memset(&rreq_table[i], 0, sizeof(rreq_table[i])); } }
/* * Check if entry at index i is stale as described in Section 6.3. * and clear the struct it fills if it is */ static void _reset_entry_if_stale(uint8_t i) { vtimer_now(&now); timex_t lastUsed, expirationTime; if (timex_cmp(routing_table[i].expirationTime, null_time) == 0) { return; } int state = routing_table[i].state; lastUsed = routing_table[i].lastUsed; expirationTime = routing_table[i].expirationTime; /* an Active route is considered to remain Active as long as it is used at least once * during every ACTIVE_INTERVAL. When a route is no longer Active, it becomes an Idle route. */ /* if the node is younger than the active interval, don't bother */ if (timex_cmp(now, active_interval) < 0) { return; } if ((state == ROUTE_STATE_ACTIVE) && (timex_cmp(timex_sub(now, active_interval), lastUsed) == 1)) { DEBUG("\t[routing] route towards %s Idle\n", netaddr_to_string(&nbuf, &routing_table[i].addr)); routing_table[i].state = ROUTE_STATE_IDLE; routing_table[i].lastUsed = now; /* mark the time entry was set to Idle */ } /* After an Idle route remains Idle for MAX_IDLETIME, it becomes an Invalid route. */ /* if the node is younger than the expiration time, don't bother */ if (timex_cmp(now, expirationTime) < 0) { return; } /* If Current_Time > Route.ExpirationTime, set Route.State := Invalid. */ if ((state == ROUTE_STATE_IDLE) && (timex_cmp(now, expirationTime) > 0)) { DEBUG("\t[routing] route towards %s became Invalid\n", netaddr_to_string(&nbuf, &routing_table[i].addr)); routing_table[i].state = ROUTE_STATE_INVALID; routing_table[i].lastUsed = now; /* mark the time entry was set to Invalid */ } /* If (Current_Time - Route.LastUsed) > (ACTIVE_INTERVAL + MAX_IDLETIME), * and if (Route.Timed == FALSE), set Route.State := Invalid. */ if ((timex_cmp(timex_sub(now, lastUsed), timex_add(active_interval, max_idletime)) > 0) && (state != ROUTE_STATE_TIMED)) { routing_table[i].state = ROUTE_STATE_INVALID; } /* After that time, old sequence number information is considered no longer * valid and the Invalid route MUST BE expunged */ if (timex_cmp(timex_sub(now, lastUsed), max_seqnum_lifetime) >= 0) { DEBUG("\t[routing] Expunged routing table entry for %s at %i\n", netaddr_to_string(&nbuf, &routing_table[i].addr), i); memset(&routing_table[i], 0, sizeof(routing_table[i])); } }
cv_status condition_variable::wait_until(unique_lock<mutex>& lock, const time_point& timeout_time) { xtimer_t timer; // todo: use function to wait for absolute timepoint once available timex_t before; xtimer_now_timex(&before); auto diff = timex_sub(timeout_time.native_handle(), before); xtimer_set_wakeup(&timer, timex_uint64(diff), sched_active_pid); wait(lock); timex_t after; xtimer_now_timex(&after); xtimer_remove(&timer); auto cmp = timex_cmp(after, timeout_time.native_handle()); return cmp < 1 ? cv_status::no_timeout : cv_status::timeout; }
void cc1100_phy_init(void) { int i; rx_buffer_head = 0; rx_buffer_tail = 0; rx_buffer_size = 0; /* Initialize RX-Buffer (clear content) */ for (i = 0; i < RX_BUFF_SIZE; i++) { rx_buffer->packet.length = 0; } /* Initialize handler table & packet monitor */ packet_monitor = NULL; pm_init_table((pm_table_t *)&handler_table, MAX_PACKET_HANDLERS, handlers); /* Clear sequence number buffer */ memset(seq_buffer, 0, sizeof(seq_buffer_entry_t) * MAX_SEQ_BUFFER_SIZE); /* Initialize mutex */ cc1100_mutex_pid = -1; mutex_init(&cc1100_mutex); /* Allocate event numbers and start cc1100 event process */ cc1100_event_handler_pid = thread_create(event_handler_stack, sizeof(event_handler_stack), PRIORITY_CC1100, CREATE_STACKTEST, cc1100_event_handler_function, cc1100_event_handler_name); /* Active watchdog for the first time */ if (radio_mode == CC1100_MODE_CONSTANT_RX) { cc1100_watch_dog_period = timex_set(CC1100_WATCHDOG_PERIOD, 0); if (timex_cmp(cc1100_watch_dog_period, timex_set(0, 0)) != 0) { vtimer_set_msg(&cc1100_watch_dog, cc1100_watch_dog_period, cc1100_event_handler_pid, NULL); } } }
/** * @brief returns pointer to the entry for the given destination address * * @param[in] dst the destination address * @param[in] dst_size the destination address size * @param[out] entry_arr the array to scribe the found match * @param[in, out] entry_arr_size the number of entries provided by entry_arr (should be always 1) * this value is overwritten with the actual found number * * @return 0 if we found a next-hop prefix * 1 if we found the exact address next-hop * -EHOSTUNREACH if no fitting next-hop is available */ static int fib_find_entry(uint8_t *dst, size_t dst_size, fib_entry_t **entry_arr, size_t *entry_arr_size) { timex_t now; vtimer_now(&now); size_t count = 0; size_t prefix_size = 0; size_t match_size = dst_size; int ret = -EHOSTUNREACH; for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { /* autoinvalidate if the entry lifetime is not set to not expire */ if ((fib_table[i].lifetime.seconds != FIB_LIFETIME_NO_EXPIRE) || (fib_table[i].lifetime.microseconds != FIB_LIFETIME_NO_EXPIRE)) { /* check if the lifetime expired */ if (timex_cmp(now, fib_table[i].lifetime) > -1) { /* remove this entry if its lifetime expired */ fib_table[i].lifetime.seconds = 0; fib_table[i].lifetime.microseconds = 0; if (fib_table[i].global != NULL) { universal_address_rem(fib_table[i].global); fib_table[i].global = NULL; } if (fib_table[i].next_hop != NULL) { universal_address_rem(fib_table[i].next_hop); fib_table[i].next_hop = NULL; } } } if ((prefix_size < dst_size) && (fib_table[i].global != NULL) && (universal_address_compare(fib_table[i].global, dst, &match_size) == 0)) { /* If we found an exact match */ if (match_size == dst_size) { entry_arr[0] = &(fib_table[i]); *entry_arr_size = 1; /* we will not find a better one so we return */ return 1; } else { /* we try to find the most fitting prefix */ if (match_size > prefix_size) { entry_arr[0] = &(fib_table[i]); /* we could find a better one so we move on */ ret = 0; } } prefix_size = match_size; match_size = dst_size; count = 1; } } *entry_arr_size = count; return ret; }
/*---------------------------------------------------------------------------*/ int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, radio_packet_length_t payload_len) { uint16_t min_window_size; uint16_t max_window_size; uint16_t difs; uint16_t slottime; switch(priority) { case PRIORITY_ALARM: min_window_size = PRIO_ALARM_MIN_WINDOW_SIZE; max_window_size = PRIO_ALARM_MAX_WINDOW_SIZE; difs = PRIO_ALARM_DIFS; slottime = PRIO_ALARM_SLOTTIME; break; case PRIORITY_WARNING: min_window_size = PRIO_WARN_MIN_WINDOW_SIZE; max_window_size = PRIO_WARN_MAX_WINDOW_SIZE; difs = PRIO_WARN_DIFS; slottime = PRIO_WARN_SLOTTIME; break; default: min_window_size = PRIO_DATA_MIN_WINDOW_SIZE; max_window_size = PRIO_DATA_MAX_WINDOW_SIZE; difs = PRIO_DATA_DIFS; slottime = PRIO_DATA_SLOTTIME; } /* Calculate collisions per second */ if (collision_state == COLLISION_STATE_INITIAL) { vtimer_now(&collision_measurement_start); collision_count = 0; collisions_per_sec = 0; collision_state = COLLISION_STATE_MEASURE; } else if (collision_state == COLLISION_STATE_MEASURE) { timex_t now; vtimer_now(&now); timex_t timespan = timex_sub(now, collision_measurement_start); if (timex_cmp(timespan, timex_set(1, 0)) > 0) { collisions_per_sec = (collision_count * 1000000) / (double) timex_uint64(timespan); if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) { timex_t now; vtimer_now(&now); collision_measurement_start = now; collision_state = COLLISION_STATE_KEEP; } else if (collisions_per_sec > 2.2) { timex_t now; vtimer_now(&now); collision_measurement_start = now; collision_state = COLLISION_STATE_KEEP; } else { collision_state = COLLISION_STATE_INITIAL; } } } else if (collision_state == COLLISION_STATE_KEEP) { timex_t now; vtimer_now(&now); timex_t timespan = timex_sub(now, collision_measurement_start); if (timex_cmp(timespan, timex_set(5, 0)) > 0) { collision_state = COLLISION_STATE_INITIAL; } } /* Adjust initial window size according to collision rate */ if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) { min_window_size *= 2; } else if (collisions_per_sec > 2.2) { min_window_size *= 4; } uint16_t windowSize = min_window_size; /* Start with window size of PRIO_XXX_MIN_WINDOW_SIZE */ uint16_t backoff = 0; /* Backoff between 1 and windowSize */ uint32_t total; /* Holds the total wait time before send try */ uint32_t cs_timeout; /* Current carrier sense timeout value */ if (protocol == 0) { return RADIO_INVALID_PARAM; /* Not allowed, protocol id must be greater zero */ } cc1100_phy_mutex_lock(); /* Lock radio for exclusive access */ /* Get carrier sense timeout based on overall error rate till now */ send_csmaca_calls++; int fail_percentage = (send_csmaca_calls_cs_timeout * 100) / send_csmaca_calls; if (fail_percentage == 0) { fail_percentage = 1; } cs_timeout = CARRIER_SENSE_TIMEOUT / fail_percentage; if (cs_timeout < CARRIER_SENSE_TIMEOUT_MIN) { cs_timeout = CARRIER_SENSE_TIMEOUT_MIN; } cc1100_cs_init(); /* Initialize carrier sensing */ window: if (backoff != 0) { goto cycle; /* If backoff was 0 */ } windowSize *= 2; /* ...double the current window size */ if (windowSize > max_window_size) { windowSize = max_window_size; /* This is the maximum size allowed */ } backoff = rand() % windowSize; /* ...and choose new backoff */ backoff += (uint16_t) 1; cycle: cs_timeout_flag = 0; /* Carrier sense timeout flag */ cs_hwtimer_id = hwtimer_set(cs_timeout, /* Set hwtimer to set CS timeout flag */ cs_timeout_cb, NULL); while (cc1100_cs_read()) { /* Wait until air is free */ if (cs_timeout_flag) { send_csmaca_calls_cs_timeout++; #ifndef CSMACA_MAC_AGGRESSIVE_MODE cc1100_phy_mutex_unlock(); cc1100_go_after_tx(); /* Go from RX to default mode */ return RADIO_CS_TIMEOUT; /* Return immediately */ #endif #ifdef CSMACA_MAC_AGGRESSIVE_MODE goto send; /* Send anyway */ #endif } } hwtimer_remove(cs_hwtimer_id); /* Remove hwtimer */ cc1100_cs_write_cca(1); /* Air is free now */ cc1100_cs_set_enabled(true); if (cc1100_cs_read()) { goto window; /* GDO0 triggers on rising edge, so */ } /* test once after interrupt is enabled */ if (backoff > 0) { backoff--; /* Decrement backoff counter */ } total = slottime; /* Calculate total wait time */ total *= (uint32_t)backoff; /* Slot vector set */ total += difs; /* ...and standard DIFS wait time */ cs_timeout_flag = 0; /* Carrier sense timeout flag */ cs_hwtimer_id = hwtimer_set(total, /* Set hwtimer to set CS timeout flag */ cs_timeout_cb, NULL); while (!cs_timeout_flag || !cc1100_cs_read_cca()) { /* Wait until timeout is finished */ if (cc1100_cs_read_cca() == 0) { /* Is the air still free? */ hwtimer_remove(cs_hwtimer_id); goto window; /* No. Go back to new wait period. */ } } cc1100_cs_set_enabled(false); #ifdef CSMACA_MAC_AGGRESSIVE_MODE send: #endif int res = cc1100_send(address, protocol, priority, payload, payload_len); if (res < 0) { collision_count++; } return res; }