patch-2.2.17 linux/net/ipv4/tcp_input.c

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

diff -u --recursive --new-file v2.2.16/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
@@ -448,9 +448,6 @@
  */
 static __inline__ int tcp_fast_parse_options(struct sock *sk, struct tcphdr *th, struct tcp_opt *tp)
 {
-	/* If we didn't send out any options ignore them all. */
-	if (tp->tcp_header_len == sizeof(struct tcphdr))
-		return 0;
 	if (th->doff == sizeof(struct tcphdr)>>2) {
 		tp->saw_tstamp = 0;
 		return 0;
@@ -780,6 +777,7 @@
 		   u32 ack_seq, u32 ack, int len)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	u32 nwin = ntohs(th->window) << tp->snd_wscale;
 	int flag = 0;
 	u32 seq = 0;
 	u32 seq_rtt = 0;
@@ -810,20 +808,21 @@
 	 * snd_wl{1,2} are used to prevent unordered
 	 * segments from shrinking the window 
 	 */
-	if (before(tp->snd_wl1, ack_seq) ||
-	    (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack))) {
-		u32 nwin = ntohs(th->window) << tp->snd_wscale;
-
-		if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd)) {
-			flag |= FLAG_WIN_UPDATE;
-			tp->snd_wnd = nwin;
-
-			tp->snd_wl1 = ack_seq;
-			tp->snd_wl2 = ack;
-
-			if (nwin > tp->max_window)
-				tp->max_window = nwin;
-		}
+	if (after(ack_seq, tp->snd_wl1) ||
+	    (tp->snd_wl1 == ack_seq &&
+	     (after(ack, tp->snd_wl2) ||
+	      (tp->snd_wl2 == ack && nwin > tp->snd_wnd)))) {
+		flag |= FLAG_WIN_UPDATE;
+		tp->snd_wl1 = ack_seq;
+		tp->snd_wl2 = ack;
+		tp->snd_wnd = nwin;
+
+		if (nwin > tp->max_window)
+			tp->max_window = nwin;
+	} else if (after(ack, tp->snd_una)) {
+		/* Bad case. Window update is not accepted.
+		 * We will lockup. Break RFC to survive. */
+		tp->snd_wnd -= min(ack-tp->snd_una, tp->snd_wnd);
 	}
 
 	/* We passed data and got it acked, remove any soft error

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)