Contiki-NG
rpl.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \addtogroup rpl-lite
34  * @{
35  *
36  * \file
37  * ContikiRPL, an implementation of RPL: IPv6 Routing Protocol
38  * for Low-Power and Lossy Networks (IETF RFC 6550)
39  *
40  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
41  * Simon Duquennoy <simon.duquennoy@inria.fr>
42  */
43 
44 #include "net/routing/rpl-lite/rpl.h"
45 #include "net/routing/routing.h"
46 
47 /* Log configuration */
48 #include "sys/log.h"
49 #define LOG_MODULE "RPL"
50 #define LOG_LEVEL LOG_LEVEL_RPL
51 
52 uip_ipaddr_t rpl_multicast_addr;
53 static uint8_t rpl_leaf_only = RPL_DEFAULT_LEAF_ONLY;
54 
55 /*---------------------------------------------------------------------------*/
56 int
58 {
59  /* Check if we are comparing an initial value with an old value */
60  if(a > RPL_LOLLIPOP_CIRCULAR_REGION && b <= RPL_LOLLIPOP_CIRCULAR_REGION) {
61  return (RPL_LOLLIPOP_MAX_VALUE + 1 + b - a) > RPL_LOLLIPOP_SEQUENCE_WINDOWS;
62  }
63  /* Otherwise check if a > b and comparable => ok, or
64  if they have wrapped and are still comparable */
65  return (a > b && (a - b) < RPL_LOLLIPOP_SEQUENCE_WINDOWS) ||
66  (a < b && (b - a) > (RPL_LOLLIPOP_CIRCULAR_REGION + 1-
67  RPL_LOLLIPOP_SEQUENCE_WINDOWS));
68 }
69 /*---------------------------------------------------------------------------*/
70 const uip_ipaddr_t *
72 {
73  int i;
74  uint8_t state;
75  uip_ipaddr_t *ipaddr = NULL;
76  uip_ipaddr_t *prefix = NULL;
77  uint8_t prefix_length = 0;
78 
79  if(curr_instance.used && curr_instance.dag.prefix_info.length != 0) {
80  prefix = &curr_instance.dag.prefix_info.prefix;
81  prefix_length = curr_instance.dag.prefix_info.length;
82  }
83 
84  for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
85  state = uip_ds6_if.addr_list[i].state;
86  if(uip_ds6_if.addr_list[i].isused &&
87  state == ADDR_PREFERRED &&
88  !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr) &&
89  (prefix == NULL || uip_ipaddr_prefixcmp(prefix, &uip_ds6_if.addr_list[i].ipaddr, prefix_length))) {
90  ipaddr = &uip_ds6_if.addr_list[i].ipaddr;
91  }
92  }
93  return ipaddr;
94 }
95 /*---------------------------------------------------------------------------*/
96 void
97 rpl_link_callback(const linkaddr_t *addr, int status, int numtx)
98 {
99  if(curr_instance.used == 1 ) {
100  rpl_nbr_t *nbr = rpl_neighbor_get_from_lladdr((uip_lladdr_t *)addr);
101  if(nbr != NULL) {
102  /* If this is the neighbor we were probing urgently, mark urgent
103  probing as done */
104 #if RPL_WITH_PROBING
105  if(curr_instance.dag.urgent_probing_target == nbr) {
106  curr_instance.dag.urgent_probing_target = NULL;
107  }
108 #endif
109  /* Link stats were updated, and we need to update our internal state.
110  Updating from here is unsafe; postpone */
111  LOG_INFO("packet sent to ");
112  LOG_INFO_LLADDR(addr);
113  LOG_INFO_(", status %u, tx %u, new link metric %u\n", status, numtx, rpl_neighbor_get_link_metric(nbr));
115  }
116  }
117 }
118 /*---------------------------------------------------------------------------*/
119 int
121 {
122  return curr_instance.used && curr_instance.dag.state >= DAG_JOINED;
123 }
124 /*---------------------------------------------------------------------------*/
125 int
127 {
128  return curr_instance.used && curr_instance.dag.state == DAG_REACHABLE;
129 }
130 /*---------------------------------------------------------------------------*/
131 static void
132 set_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix)
133 {
134  memset(ipaddr, 0, sizeof(uip_ipaddr_t));
135  memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8);
137 }
138 /*---------------------------------------------------------------------------*/
139 void
141 {
142  uip_ipaddr_t ipaddr;
143  uip_ds6_addr_t *rep;
144  set_ip_from_prefix(&ipaddr, last_prefix);
145  rep = uip_ds6_addr_lookup(&ipaddr);
146  if(rep != NULL) {
147  LOG_INFO("removing global IP address ");
148  LOG_INFO_6ADDR(&ipaddr);
149  LOG_INFO_("\n");
150  uip_ds6_addr_rm(rep);
151  }
152  curr_instance.dag.prefix_info.length = 0;
153 }
154 /*---------------------------------------------------------------------------*/
155 int
156 rpl_set_prefix_from_addr(uip_ipaddr_t *addr, unsigned len, uint8_t flags)
157 {
158  uip_ipaddr_t ipaddr;
159 
160  if(addr == NULL || len == 0 || len > 128 || !(flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
161  LOG_WARN("prefix not included, not-supported or invalid\n");
162  return 0;
163  }
164 
165  /* Try and initialize prefix */
166  memset(&curr_instance.dag.prefix_info.prefix, 0, sizeof(rpl_prefix_t));
167  memcpy(&curr_instance.dag.prefix_info.prefix, addr, (len + 7) / 8);
168  curr_instance.dag.prefix_info.length = len;
169  curr_instance.dag.prefix_info.lifetime = RPL_ROUTE_INFINITE_LIFETIME;
170  curr_instance.dag.prefix_info.flags = flags;
171 
172  /* Add global address if not already there */
173  set_ip_from_prefix(&ipaddr, &curr_instance.dag.prefix_info);
174  if(uip_ds6_addr_lookup(&ipaddr) == NULL) {
175  LOG_INFO("adding global IP address ");
176  LOG_INFO_6ADDR(&ipaddr);
177  LOG_INFO_("\n");
178  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
179  }
180  return 1;
181 }
182 /*---------------------------------------------------------------------------*/
183 int
185 {
186  if(prefix != NULL && rpl_set_prefix_from_addr(&prefix->prefix, prefix->length, prefix->flags)) {
187  curr_instance.dag.prefix_info.lifetime = prefix->lifetime;
188  return 1;
189  }
190  return 0;
191 }
192 /*---------------------------------------------------------------------------*/
193 static void
194 init(void)
195 {
196  LOG_INFO("initializing\n");
197 
198  /* Initialize multicast address and register it */
199  uip_create_linklocal_rplnodes_mcast(&rpl_multicast_addr);
200  uip_ds6_maddr_add(&rpl_multicast_addr);
201 
202  rpl_dag_init();
204  rpl_timers_init();
205  rpl_icmp6_init();
206 
207  uip_sr_init();
208 }
209 /*---------------------------------------------------------------------------*/
210 static int
211 get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node)
212 {
213  if(addr != NULL && node != NULL) {
214  memcpy(addr, &curr_instance.dag.dag_id, 8);
215  memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8);
216  return 1;
217  } else {
218  return 0;
219  }
220 }
221 /*---------------------------------------------------------------------------*/
222 static void
224 {
225  /* Nothing needs be done in non-storing mode */
226 }
227 /*---------------------------------------------------------------------------*/
228 static void
230 {
231  /* Do nothing. RPL-lite only supports non-storing mode, i.e. no routes */
232 }
233 /*---------------------------------------------------------------------------*/
234 void
235 rpl_set_leaf_only(uint8_t value)
236 {
237  rpl_leaf_only = value;
238 }
239 /*---------------------------------------------------------------------------*/
240 uint8_t
242 {
243  return rpl_leaf_only;
244 }
245 /*---------------------------------------------------------------------------*/
246 const struct routing_driver rpl_lite_driver = {
247  "RPL Lite",
248  init,
266  drop_route,
267 };
268 /*---------------------------------------------------------------------------*/
269 
270 /** @}*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
void rpl_link_callback(const linkaddr_t *addr, int status, int numtx)
Called by lower layers after every packet transmission.
Definition: rpl.c:257
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
int rpl_dag_root_start(void)
Set the node as root and start a DAG.
Definition: rpl-dag-root.c:98
void rpl_dag_poison_and_leave(void)
Start poisoning and leave the DAG after a delay.
Definition: rpl-dag.c:131
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
int rpl_lollipop_greater_than(int a, int b)
Greater-than function for a lollipop counter.
Definition: rpl.c:57
void rpl_set_leaf_only(uint8_t value)
Changes the value of the rpl_leaf_only flag, which determines if a node acts only as a leaf in the ne...
Definition: rpl.c:235
void rpl_global_repair(const char *str)
Triggers a RPL global repair.
Definition: rpl-dag.c:204
void(* drop_route)(uip_ds6_route_t *route)
Called by uIP if it has decided to drop a route because.
Definition: routing.h:184
void rpl_timers_init(void)
Initialize rpl-timers module.
Definition: rpl-timers.c:499
int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
Look for next hop from SRH of current uIP packet.
uint8_t rpl_get_leaf_only(void)
Get the value of the rpl_leaf_only flag.
Definition: rpl.c:241
void uip_sr_init(void)
Initialize this module.
Definition: uip-sr.c:186
uint16_t rpl_neighbor_get_link_metric(rpl_nbr_t *nbr)
Returns a neighbor&#39;s link metric.
Definition: rpl-neighbor.c:228
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:576
RPL prefix information.
Definition: rpl.h:126
int rpl_ext_header_update(void)
Adds/updates all RPL extension headers to current uIP packet.
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
Definition: rpl-dag-root.c:152
int rpl_ext_header_hbh_update(uint8_t *ext_buf, int opt_offset)
Process and update the RPL hop-by-hop extension headers of the current uIP packet.
void(* init)(void)
Initialize the routing protocol.
Definition: routing.h:63
int rpl_set_prefix_from_addr(uip_ipaddr_t *addr, unsigned len, uint8_t flags)
Set prefix from an IPv6 address.
Definition: rpl.c:156
void rpl_timers_schedule_state_update(void)
Schedule a state update ASAP.
Definition: rpl-timers.c:557
int rpl_set_prefix(rpl_prefix_t *prefix)
Set prefix from an prefix data structure (from DIO)
Definition: rpl.c:184
An entry in the routing table.
void(* neighbor_state_changed)(uip_ds6_nbr_t *nbr)
Called by uIP to notify addition/removal of IPv6 neighbor entries.
Definition: routing.h:178
int rpl_is_reachable(void)
Get the RPL&#39;s best guess on if we are reachable via have downward route or not.
Definition: rpl.c:126
void rpl_neighbor_init(void)
Initialize rpl-dag-neighbor module.
Definition: rpl-neighbor.c:456
void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid)
Set a prefix in case the node is later set as dag root.
Definition: rpl-dag-root.c:87
Routing driver header file
All information related to a RPL neighbor.
Definition: rpl-types.h:136
Unicast address structure.
Definition: uip-ds6.h:204
uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
Add a unicast address to the interface.
Definition: uip-ds6.c:360
const uip_ipaddr_t * rpl_get_global_address(void)
Get one of the node&#39;s global addresses.
Definition: rpl.c:71
bool rpl_ext_header_remove(void)
Removes all RPL extension headers.
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:75
int rpl_dag_get_root_ipaddr(uip_ipaddr_t *ipaddr)
Returns the IPv6 address of the RPL DAG root, if any.
Definition: rpl-dag.c:89
int(* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node)
Returns the global IPv6 address of a source routing node.
Definition: routing.h:97
#define uip_create_linklocal_rplnodes_mcast(addr)
Set IP address addr to the link-local, all-rpl-nodes multicast address.
Definition: rpl-types.h:54
void rpl_local_repair(const char *str)
Triggers a RPL local repair.
Definition: rpl-dag.c:238
void rpl_reset_prefix(rpl_prefix_t *last_prefix)
Removes current prefx.
Definition: rpl.c:140
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:1877
Header file for the logging system
int rpl_has_joined(void)
Tells whether the node has joined a network or not.
Definition: rpl.c:120
The structure of a routing protocol driver.
Definition: routing.h:60
A node in a source routing graph, stored at the root and representing all child-parent relationship...
Definition: uip-sr.h:92
void rpl_icmp6_init()
Initializes rpl-icmp6 module, registers ICMPv6 handlers for all RPL ICMPv6 messages: DIO...
Definition: rpl-icmp6.c:677
void rpl_dag_init(void)
Initializes rpl-dag module.
Definition: rpl-dag.c:143
rpl_nbr_t * rpl_neighbor_get_from_lladdr(uip_lladdr_t *addr)
Returns a neighbor from its link-layer address.
Definition: rpl-neighbor.c:213
int rpl_ext_header_srh_update(void)
Process and update SRH in-place, i.e.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
Definition: uip-ds6-nbr.h:105