Commit 123105ab authored by Simon Duquennoy's avatar Simon Duquennoy
Browse files

Move source routing state management from RPL Lite and RPL Classic to uip.

parent 62d128f5
......@@ -40,17 +40,11 @@
#include "node-id.h"
#include "sys/log.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/ipv6/uip-sr.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-log.h"
#include "net/routing/routing.h"
#if ROUTING_CONF_RPL_LITE
#include "net/routing/rpl-lite/rpl.h"
#elif ROUTING_CONF_RPL_CLASSIC
#include "net/routing/rpl-classic/rpl.h"
#include "net/routing/rpl-classic/rpl-ns.h"
#endif
#define DEBUG DEBUG_PRINT
#include "net/ipv6/uip-debug.h"
......@@ -86,8 +80,8 @@ PROCESS_THREAD(node_process, ev, data)
#if (UIP_MAX_ROUTES != 0)
PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes());
#endif
#if UIP_CONF_IPV6_RPL
PRINTF("Routing links: %u\n", rpl_ns_num_nodes());
#if (UIP_SR_LINK_NUM != 0)
PRINTF("Routing links: %u\n", uip_sr_num_nodes());
#endif
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
......
......@@ -32,13 +32,8 @@
#include "contiki.h"
#include "net/routing/routing.h"
/* For RPL-specific data inclusion, in particular non-storing routing link */
#if ROUTING_CONF_RPL_LITE
#include "net/routing/rpl-lite/rpl.h"
#elif ROUTING_CONF_RPL_CLASSIC
#include "net/routing/rpl-classic/rpl.h"
#include "net/routing/rpl-classic/rpl-ns.h"
#endif
#include "net/ipv6/uip-ds6-route.h"
#include "net/ipv6/uip-sr.h"
#include <stdio.h>
#include <string.h>
......@@ -125,18 +120,18 @@ PT_THREAD(generate_routes(struct httpd_state *s))
}
#endif /* UIP_MAX_ROUTES != 0 */
#if UIP_CONF_IPV6_RPL
if(rpl_ns_num_nodes() > 0) {
static rpl_ns_node_t *link;
#if (UIP_SR_LINK_NUM != 0)
if(uip_sr_num_nodes() > 0) {
static uip_sr_node_t *link;
ADD(" Routing links\n <ul>\n");
SEND(&s->sout);
for(link = rpl_ns_node_head(); link != NULL; link = rpl_ns_node_next(link)) {
for(link = uip_sr_node_head(); link != NULL; link = uip_sr_node_next(link)) {
if(link->parent != NULL) {
uip_ipaddr_t child_ipaddr;
uip_ipaddr_t parent_ipaddr;
rpl_ns_get_node_global_addr(&child_ipaddr, link);
rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent);
NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link);
NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent);
ADD(" <li>");
ipaddr_add(&child_ipaddr);
......@@ -152,7 +147,7 @@ PT_THREAD(generate_routes(struct httpd_state *s))
ADD(" </ul>");
SEND(&s->sout);
}
#endif /* UIP_CONF_IPV6_RPL */
#endif /* UIP_SR_LINK_NUM != 0 */
SEND_STRING(&s->sout, BOTTOM);
......
......@@ -30,55 +30,59 @@
*/
/**
* \addtogroup rpl-lite
* \addtogroup uip
* @{
*
* \file
* RPL non-storing mode specific functions. Includes support for
* source routing.
* Source routing support
*
* \author Simon Duquennoy <simon.duquennoy@inria.fr>
*/
#include "net/routing/rpl-lite/rpl.h"
#include "contiki.h"
#include "net/ipv6/uip-sr.h"
#include "net/routing/routing.h"
#include "lib/list.h"
#include "lib/memb.h"
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL LOG_LEVEL_RPL
#define LOG_MODULE "IPv6 SR"
#define LOG_LEVEL LOG_LEVEL_IPV6
/* Total number of nodes */
static int num_nodes;
/* Every known node in the network */
LIST(nodelist);
MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM);
MEMB(nodememb, uip_sr_node_t, UIP_SR_LINK_NUM);
/*---------------------------------------------------------------------------*/
int
rpl_ns_num_nodes(void)
uip_sr_num_nodes(void)
{
return num_nodes;
}
/*---------------------------------------------------------------------------*/
static int
node_matches_address(const rpl_ns_node_t *node, const uip_ipaddr_t *addr)
node_matches_address(void *graph, const uip_sr_node_t *node, const uip_ipaddr_t *addr)
{
return addr != NULL
&& node != NULL
&& !memcmp(addr, &curr_instance.dag.dag_id, 8)
&& !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8);
if(node == NULL || addr == NULL || graph != node->graph) {
return 0;
} else {
uip_ipaddr_t node_ipaddr;
NETSTACK_ROUTING.get_sr_node_ipaddr(&node_ipaddr, node);
return uip_ipaddr_cmp(&node_ipaddr, addr);
}
}
/*---------------------------------------------------------------------------*/
rpl_ns_node_t *
rpl_ns_get_node(const uip_ipaddr_t *addr)
uip_sr_node_t *
uip_sr_get_node(void *graph, const uip_ipaddr_t *addr)
{
rpl_ns_node_t *l;
uip_sr_node_t *l;
for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) {
/* Compare prefix and node identifier */
if(node_matches_address(l, addr)) {
if(node_matches_address(graph, l, addr)) {
return l;
}
}
......@@ -86,11 +90,17 @@ rpl_ns_get_node(const uip_ipaddr_t *addr)
}
/*---------------------------------------------------------------------------*/
int
rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr)
uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr)
{
int max_depth = RPL_NS_LINK_NUM;
rpl_ns_node_t *node = rpl_ns_get_node(addr);
rpl_ns_node_t *root_node = rpl_ns_get_node(&curr_instance.dag.dag_id);
int max_depth = UIP_SR_LINK_NUM;
uip_ipaddr_t root_ipaddr;
uip_sr_node_t *node;
uip_sr_node_t *root_node;
NETSTACK_ROUTING.get_root_ipaddr(&root_ipaddr);
node = uip_sr_get_node(graph, addr);
root_node = uip_sr_get_node(graph, &root_ipaddr);
while(node != NULL && node != root_node && max_depth > 0) {
node = node->parent;
max_depth--;
......@@ -99,26 +109,26 @@ rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr)
}
/*---------------------------------------------------------------------------*/
void
rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent)
uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent)
{
rpl_ns_node_t *l = rpl_ns_get_node(child);
uip_sr_node_t *l = uip_sr_get_node(graph, child);
/* Check if parent matches */
if(l != NULL && node_matches_address(l->parent, parent)) {
l->lifetime = RPL_NOPATH_REMOVAL_DELAY;
if(l != NULL && node_matches_address(graph, l->parent, parent)) {
l->lifetime = UIP_SR_REMOVAL_DELAY;
}
}
/*---------------------------------------------------------------------------*/
rpl_ns_node_t *
rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime)
uip_sr_node_t *
uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime)
{
rpl_ns_node_t *child_node = rpl_ns_get_node(child);
rpl_ns_node_t *parent_node = rpl_ns_get_node(parent);
rpl_ns_node_t *old_parent_node;
uip_sr_node_t *child_node = uip_sr_get_node(graph, child);
uip_sr_node_t *parent_node = uip_sr_get_node(graph, parent);
uip_sr_node_t *old_parent_node;
if(parent != NULL) {
/* No node for the parent, add one with infinite lifetime */
if(parent_node == NULL) {
parent_node = rpl_ns_update_node(parent, NULL, RPL_ROUTE_INFINITE_LIFETIME);
parent_node = uip_sr_update_node(graph, parent, NULL, UIP_SR_INFINITE_LIFETIME);
if(parent_node == NULL) {
LOG_ERR("NS: no space left for root node!\n");
return NULL;
......@@ -142,16 +152,17 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32
}
/* Initialize node */
child_node->graph = graph;
child_node->lifetime = lifetime;
memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8);
/* Is the node reachable before the update? */
if(rpl_ns_is_addr_reachable(child)) {
if(uip_sr_is_addr_reachable(graph, child)) {
old_parent_node = child_node->parent;
/* Update node */
child_node->parent = parent_node;
/* Has the node become unreachable? May happen if we create a loop. */
if(!rpl_ns_is_addr_reachable(child)) {
if(!uip_sr_is_addr_reachable(graph, child)) {
/* The new parent makes the node unreachable, restore old parent.
* We will take the update next time, with chances we know more of
* the topology and the loop is gone. */
......@@ -171,48 +182,36 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32
}
/*---------------------------------------------------------------------------*/
void
rpl_ns_init(void)
uip_sr_init(void)
{
num_nodes = 0;
memb_init(&nodememb);
list_init(nodelist);
}
/*---------------------------------------------------------------------------*/
rpl_ns_node_t *
rpl_ns_node_head(void)
uip_sr_node_t *
uip_sr_node_head(void)
{
return list_head(nodelist);
}
/*---------------------------------------------------------------------------*/
rpl_ns_node_t *
rpl_ns_node_next(rpl_ns_node_t *item)
uip_sr_node_t *
uip_sr_node_next(uip_sr_node_t *item)
{
return list_item_next(item);
}
/*---------------------------------------------------------------------------*/
int
rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node)
{
if(addr != NULL && node != NULL) {
memcpy(addr, &curr_instance.dag.dag_id, 8);
memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8);
return 1;
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/
void
rpl_ns_periodic(unsigned seconds)
uip_sr_periodic(unsigned seconds)
{
rpl_ns_node_t *l;
rpl_ns_node_t *next;
uip_sr_node_t *l;
uip_sr_node_t *next;
/* First pass, for all expired nodes, deallocate them iff no child points to them */
for(l = list_head(nodelist); l != NULL; l = next) {
next = list_item_next(l);
if(l->lifetime == 0) {
rpl_ns_node_t *l2;
uip_sr_node_t *l2;
for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) {
if(l2->parent == l) {
break;
......@@ -220,7 +219,7 @@ rpl_ns_periodic(unsigned seconds)
}
#if LOG_INFO_ENABLED
uip_ipaddr_t node_addr;
rpl_ns_get_node_global_addr(&node_addr, l);
NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, l);
LOG_INFO("NS: removing expired node ");
LOG_INFO_6ADDR(&node_addr);
LOG_INFO_("\n");
......@@ -229,17 +228,17 @@ rpl_ns_periodic(unsigned seconds)
list_remove(nodelist, l);
memb_free(&nodememb, l);
num_nodes--;
} else if(l->lifetime != RPL_ROUTE_INFINITE_LIFETIME) {
} else if(l->lifetime != UIP_SR_INFINITE_LIFETIME) {
l->lifetime = l->lifetime > seconds ? l->lifetime - seconds : 0;
}
}
}
/*---------------------------------------------------------------------------*/
void
rpl_ns_free_all(void)
uip_sr_free_all(void)
{
rpl_ns_node_t *l;
rpl_ns_node_t *next;
uip_sr_node_t *l;
uip_sr_node_t *next;
for(l = list_head(nodelist); l != NULL; l = next) {
next = list_item_next(l);
list_remove(nodelist, l);
......
......@@ -30,37 +30,75 @@
*/
/**
* \addtogroup rpl-lite
* \addtogroup uip
* @{
*
* \file
* RPL non-storing mode specific functions. Includes support for
* source routing.
* Source routing support
*
* \author Simon Duquennoy <simon.duquennoy@inria.fr>
*/
#ifndef RPL_NS_H
#define RPL_NS_H
#ifndef UIP_SR_H
#define UIP_SR_H
/********** Includes **********/
#include "contiki.h"
#include "net/ipv6/uip.h"
#include "net/routing/rpl-lite/rpl.h"
/********** Configuration **********/
/* The number of source routing nodes, i.e. the maximum netwrok size at the root */
#ifdef UIP_SR_CONF_LINK_NUM
#define UIP_SR_LINK_NUM UIP_SR_CONF_LINK_NUM
#else /* UIP_SR_CONF_LINK_NUM */
#if ROUTING_CONF_RPL_LITE
#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES
#elif ROUTING_CONF_RPL_CLASSIC
#include "net/routing/rpl-classic/rpl-conf.h"
#if RPL_WITH_NON_STORING
#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES
#else /* RPL_WITH_NON_STORING */
#define UIP_SR_LINK_NUM 0
#endif /* RPL_WITH_NON_STORING */
#else
#define UIP_SR_LINK_NUM 0
#endif
#endif /* UIP_SR_CONF_LINK_NUM */
/* Delay between between expiration order and actual node removal */
#ifdef UIP_SR_CONF_REMOVAL_DELAY
#define UIP_SR_REMOVAL_DELAY UIP_SR_CONF_REMOVAL_DELAY
#else /* UIP_SR_CONF_REMOVAL_DELAY */
#define UIP_SR_REMOVAL_DELAY 60
#endif /* UIP_SR_CONF_REMOVAL_DELAY */
#define UIP_SR_INFINITE_LIFETIME 0xFFFFFFFF
/********** Data Structures **********/
/* A node in a RPL Non-storing graph, stored at the root and representing
/** \brief A node in a source routing graph, stored at the root and representing
* all child-parent relationship. Used to build source routes */
typedef struct rpl_ns_node {
struct rpl_ns_node *next;
typedef struct uip_sr_node {
struct uip_sr_node *next;
uint32_t lifetime;
rpl_dag_t *dag;
/* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */
/* Protocol-specific graph structure */
void *graph;
/* Store only IPv6 link identifiers, the routing protocol will provide
us with the prefix */
unsigned char link_identifier[8];
struct rpl_ns_node *parent;
} rpl_ns_node_t;
struct uip_sr_node *parent;
} uip_sr_node_t;
/********** Public functions **********/
......@@ -69,31 +107,33 @@ typedef struct rpl_ns_node {
*
* \return The number of nodes
*/
int rpl_ns_num_nodes(void);
int uip_sr_num_nodes(void);
/**
* Expires a given child-parent link
*
* \param graph The graph the link belongs to
* \param child The IPv6 address of the child
* \param parent The IPv6 address of the parent
*/
void rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent);
void uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent);
/**
* Updates a child-parent link
*
* \param graph The graph the link belongs to
* \param child The IPv6 address of the child
* \param parent The IPv6 address of the parent
* \param lifetime The link lifetime in seconds
*/
rpl_ns_node_t *rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime);
uip_sr_node_t *uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime);
/**
* Returns the head of the non-storing node list
*
* \return The head of the list
*/
rpl_ns_node_t *rpl_ns_node_head(void);
uip_sr_node_t *uip_sr_node_head(void);
/**
* Returns the next element of the non-storing node list
......@@ -101,33 +141,26 @@ rpl_ns_node_t *rpl_ns_node_head(void);
* \param item The current element in the list
* \return The next element of the list
*/
rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item);
uip_sr_node_t *uip_sr_node_next(uip_sr_node_t *item);
/**
* Looks up for a RPL NS node from its IPv6 global address
* Looks up for a source routing node from its IPv6 global address
*
* \param graph The graph where to look up for the node
* \param addr The target address
* \return A pointer to the node
*/
rpl_ns_node_t *rpl_ns_get_node(const uip_ipaddr_t *addr);
uip_sr_node_t *uip_sr_get_node(void *graph, const uip_ipaddr_t *addr);
/**
* Telle whether an address is reachable, i.e. if there exists a path from
* the root to the node in the current RPL NS graph
* the root to the node in the current source routing graph
*
* \param graph The graph where to look up for the node
* \param addr The target IPv6 global address
* \return 1 if the node is reachable, 0 otherwise
*/
int rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr);
/**
* Finds the global address of a given node
*
* \param addr A pointer to the address to be written
* \param node The target node
* \return 1 if success, 0 otherwise
*/
int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node);
int uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr);
/**
* A function called periodically. Used to age the links (decrease lifetime
......@@ -135,18 +168,18 @@ int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node);
*
* \param seconds The number of seconds elapsted since last call
*/
void rpl_ns_periodic(unsigned seconds);
void uip_sr_periodic(unsigned seconds);
/**
* Initialize rpl-ns module
* Initialize this module
*/
void rpl_ns_init(void);
void uip_sr_init(void);
/**
* Deallocate all neighbors
*/
void rpl_ns_free_all(void);
void uip_sr_free_all(void);
/** @} */
#endif /* RPL_NS_H */
#endif /* UIP_SR_H */
......@@ -70,6 +70,12 @@ get_root_ipaddr(uip_ipaddr_t *ipaddr)
return 0;
}
/*---------------------------------------------------------------------------*/
static int
get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node)
{
return 0;
}
/*---------------------------------------------------------------------------*/
static void
leave_network(void)
{
......@@ -143,6 +149,7 @@ const struct routing_driver nullrouting_driver = {
root_start,
node_is_root,
get_root_ipaddr,
get_sr_node_ipaddr,
leave_network,
node_is_reachable,
global_repair,
......
......@@ -44,6 +44,7 @@
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-ds6-nbr.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/ipv6/uip-sr.h"
#include "net/linkaddr.h"
/**
......@@ -79,6 +80,14 @@ struct routing_driver {
* \return 1 if the root address was copied, 0 otherwise
*/
int (* get_root_ipaddr)(uip_ipaddr_t *ipaddr);
/**
* Returns the global IPv6 address of a source routing node
*
* \param ipaddr A pointer where to copy the IP address of the node
* \param node The source routing node
* \return 1 if the global node address was copied, 0 otherwise
*/
int (* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node);
/**
* Leave the network the node is part of
*
......
......@@ -47,6 +47,7 @@
#include "net/link-stats.h"
#include "net/routing/rpl-classic/rpl.h"
#include "net/routing/rpl-classic/rpl-private.h"
#include "net/routing/rpl-classic/rpl-dag-root.h"
#include "net/ipv6/uip.h"
#include "net/ipv6/uip-nd6.h"
#include "net/ipv6/uip-ds6-nbr.h"
......@@ -1008,6 +1009,9 @@ int
rpl_has_downward_route(void)
{
int i;
if(rpl_dag_root_is_root()) {
return 1; /* We are the root, and know the route to ourself */
}
for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
if(instance_table[i].used && instance_table[i].has_downward_route) {
return 1;
......
......@@ -44,11 +44,12 @@
* @{
*/
#include "net/routing/routing.h"
#include "net/ipv6/uip.h"
#include "net/ipv6/tcpip.h"
#include "net/ipv6/uip-ds6.h"
#include "net/ipv6/uip-sr.h"
#include "net/routing/rpl-classic/rpl-private.h"
#include "net/routing/rpl-classic/rpl-ns.h"
#include "net/packetbuf.h"
#define DEBUG DEBUG_NONE
......@@ -181,8 +182,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
uint8_t *uip_next_hdr;
int last_uip_ext_len = uip_ext_len;
rpl_dag_t *dag;
rpl_ns_node_t *dest_node;
rpl_ns_node_t *root_node;
uip_sr_node_t *dest_node;
uip_sr_node_t *root_node;
uip_ext_len = 0;
uip_next_hdr = &UIP_IP_BUF->proto;
......@@ -208,8 +209,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
}
dag = rpl_get_dag(&UIP_IP_BUF->destipaddr);
root_node = rpl_ns_get_node(dag, &dag->dag_id);
dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr);
root_node = uip_sr_get_node(dag, &dag->dag_id);
dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr);
if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
&& UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
......@@ -339,9 +340,9 @@ insert_srh_header(void)
uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */
uint8_t *hop_ptr;
uint8_t padding;
rpl_ns_node_t *dest_node;
rpl_ns_node_t *root_node;