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 IETF ROLL RPL.
00038  *
00039  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
00040  */
00041 
00042 #include "net/uip.h"
00043 #include "net/tcpip.h"
00044 #include "net/uip-ds6.h"
00045 #include "net/rpl/rpl-private.h"
00046 #include "net/neighbor-info.h"
00047 
00048 #define DEBUG DEBUG_NONE
00049 #include "net/uip-debug.h"
00050 
00051 #include <limits.h>
00052 #include <string.h>
00053 
00054 #if RPL_CONF_STATS
00055 rpl_stats_t rpl_stats;
00056 #endif
00057 
00058 /************************************************************************/
00059 extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
00060 /************************************************************************/
00061 void
00062 rpl_purge_routes(void)
00063 {
00064   int i;
00065 
00066   for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
00067     if(uip_ds6_routing_table[i].isused) {
00068       if(uip_ds6_routing_table[i].state.lifetime <= 1) {
00069         uip_ds6_route_rm(&uip_ds6_routing_table[i]);
00070       } else {
00071         uip_ds6_routing_table[i].state.lifetime--;
00072       }
00073     }
00074   }
00075 }
00076 /************************************************************************/
00077 void
00078 rpl_remove_routes(rpl_dag_t *dag)
00079 {
00080   int i;
00081 
00082   for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
00083     if(uip_ds6_routing_table[i].state.dag == dag) {
00084       uip_ds6_route_rm(&uip_ds6_routing_table[i]);
00085     }
00086   }
00087 }
00088 /************************************************************************/
00089 uip_ds6_route_t *
00090 rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
00091               uip_ipaddr_t *next_hop)
00092 {
00093   uip_ds6_route_t *rep;
00094 
00095   rep = uip_ds6_route_lookup(prefix);
00096   if(rep == NULL) {
00097     if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop, 0)) == NULL) {
00098       PRINTF("RPL: No space for more route entries\n");
00099       return NULL;
00100     }
00101   } else {
00102     PRINTF("RPL: Updated the next hop for prefix ");
00103     PRINT6ADDR(prefix);
00104     PRINTF(" to ");
00105     PRINT6ADDR(next_hop);
00106     PRINTF("\n");
00107     uip_ipaddr_copy(&rep->nexthop, next_hop);
00108   }
00109   rep->state.dag = dag;
00110   rep->state.lifetime = DEFAULT_ROUTE_LIFETIME;
00111   rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL;
00112 
00113   PRINTF("RPL: Added a route to ");
00114   PRINT6ADDR(prefix);
00115   PRINTF("/%d via ", prefix_len);
00116   PRINT6ADDR(next_hop);
00117   PRINTF("\n");
00118 
00119   return rep;
00120 }
00121 /************************************************************************/
00122 static void
00123 rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
00124 {
00125   uip_ipaddr_t ipaddr;
00126   rpl_dag_t *dag;
00127   rpl_parent_t *parent;
00128 
00129   uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
00130   uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
00131   PRINTF("RPL: Neighbor ");
00132   PRINT6ADDR(&ipaddr);
00133   PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
00134 
00135   dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
00136   if(dag == NULL) {
00137     return;
00138   }
00139 
00140   parent = rpl_find_parent(dag, &ipaddr);
00141   if(parent == NULL) {
00142     if(!known) {
00143       PRINTF("RPL: Deleting routes installed by DAOs received from ");
00144       PRINT6ADDR(&ipaddr);
00145       PRINTF("\n");
00146       uip_ds6_route_rm_by_nexthop(&ipaddr);
00147     }
00148     return;
00149   }
00150 
00151   /* Trigger DAG rank recalculation. */
00152   parent->updated = 1;
00153 
00154   parent->link_metric = etx;
00155 
00156   if(dag->of->parent_state_callback != NULL) {
00157     dag->of->parent_state_callback(parent, known, etx);
00158   }
00159 
00160   if(!known) {
00161     PRINTF("RPL: Removing parent ");
00162     PRINT6ADDR(&parent->addr);
00163     PRINTF(" because of bad connectivity (ETX %d)\n", etx);
00164     parent->rank = INFINITE_RANK;
00165   }
00166 }
00167 /************************************************************************/
00168 void
00169 rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
00170 {
00171   rpl_dag_t *dag;
00172   rpl_parent_t *p;
00173 
00174   /* This only handles one DODAG - if multiple we need to check all */
00175   dag = rpl_get_dag(RPL_ANY_INSTANCE);
00176   if(dag == NULL) {
00177     return;
00178   }
00179 
00180   /* if this is our default route then clean the dag->def_route state */
00181   if(dag->def_route != NULL &&
00182      uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) {
00183     dag->def_route = NULL;
00184   }
00185 
00186   if(!nbr->isused) {
00187     PRINTF("RPL: Removing neighbor ");
00188     PRINT6ADDR(&nbr->ipaddr);
00189     PRINTF("\n");
00190     p = rpl_find_parent(dag, &nbr->ipaddr);
00191     if(p != NULL) {
00192       p->rank = INFINITE_RANK;
00193       /* Trigger DAG rank recalculation. */
00194       p->updated = 1;
00195     }
00196   }
00197 }
00198 /************************************************************************/
00199 void
00200 rpl_init(void)
00201 {
00202   uip_ipaddr_t rplmaddr;
00203   PRINTF("RPL started\n");
00204 
00205   rpl_reset_periodic_timer();
00206   neighbor_info_subscribe(rpl_link_neighbor_callback);
00207 
00208   /* add rpl multicast address */
00209   uip_create_linklocal_rplnodes_mcast(&rplmaddr);
00210   uip_ds6_maddr_add(&rplmaddr);
00211 
00212 #if RPL_CONF_STATS
00213   memset(&rpl_stats, 0, sizeof(rpl_stats));
00214 #endif
00215 }
00216 /************************************************************************/

Generated on Mon Apr 11 14:23:31 2011 for Contiki 2.5 by  doxygen 1.6.1