1 /* $NetBSD: kttcp.c,v 1.15 2004/04/22 01:01:40 matt 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.15 2004/04/22 01:01:40 matt 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 proc *p, struct kttcp_io_args *); 90 static int kttcp_recv(struct proc *p, struct kttcp_io_args *); 91 static int kttcp_sosend(struct socket *, unsigned long long, 92 unsigned long long *, struct proc *, int); 93 static int kttcp_soreceive(struct socket *, unsigned long long, 94 unsigned long long *, struct proc *, 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, 103 }; 104 105 void 106 kttcpattach(int count) 107 { 108 /* Do nothing. */ 109 } 110 111 int 112 kttcpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 113 { 114 int error; 115 116 if ((flag & FWRITE) == 0) 117 return EPERM; 118 119 switch (cmd) { 120 case KTTCP_IO_SEND: 121 error = kttcp_send(p, (struct kttcp_io_args *) data); 122 break; 123 124 case KTTCP_IO_RECV: 125 error = kttcp_recv(p, (struct kttcp_io_args *) data); 126 break; 127 128 default: 129 return EINVAL; 130 } 131 132 return error; 133 } 134 135 static int 136 kttcp_send(struct proc *p, struct kttcp_io_args *kio) 137 { 138 struct file *fp; 139 int error; 140 struct timeval t0, t1; 141 unsigned long long len, done; 142 143 if (kio->kio_totalsize >= KTTCP_MAX_XMIT) 144 return EINVAL; 145 146 fp = fd_getfile(p->p_fd, kio->kio_socket); 147 if (fp == NULL) 148 return EBADF; 149 FILE_USE(fp); 150 if (fp->f_type != DTYPE_SOCKET) { 151 FILE_UNUSE(fp, p); 152 return EFTYPE; 153 } 154 155 len = kio->kio_totalsize; 156 microtime(&t0); 157 do { 158 error = kttcp_sosend((struct socket *)fp->f_data, len, 159 &done, p, 0); 160 len -= done; 161 } while (error == 0 && len > 0); 162 163 FILE_UNUSE(fp, p); 164 165 microtime(&t1); 166 if (error != 0) 167 return error; 168 timersub(&t1, &t0, &kio->kio_elapsed); 169 170 kio->kio_bytesdone = kio->kio_totalsize - len; 171 172 return 0; 173 } 174 175 static int 176 kttcp_recv(struct proc *p, struct kttcp_io_args *kio) 177 { 178 struct file *fp; 179 int error; 180 struct timeval t0, t1; 181 unsigned long long len, done; 182 183 if (kio->kio_totalsize > KTTCP_MAX_XMIT) 184 return EINVAL; 185 186 fp = fd_getfile(p->p_fd, kio->kio_socket); 187 if (fp == NULL) 188 return EBADF; 189 FILE_USE(fp); 190 if (fp->f_type != DTYPE_SOCKET) { 191 FILE_UNUSE(fp, p); 192 return EBADF; 193 } 194 len = kio->kio_totalsize; 195 microtime(&t0); 196 do { 197 error = kttcp_soreceive((struct socket *)fp->f_data, 198 len, &done, p, NULL); 199 len -= done; 200 } while (error == 0 && len > 0 && done > 0); 201 202 FILE_UNUSE(fp, p); 203 204 microtime(&t1); 205 if (error == EPIPE) 206 error = 0; 207 if (error != 0) 208 return error; 209 timersub(&t1, &t0, &kio->kio_elapsed); 210 211 kio->kio_bytesdone = kio->kio_totalsize - len; 212 213 return 0; 214 } 215 216 #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) 217 218 /* 219 * Slightly changed version of sosend() 220 */ 221 static int 222 kttcp_sosend(struct socket *so, unsigned long long slen, 223 unsigned long long *done, struct proc *p, int flags) 224 { 225 struct mbuf **mp, *m, *top; 226 long space, len, mlen; 227 int error, s, dontroute, atomic; 228 long long resid; 229 230 atomic = sosendallatonce(so); 231 resid = slen; 232 top = NULL; 233 /* 234 * In theory resid should be unsigned. 235 * However, space must be signed, as it might be less than 0 236 * if we over-committed, and we must use a signed comparison 237 * of space and resid. On the other hand, a negative resid 238 * causes us to loop sending 0-length segments to the protocol. 239 */ 240 if (resid < 0) { 241 error = EINVAL; 242 goto out; 243 } 244 dontroute = 245 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 246 (so->so_proto->pr_flags & PR_ATOMIC); 247 p->p_stats->p_ru.ru_msgsnd++; 248 #define snderr(errno) { error = errno; splx(s); goto release; } 249 250 restart: 251 if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) 252 goto out; 253 do { 254 s = splsoftnet(); 255 if (so->so_state & SS_CANTSENDMORE) 256 snderr(EPIPE); 257 if (so->so_error) { 258 error = so->so_error; 259 so->so_error = 0; 260 splx(s); 261 goto release; 262 } 263 if ((so->so_state & SS_ISCONNECTED) == 0) { 264 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 265 if ((so->so_state & SS_ISCONFIRMING) == 0) 266 snderr(ENOTCONN); 267 } else 268 snderr(EDESTADDRREQ); 269 } 270 space = sbspace(&so->so_snd); 271 if (flags & MSG_OOB) 272 space += 1024; 273 if ((atomic && resid > so->so_snd.sb_hiwat)) 274 snderr(EMSGSIZE); 275 if (space < resid && (atomic || space < so->so_snd.sb_lowat)) { 276 if (so->so_state & SS_NBIO) 277 snderr(EWOULDBLOCK); 278 SBLASTRECORDCHK(&so->so_rcv, 279 "kttcp_soreceive sbwait 1"); 280 SBLASTMBUFCHK(&so->so_rcv, 281 "kttcp_soreceive sbwait 1"); 282 sbunlock(&so->so_snd); 283 error = sbwait(&so->so_snd); 284 splx(s); 285 if (error) 286 goto out; 287 goto restart; 288 } 289 splx(s); 290 mp = ⊤ 291 do { 292 do { 293 if (top == 0) { 294 m = m_gethdr(M_WAIT, MT_DATA); 295 mlen = MHLEN; 296 m->m_pkthdr.len = 0; 297 m->m_pkthdr.rcvif = NULL; 298 } else { 299 m = m_get(M_WAIT, MT_DATA); 300 mlen = MLEN; 301 } 302 if (resid >= MINCLSIZE && space >= MCLBYTES) { 303 m_clget(m, M_WAIT); 304 if ((m->m_flags & M_EXT) == 0) 305 goto nopages; 306 mlen = MCLBYTES; 307 #ifdef MAPPED_MBUFS 308 len = lmin(MCLBYTES, resid); 309 #else 310 if (atomic && top == 0) { 311 len = lmin(MCLBYTES - max_hdr, 312 resid); 313 m->m_data += max_hdr; 314 } else 315 len = lmin(MCLBYTES, resid); 316 #endif 317 space -= len; 318 } else { 319 nopages: 320 len = lmin(lmin(mlen, resid), space); 321 space -= len; 322 /* 323 * For datagram protocols, leave room 324 * for protocol headers in first mbuf. 325 */ 326 if (atomic && top == 0 && len < mlen) 327 MH_ALIGN(m, len); 328 } 329 resid -= len; 330 m->m_len = len; 331 *mp = m; 332 top->m_pkthdr.len += len; 333 if (error) 334 goto release; 335 mp = &m->m_next; 336 if (resid <= 0) { 337 if (flags & MSG_EOR) 338 top->m_flags |= M_EOR; 339 break; 340 } 341 } while (space > 0 && atomic); 342 343 s = splsoftnet(); 344 345 if (so->so_state & SS_CANTSENDMORE) 346 snderr(EPIPE); 347 348 if (dontroute) 349 so->so_options |= SO_DONTROUTE; 350 if (resid > 0) 351 so->so_state |= SS_MORETOCOME; 352 error = (*so->so_proto->pr_usrreq)(so, 353 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 354 top, NULL, NULL, p); 355 if (dontroute) 356 so->so_options &= ~SO_DONTROUTE; 357 if (resid > 0) 358 so->so_state &= ~SS_MORETOCOME; 359 splx(s); 360 361 top = 0; 362 mp = ⊤ 363 if (error) 364 goto release; 365 } while (resid && space > 0); 366 } while (resid); 367 368 release: 369 sbunlock(&so->so_snd); 370 out: 371 if (top) 372 m_freem(top); 373 *done = slen - resid; 374 #if 0 375 printf("sosend: error %d slen %llu resid %lld\n", error, slen, resid); 376 #endif 377 return (error); 378 } 379 380 static int 381 kttcp_soreceive(struct socket *so, unsigned long long slen, 382 unsigned long long *done, struct proc *p, int *flagsp) 383 { 384 struct mbuf *m, **mp; 385 int flags, len, error, s, offset, moff, type; 386 long long orig_resid, resid; 387 const struct protosw *pr; 388 struct mbuf *nextrecord; 389 390 pr = so->so_proto; 391 mp = NULL; 392 type = 0; 393 resid = orig_resid = slen; 394 if (flagsp) 395 flags = *flagsp &~ MSG_EOR; 396 else 397 flags = 0; 398 if (flags & MSG_OOB) { 399 m = m_get(M_WAIT, MT_DATA); 400 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, 401 (struct mbuf *)(long)(flags & MSG_PEEK), NULL, NULL); 402 if (error) 403 goto bad; 404 do { 405 resid -= min(resid, m->m_len); 406 m = m_free(m); 407 } while (resid && error == 0 && m); 408 bad: 409 if (m) 410 m_freem(m); 411 return (error); 412 } 413 if (mp) 414 *mp = NULL; 415 if (so->so_state & SS_ISCONFIRMING && resid) 416 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, NULL); 417 418 restart: 419 if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) 420 return (error); 421 s = splsoftnet(); 422 423 m = so->so_rcv.sb_mb; 424 /* 425 * If we have less data than requested, block awaiting more 426 * (subject to any timeout) if: 427 * 1. the current count is less than the low water mark, 428 * 2. MSG_WAITALL is set, and it is possible to do the entire 429 * receive operation at once if we block (resid <= hiwat), or 430 * 3. MSG_DONTWAIT is not set. 431 * If MSG_WAITALL is set but resid is larger than the receive buffer, 432 * we have to do the receive in sections, and thus risk returning 433 * a short count if a timeout or signal occurs after we start. 434 */ 435 if (m == NULL || (((flags & MSG_DONTWAIT) == 0 && 436 so->so_rcv.sb_cc < resid) && 437 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || 438 ((flags & MSG_WAITALL) && resid <= so->so_rcv.sb_hiwat)) && 439 m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) { 440 #ifdef DIAGNOSTIC 441 if (m == NULL && so->so_rcv.sb_cc) 442 panic("receive 1"); 443 #endif 444 if (so->so_error) { 445 if (m) 446 goto dontblock; 447 error = so->so_error; 448 if ((flags & MSG_PEEK) == 0) 449 so->so_error = 0; 450 goto release; 451 } 452 if (so->so_state & SS_CANTRCVMORE) { 453 if (m) 454 goto dontblock; 455 else 456 goto release; 457 } 458 for (; m; m = m->m_next) 459 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { 460 m = so->so_rcv.sb_mb; 461 goto dontblock; 462 } 463 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 464 (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 465 error = ENOTCONN; 466 goto release; 467 } 468 if (resid == 0) 469 goto release; 470 if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { 471 error = EWOULDBLOCK; 472 goto release; 473 } 474 sbunlock(&so->so_rcv); 475 error = sbwait(&so->so_rcv); 476 splx(s); 477 if (error) 478 return (error); 479 goto restart; 480 } 481 dontblock: 482 /* 483 * On entry here, m points to the first record of the socket buffer. 484 * While we process the initial mbufs containing address and control 485 * info, we save a copy of m->m_nextpkt into nextrecord. 486 */ 487 #ifdef notyet /* XXXX */ 488 if (uio->uio_procp) 489 uio->uio_procp->p_stats->p_ru.ru_msgrcv++; 490 #endif 491 KASSERT(m == so->so_rcv.sb_mb); 492 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 1"); 493 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 1"); 494 nextrecord = m->m_nextpkt; 495 if (pr->pr_flags & PR_ADDR) { 496 #ifdef DIAGNOSTIC 497 if (m->m_type != MT_SONAME) 498 panic("receive 1a"); 499 #endif 500 orig_resid = 0; 501 if (flags & MSG_PEEK) { 502 m = m->m_next; 503 } else { 504 sbfree(&so->so_rcv, m); 505 MFREE(m, so->so_rcv.sb_mb); 506 m = so->so_rcv.sb_mb; 507 } 508 } 509 while (m && m->m_type == MT_CONTROL && error == 0) { 510 if (flags & MSG_PEEK) { 511 m = m->m_next; 512 } else { 513 sbfree(&so->so_rcv, m); 514 MFREE(m, so->so_rcv.sb_mb); 515 m = so->so_rcv.sb_mb; 516 } 517 } 518 519 /* 520 * If m is non-NULL, we have some data to read. From now on, 521 * make sure to keep sb_lastrecord consistent when working on 522 * the last packet on the chain (nextrecord == NULL) and we 523 * change m->m_nextpkt. 524 */ 525 if (m) { 526 if ((flags & MSG_PEEK) == 0) { 527 m->m_nextpkt = nextrecord; 528 /* 529 * If nextrecord == NULL (this is a single chain), 530 * then sb_lastrecord may not be valid here if m 531 * was changed earlier. 532 */ 533 if (nextrecord == NULL) { 534 KASSERT(so->so_rcv.sb_mb == m); 535 so->so_rcv.sb_lastrecord = m; 536 } 537 } 538 type = m->m_type; 539 if (type == MT_OOBDATA) 540 flags |= MSG_OOB; 541 } else { 542 if ((flags & MSG_PEEK) == 0) { 543 KASSERT(so->so_rcv.sb_mb == m); 544 so->so_rcv.sb_mb = nextrecord; 545 SB_EMPTY_FIXUP(&so->so_rcv); 546 } 547 } 548 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 2"); 549 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 2"); 550 551 moff = 0; 552 offset = 0; 553 while (m && resid > 0 && error == 0) { 554 if (m->m_type == MT_OOBDATA) { 555 if (type != MT_OOBDATA) 556 break; 557 } else if (type == MT_OOBDATA) 558 break; 559 #ifdef DIAGNOSTIC 560 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 561 panic("receive 3"); 562 #endif 563 so->so_state &= ~SS_RCVATMARK; 564 len = resid; 565 if (so->so_oobmark && len > so->so_oobmark - offset) 566 len = so->so_oobmark - offset; 567 if (len > m->m_len - moff) 568 len = m->m_len - moff; 569 /* 570 * If mp is set, just pass back the mbufs. 571 * Otherwise copy them out via the uio, then free. 572 * Sockbuf must be consistent here (points to current mbuf, 573 * it points to next record) when we drop priority; 574 * we must note any additions to the sockbuf when we 575 * block interrupts again. 576 */ 577 resid -= len; 578 if (len == m->m_len - moff) { 579 if (m->m_flags & M_EOR) 580 flags |= MSG_EOR; 581 if (flags & MSG_PEEK) { 582 m = m->m_next; 583 moff = 0; 584 } else { 585 nextrecord = m->m_nextpkt; 586 sbfree(&so->so_rcv, m); 587 if (mp) { 588 *mp = m; 589 mp = &m->m_next; 590 so->so_rcv.sb_mb = m = m->m_next; 591 *mp = NULL; 592 } else { 593 MFREE(m, so->so_rcv.sb_mb); 594 m = so->so_rcv.sb_mb; 595 } 596 /* 597 * If m != NULL, we also know that 598 * so->so_rcv.sb_mb != NULL. 599 */ 600 KASSERT(so->so_rcv.sb_mb == m); 601 if (m) { 602 m->m_nextpkt = nextrecord; 603 if (nextrecord == NULL) 604 so->so_rcv.sb_lastrecord = m; 605 } else { 606 so->so_rcv.sb_mb = nextrecord; 607 SB_EMPTY_FIXUP(&so->so_rcv); 608 } 609 SBLASTRECORDCHK(&so->so_rcv, 610 "kttcp_soreceive 3"); 611 SBLASTMBUFCHK(&so->so_rcv, 612 "kttcp_soreceive 3"); 613 } 614 } else { 615 if (flags & MSG_PEEK) 616 moff += len; 617 else { 618 if (mp) 619 *mp = m_copym(m, 0, len, M_WAIT); 620 m->m_data += len; 621 m->m_len -= len; 622 so->so_rcv.sb_cc -= len; 623 } 624 } 625 if (so->so_oobmark) { 626 if ((flags & MSG_PEEK) == 0) { 627 so->so_oobmark -= len; 628 if (so->so_oobmark == 0) { 629 so->so_state |= SS_RCVATMARK; 630 break; 631 } 632 } else { 633 offset += len; 634 if (offset == so->so_oobmark) 635 break; 636 } 637 } 638 if (flags & MSG_EOR) 639 break; 640 /* 641 * If the MSG_WAITALL flag is set (for non-atomic socket), 642 * we must not quit until "uio->uio_resid == 0" or an error 643 * termination. If a signal/timeout occurs, return 644 * with a short count but without error. 645 * Keep sockbuf locked against other readers. 646 */ 647 while (flags & MSG_WAITALL && m == NULL && resid > 0 && 648 !sosendallatonce(so) && !nextrecord) { 649 if (so->so_error || so->so_state & SS_CANTRCVMORE) 650 break; 651 /* 652 * If we are peeking and the socket receive buffer is 653 * full, stop since we can't get more data to peek at. 654 */ 655 if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0) 656 break; 657 /* 658 * If we've drained the socket buffer, tell the 659 * protocol in case it needs to do something to 660 * get it filled again. 661 */ 662 if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb) 663 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, 664 (struct mbuf *)(long)flags, NULL, NULL); 665 SBLASTRECORDCHK(&so->so_rcv, 666 "kttcp_soreceive sbwait 2"); 667 SBLASTMBUFCHK(&so->so_rcv, 668 "kttcp_soreceive sbwait 2"); 669 error = sbwait(&so->so_rcv); 670 if (error) { 671 sbunlock(&so->so_rcv); 672 splx(s); 673 return (0); 674 } 675 if ((m = so->so_rcv.sb_mb) != NULL) 676 nextrecord = m->m_nextpkt; 677 } 678 } 679 680 if (m && pr->pr_flags & PR_ATOMIC) { 681 flags |= MSG_TRUNC; 682 if ((flags & MSG_PEEK) == 0) 683 (void) sbdroprecord(&so->so_rcv); 684 } 685 if ((flags & MSG_PEEK) == 0) { 686 if (m == NULL) { 687 /* 688 * First part is an SB_EMPTY_FIXUP(). Second part 689 * makes sure sb_lastrecord is up-to-date if 690 * there is still data in the socket buffer. 691 */ 692 so->so_rcv.sb_mb = nextrecord; 693 if (so->so_rcv.sb_mb == NULL) { 694 so->so_rcv.sb_mbtail = NULL; 695 so->so_rcv.sb_lastrecord = NULL; 696 } else if (nextrecord->m_nextpkt == NULL) 697 so->so_rcv.sb_lastrecord = nextrecord; 698 } 699 SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 4"); 700 SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 4"); 701 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 702 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, 703 (struct mbuf *)(long)flags, NULL, NULL); 704 } 705 if (orig_resid == resid && orig_resid && 706 (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { 707 sbunlock(&so->so_rcv); 708 splx(s); 709 goto restart; 710 } 711 712 if (flagsp) 713 *flagsp |= flags; 714 release: 715 sbunlock(&so->so_rcv); 716 splx(s); 717 *done = slen - resid; 718 #if 0 719 printf("soreceive: error %d slen %llu resid %lld\n", error, slen, resid); 720 #endif 721 return (error); 722 } 723