diff --git a/include/net/tcp.h b/include/net/tcp.h index 3b91bbdf3f313..daa878118bd33 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -371,6 +371,7 @@ static inline void tcp_dec_quickack_mode(struct sock *sk, #define TCP_ECN_QUEUE_CWR 2 #define TCP_ECN_DEMAND_CWR 4 #define TCP_ECN_SEEN 8 +#define TCP_ECN_ECT_PERMANENT 16 enum tcp_tw_status { TCP_TW_SUCCESS = 0, diff --git a/net/ipv4/tcp_bbr2.c b/net/ipv4/tcp_bbr2.c index 5510adc92bbb4..fa49e17c47ca9 100644 --- a/net/ipv4/tcp_bbr2.c +++ b/net/ipv4/tcp_bbr2.c @@ -2471,6 +2471,9 @@ static void bbr2_init(struct sock *sk) bbr->alpha_last_delivered_ce = 0; tp->fast_ack_mode = min_t(u32, 0x2U, bbr_fast_ack_mode); + + if ((tp->ecn_flags & TCP_ECN_OK) && bbr_ecn_enable) + tp->ecn_flags |= TCP_ECN_ECT_PERMANENT; } /* Core TCP stack informs us that the given skb was just marked lost. */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9d87dc854c850..0eb462008718f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -377,7 +377,8 @@ static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb, th->cwr = 1; skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; } - } else if (!tcp_ca_needs_ecn(sk)) { + } else if (!(tp->ecn_flags & TCP_ECN_ECT_PERMANENT) && + !tcp_ca_needs_ecn(sk)) { /* ACK or retransmitted segment: clear ECT|CE */ INET_ECN_dontxmit(sk); }