Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 265535
b: refs/heads/master
c: a262f0c
h: refs/heads/master
i:
  265533: b5e4192
  265531: 084b372
  265527: 108ca52
  265519: 063e11a
  265503: 98dc042
  265471: 771a277
v: v3
  • Loading branch information
Nandita Dukkipati authored and David S. Miller committed Aug 25, 2011
1 parent 2949314 commit 1c30f5b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f6fb8f100b807378fda19e83e5ac6828b638603a
refs/heads/master: a262f0cdf1f2916ea918dc329492abb5323d9a6c
4 changes: 4 additions & 0 deletions trunk/include/linux/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,10 @@ struct tcp_sock {
u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
u32 snd_cwnd_used;
u32 snd_cwnd_stamp;
u32 prior_cwnd; /* Congestion window at start of Recovery. */
u32 prr_delivered; /* Number of newly delivered packets to
* receiver in Recovery. */
u32 prr_out; /* Total number of pkts sent during Recovery. */

u32 rcv_wnd; /* Current receiver window */
u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
Expand Down
58 changes: 52 additions & 6 deletions trunk/net/ipv4/tcp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -2830,9 +2830,13 @@ static int tcp_try_undo_loss(struct sock *sk)
static inline void tcp_complete_cwr(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
/* Do not moderate cwnd if it's already undone in cwr or recovery */
if (tp->undo_marker && tp->snd_cwnd > tp->snd_ssthresh) {
tp->snd_cwnd = tp->snd_ssthresh;

/* Do not moderate cwnd if it's already undone in cwr or recovery. */
if (tp->undo_marker) {
if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR)
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
else /* PRR */
tp->snd_cwnd = tp->snd_ssthresh;
tp->snd_cwnd_stamp = tcp_time_stamp;
}
tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
Expand Down Expand Up @@ -2950,6 +2954,38 @@ void tcp_simple_retransmit(struct sock *sk)
}
EXPORT_SYMBOL(tcp_simple_retransmit);

/* This function implements the PRR algorithm, specifcally the PRR-SSRB
* (proportional rate reduction with slow start reduction bound) as described in
* http://www.ietf.org/id/draft-mathis-tcpm-proportional-rate-reduction-01.txt.
* It computes the number of packets to send (sndcnt) based on packets newly
* delivered:
* 1) If the packets in flight is larger than ssthresh, PRR spreads the
* cwnd reductions across a full RTT.
* 2) If packets in flight is lower than ssthresh (such as due to excess
* losses and/or application stalls), do not perform any further cwnd
* reductions, but instead slow start up to ssthresh.
*/
static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked,
int fast_rexmit, int flag)
{
struct tcp_sock *tp = tcp_sk(sk);
int sndcnt = 0;
int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp);

if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) {
u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
tp->prior_cwnd - 1;
sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
} else {
sndcnt = min_t(int, delta,
max_t(int, tp->prr_delivered - tp->prr_out,
newly_acked_sacked) + 1);
}

sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0));
tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt;
}

/* Process an event, which can update packets-in-flight not trivially.
* Main goal of this function is to calculate new estimate for left_out,
* taking into account both packets sitting in receiver's buffer and
Expand All @@ -2961,7 +2997,8 @@ EXPORT_SYMBOL(tcp_simple_retransmit);
* It does _not_ decide what to send, it is made in function
* tcp_xmit_retransmit_queue().
*/
static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
int newly_acked_sacked, int flag)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
Expand Down Expand Up @@ -3111,13 +3148,17 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)

tp->bytes_acked = 0;
tp->snd_cwnd_cnt = 0;
tp->prior_cwnd = tp->snd_cwnd;
tp->prr_delivered = 0;
tp->prr_out = 0;
tcp_set_ca_state(sk, TCP_CA_Recovery);
fast_rexmit = 1;
}

if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk)))
tcp_update_scoreboard(sk, fast_rexmit);
tcp_cwnd_down(sk, flag);
tp->prr_delivered += newly_acked_sacked;
tcp_update_cwnd_in_recovery(sk, newly_acked_sacked, fast_rexmit, flag);
tcp_xmit_retransmit_queue(sk);
}

Expand Down Expand Up @@ -3632,6 +3673,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 prior_in_flight;
u32 prior_fackets;
int prior_packets;
int prior_sacked = tp->sacked_out;
int newly_acked_sacked = 0;
int frto_cwnd = 0;

/* If the ack is older than previous acks
Expand Down Expand Up @@ -3703,6 +3746,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
/* See if we can take anything off of the retransmit queue. */
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);

newly_acked_sacked = (prior_packets - prior_sacked) -
(tp->packets_out - tp->sacked_out);

if (tp->frto_counter)
frto_cwnd = tcp_process_frto(sk, flag);
/* Guarantee sacktag reordering detection against wrap-arounds */
Expand All @@ -3715,7 +3761,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
tcp_may_raise_cwnd(sk, flag))
tcp_cong_avoid(sk, ack, prior_in_flight);
tcp_fastretrans_alert(sk, prior_packets - tp->packets_out,
flag);
newly_acked_sacked, flag);
} else {
if ((flag & FLAG_DATA_ACKED) && !frto_cwnd)
tcp_cong_avoid(sk, ack, prior_in_flight);
Expand Down
7 changes: 6 additions & 1 deletion trunk/net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -1796,11 +1796,13 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
tcp_event_new_data_sent(sk, skb);

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

if (push_one)
break;
}
if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery)
tp->prr_out += sent_pkts;

if (likely(sent_pkts)) {
tcp_cwnd_validate(sk);
Expand Down Expand Up @@ -2294,6 +2296,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
return;
NET_INC_STATS_BH(sock_net(sk), mib_idx);

if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery)
tp->prr_out += tcp_skb_pcount(skb);

if (skb == tcp_write_queue_head(sk))
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
inet_csk(sk)->icsk_rto,
Expand Down

0 comments on commit 1c30f5b

Please sign in to comment.