RPL DIO Message Contents

The DIO message is the primary mechanism for RPL nodes to discover the DODAG, select their parents, and maintain the routing topology. Nodes periodically transmit DIO messages to advertise their presence and routing information, allowing other nodes to join the DODAG and maintain routing paths.

struct rpl_dio {
uip_ipaddr_t dag_id;
rpl_ocp_t ocp;
rpl_rank_t rank;
uint8_t grounded;
uint8_t mop;
uint8_t preference;
uint8_t version;
uint8_t instance_id;
uint8_t dtsn;
uint8_t dag_intdoubl;
uint8_t dag_intmin;
uint8_t dag_redund;
uint8_t default_lifetime;
uint16_t lifetime_unit;
rpl_rank_t dag_max_rankinc;
rpl_rank_t dag_min_hoprankinc;
rpl_prefix_t destination_prefix;
rpl_prefix_t prefix_info;
struct rpl_metric_container mc;
};
typedef struct rpl_dio rpl_dio_t;

The provided code defines a structure called rpl_dio that represents the RPL (Routing Protocol for Low-Power and Lossy Networks) DODAG Information Object (DIO) message. The DIO message is a crucial component of the RPL protocol and is used for network discovery, parent selection, and DODAG maintenance.

Here’s a breakdown of the fields within the rpl_dio structure:

  1. dag_id: The identifier of the DODAG (Destination-Oriented Directed Acyclic Graph) to which the node belongs.
  2. ocp: The Objective Code Point, which identifies the Objective Function used by the RPL instance.
  3. rank: The rank of the node within the DODAG, indicating its position in the routing hierarchy.
  4. grounded: A flag indicating whether the DODAG is grounded (i.e., has a border router connected to a larger infrastructure).
  5. mop: The Mode of Operation, which specifies the method used for forwarding data packets.
  6. preference: The preference value of the node, which can be used to influence the DODAG construction.
  7. version: The version number of the DODAG.
  8. instance_id: The identifier of the RPL instance.
  9. dtsn: The Destination Advertisement Trigger Sequence Number, used to trigger DODAG updates.
  10. dag_intdoubl: The DODAG Interval Doubling, which specifies the interval between successive DIO transmissions.
  11. dag_intmin: The minimum interval between successive DIO transmissions.
  12. dag_redund: The DODAG Redundancy Constant, which controls the redundancy of DIO transmissions.
  13. default_lifetime: The default lifetime of the DODAG, used for setting the lifetime of routing table entries.
  14. lifetime_unit: The unit of time for the default lifetime.
  15. dag_max_rankinc: The maximum rank increase allowed when calculating a new rank.
  16. dag_min_hoprankinc: The minimum increment in rank when going up one hop.
  17. destination_prefix: The destination prefix information.
  18. prefix_info: The prefix information option.
  19. mc: The Metric Container, which holds information about the path metrics.

Online Math Formula Writing Tool for Latex

LaTeX is a document editing system that allows for the professional and aesthetic typesetting of mathematical formulas and equations. It is commonly used in scientific articles, theses, presentation files, and other academic documents.

Writing mathematical formulas in LaTeX enables the correct formatting of special symbols, equation structures, and mathematical expressions. LaTeX provides users with a wide range of mathematical symbols and notation, enhancing the readability and professionalism of the formulas.

Creating mathematical formulas with LaTeX is made easy by using the Online LaTeX Equation Editor available at “https://latex.codecogs.com/eqneditor/editor.php“. This website allows you to create, edit, and download LaTeX formulas. The site allows you to input your formula through a visual interface and automatically generates the corresponding LaTeX code. You can then copy or download the generated LaTeX code and integrate the formula into your project.

Finding the number of routes in Contiki OS

To find the number of routes in Contiki OS, you can use the uip_ds6_route_num_routes function. This function is part of the uIP stack in Contiki OS and returns the number of routes in the routing table.

int
uip_ds6_route_num_routes(void)
{
#if (UIP_CONF_MAX_ROUTES != 0)
return num_routes;
#else /* (UIP_CONF_MAX_ROUTES != 0) */
return 0;
#endif /* (UIP_CONF_MAX_ROUTES != 0) */
}

Here is a step-by-step explanation of the function:

  1. The function uip_ds6_route_num_routes is called.
  2. It checks if the value of UIP_CONF_MAX_ROUTES is not equal to zero using the #if preprocessor directive.
  3. If UIP_CONF_MAX_ROUTES is not zero, it means that the maximum number of routes is defined in the configuration. In this case, the function returns the value of the variable num_routes, which likely holds the current number of routes in the routing table.
  4. If UIP_CONF_MAX_ROUTES is zero, it means that the maximum number of routes is not defined or set to zero. In this case, the function returns 0 to indicate that there are no routes in the routing table.

In summary, the uip_ds6_route_num_routes function in Contiki OS provides a way to obtain the number of routes in the routing table. The specific value returned depends on the configuration of UIP_CONF_MAX_ROUTES.

Pulling link_stats and node ids from Neighborhood table in Contiki OS

The uip_ds6_nbr_t structure is a data structure used in Contiki OS to represent information associated with neighboring nodes in an IPv6 network. The definition of this structure is as follows:

/** \brief The default nbr_table entry (when
 * UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr
 * cache */
typedef struct uip_ds6_nbr {
#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
  struct uip_ds6_nbr *next;
  uip_ds6_nbr_entry_t *nbr_entry;
#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
  uip_ipaddr_t ipaddr;
  uint8_t isrouter;
  uint8_t state;
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA
  struct stimer reachable;
  struct stimer sendns;
  uint8_t nscount;
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA */
#if UIP_CONF_IPV6_QUEUE_PKT
  struct uip_packetqueue_handle packethandle;
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
#endif                          /*UIP_CONF_QUEUE_PKT */
} uip_ds6_nbr_t;

This structure represents the IPv6 neighbor node table entry in Contiki OS. Descriptions of the areas within the building are as follows:

next: Holds a pointer to the next neighbor node in the neighbor node table.

nbr_entry: Pointer to the neighbor table entry. This is used to support multiple IPv6 addresses.

ipaddr: Keeps the IPv6 address of the neighbor node.

isrouter: A byte that indicates whether the neighboring node is a router.

state: A byte that indicates the state of the neighboring node.

reachable: Reachability timer. This timer is used to determine the reachability of the neighboring node.

sendns: NS (Neighbor Solicitation) send scheduler. This scheduler controls the sending of NS messages to the neighboring node.

nscount: NS (Neighbor Solicitation) counter. This counter is used to keep track of the number of NS messages sent.

packethandle: Packet queue pointer. This is used to hold packets to be sent to the neighboring node.

This structure stores information about neighboring nodes in the IPv6 network and is used in the operation of routing protocols.

The uip_lladdr_t type represents the link-layer addresses of nodes in the IPv6 network in Contiki OS. The expression const uip_lladdr_t *current_nbr creates a pointer named current_nbr, which points to a constant of type uip_lladdr_t. Link layer addresses depend on physical or cable network technologies that enable direct communication between nodes.

For example, in an Ethernet network, the link layer address is known as the MAC (Media Access Control) address. Using this expression, the current_nbr pointer provides access to the link layer address of a neighbor node in the IPv6 network. Appropriate methods or fields can be used to access the link layer address via the current_nbr pointer. This will depend on the specific application context. This type of pointer can be used, for example, to communicate directly with a neighbor node in an IPv6 network or to provide access to other nodes in the network. Link layer addresses play an important role for addressing and routing in data communication between nodes.

The current_nbr_link_stats expression creates a pointer to a structure of type struct link_stats. This pointer provides access to all statistics of a particular link.

The “struct link_stats” structure represents the statistical information of a link. Its content is as follows:

struct link_stats {
  clock_time_t last_tx_time;    // Son gönderim zaman damgası
  clock_time_t last_rx_time;    // Son alım zaman damgası
  uint16_t etx;                 // ETX (Expected Transmission Count)
  int16_t rssi;                 // RSSI (received signal strength indicator)
  uint8_t freshness;            // İstatistiklerin tazeliği
#if LINK_STATS_ETX_FROM_PACKET_COUNT
  uint8_t tx_count;             // Gönderim sayısı, ETX hesaplaması için kullanılır
  uint8_t ack_count;            // ACK sayısı, ETX hesaplaması için kullanılır
#endif /* LINK_STATS_ETX_FROM_PACKET_COUNT */

#if LINK_STATS_PACKET_COUNTERS
  struct link_packet_counter cnt_current;  // Mevcut dönemdeki paket sayısı
  struct link_packet_counter cnt_total;    // Toplam paket sayısı
#endif
};

This structure stores statistical information used to evaluate the performance and quality of a link. Descriptions of the fields inside are as follows:

  • last_tx_time: The last send timestamp represents the time of the last transmission.
  • last_rx_time: The last reception timestamp represents the time of the last reception.
  • etx: ETX (Expected Transmission Count) represents the expected transmission count of the transmission. ETX is used to measure communication quality in wireless networks.
  • rssi: RSSI (received signal strength indicator) represents the received signal strength. RSSI is used to measure the received signal strength. freshness: It is a value that expresses the freshness of the statistics.
  • tx_count and ack_count: The number of transmissions and the number of ACKs used for ETX calculation. These numbers are used in the ETX calculation algorithm.
  • cnt_current and cnt_total: These are structures containing packet counts. cnt_current represents the number of packages in the current period, while cnt_total represents the total number of packages.

This structure provides statistical information used to measure the performance of a link and make decisions of network protocols. For example, it contains information such as transmission power, received signal quality, and transmission stability.

    while(uip_nbr != NULL) {
        current_nbr = uip_ds6_nbr_lladdr_from_ipaddr((const uip_ipaddr_t *)&uip_nbr->ipaddr);
        current_nbr_link_stats = link_stats_from_lladdr((const linkaddr_t *)current_nbr);
        current_nbr_id = uip_nbr->ipaddr.u16[7];

        if(n != NULL)
        {
          n->current_nbr_id = current_nbr_id;
          rpl_parent_t *current_nbr_t = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)current_nbr);  
        }
        else
        {
          n = memb_alloc(&vrt_reward_list_mem);
          if(n != NULL)
          {
            list_add(reward_list, n);
            n->current_nbr_id = current_nbr_id;
            rpl_parent_t *current_nbr_t = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)current_nbr); 
          }
        }
        uip_nbr = uip_ds6_nbr_next(uip_nbr);
      }

This piece of code performs a series of operations that run in a loop. Operations focus on obtaining information about neighboring nodes in an IPv6 network and performing some operations using this information. Let’s explain the functioning of the code snippet step by step:

  • The loop continues as long as the uip_nbr pointer is not NULL.
  • The current_nbr pointer accesses the link layer address of the neighbor node using the uip_ds6_nbr_lladdr_from_ipaddr function via the uip_nbr pointer.
  • The current_nbr_link_stats pointer accesses the statistics of the corresponding neighbor node via the current_nbr pointer using the link_stats_from_lladdr function.
  • current_nbr_id retrieves the 7th component of the IPv6 address (uip_nbr->ipaddr.u16[7]) via the uip_nbr pointer.
  • If pointer n is not NULL, it updates the current_nbr_id field of structure n.
  • The current_nbr_t pointer retrieves a reference to an entry matching the current_nbr pointer from the rpl_parents table using the nbr_table_get_from_lladdr function.
  • If pointer n is NULL, vrt_reward_list_mem allocates an item (n) from the memory pool and adds it to the reward_list list.
  • Updates the current_nbr_id field of structure n.
  • The current_nbr_t pointer retrieves a reference to an entry matching the current_nbr pointer from the rpl_parents table using the nbr_table_get_from_lladdr function.
  • The uip_nbr pointer moves to the next neighboring node’s reference using the uip_ds6_nbr_next function.

This piece of code retrieves information about neighboring nodes in the IPv6 network, performs some operations using this information, and finally passes on the information of the next neighboring node. The function of the code can be clearer if the relevant network structures and functions are fully understood.

Writing the coordinates of the nodes to the file on Cooja

The coordinates of the nodes are important when creating simulations on Cooja. For this, we need to make the necessary definitions under the “private Action startAction” function in Simcontrol.java.

First of all, let’s import the necessary files for the function we will write.

import org.contikios.cooja.Mote;
import org.contikios.cooja.interfaces.Position;

With the Mote and Position imports, the necessary information of the nodes is taken.

/* Warning: static variable, used by all active test editor plugins */
File logFile = new File("/home/mavialp/Download/contiki/log/position.testlog");

We opened a file with File, otherwise we created this file from scratch.

try{
   if(!logFile.exists()){
      logFile.createNewFile();
   }else{
     System.out.println("File already exists");
    }
   }
catch(IOException file_error){
    file_error.printStackTrace();
}

As can be seen from the code, logFile file control is performed. After the LogFile file is created, data is written to the buffer. For this, it is necessary to define a new BufferedWrite.

private static BufferedWriter logWriter_hakan = null; /* For non-GUI tests */

With the for loop, we pull all the nodes from the Simulation class. Then we get the positions of these motes via getInterface(). We assign mote.getInterfaces().getPosition() value to Position class and get x and y coordinates from this class.

      try{
        if(logWriter_hakan == null){

            System.out.println("logWriter_hakan: NULL \n");
            logWriter_hakan = new BufferedWriter(new FileWriter(logFile));

            logWriter_hakan.write("SUCCESS_RATIO_RX: \t\t"+ simulation.getTitle() + "\n");
            logWriter_hakan.write("SUCCESS_RATIO_TX: \t\t"+ simulation.getRandomSeed() + "\n");
            logWriter_hakan.write("TRANSMITTING_RANGE: \t\t"+ simulation.getSpeedLimit() + "\n");

            for (Mote mote: simulation.getMotes()) {
              Position p = mote.getInterfaces().getPosition();
              System.out.println("Node ID:" + mote.getID() +"  x: " + p.getXCoordinate() + " y: " + p.getYCoordinate());
              logWriter_hakan.write("Node ID:" + mote.getID() +"  x: " + p.getXCoordinate() + " y: " + p.getYCoordinate() + "\n");
          }
        }
        else{
            logWriter_hakan.write("SUCCESS_RATIO_RX: \t\t"+ simulation.getTitle() + "\n");
            logWriter_hakan.write("SUCCESS_RATIO_TX: \t\t"+ simulation.getRandomSeed() + "\n");
            logWriter_hakan.write("TRANSMITTING_RANGE: \t\t"+ simulation.getSpeedLimit() + "\n");

            for (Mote mote: simulation.getMotes()) {
              Position p = mote.getInterfaces().getPosition();
              System.out.println("Node ID:" + mote.getID() +"  x: " + p.getXCoordinate() + " y: " + p.getYCoordinate());
              logWriter_hakan.write("Node ID:" + mote.getID() +"  x: " + p.getXCoordinate() + " y: " + p.getYCoordinate() + "\n");
          }
        }
        try{
        logWriter_hakan.flush();
        logWriter_hakan.close();
        } catch (IOException ex) {
          System.out.println("Error when writing to test log file: " + ex);
        }
        logWriter_hakan = null;
      }
       catch (Exception exxx) {
        System.out.println("Create log writer error: " + exxx);
        }

The output of the obtained values is as follows.

SUCCESS_RATIO_RX: 		My simulation
SUCCESS_RATIO_TX: 		123458
TRANSMITTING_RANGE: 		1.0
Node ID:1  x: 0.0 y: 0.0
Node ID:2  x: 0.0 y: 0.0
Node ID:3  x: 0.0 y: 37.5
Node ID:4  x: 0.0 y: 75.0
Node ID:5  x: 0.0 y: 112.5
Node ID:6  x: 37.5 y: 0.0
Node ID:7  x: 37.5 y: 37.5
Node ID:8  x: 37.5 y: 75.0
Node ID:9  x: 37.5 y: 112.5
Node ID:10  x: 75.0 y: 0.0
Node ID:11  x: 75.0 y: 37.5
Node ID:12  x: 75.0 y: 75.0
Node ID:13  x: 75.0 y: 112.5
Node ID:14  x: 112.5 y: 0.0
Node ID:15  x: 112.5 y: 37.5
Node ID:16  x: 112.5 y: 75.0
Node ID:17  x: 112.5 y: 112.5
Node ID:18  x: 150.0 y: 0.0
Node ID:19  x: 150.0 y: 37.5
Node ID:20  x: 150.0 y: 75.0
Node ID:21  x: 150.0 y: 112.5

Suspending certain processes on Contiki OS

In this article, we will see how to wait for certain operations to be performed on Contiki OS until the conditions are met. For example; we have a transaction, but this operation should allow us after performing it under different processes.

It’s definitely a bug for nodes to get prefixes out of sync. For this reason, it is necessary to wait until the desired job is synchronized.

static struct etimer et;

etimer_set(&et, CLOCK_SECOND);

while(!foure_control.synched){
    PROCESS_WAIT_UNTIL(etimer_expired(&et));
    etimer_reset(&et);
}