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
00055
00056
00057
00058 #include <math.h>
00059 #include "agent.h"
00060 #include "tclcl.h"
00061 #include "packet.h"
00062 #include "ip.h"
00063 #include "rtp.h"
00064 #include "lms.h"
00065 #include "rcvbuf.h"
00066
00067 #define LMS_NAK_TIMEOUT 0
00068 #define LMS_RDL_TIMEOUT 1
00069 #define LMS_RFR_TIMEOUT 2
00070
00071 #define LMS_RQL_MAX 10 // requests to remember
00072 #define LMS_RDL_MAX 10 // rdata to remember
00073
00074 #define LMS_LOSS_SMPL_IVL 0 // sample loss every LMS_LOSS_SMPL_IVL packets
00075
00076 #define LMS_COST_THR 1 // change in packet loss required to trigger LMS_REFRESH
00077
00078 static int rcv_uid_ = 0;
00079
00080
00081 class LmsReceiver;
00082 class LmsNak;
00083
00084
00085
00086
00087
00088 class LmsNakTimer : public TimerHandler {
00089 public:
00090 LmsNakTimer(LmsNak *a) : TimerHandler() { a_ = a; }
00091 void expire(Event *e);
00092 protected:
00093 LmsNak *a_;
00094 };
00095
00096
00097
00098
00099 class LmsReceiver: public Agent {
00100 public:
00101 LmsReceiver();
00102 LmsReceiver* next_;
00103 int command (int argc, const char*const* argv);
00104 void recv (Packet* pkt, Handler*);
00105 virtual void timeout (int type, int lo, int hi);
00106
00107 protected:
00108 void handle_lms_pkt (Packet* pkt);
00109 void send_refresh ();
00110 void send_dmcast (hdr_lms* lh, int seqno, int fid);
00111 int add_req (Packet *rq);
00112 void send_nak (int sqn, int lo, int hi);
00113 void create_nak (int lo, int hi);
00114 void delete_nak (LmsNak *n);
00115 LmsNak* find_nak (int i);
00116 void add_rdl (int rseq, double clock);
00117 int exists_rdl (int rseq);
00118 void print_stats ();
00119 void print_all_stats (int drops);
00120
00121 char uname_[8];
00122 RcvBuffer* rcvbuf_;
00123 int dataSize_;
00124 double rtt_;
00125 nsaddr_t lms_src_;
00126 nsaddr_t lms_group_;
00127
00128
00129 nsaddr_t upstream_lms_;
00130 int lms_cost_;
00131 Packet* rql_;
00132 int rql_sz_;
00133 struct lms_rdl* rdl_;
00134 int rdl_sz_;
00135 LmsNak* nak_;
00136
00137
00138 int ls_last_rq_;
00139 int ls_last_seq_;
00140 int ls_smpl_ivl_;
00141 int ls_cntdown_;
00142
00143
00144 int req_sent_;
00145 int req_rcvd_;
00146 int dup_reqs_;
00147 static int max_dup_naks_;
00148
00149
00150
00151
00152
00153 };
00154
00155
00156
00157
00158 class LmsNak {
00159 public:
00160 LmsNak (LmsReceiver *a, int lo, int hi);
00161 LmsNak *next_;
00162 void timeout (int type) {
00163 a_->timeout (type, lo_, hi_); }
00164 LmsNakTimer nak_timer_;
00165 int lo_;
00166 int hi_;
00167 int seqn_;
00168 double nak_timeout_;
00169 private:
00170 LmsReceiver *a_;
00171 int fid_;
00172 };
00173
00174 LmsNak::LmsNak(LmsReceiver *a, int lo, int hi): nak_timer_(this), lo_(lo), hi_(hi), a_(a)
00175 {
00176 seqn_ = 0;
00177 }
00178
00179 void LmsNakTimer::expire(Event *e) {
00180 a_->timeout(LMS_NAK_TIMEOUT);
00181 }
00182
00183 LmsReceiver *all_lms_receivers = 0;
00184
00185 static class LmsReceiverClass : public TclClass {
00186 public:
00187 LmsReceiverClass() : TclClass("Agent/LMS/Receiver") {}
00188 TclObject* create(int, const char*const*) {
00189 return (new LmsReceiver());
00190 }
00191 } class_lms_receiver;
00192
00193
00194
00195
00196 int LmsReceiver::max_dup_naks_ = 0;
00197
00198 LmsReceiver::LmsReceiver(): Agent(PT_LMS)
00199 {
00200 sprintf (uname_, "rcv%d", rcv_uid_++);
00201 lms_cost_ = 0;
00202 lms_src_ = lms_group_ = LMS_NOADDR;
00203 rtt_ = 0.0;
00204 rcvbuf_ = new RcvBuffer;
00205 req_sent_ = req_rcvd_ = dup_reqs_ = max_dup_naks_ = 0;
00206 upstream_lms_ = LMS_NOADDR;
00207 dataSize_ = 0;
00208 ls_smpl_ivl_ = LMS_LOSS_SMPL_IVL;
00209 ls_cntdown_ = ls_smpl_ivl_;
00210 ls_last_rq_ = ls_last_seq_ = 0;
00211 nak_ = NULL;
00212 rql_ = NULL;
00213 rdl_ = NULL;
00214 rdl_sz_ = 0;
00215
00216 this->next_ = all_lms_receivers;
00217 all_lms_receivers = this;
00218
00219 bind("lmsPacketSize_", &size_);
00220
00221
00222
00223
00224 }
00225
00226
00227
00228
00229 void LmsReceiver::send_nak (int sqn, int lo, int hi)
00230 {
00231 Packet* p = allocpkt(sizeof (struct lms_nak));
00232 struct lms_nak *n = (struct lms_nak*)p->accessdata ();
00233
00234 hdr_ip* iph = HDR_IP(p);
00235 hdr_cmn* ch = HDR_CMN(p);
00236
00237 ch->size_ = sizeof(struct lms_nak) + sizeof(hdr_lms);
00238 iph->daddr() = upstream_lms_;
00239 iph->flowid() = 8;
00240 #ifdef LMS_DEBUG
00241 printf("at %f %s send nak to upstream lms %d, size is %d\n\n",
00242 now,uname_, upstream_lms_, (HDR_CMN(p))->size_);
00243 #endif
00244 hdr_lms* lh = HDR_LMS(p);
00245 lh->type_ = LMS_REQ;
00246 lh->from_ = addr();
00247 lh->src_ = lms_src_;
00248 lh->group_ = lms_group_;
00249
00250 lh->tp_addr_ = LMS_NOADDR;
00251 lh->tp_port_ = -1;
00252 lh->tp_iface_ = LMS_NOIFACE;
00253 lh->lo_ = n->nak_lo_ = lo;
00254 lh->hi_ = n->nak_hi_ = hi;
00255 n->nak_seqn_ = sqn;
00256 n->dup_cnt_ = 0;
00257
00258 target_->recv(p);
00259 }
00260
00261
00262
00263
00264 void LmsReceiver::send_refresh ()
00265 {
00266 Packet* p = allocpkt (sizeof (struct lms_ctl));
00267 struct lms_ctl *ctl = (struct lms_ctl*)p->accessdata ();
00268
00269 hdr_ip* iph = HDR_IP(p);
00270 hdr_cmn *ch = HDR_CMN(p);
00271
00272 ch->size_ = sizeof(struct lms_ctl) + sizeof(hdr_lms);
00273 iph->daddr() = upstream_lms_;
00274 iph->flowid() = 7;
00275 #ifdef LMS_DEBUG
00276 printf("%s send refresh packet, size is %d\n\n",
00277 uname_, (HDR_CMN(p))->size_);
00278 #endif
00279 hdr_lms* lh = HDR_LMS(p);
00280 lh->type_ = LMS_REFRESH;
00281 lh->from_ = addr();
00282 lh->src_ = lms_src_;
00283 lh->group_ = lms_group_;
00284
00285 ctl->cost_ = lms_cost_;
00286 ctl->hop_cnt_ = 0;
00287 ctl->downstream_lms_.addr_ = addr();
00288 ctl->downstream_lms_.port_ = port();
00289
00290 target_->recv(p);
00291 }
00292
00293
00294
00295
00296 void LmsReceiver::recv (Packet* pkt, Handler*)
00297 {
00298 hdr_cmn* h = HDR_CMN(pkt);
00299
00300
00301 if (h->ptype_ == PT_LMS)
00302 {
00303 handle_lms_pkt (pkt);
00304 return;
00305 }
00306
00307
00308 double clock = Scheduler::instance().clock();
00309 hdr_rtp* rh = HDR_RTP(pkt);
00310 int rseq = rh->seqno();
00311
00312 dataSize_ = h->size_;
00313
00314 #ifdef LMS_DEBUG
00315 printf ("%s got data pkt %d\n", uname_, rseq);
00316 #endif
00317
00318 if (rcvbuf_->nextpkt_ < rseq)
00319 {
00320 int lo = rcvbuf_->nextpkt_;
00321 int hi = rseq - 1;
00322 req_sent_++;
00323 #ifdef LMS_DEBUG
00324 printf ("%s Sending REQ, lo %d, hi %d\n", uname_, lo, hi);
00325 #endif
00326 create_nak (lo, hi);
00327 send_nak (0, lo, hi);
00328 }
00329
00330 else if (rcvbuf_->nextpkt_ > rseq &&
00331 !rcvbuf_->exists_pkt (rseq))
00332 {
00333 add_rdl (rseq, clock);
00334
00335 LmsNak *nak = find_nak (rseq);
00336 if (nak->lo_ != nak->hi_)
00337 {
00338 if (rseq == nak->lo_)
00339 create_nak (rseq+1, nak->hi_);
00340 else if (rseq == nak->hi_)
00341 create_nak (nak->lo_, rseq-1);
00342 else {
00343 create_nak (nak->lo_, rseq-1);
00344 create_nak (rseq+1, nak->hi_);
00345 }
00346 }
00347 delete_nak (nak);
00348 }
00349
00350 rcvbuf_->add_pkt (rseq, clock);
00351
00352
00353
00354
00355
00356
00357
00358
00359 if (ls_smpl_ivl_ && --ls_cntdown_ == 0)
00360 {
00361 int newcost = req_sent_ - ls_last_rq_;
00362 assert (newcost >= 0);
00363 if (abs (newcost - lms_cost_) >= LMS_COST_THR)
00364 {
00365 lms_cost_ = newcost;
00366 if (newcost > 0)
00367 ls_last_rq_ = req_sent_;
00368 #ifdef LMS_DEBUG
00369 printf ("%s NEW LMS_COST %d\n", uname_, lms_cost_);
00370 #endif
00371 }
00372 send_refresh ();
00373 ls_cntdown_ = ls_smpl_ivl_;
00374 }
00375
00376 Packet::free(pkt);
00377 }
00378
00379
00380
00381
00382 void LmsReceiver::handle_lms_pkt (Packet* pkt)
00383 {
00384 hdr_lms* lh = HDR_LMS(pkt);
00385 hdr_ip* iph = HDR_IP(pkt);
00386 int st = 0;
00387 #ifdef LMS_DEBUG
00388 int a1, a2;
00389 #endif
00390 switch (lh->type())
00391 {
00392 case LMS_REQ:
00393 {
00394 struct lms_nak *n = (struct lms_nak *)pkt->accessdata ();
00395 req_rcvd_++;
00396 #ifdef LMS_DEBUG
00397 a1 = lh->from(); a2 = lh->src();
00398 printf ("%s got LMS_REQ from %d:%d src %d:%d group 0x%x ",
00399 uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group());
00400 printf ("TP: (%d:%d, %d)\n\n", lh->tp_addr_>>8, lh->tp_addr_&0xff, lh->tp_iface_);
00401 #endif
00402 if ((st = add_req (pkt)) != 0)
00403 {
00404 for (int i = lh->lo_; i <= lh->hi_; i++)
00405 if (!(n->nak_seqn_ == 0 && exists_rdl (i)) &&
00406 (rcvbuf_->exists_pkt (i)))
00407 send_dmcast (lh, i, 3);
00408 }
00409 else dup_reqs_++;
00410
00411 break;
00412 }
00413 case LMS_SETUP:
00414 {
00415 lms_src_ = iph->saddr();
00416 lms_group_ = iph->daddr();
00417 rtt_ = 2.0*(Scheduler::instance().clock() - lh->ts_);
00418 upstream_lms_ = lh->from_;
00419 dataSize_ = lh->cost_;
00420
00421 Tcl& tcl = Tcl::instance();
00422 char wrk[64];
00423 sprintf (wrk, "set_max_rtt %f", rtt_);
00424 tcl.eval (wrk);
00425
00426 #ifdef LMS_DEBUG
00427 a1 = lh->from(); a2 = lh->src();
00428
00429 printf("%s the upstream_lms is %d\n\n", uname_, upstream_lms_);
00430 printf ("%s LMS_SETUP from %d:%d src %d:%d group 0x%x RTT %f dataSize %d\n\n",
00431 uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group(), rtt_, dataSize_);
00432 #endif
00433 send_refresh ();
00434 break;
00435 }
00436 case LMS_SPM:
00437 {
00438 struct lms_spm *spm = (struct lms_spm *)pkt->accessdata ();
00439 #ifdef LMS_DEBUG
00440 printf ("%s LMS_SPM seqno %d, upstream %d:%d\n\n",
00441 uname_, spm->spm_seqno_, adr>>8, adr&0xff);
00442 #endif
00443 if (upstream_lms_ != spm->spm_path_)
00444 upstream_lms_ = spm->spm_path_;
00445 }
00446 break;
00447 case LMS_LINKS:
00448 case LMS_SRC_REFRESH:
00449 break;
00450 default:
00451 printf ("ERROR: %s Unexpected LMS packet type: %d\n\n", uname_, lh->type());
00452 abort ();
00453 }
00454 if (!st)
00455 Packet::free(pkt);
00456 }
00457
00458 int LmsReceiver::command(int argc, const char*const* argv)
00459 {
00460 if (argc == 2) {
00461 if (strcmp(argv[1], "clear") == 0) {
00462 return (TCL_OK);
00463 }
00464 if (strcmp(argv[1], "print-stats") == 0) {
00465 print_stats ();
00466 return (TCL_OK);
00467 }
00468 }
00469 if (argc == 3)
00470 {
00471 if (strcmp(argv[1], "print-all-stats") == 0) {
00472 print_all_stats (atoi (argv[2]));
00473 return (TCL_OK);
00474 }
00475 if (strcmp(argv[1], "set-replier-cost") == 0)
00476 {
00477 lms_cost_ = atoi (argv[2]);
00478 send_refresh ();
00479 return (TCL_OK);
00480 }
00481 if (strcmp(argv[1], "loss-smpl-ivl") == 0)
00482 {
00483 ls_cntdown_ = ls_smpl_ivl_ = atoi (argv[2]);
00484 return (TCL_OK);
00485 }
00486 }
00487 return (Agent::command(argc, argv));
00488 }
00489
00490
00491
00492
00493 void LmsReceiver::send_dmcast (hdr_lms* lh, int seqno, int fid)
00494 {
00495 Packet *p = allocpkt();
00496 hdr_cmn *ch = HDR_CMN(p);
00497 hdr_rtp *rh = HDR_RTP(p);
00498 hdr_ip *piph = HDR_IP(p);
00499 #ifdef LMS_DEBUG
00500 printf ("%s Sending DMCAST %d to %d:%d, size is %d\n",
00501 uname_, seqno, lh->tp_addr_>>8, lh->tp_addr_&0xff, ch->size_);
00502 #endif
00503
00504 hdr_lms *plh = HDR_LMS(p);
00505 ch->ptype_ = PT_CBR;
00506 ch->size() = dataSize_;
00507
00508 rh->seqno() = seqno;
00509
00510 piph->daddr() = lh->tp_addr_;
00511 piph->dport() = lh->tp_port_;
00512 piph->flowid() = fid;
00513
00514 plh->type_ = LMS_DMCAST;
00515 plh->from_ = addr();
00516 plh->src_ = lms_src_;
00517 plh->group_ = lms_group_;
00518 plh->tp_addr_ = lh->tp_addr_;
00519 plh->tp_port_ = lh->tp_port_;
00520 plh->tp_iface_ = lh->tp_iface_;
00521
00522 target_->recv(p);
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 int LmsReceiver::add_req (Packet *rq)
00533 {
00534 hdr_lms *lh = HDR_LMS(rq);
00535 Packet *p = rql_;
00536 int i = 0;
00537
00538 if (!p)
00539 {
00540 rql_ = rq;
00541 rq->next_ = 0;
00542 rql_sz_ = 1;
00543 return 1;
00544 }
00545
00546 #ifdef LMS_DEBUG
00547 printf("%s REQ: \tlo=%d \thi=%d \ttp_addr=%d \ttp_if=%d\n",
00548 uname_, lh->lo_, lh->hi_, lh->tp_addr_, lh->tp_iface_);
00549 #endif
00550
00551 while (p)
00552 {
00553 if (++i > LMS_RQL_MAX)
00554 break;
00555
00556 hdr_lms *plh = HDR_LMS(p);
00557
00558 #ifdef LMS_DEBUG
00559 printf("%s DB: \tlo=%d \thi=%d \ttp_addr=%d \ttp_if=%d\n",
00560 uname_, plh->lo_, plh->hi_, plh->tp_addr_, plh->tp_iface_);
00561 #endif
00562
00563
00564 if ((plh->lo_ == lh->lo_) &&
00565 (plh->hi_ == lh->hi_) &&
00566 (plh->tp_addr_ == lh->tp_addr_) &&
00567 (plh->tp_iface_ == lh->tp_iface_))
00568 {
00569 struct lms_nak *nh = (struct lms_nak *)p->accessdata();
00570
00571
00572 ++nh->dup_cnt_;
00573
00574 #ifdef LMS_DEBUG
00575 printf ("%s got %d dup reqs, max is %d\n", uname_, nh->dup_cnt_, max_dup_naks_);
00576 #endif
00577
00578 if( nh->dup_cnt_ > max_dup_naks_)
00579 max_dup_naks_ = nh->dup_cnt_;
00580
00581 return 0;
00582 }
00583
00584 p = p->next_;
00585 }
00586
00587 if (i > LMS_RQL_MAX && p && p->next_)
00588 {
00589 Packet::free (p->next_);
00590 p->next_ = 0;
00591 rql_sz_--;
00592 }
00593
00594 rq->next_ = rql_;
00595 rql_ = rq;
00596 rql_sz_++;
00597 return 1;
00598 }
00599
00600 void LmsReceiver::print_all_stats (int drops)
00601 {
00602 LmsReceiver *r = all_lms_receivers;
00603 int nrcvs = 0;
00604 int cnt1 = 0;
00605 int cnt2 = 0;
00606 int dup_replies = 0;
00607 double avg_norm_latency = 0.0;
00608 double min = 1000000.0, max = 0.0;
00609 float aveTotalDupReqs = 0.0;
00610
00611 while (r)
00612 {
00613 ++nrcvs;
00614
00615
00616
00617 aveTotalDupReqs += float(r->dup_reqs_);
00618
00619 if (r->rcvbuf_->duplicates_)
00620 {
00621 cnt1++;
00622 dup_replies += r->rcvbuf_->duplicates_;
00623 }
00624 if (r->rcvbuf_->pkts_recovered_)
00625 {
00626 cnt2++;
00627 double avl = r->rcvbuf_->delay_sum_/(double)r->rcvbuf_->pkts_recovered_;
00628 avg_norm_latency += avl / r->rtt_;
00629
00630 double m = r->rcvbuf_->min_delay_/r->rtt_;
00631 double x = r->rcvbuf_->max_delay_/r->rtt_;
00632 if (m < min)
00633 min = m;
00634 if (x > max)
00635 max = x;
00636 }
00637 r = r->next_;
00638 }
00639 if(drops)
00640 aveTotalDupReqs = (float(aveTotalDupReqs) / float(nrcvs)) / float(drops);
00641 else
00642 aveTotalDupReqs = 0.0;
00643
00644
00645
00646
00647 if (drops)
00648 {
00649 printf ("\t%.5lf\t %d\t%.4lf", aveTotalDupReqs, max_dup_naks_,
00650 ((double)dup_replies/(double)(nrcvs*drops)) );
00651 }
00652 else {
00653 printf ("\t0.0\t 0\t0.0");
00654 }
00655
00656
00657 if (cnt2)
00658 {
00659 printf ("\t%.2lf\t%.2lf\t%.2lf\n", avg_norm_latency/(double)cnt2, min, max);
00660 }
00661 else
00662 {
00663 printf ("\t0.0\t0.0\t0.0\n");
00664 }
00665 printf ("\n");
00666
00667
00668
00669 }
00670
00671 void LmsReceiver::print_stats ()
00672 {
00673 printf ("%s:\n", uname_);
00674 printf ("\tLast packet:\t\t%d\n", rcvbuf_->nextpkt_-1);
00675 printf ("\tMax packet:\t\t%d\n", rcvbuf_->maxpkt_);
00676 printf ("\tRequests sent:\t\t%d\n", req_sent_);
00677 printf ("\tRequests received:\t%d\n", req_rcvd_);
00678 if (rcvbuf_->pkts_recovered_)
00679 {
00680 printf ("\tPackets recovered:\t%d\n", rcvbuf_->pkts_recovered_);
00681 printf ("\tNormalized latency (min, max, avg):\t%lf, %lf, %lf\n",
00682 rcvbuf_->min_delay_/rtt_, rcvbuf_->max_delay_/rtt_,
00683 (rcvbuf_->delay_sum_/(double)rcvbuf_->pkts_recovered_)/rtt_);
00684 }
00685 printf ("\tDuplicate Replies:\t%d\n", rcvbuf_->duplicates_);
00686 printf ("\tDuplicate Requests:\t%d\n", dup_reqs_);
00687 printf ("\tRtt:\t\t\t%lf\n", rtt_);
00688 printf ("\n");
00689 }
00690
00691 void LmsReceiver::timeout (int type, int lo, int hi)
00692 {
00693 if (type == LMS_NAK_TIMEOUT)
00694 {
00695 #ifdef LMS_DEBUG
00696 double now= Scheduler::instance().clock();
00697 printf ("at %f %s LMS_NAK_TIMEOUT for %d, %d\n", now, uname_, lo, hi);
00698 #endif
00699 LmsNak *nak = find_nak (lo);
00700 send_nak (++nak->seqn_, lo, hi);
00701 nak->nak_timeout_ *= 2.0;
00702 nak->nak_timer_.resched (nak->nak_timeout_);
00703 }
00704 }
00705
00706 void LmsReceiver::create_nak (int lo, int hi)
00707 {
00708 #ifdef LMS_DEBUG
00709 printf ("%s Creating NAK %d, %d\n", uname_, lo, hi);
00710 #endif
00711 LmsNak *nak = new LmsNak (this, lo, hi);
00712 nak->nak_timeout_ = rtt_ * 2.0;
00713 nak->nak_timer_.resched (nak->nak_timeout_);
00714 nak->next_ = nak_;
00715 nak_ = nak;
00716 }
00717
00718 LmsNak *LmsReceiver::find_nak (int i)
00719 {
00720 for (LmsNak *n = nak_; n; n = n->next_)
00721 if (n->lo_ <= i && i <= n->hi_)
00722 return n;
00723
00724 printf("ERROR: %s nak %d not found\n", uname_, i);
00725 abort ();
00726 return 0;
00727 }
00728
00729 void LmsReceiver::delete_nak (LmsNak *n)
00730 {
00731 if (n == nak_)
00732 nak_ = nak_->next_;
00733 else {
00734 LmsNak *cur, *prev = nak_;
00735 cur = nak_->next_;
00736 while (cur)
00737 {
00738 if (cur == n)
00739 {
00740 prev->next_ = cur->next_;
00741 break;
00742 }
00743 prev = cur;
00744 cur = cur->next_;
00745 }
00746 }
00747 n->nak_timer_.cancel();
00748 #ifdef LMS_DEBUG
00749 printf ("%s Deleting NAK %d, %d\n", uname_, n->lo_, n->hi_);
00750 #endif
00751 delete n;
00752 }
00753
00754
00755
00756
00757
00758
00759 void LmsReceiver::add_rdl (int rseq, double clock)
00760 {
00761 struct lms_rdl *r = new (struct lms_rdl);
00762 r->seqn_ = rseq;
00763 r->ts_ = clock;
00764 r->next_ = rdl_;
00765 rdl_ = r;
00766
00767 if (++rdl_sz_ > LMS_RDL_MAX)
00768 {
00769 struct lms_rdl *r = rdl_;
00770 for (int i = 0; i < LMS_RDL_MAX; i++)
00771 r = r->next_;
00772 delete r->next_;
00773 r->next_ = NULL;
00774 --rdl_sz_;
00775 }
00776 }
00777
00778 int LmsReceiver::exists_rdl (int rseq)
00779 {
00780 struct lms_rdl *r = rdl_;
00781 for (; r; r = r->next_)
00782 if (r->seqn_ == rseq)
00783 return 1;
00784 return 0;
00785 }