Friday, December 2, 2016

How to calculate the latency in Contiki OS

Objective

In this tutorial i am going to show you how to calculate the latency of a packet in a wireless link. I am using Contiki v3.x, sky (CM5000) nodes and lubuntu 16.04. First of all, to compute the latency of a packet you need to have the nodes synchronized. In order to synchronize the nodes of the network, you can use the Implicit Network Time Synchronization of Contiki, which i explain in the following tutorial:

http://contiki-iot.blogspot.com.co/2016/11/implicit-network-time-synchronization_28.html

It means that you must to do the above tutorial if you want to calculate the latency of a packet.

NOTE: Since the Implicit Network Time Synchronization mechanism of Contiki only works on sky nodes, this latency computation only works on sky nodes too.

Step 1: Synchronize your nodes

As mentioned above, you must have your nodes synchronized to calculate the latency of a packet. In order to synchronize your nodes, go to the following tutorial:

http://contiki-iot.blogspot.com.co/2016/11/implicit-network-time-synchronization_28.html

Step 2: Modify your example-broadcast.c

I am going to calculate the latency of a packet in the broadcast rime example. I got the basic idea from an example named shell-rime-debug.c which is located in /home/YOUR_USER/Desktop/contiki/apps/shell. So, you can go and check that file in order to get the information directly from a contiki source file.

Next, i am going to explain the changes that i made to the example-broadcast.c file:

  • Create a latency structure: We create a latency structure to save the timestamp of the message, i.e. the time when the message was sent.
  • Send a broadcast with the timestamp: The normal/original example-broadcast.c file sends a broadcast with a 'hello' message, in this tutorial, we are going to send a broadcast with the timestamp. So, we comment/delete the 'hello' message and add our timestamp to the broadcast.
  • Receive a broadcast with the timestamp and compute the latency: We receive the broadcast that includes the timestamp. Then, we compute the time difference between the current time (timesynch_time()) and the broadcast timestamp (msg.timestamp), that difference (timesynch_time() - msg.timestamp) is equal to the latency.

Now, we show you the full code:

/*
 * Copyright (c) 2007, Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Contiki operating system.
 *
 */

/**
 * \file
 *         Testing the broadcast layer in Rime
 * \author
 *         Adam Dunkels 
 */

#include "contiki.h"
#include "net/rime/rime.h"
#include "random.h"

#include "dev/button-sensor.h"

#include "dev/leds.h"

#include 


/*--------------------------------------*/

struct latency_structure{ // Structure to save the time when the message was send

   rtimer_clock_t timestamp;// Time when the message was send

};
/*---------------------------------------------------------------------------*/
PROCESS(example_broadcast_process, "Broadcast example");
AUTOSTART_PROCESSES(&example_broadcast_process);
/*---------------------------------------------------------------------------*/

//Receive a broadcast with the timestamp and compute the latency
static void
broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from)
{
  struct latency_structure msg;
  rtimer_clock_t latency;

  packetbuf_copyto( &msg ); // Copy the message from the packet buffer to the structure called msg

#if TIMESYNCH_CONF_ENABLED
  latency = timesynch_time() - msg.timestamp;
#else
  latency = 0;
#endif

  printf("broadcast message received from %d.%d with latency %lu ms\n",
         from->u8[0], from->u8[1], (1000L * latency) / RTIMER_ARCH_SECOND );
}
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
static struct broadcast_conn broadcast;
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_broadcast_process, ev, data)
{
  struct latency_structure *msg;

  static struct etimer et;

  PROCESS_EXITHANDLER(broadcast_close(&broadcast);)

  PROCESS_BEGIN();

  broadcast_open(&broadcast, 129, &broadcast_call);

  while(1) {

    /* Delay 2-4 seconds */
    etimer_set(&et, CLOCK_SECOND * 4 + random_rand() % (CLOCK_SECOND * 4));

    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));

#if TIMESYNCH_CONF_ENABLED
      msg->timestamp = timesynch_time();
#else
      msg->timestamp = 0;
#endif

    // Do not send the normal/original 'hello' message. Instead, send a message with the timestamp.
    packetbuf_copyfrom(msg,   sizeof(*msg) ); // This message msg includes the timestamp
    //packetbuf_copyfrom("Hello", 6);
    broadcast_send(&broadcast);
    printf("broadcast message sent\n");
  }

  PROCESS_END();
}
/*---------------------------------------------------------------------------*/


Step 3: Upload the code to 2 or more sky nodes

Since the Implicit Network Time Synchronization mechanism of Contiki only works on sky nodes, this latency computation only works on sky nodes. In order to upload the code to the sky nodes, do this:

make clean && make TARGET=sky example-broadcast.upload && make login

If everything is working correctly you should see a message like this:

broadcast message received from X.X with latency 1167 ms

When i tested the code the latency varies from 12ms to 1652 ms. Notice that X.X is the address of the node that sent the broadcast. In my example, the sky node has address 185.144

6 comments:

  1. I learned a lot from these tutorials. To my knowledge these are the first tutorials that explain so well the program structure of contiki and how to use different functionality. Well done and hope you will keep posting more tutorials in future.

    ReplyDelete
  2. can we use this method for cooja simulations without connecting hardware?

    ReplyDelete
  3. why does the latency value keep changing inspite of the fact that the motes aren't moving? As far as I understand, latency is the time to reach one mote to another. so if my motes are stationary then the latency should be same. I've also noticed that you said your latency clues varied from 12-1657ms but I'm getting from 5-1770ms

    ReplyDelete
  4. can you please tell me how can i find latency of z1 nodes and wismoe nodes

    ReplyDelete