Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'tcp-add-a-new-tw_paws-drop-reason'

Jiayuan Chen says:

====================
tcp: add a new TW_PAWS drop reason

Devices in the networking path, such as firewalls, NATs, or routers, which
can perform SNAT or DNAT, use addresses from their own limited address
pools to masquerade the source address during forwarding, causing PAWS
verification to fail more easily under TW status.

Currently, packet loss statistics for PAWS can only be viewed through MIB,
which is a global metric and cannot be precisely obtained through tracing
to get the specific 4-tuple of the dropped packet. In the past, we had to
use kprobe ret to retrieve relevant skb information from
tcp_timewait_state_process().

We add a drop_reason pointer and a new counter.

I didn't provide a packetdrill script.
I struggled for a long time to get packetdrill to fix the client port, but
ultimately failed to do so...

Instead, I wrote my own program to trigger PAWS, which can be found at
https://github.com/mrpre/nettrigger/tree/main
'''
//assume nginx running on 172.31.75.114:9999, current host is 172.31.75.115
iptables -t filter -I OUTPUT -p tcp --sport 12345 --tcp-flags RST RST -j DROP
./nettrigger -i eth0 -s 172.31.75.115:12345 -d 172.31.75.114:9999 -action paws
'''

v2: https://lore.kernel.org/5cdc1bdd9caee92a6ae932638a862fd5c67630e8@linux.dev
v3: https://lore.kernel.org/20250407140001.13886-1-jiayuan.chen@linux.dev
====================

Link: https://patch.msgid.link/20250409112614.16153-1-jiayuan.chen@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+23 -6
+2
Documentation/networking/net_cachelines/snmp.rst
··· 37 37 unsigned_long LINUX_MIB_PAWSACTIVEREJECTED 38 38 unsigned_long LINUX_MIB_PAWSESTABREJECTED 39 39 unsigned_long LINUX_MIB_TSECR_REJECTED 40 + unsigned_long LINUX_MIB_PAWS_OLD_ACK 41 + unsigned_long LINUX_MIB_PAWS_TW_REJECTED 40 42 unsigned_long LINUX_MIB_DELAYEDACKLOST 41 43 unsigned_long LINUX_MIB_LISTENOVERFLOWS 42 44 unsigned_long LINUX_MIB_LISTENDROPS
+7
include/net/dropreason-core.h
··· 40 40 FN(TCP_OFOMERGE) \ 41 41 FN(TCP_RFC7323_PAWS) \ 42 42 FN(TCP_RFC7323_PAWS_ACK) \ 43 + FN(TCP_RFC7323_TW_PAWS) \ 43 44 FN(TCP_RFC7323_TSECR) \ 44 45 FN(TCP_LISTEN_OVERFLOW) \ 45 46 FN(TCP_OLD_SEQUENCE) \ ··· 284 283 * Corresponds to LINUX_MIB_PAWS_OLD_ACK. 285 284 */ 286 285 SKB_DROP_REASON_TCP_RFC7323_PAWS_ACK, 286 + /** 287 + * @SKB_DROP_REASON_TCP_RFC7323_TW_PAWS: PAWS check, socket is in 288 + * TIME_WAIT state. 289 + * Corresponds to LINUX_MIB_PAWS_TW_REJECTED. 290 + */ 291 + SKB_DROP_REASON_TCP_RFC7323_TW_PAWS, 287 292 /** 288 293 * @SKB_DROP_REASON_TCP_RFC7323_TSECR: PAWS check, invalid TSEcr. 289 294 * Corresponds to LINUX_MIB_TSECRREJECTED.
+2 -1
include/net/tcp.h
··· 427 427 enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw, 428 428 struct sk_buff *skb, 429 429 const struct tcphdr *th, 430 - u32 *tw_isn); 430 + u32 *tw_isn, 431 + enum skb_drop_reason *drop_reason); 431 432 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, 432 433 struct request_sock *req, bool fastopen, 433 434 bool *lost_race, enum skb_drop_reason *drop_reason);
+1
include/uapi/linux/snmp.h
··· 188 188 LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */ 189 189 LINUX_MIB_TSECRREJECTED, /* TSEcrRejected */ 190 190 LINUX_MIB_PAWS_OLD_ACK, /* PAWSOldAck */ 191 + LINUX_MIB_PAWS_TW_REJECTED, /* PAWSTimewait */ 191 192 LINUX_MIB_DELAYEDACKS, /* DelayedACKs */ 192 193 LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */ 193 194 LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */
+1
net/ipv4/proc.c
··· 191 191 SNMP_MIB_ITEM("PAWSEstab", LINUX_MIB_PAWSESTABREJECTED), 192 192 SNMP_MIB_ITEM("TSEcrRejected", LINUX_MIB_TSECRREJECTED), 193 193 SNMP_MIB_ITEM("PAWSOldAck", LINUX_MIB_PAWS_OLD_ACK), 194 + SNMP_MIB_ITEM("PAWSTimewait", LINUX_MIB_PAWS_TW_REJECTED), 194 195 SNMP_MIB_ITEM("DelayedACKs", LINUX_MIB_DELAYEDACKS), 195 196 SNMP_MIB_ITEM("DelayedACKLocked", LINUX_MIB_DELAYEDACKLOCKED), 196 197 SNMP_MIB_ITEM("DelayedACKLost", LINUX_MIB_DELAYEDACKLOST),
+2 -1
net/ipv4/tcp_ipv4.c
··· 2417 2417 goto csum_error; 2418 2418 } 2419 2419 2420 - tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn); 2420 + tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn, 2421 + &drop_reason); 2421 2422 switch (tw_status) { 2422 2423 case TCP_TW_SYN: { 2423 2424 struct sock *sk2 = inet_lookup_listener(net,
+6 -3
net/ipv4/tcp_minisocks.c
··· 97 97 */ 98 98 enum tcp_tw_status 99 99 tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, 100 - const struct tcphdr *th, u32 *tw_isn) 100 + const struct tcphdr *th, u32 *tw_isn, 101 + enum skb_drop_reason *drop_reason) 101 102 { 102 103 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); 103 104 u32 rcv_nxt = READ_ONCE(tcptw->tw_rcv_nxt); ··· 246 245 return TCP_TW_SYN; 247 246 } 248 247 249 - if (paws_reject) 250 - __NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED); 248 + if (paws_reject) { 249 + *drop_reason = SKB_DROP_REASON_TCP_RFC7323_TW_PAWS; 250 + __NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWS_TW_REJECTED); 251 + } 251 252 252 253 if (!th->rst) { 253 254 /* In this case we must reset the TIMEWAIT timer.
+2 -1
net/ipv6/tcp_ipv6.c
··· 1970 1970 goto csum_error; 1971 1971 } 1972 1972 1973 - tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn); 1973 + tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn, 1974 + &drop_reason); 1974 1975 switch (tw_status) { 1975 1976 case TCP_TW_SYN: 1976 1977 {