diff --git a/nanostack/nwk_stats_api.h b/nanostack/nwk_stats_api.h index 5b05715d1d35..a59d062e430b 100644 --- a/nanostack/nwk_stats_api.h +++ b/nanostack/nwk_stats_api.h @@ -73,6 +73,7 @@ typedef struct nwk_stats_t { /* MAC */ uint16_t adapt_layer_tx_queue_size; /**< Adaptation layer direct TX queue size. */ uint16_t adapt_layer_tx_queue_peak; /**< Adaptation layer direct TX queue size peak. */ + uint32_t adapt_layer_tx_congestion_drop; /**< Adaptation layer direct TX randon early detection drop packet. */ } nwk_stats_t; /** diff --git a/nanostack/platform/arm_hal_phy.h b/nanostack/platform/arm_hal_phy.h index 7b555ef80012..ec065edc80d1 100644 --- a/nanostack/platform/arm_hal_phy.h +++ b/nanostack/platform/arm_hal_phy.h @@ -175,6 +175,25 @@ typedef enum { MODULATION_INDEX_UNDEFINED ///< Modulation index undefined } phy_modulation_index_e; +/** OFDM option */ +typedef enum { + OFDM_OPTION_1 = 1, ///< OFDM option 1 + OFDM_OPTION_2 = 2, ///< OFDM option 2 + OFDM_OPTION_3 = 3, ///< OFDM option 3 + OFDM_OPTION_4 = 4 ///< OFDM option 4 +} phy_ofdm_option_e; + +/** Modulation and coding scheme (OFDM) */ +typedef enum { + OFDM_MCS_0 = 0, ///< OFDM MCS 0 + OFDM_MCS_1 = 1, ///< OFDM MCS 1 + OFDM_MCS_2 = 2, ///< OFDM MCS 2 + OFDM_MCS_3 = 3, ///< OFDM MCS 3 + OFDM_MCS_4 = 4, ///< OFDM MCS 4 + OFDM_MCS_5 = 5, ///< OFDM MCS 5 + OFDM_MCS_6 = 6 ///< OFDM MCS 6 +} phy_ofdm_mcs_e; + /** * @brief enum phy_802_15_4_mode_t IEEE 802.15.4 mode * @@ -192,6 +211,9 @@ typedef struct phy_rf_channel_configuration_s { uint16_t number_of_channels; ///< Number of channels phy_modulation_e modulation; ///< Modulation scheme phy_modulation_index_e modulation_index; ///< Modulation index + bool fec; ///< Forward error correction, true - enabled, false - disabled + phy_ofdm_option_e ofdm_option; ///< OFDM option + phy_ofdm_mcs_e ofdm_mcs; ///< OFDM modulation and coding scheme } phy_rf_channel_configuration_s; /** Channel page configuration */ diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index 741953b2dec2..408eb7e3e9d4 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -96,7 +96,8 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id); #define BBR_GUA_ROUTE 0x0002 /**< More specific route is added for GUA prefix */ #define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */ #define BBR_DEFAULT_ROUTE 0x0008 /**< Add default route parameter to DIO */ -#define BBR_REQUIRE_DAO_REFRESH 0x0010 /**< Do not increment PAN version number when active forces DAO update from nodes*/ +#define BBR_REQUIRE_DAO_REFRESH 0x0000 /**< Deprecated DAO Refresh is now the default functionality*/ +#define BBR_PERIODIC_VERSION_INC 0x0010 /**< Increment PAN version number Periodically*/ #define BBR_GUA_SLAAC 0x0020 /**< in Global prefix use SLAAC address generation to reduce traffic during bootstrap */ /** diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c index b5043e41a742..a8279994eb35 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan.c @@ -799,15 +799,15 @@ bool protocol_6lowpan_latency_estimate_get(int8_t interface_id, uint32_t *latenc if (cur_interface->eth_mac_api) { // either PPP or Ethernet interface. - latency_estimate = 100; + latency_estimate = 1000; } else if (thread_info(cur_interface)) { // thread network - latency_estimate = 2000; + latency_estimate = 5000; } else if (ws_info(cur_interface)) { latency_estimate = ws_common_latency_estimate_get(cur_interface); } else { // 6LoWPAN ND - latency_estimate = 8000; + latency_estimate = 20000; } if (latency_estimate != 0) { diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index 53ff5ac59f16..25441af0a3fa 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -930,7 +930,7 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin /* TODO - check hard upper limit on registrations? */ if (ws_info(cur_interface)) { - aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64); + aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64, aro_out->lifetime); if (aro_out->status != ARO_SUCCESS) { aro_out->present = true; return true; diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index fac7616df629..bf925c47040e 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -42,13 +42,14 @@ #include "MLE/mle.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Common_Protocols/icmpv6.h" +#include "Common_Protocols/ip.h" #ifdef HAVE_RPL #include "RPL/rpl_data.h" #endif #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/ws/ws_common.h" - +#include "Service_Libs/random_early_detection/random_early_detection_api.h" #define TRACE_GROUP "6lAd" typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm); @@ -60,6 +61,8 @@ typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, bu #define tr_debug_extra(...) #endif +#define ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE 20 + typedef struct { uint16_t tag; /*!< Fragmentation datagram TAG ID */ uint16_t size; /*!< Datagram Total Size (uncompressed) */ @@ -93,6 +96,8 @@ typedef struct { fragmenter_tx_list_t activeUnicastList; //Unicast packets waiting data confirmation from MAC buffer_list_t directTxQueue; //Waiting free tx process uint16_t directTxQueue_size; + uint16_t directTxQueue_level; + uint16_t activeTxList_size; uint16_t indirect_big_packet_threshold; uint16_t max_indirect_big_packets_total; uint16_t max_indirect_small_packets_per_child; @@ -103,6 +108,8 @@ typedef struct { ns_list_link_t link; /*!< List link entry */ } fragmenter_interface_t; +#define LOWPAN_ACTIVE_UNICAST_ONGOING_MAX 10 + static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link); /* Adaptation interface local functions */ @@ -203,11 +210,22 @@ static struct protocol_interface_info_entry *lowpan_adaptation_network_interface } +static void lowpan_adaptation_tx_queue_level_update(fragmenter_interface_t *interface_ptr) +{ + if (interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level + ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE || + interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level - ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE) { + interface_ptr->directTxQueue_level = interface_ptr->directTxQueue_size; + tr_info("Adaptation layer TX queue size %u Active MAC tx request %u", interface_ptr->directTxQueue_level, interface_ptr->activeTxList_size); + } +} + + static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf) { buffer_t *lower_priority_buf = NULL; ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) { + if (cur->priority < buf->priority) { lower_priority_buf = cur; break; @@ -220,6 +238,7 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p ns_list_add_to_end(&interface_ptr->directTxQueue, buf); } interface_ptr->directTxQueue_size++; + lowpan_adaptation_tx_queue_level_update(interface_ptr); protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); } @@ -233,6 +252,7 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa if (lowpan_buffer_tx_allowed(interface_ptr, buf)) { ns_list_remove(&interface_ptr->directTxQueue, buf); interface_ptr->directTxQueue_size--; + lowpan_adaptation_tx_queue_level_update(interface_ptr); protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); return buf; } @@ -365,6 +385,9 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si ns_list_init(&interface_ptr->indirect_tx_queue); ns_list_init(&interface_ptr->directTxQueue); ns_list_init(&interface_ptr->activeUnicastList); + interface_ptr->activeTxList_size = 0; + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; ns_list_add_to_end(&fragmenter_interface_list, interface_ptr); @@ -390,13 +413,15 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id) ns_list_remove(&fragmenter_interface_list, interface_ptr); //free active tx process lowpan_list_free(&interface_ptr->activeUnicastList, false); + interface_ptr->activeTxList_size = 0; lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Free Indirect entry lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); - + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; //Free Dynamic allocated entries ns_dyn_mem_free(interface_ptr->fragment_indirect_tx_buffer); ns_dyn_mem_free(interface_ptr); @@ -415,6 +440,7 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) //free active tx process lowpan_list_free(&interface_ptr->activeUnicastList, false); + interface_ptr->activeTxList_size = 0; lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Clean fragmented message flag interface_ptr->fragmenter_active = false; @@ -423,6 +449,8 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; return 0; } @@ -597,6 +625,7 @@ static fragmenter_tx_entry_t *lowpan_adaptation_tx_process_init(fragmenter_inter return NULL; } ns_list_add_to_end(&interface_ptr->activeUnicastList, tx_entry); + interface_ptr->activeTxList_size++; } else { tx_entry = &interface_ptr->active_broadcast_tx_buf; } @@ -969,6 +998,13 @@ static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buff if (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf) { return false; } + + if (is_unicast && interface_ptr->activeTxList_size >= LOWPAN_ACTIVE_UNICAST_ONGOING_MAX) { + //New TX is not possible there is already too manyactive connecting + return false; + } + + // Do not accept more than one active unicast TX per destination if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) { return false; @@ -992,6 +1028,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff goto tx_error_handler; } + uint8_t traffic_class = buf->options.traffic_class >> IP_TCLASS_DSCP_SHIFT; + + if (traffic_class == IP_DSCP_EF) { + buffer_priority_set(buf, QOS_EXPEDITE_FORWARD); + } else if (traffic_class == IP_DSCP_CS6) { + //Network Control + buffer_priority_set(buf, QOS_NETWORK_CTRL); + } else if (traffic_class) { + buffer_priority_set(buf, QOS_HIGH); + } + + //Check packet size bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); if (fragmented_needed) { @@ -1010,7 +1058,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess; if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) { + + if (buf->priority == QOS_NORMAL) { + + if (random_early_detection_congestion_check(cur->random_early_detection)) { + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); + protocol_stats_update(STATS_AL_TX_CONGESTION_DROP, 1); + goto tx_error_handler; + } + } + lowpan_adaptation_tx_queue_write(interface_ptr, buf); + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); return 0; } @@ -1166,6 +1225,7 @@ static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interfa } else if (buf->link_specific.ieee802_15_4.requestAck) { ns_list_remove(&interface_ptr->activeUnicastList, tx_ptr); ns_dyn_mem_free(tx_ptr); + interface_ptr->activeTxList_size--; } socket_tx_buffer_event_and_free(buf, socket_event); @@ -1205,7 +1265,6 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c tr_error("No data request for this confirmation %u", confirm->msduHandle); return -1; } - //Check status for buffer_t *buf = tx_ptr->buf; @@ -1229,64 +1288,58 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c buf->link_specific.ieee802_15_4.rf_channel_switch = false; } - switch (confirm->status) { + if (confirm->status == MLME_SUCCESS) { + //Check is there more packets + if (lowpan_adaptation_tx_process_ready(tx_ptr)) { + bool triggered_from_indirect_cache = false; + if (tx_ptr->fragmented_data && active_direct_confirm) { + interface_ptr->fragmenter_active = false; + } - case MLME_BUSY_CHAN: - lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); - break; - case MLME_SUCCESS: + if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) { + triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr); + } - //Check is there more packets - if (lowpan_adaptation_tx_process_ready(tx_ptr)) { - bool triggered_from_indirect_cache = false; - if (tx_ptr->fragmented_data && active_direct_confirm) { - //Clean - interface_ptr->fragmenter_active = false; - } + lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); - if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) { - triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr); - } + if (triggered_from_indirect_cache) { + return 0; + } + } else { + lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); + } + } else if ((confirm->status == MLME_BUSY_CHAN) && !ws_info(cur)) { + lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); + } else { - lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); - if (triggered_from_indirect_cache) { - return 0; - } - } else { - lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); - } + if (confirm->status == MLME_TRANSACTION_OVERFLOW) { + tr_error("MCPS Data fail by MLME_TRANSACTION_OVERFLOW"); + } - break; - case MLME_TX_NO_ACK: - case MLME_SECURITY_FAIL: - case MLME_TRANSACTION_EXPIRED: - default: - tr_error("MCPS Data fail by status %u", confirm->status); - if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) { - tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2)); - } else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) { - tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8)); - } + tr_error("MCPS Data fail by status %u", confirm->status); + if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) { + tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2)); + } else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) { + tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8)); + } #ifdef HAVE_RPL - if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) { - if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { - protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); - } + if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) { + if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { + protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); } + } #endif - if (tx_ptr->fragmented_data) { - tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; - tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; - if (active_direct_confirm) { - interface_ptr->fragmenter_active = false; - } + if (tx_ptr->fragmented_data) { + tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; + tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; + if (active_direct_confirm) { + interface_ptr->fragmenter_active = false; } + } - lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); - break; - + lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); } // When confirmation is for direct transmission, push all allowed buffers to MAC if (active_direct_confirm == true) { @@ -1295,6 +1348,8 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c lowpan_adaptation_interface_tx(cur, buf_from_queue); buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr); } + //Update Average QUEUE + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); } return 0; } @@ -1492,6 +1547,18 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in } } + //Check next directTxQueue there may be pending packets also + ns_list_foreach_safe(buffer_t, entry, &interface_ptr->directTxQueue) { + if (lowpan_tx_buffer_address_compare(&entry->dst_sa, address_ptr, adr_type)) { + ns_list_remove(&interface_ptr->directTxQueue, entry); + interface_ptr->directTxQueue_size--; + //Update Average QUEUE + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); + lowpan_adaptation_tx_queue_level_update(interface_ptr); + socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL); + } + } + return 0; } diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index d2b306d465f3..990d6969db13 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -712,11 +712,13 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur) return; } tr_debug("Border router version number update"); - if (configuration & BBR_REQUIRE_DAO_REFRESH) { + if (configuration & BBR_PERIODIC_VERSION_INC) { + // Periodically increase the version number. + // This removes need for DAO, but causes slowness in recovery + pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL; + } else { // Version number is not periodically increased forcing nodes to check Border router availability using DAO pan_version_timer = 0; - } else { - pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL; } cur->ws_info->pan_information.pan_version++; // Inconsistent for border router to make information distribute faster @@ -923,12 +925,16 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options) protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (protocol_6lowpan_rpl_root_dodag && - options != configuration) { - //Configuration changed delete previous setup - ws_bbr_routing_stop(cur); + if (options == configuration) { + return 0; } + //Configuration changed configuration = options; + if (protocol_6lowpan_rpl_root_dodag) { + // Already active needs to restart + ws_bbr_routing_stop(cur); + ws_bbr_pan_version_increase(cur); + } return 0; #else (void)interface_id; diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 825c924b1fef..8fc1120d1383 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -20,6 +20,7 @@ #ifdef HAVE_WS #include "ns_types.h" #include "ns_trace.h" +#include "nsdynmemLIB.h" #include "net_interface.h" #include "eventOS_event.h" #include "randLIB.h" @@ -43,6 +44,7 @@ #include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6_radv.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "Service_Libs/Trickle/trickle.h" #include "Service_Libs/fhss/channel_list.h" #include "6LoWPAN/ws/ws_common_defines.h" @@ -75,6 +77,7 @@ #include "6LoWPAN/ws/ws_eapol_auth_relay.h" #include "6LoWPAN/ws/ws_eapol_relay.h" #include "libNET/src/net_dns_internal.h" +#include "Service_Libs/random_early_detection/random_early_detection_api.h" #define TRACE_GROUP "wsbs" @@ -111,6 +114,7 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry); +static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur); typedef enum { WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ @@ -163,7 +167,7 @@ void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_ent { mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT); - if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (neighbor && neighbor->link_lifetime <= valid_time) { //mlme_device_descriptor_t device_desc; neighbor->lifetime = valid_time; neighbor->link_lifetime = valid_time; @@ -426,19 +430,47 @@ static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighb ws_nud_state_clean(cur, nud_entry); } } +if_address_entry_t *ws_probe_aro_address(protocol_interface_info_entry_t *interface) +{ + if (interface->global_address_available) { + ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) { + if (addr_ipv6_scope(address->address, interface) > IPV6_SCOPE_LINK_LOCAL) { + return address; + } + } + } + return NULL; +} + static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor, bool nud_process) { //Send NS uint8_t ll_target[16]; + aro_t aro_temp; + //SET ARO and src address pointer to NULL by default + aro_t *aro_ptr = NULL; + uint8_t *src_address_ptr = NULL; + ws_bootsrap_create_ll_address(ll_target, neighbor->mac64); if (nud_process) { tr_info("NUD generate NS %u", neighbor->index); } else { tr_info("Probe generate NS %u", neighbor->index); - } - buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); + if_address_entry_t *gp_address = ws_probe_aro_address(cur); + if (gp_address) { + src_address_ptr = gp_address->address; + aro_temp.status = ARO_SUCCESS; + aro_temp.present = true; + memcpy(aro_temp.eui64, cur->mac, 8); + //Just Short Test + aro_temp.lifetime = 1; + aro_ptr = &aro_temp; + } + } + buffer_t *buffer = icmpv6_build_ns(cur, ll_target, src_address_ptr, true, false, aro_ptr); if (buffer) { + buffer->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; protocol_push(buffer); return true; } @@ -1595,10 +1627,15 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry //When Config is learned and USE Parent BS is enabled compare is this new BSI if (cur->ws_info->configuration_learned && cur->ws_info->pan_information.use_parent_bs && ws_bs_ie.broadcast_schedule_identifier != cur->ws_info->hopping_schdule.fhss_bsi) { - tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); - cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; - cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; - ws_bootstrap_event_discovery_start(cur); + //Accept only next possible BSI number + if ((cur->ws_info->hopping_schdule.fhss_bsi + 1) != ws_bs_ie.broadcast_schedule_identifier) { + tr_debug("Do not accept a unknown BSI: %u", ws_bs_ie.broadcast_schedule_identifier); + } else { + tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); + cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; + cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; + ws_bootstrap_event_discovery_start(cur); + } return; } } @@ -2359,6 +2396,7 @@ int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t static int ws_bootstrap_set_domain_rf_config(protocol_interface_info_entry_t *cur) { phy_rf_channel_configuration_s rf_configs; + memset(&rf_configs, 0, sizeof(phy_rf_channel_configuration_s)); rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000; rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing); rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); @@ -2536,6 +2574,10 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) * */ + } else if (event == RPL_EVENT_LOCAL_REPAIR_START) { + tr_debug("RPL local repair start"); + ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN); + } else if (event == RPL_EVENT_DAO_PARENT_ADD) { ws_address_parent_update(cur); } @@ -3272,6 +3314,8 @@ static void ws_bootstrap_event_handler(arm_event_s *event) // All trickle timers stopped to allow entry from any state ws_bootstrap_asynch_trickle_stop(cur); + //Init Packet congestion + ws_bootstrap_packet_congestion_init(cur); if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); @@ -3761,4 +3805,78 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_ return 0; } +//Calculate max_packet queue size +static uint16_t ws_bootstrap_define_congestin_max_threshold(uint32_t heap_total_size, uint16_t packet_size, uint16_t packet_per_seconds, uint32_t max_delay, uint16_t min_packet_queue_size, uint16_t max_packet_queue_size) +{ + uint32_t max_packet_count = 0; + if (heap_total_size) { + //Claculate how many packet can be max queue to half of heap + max_packet_count = (heap_total_size / 2) / packet_size; + } + + //Calculate how many packet is possible to queue for guarantee given max delay + uint32_t max_delayded_queue_size = max_delay * packet_per_seconds; + + if (max_packet_count > max_delayded_queue_size) { + //Limit queue size by MAX delay + max_packet_count = max_delayded_queue_size; + } + + if (max_packet_count > max_packet_queue_size) { + //Limit queue size by Max + max_packet_count = max_packet_queue_size; + } else if (max_packet_count < min_packet_queue_size) { + //Limit queue size by Min + max_packet_count = min_packet_queue_size; + } + return (uint16_t)max_packet_count; +} + +static uint16_t ws_bootstrap_packet_per_seconds(protocol_interface_info_entry_t *cur, uint16_t packet_size) +{ + uint32_t data_rate = ws_common_datarate_get(cur); + + //calculate how many packet is possible send in paper + data_rate /= 8 * packet_size; + + //Divide optimal by / 5 because we split TX / RX slots and BC schedule + //With Packet size 500 it should return + //Return 15 for 300kBits + //Return 7 for 150kBits + //Return 2 for 50kBits + return data_rate / 5; +} + + + +static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur) +{ + random_early_detection_free(cur->random_early_detection); + cur->random_early_detection = NULL; + + //TODO implement API for HEAP info request + uint32_t heap_size; + const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat(); + if (mem_stats) { + heap_size = mem_stats->heap_sector_size; + } else { + heap_size = 0; + } + + uint16_t packet_per_seconds = ws_bootstrap_packet_per_seconds(cur, WS_CONGESTION_PACKET_SIZE); + + uint16_t min_th, max_th; + + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_BR_MIN_QUEUE_SIZE, WS_CONGESTION_BR_MAX_QUEUE_SIZE); + } else { + max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_NODE_MIN_QUEUE_SIZE, WS_CONGESTION_NODE_MAX_QUEUE_SIZE); + } + + min_th = max_th / 2; + tr_info("Wi-SUN packet congestion minTh %u, maxTh %u, drop probability %u weight %u, Packet/Seconds %u", min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH, packet_per_seconds); + cur->random_early_detection = random_early_detection_create(min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH); + +} + #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 5a242cfa4b5f..11532e41ad40 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -390,29 +390,41 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size) } } -static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint32_t link_lifetime) { + if (link_lifetime > WS_NEIGHBOR_LINK_TIMEOUT) { + link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + } /* * ARO registration from child can update the link timeout so we don't need to send extra NUD if ARO received */ mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, false, false); if (mac_neighbor) { - if (mac_neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (mac_neighbor->link_lifetime < link_lifetime) { //Set Stable timeout for temporary entry here + if (link_lifetime > WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME && mac_neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { + tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index); + } mac_neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; - tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index); + } //Refresh mac_neighbor->lifetime = mac_neighbor->link_lifetime; } } -uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint16_t aro_timeout) { uint8_t child_count = 0; uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size); + if (aro_timeout == 0) { + //DeRegister Address Reg + return ARO_SUCCESS; + } + uint32_t link_lifetime = (aro_timeout * 60) + 1; + // Test API to limit child count if (test_max_child_count_override != 0xffff) { max_child_count = test_max_child_count_override; @@ -420,8 +432,9 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte //Validate Is EUI64 already allocated for any address if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) { - ws_common_neighbour_address_reg_link_update(interface, eui64); + ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime); tr_info("Child registration from old child"); + return ARO_SUCCESS; } @@ -431,20 +444,21 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte return ARO_TOPOLOGICALLY_INCORRECT; } - ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) { if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) { child_count++; } } + if (child_count >= max_child_count) { tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_FULL; } - ws_common_neighbour_address_reg_link_update(interface, eui64); + ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime); tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); + return ARO_SUCCESS; } @@ -472,13 +486,13 @@ uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur) if (network_size <= NETWORK_SIZE_SMALL) { // handles also NETWORK_SIZE_CERTIFICATE - latency = 4000; + latency = 5000; } else if (network_size <= NETWORK_SIZE_MEDIUM) { - latency = 8000; + latency = 10000; } else if (network_size <= NETWORK_SIZE_LARGE) { - latency = 16000; + latency = 20000; } else { - latency = 24000; + latency = 30000; } return latency; diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 5b468d27adb2..f0aaf9fde03c 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -148,7 +148,7 @@ void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t * void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); -uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64); +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64, uint16_t aro_timeout); bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64); @@ -173,7 +173,7 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size); #define ws_common_aro_failure(cur, ll_address) #define ws_common_neighbor_remove(cur, ll_address) #define ws_common_fast_timer(cur, ticks) ((void) 0) -#define ws_common_allow_child_registration(cur, eui64) (2) +#define ws_common_allow_child_registration(cur, eui64, aro_timeout) (2) #define ws_common_negative_aro_mark(interface, eui64)(false) #define ws_common_latency_estimate_get(cur) 0 #define ws_common_datarate_get(cur) 0 diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 6efcf20c802e..f202cfea2fe9 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -144,9 +144,9 @@ extern uint8_t DEVICE_MIN_SENS; #define MPL_SMALL_K 8 #define MPL_SMALL_SEED_LIFETIME (MPL_SMALL_IMAX * MPL_SAFE_HOP_COUNT * (MPL_SMALL_EXPIRATIONS + 1)) // time that packet should get to safe distance /*Medium network size*/ -#define MPL_MEDIUM_IMIN 5 -#define MPL_MEDIUM_IMAX 20 -#define MPL_MEDIUM_EXPIRATIONS 2 +#define MPL_MEDIUM_IMIN 1 +#define MPL_MEDIUM_IMAX 32 +#define MPL_MEDIUM_EXPIRATIONS 1 #define MPL_MEDIUM_K 8 #define MPL_MEDIUM_SEED_LIFETIME (MPL_MEDIUM_IMAX * MPL_SAFE_HOP_COUNT * (MPL_MEDIUM_EXPIRATIONS + 1)) // time that packet should get to safe distance /*Large network size*/ @@ -221,6 +221,13 @@ extern uint8_t DEVICE_MIN_SENS; #define WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY 5 // During discovery state how many neighbours per pan #define WS_PARENT_LIST_MAX_PAN_IN_ACTIVE 2 // During active state two nodes per pan is allowed +#define WS_CONGESTION_PACKET_SIZE 500 // Packet length for calculate how much heap message queue can fit +#define WS_CONGESTION_QUEUE_DELAY 60 // Define message queue max length for given delay. This value is multiple by packet/seconds +#define WS_CONGESTION_RED_DROP_PROBABILITY 10 //10.0% +#define WS_CONGESTION_BR_MIN_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_BR_MAX_QUEUE_SIZE 600000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_NODE_MIN_QUEUE_SIZE 10000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_NODE_MAX_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE /* * Modifications for base specification. * diff --git a/source/6LoWPAN/ws/ws_eapol_auth_relay.c b/source/6LoWPAN/ws/ws_eapol_auth_relay.c index cad3a521287a..76f6221a74bd 100644 --- a/source/6LoWPAN/ws/ws_eapol_auth_relay.c +++ b/source/6LoWPAN/ws/ws_eapol_auth_relay.c @@ -26,6 +26,7 @@ #include "mac_api.h" #include "mac_mcps.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "socket_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mpx_api.h" @@ -80,6 +81,8 @@ int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr, ns_dyn_mem_free(eapol_auth_relay); return -1; } + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(eapol_auth_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); ns_list_add_to_end(&eapol_auth_relay_list, eapol_auth_relay); diff --git a/source/6LoWPAN/ws/ws_eapol_pdu.c b/source/6LoWPAN/ws/ws_eapol_pdu.c index f20530d46620..b32892eaed22 100644 --- a/source/6LoWPAN/ws/ws_eapol_pdu.c +++ b/source/6LoWPAN/ws/ws_eapol_pdu.c @@ -278,6 +278,9 @@ static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcp status = EAPOL_PDU_TX_OK; } else if (data->status == MLME_TX_NO_ACK) { status = EAPOL_PDU_TX_ERR_TX_NO_ACK; + tr_error("EAPOL TX err no ack"); + } else { + tr_error("EAPOL TX err"); } msdu->tx_status(eapol_pdu_data->interface_ptr, status, msdu->tx_identifier); } diff --git a/source/6LoWPAN/ws/ws_eapol_relay.c b/source/6LoWPAN/ws/ws_eapol_relay.c index 0bc7a5a472e9..41e01be8f1d0 100644 --- a/source/6LoWPAN/ws/ws_eapol_relay.c +++ b/source/6LoWPAN/ws/ws_eapol_relay.c @@ -26,6 +26,7 @@ #include "mac_api.h" #include "mac_mcps.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "socket_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mpx_api.h" @@ -89,6 +90,8 @@ int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint ns_dyn_mem_free(eapol_relay); return -1; } + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(eapol_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); if (ws_eapol_pdu_cb_register(interface_ptr, &eapol_pdu_recv_cb_data) < 0) { ns_dyn_mem_free(eapol_relay); diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 79748d453359..1f6f15abad60 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -537,7 +537,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * ws_llc_mpx_eapol_send(base, message); } } else { - if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { + if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime <= WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME) { //Remove temp neighbour tr_debug("Remove Temp Entry by TX confirm"); mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor); diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 0d381eae7a8c..a661f7438601 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -1110,6 +1110,7 @@ buffer_t *icmpv6_up(buffer_t *buf) || (buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL && (buf->options.code != ICMPV6_CODE_RPL_DIO && buf->options.code != ICMPV6_CODE_RPL_DIS))) { + tr_warn("Drop: ICMP EP unsecured packet"); goto drop; } } @@ -1526,7 +1527,11 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta /* If ARO Success sending is omitted, MAC ACK is used instead */ /* Setting callback for receiving ACK from adaptation layer */ if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) { - buf->ack_receive_cb = icmpv6_aro_cb; + if (aro->lifetime > 1) { + buf->ack_receive_cb = icmpv6_aro_cb; + } else { + buf->ack_receive_cb = ack_receive_cb; + } } } if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) { @@ -1761,6 +1766,7 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited, tr_debug("Neighbour removed for negative response send"); return buffer_free(buf); } + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; buf->ack_receive_cb = ack_remove_neighbour_cb; } diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index 11df4aafa45a..8ccf5cb4a874 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -1416,6 +1416,7 @@ buffer_t *ipv6_forwarding_up(buffer_t *buf) #endif default: { if (buf->options.ll_security_bypass_rx) { + tr_warn("Drop: unsecured by BAD Next header %u", *nh_ptr); goto bad_nh; } buffer_socket_set(buf, socket_lookup_ipv6(*nh_ptr, &buf->dst_sa, &buf->src_sa, true)); diff --git a/source/Core/include/ns_buffer.h b/source/Core/include/ns_buffer.h index 0168495ff2d9..42defbc3cdea 100644 --- a/source/Core/include/ns_buffer.h +++ b/source/Core/include/ns_buffer.h @@ -180,7 +180,9 @@ typedef enum { typedef enum { QOS_NORMAL = 0, QOS_HIGH = 1, - QOS_MAC_BEACON = 2 + QOS_NETWORK_CTRL = 2, + QOS_EXPEDITE_FORWARD = 3, + QOS_MAC_BEACON = 4 } buffer_priority_t; #define B_TO_MAC_MLME_MASK (B_DIR_MASK + B_FROM_MASK + B_TO_MASK ) diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index 8229e29f3f34..0e6ae5ca36af 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -828,6 +828,9 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m tr_info("Number of channels: %u", config_params->number_of_channels); tr_info("Modulation: %u", config_params->modulation); tr_info("Modulation index: %u", config_params->modulation_index); + tr_info("FEC: %u", config_params->fec); + tr_info("OFDM MCS: %u", config_params->ofdm_mcs); + tr_info("OFDM option: %u", config_params->ofdm_option); return 0; default: return mac_mlme_handle_set_values(rf_mac_setup, set_req); diff --git a/source/MPL/mpl.c b/source/MPL/mpl.c index 913745f0c96c..68c56b95c14f 100644 --- a/source/MPL/mpl.c +++ b/source/MPL/mpl.c @@ -406,6 +406,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do uint16_t ip_len = buffer_data_length(buf); while (mpl_total_buffered + ip_len > MAX_BUFFERED_MESSAGES_SIZE) { + tr_debug("MPL MAX buffered message size limit...free space"); mpl_free_space(); } @@ -427,6 +428,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do mpl_buffered_message_t *message = ns_dyn_mem_alloc(sizeof(mpl_buffered_message_t) + ip_len); if (!message) { + tr_debug("No heap for new MPL message"); return NULL; } memcpy(message->message, buffer_data_pointer(buf), ip_len); @@ -475,6 +477,7 @@ static void mpl_buffer_transmit(mpl_domain_t *domain, mpl_buffered_message_t *me uint16_t ip_len = mpl_buffer_size(message); buffer_t *buf = buffer_get(ip_len); if (!buf) { + tr_debug("No heap for MPL transmit"); return; } @@ -939,6 +942,9 @@ bool mpl_forwarder_process_message(buffer_t *buf, mpl_domain_t *domain, bool see } message = mpl_buffer_create(buf, domain, seed, sequence, hop_limit); + if (!message) { + tr_debug("MPL Buffer Craete fail"); + } return true; } diff --git a/source/NWK_INTERFACE/Include/protocol.h b/source/NWK_INTERFACE/Include/protocol.h index 9880a5d2cc8a..a9f26329db11 100644 --- a/source/NWK_INTERFACE/Include/protocol.h +++ b/source/NWK_INTERFACE/Include/protocol.h @@ -57,6 +57,7 @@ struct arm_device_driver_list; struct mlme_security_s; struct load_balance_api; struct nwk_wpan_nvm_api; +struct red_info_s; #define SLEEP_MODE_REQ 0x80 #define SLEEP_PERIOD_ACTIVE 0x40 @@ -445,6 +446,7 @@ struct protocol_interface_info_entry { struct auth_info *pana_sec_info_temp; br_info_t *border_router_setup; struct load_balance_api *lb_api; + struct red_info_s *random_early_detection; neigh_cache_s neigh_cache; pan_blaclist_cache_s pan_blaclist_cache; pan_coordinator_blaclist_cache_s pan_cordinator_black_list; diff --git a/source/NWK_INTERFACE/Include/protocol_stats.h b/source/NWK_INTERFACE/Include/protocol_stats.h index e8ee77f2ca5f..193a9538e9af 100644 --- a/source/NWK_INTERFACE/Include/protocol_stats.h +++ b/source/NWK_INTERFACE/Include/protocol_stats.h @@ -44,7 +44,8 @@ typedef enum { STATS_BUFFER_HEADROOM_FAIL, STATS_ETX_1ST_PARENT, STATS_ETX_2ND_PARENT, - STATS_AL_TX_QUEUE_SIZE + STATS_AL_TX_QUEUE_SIZE, + STATS_AL_TX_CONGESTION_DROP } nwk_stats_type_t; diff --git a/source/NWK_INTERFACE/protocol_stats.c b/source/NWK_INTERFACE/protocol_stats.c index aedec1cbae33..074dc079519e 100644 --- a/source/NWK_INTERFACE/protocol_stats.c +++ b/source/NWK_INTERFACE/protocol_stats.c @@ -152,6 +152,9 @@ void protocol_stats_update(nwk_stats_type_t type, uint16_t update_val) nwk_stats_ptr->adapt_layer_tx_queue_peak = nwk_stats_ptr->adapt_layer_tx_queue_size; } break; + case STATS_AL_TX_CONGESTION_DROP: + nwk_stats_ptr->adapt_layer_tx_congestion_drop++; + break; } } } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 37eacc434520..29ddcdd48e55 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -45,6 +45,7 @@ #include "NWK_INTERFACE/Include/protocol_stats.h" #include "Common_Protocols/ipv6_constants.h" #include "Common_Protocols/icmpv6.h" +#include "Common_Protocols/ip.h" #include "ipv6_stack/protocol_ipv6.h" #include "Service_Libs/etx/etx.h" /* slight ick */ @@ -1292,6 +1293,10 @@ void rpl_control_transmit(rpl_domain_t *domain, protocol_interface_info_entry_t /* Others set "0", which means use interface default */ buf->options.hop_limit = addr_ipv6_scope(buf->dst_sa.address, cur) <= IPV6_SCOPE_LINK_LOCAL ? 255 : 0; + if (code == ICMPV6_CODE_RPL_DAO || code == ICMPV6_CODE_RPL_DAO_ACK || buf->dst_sa.address[0] != 0xff) { + //DAO and DAO ACK and unicast traffic with Higher priority + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + } if (dst == NULL && cur == NULL) { rpl_control_transmit_all_interfaces(domain, buf); diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 72ddf1281f66..6bbd5f02a589 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -91,6 +91,7 @@ #include "Common_Protocols/icmpv6.h" #include "NWK_INTERFACE/Include/protocol.h" #include "ipv6_stack/ipv6_routing_table.h" +#include "Common_Protocols/ip.h" #include "net_rpl.h" #include "RPL/rpl_protocol.h" @@ -1874,6 +1875,7 @@ static bool rpl_instance_push_address_registration(protocol_interface_info_entry if (!buf) { return false; } + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; tr_info("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address)); protocol_push(buf); return true; diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index dec173ef71d5..3037755bbd01 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1840,7 +1840,13 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) /* Delay sending first DIO if we are still potentially gathering info */ /* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */ if (!rpl_instance_am_root(instance) && !instance->last_advertised_dodag_version && rpl_policy_parent_confirmation_requested()) { - // We dont have any valid parent selected + + // We don't have DAO target generated + if (ns_list_count(&instance->dao_targets) == 0) { + return; + } + + // We don't have any valid parent selected if (!rpl_instance_parent_selection_ready(instance)) { return; } diff --git a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index 6b729450a0da..882df678fd0b 100644 --- a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -652,6 +652,14 @@ static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t radius_msg_length += AVP_TYPE_NAS_IPV6_ADDRESS_LEN; uint8_t *radius_msg_ptr = ns_dyn_mem_temporary_alloc(radius_msg_length); + if (radius_msg_ptr == NULL) { + if (data->send_radius_msg != NULL) { + ns_dyn_mem_free(data->send_radius_msg); + } + data->send_radius_msg = NULL; + data->send_radius_msg_len = 0; + return; + } uint8_t *radius_msg_start_ptr = radius_msg_ptr; *radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code diff --git a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c index de1d86b515c6..1ba7f109ab16 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c @@ -416,7 +416,7 @@ static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int l int8_t tls_sec_prot_lib_process(tls_security_t *sec) { - int ret = -1; + int32_t ret = -1; while (ret != MBEDTLS_ERR_SSL_WANT_READ) { ret = mbedtls_ssl_handshake_step(&sec->ssl); @@ -428,6 +428,7 @@ int8_t tls_sec_prot_lib_process(tls_security_t *sec) #endif if (ret && (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { + tr_error("TLS error: %" PRId32, ret); return TLS_SEC_PROT_LIB_ERROR; } diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 43d1e39b1687..7810453bb7e5 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -604,9 +604,14 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a if (!fhss_structure) { return -1; } - if (is_broadcast_addr) { + // Allow broadcast destination on broadcast channel + if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) { return 0; } + // Do not allow broadcast destination on unicast channel + if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == false)) { + return -3; + } // Do not allow unicast destination on broadcast channel if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) { return -1; diff --git a/source/Service_Libs/random_early_detection/random_early_detection.c b/source/Service_Libs/random_early_detection/random_early_detection.c new file mode 100644 index 000000000000..b1a4b73d74de --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nsconfig.h" +#include "ns_types.h" +#include "string.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "randLIB.h" +#include "Service_Libs/random_early_detection/random_early_detection.h" +#include "Service_Libs/random_early_detection/random_early_detection_api.h" + + +red_info_t *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_max_p, uint16_t weight) +{ + //Weight must be between 1-256 + if (weight == 0 || weight > 256) { + return NULL; + } + + //Probability must be between 1-100 + if (drop_max_p == 0 || drop_max_p > 100) { + return NULL; + } + + //Max Threshold can't smaller or similar than min + if (threshold_max <= threshold_min) { + return NULL; + } + + red_info_t *red_info = ns_dyn_mem_alloc(sizeof(red_info_t)); + if (red_info) { + red_info->count = 0; + red_info->averageQ = 0; + red_info->parameters.drop_maX_P = drop_max_p; + red_info->parameters.threshold_max = threshold_max; + red_info->parameters.threshold_min = threshold_min; + red_info->parameters.weight = weight; + } + + return red_info; +} + + +void random_early_detection_free(struct red_info_s *red_info) +{ + ns_dyn_mem_free(red_info); +} + +//calculate average and return averaged value back +uint16_t random_early_detetction_aq_calc(red_info_t *red_info, uint16_t sampleLen) +{ + if (!red_info) { + return 0; + } + + if (red_info->parameters.weight == RED_AVERAGE_WEIGHT_DISABLED || red_info->averageQ == 0) { + red_info->averageQ = sampleLen * 256; + return sampleLen; + } + + // AQ = (1-weight) * average_queue + weight*sampleLen + // Now Sample is scaled by 256 which is not loosing so much tail at average + + //Weight Last Average part (1-weight) * average_queue with scaled 256 + uint32_t averageSum = ((256 - red_info->parameters.weight) * red_info->averageQ) / 256; + //Add new weighted sample lenght (weight*sampleLen) + averageSum += (red_info->parameters.weight * sampleLen); + + if (averageSum & 1) { + //If sum is ODD add 1 this will help to not stuck like 1,99 average to -> 2 + averageSum++; + } + //Store new average + red_info->averageQ = averageSum; + //Return always same format scaled than inn + return red_info->averageQ / 256; + +} + +uint16_t random_early_detetction_aq_read(red_info_t *red_info) +{ + if (!red_info) { + return 0; + } + return red_info->averageQ / 256; +} + + + +bool random_early_detection_congestion_check(red_info_t *red_info) +{ + if (!red_info) { + return false; + } + + //Calulate Average queue size + uint16_t sampleLen = red_info->averageQ / 256;; + + if (sampleLen <= red_info->parameters.threshold_min) { + //Can be added to queue without any RED operation + red_info->count = 0; + return false; + } + + if (sampleLen > red_info->parameters.threshold_max) { + //Always drop over threshold_max + red_info->count = 0; + return true; + } + + // Calculate probability for packet drop + // tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min); + uint32_t tempP = (uint32_t) red_info->parameters.drop_maX_P * PROB_SCALE + * (sampleLen - red_info->parameters.threshold_min) + / (red_info->parameters.threshold_max - red_info->parameters.threshold_min); + + // Next Prob = tempP / (1 - count*tempP) + // This will increase probability and + + //Calculate first divider part + uint32_t Prob = red_info->count * tempP; + + //Check that divider it is not >= 0 + if (Prob >= PROB_SCALE_MAX) { + + red_info->count = 0; + return true; + } + + //Calculate only when count * tempP is smaller than scaler + Prob = (tempP * PROB_SCALE_MAX) / (PROB_SCALE_MAX - Prob); + if (Prob > randLIB_get_random_in_range(0, PROX_MAX_RANDOM)) { + //Drop packet + red_info->count = 0; + return true; + } + + //Increment count next round check + red_info->count++; + return false; + +} diff --git a/source/Service_Libs/random_early_detection/random_early_detection.h b/source/Service_Libs/random_early_detection/random_early_detection.h new file mode 100644 index 000000000000..9f81ed660c46 --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ +#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//This value cant be bigger than 655 +#define PROB_SCALE 512 +#define PROB_SCALE_MAX PROB_SCALE * 100 +#define PROX_MAX_RANDOM PROB_SCALE_MAX-1 + +typedef struct red_config_s { + uint16_t weight; /*< Weight for new sample len, 256 disabled average */ + uint16_t threshold_min; /*< Threshold Min value which start possibility start drop a packet */ + uint16_t threshold_max; /*< Threshold Max this value give max Probability for configured value over that every new packet will be dropped*/ + uint8_t drop_maX_P; /*< Max probability for drop packet between threshold_min and threshold_max threshold */ +} red_config_t; + +typedef struct red_info_s { + red_config_t parameters; /*< Random Early detetction parameters for queue avarge and packet drop */ + uint32_t averageQ; /*< Average queue size Scaled by 256 1.0 is 256 */ + uint16_t count; /*< Missed Packet drop's. This value is incremented when average queue is over min threshoild and packet is noot dropped */ +} red_info_t; + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ */ diff --git a/source/Service_Libs/random_early_detection/random_early_detection_api.h b/source/Service_Libs/random_early_detection/random_early_detection_api.h new file mode 100644 index 000000000000..dcefc35ec844 --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection_api.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ +#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct red_info_s; + +#define RED_AVERAGE_WEIGHT_DISABLED 256 /*< Average is disabled */ +#define RED_AVERAGE_WEIGHT_HALF 128 /*< Average weight for new sample is 0.5*new + 0.5 to last one */ +#define RED_AVERAGE_WEIGHT_QUARTER 64 /*< Average weight for new sample is 1/4 + 3/4 to last one */ +#define RED_AVERAGE_WEIGHT_EIGHTH 32 /*< Average weight for new sample is 1/8 + 7/8 to last one */ + +/** + * \brief Create Random early detection data + * + * Function will config parameters how wide are Random Early detection drop will work. + * + * How to use parameters: + * + * Weight is definition how message queue Average (AQ) is calculated. Smaller weight will give smoother AQ update. + * + * AQ = (1-weight) * average_queue + weight*sampleLen; + * + * * RED_AVERAGE_WEIGHT_DISABLED disable Average by max weight to new sample length + * * RED_AVERAGE_WEIGHT_HALF last average*0.5 + 0.5*new sample: Smooth Average light packet filter + * * RED_AVERAGE_WEIGHT_QUARTER last average*0.75 + 0.25*new sample: Medium packet burst filtering + * * RED_AVERAGE_WEIGHT_EIGHTH last average*7/8 + 1/8*new sample: Good for filtering packet burst and big networks + * + * How to configure packet drop possibility: + * + * Define base Probability based current AQ, average length + * + * tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min); + * + * Prob = tempP / (1 - count*tempP) + * + * threshold_min and threshold_max threshold define area for random early detection drop. When Average queue size go over Min threshold packet may drop by given maxProbability. + * System will work smoother if min -max threshold range is wide. Then random drop is may cover small data burst until Max threshold Avarage is reached. + * After Max every new packet will be dropped. + * + * Config Examples. + * + * Threshold values must be set how much device can buffer data. + * + * Small size data buffering: + * random_early_detection_create(32, 96, 10, RED_AVERAGE_WEIGHT_QUARTER) + * + * Medium size data buffering: + * random_early_detection_create(96, 256, 10, RED_AVERAGE_WEIGHT_EIGHTH) + * + * High size buffering: + * random_early_detection_create(256, 600, 10, RED_AVERAGE_WEIGHT_EIGHTH) + * + * \param threshold_min min average queue size which enable packet drop + * \param threshold_max average queue size when all new packets start drop + * \param drop_maX_P is percent probability to drop packet 100-1 are possible values + * \param weight accepted values 256-1, 256 is 1.0 weight which mean that new queue size overwrite old. 128 is 0.5 which gives 0.5 from old + 0.5 from new. + * \return Pointer for allocated structure, NULL if memory allocation fail + */ +struct red_info_s *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_maX_P, uint16_t weight); + + +/** + * \brief Free Random early detection data + * + * + * \param red_info pointer to data + */ +void random_early_detection_free(struct red_info_s *red_info); + + +/** + * \brief Random early detection drop function + * + * \param red_info pointer, which is created user include all configurations + * \param sampleLen Current queue length + * \return true Drop packet + * \return false Packet can be added to queue + */ +bool random_early_detection_congestion_check(struct red_info_s *red_info); + +/** + * \brief Random early detection Average queue calculate + * + * Call this when add or remove from queue + * + * \param red_info pointer, which is created user include all configurations + * \param sampleLen Current queue length + * + * \return New average + */ +uint16_t random_early_detetction_aq_calc(struct red_info_s *red_info, uint16_t sampleLen); + +/** + * \brief Read Random early detection Average queue size + * + * Call this when add or remove from queue + * + * \param red_info pointer, which is created user include all configurations + * + * \return Current average + */ +uint16_t random_early_detetction_aq_read(struct red_info_s *red_info); + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ */ diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index c720a14c01b9..66cda2e6d4f8 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -29,9 +29,10 @@ #include "socket_api.h" #include "net_interface.h" #include "common_functions.h" + #include "libDHCPv6/libDHCPv6.h" #include "NWK_INTERFACE/Include/protocol.h" // just for protocol_core_monotonic_time - +#include "Common_Protocols/ip.h" #include "dhcp_service_api.h" #ifdef HAVE_DHCPV6 #define TRACE_GROUP "dhcp" @@ -437,7 +438,7 @@ void recv_dhcp_relay_msg(void *cb_res) uint8_t *ptr = msg_iov[1].iov_base; uint8_t msg_type = *ptr; - + int16_t tc = 0; if (msg_type == DHCPV6_RELAY_FORWARD) { tr_error("Drop not supported DHCPv6 forward at Agent"); goto cleanup; @@ -497,7 +498,10 @@ void recv_dhcp_relay_msg(void *cb_res) msg_iov[0].iov_len = 38; msg_iov[1].iov_len = msg_len; tr_debug("Forward Client msg to server"); + tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + } + socket_setsockopt(sckt_data->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); cleanup: ns_dyn_mem_free(msg_iov[1].iov_base); @@ -845,6 +849,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) if (msg_tr_ptr->relay_start) { //Build Relay Reply only server do this + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); ns_iovec_t data_vector[2]; ns_msghdr_t msghdr; memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16); @@ -872,6 +878,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0); } else { + int16_t tc = 0; + socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); } if (retval != 0) { diff --git a/sources.mk b/sources.mk index 2d895e803a79..ef0ec5125378 100644 --- a/sources.mk +++ b/sources.mk @@ -165,6 +165,7 @@ SRCS += \ source/Service_Libs/Trickle/trickle.c \ source/Service_Libs/whiteboard/whiteboard.c \ source/Service_Libs/pan_blacklist/pan_blacklist.c \ + source/Service_Libs/random_early_detection/random_early_detection.c \ source/6LoWPAN/Thread/thread_management_if.c \ source/6LoWPAN/Thread/thread_management_api.c \ source/6LoWPAN/Thread/thread_commissioning_api.c \ diff --git a/test/nanostack/unittest/service_libs/random_early_detetction/Makefile b/test/nanostack/unittest/service_libs/random_early_detetction/Makefile new file mode 100644 index 000000000000..d23356e8862a --- /dev/null +++ b/test/nanostack/unittest/service_libs/random_early_detetction/Makefile @@ -0,0 +1,18 @@ +include ../../makefile_defines.txt + +COMPONENT_NAME = random_early_detection_unit + +#This must be changed manually +SRC_FILES = \ + ../../../../../source/Service_Libs/random_early_detection/random_early_detection.c \ + +TEST_SRC_FILES = \ + main.cpp \ + randomEarlyDetection_test.cpp \ + ../../stub/mbed_trace_stub.c \ + ../../stub/nsdynmemLIB_stub.c \ + ../../stub/rand_lib2_stub.c \ + +include ../../MakefileWorker.mk + +CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -DEXTRA_CONSISTENCY_CHECKS \ No newline at end of file