⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_timer.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * connection. If the socket is an orphan, time it out,		 * we cannot allow such beasts to hang infinitely.		 */#ifdef TCP_DEBUG		if (net_ratelimit()) {			struct inet_opt *inet = inet_sk(sk);			printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",			       NIPQUAD(inet->daddr), htons(inet->dport),			       inet->num, tp->snd_una, tp->snd_nxt);		}#endif		if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {			tcp_write_err(sk);			goto out;		}		tcp_enter_loss(sk, 0);		tcp_retransmit_skb(sk, skb_peek(&sk->sk_write_queue));		__sk_dst_reset(sk);		goto out_reset_timer;	}	if (tcp_write_timeout(sk))		goto out;	if (tp->retransmits == 0) {		if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {			if (tp->sack_ok) {				if (tp->ca_state == TCP_CA_Recovery)					NET_INC_STATS_BH(LINUX_MIB_TCPSACKRECOVERYFAIL);				else					NET_INC_STATS_BH(LINUX_MIB_TCPSACKFAILURES);			} else {				if (tp->ca_state == TCP_CA_Recovery)					NET_INC_STATS_BH(LINUX_MIB_TCPRENORECOVERYFAIL);				else					NET_INC_STATS_BH(LINUX_MIB_TCPRENOFAILURES);			}		} else if (tp->ca_state == TCP_CA_Loss) {			NET_INC_STATS_BH(LINUX_MIB_TCPLOSSFAILURES);		} else {			NET_INC_STATS_BH(LINUX_MIB_TCPTIMEOUTS);		}	}	if (tcp_use_frto(sk)) {		tcp_enter_frto(sk);	} else {		tcp_enter_loss(sk, 0);	}	if (tcp_retransmit_skb(sk, skb_peek(&sk->sk_write_queue)) > 0) {		/* Retransmission failed because of local congestion,		 * do not backoff.		 */		if (!tp->retransmits)			tp->retransmits=1;		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,				     min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));		goto out;	}	/* Increase the timeout each time we retransmit.  Note that	 * we do not increase the rtt estimate.  rto is initialized	 * from rtt, but increases here.  Jacobson (SIGCOMM 88) suggests	 * that doubling rto each time is the least we can get away with.	 * In KA9Q, Karn uses this for the first few times, and then	 * goes to quadratic.  netBSD doubles, but only goes up to *64,	 * and clamps at 1 to 64 sec afterwards.  Note that 120 sec is	 * defined in the protocol as the maximum possible RTT.  I guess	 * we'll have to use something other than TCP to talk to the	 * University of Mars.	 *	 * PAWS allows us longer timeouts and large windows, so once	 * implemented ftp to mars will work nicely. We will have to fix	 * the 120 second clamps though!	 */	tp->backoff++;	tp->retransmits++;out_reset_timer:	tp->rto = min(tp->rto << 1, TCP_RTO_MAX);	tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);	if (tp->retransmits > sysctl_tcp_retries1)		__sk_dst_reset(sk);out:;}static void tcp_write_timer(unsigned long data){	struct sock *sk = (struct sock*)data;	struct tcp_opt *tp = tcp_sk(sk);	int event;	bh_lock_sock(sk);	if (sock_owned_by_user(sk)) {		/* Try again later */		sk_reset_timer(sk, &tp->retransmit_timer, jiffies + (HZ / 20));		goto out_unlock;	}	if (sk->sk_state == TCP_CLOSE || !tp->pending)		goto out;	if (time_after(tp->timeout, jiffies)) {		sk_reset_timer(sk, &tp->retransmit_timer, tp->timeout);		goto out;	}	event = tp->pending;	tp->pending = 0;	switch (event) {	case TCP_TIME_RETRANS:		tcp_retransmit_timer(sk);		break;	case TCP_TIME_PROBE0:		tcp_probe_timer(sk);		break;	}	TCP_CHECK_TIMER(sk);out:	sk_stream_mem_reclaim(sk);out_unlock:	bh_unlock_sock(sk);	sock_put(sk);}/* *	Timer for listening sockets */static void tcp_synack_timer(struct sock *sk){	struct tcp_opt *tp = tcp_sk(sk);	struct tcp_listen_opt *lopt = tp->listen_opt;	int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;	int thresh = max_retries;	unsigned long now = jiffies;	struct open_request **reqp, *req;	int i, budget;	if (lopt == NULL || lopt->qlen == 0)		return;	/* Normally all the openreqs are young and become mature	 * (i.e. converted to established socket) for first timeout.	 * If synack was not acknowledged for 3 seconds, it means	 * one of the following things: synack was lost, ack was lost,	 * rtt is high or nobody planned to ack (i.e. synflood).	 * When server is a bit loaded, queue is populated with old	 * open requests, reducing effective size of queue.	 * When server is well loaded, queue size reduces to zero	 * after several minutes of work. It is not synflood,	 * it is normal operation. The solution is pruning	 * too old entries overriding normal timeout, when	 * situation becomes dangerous.	 *	 * Essentially, we reserve half of room for young	 * embrions; and abort old ones without pity, if old	 * ones are about to clog our table.	 */	if (lopt->qlen>>(lopt->max_qlen_log-1)) {		int young = (lopt->qlen_young<<1);		while (thresh > 2) {			if (lopt->qlen < young)				break;			thresh--;			young <<= 1;		}	}	if (tp->defer_accept)		max_retries = tp->defer_accept;	budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));	i = lopt->clock_hand;	do {		reqp=&lopt->syn_table[i];		while ((req = *reqp) != NULL) {			if (time_after_eq(now, req->expires)) {				if ((req->retrans < thresh ||				     (req->acked && req->retrans < max_retries))				    && !req->class->rtx_syn_ack(sk, req, NULL)) {					unsigned long timeo;					if (req->retrans++ == 0)						lopt->qlen_young--;					timeo = min((TCP_TIMEOUT_INIT << req->retrans),						    TCP_RTO_MAX);					req->expires = now + timeo;					reqp = &req->dl_next;					continue;				}				/* Drop this request */				write_lock(&tp->syn_wait_lock);				*reqp = req->dl_next;				write_unlock(&tp->syn_wait_lock);				lopt->qlen--;				if (req->retrans == 0)					lopt->qlen_young--;				tcp_openreq_free(req);				continue;			}			reqp = &req->dl_next;		}		i = (i+1)&(TCP_SYNQ_HSIZE-1);	} while (--budget > 0);	lopt->clock_hand = i;	if (lopt->qlen)		tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);}void tcp_delete_keepalive_timer (struct sock *sk){	sk_stop_timer(sk, &sk->sk_timer);}void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len){	sk_reset_timer(sk, &sk->sk_timer, jiffies + len);}void tcp_set_keepalive(struct sock *sk, int val){	if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))		return;	if (val && !sock_flag(sk, SOCK_KEEPOPEN))		tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));	else if (!val)		tcp_delete_keepalive_timer(sk);}static void tcp_keepalive_timer (unsigned long data){	struct sock *sk = (struct sock *) data;	struct tcp_opt *tp = tcp_sk(sk);	__u32 elapsed;	/* Only process if socket is not in use. */	bh_lock_sock(sk);	if (sock_owned_by_user(sk)) {		/* Try again later. */ 		tcp_reset_keepalive_timer (sk, HZ/20);		goto out;	}	if (sk->sk_state == TCP_LISTEN) {		tcp_synack_timer(sk);		goto out;	}	if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {		if (tp->linger2 >= 0) {			int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;			if (tmo > 0) {				tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);				goto out;			}		}		tcp_send_active_reset(sk, GFP_ATOMIC);		goto death;	}	if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)		goto out;	elapsed = keepalive_time_when(tp);	/* It is alive without keepalive 8) */	if (tcp_get_pcount(&tp->packets_out) || sk->sk_send_head)		goto resched;	elapsed = tcp_time_stamp - tp->rcv_tstamp;	if (elapsed >= keepalive_time_when(tp)) {		if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||		     (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {			tcp_send_active_reset(sk, GFP_ATOMIC);			tcp_write_err(sk);			goto out;		}		if (tcp_write_wakeup(sk) <= 0) {			tp->probes_out++;			elapsed = keepalive_intvl_when(tp);		} else {			/* If keepalive was lost due to local congestion,			 * try harder.			 */			elapsed = TCP_RESOURCE_PROBE_INTERVAL;		}	} else {		/* It is tp->rcv_tstamp + keepalive_time_when(tp) */		elapsed = keepalive_time_when(tp) - elapsed;	}	TCP_CHECK_TIMER(sk);	sk_stream_mem_reclaim(sk);resched:	tcp_reset_keepalive_timer (sk, elapsed);	goto out;death:		tcp_done(sk);out:	bh_unlock_sock(sk);	sock_put(sk);}EXPORT_SYMBOL(tcp_clear_xmit_timers);EXPORT_SYMBOL(tcp_delete_keepalive_timer);EXPORT_SYMBOL(tcp_init_xmit_timers);EXPORT_SYMBOL(tcp_reset_keepalive_timer);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -