@@ -242,6 +242,7 @@ static_assert((1 << ATO_BITS) > TCP_DELACK_MAX);
#define TCP_ACCECN_MAXSIZE (TCPOLEN_ACCECN_BASE + \
TCPOLEN_ACCECN_PERFIELD * \
TCP_ACCECN_NUMFIELDS)
+#define TCP_ACCECN_SAFETY_SHIFT 1 /* SAFETY_FACTOR in accecn draft */
/* tp->accecn_fail_mode */
#define TCP_ACCECN_ACE_FAIL_SEND BIT(0)
@@ -669,15 +669,17 @@ static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
static u32 __tcp_accecn_process(struct sock *sk, const struct sk_buff *skb,
u32 delivered_pkts, u32 delivered_bytes, int flag)
{
+ u32 old_ceb = tcp_sk(sk)->delivered_ecn_bytes[INET_ECN_CE - 1];
struct tcp_sock *tp = tcp_sk(sk);
- u32 delta, safe_delta;
+ u32 delta, safe_delta, d_ceb;
+ bool opt_deltas_valid;
u32 corrected_ace;
/* Reordered ACK? (...or uncertain due to lack of data to send and ts) */
if (!(flag & (FLAG_FORWARD_PROGRESS | FLAG_TS_PROGRESS)))
return 0;
- tcp_accecn_process_option(tp, skb, delivered_bytes, flag);
+ opt_deltas_valid = tcp_accecn_process_option(tp, skb, delivered_bytes, flag);
if (!(flag & FLAG_SLOWPATH)) {
/* AccECN counter might overflow on large ACKs */
@@ -699,6 +701,16 @@ static u32 __tcp_accecn_process(struct sock *sk, const struct sk_buff *skb,
safe_delta = delivered_pkts - ((delivered_pkts - delta) & TCP_ACCECN_CEP_ACE_MASK);
+ if (opt_deltas_valid) {
+ d_ceb = tp->delivered_ecn_bytes[INET_ECN_CE - 1] - old_ceb;
+ if (!d_ceb)
+ return delta;
+ if (d_ceb > delta * tp->mss_cache)
+ return safe_delta;
+ if (d_ceb < safe_delta * tp->mss_cache >> TCP_ACCECN_SAFETY_SHIFT)
+ return delta;
+ }
+
return safe_delta;
}