Contiki 2.5
rpl.c
Go to the documentation of this file.
1 /**
2  * \addtogroup uip6
3  * @{
4  */
5 /*
6  * Copyright (c) 2009, Swedish Institute of Computer Science.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the Institute nor the names of its contributors
18  * may be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * This file is part of the Contiki operating system.
34  */
35 /**
36  * \file
37  * ContikiRPL, an implementation of IETF ROLL RPL.
38  *
39  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
40  */
41 
42 #include "net/uip.h"
43 #include "net/tcpip.h"
44 #include "net/uip-ds6.h"
45 #include "net/rpl/rpl-private.h"
46 #include "net/neighbor-info.h"
47 
48 #define DEBUG DEBUG_NONE
49 #include "net/uip-debug.h"
50 
51 #include <limits.h>
52 #include <string.h>
53 
54 #if RPL_CONF_STATS
55 rpl_stats_t rpl_stats;
56 #endif
57 
58 /************************************************************************/
59 extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
60 /************************************************************************/
61 void
62 rpl_purge_routes(void)
63 {
64  int i;
65 
66  for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
67  if(uip_ds6_routing_table[i].isused) {
68  if(uip_ds6_routing_table[i].state.lifetime <= 1) {
69  uip_ds6_route_rm(&uip_ds6_routing_table[i]);
70  } else {
71  uip_ds6_routing_table[i].state.lifetime--;
72  }
73  }
74  }
75 }
76 /************************************************************************/
77 void
78 rpl_remove_routes(rpl_dag_t *dag)
79 {
80  int i;
81 
82  for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
83  if(uip_ds6_routing_table[i].state.dag == dag) {
84  uip_ds6_route_rm(&uip_ds6_routing_table[i]);
85  }
86  }
87 }
88 /************************************************************************/
90 rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len,
91  uip_ipaddr_t *next_hop)
92 {
93  uip_ds6_route_t *rep;
94 
95  rep = uip_ds6_route_lookup(prefix);
96  if(rep == NULL) {
97  if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop, 0)) == NULL) {
98  PRINTF("RPL: No space for more route entries\n");
99  return NULL;
100  }
101  } else {
102  PRINTF("RPL: Updated the next hop for prefix ");
103  PRINT6ADDR(prefix);
104  PRINTF(" to ");
105  PRINT6ADDR(next_hop);
106  PRINTF("\n");
107  uip_ipaddr_copy(&rep->nexthop, next_hop);
108  }
109  rep->state.dag = dag;
110  rep->state.lifetime = RPL_LIFETIME(dag, dag->default_lifetime);
111  rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL;
112 
113  PRINTF("RPL: Added a route to ");
114  PRINT6ADDR(prefix);
115  PRINTF("/%d via ", prefix_len);
116  PRINT6ADDR(next_hop);
117  PRINTF("\n");
118 
119  return rep;
120 }
121 /************************************************************************/
122 static void
123 rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
124 {
125  uip_ipaddr_t ipaddr;
126  rpl_dag_t *dag;
127  rpl_parent_t *parent;
128 
129  uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
130  uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
131  PRINTF("RPL: Neighbor ");
132  PRINT6ADDR(&ipaddr);
133  PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));
134 
135  dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
136  if(dag == NULL) {
137  return;
138  }
139 
140  parent = rpl_find_parent(dag, &ipaddr);
141  if(parent == NULL) {
142  if(!known) {
143  PRINTF("RPL: Deleting routes installed by DAOs received from ");
144  PRINT6ADDR(&ipaddr);
145  PRINTF("\n");
146  uip_ds6_route_rm_by_nexthop(&ipaddr);
147  }
148  return;
149  }
150 
151  /* Trigger DAG rank recalculation. */
152  parent->updated = 1;
153 
154  parent->link_metric = etx;
155 
156  if(dag->of->parent_state_callback != NULL) {
157  dag->of->parent_state_callback(parent, known, etx);
158  }
159 
160  if(!known) {
161  PRINTF("RPL: Removing parent ");
162  PRINT6ADDR(&parent->addr);
163  PRINTF(" because of bad connectivity (ETX %d)\n", etx);
164  parent->rank = INFINITE_RANK;
165  }
166 }
167 /************************************************************************/
168 void
169 rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
170 {
171  rpl_dag_t *dag;
172  rpl_parent_t *p;
173 
174  /* This only handles one DODAG - if multiple we need to check all */
175  dag = rpl_get_dag(RPL_ANY_INSTANCE);
176  if(dag == NULL) {
177  return;
178  }
179 
180  /* if this is our default route then clean the dag->def_route state */
181  if(dag->def_route != NULL &&
182  uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) {
183  dag->def_route = NULL;
184  }
185 
186  if(!nbr->isused) {
187  PRINTF("RPL: Removing neighbor ");
188  PRINT6ADDR(&nbr->ipaddr);
189  PRINTF("\n");
190  p = rpl_find_parent(dag, &nbr->ipaddr);
191  if(p != NULL) {
192  p->rank = INFINITE_RANK;
193  /* Trigger DAG rank recalculation. */
194  p->updated = 1;
195  }
196  }
197 }
198 /************************************************************************/
199 void
200 rpl_init(void)
201 {
202  uip_ipaddr_t rplmaddr;
203  PRINTF("RPL started\n");
204 
205  rpl_reset_periodic_timer();
206  neighbor_info_subscribe(rpl_link_neighbor_callback);
207 
208  /* add rpl multicast address */
209  uip_create_linklocal_rplnodes_mcast(&rplmaddr);
210  uip_ds6_maddr_add(&rplmaddr);
211 
212 #if RPL_CONF_STATS
213  memset(&rpl_stats, 0, sizeof(rpl_stats));
214 #endif
215 }
216 /************************************************************************/