1 static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,2 const struct tcphdr *th)3 {4 struct inet_connection_sock *icsk =inet_csk(sk);5 struct tcp_sock *tp =tcp_sk(sk);6 struct tcp_fastopen_cookie foc = { .len = -1};7 int saved_clamp = tp->rx_opt.mss_clamp;8 boolfastopen_fail;9
10 /*解析tcp选项*/
11 tcp_parse_options(skb, &tp->rx_opt, 0, &foc);12
13 /*有时间戳,有回显,记录回显*/
14 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)15 tp->rx_opt.rcv_tsecr -= tp->tsoffset;16
17 if (th->ack) {18 /*rfc793:19 * "If the state is SYN-SENT then20 * first check the ACK bit21 * If the ACK bit is set22 * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send23 * a reset (unless the RST bit is set, if so drop24 * the segment and return)"25 */
26 /*ack <= una || ack > nxt,ack确认序号错误*/
27 if (!after(TCP_SKB_CB(skb)->ack_seq, tp->snd_una) ||
28 after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt))29 gotoreset_and_undo;30
31 /*对端时间戳不合法*/
32 if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
33 !between(tp->rx_opt.rcv_tsecr, tp->retrans_stamp,34 tcp_time_stamp)) {35 NET_INC_STATS(sock_net(sk),36 LINUX_MIB_PAWSACTIVEREJECTED);37 gotoreset_and_undo;38 }39
40 /*Now ACK is acceptable.41 *42 * "If the RST bit is set43 * If the ACK was acceptable then signal the user "error:44 * connection reset", drop the segment, enter CLOSED state,45 * delete TCB, and return."46 */
47
48 /*设置了rst标志*/
49 if (th->rst) {50 tcp_reset(sk);51 gotodiscard;52 }53
54 /*rfc793:55 * "fifth, if neither of the SYN or RST bits is set then56 * drop the segment and return."57 *58 * See note below!59 * --ANK(990513)60 */
61 /*未设置syn标志*/
62 if (!th->syn)63 gotodiscard_and_undo;64
65 /*rfc793:66 * "If the SYN bit is on ...67 * are acceptable then ...68 * (our SYN has been ACKed), change the connection69 * state to ESTABLISHED..."70 */
71 /*ecn标记*/
72 tcp_ecn_rcv_synack(tp, th);73
74 /*记录窗口更新时数据包序号*/
75 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);76
77 //输入ack处理,使用慢速路径,可能会更新发送窗口
78 tcp_ack(sk, skb, FLAG_SLOWPATH);79
80 /*Ok.. it's good. Set up sequence numbers and81 * move to established.82 */
83
84 /*更新下一个要接收的序号*/
85 tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;86 /*更新窗口左边,即窗口中最小的序号*/
87 tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;88
89 /*RFC1323: The window in SYN & SYN/ACK segments is90 * never scaled.91 */
92 /*获取发送窗口*/
93 tp->snd_wnd = ntohs(th->window);94
95 /*没有窗口扩大因子*/
96 if (!tp->rx_opt.wscale_ok) {97 /*设置为0*/
98 tp->rx_opt.snd_wscale = tp->rx_opt.rcv_wscale = 0;99 /*设置最大值*/
100 tp->window_clamp = min(tp->window_clamp, 65535U);101 }102
103 /*有时间戳选项*/
104 if (tp->rx_opt.saw_tstamp) {105 /*在syn中有时间戳选项*/
106 tp->rx_opt.tstamp_ok = 1;107
108 /*tcp首部需要增加时间戳长度*/
109 tp->tcp_header_len =
110 sizeof(struct tcphdr) +TCPOLEN_TSTAMP_ALIGNED;111
112 /*mss需要减去时间戳长度*/
113 tp->advmss -=TCPOLEN_TSTAMP_ALIGNED;114
115 /*设置回显时间戳*/
116 tcp_store_ts_recent(tp);117 } else{118 /*记录tcp首部长度*/
119 tp->tcp_header_len = sizeof(structtcphdr);120 }121
122 /*有sack选项,开启了fack算法,则打标记*/
123 if (tcp_is_sack(tp) &&sysctl_tcp_fack)124 tcp_enable_fack(tp);125
126 /*MTU探测相关初始化*/
127 tcp_mtup_init(sk);128 /*计算mss*/
129 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);130 /*初始化rcv_mss*/
131 tcp_initialize_rcv_mss(sk);132
133 /*Remember, tcp_poll() does not lock socket!134 * Change state from SYN-SENT only after copied_seq135 * is initialized.*/
136
137 /*记录用户空间待读取的序号*/
138 tp->copied_seq = tp->rcv_nxt;139
140 smp_mb();141
142 /*连接建立完成的状态改变和相关初始化*/
143 tcp_finish_connect(sk, skb);144
145 /*fastopen处理*/
146 fastopen_fail = (tp->syn_fastopen || tp->syn_data) &&
147 tcp_rcv_fastopen_synack(sk, skb, &foc);148
149 /*连接未在关闭态,则进行一些唤醒操作*/
150 if (!sock_flag(sk, SOCK_DEAD)) {151 sk->sk_state_change(sk);152 sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);153 }154 if(fastopen_fail)155 return -1;156
157 /*有写数据请求|| 收包accept || 延迟ack*/
158 if (sk->sk_write_pending ||
159 icsk->icsk_accept_queue.rskq_defer_accept ||
160 icsk->icsk_ack.pingpong) {161 /*Save one ACK. Data will be ready after162 * several ticks, if write_pending is set.163 *164 * It may be deleted, but with this feature tcpdumps165 * look so _wonderfully_ clever, that I was not able166 * to stand against the temptation 8) --ANK167 */
168 /*标志ack调度*/
169 inet_csk_schedule_ack(sk);170 /*进入快速ack模式*/
171 tcp_enter_quickack_mode(sk);172 /*设置延迟ack定时器*/
173 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,174 TCP_DELACK_MAX, TCP_RTO_MAX);175
176 discard:177 tcp_drop(sk, skb);178 return 0;179 } else{180 /*回复ack*/
181 tcp_send_ack(sk);182 }183 return -1;184 }185
186 /*省略了rst以及syn状态的代码*/
187 }