49#include "net/routing/rpl-classic/rpl-private.h"
50#include "net/routing/rpl-classic/rpl-dag-root.h"
58#define LOG_MODULE "RPL"
59#define LOG_LEVEL LOG_LEVEL_RPL
65static enum rpl_mode mode = RPL_MODE_MESH;
76 enum rpl_mode oldmode = mode;
80 if(m == RPL_MODE_MESH) {
88 LOG_DBG(
"rpl_set_mode: switching to mesh mode\n");
91 if(default_instance != NULL) {
92 rpl_schedule_dao_immediately(default_instance);
94 }
else if(m == RPL_MODE_FEATHER) {
96 LOG_INFO(
"rpl_set_mode: switching to feather mode\n");
97 if(default_instance != NULL) {
98 LOG_INFO(
"rpl_set_mode: RPL sending DAO with zero lifetime\n");
99 if(default_instance->current_dag != NULL) {
100 dao_output(default_instance->current_dag->preferred_parent,
103 rpl_cancel_dao(default_instance);
105 LOG_INFO(
"rpl_set_mode: no default instance\n");
117rpl_purge_routes(
void)
122#if RPL_WITH_MULTICAST
127 r = uip_ds6_route_head();
130 if(r->state.lifetime >= 1 &&
131 r->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) {
139 r = uip_ds6_route_next(r);
143 r = uip_ds6_route_head();
146 if(r->state.lifetime < 1) {
154 r = uip_ds6_route_head();
155 LOG_INFO(
"No more routes to ");
156 LOG_INFO_6ADDR(&prefix);
157 dag = default_instance->current_dag;
160 if(dag->rank != ROOT_RANK(default_instance)) {
161 LOG_INFO_(
" -> generate No-Path DAO\n");
162 dao_output_target(dag->preferred_parent, &prefix, RPL_ZERO_LIFETIME);
169 r = uip_ds6_route_next(r);
173#if RPL_WITH_MULTICAST
176 while(mcast_route != NULL) {
192#if RPL_WITH_MULTICAST
196 r = uip_ds6_route_head();
199 if(r->state.dag == dag) {
201 r = uip_ds6_route_head();
203 r = uip_ds6_route_next(r);
207#if RPL_WITH_MULTICAST
210 while(mcast_route != NULL) {
211 if(mcast_route->
dag == dag) {
222rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop,
rpl_dag_t *dag)
226 r = uip_ds6_route_head();
229 if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), nexthop) &&
230 r->state.dag == dag) {
231 r->state.lifetime = 0;
233 r = uip_ds6_route_next(r);
235 LOG_ANNOTATE(
"#L %u 0\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
239rpl_add_route(
rpl_dag_t *dag, uip_ipaddr_t *prefix,
int prefix_len,
240 uip_ipaddr_t *next_hop)
244 if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop)) == NULL) {
245 LOG_ERR(
"No space for more route entries\n");
249 rep->state.dag = dag;
250 rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime);
253 RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep);
255 LOG_INFO(
"Added a route to ");
256 LOG_INFO_6ADDR(prefix);
257 LOG_INFO_(
"/%d via ", prefix_len);
258 LOG_INFO_6ADDR(next_hop);
268 rpl_parent_t *parent;
275 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
276 if(instance->used == 1) {
277 parent = rpl_find_parent_any_dag(instance, &
ipaddr);
282 if(instance->urgent_probing_target == parent) {
283 instance->urgent_probing_target = NULL;
287 LOG_DBG(
"rpl_link_callback triggering update\n");
288 parent->flags |= RPL_PARENT_FLAG_UPDATED;
301 LOG_DBG(
"Neighbor state changed for ");
302 LOG_DBG_6ADDR(&
nbr->ipaddr);
303#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA
304 LOG_DBG_(
", nscount=%u, state=%u\n",
nbr->nscount,
nbr->state);
306 LOG_DBG_(
", state=%u\n",
nbr->state);
308 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
309 if(instance->used == 1) {
310 p = rpl_find_parent_any_dag(instance, &
nbr->ipaddr);
312 p->rank = RPL_INFINITE_RANK;
314 LOG_DBG(
"rpl_ipv6_neighbor_callback infinite rank\n");
315 p->flags |= RPL_PARENT_FLAG_UPDATED;
328 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
329 instance < end; ++instance) {
331 for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
332 if(instance->dag_table[i].used) {
333 if(instance->dag_table[i].lifetime == 0) {
334 if(!instance->dag_table[i].joined) {
335 LOG_INFO(
"Removing dag ");
336 LOG_INFO_6ADDR(&instance->dag_table[i].dag_id);
338 rpl_free_dag(&instance->dag_table[i]);
341 instance->dag_table[i].lifetime--;
352 uip_ipaddr_t rplmaddr;
354 LOG_INFO(
"rpl-classic started\n");
355 default_instance = NULL;
358 rpl_reset_periodic_timer();
359 rpl_icmp6_register_handlers();
362 uip_create_linklocal_rplnodes_mcast(&rplmaddr);
363 uip_ds6_maddr_add(&rplmaddr);
366 memset(&rpl_stats, 0,
sizeof(rpl_stats));
369#if RPL_WITH_NON_STORING
377 if(
addr != NULL && node != NULL) {
379 memcpy(((
unsigned char *)
addr) + 8, &node->link_identifier, 8);
387global_repair(
const char *str)
390 if(dag != NULL && dag->instance != NULL) {
391 rpl_repair_root(dag->instance->instance_id);
396local_repair(
const char *str)
400 rpl_local_repair(dag->instance);
411 if(dag != NULL && dag->instance != NULL) {
412 rpl_repair_root(dag->instance->instance_id);
419 LOG_ERR(
"leave_network not supported in RPL Classic\n");
423get_root_ipaddr(uip_ipaddr_t *
ipaddr)
427 dag = rpl_get_any_dag();
428 if(dag != NULL &&
ipaddr != NULL) {
444 return RPL_LEAF_ONLY ? 1 : 0;
450 rpl_dag_root_set_prefix,
452 rpl_dag_root_is_root,
460 rpl_ext_header_remove,
461 rpl_ext_header_update,
462 rpl_ext_header_hbh_update,
463 rpl_ext_header_srh_update,
464 rpl_ext_header_srh_get_next_hop,
466 rpl_ipv6_neighbor_callback,
static void * list_item_next(const void *item)
Get the next item following this item.
uip_mcast6_route_t * uip_mcast6_route_list_head(void)
Retrieve a pointer to the start of the multicast routes list.
void uip_mcast6_route_rm(uip_mcast6_route_t *route)
Remove a multicast route.
int rpl_has_downward_route(void)
Get the RPL's best guess on if we have downward route or not.
enum rpl_mode rpl_set_mode(enum rpl_mode m)
Set the RPL mode.
int rpl_has_joined(void)
Tells whether the node has joined a network or not.
void uip_sr_init(void)
Initialize this module.
uint8_t rpl_is_in_leaf_mode(void)
Tells whether the protocol is in leaf mode.
enum rpl_mode rpl_get_mode(void)
Get the RPL mode.
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
void rpl_link_callback(const linkaddr_t *addr, int status, int numtx)
Called by lower layers after every packet transmission.
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Header file for the logging system.
Routing driver header file.
The structure of a routing protocol driver.
void(* init)(void)
Initialize the routing protocol.
int(* get_root_ipaddr)(uip_ipaddr_t *ipaddr)
Returns the IPv6 address of the network root, if any.
void(* leave_network)(void)
Leave the network the node is part of.
void(* global_repair)(const char *str)
Triggers a global topology repair.
int(* get_sr_node_ipaddr)(uip_ipaddr_t *ipaddr, const uip_sr_node_t *node)
Returns the global IPv6 address of a source routing node.
void(* local_repair)(const char *str)
Triggers a RPL local topology repair.
void(* drop_route)(uip_ds6_route_t *route)
Called by uIP if it has decided to drop a route because.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
An entry in the routing table.
An entry in the multicast routing table.
void * dag
Pointer to an rpl_dag_t struct.
uint32_t lifetime
Entry lifetime seconds.
A node in a source routing graph, stored at the root and representing all child-parent relationship.
Header for the Contiki/uIP interface.
Header file for IPv6-related data structures.
Header file for ICMPv6 message and error handing (RFC 4443)
This header file contains configuration directives for uIPv6 multicast support.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for the uIP TCP/IP stack.