udpcontikicoojacontiki-ng6lowpan

How to make downward connection in Contiki-NG with UDP


I'm trying to make a simple mesh connection using 6LoWPAN with Contiki.

For simplicity I'm making this in Cooja, so the hardware is not a constrain in this problem i think.

My objective is to have one root (UDP Server) and many motes (UDP Client). With the examples provided by Contiki, I'm able to do start the communication with the Motes and talk to the Server, but is it possible to do it the other way around?

I want the Root to start send the message to any client, and if it's neccesary, to hop the message via another clients in the network.

Do you have any idea if this is possible to do? Or any track for achieve this?

Update: What I've tried so far:

What i've tried so far, in the server device, create two process, one for initiating the root, and the other one for sendig the packet periodically:

#include "contiki.h"
#include <stdlib.h>
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"
#include "sys/log.h"

#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG

#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678

#define SEND_INTERVAL         (5 * CLOCK_SECOND)

static struct simple_udp_connection udp_conn;
static struct etimer periodic_timer;

PROCESS(udp_server_process, "UDP server");
PROCESS(send_msg_process, "UDP server");
AUTOSTART_PROCESSES(&udp_server_process, &send_msg_process);


static void
udp_rx_callback(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
  LOG_INFO("Received response '%.*s' from ", datalen, (char *) data);
  LOG_INFO_6ADDR(sender_addr);
  LOG_INFO_("\n");
}




PROCESS_THREAD(udp_server_process, ev, data)
{
  PROCESS_BEGIN();

  /* Initialize DAG root */
  NETSTACK_ROUTING.root_start();

  /* Initialize UDP connection */
  simple_udp_register(&udp_conn, UDP_SERVER_PORT, NULL,
                      UDP_CLIENT_PORT, udp_rx_callback);

  PROCESS_END();
}


PROCESS_THREAD(send_msg_process, ev, data)
{
  
  static unsigned count;
  static char str[32];
  uip_ipaddr_t dest_ipaddr;
  LOG_INFO("%u", count);
  PROCESS_BEGIN();

  while(1) {
      etimer_set(&periodic_timer, CLOCK_SECOND);
      PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
        uip_ip6addr(&dest_ipaddr,0xfe80,0,0,0,0x207,0x7,0x7,0x7);
        LOG_INFO("Sending request %u to ", count);
        LOG_INFO_6ADDR(&dest_ipaddr);
        LOG_INFO_("\n");
        snprintf(str, sizeof(str), "hello %d", count);
        simple_udp_sendto(&udp_conn, str, strlen(str), &dest_ipaddr);
        count++;
  }
  PROCESS_END();
}

In the cliend side, the code is based simply on listening to the UDP socket, and make a response in the case that it receives a packet.

#include "contiki.h"
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"

#include "sys/log.h"
#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG

#define WITH_SERVER_REPLY  1
#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678

#define SEND_INTERVAL         (5 * CLOCK_SECOND)

static struct simple_udp_connection udp_conn;

/*---------------------------------------------------------------------------*/
PROCESS(udp_client_process, "UDP client");
AUTOSTART_PROCESSES(&udp_client_process);
/*---------------------------------------------------------------------------*/
static void
udp_rx_callback(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{

  LOG_INFO("Received request '%.*s' from ", datalen, (char *) data);
  LOG_INFO_6ADDR(sender_addr);

  LOG_INFO("Sending response.\n");
  simple_udp_sendto(&udp_conn, data, datalen, sender_addr);

  LOG_INFO_("\n");

}

PROCESS_THREAD(udp_client_process, ev, data)
{
  PROCESS_BEGIN();
  simple_udp_register(&udp_conn, UDP_CLIENT_PORT, NULL,
                      UDP_SERVER_PORT, udp_rx_callback);
  PROCESS_END();
}

As you can see, the code for the server sends periodically a packet to the ipv6 direction: 0xfe80:0:0:0:0x207:0x7:0x7:0x7, which is the ip that will be assigned to a mote in cooja when it is the number 7 in the simulation.

The results I've obtained is that, when the root (A) and the client (B) are in direct connection, they talk to each other perfectly, but when I separate them and try to make the connection from the root (A) to the client (B) via another client (C), the message won't get from A to B.


Solution

  • Yes, it is possible. The RPL routing protocol allows to send packets in both directions from and to the root. Simply use the node's IP address as the destination.

    One issue is that a node typically has two IPv6 addresses:

    Packets to link-local addresses must be single-hop, they are not forwarded by nodes. In order to utilize the multi-hop mesh forwarding properly, use the other address as the destination.