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