Commit d20bac35 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

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: default avatarJakub Kicinski <kuba@kernel.org>
parents 2f3c7195 19822a98
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -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

+39 −3
Original line number Diff line number Diff line
@@ -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",
+1 −1
Original line number Diff line number Diff line
@@ -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,
+3 −4
Original line number Diff line number Diff line
@@ -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);
	}

	BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) !=
		     offsetof(struct inet_timewait_sock, tw_bound_dev_if));
+2 −1
Original line number Diff line number Diff line
@@ -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);