Commit 81b36803 authored by Eric Dumazet's avatar Eric Dumazet Committed by Paolo Abeni

udp: introduce udp->udp_flags

According to syzbot, it is time to use proper atomic flags
for various UDP flags.

Add udp_flags field, and convert udp->corkflag to first
bit in it.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 486e6ca6
...@@ -32,14 +32,20 @@ static inline u32 udp_hashfn(const struct net *net, u32 num, u32 mask) ...@@ -32,14 +32,20 @@ static inline u32 udp_hashfn(const struct net *net, u32 num, u32 mask)
return (num + net_hash_mix(net)) & mask; return (num + net_hash_mix(net)) & mask;
} }
enum {
UDP_FLAGS_CORK, /* Cork is required */
};
struct udp_sock { struct udp_sock {
/* inet_sock has to be the first member */ /* inet_sock has to be the first member */
struct inet_sock inet; struct inet_sock inet;
#define udp_port_hash inet.sk.__sk_common.skc_u16hashes[0] #define udp_port_hash inet.sk.__sk_common.skc_u16hashes[0]
#define udp_portaddr_hash inet.sk.__sk_common.skc_u16hashes[1] #define udp_portaddr_hash inet.sk.__sk_common.skc_u16hashes[1]
#define udp_portaddr_node inet.sk.__sk_common.skc_portaddr_node #define udp_portaddr_node inet.sk.__sk_common.skc_portaddr_node
unsigned long udp_flags;
int pending; /* Any pending frames ? */ int pending; /* Any pending frames ? */
unsigned int corkflag; /* Cork is required */
__u8 encap_type; /* Is this an Encapsulation socket? */ __u8 encap_type; /* Is this an Encapsulation socket? */
unsigned char no_check6_tx:1,/* Send zero UDP6 checksums on TX? */ unsigned char no_check6_tx:1,/* Send zero UDP6 checksums on TX? */
no_check6_rx:1,/* Allow zero UDP6 checksums on RX? */ no_check6_rx:1,/* Allow zero UDP6 checksums on RX? */
...@@ -51,6 +57,11 @@ struct udp_sock { ...@@ -51,6 +57,11 @@ struct udp_sock {
gro_enabled:1, /* Request GRO aggregation */ gro_enabled:1, /* Request GRO aggregation */
accept_udp_l4:1, accept_udp_l4:1,
accept_udp_fraglist:1; accept_udp_fraglist:1;
/* indicator bits used by pcflag: */
#define UDPLITE_BIT 0x1 /* set by udplite proto init function */
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
__u8 pcflag; /* marks socket as UDP-Lite if > 0 */
/* /*
* Following member retains the information to create a UDP header * Following member retains the information to create a UDP header
* when the socket is uncorked. * when the socket is uncorked.
...@@ -62,12 +73,6 @@ struct udp_sock { ...@@ -62,12 +73,6 @@ struct udp_sock {
*/ */
__u16 pcslen; __u16 pcslen;
__u16 pcrlen; __u16 pcrlen;
/* indicator bits used by pcflag: */
#define UDPLITE_BIT 0x1 /* set by udplite proto init function */
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
__u8 pcflag; /* marks socket as UDP-Lite if > 0 */
__u8 unused[3];
/* /*
* For encapsulation sockets. * For encapsulation sockets.
*/ */
...@@ -95,6 +100,15 @@ struct udp_sock { ...@@ -95,6 +100,15 @@ struct udp_sock {
int forward_threshold; int forward_threshold;
}; };
#define udp_test_bit(nr, sk) \
test_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
#define udp_set_bit(nr, sk) \
set_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
#define udp_clear_bit(nr, sk) \
clear_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
#define udp_assign_bit(nr, sk, val) \
assign_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags, val)
#define UDP_MAX_SEGMENTS (1 << 6UL) #define UDP_MAX_SEGMENTS (1 << 6UL)
#define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk) #define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk)
......
...@@ -1051,7 +1051,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ...@@ -1051,7 +1051,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
u8 tos, scope; u8 tos, scope;
__be16 dport; __be16 dport;
int err, is_udplite = IS_UDPLITE(sk); int err, is_udplite = IS_UDPLITE(sk);
int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE; int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
struct sk_buff *skb; struct sk_buff *skb;
struct ip_options_data opt_copy; struct ip_options_data opt_copy;
...@@ -1315,11 +1315,11 @@ void udp_splice_eof(struct socket *sock) ...@@ -1315,11 +1315,11 @@ void udp_splice_eof(struct socket *sock)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct udp_sock *up = udp_sk(sk); struct udp_sock *up = udp_sk(sk);
if (!up->pending || READ_ONCE(up->corkflag)) if (!up->pending || udp_test_bit(CORK, sk))
return; return;
lock_sock(sk); lock_sock(sk);
if (up->pending && !READ_ONCE(up->corkflag)) if (up->pending && !udp_test_bit(CORK, sk))
udp_push_pending_frames(sk); udp_push_pending_frames(sk);
release_sock(sk); release_sock(sk);
} }
...@@ -2658,9 +2658,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, ...@@ -2658,9 +2658,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
switch (optname) { switch (optname) {
case UDP_CORK: case UDP_CORK:
if (val != 0) { if (val != 0) {
WRITE_ONCE(up->corkflag, 1); udp_set_bit(CORK, sk);
} else { } else {
WRITE_ONCE(up->corkflag, 0); udp_clear_bit(CORK, sk);
lock_sock(sk); lock_sock(sk);
push_pending_frames(sk); push_pending_frames(sk);
release_sock(sk); release_sock(sk);
...@@ -2783,7 +2783,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, ...@@ -2783,7 +2783,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
switch (optname) { switch (optname) {
case UDP_CORK: case UDP_CORK:
val = READ_ONCE(up->corkflag); val = udp_test_bit(CORK, sk);
break; break;
case UDP_ENCAP: case UDP_ENCAP:
......
...@@ -1332,7 +1332,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ...@@ -1332,7 +1332,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
int addr_len = msg->msg_namelen; int addr_len = msg->msg_namelen;
bool connected = false; bool connected = false;
int ulen = len; int ulen = len;
int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE; int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
int err; int err;
int is_udplite = IS_UDPLITE(sk); int is_udplite = IS_UDPLITE(sk);
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
...@@ -1644,11 +1644,11 @@ static void udpv6_splice_eof(struct socket *sock) ...@@ -1644,11 +1644,11 @@ static void udpv6_splice_eof(struct socket *sock)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct udp_sock *up = udp_sk(sk); struct udp_sock *up = udp_sk(sk);
if (!up->pending || READ_ONCE(up->corkflag)) if (!up->pending || udp_test_bit(CORK, sk))
return; return;
lock_sock(sk); lock_sock(sk);
if (up->pending && !READ_ONCE(up->corkflag)) if (up->pending && !udp_test_bit(CORK, sk))
udp_v6_push_pending_frames(sk); udp_v6_push_pending_frames(sk);
release_sock(sk); release_sock(sk);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment