Skip to content

Commit 96ffe92

Browse files
author
Jarkko Paso
authored
Adaptation layer to support multiple simultaneous unicast transmissions (#2243)
* Adaptation layer to support multiple simultaneous unicast transmissions * Prevent all frames when fragmenter active
1 parent 45f8519 commit 96ffe92

File tree

2 files changed

+95
-52
lines changed

2 files changed

+95
-52
lines changed

source/6LoWPAN/adaptation_interface.c

Lines changed: 89 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ typedef struct {
8989
fragmenter_tx_list_t indirect_tx_queue;
9090
uint8_t *fragment_indirect_tx_buffer; //Used for write fragmentation header
9191
uint16_t mtu_size;
92-
fragmenter_tx_entry_t active_unicast_tx_buf; //Current active direct unicast tx process
9392
fragmenter_tx_entry_t active_broadcast_tx_buf; //Current active direct broadcast tx process
93+
fragmenter_tx_list_t activeUnicastList; //Unicast packets waiting data confirmation from MAC
9494
buffer_list_t directTxQueue; //Waiting free tx process
9595
uint16_t directTxQueue_size;
9696
uint16_t indirect_big_packet_threshold;
@@ -110,7 +110,7 @@ static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t inter
110110

111111
/* Interface direct message pending queue functions */
112112
static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf);
113-
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur);
113+
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr);
114114

115115
/* Data direction and message length validation */
116116
static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *mle_entry);
@@ -126,7 +126,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
126126

127127
/* Tx confirmation local functions */
128128
static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf);
129-
static fragmenter_tx_entry_t *lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue);
129+
static fragmenter_tx_entry_t *lowpan_listed_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue);
130130
static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event);
131131
static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status);
132132
static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr);
@@ -138,6 +138,8 @@ static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interf
138138

139139
static fragmenter_tx_entry_t *lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
140140

141+
static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buffer_t *buf);
142+
141143
static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm)
142144
{
143145
switch (confirm->status) {
@@ -221,18 +223,14 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
221223
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
222224
}
223225

224-
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur)
226+
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr)
225227
{
226-
/* Currently this function is called only when data confirm is received for previously sent packet.
227-
* Data confirm has freed the corresponding "active buffer" and this function will look for new buffer to be set as active buffer.
228-
*/
228+
// Currently this function is called only when data confirm is received for previously sent packet.
229+
if (!interface_ptr->directTxQueue_size) {
230+
return NULL;
231+
}
229232
ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) {
230-
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
231-
//Check that we not trig second active fragmentation process
232-
if (fragmented_needed && interface_ptr->fragmenter_active) {
233-
tr_debug("Do not trig Second active fragmentation");
234-
} else if ((buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_unicast_tx_buf.buf)
235-
|| (!buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_broadcast_tx_buf.buf)) {
233+
if (lowpan_buffer_tx_allowed(interface_ptr, buf)) {
236234
ns_list_remove(&interface_ptr->directTxQueue, buf);
237235
interface_ptr->directTxQueue_size--;
238236
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
@@ -292,7 +290,7 @@ static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf)
292290

293291

294292

295-
static fragmenter_tx_entry_t *lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue)
293+
static fragmenter_tx_entry_t *lowpan_listed_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue)
296294
{
297295
ns_list_foreach(fragmenter_tx_entry_t, entry, indirect_tx_queue) {
298296
if (entry->buf->seq == handle) {
@@ -310,17 +308,17 @@ static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *int
310308
uint8_t handle;
311309
while (!valid_info) {
312310
handle = interface_ptr->msduHandle++;
313-
if (!lowpan_active_tx_handle_verify(handle, interface_ptr->active_unicast_tx_buf.buf)
311+
if (!lowpan_listed_tx_handle_verify(handle, &interface_ptr->activeUnicastList)
314312
&& !lowpan_active_tx_handle_verify(handle, interface_ptr->active_broadcast_tx_buf.buf)
315-
&& !lowpan_indirect_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) {
313+
&& !lowpan_listed_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) {
316314
valid_info = true;
317315
}
318316
}
319317
return handle;
320318

321319
}
322320

323-
static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list, fragmenter_tx_entry_t *entry)
321+
static void lowpan_list_entry_free(fragmenter_tx_list_t *list, fragmenter_tx_entry_t *entry)
324322
{
325323
ns_list_remove(list, entry);
326324
if (entry->buf) {
@@ -330,11 +328,11 @@ static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list, fragmenter_tx
330328
ns_dyn_mem_free(entry);
331329
}
332330

333-
static void lowpan_indirect_queue_free(fragmenter_tx_list_t *list)
331+
static void lowpan_list_free(fragmenter_tx_list_t *list)
334332
{
335333
while (!ns_list_is_empty(list)) {
336334
fragmenter_tx_entry_t *entry = ns_list_get_first(list);
337-
lowpan_indirect_entry_free(list, entry);
335+
lowpan_list_entry_free(list, entry);
338336
}
339337
}
340338

@@ -365,6 +363,7 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si
365363

366364
ns_list_init(&interface_ptr->indirect_tx_queue);
367365
ns_list_init(&interface_ptr->directTxQueue);
366+
ns_list_init(&interface_ptr->activeUnicastList);
368367

369368
ns_list_add_to_end(&fragmenter_interface_list, interface_ptr);
370369

@@ -389,11 +388,11 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id)
389388

390389
ns_list_remove(&fragmenter_interface_list, interface_ptr);
391390
//free active tx process
392-
lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf);
391+
lowpan_list_free(&interface_ptr->activeUnicastList);
393392
lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf);
394393

395394
//Free Indirect entry
396-
lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue);
395+
lowpan_list_free(&interface_ptr->indirect_tx_queue);
397396

398397
buffer_free_list(&interface_ptr->directTxQueue);
399398

@@ -414,13 +413,13 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
414413
}
415414

416415
//free active tx process
417-
lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf);
416+
lowpan_list_free(&interface_ptr->activeUnicastList);
418417
lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf);
419418
//Clean fragmented message flag
420419
interface_ptr->fragmenter_active = false;
421420

422421
//Free Indirect entry
423-
lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue);
422+
lowpan_list_free(&interface_ptr->indirect_tx_queue);
424423

425424
buffer_free_list(&interface_ptr->directTxQueue);
426425

@@ -588,10 +587,15 @@ static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry
588587

589588
static fragmenter_tx_entry_t *lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast)
590589
{
590+
// For broadcast, the active TX queue is only 1 entry. For unicast, using a list.
591591
fragmenter_tx_entry_t *tx_entry;
592592
if (!indirect) {
593593
if (is_unicast) {
594-
tx_entry = &interface_ptr->active_unicast_tx_buf;
594+
tx_entry = lowpan_indirect_entry_allocate(0);
595+
if (!tx_entry) {
596+
return NULL;
597+
}
598+
ns_list_add_to_end(&interface_ptr->activeUnicastList, tx_entry);
595599
} else {
596600
tx_entry = &interface_ptr->active_broadcast_tx_buf;
597601
}
@@ -936,6 +940,40 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
936940
}
937941
}
938942

943+
static bool lowpan_adaptation_is_destination_tx_active(fragmenter_tx_list_t *list, buffer_t *buf)
944+
{
945+
ns_list_foreach(fragmenter_tx_entry_t, entry, list) {
946+
if (entry->buf) {
947+
if (!memcmp(&entry->buf->dst_sa.address[2], &buf->dst_sa.address[2], 8)) {
948+
return true;
949+
}
950+
}
951+
}
952+
return false;
953+
}
954+
955+
static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buffer_t *buf)
956+
{
957+
bool is_unicast = buf->link_specific.ieee802_15_4.requestAck;
958+
// Indirect allowed always
959+
if (buf->link_specific.ieee802_15_4.indirectTxProcess) {
960+
return true;
961+
}
962+
// Do not accept any other TX when fragmented TX active. Prevents other frames to be sent in between two fragments.
963+
if (interface_ptr->fragmenter_active) {
964+
return false;
965+
}
966+
// Do not accept more than one active broadcast TX
967+
if (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf) {
968+
return false;
969+
}
970+
// Do not accept more than one active unicast TX per destination
971+
if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) {
972+
return false;
973+
}
974+
return true;
975+
}
976+
939977
int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf)
940978
{
941979
bool is_room_for_new_message;
@@ -956,11 +994,10 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
956994
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
957995
bool is_unicast = buf->link_specific.ieee802_15_4.requestAck;
958996
bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess;
959-
if (!indirect) {
960-
if (((is_unicast && interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf)) || (fragmented_needed && interface_ptr->fragmenter_active)) {
961-
lowpan_adaptation_tx_queue_write(interface_ptr, buf);
962-
return 0; //Return here
963-
}
997+
998+
if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) {
999+
lowpan_adaptation_tx_queue_write(interface_ptr, buf);
1000+
return 0;
9641001
}
9651002

9661003
//Allocate Handle
@@ -1107,10 +1144,14 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr)
11071144
static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event)
11081145
{
11091146
buffer_t *buf = tx_ptr->buf;
1147+
11101148
tx_ptr->buf = NULL;
11111149
if (buf->link_specific.ieee802_15_4.indirectTxProcess) {
11121150
//release from list and free entry
1113-
lowpan_indirect_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr);
1151+
lowpan_list_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr);
1152+
} else if (buf->link_specific.ieee802_15_4.requestAck) {
1153+
ns_list_remove(&interface_ptr->activeUnicastList, tx_ptr);
1154+
ns_dyn_mem_free(tx_ptr);
11141155
}
11151156

11161157
socket_tx_buffer_event_and_free(buf, socket_event);
@@ -1131,18 +1172,19 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
11311172
//Check first
11321173
fragmenter_tx_entry_t *tx_ptr;
11331174
bool active_direct_confirm;
1134-
bool is_unicast = true;
1135-
1136-
if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_unicast_tx_buf.buf)) {
1137-
active_direct_confirm = true;
1138-
tx_ptr = &interface_ptr->active_unicast_tx_buf;
1139-
} else if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_broadcast_tx_buf.buf)) {
1175+
if (lowpan_active_tx_handle_verify(confirm->msduHandle, interface_ptr->active_broadcast_tx_buf.buf)) {
11401176
active_direct_confirm = true;
11411177
tx_ptr = &interface_ptr->active_broadcast_tx_buf;
1142-
is_unicast = false;
11431178
} else {
1144-
active_direct_confirm = false;
1145-
tx_ptr = lowpan_indirect_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue);
1179+
tx_ptr = lowpan_listed_tx_handle_verify(confirm->msduHandle, &interface_ptr->activeUnicastList);
1180+
if (tx_ptr) {
1181+
active_direct_confirm = true;
1182+
} else {
1183+
tx_ptr = lowpan_listed_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue);
1184+
if (tx_ptr) {
1185+
active_direct_confirm = false;
1186+
}
1187+
}
11461188
}
11471189

11481190
if (!tx_ptr) {
@@ -1232,14 +1274,15 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
12321274
break;
12331275

12341276
}
1235-
1236-
if ((is_unicast && !interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && !interface_ptr->active_broadcast_tx_buf.buf)) {
1237-
//Read Buffer and trig next direct request
1238-
lowpan_adaptation_interface_tx(cur, lowpan_adaptation_tx_queue_read(interface_ptr, cur));
1277+
// When confirmation is for direct transmission, push all allowed buffers to MAC
1278+
if (active_direct_confirm == true) {
1279+
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1280+
while (buf_from_queue) {
1281+
lowpan_adaptation_interface_tx(cur, buf_from_queue);
1282+
buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1283+
}
12391284
}
1240-
12411285
return 0;
1242-
12431286
}
12441287

12451288
static bool mac_data_is_broadcast_addr(const sockaddr_t *addr)
@@ -1332,7 +1375,7 @@ bool lowpan_adaptation_tx_active(int8_t interface_id)
13321375
{
13331376
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
13341377

1335-
if (!interface_ptr || (!interface_ptr->active_unicast_tx_buf.buf && !interface_ptr->active_broadcast_tx_buf.buf)) {
1378+
if (!interface_ptr || (!ns_list_count(&interface_ptr->activeUnicastList) && !interface_ptr->active_broadcast_tx_buf.buf)) {
13361379
return false;
13371380
}
13381381
return true;

test/nanostack/unittest/6LoWPAN/adaptation_interface/test_adaptation_interface.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ bool test_lowpan_adaptation_interface_tx()
534534
}
535535

536536
test_buf->link_specific.ieee802_15_4.useDefaultPanId = true;
537-
test_buf->link_specific.ieee802_15_4.requestAck = true;
537+
test_buf->link_specific.ieee802_15_4.requestAck = false;
538538

539539
if (0 != lowpan_adaptation_interface_tx(&entry, test_buf)) {
540540
return false;
@@ -546,7 +546,7 @@ bool test_lowpan_adaptation_interface_tx()
546546
test_buf2->dst_sa.addr_type = ADDR_802_15_4_SHORT;
547547

548548
test_buf2->link_specific.ieee802_15_4.useDefaultPanId = true;
549-
test_buf2->link_specific.ieee802_15_4.requestAck = true;
549+
test_buf2->link_specific.ieee802_15_4.requestAck = false;
550550
test_buf2->link_specific.ieee802_15_4.indirectTxProcess = false;
551551
test_buf2->link_specific.ieee802_15_4.rf_channel_switch = true;
552552
test_buf2->link_specific.ieee802_15_4.selected_channel = 12;
@@ -562,7 +562,7 @@ bool test_lowpan_adaptation_interface_tx()
562562

563563
test_buf3->dst_sa.addr_type = ADDR_802_15_4_SHORT;
564564

565-
test_buf3->link_specific.ieee802_15_4.requestAck = true;
565+
test_buf3->link_specific.ieee802_15_4.requestAck = false;
566566
test_buf3->buf_end = 90;
567567
test_buf3->priority = QOS_HIGH;
568568

@@ -791,7 +791,7 @@ bool test_lowpan_adaptation_interface_tx_confirm()
791791
buffer_dyn_stub.buffer_ptr = test_buf;
792792
test_buf->buf_ptr = 10;
793793
test_buf->buf_end = 70;
794-
test_buf->link_specific.ieee802_15_4.requestAck = true;
794+
test_buf->link_specific.ieee802_15_4.requestAck = false;
795795
test_buf->link_specific.ieee802_15_4.key_id_mode =
796796
B_SECURITY_KEY_ID_MODE_DEFAULT;
797797
test_buf->link_specific.ieee802_15_4.rf_channel_switch = true;
@@ -802,7 +802,7 @@ bool test_lowpan_adaptation_interface_tx_confirm()
802802
test_buf2->dst_sa.addr_type = ADDR_802_15_4_SHORT;
803803
test_buf2->buf_ptr = 10;
804804
test_buf2->buf_end = 70;
805-
test_buf2->link_specific.ieee802_15_4.requestAck = true;
805+
test_buf2->link_specific.ieee802_15_4.requestAck = false;
806806
test_buf2->link_specific.ieee802_15_4.rf_channel_switch = true;
807807
test_buf2->link_specific.ieee802_15_4.selected_channel = 12;
808808

@@ -811,7 +811,7 @@ bool test_lowpan_adaptation_interface_tx_confirm()
811811
test_buf3->dst_sa.addr_type = ADDR_802_15_4_SHORT;
812812
test_buf3->buf_ptr = 10;
813813
test_buf3->buf_end = 70;
814-
test_buf3->link_specific.ieee802_15_4.requestAck = true;
814+
test_buf3->link_specific.ieee802_15_4.requestAck = false;
815815
test_buf3->link_specific.ieee802_15_4.indirectTxProcess = true;
816816

817817
entry.mac_api = &api;

0 commit comments

Comments
 (0)