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>
This commit is contained in:
@@ -37,6 +37,8 @@ unsigned_long LINUX_MIB_TIMEWAITKILLED
|
||||
unsigned_long LINUX_MIB_PAWSACTIVEREJECTED
|
||||
unsigned_long LINUX_MIB_PAWSESTABREJECTED
|
||||
unsigned_long LINUX_MIB_TSECR_REJECTED
|
||||
unsigned_long LINUX_MIB_PAWS_OLD_ACK
|
||||
unsigned_long LINUX_MIB_PAWS_TW_REJECTED
|
||||
unsigned_long LINUX_MIB_DELAYEDACKLOST
|
||||
unsigned_long LINUX_MIB_LISTENOVERFLOWS
|
||||
unsigned_long LINUX_MIB_LISTENDROPS
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
FN(TCP_OFOMERGE) \
|
||||
FN(TCP_RFC7323_PAWS) \
|
||||
FN(TCP_RFC7323_PAWS_ACK) \
|
||||
FN(TCP_RFC7323_TW_PAWS) \
|
||||
FN(TCP_RFC7323_TSECR) \
|
||||
FN(TCP_LISTEN_OVERFLOW) \
|
||||
FN(TCP_OLD_SEQUENCE) \
|
||||
@@ -283,6 +284,12 @@ enum skb_drop_reason {
|
||||
* Corresponds to LINUX_MIB_PAWS_OLD_ACK.
|
||||
*/
|
||||
SKB_DROP_REASON_TCP_RFC7323_PAWS_ACK,
|
||||
/**
|
||||
* @SKB_DROP_REASON_TCP_RFC7323_TW_PAWS: PAWS check, socket is in
|
||||
* TIME_WAIT state.
|
||||
* Corresponds to LINUX_MIB_PAWS_TW_REJECTED.
|
||||
*/
|
||||
SKB_DROP_REASON_TCP_RFC7323_TW_PAWS,
|
||||
/**
|
||||
* @SKB_DROP_REASON_TCP_RFC7323_TSECR: PAWS check, invalid TSEcr.
|
||||
* Corresponds to LINUX_MIB_TSECRREJECTED.
|
||||
|
||||
+2
-1
@@ -427,7 +427,8 @@ enum tcp_tw_status {
|
||||
enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
|
||||
struct sk_buff *skb,
|
||||
const struct tcphdr *th,
|
||||
u32 *tw_isn);
|
||||
u32 *tw_isn,
|
||||
enum skb_drop_reason *drop_reason);
|
||||
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req, bool fastopen,
|
||||
bool *lost_race, enum skb_drop_reason *drop_reason);
|
||||
|
||||
@@ -188,6 +188,7 @@ enum
|
||||
LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */
|
||||
LINUX_MIB_TSECRREJECTED, /* TSEcrRejected */
|
||||
LINUX_MIB_PAWS_OLD_ACK, /* PAWSOldAck */
|
||||
LINUX_MIB_PAWS_TW_REJECTED, /* PAWSTimewait */
|
||||
LINUX_MIB_DELAYEDACKS, /* DelayedACKs */
|
||||
LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */
|
||||
LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */
|
||||
|
||||
@@ -191,6 +191,7 @@ static const struct snmp_mib snmp4_net_list[] = {
|
||||
SNMP_MIB_ITEM("PAWSEstab", LINUX_MIB_PAWSESTABREJECTED),
|
||||
SNMP_MIB_ITEM("TSEcrRejected", LINUX_MIB_TSECRREJECTED),
|
||||
SNMP_MIB_ITEM("PAWSOldAck", LINUX_MIB_PAWS_OLD_ACK),
|
||||
SNMP_MIB_ITEM("PAWSTimewait", LINUX_MIB_PAWS_TW_REJECTED),
|
||||
SNMP_MIB_ITEM("DelayedACKs", LINUX_MIB_DELAYEDACKS),
|
||||
SNMP_MIB_ITEM("DelayedACKLocked", LINUX_MIB_DELAYEDACKLOCKED),
|
||||
SNMP_MIB_ITEM("DelayedACKLost", LINUX_MIB_DELAYEDACKLOST),
|
||||
|
||||
+2
-1
@@ -2417,7 +2417,8 @@ do_time_wait:
|
||||
goto csum_error;
|
||||
}
|
||||
|
||||
tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn);
|
||||
tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn,
|
||||
&drop_reason);
|
||||
switch (tw_status) {
|
||||
case TCP_TW_SYN: {
|
||||
struct sock *sk2 = inet_lookup_listener(net,
|
||||
|
||||
@@ -97,7 +97,8 @@ static void twsk_rcv_nxt_update(struct tcp_timewait_sock *tcptw, u32 seq,
|
||||
*/
|
||||
enum tcp_tw_status
|
||||
tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
|
||||
const struct tcphdr *th, u32 *tw_isn)
|
||||
const struct tcphdr *th, u32 *tw_isn,
|
||||
enum skb_drop_reason *drop_reason)
|
||||
{
|
||||
struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
||||
u32 rcv_nxt = READ_ONCE(tcptw->tw_rcv_nxt);
|
||||
@@ -245,8 +246,10 @@ kill:
|
||||
return TCP_TW_SYN;
|
||||
}
|
||||
|
||||
if (paws_reject)
|
||||
__NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED);
|
||||
if (paws_reject) {
|
||||
*drop_reason = SKB_DROP_REASON_TCP_RFC7323_TW_PAWS;
|
||||
__NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWS_TW_REJECTED);
|
||||
}
|
||||
|
||||
if (!th->rst) {
|
||||
/* In this case we must reset the TIMEWAIT timer.
|
||||
|
||||
+2
-1
@@ -1970,7 +1970,8 @@ do_time_wait:
|
||||
goto csum_error;
|
||||
}
|
||||
|
||||
tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn);
|
||||
tw_status = tcp_timewait_state_process(inet_twsk(sk), skb, th, &isn,
|
||||
&drop_reason);
|
||||
switch (tw_status) {
|
||||
case TCP_TW_SYN:
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user