diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/Makefile.in ns-allinone-2.32-LAR_DREAM/ns-2.32/Makefile.in --- ns-allinone-2.32/ns-2.32/Makefile.in 2007-08-24 00:26:16.000000000 -0400 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/Makefile.in 2007-10-17 16:09:22.000000000 -0400 @@ -308,10 +308,12 @@ wpan/p802_15_4csmaca.o wpan/p802_15_4fail.o \ wpan/p802_15_4hlist.o wpan/p802_15_4mac.o \ wpan/p802_15_4nam.o wpan/p802_15_4phy.o \ wpan/p802_15_4sscs.o wpan/p802_15_4timer.o \ wpan/p802_15_4trace.o wpan/p802_15_4transac.o \ + lar/lar.o \ + dream/dream.o \ @V_STLOBJ@ # don't allow comments to follow continuation lines diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/common/packet.h ns-allinone-2.32-LAR_DREAM/ns-2.32/common/packet.h --- ns-allinone-2.32/ns-2.32/common/packet.h 2006-02-22 08:32:23.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/common/packet.h 2007-10-17 16:09:22.000000000 -0400 @@ -66,11 +66,18 @@ #define HDR_TFRC(p) (hdr_tfrc::access(p)) #define HDR_TORA(p) (hdr_tora::access(p)) #define HDR_IMEP(p) (hdr_imep::access(p)) #define HDR_CDIFF(p) (hdr_cdiff::access(p)) /* chalermak's diffusion*/ //#define HDR_DIFF(p) (hdr_diff::access(p)) /* SCADD's diffusion ported into ns */ -#define HDR_LMS(p) (hdr_lms::access(p)) +#define HDR_LMS(p) (hdr_lms::access(p)) +#define HDR_FEEDBACK(p) (hdr_feedback::access(p)) +#define HDR_ALARM(p) (hdr_alarm::access(p)) +#define HDR_FLOOD(p) (hdr_flood:access(p)) +#define HDR_LAR(p) (hdr_lar::access(p)) +#define HDR_DREAM(p) (hdr_dream::access(p)) +#define HDR_ZRP(p) (hdr_zrp::access(p)) + /* --------------------------------------------------------------------*/ enum packet_t { PT_TCP, @@ -168,10 +175,28 @@ PT_HDLC, // Bell Labs Traffic Trace Type (PackMime OL) PT_BLTRACE, + // Flood + PT_FLOOD, + + // Feedback + PT_FEEDBACK, + + // DREAm + PT_DREAM, + + // alarm + PT_ALARM, + + // Lar + PT_LAR, + + // ZRP + PT_ZRP, + // insert new packet types here PT_NTYPE // This MUST be the LAST one }; class p_info { @@ -266,10 +291,28 @@ // XCP name_[PT_XCP]="xcp"; // Bell Labs (PackMime OL) name_[PT_BLTRACE]="BellLabsTrace"; + + // flood + name_[PT_FLOOD]="FLOOD"; + + // feedback + name_[PT_FEEDBACK]="FeedbackBeacon"; + + // alarm + name_[PT_ALARM]="ALARM"; + + // DREAM + name_[PT_DREAM] = "Dream"; + + // lar + name_[PT_LAR]="LAR"; + + // ZRP + name_[PT_ZRP]= "ZRP"; name_[PT_NTYPE]= "undefined"; } const char* name(packet_t p) const { if ( p <= PT_NTYPE ) return name_[p]; diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/README ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/README --- ns-allinone-2.32/ns-2.32/dream/README 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/README 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,93 @@ +/****************************************************************************** +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details in LAR-DREAM/. + +*******************************************************************************/ + +Toilers code for DREAM in NS-2. + +The paper related to this code is: + +T. Camp, J. Boleng, B. Williams, L. Wilcox, and W. Navidi, Performance +Comparision of Two Location Based Routing Protocols for Ad Hoc +Networks, Proceedings of the IEEE INFOCOM, pp. 1678-1687, 2002. + +=========================== + +We are happy to share our code with you. We only ask that any +published research from using our code include a reference to our +INFOCOM 2002 paper. + +If you have any questions on the code, send email to Tracy Camp at +tcamp@mines.edu. + +The research group's URL is http://toilers.mines.edu. + +=========================== + +Please be advised that this code has only been integrated into and +tested with ns2.1b7a. + +See the README file in LAR-DREAM/ for further details. + +=========================== + +Steps to get DREAM to work in ns2.1b7a + +1. Download, install and compile the ns2.1b7a distribution from Berkely. +2. In the base ns2.1b7a directory create a new directory called dream. +3. Move following files into that dir: + + dream.h - header file for ns agent + dream.cc - cc file for ns agent + dream.tcl - tcl file to run dream scenario + dream2.awk - awk filter to pipe trace file through to + - collect stats + scen-300x600-50-10-5-00 - mobility scenario file for 50 nodes in a + 300x600 sim area. Average pause time = 10 + seconds, ave speed = 5 m/s + sendDataFile.dat - file to schedule data packet delivery using + dream + + +4. Modify following ns2.1b7a files to support Dream: + (Examples of these files are under ~ns2-modify) + + cmu-trace.h + cmu-trace.cc + packet.h + Makefile + tcl/lib/ns-packet.tcl + + Examples of the required modifications are included in this dir. I recommend + changing your files for dream only, because these included files have + modifications for other protocols that you won't have in your distribution. + Basically, don't just copy them over, because it'll blow chunks on compilation. + +5. Make a new ns executable. + +6. Go to the dream directory and run a simulation with the following command + + ../ns dream.tcl ./output.dat ./scen-300x600-50-10-5-00 + +7. output.dat should have filtered results from simulation: + + rpt - # routing packets (control) transmitted during sim + rpr - # routing packet received + dpt - # data packets tranmitted during sim + dpr - # data packets received during sim + tpt - # total packets transmitted + tpr - # total packets received + dps - # data packets transmitted + dpa - # data packets arrived at destination + drat - delivery ratio + hc - hop count average + ee - end/end delay average + +8. Code written by Brad Williams (M.S. 2002 from Colorado School of +Mines). If you have any problems with this code, email Tracy Camp: +tcamp@mines.edu. + +=========================== \ No newline at end of file diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/dream.cc ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.cc --- ns-allinone-2.32/ns-2.32/dream/dream.cc 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.cc 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,1709 @@ +/****************************************************************************** +* File Name: dream.cc +* Purpose: DREAM cc file for ns2 +* Original Author: Jeff Boleng +* Modified by: +* Date Created: Some time in 2002 +* +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details. +*******************************************************************************/ + +#include +#include +#include +#include + +#include "dream.h" + +using namespace std; + +// I had to put this here since it is a static variable or else I was getting +// link errors when I compiled ns. I got the solution of the mailing list. +int hdr_dream::offset_; + +// The next two class declarations bind our C++ classes to the OTcl +// class. +static class DreamHeaderClass : public PacketHeaderClass +{ + public: + DreamHeaderClass() : PacketHeaderClass("PacketHeader/Dream", + sizeof(hdr_dream)) + { + // Consult the NS manual about this stuff, that is where I found it. + bind_offset(&hdr_dream::offset_); + } +} class_dreamhdr; + +static class DreamClass : public TclClass +{ + public: + DreamClass() : TclClass("Agent/Dream") + { + } + + TclObject* create(int, const char*const*) + { + return (new DreamAgent()); + } +} class_dream; + +// *********************************************************************** +// DreamLocationTimer expire +// *********************************************************************** +// this gets called when a packet timer expires +void DreamLocationTimer::expire(Event *e) +{ + agent->bradsDreamSendLocationPacket(sendLong); +} + +// *********************************************************************** +// DreamPacketTimer expire +// *********************************************************************** +// this gets called when a packet timer expires +void DreamPacketTimer::expire(Event *e) +{ + a_->setDebugValue(4); + wasCanceled_ = true; + //cout << endl << endl << "Sending Recovery packet!!!"<< endl; + a_->printPacketHeader(p_); + //cerr << "Sending Recovery packet!!!"<< endl; + a_->recovery(p_, true, true); +} + +// *********************************************************************** +// DreamPacketTimer wasCanceled +// *********************************************************************** +// call this to cancel a timer. +void DreamPacketTimer::dcancel() +{ + if(!wasCanceled_) + { + cancel(); + Packet::free(p_); + wasCanceled_ = true; + } +} + +// *********************************************************************** +// DreamAgent Constructor +// *********************************************************************** +DreamAgent::DreamAgent() : Agent(PT_DREAM) +{ + // Default values of one long packet per freqOfLongLocationPackets short + // packets + freqOfLongLocationPackets = 10; + + // Default distance of location packets if either is set to -1 then the + // packet will be transmitted to all of the nodes in reach (flood the + // network). + shortLocationPacketDistance = DREAM_TRANS_DIST; + longLocationPacketDistance = -1; + + // This is the counter that determines if a long or short location packet + // will be sent. + if(USE_STAGGER_LONG_LOCATION) + { + // This code did not work and I don't know why. + //randomVariable = UniformRandomVariable((double)0, + // (double)freqOfLongLocationPackets - 1); + // This will truncate the output of randomVariable.value() to an int. + //longShort = (int)randomVariable.value(); + + // Use the default random number generator. + longShort = (int)RNG::defaultrng()->uniform(0, + (freqOfLongLocationPackets - 1)); + //cout << "longShort = " << longShort << endl; + } + else + { + // This is the value longShort needs so that a long location packet + // will be sent out the first time. + longShort = 0; + } + + // This is the maximum distance that a node will be considered a neighbor + maxNeighborDistance = DREAM_TRANS_DIST; + + // counter for packets + sentDataPackets = 0; + receivedDataPackets = 0; + + // initialize constants with default that can be changed in the tcl script + locationGoodTime = 46; + bradsDreamFactor = 5; + bradsDreamLongTime = 23; + bradsDreamLocationTimer = NULL; + bradsDreamLongLocationTimer = NULL; + maxPacketTimeout = MAX_PACKET_TIMEOUT; + maxNodeVelocity = MAX_NODE_VELOCITY; + + // link layer and node handles + ll = NULL; + node = NULL; + + // The debug level the higher the more stuff will be sent to stdout + // set to -1 for no output. + debugLevel = -1; + + // This set the default debug Value to 10 + setDebugValue(10); + + return; +} + +// *********************************************************************** +// DreamAgent Destructor +// *********************************************************************** +DreamAgent::~DreamAgent() +{ + rcvdPackets.erase(rcvdPackets.begin(), rcvdPackets.end()); + sentPackets.erase(sentPackets.begin(), sentPackets.end()); + locationMap.erase(locationMap.begin(), locationMap.end()); + return; +} + +// *********************************************************************** +// DreamAgent printDebug +// *********************************************************************** +// This function returns true if the debug message should be printed. +bool DreamAgent::printDebug() +{ + if(debugLevel > debugValue) + { + return true; + } + else + { + return false; + } +} + +// *********************************************************************** +// DreamAgent setDebugValue +// *********************************************************************** +// This set the debugValue of the next statements to be printed. +void DreamAgent::setDebugValue(int dbv) +{ + debugValue = dbv; +} + +// *********************************************************************** +// DreamAgent command +// *********************************************************************** +int DreamAgent::command(int argc, const char*const* argv) +{ + TclObject *obj; + + if (argc == 2) + { + if (strcmp(argv[1], "startLocationService") == 0) + { + if(!USE_BRADS_DREAM) + { + fprintf(stderr, "You have USE_BRADS_DREAM set to false.\n"); + fprintf(stderr, "USE_BRADS_DREAM needs to be true to use\n"); + fprintf(stderr, "startLocationService to tell the dream agent when\n"); + fprintf(stderr, "to start to send the location packets.\n"); + return(TCL_ERROR); + } + + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a dream agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + + bradsDreamSendLocationPacket(false); + + return (TCL_OK); + } + else if (strcmp(argv[1], "sendLocation") == 0) + { + // This will make a node send its location information. + // A node will only sent its location information once you have + // to keep calling this from the tcl script to get more. + if(USE_BRADS_DREAM) + { + fprintf(stderr, "You have USE_BRADS_DREAM set to true.\n"); + fprintf(stderr, "USE_BRADS_DREAM needs to be false to use\n"); + fprintf(stderr, "sendLocation to tell the dream agent when\n"); + fprintf(stderr, "to sent the location packets.\n"); + return(TCL_ERROR); + } + + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a dream agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + node->update_position(); + + // Create a new packet + Packet* pkt = allocpkt(); + + // Access the Dream header for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + // Store the current time in the 'send_time' field + dreamhdr->sendTime_ = Scheduler::instance().clock(); + + // Fill in this field with the packet id since it is not and ack + dreamhdr->ackPacketId_ = hdrcmn->uid_; + + // This fills the location info into the header. + dreamhdr->dreamPacketType_ = DREAM_LOCATION_PACKET; + dreamhdr->sourceX_ = node->X(); + dreamhdr->sourceY_ = node->Y(); + dreamhdr->sourceSpeed_ = node->speed(); + + // This initializes the hop information in the header + dreamhdr->hops() = 0; + dreamhdr->route_[dreamhdr->hops()] = this->addr(); + dreamhdr->hops()++; + + // The location packet doesn't have a data part + dreamhdr->dataLength_ = 0; + + //.This means that the packet is being flooded. + dreamhdr->broadcast_ = true; + + // Not using the recovey + dreamhdr->usedRecovery_ = false; + + // Since this is a location packet it is always the original packet. + dreamhdr->originalPacketId_ = hdrcmn->uid_; + + // This is the first time this packet is being sent + dreamhdr->first_ = true; + + // The location packet is broadcast to everybody neighbors do not have + // to be listed. + dreamhdr->numDreamNodes_ = 0; + + // This determines if a long or short location packet should be sent, + // this is implemented as describe in the DREAM paper, I would like to + // try something different later. + if(longShort == 0) + { + dreamhdr->maxDistance_ = longLocationPacketDistance; + } + else + { + dreamhdr->maxDistance_ = shortLocationPacketDistance; + } + // Increment for the next location packet. + longShort++; + // Keep the longShort a number in the range + // [0, freqOfLongLocaitonPackets - 1] + longShort %= freqOfLongLocationPackets; + + // This puts the IP_BROADCAST Number in the toAddr of the DREAM header + dreamhdr->toAddr_ = IP_BROADCAST; + + // Set the debug value for the following debug statements. + setDebugValue(5); + if (printDebug()) + { + cout << "****************************************************" << endl; + cout << "Sending Location Information from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" + << endl << "Time: " << Scheduler::instance().clock() << endl; + } + + // Send the location packet. + this->broadcastPacket(pkt); + + if (printDebug()) + { + cout << "****************************************************" << endl + << endl; + } + + // return TCL_OK, so the calling function knows that the + // command has been processed + return (TCL_OK); + } + else if (strcmp(argv[1], "printLocationTable") == 0) + { + // If called from the tcl script this will print out the node's location + // table + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a dream agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + node->update_position(); + cout << "****************************************************" << endl; + cout << "Printing Location Table for node: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + printLocationTable(); + cout << "****************************************************" << endl + << endl; + return (TCL_OK); + } + else if (strcmp(argv[1], "printStatistics") == 0) + { + // If called from the tcl script this will print out the node's + // statistics that I keep track of. Node that these might not return + // what you expect because it was designed to be used with the recovery + // method commented out. + // ** Note that this is an old thing that is not currently being used ** + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a dream agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + node->update_position(); + //cout << "****************************************************" << endl; + //cout << "Printing Statistics for node: " << this->addr() + // << " at [" << node->X() << "," << node->Y() << "]" << endl; + //cout << "Time: " << Scheduler::instance().clock() << endl; + printStatistics(); + //cout << "****************************************************" << endl + // << endl; + return (TCL_OK); + } + } + else if (argc == 3) + { + if (strcmp(argv[1], "set-ll") == 0) + { + // This sets the link layer so packet can be sent directly to the link + // layer. + if( (obj = TclObject::lookup(argv[2])) == 0) + { + fprintf(stderr, "DreamAgent(set-ll): %s lookup of %s failed\n", + argv[1], argv[2]); + return (TCL_ERROR); + } + ll = (NsObject*) obj; + return (TCL_OK); + } + else if (strcmp(argv[1], "set-node") == 0) + { + // This sets the node to which this agent is attached. + if( (obj = TclObject::lookup(argv[2])) == 0) + { + fprintf(stderr, "DreamAgent(set-node): %s lookup of %s failed\n", + argv[1], argv[2]); + return (TCL_ERROR); + } + node = dynamic_cast< MobileNode * >(obj); + if (node) // dynamic cast was successful and didn't return NULL + { + return (TCL_OK); + } + else + { + fprintf(stderr, "Unable to dynamically cast %s to a MobileNode\n", + argv[2]); + return (TCL_ERROR); + } + } + else if (strcmp(argv[1], "set-freqOfLongLocationPackets") == 0) + { + freqOfLongLocationPackets = atoi(argv[2]); + // This is the counter that determines if a long or short location packet + // will be sent. + if(USE_STAGGER_LONG_LOCATION) + { + // Use the default random number generator. + longShort = (int)RNG::defaultrng()->uniform(0, + (freqOfLongLocationPackets - 1)); + //cout << "longShort = " << longShort << endl; + } + else + { + // This is the value longShort needs so that a long location packet + // will be sent out the first time. + longShort = 0; + } + + return (TCL_OK); + } + else if (strcmp(argv[1], "set-shortLocationPacketDistance") == 0) + { + shortLocationPacketDistance = atof(argv[2]); + return (TCL_OK); + } + else if (strcmp(argv[1], "set-neighborDistance") == 0) + { + maxNeighborDistance = atof(argv[2]); + return (TCL_OK); + } + else if (strcmp(argv[1], "set-longLocationPacketDistance") == 0) + { + longLocationPacketDistance = atof(argv[2]); + return (TCL_OK); + } + else if (strcmp(argv[1], "set-locationGoodTime") == 0) + { + locationGoodTime = atof(argv[2]); + return (TCL_OK); + } + else if (strcmp(argv[1], "set-bradsDreamFactor") == 0) + { + if(USE_BRADS_DREAM) + { + bradsDreamFactor = atof(argv[2]); + return (TCL_OK); + } + else + { + fprintf(stderr, "set-bradsDreamFactor is only used when\n:"); + fprintf(stderr, "USE_BRADS_DREAM is true.\n"); + return (TCL_ERROR); + } + } + else if (strcmp(argv[1], "set-bradsDreamLongTime") == 0) + { + if(USE_BRADS_DREAM) + { + bradsDreamLongTime = atof(argv[2]); + return (TCL_OK); + } + else + { + fprintf(stderr, "set-bradsDreamLongTime is only used when\n:"); + fprintf(stderr, "USE_BRADS_DREAM is true.\n"); + return (TCL_ERROR); + } + } + else if (strcmp(argv[1], "set-maxPacketTimeout") == 0) + { + maxPacketTimeout = atof(argv[2]); + return (TCL_OK); + } + else if (strcmp(argv[1], "set-maxNodeVelocity") == 0) + { + // This set is only useful if we are using a global max speed for all of + // the nodes. + if(USE_GLOBAL_NODE_SPEED) + { + maxNodeVelocity = atof(argv[2]); + return (TCL_OK); + } + else + { + fprintf(stderr, "You have USE_GLOBAL_NODE_SPEED set to false.\n"); + fprintf(stderr, "USE_GLOBAL_NODE_SPEED needs to be true to use\n"); + fprintf(stderr, "a global speed for every node.\n"); + return(TCL_ERROR); + } + } + else if (strcmp(argv[1], "set-debugLevel") == 0) + { + debugLevel = atoi(argv[2]); + return (TCL_OK); + } + } + else if (argc == 4) + { + if (strcmp(argv[1], "sendData") == 0) + { + // This will send a message to the node with the address specified + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a dream agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + // The first argument to sendData is the address of the node that we + // are going to sent the data to. + int dAddress = atoi(argv[2]); + + // This is the second argument to send data and it is the inter size + // of the data section of the packet. + int dataLength = atoi(argv[3]); + + // Refresh the node's position. + node->update_position(); + + // Create a new packet for the data packet. + Packet* pkt = allocpkt(); + + // Access the headers for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + // Store the current time in the 'send_time' field + dreamhdr->sendTime_ = Scheduler::instance().clock(); + + // Fill in this field with the packet id since it is not and ack + dreamhdr->ackPacketId_ = hdrcmn->uid_; + + // This fills the location info into the header. + dreamhdr->dreamPacketType_ = DREAM_DATA_PACKET; + dreamhdr->sourceX_ = node->X(); + dreamhdr->sourceY_ = node->Y(); + + // This puts in the address the packet is to + dreamhdr->toAddr_ = dAddress; + + // This initializes the hop information in the header + dreamhdr->hops() = 0; + dreamhdr->route_[dreamhdr->hops()] = this->addr(); + dreamhdr->hops()++; + + // Initialize the usedRecovery variable + dreamhdr->usedRecovery_ = false; + + // The location packet has a data part + dreamhdr->dataLength_ = dataLength; + + // Since this is the first data packet it is always the original packet. + dreamhdr->originalPacketId_ = hdrcmn->uid_; + + // This is the first time this packet is being sent + dreamhdr->first_ = true; + + // This sets the debugValue + setDebugValue(4); + + if (printDebug()) + { + cout << "****************************************************" << endl; + cout << "Sending Data from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + } + + // Send the packet. + sendDirectionalPacket(pkt, true); + + if (printDebug()) + { + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "****************************************************" << endl + << endl; + } + + // This something old that was used by the print statistics stuff. + sentDataPackets++; + + return (TCL_OK); + } + } + + // If the command hasn't been processed by DreamAgent()::command, + // call the command() function for the base class + return (Agent::command(argc, argv)); +} + +// *********************************************************************** +// DreamAgent bradsDreamSendLocationPacket() +// *********************************************************************** +void DreamAgent::bradsDreamSendLocationPacket(bool mustBeLong) +{ + node->update_position(); + + Packet* pkt = allocpkt(); + + // Access the Dream header for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + + // Store the current time in the 'send_time' field + dreamhdr->sendTime_ = Scheduler::instance().clock(); + + // Fill in this field with the packet id since it is not and ack + dreamhdr->ackPacketId_ = hdrcmn->uid_; + + // This fills the location info into the header. + dreamhdr->dreamPacketType_ = DREAM_LOCATION_PACKET; + dreamhdr->sourceX_ = node->X(); + dreamhdr->sourceY_ = node->Y(); + dreamhdr->sourceSpeed_ = node->speed(); + + // This initializes the hop information in the header + dreamhdr->hops() = 0; + dreamhdr->route_[dreamhdr->hops()] = this->addr(); + dreamhdr->hops()++; + + // The location packet doesn't have a data part + dreamhdr->dataLength_ = 0; + + //.This means that the packet is being flooded. + dreamhdr->broadcast_ = true; + + // Not using the recovey + dreamhdr->usedRecovery_ = false; + + // Since this is a location packet it is always the original packet. + dreamhdr->originalPacketId_ = hdrcmn->uid_; + + // This is the first time this packet is being sent + dreamhdr->first_ = true; + + // The location packet is broadcast to everybody neighbors do not have + // to be listed. + dreamhdr->numDreamNodes_ = 0; + + // If the location packet must be a long we will take care of it. + if(mustBeLong) + { + longShort = 0; + } + + // This determines if a long or short location packet should be sent, + // this is implemented as describe in the DREAM paper, I would like to + // try something different later. + if(longShort == 0) + { + dreamhdr->maxDistance_ = longLocationPacketDistance; + } + else + { + dreamhdr->maxDistance_ = shortLocationPacketDistance; + } + // Increment for the next location packet. + longShort++; + // Keep the longShort a number in the range + // [0, freqOfLongLocaitonPackets - 1] + longShort %= freqOfLongLocationPackets; + + // This puts the IP_BROADCAST Number in the toAddr of the DREAM header + dreamhdr->toAddr_ = IP_BROADCAST; + + + // Set the debug value for the following debug statements. + setDebugValue(5); + + if (printDebug()) + { + cout << "****************************************************" << endl; + cout << "Sending Location Information from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" + << endl << "Time: " << Scheduler::instance().clock() << endl; + } + + this->broadcastPacket(pkt); + + if (printDebug()) + { + cout << "****************************************************" << endl + << endl; + } + + + if(bradsDreamLocationTimer != NULL) + { + if(mustBeLong) + { + bradsDreamLocationTimer->cancel(); + } + delete bradsDreamLocationTimer; + bradsDreamLocationTimer = NULL; + } + + if(mustBeLong) + { + delete bradsDreamLongLocationTimer; + bradsDreamLongLocationTimer = NULL; + } + + if(bradsDreamLongLocationTimer == NULL) + { + bradsDreamLongLocationTimer = new DreamLocationTimer(this, true); + bradsDreamLongLocationTimer->sched(bradsDreamLongTime); + } + + if(node->speed() != 0) + { + double timeInterval; + timeInterval = maxNeighborDistance/(bradsDreamFactor * node->speed()); + bradsDreamLocationTimer = new DreamLocationTimer(this, false); + bradsDreamLocationTimer->sched(timeInterval); + } + + return; +} +// *********************************************************************** +// DreamAgent sendDirectionalPacket +// *********************************************************************** +// This function will try to send a data packet using the cone described in +// the DREAM paper. +void DreamAgent::sendDirectionalPacket(Packet* pkt, bool initialSend) +{ + double theta; + double r; + double alpha; + locationTableRecord* record; + // Access the Dream header for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + node->update_position(); + + // If it is a data packet or an ack packet not using reverse path acks + // then we need to reset the numDreamNodes because we are going to refill + // the dreamNodes array using the dream method. + if(dreamhdr->dreamPacketType_ != DREAM_ACK_PACKET || !USE_REVERSE_PATH_ACKS) + { + dreamhdr->numDreamNodes_ = 0; + } + + // This is not being sent by flooding. + dreamhdr->broadcast_ = false; + + // look for the destination node in the location table. + LTI locationMapIterator = locationMap.find(dreamhdr->toAddr()); + + // If we are sending a reverse path ack, we want to print soe debug stuff + // and then send the packet right away. + if(USE_REVERSE_PATH_ACKS && dreamhdr->dreamPacketType_ == DREAM_ACK_PACKET) + { + if(printDebug()) + { + cout << "Sending to: " << dreamhdr->toAddr() << endl; + cout << "Reverse Path for Ack: "; + for (int i=0; inumDreamNodes(); i++) + { + cout << dreamhdr->dreamNodes_[i] << " "; + } + cout << endl; + } + if(initialSend) + { + broadcastPacket(pkt); + } + else + { + rebroadcastPacket(pkt); + } + } + // This will be executed for and packets that need to be sent by the + // DREAM method. + // If the node is found look for neighbors to send the packet to + else if (locationMapIterator != locationMap.end()) + { + // This is the speed of the destination node. + double speedOfDestination; + // This is the location record for the destination node. + record = &locationMapIterator->second; + + // If we are using a global max speed set it here else use the speed + // from the location table. + if(USE_GLOBAL_NODE_SPEED) + { + speedOfDestination = maxNodeVelocity; + } + else + { + speedOfDestination = record->speed; + } + + // find the angle of the vector from this node to the destination node. + theta = calculateTheta(node->X(), node->Y(), record->x, record->y); + + r = distance(node->X(), node->Y(), record->x, record->y); + + alpha = calculateAlpha(record->time, Scheduler::instance().clock(), + speedOfDestination, r); + + if(printDebug()) + { + cout << "Sending to: " << dreamhdr->toAddr() + << " at(last known) [" << record->x << "," << record->y << "]" + << endl; +// cout << "DeltaX = " << record->x - node->X() << endl; +// cout << "DeltaY = " << record->y - node->Y() << endl; + cout << "Sent Time = " << record->time << endl; + cout << "Time Now = " << Scheduler::instance().clock() << endl; +// cout << "Velocity = " << speedOfDestination << endl; + cout << "distance = " << r << endl; + cout << "Theta = " << theta * DEG_PER_RAD << endl; + cout << "Alpha = " << alpha * DEG_PER_RAD << endl; + } + + // Look for neighbors that are in the cone. + for(LTI l = locationMap.begin(); l != locationMap.end(); ++l) + { + //if(printDebug()) + // cout << "Checking node " << l->first << " to see if it is a neighbor + // << endl; + if(isNeighbor(l->second.x, l->second.y, theta, alpha) && + dreamhdr->numDreamNodes() < MAX_NUM_DREAM_NODES) + { + dreamhdr->dreamNodes_[dreamhdr->numDreamNodes()] = l->first; + dreamhdr->numDreamNodes_++; + } + } + + // If we have found some neighbors in the cone and the node we are + // sending to location information is still good then we will send it. + if(dreamhdr->numDreamNodes_ > 0 && + (Scheduler::instance().clock() - record->time) < locationGoodTime) + { + if(printDebug()) + { + cout << "One Hop Neighbors in wedge: "; + for (int i=0; inumDreamNodes(); i++) + { + cout << dreamhdr->dreamNodes_[i] << " "; + } + cout << endl; + } + if(initialSend) + { + broadcastPacket(pkt); + // set the packet timeout() to wait for an ack packet + if(dreamhdr->dreamPacketType_ == DREAM_DATA_PACKET) + { + packetTimers[hdrcmn->uid_] = new DreamPacketTimer(this, pkt->copy()); + packetTimers[hdrcmn->uid_]->sched(maxPacketTimeout); + } + } + else + { + rebroadcastPacket(pkt); + } + } + else + { + if(printDebug()) + { + cout << "!!! No one hop neighbors for node: " << dreamhdr->toAddr() + << endl; + if(initialSend) + { + cout << "!!! data packet will be handled by the recovery method." + << endl; + } + } + if(initialSend) + { + recovery(pkt, initialSend, false); + } + } + } + else + { + if(printDebug()) + { + cout << "!!! Node with address: " << dreamhdr->toAddr() + << " is not in my location table" << endl; + if(initialSend && dreamhdr->dreamPacketType_ != DREAM_ACK_PACKET) + { + cout << "!!! data packet will be handled by the recovery method." + << endl; + } + } + if(initialSend && dreamhdr->dreamPacketType_ != DREAM_ACK_PACKET) + { + recovery(pkt, initialSend, false); + } + } + return; +} + + +// *********************************************************************** +// DreamAgent calculateAlpha +// *********************************************************************** +double DreamAgent::calculateAlpha(double t0, double t1, double v, double r) +{ + double alpha = 0; + double minAlphaRad = MIN_ALPHA_DEG * RAD_PER_DEG; + double argument; + // This is how the DREAM paper implements the Alpha calculation + if (r != 0) + { + argument = (v*(t1-t0))/r; + if (argument > 1) + { + alpha = PI; + } + else + { + alpha = asin(argument); + } + if(alpha < minAlphaRad) + { + alpha = minAlphaRad; + } + } + return alpha; +} + +// *********************************************************************** +// DreamAgent calculateTheta +// *********************************************************************** +double DreamAgent::calculateTheta(double x0, double y0, double x1, double y1) +{ + double theta; + double deltaY = y1 - y0; + double deltaX = x1 - x0; + + if(deltaX == 0) + { + theta = PI_OVER_TWO; + if(deltaY < 0) + { + theta *= -1; + } + } + else + { + theta = atan(deltaY/deltaX); + } + + if(theta < 0) + { + theta = TWO_PI + theta; + } + if(theta < PI_OVER_TWO && (deltaX < 0 || deltaY < 0)) + { + theta += PI; + } + else if ((theta > PI_OVER_TWO) && (deltaX < 0)) + { + theta -= PI; + } + + return theta; +} + +// *********************************************************************** +// DreamAgent distance +// *********************************************************************** +double DreamAgent::distance(double x0, double y0, double x1, double y1) +{ + return sqrt((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)); +} + +// *********************************************************************** +// DreamAgent isNeighbor +// *********************************************************************** +bool DreamAgent::isNeighbor(double x, double y, double theta, double alpha) +{ + double dTheta; + node->update_position(); + double testTheta = calculateTheta(node->X(), node->Y(), x, y); + double r = distance(node->X(), node->Y(), x, y); + + if(r <= maxNeighborDistance) + { + if (testTheta > theta) + { + dTheta = testTheta - theta; + } + else + { + dTheta = theta - testTheta; + } + + if(dTheta > PI) + { + dTheta = TWO_PI - dTheta; + } + //if(printDebug()) { + // cout << " Theta of potential neighbor = " << testTheta << endl; + // cout << " dTheta = " << dTheta << endl; + //} + + if(alpha >= dTheta) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +} + + +// *********************************************************************** +// DreamAgent recv +// *********************************************************************** +void DreamAgent::recv(Packet* pkt, Handler*) +{ + // Set the debugValue + setDebugValue(6); + + // Access the common header for the received packet: + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + // Access the IP header for the received packet: + struct hdr_ip* hdrip = hdr_ip::access(pkt); + + // Access the dream header for the received packet: + struct hdr_dream* hdr = hdr_dream::access(pkt); + + node->update_position(); + + double packetTravelDistance = distance((double)hdr->sourceX(), + (double)hdr->sourceY(), (double)node->X(), (double)node->Y()); + + // Is it a duplicate packet use if not counting received packets + // This should catch all packets except nonfloodeded data. + if ((this->dupRcvdPacket(hdrcmn->uid_) + || this->dupSentPacket(hdrcmn->uid_)) && + !(!hdr->broadcast() && hdr->toAddr() == this->addr())) + { + if (printDebug()) + { + printPacketHeader(pkt); + cout << "Duplicate packet seen from " << hdrcmn->prev_hop_ + << ", freeing it." << endl; + cout << "Returning from recv early" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "****************************************************" << endl + << endl; + } + Packet::free(pkt); + return; + } + else + { + recordRcvdPacket(hdrcmn->uid_); + } + + // Since this packet was received it is not the first time it was sent. + hdr->first_ = false; + + // This is set to true when we need to free the packet pkt + bool freePacket = false; + + // What kind of packet is it? + if (hdr->dreamPacketType() == DREAM_LOCATION_PACKET) + { + // set the debugValue + setDebugValue(5); + + printPacketHeader(pkt); + processLocationPacket(hdr, hdrip); + + if (printDebug()) + { + printLocationTable(); + cout << "packetTravelDistance = " << packetTravelDistance << endl; + cout << "maxDistance = " << hdr->maxDistance() << endl; + } + + // only forward it if it has not already traveled the max distance + if (hdr->maxDistance() < 0 || packetTravelDistance < hdr->maxDistance()) + { + if (printDebug()) + { + cout << "Rebroadcasting Packet" << endl; + } + + hdr->broadcast_ = true; + hdr->route_[hdr->hops()] = this->addr(); + hdr->hops()++; + this->rebroadcastPacket(pkt); + } + else + { + Packet::free(pkt); + } + if (printDebug()) + cout << "****************************************************" << endl + << endl; + } + else if (hdr->dreamPacketType() == DREAM_DATA_PACKET || + hdr->dreamPacketType() == DREAM_ACK_PACKET) + { + // Set the debugValue + setDebugValue(4); + + printPacketHeader(pkt); + if(printDebug()) + { + cout << "packetTravelDistance = " << packetTravelDistance << endl; + } + // Check to see if the packet is for me + if (hdr->toAddr() == this->addr()) + { + // We want to free the packet at the end of this + freePacket = true; + + if(hdr->dreamPacketType() == DREAM_DATA_PACKET) + { + receivedDataPackets++; + } + + if (printDebug()) + { + cout << "I received "; + if (hdr->dreamPacketType() == DREAM_DATA_PACKET) + { + cout << "a data"; + } + else + { + cout << "an ack"; + } + cout << " packet for me at node " << this->addr() << endl; + } + if (hdr->dreamPacketType() == DREAM_DATA_PACKET && !hdr->broadcast()) + { + if (printDebug()) + { + cout << "Sending ack packet." << endl; + } + + // send an ack packet for the data packet received + sendAck(pkt); + } + else if(hdr->dreamPacketType() == DREAM_ACK_PACKET) + { + if (printDebug()) + { + cout << "Canceling the timer for packet " << hdr->ackPacketId() + << "." << endl; + cout << "known timers:"; + for(PTI p = packetTimers.begin(); p != packetTimers.end(); ++p) + { + cout << " " << (int)p->first; + } + cout << endl; + cout << "Looking for timer: " << hdr->ackPacketId() << endl; + + } + // try to kill the packet timer since we received an ack + PTI found = packetTimers.find(hdr->ackPacketId()); + if(found != packetTimers.end()) + { + if(found->second != NULL) + { + found->second->dcancel(); + delete found->second; + found->second = NULL; + } + } + + } + } + else if(hdr->broadcast()) + { + recovery(pkt, false, false); + } + else if(isInAddrList(this->addr(), hdr->dreamNodes_, + hdr->numDreamNodes())) + { + if (printDebug()) + { + cout << "I received a "; + if (hdr->dreamPacketType() == DREAM_DATA_PACKET) + { + cout << "data"; + } + else + { + cout << "act"; + } + cout << " packet with my address in the list of Neighbors." << endl; + } + + hdr->route_[hdr->hops()] = this->addr(); + hdr->hops()++; + + if (printDebug()) + { + cout << "Rebroadcasting packet from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + } + sendDirectionalPacket(pkt, false); + if (printDebug()) + { + cout << "Time: " << Scheduler::instance().clock() << endl; + } + } + else + { + Packet::free(pkt); + } + + if (printDebug()) + { + cout << "****************************************************" << endl + << endl; + } + } + else + { + cerr << "Received Unknown Packet Type: " << hdr->dreamPacketType() + << endl; + } + + if(freePacket) + { + freePacket = true; + } + + return; +} + +// *********************************************************************** +// DreamAgent sendAck +// *********************************************************************** +void DreamAgent::sendAck(Packet *p) +{ + node->update_position(); + + // Create a new packet + Packet* pkt = allocpkt(); + + // Access the Dream header for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(pkt); + + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + + // Store the current time in the 'send_time' field + dreamhdr->sendTime_ = Scheduler::instance().clock(); + + // Access the Dream header for the new packet: + struct hdr_dream* olddreamhdr = hdr_dream::access(p); + + struct hdr_cmn* oldhdrcmn = hdr_cmn::access(p); + + // Access the IP header for the new packet: + struct hdr_ip* oldiphdr = hdr_ip::access(p); + + + // This fills the location info into the header. + dreamhdr->dreamPacketType_ = DREAM_ACK_PACKET; + dreamhdr->sourceX_ = node->X(); + dreamhdr->sourceY_ = node->Y(); + + // This puts in the address the packet is to + dreamhdr->toAddr_ = oldiphdr->saddr(); + + dreamhdr->ackPacketId_ = oldhdrcmn->uid_; + + // This initializes the hop information in the header + dreamhdr->hops() = 0; + dreamhdr->route_[dreamhdr->hops()] = this->addr(); + dreamhdr->hops()++; + + // Initialize the usedRecovery variable + dreamhdr->usedRecovery_ = false; + + // The location packet has a data part + dreamhdr->dataLength_ = 0; + + // Since this is a ack packet it is always the original packet. + dreamhdr->originalPacketId_ = hdrcmn->uid_; + + // This is the first time this packet is being sent + dreamhdr->first_ = true; + + // If use revers path is turned on then put the reverse path + // as the nodes that will rebroadcast this packet. + if(USE_REVERSE_PATH_ACKS) + { + dreamhdr->numDreamNodes_ = olddreamhdr->hops(); + for (int i=0; inumDreamNodes(); i++) + { + dreamhdr->dreamNodes_[i] = olddreamhdr->route_[i]; + } + } + + if (printDebug()) + { + cout << "####################################################" << endl; + cout << "Sending Ack from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "For the packet: " << dreamhdr->ackPacketId() << endl; + } + + sendDirectionalPacket(pkt, true); + + if (printDebug()) + { + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "####################################################" << endl + << endl; + } + +} + +// *********************************************************************** +// DreamAgent isInAddrList +// *********************************************************************** +// returns true if the searchForAddr is in the list addrList with numberInList +// members +bool DreamAgent::isInAddrList(int searchForAddr, int* addrList, + int numberInList) +{ + bool isInList = false; + for(int i = 0; i < numberInList && !isInList; i++) + { + if(searchForAddr == addrList[i]) + { + isInList = true; + } + } + return isInList; +} + +// *********************************************************************** +// DreamAgent recovery +// *********************************************************************** +void DreamAgent::recovery(Packet *p, bool initialSend, bool timedOut) +{ + // this is the recovery methed here implemented as flooding + if(USE_RECOVERY) + { + // Access the dream header for the old packet: + struct hdr_dream* hdrdream_old = hdr_dream::access(p); + + hdrdream_old->usedRecovery_ = true; + hdrdream_old->broadcast_ = true; + hdrdream_old->numDreamNodes_ = 0; + + if(initialSend) + { + // We need to make a new paket for the recovery packet associated with + // the hdr_old packet + + node->update_position(); + + // Create the recovery packet + Packet* recoveryPacket = allocpkt(); + + // Get the packet headers for the recovery packet + struct hdr_dream* hdrdream = hdr_dream::access(recoveryPacket); + struct hdr_cmn* hdrcmn = hdr_cmn::access(recoveryPacket); + + // Now we are going to start copying the packet header information + // from the old packet to the recovery packet. + + // Store the current time in the 'send_time' field + hdrdream->sendTime_ = hdrdream_old->sendTime(); + + // This is the packet type + hdrdream->dreamPacketType_ = hdrdream_old->dreamPacketType(); + + // This fills the location info into the header. + hdrdream->sourceX_ = node->X(); + hdrdream->sourceY_ = node->Y(); + + // This puts in the address the packet is to + hdrdream->toAddr_ = hdrdream_old->toAddr(); + + // This initializes the hop information in the header + hdrdream->hops() = 0; + hdrdream->route_[hdrdream->hops()] = this->addr(); + hdrdream->hops()++; + + // Initialize the recovery variable + hdrdream->usedRecovery_ = hdrdream_old->usedRecovery(); + + // set bradcast + hdrdream->broadcast_ = hdrdream_old->broadcast(); + + // set number of neighbors + hdrdream->numDreamNodes_ = hdrdream_old->numDreamNodes(); + + // The location packet has a data part + hdrdream->dataLength_ = hdrdream_old->dataLength(); + + if(timedOut) + { + hdrdream->originalPacketId_ = hdrdream_old->originalPacketId(); + hdrdream->first_ = false; + } + else + { + hdrdream->first_ = true; + hdrdream->originalPacketId_ = hdrcmn->uid_; + } + + // Send the recovery packet on its merry way. + broadcastPacket(recoveryPacket); + Packet::free(p); + + if(printDebug()) + { + cout << "Recovery now flooding the packet." << endl; + } + } + else + { + hdrdream_old->route_[hdrdream_old->hops()] = this->addr(); + hdrdream_old->hops()++; + rebroadcastPacket(p); + } + } +} + +// *********************************************************************** +// DreamAgent broadcastPacket +// *********************************************************************** +void DreamAgent::broadcastPacket(Packet *p) +{ + // Access the common header for the new packet: + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + + // Access the IP header for the new packet: + struct hdr_ip* iphdr = hdr_ip::access(p); + + // Access the dream header for the new packet: + struct hdr_dream* hdr = hdr_dream::access(p); + + // set all the necessary things for the common header + cmnhdr->next_hop_ = IP_BROADCAST; // broadcast + cmnhdr->prev_hop_ = this->addr(); + cmnhdr->direction() = hdr_cmn::DOWN; // hopefully send it out + + // now the ip header stuff + iphdr->saddr() = this->addr(); + iphdr->sport() = DREAM_PORT; + iphdr->daddr() = IP_BROADCAST; + iphdr->dport() = DREAM_PORT; + iphdr->ttl() = 32; + + + // Send the packet + recordSentPacket(cmnhdr->uid_); + + // this one is different and was taken from dsragent::sendOutBCastPkt + // I had to add a little jitter because it turned out that neighboring nodes + // where re-broadcasting in the simulator at "exactly" the same time and + // killing each other's transmissions. + double jitter = ((double)rand()/(double)RAND_MAX) / DREAM_JITTER; + cmnhdr->size_ = hdr->size(); + if(printDebug()) + { + cout << "Scheduling the packet for delivery: " << cmnhdr->uid_ + << " with jitter=" << jitter << endl; + cout << "Really sending at: " << Scheduler::instance().clock() + jitter + << endl; + cout << "Common header size: " << cmnhdr->size_ << endl; + } + Scheduler::instance().schedule(ll, p, jitter); + + if (!ll) + { + cerr << "Crap, the link layer is NULL!!!!!" << endl; + } + return; +} + +// *********************************************************************** +// DreamAgent rebroadcastPacket +// *********************************************************************** +// same as broadcastPacket, but +// - we don't change the ip header source address, +// - we have to set previous hop, +// - we need to decrement the ttl +// - and we have to set the direction to down + +void DreamAgent::rebroadcastPacket(Packet *p) +{ + // Access the common header for the new packet: + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + + // Access the IP header for the new packet: + struct hdr_ip* iphdr = hdr_ip::access(p); + + // Access the dream header for the new packet: + struct hdr_dream* dreamhdr = hdr_dream::access(p); + + // set all the necessary things for the common header + cmnhdr->next_hop_ = IP_BROADCAST; // broadcast + cmnhdr->prev_hop_ = this->addr(); + cmnhdr->direction() = hdr_cmn::DOWN; // hopefully send it out + + // now the ip header stuff + // don't reset this on a rebroadcast + //iphdr->saddr() = this->addr(); + + // this doesn't have to be done, (it should be ok from the original) + // but just in case... + iphdr->sport() = DREAM_PORT; + iphdr->daddr() = IP_BROADCAST; + iphdr->dport() = DREAM_PORT; + + // this is a difference from the regular broadcast + // it appears that this needs to be done + // since this packet doesn't go through the routing agent, this is never + // done anywhere but here + //cout << "ttl before decrement: " << iphdr->ttl_ << endl; + iphdr->ttl()--; + + // Send the packet + recordSentPacket(cmnhdr->uid_); + + // this one is different and was taken from dsragent::sendOutBCastPkt + // I had to add a little jitter because it turned out that neighboring nodes + // where re-broadcasting in the simulator at "exactly" the same time and + // killing each other's transmissions. + double jitter = ((double)rand()/(double)RAND_MAX) / DREAM_JITTER; + cmnhdr->size_ = dreamhdr->size(); + + if(printDebug()) + { + cout << "Scheduling the packet for delivery: " << cmnhdr->uid_ + << " with jitter=" << jitter << endl; + cout << "Really sending at: " << Scheduler::instance().clock() + jitter + << endl; + cout << "Common header size: " << cmnhdr->size_ << endl; + } + + Scheduler::instance().schedule(ll, p, jitter); + + if (!ll) + { + cerr << "Crap, the link layer is NULL!!!!!" << endl; + } + + //cout << "Dream: Done rebroadcasting." << endl; + + return; +} + +// *********************************************************************** +// DreamAgent printPacketHeader +// *********************************************************************** +void DreamAgent::printPacketHeader(Packet *p) +{ + if (printDebug()) + { + // Access the common header for the new packet: + struct hdr_cmn* hdrcmn = hdr_cmn::access(p); + + // Access the dream header for the new packet: + struct hdr_dream* hdr = hdr_dream::access(p); + + node->update_position(); + + cout << "****************************************************" << endl; + cout << "In Dream recv at node: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "Sent Time: " << hdr->sendTime() << endl; + cout << "Route thus far: "; + for (int i=0; ihops(); i++) + { + cout << hdr->route_[i] << " "; + } + cout << endl; + cout << "Packet ID: " << hdrcmn->uid_ << endl + << "Dream Type: " << hdr->dreamPacketType() << endl; + } +} + +// *********************************************************************** +// DreamAgent dupRcvdPacket +// *********************************************************************** +bool DreamAgent::dupRcvdPacket(int id) +{ + // I may need to limit the size of this in the future. + if (rcvdPackets.find(id) != rcvdPackets.end()) + { + return true; + } + else + { + return false; + } +} + +// *********************************************************************** +// DreamAgent dupSentPacket +// *********************************************************************** +bool DreamAgent::dupSentPacket(int id) +{ + if (sentPackets.find(id) != sentPackets.end()) + { + return true; + } + else + { + return false; + } +} + +// *********************************************************************** +// DreamAgent recordSentPacket +// *********************************************************************** +void DreamAgent::recordSentPacket(int id) +{ + sentPackets.insert(id); + return; +} + +// *********************************************************************** +// DreamAgent recordRcvdPacket +// *********************************************************************** +void DreamAgent::recordRcvdPacket(int id) +{ + rcvdPackets.insert(id); + return; +} + +// *********************************************************************** +// DreamAgent processLocationPacket +// *********************************************************************** +// handel the location packets by adding the information to the location table. +bool DreamAgent::processLocationPacket(hdr_dream* hdr, hdr_ip* hdrip) +{ + locationTableRecord* record; + + record = new locationTableRecord(); + + if (hdr->dreamPacketType() != DREAM_LOCATION_PACKET) + { + cerr << "DreamLocationTable::~processPacket: Received non location packet" + << endl; + return false; + } + + //record->addr = (nsaddr_t) hdrip->saddr(); + record->time = hdr->sendTime(); + record->x = hdr->sourceX(); + record->y = hdr->sourceY(), + record->speed = hdr->sourceSpeed(), + + locationMap[hdrip->saddr()] = (*record); + + return true; +} + +// *********************************************************************** +// DreamAgent printLocationTable +// *********************************************************************** +void DreamAgent::printLocationTable() +{ + cout << " ##########Location Table##########" << endl; + cout << " Address Time X Y Speed" << endl; + for(LTI l = locationMap.begin(); l != locationMap.end(); ++l) + { + cout << " " << (int)l->first << " " + << (double)l->second.time << " " + << (double)l->second.x << " " + << (double)l->second.y << " " + << (double)l->second.speed << endl; + } + cout << " ##################################" << endl; + + return; +} + +// *********************************************************************** +// DreamAgent printStatistics +// *********************************************************************** +void DreamAgent::printStatistics() +{ + cout << this->addr() << "\t" << sentDataPackets << "\t" + << receivedDataPackets << endl; + return; +} diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/dream.h ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.h --- ns-allinone-2.32/ns-2.32/dream/dream.h 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.h 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,528 @@ +/****************************************************************************** +* File Name: dream.h +* Purpose: +* This is the header file for the DREAM routing protocal. I have copied +* as much as I can from the geocast.h file to not reinvent the wheel. +* Original Author: Lucas Wilcox +* Modified by: +* Date Created: 09/30/2000 +* +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details. +*******************************************************************************/ + +#ifndef ns_dream_h +#define ns_dream_h + +#include "object.h" +#include "agent.h" +#include "tclcl.h" +#include "packet.h" +#include "address.h" +#include "ip.h" +#include "mac.h" +#include "mobilenode.h" +#include "rng.h" +#include +#include + +using namespace std; +// This is an importian section because you can set up the switches to that +// the protocal works like it did in the paper. +// +// There were not reverse path acks in the paper. +// #define USE_REVERSE_PATH_ACKS false +#define USE_REVERSE_PATH_ACKS false + +// In the paper they used the recovery method. +// #define USE_RECOVERY true +#define USE_RECOVERY true + +// In the paper they used a global speed that you have to set at each node +// in the TCL script if USE_GLOBAL_NODE_SPEED is set to true. Otherwise we will +// use the speed sent in the location packets. +#define USE_GLOBAL_NODE_SPEED false + +// USE_STAGGER_LONG_LOCATION if set to true will stagger the long location +// packets so that the node will not always send a long location packet first. +// If set to fase it will ack like the way we had it in our paper. +#define USE_STAGGER_LONG_LOCATION true + +// This is set to true when we want to use Brad's Dream. This means that +// if the next #define is set to true then the interval for which location +// updates are sent is based on speed. note: when USE_BRADS_DREAM is +// set to true all we need to do in the tcl script is to run the +// member function startLocationService once and everything else +// will will happen. +#define USE_BRADS_DREAM true + +// This section now has the default values and other constants. + +// This is for pi and two pi and other usefull constants. +const double PI = 2.0*asin(1.0); +const double TWO_PI = 2.0 * PI; +const double PI_OVER_TWO = PI/2.0; +const double DEG_PER_RAD = 180.0/PI; +const double RAD_PER_DEG = PI/180.0; + +// This means that the jitter ranges from 0.0 to 0.0001 with +// a mean of 0.00005, so the average number of bits that could +// transmitted without jitter is 50 per transmission. This seems +// acceptable. +// Note: this is just the divisor in the random number range calculation. +#define DREAM_JITTER 10000.0 + +// This is the Location packet fixed size +// Bytes Field +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// 4 packetId +// 4 sourceX +// 4 sourceY +// 4 sourceSpeed +// 4 sourceAddress +// 4 timeSent +// 4 maxTravelDistance +// 1 dreamType +// +// Total: 29 bytes +#define DREAM_LOCATION_HDR_SIZE_FIXED 29 + +// This is the Data packet fixed size +// Bytes Field +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// 4 packetId +// 4 sourceAddress +// 4 toAddress +// 1 dreamType +// 1 numDreamNodes +// 2 dataPayloadLength +// +// Total: 16 bytes +#define DREAM_DATA_HDR_SIZE_FIXED 16 + +// This is the Ack packet fixed size +// Bytes Field +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// 4 packetId +// 4 sourceAddress +// 4 toAddress +// 4 ackPacketId +// 1 dreamType +// 1 numDreamNodes +// +// Total: 18 bytes +#define DREAM_ACK_HDR_SIZE_FIXED 18 + +// This is the port number that dream packets get sent to. +#define DREAM_PORT 253 + +// These are the packet types. +#define DREAM_LOCATION_PACKET 0 +#define DREAM_DATA_PACKET 1 +#define DREAM_ACK_PACKET 2 // These are acknowledgement packets. + +// This is the transmission distance +#define DREAM_TRANS_DIST 40 + +// This is the number of neighbors allowed on a packet. +#define MAX_NUM_DREAM_NODES 32 + +// This is the default max node velocity in grid units per second +#define MAX_NODE_VELOCITY 6 + +// This is the default number of seconds that will pass to let an ack +// come back for a data packet +#define MAX_PACKET_TIMEOUT 1 + +// This is the minimum dregrees for alpha +#define MIN_ALPHA_DEG 15 + +struct hdr_dream +{ + // look at #define's for packet types + int dreamPacketType_; + + // Fields needed by location packets + double sendTime_; // This is the time the packet is sent. + // NodeID: I will use the saddr() for the Node ID + double sourceX_; // This is the sender's X coordinate location @ sendTime_ + double sourceY_; // This is the sender's Y coordinate location @ sendTime_ + double sourceSpeed_; // This is the sender's speed @ sendTime_ + double maxDistance_; // This is the maximum distance that the Loction + // Packet will travel. + + // fields to keep track of the hops for fun. + nsaddr_t route_[32]; // currently nsaddr_t is a 32 bit int defined in + // config.h + + // This is the number of hops that the packet has taken. + int hops_; + + // This is the number of neighbors that the packet will be sent to determined + // by the DREAM method for a data packet and a traditional ack packet. For + // a reverse path ack packet this is the number of nodes in the reverse + // path. + int numDreamNodes_; + + // This is the list of neighbors that should receive and rebroadcast the + // data packet sent by the dream method. This is also used by the ack + // packets as the neighbors that will receive and transmit the DREAM + // ack packets. Right now the ack packets can use reverse path or + // the DREAM method. If acks are set to reverse path acks then this + // is the nodes in the reverse path. + int dreamNodes_[MAX_NUM_DREAM_NODES]; + + // This is the address that is the final destination of the DREAM data and + // ack packets. + int toAddr_; + + // This is set to true if the packet was sent by flooding. + bool broadcast_; + + // This is true if the data packet is using the recovery method. + bool usedRecovery_; + + // This is the packet id of the data packet that the ack packet is replying + // to. + int ackPacketId_; + + // Fields needed by data packets + int dataLength_; // length of the data in the packet in bytes + // does not include the header length + + // This is the ID of the original packet id. For location and + // ack packets this will always be the ID of the current packet. + // For data packets this will be the ID of the data packcket if it + // is sent by the dream method. If the packet is sent by the recovery + // method then this is the id of of the current packet if there was not + // an original packeck then this is set to the current packet id. + int originalPacketId_; + + // This is set to true if it is the first time the packet is being set + // ie the packet has not been rebroadcasted yet. + bool first_; + + // things I get for "free" from hdr_ip in packet.h + // int saddr(); // IP addr of source sender + // int sport(); // port number of the source sender + // int daddr(); // IP addr of the destination + // int dport(); // port of the destination + + // things I get for "free" from hdr_cmn in packet.h + // double ts_; // timestamp + // int size_; // simulated packet size + // int uid_; // unique packet id + // nsaddr_t prev_hop_; // IP addr of forwarding hop + // int num_forwards_; // number of forwards + + // Now I need to provide access functions for my structure members + inline int &dreamPacketType() { return dreamPacketType_; } + inline double &sendTime() { return sendTime_; } + inline double &sourceX() { return sourceX_; } + inline double &sourceY() { return sourceY_; } + inline double &sourceSpeed() { return sourceSpeed_; } + inline double &maxDistance() { return maxDistance_; } + inline int &hops() { return hops_; } + inline int &numDreamNodes() { return numDreamNodes_; } + inline int &dataLength() { return dataLength_; } + inline int &toAddr() { return toAddr_; } + inline bool &broadcast() { return broadcast_; } + inline bool &usedRecovery() { return usedRecovery_; } + inline int &ackPacketId() { return ackPacketId_; } + inline int &originalPacketId() { return originalPacketId_; } + inline bool &first() { return first_; } + inline int size() + { + int packetSize = 0; + + if(dreamPacketType() == DREAM_DATA_PACKET) + { + packetSize += DREAM_DATA_HDR_SIZE_FIXED + + 4 * numDreamNodes_ + dataLength_; + } + else if(dreamPacketType() == DREAM_ACK_PACKET) + { + packetSize += DREAM_ACK_HDR_SIZE_FIXED + + 4 * numDreamNodes_; + } + else if(dreamPacketType() == DREAM_LOCATION_PACKET) + { + packetSize += DREAM_LOCATION_HDR_SIZE_FIXED; + } + + // This adds the length for the route if we are using reverse path acks. + if(USE_REVERSE_PATH_ACKS && dreamPacketType() == DREAM_DATA_PACKET) + { + packetSize += 4 * hops_; + } + + return packetSize; + } + + // This is somthing I think is needed to access the header in the new ns. + // Check the NS manual for a discussion on the following lines. Look at + // the section about add a new packet header type. + static int offset_; // required by PacketHeaderManager + inline static int& offset() + { + return offset_; + } + inline static hdr_dream* access(const Packet* p) + { + return (hdr_dream*) p->access(offset_); + } +}; + +//int hdr_dream::offset_; + + +class DreamAgent; + +// This is a timer that is used to send a recovery packet when the +// timer goes off. +class DreamPacketTimer : public TimerHandler +{ + public: + // This is the constructor. a is the DREAM agent that sets the timer. + // p is the data packet that a recovery packet will be sent for + // when the timer expires. + DreamPacketTimer(DreamAgent* a, Packet* p) + : TimerHandler(), a_(a), p_(p), wasCanceled_(false) + { + } + + // Call this function to cancel the timer. + void dcancel(); +protected: + // This is the function that will be called by ns when the timer expires. + virtual void expire(Event *e); + // This is the DREAM agent that created the packet timer. + DreamAgent *a_; + // This is the data packet that will have a recovery packet sent for it if + // the timer is not canceled. + Packet *p_; + // This is set to true if the packet timer is canceled. Since there are + // unknown number of times that this packet timer wil be called we + // don't really want to cancel the timer more then once. I think + // there might be a better way of doing this that would free up the memory + // that the packet timer takes up. Hopefully this will be implemented some + // day. + bool wasCanceled_; +}; + +// This is a timer used to implement Brad's Dream location updates +class DreamLocationTimer : public TimerHandler +{ + public: + // This is the constructor. a is the DREAM agent that sets the timer. + DreamLocationTimer(DreamAgent* a, bool sl) + : TimerHandler(), agent(a), sendLong(sl) + { + } +protected: + // This is the function that will be called by ns when the timer expires. + virtual void expire(Event *e); + // This is the DREAM agent that created the location timer. + DreamAgent *agent; + + // This is used to tell if this timer should send a long + bool sendLong; +}; + + +// Agent inheritance is because this is a specialized Agent +class DreamAgent : public Agent +{ + friend class DreamPacketTimer; + public: + DreamAgent(); + ~DreamAgent(); + // This is the function that will be called when a command is passed to + // the DREAM agent in the TCL script. + int command(int argc, const char*const* argv); + + // This is the function that will be called when the DREAM agent receives + // a packet. + void recv(Packet*, Handler*); + // Prints the packet header. + void printPacketHeader(Packet *p); + // Returns true if a debug message needs to be printed + bool printDebug(); + // This sets the debugValue + void setDebugValue(int dbv); + + // This is the method that takes care of the location packets brad's + // style. + void bradsDreamSendLocationPacket(bool mustBeLong); + + protected: + //int off_dream_; + // This returns true if the packet has been received before. + bool dupRcvdPacket(int id); + // This returns true if the packet was sent by this node. + bool dupSentPacket(int id); + // This records that a packet was received by this node. + void recordSentPacket(int id); + // This records that a packet was sent by this node. + void recordRcvdPacket(int id); + // This is used to send a packet using the DREAM directional method. + // initialSend is set to true if the packet + // is being sent for the first time. + void sendDirectionalPacket(Packet* pkt, bool initialSend); + + // This is a function Jeff worte that sends the packet for the first time. + void broadcastPacket(Packet* p); + // This is a function Jeff wrote that sends the packet after the first + // time. + void rebroadcastPacket(Packet* p); + // This is a method that will send a data packet by the recovery method + // here implemented by flooding. p is the data packet that will be sent + // by the recovery method. initialSend is set to true + // if this is the first time the packet is being sent. The value of + // timedOut is set to true if the recovery method was called by a + // DreamPacketTimer, this is used to put data in the trace files for + // Brad. + void recovery(Packet* p, bool initialSend, bool timedOut); + + private: + // A long location packet will go out for every freqOfLongControlPackets + // number of short packets + int freqOfLongLocationPackets; + + // The distance that a short lived location packet will travel before nodes + // stop forwarding it. + double shortLocationPacketDistance; + + // The distance that a long lived location packet will travel before nodes + // stop forwarding it. + double longLocationPacketDistance; + + // This is the int that determines if a long or short location packet will + // be set. longShort will always be between 0 and + // freqOfLongLocationPackets -1 and will be increased when a location packet + // is set. If the increas will make longShort == freqOfLongLocationPackets + // then we set longShort to 0. If longShort is equal to 0 then we will + // send a long location packet. + int longShort; + + // This is a set of packets this agent sent + set > sentPackets; + + // This is a set of packets this agent received + set > rcvdPackets; + + // This is a set of packets this agent sent that were broadcasted + int sentDataPackets; + int receivedDataPackets; + + // link layer output in order to avoid using a routing agent + NsObject *ll; + + // the node that this agent is attached to + MobileNode *node; + + // Debug Level 0(no output) to 10(all output) + int debugLevel; + + // This is used to compare againt the debugLevel in printDebug() to + // see if the debugValue < debugLevel and if so then printDebug() + // returns true. So set debugValue when you want to change the value + // for the next debug statements. + int debugValue; + + // This is the max distance a node is considered a neighbor. + double maxNeighborDistance; + + // This th function that calculates the angle that the line from (x0,y0) to + // (x1,y1) makes with the x axis. + double calculateTheta(double x0, double y0, double x1, double y1); + + // This caculates the euclidean distance between (x0,y0) and (x1,y1) + double distance(double x0, double y0, double x1, double y1); + + // This cacultes the angle alpha as described in the DREAM paper that + // is one half the angle if the cone. + double calculateAlpha(double t0, double t1, double v, double r); + + // This takes in the current location of the possible neighbor (x,y) and + // uses theta as caculated by caculateTheta with the sending and destination + // nodes' locations as the argument. alpha is the angle isNeighbor will use + // as half the cone's angle. + // isNeighbor returns true if the node at (x,y) is a one hop neighbor in + // the cone of the sending node as described in the paper. + bool isNeighbor(double x, double y, double theta, double alpha); + + // This method returns true if the number searchForAddr is in + // the array addrList which has numberInList entries. + bool isInAddrList(int searchForAddr, int* addrList, int numberInList); + + // This method will send an ack packet for the data packet p received by + // node. + void sendAck(Packet* p); + + // This is an old function that was to initially test DREAM but has + // since been replaced by awk scripts written by Brad to parse the + // trace output. + void printStatistics(); + + // This max velocity of all the nodes; + double maxNodeVelocity; + + // this is the time to wait for an act before reducing to the recovery + // method + double maxPacketTimeout; + + // This it the amount of seconds location information is concidered good. + double locationGoodTime; + + typedef struct + { + //nsaddr_t addr; // This address of the node the locationTableRecord + // belongs. + double time; // The time the record was sent by the sender of the + // Location Packet + double x; // The x coordinate of the node + double y; // The y coordinate if the node + double speed; // The speed of the node when it sent the location + // information. + } locationTableRecord; + + // This is the location table map. It will hold the location table + // records for each node it knows about. the key to the map is the + // address of the node. + map > locationMap; + + // This is just a typedef so that it is easy to get an iterator + // for the above map. + typedef map >::iterator LTI; + + // This will take the location information from the headers passed in + // and add/update the location table entry for the node who sent the + // packet with the headers passed in. + bool processLocationPacket(hdr_dream* hdr, hdr_ip* hdrip); + + // This outputs to the screen the location table for the given node. + void printLocationTable(); + + // These are for the timeout of sending directional packets. + map > packetTimers; + + // This is just a typedef for the above map so that it is easier to use. + typedef map >::iterator PTI; + + + // This is the factor in brad's DREAM which is used to calculate when + // location packets are sent + double bradsDreamFactor; + + // This is timeout time for long location packets in Brad's Dream. + double bradsDreamLongTime; + + // This is the location packet timer + DreamLocationTimer* bradsDreamLocationTimer; + DreamLocationTimer* bradsDreamLongLocationTimer; +}; + +#endif diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/dream.tcl ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.tcl --- ns-allinone-2.32/ns-2.32/dream/dream.tcl 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream.tcl 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,330 @@ +#*****************************************************************************# +# File Name: dream.tcl # +# Purpose: DREAM protocol for ns2 - tcl script # +# Original Author: Jeff Boleng # +# Modified by: # +# Date Created: some time in 2002 # +# +# Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines # +# +# Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license # +# details. +#******************************************************************************# + +# This is a new style +# ====================================================================== +# Define options +# ====================================================================== + +set opt(chan) Channel/WirelessChannel +set opt(prop) Propagation/TwoRayGround +set opt(netif) Phy/WirelessPhy +set opt(mac) Mac/802_11 +set opt(ifq) Queue/DropTail/PriQueue +set opt(ll) LL +set opt(ant) Antenna/OmniAntenna +set opt(x) 300 ;# X dimension of the topography +set opt(y) 600 ;# Y dimension of the topography +set opt(ifqlen) 50 ;# max packet in ifq +set opt(seed) 0.0 +#set opt(tr) brad.tr ;# trace file +set opt(nam) brad.nam ;# nam trace file +set opt(tf) "./sendDataFile.dat" +#set opt(mf) "./scen-300x600-50-10-10-00" +set opt(adhocRouting) AODV +set opt(nn) 50 ;# how many nodes are simulated +set opt(stop) 20.0 ;# simulation time + +set opt(tr) [lindex $argv 0] ;# trace file +set opt(mf) [lindex $argv 1] ;# mobility file + + +# ===================================================================== +# DREAM options +# ===================================================================== +# This is the earliest time a location packet might be sent +set locationStartTime 1.1 +# Location packets will be started uniform randomly between $locationStartTime +# and $locationStartTime + $locationStartOffset +set locationStartOffset 5 + +# Set the seed of the default random number generator. +#ns-random 538474442L + +# This is the random variable that determines when the location +# information will start sending. +set randomVar [new RandomVariable/Uniform] +$randomVar set min_ $locationStartTime +$randomVar set max_ [expr $locationStartTime + $locationStartOffset] + +# ===================================================================== +# Other default settings + +LL set mindelay_ 50us +LL set delay_ 25us +LL set bandwidth_ 0 ;# not used + +Agent/Null set sport_ 0 +Agent/Null set dport_ 0 + +Agent/CBR set sport_ 0 +Agent/CBR set dport_ 0 + +Agent/TCPSink set sport_ 0 +Agent/TCPSink set dport_ 0 + +Agent/TCP set sport_ 0 +Agent/TCP set dport_ 0 +Agent/TCP set packetSize_ 512 + +Queue/DropTail/PriQueue set Prefer_Routing_Protocols 1 + +# unity gain, omni-directional antennas +# set up the antennas to be centered in the node and 1.5 meters above it +Antenna/OmniAntenna set X_ 0 +Antenna/OmniAntenna set Y_ 0 +Antenna/OmniAntenna set Z_ 1.5 +Antenna/OmniAntenna set Gt_ 1.0 +Antenna/OmniAntenna set Gr_ 1.0 + +# Initialize the SharedMedia interface with parameters to make +# it work like the 914MHz Lucent WaveLAN DSSS radio interface +Phy/WirelessPhy set CPThresh_ 10.0 +Phy/WirelessPhy set CSThresh_ 1.559e-11 +Phy/WirelessPhy set RXThresh_ 3.652e-10 +Phy/WirelessPhy set Rb_ 2*1e6 +#this was the default +#Phy/WirelessPhy set Pt_ 0.2818 +# This is for 100m +Phy/WirelessPhy set Pt_ 7.214e-3 +# This is for 40m +#Phy/WirelessPhy set Pt_ 8.5872e-4 +# This is for 250m +#Phy/WirelessPhy set Pt_ 0.2818 +Phy/WirelessPhy set freq_ 914e+6 +Phy/WirelessPhy set L_ 1.0 + +# ===================================================================== +# This puts in only the headers that we need. +# ===================================================================== +remove-all-packet-headers +add-packet-header IP +add-packet-header TCP +add-packet-header Common +add-packet-header Dream +add-packet-header AODV +add-packet-header Flags +add-packet-header LL +add-packet-header Mac + +# ====================================================================== +# Main Program +# ====================================================================== + + +# +# Initialize Global Variables +# + +# create simulator instance + +set ns_ [new Simulator] + +# set wireless channel, radio-model and topography objects + +#set wchan [new $opt(chan)] +#set wprop [new $opt(prop)] +set wtopo [new Topography] + +# create trace object for ns and nam + +#set nt [open "|awk -f ./dream2.awk > $opt(tr)" w] +set nt [open "$opt(tr)" w] +#set nf [open $opt(nam) w] + +$ns_ use-newtrace +$ns_ trace-all $nt +#$ns_ namtrace-all-wireless $nf $opt(x) $opt(y) + +# define topology +$wtopo load_flatgrid $opt(x) $opt(y) + +#$wprop topography $wtopo + +# +# Create God +# +set god_ [create-god $opt(nn)] + + +# New API to config node: +# 1. Create channel (or multiple-channels); +# 2. Specify channel in node-config (instead of channelType); +# 3. Create nodes for simulations. + +# Create channel #1 +set chan_1_ [new $opt(chan)] + +# +# define how node should be created +# + +#global node setting + +$ns_ node-config -adhocRouting $opt(adhocRouting) \ + -llType $opt(ll) \ + -macType $opt(mac) \ + -ifqType $opt(ifq) \ + -ifqLen $opt(ifqlen) \ + -antType $opt(ant) \ + -propType $opt(prop) \ + -phyType $opt(netif) \ + #-channelType $opt(chan) \ + -channel $chan_1_ \ + -topoInstance $wtopo \ + -agentTrace OFF \ + -routerTrace OFF \ + -macTrace ON + +# +# Create the specified number of nodes [$opt(nn)] and "attach" them +# to the channel. +for {set i 0} {$i < $opt(nn) } {incr i} { + set node_($i) [$ns_ node] + $node_($i) random-motion 0 ;# disable random motion +} + +#Define a 'finish' procedure +proc finish {} { +# global ns_ nf nt + global ns_ nt + $ns_ flush-trace +# close $nf + close $nt +# exec nam out.nam & + exit 0 +} + +#Provide initial positions for the nodes +puts "loading mobility file" +source $opt(mf) + +puts "done loading mob file" + +# Define node initial position in nam +for {set i 0} {$i < $opt(nn)} {incr i} { + # 20 defines the node size in nam, must adjust it according to your scenario + # The function must be called after mobility model is defined + $ns_ initial_node_pos $node_($i) 20 +} + +#Create dream agents and attach them to the nodes +for {set i 0} {$i < $opt(nn)} {incr i} { + set d($i) [new Agent/Dream] + $node_($i) attach $d($i) 253 + + # need to tell the geocast agents about their link layers + set ll($i) [$node_($i) set ll_(0)] + $ns_ at 0.0 "$d($i) set-ll $ll($i)" + + # need to tell the geocast agents which nodes they're on also + $ns_ at 0.0 "$d($i) set-node $node_($i)" + + # This is the number of short location packets per long packet + $ns_ at 0.0 "$d($i) set-freqOfLongLocationPackets 13" + + # This is the transmission distance of the node, so that the + # dream agent can make the right size circle. + $ns_ at 0.0 "$d($i) set-neighborDistance 100" + + # This is the distance that a short location packet will travel. + # If set to -1 the packet will travel the whole screen and if set to + # 0 then only one packet will be sent per locaiton packet except + # if there are two nodes in the exact same place. + # 100 for old way + $ns_ at 0.0 "$d($i) set-shortLocationPacketDistance 0" + #$ns_ at 0.0 "$d($i) set-shortLocationPacketDistance 0" + + # This is the transmission distance of the long location packets + # this is set to -1 for and infinite transmission distance (entire net) + $ns_ at 0.0 "$d($i) set-longLocationPacketDistance -1" + + # This is the number of seconds that location time is considered good + $ns_ at 0.0 "$d($i) set-locationGoodTime 46" + + # This is the number of seconds that a dream agent will wait for an ack + # packet for a data packet before it resorts to the recovery method + $ns_ at 0.0 "$d($i) set-maxPacketTimeout 1" + + $ns_ at 0.0 "$d($i) set-bradsDreamFactor 10" + + $ns_ at 0.0 "$d($i) set-bradsDreamLongTime 23" + + # This is the maximum node velocity in grid units per second + # We do not need this line if we are not using a global max node velocity. + # Add 1 to speed of mobility file for this + #$ns_ at 0.0 "$d($i) set-maxNodeVelocity 0" + + # This is the debug value, set to -1 for no output + $ns_ at 0.0 "$d($i) set-debugLevel -1" +} + +puts "Scheduling the location events" + +# This sets the time when the location packets start being sent. +for {set i 0} {$i < $opt(nn) } {incr i} { + set locationStart_($i) [$randomVar value] + #puts "Location Start Time for node($i) = $locationStart_($i)" +} + +for {set i 0} {$i < $opt(nn)} {incr i} { + $ns_ at $locationStart_($i) "$d($i) startLocationService" +} + +puts "Scheduling the send events" +#$ns_ at 2.5 "$d(2) sendData 10" +#$ns_ at 2.5 "$d(5) sendData 14" +#$ns_ at 2.5 "$d(8) sendData 18" + +# doesn't work right away +#$ns_ at 2.5 "$d(10) sendData 2" + +#$ns_ at 2.5 "$d(14) sendData 2" +source $opt(tf) + +for {set i 0} {$i < $opt(nn)} {incr i} { + $ns_ at $opt(stop) "$d($i) printLocationTable" +} + +# +# Tell nodes when the simulation ends +# +for {set i 0} {$i < $opt(nn) } {incr i} { + $ns_ at $opt(stop).000000001 "$node_($i) reset"; +} +# tell nam the simulation stop time +#$ns_ at $opt(stop) "$ns_ nam-end-wireless $opt(stop)" +$ns_ at $opt(stop).000000001 "puts \"NS EXITING...\" ; $ns_ halt" + +# Create some feedback for hov far we are into the simulation +for {set i 0} {$i < 100} {incr i} { + $ns_ at [expr $i * $opt(stop) / 100] "puts \" ... $i % into sim ....\"" +} + + + +#Run the simulation +puts "" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "Running the simulation" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "" +$ns_ run diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/dream2.awk ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream2.awk --- ns-allinone-2.32/ns-2.32/dream/dream2.awk 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/dream2.awk 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,58 @@ +BEGIN{dps=0; dpa=0;} +#print out all the send lines: +#($1=="s") {print $1" "$3" "$9" "$41" "$43" " $45" "$46" "$51} +#routing packet is sent - add 1 to rpt: +($1=="s" && ($45=="[0]" || $45=="[2]")) {rpt++} +#routing packet is received - add 1 to rpr: +($1=="r" && ($45=="[0]" || $45=="[2]")) {rpr++} +#data packet is sent - add 1 to dpt: +($1=="s" && $45=="[1]") {dpt++} +#data packet is received - add 1 to dpr: +($1=="r" && $45=="[1]") {dpr++} + +#data packet is sent from source - add 1 to dps +($1=="s" && $9==$48 && $45=="[1]" && $53==1 && $41==$57) {dps+=1.0; } +#print $1" "$3" "$9" "$41" "$43" "$45" "$46" "$51" "$55}; + +#data packet is received at destination - add 1 to dpa (data packet arrived) +($1=="r" && $51==$9 && $45=="[1]" && freq[$57] == 0) { + dpa+=1.0; hc+=(33-$43); ee+=($3 - $55); freq[$57]++;} +#print $1" "$3" "$9" "$41" "$43" "$45" "$46" "$51" "$55}; + + + +END{ + +#STANDARD OPTION +print "rpt " 1*rpt " rpr " 1*rpr " dpt " 1*dpt " dpr " 1*dpr \ + " tpt " rpt+dpt " tpr " rpr+dpr " dps " dps " dpa " dpa \ + " drat " dpa/dps*100 " hc " hc/dpa " ee " ee/dpa + + + + + +#VERBOSE OPTION +print "routing overhead (tx): Packets - " 1*rpt " Bytes - " rpt*40 +print "routing overhead (rx): Packets - " 1*rpr " Bytes - " rpr*40 +print "data overhead (tx): Packets - " dpt " Bytes - " dpt*64 +print "data overhead (rx): Packets - " dpr " Bytes - " dpr*64 +print "total overhead (tx): Packets - " rpt+dpt " Bytes - " rpt*40+dpt*64 +print "total overhead (rx): Packets - " rpr+dpr " Bytes - " rpr*40+dpr*64 +print "data packets sent (from source) - " dps +print "data packets arrived at dest - " dpa +print "data packet delivery ratio - " dpa/dps*100 + +if (hc > 0) {print "ave hop count - " hc/dpa} +if (hc == 0 ) {print "ave hop count - 0 "} + +if (ee > 0) {print "ave ee delay - " ee/dpa} +if (ee == 0 ) { print "ave ee delay - 0 "} + +#for(words in freq) print words, freq[words] + + +} + + + diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/dream/sendDataFile.dat ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/sendDataFile.dat --- ns-allinone-2.32/ns-2.32/dream/sendDataFile.dat 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/dream/sendDataFile.dat 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,22 @@ +for {set k 10} {$k < 20 } {set k [expr $k + .25] } { + $ns_ at $k "$d(0) sendData 49 64" + $ns_ at [expr $k + .0001] "$d(1) sendData 48 64" + $ns_ at [expr $k + .0002] "$d(2) sendData 47 64" + $ns_ at [expr $k + .0003] "$d(3) sendData 46 64" + $ns_ at [expr $k + .0004] "$d(4) sendData 45 64" + $ns_ at [expr $k + .0005] "$d(5) sendData 44 64" + $ns_ at [expr $k + .0006] "$d(6) sendData 43 64" + $ns_ at [expr $k + .0007] "$d(7) sendData 42 64" + $ns_ at [expr $k + .0008] "$d(8) sendData 41 64" + $ns_ at [expr $k + .0009] "$d(9) sendData 40 64" + $ns_ at [expr $k + .0010] "$d(10) sendData 39 64" + $ns_ at [expr $k + .0011] "$d(11) sendData 38 64" + $ns_ at [expr $k + .0012] "$d(12) sendData 37 64" + $ns_ at [expr $k + .0013] "$d(13) sendData 36 64" + $ns_ at [expr $k + .0014] "$d(14) sendData 35 64" + $ns_ at [expr $k + .0015] "$d(15) sendData 34 64" + $ns_ at [expr $k + .0016] "$d(16) sendData 33 64" + $ns_ at [expr $k + .0017] "$d(17) sendData 32 64" + $ns_ at [expr $k + .0018] "$d(18) sendData 31 64" + $ns_ at [expr $k + .0019] "$d(19) sendData 30 64" +} diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/lar/README ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/README --- ns-allinone-2.32/ns-2.32/lar/README 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/README 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,45 @@ +/****************************************************************************** +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details in LAR-DREAM/. + +*******************************************************************************/ + +Toilers code for LAR in NS-2. + +The paper related to this code is: + +T. Camp, J. Boleng, B. Williams, L. Wilcox, and W. Navidi, Performance +Comparision of Two Location Based Routing Protocols for Ad Hoc +Networks, Proceedings of the IEEE INFOCOM, pp. 1678-1687, 2002. + +=========================== + +We are happy to share our code with you. We only ask that any +published research from using our code include a reference to our +INFOCOM 2002 paper. + +If you have any questions on the code, send email to Tracy Camp at +tcamp@mines.edu. + +The research group's URL is http://toilers.mines.edu. + +=========================== + +Please be advised that this code has only been integrated into and +tested with ns2.1b7a. + +See the README file in LAR-DREAM/ for further details. + +See the README file in LAR-DREAM/mines-dream-ns/ for example +steps on installation. + +=========================== + +Code written by Jeff Boleng (Ph.D. 2002 from the Colorado School of +Mines). + +=========================== + + diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/lar/box.tcl ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/box.tcl --- ns-allinone-2.32/ns-2.32/lar/box.tcl 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/box.tcl 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,241 @@ +#*****************************************************************************# +# File Name: box.tcl # +# Purpose: # +# Original Author: # +# Modified by: # +# Date Created: # +# +# Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines # +# +# Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license # +# details. # +#******************************************************************************/ + +if {$argc != 1} { + puts "Usage: " + exit 65 + } + +puts "setting initial variables..." +set val(chan) Channel/WirelessChannel +set val(prop) Propagation/TwoRayGround +set val(netif) Phy/WirelessPhy +set val(mac) Mac/802_11 +set val(ifq) Queue/DropTail/PriQueue +set val(ll) LL +set val(ant) Antenna/OmniAntenna +set val(x) 300 +set val(y) 600 +set val(ifqlen) 50 +set val(rp) AODV +#set val(rp) DSR +#set val(rp) DSDV +set val(nn) 50 +set val(txPower) 0.0075 ; #100 meters +set val(rxPower) 1 +#set val(sc) "test.mob" +set val(sc) [lindex $argv 0] ;# mobility file +set val(dataStart) 1000.0 +set val(dataStop) 2000.0 +set val(signalStop) 2005.0 +set val(finish) 2010.0 + +# ===================================================================== +# Other default settings + +puts "setting other default settings..." + +LL set mindelay_ 50us +LL set delay_ 25us +LL set bandwidth_ 0 ;# not used + +Agent/Null set sport_ 0 +Agent/Null set dport_ 0 + +Agent/CBR set sport_ 0 +Agent/CBR set dport_ 0 + +Agent/TCPSink set sport_ 0 +Agent/TCPSink set dport_ 0 + +Agent/TCP set sport_ 0 +Agent/TCP set dport_ 0 +Agent/TCP set packetSize_ 512 + +Queue/DropTail/PriQueue set Prefer_Routing_Protocols 1 + +# unity gain, omni-directional antennas +# set up the antennas to be centered in the node and 1.5 meters above it +Antenna/OmniAntenna set X_ 0 +Antenna/OmniAntenna set Y_ 0 +Antenna/OmniAntenna set Z_ 1.5 +Antenna/OmniAntenna set Gt_ 1.0 +Antenna/OmniAntenna set Gr_ 1.0 + +# Initialize the SharedMedia interface with parameters to make +# it work like the 914MHz Lucent WaveLAN DSSS radio interface +Phy/WirelessPhy set CPThresh_ 10.0 +Phy/WirelessPhy set CSThresh_ 1.559e-11 +Phy/WirelessPhy set RXThresh_ 3.652e-10 +Phy/WirelessPhy set Rb_ 2*1e6 +#this was the default +#Phy/WirelessPhy set Pt_ 0.2818 +# This is for 100m +Phy/WirelessPhy set Pt_ 7.214e-3 +# This is for 40m +#Phy/WirelessPhy set Pt_ 8.5872e-4 +# This is for 250m +#Phy/WirelessPhy set Pt_ 0.2818 +Phy/WirelessPhy set freq_ 914e+6 +Phy/WirelessPhy set L_ 1.0 + +# ===================================================================== +# This puts in only the headers that we need. +# ===================================================================== +puts "removing unecessary packet headers..." +remove-all-packet-headers +add-packet-header IP +add-packet-header Common +add-packet-header LAR +add-packet-header LL +add-packet-header Mac + +#Create a simulator object +set ns_ [new Simulator] + +#Open a trace file + +set nt [open out.trace w] +$ns_ trace-all $nt + +set topo [new Topography] +$topo load_flatgrid $val(x) $val(y) + +create-god $val(nn) + +# New API to config node: +# 1. Create channel (or multiple-channels); +# 2. Specify channel in node-config (instead of channelType); +# 3. Create nodes for simulations. + +# Create channel #1 +puts "creating channel..." +set chan_1_ [new $val(chan)] + +# +# define how node should be created +# + +#global node setting +puts "setting global node values..." +$ns_ node-config -adhocRouting $val(rp) \ + -llType $val(ll) \ + -macType $val(mac) \ + -ifqType $val(ifq) \ + -ifqLen $val(ifqlen) \ + -antType $val(ant) \ + -propType $val(prop) \ + -phyType $val(netif) \ + #-channelType $val(chan) \ + -channel $chan_1_ \ + -topoInstance $topo \ + -agentTrace OFF \ + -routerTrace OFF \ + -macTrace OFF \ + -movementTrace OFF \ + -txPower $val(txPower) \ + -rxPower $val(rxPower) + +# create the nodes +puts "creating the nodes..." + +# create the nodes +for {set i 0} {$i < $val(nn) } {incr i} { + set node_($i) [$ns_ node] + $node_($i) random-motion 0 ;# disable random motion +} + +# +#Define a 'finish' procedure +proc finish {} { + global ns_ nt + $ns_ flush-trace + close $nt + exit 0 +} + +# Load the movement file +puts "Loading the mobility file..." +source $val(sc) + +#Create lar agents and attach them to the nodes +puts "creating lar agents and attaching them to nodes..." +for {set i 0} {$i < $val(nn)} {incr i} { + set g($i) [new Agent/LAR] + $node_($i) attach $g($i) 254 + + # need to tell the lar agents about their link layers + set ll($i) [$node_($i) set ll_(0)] + $ns_ at 0.0 "$g($i) set-ll $ll($i)" + + # need to tell the lar agents which nodes they're on also + $ns_ at 0.0 "$g($i) set-node $node_($i)" +} + +# the format now for the lar send is +# +# "$nodeId sendData " +# +# this will be used to test in a static configuration, and will +# change once the mobility portion is figured out. +#Schedule events + +puts "Scheduling the send events" +for {set k $val(dataStart)} {$k < $val(dataStop)} {set k [expr $k + 0.25] } \ +{ + $ns_ at $k "$g(0) sendData 49 64 B" + $ns_ at [expr $k + .0001] "$g(1) sendData 48 64 B" + $ns_ at [expr $k + .0002] "$g(2) sendData 47 64 B" + $ns_ at [expr $k + .0003] "$g(3) sendData 46 64 B" + $ns_ at [expr $k + .0004] "$g(4) sendData 45 64 B" + $ns_ at [expr $k + .0005] "$g(5) sendData 44 64 B" + $ns_ at [expr $k + .0006] "$g(6) sendData 43 64 B" + $ns_ at [expr $k + .0007] "$g(7) sendData 42 64 B" + $ns_ at [expr $k + .0008] "$g(8) sendData 41 64 B" + $ns_ at [expr $k + .0009] "$g(9) sendData 40 64 B" + $ns_ at [expr $k + .0010] "$g(10) sendData 39 64 B" + $ns_ at [expr $k + .0011] "$g(11) sendData 38 64 B" + $ns_ at [expr $k + .0012] "$g(12) sendData 37 64 B" + $ns_ at [expr $k + .0013] "$g(13) sendData 36 64 B" + $ns_ at [expr $k + .0014] "$g(14) sendData 35 64 B" + $ns_ at [expr $k + .0015] "$g(15) sendData 34 64 B" + $ns_ at [expr $k + .0016] "$g(16) sendData 33 64 B" + $ns_ at [expr $k + .0017] "$g(17) sendData 32 64 B" + $ns_ at [expr $k + .0018] "$g(18) sendData 31 64 B" + $ns_ at [expr $k + .0019] "$g(19) sendData 30 64 B" +} + + +# this is done to make the simulator continue running and "settle" things out +for {set i 0} {$i < $val(nn)} {incr i} { + $ns_ at $val(signalStop) "$g($i) larDone" +} + +$ns_ at $val(finish) "finish" +$ns_ at [expr $val(finish) + 0.1] "puts \"NS Exiting...\" ; $ns_ halt" + +#Run the simulation +puts "" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "Running the simulation" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "" +$ns_ run diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/lar/lar.cc ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/lar.cc --- ns-allinone-2.32/ns-2.32/lar/lar.cc 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/lar.cc 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,2704 @@ +/****************************************************************************** +* File Name: lar.cc +* Purpose: LAR protocol cc file for ns-2 +* Original Author: Jeff Boleng +* Modified by: +* Date Created: Some time in 2002 +* +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details. +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "lar.h" + +using namespace std; + +int hdr_lar::offset_; + +static class LARHeaderClass: public PacketHeaderClass +{ + public: + LARHeaderClass(): PacketHeaderClass("PacketHeader/LAR", + sizeof(hdr_lar)) + { + bind_offset(&hdr_lar::offset_); + } +} class_larhdr; + +static class LARClass: public TclClass +{ + public: + LARClass() : TclClass("Agent/LAR") {} + TclObject* create(int, const char*const*) + { + return (new LARAgent()); + } +} class_lar; + +// The next two class declarations bind our C++ classes to the OTcl +// class. +//static class LARHeaderClass : public PacketHeaderClass { +//public: + //LARHeaderClass() : PacketHeaderClass("PacketHeader/LAR", + //sizeof(hdr_lar)) {} +//} class_larhdr; + + +//static class LARClass : public TclClass { +//public: + //LARClass() : TclClass("Agent/LAR") {} + //TclObject* create(int, const char*const*) { + //return (new LARAgent()); + //} +//} class_lar; + +// if a route reply is not recieved in this amount of time the +// request is flooded +double LARrouteRequestTimeout = 0.5; + +// This is the lar "fudge factor". It is used to make the box or +// step methods "slightly" bigger or smaller. It is measured in units or meters +double LARDelta = 0.0; + +// if true, this will add jitter to unicast packets being sent +bool LARuseJitteronSend = true; +bool LARuseJitteronBroadcast = true; + +// timer to drop packets in the pending queue after +bool purgePending = true; +double dropPendingPacketsAfter = 30.0; + +// if true, then the node will query immediate neighbors for a route before +// sending a normal LAR route request +bool useRingZeroSearch = true; +double ringZeroWait = 0.030; // this is 10 milliseconds + +bool usePromiscuousListening = false; + +bool useIntermediateRouteRepair = true; + +// This option and useRoutePersistence are mutually exclusive. Only one can be +// true at a time, and this one is given preference. Although both can be false. +// This option is also only used if the useIntermediateRouteRepair flag is set. +// Otherwise, intermediate packets are dropped on a route error no matter what. +bool dropIntermediatePacketsIfNoRoute = true; + +// WARNING - this option isn't working correctly. It works some, but creates too +// much overhead. +bool useIntermediateRouteReply = false; + +int pendingPacketQueueLength = 64; // this is the maximum number of packets that + // can be in the pending packet queue at one time +// set it to a big number that is more packets than you expect for an infinite queue + +// these are used to set the timeout for continued flooding of route requests if there +// are packets still in the pending queue +// +// WARNING - this option doesn't work, and using it means the simulation will never +// terminate! I'll fix it soon. +bool useRoutePersistence = false; +// This option and dropIntermediatePacketsIfNoRoute are mutually exclusive. Only one can be +// true at a time. Although both can be false. +double LARroutePersistenceTimeout = 0.5; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +nsaddr_t routeBreakPoint = -77; + +// used for reporting status, higher numbers imply more verbose output +int LARverbosity = 0; + +// here is the implementation of the timer +void LARRouteRequestTimer::expire(Event *e) +{ + if (LARverbosity > 0) + { + cout << endl << "*******************************" << endl; + cout << "In LARRouteRequestTimer::expire" << endl; + cout << "Time = " << Scheduler::instance().clock() << endl; + } + + if (triesLeft >= 1) + { + if (LARverbosity > 0) + { + cout << "Trying again with forward code " << forwardMethod << "..." << endl; + cout << "destX: " << routeInfo->x << endl; + cout << "destY: " << routeInfo->y << endl; + cout << "destV: " << routeInfo->v << endl; + cout << "destVtime: " << routeInfo->timeOfVelocity << endl; + } + + triesLeft--; + // no need to reschedule a new timer because sendRouteRequest does that + //agent->timers[this->dest]->resched(LARrouteRequestTimeout); + agent->sendRouteRequest(this->dest, forwardMethod, this->routeInfo, false); + } else { + if (LARverbosity > 0) + { + cout << "Didn't find a route, emptying the pending packet queue." << endl; + cout << "My address: " << this->agent->addr() << endl; + cout << "Dest address: " << this->dest << endl; + } + // if this is not the first try on the timer, then the pending route queue needs to be + // emptied of it's contents because we've failed to find a route twice... + triesLeft = 0; + agent->clearRequestPending(this->dest); + if (purgePending) + { + agent->purgePendingPacketsFor(this->dest); + } + if (useRoutePersistence) + { + agent->checkPendingQueueForPackets(this->dest); + } + } + if (LARverbosity > 0) + { + cout << "Done in LARRouteRequestTimer::expire" << endl; + cout << "*******************************" << endl << endl; + } + return; +} + + +// *********************************************************************** +// Creator +// *********************************************************************** +LARAgent::LARAgent() : Agent(PT_LAR) +{ + //off_lar_ = hdr_lar::offset(); + //bind("packetSize_", &size_); + //bind("off_lar_", &off_lar_); + // This binds the C++ and OTcl variables. I may need to do some + // more, but I don't know right now. + + ll = NULL; + node = NULL; + + dataTxPkts = 0; + dataRxPkts = 0; + dataTxBytes = 0; + dataRxBytes = 0; + totalEEdelay = 0.0; + totalHops = 0; + protocolTxPkts = 0; + protocolRxPkts = 0; + protocolTxBytes = 0; + protocolRxBytes = 0; + dataTxPktsFwd = 0; + dataRxPktsFwd = 0; + dataTxBytesFwd = 0; + dataRxBytesFwd = 0; + dataDroppedSrc = 0; + dataDroppedInt = 0; + routeErrorsGen= 0; + routeErrorsRx = 0; + larRtReqTx = 0; + larRtReqRx = 0; + floodRtReqTx = 0; + floodRtReqRx = 0; + oneHopRtReqTx = 0; + oneHopRtReqRx = 0; + srcRtErrors = 0; + droppedAtEnd = 0; + pktOverflow = 0; + + srand(clock()); + + return; +} + +// *********************************************************************** +// Destructor +// *********************************************************************** +LARAgent::~LARAgent() +{ + rcvdPackets.erase(rcvdPackets.begin(), rcvdPackets.end()); + sentPackets.erase(sentPackets.begin(), sentPackets.end()); + routeTable.erase(routeTable.begin(), routeTable.end()); + updatedRoute.erase(updatedRoute.begin(), updatedRoute.end()); + timers.erase(timers.begin(), timers.end()); + pendingPackets.erase(pendingPackets.begin(), pendingPackets.end()); + return; +} + +void larRouteErrorCallback(Packet *p, void *arg) +{ + ((LARAgent*) arg)->routeError(p); +} + +// *********************************************************************** +// command +// *********************************************************************** +int LARAgent::command(int argc, const char*const* argv) +{ + TclObject *obj; + + if (argc == 2) + { + if (strcmp(argv[1], "larDone") == 0) + { + // this purges any pending packets at the end of the run, just in case + this->purgeAllPendingPackets(); + + cout << endl << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; + cout << "LAR agent on node " << this->addr() << " done at " + << Scheduler::instance().clock() << endl; + cout << "Statistics for node: " << this->addr() << endl; + cout << "Data Received:" << endl; + cout << "\tdataRxPkts: " << dataRxPkts << endl; + cout << "\tdataRxBytes: " << dataRxBytes << endl; + cout << "\ttotalEEdelay: " << totalEEdelay << endl; + cout << "\ttotalHops: " << totalHops << endl; + if (dataRxPkts > 0) + { + cout << "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; + cout << "\tAverage EE delay: " << (double)totalEEdelay/(double)dataRxPkts << endl; + cout << "\tAverage Hops: " << (double)totalHops/(double)dataRxPkts << endl; + } + cout << "Data Sent or Dropped:" << endl; + cout << "\tdataTxPkts: " << dataTxPkts << endl; + cout << "\tdataTxBytes: " << dataTxBytes << endl; + cout << "\tdataDroppedSrc: " << dataDroppedSrc << endl; + cout << "\tdataDroppedInt: " << dataDroppedInt << endl; + cout << "Data Overhead:" << endl; + cout << "\tdataTxPktsFwd: " << dataTxPktsFwd << endl; + cout << "\tdataTxBytesFwd: " << dataTxBytesFwd << endl; + cout << "\tdataRxPktsFwd: " << dataRxPktsFwd << endl; + cout << "\tdataRxBytesFwd: " << dataRxBytesFwd << endl; + cout << "Protocol Overhead:" << endl; + cout << "\tprotocolTxPkts: " << protocolTxPkts << endl; + cout << "\tprotocolTxBytes: " << protocolTxBytes << endl; + cout << "\tprotocolRxPkts: " << protocolRxPkts << endl; + cout << "\tprotocolRxBytes: " << protocolRxBytes << endl; + cout << "\trouteErrorsGen: " << routeErrorsGen<< endl; + cout << "\trouteErrorsRx: " << routeErrorsRx << endl; + cout << "\tlarRtReqTx: " << larRtReqTx << endl; + cout << "\tlarRtReqRx: " << larRtReqRx << endl; + cout << "\tfloodRtReqTx: " << floodRtReqTx << endl; + cout << "\tfloodRtReqRx: " << floodRtReqRx << endl; + cout << "\toneHopRtReqTx: " << oneHopRtReqTx << endl; + cout << "\toneHopRtReqRx: " << oneHopRtReqRx << endl; + cout << "\tsrcRtErrors: " << srcRtErrors << endl; + cout << "\tdroppedAtEnd: " << droppedAtEnd << endl; + cout << "\tpktOverflow: " << pktOverflow << endl; + cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl << endl; + return (TCL_OK); + } + } else if (argc == 3) { + if (strcmp(argv[1], "setVerbosity") == 0) + { + LARverbosity = atoi(argv[2]); + if (LARverbosity < 0) + { + LARverbosity = 0; + } else if (LARverbosity > 2) { + LARverbosity = 2; + } + return (TCL_OK); + } else if (strcmp(argv[1], "set-ll") == 0) { + if( (obj = TclObject::lookup(argv[2])) == 0) + { + fprintf(stderr, "LARAgent(set-ll): %s lookup of %s failed\n", + argv[1], argv[2]); + return (TCL_ERROR); + } + ll = (NsObject*) obj; + return (TCL_OK); + } else if (strcmp(argv[1], "set-node") == 0) { + if( (obj = TclObject::lookup(argv[2])) == 0) + { + fprintf(stderr, "LARAgent(set-node): %s lookup of %s failed\n", + argv[1], argv[2]); + return (TCL_ERROR); + } + node = dynamic_cast< MobileNode * >(obj); + if (node) // dynamic cast was successful and didn't return NULL + { + return (TCL_OK); + } else { + fprintf(stderr, "Unable to dynamically cast %s to a MobileNode\n", + argv[2]); + return (TCL_ERROR); + } + } else if (strcmp(argv[1], "setRouteRequestTimeout") == 0) { + LARrouteRequestTimeout = atoi(argv[2]); + return (TCL_OK); + } else if (strcmp(argv[1], "setLARDelta") == 0) { + LARDelta = atof(argv[2]); + if (LARverbosity > 0) + { + fprintf(stderr, "Set LARDelta to %f at node %d.\n", LARDelta, this->addr()); + } + return (TCL_OK); + } + } else if (argc == 5) { + if (strcmp(argv[1], "sendData") == 0) + { + if ((ll == NULL) || (node == NULL)) + { + fprintf(stderr, "Link layer and node must be set on a lar agent\n"); + fprintf(stderr, "before anything can be sent.\n"); + return (TCL_ERROR); + } + nsaddr_t destID = (nsaddr_t)atoi(argv[2]); + node->update_position(); + + // Create a new packet + Packet* dataPkt = allocpkt(); + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(dataPkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(dataPkt); + + // old way to do this + //hdr_lar* larhdr = (hdr_lar*)dataPkt->access(off_lar_); + //hdr_cmn* hdrcmn = (hdr_cmn*)dataPkt->access(off_cmn_); + + hdrcmn->xmit_failure_ = larRouteErrorCallback; + hdrcmn->xmit_failure_data_ = (void *) this; + + // Store the current time in the 'send_time' field + larhdr->sendTime_ = Scheduler::instance().clock(); + + larhdr->larCode_ = 'D'; + larhdr->forwardCode_ = toupper(argv[4][0]); + //cout << "forwardCode = " << larhdr->forwardCode() << endl; + larhdr->sourceX_ = node->X(); + larhdr->sourceY_ = node->Y(); + larhdr->lastHopX_ = node->X(); + larhdr->lastHopY_ = node->Y(); + larhdr->destinationID_ = destID; + larhdr->dataLength_ = atoi(argv[3]); + larhdr->newPkt_ = true; + + larhdr->requestID_ = 0; + larhdr->requestSendTime_ = 0; + + sendNewData(dataPkt, destID); + + // return TCL_OK, so the calling function knows that the + // command has been processed + return (TCL_OK); + } // if (strcmp(argv[1], "sendData") == 0) + } // } else if (argc == 5) { + // If the command hasn't been processed by LARAgent()::command, + // call the command() function for the base class + return (Agent::command(argc, argv)); +} + + +// *********************************************************************** +// recv +// *********************************************************************** +void LARAgent::recv(Packet* pkt, Handler*) +{ + // Access the common header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + struct hdr_ip* hdrip = hdr_ip::access(pkt); + + // old way to do this + //hdr_cmn* hdrcmn = (hdr_cmn*)pkt->access(off_cmn_); + + // Access the IP header for the received packet: + //hdr_ip* hdrip = (hdr_ip*)pkt->access(off_ip_); + + // Access the LAR header for the received packet: + //hdr_lar* larhdr = (hdr_lar*)pkt->access(off_lar_); + + node->update_position(); + // Set the newPkt field to false. Since this packet has been received, + // it can't be new. + larhdr->newPkt() = false; + + if (larhdr->larCode() == 'D') + { + // only do this if this packet is not destined for me + if (this->addr() != larhdr->destinationID()) + { + dataRxPktsFwd++; + dataRxBytesFwd += larhdr->dataLength(); + } + // count the protocol header bytes as control bytes for + // all packets, even data + protocolRxBytes += larhdr->headerLength(); + } else { + protocolRxPkts++; + protocolRxBytes += larhdr->headerLength(); + } + // Is it a duplicate packet? + if (this->dupRcvdPacket(hdrcmn->uid_) || this->dupSentPacket(hdrcmn->uid_)) + { + // already seen it, or I sent it, just free it and drop it + if (LARverbosity == 2) + { + cout << "****************************************************" << endl; + cout << "In LAR recv at node: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "Route in header: "; + for (int i=0; ihops(); i++) + { + cout << larhdr->route_[i] << " "; + } + cout << endl; + cout << "Packet ID: " << hdrcmn->uid_ + << " Type: " << larhdr->larCode() << endl; + cout << "Duplicate packet seen from " << hdrcmn->prev_hop_ + << ", freeing it." << endl; + cout << "Returning from recv early" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "****************************************************" << endl << endl; + } + Packet::free(pkt); + return; + } else { + // This is redundant for now because dupRcvdPacket records the packet + // as recieved, but I don't like that side effect and may change it + // later. + recordRcvdPacket(hdrcmn->uid_); + } + + if (LARverbosity > 0) + { + cout << "****************************************************" << endl; + cout << "In LAR recv at node: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "Route in header: "; + + for (int i=0; ihops(); i++) + { + cout << larhdr->route_[i] << " "; + } + cout << endl; + cout << "Packet Type: " << larhdr->larCode() << endl; + cout << "Forwarding Code: " << larhdr->forwardCode() << endl; + } // if (LARverbosity > 0) + + nsaddr_t dest = larhdr->destinationID(); + map >::iterator destPtr; + destPtr = routeTable.find(dest); + // What kind of packet is it? + // *********************************************************************** + // Route Request + // *********************************************************************** + if (larhdr->larCode() == 'R') + { + if(LARverbosity > 0) + { + cout << "Route Request packet seen" << endl; + cout << "From: " << hdrip->src_.addr_ + << " at [" << larhdr->sourceX() << "," << larhdr->sourceY() << "]" << endl; + cout << "Last hop: " << hdrcmn->prev_hop_ << endl; + cout << "Packet ID: " << hdrcmn->uid_ << endl; + } +//LARprintHeaders(pkt); + if (this->addr() == larhdr->destinationID()) + { + if (larhdr->forwardCode() == 'F') + { + floodRtReqRx++; + } else { + larRtReqRx++; + } + // this is a route request for a route to me + // I need to reply with a route reply + // Create a new packet + Packet* newpkt = allocpkt(); + // Access the headers for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* newlarhdr = hdr_lar::access(newpkt); + struct hdr_cmn* newhdrcmn = hdr_cmn::access(newpkt); + + // old way to do this + //hdr_lar* newlarhdr = (hdr_lar*)newpkt->access(off_lar_); + newlarhdr->hops() = 0; + //hdr_cmn* newhdrcmn = (hdr_cmn*)newpkt->access(off_cmn_); + + newlarhdr->larCode_ = 'A'; + newlarhdr->forwardCode_ = larhdr->forwardCode(); + newlarhdr->sourceX_ = larhdr->sourceX_; + newlarhdr->sourceY_ = larhdr->sourceY_; + newlarhdr->lastHopX_ = node->X(); + newlarhdr->lastHopY_ = node->Y(); + newlarhdr->destinationX_ = node->X(); + newlarhdr->destinationY_ = node->Y(); + newlarhdr->destinationID_ = larhdr->route_[0]; + newlarhdr->sendTime_ = Scheduler::instance().clock(); + newlarhdr->newPkt_ = true; + newlarhdr->destinationSpeed_ = node->speed(); + newlarhdr->speedTime_ = Scheduler::instance().clock(); + // puts the route that the join demand took in the join table + for (int i=0; ihops(); i++) + { + newlarhdr->route_[i] = larhdr->route_[i]; + } + newlarhdr->hops() = larhdr->hops(); + + // adds the final destination to the route + newlarhdr->route_[newlarhdr->hops()] = this->addr(); + newlarhdr->hops()++; + newlarhdr->requestID_ = hdrcmn->uid_; + newlarhdr->requestSendTime_ = larhdr->requestSendTime(); + newlarhdr->dataLength_ = 0; + + nsaddr_t srcID = larhdr->route_[larhdr->hops()-1]; + if (LARverbosity > 0) + { + cout << "Sending a Route Reply, ID: " << newhdrcmn->uid_ + << " to " << srcID << endl; + } + //this->broadcastPacket(newpkt); + // Don't want to rebroadcast, want send it to my "upstream" neighbor + + // this is a Route Request intended for me, so I should put it in my + // route table no matter what + //if (usePromiscuousListening) + //{ + maintainRouteTable(newpkt); + //} + this->sendPacket(newpkt, srcID); + Packet::free(pkt); + return; + } else if (useIntermediateRouteReply && (destPtr != routeTable.end())) { +//cerr << "One: " << flush; + this->sendRouteReply(pkt); + Packet::free(pkt); + return; + } else if ((larhdr->forwardCode() == 'N') && (destPtr != routeTable.end())) { + // I must be a direct neighbor of the node doing a route request + // this depends on short circuit boolean... If the first condition isn't true, the + // second condition will create an access fault +//cerr << "Two: " << flush; + this->sendRouteReply(pkt); + Packet::free(pkt); + return; + } else if (this->inForwardingRegion(larhdr->forwardCode(), + larhdr->lastHopX(), larhdr->lastHopY(), + larhdr->destinationX(), larhdr->destinationY(), + larhdr->destinationSpeed(), larhdr->speedTime())) { + // re-broadcast the packet, because I'm in the forwarding region. + if (LARverbosity > 0) + { + cout << "Rebroadcasting, forwarding node, but not the destination..." << endl; + cout << "last hop location: (" << larhdr->lastHopX() << "," << larhdr->lastHopY() + << ")" << endl; + cout << "destination location: (" << larhdr->destinationX() << "," << larhdr->destinationY() + << ")" << endl; + cout << "destination speed: " << larhdr->destinationSpeed() << endl; + cout << "speed time: " << larhdr->speedTime() << endl; + } + larhdr->lastHopX_ = node->X(); + larhdr->lastHopY_ = node->Y(); + larhdr->route_[larhdr->hops()] = this->addr(); + larhdr->hops()++; + //if (usePromiscuousListening) + //{ + // this is a Route Request, and I'm a flooding node in the forwarding + // region, so I should update my route table regardless of if this is true. + maintainRouteTable(pkt); + //} + this->rebroadcastPacket(pkt); + return; + } else { + if (LARverbosity > 0) + { + cout << "Not in forwarding region and not the destination. Ignoring." << endl; + } + // don't really need an else here because I take care of duplicate + // packets up above + Packet::free(pkt); + return; + } + // *********************************************************************** + // Route Reply + // *********************************************************************** + } else if (larhdr->larCode() == 'A') { + if (LARverbosity > 0 ) + { + cout << "Route Reply packet seen" << endl; + cout << "From: " << hdrip->src_.addr_ + << " at [" << larhdr->sourceX() << "," << larhdr->sourceY() << "]" << endl; + cout << "Last hop: " << hdrcmn->prev_hop_ << endl; + cout << "Packet ID: " << hdrcmn->uid_ << endl; + cout << "Request ID: " << larhdr->requestID_ << endl; + } + + if (this->addr() == larhdr->destinationID()) + { + // I sent the corresponding route request, and the reply just got back. + if (LARverbosity > 0) + { + cout << "Back at originating node!" << endl; + cout << "Route Request sent at " << larhdr->requestSendTime_ + << " received at " << Scheduler::instance().clock() << endl; + cout << "Round trip delay = " + << Scheduler::instance().clock() - larhdr->requestSendTime_ << endl; + } + // up date the routing table entry and check the pending packets list for + // any data packets waiting for this route + + maintainRouteTable(pkt); + nsaddr_t destID = larhdr->route_[larhdr->hops()-1]; + if (updatedRoute[destID]) + { + // now, check and see if there are packets waiting for this route + // if we got a route reply, there must have been a route request, and there + // probably are packets pending + destPtr = routeTable.find(destID); + list::iterator pendingPtr; + for (pendingPtr=pendingPackets.begin(); pendingPtr!=pendingPackets.end(); /*nothing*/) + { + // Access the headers for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* pendinglarhdr = hdr_lar::access((*pendingPtr)); + + // old way to do this + //hdr_lar* pendinglarhdr = (hdr_lar*)(*pendingPtr)->access(off_lar_); + + if (LARverbosity > 0) + { + cout << "Checking pending packet addressed to " << pendinglarhdr->destinationID() << endl; + } + if (pendinglarhdr->destinationID() == destID) + { + if (LARverbosity > 0) + { + cout << "Sending a pending packet to " << destID << endl; + } + // if the pending packet is destined to the node we just received a route request + // from, then flesh out the header and send it off + pendinglarhdr->destinationX_ = destPtr->second.x; + pendinglarhdr->destinationY_ = destPtr->second.y; + pendinglarhdr->destinationSpeed_ = destPtr->second.v; + pendinglarhdr->speedTime_ = destPtr->second.timeOfVelocity; + pendinglarhdr->requestSendTime_ = destPtr->second.timeOfLastRequest; + pendinglarhdr->hops_ = destPtr->second.hops; + if (LARverbosity > 0) + { + cout << "Using route: "; + } + for (int k=0; ksecond.hops; k++) + { + pendinglarhdr->route_[k] = destPtr->second.route[k]; + if (LARverbosity > 0) + { + cout << destPtr->second.route[k] << " "; + } + } // for (int k=0; ksecond.hops; k++) + if (LARverbosity > 0) + { + cout << endl; + } + // send it out + if (LARverbosity > 0) + { + cout << "****************************************************" << endl; + cout << "Just received a route reply, so sending queued lar data from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "Data size: " << pendinglarhdr->dataLength() << endl; + cout << "Total size: " << pendinglarhdr->size() << endl; + } // if (LARverbosity > 0) + this->sendPacket((*pendingPtr), destPtr->second.route[1]); + if (LARverbosity > 0) + { + cout << "****************************************************" << endl << endl; + } // if (LARverbosity > 0) + pendingPackets.erase(pendingPtr++); + } else { + pendingPtr++; + } // if (pendinglarhdr->destinationID() == destID) + } // for (pendingPtr=pendingPackets.begin(); pendingPtr!=pendingPackets.end(); /*nothing*/) + + // clear the flood timer for this destination if it exists + map >::iterator timerPtr; + timerPtr = timers.find(destID); + if (timerPtr != timers.end()) + { + if (LARverbosity > 0) + { + cout << "Cancelling the flood timer for this data packet." << endl; + } + timerPtr->second->force_cancel(); + } // if (timerPtr != timers.end()) + } else { + // the packet didn't update the route table, so I still need a new route + // basically, I should just return and let the timer expire + if (LARverbosity > 0) + { + cout << "The route reply didn't update the routing table!" << endl; + } + } + Packet::free(pkt); + return; + } else { + // if I get a route reply and am not the sender, then I must be + // the addressee of the route reply, and I should forward it back downstream + nsaddr_t dest = -5; + for (int i=0; ihops(); i++) + { + if (larhdr->route_[i] == this->addr()) + { + // after the find, dest is pointing to my address, so decrement it to + // the previous one in the route + dest = larhdr->route_[i-1]; + break; + } + } + if (LARverbosity > 0) + { + cout << "Re-sending a Route Request, ID: " << hdrcmn->uid_ + << " to " << dest << endl; + } + if (dest != -5) + { + larhdr->lastHopX_ = node->X(); + larhdr->lastHopY_ = node->Y(); + //if (usePromiscuousListening) + //{ + // this is a Route Reply and I'm on the reverse source route, so I + // should update my route table no matter what + maintainRouteTable(pkt); + //} + this->sendPacket(pkt, dest); + return; + } else { + cerr << "I'm supposed to forward this route reply back upstream, but I'm not in the" << endl; + cerr << "recorded route! I'm freeing the packet and returning. In Route Reply code." << endl; + cerr << "Pkt id: " << hdrcmn->uid_ << " My id: " << this->addr() << " Route: "; + for (int i=0; ihops(); i++) + { + cerr << larhdr->route_[i] << " "; + } + cerr << endl; + Packet::free(pkt); + return; + } + } // else of if (this->addr() == larhdr->destinationID()) + // *********************************************************************** + // Data Packet + // *********************************************************************** + } else if (larhdr->larCode() == 'D') { + if (LARverbosity > 0) + { + cout << "LAR data packet seen" << endl; + cout << "From: " << hdrip->src_.addr_ + << " at [" << larhdr->sourceX() << "," << larhdr->sourceY() << "]" << endl; + cout << "Last hop: " << hdrcmn->prev_hop_ << endl; + cout << "Packet ID: " << hdrcmn->uid_ << endl; + } + if (usePromiscuousListening) + { + // if I'm on the source route, or the source or destination, I should + // already have all this routing information, so this should not be needed + // anywhere else + maintainRouteTable(pkt); + } + + if (this->addr() == larhdr->destinationID()) + { + // print some nice informational message + if (LARverbosity > 0) + { + cout << "Recieved a data packet sucessfully!!!" << endl; + cout << "Send scheduled at: " << larhdr->sendTime() << endl; + cout << "Received at: " << Scheduler::instance().clock() << endl; + cout << "Total Delay: " + << Scheduler::instance().clock()-larhdr->sendTime() << endl; + cout << "****************************************************" << endl << endl; + } + dataRxPkts++; + dataRxBytes += larhdr->dataLength(); + + // again, count all header bytes as control overhead + protocolRxBytes += larhdr->headerLength(); + + totalEEdelay += Scheduler::instance().clock()-larhdr->sendTime(); + totalHops += larhdr->hops() - 1; + + // Discard the packet + Packet::free(pkt); + return; + } else { + // if I get it, and it's not for me, then I must be on the route and I need + // to forward it to the next down stream neighbor + nsaddr_t dest = -5; + for (int i=0; ihops(); i++) + { + if (larhdr->route_[i] == this->addr()) + { + // after the find, dest is pointing to my address, so increment it to + // the previous one in the route + dest = larhdr->route_[i+1]; + break; + } + } + if (LARverbosity > 0) + { + cout << "Forwarding the data packet " << hdrcmn->uid_ + << " downstream to " << dest << endl; + } + if (dest != -5) + { + larhdr->lastHopX_ = node->X(); + larhdr->lastHopY_ = node->Y(); + // the transmit failure callback node pointer must be changed to me before resending + // this is what generates a route error if when I send this packet there is a link + // layer error returned + hdrcmn->xmit_failure_data_ = (void *) this; + this->sendPacket(pkt, dest); + return; + } else { + cerr << "I'm supposed to forward this data packet downstream, but I'm not in the" << endl; + cerr << "recorded route! I'm freeing the packet and returning. In Data Packet code." << endl; + Packet::free(pkt); + cout << "****************************************************" << endl << endl; + return; + } + } + // *********************************************************************** + // Route Error Packet + // *********************************************************************** + } else if (larhdr->larCode() == 'E') { + if (LARverbosity > 0) + { + cout << "LAR route error packet seen" << endl; + cout << "From: " << hdrip->src_.addr_ + << " at [" << larhdr->sourceX() << "," << larhdr->sourceY() << "]" << endl; + cout << "Last hop: " << hdrcmn->prev_hop_ << endl; + cout << "Packet ID: " << hdrcmn->uid_ << endl; + } + if (usePromiscuousListening) + { + // route error + maintainRouteTable(pkt); + } + if (this->addr() == larhdr->destinationID()) + { + routeErrorsRx++; + // this route error message is for me and I should initiate another route request + routeRequest(pkt); + return; + } else { // if (this->addr() == larhdr->destinationID()) + // this isn't for me directly, but I must be on the reverse route, so I + // should just forward it to the next destination on the route. + + // I should do this no matter what since I'm on the reverse route + maintainRouteTable(pkt); + nsaddr_t dest = -5; + for (int i=0; ihops(); i++) + { + if (larhdr->route_[i] == this->addr()) + { + // after the find, dest is pointing to my address, so decrement it to + // the previous one in the route + dest = larhdr->route_[i-1]; + break; + } // if (larhdr->route_[i] == this->addr()) + } // for (int i=0; ihops(); i++) + if (LARverbosity > 0) + { + cout << "Forwarding the data packet " << hdrcmn->uid_ + << " upstream to " << dest << endl; + } // if (LARverbosity > 0) + if (dest != -5) + { + larhdr->lastHopX_ = node->X(); + larhdr->lastHopY_ = node->Y(); + this->sendPacket(pkt, dest); + return; + } else { + cerr << "I'm supposed to forward this route error downstream, but I'm not in the" << endl; + cerr << "recorded route! I'm freeing the packet and returning. In route error." << endl; + Packet::free(pkt); + cout << "****************************************************" << endl << endl; + return; + } // if (dest != -5) + } // else of if (this->addr() == larhdr->destinationID()) + } else if (larhdr->larCode() == 'U') { + // there is an error if this happens, but I'm not sure how to + // respond, so it is commented out for now + cerr << "The lar code is unset, so I'm freeing the packet." << endl; + Packet::free(pkt); + return; + } + if (LARverbosity > 0) + { + cout << "Returning from recv at the bottom" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "****************************************************" << endl << endl; + } + + return; +} + +// *********************************************************************** +// maintainRouteTable +// *********************************************************************** +void LARAgent::maintainRouteTable(Packet *p) +{ + // clear all the flags in updatedRoute + map >::iterator flagPtr; + for (flagPtr=updatedRoute.begin(); flagPtr!=updatedRoute.end(); flagPtr++) + { + flagPtr->second = false; + } + // Access the LAR header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + if (LARverbosity > 0) + { + cout << "in maintainRouteTable of = " << this->addr() << endl; + } + int myIndex; + bool myIndexIsInRoute = false; + for (myIndex=0; myIndexhops(); myIndex++) + { + if (larhdr->route_[myIndex] == this->addr()) + { + if (LARverbosity > 0) + { + cout << "Found my address in the route at index " << myIndex << endl; + } + myIndexIsInRoute = true; + break; + } + } + + if (myIndexIsInRoute) + { + map >::iterator destPtr; + nsaddr_t dest; + // ********************************************************** + // route error, invalidate routes + // ********************************************************** + if (larhdr->larCode() == 'E') + { + // this is a route error, so I have to invalidate all the routes from + // me to all the destinations after the break point + int breakIndex; + for (breakIndex=0; breakIndexhops(); breakIndex++) + { + if (larhdr->route_[breakIndex] == routeBreakPoint) + { + break; + } + } + for (int e=(breakIndex+1); ehops(); e++) + { + dest = larhdr->route_[e]; + destPtr = routeTable.find(dest); + if (destPtr != routeTable.end()) + { + destPtr->second.noRoute = true; + updatedRoute[dest] = true; + } + } + } else { + int j, k; + int entries=1; + // ********************************************************** + // update routes going up the route + // ********************************************************** + for (j=(myIndex+1); jhops(); j++) + { + entries++; + dest = larhdr->route_[j]; + destPtr = routeTable.find(dest); + if (destPtr == routeTable.end()) + { + if (LARverbosity > 0) + { + cout << "(up) This route entry didn't exist, creating a new entry for " << dest << endl; + cout << "Route: "; + for (k=0; kroute_[myIndex+k] << " "; + } + cout << endl; + } + // this is a new entry in the route table + larDestType newEntry; + newEntry.x = larhdr->destinationX(); + newEntry.y = larhdr->destinationY(); + newEntry.v = larhdr->destinationSpeed(); + newEntry.method = larhdr->forwardCode(); + + newEntry.hops = entries; + for (k=0; kroute_[myIndex+k]; + } + newEntry.timeOfLastRequest = larhdr->requestSendTime(); + newEntry.timeOfVelocity = larhdr->speedTime(); + newEntry.requestPending = false; + newEntry.noRoute = false; + routeTable[dest] = newEntry; + updatedRoute[dest] = true; + } else { + if (LARverbosity > 0) + { + cout << "(up) This route entry did exist, checking the time stamp." << endl; + cout << "Route: "; + for (k=0; kroute_[myIndex+k] << " "; + } + cout << endl; + } + if (larhdr->speedTime() > destPtr->second.timeOfVelocity) + { + if (LARverbosity > 0) + { + cout << "(up) The time stamp is newer, so I'm using this one." << endl; + } + // this entry existed in the route table and we just need to update the information + destPtr->second.x = larhdr->destinationX(); + destPtr->second.y = larhdr->destinationY(); + destPtr->second.v = larhdr->destinationSpeed(); + destPtr->second.method = larhdr->forwardCode(); + + destPtr->second.hops = entries; + for (k=0; ksecond.route[k] = larhdr->route_[myIndex+k]; + } + destPtr->second.timeOfLastRequest = larhdr->requestSendTime(); + destPtr->second.timeOfVelocity = larhdr->speedTime(); + destPtr->second.requestPending = false; + destPtr->second.noRoute = false; + updatedRoute[dest] = true; + } else { + if (LARverbosity > 0) + { + //cout << "(up) The time stamp is NOT newer, so re-setting the requestPending flag." << endl; + cout << "(up) The time stamp is NOT newer." << endl; + } + //destPtr->second.requestPending = false; + //destPtr->second.noRoute = true; + //updated = false; + } + } + } + + entries=1; + // ********************************************************** + // update routes going down the route + // ********************************************************** + for (j=(myIndex-1); j>=0; j--) + { + entries++; + dest = larhdr->route_[j]; + destPtr = routeTable.find(dest); + if (destPtr == routeTable.end()) + { + if (LARverbosity > 0) + { + cout << "(down) This route entry didn't exist, creating a new entry for " << dest << endl; + cout << "Route: "; + for (k=0; kroute_[myIndex-k] << " "; + } + cout << endl; + } + // this is a new entry in the route table + larDestType newEntry; + newEntry.x = larhdr->destinationX(); + newEntry.y = larhdr->destinationY(); + newEntry.v = larhdr->destinationSpeed(); + newEntry.method = larhdr->forwardCode(); + + newEntry.hops = entries; + for (k=0; kroute_[myIndex-k]; + } + newEntry.timeOfLastRequest = larhdr->requestSendTime(); + newEntry.timeOfVelocity = larhdr->speedTime(); + newEntry.requestPending = false; + newEntry.noRoute = false; + routeTable[dest] = newEntry; + updatedRoute[dest] = true; + } else { + if (LARverbosity > 0) + { + cout << "(down) This route entry did exist, checking the time stamp." << endl; + cout << "Route: "; + for (k=0; kroute_[myIndex-k] << " "; + } + cout << endl; + } + if (larhdr->speedTime() > destPtr->second.timeOfVelocity) + { + if (LARverbosity > 0) + { + cout << "(down) The time stamp is newer, so I'm using this one." << endl; + } + // this entry existed in the route table and we just need to update the information + destPtr->second.x = larhdr->destinationX(); + destPtr->second.y = larhdr->destinationY(); + destPtr->second.v = larhdr->destinationSpeed(); + destPtr->second.method = larhdr->forwardCode(); + + destPtr->second.hops = entries; + for (k=0; ksecond.route[k] = larhdr->route_[myIndex-k]; + } + destPtr->second.timeOfLastRequest = larhdr->requestSendTime(); + destPtr->second.timeOfVelocity = larhdr->speedTime(); + destPtr->second.requestPending = false; + destPtr->second.noRoute = false; + updatedRoute[dest] = true; + } else { + if (LARverbosity > 0) + { + //cout << "(down) The time stamp is NOT newer, so re-setting the requestPending flag." << endl; + cout << "(down) The time stamp is NOT newer." << endl; + } + //destPtr->second.requestPending = false; + //destPtr->second.noRoute = true; + //updated = false; + } + } + } + } + } + + return; +} + +// *********************************************************************** +// sendRouteReply +// *********************************************************************** +void LARAgent::sendRouteReply(Packet *p) +{ + // Access the common header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + struct hdr_cmn* hdrcmn = hdr_cmn::access(p); + + // old way to do this + //hdr_cmn* hdrcmn = (hdr_cmn*)p->access(off_cmn_); + // Access the LAR header for the received packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + nsaddr_t dest = larhdr->destinationID(); + map >::iterator destPtr; + destPtr = routeTable.find(dest); + if (destPtr->second.timeOfVelocity > larhdr->speedTime()) + { + if (larhdr->hops() <= 1) + { + oneHopRtReqRx++; + } + // I need to reply with a route reply + // Create a new packet + Packet* newpkt = allocpkt(); + // Access the headers for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* newlarhdr = hdr_lar::access(newpkt); + struct hdr_cmn* newhdrcmn = hdr_cmn::access(newpkt); + + // old way to do this + //hdr_lar* newlarhdr = (hdr_lar*)newpkt->access(off_lar_); + //hdr_cmn* newhdrcmn = (hdr_cmn*)newpkt->access(off_cmn_); + + newlarhdr->larCode_ = 'A'; + newlarhdr->forwardCode_ = larhdr->forwardCode(); + newlarhdr->sourceX_ = larhdr->sourceX_; + newlarhdr->sourceY_ = larhdr->sourceY_; + newlarhdr->lastHopX_ = node->X(); + newlarhdr->lastHopY_ = node->Y(); + newlarhdr->destinationX_ = destPtr->second.x; + newlarhdr->destinationY_ = destPtr->second.y; + newlarhdr->destinationID_ = larhdr->route_[0]; + newlarhdr->sendTime_ = Scheduler::instance().clock(); + newlarhdr->newPkt_ = true; + newlarhdr->destinationSpeed_ = destPtr->second.v; + newlarhdr->speedTime_ = destPtr->second.timeOfVelocity; + + // first, check to see if the route I have for the required destination + // contains the requesting node + int i; + int srcIndex = -5; + nsaddr_t srcID = larhdr->route_[larhdr->hops()-1]; + for (i=0; isecond.hops; i++) + { + if (destPtr->second.route[i] == larhdr->route_[0]) + { + srcIndex = i; + break; + } + } + //if (i==destPtr->second.hops) + if (srcIndex == -5) + { + // the requesting node didn't exist in the route + newlarhdr->hops() = destPtr->second.hops + larhdr->hops(); + int j; + // puts the route that the join request took in the route + for (j=0; jhops(); j++) + { + newlarhdr->route_[j] = larhdr->route_[j]; + } + // puts the route from the route table on the end + for (j=0; jsecond.hops; j++) + { + newlarhdr->route_[j+larhdr->hops()] = destPtr->second.route[j]; + } + } else { + int j=0; + // the requesting node did exist in the route + newlarhdr->hops() = destPtr->second.hops - srcIndex; + for (i=srcIndex; isecond.hops; i++, j++) + { + newlarhdr->route_[j] = destPtr->second.route[i]; + } + } + + newlarhdr->requestID_ = hdrcmn->uid_; + newlarhdr->requestSendTime_ = larhdr->requestSendTime(); + newlarhdr->dataLength_ = 0; + if (LARverbosity > 0) + { + cout << "Sending a Route Reply, ID: " << newhdrcmn->uid_ + << " to " << srcID << endl; + } + //this->broadcastPacket(newpkt); + // Don't want to rebroadcast, want send it to my "upstream" neighbor + + this->sendPacket(newpkt, srcID); + } + return; +} + +// *********************************************************************** +// sendNewData +// *********************************************************************** +void LARAgent::sendNewData(Packet *p, nsaddr_t destID) +{ + // Access the common header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + struct hdr_cmn* hdrcmn = hdr_cmn::access(p); + + // old way to do this + //hdr_cmn* hdrcmn = (hdr_cmn*)p->access(off_cmn_); + + // Access the LAR header for the received packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + node->update_position(); + + map >::iterator destPtr; + destPtr = routeTable.find(destID); + if (destPtr == routeTable.end()) + { + // there is no entry for this destination in the route table + // we need to create a routing table entry with the requestPending + // field set, perform a route request, and put this packet on the + // pending list + + // this is a new entry in the route table + larDestType newEntry; + newEntry.x = -1.0; + newEntry.y = -1.0; + newEntry.v = -1.0; + newEntry.method = larhdr->forwardCode(); + newEntry.hops = 0; + for (int k=0; k 0) + { + cout << "****************************************************" << endl; + cout << "Sending lar route request from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + } + this->sendInitialRouteRequest(destID, &newEntry); + + // put the data packet on the pending list + this->addToPendingPackets(p); + } else if (destPtr->second.requestPending) { + // there is already a route entry for this destination, but we need to check and see if + // there is a pending request + if (LARverbosity > 0) + { + cout << "****************************************************" << endl; + cout << "There is already a pending route request for this destination: " << destID << endl; + cout << "Putting the data packet on the pending packet list. Packet ID: " << hdrcmn->uid_ << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + } + // put the data packet on the pending list + this->addToPendingPackets(p); + + } else if (destPtr->second.noRoute) { + // there is a routing entry, but I still haven't been able to find a route, so I need + // to initiate another route request + destPtr->second.requestPending = true; + + // send it out + if (LARverbosity > 0) + { + cout << "****************************************************" << endl; + cout << "There is a route entry, but no route..." << endl; + cout << "Sending lar route request from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + } + this->sendInitialRouteRequest(destID, &(destPtr->second)); + + // put the data packet on the pending list + this->addToPendingPackets(p); + } else { +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// I may want to check the route table time stamp against the route time stamp +// in the header here, but I'm not sure what to do if the route I have is older, +// or if it actually matters... +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // we can fill in the rest of the header fields from the routing + // table and send this packet + larhdr->destinationX_ = destPtr->second.x; + larhdr->destinationY_ = destPtr->second.y; + larhdr->destinationSpeed_ = destPtr->second.v; + larhdr->speedTime_ = destPtr->second.timeOfVelocity; + larhdr->requestSendTime_ = destPtr->second.timeOfLastRequest; + larhdr->hops_ = destPtr->second.hops; + for (int k=0; ksecond.hops; k++) + { + larhdr->route_[k] = destPtr->second.route[k]; + } + // send it out + if (LARverbosity > 0) + { + cout << "****************************************************" << endl; + cout << "Sending lar data from: " << this->addr() + << " at [" << node->X() << "," << node->Y() << "]" << endl; + cout << "Time: " << Scheduler::instance().clock() << endl; + cout << "Data size: " << larhdr->dataLength() << endl; + cout << "Total size: " << larhdr->size() << endl; + } + this->sendPacket(p, destPtr->second.route[1]); + } + if (LARverbosity > 0) + { + cout << "****************************************************" << endl << endl; + } + return; +} + +// *********************************************************************** +// routeRequest +// *********************************************************************** +void LARAgent::routeRequest(Packet *p) +{ + // Access the LAR header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + // The destination for the route request is the last one in the source route + nsaddr_t dest = larhdr->route_[larhdr->hops()-1]; + + map >::iterator destPtr; + destPtr = routeTable.find(dest); + if (destPtr == routeTable.end()) + { + // I think this shouldn't happen, but I put it in just in case... + // this is a new entry in the route table + larDestType newEntry; + newEntry.x = -1.0; + newEntry.y = -1.0; + newEntry.v = -1.0; + newEntry.method = larhdr->forwardCode(); + newEntry.hops = 0; + for (int k=0; ksendInitialRouteRequest(dest, &(newEntry)); + } else { + if (LARverbosity > 0) + { + cout << "This route error is from a data packet I generated." << endl; + cout << "Creating a route request to refresh the route." << endl; + } + // switch the routing table entry to pending, and set the noRoute flag + destPtr->second.requestPending = true; + destPtr->second.noRoute = true; + + // for now, the data packet that generated the route error is lost. + // another option would be to return it with/after the route error and I + // could put it in the pending packet list here + + this->sendRouteRequest(dest, larhdr->forwardCode(), &(destPtr->second), useRingZeroSearch); + } // else of if (destPtr == routeTable.end()) + + //Packet::free(p); + return; +} + +// *********************************************************************** +// subRoute +// *********************************************************************** +bool LARAgent::subRoute(larDestType *rt, Packet *p) +{ + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + int i, j; + bool within = false; + + if (larhdr->hops() < rt->hops) + { + return false; + } + for (i=0; ihops(); i++) + { + for (j=0; jhops; j++) + { + if (rt->route[j] != larhdr->route_[i+j]) + { + break; + } + } + if (j == rt->hops) + { + return true; + } + } + + return within; +} + +// *********************************************************************** +// routeError +// *********************************************************************** +void LARAgent::routeError(Packet *p) +{ + if (LARverbosity > 0) + { + cout << "Route Error Detected!" << endl; + cout << "at node: " << this->addr() << endl; + } + // this is called by the route error callback and should create a route + // error message and send it upstream to the originator of the data packet + // Access the common header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(p); + struct hdr_cmn* hdrcmn = hdr_cmn::access(p); + + // old way to do this + //hdr_cmn* hdrcmn = (hdr_cmn*)p->access(off_cmn_); + + // Access the LAR header for the received packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + node->update_position(); + + if (this->addr() == larhdr->route_[0]) + { + if (LARverbosity > 0) + { + cout << "This is a first hop error. Sending a route request" << endl; + } + // this is a first hop route error and means I should initiate a route request + + //cerr << "I just got a routeError callback and I originated the packet!" << endl; + //cerr << "Packet ID: " << hdrcmn->uid_ << endl; + srcRtErrors++; + // since this is a first hop route error, I can put the data packet on the pending list + this->addToPendingPackets(p); + routeRequest(p); + + return; + } else { + if (useIntermediateRouteRepair) + { + if (LARverbosity > 0) + { + cout << "Performing intermediate route repair and sending a route error." << endl; + } + // Create a new packet + Packet* dataPkt = allocpkt(); + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* newlarhdr = hdr_lar::access(dataPkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(dataPkt); + + // old way to do this + //hdr_lar* newlarhdr = (hdr_lar*)dataPkt->access(off_lar_); + + //hdr_cmn* hdrcmn = (hdr_cmn*)dataPkt->access(off_cmn_); + hdrcmn->xmit_failure_ = larRouteErrorCallback; + hdrcmn->xmit_failure_data_ = (void *) this; + + // Store the current time in the 'send_time' field + newlarhdr->sendTime_ = larhdr->sendTime(); + + newlarhdr->larCode_ = 'D'; + newlarhdr->forwardCode_ = larhdr->forwardCode(); + //cout << "forwardCode = " << larhdr->forwardCode() << endl; + newlarhdr->sourceX_ = larhdr->sourceX(); + newlarhdr->sourceY_ = larhdr->sourceY(); + newlarhdr->lastHopX_ = node->X(); + newlarhdr->lastHopY_ = node->Y(); + newlarhdr->destinationID_ = larhdr->destinationID(); + newlarhdr->dataLength_ = larhdr->dataLength(); + newlarhdr->newPkt_ = false; + + newlarhdr->requestID_ = 0; + newlarhdr->requestSendTime_ = 0; + if (dropIntermediatePacketsIfNoRoute) + { + map >::iterator destPtr; + destPtr = routeTable.find(larhdr->destinationID()); + // again, this depends on short circuit boolean... +/* + if ((destPtr != routeTable.end()) && (!destPtr->second.requestPending) && \ + (!destPtr->second.noRoute) && (destPtr->second.timeOfVelocity > larhdr->speedTime())) +*/ + if ((destPtr != routeTable.end()) && (!subRoute(&(destPtr->second),p))) + { + if (LARverbosity > 0) + { + cout << "Found a new route at (" << this->addr() << "). Adding it and forwarding the packet." << endl; + cout << "\tOld Route: " << flush; + int q; + for (q=0; qhops(); q++) + { + cout << larhdr->route_[q] << " " << flush; + } + cout << endl << "\tMy Route: " << flush; + for (q=0; qsecond.hops; q++) + { + cout << destPtr->second.route[q] << " " << flush; + } + cout << endl; + } + if (LARverbosity > 0) + { + cout << "\t\tNot a sub route!" << endl; + } + sendNewData(dataPkt, larhdr->destinationID()); + } else { + if (LARverbosity > 0) + { + cout << "Tried to do intermediate route repair, but had to" + << " drop the packet because there is no route." << endl; + } + if (destPtr != routeTable.end()) + { + if (LARverbosity > 0) + { + // I can set no route since I know my information is older... + cout << "\t\tIs a sub route!" << endl; + cout << "Setting the route to no route." << endl; + } + destPtr->second.noRoute = true; + } + // not going to use the packet I created above + Packet::free(dataPkt); + } + } else { + if (LARverbosity > 0) + { + cout << "Don't care if there is a route or not, trying to save the packet" << endl; + cout << "no matter what." << endl; + } + sendNewData(dataPkt, larhdr->destinationID()); + } + } else { + if (LARverbosity > 0) + { + cout << "Not doing intermediate route repair, dropping the data packet and sending a route error." << endl; + } + } + // This is not a first hop route error, so I should send back a route error packet + + // Create a new route error packet + Packet* errorPkt = allocpkt(); + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larErrHdr = hdr_lar::access(errorPkt); + + // old way to do this + //hdr_lar* larErrHdr = (hdr_lar*)errorPkt->access(off_lar_); + + // Store the current time in the 'send_time' field + larErrHdr->sendTime_ = Scheduler::instance().clock(); + + larErrHdr->larCode_ = 'E'; + larErrHdr->forwardCode_ = larhdr->forwardCode_; + larErrHdr->sourceX_ = node->X(); + larErrHdr->sourceY_ = node->Y(); + larErrHdr->lastHopX_ = node->X(); + larErrHdr->lastHopY_ = node->Y(); + larErrHdr->destinationX_ = larhdr->sourceX(); + larErrHdr->destinationY_ = larhdr->sourceY(); + larErrHdr->destinationID_ = larhdr->route_[0]; + larErrHdr->destinationSpeed_ = 0; + larErrHdr->speedTime_ = 0; + larErrHdr->hops() = larhdr->hops(); + larErrHdr->dataLength_ = 0; + larErrHdr->newPkt_ = true; + + larErrHdr->requestID_ = hdrcmn->uid_; + larErrHdr->requestSendTime_ = larhdr->requestSendTime_; + + // copy the source route into the route error packet route. Just an + // important note here, the route in the error packet is "backwards". + // Instead of reversing the route, I use it from end to beginning... + nsaddr_t dest = -5; + if (LARverbosity > 0) + { + cout << "Route: " << flush; + } + for (int k=0; khops(); k++) + { + if (LARverbosity > 0) + { + cout << larhdr->route_[k] << " " << flush; + } + larErrHdr->route_[k] = larhdr->route_[k]; + if (this->addr() == larhdr->route_[k]) + { + larErrHdr->route_[k] = routeBreakPoint; + dest = larhdr->route_[k-1]; + } + } + routeErrorsGen++; + if (LARverbosity > 0) + { + cout << endl; + + cout << "Creating a route error and sending to: " << dest << endl; + } + if (dest != -5) + { + this->sendPacket(errorPkt, dest); + } else { + cerr << "There should be an error packet send to the upstream neighbor," << endl + << "but I can't find my address in the route." << endl; + cerr << "I'm going to broadcast it instead." << endl; + larErrHdr->forwardCode_ = 'F'; + this->broadcastPacket(errorPkt); + } + Packet::free(p); + } + + return; +} + +// *********************************************************************** +// sendInitialRouteRequest +// *********************************************************************** +int LARAgent::sendInitialRouteRequest(nsaddr_t id, larDestType *routeEntry) +{ + if (useRingZeroSearch) + { + oneHopRtReqTx++; + } else { + floodRtReqTx++; + if (LARverbosity > 0) + { + cout << "In sendInitialRouteRequest, flooding the first route request." << endl; + } + } + node->update_position(); + + // add/find a timer for this destination that purges the pending packets if it times out + map >::iterator timerPtr; + timerPtr = timers.find(id); + if (timerPtr == timers.end()) + { + if (useRingZeroSearch) + { + timers[id] = new LARRouteRequestTimer (this, id, 1, routeEntry, 'F'); + timers[id]->sched(ringZeroWait); + } else { + timers[id] = new LARRouteRequestTimer (this, id, 0, routeEntry, 'F'); + timers[id]->sched(LARrouteRequestTimeout); + } + } else { + timerPtr->second->setForwardMethod('F'); + timerPtr->second->setRouteInfo(routeEntry); + if (useRingZeroSearch) + { + timerPtr->second->setTriesLeft(1); + timerPtr->second->resched(ringZeroWait); + } else { + timerPtr->second->setTriesLeft(0); + timerPtr->second->resched(LARrouteRequestTimeout); + } + } + + // Create a new route request packet + Packet* requestPkt = allocpkt(); + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larReqHdr = hdr_lar::access(requestPkt); + struct hdr_cmn* requestHdrCmn = hdr_cmn::access(requestPkt); + + // old way to do this + //hdr_lar* larReqHdr = (hdr_lar*)requestPkt->access(off_lar_); + larReqHdr->hops() = 0; + //hdr_cmn* requestHdrCmn = (hdr_cmn*)requestPkt->access(off_cmn_); + + // Store the current time in the 'send_time' field + larReqHdr->sendTime_ = Scheduler::instance().clock(); + + larReqHdr->larCode_ = 'R'; + if (useRingZeroSearch) + { + larReqHdr->forwardCode_ = 'N'; + } else { + // all initial requests must flood!! + larReqHdr->forwardCode_ = 'F'; + } + larReqHdr->sourceX_ = node->X(); + larReqHdr->sourceY_ = node->Y(); + larReqHdr->lastHopX_ = node->X(); + larReqHdr->lastHopY_ = node->Y(); + larReqHdr->destinationX_ = 0; + larReqHdr->destinationY_ = 0; + larReqHdr->destinationID_ = id; + larReqHdr->destinationSpeed_ = 0; + larReqHdr->speedTime_ = 0; + larReqHdr->hops()++; + larReqHdr->dataLength_ = 0; + larReqHdr->newPkt_ = true; + + larReqHdr->requestID_ = requestHdrCmn->uid_; + larReqHdr->requestSendTime_ = larReqHdr->sendTime_; + + larReqHdr->route_[0] = this->addr(); + for (int k=1; kroute_[k] = -1; + } + + this->broadcastPacket(requestPkt); + + return requestHdrCmn->uid_; +} + +// *********************************************************************** +// sendRouteRequest +// *********************************************************************** +int LARAgent::sendRouteRequest(nsaddr_t id, char fwdCode, larDestType *routeEntry, bool ringZero) +{ + node->update_position(); + + if (LARverbosity > 0) + { + cout << "In sendRouteRequest and fwdCode = " << fwdCode << endl; + } + map >::iterator timerPtr; + timerPtr = timers.find(id); + if ((fwdCode == 'B') || (fwdCode == 'S')) + { + // add a timer for this destination in case we have to flood the route request + if (timerPtr == timers.end()) + { + if (ringZero) + { + timers[id] = new LARRouteRequestTimer (this, id, 2, routeEntry, fwdCode); + timers[id]->sched(ringZeroWait); + oneHopRtReqTx++; + } else { + timers[id] = new LARRouteRequestTimer (this, id, 1, routeEntry, 'F'); + timers[id]->sched(LARrouteRequestTimeout); + larRtReqTx++; + } + } else { + timerPtr->second->setRouteInfo(routeEntry); + if (ringZero) + { + timerPtr->second->setForwardMethod(fwdCode); + timerPtr->second->setTriesLeft(2); + timerPtr->second->resched(ringZeroWait); + oneHopRtReqTx++; + } else { + timerPtr->second->setForwardMethod('F'); + timerPtr->second->setTriesLeft(1); + timerPtr->second->resched(LARrouteRequestTimeout); + larRtReqTx++; + } + } + } else { + // add a timer for this destination that purges the pending packets if it times out + if (timerPtr == timers.end()) + { + timers[id] = new LARRouteRequestTimer (this, id, 0, routeEntry, 'F'); + timers[id]->sched(LARrouteRequestTimeout); + } else { + timerPtr->second->setForwardMethod('F'); + timerPtr->second->setTriesLeft(0); + timerPtr->second->setRouteInfo(routeEntry); + timerPtr->second->resched(LARrouteRequestTimeout); + } + floodRtReqTx++; + } + + // Create a new route request packet + Packet* requestPkt = allocpkt(); + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larReqHdr = hdr_lar::access(requestPkt); + struct hdr_cmn* requestHdrCmn = hdr_cmn::access(requestPkt); + + // old way to do this + //hdr_lar* larReqHdr = (hdr_lar*)requestPkt->access(off_lar_); + larReqHdr->hops() = 0; + //hdr_cmn* requestHdrCmn = (hdr_cmn*)requestPkt->access(off_cmn_); + + // Store the current time in the 'send_time' field + larReqHdr->sendTime_ = Scheduler::instance().clock(); + + larReqHdr->larCode_ = 'R'; + if (ringZero) + { + larReqHdr->forwardCode_ = 'N'; + } else { + larReqHdr->forwardCode_ = fwdCode; + } + larReqHdr->sourceX_ = node->X(); + larReqHdr->sourceY_ = node->Y(); + larReqHdr->lastHopX_ = node->X(); + larReqHdr->lastHopY_ = node->Y(); + larReqHdr->destinationX_ = routeEntry->x; + larReqHdr->destinationY_ = routeEntry->y; + larReqHdr->destinationID_ = id; + larReqHdr->destinationSpeed_ = routeEntry->v; + larReqHdr->speedTime_ = routeEntry->timeOfVelocity; + larReqHdr->hops()++; + larReqHdr->dataLength_ = 0; + larReqHdr->newPkt_ = true; + + larReqHdr->requestID_ = requestHdrCmn->uid_; + larReqHdr->requestSendTime_ = larReqHdr->sendTime_; + + larReqHdr->route_[0] = this->addr(); + for (int k=1; kroute_[k] = -1; + } + + larReqHdr->requestID_ = requestHdrCmn->uid_; + larReqHdr->requestSendTime_ = larReqHdr->sendTime_; + + this->broadcastPacket(requestPkt); + + return requestHdrCmn->uid_; +} + +// *********************************************************************** +// clearRequestPending +// *********************************************************************** +void LARAgent::clearRequestPending(nsaddr_t id) +{ + map >::iterator destPtr; + destPtr = routeTable.find(id); + if (destPtr == routeTable.end()) + { + cerr << "Trying to clear a request pending flag in the route table and can't" << endl + << "find the corresponding routing entry for node: " << id << endl; + } else { + destPtr->second.requestPending = false; + } + + return; +} + +// *********************************************************************** +// addToPendingPackets +// *********************************************************************** +void LARAgent::addToPendingPackets(Packet *p) +{ + int amountToDump = pendingPackets.size() - pendingPacketQueueLength + 1; + // the "magic" + 1 is to make room for the packet we + // need to add + // if there are fewer packets on the queue than the max length, then + // this number will be negative and the loop will never execute + + for (int i=0; i 0) + { + cout << "Dropping a packet due to send queue overflow." << endl; + } + pendingPackets.pop_front(); + } + pendingPackets.push_back(p); + + return; +} + +// *********************************************************************** +// checkPendingQueueForPackets +// *********************************************************************** +void LARAgent::checkPendingQueueForPackets(nsaddr_t id) +{ + bool packetsLeftInQueue = false; + list::iterator pendingPtr; + for (pendingPtr=pendingPackets.begin(); pendingPtr!=pendingPackets.end(); /* nothing */) + { + // new way to do this (2.1b7 and later) + struct hdr_lar* pendinglarhdr = hdr_lar::access((*pendingPtr)); + + // old way to do this + //hdr_lar* pendinglarhdr = (hdr_lar*)(*pendingPtr)->access(off_lar_); + if (pendinglarhdr->destinationID() == id) + { + packetsLeftInQueue = true; + break; + } + } + if (packetsLeftInQueue) + { + map >::iterator destPtr; + destPtr = routeTable.find(id); + if (destPtr == routeTable.end()) + { + // this is a new entry in the route table, and it shouldn't be at this point! +cerr << "There is a pending packet on the pending packet" + << " queue without a route table entry! (addr=" + << this->addr() << ") (id=" << id << ")" << endl; + larDestType newEntry; + newEntry.x = -1.0; + newEntry.y = -1.0; + newEntry.v = -1.0; + newEntry.method = 'F'; + newEntry.hops = 0; + for (int k=0; ksecond.method = 'F'; + destPtr->second.requestPending = false; + destPtr->second.noRoute = true; + updatedRoute[id] = true; + + // reschedule a timer to timeout and restart the route request process + map >::iterator timerPtr; + timerPtr = timers.find(id); + if (timerPtr == timers.end()) + { + // I really hope this doesn't happen, because it means that something + // serious went wrong and there isn't already a timer for this destination + //if (useRingZeroSearch) + //{ + //timers[id] = new LARRouteRequestTimer (this, id, 1, routeEntry, 'F'); + //timers[id]->sched(ringZeroWait); + //} else { +cerr << "There is a problem. I'm trying to fall back to persitent route request" << endl + << "mode, and there is not a timer for this node! (addr=" + << this->addr() << ") (id=" << id << ")" << endl; + timers[id] = new LARRouteRequestTimer (this, id, 1, &(destPtr->second), 'F'); + timers[id]->sched(LARroutePersistenceTimeout); + //} + } else { + timerPtr->second->setForwardMethod('F'); + timerPtr->second->setRouteInfo(&(destPtr->second)); + //if (useRingZeroSearch) + //{ + //timerPtr->second->setTriesLeft(1); + //timerPtr->second->resched(ringZeroWait); + //} else { + timerPtr->second->setTriesLeft(1); + timerPtr->second->resched(LARroutePersistenceTimeout); + //} + } + } + return; +} + +// *********************************************************************** +// purgePendingPacketsFor +// *********************************************************************** +void LARAgent::purgePendingPacketsFor(nsaddr_t id) +{ + int i = 1; + double time = Scheduler::instance().clock(); + + list::iterator pendingPtr; + for (pendingPtr=pendingPackets.begin(); pendingPtr!=pendingPackets.end(); /* nothing */) + { + // new way to do this (2.1b7 and later) + struct hdr_lar* pendinglarhdr = hdr_lar::access((*pendingPtr)); + + // old way to do this + //hdr_lar* pendinglarhdr = (hdr_lar*)(*pendingPtr)->access(off_lar_); + if (pendinglarhdr->destinationID() == id) + { + if (fabs(time - pendinglarhdr->sendTime()) > dropPendingPacketsAfter) + { + if (pendinglarhdr->newPkt()) + { + dataDroppedSrc++; + } else { + dataDroppedInt++; + } + if (LARverbosity > 0) + { + // new way to do this (2.1b7 and later) + struct hdr_cmn* hdrCmn = hdr_cmn::access((*pendingPtr)); + + // old way to do this + //hdr_cmn* hdrCmn = (hdr_cmn*)(*pendingPtr)->access(off_cmn_); + cout << "Deleting pending packet " << i++ << " ID: " << hdrCmn->uid_ << endl; + } + pendingPackets.erase(pendingPtr++); + } else { + pendingPtr++; + } + } else { + pendingPtr++; + } + } + + return; +} + +// *********************************************************************** +// purgeAllPendingPackets +// *********************************************************************** +void LARAgent::purgeAllPendingPackets() +{ + int i = 1; + list::iterator pendingPtr; + for (pendingPtr=pendingPackets.begin(); pendingPtr!=pendingPackets.end(); /* nothing */) + { + // new way to do this (2.1b7 and later) + struct hdr_lar* pendinglarhdr = hdr_lar::access((*pendingPtr)); + + // old way to do this + //hdr_lar* pendinglarhdr = (hdr_lar*)(*pendingPtr)->access(off_lar_); + if (pendinglarhdr->newPkt()) + { + dataDroppedSrc++; + } else { + dataDroppedInt++; + } + droppedAtEnd++; + if (LARverbosity > 0) + { + // new way to do this (2.1b7 and later) + struct hdr_cmn* hdrCmn = hdr_cmn::access((*pendingPtr)); + + // old way to do this + //hdr_cmn* hdrCmn = (hdr_cmn*)(*pendingPtr)->access(off_cmn_); + cout << "Deleting pending packet " << i++ << " ID: " << hdrCmn->uid_ << endl; + } + pendingPackets.erase(pendingPtr++); + } + return; +} + +// *********************************************************************** +// dupRcvdPacket +// *********************************************************************** +bool LARAgent::dupRcvdPacket(int id) +{ + // I may need to limit the size of this in the future. + if (rcvdPackets.find(id) != rcvdPackets.end()) + { + return true; + } else { + rcvdPackets.insert(id); + return false; + } +} + +// *********************************************************************** +// dupSentPacket +// *********************************************************************** +bool LARAgent::dupSentPacket(int id) +{ + // I may need to limit the size of this in the future. + if (sentPackets.find(id) != sentPackets.end()) + { + return true; + } else { + sentPackets.insert(id); + return false; + } +} + +// *********************************************************************** +// inForwardingRegion +// *********************************************************************** +bool LARAgent::inForwardingRegion(char fwdCode, + double srcX, double srcY, + double destX, double destY, + double destSpeed, double speedTime) +{ + node->update_position(); + if (fwdCode == 'F') + { +//cout << "One " << endl; + return true; + } else if (fwdCode == 'N') { + return false; + } else if (fwdCode == 'B') { +//cout << "Two " << endl; + double delta = fabs(Scheduler::instance().clock() - speedTime); + double radius = destSpeed * delta; + double llx, lly, urx, ury; + + if (srcX < destX) + { + llx = lar_min(srcX, (destX-radius)); + urx = destX + radius; + } else { + llx = destX - radius; + urx = lar_max(srcX, (destX+radius)); + } + if (srcY < destY) + { + lly = lar_min(srcY, (destY-radius)); + ury = destY + radius; + } else { + lly = destY - radius; + ury = lar_max(srcY, (destY+radius)); + } + + if ((node->X() >= (llx-LARDelta)) && (node->X() <= (urx+LARDelta)) && + (node->Y() >= (lly-LARDelta)) && (node->Y() <= (ury+LARDelta))) + { + return true; + } else { + return false; + } + } else if (fwdCode == 'S') { +//cout << "Three " << endl; + double lastHopDistSquared = (srcX-destX)*(srcX-destX) + (srcY-destY)*(srcY-destY); + double myDistSquared = (node->X()-destX)*(node->X()-destX) + (node->Y()-destY)*(node->Y()-destY); + //cout << "lastHopDistSquared = " << lastHopDistSquared << endl; + //cout << "myDistSquared = " << myDistSquared << endl; + //cout << "LARDelta = " << LARDelta << endl; + return (myDistSquared <= (lastHopDistSquared + (LARDelta)*(LARDelta))); + } else { + cerr << "inForwardingRegion and the forward code is not set!" << endl; + return false; + } +} + +// *********************************************************************** +// recordSentPacket +// *********************************************************************** +void LARAgent::recordSentPacket(int id) +{ + sentPackets.insert(id); + return; +} + +// *********************************************************************** +// recordRcvdPacket +// *********************************************************************** +void LARAgent::recordRcvdPacket(int id) +{ + rcvdPackets.insert(id); + return; +} + +void LARprintHeaders(Packet *p) +{ + // Access the LAR header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + struct hdr_ip* iphdr = hdr_ip::access(p); + struct hdr_mac* machdr = hdr_mac::access(p); + + // old way to do this + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + // Access the common header for the new packet: + //hdr_cmn* cmnhdr = (hdr_cmn*)p->access(hdr_cmn::offset()); + + // Access the IP header for the new packet: + //hdr_ip* iphdr = (hdr_ip*)p->access(hdr_ip::offset()); + + // Access the mac header for the new packet: + //hdr_mac* machdr = (hdr_mac*)p->access(hdr_mac::offset()); + + cout << "IP Header Information:" << endl; + cout << "\tSrc Address: " << iphdr->saddr() << endl; + cout << "\tSrc Port: " << iphdr->sport() << endl; + cout << "\tDest Address: " << iphdr->daddr() << endl; + cout << "\tDest Port: " << iphdr->dport() << endl; + cout << "\tTTL: " << iphdr->ttl() << endl; + + cout << endl << "Common Header Information:" << endl; + cout << "\tPacket Type: " << p_info().name(cmnhdr->ptype()) << endl; +// cout << "\tPacket Type: " << cmnhdr->ptype() << endl; + cout << "\tSize: " << cmnhdr->size() << endl; + cout << "\tUID: " << cmnhdr->uid() << endl; + cout << "\terror: " << cmnhdr->error() << endl; + cout << "\ttimestamp: " << cmnhdr->timestamp() << endl; + cout << "\tinterface: " << cmnhdr->iface() << endl; + cout << "\tDirection: " << cmnhdr->direction() << endl; + // cout << "\tref count: " << cmnhdr->ref_count() << endl; + cout << "\tprev hop: " << cmnhdr->prev_hop_ << endl; + cout << "\tnext hop: " << cmnhdr->next_hop() << endl; + cout << "\taddress type: " << cmnhdr->addr_type() << endl; + cout << "\tlast hop: " << cmnhdr->last_hop_ << endl; + cout << "\tnum forwards: " << cmnhdr->num_forwards() << endl; + cout << "\topt forwards: " << cmnhdr->opt_num_forwards() << endl; + + cout << endl << "MAC Header Information:" << endl; + cout << "\tSrc Address: " << machdr->macSA() << endl; + cout << "\tDest Address: " << machdr->macDA() << endl; + + return; +} + +// *********************************************************************** +// sendPacket +// *********************************************************************** +void LARAgent::sendPacket(Packet *p, nsaddr_t to) +{ + // Access the common header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + struct hdr_ip* iphdr = hdr_ip::access(p); + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_cmn* cmnhdr = (hdr_cmn*)p->access(off_cmn_); + + // Access the IP header for the new packet: + //hdr_ip* iphdr = (hdr_ip*)p->access(off_ip_); + + // Access the lar header for the new packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + //LARprintHeaders(p); + + // Update performance tracking variables + if (larhdr->larCode() == 'D') + { + if ((larhdr->route_[0] == this->addr()) && (larhdr->newPkt())) + { + // I originated this data packet and it is a new one not an + // intermediate reforward + dataTxPkts++; + dataTxBytes += larhdr->dataLength(); + } else { + // this is a data packet and I'm just forwarding it along because + // I'm on the route + dataTxPktsFwd++; + dataTxBytesFwd += larhdr->dataLength(); + } + // count all header bytes, even those on data as control overhead + protocolTxBytes += larhdr->headerLength(); + } else { + // all other packets being sent by this agent at this layer are + // protocol packets, either route request, reply, or error + protocolTxPkts++; + protocolTxBytes += larhdr->headerLength(); + } + + // set all the necessary things for the common header + cmnhdr->next_hop_ = to; + cmnhdr->prev_hop_ = this->addr(); + //cmnhdr->next_hop_ = 1; + //cmnhdr->iface() = iface_literal::ANY_IFACE; // any interface + cmnhdr->direction() = hdr_cmn::DOWN; // hopefully send it out + //cmnhdr->direction() = hdr_cmn::UP; + + // now the ip header stuff + iphdr->saddr() = this->addr(); + iphdr->sport() = 254; + iphdr->daddr() = to; + //iphdr->daddr() = 1; + iphdr->dport() = 254; + //iphdr->dport() = 255; // router port + iphdr->ttl() = 32; + + //cout << endl << "After Modification" << endl; + //LARprintHeaders(p); + + // Send the packet + recordSentPacket(cmnhdr->uid_); + //cout << "LAR: Sending a packet..." << endl; + + // The next three lines should all be equivilant ways to send a packet, + // I'm just trying them all to get the broadcast to go. + //send(p, 0); + //send(p, ll); + //target_->recv(p, (Handler*) 0); + //Scheduler::instance().schedule(target_,p,0); + + double jitter = 0.0; + if (LARuseJitteronSend) + { + // this one is different and was taken from dsragent::sendOutBCastPkt + // I had to add a little jitter because it turned out that neighboring nodes + // where re-broadcasting in the simulator at "exactly" the same time and + // killing each other's transmissions. + jitter = ((double)rand()/(double)RAND_MAX) / larJitter; + } else { + jitter = 0.0; + } + + if (LARverbosity > 0) + { + cout << "Scheduling the packet for delivery: " << cmnhdr->uid_ + << " with jitter=" << jitter << endl; + cout << "Really sending at: " << Scheduler::instance().clock() + jitter << endl; + cout << "Common header size: " << cmnhdr->size_ << endl; + } + cmnhdr->size_ = larhdr->size(); + if (LARverbosity > 0) + { + cout << "Common header size: " << cmnhdr->size_ << endl; + } + Scheduler::instance().schedule(ll, p, jitter); + + if (!ll) + { + cerr << "Crap, the link layer is NULL!!!!!" << endl; + } + +//cout << "LAR: Done sending." << endl; + + return; +} + +// *********************************************************************** +// broadcastPacket +// *********************************************************************** +void LARAgent::broadcastPacket(Packet *p) +{ + // Access the common header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + struct hdr_ip* iphdr = hdr_ip::access(p); + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_cmn* cmnhdr = (hdr_cmn*)p->access(off_cmn_); + + // Access the IP header for the new packet: + //hdr_ip* iphdr = (hdr_ip*)p->access(off_ip_); + + // Access the lar header for the new packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + //LARprintHeaders(p); + + // Update performance tracking variables + if (larhdr->larCode() == 'D') + { + cerr << "broadcastPacket called for data! LAR should never do this." << endl; + if ((larhdr->route_[0] == this->addr()) && (larhdr->newPkt())) + { + // I originated this data packet + dataTxPkts++; + dataTxBytes += larhdr->dataLength(); + } else { + // this is a data packet and I'm just forwarding it along because + // I'm on the route + dataTxPktsFwd++; + dataTxBytesFwd += larhdr->dataLength(); + } + // count all header bytes, even those on data as control overhead + protocolTxBytes += larhdr->headerLength(); + } else { + // all other packets being sent by this agent at this layer are + // protocol packets, either route request, reply, or error + protocolTxPkts++; + protocolTxBytes += larhdr->headerLength(); + } + + // set all the necessary things for the common header + cmnhdr->next_hop_ = IP_BROADCAST; // broadcast + cmnhdr->prev_hop_ = this->addr(); + //cmnhdr->next_hop_ = 1; + //cmnhdr->iface() = iface_literal::ANY_IFACE; // any interface + cmnhdr->direction() = hdr_cmn::DOWN; // hopefully send it out + //cmnhdr->direction() = hdr_cmn::UP; + + // now the ip header stuff + iphdr->saddr() = this->addr(); + iphdr->sport() = 254; + iphdr->daddr() = IP_BROADCAST; + //iphdr->daddr() = 1; + iphdr->dport() = 254; + //iphdr->dport() = 255; // router port + iphdr->ttl() = 32; + + //cout << endl << "After Modification" << endl; + //LARprintHeaders(p); + + // Send the packet + recordSentPacket(cmnhdr->uid_); + //cout << "LAR: Sending a packet..." << endl; + + // The next three lines should all be equivilant ways to send a packet, + // I'm just trying them all to get the broadcast to go. + //send(p, 0); + //send(p, ll); + //target_->recv(p, (Handler*) 0); + //Scheduler::instance().schedule(target_,p,0); + + double jitter = 0.0; + if (LARuseJitteronBroadcast) + { + // this one is different and was taken from dsragent::sendOutBCastPkt + // I had to add a little jitter because it turned out that neighboring nodes + // where re-broadcasting in the simulator at "exactly" the same time and + // killing each other's transmissions. + jitter = ((double)rand()/(double)RAND_MAX) / larJitter; + } else { + jitter = 0.0; + } + + if (LARverbosity > 0) + { + cout << "Scheduling the packet for delivery: " << cmnhdr->uid_ + << " with jitter=" << jitter << endl; + cout << "Really sending at: " << Scheduler::instance().clock() + jitter << endl; + cout << "Common header size: " << cmnhdr->size_ << endl; + } + cmnhdr->size_ = larhdr->size(); + if (LARverbosity > 0) + { + cout << "Common header size: " << cmnhdr->size_ << endl; + } + Scheduler::instance().schedule(ll, p, jitter); + + if (!ll) + { + cerr << "Crap, the link layer is NULL!!!!!" << endl; + } + +//cout << "LAR: Done sending." << endl; + + return; +} + +// *********************************************************************** +// rebroadcastPacket +// *********************************************************************** +// same as broadcastPacket, but +// - we don't change the ip header source address, +// - we have to set previous hop, +// - we need to decrement the ttl +// - and we have to set the direction to down + +void LARAgent::rebroadcastPacket(Packet *p) +{ + // Access the common header for the new packet: + // new way to do this (2.1b7 and later) + struct hdr_cmn* cmnhdr = hdr_cmn::access(p); + struct hdr_ip* iphdr = hdr_ip::access(p); + struct hdr_lar* larhdr = hdr_lar::access(p); + + // old way to do this + //hdr_cmn* cmnhdr = (hdr_cmn*)p->access(off_cmn_); + + // Access the IP header for the new packet: + //hdr_ip* iphdr = (hdr_ip*)p->access(off_ip_); + + // Access the lar header for the new packet: + //hdr_lar* larhdr = (hdr_lar*)p->access(off_lar_); + + //LARprintHeaders(p); + + // Update performance tracking variables + if (larhdr->larCode() == 'D') + { + cerr << "rebroadcastPacket called for data! LAR should never do this." << endl; + if ((larhdr->route_[0] == this->addr()) && (larhdr->newPkt())) + { + // I originated this data packet + dataTxPkts++; + dataTxBytes += larhdr->dataLength(); + } else { + // this is a data packet and I'm just forwarding it along because + // I'm on the route + dataTxPktsFwd++; + dataTxBytesFwd += larhdr->dataLength(); + } + // count all header bytes, even those on data as control overhead + protocolTxBytes += larhdr->headerLength(); + } else { + // all other packets being sent by this agent at this layer are + // protocol packets, either route request, reply, or error + protocolTxPkts++; + protocolTxBytes += larhdr->headerLength(); + } + + // set all the necessary things for the common header + cmnhdr->next_hop_ = IP_BROADCAST; // broadcast + cmnhdr->prev_hop_ = this->addr(); + //cmnhdr->next_hop_ = 1; + //cmnhdr->iface() = iface_literal::ANY_IFACE; // any interface + cmnhdr->direction() = hdr_cmn::DOWN; // hopefully send it out + //cmnhdr->direction() = hdr_cmn::UP; + + // now the ip header stuff + // don't reset this on a rebroadcast + //iphdr->saddr() = this->addr(); + + // this doesn't have to be done, (it should be ok from the original) + // but just in case... + iphdr->sport() = 254; + iphdr->daddr() = IP_BROADCAST; + //iphdr->daddr() = 1; + iphdr->dport() = 254; + //iphdr->dport() = 255; // router port + + // this is a difference from the regular broadcast + // it appears that this needs to be done + // since this packet doesn't go through the routing agent, this is never + // done anywhere but here +//cout << "ttl before decrement: " << iphdr->ttl_ << endl; + iphdr->ttl()--; + + //cout << endl << "After Modification" << endl; + //LARprintHeaders(p); + + // Send the packet + recordSentPacket(cmnhdr->uid_); + //cout << "LAR: Sending a packet..." << endl; + + // The next three lines should all be equivilant ways to send a packet, + // I'm just trying them all to get the broadcast to go. + //send(p, 0); + //send(p, ll); + //target_->recv(p, (Handler*) 0); + //Scheduler::instance().schedule(target_,p,0); + + double jitter = 0.0; + if (LARuseJitteronBroadcast) + { + // this one is different and was taken from dsragent::sendOutBCastPkt + // I had to add a little jitter because it turned out that neighboring nodes + // where re-broadcasting in the simulator at "exactly" the same time and + // killing each other's transmissions. + jitter = ((double)rand()/(double)RAND_MAX) / larJitter; + } else { + jitter = 0.0; + } + + if (LARverbosity > 0) + { + cout << "Scheduling the packet for delivery: " << cmnhdr->uid_ + << " with jitter=" << jitter << endl; + cout << "Really sending at: " << Scheduler::instance().clock() + jitter << endl; + cout << "Common header size: " << cmnhdr->size_ << endl; + } + cmnhdr->size_ = larhdr->size(); + if (LARverbosity > 0) + { + cout << "Common header size: " << cmnhdr->size_ << endl; + } + Scheduler::instance().schedule(ll, p, jitter); + + if (!ll) + { + cerr << "Crap, the link layer is NULL!!!!!" << endl; + } + +//cout << "LAR: Done sending." << endl; + + return; +} + +/* + commented out until the full up promiscuous mode is working + +// *********************************************************************** +// tap +// *********************************************************************** +void LARAgent::tap(const Packet *p) +{ + if (!usePromiscuousListening) + { + return; + } + + // Access the common header for the received packet: + // new way to do this (2.1b7 and later) + struct hdr_lar* larhdr = hdr_lar::access(pkt); + struct hdr_cmn* hdrcmn = hdr_cmn::access(pkt); + struct hdr_ip* hdrip = hdr_ip::access(pkt); + + // ignore packets that will be passed up to my recv method anyway + // (those addressed to me or the broadcast address) + if ((hdrip->daddr() == this->addr()) || (hdrip->daddr() == IP_BROADCAST)) + { + return; + } + + // ignore if this is a duplicate packet + if (this->dupRcvdPacket(hdrcmn->uid_) || this->dupSentPacket(hdrcmn->uid_)) + { + return; + } else { + // This is redundant for now because dupRcvdPacket records the packet + // as recieved, but I don't like that side effect and may change it + // later. + recordRcvdPacket(hdrcmn->uid_); + } + + // now there must be some kind of call to a route cache maintenance routine + + return; +} + +*/ diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/lar/lar.h ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/lar.h --- ns-allinone-2.32/ns-2.32/lar/lar.h 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/lar.h 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,333 @@ +/****************************************************************************** +* File Name: lar.h +* Purpose: LAR protocol for ns-2 header file +* Original Author: Jeff Boleng +* Modified by: +* Date Created: Some time in 2002 +* +* Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines +* +* Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license +* details. +*******************************************************************************/ + +#ifndef ns_lar_h +#define ns_lar_h + +#include "object.h" +#include "agent.h" +#include "tclcl.h" +#include "packet.h" +#include "address.h" +#include "ip.h" +#include "mac.h" +#include "mobilenode.h" +#include "timer-handler.h" + +#include +#include +#include +#include + +using namespace std; + +#define maxRouteLength 32 + +// This means that the jitter ranges from 0.0 to 0.0001 with +// a mean of 0.00005, so the average number of bits that could +// be transmitted without jitter is 50 per transmission. This seems +// acceptable. +// Note: this is just the divisor in the random number range calculation. +#define larJitter 10000.0 + +#define lar_min(x,y) (((x) < (y)) ? (x) : (y)) +#define lar_max(x,y) (((x) > (y)) ? (x) : (y)) + +// size of the fixed portion of the simulated header +#define LAR_RTREQ_HDR_SIZE_FIXED 38 +#define LAR_RTREQ_FLOOD_HDR_SIZE_FIXED 26 +#define LAR_RTREP_HDR_SIZE_FIXED 38 +#define LAR_DATA_HDR_SIZE_FIXED 28 +#define LAR_RTERR_HDR_SIZE_FIXED 38 + +// prototypes for utility functions +void LARprintHeaders(Packet *p); + +struct hdr_lar { + + // 'R' = Route Request + // 'A' = Route Reply (A for Answer) + // 'D' = Data Packet + // 'E' = Route Error (broken link) + // 'U' = unset + char larCode_; + + // 'F' = flood + // 'B' = box + // 'S' = step + // 'N' = no forward used for the ringZeroSearch option + // 'U' = unset + char forwardCode_; + + // fields needed by route requests + + // fields needed by box and step forwarding methods + double sourceX_; + double sourceY_; + double lastHopX_; + double lastHopY_; + double destinationX_; + double destinationY_; + nsaddr_t destinationID_; + double sendTime_; + bool newPkt_; // true if the packet came from the originator + // false if an intermediate node has taken it over + + // fields needed for Box forwarding method + double destinationSpeed_; + double speedTime_; + + + // fields needed by route replies / data packets / route error messages + nsaddr_t route_[maxRouteLength]; // currently nsaddr_t is a 32 bit int defined in + // config.h + int hops_; + nsaddr_t requestID_; // this is the packet ID of the route request that + // prompted this route reply packet + + double requestSendTime_; // used to calculate the total delay + + // fields needed by data packets + int dataLength_; // length of the data in the packet in bytes + // does not include the header length + + // things I get for "free" from hdr_ip in packet.h + // int saddr(); // IP addr of source sender + // int sport(); // port number of the source sender + // int daddr(); // IP addr of the destination + // int dport(); // port of the destination + + // things I get for "free" from hdr_cmn in packet.h + // double ts_; // timestamp + // int size_; // simulated packet size + // int uid_; // unique packet id + // nsaddr_t prev_hop_; // IP addr of forwarding hop + // int num_forwards_; // number of forwards + + // Now I need to provide access functions for my structure members + inline char &larCode() { return larCode_; } + inline char &forwardCode() { return forwardCode_; } + inline double &sourceX() { return sourceX_; } + inline double &sourceY() { return sourceY_; } + inline double &lastHopX() { return lastHopX_; } + inline double &lastHopY() { return lastHopY_; } + inline double &destinationX() { return destinationX_; } + inline double &destinationY() { return destinationY_; } + inline nsaddr_t &destinationID() { return destinationID_; } + inline double &destinationSpeed() { return destinationSpeed_; } + inline double &speedTime() { return speedTime_; } + inline double &sendTime() { return sendTime_; } + inline bool &newPkt() { return newPkt_; } + inline int &hops() { return hops_; } + inline nsaddr_t &requestID() { return requestID_; } + inline double &requestSendTime() { return requestSendTime_; } + inline int &dataLength() { return dataLength_; } + + inline int size() + { + int s=0; + if (larCode_ == 'R') + { + if (forwardCode_ == 'F') + { + s = LAR_RTREQ_FLOOD_HDR_SIZE_FIXED + 4 * hops_; + } else { + s = LAR_RTREQ_HDR_SIZE_FIXED + 4 * hops_; + } + } else if (larCode_ == 'D') { + s = LAR_DATA_HDR_SIZE_FIXED + 4 * hops_ + dataLength_; + } else if (larCode_ == 'A') { + s = LAR_RTREP_HDR_SIZE_FIXED + 4 * hops_; + } else if (larCode_ == 'E') { + s = LAR_RTERR_HDR_SIZE_FIXED + 4 * hops_; + } + + return s; + } + + inline int headerLength() + { + int s=0; + if (larCode_ == 'R') + { + if (forwardCode_ == 'F') + { + s = LAR_RTREQ_FLOOD_HDR_SIZE_FIXED + 4 * hops_; + } else { + s = LAR_RTREQ_HDR_SIZE_FIXED + 4 * hops_; + } + } else if (larCode_ == 'D') { + s = LAR_DATA_HDR_SIZE_FIXED + 4 * hops_; + } else if (larCode_ == 'A') { + s = LAR_RTREP_HDR_SIZE_FIXED + 4 * hops_; + } else if (larCode_ == 'E') { + s = LAR_RTERR_HDR_SIZE_FIXED + 4 * hops_; + } + + return s; + } + + static int offset_; + inline static int& offset() + { + return offset_; + } + inline static hdr_lar* access(const Packet *p) + { + return (hdr_lar*) p->access(offset_); + } + +}; + +class LARAgent; + +typedef struct +{ + double x; + double y; + double v; + char method; //flood, box, or step (F,B, or S) + nsaddr_t route[maxRouteLength]; + int hops; + double timeOfLastRequest; + double timeOfVelocity; + bool requestPending; + bool noRoute; +} larDestType; + +// timer class needed for the route request timeout +class LARRouteRequestTimer : public TimerHandler +{ + public: + LARRouteRequestTimer(LARAgent *a, nsaddr_t d, int t, larDestType *r, char m): TimerHandler() + { + agent = a; + dest = d; + triesLeft = t; + routeInfo = r; + forwardMethod = m; + } + void setTriesLeft(int t) {triesLeft = t;} + void setForwardMethod(char c) {forwardMethod = c;} + void setRouteInfo(larDestType *r) { routeInfo = r; } + virtual void expire(Event *e); + protected: +// virtual void expire(Event *e); + LARAgent *agent; + nsaddr_t dest; + int triesLeft; + larDestType *routeInfo; + char forwardMethod; +}; + +// Agent inheritance is because this is a specialized Agent + +// this will be needed when full up promiscuous mode is implemented +// class LARAgent : public Tap, public Agent +class LARAgent : public Agent +{ + public: + LARAgent(); + ~LARAgent(); + int command(int argc, const char*const* argv); + void recv(Packet*, Handler*); + void routeError(Packet *p); + + // This method gets all the packet that the node's MAC layer hears + // so it can promiscuously listen to them. + //void tap(const Packet *p); + + protected: + int off_lar_; + bool inForwardingRegion(char fwdCode, double srcX, double srcY, + double destX, double destY, + double destSpeed, double speedTime); + int sendInitialRouteRequest(nsaddr_t id, larDestType *routeEntry); + bool dupRcvdPacket(int id); + bool dupSentPacket(int id); + void recordSentPacket(int id); + void recordRcvdPacket(int id); + void sendPacket(Packet *p, nsaddr_t to); + void broadcastPacket(Packet *p); + void rebroadcastPacket(Packet *p); + + friend void LARRouteRequestTimer::expire(Event *e); + + private: + void sendNewData(Packet *p, nsaddr_t destID); + void sendRouteReply(Packet *p); + void purgePendingPacketsFor(nsaddr_t id); + void purgeAllPendingPackets(); + void addToPendingPackets(Packet *p); + void checkPendingQueueForPackets(nsaddr_t id); + + void clearRequestPending(nsaddr_t id); + void maintainRouteTable(Packet *p); + bool subRoute(larDestType *rt, Packet *p); + + // this function looks up the current destination in the route table and calls + // sendRouteRequest appropriately + void routeRequest(Packet *p); + int sendRouteRequest(nsaddr_t id, char fwdCode, larDestType *routeEntry, bool ringZero); + + // this is just a set of packets I've sent + set > sentPackets; + // this is just a set of packets I've received + set > rcvdPackets; + + list pendingPackets; + + // this is the routing table. It is indexed by destination node id + map > routeTable; + map > updatedRoute; + + // this is a list of route request timers indexed by the destination node id + map > timers; + + NsObject *ll; // link layer output in order to avoid using a routing + // agent + MobileNode *node; // the node that this agent is attached to + + // all these variables are for statistics keeping... + int dataTxPkts; + int dataRxPkts; + int dataTxBytes; + int dataRxBytes; + double totalEEdelay; + int totalHops; + int protocolTxPkts; + int protocolRxPkts; + int protocolTxBytes; + int protocolRxBytes; + int dataTxPktsFwd; + int dataRxPktsFwd; + int dataTxBytesFwd; + int dataRxBytesFwd; + int dataDroppedSrc; + int dataDroppedInt; + int routeErrorsGen; + int routeErrorsRx; + int larRtReqTx; + int larRtReqRx; + int floodRtReqTx; + int floodRtReqRx; + int oneHopRtReqTx; + int oneHopRtReqRx; + int srcRtErrors; + int droppedAtEnd; + int pktOverflow; +}; + +#endif + + diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/lar/step.tcl ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/step.tcl --- ns-allinone-2.32/ns-2.32/lar/step.tcl 1969-12-31 19:00:00.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/lar/step.tcl 2007-10-17 16:09:22.000000000 -0400 @@ -0,0 +1,236 @@ +#*****************************************************************************# +# File Name: step.tcl # +# Purpose: # +# Original Author: # +# Modified by: # +# Date Created: # +# +# Copyright (C) 2004 Toilers Research Group -- Colorado School of Mines # +# +# Please see COPYRIGHT.TXT and LICENSE.TXT for copyright and license # +# details. # +#******************************************************************************/ + +puts "setting initial variables..." +set val(chan) Channel/WirelessChannel +set val(prop) Propagation/TwoRayGround +set val(netif) Phy/WirelessPhy +set val(mac) Mac/802_11 +set val(ifq) Queue/DropTail/PriQueue +set val(ll) LL +set val(ant) Antenna/OmniAntenna +set val(x) 300 +set val(y) 600 +set val(ifqlen) 50 +set val(rp) AODV +#set val(rp) DSR +#set val(rp) DSDV +set val(nn) 50 +set val(txPower) 0.0075 ; #100 meters +set val(rxPower) 1 +#set val(sc) "test.mob" +set val(sc) [lindex $argv 0] +set val(dataStart) 1000.0 +set val(dataStop) 2000.0 +set val(signalStop) 2005.0 +set val(finish) 2010.0 + +# ===================================================================== +# Other default settings + +puts "setting other default settings..." + +LL set mindelay_ 50us +LL set delay_ 25us +LL set bandwidth_ 0 ;# not used + +Agent/Null set sport_ 0 +Agent/Null set dport_ 0 + +Agent/CBR set sport_ 0 +Agent/CBR set dport_ 0 + +Agent/TCPSink set sport_ 0 +Agent/TCPSink set dport_ 0 + +Agent/TCP set sport_ 0 +Agent/TCP set dport_ 0 +Agent/TCP set packetSize_ 512 + +Queue/DropTail/PriQueue set Prefer_Routing_Protocols 1 + +# unity gain, omni-directional antennas +# set up the antennas to be centered in the node and 1.5 meters above it +Antenna/OmniAntenna set X_ 0 +Antenna/OmniAntenna set Y_ 0 +Antenna/OmniAntenna set Z_ 1.5 +Antenna/OmniAntenna set Gt_ 1.0 +Antenna/OmniAntenna set Gr_ 1.0 + +# Initialize the SharedMedia interface with parameters to make +# it work like the 914MHz Lucent WaveLAN DSSS radio interface +Phy/WirelessPhy set CPThresh_ 10.0 +Phy/WirelessPhy set CSThresh_ 1.559e-11 +Phy/WirelessPhy set RXThresh_ 3.652e-10 +Phy/WirelessPhy set Rb_ 2*1e6 +#this was the default +#Phy/WirelessPhy set Pt_ 0.2818 +# This is for 100m +Phy/WirelessPhy set Pt_ 7.214e-3 +# This is for 40m +#Phy/WirelessPhy set Pt_ 8.5872e-4 +# This is for 250m +#Phy/WirelessPhy set Pt_ 0.2818 +Phy/WirelessPhy set freq_ 914e+6 +Phy/WirelessPhy set L_ 1.0 + +# ===================================================================== +# This puts in only the headers that we need. +# ===================================================================== +puts "removing unecessary packet headers..." +remove-all-packet-headers +add-packet-header IP +add-packet-header Common +add-packet-header LAR +add-packet-header LL +add-packet-header Mac + +#Create a simulator object +set ns_ [new Simulator] + +#Open a trace file + +set nt [open out.trace w] +$ns_ trace-all $nt + +set topo [new Topography] +$topo load_flatgrid $val(x) $val(y) + +create-god $val(nn) + +# New API to config node: +# 1. Create channel (or multiple-channels); +# 2. Specify channel in node-config (instead of channelType); +# 3. Create nodes for simulations. + +# Create channel #1 +puts "creating channel..." +set chan_1_ [new $val(chan)] + +# +# define how node should be created +# + +#global node setting +puts "setting global node values..." +$ns_ node-config -adhocRouting $val(rp) \ + -llType $val(ll) \ + -macType $val(mac) \ + -ifqType $val(ifq) \ + -ifqLen $val(ifqlen) \ + -antType $val(ant) \ + -propType $val(prop) \ + -phyType $val(netif) \ + #-channelType $val(chan) \ + -channel $chan_1_ \ + -topoInstance $topo \ + -agentTrace OFF \ + -routerTrace OFF \ + -macTrace OFF \ + -movementTrace OFF \ + -txPower $val(txPower) \ + -rxPower $val(rxPower) + +# create the nodes +puts "creating the nodes..." + +# create the nodes +for {set i 0} {$i < $val(nn) } {incr i} { + set node_($i) [$ns_ node] + $node_($i) random-motion 0 ;# disable random motion +} + +# +#Define a 'finish' procedure +proc finish {} { + global ns_ nt + $ns_ flush-trace + close $nt + exit 0 +} + +# Load the movement file +puts "Loading the mobility file..." +source $val(sc) + +#Create lar agents and attach them to the nodes +puts "creating lar agents and attaching them to nodes..." +for {set i 0} {$i < $val(nn)} {incr i} { + set g($i) [new Agent/LAR] + $node_($i) attach $g($i) 254 + + # need to tell the lar agents about their link layers + set ll($i) [$node_($i) set ll_(0)] + $ns_ at 0.0 "$g($i) set-ll $ll($i)" + + # need to tell the lar agents which nodes they're on also + $ns_ at 0.0 "$g($i) set-node $node_($i)" +} + +# the format now for the lar send is +# +# "$nodeId sendData " +# +# this will be used to test in a static configuration, and will +# change once the mobility portion is figured out. +#Schedule events + +puts "Scheduling the send events" +for {set k $val(dataStart)} {$k < $val(dataStop)} {set k [expr $k + 0.25] } \ +{ + $ns_ at $k "$g(0) sendData 49 64 S" + $ns_ at [expr $k + .0001] "$g(1) sendData 48 64 S" + $ns_ at [expr $k + .0002] "$g(2) sendData 47 64 S" + $ns_ at [expr $k + .0003] "$g(3) sendData 46 64 S" + $ns_ at [expr $k + .0004] "$g(4) sendData 45 64 S" + $ns_ at [expr $k + .0005] "$g(5) sendData 44 64 S" + $ns_ at [expr $k + .0006] "$g(6) sendData 43 64 S" + $ns_ at [expr $k + .0007] "$g(7) sendData 42 64 S" + $ns_ at [expr $k + .0008] "$g(8) sendData 41 64 S" + $ns_ at [expr $k + .0009] "$g(9) sendData 40 64 S" + $ns_ at [expr $k + .0010] "$g(10) sendData 39 64 S" + $ns_ at [expr $k + .0011] "$g(11) sendData 38 64 S" + $ns_ at [expr $k + .0012] "$g(12) sendData 37 64 S" + $ns_ at [expr $k + .0013] "$g(13) sendData 36 64 S" + $ns_ at [expr $k + .0014] "$g(14) sendData 35 64 S" + $ns_ at [expr $k + .0015] "$g(15) sendData 34 64 S" + $ns_ at [expr $k + .0016] "$g(16) sendData 33 64 S" + $ns_ at [expr $k + .0017] "$g(17) sendData 32 64 S" + $ns_ at [expr $k + .0018] "$g(18) sendData 31 64 S" + $ns_ at [expr $k + .0019] "$g(19) sendData 30 64 S" +} + + +# this is done to make the simulator continue running and "settle" things out +for {set i 0} {$i < $val(nn)} {incr i} { + $ns_ at $val(signalStop) "$g($i) larDone" +} + +$ns_ at $val(finish) "finish" +$ns_ at [expr $val(finish) + 0.1] "puts \"NS Exiting...\" ; $ns_ halt" + +#Run the simulation +puts "" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "Running the simulation" +puts "" +puts "***********************************************" +puts "***********************************************" +puts "***********************************************" +puts "" +puts "" +$ns_ run diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/tcl/lib/ns-packet.tcl ns-allinone-2.32-LAR_DREAM/ns-2.32/tcl/lib/ns-packet.tcl --- ns-allinone-2.32/ns-2.32/tcl/lib/ns-packet.tcl 2005-06-17 13:41:16.000000000 -0400 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/tcl/lib/ns-packet.tcl 2007-10-17 16:09:22.000000000 -0400 @@ -164,14 +164,22 @@ Diffusion # diffusion/diffusion.cc IMEP # Internet MANET Encapsulation Protocol, for ad-hoc networks MIP # Mobile IP, mobile/mip-reg.cc Smac # Sensor-MAC TORA # routing protocol for ad-hoc networks + # Other: Encap # common/encap.cc IPinIP # IP encapsulation HDLC # High Level Data Link Control +# TOILERS + LAR # LAR implementation, lar/lar.cc + FLOOD # flooding algorithm for wireless ad-hoc + DREAM +# FEEDBACK +# ALARM +# ZRP } { add-packet-header $prot } proc PktHdr_offset { hdrName {field ""} } { diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/trace/cmu-trace.cc ns-allinone-2.32-LAR_DREAM/ns-2.32/trace/cmu-trace.cc --- ns-allinone-2.32/ns-2.32/trace/cmu-trace.cc 2006-03-21 17:31:32.000000000 -0500 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/trace/cmu-trace.cc 2007-10-17 16:09:22.000000000 -0400 @@ -59,10 +59,14 @@ #include "wpan/p802_15_4trace.h" #include "wpan/p802_15_4nam.h" // #include "diffusion/diff_header.h" // DIFFUSION -- Chalermek +#include //LAR +// #include //ALARM +#include +// #include //FLOOD //#define LOG_POSITION //extern char* pt_names[]; @@ -231,11 +235,11 @@ node_->getLoc(&x, &y, &z); #endif sprintf(pt_->buffer() + offset, #ifdef LOG_POSITION - "%c %.9f %d (%6.2f %6.2f) %3s %4s %d %s %d ", + "%c %.9f %d (%6.2f %6.2f) %3s %4s %d %s %d [%x %x %x %x] ", #else "%c %.9f _%d_ %3s %4s %d %s %d", #endif op, Scheduler::instance().clock(), @@ -549,12 +553,12 @@ */ void CMUTrace::format_sctp(Packet* p,int offset) { struct hdr_cmn *ch = HDR_CMN(p); + struct hdr_ip *ih = HDR_IP(p); struct hdr_sctp *sh = HDR_SCTP(p); - //struct hdr_ip *ih = HDR_IP(p); char cChunkType; for(u_int i = 0; i < sh->NumChunks(); i++) { switch(sh->SctpTrace()[i].eType) { case SCTP_CHUNK_INIT: @@ -884,10 +888,159 @@ #endif abort(); } } +//SHK +//Feedback +/* void +CMUTrace::format_feedback(Packet *p, int offset) +{ + //sprintf(wrk_ + offset, "Sent a feedback beacon."); + //SHK + sprintf(pt_->buffer() + offset, "Sent a feedback beacon."); + return; +} */ + +//LAR +void +CMUTrace::format_lar(Packet *p, int offset) +{ + struct hdr_lar* larhdr = hdr_lar::access(p); + struct hdr_mac* machdr = hdr_mac::access(p); + //hdr_lar* larhdr =(hdr_lar*)p->access(off_lar_); + // //hdr_mac* machdr = (hdr_mac*)p->access(off_mac_); + struct hdr_ip *iphdr = HDR_IP(p); + //sprintf(wrk_ + offset, + //SHK + sprintf(pt_->buffer() + offset, + "LAR [%c %c] src[%d (%.3f,%.3f)] to[%d (%.3f,%.3f) s=%.3f t=%f] h=%d last[%d (%.3f,%.3f)] data=%d t=%f", + larhdr->larCode_, + larhdr->forwardCode_, + iphdr->saddr(), + larhdr->sourceX_, + larhdr->sourceY_, + larhdr->destinationID_, + larhdr->destinationX_, + larhdr->destinationY_, + larhdr->destinationSpeed_, + larhdr->speedTime_, + larhdr->hops_, + machdr->macSA(), + larhdr->lastHopX_, + larhdr->lastHopY_, + larhdr->dataLength_, + larhdr->sendTime_); +return; +} + +void +CMUTrace::format_dream(Packet* p, int offset) +{ + struct hdr_dream* hdr = HDR_DREAM(p); + struct hdr_ip *iphdr = HDR_IP(p); +// sprintf(wrk_ + offset, + + sprintf(pt_->buffer() + offset, + "Dream [%d] dist[%.2f] src[ %d (%.3f,%.3f)] to %d first? %d t %f o_id %d", + hdr->dreamPacketType(), + hdr->maxDistance(), + iphdr->saddr(), + hdr->sourceX(), + hdr->sourceY(), + hdr->toAddr(), + hdr->first(), + hdr->sendTime(), + hdr->originalPacketId()); + return; +} + +/* void +CMUTrace::format_flood(Packet *p, int offset) +{ + struct hdr_flood *fh = hdr_flood:access(p); + sprintf(pt_->buffer() + offset, + "Flood typ %d src %d to %d st %f hop %d", + fh->floodPacketType(), + fh->origAddr(), + fh->toAddr(), + fh->sendTime(), + fh->hops()); + + return; +} */ + +//ALARM +/*void +CMUTrace::format_alarm(Packet *p, int offset) +{ +// struct hdr_alarm* alarmhdr = hdr_alarm::access(p); +// struct hdr_mac* machdr = hdr_mac::access(p); +// //hdr_alarm* alarmhdr =(hdr_alarm*)p->access(off_alarm); +// //hdr_mac* machdr = (hdr_mac*)p->access(off_mac_); +// struct hdr_ip *iphdr = HDR_IP(p); +// //sprintf(wrk_ + offset, +// //SHK +// sprintf(pt_->buffer() + offset, +// "LAR [%c %c] src[%d (%.3f,%.3f)] to[%d (%.3f,%.3f) s=%.3f t=%f] h=%d last[%d (%.3f,%.3f)] data=%d t=%f", +// alarmhdr->alarmCode_, +// alarmhdr->forwardCode_, +// iphdr->saddr(), +// alarmhdr->sourceX_, +// alarmhdr->sourceY_, +// alarmhdr->destinationID_, +// alarmhdr->destinationX_, +// alarmhdr->destinationY_, +// alarmhdr->destinationSpeed_, +// alarmhdr->speedTime_, +// alarmhdr->hops_, +// machdr->macSA(), +// alarmhdr->lastHopX_, +// alarmhdr->lastHopY_, +// alarmhdr->dataLength_, +// alarmhdr->sendTime_); + +// return; +} */ + +//SHK +/* void +CMUTrace::format_zrp(Packet *p, int offset) +{ + struct hdr_cmn *ch = HDR_CMN(p); + struct hdr_ip *ih = HDR_IP(p); + + // hack the IP address to convert pkt format to hostid format + // for now until port ids are removed from IP address. -Padma. + int src = Address::instance().get_nodeaddr(ih->saddr()); + int dst = Address::instance().get_nodeaddr(ih->daddr()); + + if (pt_->tagged()) { + // Need to determine tag names for this data + //sprintf(pt_->buffer() + offset, + // "", + // ); + } else if (newtrace_) { + sprintf(pt_->buffer() + offset, + "-Is %d.%d -Id %d.%d -It %s -Il %d -If %d -Ii %d -Iv %d ", + src, // packet src + ih->sport(), // src port + dst, // packet dest + ih->dport(), // dst port + packet_info.name(ch->ptype()), // packet type + ch->size(), // packet size + ih->flowid(), // flow id + ch->uid(), // unique id + ih->ttl_); // ttl + } else { + sprintf(pt_->buffer() + offset, "------- [%d:%d %d:%d %d %d] ", + src, ih->sport(), + dst, ih->dport(), + ih->ttl_, (ch->next_hop_ < 0) ? 0 : ch->next_hop_); + } +} */ + void CMUTrace::nam_format(Packet *p, int offset) { Node* srcnode = 0 ; Node* dstnode = 0 ; @@ -1121,11 +1274,12 @@ offset = strlen(pt_->nbuffer()); pt_->namdump(); } -void CMUTrace::format(Packet* p, const char *why) +void +CMUTrace::format(Packet* p, const char *why) { hdr_cmn *ch = HDR_CMN(p); int offset = 0; /* @@ -1173,10 +1327,29 @@ format_sctp(p, offset); break; case PT_CBR: format_rtp(p, offset); break; + case PT_DREAM: + format_dream(p, offset); + break; + case PT_LAR: + format_lar(p, offset); + break; +// case PT_FLOOD: +// format_flood(p, offset); +// break; +// case PT_ALARM: +// format_alarm(p, offset); +// break; +// case PT_FEEDBACK: +// format_feedback(p, offset); +// break; +//SHK +// case PT_ZRP: +// format_zrp(p, offset); +// break; case PT_DIFF: break; case PT_GAF: case PT_PING: break; diff -U 5 -H -d -r -N -- ns-allinone-2.32/ns-2.32/trace/cmu-trace.h ns-allinone-2.32-LAR_DREAM/ns-2.32/trace/cmu-trace.h --- ns-allinone-2.32/ns-2.32/trace/cmu-trace.h 2005-07-26 21:13:45.000000000 -0400 +++ ns-allinone-2.32-LAR_DREAM/ns-2.32/trace/cmu-trace.h 2007-10-17 16:09:22.000000000 -0400 @@ -86,10 +86,15 @@ #define DROP_IFQ_ARP_FULL "ARP" // dropped by ARP #define DROP_IFQ_FILTER "FIL" #define DROP_OUTSIDE_SUBNET "OUT" // dropped by base stations if received rtg updates from nodes outside its domain. +//SHK +#define DROP_RTR_HIYA "HIYA" +#define DROP_RTR_IERP "IERP" +#define DROP_RTR_IARP "IARP" + #define MAX_ID_LEN 3 #define MAX_NODE 4096 class CMUTrace : public Trace { public: @@ -130,9 +135,15 @@ void format_tcp(Packet *p, int offset); void format_sctp(Packet *p, int offset); void format_rtp(Packet *p, int offset); void format_tora(Packet *p, int offset); void format_imep(Packet *p, int offset); + void format_feedback(Packet *p, int offset); + void format_flood(Packet *p, int offset); + void format_lar(Packet *p, int offset); + void format_dream(Packet *p, int offset); +// void format_alarm(Packet *p, int offset); +// void format_zrp(Packet *p, int offset); void format_aodv(Packet *p, int offset); }; #endif /* __cmu_trace__ */