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  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU General Public License as published by the
00007  * Free Software Foundation; either version 2 of the License, or (at your
00008  * option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along
00016  * with this program; if not, write to the Free Software Foundation, Inc.,
00017  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  *
00019  * Linking this file statically or dynamically with other modules is making
00020  * a combined work based on this file.  Thus, the terms and conditions of
00021  * the GNU General Public License cover the whole combination.
00022  *
00023  * In addition, as a special exception, the copyright holders of this file
00024  * give you permission to combine this file with free software programs or
00025  * libraries that are released under the GNU LGPL and with code included in
00026  * the standard release of ns-2 under the Apache 2.0 license or under
00027  * otherwise-compatible licenses with advertising requirements (or modified
00028  * versions of such code, with unchanged license).  You may copy and
00029  * distribute such a system following the terms of the GNU GPL for this
00030  * file and the licenses of the other code concerned, provided that you
00031  * include the source code of that other code when and as the GNU GPL
00032  * requires distribution of source code.
00033  *
00034  * Note that people who make modified versions of this file are not
00035  * obligated to grant this special exception for their modified versions;
00036  * it is their choice whether to do so.  The GNU General Public License
00037  * gives permission to release a modified version without this exception;
00038  * this exception also makes it possible to release a modified version
00039  * which carries forward this exception.
00040  */
00041 
00042 #ifndef lint
00043 static const char rcsid[] =
00044     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/trace/traffictrace.cc,v 1.16 2005/08/26 05:05:31 tomh Exp $ (Xerox)";
00045 #endif
00046 
00047 /* XXX: have not dealt with errors.  e.g., if something fails during
00048  * TraceFile::setup(), or TrafficTrace is not pointing to a TraceFile,
00049  * no guarantee about results.
00050  */
00051  
00052 #include <sys/types.h>
00053 #include <sys/stat.h> 
00054 #include <stdio.h>
00055 
00056 #include "config.h"
00057 #ifdef HAVE_NETINET_IN_H
00058 #include <netinet/in.h>
00059 #endif /* HAVE_NETINET_IN_H */
00060 
00061 
00062 #include "random.h"
00063 /* module to implement a traffic generator in ns driven by a trace
00064  * file.  records in the trace file consist of 2 32 bit fields, the
00065  * first indicating the inter-packet time in microseconds, and the
00066  * second indicating the packet length in bytes.  multiple TraffficTrace
00067  * objects can use the same trace file, and different TrafficTrace
00068  * objects can use different trace files.  For each TrafficTrace, a
00069  * random starting point within the trace file is selected.
00070  */
00071 
00072 #include "object.h"
00073 #include "trafgen.h"
00074 
00075 struct tracerec {
00076         u_int32_t trec_time; /* inter-packet time (usec) */
00077     u_int32_t trec_size; /* size of packet (bytes */
00078 };
00079 
00080 
00081 /* object to hold a single trace file */
00082 
00083 class TraceFile : public NsObject {
00084  public:
00085     TraceFile();
00086     void get_next(int&, struct tracerec&); /* called by TrafficGenerator
00087                         * to get next record in trace.
00088                         */
00089     int setup();  /* initialize the trace file */
00090     int command(int argc, const char*const* argv);
00091  private:
00092     void recv(Packet*, Handler*); /* must be defined for NsObject */
00093         int status_; 
00094     char *name_;  /* name of the file in which the trace is stored */
00095     int nrec_;    /* number of records in the trace file */
00096     struct tracerec *trace_; /* array holding the trace */
00097 };
00098 
00099 /* instance of a traffic generator.  has a pointer to the TraceFile
00100  * object and implements the interval() function.
00101  */
00102 
00103 class TrafficTrace : public TrafficGenerator {
00104  public:
00105     TrafficTrace();
00106     int command(int argc, const char*const* argv);
00107     virtual double next_interval(int &);
00108  protected:
00109     void timeout();
00110     TraceFile *tfile_;
00111     struct tracerec trec_;
00112     int ndx_;
00113     void init();
00114 };
00115 
00116 
00117 static class TraceFileClass : public TclClass {
00118  public:
00119     TraceFileClass() : TclClass("Tracefile") {}
00120     TclObject* create(int, const char*const*) {
00121         return (new TraceFile());
00122     }
00123 } class_tracefile;
00124 
00125 TraceFile::TraceFile() : status_(0)
00126 {
00127 }
00128 
00129 int TraceFile::command(int argc, const char*const* argv)
00130 {
00131 
00132     if (argc == 3) {
00133         if (strcmp(argv[1], "filename") == 0) {
00134             name_ = new char[strlen(argv[2])+1];
00135             strcpy(name_, argv[2]);
00136             return(TCL_OK);
00137         }
00138     }
00139     return (NsObject::command(argc, argv));
00140 }
00141 
00142 void TraceFile::get_next(int& ndx, struct tracerec& t)
00143 {
00144     t.trec_time = trace_[ndx].trec_time;
00145     t.trec_size = trace_[ndx].trec_size;
00146 
00147     if (++ndx == nrec_)
00148         ndx = 0;
00149 
00150 }
00151 
00152 int TraceFile::setup()
00153 {
00154     tracerec* t;
00155     struct stat buf;
00156     int i;
00157     FILE *fp;
00158 
00159     /* only open/read the file once (could be shared by multiple
00160      * SourceModel's
00161      */
00162     if (! status_) {
00163         status_ = 1;
00164 
00165         if (stat(name_, (struct stat *)&buf)) {
00166             printf("could not stat %s\n", name_);
00167             return -1;
00168         }
00169 
00170         nrec_ = buf.st_size/sizeof(tracerec);
00171         unsigned nrecplus = nrec_ * sizeof(tracerec);
00172         unsigned bufst = buf.st_size;
00173 
00174         //  if ((unsigned)(nrec_ * sizeof(tracerec)) != buf.st_size) {
00175         if (nrecplus != bufst) {
00176             printf("bad file size in %s\n", name_);
00177             return -1;
00178         }
00179 
00180         trace_ = new struct tracerec[nrec_];
00181 
00182         if ((fp = fopen(name_, "rb")) == NULL) {
00183             printf("can't open file %s\n", name_);
00184             return -1;
00185         }
00186 
00187         for (i = 0, t = trace_; i < nrec_; i++, t++)
00188             if (fread((char *)t, sizeof(tracerec), 1, fp) != 1) {
00189                 printf("read failed\n");
00190                 return -1 ;
00191             }
00192             else {
00193         
00194                 t->trec_time = ntohl(t->trec_time);
00195                 t->trec_size = ntohl(t->trec_size);
00196             }
00197 
00198     }
00199 
00200     /* pick a random starting place in the trace file */
00201     return (int(Random::uniform((double)nrec_)+.5));
00202 
00203 }
00204 
00205 void TraceFile::recv(Packet*, Handler*)
00206 {
00207         /* shouldn't get here */
00208         abort();
00209 }
00210 
00211 /**************************************************************/
00212 
00213 static class TrafficTraceClass : public TclClass {
00214  public:
00215     TrafficTraceClass() : TclClass("Application/Traffic/Trace") {}
00216     TclObject* create(int, const char*const*) {
00217             return(new TrafficTrace());
00218     }
00219 } class_traffictrace;
00220 
00221 TrafficTrace::TrafficTrace()
00222 {
00223     tfile_ = (TraceFile *)NULL;
00224 }
00225 
00226 void TrafficTrace::init()
00227 {
00228     if (tfile_) 
00229         ndx_ = tfile_->setup();
00230 }
00231 
00232 int TrafficTrace::command(int argc, const char*const* argv)
00233 {
00234     Tcl& tcl = Tcl::instance();
00235     
00236     if (argc == 3) {
00237         if (strcmp(argv[1], "attach-tracefile") == 0) {
00238             tfile_ = (TraceFile *)TclObject::lookup(argv[2]);
00239             if (tfile_ == 0) {
00240                 tcl.resultf("no such node %s", argv[2]);
00241                 return(TCL_ERROR);
00242             }
00243             return(TCL_OK);
00244         }
00245     }
00246 
00247     return (TrafficGenerator::command(argc, argv));
00248 
00249 }
00250 
00251 void TrafficTrace::timeout()
00252 {
00253         if (! running_)
00254                 return;
00255 
00256         /* send a packet */
00257     // Note:  May need to set "NEW_BURST" flag in sendmsg() for 
00258     // signifying a new talkspurt when using vat traces.
00259     // (see expoo.cc, tcl/ex/test-rcvr.tcl)
00260     agent_->sendmsg(size_);
00261         /* figure out when to send the next one */
00262         nextPkttime_ = next_interval(size_);
00263         /* schedule it */
00264         timer_.resched(nextPkttime_);
00265 }
00266 
00267 
00268 double TrafficTrace::next_interval(int& size)
00269 {
00270         tfile_->get_next(ndx_, trec_);
00271     size = trec_.trec_size;
00272     return(((double)trec_.trec_time)/1000000.0); /* usecs->secs */
00273 }

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