Skip to content

Commit

Permalink
[TCP]: Eliminate redundant computations in tcp_write_xmit().
Browse files Browse the repository at this point in the history
tcp_snd_test() is run for every packet output by a single
call to tcp_write_xmit(), but this is not necessary.

For one, the congestion window space needs to only be
calculated one time, then used throughout the duration
of the loop.

This cleanup also makes experimenting with different TSO
packetization schemes much easier.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 5, 2005
1 parent 7f4dd0a commit aa93466
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
unsigned int tso_segs, cwnd_quota;
int sent_pkts;

/* If we are closed, the bytes will have to remain here.
Expand All @@ -896,19 +897,31 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
if (unlikely(sk->sk_state == TCP_CLOSE))
return 0;

skb = sk->sk_send_head;
if (unlikely(!skb))
return 0;

tso_segs = tcp_init_tso_segs(sk, skb);
cwnd_quota = tcp_cwnd_test(tp, skb);
sent_pkts = 0;
while ((skb = sk->sk_send_head) &&
tcp_snd_test(sk, skb, mss_now,
tcp_skb_is_last(sk, skb) ? nonagle :
TCP_NAGLE_PUSH)) {
if (skb->len > mss_now) {
if (tcp_fragment(sk, skb, mss_now))

while (cwnd_quota >= tso_segs) {
if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
(tcp_skb_is_last(sk, skb) ?
nonagle : TCP_NAGLE_PUSH))))
break;

if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
break;

if (unlikely(skb->len > mss_now)) {
if (unlikely(tcp_fragment(sk, skb, mss_now)))
break;
}

TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_tso_set_push(skb);
if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC))))
break;

/* Advance the send_head. This one is sent out.
Expand All @@ -917,10 +930,19 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
update_send_head(sk, tp, skb);

tcp_minshall_update(tp, mss_now, skb);
sent_pkts = 1;
sent_pkts++;

/* Do not optimize this to use tso_segs. If we chopped up
* the packet above, tso_segs will no longer be valid.
*/
cwnd_quota -= tcp_skb_pcount(skb);
skb = sk->sk_send_head;
if (!skb)
break;
tso_segs = tcp_init_tso_segs(sk, skb);
}

if (sent_pkts) {
if (likely(sent_pkts)) {
tcp_cwnd_validate(sk, tp);
return 0;
}
Expand Down

0 comments on commit aa93466

Please sign in to comment.