📄 rap.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *///// Copyright (c) 1997 by the University of Southern California// All rights reserved.//// Permission to use, copy, modify, and distribute this software and its// documentation in source and binary forms for non-commercial purposes// and without fee is hereby granted, provided that the above copyright// notice appear in all copies and that both the copyright notice and// this permission notice appear in supporting documentation. and that// any documentation, advertising materials, and other materials related// to such distribution and use acknowledge that the software was// developed by the University of Southern California, Information// Sciences Institute. The name of the University may not be used to// endorse or promote products derived from this software without// specific prior written permission.//// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about// the suitability of this software for any purpose. THIS SOFTWARE IS// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// Other copyrights might apply to parts of this software and are so// noted when applicable.//// rap.cc // Code for the 'RAP Source' Agent Class//// Author: // Mohit Talwar (mohit@catarina.usc.edu)//// $Header: /nfs/jade/vint/CVSROOT/ns-2/rap/rap.cc,v 1.11 2000/01/07 06:25:32 sfloyd Exp $#include "rap.h"int hdr_rap::offset_; // static offset of RAP headerstatic class RapHeaderClass : public PacketHeaderClass {public: RapHeaderClass() : PacketHeaderClass("PacketHeader/RAP", sizeof(hdr_rap)) { bind_offset(&hdr_rap::offset_); }} class_raphdr;static class RapClass : public TclClass {public: RapClass() : TclClass("Agent/RAP") {} TclObject* create(int, const char*const*) { return (new RapAgent()); }} class_rap;void IpgTimer::expire(Event *){ a_->timeout(RAP_IPG_TIMEOUT); }void RttTimer::expire(Event *){ a_->timeout(RAP_RTT_TIMEOUT); }//----------------------------------------------------------------------// EqualSeqno// Compare TransHistory Entries on the seqno field.//// "i1", "i2" are the TransHistory entries to be compared.//---------------------------------------------------------------------- int EqualSeqno(void *i1, void *i2){ return (((TransHistoryEntry *) i1)->seqno == ((TransHistoryEntry *) i2)->seqno);}//----------------------------------------------------------------------// RapAgent::RapAgent// Initialize the RAP agent.// Bind variables which have to be accessed in both Tcl and C++.// Initializes time values.//----------------------------------------------------------------------RapAgent::RapAgent() : Agent(PT_RAP_DATA), ipgTimer_(this), rttTimer_(this), seqno_(0), sessionLossCount_(0), curseq_(0), ipg_(2.0), srtt_(2.0), timeout_(2.0), lastRecv_(0), lastMiss_(0), prevRecv_(0), dctr_(0), flags_(0), fixIpg_(0){ bind("packetSize_", &size_); // Default 512 bind("seqno_", &seqno_); // Default 0 bind("sessionLossCount_", &sessionLossCount_); // Default 0 bind("ipg_", &ipg_); // Default 2 seconds bind("beta_", &beta_); // Default 0.5 bind("alpha_", &alpha_); // Default 1.0 bind("srtt_", &srtt_); // Default 2 seconds bind("variance_", &variance_);// Default 0 bind("delta_", &delta_); // Default 0.5 bind("mu_", &mu_); // Default 1.2 bind("phi_", &phi_); // Default 4 bind("timeout_", &timeout_); // Default 2 seconds bind("overhead_", &overhead_); // Default 0 bind("useFineGrain_", &useFineGrain_); // Default FALSE bind("kfrtt_", &kfrtt_); // Default 0.9 bind("kxrtt_", &kxrtt_); // Default 0.01 bind("debugEnable_", &debugEnable_); // Default FALSE bind("off_rap_", &off_rap_); bind("rap_base_hdr_size_", &rap_base_hdr_size_); bind("dpthresh_", &dpthresh_); frtt_ = xrtt_ = srtt_;}// Cancel all our timers before we quitRapAgent::~RapAgent(){// fprintf(stderr, "%g: rap agent %s(%d) stops.\n", // Scheduler::instance().clock(), name(), addr());// Tcl::instance().eval("[Simulator instance] flush-trace"); stop();}//----------------------------------------------------------------------// RapAgent::UpdateTimeValues// Update the values for srtt_, variance_ and timeout_ based on// the "sampleRtt". Use Jacobson/Karl's algorithm.// // "sampleRtt" is the sample round trip time obtained from the // current ack packet.//----------------------------------------------------------------------void RapAgent::UpdateTimeValues(double sampleRtt){ double diff; static int initial = TRUE; if (initial) { frtt_ = xrtt_ = srtt_ = sampleRtt; // First sample, no history variance_ = 0; initial = FALSE; } diff = sampleRtt - srtt_; srtt_ += delta_ * diff; diff = (diff < 0) ? diff * -1 : diff; // Take mod variance_ += delta_ * (diff - variance_); timeout_ = mu_ * srtt_ + phi_ * variance_; if (useFineGrain_) { frtt_ = (1 - kfrtt_) * frtt_ + kfrtt_ * sampleRtt; xrtt_ = (1 - kxrtt_) * xrtt_ + kxrtt_ * sampleRtt; } double debugSrtt = srtt_; // $%#& stoopid compiler Debug(debugEnable_, logfile_, "- srtt updated to %f\n", debugSrtt);}void RapAgent::start(){ if (debugEnable_) logfile_ = DebugEnable(this->addr() >> Address::instance().NodeShift_[1]); else // Should initialize it regardless of whether it'll be used. logfile_ = NULL; Debug(debugEnable_, logfile_, "%.3f: RAP start.\n", Scheduler::instance().clock()); flags_ = flags_ & ~RF_STOP; startTime_ = Scheduler::instance().clock(); RttTimeout(); // Decreases initial IPG IpgTimeout();}// Used by a sink to listen to incoming packetsvoid RapAgent::listen(){ if (debugEnable_) logfile_ = DebugEnable(this->addr() >> Address::instance().NodeShift_[1]);}void RapAgent::stop(){ Debug(debugEnable_, logfile_, "%.3f: RAP stop.\n", Scheduler::instance().clock()); // Cancel the timer only when there is one if (ipgTimer_.status() == TIMER_PENDING) ipgTimer_.cancel(); if (rttTimer_.status() == TIMER_PENDING) rttTimer_.cancel(); stopTime_ = Scheduler::instance().clock(); int debugSeqno = seqno_; Debug(debugEnable_, logfile_, "- numPackets %d, totalTime %f\n", debugSeqno, stopTime_ - startTime_); flags_ |= RF_STOP;}//----------------------------------------------------------------------// RapAgent::command// Called when a Tcl command for the RAP agent is executed.// Two commands are supported// $rapsource start// $rapsource stop//----------------------------------------------------------------------int RapAgent::command(int argc, const char*const* argv){ if (argc == 2) { if (strcmp(argv[1], "start") == 0) { start(); // return TCL_OK, so the calling function knows that // the command has been processed return (TCL_OK); } else if (strcmp(argv[1], "stop") == 0) { stop(); return (TCL_OK); } else if (strcmp(argv[1], "listen") == 0) { listen(); return (TCL_OK); } } else if (argc == 3) { if (strcmp(argv[1], "advanceby") == 0) { advanceby(atoi(argv[2])); return (TCL_OK); } } // If the command hasn't been processed by RapAgent()::command, // call the command() function for the base class return (Agent::command(argc, argv));}//----------------------------------------------------------------------// RapAgent::SendPacket// Called in IpgTimeout().// Create a packet, increase seqno_, send the packet out.//----------------------------------------------------------------------void RapAgent::SendPacket(int nbytes, AppData *data){ TransHistoryEntry *pktInfo; Packet *pkt; type_ = PT_RAP_DATA; if (data) pkt = allocpkt(data->size()); else pkt = allocpkt(); // Fill in RAP headers hdr_rap* hdr = (hdr_rap*) pkt->access(off_rap_); hdr->seqno() = ++seqno_; // Start counting from 1; hdr->lastRecv = hdr->lastMiss = hdr->prevRecv = 0; // Ignore @ sender hdr->flags() = RH_DATA; if (data) { hdr->size() = data->size(); pkt->setdata(data); } else { hdr->size() = size_; } // XXX Simply set packet size to the given ADU's nominal size. // Make sure that the size is reasonable!! hdr_cmn *ch = (hdr_cmn*)pkt->access(off_cmn_); ch->size() = nbytes; send(pkt, 0); pktInfo = new TransHistoryEntry(seqno_); transmissionHistory_.SetInsert((void *) pktInfo, EqualSeqno); int debugSeqno = seqno_; Debug(debugEnable_, logfile_, "- packet %d sent\n", debugSeqno);}//----------------------------------------------------------------------// RapAgent::recv// Called when a packet is received.// Should be of type PT_RAP_ACK.//----------------------------------------------------------------------void RapAgent::recv(Packet* pkt, Handler*){ Debug(debugEnable_, logfile_, "%.3f: RAP packet received.\n", Scheduler::instance().clock()); hdr_rap* hdr = (hdr_rap*) pkt->access(off_rap_); // Access RAP header switch (hdr->flags()) { case RH_DATA: UpdateLastHole(hdr->seqno()); SendAck(hdr->seqno()); if ((pkt->datalen() > 0) && app_) // We do have user data, process it app_->process_data(pkt->datalen(), pkt->userdata()); break; case RH_ACK: RecvAck(hdr); break; default: fprintf(stderr, "RAP agent %s received a packet with unknown flags %x", name(), hdr->flags()); break; } Packet::free(pkt); // Discard the packet}//----------------------------------------------------------------------// RapAgent::RecvAck// Called when an Ack is received.// // "header" is the RAP header of the Ack.//----------------------------------------------------------------------void RapAgent::RecvAck(hdr_rap *ackHeader){ double sampleRtt; TransHistoryEntry *old, key(ackHeader->seqno_); assert(ackHeader->seqno_ > 0); Debug(debugEnable_, logfile_, "- ack %d\n", ackHeader->seqno_); old = (TransHistoryEntry *) transmissionHistory_.SetRemove((void *) &key, EqualSeqno); if (old != NULL) { Debug(debugEnable_, logfile_, "- found in transmission history\n"); assert((old->status == RAP_SENT) || (old->status == RAP_INACTIVE)); // Get sample rtt sampleRtt = key.departureTime - old->departureTime; UpdateTimeValues(sampleRtt); delete old; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -