diff mbox series

[mptcp-next,3/4] mptcp: listen diag dump support

Message ID 20220324135753.25182-4-fw@strlen.de (mailing list archive)
State Superseded, archived
Headers show
Series mptcp: listen dump support | expand

Checks

Context Check Description
matttbe/build success Build and static analysis OK
matttbe/checkpatch success total: 0 errors, 0 warnings, 0 checks, 79 lines checked

Commit Message

Florian Westphal March 24, 2022, 1:57 p.m. UTC
makes 'ss -Ml' show mptcp listen sockets.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/mptcp/mptcp_diag.c | 67 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

Comments

Paolo Abeni March 24, 2022, 4:52 p.m. UTC | #1
On Thu, 2022-03-24 at 14:57 +0100, Florian Westphal wrote:
> makes 'ss -Ml' show mptcp listen sockets.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  net/mptcp/mptcp_diag.c | 67 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c
> index c4992eeb67d8..6a6dfc7eac33 100644
> --- a/net/mptcp/mptcp_diag.c
> +++ b/net/mptcp/mptcp_diag.c
> @@ -69,6 +69,8 @@ static int mptcp_diag_dump_one(struct netlink_callback *cb,
>  struct mptcp_diag_ctx {
>  	long s_slot;
>  	long s_num;
> +	unsigned int l_slot;
> +	unsigned int l_num;
>  };
>  
>  static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
> @@ -114,6 +116,71 @@ static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
>  		}
>  		cond_resched();
>  	}
> +
> +	if (r->idiag_states & TCPF_LISTEN) {
> +		int i;

perhaps here we need to add something alike:

		if (r->id.idiag_dport)
			return;

???

Also, what about moving the following chunk in separate helper -
mptcp_diag_dump_listener()?

Thanks!

Paolo
Florian Westphal March 24, 2022, 5:07 p.m. UTC | #2
Paolo Abeni <pabeni@redhat.com> wrote:
> On Thu, 2022-03-24 at 14:57 +0100, Florian Westphal wrote:
> > makes 'ss -Ml' show mptcp listen sockets.
> > 
> > Signed-off-by: Florian Westphal <fw@strlen.de>
> > ---
> >  net/mptcp/mptcp_diag.c | 67 ++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 67 insertions(+)
> > 
> > diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c
> > index c4992eeb67d8..6a6dfc7eac33 100644
> > --- a/net/mptcp/mptcp_diag.c
> > +++ b/net/mptcp/mptcp_diag.c
> > @@ -69,6 +69,8 @@ static int mptcp_diag_dump_one(struct netlink_callback *cb,
> >  struct mptcp_diag_ctx {
> >  	long s_slot;
> >  	long s_num;
> > +	unsigned int l_slot;
> > +	unsigned int l_num;
> >  };
> >  
> >  static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
> > @@ -114,6 +116,71 @@ static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
> >  		}
> >  		cond_resched();
> >  	}
> > +
> > +	if (r->idiag_states & TCPF_LISTEN) {
> > +		int i;
> 
> perhaps here we need to add something alike:
> 
> 		if (r->id.idiag_dport)
> 			return;
[..]

> Also, what about moving the following chunk in separate helper -
> mptcp_diag_dump_listener()?
Changed to:

if ((r->idiag_states & TCPF_LISTEN) && r->id.idiag_dport == 0)
            mptcp_diag_dump_listeners(skb, cb, r, net_admin);
diff mbox series

Patch

diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c
index c4992eeb67d8..6a6dfc7eac33 100644
--- a/net/mptcp/mptcp_diag.c
+++ b/net/mptcp/mptcp_diag.c
@@ -69,6 +69,8 @@  static int mptcp_diag_dump_one(struct netlink_callback *cb,
 struct mptcp_diag_ctx {
 	long s_slot;
 	long s_num;
+	unsigned int l_slot;
+	unsigned int l_num;
 };
 
 static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
@@ -114,6 +116,71 @@  static void mptcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
 		}
 		cond_resched();
 	}
+
+	if (r->idiag_states & TCPF_LISTEN) {
+		int i;
+
+		for (i = diag_ctx->l_slot; i < INET_LHTABLE_SIZE; i++) {
+			struct inet_listen_hashbucket *ilb;
+			struct hlist_nulls_node *node;
+			struct sock *sk;
+			int num = 0;
+
+			ilb = &tcp_hashinfo.listening_hash[i];
+
+			rcu_read_lock();
+			spin_lock(&ilb->lock);
+			sk_nulls_for_each(sk, node, &ilb->nulls_head) {
+				const struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(sk);
+				struct inet_sock *inet = inet_sk(sk);
+				int ret;
+
+				if (num < diag_ctx->l_num)
+					goto next_listen;
+
+				if (!ctx || strcmp(inet_csk(sk)->icsk_ulp_ops->name, "mptcp"))
+					goto next_listen;
+
+				sk = ctx->conn;
+				if (!sk || !net_eq(sock_net(sk), net))
+					goto next_listen;
+
+				if (r->sdiag_family != AF_UNSPEC &&
+				    sk->sk_family != r->sdiag_family)
+					goto next_listen;
+
+				if (r->id.idiag_sport != inet->inet_sport &&
+				    r->id.idiag_sport)
+					goto next_listen;
+
+				if (!refcount_inc_not_zero(&sk->sk_refcnt))
+					goto next_listen;
+
+				ret = sk_diag_dump(sk, skb, cb, r, bc, net_admin);
+				sock_put(sk);
+
+				if (ret < 0) {
+					spin_unlock(&ilb->lock);
+					rcu_read_unlock();
+					diag_ctx->l_slot = i;
+					diag_ctx->l_num = num;
+					return;
+				}
+				diag_ctx->l_num = num + 1;
+				num = 0;
+next_listen:
+				++num;
+			}
+			spin_unlock(&ilb->lock);
+			rcu_read_unlock();
+
+			cond_resched();
+			diag_ctx->l_num = 0;
+		}
+
+		diag_ctx->l_num = 0;
+		diag_ctx->l_slot = i;
+	}
 }
 
 static void mptcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,