From: Ilpo Järvinen <i...@kernel.org>

The heuristic algorithm from draft-11 Appendix A.2.2 to
mitigate against false ACE field overflows.

Signed-off-by: Ilpo Järvinen <i...@kernel.org>
Signed-off-by: Chia-Yu Chang <chia-yu.ch...@nokia-bell-labs.com>
---
 include/net/tcp.h    |  1 +
 net/ipv4/tcp_input.c | 18 ++++++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5e4593e39de4..201326b10396 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -247,6 +247,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)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c93e4bffb23e..f206c1a93a56 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -709,16 +709,19 @@ 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];
        const struct tcphdr *th = tcp_hdr(skb);
        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 */
@@ -741,6 +744,17 @@ 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;
 }
 
-- 
2.34.1


Reply via email to