diff options
Diffstat (limited to 'shaping/src/shaper_aqm.cpp')
| -rw-r--r-- | shaping/src/shaper_aqm.cpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/shaping/src/shaper_aqm.cpp b/shaping/src/shaper_aqm.cpp new file mode 100644 index 0000000..e7b00e5 --- /dev/null +++ b/shaping/src/shaper_aqm.cpp @@ -0,0 +1,177 @@ +#include <cstdlib> +#include <time.h> + +#include "shaper.h" +#include "shaper_aqm.h" + + +/**************************blue******************************/ +#define PROBABILITY_MAX 100 +#define INCREMENT 10 +#define DECREMENT 1 +#define FREEZE_TIME 3 //unit:s + +static int shaper_aqm_blue_need_drop(int profile_id, struct shaper_aqm_blue_para *para) +{ + time_t curr_time; + if (time(&curr_time) - para->update_time >= FREEZE_TIME) { + para->update_time = curr_time; + if (para->queue_len >= para->queue_len_max) { + para->probability = (para->probability + INCREMENT) > PROBABILITY_MAX ? PROBABILITY_MAX : (para->probability + INCREMENT); + } else if (para->queue_len == 0) { + para->probability = (para->probability - DECREMENT) >= 0 ? (para->probability - DECREMENT) : 0; + } + } + + if (rand() / PROBABILITY_MAX < para->probability) { + return 1; + } + + return 0; +} +/**************************blue*****************************/ + +#if 0 +/**************************stochastic fair blue*****************************/ +/* + * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level) + * This implementation uses L = 8 and N = 16 + * This permits us to split one 32bit hash (provided per packet by rxhash or + * external classifier) into 8 subhashes of 4 bits. + */ +#define SFB_BUCKET_SHIFT 4 +#define SFB_NUMBUCKETS (1 << SFB_BUCKET_SHIFT) /* N bins per Level */ +#define SFB_BUCKET_MASK (SFB_NUMBUCKETS - 1) +#define SFB_LEVELS (32 / SFB_BUCKET_SHIFT) /* L */ + +struct sfb_bucket { + int queue_len; + int probability; +}; +struct shaper_aqm_sfb_para { + struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS]; +}; +/**************************stochastic fair blue*****************************/ +#endif + + +#if 0 +/**************************codel*****************************/ +#define CODEL_MAX_LATENCY 1500000 //unit:us + +#define REC_INV_SQRT_BITS (8 * sizeof(unsigned short)) /* or sizeof_in_bits(rec_inv_sqrt) */ +/* needed shift to get a Q0.32 number from rec_inv_sqrt */ +#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS) + +static void shaper_aqm_codel_enqueue() +{ + return; +} + +static void shaper_aqm_codel_Newton_step(struct codel_vars *vars) +{ + unsigned int invsqrt = ((unsigned int)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; + unsigned int invsqrt2 = ((unsigned long long)invsqrt * invsqrt) >> 32; + unsigned long long val = (3LL << 32) - ((unsigned long long)vars->count * invsqrt2); + + val >>= 2; /* avoid overflow in following multiply */ + val = (val * invsqrt) >> (32 - 2 + 1); + + vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; +} + +static inline unsigned int reciprocal_scale(unsigned int val, unsigned int ep_ro) +{ + return (unsigned int)(((unsigned long long) val * ep_ro) >> 32); +} + +static unsigned long long shaper_aqm_codel_control_law(unsigned long long t, + unsigned long long interval, + unsigned int rec_inv_sqrt) +{ + return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); +} + +static int shaper_aqm_codel_need_drop(struct shaper_aqm_codel_para *para, struct shaping_profile_info *profile) +{ + struct timespec time; + unsigned long long curr_time; + + clock_gettime(CLOCK_MONOTONIC, &time); + curr_time = time.tv_sec * MICRO_SECONDS_PER_SEC + time.tv_nsec / NANO_SECONDS_PER_MICRO_SEC; + + if (curr_time - profile->enqueue_time_us < CODEL_MAX_LATENCY) { + //TODO:swarmkv set first above time to 0 + return 0; + } + + if (first_above_time_us == 0) { + first_above_time_us = curr_time + para->interval;//set in swarmkv + return 0; + } else if (curr_time > first_above_time_us) { + return 1; + } +} + +static int shaper_aqm_codel_dequeue_action() +{ + int need_drop = shaper_aqm_codel_need_drop(); + + if (dropping_state) { + if (!need_drop) { + dropping_state = 0; + } else if (curr_time > drop_next) { + drop_count++; + shaper_aqm_codel_Newton_step(); + drop_next = shaper_aqm_codel_control_law(); + } + } else if (need_drop) { + dropping_state = 1; + delta = drop_count - last_drop_count; + if (delta > 1 && (curr_time - drop_next) < 16 * interval) { + drop_count = delta; + shaper_aqm_codel_Newton_step(); + } else { + drop_count = 1; + rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT; + } + + last_drop_count = drop_count; + drop_next = shaper_aqm_codel_control_law(); + } +} +/**************************codel*****************************/ +#endif + + +int shaper_aqm_enqueue(struct shaping_profile_info *profile) +{ + switch (profile->aqm_type) { + case AQM_TYPE_BLUE: + if (shaper_aqm_blue_need_drop(profile->id, &profile->aqm_para.blue_para)) { + return AQM_ACTION_DROP; + } else { + return AQM_ACTION_PASS; + } + case AQM_TYPE_CODEL: + default: + return AQM_ACTION_PASS; + } +} + +int shaper_aqm_dequeue() +{ + return AQM_ACTION_PASS; +} + +int shaper_aqm_need_drop(struct shaping_profile_info *profile, struct shaping_packet_wrapper *pkt_wrapper) +{ + switch (profile->aqm_type) { + case AQM_TYPE_BLUE: + + case AQM_TYPE_CODEL: + + default: + return 0; + } +}
\ No newline at end of file |
