00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include "rq.h"
00055
00056 ReassemblyQueue::seginfo* ReassemblyQueue::freelist_ = NULL;
00057
00058 ReassemblyQueue::seginfo* ReassemblyQueue::newseginfo()
00059 {
00060 seginfo *s;
00061
00062 if( (s = freelist_) ){
00063 freelist_ = s->next_;
00064 return s;
00065 }else{
00066 return new seginfo;
00067 }
00068 }
00069
00070 void ReassemblyQueue::deleteseginfo(ReassemblyQueue::seginfo* s)
00071 {
00072 s->next_ = freelist_;
00073 freelist_ = s;
00074 }
00075
00076
00077
00078
00079 void
00080 ReassemblyQueue::fremove(seginfo* p)
00081 {
00082 if (hint_ == p)
00083 hint_ = NULL;
00084
00085 if (p->prev_)
00086 p->prev_->next_ = p->next_;
00087 else
00088 head_ = p->next_;
00089 if (p->next_)
00090 p->next_->prev_ = p->prev_;
00091 else
00092 tail_ = p->prev_;
00093 }
00094
00095
00096
00097
00098 void
00099 ReassemblyQueue::sremove(seginfo* p)
00100 {
00101 if (hint_ == p)
00102 hint_ = NULL;
00103
00104 if (p->sprev_)
00105 p->sprev_->snext_ = p->snext_;
00106 else
00107 top_ = p->snext_;
00108 if (p->snext_)
00109 p->snext_->sprev_ = p->sprev_;
00110 else
00111 bottom_ = p->sprev_;
00112
00113 }
00114
00115
00116
00117
00118 void
00119 ReassemblyQueue::push(seginfo *p)
00120 {
00121 p->snext_ = top_;
00122 p->sprev_ = NULL;
00123 top_ = p;
00124 if (p->snext_)
00125 p->snext_->sprev_ = p;
00126 else
00127 bottom_ = p;
00128 }
00129
00130
00131
00132
00133
00134 void
00135 ReassemblyQueue::cnts(seginfo *p, int& blkcnt, int& bytecnt)
00136 {
00137 int blks = 0;
00138 int bytes = 0;
00139
00140 while (p != NULL) {
00141 ++blks;
00142 bytes += (p->endseq_ - p->startseq_);
00143 p = p->next_;
00144 }
00145 blkcnt = blks;
00146 bytecnt = bytes;
00147 return;
00148 }
00149
00150
00151
00152
00153
00154
00155 void
00156 ReassemblyQueue::clear()
00157 {
00158
00159 tail_ = top_ = bottom_ = hint_ = NULL;
00160
00161 seginfo *p = head_;
00162 while (head_) {
00163 p = head_;
00164 head_= head_->next_;
00165 ReassemblyQueue::deleteseginfo(p);
00166 }
00167 tail_ = NULL;
00168 total_ = 0;
00169 return;
00170 }
00171
00172
00173
00174
00175
00176
00177 TcpFlag
00178 ReassemblyQueue::clearto(TcpSeq seq)
00179 {
00180 TcpFlag flag = 0;
00181 seginfo *p = head_, *q;
00182 while (p) {
00183 if (p->endseq_ <= seq) {
00184 q = p->next_;
00185 flag |= p->pflags_;
00186 total_ -= (p->endseq_ - p->startseq_);
00187 sremove(p);
00188 fremove(p);
00189 ReassemblyQueue::deleteseginfo(p);
00190 p = q;
00191 } else
00192 break;
00193 }
00194
00195 if (p && p->startseq_ <= seq && p->endseq_ > seq) {
00196 total_ -= (seq - p->startseq_);
00197 p->startseq_ = seq;
00198 flag |= p->pflags_;
00199 }
00200 return flag;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 int
00214 ReassemblyQueue::gensack(int *sacks, int maxsblock)
00215 {
00216 seginfo *p = top_;
00217 int cnt = maxsblock;
00218
00219 while (p && maxsblock) {
00220 *sacks++ = p->startseq_;
00221 *sacks++ = p->endseq_;
00222 --maxsblock;
00223 p = p->snext_;
00224 }
00225 return (cnt - maxsblock);
00226 }
00227
00228
00229
00230
00231
00232 void
00233 ReassemblyQueue::dumplist()
00234 {
00235
00236 printf("FIFO [size:%d]: ", total_);
00237 if (head_ == NULL) {
00238 printf("NULL\n");
00239 } else {
00240 register seginfo* p = head_;
00241 while (p != NULL) {
00242 if (p->rqflags_ & RQF_MARK) {
00243 printf("OOPS: LOOP1\n");
00244 abort();
00245 }
00246 printf("[->%d, %d<-<f:0x%x,c:%d>]",
00247 p->startseq_, p->endseq_, p->pflags_, p->cnt_);
00248 p->rqflags_ |= RQF_MARK;
00249 p = p->next_;
00250 }
00251 printf("\n");
00252 p = tail_;
00253 while (p != NULL) {
00254 printf("[->%d, %d<-]",
00255 p->startseq_, p->endseq_);
00256 p = p->prev_;
00257 }
00258 printf("\n");
00259 }
00260
00261 printf("LIFO: ");
00262 if (top_ == NULL) {
00263 printf("NULL\n");
00264 } else {
00265 register seginfo* s = top_;
00266 while (s != NULL) {
00267 if (s->rqflags_ & RQF_MARK)
00268 s->rqflags_ &= ~RQF_MARK;
00269 else {
00270 printf("OOPS: LOOP2\n");
00271 abort();
00272 }
00273 printf("[->%d, %d<-]",
00274 s->startseq_, s->endseq_);
00275 s = s->snext_;
00276 }
00277 printf("\n");
00278 s = bottom_;
00279 while (s != NULL) {
00280 printf("[->%d, %d<-]",
00281 s->startseq_, s->endseq_);
00282 s = s->sprev_;
00283 }
00284 printf("\n");
00285 }
00286 printf("RCVNXT: %d\n", rcv_nxt_);
00287 printf("\n");
00288 fflush(stdout);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 TcpFlag
00306 ReassemblyQueue::add(TcpSeq start, TcpSeq end, TcpFlag tiflags, RqFlag rqflags)
00307 {
00308
00309 int needmerge = FALSE;
00310 int altered = FALSE;
00311 int initcnt = 1;
00312
00313 if (end < start) {
00314 fprintf(stderr, "ReassemblyQueue::add() - end(%d) before start(%d)\n",
00315 end, start);
00316 abort();
00317 }
00318
00319 if (head_ == NULL) {
00320 if (top_ != NULL) {
00321 fprintf(stderr, "ReassemblyQueue::add() - problem: FIFO empty, LIFO not\n");
00322 abort();
00323 }
00324
00325
00326
00327
00328 tail_ = head_ = top_ = bottom_ = ReassemblyQueue::newseginfo();
00329 head_->prev_ = head_->next_ = head_->snext_ = head_->sprev_ = NULL;
00330 head_->startseq_ = start;
00331 head_->endseq_ = end;
00332 head_->pflags_ = tiflags;
00333 head_->rqflags_ = rqflags;
00334 head_->cnt_ = initcnt;
00335
00336 total_ = (end - start);
00337
00338
00339
00340
00341 if (rcv_nxt_ >= start)
00342 rcv_nxt_ = end;
00343
00344 return (tiflags);
00345 } else {
00346
00347 again2:
00348 seginfo *p = NULL, *q = NULL, *n, *r;
00349
00350
00351
00352
00353
00354
00355
00356 if (start >= tail_->endseq_) {
00357
00358 p = tail_;
00359 if (start == tail_->endseq_)
00360 needmerge = TRUE;
00361 goto endfast;
00362 }
00363
00364 if (end <= head_->startseq_) {
00365
00366 q = head_;
00367 if (end == head_->startseq_)
00368 needmerge = TRUE;
00369 goto endfast;
00370 }
00371
00372
00373
00374
00375
00376 q = head_;
00377 while (q && q->startseq_ < end)
00378 q = q->next_;
00379
00380 p = tail_;
00381 while (p && p->endseq_ > start)
00382 p = p->prev_;
00383
00384 #ifdef notdef
00385 printf("Thinking of merging (s:%d, e:%d), p:%p (%d,%d), q:%p (%d,%d) into: \n",
00386 start, end, p, q,
00387 p ? p->startseq_ : 0,
00388 p ? p->endseq_ : 0,
00389 q ? n->startseq_ : 0,
00390 q ? n->endseq_ : 0);
00391 #endif
00392
00393
00394
00395
00396
00397 r = p ? p : head_;
00398 while (r && r != q) {
00399 if (start == r->startseq_ && end == r->endseq_) {
00400
00401 r->pflags_ |= tiflags;
00402 if (RQC_CNTDUPS == TRUE)
00403 r->cnt_++;
00404 return (r->pflags_);
00405 } else if (start <= r->startseq_ && end >= r->endseq_) {
00406
00407 total_ -= (r->endseq_ - r->startseq_);
00408 n = r;
00409 r = r->next_;
00410 tiflags |= n->pflags_;
00411 initcnt += n->cnt_;
00412 fremove(n);
00413 sremove(n);
00414 ReassemblyQueue::deleteseginfo(n);
00415 altered = TRUE;
00416 } else
00417 r = r->next_;
00418 }
00419
00420
00421
00422
00423
00425
00426 if (empty())
00427 goto endfast;
00428
00429 if (altered) {
00430 altered = FALSE;
00431 goto again2;
00432 }
00433
00434
00435
00436 if (p == NULL || p->next_->startseq_ < start) {
00437 if (p == NULL)
00438 p = head_;
00439 else
00440 p = p->next_;
00441
00442 if (start < p->startseq_) {
00443 total_ += (p->startseq_ - start);
00444 p->startseq_ = start;
00445 }
00446 start = p->endseq_;
00447 needmerge = TRUE;
00448 p->pflags_ |= tiflags;
00449 p->cnt_++;
00450 --initcnt;
00451 }
00452
00453
00454
00455 if (q == NULL || q->prev_->endseq_ > end) {
00456 if (q == NULL)
00457 q = tail_;
00458 else
00459 q = q->prev_;
00460
00461 if (end > q->endseq_) {
00462 total_ += (end - q->endseq_);
00463 q->endseq_ = end;
00464 }
00465 end = q->startseq_;
00466 needmerge = TRUE;
00467 q->pflags_ |= tiflags;
00468 if (!needmerge) {
00469
00470
00471
00472
00473 q->cnt_++;
00474 --initcnt;
00475 }
00476 }
00477
00478
00479 if (end <= start) {
00480 if (rcv_nxt_ >= head_->startseq_)
00481 rcv_nxt_ = head_->endseq_;
00482 return (tiflags);
00483 }
00484
00485
00486
00487
00488
00489
00490
00491 if (!needmerge && p->next_ == q && p->endseq_ <= start && q->startseq_ >= end) {
00492 if (p->endseq_ == start || q->startseq_ == end)
00493 needmerge = TRUE;
00494 }
00495
00496 endfast:
00497 n = ReassemblyQueue::newseginfo();
00498 n->startseq_ = start;
00499 n->endseq_ = end;
00500 n->pflags_ = tiflags;
00501 n->rqflags_ = rqflags;
00502 n->cnt_= initcnt;
00503
00504 n->prev_ = p;
00505 n->next_ = q;
00506
00507 push(n);
00508
00509 if (p)
00510 p->next_ = n;
00511 else
00512 head_ = n;
00513
00514 if (q)
00515 q->prev_ = n;
00516 else
00517 tail_ = n;
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 total_ += (end - start);
00530
00531 if (needmerge)
00532 return(coalesce(p, n, q));
00533 else if (rcv_nxt_ >= start) {
00534 rcv_nxt_ = end;
00535 }
00536
00537 return tiflags;
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546 TcpFlag
00547 ReassemblyQueue::coalesce(seginfo *p, seginfo *n, seginfo *q)
00548 {
00549 TcpFlag flags = 0;
00550
00551 #ifdef RQDEBUG
00552 printf("coalesce(%p,%p,%p)\n", p, n, q);
00553 printf(" [(%d,%d),%d],[(%d,%d),%d],[(%d,%d),%d]\n",
00554 p ? p->startseq_ : 0,
00555 p ? p->endseq_ : 0,
00556 p ? p->cnt_ : -1000,
00557 n ? n->startseq_ : 0,
00558 n ? n->endseq_ : 0,
00559 n ? n->cnt_ : -1000,
00560 q ? n->startseq_ : 0,
00561 q ? n->endseq_ : 0,
00562 q ? n->cnt_ : -1000);
00563 dumplist();
00564 #endif
00565
00566 if (p && q && p->endseq_ == n->startseq_ && n->endseq_ == q->startseq_) {
00567
00568
00569 sremove(n);
00570 fremove(n);
00571 sremove(q);
00572 fremove(q);
00573 p->endseq_ = q->endseq_;
00574 p->cnt_ += (n->cnt_ + q->cnt_);
00575 flags = (p->pflags_ |= n->pflags_);
00576 ReassemblyQueue::deleteseginfo(n);
00577 ReassemblyQueue::deleteseginfo(q);
00578 } else if (p && (p->endseq_ == n->startseq_)) {
00579
00580
00581 sremove(n);
00582 fremove(n);
00583 p->endseq_ = n->endseq_;
00584 flags = (p->pflags_ |= n->pflags_);
00585 p->cnt_ += n->cnt_;
00586 ReassemblyQueue::deleteseginfo(n);
00587 } else if (q && (n->endseq_ == q->startseq_)) {
00588
00589
00590 sremove(n);
00591 fremove(n);
00592 q->startseq_ = n->startseq_;
00593 flags = (q->pflags_ |= n->pflags_);
00594 q->cnt_ += n->cnt_;
00595 ReassemblyQueue::deleteseginfo(n);
00596 p = q;
00597 }
00598
00599
00600
00601
00602
00603
00604 if (rcv_nxt_ >= p->startseq_)
00605 rcv_nxt_ = p->endseq_;
00606 return (flags);
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 int
00618 ReassemblyQueue::nexthole(TcpSeq seq, int& nxtcnt, int& nxtbytes)
00619 {
00620
00621 nxtbytes = nxtcnt = -1;
00622 hint_ = head_;
00623
00624 seginfo* p;
00625 for (p = hint_; p; p = p->next_) {
00626
00627
00628 if (p->startseq_ > seq) {
00629 cnts(p, nxtcnt, nxtbytes);
00630 return (seq);
00631 }
00632
00633
00634
00635 if ((p->startseq_ <= seq) && (p->endseq_ >= seq)) {
00636 if (p->next_) {
00637 cnts(p->next_, nxtcnt, nxtbytes);
00638 }
00639 return (p->endseq_);
00640 }
00641 }
00642 return (-1);
00643 }
00644
00645
00646 #ifdef RQDEBUG
00647 main()
00648 {
00649 int rcvnxt = 1;
00650 ReassemblyQueue rq(rcvnxt);
00651
00652 static int blockstore[64];
00653 int *blocks = blockstore;
00654 int nblocks = 5;
00655 int i;
00656
00657 printf("Simple---\n");
00658 rq.add(2, 4, 0, 0);
00659 rq.add(6, 8, 0, 0);
00660 printf("D1\n");
00661 rq.dumplist();
00662
00663 rq.add(1,2, 0, 0);
00664 printf("D2\n");
00665 rq.dumplist();
00666
00667 rq.add(8, 10, 0, 00);
00668 printf("D3\n");
00669 rq.dumplist();
00670
00671 rq.add(4, 6, 0, 0);
00672 printf("Simple output:\n");
00673 rq.dumplist();
00674
00675 printf("X0:\n");
00676 rq.init(1);
00677 rq.add(5,10, 0, 0);
00678 rq.add(11,20, 0, 0);
00679 rq.add(5,10, 0, 0);
00680 rq.dumplist();
00681
00682 printf("X1:\n");
00683 rq.init(1);
00684 rq.add(5,10, 0, 0);
00685 rq.add(11,20, 0, 0);
00686 rq.add(11,20, 0, 0);
00687 rq.dumplist();
00688
00689 printf("X2:\n");
00690 rq.init(1);
00691 rq.add(5,10, 0, 0);
00692 rq.add(11,20, 0, 0);
00693 rq.add(30, 40, 0, 0);
00694 rq.add(11,20, 0, 0);
00695 rq.dumplist();
00696
00697 printf("X3\n");
00698 rq.add(30,50,0,0);
00699 rq.dumplist();
00700
00701 printf("X4\n");
00702 rq.add(1,10,0,0);
00703 rq.dumplist();
00704
00705 printf("C1:\n");
00706 rq.init(1);
00707 rq.add(2, 4, 0, 0);
00708 rq.add(1, 4, 0, 0);
00709 rq.dumplist();
00710
00711 printf("C2:\n");
00712 rq.init(1);
00713 rq.add(2, 4, 0, 0);
00714 rq.add(1, 3, 0, 0);
00715 rq.dumplist();
00716
00717 printf("C3:\n");
00718 rq.init(1);
00719 rq.add(2, 4, 0, 0);
00720 rq.add(2, 7, 0, 0);
00721 rq.dumplist();
00722
00723 printf("C4:\n");
00724 rq.init(1);
00725 rq.add(2, 4, 0, 0);
00726 rq.add(3, 7, 0, 0);
00727 rq.dumplist();
00728
00729 printf("C5:\n");
00730 rq.init(1);
00731 rq.add(2, 4, 0, 0);
00732 rq.add(6, 8, 0, 0);
00733 rq.add(1, 9, 0, 0);
00734 rq.dumplist();
00735
00736 printf("C6:\n");
00737 rq.init(1);
00738 rq.add(2, 4, 0, 0);
00739 rq.add(6, 8, 0, 0);
00740 rq.add(15, 20, 0, 0);
00741 rq.dumplist();
00742 rq.add(5, 9, 0, 0);
00743 rq.dumplist();
00744
00745 printf("C7:\n");
00746 rq.init(1);
00747 rq.add(1, 2, 0, 0);
00748 rq.add(3, 5, 0, 0);
00749 rq.add(6, 8, 0, 0);
00750 rq.add(9, 10, 0, 0);
00751 rq.dumplist();
00752 rq.add(4, 7, 0, 0);
00753 rq.dumplist();
00754
00755 printf("C8:\n");
00756 rq.init(1);
00757 rq.add(1, 2, 0, 0);
00758 rq.add(3, 5, 0, 0);
00759 rq.add(10, 12, 0, 0);
00760 rq.add(20, 30, 0, 0);
00761 rq.dumplist();
00762 rq.add(4, 8, 0, 0);
00763 rq.dumplist();
00764
00765 rq.init(1);
00766 rq.add(1, 5, 0, 0);
00767 rq.add(10, 20, 0, 0);
00768
00769
00770
00771 rq.dumplist();
00772
00773 rq.add(1, 5, 0, 0);
00774 rq.dumplist();
00775
00776 int x, y;
00777 printf("NH1: %d\n", rq.nexthole(3, x, y));
00778 printf("NH2: %d\n", rq.nexthole(5, x, y));
00779 printf("CLR to 4\n");
00780 rq.clearto(4);
00781 rq.dumplist();
00782
00783 exit(0);
00784 }
00785 #endif
00786