rap.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * rap.cc
00005  * Copyright (C) 1997 by the University of Southern California
00006  * $Id: rap.cc,v 1.14 2005/09/18 23:33:34 tomh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 //
00049 // rap.cc 
00050 //      Code for the 'RAP Source' Agent Class
00051 //
00052 // Author: 
00053 //   Mohit Talwar (mohit@catarina.usc.edu)
00054 //
00055 // $Header: /nfs/jade/vint/CVSROOT/ns-2/rap/rap.cc,v 1.14 2005/09/18 23:33:34 tomh Exp $
00056 
00057 #include "rap.h"
00058 
00059 int hdr_rap::offset_; // static offset of RAP header
00060 
00061 static class RapHeaderClass : public PacketHeaderClass 
00062 {
00063 public:
00064     RapHeaderClass() : PacketHeaderClass("PacketHeader/RAP", 
00065                          sizeof(hdr_rap)) {
00066         bind_offset(&hdr_rap::offset_);
00067     }
00068 } class_raphdr;
00069 
00070 
00071 static class RapClass : public TclClass 
00072 {
00073 public:
00074     RapClass() : TclClass("Agent/RAP") {}
00075     TclObject* create(int, const char*const*) 
00076         { return (new RapAgent()); }
00077 } class_rap;
00078 
00079 
00080 void IpgTimer::expire(Event *)
00081 { 
00082     a_->timeout(RAP_IPG_TIMEOUT); 
00083 }
00084 
00085 void RttTimer::expire(Event *)
00086 { 
00087     a_->timeout(RAP_RTT_TIMEOUT); 
00088 }
00089 
00090 //----------------------------------------------------------------------
00091 // EqualSeqno
00092 //      Compare TransHistory Entries on the seqno field.
00093 //
00094 //      "i1", "i2" are the TransHistory entries to be compared.
00095 //----------------------------------------------------------------------
00096  
00097 int EqualSeqno(void *i1, void *i2)
00098 { 
00099     return (((TransHistoryEntry *) i1)->seqno == 
00100         ((TransHistoryEntry *) i2)->seqno);
00101 }
00102 
00103 //----------------------------------------------------------------------
00104 // RapAgent::RapAgent
00105 //  Initialize the RAP agent.
00106 //      Bind variables which have to be accessed in both Tcl and C++.
00107 //      Initializes time values.
00108 //----------------------------------------------------------------------
00109 
00110 RapAgent::RapAgent() : Agent(PT_RAP_DATA), ipgTimer_(this), rttTimer_(this),
00111     seqno_(0), sessionLossCount_(0), curseq_(0), ipg_(2.0), srtt_(2.0), 
00112     timeout_(2.0), lastRecv_(0), lastMiss_(0), prevRecv_(0), dctr_(0), 
00113     flags_(0), fixIpg_(0)
00114 {
00115     bind("packetSize_", &size_);    // Default 512
00116     bind("seqno_", &seqno_);    // Default 0
00117     bind("sessionLossCount_", &sessionLossCount_); // Default 0
00118 
00119     bind("ipg_", &ipg_);        // Default 2 seconds
00120     bind("beta_", &beta_);  // Default 0.5
00121     bind("alpha_", &alpha_);    // Default 1.0
00122 
00123     bind("srtt_", &srtt_);  // Default 2 seconds
00124     bind("variance_", &variance_);// Default 0
00125     bind("delta_", &delta_);    // Default 0.5
00126     bind("mu_", &mu_);      // Default 1.2
00127     bind("phi_", &phi_);        // Default 4
00128 
00129     bind("timeout_", &timeout_);    // Default 2 seconds
00130 
00131     bind("overhead_", &overhead_); // Default 0
00132 
00133     bind("useFineGrain_", &useFineGrain_); // Default FALSE
00134     bind("kfrtt_", &kfrtt_);    // Default 0.9
00135     bind("kxrtt_", &kxrtt_);    // Default 0.01
00136 
00137     bind("debugEnable_", &debugEnable_);    // Default FALSE
00138 
00139     bind("rap_base_hdr_size_", &rap_base_hdr_size_);
00140 
00141     bind("dpthresh_", &dpthresh_);
00142 
00143     frtt_ = xrtt_ = srtt_;
00144 }
00145 
00146 // Cancel all our timers before we quit
00147 RapAgent::~RapAgent()
00148 {
00149 //      fprintf(stderr, "%g: rap agent %s(%d) stops.\n", 
00150 //          Scheduler::instance().clock(), name(), addr());
00151 //      Tcl::instance().eval("[Simulator instance] flush-trace");
00152     stop();
00153 }
00154 
00155 //----------------------------------------------------------------------
00156 // RapAgent::UpdateTimeValues
00157 //      Update the values for srtt_, variance_ and timeout_ based on
00158 //      the "sampleRtt". Use Jacobson/Karl's algorithm.
00159 //      
00160 //  "sampleRtt" is the sample  round trip time obtained from the 
00161 //      current ack packet.
00162 //----------------------------------------------------------------------
00163 
00164 void RapAgent::UpdateTimeValues(double sampleRtt)
00165 { 
00166     double diff;
00167     static int initial = TRUE;
00168 
00169     if (initial) {
00170         frtt_ = xrtt_ = srtt_ = sampleRtt; // First sample, no history
00171         variance_ = 0;
00172         initial = FALSE;
00173     }
00174 
00175     diff = sampleRtt - srtt_;
00176     srtt_ += delta_ * diff;
00177       
00178     diff = (diff < 0) ? diff * -1 : diff; // Take mod
00179     variance_ += delta_ * (diff - variance_);
00180 
00181     timeout_ = mu_ * srtt_ + phi_ * variance_;
00182 
00183     if (useFineGrain_) {
00184         frtt_ = (1 - kfrtt_) * frtt_ + kfrtt_ * sampleRtt;
00185         xrtt_ = (1 - kxrtt_) * xrtt_ + kxrtt_ * sampleRtt;
00186     }
00187 
00188     double debugSrtt = srtt_;   // $%#& stoopid compiler
00189     Debug(debugEnable_, logfile_, 
00190           "- srtt updated to %f\n", debugSrtt);
00191 }
00192 
00193 void RapAgent::start()
00194 {
00195     if (debugEnable_)
00196         logfile_ = DebugEnable(this->addr() >> 
00197                        Address::instance().NodeShift_[1]);
00198     else
00199         // Should initialize it regardless of whether it'll be used.
00200         logfile_ = NULL;
00201     Debug(debugEnable_, logfile_, "%.3f: RAP start.\n", 
00202           Scheduler::instance().clock());
00203 
00204     flags_ = flags_ & ~RF_STOP;
00205     startTime_ = Scheduler::instance().clock();
00206     RttTimeout();       // Decreases initial IPG
00207     IpgTimeout();
00208 }
00209 
00210 // Used by a sink to listen to incoming packets
00211 void RapAgent::listen()
00212 {
00213     if (debugEnable_)
00214         logfile_ = DebugEnable(this->addr() >> 
00215                        Address::instance().NodeShift_[1]);
00216 }
00217 
00218 void RapAgent::stop()
00219 {
00220     Debug(debugEnable_, logfile_, 
00221           "%.3f: RAP stop.\n", Scheduler::instance().clock());
00222             
00223     // Cancel the timer only when there is one
00224     if (ipgTimer_.status() == TIMER_PENDING)
00225         ipgTimer_.cancel();  
00226     if (rttTimer_.status() == TIMER_PENDING)
00227         rttTimer_.cancel();
00228 
00229     stopTime_ = Scheduler::instance().clock();
00230     int debugSeqno = seqno_;
00231     Debug(debugEnable_, logfile_, 
00232           "- numPackets %d, totalTime %f\n", 
00233           debugSeqno, stopTime_ - startTime_);
00234     flags_ |= RF_STOP;
00235 }
00236 
00237 //----------------------------------------------------------------------
00238 // RapAgent::command
00239 //      Called when a Tcl command for the RAP agent is executed.
00240 //      Two commands are supported
00241 //         $rapsource start
00242 //         $rapsource stop
00243 //----------------------------------------------------------------------
00244 int RapAgent::command(int argc, const char*const* argv)
00245 {
00246     if (argc == 2) {
00247         if (strcmp(argv[1], "start") == 0) {
00248             start();
00249             // return TCL_OK, so the calling function knows that 
00250             // the command has been processed
00251             return (TCL_OK);
00252         } else if (strcmp(argv[1], "stop") == 0) {
00253             stop();
00254             return (TCL_OK);
00255         } else if (strcmp(argv[1], "listen") == 0) {
00256             listen();
00257             return (TCL_OK);
00258         }
00259     } else if (argc == 3) {
00260                 if (strcmp(argv[1], "advanceby") == 0) {
00261                         advanceby(atoi(argv[2]));
00262                         return (TCL_OK);
00263                 }
00264     }
00265 
00266 
00267     // If the command hasn't been processed by RapAgent()::command,
00268     // call the command() function for the base class
00269     return (Agent::command(argc, argv));
00270 }
00271 
00272 //----------------------------------------------------------------------
00273 // RapAgent::SendPacket
00274 //      Called in IpgTimeout().
00275 //      Create a packet, increase seqno_, send the packet out.
00276 //----------------------------------------------------------------------
00277 
00278 void RapAgent::SendPacket(int nbytes, AppData *data)
00279 {
00280     TransHistoryEntry *pktInfo;
00281     Packet *pkt;
00282 
00283     type_ = PT_RAP_DATA;
00284     if (data)
00285         pkt = allocpkt(data->size()); 
00286     else 
00287         pkt = allocpkt();
00288 
00289     // Fill in RAP headers
00290     hdr_rap* hdr = hdr_rap::access(pkt);
00291     hdr->seqno() = ++seqno_;    // Start counting from 1;
00292     hdr->lastRecv = hdr->lastMiss = hdr->prevRecv = 0; // Ignore @ sender
00293     hdr->flags() = RH_DATA;
00294     if (data) {
00295         hdr->size() = data->size();
00296         pkt->setdata(data);
00297     } else {
00298         hdr->size() = size_;
00299     }
00300     // XXX Simply set packet size to the given ADU's nominal size. 
00301     // Make sure that the size is reasonable!!
00302     hdr_cmn *ch = hdr_cmn::access(pkt);
00303     ch->size() = nbytes; 
00304 
00305     send(pkt, 0);
00306     pktInfo = new TransHistoryEntry(seqno_);
00307     transmissionHistory_.SetInsert((void *) pktInfo, EqualSeqno);
00308     int debugSeqno = seqno_;
00309     Debug(debugEnable_, logfile_, 
00310           "- packet %d sent\n", debugSeqno);
00311 }
00312 
00313 //----------------------------------------------------------------------
00314 // RapAgent::recv
00315 //      Called when a packet is received.
00316 //      Should be of type PT_RAP_ACK.
00317 //----------------------------------------------------------------------
00318 
00319 void RapAgent::recv(Packet* pkt, Handler*)
00320 {
00321     Debug(debugEnable_, logfile_, 
00322           "%.3f: RAP packet received.\n", Scheduler::instance().clock());
00323 
00324     hdr_rap* hdr = hdr_rap::access(pkt); // Access RAP header
00325 
00326     switch (hdr->flags()) { 
00327     case RH_DATA:
00328         UpdateLastHole(hdr->seqno());
00329         SendAck(hdr->seqno());
00330         if ((pkt->datalen() > 0) && app_) 
00331             // We do have user data, process it
00332             app_->process_data(pkt->datalen(), pkt->userdata());
00333         break;
00334     case RH_ACK:
00335         RecvAck(hdr);
00336         break;
00337     default:
00338         fprintf(stderr, 
00339             "RAP agent %s received a packet with unknown flags %x",
00340             name(), hdr->flags());
00341         break;
00342     } 
00343     Packet::free(pkt);      // Discard the packet
00344 }
00345 
00346 //----------------------------------------------------------------------
00347 // RapAgent::RecvAck
00348 //      Called when an Ack is received.
00349 //      
00350 //      "header" is the RAP header of the Ack.
00351 //----------------------------------------------------------------------
00352 
00353 void RapAgent::RecvAck(hdr_rap *ackHeader)
00354 {
00355     double sampleRtt;
00356     TransHistoryEntry *old, key(ackHeader->seqno_);
00357 
00358     assert(ackHeader->seqno_ > 0);
00359 
00360     Debug(debugEnable_, logfile_, 
00361           "- ack %d\n", ackHeader->seqno_);
00362 
00363     old = (TransHistoryEntry *) 
00364         transmissionHistory_.SetRemove((void *) &key, EqualSeqno);
00365 
00366     if (old != NULL) {
00367         Debug(debugEnable_, logfile_, 
00368               "- found in transmission history\n");
00369         assert((old->status == RAP_SENT) || (old->status == RAP_INACTIVE));
00370 
00371         // Get sample rtt       
00372         sampleRtt = key.departureTime - old->departureTime; 
00373 
00374         UpdateTimeValues(sampleRtt);
00375         
00376         delete old;
00377     }
00378   
00379     if (!anyack()) {
00380         flags_ |= RF_ANYACK;
00381         ipg_ = srtt_;
00382     }
00383   
00384     if (LossDetection(RAP_ACK_BASED, ackHeader))
00385         LossHandler();
00386 
00387     // XXX We only stop by sequence number when we are in 
00388     // "counting sequence number" mode.   -- haoboy
00389     if (counting_pkt() && (ackHeader->seqno_ >= curseq_)) 
00390         finish();
00391 }
00392 
00393 //----------------------------------------------------------------------
00394 // RapAgent::timeout
00395 //      Called when a timer fires.
00396 //
00397 //      "type" is the type of Timeout event
00398 //----------------------------------------------------------------------
00399 
00400 void RapAgent::timeout(int type)
00401 {
00402     if (type == RAP_IPG_TIMEOUT)
00403         IpgTimeout();
00404     else if (type == RAP_RTT_TIMEOUT)
00405         RttTimeout();
00406     else
00407         assert(FALSE);
00408 }
00409 
00410 //----------------------------------------------------------------------
00411 // RapAgent::IpgTimeout
00412 //      Called when the ipgTimer_ fires.
00413 //----------------------------------------------------------------------
00414 
00415 void RapAgent::IpgTimeout()
00416 {
00417     double waitPeriod;      // Time before next transmission
00418 
00419     Debug(debugEnable_, logfile_, 
00420           "%.3f: IPG Timeout.\n", Scheduler::instance().clock());
00421 
00422     if (LossDetection(RAP_TIMER_BASED))
00423         LossHandler();
00424     else if (!counting_pkt()) {
00425         if (app_) {
00426             int nbytes;
00427             AppData* data = app_->get_data(nbytes);
00428             // Missing data in application. What should we do??
00429             // For now, simply schedule the next SendPacket(). 
00430             // If the application has nothing to send, it'll stop 
00431             // the rap agent later on. 
00432             if (data != NULL) {
00433                 SendPacket(nbytes, data);
00434                 dctr_++;
00435             }
00436         } else {
00437             // If RAP doesn't have application, just go ahead and 
00438             // send packet
00439             SendPacket(size_);
00440             dctr_++;
00441         }
00442     } else if (seqno_ < curseq_) {
00443             SendPacket(size_);
00444             dctr_++;
00445     }
00446 
00447     // XXX If we only bound IPG in DecreaseIpg(), the thresholding will 
00448     // happen immediately because DecreaseIpg() isn't called immediately. 
00449     // So we do it here. 
00450     if (fixIpg_ != 0)
00451         ipg_ = fixIpg_;
00452 
00453     if (useFineGrain_)
00454         waitPeriod = frtt_ / xrtt_ * ipg_;
00455     else 
00456         waitPeriod = ipg_;
00457     // By this point, we may have been stopped by applications above
00458     // Thus, do not reschedule a timer if we are stopped. 
00459     if (!is_stopped())
00460         ipgTimer_.resched(waitPeriod + Random::uniform(overhead_));
00461 }
00462   
00463 //----------------------------------------------------------------------
00464 // RapAgent::RttTimeout
00465 //      Called when the rttTimer_ fires.
00466 //      Decrease IPG. Restart rttTimer_.
00467 //----------------------------------------------------------------------
00468 
00469 void RapAgent::RttTimeout()
00470 {
00471     Debug(debugEnable_, logfile_, 
00472           "%.3f: RTT Timeout.\n", Scheduler::instance().clock());
00473 
00474     // During the past srtt_, we are supposed to send out srtt_/ipg_
00475     // packets. If we sent less than that, we may not increase rate
00476     if (100*dctr_*(ipg_/srtt_) >= dpthresh_)
00477         DecreaseIpg();      // Additive increase in rate
00478     else 
00479         Debug(debugEnable_, logfile_, 
00480               "- %f Cannot increase rate due to insufficient data.\n",
00481               Scheduler::instance().clock());
00482     dctr_ = 0;
00483 
00484     double debugIpg = ipg_ + overhead_ / 2;
00485     Debug(debugEnable_, logfile_, 
00486           "- ipg decreased at %.3f to %f\n", 
00487           Scheduler::instance().clock(), debugIpg);
00488 
00489     rttTimer_.resched(srtt_);
00490 }
00491 
00492 //----------------------------------------------------------------------
00493 // RapAgent::LossDetection
00494 //      Called in ipgTimeout (RAP_TIMER_BASED) 
00495 //          or in RecvAck (RAP_ACK_BASED).
00496 //
00497 // Returns:
00498 //      TRUE if loss detected, FALSE otherwise.
00499 //
00500 //      "ackHeader" is the RAP header of the received Ack (PT_RAP_ACK).
00501 //----------------------------------------------------------------------
00502 
00503 static double currentTime;
00504 static hdr_rap *ackHdr;
00505 static RapAgent *rapAgent; 
00506 static int numLosses;
00507 
00508 int EqualStatus(void *i1, void *i2)
00509 { 
00510     return (((TransHistoryEntry *) i1)->status == 
00511         ((TransHistoryEntry *) i2)->status);
00512 }
00513 
00514 void DestroyTransHistoryEntry(long item)
00515 {
00516     TransHistoryEntry *entry = (TransHistoryEntry *) item;
00517 
00518     Debug(rapAgent->GetDebugFlag(), rapAgent->GetLogfile(),
00519           "- purged seq num %d\n", entry->seqno);
00520 
00521     delete entry;
00522 }
00523 
00524 void TimerLostPacket(long item)
00525 {
00526     TransHistoryEntry *entry = (TransHistoryEntry *) item;
00527 
00528     if ((entry->departureTime + rapAgent->GetTimeout()) <= currentTime) {
00529         // ~ Packets lost in RAP session
00530         rapAgent->IncrementLossCount(); 
00531 
00532         // Ignore cluster losses
00533         if (entry->status != RAP_INACTIVE) {
00534             assert(entry->status == RAP_SENT);
00535 
00536             numLosses++;
00537             Debug(rapAgent->GetDebugFlag(), rapAgent->GetLogfile(),
00538                   "- timerlost seq num %d , last sent %d\n", 
00539                   entry->seqno, rapAgent->GetSeqno());
00540         }
00541         entry->status = RAP_PURGED; 
00542     }
00543 }
00544 
00545 void AckLostPacket(long item)
00546 {
00547     TransHistoryEntry *entry = (TransHistoryEntry *) item;
00548 
00549     int seqno, lastRecv, lastMiss, prevRecv;
00550 
00551     seqno = entry->seqno;
00552     lastRecv = ackHdr->lastRecv;
00553     lastMiss = ackHdr->lastMiss;
00554     prevRecv = ackHdr->prevRecv;
00555 
00556     if (seqno <= lastRecv) {
00557         if ((seqno > lastMiss) || (seqno == prevRecv))
00558             entry->status = RAP_PURGED; // Was Received, now purge
00559         else if ((lastRecv - seqno) >= 3) {
00560             // ~ Packets lost in RAP session
00561             rapAgent->IncrementLossCount(); 
00562             
00563             if (entry->status != RAP_INACTIVE) {
00564                 assert(entry->status == RAP_SENT);
00565 
00566                 numLosses++;
00567                 Debug(rapAgent->GetDebugFlag(), 
00568                       rapAgent->GetLogfile(),
00569                       "- acklost seqno %d , last sent %d\n", 
00570                       seqno, rapAgent->GetSeqno());
00571             }
00572             // Was Lost, purge from history
00573             entry->status = RAP_PURGED; 
00574         }
00575     }
00576 }
00577 
00578 int RapAgent::LossDetection(RapLossType type, hdr_rap *ackHeader)
00579 {
00580     TransHistoryEntry key(0, RAP_PURGED);
00581 
00582     currentTime = key.departureTime;
00583     ackHdr = ackHeader;
00584     rapAgent = this;
00585     numLosses = 0;
00586 
00587     switch(type) {
00588     case RAP_TIMER_BASED:
00589         transmissionHistory_.Mapcar(TimerLostPacket);
00590         break;
00591         
00592     case RAP_ACK_BASED:
00593         transmissionHistory_.Mapcar(AckLostPacket);
00594         break;
00595 
00596     default:
00597         assert(FALSE);
00598     }
00599 
00600     Debug(debugEnable_, logfile_, 
00601           "- %d losses detected\n", numLosses); 
00602 
00603     Debug(debugEnable_, logfile_, 
00604           "- history size %d\n", transmissionHistory_.Size());
00605   
00606     transmissionHistory_.Purge((void *) &key, 
00607                    EqualStatus, // Purge PURGED packets
00608                    DestroyTransHistoryEntry);
00609 
00610     Debug(debugEnable_, logfile_, 
00611           "- history size %d\n", transmissionHistory_.Size());
00612 
00613     if (numLosses)
00614         return TRUE;
00615     else
00616         return FALSE;
00617 }
00618 
00619 //----------------------------------------------------------------------
00620 // RapAgent::LossHandler
00621 //      Called when loss detected.
00622 //      Increase IPG. Mark packets INACTIVE. Reschedule rttTimer_.
00623 //----------------------------------------------------------------------
00624 
00625 void MarkInactive(long item)
00626 {
00627     TransHistoryEntry *entry = (TransHistoryEntry *) item;
00628 
00629     entry->status = RAP_INACTIVE;
00630 }
00631 
00632 void RapAgent::LossHandler()
00633 {
00634     IncreaseIpg();      // Multiplicative decrease in rate
00635 
00636     double debugIpg = ipg_ + overhead_ / 2;
00637     Debug(debugEnable_, logfile_, 
00638           "- ipg increased at %.3f to %f\n", 
00639           Scheduler::instance().clock(), debugIpg);
00640 
00641     transmissionHistory_.Mapcar(MarkInactive);
00642     Debug(debugEnable_, logfile_, 
00643           "- window full packets marked inactive\n");
00644 
00645     rttTimer_.resched(srtt_);
00646 }
00647 
00648 //----------------------------------------------------------------------
00649 // RapAgent::SendAck
00650 //      Create an ack packet, set fields, send the packet out.
00651 //
00652 //      "seqNum" is the sequence number of the packet being acked.
00653 //----------------------------------------------------------------------
00654 
00655 void RapAgent::SendAck(int seqNum)
00656 {
00657     type_ = PT_RAP_ACK;
00658     Packet* pkt = allocpkt();   // Create a new packet
00659     hdr_rap* hdr = hdr_rap::access(pkt);   // Access header
00660 
00661     hdr->seqno() = seqNum;
00662     hdr->flags() = RH_ACK;
00663 
00664     hdr->lastRecv = lastRecv_;
00665     hdr->lastMiss = lastMiss_;
00666     hdr->prevRecv = prevRecv_;
00667 
00668     hdr_cmn *ch = hdr_cmn::access(pkt);
00669     ch->size() = rap_base_hdr_size_;
00670 
00671     send(pkt, 0);
00672     Debug(debugEnable_, logfile_, 
00673           "- ack sent %u [%u %u %u]\n", 
00674           seqNum, lastRecv_, lastMiss_, prevRecv_);
00675 }
00676 
00677 //----------------------------------------------------------------------
00678 // RapSinkAgent::UpdateLastHole
00679 //      Update the last hole in sequence number space at the receiver.
00680 //      
00681 //  "seqNum" is the sequence number of the data packet received.
00682 //----------------------------------------------------------------------
00683 
00684 void RapAgent::UpdateLastHole(int seqNum)
00685 {
00686     assert(seqNum > 0);
00687 
00688     if (seqNum > (lastRecv_ + 1)) {
00689         prevRecv_ = lastRecv_;
00690         lastRecv_ = seqNum;
00691         lastMiss_ = seqNum - 1;
00692         return;
00693     }
00694 
00695     if (seqNum == (lastRecv_ + 1)) {
00696         lastRecv_ = seqNum;
00697         return;
00698     }
00699     
00700     if ((lastMiss_ < seqNum) && (seqNum <= lastRecv_)) // Duplicate
00701         return;
00702 
00703     if (seqNum == lastMiss_) {
00704         if ((prevRecv_ + 1) == seqNum) // Hole filled
00705             prevRecv_ = lastMiss_ = 0;
00706         else
00707             lastMiss_--;
00708         
00709         return;
00710     }
00711     
00712     if ((prevRecv_ < seqNum) && (seqNum < lastMiss_)) {
00713         prevRecv_ = seqNum;
00714         return;
00715     }
00716 
00717     assert(seqNum <= prevRecv_);    // Pretty late...
00718 }
00719 
00720 
00721 // take pkt count
00722 void RapAgent::advanceby(int delta)
00723 {
00724     flags_ |= RF_COUNTPKT;
00725         curseq_ = delta;
00726     start();
00727 }
00728 
00729 void RapAgent::finish()
00730 {
00731     stop();
00732     Tcl::instance().evalf("%s done", this->name());
00733 }
00734 

Generated on Tue Mar 6 16:47:49 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6