Index: share/man/man4/cc_dctcp.4 =================================================================== --- share/man/man4/cc_dctcp.4 +++ share/man/man4/cc_dctcp.4 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2019 +.Dd May 17, 2020 .Dt CC_DCTCP 4 .Os .Sh NAME @@ -91,6 +91,11 @@ .It Va slowstart A flag if the congestion window should be reduced by one half after slow start. Valid settings 0 and 1, default 0. +.It Va ect1 +Controls if a DCTCP session should use IP ECT(1) marking when sending out +segments (default), or ECT(0) marking like regular RFC3168 sessions. +Changes to this setting will only affect new sessions, existing sessions will +retain their previous marking value. .El .Sh SEE ALSO .Xr cc_chd 4 , Index: sys/netinet/cc/cc_dctcp.c =================================================================== --- sys/netinet/cc/cc_dctcp.c +++ sys/netinet/cc/cc_dctcp.c @@ -64,6 +64,8 @@ #define V_dctcp_shift_g VNET(dctcp_shift_g) VNET_DEFINE_STATIC(uint32_t, dctcp_slowstart) = 0; #define V_dctcp_slowstart VNET(dctcp_slowstart) +VNET_DEFINE_STATIC(uint32_t, dctcp_ect1) = 1; +#define V_dctcp_ect1 VNET(dctcp_ect1) struct dctcp { uint32_t bytes_ecn; /* # of marked bytes during a RTT */ @@ -300,8 +302,11 @@ dctcp_data = ccv->cc_data; - if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) + if (CCV(ccv, t_flags2) & TF2_ECN_PERMIT) { dctcp_data->save_sndnxt = CCV(ccv, snd_nxt); + if (V_dctcp_ect1) + CCV(ccv, t_flags2) |= TF2_ECN_USE_ECT1; + } } /* @@ -465,4 +470,9 @@ &VNET_NAME(dctcp_slowstart), 0, &dctcp_slowstart_handler, "IU", "half CWND reduction after the first slow start"); +SYSCTL_UINT(_net_inet_tcp_cc_dctcp, OID_AUTO, ect1, + CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + &VNET_NAME(dctcp_ect1), 0, + "Send DCTCP segments with ÍP ECT(1) or ECT(0)"); + DECLARE_CC_MODULE(dctcp, &dctcp_cc_algo); Index: sys/netinet/tcp_output.c =================================================================== --- sys/netinet/tcp_output.c +++ sys/netinet/tcp_output.c @@ -1165,13 +1165,20 @@ if (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) && (sack_rxmit == 0) && !((tp->t_flags & TF_FORCEDATA) && len == 1)) { + int ect; + if (tp->t_flags2 & TF2_ECN_USE_ECT1) { + ect = IPTOS_ECN_ECT1; + TCPSTAT_INC(tcps_ecn_ect1); + } else { + ect = IPTOS_ECN_ECT0; + TCPSTAT_INC(tcps_ecn_ect0); + } #ifdef INET6 if (isipv6) - ip6->ip6_flow |= htonl(IPTOS_ECN_ECT0 << 20); + ip6->ip6_flow |= htonl(ect << 20); else #endif - ip->ip_tos |= IPTOS_ECN_ECT0; - TCPSTAT_INC(tcps_ecn_ect0); + ip->ip_tos |= ect; } /* Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -434,6 +434,7 @@ #define TF2_ECN_SND_CWR 0x00000040 /* ECN CWR in queue */ #define TF2_ECN_SND_ECE 0x00000080 /* ECN ECE in queue */ #define TF2_ACE_PERMIT 0x00000100 /* Accurate ECN mode */ +#define TF2_ECN_USE_ECT1 0x00000200 /* Use ECT(1) marking on session */ /* * Structure to hold TCP options that are only used during segment