假定客户端执行主动打开,发送syn包到服务器,服务器执行完该包的第一次握手操作后,调用af_ops->send_synack向客户端发送syn+ack包,该回调实际调用tcp_v4_send_synack函数;
1 int tcp_conn_request(struct request_sock_ops *rsk_ops,
2 const struct tcp_request_sock_ops *af_ops,
3 struct sock *sk, struct sk_buff *skb)
4 {
5 /* 第一次握手的服务器处理 */
6
7 /* 发送syn+ack */
8 af_ops->send_synack(sk, dst, &fl, req, &foc,
9 !want_cookie ? TCP_SYNACK_NORMAL :
10 TCP_SYNACK_COOKIE);
11 return 0;
12 }
tcp_v4_send_synack完成路由查找,构造syn+ack包,构造ip包,然后发送出去;
1 /*
2 * Send a SYN-ACK after having received a SYN.
3 * This still operates on a request_sock only, not on a big
4 * socket.
5 */
6 static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
7 struct flowi *fl,
8 struct request_sock *req,
9 struct tcp_fastopen_cookie *foc,
10 enum tcp_synack_type synack_type)
11 {
12 const struct inet_request_sock *ireq = inet_rsk(req);
13 struct flowi4 fl4;
14 int err = -1;
15 struct sk_buff *skb;
16
17 /* First, grab a route. */
18 /* 路由为空则查路由 */
19 if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
20 return -1;
21
22 /* 构造syn+ack包 */
23 skb = tcp_make_synack(sk, dst, req, foc, synack_type);
24
25 if (skb) {
26 /* 生成校验码 */
27 __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
28
29 /* 构造ip包并发送 */
30 err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
31 ireq->ir_rmt_addr,
32 ireq->opt);
33
34 /* 返回错误是否为本地阻塞判断 */
35 err = net_xmit_eval(err);
36 }
37
38 return err;
39 }
tcp_make_synack函数完成skb分配,tcp首部的构造;
1 struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
2 struct request_sock *req,
3 struct tcp_fastopen_cookie *foc,
4 enum tcp_synack_type synack_type)
5 {
6 struct inet_request_sock *ireq = inet_rsk(req);
7 const struct tcp_sock *tp = tcp_sk(sk);
8 struct tcp_md5sig_key *md5 = NULL;
9 struct tcp_out_options opts;
10 struct sk_buff *skb;
11 int tcp_header_size;
12 struct tcphdr *th;
13 int mss;
14
15 /* 分配skb */
16 skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
17 if (unlikely(!skb)) {
18 dst_release(dst);
19 return NULL;
20 }
21 /* Reserve space for headers. */
22 /* 保留头部空间 */
23 skb_reserve(skb, MAX_TCP_HEADER);
24
25 switch (synack_type) {
26 case TCP_SYNACK_NORMAL:
27 /* skb关联控制块 */
28 skb_set_owner_w(skb, req_to_sk(req));
29 break;
30 case TCP_SYNACK_COOKIE:
31 /* Under synflood, we do not attach skb to a socket,
32 * to avoid false sharing.
33 */
34 break;
35 case TCP_SYNACK_FASTOPEN:
36 /* sk is a const pointer, because we want to express multiple
37 * cpu might call us concurrently.
38 * sk->sk_wmem_alloc in an atomic, we can promote to rw.
39 */
40 skb_set_owner_w(skb, (struct sock *)sk);
41 break;
42 }
43
44 /* 设置路由缓存 */
45 skb_dst_set(skb, dst);
46
47 /* mss取从路由表中查询的mss与user_mss之间的较小值 */
48 mss = tcp_mss_clamp(tp, dst_metric_advmss(dst));
49
50 memset(&opts, 0, sizeof(opts));
51 #ifdef CONFIG_SYN_COOKIES
52 if (unlikely(req->cookie_ts))
53 skb->skb_mstamp.stamp_jiffies = cookie_init_timestamp(req);
54 else
55 #endif
56
57 /* 获取时间戳 */
58 skb_mstamp_get(&skb->skb_mstamp);
59
60 #ifdef CONFIG_TCP_MD5SIG
61 rcu_read_lock();
62 md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req));
63 #endif
64
65 /* 设置hash */
66 skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4);
67 /* 设置tcp选项 */
68 tcp_header_size = tcp_synack_options(req, mss, skb, &opts, md5, foc) +
69 sizeof(*th);
70
71 /* 构造填充tcp头 */
72 skb_push(skb, tcp_header_size);
73 skb_reset_transport_header(skb);
74
75 th = (struct tcphdr *)skb->data;
76 memset(th, 0, sizeof(struct tcphdr));
77 /* 设置syn+ack标记 */
78 th->syn = 1;
79 th->ack = 1;
80 tcp_ecn_make_synack(req, th);
81 /* 设置源目的端口 */
82 th->source = htons(ireq->ir_num);
83 th->dest = ireq->ir_rmt_port;
84 /* Setting of flags are superfluous here for callers (and ECE is
85 * not even correctly set)
86 */
87
88 /* 初始化无数据的skb,标志为syn+ack */
89 tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
90 TCPHDR_SYN | TCPHDR_ACK);
91
92 /* 设置序号和确认序号 */
93 th->seq = htonl(TCP_SKB_CB(skb)->seq);
94 /* XXX data is queued and acked as is. No buffer/window check */
95 th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
96
97 /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
98 /* 设置窗口 */
99 th->window = htons(min(req->rsk_rcv_wnd, 65535U));
100
101 /* 写入选项 */
102 tcp_options_write((__be32 *)(th + 1), NULL, &opts);
103
104 /* 设置首部长度 */
105 th->doff = (tcp_header_size >> 2);
106 __TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS);
107
108 #ifdef CONFIG_TCP_MD5SIG
109 /* Okay, we have all we need - do the md5 hash if needed */
110 if (md5)
111 tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location,
112 md5, req_to_sk(req), skb);
113 rcu_read_unlock();
114 #endif
115
116 /* Do not fool tcpdump (if any), clean our debris */
117 skb->tstamp = 0;
118 return skb;
119 }