@@ -332,6 +332,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 */
+ u16 pkts_acked_ewma;/* EWMA of packets acked for AccECN cep heuristic */
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 */
@@ -2629,6 +2629,7 @@ int tcp_disconnect(struct sock *sk, int flags)
tcp_accecn_init_counters(tp);
tp->prev_ecnfield = 0;
tp->accecn_opt_tstamp = 0;
+ tp->pkts_acked_ewma = 0;
tcp_set_ca_state(sk, TCP_CA_Open);
tp->is_sack_reneg = 0;
tcp_clear_retrans(tp);
@@ -514,6 +514,10 @@ static bool tcp_accecn_process_option(struct tcp_sock *tp,
return res;
}
+#define PKTS_ACKED_WEIGHT 6
+#define PKTS_ACKED_PREC 6
+#define ACK_COMP_THRESH 4
+
/* Returns the ECN CE delta */
static u32 tcp_accecn_process(struct tcp_sock *tp, const struct sk_buff *skb,
u32 delivered_pkts, u32 delivered_bytes, int flag)
@@ -529,6 +533,19 @@ static u32 tcp_accecn_process(struct tcp_sock *tp, const struct sk_buff *skb,
opt_deltas_valid = tcp_accecn_process_option(tp, skb, delivered_bytes);
+ if (delivered_pkts) {
+ if (!tp->pkts_acked_ewma) {
+ tp->pkts_acked_ewma = delivered_pkts << PKTS_ACKED_PREC;
+ } else {
+ u32 ewma = tp->pkts_acked_ewma;
+
+ ewma = (((ewma << PKTS_ACKED_WEIGHT) - ewma) +
+ (delivered_pkts << PKTS_ACKED_PREC)) >>
+ PKTS_ACKED_WEIGHT;
+ tp->pkts_acked_ewma = min_t(u32, ewma, 0xFFFFU);
+ }
+ }
+
if (!(flag & FLAG_SLOWPATH)) {
/* AccECN counter might overflow on large ACKs */
if (delivered_pkts <= TCP_ACCECN_CEP_ACE_MASK)
@@ -555,7 +572,8 @@ static u32 tcp_accecn_process(struct tcp_sock *tp, const struct sk_buff *skb,
return safe_delta;
if (d_ceb < safe_delta * tp->mss_cache >> TCP_ACCECN_SAFETY_SHIFT)
return delta;
- }
+ } else if (tp->pkts_acked_ewma > (ACK_COMP_THRESH << PKTS_ACKED_PREC))
+ return delta;
return safe_delta;
}