Skip to content

Commit 903ab86

Browse files
herbertxdavem330
authored andcommitted
udp: Add lockless transmit path
The UDP transmit path has been running under the socket lock for a long time because of the corking feature. This means that transmitting to the same socket in multiple threads does not scale at all. However, as most users don't actually use corking, the locking can be removed in the common case. This patch creates a lockless fast path where corking is not used. Please note that this does create a slight inaccuracy in the enforcement of socket send buffer limits. In particular, we may exceed the socket limit by up to (number of CPUs) * (packet size) because of the way the limit is computed. As the primary purpose of socket buffers is to indicate congestion, this should not be a great problem for now. Signed-off-by: Herbert Xu <[email protected]> Acked-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f6b9664 commit 903ab86

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

net/ipv4/udp.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
802802
int err, is_udplite = IS_UDPLITE(sk);
803803
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
804804
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
805+
struct sk_buff *skb;
805806

806807
if (len > 0xFFFF)
807808
return -EMSGSIZE;
@@ -816,6 +817,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
816817
ipc.opt = NULL;
817818
ipc.tx_flags = 0;
818819

820+
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
821+
819822
if (up->pending) {
820823
/*
821824
* There are pending frames.
@@ -940,6 +943,17 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
940943
if (!ipc.addr)
941944
daddr = ipc.addr = rt->rt_dst;
942945

946+
/* Lockless fast path for the non-corking case. */
947+
if (!corkreq) {
948+
skb = ip_make_skb(sk, getfrag, msg->msg_iov, ulen,
949+
sizeof(struct udphdr), &ipc, &rt,
950+
msg->msg_flags);
951+
err = PTR_ERR(skb);
952+
if (skb && !IS_ERR(skb))
953+
err = udp_send_skb(skb, daddr, dport);
954+
goto out;
955+
}
956+
943957
lock_sock(sk);
944958
if (unlikely(up->pending)) {
945959
/* The socket is already corked while preparing it. */
@@ -961,7 +975,6 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
961975

962976
do_append_data:
963977
up->len += ulen;
964-
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
965978
err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
966979
sizeof(struct udphdr), &ipc, &rt,
967980
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);

0 commit comments

Comments
 (0)