diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index 10fd85a6f9a..4e8cec5ba1b 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1786,7 +1786,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode */ if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) { //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } #endif cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED; @@ -2181,7 +2181,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t * // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); } // Send unicast DIS to coordinator nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index c19ce516778..5a7111fc65c 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -29,6 +29,7 @@ #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" +#include "ipv6_stack/protocol_ipv6.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_data_poll.h" #include "6LoWPAN/MAC/mpx_api.h" @@ -57,7 +58,7 @@ #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/nd_proxy/nd_proxy.h" #include "platform/topo_trace.h" - +#include "DHCPv6_client/dhcpv6_client_api.h" #include "net_rpl.h" #include "mac_api.h" @@ -127,7 +128,7 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_ } if (reason == ADDR_CALLBACK_DAD_COMPLETE) { //Trig Address Registartion only when Bootstrap is ready - if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { + if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE || addr->source == ADDR_SOURCE_DHCP) { ws_bootsrap_event_trig(WS_ADDRESS_ADDED, interface->bootStrapId, ARM_LIB_LOW_PRIORITY_EVENT, (void *)addr); } if (addr_ipv6_scope(addr->address,interface) > IPV6_SCOPE_LINK_LOCAL) { @@ -604,6 +605,7 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) cur->ipv6_neighbour_cache.omit_aro_success = true; /* Disable NUD Probes */ cur->ipv6_neighbour_cache.send_nud_probes = false; + dhcp_client_init(cur->id); ws_nud_table_reset(cur); @@ -627,6 +629,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) ws_llc_reset(cur); nd_proxy_downstream_interface_unregister(cur->id); ws_nud_table_reset(cur); + dhcp_client_delete(cur->id); return nwk_6lowpan_down(cur); } @@ -1509,6 +1512,51 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) tr_info("RPL event %d", event); } +static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) +{ + (void)prefix; + (void)interface; + //TODO add handler for negative status + tr_debug("DHCPv6 %s status %u",trace_ipv6(dhcp_addr), register_status); +} + +static bool ws_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list) +{ + bool addressReady = false; + ns_list_foreach(if_address_entry_t, entry, list) { + if (memcmp(entry->address, prefixPtr, 8) == 0) { + addressReady = true; + break; + } + } + return addressReady; +} + +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local) +{ + if (!ws_address_entry_available(prefix, &cur->ip_addresses)) { + if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, cur->mac, ws_dhcp_client_global_adress_cb) != 0) { + tr_error("DHCPp client request fail"); + } + } +} + +static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local) +{ + protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t*) handle; + /* 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 (prefix->options & PIO_A) { + if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) { + ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime); + } + } else if (prefix->prefix_len) { + ws_dhcp_client_address_request(cur, prefix->prefix, parent_link_local); + } +} + static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) { tr_debug("RPL Activate"); @@ -1517,7 +1565,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) addr_add_router_groups(cur); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, cur); // If i am router I Do this rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index ba78e41eaeb..7d436eadb8f 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -62,6 +62,8 @@ void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neig void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local); + #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index ccde461367c..8239bc0fdd2 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -348,9 +348,10 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c } } -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle) +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle) { domain->callback = callback; + domain->prefix_cb = prefix_learn_cb; domain->cb_handle = cb_handle; } @@ -686,6 +687,12 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t * prefix_entry_t *prefix_entry = rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); if (prefix_entry && pref_parent) { rpl_control_process_prefix_option(prefix_entry, cur); + rpl_domain_t *domain = cur->rpl_domain; + if (domain && domain->prefix_cb) { + uint8_t ll_address[16]; + memcpy(ll_address, rpl_neighbour_ll_address(pref_parent), 16); + domain->prefix_cb(prefix_entry, domain->cb_handle,ll_address); + } } } @@ -711,15 +718,7 @@ void rpl_control_process_prefix_option(prefix_entry_t *prefix, protocol_interfac //tr_debug("Register On Link Prefix to routing table"); ipv6_route_add(prefix->prefix, prefix->prefix_len, cur->id, NULL, ROUTE_RADV, prefix->lifetime, 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 (prefix->options & PIO_A) { - if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) { - ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime); - } - } + } diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 8c11df439ae..c924750d796 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -40,6 +40,8 @@ typedef enum rpl_event { typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); +typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local); + typedef struct rpl_domain { NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; @@ -52,6 +54,7 @@ typedef struct rpl_domain /* As part of shutdown, we can force entering leaf mode */ bool force_leaf; rpl_domain_callback_t *callback; + rpl_prefix_callback_t *prefix_cb; void *cb_handle; } rpl_domain_t; @@ -141,7 +144,7 @@ rpl_domain_t *rpl_control_create_domain(void); void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle); +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 8460934da51..fdc5f341bd4 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1407,6 +1407,9 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) if (rpl_interface) { ns_list_foreach(prefix_entry_t, prefix, &dodag->prefixes) { rpl_control_process_prefix_option(prefix, rpl_interface); + if (instance->domain->prefix_cb) { + instance->domain->prefix_cb(prefix, rpl_interface, preferred_parent->ll_address); + } } } } diff --git a/source/nsconfig.h b/source/nsconfig.h index bd7df30a632..59e3dc1a6fc 100644 --- a/source/nsconfig.h +++ b/source/nsconfig.h @@ -57,6 +57,12 @@ #endif #endif /* HAVE_THREAD */ +#if defined(HAVE_WS) +#ifndef HAVE_DHCPV6 +#define HAVE_DHCPV6 +#endif +#endif /* HAVE_WS */ + #endif // ifndef _NANOSTACK_SOURCE_CONFIG_H diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index 6ea18991a94..a365a76296a 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -99,7 +99,7 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c } -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle) +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle) { }