49 #include "net/rpl/rpl-private.h"
53 #define DEBUG DEBUG_NONE
60 rpl_stats_t rpl_stats;
63 static enum rpl_mode mode = RPL_MODE_MESH;
74 enum rpl_mode oldmode = mode;
78 if(m == RPL_MODE_MESH) {
84 PRINTF(
"RPL: switching to mesh mode\n");
87 if(default_instance !=
NULL) {
88 rpl_schedule_dao_immediately(default_instance);
90 }
else if(m == RPL_MODE_FEATHER) {
92 PRINTF(
"RPL: switching to feather mode\n");
93 if(default_instance !=
NULL) {
94 PRINTF(
"rpl_set_mode: RPL sending DAO with zero lifetime\n");
95 if(default_instance->current_dag !=
NULL) {
96 dao_output(default_instance->current_dag->preferred_parent, RPL_ZERO_LIFETIME);
98 rpl_cancel_dao(default_instance);
100 PRINTF(
"rpl_set_mode: no default instance\n");
112 rpl_purge_routes(
void)
117 #if RPL_CONF_MULTICAST
122 r = uip_ds6_route_head();
125 if(r->state.lifetime >= 1) {
133 r = uip_ds6_route_next(r);
137 r = uip_ds6_route_head();
140 if(r->state.lifetime < 1) {
145 r = uip_ds6_route_head();
146 PRINTF(
"No more routes to ");
148 dag = default_instance->current_dag;
150 if(dag->rank != ROOT_RANK(default_instance)) {
151 PRINTF(
" -> generate No-Path DAO\n");
152 dao_output_target(dag->preferred_parent, &prefix, RPL_ZERO_LIFETIME);
158 r = uip_ds6_route_next(r);
162 #if RPL_CONF_MULTICAST
165 while(mcast_route !=
NULL) {
178 rpl_remove_routes(rpl_dag_t *dag)
181 #if RPL_CONF_MULTICAST
185 r = uip_ds6_route_head();
188 if(r->state.dag == dag) {
190 r = uip_ds6_route_head();
192 r = uip_ds6_route_next(r);
196 #if RPL_CONF_MULTICAST
199 while(mcast_route !=
NULL) {
200 if(mcast_route->
dag == dag) {
211 rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag)
215 r = uip_ds6_route_head();
218 if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), nexthop) &&
219 r->state.dag == dag) {
220 r->state.lifetime = 0;
222 r = uip_ds6_route_next(r);
224 ANNOTATE(
"#L %u 0\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
228 rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix,
int prefix_len,
229 uip_ipaddr_t *next_hop)
233 if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop)) ==
NULL) {
234 PRINTF(
"RPL: No space for more route entries\n");
238 rep->state.dag = dag;
239 rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime);
241 RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep);
243 PRINTF(
"RPL: Added a route to ");
245 PRINTF(
"/%d via ", prefix_len);
246 PRINT6ADDR(next_hop);
253 rpl_link_neighbor_callback(
const linkaddr_t *
addr,
int status,
int numtx)
256 rpl_parent_t *parent;
257 rpl_instance_t *instance;
263 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
264 if(instance->used == 1 ) {
265 parent = rpl_find_parent_any_dag(instance, &ipaddr);
268 PRINTF(
"RPL: rpl_link_neighbor_callback triggering update\n");
269 parent->flags |= RPL_PARENT_FLAG_UPDATED;
279 rpl_instance_t *instance;
282 PRINTF(
"RPL: Neighbor state changed for ");
283 PRINT6ADDR(&nbr->ipaddr);
284 #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA
285 PRINTF(
", nscount=%u, state=%u\n", nbr->nscount, nbr->state);
287 PRINTF(
", state=%u\n", nbr->state);
289 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
290 if(instance->used == 1 ) {
291 p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
293 p->rank = INFINITE_RANK;
295 PRINTF(
"RPL: rpl_ipv6_neighbor_callback infinite rank\n");
296 p->flags |= RPL_PARENT_FLAG_UPDATED;
305 rpl_instance_t *instance;
309 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
310 instance < end; ++instance) {
312 for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
313 if(instance->dag_table[i].used) {
314 if(instance->dag_table[i].lifetime == 0) {
315 if(!instance->dag_table[i].joined) {
316 PRINTF(
"Removing dag ");
317 PRINT6ADDR(&instance->dag_table[i].dag_id);
319 rpl_free_dag(&instance->dag_table[i]);
322 instance->dag_table[i].lifetime--;
333 uip_ipaddr_t rplmaddr;
334 PRINTF(
"RPL started\n");
335 default_instance =
NULL;
338 rpl_reset_periodic_timer();
339 rpl_icmp6_register_handlers();
342 uip_create_linklocal_rplnodes_mcast(&rplmaddr);
343 uip_ds6_maddr_add(&rplmaddr);
346 memset(&rpl_stats, 0,
sizeof(rpl_stats));
349 #if RPL_WITH_NON_STORING
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
void * dag
Pointer to an rpl_dag_t struct.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Header file for IPv6-related data structures.
void * list_item_next(void *item)
Get the next item following this item.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
An entry in the nbr cache.
uip_mcast6_route_t * uip_mcast6_route_list_head(void)
Retrieve a pointer to the start of the multicast routes list.
Header for the Contiki/uIP interface.
void uip_mcast6_route_rm(uip_mcast6_route_t *route)
Remove a multicast route.
This header file contains configuration directives for uIPv6 multicast support.
#define NULL
The null pointer.
Header file for ICMPv6 message and error handing (RFC 4443)
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
enum rpl_mode rpl_set_mode(enum rpl_mode m)
Set the RPL mode.
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
An entry in the multicast routing table.
Header file for the uIP TCP/IP stack.
A set of debugging macros for the IP stack
enum rpl_mode rpl_get_mode(void)
Get the RPL mode.
RPL non-storing mode specific functions.
An entry in the routing table.
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
uint32_t lifetime
Entry lifetime seconds.