Contiki 2.6

rpl.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup uip6
00003  * @{
00004  */
00005 /*
00006  * Copyright (c) 2009, Swedish Institute of Computer Science.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 3. Neither the name of the Institute nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * This file is part of the Contiki operating system.
00034  */
00035 /**
00036  * \file
00037  *         ContikiRPL, an implementation of RPL: IPv6 Routing Protocol
00038  *         for Low-Power and Lossy Networks (IETF RFC 6550)
00039  *
00040  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
00041  */
00042 
00043 #include "net/uip.h"
00044 #include "net/tcpip.h"
00045 #include "net/uip-ds6.h"
00046 #include "net/rpl/rpl-private.h"
00047 #include "net/neighbor-info.h"
00048 
00049 #define DEBUG DEBUG_NONE
00050 #include "net/uip-debug.h"
00051 
00052 #include <limits.h>
00053 #include <string.h>
00054 
00055 #if RPL_CONF_STATS
00056 rpl_stats_t rpl_stats;
00057 #endif
00058 
00059 /************************************************************************/
00060 extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
00061 /************************************************************************/
00062 void
00063 rpl_purge_routes(void)
00064 {
00065   int i;
00066 
00067   for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
00068     if(uip_ds6_routing_table[i].isused) {
00069       if(uip_ds6_routing_table[i].state.lifetime <= 1) {
00070         uip_ds6_route_rm(&uip_ds6_routing_table[i]);
00071       } else {
00072         uip_ds6_routing_table[i].state.lifetime--;
00073       }
00074     }
00075   }
00076 }
00077 /************************************************************************/
00078 void
00079 rpl_remove_routes(rpl_dag_t *dag)
00080 {
00081   int i;
00082 
00083   for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
00084     if(uip_ds6_routing_table[i].state.dag == dag) {
00085       uip_ds6_route_rm(&uip_ds6_routing_table[i]);
00086     }
00087   }
00088 }
00089 /************************************************************************/
00090 void
00091 rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag)
00092 {
00093   uip_ds6_route_t *locroute;
00094 
00095   for(locroute = uip_ds6_routing_table;
00096       locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB;
00097       locroute++) {
00098     if(locroute->isused
00099         && uip_ipaddr_cmp(&locroute->nexthop, nexthop)
00100         && locroute->state.dag == dag) {
00101       locroute->isused = 0;
00102     }
00103   }
00104   ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
00105 }
00106 /************************************************************************/
00107 uip_ds6_route_t *
00108 rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
00109               uip_ipaddr_t *next_hop)
00110 {
00111   uip_ds6_route_t *rep;
00112 
00113   rep = uip_ds6_route_lookup(prefix);
00114   if(rep == NULL) {
00115     if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop, 0)) == NULL) {
00116       PRINTF("RPL: No space for more route entries\n");
00117       return NULL;
00118     }
00119   } else {
00120     PRINTF("RPL: Updated the next hop for prefix ");
00121     PRINT6ADDR(prefix);
00122     PRINTF(" to ");
00123     PRINT6ADDR(next_hop);
00124     PRINTF("\n");
00125     uip_ipaddr_copy(&rep->nexthop, next_hop);
00126   }
00127   rep->state.dag = dag;
00128   rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime);
00129   rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL;
00130 
00131   PRINTF("RPL: Added a route to ");
00132   PRINT6ADDR(prefix);
00133   PRINTF("/%d via ", prefix_len);
00134   PRINT6ADDR(next_hop);
00135   PRINTF("\n");
00136 
00137   return rep;
00138 }
00139 /************************************************************************/
00140 static void
00141 rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
00142 {
00143   uip_ipaddr_t ipaddr;
00144   rpl_parent_t *parent;
00145   rpl_instance_t *instance;
00146   rpl_instance_t *end;
00147 
00148   uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
00149   uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
00150   PRINTF("RPL: Neighbor ");
00151   PRINT6ADDR(&ipaddr);
00152   PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
00153 
00154   for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
00155     if(instance->used == 1 ) {
00156       parent = rpl_find_parent_any_dag(instance, &ipaddr);
00157       if(parent != NULL) {
00158         /* Trigger DAG rank recalculation. */
00159         parent->updated = 1;
00160         parent->link_metric = etx;
00161 
00162         if(instance->of->parent_state_callback != NULL) {
00163           instance->of->parent_state_callback(parent, known, etx);
00164         }
00165         if(!known) {
00166           PRINTF("RPL: Removing parent ");
00167           PRINT6ADDR(&parent->addr);
00168           PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx);
00169           parent->rank = INFINITE_RANK;
00170         }
00171       }
00172     }
00173   }
00174 
00175   if(!known) {
00176     PRINTF("RPL: Deleting routes installed by DAOs received from ");
00177     PRINT6ADDR(&ipaddr);
00178     PRINTF("\n");
00179     uip_ds6_route_rm_by_nexthop(&ipaddr);
00180   }
00181 }
00182 /************************************************************************/
00183 void
00184 rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
00185 {
00186   rpl_parent_t *p;
00187   rpl_instance_t *instance;
00188   rpl_instance_t *end;
00189 
00190   if(!nbr->isused) {
00191     PRINTF("RPL: Removing neighbor ");
00192     PRINT6ADDR(&nbr->ipaddr);
00193     PRINTF("\n");
00194     for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
00195       if(instance->used == 1 ) {
00196         p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
00197         if(p != NULL) {
00198           p->rank = INFINITE_RANK;
00199           /* Trigger DAG rank recalculation. */
00200           p->updated = 1;
00201         }
00202       }
00203     }
00204   }
00205 }
00206 /************************************************************************/
00207 void
00208 rpl_init(void)
00209 {
00210   uip_ipaddr_t rplmaddr;
00211   PRINTF("RPL started\n");
00212   default_instance = NULL;
00213 
00214   rpl_reset_periodic_timer();
00215   neighbor_info_subscribe(rpl_link_neighbor_callback);
00216 
00217   /* add rpl multicast address */
00218   uip_create_linklocal_rplnodes_mcast(&rplmaddr);
00219   uip_ds6_maddr_add(&rplmaddr);
00220 
00221 #if RPL_CONF_STATS
00222   memset(&rpl_stats, 0, sizeof(rpl_stats));
00223 #endif
00224 }
00225 /************************************************************************/