1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 30 */ 31 32#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 30 */ 31 32#include <sys/cdefs.h>
|
33__FBSDID("$FreeBSD: head/sys/kern/uipc_sockbuf.c 169236 2007-05-03 14:42:42Z rwatson $");
| 33__FBSDID("$FreeBSD: head/sys/kern/uipc_sockbuf.c 169624 2007-05-16 20:41:08Z rwatson $");
|
34 35#include "opt_param.h" 36 37#include <sys/param.h> 38#include <sys/aio.h> /* for aio_swake proto */ 39#include <sys/kernel.h> 40#include <sys/lock.h> 41#include <sys/mbuf.h> 42#include <sys/mutex.h> 43#include <sys/proc.h> 44#include <sys/protosw.h> 45#include <sys/resourcevar.h> 46#include <sys/signalvar.h> 47#include <sys/socket.h> 48#include <sys/socketvar.h> 49#include <sys/sx.h> 50#include <sys/sysctl.h> 51 52/* 53 * Function pointer set by the AIO routines so that the socket buffer code 54 * can call back into the AIO module if it is loaded. 55 */ 56void (*aio_swake)(struct socket *, struct sockbuf *); 57 58/* 59 * Primitive routines for operating on socket buffers 60 */ 61 62u_long sb_max = SB_MAX; 63static u_long sb_max_adj = 64 SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */ 65 66static u_long sb_efficiency = 8; /* parameter for sbreserve() */ 67 68static void sbdrop_internal(struct sockbuf *sb, int len); 69static void sbflush_internal(struct sockbuf *sb); 70static void sbrelease_internal(struct sockbuf *sb, struct socket *so); 71 72/* 73 * Socantsendmore indicates that no more data will be sent on the socket; it 74 * would normally be applied to a socket when the user informs the system 75 * that no more data is to be sent, by the protocol code (in case 76 * PRU_SHUTDOWN). Socantrcvmore indicates that no more data will be 77 * received, and will normally be applied to the socket by a protocol when it 78 * detects that the peer will send no more data. Data queued for reading in 79 * the socket may yet be read. 80 */ 81void 82socantsendmore_locked(struct socket *so) 83{ 84 85 SOCKBUF_LOCK_ASSERT(&so->so_snd); 86 87 so->so_snd.sb_state |= SBS_CANTSENDMORE; 88 sowwakeup_locked(so); 89 mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); 90} 91 92void 93socantsendmore(struct socket *so) 94{ 95 96 SOCKBUF_LOCK(&so->so_snd); 97 socantsendmore_locked(so); 98 mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); 99} 100 101void 102socantrcvmore_locked(struct socket *so) 103{ 104 105 SOCKBUF_LOCK_ASSERT(&so->so_rcv); 106 107 so->so_rcv.sb_state |= SBS_CANTRCVMORE; 108 sorwakeup_locked(so); 109 mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); 110} 111 112void 113socantrcvmore(struct socket *so) 114{ 115 116 SOCKBUF_LOCK(&so->so_rcv); 117 socantrcvmore_locked(so); 118 mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); 119} 120 121/* 122 * Wait for data to arrive at/drain from a socket buffer. 123 */ 124int 125sbwait(struct sockbuf *sb) 126{ 127 128 SOCKBUF_LOCK_ASSERT(sb); 129 130 sb->sb_flags |= SB_WAIT; 131 return (msleep(&sb->sb_cc, &sb->sb_mtx, 132 (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", 133 sb->sb_timeo)); 134} 135 136int 137sblock(struct sockbuf *sb, int flags) 138{ 139 140 if (flags == M_WAITOK) { 141 sx_xlock(&sb->sb_sx); 142 return (0); 143 } else { 144 if (sx_try_xlock(&sb->sb_sx) == 0) 145 return (EWOULDBLOCK); 146 return (0); 147 } 148} 149 150void 151sbunlock(struct sockbuf *sb) 152{ 153 154 sx_xunlock(&sb->sb_sx); 155} 156 157/* 158 * Wakeup processes waiting on a socket buffer. Do asynchronous notification 159 * via SIGIO if the socket has the SS_ASYNC flag set. 160 * 161 * Called with the socket buffer lock held; will release the lock by the end 162 * of the function. This allows the caller to acquire the socket buffer lock 163 * while testing for the need for various sorts of wakeup and hold it through 164 * to the point where it's no longer required. We currently hold the lock 165 * through calls out to other subsystems (with the exception of kqueue), and 166 * then release it to avoid lock order issues. It's not clear that's 167 * correct. 168 */ 169void 170sowakeup(struct socket *so, struct sockbuf *sb) 171{ 172 173 SOCKBUF_LOCK_ASSERT(sb); 174 175 selwakeuppri(&sb->sb_sel, PSOCK); 176 sb->sb_flags &= ~SB_SEL; 177 if (sb->sb_flags & SB_WAIT) { 178 sb->sb_flags &= ~SB_WAIT; 179 wakeup(&sb->sb_cc); 180 } 181 KNOTE_LOCKED(&sb->sb_sel.si_note, 0); 182 SOCKBUF_UNLOCK(sb); 183 if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) 184 pgsigio(&so->so_sigio, SIGIO, 0); 185 if (sb->sb_flags & SB_UPCALL) 186 (*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT); 187 if (sb->sb_flags & SB_AIO) 188 aio_swake(so, sb); 189 mtx_assert(SOCKBUF_MTX(sb), MA_NOTOWNED); 190} 191 192/* 193 * Socket buffer (struct sockbuf) utility routines. 194 * 195 * Each socket contains two socket buffers: one for sending data and one for 196 * receiving data. Each buffer contains a queue of mbufs, information about 197 * the number of mbufs and amount of data in the queue, and other fields 198 * allowing select() statements and notification on data availability to be 199 * implemented. 200 * 201 * Data stored in a socket buffer is maintained as a list of records. Each 202 * record is a list of mbufs chained together with the m_next field. Records 203 * are chained together with the m_nextpkt field. The upper level routine 204 * soreceive() expects the following conventions to be observed when placing 205 * information in the receive buffer: 206 * 207 * 1. If the protocol requires each message be preceded by the sender's name, 208 * then a record containing that name must be present before any 209 * associated data (mbuf's must be of type MT_SONAME). 210 * 2. If the protocol supports the exchange of ``access rights'' (really just 211 * additional data associated with the message), and there are ``rights'' 212 * to be received, then a record containing this data should be present 213 * (mbuf's must be of type MT_RIGHTS). 214 * 3. If a name or rights record exists, then it must be followed by a data 215 * record, perhaps of zero length. 216 * 217 * Before using a new socket structure it is first necessary to reserve 218 * buffer space to the socket, by calling sbreserve(). This should commit 219 * some of the available buffer space in the system buffer pool for the 220 * socket (currently, it does nothing but enforce limits). The space should 221 * be released by calling sbrelease() when the socket is destroyed. 222 */ 223int 224soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 225{ 226 struct thread *td = curthread; 227 228 SOCKBUF_LOCK(&so->so_snd); 229 SOCKBUF_LOCK(&so->so_rcv); 230 if (sbreserve_locked(&so->so_snd, sndcc, so, td) == 0) 231 goto bad; 232 if (sbreserve_locked(&so->so_rcv, rcvcc, so, td) == 0) 233 goto bad2; 234 if (so->so_rcv.sb_lowat == 0) 235 so->so_rcv.sb_lowat = 1; 236 if (so->so_snd.sb_lowat == 0) 237 so->so_snd.sb_lowat = MCLBYTES; 238 if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 239 so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 240 SOCKBUF_UNLOCK(&so->so_rcv); 241 SOCKBUF_UNLOCK(&so->so_snd); 242 return (0); 243bad2: 244 sbrelease_locked(&so->so_snd, so); 245bad: 246 SOCKBUF_UNLOCK(&so->so_rcv); 247 SOCKBUF_UNLOCK(&so->so_snd); 248 return (ENOBUFS); 249} 250 251static int 252sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS) 253{ 254 int error = 0; 255 u_long tmp_sb_max = sb_max; 256 257 error = sysctl_handle_long(oidp, &tmp_sb_max, arg2, req); 258 if (error || !req->newptr) 259 return (error); 260 if (tmp_sb_max < MSIZE + MCLBYTES) 261 return (EINVAL); 262 sb_max = tmp_sb_max; 263 sb_max_adj = (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES); 264 return (0); 265} 266 267/* 268 * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't 269 * become limiting if buffering efficiency is near the normal case. 270 */ 271int 272sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, 273 struct thread *td) 274{ 275 rlim_t sbsize_limit; 276 277 SOCKBUF_LOCK_ASSERT(sb); 278 279 /* 280 * td will only be NULL when we're in an interrupt (e.g. in 281 * tcp_input()). 282 * 283 * XXXRW: This comment needs updating, as might the code. 284 */ 285 if (cc > sb_max_adj) 286 return (0); 287 if (td != NULL) { 288 PROC_LOCK(td->td_proc); 289 sbsize_limit = lim_cur(td->td_proc, RLIMIT_SBSIZE); 290 PROC_UNLOCK(td->td_proc); 291 } else 292 sbsize_limit = RLIM_INFINITY; 293 if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, 294 sbsize_limit)) 295 return (0); 296 sb->sb_mbmax = min(cc * sb_efficiency, sb_max); 297 if (sb->sb_lowat > sb->sb_hiwat) 298 sb->sb_lowat = sb->sb_hiwat; 299 return (1); 300} 301 302int 303sbreserve(struct sockbuf *sb, u_long cc, struct socket *so, 304 struct thread *td) 305{ 306 int error; 307 308 SOCKBUF_LOCK(sb); 309 error = sbreserve_locked(sb, cc, so, td); 310 SOCKBUF_UNLOCK(sb); 311 return (error); 312} 313 314/* 315 * Free mbufs held by a socket, and reserved mbuf space. 316 */ 317static void 318sbrelease_internal(struct sockbuf *sb, struct socket *so) 319{ 320 321 sbflush_internal(sb); 322 (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, 323 RLIM_INFINITY); 324 sb->sb_mbmax = 0; 325} 326 327void 328sbrelease_locked(struct sockbuf *sb, struct socket *so) 329{ 330 331 SOCKBUF_LOCK_ASSERT(sb); 332 333 sbrelease_internal(sb, so); 334} 335 336void 337sbrelease(struct sockbuf *sb, struct socket *so) 338{ 339 340 SOCKBUF_LOCK(sb); 341 sbrelease_locked(sb, so); 342 SOCKBUF_UNLOCK(sb); 343} 344 345void 346sbdestroy(struct sockbuf *sb, struct socket *so) 347{ 348 349 sbrelease_internal(sb, so); 350} 351
| 34 35#include "opt_param.h" 36 37#include <sys/param.h> 38#include <sys/aio.h> /* for aio_swake proto */ 39#include <sys/kernel.h> 40#include <sys/lock.h> 41#include <sys/mbuf.h> 42#include <sys/mutex.h> 43#include <sys/proc.h> 44#include <sys/protosw.h> 45#include <sys/resourcevar.h> 46#include <sys/signalvar.h> 47#include <sys/socket.h> 48#include <sys/socketvar.h> 49#include <sys/sx.h> 50#include <sys/sysctl.h> 51 52/* 53 * Function pointer set by the AIO routines so that the socket buffer code 54 * can call back into the AIO module if it is loaded. 55 */ 56void (*aio_swake)(struct socket *, struct sockbuf *); 57 58/* 59 * Primitive routines for operating on socket buffers 60 */ 61 62u_long sb_max = SB_MAX; 63static u_long sb_max_adj = 64 SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */ 65 66static u_long sb_efficiency = 8; /* parameter for sbreserve() */ 67 68static void sbdrop_internal(struct sockbuf *sb, int len); 69static void sbflush_internal(struct sockbuf *sb); 70static void sbrelease_internal(struct sockbuf *sb, struct socket *so); 71 72/* 73 * Socantsendmore indicates that no more data will be sent on the socket; it 74 * would normally be applied to a socket when the user informs the system 75 * that no more data is to be sent, by the protocol code (in case 76 * PRU_SHUTDOWN). Socantrcvmore indicates that no more data will be 77 * received, and will normally be applied to the socket by a protocol when it 78 * detects that the peer will send no more data. Data queued for reading in 79 * the socket may yet be read. 80 */ 81void 82socantsendmore_locked(struct socket *so) 83{ 84 85 SOCKBUF_LOCK_ASSERT(&so->so_snd); 86 87 so->so_snd.sb_state |= SBS_CANTSENDMORE; 88 sowwakeup_locked(so); 89 mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); 90} 91 92void 93socantsendmore(struct socket *so) 94{ 95 96 SOCKBUF_LOCK(&so->so_snd); 97 socantsendmore_locked(so); 98 mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); 99} 100 101void 102socantrcvmore_locked(struct socket *so) 103{ 104 105 SOCKBUF_LOCK_ASSERT(&so->so_rcv); 106 107 so->so_rcv.sb_state |= SBS_CANTRCVMORE; 108 sorwakeup_locked(so); 109 mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); 110} 111 112void 113socantrcvmore(struct socket *so) 114{ 115 116 SOCKBUF_LOCK(&so->so_rcv); 117 socantrcvmore_locked(so); 118 mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); 119} 120 121/* 122 * Wait for data to arrive at/drain from a socket buffer. 123 */ 124int 125sbwait(struct sockbuf *sb) 126{ 127 128 SOCKBUF_LOCK_ASSERT(sb); 129 130 sb->sb_flags |= SB_WAIT; 131 return (msleep(&sb->sb_cc, &sb->sb_mtx, 132 (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", 133 sb->sb_timeo)); 134} 135 136int 137sblock(struct sockbuf *sb, int flags) 138{ 139 140 if (flags == M_WAITOK) { 141 sx_xlock(&sb->sb_sx); 142 return (0); 143 } else { 144 if (sx_try_xlock(&sb->sb_sx) == 0) 145 return (EWOULDBLOCK); 146 return (0); 147 } 148} 149 150void 151sbunlock(struct sockbuf *sb) 152{ 153 154 sx_xunlock(&sb->sb_sx); 155} 156 157/* 158 * Wakeup processes waiting on a socket buffer. Do asynchronous notification 159 * via SIGIO if the socket has the SS_ASYNC flag set. 160 * 161 * Called with the socket buffer lock held; will release the lock by the end 162 * of the function. This allows the caller to acquire the socket buffer lock 163 * while testing for the need for various sorts of wakeup and hold it through 164 * to the point where it's no longer required. We currently hold the lock 165 * through calls out to other subsystems (with the exception of kqueue), and 166 * then release it to avoid lock order issues. It's not clear that's 167 * correct. 168 */ 169void 170sowakeup(struct socket *so, struct sockbuf *sb) 171{ 172 173 SOCKBUF_LOCK_ASSERT(sb); 174 175 selwakeuppri(&sb->sb_sel, PSOCK); 176 sb->sb_flags &= ~SB_SEL; 177 if (sb->sb_flags & SB_WAIT) { 178 sb->sb_flags &= ~SB_WAIT; 179 wakeup(&sb->sb_cc); 180 } 181 KNOTE_LOCKED(&sb->sb_sel.si_note, 0); 182 SOCKBUF_UNLOCK(sb); 183 if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) 184 pgsigio(&so->so_sigio, SIGIO, 0); 185 if (sb->sb_flags & SB_UPCALL) 186 (*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT); 187 if (sb->sb_flags & SB_AIO) 188 aio_swake(so, sb); 189 mtx_assert(SOCKBUF_MTX(sb), MA_NOTOWNED); 190} 191 192/* 193 * Socket buffer (struct sockbuf) utility routines. 194 * 195 * Each socket contains two socket buffers: one for sending data and one for 196 * receiving data. Each buffer contains a queue of mbufs, information about 197 * the number of mbufs and amount of data in the queue, and other fields 198 * allowing select() statements and notification on data availability to be 199 * implemented. 200 * 201 * Data stored in a socket buffer is maintained as a list of records. Each 202 * record is a list of mbufs chained together with the m_next field. Records 203 * are chained together with the m_nextpkt field. The upper level routine 204 * soreceive() expects the following conventions to be observed when placing 205 * information in the receive buffer: 206 * 207 * 1. If the protocol requires each message be preceded by the sender's name, 208 * then a record containing that name must be present before any 209 * associated data (mbuf's must be of type MT_SONAME). 210 * 2. If the protocol supports the exchange of ``access rights'' (really just 211 * additional data associated with the message), and there are ``rights'' 212 * to be received, then a record containing this data should be present 213 * (mbuf's must be of type MT_RIGHTS). 214 * 3. If a name or rights record exists, then it must be followed by a data 215 * record, perhaps of zero length. 216 * 217 * Before using a new socket structure it is first necessary to reserve 218 * buffer space to the socket, by calling sbreserve(). This should commit 219 * some of the available buffer space in the system buffer pool for the 220 * socket (currently, it does nothing but enforce limits). The space should 221 * be released by calling sbrelease() when the socket is destroyed. 222 */ 223int 224soreserve(struct socket *so, u_long sndcc, u_long rcvcc) 225{ 226 struct thread *td = curthread; 227 228 SOCKBUF_LOCK(&so->so_snd); 229 SOCKBUF_LOCK(&so->so_rcv); 230 if (sbreserve_locked(&so->so_snd, sndcc, so, td) == 0) 231 goto bad; 232 if (sbreserve_locked(&so->so_rcv, rcvcc, so, td) == 0) 233 goto bad2; 234 if (so->so_rcv.sb_lowat == 0) 235 so->so_rcv.sb_lowat = 1; 236 if (so->so_snd.sb_lowat == 0) 237 so->so_snd.sb_lowat = MCLBYTES; 238 if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) 239 so->so_snd.sb_lowat = so->so_snd.sb_hiwat; 240 SOCKBUF_UNLOCK(&so->so_rcv); 241 SOCKBUF_UNLOCK(&so->so_snd); 242 return (0); 243bad2: 244 sbrelease_locked(&so->so_snd, so); 245bad: 246 SOCKBUF_UNLOCK(&so->so_rcv); 247 SOCKBUF_UNLOCK(&so->so_snd); 248 return (ENOBUFS); 249} 250 251static int 252sysctl_handle_sb_max(SYSCTL_HANDLER_ARGS) 253{ 254 int error = 0; 255 u_long tmp_sb_max = sb_max; 256 257 error = sysctl_handle_long(oidp, &tmp_sb_max, arg2, req); 258 if (error || !req->newptr) 259 return (error); 260 if (tmp_sb_max < MSIZE + MCLBYTES) 261 return (EINVAL); 262 sb_max = tmp_sb_max; 263 sb_max_adj = (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES); 264 return (0); 265} 266 267/* 268 * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't 269 * become limiting if buffering efficiency is near the normal case. 270 */ 271int 272sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, 273 struct thread *td) 274{ 275 rlim_t sbsize_limit; 276 277 SOCKBUF_LOCK_ASSERT(sb); 278 279 /* 280 * td will only be NULL when we're in an interrupt (e.g. in 281 * tcp_input()). 282 * 283 * XXXRW: This comment needs updating, as might the code. 284 */ 285 if (cc > sb_max_adj) 286 return (0); 287 if (td != NULL) { 288 PROC_LOCK(td->td_proc); 289 sbsize_limit = lim_cur(td->td_proc, RLIMIT_SBSIZE); 290 PROC_UNLOCK(td->td_proc); 291 } else 292 sbsize_limit = RLIM_INFINITY; 293 if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, 294 sbsize_limit)) 295 return (0); 296 sb->sb_mbmax = min(cc * sb_efficiency, sb_max); 297 if (sb->sb_lowat > sb->sb_hiwat) 298 sb->sb_lowat = sb->sb_hiwat; 299 return (1); 300} 301 302int 303sbreserve(struct sockbuf *sb, u_long cc, struct socket *so, 304 struct thread *td) 305{ 306 int error; 307 308 SOCKBUF_LOCK(sb); 309 error = sbreserve_locked(sb, cc, so, td); 310 SOCKBUF_UNLOCK(sb); 311 return (error); 312} 313 314/* 315 * Free mbufs held by a socket, and reserved mbuf space. 316 */ 317static void 318sbrelease_internal(struct sockbuf *sb, struct socket *so) 319{ 320 321 sbflush_internal(sb); 322 (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, 323 RLIM_INFINITY); 324 sb->sb_mbmax = 0; 325} 326 327void 328sbrelease_locked(struct sockbuf *sb, struct socket *so) 329{ 330 331 SOCKBUF_LOCK_ASSERT(sb); 332 333 sbrelease_internal(sb, so); 334} 335 336void 337sbrelease(struct sockbuf *sb, struct socket *so) 338{ 339 340 SOCKBUF_LOCK(sb); 341 sbrelease_locked(sb, so); 342 SOCKBUF_UNLOCK(sb); 343} 344 345void 346sbdestroy(struct sockbuf *sb, struct socket *so) 347{ 348 349 sbrelease_internal(sb, so); 350} 351
|
352
| |
353/* 354 * Routines to add and remove data from an mbuf queue. 355 * 356 * The routines sbappend() or sbappendrecord() are normally called to append 357 * new mbufs to a socket buffer, after checking that adequate space is 358 * available, comparing the function sbspace() with the amount of data to be 359 * added. sbappendrecord() differs from sbappend() in that data supplied is 360 * treated as the beginning of a new record. To place a sender's address, 361 * optional access rights, and data in a socket receive buffer, 362 * sbappendaddr() should be used. To place access rights and data in a 363 * socket receive buffer, sbappendrights() should be used. In either case, 364 * the new data begins a new record. Note that unlike sbappend() and 365 * sbappendrecord(), these routines check for the caller that there will be 366 * enough space to store the data. Each fails if there is not enough space, 367 * or if it cannot find mbufs to store additional information in. 368 * 369 * Reliable protocols may use the socket send buffer to hold data awaiting 370 * acknowledgement. Data is normally copied from a socket send buffer in a 371 * protocol with m_copy for output to a peer, and then removing the data from 372 * the socket buffer with sbdrop() or sbdroprecord() when the data is 373 * acknowledged by the peer. 374 */ 375#ifdef SOCKBUF_DEBUG 376void 377sblastrecordchk(struct sockbuf *sb, const char *file, int line) 378{ 379 struct mbuf *m = sb->sb_mb; 380 381 SOCKBUF_LOCK_ASSERT(sb); 382 383 while (m && m->m_nextpkt) 384 m = m->m_nextpkt; 385 386 if (m != sb->sb_lastrecord) { 387 printf("%s: sb_mb %p sb_lastrecord %p last %p\n", 388 __func__, sb->sb_mb, sb->sb_lastrecord, m); 389 printf("packet chain:\n"); 390 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) 391 printf("\t%p\n", m); 392 panic("%s from %s:%u", __func__, file, line); 393 } 394} 395 396void 397sblastmbufchk(struct sockbuf *sb, const char *file, int line) 398{ 399 struct mbuf *m = sb->sb_mb; 400 struct mbuf *n; 401 402 SOCKBUF_LOCK_ASSERT(sb); 403 404 while (m && m->m_nextpkt) 405 m = m->m_nextpkt; 406 407 while (m && m->m_next) 408 m = m->m_next; 409 410 if (m != sb->sb_mbtail) { 411 printf("%s: sb_mb %p sb_mbtail %p last %p\n", 412 __func__, sb->sb_mb, sb->sb_mbtail, m); 413 printf("packet tree:\n"); 414 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) { 415 printf("\t"); 416 for (n = m; n != NULL; n = n->m_next) 417 printf("%p ", n); 418 printf("\n"); 419 } 420 panic("%s from %s:%u", __func__, file, line); 421 } 422} 423#endif /* SOCKBUF_DEBUG */ 424 425#define SBLINKRECORD(sb, m0) do { \ 426 SOCKBUF_LOCK_ASSERT(sb); \ 427 if ((sb)->sb_lastrecord != NULL) \ 428 (sb)->sb_lastrecord->m_nextpkt = (m0); \ 429 else \ 430 (sb)->sb_mb = (m0); \ 431 (sb)->sb_lastrecord = (m0); \ 432} while (/*CONSTCOND*/0) 433 434/* 435 * Append mbuf chain m to the last record in the socket buffer sb. The 436 * additional space associated the mbuf chain is recorded in sb. Empty mbufs 437 * are discarded and mbufs are compacted where possible. 438 */ 439void 440sbappend_locked(struct sockbuf *sb, struct mbuf *m) 441{ 442 struct mbuf *n; 443 444 SOCKBUF_LOCK_ASSERT(sb); 445 446 if (m == 0) 447 return; 448 449 SBLASTRECORDCHK(sb); 450 n = sb->sb_mb; 451 if (n) { 452 while (n->m_nextpkt) 453 n = n->m_nextpkt; 454 do { 455 if (n->m_flags & M_EOR) { 456 sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 457 return; 458 } 459 } while (n->m_next && (n = n->m_next)); 460 } else { 461 /* 462 * XXX Would like to simply use sb_mbtail here, but 463 * XXX I need to verify that I won't miss an EOR that 464 * XXX way. 465 */ 466 if ((n = sb->sb_lastrecord) != NULL) { 467 do { 468 if (n->m_flags & M_EOR) { 469 sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 470 return; 471 } 472 } while (n->m_next && (n = n->m_next)); 473 } else { 474 /* 475 * If this is the first record in the socket buffer, 476 * it's also the last record. 477 */ 478 sb->sb_lastrecord = m; 479 } 480 } 481 sbcompress(sb, m, n); 482 SBLASTRECORDCHK(sb); 483} 484 485/* 486 * Append mbuf chain m to the last record in the socket buffer sb. The 487 * additional space associated the mbuf chain is recorded in sb. Empty mbufs 488 * are discarded and mbufs are compacted where possible. 489 */ 490void 491sbappend(struct sockbuf *sb, struct mbuf *m) 492{ 493 494 SOCKBUF_LOCK(sb); 495 sbappend_locked(sb, m); 496 SOCKBUF_UNLOCK(sb); 497} 498 499/* 500 * This version of sbappend() should only be used when the caller absolutely 501 * knows that there will never be more than one record in the socket buffer, 502 * that is, a stream protocol (such as TCP). 503 */ 504void 505sbappendstream_locked(struct sockbuf *sb, struct mbuf *m) 506{ 507 SOCKBUF_LOCK_ASSERT(sb); 508 509 KASSERT(m->m_nextpkt == NULL,("sbappendstream 0")); 510 KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1")); 511 512 SBLASTMBUFCHK(sb); 513 514 sbcompress(sb, m, sb->sb_mbtail); 515 516 sb->sb_lastrecord = sb->sb_mb; 517 SBLASTRECORDCHK(sb); 518} 519 520/* 521 * This version of sbappend() should only be used when the caller absolutely 522 * knows that there will never be more than one record in the socket buffer, 523 * that is, a stream protocol (such as TCP). 524 */ 525void 526sbappendstream(struct sockbuf *sb, struct mbuf *m) 527{ 528 529 SOCKBUF_LOCK(sb); 530 sbappendstream_locked(sb, m); 531 SOCKBUF_UNLOCK(sb); 532} 533 534#ifdef SOCKBUF_DEBUG 535void 536sbcheck(struct sockbuf *sb) 537{ 538 struct mbuf *m; 539 struct mbuf *n = 0; 540 u_long len = 0, mbcnt = 0; 541 542 SOCKBUF_LOCK_ASSERT(sb); 543 544 for (m = sb->sb_mb; m; m = n) { 545 n = m->m_nextpkt; 546 for (; m; m = m->m_next) { 547 len += m->m_len; 548 mbcnt += MSIZE; 549 if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 550 mbcnt += m->m_ext.ext_size; 551 } 552 } 553 if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { 554 printf("cc %ld != %u || mbcnt %ld != %u\n", len, sb->sb_cc, 555 mbcnt, sb->sb_mbcnt); 556 panic("sbcheck"); 557 } 558} 559#endif 560 561/* 562 * As above, except the mbuf chain begins a new record. 563 */ 564void 565sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0) 566{ 567 struct mbuf *m; 568 569 SOCKBUF_LOCK_ASSERT(sb); 570 571 if (m0 == 0) 572 return; 573 m = sb->sb_mb; 574 if (m) 575 while (m->m_nextpkt) 576 m = m->m_nextpkt; 577 /* 578 * Put the first mbuf on the queue. Note this permits zero length 579 * records. 580 */ 581 sballoc(sb, m0); 582 SBLASTRECORDCHK(sb); 583 SBLINKRECORD(sb, m0); 584 if (m) 585 m->m_nextpkt = m0; 586 else 587 sb->sb_mb = m0; 588 m = m0->m_next; 589 m0->m_next = 0; 590 if (m && (m0->m_flags & M_EOR)) { 591 m0->m_flags &= ~M_EOR; 592 m->m_flags |= M_EOR; 593 } 594 sbcompress(sb, m, m0); 595} 596 597/* 598 * As above, except the mbuf chain begins a new record. 599 */ 600void 601sbappendrecord(struct sockbuf *sb, struct mbuf *m0) 602{ 603 604 SOCKBUF_LOCK(sb); 605 sbappendrecord_locked(sb, m0); 606 SOCKBUF_UNLOCK(sb); 607} 608 609/* 610 * Append address and data, and optionally, control (ancillary) data to the 611 * receive queue of a socket. If present, m0 must include a packet header 612 * with total length. Returns 0 if no space in sockbuf or insufficient 613 * mbufs. 614 */ 615int 616sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, 617 struct mbuf *m0, struct mbuf *control) 618{ 619 struct mbuf *m, *n, *nlast; 620 int space = asa->sa_len; 621 622 SOCKBUF_LOCK_ASSERT(sb); 623 624 if (m0 && (m0->m_flags & M_PKTHDR) == 0) 625 panic("sbappendaddr_locked"); 626 if (m0) 627 space += m0->m_pkthdr.len; 628 space += m_length(control, &n); 629 630 if (space > sbspace(sb)) 631 return (0); 632#if MSIZE <= 256 633 if (asa->sa_len > MLEN) 634 return (0); 635#endif 636 MGET(m, M_DONTWAIT, MT_SONAME); 637 if (m == 0) 638 return (0); 639 m->m_len = asa->sa_len; 640 bcopy(asa, mtod(m, caddr_t), asa->sa_len); 641 if (n) 642 n->m_next = m0; /* concatenate data to control */ 643 else 644 control = m0; 645 m->m_next = control; 646 for (n = m; n->m_next != NULL; n = n->m_next) 647 sballoc(sb, n); 648 sballoc(sb, n); 649 nlast = n; 650 SBLINKRECORD(sb, m); 651 652 sb->sb_mbtail = nlast; 653 SBLASTMBUFCHK(sb); 654 655 SBLASTRECORDCHK(sb); 656 return (1); 657} 658 659/* 660 * Append address and data, and optionally, control (ancillary) data to the 661 * receive queue of a socket. If present, m0 must include a packet header 662 * with total length. Returns 0 if no space in sockbuf or insufficient 663 * mbufs. 664 */ 665int 666sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, 667 struct mbuf *m0, struct mbuf *control) 668{ 669 int retval; 670 671 SOCKBUF_LOCK(sb); 672 retval = sbappendaddr_locked(sb, asa, m0, control); 673 SOCKBUF_UNLOCK(sb); 674 return (retval); 675} 676 677int 678sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, 679 struct mbuf *control) 680{ 681 struct mbuf *m, *n, *mlast; 682 int space; 683 684 SOCKBUF_LOCK_ASSERT(sb); 685 686 if (control == 0) 687 panic("sbappendcontrol_locked"); 688 space = m_length(control, &n) + m_length(m0, NULL); 689 690 if (space > sbspace(sb)) 691 return (0); 692 n->m_next = m0; /* concatenate data to control */ 693 694 SBLASTRECORDCHK(sb); 695 696 for (m = control; m->m_next; m = m->m_next) 697 sballoc(sb, m); 698 sballoc(sb, m); 699 mlast = m; 700 SBLINKRECORD(sb, control); 701 702 sb->sb_mbtail = mlast; 703 SBLASTMBUFCHK(sb); 704 705 SBLASTRECORDCHK(sb); 706 return (1); 707} 708 709int 710sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control) 711{ 712 int retval; 713 714 SOCKBUF_LOCK(sb); 715 retval = sbappendcontrol_locked(sb, m0, control); 716 SOCKBUF_UNLOCK(sb); 717 return (retval); 718} 719 720/* 721 * Append the data in mbuf chain (m) into the socket buffer sb following mbuf 722 * (n). If (n) is NULL, the buffer is presumed empty. 723 * 724 * When the data is compressed, mbufs in the chain may be handled in one of 725 * three ways: 726 * 727 * (1) The mbuf may simply be dropped, if it contributes nothing (no data, no 728 * record boundary, and no change in data type). 729 * 730 * (2) The mbuf may be coalesced -- i.e., data in the mbuf may be copied into 731 * an mbuf already in the socket buffer. This can occur if an 732 * appropriate mbuf exists, there is room, and no merging of data types 733 * will occur. 734 * 735 * (3) The mbuf may be appended to the end of the existing mbuf chain. 736 * 737 * If any of the new mbufs is marked as M_EOR, mark the last mbuf appended as 738 * end-of-record. 739 */ 740void 741sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 742{ 743 int eor = 0; 744 struct mbuf *o; 745 746 SOCKBUF_LOCK_ASSERT(sb); 747 748 while (m) { 749 eor |= m->m_flags & M_EOR; 750 if (m->m_len == 0 && 751 (eor == 0 || 752 (((o = m->m_next) || (o = n)) && 753 o->m_type == m->m_type))) { 754 if (sb->sb_lastrecord == m) 755 sb->sb_lastrecord = m->m_next; 756 m = m_free(m); 757 continue; 758 } 759 if (n && (n->m_flags & M_EOR) == 0 && 760 M_WRITABLE(n) && 761 m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 762 m->m_len <= M_TRAILINGSPACE(n) && 763 n->m_type == m->m_type) { 764 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 765 (unsigned)m->m_len); 766 n->m_len += m->m_len; 767 sb->sb_cc += m->m_len; 768 if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 769 /* XXX: Probably don't need.*/ 770 sb->sb_ctl += m->m_len; 771 m = m_free(m); 772 continue; 773 } 774 if (n) 775 n->m_next = m; 776 else 777 sb->sb_mb = m; 778 sb->sb_mbtail = m; 779 sballoc(sb, m); 780 n = m; 781 m->m_flags &= ~M_EOR; 782 m = m->m_next; 783 n->m_next = 0; 784 } 785 if (eor) { 786 KASSERT(n != NULL, ("sbcompress: eor && n == NULL")); 787 n->m_flags |= eor; 788 } 789 SBLASTMBUFCHK(sb); 790} 791 792/* 793 * Free all mbufs in a sockbuf. Check that all resources are reclaimed. 794 */ 795static void 796sbflush_internal(struct sockbuf *sb) 797{ 798 799 while (sb->sb_mbcnt) { 800 /* 801 * Don't call sbdrop(sb, 0) if the leading mbuf is non-empty: 802 * we would loop forever. Panic instead. 803 */ 804 if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len)) 805 break; 806 sbdrop_internal(sb, (int)sb->sb_cc); 807 } 808 if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt) 809 panic("sbflush_internal: cc %u || mb %p || mbcnt %u", 810 sb->sb_cc, (void *)sb->sb_mb, sb->sb_mbcnt); 811} 812 813void 814sbflush_locked(struct sockbuf *sb) 815{ 816 817 SOCKBUF_LOCK_ASSERT(sb); 818 sbflush_internal(sb); 819} 820 821void 822sbflush(struct sockbuf *sb) 823{ 824 825 SOCKBUF_LOCK(sb); 826 sbflush_locked(sb); 827 SOCKBUF_UNLOCK(sb); 828} 829 830/* 831 * Drop data from (the front of) a sockbuf. 832 */ 833static void 834sbdrop_internal(struct sockbuf *sb, int len) 835{ 836 struct mbuf *m; 837 struct mbuf *next; 838 839 next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 840 while (len > 0) { 841 if (m == 0) { 842 if (next == 0) 843 panic("sbdrop"); 844 m = next; 845 next = m->m_nextpkt; 846 continue; 847 } 848 if (m->m_len > len) { 849 m->m_len -= len; 850 m->m_data += len; 851 sb->sb_cc -= len; 852 if (sb->sb_sndptroff != 0) 853 sb->sb_sndptroff -= len; 854 if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 855 sb->sb_ctl -= len; 856 break; 857 } 858 len -= m->m_len; 859 sbfree(sb, m); 860 m = m_free(m); 861 } 862 while (m && m->m_len == 0) { 863 sbfree(sb, m); 864 m = m_free(m); 865 } 866 if (m) { 867 sb->sb_mb = m; 868 m->m_nextpkt = next; 869 } else 870 sb->sb_mb = next; 871 /* 872 * First part is an inline SB_EMPTY_FIXUP(). Second part makes sure 873 * sb_lastrecord is up-to-date if we dropped part of the last record. 874 */ 875 m = sb->sb_mb; 876 if (m == NULL) { 877 sb->sb_mbtail = NULL; 878 sb->sb_lastrecord = NULL; 879 } else if (m->m_nextpkt == NULL) { 880 sb->sb_lastrecord = m; 881 } 882} 883 884/* 885 * Drop data from (the front of) a sockbuf. 886 */ 887void 888sbdrop_locked(struct sockbuf *sb, int len) 889{ 890 891 SOCKBUF_LOCK_ASSERT(sb); 892 893 sbdrop_internal(sb, len); 894} 895 896void 897sbdrop(struct sockbuf *sb, int len) 898{ 899 900 SOCKBUF_LOCK(sb); 901 sbdrop_locked(sb, len); 902 SOCKBUF_UNLOCK(sb); 903} 904
| 352/* 353 * Routines to add and remove data from an mbuf queue. 354 * 355 * The routines sbappend() or sbappendrecord() are normally called to append 356 * new mbufs to a socket buffer, after checking that adequate space is 357 * available, comparing the function sbspace() with the amount of data to be 358 * added. sbappendrecord() differs from sbappend() in that data supplied is 359 * treated as the beginning of a new record. To place a sender's address, 360 * optional access rights, and data in a socket receive buffer, 361 * sbappendaddr() should be used. To place access rights and data in a 362 * socket receive buffer, sbappendrights() should be used. In either case, 363 * the new data begins a new record. Note that unlike sbappend() and 364 * sbappendrecord(), these routines check for the caller that there will be 365 * enough space to store the data. Each fails if there is not enough space, 366 * or if it cannot find mbufs to store additional information in. 367 * 368 * Reliable protocols may use the socket send buffer to hold data awaiting 369 * acknowledgement. Data is normally copied from a socket send buffer in a 370 * protocol with m_copy for output to a peer, and then removing the data from 371 * the socket buffer with sbdrop() or sbdroprecord() when the data is 372 * acknowledged by the peer. 373 */ 374#ifdef SOCKBUF_DEBUG 375void 376sblastrecordchk(struct sockbuf *sb, const char *file, int line) 377{ 378 struct mbuf *m = sb->sb_mb; 379 380 SOCKBUF_LOCK_ASSERT(sb); 381 382 while (m && m->m_nextpkt) 383 m = m->m_nextpkt; 384 385 if (m != sb->sb_lastrecord) { 386 printf("%s: sb_mb %p sb_lastrecord %p last %p\n", 387 __func__, sb->sb_mb, sb->sb_lastrecord, m); 388 printf("packet chain:\n"); 389 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) 390 printf("\t%p\n", m); 391 panic("%s from %s:%u", __func__, file, line); 392 } 393} 394 395void 396sblastmbufchk(struct sockbuf *sb, const char *file, int line) 397{ 398 struct mbuf *m = sb->sb_mb; 399 struct mbuf *n; 400 401 SOCKBUF_LOCK_ASSERT(sb); 402 403 while (m && m->m_nextpkt) 404 m = m->m_nextpkt; 405 406 while (m && m->m_next) 407 m = m->m_next; 408 409 if (m != sb->sb_mbtail) { 410 printf("%s: sb_mb %p sb_mbtail %p last %p\n", 411 __func__, sb->sb_mb, sb->sb_mbtail, m); 412 printf("packet tree:\n"); 413 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) { 414 printf("\t"); 415 for (n = m; n != NULL; n = n->m_next) 416 printf("%p ", n); 417 printf("\n"); 418 } 419 panic("%s from %s:%u", __func__, file, line); 420 } 421} 422#endif /* SOCKBUF_DEBUG */ 423 424#define SBLINKRECORD(sb, m0) do { \ 425 SOCKBUF_LOCK_ASSERT(sb); \ 426 if ((sb)->sb_lastrecord != NULL) \ 427 (sb)->sb_lastrecord->m_nextpkt = (m0); \ 428 else \ 429 (sb)->sb_mb = (m0); \ 430 (sb)->sb_lastrecord = (m0); \ 431} while (/*CONSTCOND*/0) 432 433/* 434 * Append mbuf chain m to the last record in the socket buffer sb. The 435 * additional space associated the mbuf chain is recorded in sb. Empty mbufs 436 * are discarded and mbufs are compacted where possible. 437 */ 438void 439sbappend_locked(struct sockbuf *sb, struct mbuf *m) 440{ 441 struct mbuf *n; 442 443 SOCKBUF_LOCK_ASSERT(sb); 444 445 if (m == 0) 446 return; 447 448 SBLASTRECORDCHK(sb); 449 n = sb->sb_mb; 450 if (n) { 451 while (n->m_nextpkt) 452 n = n->m_nextpkt; 453 do { 454 if (n->m_flags & M_EOR) { 455 sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 456 return; 457 } 458 } while (n->m_next && (n = n->m_next)); 459 } else { 460 /* 461 * XXX Would like to simply use sb_mbtail here, but 462 * XXX I need to verify that I won't miss an EOR that 463 * XXX way. 464 */ 465 if ((n = sb->sb_lastrecord) != NULL) { 466 do { 467 if (n->m_flags & M_EOR) { 468 sbappendrecord_locked(sb, m); /* XXXXXX!!!! */ 469 return; 470 } 471 } while (n->m_next && (n = n->m_next)); 472 } else { 473 /* 474 * If this is the first record in the socket buffer, 475 * it's also the last record. 476 */ 477 sb->sb_lastrecord = m; 478 } 479 } 480 sbcompress(sb, m, n); 481 SBLASTRECORDCHK(sb); 482} 483 484/* 485 * Append mbuf chain m to the last record in the socket buffer sb. The 486 * additional space associated the mbuf chain is recorded in sb. Empty mbufs 487 * are discarded and mbufs are compacted where possible. 488 */ 489void 490sbappend(struct sockbuf *sb, struct mbuf *m) 491{ 492 493 SOCKBUF_LOCK(sb); 494 sbappend_locked(sb, m); 495 SOCKBUF_UNLOCK(sb); 496} 497 498/* 499 * This version of sbappend() should only be used when the caller absolutely 500 * knows that there will never be more than one record in the socket buffer, 501 * that is, a stream protocol (such as TCP). 502 */ 503void 504sbappendstream_locked(struct sockbuf *sb, struct mbuf *m) 505{ 506 SOCKBUF_LOCK_ASSERT(sb); 507 508 KASSERT(m->m_nextpkt == NULL,("sbappendstream 0")); 509 KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1")); 510 511 SBLASTMBUFCHK(sb); 512 513 sbcompress(sb, m, sb->sb_mbtail); 514 515 sb->sb_lastrecord = sb->sb_mb; 516 SBLASTRECORDCHK(sb); 517} 518 519/* 520 * This version of sbappend() should only be used when the caller absolutely 521 * knows that there will never be more than one record in the socket buffer, 522 * that is, a stream protocol (such as TCP). 523 */ 524void 525sbappendstream(struct sockbuf *sb, struct mbuf *m) 526{ 527 528 SOCKBUF_LOCK(sb); 529 sbappendstream_locked(sb, m); 530 SOCKBUF_UNLOCK(sb); 531} 532 533#ifdef SOCKBUF_DEBUG 534void 535sbcheck(struct sockbuf *sb) 536{ 537 struct mbuf *m; 538 struct mbuf *n = 0; 539 u_long len = 0, mbcnt = 0; 540 541 SOCKBUF_LOCK_ASSERT(sb); 542 543 for (m = sb->sb_mb; m; m = n) { 544 n = m->m_nextpkt; 545 for (; m; m = m->m_next) { 546 len += m->m_len; 547 mbcnt += MSIZE; 548 if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */ 549 mbcnt += m->m_ext.ext_size; 550 } 551 } 552 if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) { 553 printf("cc %ld != %u || mbcnt %ld != %u\n", len, sb->sb_cc, 554 mbcnt, sb->sb_mbcnt); 555 panic("sbcheck"); 556 } 557} 558#endif 559 560/* 561 * As above, except the mbuf chain begins a new record. 562 */ 563void 564sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0) 565{ 566 struct mbuf *m; 567 568 SOCKBUF_LOCK_ASSERT(sb); 569 570 if (m0 == 0) 571 return; 572 m = sb->sb_mb; 573 if (m) 574 while (m->m_nextpkt) 575 m = m->m_nextpkt; 576 /* 577 * Put the first mbuf on the queue. Note this permits zero length 578 * records. 579 */ 580 sballoc(sb, m0); 581 SBLASTRECORDCHK(sb); 582 SBLINKRECORD(sb, m0); 583 if (m) 584 m->m_nextpkt = m0; 585 else 586 sb->sb_mb = m0; 587 m = m0->m_next; 588 m0->m_next = 0; 589 if (m && (m0->m_flags & M_EOR)) { 590 m0->m_flags &= ~M_EOR; 591 m->m_flags |= M_EOR; 592 } 593 sbcompress(sb, m, m0); 594} 595 596/* 597 * As above, except the mbuf chain begins a new record. 598 */ 599void 600sbappendrecord(struct sockbuf *sb, struct mbuf *m0) 601{ 602 603 SOCKBUF_LOCK(sb); 604 sbappendrecord_locked(sb, m0); 605 SOCKBUF_UNLOCK(sb); 606} 607 608/* 609 * Append address and data, and optionally, control (ancillary) data to the 610 * receive queue of a socket. If present, m0 must include a packet header 611 * with total length. Returns 0 if no space in sockbuf or insufficient 612 * mbufs. 613 */ 614int 615sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, 616 struct mbuf *m0, struct mbuf *control) 617{ 618 struct mbuf *m, *n, *nlast; 619 int space = asa->sa_len; 620 621 SOCKBUF_LOCK_ASSERT(sb); 622 623 if (m0 && (m0->m_flags & M_PKTHDR) == 0) 624 panic("sbappendaddr_locked"); 625 if (m0) 626 space += m0->m_pkthdr.len; 627 space += m_length(control, &n); 628 629 if (space > sbspace(sb)) 630 return (0); 631#if MSIZE <= 256 632 if (asa->sa_len > MLEN) 633 return (0); 634#endif 635 MGET(m, M_DONTWAIT, MT_SONAME); 636 if (m == 0) 637 return (0); 638 m->m_len = asa->sa_len; 639 bcopy(asa, mtod(m, caddr_t), asa->sa_len); 640 if (n) 641 n->m_next = m0; /* concatenate data to control */ 642 else 643 control = m0; 644 m->m_next = control; 645 for (n = m; n->m_next != NULL; n = n->m_next) 646 sballoc(sb, n); 647 sballoc(sb, n); 648 nlast = n; 649 SBLINKRECORD(sb, m); 650 651 sb->sb_mbtail = nlast; 652 SBLASTMBUFCHK(sb); 653 654 SBLASTRECORDCHK(sb); 655 return (1); 656} 657 658/* 659 * Append address and data, and optionally, control (ancillary) data to the 660 * receive queue of a socket. If present, m0 must include a packet header 661 * with total length. Returns 0 if no space in sockbuf or insufficient 662 * mbufs. 663 */ 664int 665sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, 666 struct mbuf *m0, struct mbuf *control) 667{ 668 int retval; 669 670 SOCKBUF_LOCK(sb); 671 retval = sbappendaddr_locked(sb, asa, m0, control); 672 SOCKBUF_UNLOCK(sb); 673 return (retval); 674} 675 676int 677sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, 678 struct mbuf *control) 679{ 680 struct mbuf *m, *n, *mlast; 681 int space; 682 683 SOCKBUF_LOCK_ASSERT(sb); 684 685 if (control == 0) 686 panic("sbappendcontrol_locked"); 687 space = m_length(control, &n) + m_length(m0, NULL); 688 689 if (space > sbspace(sb)) 690 return (0); 691 n->m_next = m0; /* concatenate data to control */ 692 693 SBLASTRECORDCHK(sb); 694 695 for (m = control; m->m_next; m = m->m_next) 696 sballoc(sb, m); 697 sballoc(sb, m); 698 mlast = m; 699 SBLINKRECORD(sb, control); 700 701 sb->sb_mbtail = mlast; 702 SBLASTMBUFCHK(sb); 703 704 SBLASTRECORDCHK(sb); 705 return (1); 706} 707 708int 709sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control) 710{ 711 int retval; 712 713 SOCKBUF_LOCK(sb); 714 retval = sbappendcontrol_locked(sb, m0, control); 715 SOCKBUF_UNLOCK(sb); 716 return (retval); 717} 718 719/* 720 * Append the data in mbuf chain (m) into the socket buffer sb following mbuf 721 * (n). If (n) is NULL, the buffer is presumed empty. 722 * 723 * When the data is compressed, mbufs in the chain may be handled in one of 724 * three ways: 725 * 726 * (1) The mbuf may simply be dropped, if it contributes nothing (no data, no 727 * record boundary, and no change in data type). 728 * 729 * (2) The mbuf may be coalesced -- i.e., data in the mbuf may be copied into 730 * an mbuf already in the socket buffer. This can occur if an 731 * appropriate mbuf exists, there is room, and no merging of data types 732 * will occur. 733 * 734 * (3) The mbuf may be appended to the end of the existing mbuf chain. 735 * 736 * If any of the new mbufs is marked as M_EOR, mark the last mbuf appended as 737 * end-of-record. 738 */ 739void 740sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n) 741{ 742 int eor = 0; 743 struct mbuf *o; 744 745 SOCKBUF_LOCK_ASSERT(sb); 746 747 while (m) { 748 eor |= m->m_flags & M_EOR; 749 if (m->m_len == 0 && 750 (eor == 0 || 751 (((o = m->m_next) || (o = n)) && 752 o->m_type == m->m_type))) { 753 if (sb->sb_lastrecord == m) 754 sb->sb_lastrecord = m->m_next; 755 m = m_free(m); 756 continue; 757 } 758 if (n && (n->m_flags & M_EOR) == 0 && 759 M_WRITABLE(n) && 760 m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */ 761 m->m_len <= M_TRAILINGSPACE(n) && 762 n->m_type == m->m_type) { 763 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 764 (unsigned)m->m_len); 765 n->m_len += m->m_len; 766 sb->sb_cc += m->m_len; 767 if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 768 /* XXX: Probably don't need.*/ 769 sb->sb_ctl += m->m_len; 770 m = m_free(m); 771 continue; 772 } 773 if (n) 774 n->m_next = m; 775 else 776 sb->sb_mb = m; 777 sb->sb_mbtail = m; 778 sballoc(sb, m); 779 n = m; 780 m->m_flags &= ~M_EOR; 781 m = m->m_next; 782 n->m_next = 0; 783 } 784 if (eor) { 785 KASSERT(n != NULL, ("sbcompress: eor && n == NULL")); 786 n->m_flags |= eor; 787 } 788 SBLASTMBUFCHK(sb); 789} 790 791/* 792 * Free all mbufs in a sockbuf. Check that all resources are reclaimed. 793 */ 794static void 795sbflush_internal(struct sockbuf *sb) 796{ 797 798 while (sb->sb_mbcnt) { 799 /* 800 * Don't call sbdrop(sb, 0) if the leading mbuf is non-empty: 801 * we would loop forever. Panic instead. 802 */ 803 if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len)) 804 break; 805 sbdrop_internal(sb, (int)sb->sb_cc); 806 } 807 if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt) 808 panic("sbflush_internal: cc %u || mb %p || mbcnt %u", 809 sb->sb_cc, (void *)sb->sb_mb, sb->sb_mbcnt); 810} 811 812void 813sbflush_locked(struct sockbuf *sb) 814{ 815 816 SOCKBUF_LOCK_ASSERT(sb); 817 sbflush_internal(sb); 818} 819 820void 821sbflush(struct sockbuf *sb) 822{ 823 824 SOCKBUF_LOCK(sb); 825 sbflush_locked(sb); 826 SOCKBUF_UNLOCK(sb); 827} 828 829/* 830 * Drop data from (the front of) a sockbuf. 831 */ 832static void 833sbdrop_internal(struct sockbuf *sb, int len) 834{ 835 struct mbuf *m; 836 struct mbuf *next; 837 838 next = (m = sb->sb_mb) ? m->m_nextpkt : 0; 839 while (len > 0) { 840 if (m == 0) { 841 if (next == 0) 842 panic("sbdrop"); 843 m = next; 844 next = m->m_nextpkt; 845 continue; 846 } 847 if (m->m_len > len) { 848 m->m_len -= len; 849 m->m_data += len; 850 sb->sb_cc -= len; 851 if (sb->sb_sndptroff != 0) 852 sb->sb_sndptroff -= len; 853 if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA) 854 sb->sb_ctl -= len; 855 break; 856 } 857 len -= m->m_len; 858 sbfree(sb, m); 859 m = m_free(m); 860 } 861 while (m && m->m_len == 0) { 862 sbfree(sb, m); 863 m = m_free(m); 864 } 865 if (m) { 866 sb->sb_mb = m; 867 m->m_nextpkt = next; 868 } else 869 sb->sb_mb = next; 870 /* 871 * First part is an inline SB_EMPTY_FIXUP(). Second part makes sure 872 * sb_lastrecord is up-to-date if we dropped part of the last record. 873 */ 874 m = sb->sb_mb; 875 if (m == NULL) { 876 sb->sb_mbtail = NULL; 877 sb->sb_lastrecord = NULL; 878 } else if (m->m_nextpkt == NULL) { 879 sb->sb_lastrecord = m; 880 } 881} 882 883/* 884 * Drop data from (the front of) a sockbuf. 885 */ 886void 887sbdrop_locked(struct sockbuf *sb, int len) 888{ 889 890 SOCKBUF_LOCK_ASSERT(sb); 891 892 sbdrop_internal(sb, len); 893} 894 895void 896sbdrop(struct sockbuf *sb, int len) 897{ 898 899 SOCKBUF_LOCK(sb); 900 sbdrop_locked(sb, len); 901 SOCKBUF_UNLOCK(sb); 902} 903
|
905
| |
906/* 907 * Maintain a pointer and offset pair into the socket buffer mbuf chain to 908 * avoid traversal of the entire socket buffer for larger offsets. 909 */ 910struct mbuf * 911sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff) 912{ 913 struct mbuf *m, *ret; 914 915 KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 916 KASSERT(off + len <= sb->sb_cc, ("%s: beyond sb", __func__)); 917 KASSERT(sb->sb_sndptroff <= sb->sb_cc, ("%s: sndptroff broken", __func__)); 918 919 /* 920 * Is off below stored offset? Happens on retransmits. 921 * Just return, we can't help here. 922 */ 923 if (sb->sb_sndptroff > off) { 924 *moff = off; 925 return (sb->sb_mb); 926 } 927 928 /* Return closest mbuf in chain for current offset. */ 929 *moff = off - sb->sb_sndptroff; 930 m = ret = sb->sb_sndptr ? sb->sb_sndptr : sb->sb_mb; 931 932 /* Advance by len to be as close as possible for the next transmit. */ 933 for (off = off - sb->sb_sndptroff + len - 1; 934 off > 0 && off >= m->m_len; 935 m = m->m_next) { 936 sb->sb_sndptroff += m->m_len; 937 off -= m->m_len; 938 } 939 sb->sb_sndptr = m; 940 941 return (ret); 942} 943 944/* 945 * Drop a record off the front of a sockbuf and move the next record to the 946 * front. 947 */ 948void 949sbdroprecord_locked(struct sockbuf *sb) 950{ 951 struct mbuf *m; 952 953 SOCKBUF_LOCK_ASSERT(sb); 954 955 m = sb->sb_mb; 956 if (m) { 957 sb->sb_mb = m->m_nextpkt; 958 do { 959 sbfree(sb, m); 960 m = m_free(m); 961 } while (m); 962 } 963 SB_EMPTY_FIXUP(sb); 964} 965 966/* 967 * Drop a record off the front of a sockbuf and move the next record to the 968 * front. 969 */ 970void 971sbdroprecord(struct sockbuf *sb) 972{ 973 974 SOCKBUF_LOCK(sb); 975 sbdroprecord_locked(sb); 976 SOCKBUF_UNLOCK(sb); 977} 978 979/* 980 * Create a "control" mbuf containing the specified data with the specified 981 * type for presentation on a socket buffer. 982 */ 983struct mbuf *
| 904/* 905 * Maintain a pointer and offset pair into the socket buffer mbuf chain to 906 * avoid traversal of the entire socket buffer for larger offsets. 907 */ 908struct mbuf * 909sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff) 910{ 911 struct mbuf *m, *ret; 912 913 KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); 914 KASSERT(off + len <= sb->sb_cc, ("%s: beyond sb", __func__)); 915 KASSERT(sb->sb_sndptroff <= sb->sb_cc, ("%s: sndptroff broken", __func__)); 916 917 /* 918 * Is off below stored offset? Happens on retransmits. 919 * Just return, we can't help here. 920 */ 921 if (sb->sb_sndptroff > off) { 922 *moff = off; 923 return (sb->sb_mb); 924 } 925 926 /* Return closest mbuf in chain for current offset. */ 927 *moff = off - sb->sb_sndptroff; 928 m = ret = sb->sb_sndptr ? sb->sb_sndptr : sb->sb_mb; 929 930 /* Advance by len to be as close as possible for the next transmit. */ 931 for (off = off - sb->sb_sndptroff + len - 1; 932 off > 0 && off >= m->m_len; 933 m = m->m_next) { 934 sb->sb_sndptroff += m->m_len; 935 off -= m->m_len; 936 } 937 sb->sb_sndptr = m; 938 939 return (ret); 940} 941 942/* 943 * Drop a record off the front of a sockbuf and move the next record to the 944 * front. 945 */ 946void 947sbdroprecord_locked(struct sockbuf *sb) 948{ 949 struct mbuf *m; 950 951 SOCKBUF_LOCK_ASSERT(sb); 952 953 m = sb->sb_mb; 954 if (m) { 955 sb->sb_mb = m->m_nextpkt; 956 do { 957 sbfree(sb, m); 958 m = m_free(m); 959 } while (m); 960 } 961 SB_EMPTY_FIXUP(sb); 962} 963 964/* 965 * Drop a record off the front of a sockbuf and move the next record to the 966 * front. 967 */ 968void 969sbdroprecord(struct sockbuf *sb) 970{ 971 972 SOCKBUF_LOCK(sb); 973 sbdroprecord_locked(sb); 974 SOCKBUF_UNLOCK(sb); 975} 976 977/* 978 * Create a "control" mbuf containing the specified data with the specified 979 * type for presentation on a socket buffer. 980 */ 981struct mbuf *
|
984sbcreatecontrol(p, size, type, level) 985 caddr_t p; 986 register int size; 987 int type, level;
| 982sbcreatecontrol(caddr_t p, int size, int type, int level)
|
988{
| 983{
|
989 register struct cmsghdr *cp;
| 984 struct cmsghdr *cp;
|
990 struct mbuf *m; 991 992 if (CMSG_SPACE((u_int)size) > MCLBYTES) 993 return ((struct mbuf *) NULL); 994 if (CMSG_SPACE((u_int)size) > MLEN) 995 m = m_getcl(M_DONTWAIT, MT_CONTROL, 0); 996 else 997 m = m_get(M_DONTWAIT, MT_CONTROL); 998 if (m == NULL) 999 return ((struct mbuf *) NULL); 1000 cp = mtod(m, struct cmsghdr *); 1001 m->m_len = 0; 1002 KASSERT(CMSG_SPACE((u_int)size) <= M_TRAILINGSPACE(m), 1003 ("sbcreatecontrol: short mbuf")); 1004 if (p != NULL) 1005 (void)memcpy(CMSG_DATA(cp), p, size); 1006 m->m_len = CMSG_SPACE(size); 1007 cp->cmsg_len = CMSG_LEN(size); 1008 cp->cmsg_level = level; 1009 cp->cmsg_type = type; 1010 return (m); 1011} 1012 1013/* 1014 * This does the same for socket buffers that sotoxsocket does for sockets: 1015 * generate an user-format data structure describing the socket buffer. Note 1016 * that the xsockbuf structure, since it is always embedded in a socket, does 1017 * not include a self pointer nor a length. We make this entry point public 1018 * in case some other mechanism needs it. 1019 */ 1020void 1021sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) 1022{
| 985 struct mbuf *m; 986 987 if (CMSG_SPACE((u_int)size) > MCLBYTES) 988 return ((struct mbuf *) NULL); 989 if (CMSG_SPACE((u_int)size) > MLEN) 990 m = m_getcl(M_DONTWAIT, MT_CONTROL, 0); 991 else 992 m = m_get(M_DONTWAIT, MT_CONTROL); 993 if (m == NULL) 994 return ((struct mbuf *) NULL); 995 cp = mtod(m, struct cmsghdr *); 996 m->m_len = 0; 997 KASSERT(CMSG_SPACE((u_int)size) <= M_TRAILINGSPACE(m), 998 ("sbcreatecontrol: short mbuf")); 999 if (p != NULL) 1000 (void)memcpy(CMSG_DATA(cp), p, size); 1001 m->m_len = CMSG_SPACE(size); 1002 cp->cmsg_len = CMSG_LEN(size); 1003 cp->cmsg_level = level; 1004 cp->cmsg_type = type; 1005 return (m); 1006} 1007 1008/* 1009 * This does the same for socket buffers that sotoxsocket does for sockets: 1010 * generate an user-format data structure describing the socket buffer. Note 1011 * that the xsockbuf structure, since it is always embedded in a socket, does 1012 * not include a self pointer nor a length. We make this entry point public 1013 * in case some other mechanism needs it. 1014 */ 1015void 1016sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) 1017{
|
| 1018
|
1023 xsb->sb_cc = sb->sb_cc; 1024 xsb->sb_hiwat = sb->sb_hiwat; 1025 xsb->sb_mbcnt = sb->sb_mbcnt; 1026 xsb->sb_mbmax = sb->sb_mbmax; 1027 xsb->sb_lowat = sb->sb_lowat; 1028 xsb->sb_flags = sb->sb_flags; 1029 xsb->sb_timeo = sb->sb_timeo; 1030} 1031 1032/* This takes the place of kern.maxsockbuf, which moved to kern.ipc. */ 1033static int dummy; 1034SYSCTL_INT(_kern, KERN_DUMMY, dummy, CTLFLAG_RW, &dummy, 0, ""); 1035SYSCTL_OID(_kern_ipc, KIPC_MAXSOCKBUF, maxsockbuf, CTLTYPE_ULONG|CTLFLAG_RW, 1036 &sb_max, 0, sysctl_handle_sb_max, "LU", "Maximum socket buffer size"); 1037SYSCTL_ULONG(_kern_ipc, KIPC_SOCKBUF_WASTE, sockbuf_waste_factor, CTLFLAG_RW, 1038 &sb_efficiency, 0, "");
| 1019 xsb->sb_cc = sb->sb_cc; 1020 xsb->sb_hiwat = sb->sb_hiwat; 1021 xsb->sb_mbcnt = sb->sb_mbcnt; 1022 xsb->sb_mbmax = sb->sb_mbmax; 1023 xsb->sb_lowat = sb->sb_lowat; 1024 xsb->sb_flags = sb->sb_flags; 1025 xsb->sb_timeo = sb->sb_timeo; 1026} 1027 1028/* This takes the place of kern.maxsockbuf, which moved to kern.ipc. */ 1029static int dummy; 1030SYSCTL_INT(_kern, KERN_DUMMY, dummy, CTLFLAG_RW, &dummy, 0, ""); 1031SYSCTL_OID(_kern_ipc, KIPC_MAXSOCKBUF, maxsockbuf, CTLTYPE_ULONG|CTLFLAG_RW, 1032 &sb_max, 0, sysctl_handle_sb_max, "LU", "Maximum socket buffer size"); 1033SYSCTL_ULONG(_kern_ipc, KIPC_SOCKBUF_WASTE, sockbuf_waste_factor, CTLFLAG_RW, 1034 &sb_efficiency, 0, "");
|