diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-11-05 22:44:21 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-11-05 22:44:21 +0000 |
commit | ed14024405c2dd9ccb9d3f95fa4a01ae2f5904f6 (patch) | |
tree | 63b95d6f084118592e6f02a14762e1550a127709 /sys/netinet/udp_usrreq.c | |
parent | 79049d6f58fa84c13f5e3f3edfeae50d97e14c22 (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.c | 11 |
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); |