aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2014-09-26 16:37:35 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-29 00:13:10 -0400
commit9890092e46b2996bb85f7f973e69424cb5c07bc0 (patch)
tree4cc1000c27918b9fcf63806bb5ae02cee36feeda /net/ipv4/tcp_input.c
parent7354c8c389d18719dd71cc810da70b0921d66694 (diff)
net: tcp: more detailed ACK events and events for CE marked packets
DataCenter TCP (DCTCP) determines cwnd growth based on ECN information and ACK properties, e.g. ACK that updates window is treated differently than DUPACK. Also DCTCP needs information whether ACK was delayed ACK. Furthermore, DCTCP also implements a CE state machine that keeps track of CE markings of incoming packets. Therefore, extend the congestion control framework to provide these event types, so that DCTCP can be properly implemented as a normal congestion algorithm module outside of the core stack. Joint work with Daniel Borkmann and Glenn Judd. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Glenn Judd <glenn.judd@morganstanley.com> Acked-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 8a38774cc66e..fc133178c787 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -233,14 +233,21 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, const struct sk_buff *s
233 tcp_enter_quickack_mode((struct sock *)tp); 233 tcp_enter_quickack_mode((struct sock *)tp);
234 break; 234 break;
235 case INET_ECN_CE: 235 case INET_ECN_CE:
236 if (tcp_ca_needs_ecn((struct sock *)tp))
237 tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_IS_CE);
238
236 if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { 239 if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) {
237 /* Better not delay acks, sender can have a very low cwnd */ 240 /* Better not delay acks, sender can have a very low cwnd */
238 tcp_enter_quickack_mode((struct sock *)tp); 241 tcp_enter_quickack_mode((struct sock *)tp);
239 tp->ecn_flags |= TCP_ECN_DEMAND_CWR; 242 tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
240 } 243 }
241 /* fallinto */ 244 tp->ecn_flags |= TCP_ECN_SEEN;
245 break;
242 default: 246 default:
247 if (tcp_ca_needs_ecn((struct sock *)tp))
248 tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_NO_CE);
243 tp->ecn_flags |= TCP_ECN_SEEN; 249 tp->ecn_flags |= TCP_ECN_SEEN;
250 break;
244 } 251 }
245} 252}
246 253
@@ -3429,10 +3436,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3429 tp->snd_una = ack; 3436 tp->snd_una = ack;
3430 flag |= FLAG_WIN_UPDATE; 3437 flag |= FLAG_WIN_UPDATE;
3431 3438
3432 tcp_in_ack_event(sk, 0); 3439 tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
3433 3440
3434 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPACKS); 3441 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPACKS);
3435 } else { 3442 } else {
3443 u32 ack_ev_flags = CA_ACK_SLOWPATH;
3444
3436 if (ack_seq != TCP_SKB_CB(skb)->end_seq) 3445 if (ack_seq != TCP_SKB_CB(skb)->end_seq)
3437 flag |= FLAG_DATA; 3446 flag |= FLAG_DATA;
3438 else 3447 else
@@ -3444,10 +3453,15 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3444 flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, 3453 flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
3445 &sack_rtt_us); 3454 &sack_rtt_us);
3446 3455
3447 if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) 3456 if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) {
3448 flag |= FLAG_ECE; 3457 flag |= FLAG_ECE;
3458 ack_ev_flags |= CA_ACK_ECE;
3459 }
3460
3461 if (flag & FLAG_WIN_UPDATE)
3462 ack_ev_flags |= CA_ACK_WIN_UPDATE;
3449 3463
3450 tcp_in_ack_event(sk, CA_ACK_SLOWPATH); 3464 tcp_in_ack_event(sk, ack_ev_flags);
3451 } 3465 }
3452 3466
3453 /* We passed data and got it acked, remove any soft error 3467 /* We passed data and got it acked, remove any soft error