diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index e83e790bc..e103d65f9 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -38,6 +38,7 @@ * Logic for Directed Acyclic Graphs in RPL. * * \author Joakim Eriksson , Nicolas Tsiftes + * Contributors: George Oikonomou (multicast) */ @@ -46,6 +47,7 @@ #include "net/ip/uip.h" #include "net/ipv6/uip-nd6.h" #include "net/nbr-table.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include "lib/list.h" #include "lib/memb.h" #include "sys/ctimer.h" @@ -1147,7 +1149,13 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; +#if RPL_CONF_MULTICAST + /* If the root is advertising MOP 2 but we support MOP 3 we can still join + * In that scenario, we suppress DAOs for multicast targets */ + if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) { +#else if(dio->mop != RPL_MOP_DEFAULT) { +#endif PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); return; } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index c7f950cbb..c1cc6060b 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -40,6 +40,7 @@ * \author Joakim Eriksson , Nicolas Tsiftes * Contributors: Niclas Finne , Joel Hoglund , * Mathieu Pouillot + * George Oikonomou (multicast) */ #include "net/ip/tcpip.h" @@ -49,6 +50,7 @@ #include "net/ipv6/uip-icmp6.h" #include "net/rpl/rpl-private.h" #include "net/packetbuf.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include #include @@ -86,6 +88,9 @@ static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; extern rpl_of_t RPL_OF; +#if RPL_CONF_MULTICAST +static uip_mcast6_route_t *mcast_group; +#endif /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -682,6 +687,17 @@ dao_input(void) PRINT6ADDR(&prefix); PRINTF("\n"); +#if RPL_CONF_MULTICAST + if(uip_is_addr_mcast_global(&prefix)) { + mcast_group = uip_mcast6_route_add(&prefix); + if(mcast_group) { + mcast_group->dag = dag; + mcast_group->lifetime = RPL_LIFETIME(instance, lifetime); + } + goto fwd_dao; + } +#endif + rep = uip_ds6_route_lookup(&prefix); if(lifetime == RPL_ZERO_LIFETIME) { @@ -752,6 +768,10 @@ dao_input(void) rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.learned_from = learned_from; +#if RPL_CONF_MULTICAST +fwd_dao: +#endif + if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index acabda4b7..0df8a91ca 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -44,6 +44,7 @@ #include "sys/clock.h" #include "sys/ctimer.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/multicast/uip-mcast6.h" /*---------------------------------------------------------------------------*/ /** \brief Is IPv6 address addr the link-local, all-RPL-nodes @@ -177,8 +178,24 @@ #ifdef RPL_CONF_MOP #define RPL_MOP_DEFAULT RPL_CONF_MOP +#else /* RPL_CONF_MOP */ +#if RPL_CONF_MULTICAST +#define RPL_MOP_DEFAULT RPL_MOP_STORING_MULTICAST #else #define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST +#endif /* UIP_IPV6_MULTICAST_RPL */ +#endif /* RPL_CONF_MOP */ + +/* Emit a pre-processor error if the user configured multicast with bad MOP */ +#if RPL_CONF_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST) +#error "RPL Multicast requires RPL_MOP_DEFAULT==3. Check contiki-conf.h" +#endif + +/* Multicast Route Lifetime as a multiple of the lifetime unit */ +#ifdef RPL_CONF_MCAST_LIFETIME +#define RPL_MCAST_LIFETIME RPL_CONF_MCAST_LIFETIME +#else +#define RPL_MCAST_LIFETIME 3 #endif /* diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 4465bd81b..b4c25df19 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -41,6 +41,7 @@ #include "contiki-conf.h" #include "net/rpl/rpl-private.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -220,6 +221,10 @@ static void handle_dao_timer(void *ptr) { rpl_instance_t *instance; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; + uint8_t i; +#endif instance = (rpl_instance_t *)ptr; @@ -234,6 +239,31 @@ handle_dao_timer(void *ptr) PRINTF("RPL: handle_dao_timer - sending DAO\n"); /* Set the route lifetime to the default value. */ dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); + +#if RPL_CONF_MULTICAST + /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */ + if(instance->mop == RPL_MOP_STORING_MULTICAST) { + /* Send a DAO for own multicast addresses */ + for(i = 0; i < UIP_DS6_MADDR_NB; i++) { + if(uip_ds6_if.maddr_list[i].isused + && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) { + dao_output_target(instance->current_dag->preferred_parent, + &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME); + } + } + + /* Iterate over multicast routes and send DAOs */ + mcast_route = uip_mcast6_route_list_head(); + while(mcast_route != NULL) { + /* Don't send if it's also our own address, done that already */ + if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) { + dao_output_target(instance->current_dag->preferred_parent, + &mcast_route->group, RPL_MCAST_LIFETIME); + } + mcast_route = list_item_next(mcast_route); + } + } +#endif } else { PRINTF("RPL: No suitable DAO parent\n"); } diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 574497235..9fca4c28e 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -44,6 +44,7 @@ #include "net/ip/tcpip.h" #include "net/ipv6/uip-ds6.h" #include "net/rpl/rpl-private.h" +#include "net/ipv6/multicast/uip-mcast6.h" #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" @@ -105,6 +106,9 @@ rpl_purge_routes(void) uip_ds6_route_t *r; uip_ipaddr_t prefix; rpl_dag_t *dag; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; +#endif /* First pass, decrement lifetime */ r = uip_ds6_route_head(); @@ -146,12 +150,29 @@ rpl_purge_routes(void) r = uip_ds6_route_next(r); } } + +#if RPL_CONF_MULTICAST + mcast_route = uip_mcast6_route_list_head(); + + while(mcast_route != NULL) { + if(mcast_route->lifetime <= 1) { + uip_mcast6_route_rm(mcast_route); + mcast_route = uip_mcast6_route_list_head(); + } else { + mcast_route->lifetime--; + mcast_route = list_item_next(mcast_route); + } + } +#endif } /*---------------------------------------------------------------------------*/ void rpl_remove_routes(rpl_dag_t *dag) { uip_ds6_route_t *r; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; +#endif r = uip_ds6_route_head(); @@ -163,6 +184,19 @@ rpl_remove_routes(rpl_dag_t *dag) r = uip_ds6_route_next(r); } } + +#if RPL_CONF_MULTICAST + mcast_route = uip_mcast6_route_list_head(); + + while(mcast_route != NULL) { + if(mcast_route->dag == dag) { + uip_mcast6_route_rm(mcast_route); + mcast_route = uip_mcast6_route_list_head(); + } else { + mcast_route = list_item_next(mcast_route); + } + } +#endif } /*---------------------------------------------------------------------------*/ void