aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2024-04-03 19:26:16 -0700
committerJakub Kicinski <kuba@kernel.org>2024-04-03 19:26:16 -0700
commitd20bac353be7f169b8b032ff6346d2fe608d8312 (patch)
treeff2abee2b5fd4ec8a9c22967bb598596555c6266
parent2f3c7195a702178629575b637f3f9a91eabdab73 (diff)
parent19822a980e1956a6572998887a7df5a0607a32f6 (diff)
downloadipsec-next-d20bac353be7f169b8b032ff6346d2fe608d8312.tar.gz
Merge branch 'tcp-make-trace-of-reset-logic-complete'
Jason Xing says: ==================== tcp: make trace of reset logic complete Before this, we miss some cases where the TCP layer could send RST but we cannot trace it. So I decided to complete it :) Link: https://lore.kernel.org/all/20240329034243.7929-1-kerneljasonxing@gmail.com/ ==================== Link: https://lore.kernel.org/r/20240401073605.37335-1-kerneljasonxing@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--include/trace/events/net_probe_common.h20
-rw-r--r--include/trace/events/tcp.h42
-rw-r--r--include/trace/events/udp.h2
-rw-r--r--net/ipv4/tcp_ipv4.c7
-rw-r--r--net/ipv6/tcp_ipv6.c3
5 files changed, 56 insertions, 18 deletions
diff --git a/include/trace/events/net_probe_common.h b/include/trace/events/net_probe_common.h
index 5e33f91bdea373..976a58364bff15 100644
--- a/include/trace/events/net_probe_common.h
+++ b/include/trace/events/net_probe_common.h
@@ -70,14 +70,14 @@
TP_STORE_V4MAPPED(__entry, saddr, daddr)
#endif
-#define TP_STORE_ADDR_PORTS_SKB_V4(__entry, skb, protoh) \
+#define TP_STORE_ADDR_PORTS_SKB_V4(skb, protoh, entry_saddr, entry_daddr) \
do { \
- struct sockaddr_in *v4 = (void *)__entry->saddr; \
+ struct sockaddr_in *v4 = (void *)entry_saddr; \
\
v4->sin_family = AF_INET; \
v4->sin_port = protoh->source; \
v4->sin_addr.s_addr = ip_hdr(skb)->saddr; \
- v4 = (void *)__entry->daddr; \
+ v4 = (void *)entry_daddr; \
v4->sin_family = AF_INET; \
v4->sin_port = protoh->dest; \
v4->sin_addr.s_addr = ip_hdr(skb)->daddr; \
@@ -85,28 +85,30 @@
#if IS_ENABLED(CONFIG_IPV6)
-#define TP_STORE_ADDR_PORTS_SKB(__entry, skb, protoh) \
+#define TP_STORE_ADDR_PORTS_SKB(skb, protoh, entry_saddr, entry_daddr) \
do { \
const struct iphdr *iph = ip_hdr(skb); \
\
if (iph->version == 6) { \
- struct sockaddr_in6 *v6 = (void *)__entry->saddr; \
+ struct sockaddr_in6 *v6 = (void *)entry_saddr; \
\
v6->sin6_family = AF_INET6; \
v6->sin6_port = protoh->source; \
v6->sin6_addr = ipv6_hdr(skb)->saddr; \
- v6 = (void *)__entry->daddr; \
+ v6 = (void *)entry_daddr; \
v6->sin6_family = AF_INET6; \
v6->sin6_port = protoh->dest; \
v6->sin6_addr = ipv6_hdr(skb)->daddr; \
} else \
- TP_STORE_ADDR_PORTS_SKB_V4(__entry, skb, protoh); \
+ TP_STORE_ADDR_PORTS_SKB_V4(skb, protoh, \
+ entry_saddr, \
+ entry_daddr); \
} while (0)
#else
-#define TP_STORE_ADDR_PORTS_SKB(__entry, skb, protoh) \
- TP_STORE_ADDR_PORTS_SKB_V4(__entry, skb, protoh)
+#define TP_STORE_ADDR_PORTS_SKB(skb, protoh, entry_saddr, entry_daddr) \
+ TP_STORE_ADDR_PORTS_SKB_V4(skb, protoh, entry_saddr, entry_daddr)
#endif
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 1db95175c1e528..5c04a61a11c2c8 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -78,11 +78,47 @@ DEFINE_EVENT(tcp_event_sk_skb, tcp_retransmit_skb,
* skb of trace_tcp_send_reset is the skb that caused RST. In case of
* active reset, skb should be NULL
*/
-DEFINE_EVENT(tcp_event_sk_skb, tcp_send_reset,
+TRACE_EVENT(tcp_send_reset,
TP_PROTO(const struct sock *sk, const struct sk_buff *skb),
- TP_ARGS(sk, skb)
+ TP_ARGS(sk, skb),
+
+ TP_STRUCT__entry(
+ __field(const void *, skbaddr)
+ __field(const void *, skaddr)
+ __field(int, state)
+ __array(__u8, saddr, sizeof(struct sockaddr_in6))
+ __array(__u8, daddr, sizeof(struct sockaddr_in6))
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->skaddr = sk;
+ /* Zero means unknown state. */
+ __entry->state = sk ? sk->sk_state : 0;
+
+ memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
+ memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
+
+ if (sk && sk_fullsock(sk)) {
+ const struct inet_sock *inet = inet_sk(sk);
+
+ TP_STORE_ADDR_PORTS(__entry, inet, sk);
+ } else if (skb) {
+ const struct tcphdr *th = (const struct tcphdr *)skb->data;
+ /*
+ * We should reverse the 4-tuple of skb, so later
+ * it can print the right flow direction of rst.
+ */
+ TP_STORE_ADDR_PORTS_SKB(skb, th, entry->daddr, entry->saddr);
+ }
+ ),
+
+ TP_printk("skbaddr=%p skaddr=%p src=%pISpc dest=%pISpc state=%s",
+ __entry->skbaddr, __entry->skaddr,
+ __entry->saddr, __entry->daddr,
+ __entry->state ? show_tcp_state_name(__entry->state) : "UNKNOWN")
);
/*
@@ -295,7 +331,7 @@ DECLARE_EVENT_CLASS(tcp_event_skb,
memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
- TP_STORE_ADDR_PORTS_SKB(__entry, skb, th);
+ TP_STORE_ADDR_PORTS_SKB(skb, th, __entry->saddr, __entry->daddr);
),
TP_printk("skbaddr=%p src=%pISpc dest=%pISpc",
diff --git a/include/trace/events/udp.h b/include/trace/events/udp.h
index 62bebe2a6ecebd..6142be4068e29b 100644
--- a/include/trace/events/udp.h
+++ b/include/trace/events/udp.h
@@ -38,7 +38,7 @@ TRACE_EVENT(udp_fail_queue_rcv_skb,
memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
- TP_STORE_ADDR_PORTS_SKB(__entry, skb, uh);
+ TP_STORE_ADDR_PORTS_SKB(skb, uh, __entry->saddr, __entry->daddr);
),
TP_printk("rc=%d family=%s src=%pISpc dest=%pISpc", __entry->rc,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1e0a9762f92e60..56b75efcfd12bf 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -866,11 +866,10 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
* routing might fail in this case. No choice here, if we choose to force
* input interface, we will misroute in case of asymmetric route.
*/
- if (sk) {
+ if (sk)
arg.bound_dev_if = sk->sk_bound_dev_if;
- if (sk_fullsock(sk))
- trace_tcp_send_reset(sk, skb);
- }
+
+ trace_tcp_send_reset(sk, skb);
BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) !=
offsetof(struct inet_timewait_sock, tw_bound_dev_if));
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5ae74f661d25f9..cffebaec66f1ab 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1113,7 +1113,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
if (sk) {
oif = sk->sk_bound_dev_if;
if (sk_fullsock(sk)) {
- trace_tcp_send_reset(sk, skb);
if (inet6_test_bit(REPFLOW, sk))
label = ip6_flowlabel(ipv6h);
priority = READ_ONCE(sk->sk_priority);
@@ -1129,6 +1128,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
label = ip6_flowlabel(ipv6h);
}
+ trace_tcp_send_reset(sk, skb);
+
tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, 1,
ipv6_get_dsfield(ipv6h), label, priority, txhash,
&key);