Skip to content

Commit

Permalink
WS address registration callback for SLAAC (ARMmbed#1568)
Browse files Browse the repository at this point in the history
When receiving DIO from parent with PIO and A flag, create SLAAC address and
send NS with ARO back to parent.
  • Loading branch information
Tero Heinonen committed Feb 15, 2018
1 parent 6ace69b commit e0494b7
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 25 deletions.
1 change: 1 addition & 0 deletions source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c
Expand Up @@ -399,6 +399,7 @@ void protocol_6lowpan_register_handlers(protocol_interface_info_entry_t *cur)
* for routers, as RPL doesn't deal with it) */
cur->ipv6_neighbour_cache.send_addr_reg = true;
cur->ipv6_neighbour_cache.recv_na_aro = true;
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = false;
}
void protocol_6lowpan_release_short_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint16_t shortAddress)
{
Expand Down
9 changes: 8 additions & 1 deletion source/6LoWPAN/ND/nd_router_object.c
Expand Up @@ -41,6 +41,7 @@
#include "BorderRouter/border_router.h"
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/ws/ws_common.h"

#define TRACE_GROUP "loND"

Expand Down Expand Up @@ -967,7 +968,13 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
/* Set the LL address, ensure it's marked STALE */
ipv6_neighbour_entry_update_unsolicited(&cur_interface->ipv6_neighbour_cache, neigh, ll_addr.addr_type, ll_addr.address);
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);

if (ws_info(cur_interface)) {
aro_out->status = ARO_SUCCESS;
aro_out->present = true;
// Todo: this might not be needed...
nd_update_registration(cur_interface, neigh, aro_out);
return true;
}
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || nd_params.multihop_dad == false) {
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
whiteboard_entry_t *wb;
Expand Down
47 changes: 42 additions & 5 deletions source/6LoWPAN/ws/ws_bootstrap.c
Expand Up @@ -46,6 +46,40 @@
static void ws_bootstrap_event_handler(arm_event_s *event);
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);

static void ws_bootstrap_address_registration_ns_send(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr)
{
aro_t aro;
buffer_t *buf;

aro.status = ARO_SUCCESS;
aro.present = true;
aro.lifetime = addr->preferred_lifetime;
memcpy(aro.eui64, interface->mac, 8);

ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
const uint8_t *preferred_parent = rpl_control_preferred_parent_addr(instance, false);
if (preferred_parent) {
buf = icmpv6_build_ns(interface, preferred_parent, addr->address, true, false, &aro);
protocol_push(buf);
}
}
}


static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason)
{
/* No need for LL address registration */
if(addr->source == ADDR_SOURCE_UNKNOWN) {
return;
}

if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
// When SLAAC address is created, send NS with ARO to parent
ws_bootstrap_address_registration_ns_send(interface, addr);
} else if (reason == ADDR_CALLBACK_DELETED) {
// What to do?
}
}
static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
{
if (cur->bootStrapId < 0) {
Expand All @@ -58,6 +92,7 @@ static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
return -1;
}


return 0;
}

Expand Down Expand Up @@ -89,7 +124,6 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t
// TODO FHSS create and init!!!!
// TODO LLC create

protocol_6lowpan_register_handlers(cur);
addr_interface_set_ll64(cur, NULL);
cur->nwk_nd_re_scan_count = 0;
//WS_interface_up(cur);
Expand All @@ -98,6 +132,10 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t
if (ret_val) {
goto cleanup;
}

/* Disable SLLAO send/mandatory receive with the ARO */
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true;

ws_bootstrap_event_discovery_start(cur);

return 0;
Expand Down Expand Up @@ -244,6 +282,7 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
cur->if_down = ws_bootstrap_down;

ws_bootstrap_configuration_reset(cur);
addr_notification_register(ws_bootstrap_address_notification_cb);

return 0;
}
Expand Down Expand Up @@ -316,7 +355,6 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur)
* Event transitions
*
* */

void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur)
{
ws_bootsrap_event_trig(WS_DISCOVERY_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT);
Expand Down Expand Up @@ -377,11 +415,10 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
tr_info("Routing ready");
ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE);
break;
default:
tr_err("Invalid event received");
default:
tr_err("Invalid event received");
break;
}

}


Expand Down
27 changes: 21 additions & 6 deletions source/Common_Protocols/icmpv6.c
Expand Up @@ -416,6 +416,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
uint8_t target[16];
uint8_t dummy_sllao[16];
bool proxy = false;
const uint8_t *sllao;
const uint8_t *aro;
Expand All @@ -435,7 +436,9 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
sllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_SRC_LL_ADDR, 0);

/* If no SLLAO, ignore ARO (RFC 6775 6.5) */
if (sllao && cur->ipv6_neighbour_cache.recv_addr_reg) {
/* This rule can be bypassed by setting flag "use_eui64_as_slla_in_aro" to true */
if (cur->ipv6_neighbour_cache.recv_addr_reg &&
(cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro || sllao)) {
aro = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_ADDR_REGISTRATION, 0);
} else {
aro = NULL;
Expand All @@ -446,6 +449,15 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
goto drop;
}

/* If there was no SLLAO on ARO, use mac address to create dummy one... */
if (aro && !sllao && cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
dummy_sllao[0] = ICMPV6_OPT_SRC_LL_ADDR; // Type
dummy_sllao[1] = 2; // Length = 2x8 bytes
memcpy(dummy_sllao + 2, aro + 8, 8); // EUI-64
memset(dummy_sllao + 10, 0, 6); // Padding

sllao = dummy_sllao;
}
// Skip the 4 reserved bytes
dptr += 4;

Expand Down Expand Up @@ -526,7 +538,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)

}

int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
{
int ret_val = -1;

Expand Down Expand Up @@ -561,7 +573,7 @@ void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur
}
#endif // HAVE_IPV6_ND

if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
{
if_address_entry_t *address_entry;
uint8_t ipv6_address[16];
Expand Down Expand Up @@ -771,7 +783,7 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
ptr += 4;
uint32_t preferred_lifetime = common_read_32_bit(ptr);
ptr += 8; //Update 32-bit time and reserved 32-bit
uint8_t *prefix_ptr = ptr;
const uint8_t *prefix_ptr = ptr;

//Check is L Flag active
if (prefix_flags & PIO_L) {
Expand Down Expand Up @@ -1246,7 +1258,7 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
} else {
/* RFC 4861 7.2.2. says we should use the source of traffic prompting the NS, if possible */
/* This is also used to specify the address for ARO messages */
if (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr)) {
if (aro || (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr))) {
memcpy(buf->src_sa.address, prompting_src_addr, 16);
} else {
/* Otherwise, according to RFC 4861, we could use any address.
Expand All @@ -1270,7 +1282,10 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
}
}
/* SLLAO is required if we're sending an ARO */
ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa.address);
/* This rule can be bypassed with flag use_eui64_as_slla_in_aro */
if (!cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa.address);
}
}
buf->src_sa.addr_type = ADDR_IPV6;

Expand Down
4 changes: 2 additions & 2 deletions source/Common_Protocols/icmpv6.h
Expand Up @@ -140,8 +140,8 @@ extern void icmpv6_recv_ra_routes(struct protocol_interface_info_entry *cur, boo
extern void icmpv6_recv_ra_prefixes(struct protocol_interface_info_entry *cur, bool enable);

extern void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len);
extern int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime);
extern struct if_address_entry *icmpv6_slaac_address_add(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src);
extern int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime);
extern struct if_address_entry *icmpv6_slaac_address_add(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src);


/*
Expand Down
23 changes: 17 additions & 6 deletions source/RPL/rpl_control.c
Expand Up @@ -45,7 +45,7 @@
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "Common_Protocols/ipv6_constants.h"
#include "Common_Protocols/icmpv6.h"

#include "ipv6_stack/protocol_ipv6.h"
#include "Service_Libs/etx/etx.h" /* slight ick */

#include "net_rpl.h"
Expand Down Expand Up @@ -628,15 +628,26 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
}
uint8_t prefix_len = ptr[2];
uint8_t flags = ptr[3];
uint32_t preferred = common_read_32_bit(ptr + 4);
uint32_t valid = common_read_32_bit(ptr + 8);
uint32_t valid = common_read_32_bit(ptr + 4);
uint32_t preferred = common_read_32_bit(ptr + 8);
const uint8_t *prefix = ptr + 16;

if (!pref_parent || neighbour == pref_parent) {
/* XXX We don't yet locally handle A and L flags. Presumably should
* only locally process for DODAG's we're a member of? Should we
* process now, or later?
//Check is L Flag active
if (flags & PIO_L) {
//define ONLink Route Information
//tr_debug("Register On Link Prefix to routing table");
ipv6_route_add(prefix, prefix_len, cur->id, NULL, ROUTE_RADV, valid, 0);
}
/* Check if A-Flag.
* A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC)
* from a prefix advertised by a parent.
*/
if (pref_parent && (flags & PIO_A)) {
if (icmpv6_slaac_prefix_update(cur, prefix, prefix_len, valid, preferred) != 0) {
ipv6_interface_slaac_handler(cur, prefix, prefix_len, valid, preferred);
}
}

/* Store prefixes for possible forwarding */
/* XXX if leaf - don't bother? Or do we want to remember them for
Expand Down
1 change: 1 addition & 0 deletions source/ipv6_stack/ipv6_routing_table.h
Expand Up @@ -119,6 +119,7 @@ typedef struct ipv6_neighbour_cache {
bool send_nud_probes : 1;
bool recv_ns_aro : 1;
bool recv_na_aro : 1;
bool use_eui64_as_slla_in_aro : 1;
int8_t interface_id;
uint8_t max_ll_len;
uint8_t gc_timer;
Expand Down
2 changes: 1 addition & 1 deletion source/ipv6_stack/protocol_ipv6.c
Expand Up @@ -954,7 +954,7 @@ static void ipv6_interface_address_cb(protocol_interface_info_entry_t *interface
}
}

void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
{
if_address_entry_t *address_entry = icmpv6_slaac_address_add(cur, slaacPrefix, prefixLen, validLifeTime, preferredLifeTime, false, SLAAC_IID_DEFAULT);
if (address_entry) {
Expand Down
2 changes: 1 addition & 1 deletion source/ipv6_stack/protocol_ipv6.h
Expand Up @@ -63,7 +63,7 @@ int ipv6_prefix_register(uint8_t *prefix_64, uint32_t lifetime, uint32_t prefer_
int ipv6_prefix_router_flag_activate(uint8_t *ipv6_address);

void ipv6_nd_ra_advert(struct protocol_interface_info_entry *cur, const uint8_t *dest);
void ipv6_interface_slaac_handler(struct protocol_interface_info_entry *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime);
void ipv6_interface_slaac_handler(struct protocol_interface_info_entry *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime);
void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint8_t routePrefer);
void ipv6_stack_route_advert_remove(uint8_t *address, uint8_t prefixLength);
void ipv6_prefix_on_link_update(uint8_t *address);
Expand Down
2 changes: 2 additions & 0 deletions test/nanostack/unittest/rpl/rpl_control/Makefile
Expand Up @@ -23,6 +23,8 @@ TEST_SRC_FILES = \
../../stub/address_stub.c \
../../stub/icmpv6_stub.c \
../../stub/etx_stub.c \
../../stub/ipv6_routing_table_stub.c \
../../stub/protocol_ipv6_stub.c \

include ../../MakefileWorker.mk

Expand Down
4 changes: 2 additions & 2 deletions test/nanostack/unittest/stub/icmpv6_stub.c
Expand Up @@ -66,7 +66,7 @@ buffer_t *icmpv6_ns_handler(buffer_t *buf)

}

int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
int icmpv6_slaac_prefix_update(struct protocol_interface_info_entry *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
{
return -1;
}
Expand All @@ -75,7 +75,7 @@ void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur
{
}

if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cur, const uint8_t *prefix_ptr, uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime, bool skip_dad, slaac_src_e slaac_src)
{
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion test/nanostack/unittest/stub/protocol_ipv6_stub.c
Expand Up @@ -167,7 +167,7 @@ void ipv6_trigger_resolve_query(protocol_interface_info_entry_t *cur_interface,
{
}

void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
{
}

Expand Down

0 comments on commit e0494b7

Please sign in to comment.