summaryrefslogtreecommitdiffstats
path: root/sys/netinet/udp_usrreq.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2004-06-16 05:41:00 +0000
committerbms <bms@FreeBSD.org>2004-06-16 05:41:00 +0000
commitdeb499d51d32f9cec3bfdb35cc09c01a9c33681c (patch)
treebf592caed9fb0bab85e1c90f9c915df5e15b9702 /sys/netinet/udp_usrreq.c
parent4902310dd73041506db8a950229fba9e53fec5a7 (diff)
downloadFreeBSD-src-deb499d51d32f9cec3bfdb35cc09c01a9c33681c.zip
FreeBSD-src-deb499d51d32f9cec3bfdb35cc09c01a9c33681c.tar.gz
Disconnect a temporarily-connected UDP socket in out-of-mbufs case. This
fixes the problem of UDP sockets getting wedged in a connected state (and bound to their destination) under heavy load. Temporary bind/connect should probably be deleted in future as an optimization, as described in "A Faster UDP" [Partridge/Pink 1993]. Notes: - INP_LOCK() is already held in udp_output(). The connection is in effect happening at a layer lower than the socket layer, therefore in theory socket locking should not be needed. - Inlining the in_pcbdisconnect() operation buys us nothing (in the case of the current state of the code), as laddr is not part of the inpcb hash or the udbinfo hash. Therefore there should be no need to rehash after restoring laddr in the error case (this was a concern of the original author of the patch). PR: kern/41765 Requested by: gnn Submitted by: Jinmei Tatuya (with cleanups) Tested by: spray(8)
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r--sys/netinet/udp_usrreq.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 9c541db..47d12f8 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -837,7 +837,7 @@ udp_output(inp, m, addr, control, td)
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
if (m == 0) {
error = ENOBUFS;
- goto release;
+ goto disconnect;
}
/*
@@ -879,6 +879,12 @@ udp_output(inp, m, addr, control, td)
inp->inp_moptions, inp);
return (error);
+disconnect:
+ if (addr) {
+ in_pcbdisconnect(inp);
+ inp->inp_laddr = laddr;
+ }
+
release:
m_freem(m);
return (error);
OpenPOWER on IntegriCloud