Skip to content

Commit 96e86b6

Browse files
implemented Sleepy End Device child update requests. (#1570)
SED sends periodic child update requests to parent before MLE timeout. This helps the SED to find a new parent if parent has removed it from neighbour table during partition change.
1 parent 33cb7cb commit 96e86b6

File tree

7 files changed

+51
-140
lines changed

7 files changed

+51
-140
lines changed

source/6LoWPAN/Thread/thread_bootstrap.c

Lines changed: 6 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ static void thread_bootsrap_network_discovery_failure(int8_t interface_id);
112112

113113
static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur);
114114
static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info);
115-
static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64);
116115

117116

118117

@@ -134,37 +133,6 @@ static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t
134133
thread_reset_neighbour_info(cur_interface, cur);
135134
}
136135

137-
138-
static bool thread_child_keep_alive_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
139-
{
140-
uint8_t mac64[8];
141-
uint8_t *ll64_ptr = mle_service_get_msg_destination_address_pointer(msgId);
142-
143-
memcpy(mac64, ll64_ptr + 8, 8);
144-
mac64[0] ^= 2;
145-
146-
mle_neigh_table_entry_t *neig_info = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG);
147-
148-
if (!neig_info) {
149-
return false;//Why entry is removed before timeout??
150-
}
151-
152-
153-
if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) {
154-
return false;
155-
}
156-
157-
158-
if (usedAllRetries) {
159-
160-
//GET entry
161-
mle_class_remove_entry(interface_id, neig_info);
162-
return false;
163-
}
164-
165-
return true;
166-
}
167-
168136
int8_t thread_mle_class_init(int8_t interface_id)
169137
{
170138
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
@@ -182,7 +150,7 @@ int8_t thread_mle_class_init(int8_t interface_id)
182150
return -1;
183151
}
184152

185-
if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_child_keep_alive, &thread_interface_is_active) != 0) {
153+
if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_host_bootstrap_child_update, &thread_interface_is_active) != 0) {
186154
return -1;
187155
}
188156

@@ -231,68 +199,6 @@ uint8_t thread_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur)
231199
return mle_mode;
232200
}
233201

234-
static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64)
235-
{
236-
mle_message_timeout_params_t timeout;
237-
uint8_t ll64[16];
238-
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
239-
uint32_t keySequence;
240-
uint16_t bufId;
241-
uint8_t mode;
242-
if (!cur) {
243-
return -1;
244-
}
245-
246-
if (!thread_info(cur)) {
247-
return -1;
248-
}
249-
250-
//routers do not send keep alive
251-
if (thread_i_am_router(cur)){
252-
return -1;
253-
}
254-
255-
tr_debug("Child Keep Alive");
256-
bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false,MLE_COMMAND_CHILD_UPDATE_REQUEST);
257-
if (bufId == 0) {
258-
return -1;
259-
}
260-
261-
thread_management_get_current_keysequence(cur->id, &keySequence);
262-
mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
263-
mode = thread_mode_get_by_interface_ptr(cur);
264-
265-
uint8_t *ptr = mle_service_get_data_pointer(bufId);
266-
ptr = mle_general_write_source_address(ptr, cur);
267-
ptr = mle_tlv_write_mode(ptr, mode);
268-
269-
ptr = thread_leader_data_tlv_write(ptr, cur);
270-
271-
//Set Addresss TLV
272-
if ((mode & MLE_FFD_DEV) == 0) {
273-
ptr = thread_address_registration_tlv_write(ptr, cur);
274-
}
275-
276-
memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
277-
memcpy(&ll64[8], mac64, 8);
278-
ll64[8] ^= 2;
279-
if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
280-
tr_debug("Buffer overflow at message write");
281-
}
282-
timeout.retrans_max = 3;
283-
timeout.timeout_init = 1;
284-
timeout.timeout_max = 4;
285-
timeout.delay = MLE_NO_DELAY;
286-
287-
//SET Destination address
288-
mle_service_set_msg_destination_address(bufId, ll64);
289-
//Set Callback
290-
mle_service_set_packet_callback(bufId, thread_child_keep_alive_callback);
291-
mle_service_set_msg_timeout_parameters(bufId, &timeout);
292-
mle_service_send_message(bufId);
293-
return 0;
294-
}
295-
296202
/**
297203
* Return lower (worse) of the two margins.
298204
*/
@@ -1014,6 +920,7 @@ static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t
1014920
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE;
1015921
//SET Sleepy Host To RX on Idle mode for bootsrap
1016922
nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
923+
cur->thread_info->childUpdateReqTimer = 0.8 * cur->thread_info->host_link_timeout;
1017924
} else {
1018925
tr_debug("Set End node Mode");
1019926
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
@@ -1134,7 +1041,9 @@ void thread_tasklet(arm_event_s *event)
11341041

11351042
case THREAD_CHILD_UPDATE:
11361043
tr_debug_extra("Thread SM THREAD_CHILD_UPDATE");
1137-
thread_bootstrap_child_update(cur);
1044+
if (thread_info(cur)->thread_endnode_parent) {
1045+
thread_host_bootstrap_child_update(cur->id, cur->thread_info->thread_endnode_parent->mac64);
1046+
}
11381047
break;
11391048
case THREAD_ANNOUNCE_ACTIVE: {
11401049
tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE");
@@ -2333,21 +2242,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
23332242

23342243
void thread_bootstrap_child_update_trig(protocol_interface_info_entry_t *cur)
23352244
{
2336-
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
2337-
if (cur->thread_info->thread_endnode_parent == NULL) {
2338-
return;
2339-
}
2340-
2341-
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
2342-
//Set Pending if earlier proces is already started
2343-
cur->thread_info->thread_endnode_parent->childUpdatePending = true;
2344-
return;
2345-
}
2346-
//Trig event
2347-
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
2348-
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
2349-
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
2350-
2245+
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && cur->thread_info->thread_endnode_parent) {
23512246
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
23522247
}
23532248
}

source/6LoWPAN/Thread/thread_common.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,6 @@ static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur,
880880
if (cur->thread_info->childUpdateReqTimer == -1) {
881881
return;
882882
}
883-
884883
if (cur->thread_info->childUpdateReqTimer > seconds) {
885884
cur->thread_info->childUpdateReqTimer -= seconds;
886885
} else {

source/6LoWPAN/Thread/thread_common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ typedef struct thread_parent_info_s {
174174
uint8_t pathCostToLeader;
175175
bool childUpdatePending: 1;
176176
bool childUpdateProcessActive: 1;
177-
bool childUpdateProcessStatus: 1;
178177
} thread_parent_info_t;
179178

180179

@@ -289,6 +288,7 @@ typedef struct thread_info_s {
289288
uint16_t reedJitterTimer;
290289
uint16_t routerIdReqCoapID; // COAP msg id of RouterID request
291290
int16_t childUpdateReqTimer;
291+
uint16_t childUpdateReqMsgId;
292292
uint16_t proactive_an_timer;
293293
//uint8_t lastValidRouteMask[8];
294294
int8_t interface_id; //Thread Interface ID

source/6LoWPAN/Thread/thread_host_bootstrap.c

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,45 +1106,35 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t
11061106
static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties)
11071107
{
11081108
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
1109-
(void)msgId;
11101109
if (!cur || !cur->thread_info->thread_endnode_parent) {
11111110
return false;
11121111
}
1113-
tr_debug("Child Update CB");
1114-
if (cur->thread_info->thread_endnode_parent->childUpdateProcessStatus) {
1115-
//This process is ready
1116-
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
1117-
if (!cur->thread_info->thread_endnode_parent->childUpdatePending) {
1118-
1119-
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
1120-
//Disable Poll
1121-
mac_data_poll_protocol_poll_mode_decrement(cur);
1122-
tr_debug("Child Update ready");
1123-
} else {
1124-
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
1125-
tr_debug("Child Update Pending");
1126-
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
1127-
}
1112+
if (msgId != cur->thread_info->childUpdateReqMsgId) {
1113+
//Wrong message id
11281114
return false;
11291115
}
11301116

11311117
if (usedAllRerties) {
1132-
1118+
tr_debug("Child Update timed out");
11331119
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
11341120
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
1135-
cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
11361121
mac_data_poll_protocol_poll_mode_decrement(cur);
11371122
thread_bootstrap_reset_restart(cur->id);
11381123
tr_debug("Restart attachment");
11391124
return false;
11401125
}
1126+
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
1127+
// we have not received response so re-send
1128+
return true;
1129+
}
11411130

1142-
return true;
1131+
return false;
11431132

11441133
}
11451134

1146-
int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
1135+
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64)
11471136
{
1137+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
11481138
mle_message_timeout_params_t timeout;
11491139
uint8_t mode;
11501140
uint32_t keySequence;
@@ -1153,6 +1143,16 @@ int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
11531143
return -1;
11541144
}
11551145

1146+
if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
1147+
//Set Pending if earlier process is already started
1148+
cur->thread_info->thread_endnode_parent->childUpdatePending = true;
1149+
return -1;
1150+
}
1151+
//Trig event
1152+
cur->thread_info->thread_endnode_parent->childUpdatePending = false;
1153+
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
1154+
1155+
11561156
tr_debug("Child Update Request");
11571157

11581158
mode = thread_mode_get_by_interface_ptr(cur);
@@ -1169,11 +1169,12 @@ int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
11691169

11701170
uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(bufId);
11711171
memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
1172-
memcpy(address_ptr + 8, cur->thread_info->thread_endnode_parent->mac64, 8);
1172+
memcpy(address_ptr + 8, mac64, 8);
11731173
address_ptr[8] ^= 2;
11741174

11751175
uint8_t *ptr = mle_service_get_data_pointer(bufId);
11761176
ptr = mle_tlv_write_mode(ptr, mode);
1177+
ptr = mle_general_write_source_address(ptr, cur);
11771178
ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
11781179
ptr = thread_leader_data_tlv_write(ptr, cur);
11791180

@@ -1194,6 +1195,7 @@ int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
11941195
thread_end_device_mode_set(cur, false);
11951196
}
11961197
mac_data_poll_init_protocol_poll(cur);
1198+
cur->thread_info->childUpdateReqMsgId = bufId;
11971199
mle_service_set_packet_callback(bufId, thread_child_update_timeout_cb);
11981200
mle_service_set_msg_timeout_parameters(bufId, &timeout);
11991201
mle_service_send_message(bufId);

source/6LoWPAN/Thread/thread_host_bootstrap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct protocol_interface_info_entry;
4242
struct mle_security_header;
4343

4444
void thread_network_attach_start(struct protocol_interface_info_entry *cur);
45-
int8_t thread_bootstrap_child_update(struct protocol_interface_info_entry *cur);
45+
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64);
4646
int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge);
4747
void thread_child_set_default_route(struct protocol_interface_info_entry *cur);
4848

source/6LoWPAN/Thread/thread_mle_message_handler.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
764764
bool leader_data_received;
765765

766766
tr_debug("Child Update Response");
767-
767+
//mle_service_buffer_find
768768
leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
769769
entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
770770

@@ -783,8 +783,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
783783
return;
784784
}
785785

786-
if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
787-
&& (thread_instance_id_matches(cur, &leaderData))) {
786+
if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
788787
thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
789788
} else {
790789
tr_debug("Key ID Mode 2 not used; dropped.");
@@ -796,20 +795,36 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
796795
return;
797796
}
798797

798+
timeout = cur->thread_info->host_link_timeout;
799799
if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
800800
entry_temp->holdTime = 90;
801801
tr_debug("Setting child timeout, value=%"PRIu32, timeout);
802802
mle_entry_timeout_update(entry_temp, timeout);
803-
thread_info(cur)->thread_endnode_parent->childUpdateProcessStatus = true;
804803
}
804+
805805
tr_debug("Keep-Alive -->Respond from Parent");
806806
mle_entry_timeout_refresh(entry_temp);
807807

808808
//Save possible new Leader Data
809809
if (leader_data_received) {
810810
thread_save_leader_data(cur, &leaderData);
811811
}
812+
813+
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
814+
if (cur->thread_info->childUpdateReqTimer < 1) {
815+
cur->thread_info->childUpdateReqTimer = 0.8 * timeout;
816+
}
817+
}
818+
//This process is ready
819+
cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
820+
if (cur->thread_info->thread_endnode_parent->childUpdatePending) {
821+
tr_debug("Child Update Pending");
822+
thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
823+
return;
824+
}
825+
812826
mac_data_poll_protocol_poll_mode_decrement(cur);
827+
813828
}
814829

815830
#endif

test/nanostack/unittest/stub/thread_host_bootstrap_stub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
8383
{
8484
}
8585

86-
int8_t thread_bootstrap_child_update(protocol_interface_info_entry_t *cur)
86+
int8_t thread_host_bootstrap_child_update(int8_t interface_id, const uint8_t *mac64)
8787
{
8888
return 0;
8989
}

0 commit comments

Comments
 (0)