summaryrefslogtreecommitdiff
path: root/shaping/src/shaper_aqm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shaping/src/shaper_aqm.cpp')
-rw-r--r--shaping/src/shaper_aqm.cpp177
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