Changeset 14232 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Nov 17, 2008 7:25:28 AM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/ip.h
r14229 r14232 255 255 ipasfragp_32 ipq_next,ipq_prev; /* to ip headers of fragments */ 256 256 #else /* !VBOX_WITH_BSD_REASS */ 257 u_int8_t ipq_nfrags; /* # of fragments in this packet */ 257 258 struct mbuf *ipq_frags; /* to ip headers of fragments */ 258 259 #endif /* VBOX_WITH_BSD_REASS */ -
trunk/src/VBox/Devices/Network/slirp/ip_input.c
r14228 r14232 60 60 for (i = 0; i < IPREASS_NHASH; ++i) 61 61 TAILQ_INIT(&ipq[i]); 62 maxnipq = 100; /* ??? */ 63 maxfragsperpacket = 16; 64 nipq = 0; 62 65 #endif /* VBOX_WITH_BSD_REASS */ 63 66 ip_currid = tt.tv_sec & 0xffff; … … 208 211 ip->ip_len -= hlen; 209 212 #else /* !VBOX_WITH_BSD_REASS */ 213 if (ip->ip_off & (IP_MF | IP_OFFMASK)) { 214 m = ip_reass(pData, m); 215 if (m == NULL) 216 return; 217 ip = mtod(m, struct ip *); 218 hlen = ip->ip_len; 219 } 220 else 221 ip->ip_len -= hlen; 210 222 #endif /* !VBOX_WITH_BSD_REASS */ 211 223 … … 415 427 struct mbuf * 416 428 ip_reass(PNATState pData, struct mbuf* m) { 429 struct ip *ip; 430 struct mbuf *p, *q, *nq, *t; 431 struct ipq_t *fp = NULL; 432 struct ipqhead *head; 433 int i, hlen, next; 434 u_int8_t ecn, ecn0; 435 u_short hash; 436 437 /* If maxnipq or maxfragsperpacket are 0, never accept fragments. */ 438 if (maxnipq == 0 439 || maxfragsperpacket == 0) { 440 ipstat.ips_fragments++; 441 ipstat.ips_fragdropped++; 442 m_freem(pData, m); 443 return (NULL); 444 } 445 446 ip = mtod(m, struct ip *); 447 hlen = ip->ip_hl << 2; 448 449 hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); 450 head = &ipq[hash]; 451 452 /* 453 * Look for queue of fragments 454 * of this datagram. 455 */ 456 TAILQ_FOREACH(fp, head, ipq_list) 457 if (ip->ip_id == fp->ipq_id && 458 ip->ip_src.s_addr == fp->ipq_src.s_addr && 459 ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 460 ip->ip_p == fp->ipq_p) 461 goto found; 462 463 fp = NULL; 464 465 /* 466 * Attempt to trim the number of allocated fragment queues if it 467 * exceeds the administrative limit. 468 */ 469 if ((nipq > maxnipq) && (maxnipq > 0)) { 470 /* 471 * drop something from the tail of the current queue 472 * before proceeding further 473 */ 474 struct ipq_t *q = TAILQ_LAST(head, ipqhead); 475 if (q == NULL) { /* gak */ 476 for (i = 0; i < IPREASS_NHASH; i++) { 477 struct ipq_t *r = TAILQ_LAST(&ipq[i], ipqhead); 478 if (r) { 479 ipstat.ips_fragtimeout += r->ipq_nfrags; 480 ip_freef(pData, &ipq[i], r); 481 break; 482 } 483 } 484 } else { 485 ipstat.ips_fragtimeout += q->ipq_nfrags; 486 ip_freef(pData, head, q); 487 } 488 } 489 490 found: 491 /* 492 * Adjust ip_len to not reflect header, 493 * convert offset of this to bytes. 494 */ 495 ip->ip_len -= hlen; 496 if (ip->ip_off & IP_MF) { 497 /* 498 * Make sure that fragments have a data length 499 * that's a non-zero multiple of 8 bytes. 500 */ 501 if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { 502 ipstat.ips_toosmall++; /* XXX */ 503 goto dropfrag; 504 } 505 m->m_flags |= M_FRAG; 506 } else 507 m->m_flags &= ~M_FRAG; 508 ip->ip_off <<= 3; 509 510 511 /* 512 * Attempt reassembly; if it succeeds, proceed. 513 * ip_reass() will return a different mbuf. 514 */ 515 ipstat.ips_fragments++; 516 m->m_data = (void *)ip; 517 518 /* Previous ip_reass() started here. */ 519 /* 520 * Presence of header sizes in mbufs 521 * would confuse code below. 522 */ 523 m->m_data += hlen; 524 m->m_len -= hlen; 525 526 /* 527 * If first fragment to arrive, create a reassembly queue. 528 */ 529 if (fp == NULL) { 530 fp = malloc(sizeof(struct ipq_t)); 531 if (fp == NULL) 532 goto dropfrag; 533 TAILQ_INSERT_HEAD(head, fp, ipq_list); 534 nipq++; 535 fp->ipq_nfrags = 1; 536 fp->ipq_ttl = IPFRAGTTL; 537 fp->ipq_p = ip->ip_p; 538 fp->ipq_id = ip->ip_id; 539 fp->ipq_src = ip->ip_src; 540 fp->ipq_dst = ip->ip_dst; 541 fp->ipq_frags = m; 542 m->m_nextpkt = NULL; 543 goto done; 544 } else { 545 fp->ipq_nfrags++; 546 } 547 548 #define GETIP(m) ((struct ip*)((m)->m_data)) 549 550 551 /* 552 * Find a segment which begins after this one does. 553 */ 554 for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) 555 if (GETIP(q)->ip_off > ip->ip_off) 556 break; 557 558 /* 559 * If there is a preceding segment, it may provide some of 560 * our data already. If so, drop the data from the incoming 561 * segment. If it provides all of our data, drop us, otherwise 562 * stick new segment in the proper place. 563 * 564 * If some of the data is dropped from the the preceding 565 * segment, then it's checksum is invalidated. 566 */ 567 if (p) { 568 i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off; 569 if (i > 0) { 570 if (i >= ip->ip_len) 571 goto dropfrag; 572 m_adj(m, i); 573 ip->ip_off += i; 574 ip->ip_len -= i; 575 } 576 m->m_nextpkt = p->m_nextpkt; 577 p->m_nextpkt = m; 578 } else { 579 m->m_nextpkt = fp->ipq_frags; 580 fp->ipq_frags = m; 581 } 582 583 /* 584 * While we overlap succeeding segments trim them or, 585 * if they are completely covered, dequeue them. 586 */ 587 for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off; 588 q = nq) { 589 i = (ip->ip_off + ip->ip_len) - GETIP(q)->ip_off; 590 if (i < GETIP(q)->ip_len) { 591 GETIP(q)->ip_len -= i; 592 GETIP(q)->ip_off += i; 593 m_adj(q, i); 594 break; 595 } 596 nq = q->m_nextpkt; 597 m->m_nextpkt = nq; 598 ipstat.ips_fragdropped++; 599 fp->ipq_nfrags--; 600 m_freem(pData, q); 601 } 602 603 /* 604 * Check for complete reassembly and perform frag per packet 605 * limiting. 606 * 607 * Frag limiting is performed here so that the nth frag has 608 * a chance to complete the packet before we drop the packet. 609 * As a result, n+1 frags are actually allowed per packet, but 610 * only n will ever be stored. (n = maxfragsperpacket.) 611 * 612 */ 613 next = 0; 614 for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) { 615 if (GETIP(q)->ip_off != next) { 616 if (fp->ipq_nfrags > maxfragsperpacket) { 617 ipstat.ips_fragdropped += fp->ipq_nfrags; 618 ip_freef(pData, head, fp); 619 } 620 goto done; 621 } 622 next += GETIP(q)->ip_len; 623 } 624 /* Make sure the last packet didn't have the IP_MF flag */ 625 if (p->m_flags & M_FRAG) { 626 if (fp->ipq_nfrags > maxfragsperpacket) { 627 ipstat.ips_fragdropped += fp->ipq_nfrags; 628 ip_freef(pData, head, fp); 629 } 630 goto done; 631 } 632 633 /* 634 * Reassembly is complete. Make sure the packet is a sane size. 635 */ 636 q = fp->ipq_frags; 637 ip = GETIP(q); 638 if (next + (ip->ip_hl << 2) > IP_MAXPACKET) { 639 ipstat.ips_fragdropped += fp->ipq_nfrags; 640 ip_freef(pData, head, fp); 641 goto done; 642 } 643 644 /* 645 * Concatenate fragments. 646 */ 647 m = q; 648 t = m->m_next; 649 m->m_next = NULL; 650 m_cat(pData, m, t); 651 nq = q->m_nextpkt; 652 q->m_nextpkt = NULL; 653 for (q = nq; q != NULL; q = nq) { 654 nq = q->m_nextpkt; 655 q->m_nextpkt = NULL; 656 m_cat(pData, m, q); 657 } 658 659 /* 660 * Create header for new ip packet by modifying header of first 661 * packet; dequeue and discard fragment reassembly header. 662 * Make header visible. 663 */ 664 ip->ip_len = (ip->ip_hl << 2) + next; 665 ip->ip_src = fp->ipq_src; 666 ip->ip_dst = fp->ipq_dst; 667 TAILQ_REMOVE(head, fp, ipq_list); 668 nipq--; 669 free(fp); 670 m->m_len += (ip->ip_hl << 2); 671 m->m_data -= (ip->ip_hl << 2); 672 /* some debugging cruft by sklower, below, will go away soon */ 673 #if 0 674 if (m->m_flags & M_PKTHDR) /* XXX this should be done elsewhere */ 675 m_fixhdr(m); 676 #endif 677 ipstat.ips_reassembled++; 678 return (m); 679 680 dropfrag: 681 ipstat.ips_fragdropped++; 682 if (fp != NULL) 683 fp->ipq_nfrags--; 684 m_freem(pData, m); 685 done: 417 686 return (NULL); 687 688 #undef GETIP 418 689 } 419 690 420 691 void 421 ip_freef(PNATState pData, struct ipq_t *fp) { 692 ip_freef(PNATState pData, struct ipqhead *fhp, struct ipq_t *fp) { 693 struct mbuf *q; 694 695 while (fp->ipq_frags) { 696 q = fp->ipq_frags; 697 fp->ipq_frags = q->m_nextpkt; 698 m_freem(pData, q); 699 } 700 TAILQ_REMOVE(fhp, fp, ipq_list); 701 free(fp); 702 nipq--; 422 703 } 423 704 #endif /* VBOX_WITH_BSD_REASS */ … … 461 742 register struct ipq_t *fp; 462 743 744 #ifndef VBOX_WITH_BSD_REASS 463 745 DEBUG_CALL("ip_slowtimo"); 464 746 465 #ifndef VBOX_WITH_BSD_REASS466 747 fp = u32_to_ptr(pData, ipq.next, struct ipq_t *); 467 748 if (fp == 0) … … 480 761 * additional loop see (see ip_input.c in FreeBSD tree) 481 762 */ 763 int i; 764 DEBUG_CALL("ip_slowtimo"); 765 for (i = 0; i < IPREASS_NHASH; i++) { 766 for(fp = TAILQ_FIRST(&ipq[i]); fp;) { 767 struct ipq_t *fpp; 768 769 fpp = fp; 770 fp = TAILQ_NEXT(fp, ipq_list); 771 if(--fpp->ipq_ttl == 0) { 772 ipstat.ips_fragtimeout += fpp->ipq_nfrags; 773 ip_freef(pData, &ipq[i], fpp); 774 } 775 } 776 } 777 /* 778 * If we are over the maximum number of fragments 779 * (due to the limit being lowered), drain off 780 * enough to get down to the new limit. 781 */ 782 if (maxnipq >= 0 && nipq > maxnipq) { 783 for (i = 0; i < IPREASS_NHASH; i++) { 784 while (nipq > maxnipq && !TAILQ_EMPTY(&ipq[i])) { 785 ipstat.ips_fragdropped += 786 TAILQ_FIRST(&ipq[i])->ipq_nfrags; 787 ip_freef(pData, &ipq[i], TAILQ_FIRST(&ipq[i])); 788 } 789 } 790 } 482 791 #endif /* VBOX_WITH_BSD_REASS */ 483 792 } -
trunk/src/VBox/Devices/Network/slirp/mbuf.h
r14227 r14232 121 121 * it rather than putting it on the free list */ 122 122 #ifdef VBOX_WITH_BSD_REASS 123 #define M_FRAG 0x0800 /* packet is a fragment of a larger packet */ `123 #define M_FRAG 0x0800 /* packet is a fragment of a larger packet */ 124 124 #define M_FIRSTFRAG 0x1000 /* paket is first fragment */ 125 125 #define M_LASTFRAG 0x2000 /* paket is last fragment */ -
trunk/src/VBox/Devices/Network/slirp/slirp.c
r14227 r14232 386 386 int error; 387 387 #endif 388 #ifdef VBOX_WITH_BSD_REASS 389 int i; 390 #endif /* VBOX_WITH_BSD_REASS */ 388 391 389 392 STAM_REL_PROFILE_START(&pData->StatFill, a); … … 406 409 * new macroses 407 410 */ 411 for (i = 0; i < IPREASS_NHASH; i++) { 412 if (!TAILQ_EMPTY(&ipq[i])) { 413 do_slowtimo = 1; 414 break; 415 } 416 } 417 do_slowtimo |= (tcb.so_next != &tcb); 408 418 #endif /* VBOX_WITH_BSD_REASS */ 409 419 -
trunk/src/VBox/Devices/Network/slirp/slirp.h
r14227 r14232 335 335 #ifndef VBOX_WITH_BSD_REASS 336 336 struct ip * ip_reass _P((PNATState, register struct ipasfrag *, register struct ipq_t *)); 337 void ip_freef _P((PNATState, struct ipq_t *)); 337 338 #else /* !VBOX_WITH_BSD_REASS */ 338 339 struct mbuf * ip_reass _P((PNATState, register struct mbuf *)); 340 void ip_freef _P((PNATState, struct ipqhead *, struct ipq_t *)); 339 341 #endif /* VBOX_WITH_BSD_REASS */ 340 void ip_freef _P((PNATState, struct ipq_t *));341 342 void ip_enq _P((PNATState, register struct ipasfrag *, register struct ipasfrag *)); 342 343 void ip_deq _P((PNATState, register struct ipasfrag *)); -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r14228 r14232 73 73 #else /* !VBOX_WITH_BSD_REASS */ 74 74 struct ipqhead ipq[IPREASS_NHASH]; 75 int maxnipq; /* Administrative limit on # of reass queues*/ 76 int maxfragsperpacket; /* Maximum number of IPv4 fragments allowed per packet */ 77 int nipq; /* total number of reass queues */ 75 78 #endif /* VBOX_WITH_BSD_REASS */ 76 79 uint16_t ip_currid; … … 228 231 #define udp_last_so pData->udp_last_so 229 232 233 #ifdef VBOX_WITH_BSD_REASS 234 #define maxfragsperpacket pData->maxfragsperpacket 235 #define maxnipq pData->maxnipq 236 #define nipq pData->nipq 237 #endif /* VBOX_WITH_BSD_REASS */ 238 230 239 231 240 #if SIZEOF_CHAR_P != 4
Note:
See TracChangeset
for help on using the changeset viewer.