Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

traffictrace.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) Xerox Corporation 1997. All rights reserved.
00004  *  
00005  * License is granted to copy, to use, and to make and to use derivative
00006  * works for research and evaluation purposes, provided that Xerox is
00007  * acknowledged in all documentation pertaining to any such copy or derivative
00008  * work. Xerox grants no other licenses expressed or implied. The Xerox trade
00009  * name should not be used in any advertising without its written permission.
00010  *  
00011  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00012  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00013  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00014  * express or implied warranty of any kind.
00015  *  
00016  * These notices must be retained in any copies of any part of this software.
00017  */
00018 
00019 #ifndef lint
00020 static const char rcsid[] =
00021     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/trace/traffictrace.cc,v 1.15 2002/12/10 01:33:39 difa Exp $ (Xerox)";
00022 #endif
00023 
00024 /* XXX: have not dealt with errors.  e.g., if something fails during
00025  * TraceFile::setup(), or TrafficTrace is not pointing to a TraceFile,
00026  * no guarantee about results.
00027  */
00028  
00029 #include <sys/types.h>
00030 #include <sys/stat.h> 
00031 #include <stdio.h>
00032 
00033 #include "config.h"
00034 #ifdef HAVE_NETINET_IN_H
00035 #include <netinet/in.h>
00036 #endif /* HAVE_NETINET_IN_H */
00037 
00038 
00039 #include "random.h"
00040 /* module to implement a traffic generator in ns driven by a trace
00041  * file.  records in the trace file consist of 2 32 bit fields, the
00042  * first indicating the inter-packet time in microseconds, and the
00043  * second indicating the packet length in bytes.  multiple TraffficTrace
00044  * objects can use the same trace file, and different TrafficTrace
00045  * objects can use different trace files.  For each TrafficTrace, a
00046  * random starting point within the trace file is selected.
00047  */
00048 
00049 #include "object.h"
00050 #include "trafgen.h"
00051 
00052 struct tracerec {
00053         u_int32_t trec_time; /* inter-packet time (usec) */
00054         u_int32_t trec_size; /* size of packet (bytes */
00055 };
00056 
00057 
00058 /* object to hold a single trace file */
00059 
00060 class TraceFile : public NsObject {
00061  public:
00062         TraceFile();
00063         void get_next(int&, struct tracerec&); /* called by TrafficGenerator
00064                                                 * to get next record in trace.
00065                                                 */
00066         int setup();  /* initialize the trace file */
00067         int command(int argc, const char*const* argv);
00068  private:
00069         void recv(Packet*, Handler*); /* must be defined for NsObject */
00070         int status_; 
00071         char *name_;  /* name of the file in which the trace is stored */
00072         int nrec_;    /* number of records in the trace file */
00073         struct tracerec *trace_; /* array holding the trace */
00074 };
00075 
00076 /* instance of a traffic generator.  has a pointer to the TraceFile
00077  * object and implements the interval() function.
00078  */
00079 
00080 class TrafficTrace : public TrafficGenerator {
00081  public:
00082         TrafficTrace();
00083         int command(int argc, const char*const* argv);
00084         virtual double next_interval(int &);
00085  protected:
00086         void timeout();
00087         TraceFile *tfile_;
00088         struct tracerec trec_;
00089         int ndx_;
00090         void init();
00091 };
00092 
00093 
00094 static class TraceFileClass : public TclClass {
00095  public:
00096         TraceFileClass() : TclClass("Tracefile") {}
00097         TclObject* create(int, const char*const*) {
00098                 return (new TraceFile());
00099         }
00100 } class_tracefile;
00101 
00102 TraceFile::TraceFile() : status_(0)
00103 {
00104 }
00105 
00106 int TraceFile::command(int argc, const char*const* argv)
00107 {
00108 
00109         if (argc == 3) {
00110                 if (strcmp(argv[1], "filename") == 0) {
00111                         name_ = new char[strlen(argv[2])+1];
00112                         strcpy(name_, argv[2]);
00113                         return(TCL_OK);
00114                 }
00115         }
00116         return (NsObject::command(argc, argv));
00117 }
00118 
00119 void TraceFile::get_next(int& ndx, struct tracerec& t)
00120 {
00121         t.trec_time = trace_[ndx].trec_time;
00122         t.trec_size = trace_[ndx].trec_size;
00123 
00124         if (++ndx == nrec_)
00125                 ndx = 0;
00126 
00127 }
00128 
00129 int TraceFile::setup()
00130 {
00131         tracerec* t;
00132         struct stat buf;
00133         int i;
00134         FILE *fp;
00135 
00136         /* only open/read the file once (could be shared by multiple
00137          * SourceModel's
00138          */
00139         if (! status_) {
00140                 status_ = 1;
00141 
00142                 if (stat(name_, (struct stat *)&buf)) {
00143                         printf("could not stat %s\n", name_);
00144                         return -1;
00145                 }
00146 
00147                 nrec_ = buf.st_size/sizeof(tracerec);
00148                 unsigned nrecplus = nrec_ * sizeof(tracerec);
00149                 unsigned bufst = buf.st_size;
00150 
00151                 //      if ((unsigned)(nrec_ * sizeof(tracerec)) != buf.st_size) {
00152                 if (nrecplus != bufst) {
00153                         printf("bad file size in %s\n", name_);
00154                         return -1;
00155                 }
00156 
00157                 trace_ = new struct tracerec[nrec_];
00158 
00159                 if ((fp = fopen(name_, "rb")) == NULL) {
00160                         printf("can't open file %s\n", name_);
00161                         return -1;
00162                 }
00163 
00164                 for (i = 0, t = trace_; i < nrec_; i++, t++)
00165                         if (fread((char *)t, sizeof(tracerec), 1, fp) != 1) {
00166                                 printf("read failed\n");
00167                                 return -1 ;
00168                         }
00169                         else {
00170                 
00171                                 t->trec_time = ntohl(t->trec_time);
00172                                 t->trec_size = ntohl(t->trec_size);
00173                         }
00174 
00175         }
00176 
00177         /* pick a random starting place in the trace file */
00178         return (int(Random::uniform((double)nrec_)+.5));
00179 
00180 }
00181 
00182 void TraceFile::recv(Packet*, Handler*)
00183 {
00184         /* shouldn't get here */
00185         abort();
00186 }
00187 
00188 /**************************************************************/
00189 
00190 static class TrafficTraceClass : public TclClass {
00191  public:
00192         TrafficTraceClass() : TclClass("Application/Traffic/Trace") {}
00193         TclObject* create(int, const char*const*) {
00194                 return(new TrafficTrace());
00195         }
00196 } class_traffictrace;
00197 
00198 TrafficTrace::TrafficTrace()
00199 {
00200         tfile_ = (TraceFile *)NULL;
00201 }
00202 
00203 void TrafficTrace::init()
00204 {
00205         if (tfile_) 
00206                 ndx_ = tfile_->setup();
00207 }
00208 
00209 int TrafficTrace::command(int argc, const char*const* argv)
00210 {
00211         Tcl& tcl = Tcl::instance();
00212         
00213         if (argc == 3) {
00214                 if (strcmp(argv[1], "attach-tracefile") == 0) {
00215                         tfile_ = (TraceFile *)TclObject::lookup(argv[2]);
00216                         if (tfile_ == 0) {
00217                                 tcl.resultf("no such node %s", argv[2]);
00218                                 return(TCL_ERROR);
00219                         }
00220                         return(TCL_OK);
00221                 }
00222         }
00223 
00224         return (TrafficGenerator::command(argc, argv));
00225 
00226 }
00227 
00228 void TrafficTrace::timeout()
00229 {
00230         if (! running_)
00231                 return;
00232 
00233         /* send a packet */
00234         // Note:  May need to set "NEW_BURST" flag in sendmsg() for 
00235         // signifying a new talkspurt when using vat traces.
00236         // (see expoo.cc, tcl/ex/test-rcvr.tcl)
00237         agent_->sendmsg(size_);
00238         /* figure out when to send the next one */
00239         nextPkttime_ = next_interval(size_);
00240         /* schedule it */
00241         timer_.resched(nextPkttime_);
00242 }
00243 
00244 
00245 double TrafficTrace::next_interval(int& size)
00246 {
00247         tfile_->get_next(ndx_, trec_);
00248         size = trec_.trec_size;
00249         return(((double)trec_.trec_time)/1000000.0); /* usecs->secs */
00250 }

Generated on Tue Apr 20 12:14:37 2004 for NS2.26SourcesOriginal by doxygen 1.3.3