Subject: Problems with tcp over slip
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: None <Mark_Weaver@brown.edu>
List: current-users
Date: 05/02/1994 09:12:21
Recently, I've been having various slip lockups and crashes while
telnetted between Solaris 2.3 and NetBSD-current.  When telnetting out
from NetBSD, the telnet sessions would often hang, with netstat
showing 20-30 packets sitting in the send queue.  When telnetting in,
often all the telnet sessions would hang at once, and no new telnet or
rlogin connections would be accepted, although the machine would
respond to finger requests and pings.  Also, my machine would crash
about twice a day, and the tcp routines would usually be found in the
trace.

Just for the hell of it, I tried undoing all of the tcp changes in the
last month.  The result was a vastly more stable kernel, which hasn't
crashed once since (up 3 days so far).  I haven't had a single telnet
session hang since either.

Here are the changes I made to my 940428 kernel.  I haven't looked
into the correct fix yet, and probably won't bother since mycroft is
familiar with the code and I'm not.

	Mark
--------------------------------------------------------------------
Email: Mark_Weaver@brown.edu           | Brown University
PGP Key: finger mhw@cs.brown.edu       | Dept of Computer Science


diff -u  src/sys/netinet/tcp_input.c.mhw1 src/sys/netinet/tcp_input.c
--- src/sys/netinet/tcp_input.c.mhw1	Wed Apr 27 06:20:00 1994
+++ src/sys/netinet/tcp_input.c	Thu Apr 28 22:10:10 1994
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	from: @(#)tcp_input.c	7.25 (Berkeley) 6/30/90
- *	$Id: tcp_input.c,v 1.8 1994/04/25 19:16:53 mycroft Exp $
+ *	$Id: tcp_input.c,v 1.6 1994/01/08 23:26:40 mycroft Exp $
  */
 
 #include <sys/param.h>
@@ -81,10 +81,7 @@
 	if ((ti)->ti_seq == (tp)->rcv_nxt && \
 	    (tp)->seg_next == (struct tcpiphdr *)(tp) && \
 	    (tp)->t_state == TCPS_ESTABLISHED) { \
-		if ((ti)->ti_flags & TH_PUSH) \
-			tp->t_flags |= TF_ACKNOW; \
-		else \
-			tp->t_flags |= TF_DELACK; \
+		tp->t_flags |= TF_DELACK; \
 		(tp)->rcv_nxt += (ti)->ti_len; \
 		flags = (ti)->ti_flags & TH_FIN; \
 		tcpstat.tcps_rcvpack++;\
@@ -447,10 +444,7 @@
 			m->m_len -= sizeof(struct tcpiphdr);
 			sbappend(&so->so_rcv, m);
 			sorwakeup(so);
-			if (ti->ti_flags & TH_PUSH)
-				tp->t_flags |= TF_ACKNOW;
-			else
-				tp->t_flags |= TF_DELACK;
+			tp->t_flags |= TF_DELACK;
 			return;
 		}
 	}
@@ -633,19 +627,35 @@
 		}
 		if (todrop > ti->ti_len ||
 		    todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {
+			tcpstat.tcps_rcvduppack++;
+			tcpstat.tcps_rcvdupbyte += ti->ti_len;
 			/*
-			 * Any valid FIN must be to the left of the
-			 * window.  At this point, FIN must be a
-			 * duplicate or out-of-sequence, so drop it.
-			 */
-			tiflags &= ~TH_FIN;
-			/*
-			 * Send ACK to resynchronize, and drop any data,
+			 * If segment is just one to the left of the window,
+			 * check two special cases:
+			 * 1. Don't toss RST in response to 4.2-style keepalive.
+			 * 2. If the only thing to drop is a FIN, we can drop
+			 *    it, but check the ACK or we will get into FIN
+			 *    wars if our FINs crossed (both CLOSING).
+			 * In either case, send ACK to resynchronize,
 			 * but keep on processing for RST or ACK.
 			 */
-			tp->t_flags |= TF_ACKNOW;
-			tcpstat.tcps_rcvdupbyte += todrop = ti->ti_len;
-			tcpstat.tcps_rcvduppack++;
+			if ((tiflags & TH_FIN && todrop == ti->ti_len + 1)
+#ifdef TCP_COMPAT_42
+			  || (tiflags & TH_RST && ti->ti_seq == tp->rcv_nxt - 1)
+#endif
+			   ) {
+				todrop = ti->ti_len;
+				tiflags &= ~TH_FIN;
+				tp->t_flags |= TF_ACKNOW;
+			} else {
+				/*
+				 * Handle the case when a bound socket connects
+				 * to itself. Allow packets with a SYN and
+				 * an ACK to continue with the processing.
+				 */
+				if (todrop != 0 || (tiflags & TH_ACK) == 0)
+					goto dropafterack;
+			}
 		} else {
 			tcpstat.tcps_rcvpartduppack++;
 			tcpstat.tcps_rcvpartdupbyte += todrop;
diff -u  src/sys/netinet/tcp_output.c.mhw1 src/sys/netinet/tcp_output.c
--- src/sys/netinet/tcp_output.c.mhw1	Wed Apr 13 06:29:19 1994
+++ src/sys/netinet/tcp_output.c	Thu Apr 28 22:10:17 1994
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	from: @(#)tcp_output.c	7.22 (Berkeley) 8/31/90
- *	$Id: tcp_output.c,v 1.8 1994/04/12 18:09:47 mycroft Exp $
+ *	$Id: tcp_output.c,v 1.7 1994/01/10 20:14:30 mycroft Exp $
  */
 
 #include <sys/param.h>
@@ -344,10 +344,7 @@
 	if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
 	    tp->snd_nxt == tp->snd_max)
 		tp->snd_nxt--;
-	if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
-		ti->ti_seq = htonl(tp->snd_nxt);
-	else
-		ti->ti_seq = htonl(tp->snd_max);
+	ti->ti_seq = htonl(tp->snd_nxt);
 	ti->ti_ack = htonl(tp->rcv_nxt);
 	if (optlen) {
 		bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen);

------------------------------------------------------------------------------