@@ -330,6 +330,7 @@ struct tcp_sock {
prev_ecnfield:2,/* ECN bits from the previous segment */
accecn_opt_demand:2,/* Demand AccECN option for n next ACKs */
estimate_ecnfield:2;/* ECN field for AccECN delivered estimates */
+ u64 accecn_opt_tstamp; /* Last AccECN option sent timestamp */
u32 lost; /* Total data packets lost incl. rexmits */
u32 app_limited; /* limited until "delivered" reaches this val */
u64 first_tx_mstamp; /* start of window send phase */
@@ -224,6 +224,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCP_ACCECN_MAXSIZE (TCPOLEN_EXP_ACCECN_BASE + \
TCPOLEN_ACCECN_PERCOUNTER * \
TCP_ACCECN_NUMCOUNTERS)
+#define TCP_ACCECN_BEACON_FREQ_SHIFT 2 /* Send option at least 2^2 times per RTT */
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
@@ -2627,6 +2627,7 @@ int tcp_disconnect(struct sock *sk, int flags)
tp->ecn_fail = 0;
tcp_accecn_init_counters(tp);
tp->prev_ecnfield = 0;
+ tp->accecn_opt_tstamp = 0;
tcp_set_ca_state(sk, TCP_CA_Open);
tp->is_sack_reneg = 0;
tcp_clear_retrans(tp);
@@ -588,6 +588,7 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
}
if (tp != NULL) {
tp->accecn_minlen = 0;
+ tp->accecn_opt_tstamp = tp->tcp_mstamp;
if (tp->accecn_opt_demand)
tp->accecn_opt_demand--;
}
@@ -988,12 +989,17 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
}
}
- if (tcp_ecn_mode_accecn(tp) && tp->accecn_opt_demand &&
+ if (tcp_ecn_mode_accecn(tp) &&
!(sock_net(sk)->ipv4.sysctl_tcp_ecn & TCP_ACCECN_NO_OPT)) {
- opts->ecn_bytes = tp->received_ecn_bytes;
- size += tcp_options_fit_accecn(opts, tp->accecn_minlen,
- MAX_TCP_OPTION_SPACE - size,
- opts->num_sack_blocks > 0 ? 2 : 0);
+ if (tp->accecn_opt_demand ||
+ (tcp_stamp_us_delta(tp->tcp_mstamp, tp->accecn_opt_tstamp) >=
+ (tp->srtt_us >> (3 + TCP_ACCECN_BEACON_FREQ_SHIFT)))) {
+ opts->ecn_bytes = tp->received_ecn_bytes;
+ size += tcp_options_fit_accecn(opts, tp->accecn_minlen,
+ MAX_TCP_OPTION_SPACE - size,
+ opts->num_sack_blocks > 0 ?
+ 2 : 0);
+ }
}
return size;