diff options
author | Paolo Abeni <pabeni@redhat.com> | 2018-06-08 05:35:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-08 19:55:15 -0400 |
commit | 6c206b20092a3623184cff9470dba75d21507874 (patch) | |
tree | acc594ed296987e67d25703d1317772239dd3132 | |
parent | 49c2c3f246e2fc3009039e31a826333dcd0283cd (diff) |
udp: fix rx queue len reported by diag and proc interface
After commit 6b229cf77d68 ("udp: add batching to udp_rmem_release()")
the sk_rmem_alloc field does not measure exactly anymore the
receive queue length, because we batch the rmem release. The issue
is really apparent only after commit 0d4a6608f68c ("udp: do rmem bulk
free even if the rx sk queue is empty"): the user space can easily
check for an empty socket with not-0 queue length reported by the 'ss'
tool or the procfs interface.
We need to use a custom UDP helper to report the correct queue length,
taking into account the forward allocation deficit.
Reported-by: trevor.francis@46labs.com
Fixes: 6b229cf77d68 ("UDP: add batching to udp_rmem_release()")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/transp_v6.h | 11 | ||||
-rw-r--r-- | include/net/udp.h | 5 | ||||
-rw-r--r-- | net/ipv4/udp.c | 2 | ||||
-rw-r--r-- | net/ipv4/udp_diag.c | 2 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 6 | ||||
-rw-r--r-- | net/ipv6/udp.c | 3 |
6 files changed, 21 insertions, 8 deletions
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index c4f5caaf3778..f6a3543e5247 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h | |||
@@ -45,8 +45,15 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, | |||
45 | struct flowi6 *fl6, struct ipcm6_cookie *ipc6, | 45 | struct flowi6 *fl6, struct ipcm6_cookie *ipc6, |
46 | struct sockcm_cookie *sockc); | 46 | struct sockcm_cookie *sockc); |
47 | 47 | ||
48 | void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, | 48 | void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, |
49 | __u16 srcp, __u16 destp, int bucket); | 49 | __u16 srcp, __u16 destp, int rqueue, int bucket); |
50 | static inline void | ||
51 | ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, __u16 srcp, | ||
52 | __u16 destp, int bucket) | ||
53 | { | ||
54 | __ip6_dgram_sock_seq_show(seq, sp, srcp, destp, sk_rmem_alloc_get(sp), | ||
55 | bucket); | ||
56 | } | ||
50 | 57 | ||
51 | #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) | 58 | #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) |
52 | 59 | ||
diff --git a/include/net/udp.h b/include/net/udp.h index 7ba0ed252c52..b1ea8b0f5e6a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h | |||
@@ -247,6 +247,11 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, | |||
247 | return htons((((u64) hash * (max - min)) >> 32) + min); | 247 | return htons((((u64) hash * (max - min)) >> 32) + min); |
248 | } | 248 | } |
249 | 249 | ||
250 | static inline int udp_rqueue_get(struct sock *sk) | ||
251 | { | ||
252 | return sk_rmem_alloc_get(sk) - READ_ONCE(udp_sk(sk)->forward_deficit); | ||
253 | } | ||
254 | |||
250 | /* net/ipv4/udp.c */ | 255 | /* net/ipv4/udp.c */ |
251 | void udp_destruct_sock(struct sock *sk); | 256 | void udp_destruct_sock(struct sock *sk); |
252 | void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len); | 257 | void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3365362cac88..9bb27df4dac5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -2772,7 +2772,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, | |||
2772 | " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d", | 2772 | " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d", |
2773 | bucket, src, srcp, dest, destp, sp->sk_state, | 2773 | bucket, src, srcp, dest, destp, sp->sk_state, |
2774 | sk_wmem_alloc_get(sp), | 2774 | sk_wmem_alloc_get(sp), |
2775 | sk_rmem_alloc_get(sp), | 2775 | udp_rqueue_get(sp), |
2776 | 0, 0L, 0, | 2776 | 0, 0L, 0, |
2777 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), | 2777 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), |
2778 | 0, sock_i_ino(sp), | 2778 | 0, sock_i_ino(sp), |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index d0390d844ac8..d9ad986c7b2c 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -163,7 +163,7 @@ static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, | |||
163 | static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, | 163 | static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, |
164 | void *info) | 164 | void *info) |
165 | { | 165 | { |
166 | r->idiag_rqueue = sk_rmem_alloc_get(sk); | 166 | r->idiag_rqueue = udp_rqueue_get(sk); |
167 | r->idiag_wqueue = sk_wmem_alloc_get(sk); | 167 | r->idiag_wqueue = sk_wmem_alloc_get(sk); |
168 | } | 168 | } |
169 | 169 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a02ad100f0d7..2ee08b6a86a4 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -1019,8 +1019,8 @@ exit_f: | |||
1019 | } | 1019 | } |
1020 | EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); | 1020 | EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); |
1021 | 1021 | ||
1022 | void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, | 1022 | void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, |
1023 | __u16 srcp, __u16 destp, int bucket) | 1023 | __u16 srcp, __u16 destp, int rqueue, int bucket) |
1024 | { | 1024 | { |
1025 | const struct in6_addr *dest, *src; | 1025 | const struct in6_addr *dest, *src; |
1026 | 1026 | ||
@@ -1036,7 +1036,7 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, | |||
1036 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | 1036 | dest->s6_addr32[2], dest->s6_addr32[3], destp, |
1037 | sp->sk_state, | 1037 | sp->sk_state, |
1038 | sk_wmem_alloc_get(sp), | 1038 | sk_wmem_alloc_get(sp), |
1039 | sk_rmem_alloc_get(sp), | 1039 | rqueue, |
1040 | 0, 0L, 0, | 1040 | 0, 0L, 0, |
1041 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | 1041 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1042 | 0, | 1042 | 0, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 164afd31aebf..e6645cae403e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1523,7 +1523,8 @@ int udp6_seq_show(struct seq_file *seq, void *v) | |||
1523 | struct inet_sock *inet = inet_sk(v); | 1523 | struct inet_sock *inet = inet_sk(v); |
1524 | __u16 srcp = ntohs(inet->inet_sport); | 1524 | __u16 srcp = ntohs(inet->inet_sport); |
1525 | __u16 destp = ntohs(inet->inet_dport); | 1525 | __u16 destp = ntohs(inet->inet_dport); |
1526 | ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); | 1526 | __ip6_dgram_sock_seq_show(seq, v, srcp, destp, |
1527 | udp_rqueue_get(v), bucket); | ||
1527 | } | 1528 | } |
1528 | return 0; | 1529 | return 0; |
1529 | } | 1530 | } |