summaryrefslogtreecommitdiff
path: root/sys/netinet/udp_usrreq.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-05 22:44:21 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-05 22:44:21 +0000
commited14024405c2dd9ccb9d3f95fa4a01ae2f5904f6 (patch)
tree63b95d6f084118592e6f02a14762e1550a127709 /sys/netinet/udp_usrreq.c
parent79049d6f58fa84c13f5e3f3edfeae50d97e14c22 (diff)
Use PCB iterator for raw IP input deliver loop.
Inspired by mvs@ idea of the iterator in the UDP multicast loop, implement the same for raw IP input delivery. This removes an unneccesary rwlock and only uses table mutex. When comparing the inp routing table, address and port, the table lock must be held. So assume that in_pcb_iterator() already has the table mutex and hold it while traversing the list and doing the checks. Release the mutex during mbuf copy, socket buffer append and the upcalls. Adapt the logic for both rip_input() and udp_input(). In rip_input() move the actual work to rip_sbappend(). This can be called without mutex during list traversal and for the final element. OK mvs@
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r--sys/netinet/udp_usrreq.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 729f0991402..d2eaedd860e 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.326 2024/11/05 10:49:23 bluhm Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.327 2024/11/05 22:44:20 bluhm Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -409,6 +409,7 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
#endif
table = &udbtable;
+ mtx_enter(&table->inpt_mtx);
last = inp = NULL;
while ((inp = in_pcb_iterator(table, inp, &iter)) != NULL) {
if (ip6)
@@ -464,12 +465,16 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
if (last != NULL) {
struct mbuf *n;
+ mtx_leave(&table->inpt_mtx);
+
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (n != NULL) {
udp_sbappend(last, n, ip, ip6, iphlen,
uh, &srcsa.sa, 0);
}
in_pcbunref(last);
+
+ mtx_enter(&table->inpt_mtx);
}
last = in_pcbref(inp);
@@ -487,6 +492,7 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
break;
}
}
+ mtx_leave(&table->inpt_mtx);
if (last == NULL) {
/*
@@ -495,7 +501,8 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
* for a broadcast or multicast datgram.)
*/
udpstat_inc(udps_noportbcast);
- goto bad;
+ m_freem(m);
+ return IPPROTO_DONE;
}
udp_sbappend(last, m, ip, ip6, iphlen, uh, &srcsa.sa, 0);