Skip to content

Commit e0494b7

Browse files
author
Tero Heinonen
authored
WS address registration callback for SLAAC (ARMmbed#1568)
When receiving DIO from parent with PIO and A flag, create SLAAC address and send NS with ARO back to parent.
1 parent 6ace69b commit e0494b7

File tree

12 files changed

+99
-25
lines changed

12 files changed

+99
-25
lines changed

source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ void protocol_6lowpan_register_handlers(protocol_interface_info_entry_t *cur)
399399
* for routers, as RPL doesn't deal with it) */
400400
cur->ipv6_neighbour_cache.send_addr_reg = true;
401401
cur->ipv6_neighbour_cache.recv_na_aro = true;
402+
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = false;
402403
}
403404
void protocol_6lowpan_release_short_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint16_t shortAddress)
404405
{

source/6LoWPAN/ND/nd_router_object.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "BorderRouter/border_router.h"
4242
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
4343
#include "6LoWPAN/MAC/mac_data_poll.h"
44+
#include "6LoWPAN/ws/ws_common.h"
4445

4546
#define TRACE_GROUP "loND"
4647

@@ -967,7 +968,13 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
967968
/* Set the LL address, ensure it's marked STALE */
968969
ipv6_neighbour_entry_update_unsolicited(&cur_interface->ipv6_neighbour_cache, neigh, ll_addr.addr_type, ll_addr.address);
969970
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
970-
971+
if (ws_info(cur_interface)) {
972+
aro_out->status = ARO_SUCCESS;
973+
aro_out->present = true;
974+
// Todo: this might not be needed...
975+
nd_update_registration(cur_interface, neigh, aro_out);
976+
return true;
977+
}
971978
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || nd_params.multihop_dad == false) {
972979
if (cur_interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
973980
whiteboard_entry_t *wb;

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,40 @@
4646
static void ws_bootstrap_event_handler(arm_event_s *event);
4747
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);
4848

49+
static void ws_bootstrap_address_registration_ns_send(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr)
50+
{
51+
aro_t aro;
52+
buffer_t *buf;
53+
54+
aro.status = ARO_SUCCESS;
55+
aro.present = true;
56+
aro.lifetime = addr->preferred_lifetime;
57+
memcpy(aro.eui64, interface->mac, 8);
58+
59+
ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) {
60+
const uint8_t *preferred_parent = rpl_control_preferred_parent_addr(instance, false);
61+
if (preferred_parent) {
62+
buf = icmpv6_build_ns(interface, preferred_parent, addr->address, true, false, &aro);
63+
protocol_push(buf);
64+
}
65+
}
66+
}
67+
68+
69+
static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason)
70+
{
71+
/* No need for LL address registration */
72+
if(addr->source == ADDR_SOURCE_UNKNOWN) {
73+
return;
74+
}
75+
76+
if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
77+
// When SLAAC address is created, send NS with ARO to parent
78+
ws_bootstrap_address_registration_ns_send(interface, addr);
79+
} else if (reason == ADDR_CALLBACK_DELETED) {
80+
// What to do?
81+
}
82+
}
4983
static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
5084
{
5185
if (cur->bootStrapId < 0) {
@@ -58,6 +92,7 @@ static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
5892
return -1;
5993
}
6094

95+
6196
return 0;
6297
}
6398

@@ -89,7 +124,6 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t
89124
// TODO FHSS create and init!!!!
90125
// TODO LLC create
91126

92-
protocol_6lowpan_register_handlers(cur);
93127
addr_interface_set_ll64(cur, NULL);
94128
cur->nwk_nd_re_scan_count = 0;
95129
//WS_interface_up(cur);
@@ -98,6 +132,10 @@ static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t
98132
if (ret_val) {
99133
goto cleanup;
100134
}
135+
136+
/* Disable SLLAO send/mandatory receive with the ARO */
137+
cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true;
138+
101139
ws_bootstrap_event_discovery_start(cur);
102140

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

246284
ws_bootstrap_configuration_reset(cur);
285+
addr_notification_register(ws_bootstrap_address_notification_cb);
247286

248287
return 0;
249288
}
@@ -316,7 +355,6 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur)
316355
* Event transitions
317356
*
318357
* */
319-
320358
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur)
321359
{
322360
ws_bootsrap_event_trig(WS_DISCOVERY_START, cur->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT);
@@ -377,11 +415,10 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
377415
tr_info("Routing ready");
378416
ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE);
379417
break;
380-
default:
381-
tr_err("Invalid event received");
418+
default:
419+
tr_err("Invalid event received");
382420
break;
383421
}
384-
385422
}
386423

387424

source/Common_Protocols/icmpv6.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
416416
{
417417
protocol_interface_info_entry_t *cur;
418418
uint8_t target[16];
419+
uint8_t dummy_sllao[16];
419420
bool proxy = false;
420421
const uint8_t *sllao;
421422
const uint8_t *aro;
@@ -435,7 +436,9 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
435436
sllao = icmpv6_find_option_in_buffer(buf, 20, ICMPV6_OPT_SRC_LL_ADDR, 0);
436437

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

452+
/* If there was no SLLAO on ARO, use mac address to create dummy one... */
453+
if (aro && !sllao && cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
454+
dummy_sllao[0] = ICMPV6_OPT_SRC_LL_ADDR; // Type
455+
dummy_sllao[1] = 2; // Length = 2x8 bytes
456+
memcpy(dummy_sllao + 2, aro + 8, 8); // EUI-64
457+
memset(dummy_sllao + 10, 0, 6); // Padding
458+
459+
sllao = dummy_sllao;
460+
}
449461
// Skip the 4 reserved bytes
450462
dptr += 4;
451463

@@ -526,7 +538,7 @@ static buffer_t *icmpv6_ns_handler(buffer_t *buf)
526538

527539
}
528540

529-
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)
541+
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)
530542
{
531543
int ret_val = -1;
532544

@@ -561,7 +573,7 @@ void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur
561573
}
562574
#endif // HAVE_IPV6_ND
563575

564-
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)
576+
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)
565577
{
566578
if_address_entry_t *address_entry;
567579
uint8_t ipv6_address[16];
@@ -771,7 +783,7 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
771783
ptr += 4;
772784
uint32_t preferred_lifetime = common_read_32_bit(ptr);
773785
ptr += 8; //Update 32-bit time and reserved 32-bit
774-
uint8_t *prefix_ptr = ptr;
786+
const uint8_t *prefix_ptr = ptr;
775787

776788
//Check is L Flag active
777789
if (prefix_flags & PIO_L) {
@@ -1246,7 +1258,7 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
12461258
} else {
12471259
/* RFC 4861 7.2.2. says we should use the source of traffic prompting the NS, if possible */
12481260
/* This is also used to specify the address for ARO messages */
1249-
if (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr)) {
1261+
if (aro || (prompting_src_addr && addr_is_assigned_to_interface(cur, prompting_src_addr))) {
12501262
memcpy(buf->src_sa.address, prompting_src_addr, 16);
12511263
} else {
12521264
/* Otherwise, according to RFC 4861, we could use any address.
@@ -1270,7 +1282,10 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta
12701282
}
12711283
}
12721284
/* SLLAO is required if we're sending an ARO */
1273-
ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa.address);
1285+
/* This rule can be bypassed with flag use_eui64_as_slla_in_aro */
1286+
if (!cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro) {
1287+
ptr = icmpv6_write_icmp_lla(cur, ptr, ICMPV6_OPT_SRC_LL_ADDR, aro, buf->src_sa.address);
1288+
}
12741289
}
12751290
buf->src_sa.addr_type = ADDR_IPV6;
12761291

source/Common_Protocols/icmpv6.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ extern void icmpv6_recv_ra_routes(struct protocol_interface_info_entry *cur, boo
140140
extern void icmpv6_recv_ra_prefixes(struct protocol_interface_info_entry *cur, bool enable);
141141

142142
extern void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur, uint8_t *prefix_ptr, uint8_t prefix_len);
143-
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);
144-
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);
143+
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);
144+
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);
145145

146146

147147
/*

source/RPL/rpl_control.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#include "NWK_INTERFACE/Include/protocol_stats.h"
4646
#include "Common_Protocols/ipv6_constants.h"
4747
#include "Common_Protocols/icmpv6.h"
48-
48+
#include "ipv6_stack/protocol_ipv6.h"
4949
#include "Service_Libs/etx/etx.h" /* slight ick */
5050

5151
#include "net_rpl.h"
@@ -628,15 +628,26 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
628628
}
629629
uint8_t prefix_len = ptr[2];
630630
uint8_t flags = ptr[3];
631-
uint32_t preferred = common_read_32_bit(ptr + 4);
632-
uint32_t valid = common_read_32_bit(ptr + 8);
631+
uint32_t valid = common_read_32_bit(ptr + 4);
632+
uint32_t preferred = common_read_32_bit(ptr + 8);
633633
const uint8_t *prefix = ptr + 16;
634634

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

641652
/* Store prefixes for possible forwarding */
642653
/* XXX if leaf - don't bother? Or do we want to remember them for

source/ipv6_stack/ipv6_routing_table.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ typedef struct ipv6_neighbour_cache {
119119
bool send_nud_probes : 1;
120120
bool recv_ns_aro : 1;
121121
bool recv_na_aro : 1;
122+
bool use_eui64_as_slla_in_aro : 1;
122123
int8_t interface_id;
123124
uint8_t max_ll_len;
124125
uint8_t gc_timer;

source/ipv6_stack/protocol_ipv6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ static void ipv6_interface_address_cb(protocol_interface_info_entry_t *interface
954954
}
955955
}
956956

957-
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
957+
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
958958
{
959959
if_address_entry_t *address_entry = icmpv6_slaac_address_add(cur, slaacPrefix, prefixLen, validLifeTime, preferredLifeTime, false, SLAAC_IID_DEFAULT);
960960
if (address_entry) {

source/ipv6_stack/protocol_ipv6.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int ipv6_prefix_register(uint8_t *prefix_64, uint32_t lifetime, uint32_t prefer_
6363
int ipv6_prefix_router_flag_activate(uint8_t *ipv6_address);
6464

6565
void ipv6_nd_ra_advert(struct protocol_interface_info_entry *cur, const uint8_t *dest);
66-
void ipv6_interface_slaac_handler(struct protocol_interface_info_entry *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime);
66+
void ipv6_interface_slaac_handler(struct protocol_interface_info_entry *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime);
6767
void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint8_t routePrefer);
6868
void ipv6_stack_route_advert_remove(uint8_t *address, uint8_t prefixLength);
6969
void ipv6_prefix_on_link_update(uint8_t *address);

test/nanostack/unittest/rpl/rpl_control/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ TEST_SRC_FILES = \
2323
../../stub/address_stub.c \
2424
../../stub/icmpv6_stub.c \
2525
../../stub/etx_stub.c \
26+
../../stub/ipv6_routing_table_stub.c \
27+
../../stub/protocol_ipv6_stub.c \
2628

2729
include ../../MakefileWorker.mk
2830

test/nanostack/unittest/stub/icmpv6_stub.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ buffer_t *icmpv6_ns_handler(buffer_t *buf)
6666

6767
}
6868

69-
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)
69+
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)
7070
{
7171
return -1;
7272
}
@@ -75,7 +75,7 @@ void icmpv6_slaac_prefix_register_trig(struct protocol_interface_info_entry *cur
7575
{
7676
}
7777

78-
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)
78+
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)
7979
{
8080
return NULL;
8181
}

test/nanostack/unittest/stub/protocol_ipv6_stub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ void ipv6_trigger_resolve_query(protocol_interface_info_entry_t *cur_interface,
167167
{
168168
}
169169

170-
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
170+
void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime)
171171
{
172172
}
173173

0 commit comments

Comments
 (0)