From 8bb2b3012313b2c7855d4a32f53d91b1f1552cd9 Mon Sep 17 00:00:00 2001 From: shiyunfei Date: Tue, 26 Dec 2023 18:47:06 +0800 Subject: [PATCH] newip tcp add RFC 5961 5.2 Signed-off-by: shiyunfei --- .../linux-5.10/net/newip/tcp_nip_input.c | 68 +++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c b/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c index 4019483..7c2eabf 100644 --- a/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c +++ b/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c @@ -1568,7 +1568,56 @@ static void tcp_nip_ack_calc_ssthresh(struct sock *sk, u32 ack, int icsk_rto_las } } -static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb) +static bool __tcp_nip_oow_rate_limited(struct net *net, int mib_idx, u32 *last_oow_ack_time) +{ + if (*last_oow_ack_time) { + s32 elapsed = (s32)(tcp_jiffies32 - *last_oow_ack_time); + + if (elapsed >= 0 && + elapsed < READ_ONCE(net->ipv4.sysctl_tcp_invalid_ratelimit)) { + NET_INC_STATS(net, mib_idx); + return true; /* rate-limited: don't send yet! */ + } + } + + *last_oow_ack_time = tcp_jiffies32; + + return false; /* not rate-limited: go ahead, send dupack now! */ +} + +static void tcp_nip_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) +{ + /* unprotected vars, we dont care of overwrites */ + static u32 nip_challenge_timestamp; + static unsigned int nip_challenge_count; + struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); + u32 count, now; + + /* First check our per-socket dupack rate limit. */ + if (__tcp_nip_oow_rate_limited(net, + LINUX_MIB_TCPACKSKIPPEDCHALLENGE, + &tp->last_oow_ack_time)) + return; + + /* Then check host-wide RFC 5961 rate limit. */ + now = jiffies / HZ; + if (now != READ_ONCE(nip_challenge_timestamp)) { + u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit); + u32 half = (ack_limit + 1) >> 1; + + WRITE_ONCE(nip_challenge_timestamp, now); + WRITE_ONCE(nip_challenge_count, half + prandom_u32_max(ack_limit)); + } + count = READ_ONCE(nip_challenge_count); + if (count > 0) { + WRITE_ONCE(nip_challenge_count, count - 1); + NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK); + tcp_nip_send_ack(sk); + } +} + +static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb, int flag) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_nip_common *ntp = &tcp_nip_sk(sk)->common; @@ -1579,8 +1628,15 @@ static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb) int prior_packets = tp->packets_out; ktime_t skb_snd_tstamp = 0; - if (before(ack, prior_snd_una)) + if (before(ack, prior_snd_una)) { + if (before(ack, prior_snd_una - tp->max_window)) { + if (!(flag & FLAG_NO_CHALLENGE_ACK)) + tcp_nip_send_challenge_ack(sk, skb); + return -1; + } return 0; + } + if (after(ack, tp->snd_nxt)) return -1; @@ -1737,7 +1793,7 @@ void tcp_nip_rcv_established(struct sock *sk, struct sk_buff *skb, if (!tcp_nip_validate_incoming(sk, skb, th, 1)) return; - if (tcp_nip_ack(sk, skb) < 0) + if (tcp_nip_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0) goto discard; tcp_nip_data_queue(sk, skb); @@ -1867,7 +1923,7 @@ static int tcp_nip_rcv_synsent_state_process(struct sock *sk, struct sk_buff *sk tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); - tcp_nip_ack(sk, skb); + tcp_nip_ack(sk, skb, FLAG_SLOWPATH); tp->out_of_order_queue = RB_ROOT; /* The next data number expected to be accepted is +1 */ tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; @@ -1996,7 +2052,9 @@ int tcp_nip_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (!tcp_nip_validate_incoming(sk, skb, th, 0)) return 0; - acceptable = tcp_nip_ack(sk, skb); + acceptable = tcp_nip_ack(sk, skb, FLAG_SLOWPATH | + FLAG_UPDATE_TS_RECENT | + FLAG_NO_CHALLENGE_ACK) > 0; /* If the third handshake ACK is invalid, 1 is returned * and the SKB is discarded in tcp_nip_rcv */ -- Gitee