1 /* $NetBSD: kttcp.c,v 1.20 2006/10/12 01:30:51 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Frank van der Linden and Jason R. Thorpe for 8 * Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * kttcp.c -- 41 * 42 * This module provides kernel support for testing network 43 * throughput from the perspective of the kernel. It is 44 * similar in spirit to the classic ttcp network benchmark 45 * program, the main difference being that with kttcp, the 46 * kernel is the source and sink of the data. 47 * 48 * Testing like this is useful for a few reasons: 49 * 50 * 1. This allows us to know what kind of performance we can 51 * expect from network applications that run in the kernel 52 * space, such as the NFS server or the NFS client. These 53 * applications don't have to move the data to/from userspace, 54 * and so benchmark programs which run in userspace don't 55 * give us an accurate model. 56 * 57 * 2. Since data received is just thrown away, the receiver 58 * is very fast. This can provide better exercise for the 59 * sender at the other end. 60 * 61 * 3. Since the NetBSD kernel currently uses a run-to-completion 62 * scheduling model, kttcp provides a benchmark model where 63 * preemption of the benchmark program is not an issue. 64 */ 65 66 #include <sys/cdefs.h> 67 __KERNEL_RCSID(0, "$NetBSD: kttcp.c,v 1.20 2006/10/12 01:30:51 christos Exp $"); 68 69 #include <sys/param.h> 70 #include <sys/types.h> 71 #include <sys/ioctl.h> 72 #include <sys/file.h> 73 #include <sys/filedesc.h> 74 #include <sys/conf.h> 75 #include <sys/systm.h> 76 #include <sys/protosw.h> 77 #include <sys/proc.h> 78 #include <sys/resourcevar.h> 79 #include <sys/signal.h> 80 #include <sys/socketvar.h> 81 #include <sys/socket.h> 82 #include <sys/mbuf.h> 83 #include <sys/sa.h> 84 #include <sys/mount.h> 85 #include <sys/syscallargs.h> 86 87 #include <dev/kttcpio.h> 88 89 static int kttcp_send(struct lwp *l, struct kttcp_io_args *); 90 static int kttcp_recv(struct lwp *l, struct kttcp_io_args *); 91 static int kttcp_sosend(struct socket *, unsigned long long, 92 unsigned long long *, struct lwp *, int); 93 static int kttcp_soreceive(struct socket *, unsigned long long, 94 unsigned long long *, struct lwp *, int *); 95 96 void kttcpattach(int); 97 98 dev_type_ioctl(kttcpioctl); 99 100 const struct cdevsw kttcp_cdevsw = { 101 nullopen, nullclose, noread, nowrite, kttcpioctl, 102 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER 103 }; 104 105 void 106 kttcpattach(int count __unused) 107 { 108 /* Do nothing. */ 109 } 110 111 int 112 kttcpioctl(dev_t dev __unused, u_long cmd, caddr_t data, int flag, 113 struct lwp *l) 114 { 115 int error; 116 117 if ((flag & FWRITE) == 0) 118 return EPERM; 119 120 switch (cmd) { 121 case KTTCP_IO_SEND: 122 error = kttcp_send(l, (struct kttcp_io_args *) data); 123 break; 124 125 case KTTCP_IO_RECV: 126 error = kttcp_recv(l, (struct kttcp_io_args *) data); 127 break; 128 129 default: 130 return EINVAL; 131 } 132 133 return error; 134 } 135 136 static int 137 kttcp_send(struct lwp *l, struct kttcp_io_args *kio) 138 { 139 struct file *fp; 140 int error; 141 struct timeval t0, t1; 142 unsigned long long len, done; 143 144 if (kio->kio_totalsize >= KTTCP_MAX_XMIT) 145 return EINVAL; 146 147 fp = fd_getfile(l->l_proc->p_fd, kio->kio_socket); 148 if (fp == NULL) 149 return EBADF; 150 FILE_USE(fp); 151 if (fp->f_type != DTYPE_SOCKET) { 152 FILE_UNUSE(fp, l); 153 return EFTYPE; 154 } 155 156 len = kio->kio_totalsize; 157 microtime(&t0); 158 do { 159 error = kttcp_sosend((struct socket *)fp->f_data, len, 160 &done, l, 0); 161 len -= done; 162 } while (error == 0 && len > 0); 163 164 FILE_UNUSE(fp, l); 165 166 microtime(&t1); 167 if (error != 0) 168 return error; 169 timersub(&t1, &t0, &kio->kio_elapsed); 170 171 kio->kio_bytesdone = kio->kio_totalsize - len; 172 173 return 0; 174 } 175 176 static int 177 kttcp_recv(struct lwp *l, struct kttcp_io_args *kio) 178 { 179 struct file *fp; 180 int error; 181 struct timeval t0, t1; 182 unsigned long long len, done; 183 184 done = 0; /* XXX gcc */ 185 186 if (kio->kio_totalsize > KTTCP_MAX_XMIT) 187 return EINVAL; 188 189 fp = fd_getfile(l->l_proc->p_fd, kio->kio_socket); 190 if (fp == NULL) 191 return EBADF; 192 FILE_USE(fp); 193 if (fp->f_type != DTYPE_SOCKET) { 194 FILE_UNUSE(fp, l); 195 return EBADF; 196 } 197 len = kio->kio_totalsize; 198 microtime(&t0); 199 do { 200 error = kttcp_soreceive((struct socket *)fp->f_data, 201 len, &done, l, NULL); 202 len -= done; 203 } while (error == 0 && len > 0 && done > 0); 204 205 FILE_UNUSE(fp, l); 206 207 microtime(&t1); 208 if (error == EPIPE) 209 error = 0; 210 if (error != 0) 211 return error; 212 timersub(&t1, &t0, &kio->kio_elapsed); 213 214 kio->kio_bytesdone = kio->kio_totalsize - len; 215 216 return 0; 217 } 218 219 #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) 220 221 /* 222 * Slightly changed version of sosend() 223 */ 224 static int 225 kttcp_sosend(struct socket *so, unsigned long long slen, 226 unsigned long long *done, struct lwp *l, int flags) 227 { 228 struct mbuf **mp, *m, *top; 229 long space, len, mlen; 230 int error, s, dontroute, atomic; 231 long long resid; 232 233 atomic = sosendallatonce(so); 234 resid = slen; 235 top = NULL; 236 /* 237 * In theory resid should be unsigned. 238 * However, space must be signed, as it might be less than 0 239 * if we over-committed, and we must use a signed comparison 240 * of space and resid. On the other hand, a negative resid 241 * causes us to loop sending 0-length segments to the protocol. 242 */ 243 if (resid < 0) { 244 error = EINVAL; 245 goto out; 246 } 247 dontroute = 248 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 249 (so->so_proto->pr_flags & PR_ATOMIC); 250 /* WRS XXX - are we doing per-lwp or per-proc stats? */ 251 l->l_proc->p_stats->p_ru.ru_msgsnd++; 252 #define snderr(errno) { error = errno; splx(s); goto release; } 253 254 restart: 255 if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) 256 goto out; 257 do { 258 s = splsoftnet(); 259 if (so->so_state & SS_CANTSENDMORE) 260 snderr(EPIPE); 261 if (so->so_error) { 262 error = so->so_error; 263 so->so_error = 0; 264 splx(s); 265 goto release; 266 } 267 if ((so->so_state & SS_ISCONNECTED) == 0) { 268 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 269 if ((so->so_state & SS_ISCONFIRMING) == 0) 270 snderr(ENOTCONN); 271 } else 272 snderr(EDESTADDRREQ); 273 } 274 space = sbspace(&so->so_snd); 275 if (flags & MSG_OOB) 276 space += 1024; 277 if ((atomic && resid > so->so_snd.sb_hiwat)) 278 snderr(EMSGSIZE); 279 if (space < resid && (atomic || space < so->so_snd.sb_lowat)) { 280 if (so->so_state & SS_NBIO) 281 snderr(EWOULDBLOCK); 282 SBLASTRECORDCHK(&so->so_rcv, 283 "kttcp_soreceive sbwait 1"); 284 SBLASTMBUFCHK(&so->so_rcv, 285 "kttcp_soreceive sbwait 1"); 286 sbunlock(&so->so_snd); 287 error = sbwait(&so->so_snd); 288 splx(s); 289 if (error) 290 goto out; 291 goto restart; 292 } 293 splx(s); 294 mp = ⊤ 295 do { 296 do { 297 if (top == 0) { 298 m = m_gethdr(M_WAIT, MT_DATA); 299 mlen = MHLEN; 300 m->m_pkthdr.len = 0; 301 m->m_pkthdr.rcvif = NULL; 302 } else { 303 m = m_get(M_WAIT, MT_DATA); 304 mlen = MLEN; 305 } 306 if (resid >= MINCLSIZE && space >= MCLBYTES) { 307 m_clget(m, M_WAIT); 308 if ((m->m_flags & M_EXT) == 0) 309 goto nopages; 310 mlen = MCLBYTES; 311 #ifdef MAPPED_MBUFS 312 len = lmin(MCLBYTES, resid); 313 #else 314 if (atomic && top == 0) { 315 len = lmin(MCLBYTES - max_hdr, 316 resid); 317 m->m_data += max_hdr; 318 } else 319 len = lmin(MCLBYTES, resid); 320 #endif 321 space -= len; 322 } else { 323 nopages: 324 len = lmin(lmin(mlen, resid), space); 325 space -= len; 326 /* 327 * For datagram protocols, leave room 328 * for protocol headers in first mbuf. 329 */ 330 if (atomic && top == 0 && len < mlen) 331 MH_ALIGN(m, len); 332 } 333 resid -= len; 334 m->m_len = len; 335 *mp = m; 336 top->m_pkthdr.len += len; 337 if (error) 338 goto release; 339 mp = &m->m_next; 340 if (resid <= 0) { 341 if (flags & MSG_EOR) 342 top->m_flags |= M_EOR; 343 break; 344 } 345 } while (space > 0 && atomic); 346 347 s = splsoftnet(); 348 349 if (so->so_state & SS_CANTSENDMORE) 350 snderr(EPIPE); 351 352 if (dontroute) 353 so->so_options |= SO_DONTROUTE; 354 if (resid > 0) 355 so->so_state |= SS_MORETOCOME; 356 error = (*so->so_proto->pr_usrreq)(so, 357 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 358 top, NULL, NULL, l); 359 if (dontroute) 360 so->so_options &= ~SO_DONTROUTE; 361 if (resid > 0) 362 so->so_state &= ~SS_MORETOCOME; 363 splx(s); 364 365 top = 0; 366 mp = ⊤ 367 if (error) 368 goto release; 369 } while (resid && space > 0); 370 } while (resid); 371 372 release: 373 sbunlock(&so->so_snd); 374 out: 375 if (top) 376 m_freem(top); 377 *done = slen - resid; 378 #if 0 379 printf("sosend: error %d slen %llu resid %lld\n", error, slen, resid); 380 #endif 381 return (error); 382 } 383 384 static int 385 kttcp_soreceive(struct socket *so, unsigned long long slen, 386 unsigned long long *done, struct lwp *l __unused, int *flagsp) 387 { 388 struct mbuf *m, **mp; 389 int flags, len, error, s, offset, moff, type; 390 long long orig_resid, resid; 391 const struct protosw *pr; 392 struct mbuf *nextrecord; 393 394 pr = so->so_proto; 395 mp = NULL; 396 type = 0; 397 resid = orig_resid = slen; 398 if (flagsp) 399 flags = *flagsp &~ MSG_EOR; 400 else 401 flags = 0; 402 if (flags & MSG_OOB) { 403 m = m_get(M_WAIT, MT_DATA); 404 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, 405 (struct mbuf *)(long)(flags & MSG_PEEK), NULL, NULL); 406 if (error) 407 goto bad; 408 do { 409 resid -= min(resid, m->m_len); 410 m = m_free(m); 411 } while (resid && error == 0 && m); 412 bad: 413 if (m) 414 m_freem(m); 415 return (error); 416 } 417 if (mp) 418 *mp = NULL; 419 if (so->so_state & SS_ISCONFIRMING && resid) 420 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, NULL); 421 422 restart: 423 if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) 424 return (error); 425 s = splsoftnet(); 426 427 m = so->so_rcv.sb_mb; 428 /* 429 * If we have less data than requested, block awaiting more 430 * (subject to any timeout) if: 431 * 1. the current count is less than the low water mark, 432 * 2. MSG_WAITALL is set, and it is possible to do the entire 433 * receive operation at once if we block (resid <= hiwat), or 434 * 3. MSG_DONTWAIT is not set. 435 * If MSG_WAITALL is set but resid is larger than the receive buffer, 436 * we have to do the receive in sections, and thus risk returning 437 * a short count if a timeout or signal occurs after we start. 438 */ 439 if (m == NULL || (((flags & MSG_DONTWAIT) == 0 && 440 so->so_rcv.sb_cc < resid) && 441 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || 442 ((flags & MSG_WAITALL) && resid <= so->so_rcv.sb_hiwat)) && 443 m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) { 444 #ifdef DIAGNOSTIC 445 if (m == NULL && so->so_rcv.sb_cc) 446 panic("receive 1"); 447 #endif 448 if (so->so_error) { 449 if (m) 450 goto dontblock; 451 error = so->so_error; 452 if ((flags & MSG_PEEK) == 0) 453 so->so_error = 0; 454 goto release; 455 } 456 if (so->so_state & SS_CANTRCVMORE) { 457 if (m) 458 goto dontblock; 459 else 460 goto release; 461 } 462 for (; m; m = m->m_next) 463 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { 464 m = so->so_rcv.sb_mb; 465 goto dontblock; 466 } 467 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 468 (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 469 error = ENOTCONN; 470 goto release; 471 } 472 if (resid == 0) 473 goto release; 474 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { 475 error = EWOULDBLOCK; 476 goto release; 477 } 478 sbunlock(&so->so_rcv); 479 error = sbwait(&so->so_rcv); 480 splx(s); 481 if (error) 482 return (error); 483 goto restart; 484 } 485 dontblock: 486 /* 487 * On entry here, m points to the first record of the socket buffer. 488 * While we process the initial mbufs containing address and control 489 * info, we save a copy of m->m_nextpkt into nextrecord. 490 */ 491 #ifdef notyet /* XXXX */ 492 if (uio->uio_lwp) 493 uio->uio_lwp->l_proc->p_stats->p_ru.ru_msgrcv++; 494 #endif 495 KASSERT(m == so->so_rcv.sb_mb); 496 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 1"); 497 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 1"); 498 nextrecord = m->m_nextpkt; 499 if (pr->pr_flags & PR_ADDR) { 500 #ifdef DIAGNOSTIC 501 if (m->m_type != MT_SONAME) 502 panic("receive 1a"); 503 #endif 504 orig_resid = 0; 505 if (flags & MSG_PEEK) { 506 m = m->m_next; 507 } else { 508 sbfree(&so->so_rcv, m); 509 MFREE(m, so->so_rcv.sb_mb); 510 m = so->so_rcv.sb_mb; 511 } 512 } 513 while (m && m->m_type == MT_CONTROL && error == 0) { 514 if (flags & MSG_PEEK) { 515 m = m->m_next; 516 } else { 517 sbfree(&so->so_rcv, m); 518 MFREE(m, so->so_rcv.sb_mb); 519 m = so->so_rcv.sb_mb; 520 } 521 } 522 523 /* 524 * If m is non-NULL, we have some data to read. From now on, 525 * make sure to keep sb_lastrecord consistent when working on 526 * the last packet on the chain (nextrecord == NULL) and we 527 * change m->m_nextpkt. 528 */ 529 if (m) { 530 if ((flags & MSG_PEEK) == 0) { 531 m->m_nextpkt = nextrecord; 532 /* 533 * If nextrecord == NULL (this is a single chain), 534 * then sb_lastrecord may not be valid here if m 535 * was changed earlier. 536 */ 537 if (nextrecord == NULL) { 538 KASSERT(so->so_rcv.sb_mb == m); 539 so->so_rcv.sb_lastrecord = m; 540 } 541 } 542 type = m->m_type; 543 if (type == MT_OOBDATA) 544 flags |= MSG_OOB; 545 } else { 546 if ((flags & MSG_PEEK) == 0) { 547 KASSERT(so->so_rcv.sb_mb == m); 548 so->so_rcv.sb_mb = nextrecord; 549 SB_EMPTY_FIXUP(&so->so_rcv); 550 } 551 } 552 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 2"); 553 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 2"); 554 555 moff = 0; 556 offset = 0; 557 while (m && resid > 0 && error == 0) { 558 if (m->m_type == MT_OOBDATA) { 559 if (type != MT_OOBDATA) 560 break; 561 } else if (type == MT_OOBDATA) 562 break; 563 #ifdef DIAGNOSTIC 564 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 565 panic("receive 3"); 566 #endif 567 so->so_state &= ~SS_RCVATMARK; 568 len = resid; 569 if (so->so_oobmark && len > so->so_oobmark - offset) 570 len = so->so_oobmark - offset; 571 if (len > m->m_len - moff) 572 len = m->m_len - moff; 573 /* 574 * If mp is set, just pass back the mbufs. 575 * Otherwise copy them out via the uio, then free. 576 * Sockbuf must be consistent here (points to current mbuf, 577 * it points to next record) when we drop priority; 578 * we must note any additions to the sockbuf when we 579 * block interrupts again. 580 */ 581 resid -= len; 582 if (len == m->m_len - moff) { 583 if (m->m_flags & M_EOR) 584 flags |= MSG_EOR; 585 if (flags & MSG_PEEK) { 586 m = m->m_next; 587 moff = 0; 588 } else { 589 nextrecord = m->m_nextpkt; 590 sbfree(&so->so_rcv, m); 591 if (mp) { 592 *mp = m; 593 mp = &m->m_next; 594 so->so_rcv.sb_mb = m = m->m_next; 595 *mp = NULL; 596 } else { 597 MFREE(m, so->so_rcv.sb_mb); 598 m = so->so_rcv.sb_mb; 599 } 600 /* 601 * If m != NULL, we also know that 602 * so->so_rcv.sb_mb != NULL. 603 */ 604 KASSERT(so->so_rcv.sb_mb == m); 605 if (m) { 606 m->m_nextpkt = nextrecord; 607 if (nextrecord == NULL) 608 so->so_rcv.sb_lastrecord = m; 609 } else { 610 so->so_rcv.sb_mb = nextrecord; 611 SB_EMPTY_FIXUP(&so->so_rcv); 612 } 613 SBLASTRECORDCHK(&so->so_rcv, 614 "kttcp_soreceive 3"); 615 SBLASTMBUFCHK(&so->so_rcv, 616 "kttcp_soreceive 3"); 617 } 618 } else { 619 if (flags & MSG_PEEK) 620 moff += len; 621 else { 622 if (mp) 623 *mp = m_copym(m, 0, len, M_WAIT); 624 m->m_data += len; 625 m->m_len -= len; 626 so->so_rcv.sb_cc -= len; 627 } 628 } 629 if (so->so_oobmark) { 630 if ((flags & MSG_PEEK) == 0) { 631 so->so_oobmark -= len; 632 if (so->so_oobmark == 0) { 633 so->so_state |= SS_RCVATMARK; 634 break; 635 } 636 } else { 637 offset += len; 638 if (offset == so->so_oobmark) 639 break; 640 } 641 } 642 if (flags & MSG_EOR) 643 break; 644 /* 645 * If the MSG_WAITALL flag is set (for non-atomic socket), 646 * we must not quit until "uio->uio_resid == 0" or an error 647 * termination. If a signal/timeout occurs, return 648 * with a short count but without error. 649 * Keep sockbuf locked against other readers. 650 */ 651 while (flags & MSG_WAITALL && m == NULL && resid > 0 && 652 !sosendallatonce(so) && !nextrecord) { 653 if (so->so_error || so->so_state & SS_CANTRCVMORE) 654 break; 655 /* 656 * If we are peeking and the socket receive buffer is 657 * full, stop since we can't get more data to peek at. 658 */ 659 if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0) 660 break; 661 /* 662 * If we've drained the socket buffer, tell the 663 * protocol in case it needs to do something to 664 * get it filled again. 665 */ 666 if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb) 667 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, 668 (struct mbuf *)(long)flags, NULL, NULL); 669 SBLASTRECORDCHK(&so->so_rcv, 670 "kttcp_soreceive sbwait 2"); 671 SBLASTMBUFCHK(&so->so_rcv, 672 "kttcp_soreceive sbwait 2"); 673 error = sbwait(&so->so_rcv); 674 if (error) { 675 sbunlock(&so->so_rcv); 676 splx(s); 677 return (0); 678 } 679 if ((m = so->so_rcv.sb_mb) != NULL) 680 nextrecord = m->m_nextpkt; 681 } 682 } 683 684 if (m && pr->pr_flags & PR_ATOMIC) { 685 flags |= MSG_TRUNC; 686 if ((flags & MSG_PEEK) == 0) 687 (void) sbdroprecord(&so->so_rcv); 688 } 689 if ((flags & MSG_PEEK) == 0) { 690 if (m == NULL) { 691 /* 692 * First part is an SB_EMPTY_FIXUP(). Second part 693 * makes sure sb_lastrecord is up-to-date if 694 * there is still data in the socket buffer. 695 */ 696 so->so_rcv.sb_mb = nextrecord; 697 if (so->so_rcv.sb_mb == NULL) { 698 so->so_rcv.sb_mbtail = NULL; 699 so->so_rcv.sb_lastrecord = NULL; 700 } else if (nextrecord->m_nextpkt == NULL) 701 so->so_rcv.sb_lastrecord = nextrecord; 702 } 703 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 4"); 704 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 4"); 705 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 706 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, 707 (struct mbuf *)(long)flags, NULL, NULL); 708 } 709 if (orig_resid == resid && orig_resid && 710 (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { 711 sbunlock(&so->so_rcv); 712 splx(s); 713 goto restart; 714 } 715 716 if (flagsp) 717 *flagsp |= flags; 718 release: 719 sbunlock(&so->so_rcv); 720 splx(s); 721 *done = slen - resid; 722 #if 0 723 printf("soreceive: error %d slen %llu resid %lld\n", error, slen, resid); 724 #endif 725 return (error); 726 } 727