Skip to content

Commit f8b227f

Browse files
author
Arto Kinnunen
authored
Thread DHCP address allocation fix (#1657)
If Thread network data contains multiple border routers then global address can be allocated for each prefix. Do not allow simultaneous DHCP solicits for single prefix.
1 parent 41ca387 commit f8b227f

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

source/6LoWPAN/Thread/thread_bootstrap.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,7 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[
18071807
}
18081808
}
18091809

1810-
static bool thread_dhcpv6_address_valid(uint8_t *prefixPtr, if_address_list_t *list)
1810+
bool thread_dhcpv6_address_entry_available(uint8_t *prefixPtr, if_address_list_t *list)
18111811
{
18121812
bool addressReady = false;
18131813
ns_list_foreach(if_address_entry_t, entry, list) {
@@ -2501,8 +2501,8 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur,
25012501
memcpy(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
25022502
memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6);
25032503
common_write_16_bit(genericService.routerID, &addr[14]);
2504-
thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
25052504
tr_debug("Delete DHCPv6 given address");
2505+
thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
25062506
}
25072507
}
25082508

@@ -2729,7 +2729,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
27292729
bool validToLearnRoutes, validToLearOnMeshRoute;
27302730
thread_network_server_data_entry_t *weHostService = NULL;
27312731
uint16_t routerId;
2732-
tr_debug("Network Data:");
2732+
tr_debug("Network Data process:");
27332733
routerId = cur->mac_parameters->mac_short_address;
27342734
thread_network_data_cache_entry_t *networkData;
27352735
networkData = &cur->thread_info->networkDataStorage;
@@ -2792,14 +2792,14 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
27922792
}
27932793
}
27942794

2795-
if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
2795+
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
27962796
thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
2797-
2797+
/* Do not allow multiple DHCP solicits from one prefix => delete previous */
2798+
thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix);
27982799
if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) {
27992800
tr_debug("GP Address Requested");
28002801
}
28012802
}
2802-
28032803
} else {
28042804
/* All end device types perform RLOC16 -> 0xfffe
28052805
replacement if stable network data was requested. */
@@ -2812,7 +2812,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
28122812
}
28132813

28142814
if (curBorderRouter->P_preferred) {
2815-
if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
2815+
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
28162816
icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT);
28172817
}
28182818
}

source/6LoWPAN/Thread/thread_dhcpv6_client.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
135135
tr_error("Sol Not include all Options");
136136
goto error_exit;
137137
}
138+
139+
if (libdhcpv6_nonTemporal_entry_get_by_iaid(dhcp_ia_non_temporal_params.iaId) != srv_data_ptr) {
140+
/* Validate server data availability */
141+
tr_error("Valid instance not found");
142+
goto error_exit;
143+
}
144+
138145
if (srv_data_ptr->IAID != dhcp_ia_non_temporal_params.iaId) {
139146
tr_error("Wrong IAID");
140147
goto error_exit;
@@ -181,7 +188,9 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
181188
tr_error("Invalid parameters");
182189
return -1;
183190
}
191+
184192
srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr);
193+
185194
payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0);
186195
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
187196

@@ -207,6 +216,7 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
207216
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb);
208217
return srv_data_ptr->transActionId ? 0 : -1;
209218
}
219+
210220
void thread_dhcp_client_global_address_renew(int8_t interface)
211221
{
212222
// only prepared for changes in thread specifications
@@ -219,15 +229,23 @@ void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_add
219229
protocol_interface_info_entry_t *cur;
220230
dhcpv6_client_server_data_t *srv_data_ptr;
221231
(void) dhcp_addr;
232+
222233
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
223234
cur = protocol_stack_interface_info_get_by_id(interface);
224-
if (cur == NULL || srv_data_ptr == NULL) {
225-
tr_error("Not valid prefix");
226-
return;
227-
}
228-
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
229-
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
230-
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
235+
236+
do {
237+
if (cur == NULL || srv_data_ptr == NULL) {
238+
return;
239+
}
240+
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
241+
tr_debug("Deleting address: %s", trace_ipv6(srv_data_ptr->iaNontemporalAddress.addressPrefix));
242+
243+
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
244+
245+
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
246+
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
247+
} while (srv_data_ptr);
248+
231249
return;
232250
}
233251

@@ -306,7 +324,7 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
306324

307325
if (address_entry == NULL) {
308326
tr_error("Address add failed");
309-
return ;
327+
return;
310328
}
311329
if (renewTimer) {
312330
// translate seconds to 100ms ticks
@@ -316,7 +334,6 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
316334
renewTimer = 0xfffffffe;
317335
}
318336
}
319-
tr_debug("Added new address");
320337
address_entry->state_timer = renewTimer;
321338
address_entry->cb = thread_dhcpv6_renew;
322339
}

0 commit comments

Comments
 (0)