patch-2.2.17 linux/net/ipv4/tcp_output.c
Next file: linux/net/irda/af_irda.c
Previous file: linux/net/ipv4/tcp_ipv4.c
Back to the patch index
Back to the overall index
- Lines: 78
- Date:
Mon Sep 4 18:39:29 2000
- Orig file:
v2.2.16/net/ipv4/tcp_output.c
- Orig date:
Mon Sep 4 18:37:24 2000
diff -u --recursive --new-file v2.2.16/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
@@ -63,6 +63,31 @@
tp->send_head = NULL;
}
+static __inline__ u32 tcp_acceptable_seq(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct sk_buff *skb;
+ u32 snd_nxt;
+
+ if (!before(tp->snd_una+tp->snd_wnd, tp->snd_nxt))
+ return tp->snd_nxt;
+
+ /* Umm... No better choice. The case is marginal, no hurry. */
+ skb = skb_peek(&sk->write_queue);
+
+ snd_nxt = tp->snd_una;
+ while((skb != NULL) &&
+ (skb != tp->send_head) &&
+ (skb != (struct sk_buff *)&sk->write_queue)) {
+ if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una+tp->snd_wnd))
+ break;
+ snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ skb = skb->next;
+ }
+
+ return snd_nxt;
+}
+
/* This routine actually transmits TCP packets queued in by
* tcp_do_sendmsg(). This is used by both the initial
* transmission and possible later retransmissions.
@@ -802,7 +827,7 @@
TCP_SKB_CB(skb)->urg_ptr = 0;
/* Send it off. */
- TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk);
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_transmit_skb(sk, skb);
@@ -1066,7 +1091,7 @@
TCP_SKB_CB(buff)->urg_ptr = 0;
/* Send it off, this clears delayed acks for us. */
- TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tp->snd_nxt;
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk);
TCP_SKB_CB(buff)->when = tcp_time_stamp;
tcp_transmit_skb(sk, buff);
}
@@ -1091,15 +1116,15 @@
TCPF_LAST_ACK|TCPF_CLOSING))
return;
- if (before(tp->snd_nxt, tp->snd_una + tp->snd_wnd) &&
- ((skb = tp->send_head) != NULL)) {
+ if ((skb = tp->send_head) != NULL &&
+ before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
unsigned long win_size;
/* We are probing the opening of a window
* but the window size is != 0
* must have been a result SWS avoidance ( sender )
*/
- win_size = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
+ win_size = tp->snd_una+tp->snd_wnd - TCP_SKB_CB(skb)->seq;
if (win_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq) {
if (tcp_fragment(sk, skb, win_size))
return; /* Let a retransmit get it. */
@@ -1129,7 +1154,7 @@
* end to send an ack. Don't queue or clone SKB, just
* send it.
*/
- TCP_SKB_CB(skb)->seq = tp->snd_nxt - 1;
+ TCP_SKB_CB(skb)->seq = tp->snd_una - 1;
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_transmit_skb(sk, skb);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)