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(curr_instance.dag.urgent_probing_target == nbr) {
105  curr_instance.dag.urgent_probing_target = NULL;
106  }
107  /* Link stats were updated, and we need to update our internal state.
108  Updating from here is unsafe; postpone */
109  LOG_INFO("packet sent to ");
110  LOG_INFO_LLADDR(addr);
111  LOG_INFO_(", status %u, tx %u, new link metric %u\n", status, numtx, rpl_neighbor_get_link_metric(nbr));
113  }
114  }
115 }
116 /*---------------------------------------------------------------------------*/
117 int
119 {
120  return curr_instance.used && curr_instance.dag.state >= DAG_JOINED;
121 }
122 /*---------------------------------------------------------------------------*/
123 int
125 {
126  return curr_instance.used && curr_instance.dag.state == DAG_REACHABLE;
127 }
128 /*---------------------------------------------------------------------------*/
129 static void
130 set_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix)
131 {
132  memset(ipaddr, 0, sizeof(uip_ipaddr_t));
133  memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8);
135 }
136 /*---------------------------------------------------------------------------*/
137 void
139 {
140  uip_ipaddr_t ipaddr;
141  uip_ds6_addr_t *rep;
142  set_ip_from_prefix(&ipaddr, last_prefix);
143  rep = uip_ds6_addr_lookup(&ipaddr);
144  if(rep != NULL) {
145  LOG_INFO("removing global IP address ");
146  LOG_INFO_6ADDR(&ipaddr);
147  LOG_INFO_("\n");
148  uip_ds6_addr_rm(rep);
149  }
150  curr_instance.dag.prefix_info.length = 0;
151 }
152 /*---------------------------------------------------------------------------*/
153 int
154 rpl_set_prefix_from_addr(uip_ipaddr_t *addr, unsigned len, uint8_t flags)
155 {
156  uip_ipaddr_t ipaddr;
157 
158  if(addr == NULL || len == 0 || len > 128 || !(flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
159  LOG_WARN("prefix not included, not-supported or invalid\n");
160  return 0;
161  }
162 
163  /* Try and initialize prefix */
164  memset(&curr_instance.dag.prefix_info.prefix, 0, sizeof(rpl_prefix_t));
165  memcpy(&curr_instance.dag.prefix_info.prefix, addr, (len + 7) / 8);
166  curr_instance.dag.prefix_info.length = len;
167  curr_instance.dag.prefix_info.lifetime = RPL_ROUTE_INFINITE_LIFETIME;
168  curr_instance.dag.prefix_info.flags = flags;
169 
170  /* Add global address if not already there */
171  set_ip_from_prefix(&ipaddr, &curr_instance.dag.prefix_info);
172  if(uip_ds6_addr_lookup(&ipaddr) == NULL) {
173  LOG_INFO("adding global IP address ");
174  LOG_INFO_6ADDR(&ipaddr);
175  LOG_INFO_("\n");
176  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
177  }
178  return 1;
179 }
180 /*---------------------------------------------------------------------------*/
181 int
183 {
184  if(prefix != NULL && rpl_set_prefix_from_addr(&prefix->prefix, prefix->length, prefix->flags)) {
185  curr_instance.dag.prefix_info.lifetime = prefix->lifetime;
186  return 1;
187  }
188  return 0;
189 }
190 /*---------------------------------------------------------------------------*/
191 static void
192 init(void)
193 {
194  LOG_INFO("initializing\n");
195 
196  /* Initialize multicast address and register it */
197  uip_create_linklocal_rplnodes_mcast(&rpl_multicast_addr);
198  uip_ds6_maddr_add(&rpl_multicast_addr);
199 
200  rpl_dag_init();
202  rpl_timers_init();
203  rpl_icmp6_init();
204 
205  uip_sr_init();
206 }
207 /*---------------------------------------------------------------------------*/
208 static int
209 get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node)
210 {
211  if(addr != NULL && node != NULL) {
212  memcpy(addr, &curr_instance.dag.dag_id, 8);
213  memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8);
214  return 1;
215  } else {
216  return 0;
217  }
218 }
219 /*---------------------------------------------------------------------------*/
220 static void
222 {
223  /* Nothing needs be done in non-storing mode */
224 }
225 /*---------------------------------------------------------------------------*/
226 static void
228 {
229  /* Do nothing. RPL-lite only supports non-storing mode, i.e. no routes */
230 }
231 /*---------------------------------------------------------------------------*/
232 void
233 rpl_set_leaf_only(uint8_t value)
234 {
235  rpl_leaf_only = value;
236 }
237 /*---------------------------------------------------------------------------*/
238 uint8_t
240 {
241  return rpl_leaf_only;
242 }
243 /*---------------------------------------------------------------------------*/
244 const struct routing_driver rpl_lite_driver = {
245  "RPL Lite",
246  init,
264  drop_route,
265 };
266 /*---------------------------------------------------------------------------*/
267 
268 /** @}*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
void rpl_ext_header_remove(void)
Removes all RPL extension headers.
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:95
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:115
int rpl_ext_header_hbh_update(int uip_ext_opt_offset)
Process and update the RPL hop-by-hop extension headers of the current uIP packet.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:116
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:233
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:174
void rpl_timers_init(void)
Initialize rpl-timers module.
Definition: rpl-timers.c:498
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:239
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:225
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:557
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:147
void(* init)(void)
Initialize the routing protocol.
Definition: routing.h:56
int rpl_set_prefix_from_addr(uip_ipaddr_t *addr, unsigned len, uint8_t flags)
Set prefix from an IPv6 address.
Definition: rpl.c:154
void rpl_timers_schedule_state_update(void)
Schedule a state update ASAP.
Definition: rpl-timers.c:556
int rpl_set_prefix(rpl_prefix_t *prefix)
Set prefix from an prefix data structure (from DIO)
Definition: rpl.c:182
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:168
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:124
void rpl_neighbor_init(void)
Initialize rpl-dag-neighbor module.
Definition: rpl-neighbor.c:452
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:84
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:341
const uip_ipaddr_t * rpl_get_global_address(void)
Get one of the node&#39;s global addresses.
Definition: rpl.c:71
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:90
#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:138
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:2023
Header file for the logging system
int rpl_has_joined(void)
Tells whether the node has joined a network or not.
Definition: rpl.c:118
The structure of a routing protocol driver.
Definition: routing.h:53
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:681
void rpl_dag_init(void)
Initializes rpl-dag module.
Definition: rpl-dag.c:142
rpl_nbr_t * rpl_neighbor_get_from_lladdr(uip_lladdr_t *addr)
Returns a neighbor from its link-layer address.
Definition: rpl-neighbor.c:210
int rpl_ext_header_srh_update(void)
Process and update SRH in-place, i.e.
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:69