rap.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:20k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * rap.cc
  4.  * Copyright (C) 1997 by the University of Southern California
  5.  * $Id: rap.cc,v 1.14 2005/09/18 23:33:34 tomh Exp $
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License,
  9.  * version 2, as published by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program; if not, write to the Free Software Foundation, Inc.,
  18.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  * The copyright of this module includes the following
  22.  * linking-with-specific-other-licenses addition:
  23.  *
  24.  * In addition, as a special exception, the copyright holders of
  25.  * this module give you permission to combine (via static or
  26.  * dynamic linking) this module with free software programs or
  27.  * libraries that are released under the GNU LGPL and with code
  28.  * included in the standard release of ns-2 under the Apache 2.0
  29.  * license or under otherwise-compatible licenses with advertising
  30.  * requirements (or modified versions of such code, with unchanged
  31.  * license).  You may copy and distribute such a system following the
  32.  * terms of the GNU GPL for this module and the licenses of the
  33.  * other code concerned, provided that you include the source code of
  34.  * that other code when and as the GNU GPL requires distribution of
  35.  * source code.
  36.  *
  37.  * Note that people who make modified versions of this module
  38.  * are not obligated to grant this special exception for their
  39.  * modified versions; it is their choice whether to do so.  The GNU
  40.  * General Public License gives permission to release a modified
  41.  * version without this exception; this exception also makes it
  42.  * possible to release a modified version which carries forward this
  43.  * exception.
  44.  *
  45.  */
  46. //
  47. // rap.cc 
  48. //      Code for the 'RAP Source' Agent Class
  49. //
  50. // Author: 
  51. //   Mohit Talwar (mohit@catarina.usc.edu)
  52. //
  53. // $Header: /cvsroot/nsnam/ns-2/rap/rap.cc,v 1.14 2005/09/18 23:33:34 tomh Exp $
  54. #include "rap.h"
  55. int hdr_rap::offset_; // static offset of RAP header
  56. static class RapHeaderClass : public PacketHeaderClass 
  57. {
  58. public:
  59. RapHeaderClass() : PacketHeaderClass("PacketHeader/RAP", 
  60.      sizeof(hdr_rap)) {
  61. bind_offset(&hdr_rap::offset_);
  62. }
  63. } class_raphdr;
  64. static class RapClass : public TclClass 
  65. {
  66. public:
  67. RapClass() : TclClass("Agent/RAP") {}
  68. TclObject* create(int, const char*const*) 
  69. { return (new RapAgent()); }
  70. } class_rap;
  71. void IpgTimer::expire(Event *)
  72. a_->timeout(RAP_IPG_TIMEOUT); 
  73. }
  74. void RttTimer::expire(Event *)
  75. a_->timeout(RAP_RTT_TIMEOUT); 
  76. }
  77. //----------------------------------------------------------------------
  78. // EqualSeqno
  79. //      Compare TransHistory Entries on the seqno field.
  80. //
  81. //      "i1", "i2" are the TransHistory entries to be compared.
  82. //----------------------------------------------------------------------
  83.  
  84. int EqualSeqno(void *i1, void *i2)
  85. return (((TransHistoryEntry *) i1)->seqno == 
  86. ((TransHistoryEntry *) i2)->seqno);
  87. }
  88. //----------------------------------------------------------------------
  89. // RapAgent::RapAgent
  90. // Initialize the RAP agent.
  91. //      Bind variables which have to be accessed in both Tcl and C++.
  92. //      Initializes time values.
  93. //----------------------------------------------------------------------
  94. RapAgent::RapAgent() : Agent(PT_RAP_DATA), ipgTimer_(this), rttTimer_(this),
  95.   seqno_(0), sessionLossCount_(0), curseq_(0), ipg_(2.0), srtt_(2.0), 
  96. timeout_(2.0), lastRecv_(0), lastMiss_(0), prevRecv_(0), dctr_(0), 
  97. flags_(0), fixIpg_(0)
  98. {
  99. bind("packetSize_", &size_); // Default 512
  100. bind("seqno_", &seqno_); // Default 0
  101. bind("sessionLossCount_", &sessionLossCount_); // Default 0
  102. bind("ipg_", &ipg_); // Default 2 seconds
  103. bind("beta_", &beta_); // Default 0.5
  104. bind("alpha_", &alpha_); // Default 1.0
  105. bind("srtt_", &srtt_); // Default 2 seconds
  106. bind("variance_", &variance_);// Default 0
  107. bind("delta_", &delta_); // Default 0.5
  108. bind("mu_", &mu_); // Default 1.2
  109. bind("phi_", &phi_); // Default 4
  110. bind("timeout_", &timeout_); // Default 2 seconds
  111. bind("overhead_", &overhead_); // Default 0
  112. bind("useFineGrain_", &useFineGrain_); // Default FALSE
  113. bind("kfrtt_", &kfrtt_); // Default 0.9
  114. bind("kxrtt_", &kxrtt_); // Default 0.01
  115. bind("debugEnable_", &debugEnable_); // Default FALSE
  116. bind("rap_base_hdr_size_", &rap_base_hdr_size_);
  117. bind("dpthresh_", &dpthresh_);
  118. frtt_ = xrtt_ = srtt_;
  119. }
  120. // Cancel all our timers before we quit
  121. RapAgent::~RapAgent()
  122. {
  123. //   fprintf(stderr, "%g: rap agent %s(%d) stops.n", 
  124. //   Scheduler::instance().clock(), name(), addr());
  125. //   Tcl::instance().eval("[Simulator instance] flush-trace");
  126. stop();
  127. }
  128. //----------------------------------------------------------------------
  129. // RapAgent::UpdateTimeValues
  130. //      Update the values for srtt_, variance_ and timeout_ based on
  131. //      the "sampleRtt". Use Jacobson/Karl's algorithm.
  132. //      
  133. // "sampleRtt" is the sample  round trip time obtained from the 
  134. //      current ack packet.
  135. //----------------------------------------------------------------------
  136. void RapAgent::UpdateTimeValues(double sampleRtt)
  137. double diff;
  138. static int initial = TRUE;
  139. if (initial) {
  140. frtt_ = xrtt_ = srtt_ = sampleRtt; // First sample, no history
  141. variance_ = 0;
  142. initial = FALSE;
  143. }
  144. diff = sampleRtt - srtt_;
  145. srtt_ += delta_ * diff;
  146.       
  147. diff = (diff < 0) ? diff * -1 : diff; // Take mod
  148. variance_ += delta_ * (diff - variance_);
  149. timeout_ = mu_ * srtt_ + phi_ * variance_;
  150. if (useFineGrain_) {
  151. frtt_ = (1 - kfrtt_) * frtt_ + kfrtt_ * sampleRtt;
  152. xrtt_ = (1 - kxrtt_) * xrtt_ + kxrtt_ * sampleRtt;
  153. }
  154. double debugSrtt = srtt_; // $%#& stoopid compiler
  155. Debug(debugEnable_, logfile_, 
  156.       "- srtt updated to %fn", debugSrtt);
  157. }
  158. void RapAgent::start()
  159. {
  160. if (debugEnable_)
  161. logfile_ = DebugEnable(this->addr() >> 
  162.        Address::instance().NodeShift_[1]);
  163. else
  164. // Should initialize it regardless of whether it'll be used.
  165. logfile_ = NULL;
  166. Debug(debugEnable_, logfile_, "%.3f: RAP start.n", 
  167.       Scheduler::instance().clock());
  168. flags_ = flags_ & ~RF_STOP;
  169. startTime_ = Scheduler::instance().clock();
  170. RttTimeout(); // Decreases initial IPG
  171. IpgTimeout();
  172. }
  173. // Used by a sink to listen to incoming packets
  174. void RapAgent::listen()
  175. {
  176. if (debugEnable_)
  177. logfile_ = DebugEnable(this->addr() >> 
  178.        Address::instance().NodeShift_[1]);
  179. }
  180. void RapAgent::stop()
  181. {
  182. Debug(debugEnable_, logfile_, 
  183.       "%.3f: RAP stop.n", Scheduler::instance().clock());
  184. // Cancel the timer only when there is one
  185. if (ipgTimer_.status() == TIMER_PENDING)
  186. ipgTimer_.cancel();  
  187. if (rttTimer_.status() == TIMER_PENDING)
  188. rttTimer_.cancel();
  189. stopTime_ = Scheduler::instance().clock();
  190. int debugSeqno = seqno_;
  191. Debug(debugEnable_, logfile_, 
  192.       "- numPackets %d, totalTime %fn", 
  193.       debugSeqno, stopTime_ - startTime_);
  194. flags_ |= RF_STOP;
  195. }
  196. //----------------------------------------------------------------------
  197. // RapAgent::command
  198. //      Called when a Tcl command for the RAP agent is executed.
  199. //      Two commands are supported
  200. //         $rapsource start
  201. //         $rapsource stop
  202. //----------------------------------------------------------------------
  203. int RapAgent::command(int argc, const char*const* argv)
  204. {
  205. if (argc == 2) {
  206. if (strcmp(argv[1], "start") == 0) {
  207. start();
  208. // return TCL_OK, so the calling function knows that 
  209. // the command has been processed
  210. return (TCL_OK);
  211. } else if (strcmp(argv[1], "stop") == 0) {
  212. stop();
  213. return (TCL_OK);
  214. } else if (strcmp(argv[1], "listen") == 0) {
  215. listen();
  216. return (TCL_OK);
  217. }
  218. } else if (argc == 3) {
  219.                 if (strcmp(argv[1], "advanceby") == 0) {
  220.                         advanceby(atoi(argv[2]));
  221.                         return (TCL_OK);
  222.                 }
  223. }
  224. // If the command hasn't been processed by RapAgent()::command,
  225. // call the command() function for the base class
  226. return (Agent::command(argc, argv));
  227. }
  228. //----------------------------------------------------------------------
  229. // RapAgent::SendPacket
  230. //      Called in IpgTimeout().
  231. //      Create a packet, increase seqno_, send the packet out.
  232. //----------------------------------------------------------------------
  233. void RapAgent::SendPacket(int nbytes, AppData *data)
  234. {
  235. TransHistoryEntry *pktInfo;
  236. Packet *pkt;
  237. type_ = PT_RAP_DATA;
  238. if (data)
  239. pkt = allocpkt(data->size()); 
  240. else 
  241. pkt = allocpkt();
  242. // Fill in RAP headers
  243. hdr_rap* hdr = hdr_rap::access(pkt);
  244. hdr->seqno() = ++seqno_; // Start counting from 1;
  245. hdr->lastRecv = hdr->lastMiss = hdr->prevRecv = 0; // Ignore @ sender
  246. hdr->flags() = RH_DATA;
  247. if (data) {
  248. hdr->size() = data->size();
  249. pkt->setdata(data);
  250. } else {
  251. hdr->size() = size_;
  252. }
  253. // XXX Simply set packet size to the given ADU's nominal size. 
  254. // Make sure that the size is reasonable!!
  255. hdr_cmn *ch = hdr_cmn::access(pkt);
  256. ch->size() = nbytes; 
  257. send(pkt, 0);
  258. pktInfo = new TransHistoryEntry(seqno_);
  259. transmissionHistory_.SetInsert((void *) pktInfo, EqualSeqno);
  260. int debugSeqno = seqno_;
  261. Debug(debugEnable_, logfile_, 
  262.       "- packet %d sentn", debugSeqno);
  263. }
  264. //----------------------------------------------------------------------
  265. // RapAgent::recv
  266. //      Called when a packet is received.
  267. //      Should be of type PT_RAP_ACK.
  268. //----------------------------------------------------------------------
  269. void RapAgent::recv(Packet* pkt, Handler*)
  270. {
  271. Debug(debugEnable_, logfile_, 
  272.       "%.3f: RAP packet received.n", Scheduler::instance().clock());
  273. hdr_rap* hdr = hdr_rap::access(pkt); // Access RAP header
  274. switch (hdr->flags()) { 
  275. case RH_DATA:
  276. UpdateLastHole(hdr->seqno());
  277. SendAck(hdr->seqno());
  278. if ((pkt->datalen() > 0) && app_) 
  279. // We do have user data, process it
  280. app_->process_data(pkt->datalen(), pkt->userdata());
  281. break;
  282. case RH_ACK:
  283. RecvAck(hdr);
  284. break;
  285. default:
  286. fprintf(stderr, 
  287. "RAP agent %s received a packet with unknown flags %x",
  288. name(), hdr->flags());
  289. break;
  290. Packet::free(pkt); // Discard the packet
  291. }
  292. //----------------------------------------------------------------------
  293. // RapAgent::RecvAck
  294. //      Called when an Ack is received.
  295. //      
  296. //      "header" is the RAP header of the Ack.
  297. //----------------------------------------------------------------------
  298. void RapAgent::RecvAck(hdr_rap *ackHeader)
  299. {
  300. double sampleRtt;
  301. TransHistoryEntry *old, key(ackHeader->seqno_);
  302. assert(ackHeader->seqno_ > 0);
  303. Debug(debugEnable_, logfile_, 
  304.       "- ack %dn", ackHeader->seqno_);
  305. old = (TransHistoryEntry *) 
  306. transmissionHistory_.SetRemove((void *) &key, EqualSeqno);
  307. if (old != NULL) {
  308. Debug(debugEnable_, logfile_, 
  309.       "- found in transmission historyn");
  310. assert((old->status == RAP_SENT) || (old->status == RAP_INACTIVE));
  311. // Get sample rtt
  312. sampleRtt = key.departureTime - old->departureTime; 
  313. UpdateTimeValues(sampleRtt);
  314. delete old;
  315. }
  316.   
  317. if (!anyack()) {
  318. flags_ |= RF_ANYACK;
  319. ipg_ = srtt_;
  320. }
  321.   
  322. if (LossDetection(RAP_ACK_BASED, ackHeader))
  323. LossHandler();
  324. // XXX We only stop by sequence number when we are in 
  325. // "counting sequence number" mode.   -- haoboy
  326. if (counting_pkt() && (ackHeader->seqno_ >= curseq_)) 
  327. finish();
  328. }
  329. //----------------------------------------------------------------------
  330. // RapAgent::timeout
  331. //      Called when a timer fires.
  332. //
  333. //      "type" is the type of Timeout event
  334. //----------------------------------------------------------------------
  335. void RapAgent::timeout(int type)
  336. {
  337. if (type == RAP_IPG_TIMEOUT)
  338. IpgTimeout();
  339. else if (type == RAP_RTT_TIMEOUT)
  340. RttTimeout();
  341. else
  342. assert(FALSE);
  343. }
  344. //----------------------------------------------------------------------
  345. // RapAgent::IpgTimeout
  346. //      Called when the ipgTimer_ fires.
  347. //----------------------------------------------------------------------
  348. void RapAgent::IpgTimeout()
  349. {
  350. double waitPeriod; // Time before next transmission
  351. Debug(debugEnable_, logfile_, 
  352.       "%.3f: IPG Timeout.n", Scheduler::instance().clock());
  353. if (LossDetection(RAP_TIMER_BASED))
  354. LossHandler();
  355. else if (!counting_pkt()) {
  356. if (app_) {
  357. int nbytes;
  358. AppData* data = app_->get_data(nbytes);
  359. // Missing data in application. What should we do??
  360. // For now, simply schedule the next SendPacket(). 
  361. // If the application has nothing to send, it'll stop 
  362. // the rap agent later on. 
  363. if (data != NULL) {
  364. SendPacket(nbytes, data);
  365. dctr_++;
  366. }
  367. } else {
  368. // If RAP doesn't have application, just go ahead and 
  369. // send packet
  370. SendPacket(size_);
  371. dctr_++;
  372. }
  373. } else if (seqno_ < curseq_) {
  374. SendPacket(size_);
  375. dctr_++;
  376. }
  377. // XXX If we only bound IPG in DecreaseIpg(), the thresholding will 
  378. // happen immediately because DecreaseIpg() isn't called immediately. 
  379. // So we do it here. 
  380. if (fixIpg_ != 0)
  381. ipg_ = fixIpg_;
  382. if (useFineGrain_)
  383. waitPeriod = frtt_ / xrtt_ * ipg_;
  384. else 
  385. waitPeriod = ipg_;
  386. // By this point, we may have been stopped by applications above
  387. // Thus, do not reschedule a timer if we are stopped. 
  388. if (!is_stopped())
  389. ipgTimer_.resched(waitPeriod + Random::uniform(overhead_));
  390. }
  391.   
  392. //----------------------------------------------------------------------
  393. // RapAgent::RttTimeout
  394. //      Called when the rttTimer_ fires.
  395. //      Decrease IPG. Restart rttTimer_.
  396. //----------------------------------------------------------------------
  397. void RapAgent::RttTimeout()
  398. {
  399. Debug(debugEnable_, logfile_, 
  400.       "%.3f: RTT Timeout.n", Scheduler::instance().clock());
  401. // During the past srtt_, we are supposed to send out srtt_/ipg_
  402. // packets. If we sent less than that, we may not increase rate
  403. if (100*dctr_*(ipg_/srtt_) >= dpthresh_)
  404. DecreaseIpg(); // Additive increase in rate
  405. else 
  406. Debug(debugEnable_, logfile_, 
  407.       "- %f Cannot increase rate due to insufficient data.n",
  408.       Scheduler::instance().clock());
  409. dctr_ = 0;
  410. double debugIpg = ipg_ + overhead_ / 2;
  411. Debug(debugEnable_, logfile_, 
  412.       "- ipg decreased at %.3f to %fn", 
  413.       Scheduler::instance().clock(), debugIpg);
  414. rttTimer_.resched(srtt_);
  415. }
  416. //----------------------------------------------------------------------
  417. // RapAgent::LossDetection
  418. //      Called in ipgTimeout (RAP_TIMER_BASED) 
  419. //          or in RecvAck (RAP_ACK_BASED).
  420. //
  421. // Returns:
  422. //      TRUE if loss detected, FALSE otherwise.
  423. //
  424. //      "ackHeader" is the RAP header of the received Ack (PT_RAP_ACK).
  425. //----------------------------------------------------------------------
  426. static double currentTime;
  427. static hdr_rap *ackHdr;
  428. static RapAgent *rapAgent; 
  429. static int numLosses;
  430. int EqualStatus(void *i1, void *i2)
  431. return (((TransHistoryEntry *) i1)->status == 
  432. ((TransHistoryEntry *) i2)->status);
  433. }
  434. void DestroyTransHistoryEntry(long item)
  435. {
  436. TransHistoryEntry *entry = (TransHistoryEntry *) item;
  437. Debug(rapAgent->GetDebugFlag(), rapAgent->GetLogfile(),
  438.       "- purged seq num %dn", entry->seqno);
  439. delete entry;
  440. }
  441. void TimerLostPacket(long item)
  442. {
  443. TransHistoryEntry *entry = (TransHistoryEntry *) item;
  444. if ((entry->departureTime + rapAgent->GetTimeout()) <= currentTime) {
  445. // ~ Packets lost in RAP session
  446. rapAgent->IncrementLossCount(); 
  447. // Ignore cluster losses
  448. if (entry->status != RAP_INACTIVE) {
  449. assert(entry->status == RAP_SENT);
  450. numLosses++;
  451. Debug(rapAgent->GetDebugFlag(), rapAgent->GetLogfile(),
  452.       "- timerlost seq num %d , last sent %dn", 
  453.       entry->seqno, rapAgent->GetSeqno());
  454. }
  455. entry->status = RAP_PURGED; 
  456. }
  457. }
  458. void AckLostPacket(long item)
  459. {
  460. TransHistoryEntry *entry = (TransHistoryEntry *) item;
  461. int seqno, lastRecv, lastMiss, prevRecv;
  462. seqno = entry->seqno;
  463. lastRecv = ackHdr->lastRecv;
  464. lastMiss = ackHdr->lastMiss;
  465. prevRecv = ackHdr->prevRecv;
  466. if (seqno <= lastRecv) {
  467. if ((seqno > lastMiss) || (seqno == prevRecv))
  468. entry->status = RAP_PURGED; // Was Received, now purge
  469. else if ((lastRecv - seqno) >= 3) {
  470. // ~ Packets lost in RAP session
  471. rapAgent->IncrementLossCount(); 
  472. if (entry->status != RAP_INACTIVE) {
  473. assert(entry->status == RAP_SENT);
  474. numLosses++;
  475. Debug(rapAgent->GetDebugFlag(), 
  476.       rapAgent->GetLogfile(),
  477.       "- acklost seqno %d , last sent %dn", 
  478.       seqno, rapAgent->GetSeqno());
  479. }
  480. // Was Lost, purge from history
  481. entry->status = RAP_PURGED; 
  482. }
  483. }
  484. }
  485. int RapAgent::LossDetection(RapLossType type, hdr_rap *ackHeader)
  486. {
  487. TransHistoryEntry key(0, RAP_PURGED);
  488. currentTime = key.departureTime;
  489. ackHdr = ackHeader;
  490. rapAgent = this;
  491. numLosses = 0;
  492. switch(type) {
  493. case RAP_TIMER_BASED:
  494. transmissionHistory_.Mapcar(TimerLostPacket);
  495. break;
  496. case RAP_ACK_BASED:
  497. transmissionHistory_.Mapcar(AckLostPacket);
  498. break;
  499. default:
  500. assert(FALSE);
  501. }
  502. Debug(debugEnable_, logfile_, 
  503.       "- %d losses detectedn", numLosses); 
  504. Debug(debugEnable_, logfile_, 
  505.       "- history size %dn", transmissionHistory_.Size());
  506.   
  507. transmissionHistory_.Purge((void *) &key, 
  508.    EqualStatus, // Purge PURGED packets
  509.    DestroyTransHistoryEntry);
  510. Debug(debugEnable_, logfile_, 
  511.       "- history size %dn", transmissionHistory_.Size());
  512. if (numLosses)
  513. return TRUE;
  514. else
  515. return FALSE;
  516. }
  517. //----------------------------------------------------------------------
  518. // RapAgent::LossHandler
  519. //      Called when loss detected.
  520. //      Increase IPG. Mark packets INACTIVE. Reschedule rttTimer_.
  521. //----------------------------------------------------------------------
  522. void MarkInactive(long item)
  523. {
  524. TransHistoryEntry *entry = (TransHistoryEntry *) item;
  525. entry->status = RAP_INACTIVE;
  526. }
  527. void RapAgent::LossHandler()
  528. {
  529. IncreaseIpg(); // Multiplicative decrease in rate
  530. double debugIpg = ipg_ + overhead_ / 2;
  531. Debug(debugEnable_, logfile_, 
  532.       "- ipg increased at %.3f to %fn", 
  533.       Scheduler::instance().clock(), debugIpg);
  534. transmissionHistory_.Mapcar(MarkInactive);
  535. Debug(debugEnable_, logfile_, 
  536.       "- window full packets marked inactiven");
  537. rttTimer_.resched(srtt_);
  538. }
  539. //----------------------------------------------------------------------
  540. // RapAgent::SendAck
  541. //      Create an ack packet, set fields, send the packet out.
  542. //
  543. //      "seqNum" is the sequence number of the packet being acked.
  544. //----------------------------------------------------------------------
  545. void RapAgent::SendAck(int seqNum)
  546. {
  547. type_ = PT_RAP_ACK;
  548. Packet* pkt = allocpkt(); // Create a new packet
  549. hdr_rap* hdr = hdr_rap::access(pkt);   // Access header
  550. hdr->seqno() = seqNum;
  551. hdr->flags() = RH_ACK;
  552. hdr->lastRecv = lastRecv_;
  553. hdr->lastMiss = lastMiss_;
  554. hdr->prevRecv = prevRecv_;
  555. hdr_cmn *ch = hdr_cmn::access(pkt);
  556. ch->size() = rap_base_hdr_size_;
  557. send(pkt, 0);
  558. Debug(debugEnable_, logfile_, 
  559.       "- ack sent %u [%u %u %u]n", 
  560.       seqNum, lastRecv_, lastMiss_, prevRecv_);
  561. }
  562. //----------------------------------------------------------------------
  563. // RapSinkAgent::UpdateLastHole
  564. //      Update the last hole in sequence number space at the receiver.
  565. //      
  566. // "seqNum" is the sequence number of the data packet received.
  567. //----------------------------------------------------------------------
  568. void RapAgent::UpdateLastHole(int seqNum)
  569. {
  570. assert(seqNum > 0);
  571. if (seqNum > (lastRecv_ + 1)) {
  572. prevRecv_ = lastRecv_;
  573. lastRecv_ = seqNum;
  574. lastMiss_ = seqNum - 1;
  575. return;
  576. }
  577. if (seqNum == (lastRecv_ + 1)) {
  578. lastRecv_ = seqNum;
  579. return;
  580. }
  581. if ((lastMiss_ < seqNum) && (seqNum <= lastRecv_)) // Duplicate
  582. return;
  583. if (seqNum == lastMiss_) {
  584. if ((prevRecv_ + 1) == seqNum) // Hole filled
  585. prevRecv_ = lastMiss_ = 0;
  586. else
  587. lastMiss_--;
  588. return;
  589. }
  590. if ((prevRecv_ < seqNum) && (seqNum < lastMiss_)) {
  591. prevRecv_ = seqNum;
  592. return;
  593. }
  594. assert(seqNum <= prevRecv_); // Pretty late...
  595. }
  596. // take pkt count
  597. void RapAgent::advanceby(int delta)
  598. {
  599. flags_ |= RF_COUNTPKT;
  600.         curseq_ = delta;
  601. start();
  602. }
  603. void RapAgent::finish()
  604. {
  605. stop();
  606. Tcl::instance().evalf("%s done", this->name());
  607. }