Пример #1
0
void handle_synchro_timeout(socket_internal_t *current_socket)
{
    msg_t send;

    if (thread_getstatus(current_socket->recv_pid) == STATUS_RECEIVE_BLOCKED) {
        timex_t now;
        vtimer_now(&now);

        if ((current_socket->socket_values.tcp_control.no_of_retries == 0) &&
            (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) > TCP_SYN_INITIAL_TIMEOUT)) {
            current_socket->socket_values.tcp_control.no_of_retries++;
            net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY);
        }
        else if ((current_socket->socket_values.tcp_control.no_of_retries > 0) &&
                 (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) >
                  (current_socket->socket_values.tcp_control.no_of_retries *
                   TCP_SYN_TIMEOUT + TCP_SYN_INITIAL_TIMEOUT))) {
            current_socket->socket_values.tcp_control.no_of_retries++;

            if (current_socket->socket_values.tcp_control.no_of_retries >
                TCP_MAX_SYN_RETRIES) {
                net_msg_send(&send, current_socket->recv_pid, 0, TCP_TIMEOUT);
            }
            else {
                net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY);
            }
        }
    }
}
Пример #2
0
/*
 * 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]));
    }
}
Пример #3
0
void handle_synchro_timeout(socket_internal_t *current_socket)
	{
	msg_t send;
	if (thread_getstatus(current_socket->recv_pid) == STATUS_RECEIVE_BLOCKED)
		{
		if ((current_socket->socket_values.tcp_control.no_of_retries == 0) &&
				(timex_sub(vtimer_now(), current_socket->socket_values.tcp_control.last_packet_time).microseconds >
				TCP_SYN_INITIAL_TIMEOUT))
			{
			current_socket->socket_values.tcp_control.no_of_retries++;
			net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY);
//			printf("FIRST RETRY!\n");
			}
		else if ((current_socket->socket_values.tcp_control.no_of_retries > 0) &&
				(timex_sub(vtimer_now(), current_socket->socket_values.tcp_control.last_packet_time).microseconds >
				(current_socket->socket_values.tcp_control.no_of_retries * TCP_SYN_TIMEOUT + TCP_SYN_INITIAL_TIMEOUT)))
			{
			current_socket->socket_values.tcp_control.no_of_retries++;
			if (current_socket->socket_values.tcp_control.no_of_retries > TCP_MAX_SYN_RETRIES)
				{
				net_msg_send(&send, current_socket->recv_pid, 0, TCP_TIMEOUT);
//				printf("TCP SYN TIMEOUT!!\n");
				}
			else
				{
				net_msg_send(&send, current_socket->recv_pid, 0, TCP_RETRY);
//				printf("NEXT RETRY!\n");
				}
			}
		}
	}
Пример #4
0
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)));
}
Пример #5
0
void handle_established(socket_internal_t *current_socket)
	{
	msg_t send;
	double current_timeout = current_socket->socket_values.tcp_control.rto;
	if (current_timeout < SECOND)
		{
		current_timeout = SECOND;
		}
	uint8_t i;
	if ((current_socket->socket_values.tcp_control.send_nxt > current_socket->socket_values.tcp_control.send_una) &&
			(thread_getstatus(current_socket->send_pid) == STATUS_RECEIVE_BLOCKED))
		{
		for(i = 0; i < current_socket->socket_values.tcp_control.no_of_retries; i++)
			{
			current_timeout *= 2;
			}
		if (current_timeout > TCP_ACK_MAX_TIMEOUT)
			{
			net_msg_send(&send, current_socket->send_pid, 0, TCP_TIMEOUT);
//			printf("GOT NO ACK: TIMEOUT!\n");
			}
		else if (timex_sub(vtimer_now(), current_socket->socket_values.tcp_control.last_packet_time).microseconds >
					current_timeout)
			{
//			printReasBuffers();
			current_socket->socket_values.tcp_control.no_of_retries++;
			net_msg_send(&send, current_socket->send_pid, 0, TCP_RETRY);
//			printf("GOT NO ACK YET, %i. RETRY! Now: %lu  Before: %lu, Diff: %lu, Cur Timeout: %f\n", current_socket->socket_values.tcp_control.no_of_retries,
//					vtimer_now().microseconds, current_socket->socket_values.tcp_control.last_packet_time.microseconds,
//					vtimer_now().microseconds - current_socket->socket_values.tcp_control.last_packet_time.microseconds,
//					current_timeout);
			}
		}
	}
Пример #6
0
Файл: ip.c Проект: A-L-E-X/RIOT
uint32_t get_remaining_time(timex_t *t)
{
    timex_t now;
    vtimer_now(&now);

    return (timex_sub(*t, now).seconds);
}
Пример #7
0
void send_tcp_bandwidth_test(char *str)
	{
	timex_t start, end, total;
	double secs;

	int i = 0, count;
	char command[80];
//	char msg_string[] = "abcdefghijklmnopqrstuvwxyz0123456789!-";
	char msg_string[] = "abcdefghijklmnopqrstuvwxyz0123456789!-=/%$";

	sscanf(str, "tcp_bw %i", &count);
	ltc4150_start();
	printf("Start power: %f\n", ltc4150_get_total_mAh());
	start = vtimer_now();
	for (i = 0; i < count; i++)
		{
		sprintf(command, "send_tcp %s%.5i", msg_string, i);
		send_tcp_msg(command);
		}
	end = vtimer_now();
	total = timex_sub(end, start);
	secs = total.microseconds / 1000000.0f;
	printf("Used power: %f\n", ltc4150_get_total_Joule());
	printf("Start: %lu, End: %lu, Total: %lu\n", start.microseconds, end.microseconds, total.microseconds);
	printf("Time: %f seconds, Bandwidth: %f byte/second\n", secs, (count*48)/secs);
	}
Пример #8
0
void handle_established(socket_internal_t *current_socket)
{
    msg_t send;
    double current_timeout = current_socket->socket_values.tcp_control.rto;

    if (current_timeout < SECOND) {
        current_timeout = SECOND;
    }

    uint8_t i;

    if ((current_socket->socket_values.tcp_control.send_nxt >
         current_socket->socket_values.tcp_control.send_una) &&
        (thread_getstatus(current_socket->send_pid) == STATUS_RECEIVE_BLOCKED)) {
        for (i = 0; i < current_socket->socket_values.tcp_control.no_of_retries;
             i++) {
            current_timeout *= 2;
        }

        timex_t now;
        vtimer_now(&now);

        if (current_timeout > TCP_ACK_MAX_TIMEOUT) {
            net_msg_send(&send, current_socket->send_pid, 0, TCP_TIMEOUT);
        }
        else if (timex_uint64(timex_sub(now, current_socket->socket_values.tcp_control.last_packet_time)) >
                 current_timeout) {
            current_socket->socket_values.tcp_control.no_of_retries++;
            net_msg_send(&send, current_socket->send_pid, 0, TCP_RETRY);
        }
    }
}
Пример #9
0
void calc_rtt(void)
{
    timex_t end;
    vtimer_now(&end);
    timex_t result = timex_sub(end, start);

    rtt = result.seconds + (float)result.microseconds / (1000.0 * 1000.0);
}
Пример #10
0
int _l2_ping_req_handler(int argc, char **argv)
{
    size_t payload_strlen;
    uint16_t count = 5;
    timex_t start, end, period;

    if (transceiver_pid == KERNEL_PID_UNDEF) {
        puts("Transceiver not initialized");
        return 1;
    }
    if (argc < 2) {
        printf("Usage:\t%s <ADDR> [COUNT] [MSG]\n", argv[0]);
        return 1;
    }

    char l2_payload[L2_PING_PAYLOAD_SIZE];
    if (argc > 3) {
        payload_strlen = strlen(argv[3]);
        if (payload_strlen > L2_PING_PAYLOAD_SIZE) {
            printf("[l2_ping] Your input is too long and will be truncated to \"%.*s\".\n", L2_PING_PAYLOAD_SIZE, argv[3]);
            payload_strlen = L2_PING_PAYLOAD_SIZE;
        }
        memset(l2_payload, 0, L2_PING_PAYLOAD_SIZE);
        strncpy(l2_payload, argv[3], payload_strlen);
    }
    else {
        payload_strlen = 0;
    }

    if (argc > 2) {
        count = atoi(argv[2]);
    }

    printf("[l2_ping] Send %" PRIu8 " ping requests to %" PRIu16 " with interval %" PRIu32 ".%" PRIu32 "s and payload %s\n",
            count, atoi(argv[1]),
            timex_from_uint64(L2_PING_DEFAULT_INTERVAL).seconds,
            timex_from_uint64(L2_PING_DEFAULT_INTERVAL).microseconds,
            (argc > 3) ? l2_payload : "NULL");
    vtimer_now(&start);
    l2_ping((radio_address_t) atoi(argv[1]), count, L2_PING_DEFAULT_INTERVAL,
            l2_payload, payload_strlen, 0);
    vtimer_now(&end);
    period = timex_sub(end, start);

    printf("  --- ping statistics for host %" PRIu16 " ---\n", l2_ping_stats.dst);
    printf("  %" PRIu16 " packets transmitted, %" PRIu16 " received, %" PRIu16 "%% packet loss, time %" PRIu32 ".%06" PRIu32 "s\n",
           l2_ping_stats.ping_count,
           l2_ping_stats.pong_count,
           100 - ((l2_ping_stats.pong_count * 100) / l2_ping_stats.ping_count),
           period.seconds,
           period.microseconds);
    printf("  rtt min/avg/max = %" PRIu32 ".%06" PRIu32 "/%" PRIu32 ".%06" PRIu32 "/%" PRIu32 ".%06" PRIu32 " s\n",
            l2_ping_stats.min_rtt.seconds, l2_ping_stats.min_rtt.microseconds,
            l2_ping_stats.avg_rtt.seconds, l2_ping_stats.avg_rtt.microseconds,
            l2_ping_stats.max_rtt.seconds, l2_ping_stats.max_rtt.microseconds);

    return 0;
}
Пример #11
0
void print_tcp_cb(tcp_cb_t *cb)
{
    timex_t now;
    vtimer_now(&now);
    printf("Send_ISS: %" PRIu32 "\nSend_UNA: %" PRIu32 "\nSend_NXT: %" PRIu32 "\nSend_WND: %u\n",
           cb->send_iss, cb->send_una, cb->send_nxt, cb->send_wnd);
    printf("Rcv_IRS: %" PRIu32 "\nRcv_NXT: %" PRIu32 "\nRcv_WND: %u\n",
           cb->rcv_irs, cb->rcv_nxt, cb->rcv_wnd);
    printf("Time difference: %" PRIu32 ", No_of_retries: %u, State: %u\n\n",
           timex_sub(now, cb->last_packet_time).microseconds, cb->no_of_retries, cb->state);
}
Пример #12
0
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;
    }
}
Пример #13
0
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;
}
Пример #14
0
void send_udp(char *str)
	{
	timex_t start, end, total;
	long secs;
	int sock;
	sockaddr6_t sa;
	ipv6_addr_t ipaddr;
	int bytes_sent;
	int address, count;
	char text[] = "abcdefghijklmnopqrstuvwxyz0123456789!-=$%&/()";
	sscanf(str, "send_udp %i %i %s", &count, &address, text);

	sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
	if (-1 == sock)
		{
		printf("Error Creating Socket!");
		exit(EXIT_FAILURE);
		}

	memset(&sa, 0, sizeof sa);

	ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, (uint16_t)address);
	ipv6_print_addr(&ipaddr);

	sa.sin6_family = AF_INET;
	memcpy(&sa.sin6_addr, &ipaddr, 16);
	sa.sin6_port = HTONS(7654);
	ltc4150_start();
	printf("Start power: %f\n", ltc4150_get_total_Joule());
	start = vtimer_now();
	for (int i = 0; i < count; i++)
		{
		bytes_sent = sendto(sock, (char*)text, strlen((char*)text)+1, 0, &sa, sizeof sa);
		if (bytes_sent < 0)
			{
			printf("Error sending packet!\n");
			}
//		hwtimer_wait(20*1000);
		}
	end = vtimer_now();
	total = timex_sub(end, start);
	secs = total.microseconds / 1000000;
	printf("Used power: %f\n", ltc4150_get_total_Joule());
	printf("Start: %lu, End: %lu, Total: %lu\n", start.microseconds, end.microseconds, total.microseconds);
	secs = total.microseconds / 1000000;
	printf("Time: %lu seconds, Bandwidth: %lu byte/second\n", secs, (count*48)/secs);
	close(sock);
	}
Пример #15
0
int pthread_cond_timedwait(struct pthread_cond_t *cond, struct mutex_t *mutex, const struct timespec *abstime)
{
    timex_t now, then, reltime;

    vtimer_now(&now);
    then.seconds = abstime->tv_sec;
    then.microseconds = abstime->tv_nsec / 1000u;
    reltime = timex_sub(then, now);

    vtimer_t timer;
    vtimer_set_wakeup(&timer, reltime, sched_active_thread->pid);
    int result = pthread_cond_wait(cond, mutex);
    vtimer_remove(&timer);

    return result;
}
Пример #16
0
void fib_print_routes(void)
{
    mutex_lock(&mtx_access);
    printf("%-32s %-6s %-32s %-6s %-16s Interface\n"
           , "Destination", "Flags", "Next Hop", "Flags", "Expires");

    timex_t now;
    vtimer_now(&now);

    for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) {
        if (fib_table[i].lifetime.seconds != 0 || fib_table[i].lifetime.microseconds != 0) {
            fib_print_adress(fib_table[i].global);
            printf(" 0x%04x ", fib_table[i].global_flags);
            fib_print_adress(fib_table[i].next_hop);
            printf(" 0x%04x ", fib_table[i].next_hop_flags);

            if ((fib_table[i].lifetime.seconds != FIB_LIFETIME_NO_EXPIRE)
                || (fib_table[i].lifetime.microseconds != FIB_LIFETIME_NO_EXPIRE)) {

                timex_t tm = timex_sub(fib_table[i].lifetime, now);

                /* we must interpret the values as signed */
                if ((int32_t)tm.seconds < 0
                    || (tm.seconds == 0 && (int32_t)tm.microseconds < 0)) {
                    printf("%-16s ", "EXPIRED");
                }
                else {
                    printf("%"PRIu32".%05"PRIu32, tm.seconds, tm.microseconds);
                }
            }
            else {
                printf("%-16s ", "NEVER");
            }

            printf("%d\n", (int)fib_table[i].iface_id);
        }
    }

    mutex_unlock(&mtx_access);
}
Пример #17
0
/*---------------------------------------------------------------------------*/
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;
}