4040#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
4141#include "lowpan_adaptation_interface.h"
4242#include "MLE/mle.h"
43+ #include "Service_Libs/mle_service/mle_service_api.h"
44+ #include "Common_Protocols/icmpv6.h"
4345#ifdef HAVE_RPL
4446#include "RPL/rpl_data.h"
4547#endif
@@ -787,49 +789,110 @@ static fragmenter_tx_entry_t *lowpan_adaptation_indirect_first_cached_request_ge
787789 return NULL ;
788790}
789791
790- static void lowpan_adaptation_make_room_for_small_packet (protocol_interface_info_entry_t * cur , fragmenter_interface_t * interface_ptr , mac_neighbor_table_entry_t * neighbour_to_count )
792+ static bool lowpan_adaptation_is_priority_message (buffer_t * buf )
793+ {
794+ // Mle messages
795+ if (buf -> dst_sa .port == MLE_ALLOCATED_PORT || buf -> src_sa .port == MLE_ALLOCATED_PORT ) {
796+ return true;
797+ }
798+
799+ // Management messages: address solicit, response, query, notification
800+ if (buf -> dst_sa .port == THREAD_MANAGEMENT_PORT || buf -> src_sa .port == THREAD_MANAGEMENT_PORT ) {
801+ return true;
802+ }
803+
804+ // dhcp messages
805+ if (buf -> dst_sa .port == DHCPV6_SERVER_PORT || buf -> src_sa .port == DHCPV6_SERVER_PORT ) {
806+ return true;
807+ }
808+
809+ if (buf -> dst_sa .port == DHCPV6_CLIENT_PORT || buf -> src_sa .port == DHCPV6_CLIENT_PORT ) {
810+ return true;
811+ }
812+
813+ // ICMPv6 messages
814+ if (buf -> options .type == ICMPV6_TYPE_ERROR_DESTINATION_UNREACH ||
815+ buf -> options .type == ICMPV6_TYPE_ERROR_PACKET_TOO_BIG ||
816+ buf -> options .type == ICMPV6_TYPE_ERROR_TIME_EXCEEDED ||
817+ buf -> options .type == ICMPV6_TYPE_ERROR_PARAMETER_PROBLEM ) {
818+ return true;
819+ }
820+ return false;
821+ }
822+
823+ static bool lowpan_adaptation_make_room_for_small_packet (protocol_interface_info_entry_t * cur , fragmenter_interface_t * interface_ptr , mac_neighbor_table_entry_t * neighbour_to_count , fragmenter_tx_entry_t * new_entry )
791824{
792825 if (interface_ptr -> max_indirect_small_packets_per_child == 0 ) {
793- return ;
826+ return false ;
794827 }
795828
796829 uint_fast16_t count = 0 ;
830+ fragmenter_tx_entry_t * low_priority_msg_ptr = NULL ;
797831
798832 ns_list_foreach_reverse_safe (fragmenter_tx_entry_t , tx_entry , & interface_ptr -> indirect_tx_queue ) {
799833 mac_neighbor_table_entry_t * tx_neighbour = mac_neighbor_table_address_discover (mac_neighbor_info (cur ), tx_entry -> buf -> dst_sa .address + 2 , tx_entry -> buf -> dst_sa .addr_type );
800834 if (tx_neighbour == neighbour_to_count && buffer_data_length (tx_entry -> buf ) <= interface_ptr -> indirect_big_packet_threshold ) {
835+ if (!lowpan_adaptation_is_priority_message (tx_entry -> buf )) {
836+ // if there is sub priorities inside message example age here you could compare
837+ low_priority_msg_ptr = tx_entry ;
838+ }
801839 if (++ count >= interface_ptr -> max_indirect_small_packets_per_child ) {
802- tr_debug_extra ("Purge seq: %d" , tx_entry -> buf -> seq );
803- if (lowpan_adaptation_indirect_queue_free_message (cur , interface_ptr , tx_entry ) == false) {
840+ if (!low_priority_msg_ptr ) {
841+ // take last entry if no low priority entry found
842+ if (lowpan_adaptation_is_priority_message (new_entry -> buf )) {
843+ low_priority_msg_ptr = tx_entry ;
844+ } else {
845+ return false;
846+ }
847+ }
848+ tr_debug_extra ("Purge seq: %d" , low_priority_msg_ptr -> buf -> seq );
849+ if (lowpan_adaptation_indirect_queue_free_message (cur , interface_ptr , low_priority_msg_ptr ) == false) {
804850 /* entry could not be purged from mac, try next entry */
805851 tr_debug_extra ("Purge failed, try next" );
806852 count -- ;
807853 }
854+ low_priority_msg_ptr = NULL ;
808855 }
809856 }
810857 }
858+ return true;
811859}
812860
813- static void lowpan_adaptation_make_room_for_big_packet (struct protocol_interface_info_entry * cur , fragmenter_interface_t * interface_ptr )
861+ static bool lowpan_adaptation_make_room_for_big_packet (struct protocol_interface_info_entry * cur , fragmenter_interface_t * interface_ptr , fragmenter_tx_entry_t * new_entry )
814862{
815863 if (interface_ptr -> max_indirect_big_packets_total == 0 ) {
816- return ;
864+ return false ;
817865 }
818866
819867 uint_fast16_t count = 0 ;
868+ fragmenter_tx_entry_t * low_priority_msg_ptr = NULL ;
820869
821870 ns_list_foreach_reverse_safe (fragmenter_tx_entry_t , tx_entry , & interface_ptr -> indirect_tx_queue ) {
822871 if (buffer_data_length (tx_entry -> buf ) > interface_ptr -> indirect_big_packet_threshold ) {
872+ if (!lowpan_adaptation_is_priority_message (tx_entry -> buf )) {
873+ // if there is sub priorities inside message example age here you could compare
874+ low_priority_msg_ptr = tx_entry ;
875+ }
823876 if (++ count >= interface_ptr -> max_indirect_big_packets_total ) {
824- tr_debug_extra ("Purge seq: %d" , tx_entry -> buf -> seq );
825- if (lowpan_adaptation_indirect_queue_free_message (cur , interface_ptr , tx_entry ) == false) {
826- tr_debug ("Purge failed, try next entry" );
877+ if (!low_priority_msg_ptr ) {
878+ // take last entry if no low priority entry found
879+ if (lowpan_adaptation_is_priority_message (new_entry -> buf )) {
880+ low_priority_msg_ptr = tx_entry ;
881+ } else {
882+ return false;
883+ }
884+ }
885+ tr_debug_extra ("Purge seq: %d" , low_priority_msg_ptr -> buf -> seq );
886+ if (lowpan_adaptation_indirect_queue_free_message (cur , interface_ptr , low_priority_msg_ptr ) == false) {
887+ tr_debug_extra ("Purge failed, try next entry" );
827888 /* entry could not be purged from mac, try next entry */
828889 count -- ;
829890 }
891+ low_priority_msg_ptr = NULL ;
830892 }
831893 }
832894 }
895+ return true;
833896}
834897
835898static void lowpan_data_request_to_mac (protocol_interface_info_entry_t * cur , buffer_t * buf , fragmenter_tx_entry_t * tx_ptr , fragmenter_interface_t * interface_ptr )
@@ -868,6 +931,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
868931
869932int8_t lowpan_adaptation_interface_tx (protocol_interface_info_entry_t * cur , buffer_t * buf )
870933{
934+ bool is_room_for_new_message ;
871935 if (!buf ) {
872936 return -1 ;
873937 }
@@ -940,9 +1004,9 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
9401004
9411005 // Make room for new message if needed */
9421006 if (buffer_data_length (buf ) <= interface_ptr -> indirect_big_packet_threshold ) {
943- lowpan_adaptation_make_room_for_small_packet (cur , interface_ptr , neigh_entry_ptr );
1007+ is_room_for_new_message = lowpan_adaptation_make_room_for_small_packet (cur , interface_ptr , neigh_entry_ptr , tx_ptr );
9441008 } else {
945- lowpan_adaptation_make_room_for_big_packet (cur , interface_ptr );
1009+ is_room_for_new_message = lowpan_adaptation_make_room_for_big_packet (cur , interface_ptr , tx_ptr );
9461010 }
9471011
9481012 if (lowpan_adaptation_indirect_mac_data_request_active (interface_ptr , tx_ptr )) {
@@ -951,7 +1015,15 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
9511015 tx_ptr -> indirect_data_cached = true;
9521016 }
9531017
954- ns_list_add_to_end (& interface_ptr -> indirect_tx_queue , tx_ptr );
1018+ if (is_room_for_new_message ) {
1019+ ns_list_add_to_end (& interface_ptr -> indirect_tx_queue , tx_ptr );
1020+ } else {
1021+ if (tx_ptr -> fragmenter_buf ) {
1022+ ns_dyn_mem_free (tx_ptr -> fragmenter_buf );
1023+ }
1024+ ns_dyn_mem_free (tx_ptr );
1025+ goto tx_error_handler ;
1026+ }
9551027
9561028 // Check if current message can be delivered to MAC or should some cached message be delivered first
9571029 tx_ptr_cached = lowpan_adaptation_indirect_first_cached_request_get (interface_ptr , tx_ptr );
0 commit comments