TCP接收窗口--确定Window Scaling

19521阅读 0评论2017-05-04 frankzfz
分类:LINUX

1. rcv_scale的确定

    缓存的配置对后面三次握手交互时,设置window scale的值有很大的关系,window scale的值是在三次握手时通过tcp option确定。

1.1 client发送syn

在三次握手的过程中会根据配置的缓存大小,确定scale的大小,在发送syn数据包和syn+ack报文中,在创建syn数据包时,调用tcp_connect_init函数,在该函数中tcp_select_initial_window函数,对rcv_wscale进行赋值。

点击(此处)折叠或打开

  1. void tcp_select_initial_window(int __space, __u32 mss,
  2.              __u32 *rcv_wnd, __u32 *window_clamp,
  3.              int wscale_ok, __u8 *rcv_wscale,
  4.              __u32 init_rcv_wnd)
  5. {
  6.     unsigned int space = (__space < 0 ? 0 : __space);

  7.     /* If no clamp set the clamp to the max possible scaled window */
  8.     if (*window_clamp == 0)
  9.         (*window_clamp) = (65535 << 14);
  10.     space = min(*window_clamp, space);

  11.     /* Quantize space offering to a multiple of mss if possible. */
  12.     if (space > mss)
  13.         space = (space / mss) * mss;

  14.     if (sysctl_tcp_workaround_signed_windows)
  15.         (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
  16.     else
  17.         (*rcv_wnd) = space;
  18.     (*rcv_wscale) = 0;
  19.     if (wscale_ok) { /*这里的wscale_ok对应于sysctl_tcp_window_scaling参数,该参数内核默认配置为1,表示启用scale*/
  20.         space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
  21.         space = min_t(u32, space, *window_clamp);
  22.         while (space > 65535 && (*rcv_wscale) < 14) { /*如果可用的space大于win能表示的最大值,并且wsacle小于14,则对rcv_wscale进行加1,对space缩小。*/
  23.             space >>= 1;
  24.             (*rcv_wscale)++;
  25.         }
  26.     }

  27.     if (mss > (1 << *rcv_wscale)) {
  28.         if (!init_rcv_wnd) /* Use default unless specified otherwise */
  29.             init_rcv_wnd = tcp_default_init_rwnd(mss);
  30.         *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
  31.     }

  32.     /* Set the clamp no higher than max representable value */
  33.     (*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
  34. }



1.2  syn_ack报文设置rcv_wscale

在接收到syn报文后,发送syn+ack报文下面是设置rcv_scale的流程,也是调用tcp_select_initial_window函数进行初始化。

点击(此处)折叠或打开

  1. static unsigned int tcp_synack_options(struct sock *sk,
  2.                  struct request_sock *req,
  3.                  unsigned int mss, struct sk_buff *skb,
  4.                  struct tcp_out_options *opts,
  5.                  const struct tcp_md5sig_key *md5,
  6.                  struct tcp_fastopen_cookie *foc)
  7. {
  8.     struct inet_request_sock *ireq = inet_rsk(req);
  9.     unsigned int remaining = MAX_TCP_OPTION_SPACE;

  10. #ifdef CONFIG_TCP_MD5SIG
  11.     if (md5) {
  12.         opts->options |= OPTION_MD5;
  13.         remaining -= TCPOLEN_MD5SIG_ALIGNED;
  14.         ireq->tstamp_ok &= !ireq->sack_ok;
  15.     }
  16. #endif

  17.     /* We always send an MSS option. */
  18.     opts->mss = mss;
  19.     remaining -= TCPOLEN_MSS_ALIGNED;
  20.     if (likely(ireq->wscale_ok)) { //设置tcp的选项信息wscale
  21.         opts->ws = ireq->rcv_wscale;
  22.         opts->options |= OPTION_WSCALE;
  23.         remaining -= TCPOLEN_WSCALE_ALIGNED;
  24.     }
  25.     if (likely(ireq->tstamp_ok)) {
  26.         opts->options |= OPTION_TS;
  27.         opts->tsval = tcp_skb_timestamp(skb);
  28.         opts->tsecr = req->ts_recent;
  29.         remaining -= TCPOLEN_TSTAMP_ALIGNED;
  30.     }
  31.     if (likely(ireq->sack_ok)) {
  32.         opts->options |= OPTION_SACK_ADVERTISE;
  33.         if (unlikely(!ireq->tstamp_ok))
  34.             remaining -= TCPOLEN_SACKPERM_ALIGNED;
  35.     }
  36.     if (foc != NULL && foc->len >= 0) {
  37.         u32 need = foc->len;

  38.         need += foc->exp ? TCPOLEN_EXP_FASTOPEN_BASE :
  39.                  TCPOLEN_FASTOPEN_BASE;
  40.         need = (need + 3) & ~3U; /* Align to 32 bits */
  41.         if (remaining >= need) {
  42.             opts->options |= OPTION_FAST_OPEN_COOKIE;
  43.             opts->fastopen_cookie = foc;
  44.             remaining -= need;
  45.         }
  46.     }
  47.     return MAX_TCP_OPTION_SPACE - remaining;
  48. }

1.3 解析scale选项

接收到带有tcp选项scale数据报文时,处理流程如下,只针对syn数据包:



上一篇:TCP接收窗口--确定Window
下一篇:docker的overlay网络---Docker native overlay network