patch-2.1.90 linux/net/ipv4/tcp_timer.c

Next file: linux/net/ipv4/timer.c
Previous file: linux/net/ipv4/tcp_output.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.89/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.33 1997/12/13 21:53:01 kuznet Exp $
+ * Version:	$Id: tcp_timer.c,v 1.39 1998/03/13 08:02:17 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -31,6 +31,7 @@
 static void tcp_sltimer_handler(unsigned long);
 static void tcp_syn_recv_timer(unsigned long);
 static void tcp_keepalive(unsigned long data);
+static void tcp_bucketgc(unsigned long);
 
 struct timer_list	tcp_slow_timer = {
 	NULL, NULL,
@@ -41,7 +42,8 @@
 
 struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
 	{ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK	*/
-	{ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive}   /* KEEPALIVE	*/
+	{ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive},  /* KEEPALIVE	*/
+	{ATOMIC_INIT(0), TCP_BUCKETGC_PERIOD, 0, tcp_bucketgc}     /* BUCKETGC	*/
 };
 
 const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
@@ -87,20 +89,24 @@
 		 * The delayed ack timer can be set if we are changing the
 		 * retransmit timer when removing acked frames.
 		 */
-		del_timer(&tp->probe_timer);
-		del_timer(&tp->retransmit_timer);
+		if(tp->probe_timer.prev)
+			del_timer(&tp->probe_timer);
+		if(tp->retransmit_timer.prev)
+			del_timer(&tp->retransmit_timer);
 		tp->retransmit_timer.expires=jiffies+when;
 		add_timer(&tp->retransmit_timer);
 		break;
 
 	case TIME_DACK:
-		del_timer(&tp->delack_timer);
+		if(tp->delack_timer.prev)
+			del_timer(&tp->delack_timer);
 		tp->delack_timer.expires=jiffies+when;
 		add_timer(&tp->delack_timer);
 		break;
 
 	case TIME_PROBE0:
-		del_timer(&tp->probe_timer);
+		if(tp->probe_timer.prev)
+			del_timer(&tp->probe_timer);
 		tp->probe_timer.expires=jiffies+when;
 		add_timer(&tp->probe_timer);
 		break;	
@@ -118,9 +124,12 @@
 {	
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 
-	del_timer(&tp->retransmit_timer);
-	del_timer(&tp->delack_timer);
-	del_timer(&tp->probe_timer);
+	if(tp->retransmit_timer.prev)
+		del_timer(&tp->retransmit_timer);
+	if(tp->delack_timer.prev)
+		del_timer(&tp->delack_timer);
+	if(tp->probe_timer.prev)
+		del_timer(&tp->probe_timer);
 }
 
 static int tcp_write_err(struct sock *sk, int force)
@@ -131,9 +140,8 @@
 	tcp_clear_xmit_timers(sk);
 	
 	/* Time wait the socket. */
-	if (!force && (1<<sk->state) & (TCPF_FIN_WAIT1|TCPF_FIN_WAIT2|TCPF_CLOSING)) {
-		tcp_set_state(sk,TCP_TIME_WAIT);
-		tcp_reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+	if (!force && ((1<<sk->state) & (TCPF_FIN_WAIT1|TCPF_FIN_WAIT2|TCPF_CLOSING))) {
+		tcp_time_wait(sk);
 	} else {
 		/* Clean up time. */
 		tcp_set_state(sk, TCP_CLOSE);
@@ -173,9 +181,8 @@
 	return 1;
 }
 
-
-void tcp_delack_timer(unsigned long data) {
-
+void tcp_delack_timer(unsigned long data)
+{
 	struct sock *sk = (struct sock*)data;
 
 	if(sk->zapped)
@@ -185,8 +192,8 @@
 		tcp_read_wakeup(sk); 		
 }
 
-void tcp_probe_timer(unsigned long data) {
-
+void tcp_probe_timer(unsigned long data)
+{
 	struct sock *sk = (struct sock*)data;
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 
@@ -212,10 +219,9 @@
 			sk->err = ETIMEDOUT;
 		sk->error_report(sk);
 
-		/* Time wait the socket. */
 		if ((1<<sk->state) & (TCPF_FIN_WAIT1|TCPF_FIN_WAIT2|TCPF_CLOSING)) {
-			tcp_set_state(sk, TCP_TIME_WAIT);
-			tcp_reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
+			/* Time wait the socket. */
+			tcp_time_wait(sk);
 		} else {
 			/* Clean up time. */
 			tcp_set_state(sk, TCP_CLOSE);
@@ -250,6 +256,35 @@
 		}
 	}
 	return res;
+}
+
+/* Garbage collect TCP bind buckets. */
+static void tcp_bucketgc(unsigned long __unused)
+{
+	int i;
+
+	for(i = 0; i < TCP_BHTABLE_SIZE; i++) {
+		struct tcp_bind_bucket *tb = tcp_bound_hash[i];
+
+		while(tb) {
+			struct tcp_bind_bucket *next = tb->next;
+
+			if((tb->owners == NULL) &&
+			   !(tb->flags & TCPB_FLAG_LOCKED)) {
+				/* Eat timer reference. */
+				tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
+
+				/* Unlink bucket. */
+				if(tb->next)
+					tb->next->pprev = tb->pprev;
+				*tb->pprev = tb->next;
+
+				/* Finally, free it up. */
+				kmem_cache_free(tcp_bucket_cachep, tb);
+			}
+			tb = next;
+		}
+	}
 }
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov