@@ -101,6 +101,7 @@ typedef struct {
101101 uint16_t indirect_big_packet_threshold ;
102102 uint16_t max_indirect_big_packets_total ;
103103 uint16_t max_indirect_small_packets_per_child ;
104+ uint32_t last_rx_high_priority ;
104105 bool fragmenter_active ; /*!< Fragmenter state */
105106 adaptation_etx_update_cb * etx_update_cb ;
106107 mpx_api_t * mpx_api ;
@@ -109,6 +110,7 @@ typedef struct {
109110} fragmenter_interface_t ;
110111
111112#define LOWPAN_ACTIVE_UNICAST_ONGOING_MAX 10
113+ #define LOWPAN_HIGH_PRIORITY_STATE_LENGTH 50 //5 seconds 100us ticks
112114
113115/* Minimum buffer amount and memory size to ensure operation even in out of memory situation
114116 */
@@ -155,6 +157,7 @@ static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interf
155157static fragmenter_tx_entry_t * lowpan_adaptation_indirect_mac_data_request_active (fragmenter_interface_t * interface_ptr , fragmenter_tx_entry_t * tx_ptr );
156158
157159static bool lowpan_buffer_tx_allowed (fragmenter_interface_t * interface_ptr , buffer_t * buf );
160+ static bool lowpan_adaptation_purge_from_mac (struct protocol_interface_info_entry * cur , fragmenter_interface_t * interface_ptr , uint8_t msduhandle );
158161
159162static void lowpan_adaptation_etx_update_cb (protocol_interface_info_entry_t * cur , buffer_t * buf , const mcps_data_conf_t * confirm )
160163{
@@ -251,13 +254,41 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
251254 protocol_stats_update (STATS_AL_TX_QUEUE_SIZE , interface_ptr -> directTxQueue_size );
252255}
253256
257+ static void lowpan_adaptation_tx_queue_write_to_front (fragmenter_interface_t * interface_ptr , buffer_t * buf )
258+ {
259+ buffer_t * lower_priority_buf = NULL ;
260+
261+ ns_list_foreach (buffer_t , cur , & interface_ptr -> directTxQueue ) {
262+
263+ if (cur -> priority <= buf -> priority ) {
264+ lower_priority_buf = cur ;
265+ break ;
266+ }
267+ }
268+
269+ if (lower_priority_buf ) {
270+ ns_list_add_before (& interface_ptr -> directTxQueue , lower_priority_buf , buf );
271+ } else {
272+ ns_list_add_to_end (& interface_ptr -> directTxQueue , buf );
273+ }
274+ interface_ptr -> directTxQueue_size ++ ;
275+ lowpan_adaptation_tx_queue_level_update (interface_ptr );
276+ protocol_stats_update (STATS_AL_TX_QUEUE_SIZE , interface_ptr -> directTxQueue_size );
277+ }
278+
254279static buffer_t * lowpan_adaptation_tx_queue_read (fragmenter_interface_t * interface_ptr )
255280{
256281 // Currently this function is called only when data confirm is received for previously sent packet.
257282 if (!interface_ptr -> directTxQueue_size ) {
258283 return NULL ;
259284 }
260285 ns_list_foreach_safe (buffer_t , buf , & interface_ptr -> directTxQueue ) {
286+
287+ if (buf -> link_specific .ieee802_15_4 .requestAck && interface_ptr -> last_rx_high_priority && buf -> priority < QOS_EXPEDITE_FORWARD ) {
288+ //Stop reading at this point when Priority is not enough big
289+ return NULL ;
290+ }
291+
261292 if (lowpan_buffer_tx_allowed (interface_ptr , buf )) {
262293 ns_list_remove (& interface_ptr -> directTxQueue , buf );
263294 interface_ptr -> directTxQueue_size -- ;
@@ -460,6 +491,7 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id)
460491 buffer_free_list (& interface_ptr -> directTxQueue );
461492 interface_ptr -> directTxQueue_size = 0 ;
462493 interface_ptr -> directTxQueue_level = 0 ;
494+ interface_ptr -> last_rx_high_priority = 0 ;
463495
464496 return 0 ;
465497}
@@ -1075,9 +1107,110 @@ static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buff
10751107 if (is_unicast && lowpan_adaptation_is_destination_tx_active (& interface_ptr -> activeUnicastList , buf )) {
10761108 return false;
10771109 }
1110+
1111+ if (is_unicast && interface_ptr -> last_rx_high_priority && buf -> priority < QOS_EXPEDITE_FORWARD ) {
1112+ return false;
1113+ }
1114+ return true;
1115+ }
1116+
1117+ static uint32_t lowpan_adaptation_time_stamp_diff (uint32_t compare_stamp )
1118+ {
1119+ if (protocol_core_monotonic_time < compare_stamp ) {
1120+ return compare_stamp - protocol_core_monotonic_time ;
1121+ }
1122+ return protocol_core_monotonic_time - compare_stamp ;
1123+ }
1124+
1125+ static bool lowpan_adaptation_high_priority_state_exit (fragmenter_interface_t * interface_ptr )
1126+ {
1127+ if (!interface_ptr -> last_rx_high_priority || lowpan_adaptation_time_stamp_diff (interface_ptr -> last_rx_high_priority ) < LOWPAN_HIGH_PRIORITY_STATE_LENGTH ) {
1128+ return false;
1129+ }
1130+
1131+ //Check First buffer_from tx queue
1132+ buffer_t * buf = ns_list_get_first (& interface_ptr -> directTxQueue );
1133+ if (buf && buf -> priority == QOS_EXPEDITE_FORWARD ) {
1134+ //TX queue must not include any
1135+ return false;
1136+ }
1137+
1138+ //Check If we have a Any active TX process still active
1139+ ns_list_foreach (fragmenter_tx_entry_t , entry , & interface_ptr -> activeUnicastList ) {
1140+ if (entry -> buf -> priority == QOS_EXPEDITE_FORWARD ) {
1141+ return false;
1142+ }
1143+ }
1144+
1145+ //Disable High Priority Mode
1146+ if (interface_ptr -> mpx_api ) {
1147+ interface_ptr -> mpx_api -> mpx_priority_mode_set (interface_ptr -> mpx_api , false);
1148+ }
1149+ interface_ptr -> last_rx_high_priority = 0 ;
10781150 return true;
10791151}
10801152
1153+ static void lowpan_adaptation_high_priority_state_enable (protocol_interface_info_entry_t * cur , fragmenter_interface_t * interface_ptr )
1154+ {
1155+
1156+ if (!interface_ptr -> last_rx_high_priority ) {
1157+ // MPX enaled stack must inform MPX to priority enable
1158+ if (interface_ptr -> mpx_api ) {
1159+ interface_ptr -> mpx_api -> mpx_priority_mode_set (interface_ptr -> mpx_api , true);
1160+ }
1161+ //Purge Active tx queue's all possible's
1162+ if (!interface_ptr -> fragmenter_active ) {
1163+ //Purge Only When Fragmenter is not active
1164+ ns_list_foreach_reverse_safe (fragmenter_tx_entry_t , entry , & interface_ptr -> activeUnicastList ) {
1165+
1166+ if (lowpan_adaptation_purge_from_mac (cur , interface_ptr , entry -> buf -> seq )) {
1167+ buffer_t * buf = entry -> buf ;
1168+ ns_list_remove (& interface_ptr -> activeUnicastList , entry );
1169+ interface_ptr -> activeTxList_size -- ;
1170+ ns_dyn_mem_free (entry );
1171+ //Add message to tx queue front based on priority. Now same priority at buf is prioritised at order
1172+ lowpan_adaptation_tx_queue_write_to_front (interface_ptr , buf );
1173+ random_early_detetction_aq_calc (cur -> random_early_detection , interface_ptr -> directTxQueue_size );
1174+ }
1175+ }
1176+ }
1177+ }
1178+
1179+ //Store timestamp for indicate last RX High Priority message
1180+ interface_ptr -> last_rx_high_priority = protocol_core_monotonic_time ? protocol_core_monotonic_time : 1 ;
1181+
1182+ }
1183+
1184+
1185+ static void lowpan_adaptation_priority_status_update (protocol_interface_info_entry_t * cur , fragmenter_interface_t * interface_ptr , buffer_priority_t priority )
1186+ {
1187+ if (priority == QOS_EXPEDITE_FORWARD ) {
1188+ lowpan_adaptation_high_priority_state_enable (cur , interface_ptr );
1189+ } else {
1190+ //Let check can we disable possible High Priority state
1191+ lowpan_adaptation_high_priority_state_exit (interface_ptr );
1192+ }
1193+ }
1194+
1195+ void lowpan_adaptation_interface_slow_timer (protocol_interface_info_entry_t * cur )
1196+ {
1197+ fragmenter_interface_t * interface_ptr = lowpan_adaptation_interface_discover (cur -> id );
1198+ if (!interface_ptr ) {
1199+ return ;
1200+ }
1201+
1202+ if (lowpan_adaptation_high_priority_state_exit (interface_ptr )) {
1203+ //Activate Packets from TX queue
1204+ buffer_t * buf_from_queue = lowpan_adaptation_tx_queue_read (interface_ptr );
1205+ while (buf_from_queue ) {
1206+ lowpan_adaptation_interface_tx (cur , buf_from_queue );
1207+ buf_from_queue = lowpan_adaptation_tx_queue_read (interface_ptr );
1208+ }
1209+ //Update Average QUEUE
1210+ random_early_detetction_aq_calc (cur -> random_early_detection , interface_ptr -> directTxQueue_size );
1211+ }
1212+ }
1213+
10811214int8_t lowpan_adaptation_interface_tx (protocol_interface_info_entry_t * cur , buffer_t * buf )
10821215{
10831216 bool is_room_for_new_message ;
@@ -1105,6 +1238,8 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
11051238 buffer_priority_set (buf , QOS_HIGH );
11061239 }
11071240
1241+ //Update priority status
1242+ lowpan_adaptation_priority_status_update (cur , interface_ptr , buf -> priority );
11081243
11091244 //Check packet size
11101245 bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu (cur , buf , interface_ptr );
@@ -1409,6 +1544,8 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
14091544 }
14101545 // When confirmation is for direct transmission, push all allowed buffers to MAC
14111546 if (active_direct_confirm == true) {
1547+ //Check Possibility for exit from High Priority state
1548+ lowpan_adaptation_high_priority_state_exit (interface_ptr );
14121549 buffer_t * buf_from_queue = lowpan_adaptation_tx_queue_read (interface_ptr );
14131550 while (buf_from_queue ) {
14141551 lowpan_adaptation_interface_tx (cur , buf_from_queue );
0 commit comments