1. 程式人生 > >linux核心引數tcp_syn_retries、tcp_retries1和tcp_retries2的原始碼分析

linux核心引數tcp_syn_retries、tcp_retries1和tcp_retries2的原始碼分析

enum {
	TCP_ESTABLISHED = 1,
	TCP_SYN_SENT,
	TCP_SYN_RECV,
	TCP_FIN_WAIT1,
	TCP_FIN_WAIT2,
	TCP_TIME_WAIT,
	TCP_CLOSE,
	TCP_CLOSE_WAIT,
	TCP_LAST_ACK,
	TCP_LISTEN,
	TCP_CLOSING,	/* Now a valid state */

	TCP_MAX_STATES	/* Leave at the end! */
};

enum {
	TCPF_ESTABLISHED = (1 << 1),
	TCPF_SYN_SENT	 = (1 << 2),
	TCPF_SYN_RECV	 = (1 << 3),
	TCPF_FIN_WAIT1	 = (1 << 4),
	TCPF_FIN_WAIT2	 = (1 << 5),
	TCPF_TIME_WAIT	 = (1 << 6),
	TCPF_CLOSE	 = (1 << 7),
	TCPF_CLOSE_WAIT	 = (1 << 8),
	TCPF_LAST_ACK	 = (1 << 9),
	TCPF_LISTEN	 = (1 << 10),
	TCPF_CLOSING	 = (1 << 11) 
};

linux-2.6.20/net/ipv4/tcp_timer.c
119~167行:
/* A write timeout has occurred. Process the after effects. */
static int tcp_write_timeout(struct sock *sk)
{
	struct inet_connection_sock *icsk = inet_csk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	int retry_until;
	int mss;

	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                ////////////////// tcp_syn_retries //////////////////
		if (icsk->icsk_retransmits)
			dst_negative_advice(&sk->sk_dst_cache);
		retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
	} else {
		if (icsk->icsk_retransmits >= sysctl_tcp_retries1) {
                        ////////////////// tcp_retries1 //////////////////
			/* Black hole detection */
			if (sysctl_tcp_mtu_probing) {
				if (!icsk->icsk_mtup.enabled) {
					icsk->icsk_mtup.enabled = 1;
					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
				} else {
					mss = min(sysctl_tcp_base_mss,
					          tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
					mss = max(mss, 68 - tp->tcp_header_len);
					icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
					tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
				}
			}

			dst_negative_advice(&sk->sk_dst_cache);
		}
                ////////////////// tcp_retries2 //////////////////
		retry_until = sysctl_tcp_retries2;
		if (sock_flag(sk, SOCK_DEAD)) {
			const int alive = (icsk->icsk_rto < TCP_RTO_MAX);
 
			retry_until = tcp_orphan_retries(sk, alive);

			if (tcp_out_of_resources(sk, alive || icsk->icsk_retransmits < retry_until))
				return 1;
		}
	}

	if (icsk->icsk_retransmits >= retry_until) {
		/* Has it gone just too far? */
		tcp_write_err(sk);
		return 1;
	}
	return 0;
}



tcp_syn_retries:
(1)主動新建一個連線時(也就是sock處於SYN_SEND狀態時),核心要重試傳送多少個SYN請求包後才決定放棄;
(2)收到了SYN連線請求後(也就是sock處於SYN_RECV狀態時),核心要重試傳送多少個ACK確認包才決定放棄?  tcp_synack_retries引數一樣?

tcp_retries1:
在連線建立過程中(未啟用的sock),除了上面的情況以外,核心要重試多少次後才決定放棄連線。

http://blog.csdn.net/zhongruixian/article/details/52488358


tcp_retries2:
在通訊過程中(已啟用的sock),資料包傳送失敗後,核心要重試傳送多少次後才決定放棄連線。