Message ID | 0b1deb44b8401042542a112e8235e039fc0a5f65.1694523876.git.jbaron@akamai.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | export SO_REUSEADDR and SO_REUSEPORT via sock_diag | expand |
From: Jason Baron <jbaron@akamai.com> Date: Tue, 12 Sep 2023 10:31:48 -0400 > Add the ability to monitor SO_REUSEADDR and SO_REUSEPORT for an inet > socket. These settings are currently readable via getsockopt(). > We have an app that will sometimes fail to bind() and it's helpful to > understand what other apps are causing the bind() conflict. If bind() fails with -EADDRINUSE, you can find the conflicting sockets with just the failing 2-tuple, no ? Also, BPF iterator and bpf_sk_getsockopt() has the same functionality with more flexibility. (See: sol_socket_sockopt() in net/core/filter.c) > > Signed-off-by: Jason Baron <jbaron@akamai.com> > --- > include/linux/inet_diag.h | 2 ++ > include/uapi/linux/inet_diag.h | 7 +++++++ > net/ipv4/inet_diag.c | 7 +++++++ > 3 files changed, 16 insertions(+) > > diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h > index 84abb30a3fbb..d05a4c26b13d 100644 > --- a/include/linux/inet_diag.h > +++ b/include/linux/inet_diag.h > @@ -77,6 +77,8 @@ static inline size_t inet_diag_msg_attrs_size(void) > #endif > + nla_total_size(sizeof(struct inet_diag_sockopt)) > /* INET_DIAG_SOCKOPT */ > + + nla_total_size(sizeof(struct inet_diag_reuse)) > + /* INET_DIAG_REUSE */ > ; > } > int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, > diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h > index 50655de04c9b..f93eeea1faba 100644 > --- a/include/uapi/linux/inet_diag.h > +++ b/include/uapi/linux/inet_diag.h > @@ -161,6 +161,7 @@ enum { > INET_DIAG_SK_BPF_STORAGES, > INET_DIAG_CGROUP_ID, > INET_DIAG_SOCKOPT, > + INET_DIAG_REUSE, > __INET_DIAG_MAX, > }; > > @@ -201,6 +202,12 @@ struct inet_diag_sockopt { > unused:5; > }; > > +struct inet_diag_reuse { > + __u8 reuse:4, > + reuseport:1, > + unused:3; > +}; > + > /* INET_DIAG_VEGASINFO */ > > struct tcpvegas_info { > diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c > index e13a84433413..d6ebb1e612fc 100644 > --- a/net/ipv4/inet_diag.c > +++ b/net/ipv4/inet_diag.c > @@ -125,6 +125,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, > bool net_admin) > { > const struct inet_sock *inet = inet_sk(sk); > + struct inet_diag_reuse inet_reuse = {}; > struct inet_diag_sockopt inet_sockopt; > > if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown)) > @@ -197,6 +198,12 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, > &inet_sockopt)) > goto errout; > > + inet_reuse.reuse = sk->sk_reuse; > + inet_reuse.reuseport = sk->sk_reuseport; > + if (nla_put(skb, INET_DIAG_REUSE, sizeof(inet_reuse), > + &inet_reuse)) > + goto errout; > + > return 0; > errout: > return 1; > -- > 2.25.1
On 9/12/23 12:26 PM, Kuniyuki Iwashima wrote: > From: Jason Baron <jbaron@akamai.com> > Date: Tue, 12 Sep 2023 10:31:48 -0400 >> Add the ability to monitor SO_REUSEADDR and SO_REUSEPORT for an inet >> socket. These settings are currently readable via getsockopt(). >> We have an app that will sometimes fail to bind() and it's helpful to >> understand what other apps are causing the bind() conflict. > > If bind() fails with -EADDRINUSE, you can find the conflicting sockets > with just the failing 2-tuple, no ? True, yes one can figure out the conflicting socket as is I agree, but then the next step is what went wrong. For so_reuseport, you also need to match uid for it to work. Or if the socket is bound to different devices it is ok, regardless of the reuse/reuseport setting (if I read the code correctly)...And these other factors are currently exposed via sock_diag. So maybe you can deduce these via process of elimination but I think it could be nice to be more explicit about it. > > Also, BPF iterator and bpf_sk_getsockopt() has the same functionality > with more flexibility. (See: sol_socket_sockopt() in net/core/filter.c) > > True, yeah on one hand the fact that reuseport/reuseaddr are exposed via bpf means they are useful and reasonable to expose. On the other hand yeah there's an existing interface if you want to hook up bpf code. In the use case I had, we have a C++ application that wants to print debug information about the conflicting socket when the -EADDRINUSE happens and not necessarily have to invoke a bpf program. Thanks, -Jason >> >> Signed-off-by: Jason Baron <jbaron@akamai.com> >> --- >> include/linux/inet_diag.h | 2 ++ >> include/uapi/linux/inet_diag.h | 7 +++++++ >> net/ipv4/inet_diag.c | 7 +++++++ >> 3 files changed, 16 insertions(+) >> >> diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h >> index 84abb30a3fbb..d05a4c26b13d 100644 >> --- a/include/linux/inet_diag.h >> +++ b/include/linux/inet_diag.h >> @@ -77,6 +77,8 @@ static inline size_t inet_diag_msg_attrs_size(void) >> #endif >> + nla_total_size(sizeof(struct inet_diag_sockopt)) >> /* INET_DIAG_SOCKOPT */ >> + + nla_total_size(sizeof(struct inet_diag_reuse)) >> + /* INET_DIAG_REUSE */ >> ; >> } >> int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, >> diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h >> index 50655de04c9b..f93eeea1faba 100644 >> --- a/include/uapi/linux/inet_diag.h >> +++ b/include/uapi/linux/inet_diag.h >> @@ -161,6 +161,7 @@ enum { >> INET_DIAG_SK_BPF_STORAGES, >> INET_DIAG_CGROUP_ID, >> INET_DIAG_SOCKOPT, >> + INET_DIAG_REUSE, >> __INET_DIAG_MAX, >> }; >> >> @@ -201,6 +202,12 @@ struct inet_diag_sockopt { >> unused:5; >> }; >> >> +struct inet_diag_reuse { >> + __u8 reuse:4, >> + reuseport:1, >> + unused:3; >> +}; >> + >> /* INET_DIAG_VEGASINFO */ >> >> struct tcpvegas_info { >> diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c >> index e13a84433413..d6ebb1e612fc 100644 >> --- a/net/ipv4/inet_diag.c >> +++ b/net/ipv4/inet_diag.c >> @@ -125,6 +125,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, >> bool net_admin) >> { >> const struct inet_sock *inet = inet_sk(sk); >> + struct inet_diag_reuse inet_reuse = {}; >> struct inet_diag_sockopt inet_sockopt; >> >> if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown)) >> @@ -197,6 +198,12 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, >> &inet_sockopt)) >> goto errout; >> >> + inet_reuse.reuse = sk->sk_reuse; >> + inet_reuse.reuseport = sk->sk_reuseport; >> + if (nla_put(skb, INET_DIAG_REUSE, sizeof(inet_reuse), >> + &inet_reuse)) >> + goto errout; >> + >> return 0; >> errout: >> return 1; >> -- >> 2.25.1
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 84abb30a3fbb..d05a4c26b13d 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -77,6 +77,8 @@ static inline size_t inet_diag_msg_attrs_size(void) #endif + nla_total_size(sizeof(struct inet_diag_sockopt)) /* INET_DIAG_SOCKOPT */ + + nla_total_size(sizeof(struct inet_diag_reuse)) + /* INET_DIAG_REUSE */ ; } int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h index 50655de04c9b..f93eeea1faba 100644 --- a/include/uapi/linux/inet_diag.h +++ b/include/uapi/linux/inet_diag.h @@ -161,6 +161,7 @@ enum { INET_DIAG_SK_BPF_STORAGES, INET_DIAG_CGROUP_ID, INET_DIAG_SOCKOPT, + INET_DIAG_REUSE, __INET_DIAG_MAX, }; @@ -201,6 +202,12 @@ struct inet_diag_sockopt { unused:5; }; +struct inet_diag_reuse { + __u8 reuse:4, + reuseport:1, + unused:3; +}; + /* INET_DIAG_VEGASINFO */ struct tcpvegas_info { diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index e13a84433413..d6ebb1e612fc 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -125,6 +125,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, bool net_admin) { const struct inet_sock *inet = inet_sk(sk); + struct inet_diag_reuse inet_reuse = {}; struct inet_diag_sockopt inet_sockopt; if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown)) @@ -197,6 +198,12 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, &inet_sockopt)) goto errout; + inet_reuse.reuse = sk->sk_reuse; + inet_reuse.reuseport = sk->sk_reuseport; + if (nla_put(skb, INET_DIAG_REUSE, sizeof(inet_reuse), + &inet_reuse)) + goto errout; + return 0; errout: return 1;
Add the ability to monitor SO_REUSEADDR and SO_REUSEPORT for an inet socket. These settings are currently readable via getsockopt(). We have an app that will sometimes fail to bind() and it's helpful to understand what other apps are causing the bind() conflict. Signed-off-by: Jason Baron <jbaron@akamai.com> --- include/linux/inet_diag.h | 2 ++ include/uapi/linux/inet_diag.h | 7 +++++++ net/ipv4/inet_diag.c | 7 +++++++ 3 files changed, 16 insertions(+)