这是内核协议栈里面的一个发送窗口赋值代码
tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
snd_wscale : 4, /* Window scaling received from sender */ rcv_wscale : 4; /* Window scaling to send to receiver */
/* Maximal number of window scale according to RFC1323 */ #define TCP_MAX_WSCALE 14U
看下rfc 1312 文档
Using the Window Scale Option A model implementation of window scaling is as follows, using the notation of RFC-793 [Postel81]: * All windows are treated as 32-bit quantities for storage in the connection control block and for local calculations. This includes the send-window (SND.WND) and the receive- window (RCV.WND) values, as well as the congestion window. * The connection state is augmented by two window shift counts, Snd.Wind.Scale and Rcv.Wind.Scale, to be applied to the incoming and outgoing window fields, respectively. * If a TCP receives a <SYN> segment containing a Window Scale option, it sends its own Window Scale option in the <SYN,ACK> segment. * The Window Scale option is sent with shift.cnt = R, where R is the value that the TCP would like to use for its receive window. * Upon receiving a SYN segment with a Window Scale option containing shift.cnt = S, a TCP sets Snd.Wind.Scale to S and sets Rcv.Wind.Scale to R; otherwise, it sets both Snd.Wind.Scale and Rcv.Wind.Scale to zero. * The window field (SEG.WND) in the header of every incoming segment, with the exception of SYN segments, is left-shifted by Snd.Wind.Scale bits before updating SND.WND: SND.WND = SEG.WND << Snd.Wind.Scale (assuming the other conditions of RFC793 are met, and using the "C" notation "<<" for left-shift). * The window field (SEG.WND) of every outgoing segment, with the exception of SYN segments, is right-shifted by Rcv.Wind.Scale bits: SEG.WND = RCV.WND >> Rcv.Wind.Scale.
TCP determines if a data segment is "old" or "new" by testing whether its sequence number is within 2**31 bytes of the left edge of the window, and if it is not, discarding the data as "old". To insure that new data is never mistakenly considered old and vice- versa, the left edge of the sender's window has to be at most 2**31 away from the right edge of the receiver's window. Similarly with the sender's right edge and receiver's left edge. Since the right and left edges of either the sender's or receiver's window differ by the window size, and since the sender and receiver windows can be out of phase by at most the window size, the above constraints imply that 2 * the max window size must be less than 2**31, or max window < 2**30 Since the max window is 2**S (where S is the scaling shift count) times at most 2**16 - 1 (the maximum unscaled window), the maximum window is guaranteed to be < 2*30 if S <= 14. Thus, the shift count must be limited to 14 (which allows windows of 2**30 = 1 Gbyte). If a Window Scale option is received with a shift.cnt value exceeding 14, the TCP should log the error but use 14 instead of the specified value. The scale factor applies only to the Window field as transmitted in the TCP header; each TCP using extended windows will maintain the window values locally as 32-bit numbers. For example, the "congestion window" computed by Slow Start and Congestion Avoidance is not affected by the scale factor, so window scaling will not introduce quantization into the congestion window.
要识别一个序号相对另一个序号在前还是在后,窗口必须不能大于半个 2^32 字节,最大值为 2^31 字节,也就是 2 GB;
此时需要参考在 32bit 的 unsigned int 圆环域上,两个数字顺时针间隔在一个半圆内才能无歧义比较大小(参考 Linux kernel 的 before,after 宏定义实现)