Skip to content

Commit

Permalink
Added new service Random early detection
Browse files Browse the repository at this point in the history
Random Early detetction is for start dropping packet in high network load when
message queue's start growing over configured threshold values.
  • Loading branch information
Juha Heiuskanen committed Dec 2, 2020
1 parent f2c358d commit 11c0763
Show file tree
Hide file tree
Showing 15 changed files with 784 additions and 1 deletion.
11 changes: 10 additions & 1 deletion source/6LoWPAN/adaptation_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
#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);
Expand Down Expand Up @@ -1051,6 +1051,15 @@ 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 (cur->random_early_detection && buf->priority == QOS_NORMAL) {

if (random_early_detection_packet(cur->random_early_detection, interface_ptr->directTxQueue_size)) {
//TODO Update Statisdic drop by congestion
goto tx_error_handler;
}
}

lowpan_adaptation_tx_queue_write(interface_ptr, buf, false);
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions source/NWK_INTERFACE/Include/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
142 changes: 142 additions & 0 deletions source/Service_Libs/random_early_detection/random_early_detection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* 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
static uint16_t random_early_detetction_aq_calc(red_info_t *red_info, uint16_t sampleLen)
{

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//If sum is ODD add 1 this will
red_info->averageQ = averageSum;
//Return always same format scaled than inn
return red_info->averageQ / 256;

}



bool random_early_detection_packet(red_info_t *red_info, uint16_t sampleLen)
{
//Calulate Average queue size
sampleLen = random_early_detetction_aq_calc(red_info, sampleLen);

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;

}
Original file line number Diff line number Diff line change
@@ -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_ */
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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_packet(struct red_info_s *red_info, uint16_t sampleLen);

#ifdef __cplusplus
}
#endif

#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ */
1 change: 1 addition & 0 deletions sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ TEST_SRC_FILES = \
../../stub/thread_management_if_stub.c \
../../stub/mac_neighbor_table_stub.c \
../../stub/rpl_data_stub.c \
../../stub/random_early_detection_stub.c \


include ../../MakefileWorker.mk
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
#include "common_functions_stub.h"
#include "thread_common_stub.h"
#include "mac_neighbor_table_stub.h"
#include "Service_Libs/random_early_detection/random_early_detection_api.h"
#include "Service_Libs/random_early_detection/random_early_detection.h"
#include "random_early_detection_stub.h"
#include "6LoWPAN/ws/ws_common.h"


Expand Down
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 11c0763

Please sign in to comment.