netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change
@ 2022-06-17 10:05 menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 1/8] net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb() menglong8.dong
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev

From: Menglong Dong <imagedong@tencent.com>

In this series patches, skb drop reasons are add to code path of TCP
state change, which we have not done before. It is hard to pass these
reasons from the function to its caller, where skb is dropped. In order
to do this, we have to make some functions return skb drop reasons, or
pass the pointer of 'reason' to these function as an new function
argument.

=============================
In order to get skb drop reasons during tcp connect requesting code path,
we have to pass the pointer of the 'reason' as a new function argument of
conn_request() in 'struct inet_connection_sock_af_ops'. As the return
value of conn_request() can be positive or negative or 0, it's not
flexible to make it return drop reasons. This work is done in the 7th
patch, and functions that used as conn_request() is also modified:

  dccp_v4_conn_request()
  dccp_v6_conn_request()
  tcp_v4_conn_request()
  tcp_v6_conn_request()
  subflow_v4_conn_request()
  subflow_v6_conn_request()

As our target is TCP, dccp and mptcp are not handled more.

=============================
In the 6th patch, skb drop reasons are add to
tcp_timewait_state_process() by adding a function argument to it. In the
origin code, all skb are dropped for tw socket. In order to make less
noise, use consume_skb() for the 'good' skb. This can be checked by the
caller of tcp_timewait_state_process() from the value of drop reason.
If the drop reason is SKB_NOT_DROPPED_YET, it means this skb should not
be dropped.

=============================
In the 7th patch, skb drop reasons are add to the route_req() in struct
tcp_request_sock_ops. Following functions are involved:

  tcp_v4_route_req()
  tcp_v6_route_req()
  subflow_v4_route_req()
  subflow_v6_route_req()

In this series patches, following new drop reasons are added:

- SOCKET_DESTROYED
- LISTENOVERFLOWS
- TCP_REQQFULLDROP
- TIMEWAIT
- LSM

Changes since v3:
- Eric says what I did to tcp_rcv_state_process() is too invasive, so I
  removed that part (for now).
- As Eric suggested, make kfree_skb_reason(skb, SKB_NOT_DROPPED) the same
  as consume_skb(skb), which make code simplier. This is used in
  5th and 6th patch.

Changes since v2:
- move drop reasons to standalone header in another series

Changes since v1:
6/9 - fix the compile errors of dccp and mptcp (kernel test robot)
7/9 - skb is not freed on TCP_TW_ACK and 'ret' is not initizalized, fix
      it (Eric Dumazet)

Menglong Dong (8):
  net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb()
  net: skb: introduce __skb_queue_purge_reason()
  net: sock: introduce sk_stream_kill_queues_reason()
  net: inet: add skb drop reason to inet_csk_destroy_sock()
  net: tcp: add skb drop reasons to tcp connect requesting
  net: tcp: add skb drop reasons to tcp tw code path
  net: tcp: add skb drop reasons to route_req()
  net: tcp: use LINUX_MIB_TCPABORTONLINGER in tcp_rcv_state_process()

 include/linux/skbuff.h             | 12 ++++++++---
 include/net/dropreason.h           | 23 +++++++++++++++++++++
 include/net/inet_connection_sock.h |  3 ++-
 include/net/sock.h                 |  8 +++++++-
 include/net/tcp.h                  | 19 +++++++++--------
 net/core/skbuff.c                  | 11 ++++++++--
 net/core/stream.c                  |  7 ++++---
 net/dccp/dccp.h                    |  3 ++-
 net/dccp/input.c                   |  3 ++-
 net/dccp/ipv4.c                    |  3 ++-
 net/dccp/ipv6.c                    |  5 +++--
 net/ipv4/inet_connection_sock.c    |  2 +-
 net/ipv4/tcp_input.c               | 26 ++++++++++++++---------
 net/ipv4/tcp_ipv4.c                | 31 ++++++++++++++++++++--------
 net/ipv4/tcp_minisocks.c           | 23 +++++++++++++++++----
 net/ipv6/tcp_ipv6.c                | 33 ++++++++++++++++++++++--------
 net/mptcp/subflow.c                | 18 +++++++++-------
 17 files changed, 168 insertions(+), 62 deletions(-)

-- 
2.36.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 1/8] net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 2/8] net: skb: introduce __skb_queue_purge_reason() menglong8.dong
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev

From: Menglong Dong <imagedong@tencent.com>

Inorder to simply the code, allow SKB_NOT_DROPPED to be passed to
kfree_skb_reason(), suggested by Eric. Therefore, consume_skb(skb) can
be replaced with kfree_skb_reason(skb, SKB_NOT_DROPPED).

Not sure if it is suitable to make consume_skb() a simple call to
kfree_skb_reason(skb, SKB_NOT_DROPPED), as this can increase the
function call chain.

Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 net/core/skbuff.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b661040c100e..92f01b59ae40 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -769,15 +769,22 @@ EXPORT_SYMBOL(__kfree_skb);
  *	Drop a reference to the buffer and free it if the usage count has
  *	hit zero. Meanwhile, pass the drop reason to 'kfree_skb'
  *	tracepoint.
+ *
+ *	When the reason is SKB_NOT_DROPPED, it means that the packet is
+ *	freed normally, and the event 'consume_skb' will be triggered.
  */
 void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 {
 	if (!skb_unref(skb))
 		return;
 
-	DEBUG_NET_WARN_ON_ONCE(reason <= 0 || reason >= SKB_DROP_REASON_MAX);
+	DEBUG_NET_WARN_ON_ONCE(reason < 0 || reason >= SKB_DROP_REASON_MAX);
+
+	if (reason)
+		trace_kfree_skb(skb, __builtin_return_address(0), reason);
+	else
+		trace_consume_skb(skb);
 
-	trace_kfree_skb(skb, __builtin_return_address(0), reason);
 	__kfree_skb(skb);
 }
 EXPORT_SYMBOL(kfree_skb_reason);
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 2/8] net: skb: introduce __skb_queue_purge_reason()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 1/8] net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb() menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 3/8] net: sock: introduce sk_stream_kill_queues_reason() menglong8.dong
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng

From: Menglong Dong <imagedong@tencent.com>

Introduce __skb_queue_purge_reason() to empty a skb list with drop
reason and make __skb_queue_purge() an inline call to it.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 include/linux/skbuff.h | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 82edf0359ab3..8d5445c3d3e7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3020,18 +3020,24 @@ static inline int skb_orphan_frags_rx(struct sk_buff *skb, gfp_t gfp_mask)
 }
 
 /**
- *	__skb_queue_purge - empty a list
+ *	__skb_queue_purge_reason - empty a list with specific drop reason
  *	@list: list to empty
+ *	@reason: drop reason
  *
  *	Delete all buffers on an &sk_buff list. Each buffer is removed from
  *	the list and one reference dropped. This function does not take the
  *	list lock and the caller must hold the relevant locks to use it.
  */
-static inline void __skb_queue_purge(struct sk_buff_head *list)
+static inline void __skb_queue_purge_reason(struct sk_buff_head *list,
+					    enum skb_drop_reason reason)
 {
 	struct sk_buff *skb;
 	while ((skb = __skb_dequeue(list)) != NULL)
-		kfree_skb(skb);
+		kfree_skb_reason(skb, reason);
+}
+static inline void __skb_queue_purge(struct sk_buff_head *list)
+{
+	__skb_queue_purge_reason(list, SKB_DROP_REASON_NOT_SPECIFIED);
 }
 void skb_queue_purge(struct sk_buff_head *list);
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 3/8] net: sock: introduce sk_stream_kill_queues_reason()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 1/8] net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb() menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 2/8] net: skb: introduce __skb_queue_purge_reason() menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 4/8] net: inet: add skb drop reason to inet_csk_destroy_sock() menglong8.dong
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng

From: Menglong Dong <imagedong@tencent.com>

Introduce the function sk_stream_kill_queues_reason() and make the
origin sk_stream_kill_queues() an inline call to it.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 include/net/sock.h | 8 +++++++-
 net/core/stream.c  | 7 ++++---
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 657873e2d90f..208c87807f23 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1139,12 +1139,18 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
 int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
 void sk_stream_wait_close(struct sock *sk, long timeo_p);
 int sk_stream_error(struct sock *sk, int flags, int err);
-void sk_stream_kill_queues(struct sock *sk);
+void sk_stream_kill_queues_reason(struct sock *sk,
+				  enum skb_drop_reason reason);
 void sk_set_memalloc(struct sock *sk);
 void sk_clear_memalloc(struct sock *sk);
 
 void __sk_flush_backlog(struct sock *sk);
 
+static inline void sk_stream_kill_queues(struct sock *sk)
+{
+	sk_stream_kill_queues_reason(sk, SKB_DROP_REASON_NOT_SPECIFIED);
+}
+
 static inline bool sk_flush_backlog(struct sock *sk)
 {
 	if (unlikely(READ_ONCE(sk->sk_backlog.tail))) {
diff --git a/net/core/stream.c b/net/core/stream.c
index 06b36c730ce8..a562b23a1a6e 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -190,10 +190,11 @@ int sk_stream_error(struct sock *sk, int flags, int err)
 }
 EXPORT_SYMBOL(sk_stream_error);
 
-void sk_stream_kill_queues(struct sock *sk)
+void sk_stream_kill_queues_reason(struct sock *sk,
+				  enum skb_drop_reason reason)
 {
 	/* First the read buffer. */
-	__skb_queue_purge(&sk->sk_receive_queue);
+	__skb_queue_purge_reason(&sk->sk_receive_queue, reason);
 
 	/* Next, the write queue. */
 	WARN_ON(!skb_queue_empty(&sk->sk_write_queue));
@@ -209,4 +210,4 @@ void sk_stream_kill_queues(struct sock *sk)
 	 * have gone away, only the net layer knows can touch it.
 	 */
 }
-EXPORT_SYMBOL(sk_stream_kill_queues);
+EXPORT_SYMBOL(sk_stream_kill_queues_reason);
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 4/8] net: inet: add skb drop reason to inet_csk_destroy_sock()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (2 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 3/8] net: sock: introduce sk_stream_kill_queues_reason() menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 5/8] net: tcp: add skb drop reasons to tcp connect requesting menglong8.dong
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng

From: Menglong Dong <imagedong@tencent.com>

skb dropping in inet_csk_destroy_sock() seems to be a common case. Add
the new drop reason 'SKB_DROP_REASON_SOCKET_DESTROIED' and apply it to
inet_csk_destroy_sock() to stop confusing users with 'NOT_SPECIFIED'.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 include/net/dropreason.h        | 5 +++++
 net/ipv4/inet_connection_sock.c | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index fae9b40e54fa..3c6f1e299c35 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -231,6 +231,11 @@ enum skb_drop_reason {
 	 * MTU)
 	 */
 	SKB_DROP_REASON_PKT_TOO_BIG,
+	/**
+	 * @SKB_DROP_REASON_SOCKET_DESTROYED: socket is destroyed and the
+	 * skb in its receive or send queue are all dropped
+	 */
+	SKB_DROP_REASON_SOCKET_DESTROYED,
 	/**
 	 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
 	 * used as a real 'reason'
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index c0b7e6c21360..1812060f24cb 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -1129,7 +1129,7 @@ void inet_csk_destroy_sock(struct sock *sk)
 
 	sk->sk_prot->destroy(sk);
 
-	sk_stream_kill_queues(sk);
+	sk_stream_kill_queues_reason(sk, SKB_DROP_REASON_SOCKET_DESTROYED);
 
 	xfrm_sk_free_policy(sk);
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 5/8] net: tcp: add skb drop reasons to tcp connect requesting
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (3 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 4/8] net: inet: add skb drop reason to inet_csk_destroy_sock() menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 6/8] net: tcp: add skb drop reasons to tcp tw code path menglong8.dong
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng, kernel test robot

From: Menglong Dong <imagedong@tencent.com>

In order to get skb drop reasons during tcp connect requesting code path,
we have to pass the pointer of the 'reason' as a new function argument of
conn_request() in 'struct inet_connection_sock_af_ops'. As the return
value of conn_request() can be positive or negative or 0, it's not
flexible to make it return drop reasons.

As the return value of tcp_conn_request() is 0, so we can treat it as bool
and make it return the skb drop reasons.

The new drop reasons 'LISTENOVERFLOWS' and 'TCP_REQQFULLDROP' are added,
which are used for 'accept queue' and 'request queue' full.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
Reported-by: kernel test robot <lkp@intel.com>
--
v2:
- fix compile error reported by kernel test rebot
---
 include/net/dropreason.h           | 10 ++++++++++
 include/net/inet_connection_sock.h |  3 ++-
 include/net/tcp.h                  |  9 +++++----
 net/dccp/dccp.h                    |  3 ++-
 net/dccp/input.c                   |  3 ++-
 net/dccp/ipv4.c                    |  3 ++-
 net/dccp/ipv6.c                    |  5 +++--
 net/ipv4/tcp_input.c               | 22 ++++++++++++++--------
 net/ipv4/tcp_ipv4.c                |  9 ++++++---
 net/ipv6/tcp_ipv6.c                | 12 ++++++++----
 net/mptcp/subflow.c                |  8 +++++---
 11 files changed, 59 insertions(+), 28 deletions(-)

diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index 3c6f1e299c35..74512e60ab12 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -236,6 +236,16 @@ enum skb_drop_reason {
 	 * skb in its receive or send queue are all dropped
 	 */
 	SKB_DROP_REASON_SOCKET_DESTROYED,
+	/**
+	 * @SKB_DROP_REASON_LISTENOVERFLOWS: accept queue of the listen
+	 * socket is full, corresponding to LINUX_MIB_LISTENOVERFLOWS
+	 */
+	SKB_DROP_REASON_LISTENOVERFLOWS,
+	/**
+	 * @SKB_DROP_REASON_TCP_REQQFULLDROP: request queue of the listen
+	 * socket is full, corresponding to LINUX_MIB_TCPREQQFULLDROP
+	 */
+	SKB_DROP_REASON_TCP_REQQFULLDROP,
 	/**
 	 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
 	 * used as a real 'reason'
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 077cd730ce2f..7717c59ab3d7 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -37,7 +37,8 @@ struct inet_connection_sock_af_ops {
 	void	    (*send_check)(struct sock *sk, struct sk_buff *skb);
 	int	    (*rebuild_header)(struct sock *sk);
 	void	    (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
-	int	    (*conn_request)(struct sock *sk, struct sk_buff *skb);
+	int	    (*conn_request)(struct sock *sk, struct sk_buff *skb,
+				    enum skb_drop_reason *reason);
 	struct sock *(*syn_recv_sock)(const struct sock *sk, struct sk_buff *skb,
 				      struct request_sock *req,
 				      struct dst_entry *dst,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 1e99f5c61f84..16da150150c3 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -443,7 +443,8 @@ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
 void tcp_v4_mtu_reduced(struct sock *sk);
 void tcp_req_err(struct sock *sk, u32 seq, bool abort);
 void tcp_ld_RTO_revert(struct sock *sk, u32 seq);
-int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb,
+			enum skb_drop_reason *reason);
 struct sock *tcp_create_openreq_child(const struct sock *sk,
 				      struct request_sock *req,
 				      struct sk_buff *skb);
@@ -2034,9 +2035,9 @@ void tcp4_proc_exit(void);
 #endif
 
 int tcp_rtx_synack(const struct sock *sk, struct request_sock *req);
-int tcp_conn_request(struct request_sock_ops *rsk_ops,
-		     const struct tcp_request_sock_ops *af_ops,
-		     struct sock *sk, struct sk_buff *skb);
+enum skb_drop_reason tcp_conn_request(struct request_sock_ops *rsk_ops,
+				      const struct tcp_request_sock_ops *af_ops,
+				      struct sock *sk, struct sk_buff *skb);
 
 /* TCP af-specific functions */
 struct tcp_sock_af_ops {
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 7dfc00c9fb32..8c1241ae8449 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -255,7 +255,8 @@ void dccp_done(struct sock *sk);
 int dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,
 		    struct sk_buff const *skb);
 
-int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb,
+			 enum skb_drop_reason *reason);
 
 struct sock *dccp_create_openreq_child(const struct sock *sk,
 				       const struct request_sock *req,
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 2cbb757a894f..e12baa56ca59 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -576,6 +576,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 	const int old_state = sk->sk_state;
 	bool acceptable;
 	int queued = 0;
+	SKB_DR(reason);
 
 	/*
 	 *  Step 3: Process LISTEN state
@@ -606,7 +607,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 			 */
 			rcu_read_lock();
 			local_bh_disable();
-			acceptable = inet_csk(sk)->icsk_af_ops->conn_request(sk, skb) >= 0;
+			acceptable = inet_csk(sk)->icsk_af_ops->conn_request(sk, skb, &reason) >= 0;
 			local_bh_enable();
 			rcu_read_unlock();
 			if (!acceptable)
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index da6e3b20cd75..b0e8fcabf93b 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -581,7 +581,8 @@ static struct request_sock_ops dccp_request_sock_ops __read_mostly = {
 	.syn_ack_timeout = dccp_syn_ack_timeout,
 };
 
-int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb,
+			 enum skb_drop_reason *reason)
 {
 	struct inet_request_sock *ireq;
 	struct request_sock *req;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index fd44638ec16b..f01d6a05c7bf 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -314,7 +314,8 @@ static struct request_sock_ops dccp6_request_sock_ops = {
 	.syn_ack_timeout = dccp_syn_ack_timeout,
 };
 
-static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb,
+				enum skb_drop_reason *reason)
 {
 	struct request_sock *req;
 	struct dccp_request_sock *dreq;
@@ -324,7 +325,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
 
 	if (skb->protocol == htons(ETH_P_IP))
-		return dccp_v4_conn_request(sk, skb);
+		return dccp_v4_conn_request(sk, skb, reason);
 
 	if (!ipv6_unicast_destination(skb))
 		return 0;	/* discard, don't send a reset here */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2e2a9ece9af2..8617e7a8f841 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6453,13 +6453,14 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 			 */
 			rcu_read_lock();
 			local_bh_disable();
-			acceptable = icsk->icsk_af_ops->conn_request(sk, skb) >= 0;
+			reason = SKB_NOT_DROPPED_YET;
+			acceptable = icsk->icsk_af_ops->conn_request(sk, skb, &reason) >= 0;
 			local_bh_enable();
 			rcu_read_unlock();
 
 			if (!acceptable)
 				return 1;
-			consume_skb(skb);
+			kfree_skb_reason(skb, reason);
 			return 0;
 		}
 		SKB_DR_SET(reason, TCP_FLAGS);
@@ -6879,9 +6880,9 @@ u16 tcp_get_syncookie_mss(struct request_sock_ops *rsk_ops,
 }
 EXPORT_SYMBOL_GPL(tcp_get_syncookie_mss);
 
-int tcp_conn_request(struct request_sock_ops *rsk_ops,
-		     const struct tcp_request_sock_ops *af_ops,
-		     struct sock *sk, struct sk_buff *skb)
+enum skb_drop_reason tcp_conn_request(struct request_sock_ops *rsk_ops,
+				      const struct tcp_request_sock_ops *af_ops,
+				      struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_fastopen_cookie foc = { .len = -1 };
 	__u32 isn = TCP_SKB_CB(skb)->tcp_tw_isn;
@@ -6893,6 +6894,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 	bool want_cookie = false;
 	struct dst_entry *dst;
 	struct flowi fl;
+	SKB_DR(reason);
 
 	/* TW buckets are converted to open requests without
 	 * limitations, they conserve resources and peer is
@@ -6901,12 +6903,15 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 	if ((net->ipv4.sysctl_tcp_syncookies == 2 ||
 	     inet_csk_reqsk_queue_is_full(sk)) && !isn) {
 		want_cookie = tcp_syn_flood_action(sk, rsk_ops->slab_name);
-		if (!want_cookie)
+		if (!want_cookie) {
+			SKB_DR_SET(reason, TCP_REQQFULLDROP);
 			goto drop;
+		}
 	}
 
 	if (sk_acceptq_is_full(sk)) {
 		NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
+		SKB_DR_SET(reason, LISTENOVERFLOWS);
 		goto drop;
 	}
 
@@ -6962,6 +6967,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 			 */
 			pr_drop_req(req, ntohs(tcp_hdr(skb)->source),
 				    rsk_ops->family);
+			SKB_DR_SET(reason, TCP_REQQFULLDROP);
 			goto drop_and_release;
 		}
 
@@ -7014,7 +7020,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 		}
 	}
 	reqsk_put(req);
-	return 0;
+	return SKB_NOT_DROPPED_YET;
 
 drop_and_release:
 	dst_release(dst);
@@ -7022,6 +7028,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 	__reqsk_free(req);
 drop:
 	tcp_listendrop(sk);
-	return 0;
+	return reason;
 }
 EXPORT_SYMBOL(tcp_conn_request);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fe8f23b95d32..e1064273062a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1458,17 +1458,20 @@ const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
 	.send_synack	=	tcp_v4_send_synack,
 };
 
-int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb,
+			enum skb_drop_reason *reason)
 {
 	/* Never answer to SYNs send to broadcast or multicast */
 	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
 		goto drop;
 
-	return tcp_conn_request(&tcp_request_sock_ops,
-				&tcp_request_sock_ipv4_ops, sk, skb);
+	*reason = tcp_conn_request(&tcp_request_sock_ops,
+				   &tcp_request_sock_ipv4_ops, sk, skb);
+	return *reason;
 
 drop:
 	tcp_listendrop(sk);
+	*reason = SKB_DROP_REASON_IP_INADDRERRORS;
 	return 0;
 }
 EXPORT_SYMBOL(tcp_v4_conn_request);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f37dd4aa91c6..dbe356a166c5 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1148,24 +1148,28 @@ u16 tcp_v6_get_syncookie(struct sock *sk, struct ipv6hdr *iph,
 	return mss;
 }
 
-static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb,
+			       enum skb_drop_reason *reason)
 {
 	if (skb->protocol == htons(ETH_P_IP))
-		return tcp_v4_conn_request(sk, skb);
+		return tcp_v4_conn_request(sk, skb, reason);
 
 	if (!ipv6_unicast_destination(skb))
 		goto drop;
 
 	if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
 		__IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
+		*reason = SKB_DROP_REASON_IP_INADDRERRORS;
 		return 0;
 	}
 
-	return tcp_conn_request(&tcp6_request_sock_ops,
-				&tcp_request_sock_ipv6_ops, sk, skb);
+	*reason = tcp_conn_request(&tcp6_request_sock_ops,
+				   &tcp_request_sock_ipv6_ops, sk, skb);
+	return *reason;
 
 drop:
 	tcp_listendrop(sk);
+	*reason = SKB_DROP_REASON_IP_INADDRERRORS;
 	return 0; /* don't send reset */
 }
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 8841e8cd9ad8..5a1d05c3a1ef 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -532,7 +532,8 @@ static int subflow_v6_rebuild_header(struct sock *sk)
 struct request_sock_ops mptcp_subflow_request_sock_ops;
 static struct tcp_request_sock_ops subflow_request_sock_ipv4_ops __ro_after_init;
 
-static int subflow_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+static int subflow_v4_conn_request(struct sock *sk, struct sk_buff *skb,
+				   enum skb_drop_reason *reason)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 
@@ -556,14 +557,15 @@ static struct inet_connection_sock_af_ops subflow_v6_specific __ro_after_init;
 static struct inet_connection_sock_af_ops subflow_v6m_specific __ro_after_init;
 static struct proto tcpv6_prot_override;
 
-static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb,
+				   enum skb_drop_reason *reason)
 {
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
 
 	pr_debug("subflow=%p", subflow);
 
 	if (skb->protocol == htons(ETH_P_IP))
-		return subflow_v4_conn_request(sk, skb);
+		return subflow_v4_conn_request(sk, skb, reason);
 
 	if (!ipv6_unicast_destination(skb))
 		goto drop;
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 6/8] net: tcp: add skb drop reasons to tcp tw code path
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (4 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 5/8] net: tcp: add skb drop reasons to tcp connect requesting menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 7/8] net: tcp: add skb drop reasons to route_req() menglong8.dong
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng

From: Menglong Dong <imagedong@tencent.com>

In order to get the reasons of skb drops, add a function argument of
type 'enum skb_drop_reason *reason' to tcp_timewait_state_process().

In the origin code, all packets to time-wait socket are treated as
dropping with kfree_skb(), which can make users confused. Therefore,
we use consume_skb() for the skbs that are 'good'. We can check the
value of 'reason' to decide use kfree_skb() or consume_skb().

The new reason 'TIMEWAIT' is added for the case that the skb is dropped
as the socket in time-wait state.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
Reported-by: Eric Dumazet <edumazet@google.com>
---
v2:
- skb is not freed on TCP_TW_ACK and 'ret' is not initizalized, fix
  it (Eric Dumazet)
---
 include/net/dropreason.h |  6 ++++++
 include/net/tcp.h        |  7 ++++---
 net/ipv4/tcp_ipv4.c      |  8 ++++++--
 net/ipv4/tcp_minisocks.c | 23 +++++++++++++++++++----
 net/ipv6/tcp_ipv6.c      |  7 +++++--
 5 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index 74512e60ab12..90cdb7321926 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -246,6 +246,12 @@ enum skb_drop_reason {
 	 * socket is full, corresponding to LINUX_MIB_TCPREQQFULLDROP
 	 */
 	SKB_DROP_REASON_TCP_REQQFULLDROP,
+	/**
+	 * @SKB_DROP_REASON_TIMEWAIT: socket is in time-wait state and all
+	 * packet that received will be treated as 'drop', except a good
+	 * 'SYN' packet
+	 */
+	SKB_DROP_REASON_TIMEWAIT,
 	/**
 	 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
 	 * used as a real 'reason'
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 16da150150c3..1a88fabf0cce 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -379,9 +379,10 @@ 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);
+enum tcp_tw_status
+tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
+			   const struct tcphdr *th,
+			   enum skb_drop_reason *reason);
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 			   struct request_sock *req, bool fastopen,
 			   bool *lost_race);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index e1064273062a..f2ed9763d504 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1975,6 +1975,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
 			reqsk_put(req);
 			goto discard_it;
 		}
+		drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
 		if (tcp_checksum_complete(skb)) {
 			reqsk_put(req);
 			goto csum_error;
@@ -2049,6 +2050,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	if (drop_reason)
 		goto discard_and_relse;
 
+	drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	nf_reset_ct(skb);
 
 	if (tcp_filter(sk, skb)) {
@@ -2104,7 +2106,6 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	}
 
 discard_it:
-	SKB_DR_OR(drop_reason, NOT_SPECIFIED);
 	/* Discard frame. */
 	kfree_skb_reason(skb, drop_reason);
 	return 0;
@@ -2128,7 +2129,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
 		inet_twsk_put(inet_twsk(sk));
 		goto csum_error;
 	}
-	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th,
+					   &drop_reason)) {
 	case TCP_TW_SYN: {
 		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
 							&tcp_hashinfo, skb,
@@ -2144,6 +2146,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
 			refcounted = false;
 			goto process;
 		}
+		/* TCP_FLAGS or NO_SOCKET? */
+		SKB_DR_SET(drop_reason, TCP_FLAGS);
 	}
 		/* to ACK */
 		fallthrough;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 6854bb1fb32b..dd640574d00f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -83,13 +83,15 @@ tcp_timewait_check_oow_rate_limit(struct inet_timewait_sock *tw,
  */
 enum tcp_tw_status
 tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
-			   const struct tcphdr *th)
+			   const struct tcphdr *th,
+			   enum skb_drop_reason *reason)
 {
 	struct tcp_options_received tmp_opt;
 	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 	bool paws_reject = false;
 
 	tmp_opt.saw_tstamp = 0;
+	*reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
 		tcp_parse_options(twsk_net(tw), skb, &tmp_opt, 0, NULL);
 
@@ -113,11 +115,16 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 			return tcp_timewait_check_oow_rate_limit(
 				tw, skb, LINUX_MIB_TCPACKSKIPPEDFINWAIT2);
 
-		if (th->rst)
+		if (th->rst) {
+			SKB_DR_SET(*reason, TCP_RESET);
 			goto kill;
+		}
 
-		if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt))
+		if (th->syn && !before(TCP_SKB_CB(skb)->seq,
+				       tcptw->tw_rcv_nxt)) {
+			SKB_DR_SET(*reason, TCP_FLAGS);
 			return TCP_TW_RST;
+		}
 
 		/* Dup ACK? */
 		if (!th->ack ||
@@ -143,6 +150,9 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 		}
 
 		inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
+
+		/* skb should be free normally on this case. */
+		*reason = SKB_NOT_DROPPED_YET;
 		return TCP_TW_ACK;
 	}
 
@@ -174,6 +184,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 			 * protocol bug yet.
 			 */
 			if (twsk_net(tw)->ipv4.sysctl_tcp_rfc1337 == 0) {
+				SKB_DR_SET(*reason, TCP_RESET);
 kill:
 				inet_twsk_deschedule_put(tw);
 				return TCP_TW_SUCCESS;
@@ -219,8 +230,10 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 		return TCP_TW_SYN;
 	}
 
-	if (paws_reject)
+	if (paws_reject) {
+		SKB_DR_SET(*reason, TCP_RFC7323_PAWS);
 		__NET_INC_STATS(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED);
+	}
 
 	if (!th->rst) {
 		/* In this case we must reset the TIMEWAIT timer.
@@ -232,9 +245,11 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 		if (paws_reject || th->ack)
 			inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
 
+		SKB_DR_OR(*reason, TIMEWAIT);
 		return tcp_timewait_check_oow_rate_limit(
 			tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT);
 	}
+	SKB_DR_SET(*reason, TCP_RESET);
 	inet_twsk_put(tw);
 	return TCP_TW_SUCCESS;
 }
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index dbe356a166c5..9aeb0a7b7c12 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1644,6 +1644,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 			reqsk_put(req);
 			goto discard_it;
 		}
+		drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
 		if (tcp_checksum_complete(skb)) {
 			reqsk_put(req);
 			goto csum_error;
@@ -1715,6 +1716,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 	if (drop_reason)
 		goto discard_and_relse;
 
+	drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
 	if (tcp_filter(sk, skb)) {
 		drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
 		goto discard_and_relse;
@@ -1766,7 +1768,6 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 	}
 
 discard_it:
-	SKB_DR_OR(drop_reason, NOT_SPECIFIED);
 	kfree_skb_reason(skb, drop_reason);
 	return 0;
 
@@ -1790,7 +1791,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 		goto csum_error;
 	}
 
-	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th,
+					   &drop_reason)) {
 	case TCP_TW_SYN:
 	{
 		struct sock *sk2;
@@ -1810,6 +1812,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 			refcounted = false;
 			goto process;
 		}
+		SKB_DR_SET(drop_reason, TCP_FLAGS);
 	}
 		/* to ACK */
 		fallthrough;
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 7/8] net: tcp: add skb drop reasons to route_req()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (5 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 6/8] net: tcp: add skb drop reasons to tcp tw code path menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-17 10:05 ` [PATCH net-next v4 8/8] net: tcp: use LINUX_MIB_TCPABORTONLINGER in tcp_rcv_state_process() menglong8.dong
  2022-06-18  3:05 ` [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change Jakub Kicinski
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev, Jiang Biao, Hao Peng

From: Menglong Dong <imagedong@tencent.com>

Add skb drop reasons to the route_req() in struct tcp_request_sock_ops.
Following functions are involved:

  tcp_v4_route_req()
  tcp_v6_route_req()
  subflow_v4_route_req()
  subflow_v6_route_req()

And the new reason SKB_DROP_REASON_LSM is added, which is used when
skb is dropped by LSM.

Reviewed-by: Jiang Biao <benbjiang@tencent.com>
Reviewed-by: Hao Peng <flyingpeng@tencent.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 include/net/dropreason.h |  2 ++
 include/net/tcp.h        |  3 ++-
 net/ipv4/tcp_input.c     |  2 +-
 net/ipv4/tcp_ipv4.c      | 14 +++++++++++---
 net/ipv6/tcp_ipv6.c      | 14 +++++++++++---
 net/mptcp/subflow.c      | 10 ++++++----
 6 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/include/net/dropreason.h b/include/net/dropreason.h
index 90cdb7321926..d3143598125e 100644
--- a/include/net/dropreason.h
+++ b/include/net/dropreason.h
@@ -252,6 +252,8 @@ enum skb_drop_reason {
 	 * 'SYN' packet
 	 */
 	SKB_DROP_REASON_TIMEWAIT,
+	/** @SKB_DROP_REASON_LSM: dropped by LSM */
+	SKB_DROP_REASON_LSM,
 	/**
 	 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
 	 * used as a real 'reason'
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 1a88fabf0cce..d8895076d448 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2073,7 +2073,8 @@ struct tcp_request_sock_ops {
 	struct dst_entry *(*route_req)(const struct sock *sk,
 				       struct sk_buff *skb,
 				       struct flowi *fl,
-				       struct request_sock *req);
+				       struct request_sock *req,
+				       enum skb_drop_reason *reason);
 	u32 (*init_seq)(const struct sk_buff *skb);
 	u32 (*init_ts_off)(const struct net *net, const struct sk_buff *skb);
 	int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 8617e7a8f841..ed55616bc2a0 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6945,7 +6945,7 @@ enum skb_drop_reason tcp_conn_request(struct request_sock_ops *rsk_ops,
 	/* Note: tcp_v6_init_req() might override ir_iif for link locals */
 	inet_rsk(req)->ir_iif = inet_request_bound_dev_if(sk, skb);
 
-	dst = af_ops->route_req(sk, skb, &fl, req);
+	dst = af_ops->route_req(sk, skb, &fl, req, &reason);
 	if (!dst)
 		goto drop_and_free;
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f2ed9763d504..8accb49f3808 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1423,14 +1423,22 @@ static void tcp_v4_init_req(struct request_sock *req,
 static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
 					  struct sk_buff *skb,
 					  struct flowi *fl,
-					  struct request_sock *req)
+					  struct request_sock *req,
+					  enum skb_drop_reason *reason)
 {
+	struct dst_entry *dst;
+
 	tcp_v4_init_req(req, sk, skb);
 
-	if (security_inet_conn_request(sk, skb, req))
+	if (security_inet_conn_request(sk, skb, req)) {
+		SKB_DR_SET(*reason, LSM);
 		return NULL;
+	}
 
-	return inet_csk_route_req(sk, &fl->u.ip4, req);
+	dst = inet_csk_route_req(sk, &fl->u.ip4, req);
+	if (!dst)
+		SKB_DR_SET(*reason, IP_OUTNOROUTES);
+	return dst;
 }
 
 struct request_sock_ops tcp_request_sock_ops __read_mostly = {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 9aeb0a7b7c12..fbe37f4a73ee 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -802,14 +802,22 @@ static void tcp_v6_init_req(struct request_sock *req,
 static struct dst_entry *tcp_v6_route_req(const struct sock *sk,
 					  struct sk_buff *skb,
 					  struct flowi *fl,
-					  struct request_sock *req)
+					  struct request_sock *req,
+					  enum skb_drop_reason *reason)
 {
+	struct dst_entry *dst;
+
 	tcp_v6_init_req(req, sk, skb);
 
-	if (security_inet_conn_request(sk, skb, req))
+	if (security_inet_conn_request(sk, skb, req)) {
+		SKB_DR_SET(*reason, LSM);
 		return NULL;
+	}
 
-	return inet6_csk_route_req(sk, &fl->u.ip6, req, IPPROTO_TCP);
+	dst = inet6_csk_route_req(sk, &fl->u.ip6, req, IPPROTO_TCP);
+	if (!dst)
+		SKB_DR_SET(*reason, IP_OUTNOROUTES);
+	return dst;
 }
 
 struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 5a1d05c3a1ef..654cc602ff2c 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -285,7 +285,8 @@ EXPORT_SYMBOL_GPL(mptcp_subflow_init_cookie_req);
 static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
 					      struct sk_buff *skb,
 					      struct flowi *fl,
-					      struct request_sock *req)
+					      struct request_sock *req,
+					      enum skb_drop_reason *reason)
 {
 	struct dst_entry *dst;
 	int err;
@@ -293,7 +294,7 @@ static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
 	tcp_rsk(req)->is_mptcp = 1;
 	subflow_init_req(req, sk);
 
-	dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req);
+	dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req, reason);
 	if (!dst)
 		return NULL;
 
@@ -311,7 +312,8 @@ static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
 static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
 					      struct sk_buff *skb,
 					      struct flowi *fl,
-					      struct request_sock *req)
+					      struct request_sock *req,
+					      enum skb_drop_reason *reason)
 {
 	struct dst_entry *dst;
 	int err;
@@ -319,7 +321,7 @@ static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
 	tcp_rsk(req)->is_mptcp = 1;
 	subflow_init_req(req, sk);
 
-	dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req);
+	dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req, reason);
 	if (!dst)
 		return NULL;
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next v4 8/8] net: tcp: use LINUX_MIB_TCPABORTONLINGER in tcp_rcv_state_process()
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (6 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 7/8] net: tcp: add skb drop reasons to route_req() menglong8.dong
@ 2022-06-17 10:05 ` menglong8.dong
  2022-06-18  3:05 ` [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change Jakub Kicinski
  8 siblings, 0 replies; 10+ messages in thread
From: menglong8.dong @ 2022-06-17 10:05 UTC (permalink / raw)
  To: edumazet
  Cc: rostedt, mingo, davem, yoshfuji, dsahern, kuba, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev

From: Menglong Dong <imagedong@tencent.com>

The statistics for 'tp->linger2 < 0' in tcp_rcv_state_process() seems
more accurate to be LINUX_MIB_TCPABORTONLINGER.

Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 net/ipv4/tcp_input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ed55616bc2a0..cf4bc4b9be0c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6580,7 +6580,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 
 		if (tp->linger2 < 0) {
 			tcp_done(sk);
-			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
+			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONLINGER);
 			return 1;
 		}
 		if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change
  2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
                   ` (7 preceding siblings ...)
  2022-06-17 10:05 ` [PATCH net-next v4 8/8] net: tcp: use LINUX_MIB_TCPABORTONLINGER in tcp_rcv_state_process() menglong8.dong
@ 2022-06-18  3:05 ` Jakub Kicinski
  8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2022-06-18  3:05 UTC (permalink / raw)
  To: menglong8.dong
  Cc: edumazet, rostedt, mingo, davem, yoshfuji, dsahern, pabeni,
	imagedong, kafai, talalahmad, keescook, dongli.zhang,
	linux-kernel, netdev

On Fri, 17 Jun 2022 18:05:06 +0800 menglong8.dong@gmail.com wrote:
> From: Menglong Dong <imagedong@tencent.com>
> 
> In this series patches, skb drop reasons are add to code path of TCP
> state change, which we have not done before. It is hard to pass these
> reasons from the function to its caller, where skb is dropped. In order
> to do this, we have to make some functions return skb drop reasons, or
> pass the pointer of 'reason' to these function as an new function
> argument.

Does not cleanly apply to net-next, reportedly.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-06-18  3:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-17 10:05 [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 1/8] net: skb: use SKB_NOT_DROPPED in kfree_skb_reason() as consume_skb() menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 2/8] net: skb: introduce __skb_queue_purge_reason() menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 3/8] net: sock: introduce sk_stream_kill_queues_reason() menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 4/8] net: inet: add skb drop reason to inet_csk_destroy_sock() menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 5/8] net: tcp: add skb drop reasons to tcp connect requesting menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 6/8] net: tcp: add skb drop reasons to tcp tw code path menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 7/8] net: tcp: add skb drop reasons to route_req() menglong8.dong
2022-06-17 10:05 ` [PATCH net-next v4 8/8] net: tcp: use LINUX_MIB_TCPABORTONLINGER in tcp_rcv_state_process() menglong8.dong
2022-06-18  3:05 ` [PATCH net-next v4 0/8] net: tcp: add skb drop reasons to tcp state change Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).