empftp.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * empftp.cc
00005  * Copyright (C) 2001 by the University of Southern California
00006  * $Id: empftp.cc,v 1.5 2005/08/25 18:58:05 johnh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 //
00049 // Empirical FTP traffic model that simulates FTP traffic based on a set of
00050 // CDF (Cumulative Distribution Function) data derived from live tcpdump trace
00051 // The structure of this file is largely borrowed from empweb.cc
00052 //
00053 
00054 #include <tclcl.h>
00055 
00056 #include "empftp.h"
00057 
00058 
00059 int EmpFtpTrafSession::LASTFILE_ = 1;
00060 
00061 
00062 // XXX Must delete this after all pages are done!!
00063 EmpFtpTrafSession::~EmpFtpTrafSession() 
00064 {
00065 
00066     if (nFile_ != curFile_) {
00067         fprintf(stderr, "done files %d != all files %d\n",
00068             nFile_, curFile_);
00069         abort();
00070     }
00071     if (status_ != TIMER_IDLE) {
00072         fprintf(stderr, "EmpFtpTrafSession must be idle when deleted.\n");
00073         abort();
00074     }
00075 /*  
00076     if (rvInterPage_ != NULL)
00077         Tcl::instance().evalf("delete %s", rvInterPage_->name());
00078     if (rvPageSize_ != NULL)
00079         Tcl::instance().evalf("delete %s", rvPageSize_->name());
00080     if (rvInterObj_ != NULL)
00081         Tcl::instance().evalf("delete %s", rvInterObj_->name());
00082     if (rvObjSize_ != NULL)
00083         Tcl::instance().evalf("delete %s", rvObjSize_->name());
00084     if (rvReqSize_ != NULL)
00085         Tcl::instance().evalf("delete %s", rvReqSize_->name());
00086     if (rvPersistSel_ != NULL)
00087         Tcl::instance().evalf("delete %s", rvPersistSel_->name());
00088     if (rvServerSel_ != NULL)
00089         Tcl::instance().evalf("delete %s", rvServerSel_->name());
00090 
00091 */
00092 
00093 }
00094 
00095 
00096 // Launch the current file
00097 void EmpFtpTrafSession::expire(Event *)
00098 {
00099 
00100     if (curFile_ >= nFile_) return;
00101 
00102     sendFile(LASTFILE_++, (int)ceil(rvFileSize_->value()));
00103 
00104     if (mgr_->isdebug())
00105         printf("Session %d starting file %d, curfile %d \n", 
00106                id_, LASTFILE_-1, curFile_);
00107 
00108 }
00109 
00110 void EmpFtpTrafSession::handle(Event *e)
00111 {
00112         TimerHandler::handle(e);
00113         if (curFile_ < nFile_) {
00114                 // If this is not the last file, schedule the next
00115                 // one. Otherwise stop and tell session to delete itself.
00116                 curFile_++;
00117         sched(rvInterFile_->value());
00118         } else
00119             mgr_->doneSession(id_);
00120 }
00121 
00122 // Launch a request for a particular object
00123 void EmpFtpTrafSession::sendFile(int file, int size)
00124 {
00125 
00126     int wins = int(ceil(serverWin()->value()));
00127     int winc = int(ceil(clientWin()->value()));
00128     int window = (wins >= winc) ? wins : winc;
00129 
00130     // Choose source and dest TCP agents for both source and destination
00131 //  TcpAgent* ctcp = mgr_->picktcp(window);
00132     TcpAgent* stcp = mgr_->picktcp(window);
00133 //  TcpSink* csnk = mgr_->picksink();
00134     TcpSink* ssnk = mgr_->picksink();
00135 
00136     // Setup new TCP connection and launch request
00137     Tcl::instance().evalf("%s send-file %d %s %s %s %s %d %d", 
00138             mgr_->name(), file, src_->name(), 
00139             dst_->name(), stcp->name(), ssnk->name(), size, mgr_->color_);
00140 
00141 
00142     // Debug only
00143     // $numPacket_ $objectId_ $pageId_ $sessionId_ [$ns_ now] src dst
00144 
00145 if (mgr_->isdebug()) {
00146     printf("%d \t %d \t %d \t %g %d %d\n", size, file, id_,
00147            Scheduler::instance().clock(), 
00148            src_->address(), dst_->address());
00149     printf("** Tcp agents %d, Tcp sinks %d\n", mgr_->nTcp(),mgr_->nSink());
00150 }
00151 }
00152 
00153 
00154 static class EmpFtpTrafPoolClass : public TclClass {
00155 public:
00156         EmpFtpTrafPoolClass() : TclClass("PagePool/EmpFtpTraf") {}
00157         TclObject* create(int, const char*const*) {
00158         return (new EmpFtpTrafPool());
00159     }
00160 } class_empwebtrafpool;
00161 
00162 EmpFtpTrafPool::~EmpFtpTrafPool()
00163 {
00164     if (session_ != NULL) {
00165         for (int i = 0; i < nSession_; i++)
00166             delete session_[i];
00167         delete []session_;
00168     }
00169     if (server_ != NULL)
00170         delete []server_;
00171     if (client_ != NULL)
00172         delete []client_;
00173     // XXX Destroy tcpPool_ and sinkPool_ ?
00174 }
00175 
00176 void EmpFtpTrafPool::delay_bind_init_all()
00177 {
00178     delay_bind_init_one("debug_");
00179     PagePool::delay_bind_init_all();
00180 }
00181 
00182 int EmpFtpTrafPool::delay_bind_dispatch(const char *varName,const char *localName,
00183                      TclObject *tracer)
00184 {
00185     if (delay_bind_bool(varName, localName, "debug_", &debug_, tracer)) 
00186         return TCL_OK;
00187     return PagePool::delay_bind_dispatch(varName, localName, tracer);
00188 }
00189 
00190 EmpFtpTrafPool::EmpFtpTrafPool() : 
00191     nSrc_(0), server_(NULL), session_(NULL), nClient_(0), client_(NULL),
00192     nTcp_(0), nSink_(0)
00193 {
00194     LIST_INIT(&tcpPool_);
00195     LIST_INIT(&sinkPool_);
00196 }
00197 
00198 TcpAgent* EmpFtpTrafPool::picktcp(int win)
00199 {
00200 
00201     TcpAgent* a = (TcpAgent*)detachHead(&tcpPool_);
00202     if (a == NULL) {
00203         Tcl& tcl = Tcl::instance();
00204         tcl.evalf("%s alloc-tcp %d", name(), win);
00205         a = (TcpAgent*)lookup_obj(tcl.result());
00206         if (a == NULL) {
00207             fprintf(stderr, "Failed to allocate a TCP agent\n");
00208             abort();
00209         }
00210     } else 
00211         nTcp_--;
00212     return a;
00213 }
00214 
00215 TcpSink* EmpFtpTrafPool::picksink()
00216 {
00217     TcpSink* a = (TcpSink*)detachHead(&sinkPool_);
00218     if (a == NULL) {
00219         Tcl& tcl = Tcl::instance();
00220         tcl.evalf("%s alloc-tcp-sink", name());
00221         a = (TcpSink*)lookup_obj(tcl.result());
00222         if (a == NULL) {
00223             fprintf(stderr, "Failed to allocate a TCP sink\n");
00224             abort();
00225         }
00226     } else 
00227         nSink_--;
00228     return a;
00229 }
00230 
00231 int EmpFtpTrafPool::command(int argc, const char*const* argv)
00232 {
00233     if (argc == 3) {
00234         if (strcmp(argv[1], "set-num-session") == 0) {
00235             if (session_ != NULL) {
00236                 for (int i = 0; i < nSession_; i++) 
00237                     delete session_[i];
00238                 delete []session_;
00239             }
00240             nSession_ = atoi(argv[2]);
00241             session_ = new EmpFtpTrafSession*[nSession_];
00242             memset(session_, 0, sizeof(EmpFtpTrafSession*)*nSession_);
00243             return (TCL_OK);
00244         } else if (strcmp(argv[1], "set-num-server-lan") == 0) {
00245             nSrcL_ = atoi(argv[2]);
00246             if (nSrcL_ >  nSrc_) {
00247                 fprintf(stderr, "Wrong server index %d\n", nSrcL_);
00248                 return TCL_ERROR;
00249             }
00250             return (TCL_OK);
00251         } else if (strcmp(argv[1], "set-num-remote-client") == 0) {
00252             nClientL_ = atoi(argv[2]);
00253             if (nClientL_ > nClient_) {
00254                 fprintf(stderr, "Wrong client index %d\n", nClientL_);
00255                 return TCL_ERROR;
00256             }
00257             return (TCL_OK);
00258         } else if (strcmp(argv[1], "set-num-server") == 0) {
00259             nSrc_ = atoi(argv[2]);
00260             if (server_ != NULL) 
00261                 delete []server_;
00262             server_ = new Node*[nSrc_];
00263             return (TCL_OK);
00264         } else if (strcmp(argv[1], "set-num-client") == 0) {
00265             nClient_ = atoi(argv[2]);
00266             if (client_ != NULL) 
00267                 delete []client_;
00268             client_ = new Node*[nClient_];
00269             return (TCL_OK);
00270         }
00271     } else if (argc == 4) {
00272         if (strcmp(argv[1], "set-server") == 0) {
00273             Node* cli = (Node*)lookup_obj(argv[3]);
00274             if (cli == NULL)
00275                 return (TCL_ERROR);
00276             int nc = atoi(argv[2]);
00277             if (nc >= nSrc_) {
00278                 fprintf(stderr, "Wrong server index %d\n", nc);
00279                 return TCL_ERROR;
00280             }
00281             server_[nc] = cli;
00282             return (TCL_OK);
00283         } else if (strcmp(argv[1], "set-client") == 0) {
00284             Node* s = (Node*)lookup_obj(argv[3]);
00285             if (s == NULL)
00286                 return (TCL_ERROR);
00287             int n = atoi(argv[2]);
00288             if (n >= nClient_) {
00289                 fprintf(stderr, "Wrong client index %d\n", n);
00290                 return TCL_ERROR;
00291             }
00292             client_[n] = s;
00293             return (TCL_OK);
00294         } else if (strcmp(argv[1], "recycle") == 0) {
00295             // <obj> recycle <tcp> <sink>
00296             //
00297             // Recycle a TCP source/sink pair
00298             Agent* tcp = (Agent*)lookup_obj(argv[2]);
00299             Agent* snk = (Agent*)lookup_obj(argv[3]);
00300             nTcp_++, nSink_++;
00301             if ((tcp == NULL) || (snk == NULL))
00302                 return (TCL_ERROR);
00303             // XXX TBA: recycle tcp agents
00304             insertAgent(&tcpPool_, tcp);
00305             insertAgent(&sinkPool_, snk);
00306             return (TCL_OK);
00307         }
00308     } else if (argc == 12) {
00309         if (strcmp(argv[1], "create-session") == 0) {
00310             // <obj> create-session <session_index>
00311             //   <files_per_sess> <launch_time>
00312             //   <inter_file_rv> <file_size_rv>
00313             //   <server_sel_rv>
00314             //   <inbound/outbound flag>
00315             int n = atoi(argv[2]);
00316             if ((n < 0)||(n >= nSession_)||(session_[n] != NULL)) {
00317                 fprintf(stderr,"Invalid session index %d\n",n);
00318                 return (TCL_ERROR);
00319             }
00320             int nfile = (int)strtod(argv[3], NULL);
00321             double lt = strtod(argv[4], NULL);
00322 
00323             int flip = atoi(argv[10]);
00324             if ((flip < 0)||(flip > 1)) {
00325                 fprintf(stderr,"Invalid I/O flag %d\n",flip);
00326                 return (TCL_ERROR);
00327             }
00328 
00329             color_ = atoi(argv[11]);
00330 
00331             EmpFtpTrafSession* p = 
00332                 new EmpFtpTrafSession(this, nfile, n);
00333 
00334             int res = lookup_rv(p->interFile(), argv[5]);
00335             res = (res == TCL_OK) ? 
00336                 lookup_rv(p->fileSize(), argv[6]) : TCL_ERROR;
00337             res = (res == TCL_OK) ?
00338                     lookup_rv(p->serverSel(), argv[7]) : TCL_ERROR;
00339             res = (res == TCL_OK) ?
00340                     lookup_rv(p->serverWin(), argv[8]) : TCL_ERROR;
00341             res = (res == TCL_OK) ?
00342                     lookup_rv(p->clientWin(), argv[9]) : TCL_ERROR;
00343             if (res == TCL_ERROR) {
00344                 delete p;
00345                 fprintf(stderr, "Invalid random variable\n");
00346                 return (TCL_ERROR);
00347             }
00348 
00349                         int cl, svr;
00350             if (flip == 1) {
00351                             cl = int(floor(Random::uniform(0, nClientL_)));
00352                 svr=0;
00353             } else {
00354                             cl = int(floor(Random::uniform(nClientL_, nClient_)));
00355                     svr= int(ceil(p->serverSel()->value()));
00356             }
00357                         assert((cl >= 0) && (cl < nClient_));
00358             printf("%d %d\n",svr , nSrc_);
00359                 assert((svr >= 0) && (svr < nSrc_));
00360                         Node* c=client_[cl];
00361                 Node* s=server_[svr];
00362 
00363             p->setClient(c);
00364             p->setServer(s);
00365 
00366             p->sched(lt);
00367             session_[n] = p;
00368                
00369             return (TCL_OK);
00370         }
00371     }
00372     return PagePool::command(argc, argv);
00373 }
00374 
00375 

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