Skip to content

Commit 9890092

Browse files
Florian Westphaldavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Glenn Judd <[email protected]> Acked-by: Stephen Hemminger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7354c8c commit 9890092

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

include/net/tcp.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,10 +763,17 @@ enum tcp_ca_event {
763763
CA_EVENT_CWND_RESTART, /* congestion window restart */
764764
CA_EVENT_COMPLETE_CWR, /* end of congestion recovery */
765765
CA_EVENT_LOSS, /* loss timeout */
766+
CA_EVENT_ECN_NO_CE, /* ECT set, but not CE marked */
767+
CA_EVENT_ECN_IS_CE, /* received CE marked IP packet */
768+
CA_EVENT_DELAYED_ACK, /* Delayed ack is sent */
769+
CA_EVENT_NON_DELAYED_ACK,
766770
};
767771

772+
/* Information about inbound ACK, passed to cong_ops->in_ack_event() */
768773
enum tcp_ca_ack_event_flags {
769-
CA_ACK_SLOWPATH = (1 << 0),
774+
CA_ACK_SLOWPATH = (1 << 0), /* In slow path processing */
775+
CA_ACK_WIN_UPDATE = (1 << 1), /* ACK updated window */
776+
CA_ACK_ECE = (1 << 2), /* ECE bit is set on ack */
770777
};
771778

772779
/*

net/ipv4/tcp_input.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,14 +233,21 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, const struct sk_buff *s
233233
tcp_enter_quickack_mode((struct sock *)tp);
234234
break;
235235
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+
236239
if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) {
237240
/* Better not delay acks, sender can have a very low cwnd */
238241
tcp_enter_quickack_mode((struct sock *)tp);
239242
tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
240243
}
241-
/* fallinto */
244+
tp->ecn_flags |= TCP_ECN_SEEN;
245+
break;
242246
default:
247+
if (tcp_ca_needs_ecn((struct sock *)tp))
248+
tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_NO_CE);
243249
tp->ecn_flags |= TCP_ECN_SEEN;
250+
break;
244251
}
245252
}
246253

@@ -3429,10 +3436,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
34293436
tp->snd_una = ack;
34303437
flag |= FLAG_WIN_UPDATE;
34313438

3432-
tcp_in_ack_event(sk, 0);
3439+
tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
34333440

34343441
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPACKS);
34353442
} else {
3443+
u32 ack_ev_flags = CA_ACK_SLOWPATH;
3444+
34363445
if (ack_seq != TCP_SKB_CB(skb)->end_seq)
34373446
flag |= FLAG_DATA;
34383447
else
@@ -3444,10 +3453,15 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
34443453
flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
34453454
&sack_rtt_us);
34463455

3447-
if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb)))
3456+
if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) {
34483457
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;
34493463

3450-
tcp_in_ack_event(sk, CA_ACK_SLOWPATH);
3464+
tcp_in_ack_event(sk, ack_ev_flags);
34513465
}
34523466

34533467
/* We passed data and got it acked, remove any soft error

net/ipv4/tcp_output.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,6 +3130,8 @@ void tcp_send_delayed_ack(struct sock *sk)
31303130
int ato = icsk->icsk_ack.ato;
31313131
unsigned long timeout;
31323132

3133+
tcp_ca_event(sk, CA_EVENT_DELAYED_ACK);
3134+
31333135
if (ato > TCP_DELACK_MIN) {
31343136
const struct tcp_sock *tp = tcp_sk(sk);
31353137
int max_ato = HZ / 2;
@@ -3186,6 +3188,8 @@ void tcp_send_ack(struct sock *sk)
31863188
if (sk->sk_state == TCP_CLOSE)
31873189
return;
31883190

3191+
tcp_ca_event(sk, CA_EVENT_NON_DELAYED_ACK);
3192+
31893193
/* We are not putting this on the write queue, so
31903194
* tcp_transmit_skb() will set the ownership to this
31913195
* sock.

0 commit comments

Comments
 (0)