patch-1.3.87 linux/net/ipv4/tcp_output.c
Next file: linux/net/ipv4/tcp_timer.c
Previous file: linux/net/ipv4/tcp_input.c
Back to the patch index
Back to the overall index
- Lines: 172
- Date:
Fri Apr 12 14:42:28 1996
- Orig file:
v1.3.86/linux/net/ipv4/tcp_output.c
- Orig date:
Wed Apr 10 17:02:28 1996
diff -u --recursive --new-file v1.3.86/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
@@ -23,6 +23,19 @@
#include <linux/config.h>
#include <net/tcp.h>
+#include <linux/interrupt.h>
+
+/*
+ * Get rid of any delayed acks, we sent one already..
+ */
+static __inline__ void clear_delayed_acks(struct sock * sk)
+{
+ sk->ack_timed = 0;
+ sk->ack_backlog = 0;
+ sk->bytes_rcv = 0;
+ del_timer(&sk->delack_timer);
+}
+
/*
* This is the main buffer sending routine. We queue the buffer
* having checked it is sane seeming.
@@ -106,7 +119,7 @@
/*
* This is going straight out
*/
-
+ clear_delayed_acks(sk);
th->ack_seq = htonl(sk->acked_seq);
th->window = htons(tcp_select_window(sk));
@@ -122,10 +135,6 @@
sk->prot->queue_xmit(sk, skb->dev, skb, 0);
-
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
-
/*
* Set for next retransmit based on expected ACK time.
* FIXME: We set this every time which means our
@@ -290,10 +299,8 @@
*/
sk->prot->queue_xmit(sk, skb->dev, skb, skb->free);
-
-
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
+
+ clear_delayed_acks(sk);
/*
* Again we slide the timer wrongly
@@ -339,7 +346,7 @@
/* (the skb_pull() changes skb->data while we may */
/* actually try to send the data. Ouch. A side */
/* effect is that we'll send some unnecessary data, */
- /* but the alternative is disasterous... */
+ /* but the alternative is disastrous... */
if (skb_device_locked(skb))
break;
@@ -429,8 +436,7 @@
*/
th->ack_seq = htonl(sk->acked_seq);
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
+ clear_delayed_acks(sk);
th->window = ntohs(tcp_select_window(sk));
tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
@@ -631,7 +637,7 @@
buff->end_seq = sk->write_seq;
t1->seq = htonl(buff->seq);
t1->ack_seq = htonl(sk->acked_seq);
- t1->window = htons(sk->window=tcp_select_window(sk));
+ t1->window = htons(tcp_select_window(sk));
t1->fin = 1;
tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff);
@@ -747,6 +753,39 @@
}
/*
+ * Set up the timers for sending a delayed ack..
+ *
+ * rules for delaying an ack:
+ * - delay time <= 0.5 HZ
+ * - must send at least every 2 full sized packets
+ * - we don't have a window update to send
+ */
+void tcp_send_delayed_ack(struct sock * sk, int max_timeout)
+{
+ unsigned long timeout, now;
+
+ /* Calculate new timeout */
+ now = jiffies;
+ timeout = sk->ato;
+ if (timeout > max_timeout)
+ timeout = max_timeout;
+ timeout += now;
+ if (sk->bytes_rcv > sk->max_unacked) {
+ timeout = now;
+ mark_bh(TIMER_BH);
+ }
+
+ /* Use new timeout only if there wasn't a older one earlier */
+ if (!del_timer(&sk->delack_timer) || timeout < sk->delack_timer.expires)
+ sk->delack_timer.expires = timeout;
+
+ sk->ack_backlog++;
+ add_timer(&sk->delack_timer);
+}
+
+
+
+/*
* This routine sends an ack and also updates the window.
*/
@@ -765,10 +804,8 @@
* is on we are just doing an ACK timeout and need to switch
* to a keepalive.
*/
-
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
- sk->ack_timed = 0;
+
+ clear_delayed_acks(sk);
if (sk->send_head == NULL
&& skb_queue_empty(&sk->write_queue)
@@ -794,12 +831,8 @@
* bandwidth on slow links to send a spare ack than
* resend packets.
*/
-
- sk->ack_backlog++;
- if (sk->ip_xmit_timeout != TIME_WRITE && tcp_connected(sk->state))
- {
- tcp_reset_xmit_timer(sk, TIME_WRITE, HZ);
- }
+
+ tcp_send_delayed_ack(sk, HZ/2);
return;
}
@@ -829,12 +862,10 @@
* Fill in the packet and send it
*/
- sk->window = tcp_select_window(sk);
-
memcpy(t1, &sk->dummy_th, sizeof(*t1));
t1->seq = htonl(sk->sent_seq);
t1->ack_seq = htonl(sk->acked_seq);
- t1->window = htons(sk->window);
+ t1->window = htons(tcp_select_window(sk));
tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), buff);
if (sk->debug)
@@ -879,7 +910,7 @@
/*
* We are probing the opening of a window
* but the window size is != 0
- * must have been a result SWS advoidance ( sender )
+ * must have been a result SWS avoidance ( sender )
*/
struct iphdr *iph;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this