其实这不是我的优化,我是借用了BBR之力。         借了什么力呢?这是我一再强调的,BBR最大的共享不是为Linux贡献了一个TCP拥塞控制算法(它同时在也BSD上被实现...),而是它重构了Linux TCP的实现!借助BBR对Linux TCP实现的重构,很多之前做不到的事情,现在可以做到了。         简而言之,BBR算法对Linux TCP实现的重构中,将以下三件事完全分离: 1.重传哪些包; 2.传输多少包; 3.实际传输。 拥塞控制算法侧重解决上述第2点问题。 ----------------------------------- CDG必须要拥塞窗口的背后默默维护一个”自己的窗口“,称为shadow_wnd,该窗口只受”实际拥塞情况“的影响,而不受”Linux TCP拥塞状态机“的影响。所以说,即便在丢包重传的Recovery时期,也必须动态维护这个shadow_wnd,使其按照Reno方式增长(或者按照CUBIC方式,随便什么方式都可以)。         然则这在BBR之前的Linux 4.8版本之前的内核中是无法做到的。因为tcp_congestion_ops机构体中没有一个回调函数是在Recovery阶段可以被调用的到的,而你所能控制的拥塞算法只能通过tcp_congestion_ops结构体的回调来实现。 BBR将以下的逻辑引入到了Linux: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked,                   int flag, const struct rate_sample *rs)  {      const struct inet_connection_sock *icsk = inet_csk(sk);        if (icsk->icsk_ca_ops->cong_control) {          icsk->icsk_ca_ops->cong_control(sk, rs);          return;      }        if (tcp_in_cwnd_reduction(sk)) {          /* Reduce cwnd if state mandates */          tcp_cwnd_reduction(sk, acked_sacked, flag);      } else if (tcp_may_raise_cwnd(sk, flag)) {          /* Advance cwnd if state allows */          tcp_cong_avoid(sk, ack, acked_sacked);      }      tcp_update_pacing_rate(sk);  }

只要实现了cong_control回调,那就就不会再调用标准的PRR算法和拥塞避免tcp_cong_avoid函数,无论在任何阶段,均调用cong_control回调。因此,我的方法是,在Recovery或者Loss状态调用cong_control回调即可!在该回调中维护CDG的shadow窗口。         这谈何容易!BBR引入的逻辑非常粗糙,只要实现了cong_control,该函数就无条件返回。事实上正确的做法是cong_control回调有个返回值,当满足一定条件时返回,否则继续下面的逻辑。但是BBR并没有引入这些。 ----------------------------------- 但是,我将其引入了。         请看,我将tcp_input.c中的tcp_cong_control改成了下面的样子: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static void tcp_cong_control(struct sock *sk, u32 ack, u32 prior_in_flight, u32 acked_sacked,                                               int flag, const struct rate_sample *rs)  {          const struct inet_connection_sock *icsk = inet_csk(sk);  #ifdef BBR          if (icsk->icsk_ca_ops->cong_control) {                  icsk->icsk_ca_ops->cong_control(sk, rs);  #ifdef CDG                  // 以下是我添加的判断,新增了rs的flag字段,一旦置位就继续而不返回。                  if (!(rs->flag & CDG_CONT))                          return;  #endif          }  #endif          if (tcp_in_cwnd_reduction(sk)) {          /* Reduce cwnd if state mandates */                  tcp_cwnd_reduction(sk, acked_sacked, 1);          } else if (tcp_may_raise_cwnd(sk, flag)) {                  /* Advance cwnd if state allows */                  tcp_cong_avoid(sk, ack, prior_in_flight);          }          tcp_update_pacing_rate(sk);  }  我添加了个判断。其实我的目的很简单,就是在Recovery状态下也能调用到CDG的逻辑,就这么简单个逻辑在不懂的人眼里显得如此高大上,在懂的人眼里显得如此傻逼...不管怎样,我做了。 ----------------------------------- 以下的代码只是我对标准Linux 4.3内核CDG算法的differ,想理解代码细节的,请先阅读标准CDG代码,我虽然是个传说中有求必应的人,但那只是传说...请注意,我的目标内核是3.10内核,在我移植CDG之前,我已经移植了BBR,所以说,你最好以4.9内核为准,然而这样一来,又会对3.10内核的一些接口表示费解..这里不就不多解释了,我要说的是,想彻底逃离学院派,就必须把所有这些代码都搞清楚!不然的话,首先,你根本什么都看不懂,其次,即便你有想法,你也做不来。完整的代码我会附在本文最后。 以下是patch中几个重要函数的说明: 1.CDG的cong_control回调函数cdg_main: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static void cdg_main(struct sock *sk, struct rate_sample *rs)  {          struct inet_connection_sock *icsk = inet_csk(sk);          struct tcp_sock *tp = tcp_sk(sk);          struct cdg *ca = inet_csk_ca(sk);            if (!shadow_grow) {                  rs->flag |= CDG_CONT;                  return;          }            if (icsk->icsk_ca_state != TCP_CA_Open) {                  // 在重传阶段,依然要采集rtt,因为链路不问包类型,重传包也会影响网络可用容量。                  if (rs->rtt_us) {                          // 感谢BBR增加了rs结构体,从中可以取rtt_us                          ca->rtt.min = min_not_zero(ca->rtt.min, (s32)rs->rtt_us);                          ca->rtt.max = max(ca->rtt.max, (s32)rs->rtt_us);                  }                    if (ca->state == CDG_NONFULL && use_tolerance) {                          if (!shadow_fast && (ca->ack_sack_cnt < 0 || ca->ack_sack_cnt == 0) && ca->rtt.v64) {                                  s32 grad = 0;                                    if (ca->rtt_prev.v64)                                          grad = tcp_cdg_grad(ca);                                  ca->rtt_prev = ca->rtt;                                  ca->ack_sack_cnt = tcp_packets_in_flight(tp);                                  ca->rtt.v64 = 0;                          }                          ca->ack_sack_cnt -= rs->acked_sacked;                          if (ca->state == CDG_NONFULL || shadow_fast) {                                  // 如果链路未完全拥塞,那么shadow窗口便默默地帮助实际窗口占据空间,等到快速恢复结束,便可以由实际窗口可用。                                  tcp_cong_avoid_ai_shadow(sk, ca->shadow_wnd, rs->acked_sacked);                                  tp->snd_cwnd = ca->shadow_wnd;                          }                            rs->flag |= CDG_CONT;                  }          } else {                  // 为了让执行流继续,增加CDG_CONT标志。                  rs->flag |= CDG_CONT;          }  }

2.状态设置回调函数cdg_state: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static void cdg_state(struct sock *sk, u8 new_state)  {          struct cdg *ca = inet_csk_ca(sk);          struct tcp_sock *tp = tcp_sk(sk);            if (!recovery_restore)                  return;          if (new_state == TCP_CA_Open)                  // 进入Open状态时,直接接管shadow窗口,这里可能会有突发问题。                  tp->snd_cwnd = max(max(tp->snd_cwnd, ca->shadow_wnd), 2U);          if (new_state == TCP_CA_Loss) {                  // 进入Loss状态,判断是否是噪声丢包                  if (ca->state == CDG_NONFULL && use_tolerance) {                          // 如果是噪声丢包,那么便恢复窗口。                          tp->snd_cwnd = ca->shadow_wnd;                          printk("#### cwnd:%u \n", tp->snd_cwnd);                          if (loss_push)                                  // 如果是噪声丢包,那么在窗口内继续发送数据。                                  tcp_push_pending_frames(sk);                  }                  // 如果是拥塞丢包,那么执行原有流程。          }  }

3.UNDO函数tcp_cdg_undo_cwnd: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static u32 tcp_cdg_undo_cwnd(struct sock *sk)  {          struct cdg *ca = inet_csk_ca(sk);          struct tcp_sock *tp = tcp_sk(sk);          // undo到shadow窗口          return max3(2U, ca->shadow_wnd, max(tp->snd_cwnd, ca->undo_cwnd));  }

4.RTT梯度计算函数tcp_cdg_grad: [plain] view plain copy 在CODE上查看代码片派生到我的代码片 static s32 tcp_cdg_grad(struct cdg *ca)  {          // rtt在pkts_acked回调和cong_control中被采样值更新          s32 gmin = ca->rtt.min - ca->rtt_prev.min;          s32 gmax = ca->rtt.max - ca->rtt_prev.max;          s32 grad;            if (ca->gradients) {                  ca->gsum.min += gmin - ca->gradients[ca->tail].min;                  ca->gsum.max += gmax - ca->gradients[ca->tail].max;                  ca->gradients[ca->tail].min = gmin;                  ca->gradients[ca->tail].max = gmax;                  ca->tail = (ca->tail + 1) & (window - 1);                  gmin = ca->gsum.min;                  gmax = ca->gsum.max;          }          ......          /* Backoff was effectual: */          if (gmin <= -32 || gmax <= -32)                  ca->backoff_cnt = 0;            if (use_tolerance) {                  /* Reduce small variations to zero: */                  gmin = DIV_ROUND_CLOSEST(gmin, 64);                  gmax = DIV_ROUND_CLOSEST(gmax, 64);                  // 注意看上一篇文章CDG模型图示的边沿触发条件。                  if (gmin > 0 && gmax <= 0)                          ca->state = CDG_FULL;                  else if ((gmin > 0 && gmax > 0) || gmax < 0)                          ca->state = CDG_NONFULL;          }          return grad;  }

我首先盲测了一下原生的CDG,Oh NO!太垃圾,比CUBIC好,高丢包率下竟然与Westwood相当,在所有这一切中,BBR始终是另类,遥不可及,在我看了Paper之后,迅速自己实现了一版,感谢BBR对Linux TCP的重构!我承认我自己只懂Reno,BIC,CUBIC,Vegas,BBR这几种算法,其它HTCP,Westwood这些我并没有详细分析过,但是无论我怎么测,我发现我的CDG(应该是我改过的CDG),一直跟BBR接近。         CDG是什么?CDG实际上就是传统基于丢包的算法加上了一个抗噪声机制,本来基于丢包的算法就是以不断填充缓存为手段,直到填满缓存发生丢包进行减窗,然而有的时候并非拥塞的原因也会发生丢包,此时按照算法来看依然会减窗,这就大大降低了带宽的利用率。加上了这个CDG的RTT梯度抗噪声机制后,网络带宽的利用率大大提高了。然而可能会加重拥塞,所以CDG内置了backoff算法,这里就不赘述了。 ----------------------------------- tcp_cdg.c代码:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片 #include <linux/kernel.h>  #include <linux/random.h>  #include <linux/module.h>  #include <net/tcp.h>    #define HYSTART_ACK_TRAIN   1  #define HYSTART_DELAY       2    static int window __read_mostly = 8;  static unsigned int backoff_beta __read_mostly = 0.7071 * 1024; /* sqrt 0.5 */  static unsigned int backoff_factor __read_mostly = 42;  static unsigned int hystart_detect __read_mostly = 3;  static unsigned int use_ineff __read_mostly = 5;  static unsigned int use_shadow __read_mostly = 1;  static unsigned int backoff __read_mostly = 0;  static unsigned int use_tolerance __read_mostly = 1;  static unsigned int shadow_fast __read_mostly = 1;  static unsigned int shadow_grow __read_mostly = 1;  static unsigned int recovery_restore __read_mostly = 1;  static unsigned int loss_push __read_mostly = 1;    module_param(window, int, 0444);  MODULE_PARM_DESC(window, "gradient window size (power of two <= 256)");  module_param(backoff_beta, uint, 0644);  MODULE_PARM_DESC(backoff_beta, "backoff beta (0-1024)");  module_param(backoff_factor, uint, 0644);  MODULE_PARM_DESC(backoff_factor, "backoff probability scale factor");  module_param(hystart_detect, uint, 0644);  MODULE_PARM_DESC(hystart_detect, "use Hybrid Slow start "           "(0: disabled, 1: ACK train, 2: delay threshold, 3: both)");  module_param(use_ineff, uint, 0644);  MODULE_PARM_DESC(use_ineff, "use ineffectual backoff detection (threshold)");  module_param(use_shadow, uint, 0644);  MODULE_PARM_DESC(use_shadow, "use shadow window heuristic");  module_param(backoff, uint, 0644);  MODULE_PARM_DESC(backoff, "back");  module_param(use_tolerance, uint, 0644);  MODULE_PARM_DESC(use_tolerance, "use loss tolerance heuristic");  module_param(shadow_fast, uint, 0644);  MODULE_PARM_DESC(shadow_fast, "back");  module_param(shadow_grow, uint, 0644);  MODULE_PARM_DESC(shadow_grow, "back");  module_param(recovery_restore, uint, 0644);  MODULE_PARM_DESC(recovery_restore, "back");  module_param(loss_push, uint, 0644);  MODULE_PARM_DESC(loss_push, "back");    struct cdg_minmax {      union {          struct {              s32 min;              s32 max;          };          u64 v64;      };  };    enum cdg_state {      CDG_UNKNOWN = 0,      CDG_NONFULL = 1,      CDG_FULL    = 2,      CDG_BACKOFF = 3,  };    struct cdg {      struct cdg_minmax rtt;      struct cdg_minmax rtt_prev;      struct cdg_minmax *gradients;      struct cdg_minmax gsum;      bool gfilled;      u8  tail;      u8  state;      u8  delack;      u32 rtt_seq;      u32 undo_cwnd;      u32 shadow_wnd;      u32 snd_cwnd_cnt;      u16 backoff_cnt;      u16 sample_cnt;      s32 delay_min;      s32 ack_sack_cnt;      u32 last_ack;      u32 round_start;  };    /**   * nexp_u32 - negative base-e exponential   * @ux: x in units of micro   *   * Returns exp(ux * -1e-6) * U32_MAX.   */  static u32 __pure nexp_u32(u32 ux)  {      static const u16 v[] = {          /* exp(-x)*65536-1 for x = 0, 0.000256, 0.000512, ... */          65535,          65518, 65501, 65468, 65401, 65267, 65001, 64470, 63422,          61378, 57484, 50423, 38795, 22965, 8047,  987,   14,      };      u32 msb = ux >> 8;      u32 res;      int i;        /* Cut off when ux >= 2^24 (actual result is <= 222/U32_MAX). */      if (msb > U16_MAX)          return 0;        /* Scale first eight bits linearly: */      res = U32_MAX - (ux & 0xff) * (U32_MAX / 1000000);        /* Obtain e^(x + y + ...) by computing e^x * e^y * ...: */      for (i = 1; msb; i++, msb >>= 1) {          u32 y = v[i & -(msb & 1)] + U32_C(1);            res = ((u64)res * y) >> 16;      }        return res;  }    /* Based on the HyStart algorithm (by Ha et al.) that is implemented in   * tcp_cubic. Differences/experimental changes:   *   o Using Hayes' delayed ACK filter.   *   o Using a usec clock for the ACK train.   *   o Reset ACK train when application limited.   *   o Invoked at any cwnd (i.e. also when cwnd < 16).   *   o Invoked only when cwnd < ssthresh (i.e. not when cwnd == ssthresh).   */  static void tcp_cdg_hystart_update(struct sock *sk)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        ca->delay_min = min_not_zero(ca->delay_min, ca->rtt.min);      if (ca->delay_min == 0)          return;        if (hystart_detect & HYSTART_ACK_TRAIN) {          u32 now_us = div_u64(local_clock(), NSEC_PER_USEC);            if (ca->last_ack == 0 || !tcp_is_cwnd_limited(sk, tcp_packets_in_flight(tp))) {              ca->last_ack = now_us;              ca->round_start = now_us;          } else if (before(now_us, ca->last_ack + 3000)) {              u32 base_owd = max(ca->delay_min / 2U, 125U);                ca->last_ack = now_us;              if (after(now_us, ca->round_start + base_owd)) {                  tp->snd_ssthresh = tp->snd_cwnd;                  return;              }          }      }        if (hystart_detect & HYSTART_DELAY) {          if (ca->sample_cnt < 8) {              ca->sample_cnt++;          } else {              s32 thresh = max(ca->delay_min + ca->delay_min / 8U,                       125U);                if (ca->rtt.min > thresh) {                  tp->snd_ssthresh = tp->snd_cwnd;              }          }      }  }    static s32 tcp_cdg_grad(struct cdg *ca)  {      s32 gmin = ca->rtt.min - ca->rtt_prev.min;      s32 gmax = ca->rtt.max - ca->rtt_prev.max;      s32 grad;        if (ca->gradients) {          ca->gsum.min += gmin - ca->gradients[ca->tail].min;          ca->gsum.max += gmax - ca->gradients[ca->tail].max;          ca->gradients[ca->tail].min = gmin;          ca->gradients[ca->tail].max = gmax;          ca->tail = (ca->tail + 1) & (window - 1);          gmin = ca->gsum.min;          gmax = ca->gsum.max;      }        /* We keep sums to ignore gradients during cwnd reductions;       * the paper's smoothed gradients otherwise simplify to:       * (rtt_latest - rtt_oldest) / window.       *       * We also drop division by window here.       */      grad = gmin > 0 ? gmin : gmax;        /* Extrapolate missing values in gradient window: */      if (!ca->gfilled) {          if (!ca->gradients && window > 1)              grad *= window; /* Memory allocation failed. */          else if (ca->tail == 0)              ca->gfilled = true;          else              grad = (grad * window) / (int)ca->tail;      }        /* Backoff was effectual: */      if (gmin <= -32 || gmax <= -32)          ca->backoff_cnt = 0;        if (use_tolerance) {          /* Reduce small variations to zero: */          gmin = DIV_ROUND_CLOSEST(gmin, 64);          gmax = DIV_ROUND_CLOSEST(gmax, 64);          if (gmin > 0 && gmax <= 0)              ca->state = CDG_FULL;          else if ((gmin > 0 && gmax > 0) || gmax < 0)              ca->state = CDG_NONFULL;      }      return grad;  }    void tcp_enter_cwr_1(struct sock *sk)  {      struct tcp_sock *tp = tcp_sk(sk);        tp->prior_ssthresh = 0;      if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {          tp->undo_marker = 0;          tp->high_seq = tp->snd_nxt;          tp->tlp_high_seq = 0;          tp->snd_cwnd_cnt = 0;          tp->prior_cwnd = tp->snd_cwnd;          tp->prr_delivered = 0;          tp->prr_out = 0;          tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk);          if (tp->ecn_flags & TCP_ECN_OK)              tp->ecn_flags |= TCP_ECN_QUEUE_CWR;          tcp_set_ca_state(sk, TCP_CA_CWR);      }  }    static bool tcp_cdg_backoff(struct sock *sk, u32 grad)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        if (prandom_u32() <= nexp_u32(grad * backoff_factor))          return false;        if (use_ineff) {          ca->backoff_cnt++;          if (ca->backoff_cnt > use_ineff)              return false;      }        ca->shadow_wnd = max(ca->shadow_wnd, tp->snd_cwnd);      ca->state = CDG_BACKOFF;      tcp_enter_cwr_1(sk);      return true;  }    void tcp_cong_avoid_ai_shadow(struct sock *sk, u32 w, u32 acked)  {      struct tcp_sock *tp = tcp_sk(sk);      struct cdg *ca = inet_csk_ca(sk);      if (ca->snd_cwnd_cnt >= w) {          ca->snd_cwnd_cnt = 0;          ca->shadow_wnd ++;      }        ca->snd_cwnd_cnt += acked;      if (ca->snd_cwnd_cnt >= w) {          u32 delta = ca->snd_cwnd_cnt / w;            ca->snd_cwnd_cnt -= delta * w;          ca->shadow_wnd += delta;      }      ca->shadow_wnd = min(ca->shadow_wnd, tp->snd_cwnd_clamp);  }    /* Not called in CWR or Recovery state. */  static void tcp_cdg_cong_avoid(struct sock *sk, u32 ack, u32 acked)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);      u32 prior_snd_cwnd;      u32 incr;        if (tp->snd_cwnd <= tp->snd_ssthresh && hystart_detect)          tcp_cdg_hystart_update(sk);        if (after(ack, ca->rtt_seq) && ca->rtt.v64) {          s32 grad = 0;            if (ca->rtt_prev.v64)              grad = tcp_cdg_grad(ca);          ca->rtt_seq = tp->snd_nxt;          ca->rtt_prev = ca->rtt;          ca->rtt.v64 = 0;          ca->last_ack = 0;          ca->sample_cnt = 0;            if (backoff && grad > 0 && tcp_cdg_backoff(sk, grad))              return;      }        if (!tcp_is_cwnd_limited(sk, tcp_packets_in_flight(tp))) {          ca->shadow_wnd = min(ca->shadow_wnd, tp->snd_cwnd);          return;      }        prior_snd_cwnd = tp->snd_cwnd;      tcp_reno_cong_avoid(sk, ack, acked);        incr = tp->snd_cwnd - prior_snd_cwnd;      ca->shadow_wnd = max(ca->shadow_wnd, ca->shadow_wnd + incr);  }    static void tcp_cdg_acked(struct sock *sk, u32 num_acked, s32 rtt_us)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        if (rtt_us <= 0)          return;        /* A heuristic for filtering delayed ACKs, adapted from:       * D.A. Hayes. "Timing enhancements to the FreeBSD kernel to support       * delay and rate based TCP mechanisms." TR 100219A. CAIA, 2010.       */      if (tp->sacked_out == 0) {          if (num_acked == 1 && ca->delack) {              /* A delayed ACK is only used for the minimum if it is               * provenly lower than an existing non-zero minimum.               */              ca->rtt.min = min(ca->rtt.min, rtt_us);              ca->delack--;              return;          } else if (num_acked > 1 && ca->delack < 5) {              ca->delack++;          }      }        ca->rtt.min = min_not_zero(ca->rtt.min, rtt_us);      ca->rtt.max = max(ca->rtt.max, rtt_us);  }    static u32 tcp_cdg_ssthresh(struct sock *sk)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        ca->undo_cwnd = tp->snd_cwnd;      ca->snd_cwnd_cnt = 0;      ca->ack_sack_cnt = tcp_packets_in_flight(tp);        if (ca->state == CDG_BACKOFF)          return max(2U, (tp->snd_cwnd * min(1024U, backoff_beta)) >> 10);        if (ca->state == CDG_NONFULL && use_tolerance)          return tp->snd_cwnd;        ca->shadow_wnd = max(min(ca->shadow_wnd >> 1, tp->snd_cwnd), 2U);      if (use_shadow)          return max3(2U, ca->shadow_wnd, tp->snd_cwnd >> 1);      return max(2U, tp->snd_cwnd >> 1);  }    static u32 tcp_cdg_undo_cwnd(struct sock *sk)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);      return max3(2U, ca->shadow_wnd, max(tp->snd_cwnd, ca->undo_cwnd));  }    static void tcp_cdg_cwnd_event(struct sock *sk, const enum tcp_ca_event ev)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);      struct cdg_minmax *gradients;    www.sratchina.com  易购娱乐 www.boyuanyl.cn      switch (ev) {      case CA_EVENT_CWND_RESTART:          gradients = ca->gradients;          if (gradients)              memset(gradients, 0, window * sizeof(gradients[0]));          memset(ca, 0, sizeof www.chuangshi88.cn(*ca));            ca->gradients = gradients;          ca->rtt_seq = tp->snd_nxt;          ca->shadow_wnd = tp->snd_cwnd;          break;      case CA_EVENT_COMPLETE_CWR:          ca->state = CDG_UNKNOWN;          ca->rtt_seq = tp->snd_nxt;          ca->rtt_prev = ca-www.sbsbo.cn>rtt;          ca->rtt.v64 =www.sbsbo.cc 0;          break;      default:          break;      }  }    static void tcp_cdg_init(struct www.linkenzc.cn sock *sk)  {      struct cdg *ca = www.linlenyl.cn inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        /* We silently fall back to window = 1 if allocation fails. */      if (window > 1)          ca->gradients = kcalloc(window, sizeof(ca->gradients[0]),                      GFP_NOWAIT | __GFP_NOWARN);      ca->rtt_seq = tp->snd_nxt;      ca->shadow_wnd = tp->snd_cwnd;      ca->ack_sack_cnt = 0;  }    static void tcp_cdg_release(struct sock *sk)  {      struct cdg *ca = inet_csk_ca(sk);        kfree(ca->gradients);  }    static void cdg_main(struct sock *sk, struct rate_sample *rs)  {      struct inet_connection_sock *icsk = inet_csk(sk);      struct tcp_sock *tp = tcp_sk(sk);      struct cdg *ca = inet_csk_ca(sk);            if (!shadow_grow) {          rs->flag |= CDG_CONT;          return;      }                if (icsk->icsk_ca_state != TCP_CA_Open) {          if (rs->rtt_us) {              ca->rtt.min = min_not_zero(ca->rtt.min, (s32)rs->rtt_us);              ca->rtt.max = max(ca->rtt.max, (s32)rs->rtt_us);          }                    if (ca->state == CDG_NONFULL && use_tolerance) {               if (!shadow_fast && (ca->ack_sack_cnt < 0 || ca->ack_sack_cnt == 0) && ca->rtt.v64) {                  s32 grad = 0;                    if (ca->rtt_prev.v64)                      grad = tcp_cdg_grad(ca);                  ca->rtt_prev = ca->rtt;                  ca->ack_sack_cnt = tcp_packets_in_flight(tp);                  ca->rtt.v64 = 0;              }              ca->ack_sack_cnt -= rs->acked_sacked;              if (ca->state == CDG_NONFULL || shadow_fast) {                  tcp_cong_avoid_ai_shadow(sk, ca->shadow_wnd, rs->acked_sacked);                     tp->snd_cwnd = ca->shadow_wnd;              }                            rs->flag |= CDG_CONT;          }      } else {          rs->flag |= CDG_CONT;      }  }    static void cdg_state(struct sock *sk, u8 new_state)  {      struct cdg *ca = inet_csk_ca(sk);      struct tcp_sock *tp = tcp_sk(sk);        if (!recovery_restore)          return;      if (new_state == TCP_CA_Open)          tp->snd_cwnd = max(max(tp->snd_cwnd, ca->shadow_wnd), 2U);      if (new_state == TCP_CA_Loss) {          if (ca->state == CDG_NONFULL && use_tolerance) {              tp->snd_cwnd = ca->shadow_wnd;              if (loss_push)                  tcp_push_pending_frames(sk);          }       }  }    struct tcp_congestion_ops tcp_cdg __read_mostly = {      .cong_avoid = tcp_cdg_cong_avoid,      .cong_control   = cdg_main,      .set_state = cdg_state,      .cwnd_event = tcp_cdg_cwnd_event,      .pkts_acked = tcp_cdg_acked,      .undo_cwnd = tcp_cdg_undo_cwnd,      .ssthresh = tcp_cdg_ssthresh,      .release = tcp_cdg_release,      .init = tcp_cdg_init,      .owner = THIS_MODULE,      .name = "cdg",  };    static int __init tcp_cdg_register(void)  {      if (backoff_beta > 1024 || window < 1 || window > 256)          return -ERANGE;      if (!is_power_of_2(window))          return -EINVAL;        BUILD_BUG_ON(sizeof(struct cdg) > ICSK_CA_PRIV_SIZE);      tcp_register_congestion_control(&tcp_cdg);      return 0;  }    static void __exit tcp_cdg_unregister(void)  {      tcp_unregister_congestion_control(&tcp_cdg);  }    module_init(tcp_cdg_register);  module_exit(tcp_cdg_unregister);  MODULE_AUTHOR("...");  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("TCP CDG");

我对TCP CDG拥塞控制算法的改进和优化的更多相关文章

  1. 网络拥塞控制(三) TCP拥塞控制算法

    为了防止网络的拥塞现象,TCP提出了一系列的拥塞控制机制.最初由V. Jacobson在1988年的论文中提出的TCP的拥塞控制由“慢启动(Slow start)”和“拥塞避免(Congestion  ...

  2. TCP拥塞控制算法 优缺点 适用环境 性能分析

    [摘要]对多种TCP拥塞控制算法进行简要说明,指出它们的优缺点.以及它们的适用环境. [关键字]TCP拥塞控制算法 优点    缺点   适用环境公平性 公平性 公平性是在发生拥塞时各源端(或同一源端 ...

  3. BBR拥塞控制算法

    BBR拥塞控制算法是Google最新研发的单边TCP拥塞控制算法Linux 内核4.9 已引入这个BBR算法,本人在CAC测试Ubuntu 14.04 安装Linux 4.9内核,延迟优化效果和TCP ...

  4. Linux kernel 4.9及以上开启TCP BBR拥塞算法

    Linux kernel 4.9及以上开启TCP BBR拥塞算法 BBR 目的是要尽量跑满带宽, 并且尽量不要有排队的情况, 效果并不比速锐差 Linux kernel 4.9+ 已支持 tcp_bb ...

  5. 基于Flume的美团日志收集系统(二)改进和优化

    在<基于Flume的美团日志收集系统(一)架构和设计>中,我们详述了基于Flume的美团日志收集系统的架构设计,以及为什么做这样的设计.在本节中,我们将会讲述在实际部署和使用过程中遇到的问 ...

  6. TCP拥塞控制算法内核实现剖析(十)

    内核版本:3.2.12 主要源文件:linux-3.2.12/ net/ ipv4/ tcp_veno.c 主要内容:Veno的原理和实现 Author:zhangskd @ csdn blog 概要 ...

  7. TCP控制拥塞的四种算法:慢开始,拥塞避免,快重传,快恢复

    我们在开始假定: 1:数据是单方向传递,另一个窗口只发送确认. 2:接收方的缓存足够大,因此发送方的大小的大小由网络的拥塞程度来决定. 一:慢开始算法和拥塞避免算法 发送方会维持一个拥塞窗口,刚开始的 ...

  8. Kernel 4.9的BBR拥塞控制算法。

    重要的事情说三遍! BBR并不能突破带宽限制!!! BBR并不能突破带宽限制!!! BBR并不能突破带宽限制!!! 它的功能如下: 1.在高丢包率与低速率的网络中提升传输效果,充分利用带宽. 2.降低 ...

  9. TCP/IP详细解释--TCP/IP可靠的原则 推拉窗 拥塞窗口

    TCP和UDP在同一水平---传输层.但TCP和UDP最不一样的地方.TCP它提供了一个可靠的数据传输服务,TCP是面向连接的,那.使用TCP两台主机通过第一通信"拨打电话"这个过 ...

随机推荐

  1. NUnitForms 测试GUI应用程序的优秀工具

    著名的NUnit是单元测试的优秀工具,但是要在一个测试方法中启动GUI程序,比如Windows Form界面,这比较难做到.NUnitForms就是为解决这个问题产生的,它是NUnit的一个扩展程序, ...

  2. Linux初探

    终于心血来潮装了Ubuntu,向着正式程序员迈出了重要一步.不得不说Linux真是一个磨人的小妖精,这篇随笔记录了一些我遇到的问题和解决方法. 1.Ubuntu安装 不知道听谁说的Linux难装,一不 ...

  3. 使用val()方法设置表单中的默认选中项

    有时候我们展示给用户的表单中的checkbox,radio,selec等标签的一些项是默认选中的.比方:当用户改动文章的时候,假设相应的栏目为下拉框的话,那么它的默认选中值应该是原来的栏目位置. 能够 ...

  4. java高精度进制转换

    POJ1131   由于本题只有小数部分(整数部分均为0),故在进制转换的之后只能自己手写转换方法了.   8进制转换10进制的方法为,以0.75为例,应是7*8^-1 + 5*8^-2.所以呢,可以 ...

  5. db2索引创建和删除

    在表trpt_jv_rpt_log_td的tim列上创建索引 create index dw_rpt.irpt_jv_rpt_log_td_tim on dw_rpt.trpt_jv_rpt_log_ ...

  6. css透明背景兼容方案

    css透明是一个技术活,因为这里面涉及到了IE8及以下版本不兼容opacity这个css3属性,而filter:alpha(opacity=80)这个值则是不兼容IE6.网上比较流行的透明css是这样 ...

  7. 用JLabel显示时间-- JAVA初学者遇到的一个困难

    问题:用一个JLabe,显示秒数,每过一秒数字自动减少1 问题看似很简单,但对初学JAVA的我来说,还真费了一点劲. 首先是如何即时,可以采用线程的方法: try { Thread.sleep(100 ...

  8. SQL添加表字段以及SQL查询表,表的所有字段名

    通用式: alter table [表名] add [字段名] 字段属性 default 缺省值 default 是可选参数 增加字段: alter table [表名] add 字段名 smalli ...

  9. 在Servlet(或者Filter,或者Listener)中使用spring的IOC容器

    web.xml中的加载顺序为:listener > filter > servlet > spring. 其中filter的执行顺序是filter-mapping在web.xml中出 ...

  10. intellij IDEA mybatis插件破解方法

    1>安装mybatis插件,找到mybatis_plus.jar包的位置,在C:\Users\LZHL\.IntelliJIdea2016.3\config\plugins\mybatis_pl ...