@@ -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 */
112112static 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 */
116116static 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 */
128128static 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 );
130130static void lowpan_adaptation_data_process_clean (fragmenter_interface_t * interface_ptr , fragmenter_tx_entry_t * tx_ptr , uint8_t socket_event );
131131static uint8_t map_mlme_status_to_socket_event (uint8_t mlme_status );
132132static 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
139139static 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+
141143static 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
589588static 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+
939977int8_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)
11071144static 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
12451288static 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;
0 commit comments