Skip to content

Commit

Permalink
gnrc_ndp: add external routers to FIB when RPL is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
Yonezawa-T2 committed Dec 16, 2015
1 parent 26eeb9f commit dd4d5a6
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 5 deletions.
93 changes: 93 additions & 0 deletions sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "thread.h"
#include "xtimer.h"

#if defined(MODULE_GNRC_RPL) && defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
#include "net/gnrc/rpl/dodag.h"
#endif

#include "net/gnrc/ndp/internal.h"

#include "net/gnrc/ndp.h"
Expand Down Expand Up @@ -477,6 +481,64 @@ static inline void _set_reach_time(gnrc_ipv6_netif_t *if_entry, uint32_t mean)
if_entry->reach_time = reach_time;
}

#if defined(MODULE_GNRC_RPL) && defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
/**
* @brief Add or remove prefix route to FIB table.
*
* If given lifetime is 0, the route is removed.
*
* @param[in] iface interface of the router
* @param[in] prefix prefix to match
* @param[in] next_hop address of the router
* @param[in] lifetime lifetime of the router
* @param[in] only_if_root when true, add router only if this device is a root
* node of RPL. When false, add router only if this device is not a
* root node.
*/
static void _add_prefix_route(kernel_pid_t iface,
uint8_t *prefix,
uint8_t *next_hop,
uint32_t lifetime,
bool only_if_root) {
bool updated = false;

for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
if (gnrc_rpl_instances[i].state == 0) {
continue;
}

uint8_t node_status = gnrc_rpl_instances[i].dodag.node_status;

if ((node_status == GNRC_RPL_ROOT_NODE) != only_if_root) {
continue;
}

if (lifetime > 0) {
fib_add_entry(&gnrc_ipv6_fib_table, iface,
prefix, sizeof(ipv6_addr_t), FIB_FLAG_NET_PREFIX,
next_hop, sizeof(ipv6_addr_t), 0,
lifetime);
} else {
fib_remove_entry(&gnrc_ipv6_fib_table, prefix, sizeof(ipv6_addr_t));
}

updated = true;

break;
}

if (updated) {
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
if (gnrc_rpl_instances[i].state == 0) {
continue;
}

gnrc_rpl_delay_dao(&(gnrc_rpl_instances[i].dodag));
}
}
}
#endif

void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t *ipv6,
ndp_rtr_adv_t *rtr_adv, size_t icmpv6_size)
{
Expand Down Expand Up @@ -573,6 +635,23 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t
next_rtr_sol = valid_ltime;
}
#endif

#if defined(MODULE_GNRC_RPL) && defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
if (!(if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
ndp_opt_pi_t * pi_opt = (ndp_opt_pi_t *)opt;
uint32_t lifetime =
(pi_opt->valid_ltime.u32 == 0xFFFFFFFF) ?
(uint32_t) FIB_LIFETIME_NO_EXPIRE :
byteorder_ntohl(pi_opt->valid_ltime) * 1000;

_add_prefix_route(iface,
pi_opt->prefix.u8,
ipv6->src.u8,
lifetime,
false);
}
#endif

break;
#ifdef MODULE_GNRC_SIXLOWPAN_ND
case NDP_OPT_6CTX:
Expand Down Expand Up @@ -632,6 +711,20 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t
}
}
#endif

#if defined(MODULE_GNRC_RPL) && defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
if (!(if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
ipv6_addr_t default_route_prefix;

memset(default_route_prefix.u8, 0, sizeof(ipv6_addr_t));

_add_prefix_route(iface,
default_route_prefix.u8,
ipv6->src.u8,
(uint32_t) byteorder_ntohs(rtr_adv->ltime) * 1000,
GNRC_RPL_ROOT_NODE);
}
#endif
}

void gnrc_ndp_retrans_nbr_sol(gnrc_ipv6_nc_t *nc_entry)
Expand Down
43 changes: 38 additions & 5 deletions sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,19 @@ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt
first_target = target;
}

uint32_t fib_dst_flags = 0;

if (target->prefix_length < IPV6_ADDR_BIT_LEN) {
fib_dst_flags |= FIB_FLAG_NET_PREFIX;
}

DEBUG("RPL: adding fib entry %s/%d 0x%x\n",
ipv6_addr_to_str(addr_str, &(target->target), sizeof(addr_str)),
target->prefix_length,
fib_dst_flags);

fib_add_entry(&gnrc_ipv6_fib_table, if_id, target->target.u8,
sizeof(ipv6_addr_t), 0x0, src->u8,
sizeof(ipv6_addr_t), fib_dst_flags, src->u8,
sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
(dodag->default_lifetime * dodag->lifetime_unit) *
SEC_IN_MS);
Expand All @@ -459,6 +470,10 @@ a preceding RPL TARGET DAO option\n");
}

do {
DEBUG("RPL: updating fib entry %s/%d\n",
ipv6_addr_to_str(addr_str, &(first_target->target), sizeof(addr_str)),
first_target->prefix_length);

fib_update_entry(&gnrc_ipv6_fib_table,
first_target->target.u8,
sizeof(ipv6_addr_t), src->u8,
Expand Down Expand Up @@ -653,7 +668,7 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
}
}

gnrc_pktsnip_t *_dao_target_build(gnrc_pktsnip_t *pkt, ipv6_addr_t *addr)
gnrc_pktsnip_t *_dao_target_build(gnrc_pktsnip_t *pkt, ipv6_addr_t *addr, uint8_t prefix_length)
{
gnrc_rpl_opt_target_t *target;
gnrc_pktsnip_t *opt_snip;
Expand All @@ -667,7 +682,7 @@ gnrc_pktsnip_t *_dao_target_build(gnrc_pktsnip_t *pkt, ipv6_addr_t *addr)
target->type = GNRC_RPL_OPT_TARGET;
target->length = sizeof(target->flags) + sizeof(target->prefix_length) + sizeof(target->target);
target->flags = 0;
target->prefix_length = 128;
target->prefix_length = prefix_length;
target->target = *addr;
return opt_snip;
}
Expand Down Expand Up @@ -741,6 +756,7 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
if (!(fentry->next_hop_flags & FIB_FLAG_RPL_ROUTE)) {
ptr = &tmp;
if (!ext_processed) {
DEBUG("RPL: Send DAO - building external transit\n");
if ((tmp = _dao_transit_build(NULL, lifetime, true)) == NULL) {
DEBUG("RPL: Send DAO - no space left in packet buffer\n");
mutex_unlock(&(gnrc_ipv6_fib_table.mtx_access));
Expand All @@ -752,6 +768,7 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
else {
ptr = &pkt;
if (!int_processed) {
DEBUG("RPL: Send DAO - building internal transit\n");
if ((tr_int = pkt = _dao_transit_build(NULL, lifetime, false)) == NULL) {
DEBUG("RPL: Send DAO - no space left in packet buffer\n");
mutex_unlock(&(gnrc_ipv6_fib_table.mtx_access));
Expand All @@ -762,7 +779,21 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
}
addr = (ipv6_addr_t *) fentry->global->address;
if (ipv6_addr_is_global(addr)) {
if ((*ptr = _dao_target_build(*ptr, addr)) == NULL) {
size_t prefix_length = IPV6_ADDR_BIT_LEN;

if (fentry->global_flags & FIB_FLAG_NET_PREFIX) {
universal_address_compare(fentry->global,
fentry->global->address,
&prefix_length);
} else {
prefix_length = IPV6_ADDR_BIT_LEN;
}

DEBUG("RPL: Send DAO - building target %s/%d\n",
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
(int) prefix_length);

if ((*ptr = _dao_target_build(*ptr, addr, (uint8_t) prefix_length)) == NULL) {
DEBUG("RPL: Send DAO - no space left in packet buffer\n");
mutex_unlock(&(gnrc_ipv6_fib_table.mtx_access));
return;
Expand All @@ -781,7 +812,9 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
}

/* add own address */
if ((pkt = _dao_target_build(pkt, me)) == NULL) {
DEBUG("RPL: Send DAO - building target %s/128\n",
ipv6_addr_to_str(addr_str, me, sizeof(addr_str)));
if ((pkt = _dao_target_build(pkt, me, IPV6_ADDR_BIT_LEN)) == NULL) {
DEBUG("RPL: Send DAO - no space left in packet buffer\n");
return;
}
Expand Down

0 comments on commit dd4d5a6

Please sign in to comment.