patch-2.1.129 linux/net/ipv4/tcp_input.c
Next file: linux/net/ipv4/tcp_output.c
Previous file: linux/net/ipv4/tcp.c
Back to the patch index
Back to the overall index
- Lines: 238
- Date:
Wed Nov 18 09:06:05 1998
- Orig file:
v2.1.128/linux/net/ipv4/tcp_input.c
- Orig date:
Sun Nov 8 14:03:15 1998
diff -u --recursive --new-file v2.1.128/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.136 1998/11/07 14:36:18 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.141 1998/11/18 02:12:07 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -262,7 +262,7 @@
}
/* When we get a reset we do this. */
-static void tcp_reset(struct sock *sk, struct sk_buff *skb)
+static void tcp_reset(struct sock *sk)
{
sk->zapped = 1;
@@ -277,7 +277,7 @@
default:
sk->err = ECONNRESET;
};
- tcp_set_state(sk,TCP_CLOSE);
+ tcp_set_state(sk, TCP_CLOSE);
sk->shutdown = SHUTDOWN_MASK;
if (!sk->dead)
sk->state_change(sk);
@@ -483,33 +483,36 @@
if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
tp->dup_acks++;
if ((tp->fackets_out > 3) || (tp->dup_acks == 3)) {
- tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+ tp->snd_ssthresh =
+ max(min(tp->snd_wnd, tp->snd_cwnd) >> 1, 2);
tp->snd_cwnd = (tp->snd_ssthresh + 3);
tp->high_seq = tp->snd_nxt;
if(!tp->fackets_out)
- tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
else
tcp_fack_retransmit(sk);
tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
}
- }
-
- /* 2. Each time another duplicate ACK arrives, increment
- * cwnd by the segment size. [...] Transmit a packet...
- *
- * Packet transmission will be done on normal flow processing
- * since we're not in "retransmit mode". We do not use duplicate
- * ACKs to artificially inflate the congestion window when
- * doing FACK.
- */
- if (tp->dup_acks > 3) {
+ } else if (++tp->dup_acks > 3) {
+ /* 2. Each time another duplicate ACK arrives, increment
+ * cwnd by the segment size. [...] Transmit a packet...
+ *
+ * Packet transmission will be done on normal flow processing
+ * since we're not in "retransmit mode". We do not use
+ * duplicate ACKs to artificially inflate the congestion
+ * window when doing FACK.
+ */
if(!tp->fackets_out) {
tp->snd_cwnd++;
} else {
- /* Fill any further holes which may have appeared.
- * We may want to change this to run every further
- * multiple-of-3 dup ack increments, to be more robust
- * against out-of-order packet delivery. -DaveM
+ /* Fill any further holes which may have
+ * appeared.
+ *
+ * We may want to change this to run every
+ * further multiple-of-3 dup ack increments,
+ * to be more robust against out-of-order
+ * packet delivery. -DaveM
*/
tcp_fack_retransmit(sk);
}
@@ -552,7 +555,8 @@
* from snd_una is if this was a window update.
*/
if (ack != tp->snd_una && before(ack, tp->high_seq)) {
- tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
}
} else {
@@ -568,7 +572,7 @@
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
-static void tcp_cong_avoid(struct tcp_opt *tp)
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
{
if (tp->snd_cwnd <= tp->snd_ssthresh) {
/* In "safe" area, increase. */
@@ -656,6 +660,33 @@
}
}
+/* Should we open up the congestion window? */
+static __inline__ int should_advance_cwnd(struct tcp_opt *tp, int flag)
+{
+ /* Data must have been acked. */
+ if ((flag & FLAG_DATA_ACKED) == 0)
+ return 0;
+
+ /* Some of the data acked was retransmitted somehow? */
+ if ((flag & FLAG_RETRANS_DATA_ACKED) != 0) {
+ /* We advance in all cases except during
+ * non-FACK fast retransmit/recovery.
+ */
+ if (tp->fackets_out != 0 ||
+ tp->retransmits != 0)
+ return 1;
+
+ /* Non-FACK fast retransmit does it's own
+ * congestion window management, don't get
+ * in the way.
+ */
+ return 0;
+ }
+
+ /* New non-retransmitted data acked, always advance. */
+ return 1;
+}
+
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Superceeds RFC1323)
*/
@@ -691,8 +722,10 @@
}
} else {
tcp_set_rto(tp);
- tcp_cong_avoid(tp);
}
+ if (should_advance_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
+
/* NOTE: safe here so long as cong_ctl doesn't use rto */
tcp_bound_rto(tp);
}
@@ -810,9 +843,10 @@
tcp_set_rto(tp);
tcp_bound_rto(tp);
}
- tcp_cong_avoid(tp);
}
}
+ if (should_advance_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
}
if (tp->packets_out) {
@@ -1814,12 +1848,12 @@
if(th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
SOCK_DEBUG(sk, "syn in established state\n");
tcp_statistics.TcpInErrs++;
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
@@ -1944,8 +1978,27 @@
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
int queued = 0;
- /* state == CLOSED, hash lookup always fails, so no worries. -DaveM */
switch (sk->state) {
+ case TCP_CLOSE:
+ /* When state == CLOSED, hash lookup always fails.
+ *
+ * But, there is a back door, the backlog queue.
+ * If we have a sequence of packets in the backlog
+ * during __release_sock() which have a sequence such
+ * that:
+ * packet X causes entry to TCP_CLOSE state
+ * ...
+ * packet X + N has FIN bit set
+ *
+ * We report a (luckily) harmless error in this case.
+ * The issue is that backlog queue processing bypasses
+ * any hash lookups (we know which socket packets are for).
+ * The correct behavior here is what 2.0.x did, since
+ * a TCP_CLOSE socket does not exist. Drop the frame
+ * and send a RST back to the other end.
+ */
+ return 1;
+
case TCP_LISTEN:
/* These use the socket TOS..
* might want to be the received TOS
@@ -1998,7 +2051,7 @@
}
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
@@ -2127,7 +2180,7 @@
/* step 2: check RST bit */
if(th->rst) {
- tcp_reset(sk,skb);
+ tcp_reset(sk);
goto discard;
}
@@ -2150,7 +2203,7 @@
*/
if (th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
@@ -2230,7 +2283,7 @@
*/
if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead) {
if (after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
- tcp_reset(sk, skb);
+ tcp_reset(sk);
return 1;
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov