aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/ip.h
diff options
context:
space:
mode:
authorDavid Laight <David.Laight@ACULAB.COM>2023-12-06 13:44:20 +0000
committerJakub Kicinski <kuba@kernel.org>2023-12-08 10:44:42 -0800
commitd9f28735af8781d9c8c6c406c2a102090644133d (patch)
treeaff37910520f90b4c192c41a00fbde053c2d01e8 /include/net/ip.h
parent36b0bdb6d330fe0546fc7f97d93e8cfa57421ad9 (diff)
downloadlinux-d9f28735af8781d9c8c6c406c2a102090644133d.tar.gz
Use READ/WRITE_ONCE() for IP local_port_range.
Commit 227b60f5102cd added a seqlock to ensure that the low and high port numbers were always updated together. This is overkill because the two 16bit port numbers can be held in a u32 and read/written in a single instruction. More recently 91d0b78c5177f added support for finer per-socket limits. The user-supplied value is 'high << 16 | low' but they are held separately and the socket options protected by the socket lock. Use a u32 containing 'high << 16 | low' for both the 'net' and 'sk' fields and use READ_ONCE()/WRITE_ONCE() to ensure both values are always updated together. Change (the now trival) inet_get_local_port_range() to a static inline to optimise the calling code. (In particular avoiding returning integers by reference.) Signed-off-by: David Laight <david.laight@aculab.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Acked-by: Mat Martineau <martineau@kernel.org> Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://lore.kernel.org/r/4e505d4198e946a8be03fb1b4c3072b0@AcuMS.aculab.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include/net/ip.h')
-rw-r--r--include/net/ip.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 1fc4c8d69e333e..b31be912489af8 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -349,7 +349,13 @@ static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_o
} \
}
-void inet_get_local_port_range(const struct net *net, int *low, int *high);
+static inline void inet_get_local_port_range(const struct net *net, int *low, int *high)
+{
+ u32 range = READ_ONCE(net->ipv4.ip_local_ports.range);
+
+ *low = range & 0xffff;
+ *high = range >> 16;
+}
void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high);
#ifdef CONFIG_SYSCTL