With RFC3168 ECN, CWR SHOULD only be sent with new data
Overly conservative data receivers may ignore the CWR flag on other packets, and keep ECE latched. This can result in continous reduction of the congestion window, and very poor performance when ECN is enabled. Reviewed by: rgrimes (mentor), rrs Approved by: rgrimes (mentor), tuexen (mentor) MFC after: 3 days Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D23364
This commit is contained in:
parent
8e0511652b
commit
af2fb894c9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=361347
@ -447,9 +447,15 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
|
||||
}
|
||||
break;
|
||||
case CC_ECN:
|
||||
if (!IN_CONGRECOVERY(tp->t_flags)) {
|
||||
if (!IN_CONGRECOVERY(tp->t_flags) ||
|
||||
/*
|
||||
* Allow ECN reaction on ACK to CWR, if
|
||||
* that data segment was also CE marked.
|
||||
*/
|
||||
SEQ_GEQ(th->th_ack, tp->snd_recover)) {
|
||||
EXIT_CONGRECOVERY(tp->t_flags);
|
||||
TCPSTAT_INC(tcps_ecn_rcwnd);
|
||||
tp->snd_recover = tp->snd_max;
|
||||
tp->snd_recover = tp->snd_max + 1;
|
||||
if (tp->t_flags2 & TF2_ECN_PERMIT)
|
||||
tp->t_flags2 |= TF2_ECN_SND_CWR;
|
||||
}
|
||||
|
@ -1170,7 +1170,8 @@ tcp_output(struct tcpcb *tp)
|
||||
*/
|
||||
if (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) &&
|
||||
(sack_rxmit == 0) &&
|
||||
!((tp->t_flags & TF_FORCEDATA) && len == 1)) {
|
||||
!((tp->t_flags & TF_FORCEDATA) && len == 1 &&
|
||||
SEQ_LT(tp->snd_una, tp->snd_max))) {
|
||||
#ifdef INET6
|
||||
if (isipv6)
|
||||
ip6->ip6_flow |= htonl(IPTOS_ECN_ECT0 << 20);
|
||||
@ -1178,14 +1179,14 @@ tcp_output(struct tcpcb *tp)
|
||||
#endif
|
||||
ip->ip_tos |= IPTOS_ECN_ECT0;
|
||||
TCPSTAT_INC(tcps_ecn_ect0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reply with proper ECN notifications.
|
||||
*/
|
||||
if (tp->t_flags2 & TF2_ECN_SND_CWR) {
|
||||
flags |= TH_CWR;
|
||||
tp->t_flags2 &= ~TF2_ECN_SND_CWR;
|
||||
/*
|
||||
* Reply with proper ECN notifications.
|
||||
* Only set CWR on new data segments.
|
||||
*/
|
||||
if (tp->t_flags2 & TF2_ECN_SND_CWR) {
|
||||
flags |= TH_CWR;
|
||||
tp->t_flags2 &= ~TF2_ECN_SND_CWR;
|
||||
}
|
||||
}
|
||||
if (tp->t_flags2 & TF2_ECN_SND_ECE)
|
||||
flags |= TH_ECE;
|
||||
|
@ -4095,9 +4095,15 @@ rack_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
|
||||
}
|
||||
break;
|
||||
case CC_ECN:
|
||||
if (!IN_CONGRECOVERY(tp->t_flags)) {
|
||||
if (!IN_CONGRECOVERY(tp->t_flags) ||
|
||||
/*
|
||||
* Allow ECN reaction on ACK to CWR, if
|
||||
* that data segment was also CE marked.
|
||||
*/
|
||||
SEQ_GEQ(th->th_ack, tp->snd_recover)) {
|
||||
EXIT_CONGRECOVERY(tp->t_flags);
|
||||
KMOD_TCPSTAT_INC(tcps_ecn_rcwnd);
|
||||
tp->snd_recover = tp->snd_max;
|
||||
tp->snd_recover = tp->snd_max + 1;
|
||||
if (tp->t_flags2 & TF2_ECN_PERMIT)
|
||||
tp->t_flags2 |= TF2_ECN_SND_CWR;
|
||||
}
|
||||
@ -13556,13 +13562,14 @@ rack_output(struct tcpcb *tp)
|
||||
#endif
|
||||
ip->ip_tos |= IPTOS_ECN_ECT0;
|
||||
KMOD_TCPSTAT_INC(tcps_ecn_ect0);
|
||||
}
|
||||
/*
|
||||
* Reply with proper ECN notifications.
|
||||
*/
|
||||
if (tp->t_flags2 & TF2_ECN_SND_CWR) {
|
||||
flags |= TH_CWR;
|
||||
tp->t_flags2 &= ~TF2_ECN_SND_CWR;
|
||||
/*
|
||||
* Reply with proper ECN notifications.
|
||||
* Only set CWR on new data segments.
|
||||
*/
|
||||
if (tp->t_flags2 & TF2_ECN_SND_CWR) {
|
||||
flags |= TH_CWR;
|
||||
tp->t_flags2 &= ~TF2_ECN_SND_CWR;
|
||||
}
|
||||
}
|
||||
if (tp->t_flags2 & TF2_ECN_SND_ECE)
|
||||
flags |= TH_ECE;
|
||||
|
Loading…
Reference in New Issue
Block a user