tap.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1997, 1998 The Regents of the University of California.
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *  This product includes software developed by the MASH Research
00016  *  Group at the University of California, Berkeley.
00017  * 4. Neither the name of the University nor of the Research Group may be used
00018  *    to endorse or promote products derived from this software without
00019  *    specific prior written permission.
00020  * 
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #ifndef lint
00035 static const char rcsid[] =
00036     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/tap.cc,v 1.15 2005/08/22 05:08:33 tomh Exp $ (UCB)";
00037 #endif
00038 
00039 #include "tap.h"
00040 
00041 static class TapAgentClass : public TclClass {
00042  public:
00043     TapAgentClass() : TclClass("Agent/Tap") {}
00044     TclObject* create(int, const char*const*) {
00045         return (new TapAgent());
00046     }
00047 } class_tap_agent;
00048 
00049 TapAgent::TapAgent() : Agent(PT_LIVE), net_(NULL)
00050 {
00051     bind("maxpkt_", &maxpkt_);
00052 }
00053 
00054 //
00055 // link in a network to the agent.  Assumes net_ is non-zero
00056 //
00057 int
00058 TapAgent::linknet()
00059 {
00060     int mode = net_->mode();
00061     int rchan = net_->rchannel();
00062     int wchan = net_->schannel();
00063 
00064     unlink();
00065     if (mode == O_RDONLY || mode == O_RDWR) {
00066         // reading enabled?
00067         if (rchan < 0) {
00068             fprintf(stderr,
00069         "TapAgent(%s): network %s not open for reading (mode:%d)\n",
00070                 name(), net_->name(), mode);
00071             return (TCL_ERROR);
00072         }
00073         link(rchan, TCL_READABLE);
00074         TDEBUG3("TapAgent(%s): linked sock %d as READABLE\n",
00075             name(), rchan);
00076     } else if (mode != O_WRONLY) {
00077         if (mode == -1) {
00078             fprintf(stderr,
00079                "TapAgent(%s): Network(%s) not opened properly.\n",
00080                 name(), net_->name());
00081             fprintf(stderr,
00082                "(choose: readonly, readwrite, or writeonly)\n");
00083         } else {
00084             fprintf(stderr,
00085                 "TapAgent(%s): unknown mode %d in Network(%s)\n",
00086                 name(), mode, net_->name());
00087         }
00088         return (TCL_ERROR);
00089     }
00090 
00091     if (mode == O_WRONLY || mode == O_RDWR) {
00092         // writing enabled?
00093         if (wchan < 0) {
00094             fprintf(stderr,
00095             "TapAgent(%s): network %s not open for writing\n",
00096                 name(), net_->name());
00097             return (TCL_ERROR);
00098         }
00099     }
00100     return (TCL_OK);
00101 }
00102 
00103 int
00104 TapAgent::command(int argc, const char*const* argv)
00105 {
00106     Tcl& tcl = Tcl::instance();
00107 
00108     if (argc == 2) {
00109         if (strcmp(argv[1], "network") == 0) {
00110             tcl.result(name());
00111             return(TCL_OK);
00112         } 
00113     }
00114     if (argc == 3) {
00115         if (strcmp(argv[1], "network") == 0) {
00116             net_ = (Network *)TclObject::lookup(argv[2]);
00117             if (net_ != 0) {
00118                 return(linknet());
00119             } else {
00120                 fprintf(stderr,
00121                 "TapAgent(%s): unknown network %s\n",
00122                     name(), argv[2]);
00123                 return (TCL_ERROR);
00124             }
00125             return(TCL_OK);
00126         }   
00127     }
00128     return (Agent::command(argc, argv));
00129 }
00130 
00131 /*
00132  * Receive a packet off the network and inject into the simulation.
00133  */
00134 void
00135 TapAgent::recvpkt()
00136 {
00137 
00138     if (net_->mode() != O_RDWR && net_->mode() != O_RDONLY) {
00139         fprintf(stderr,
00140           "TapAgent(%s): recvpkt called while in write-only mode!\n",
00141           name());
00142         return;
00143     }
00144 
00145     if (maxpkt_ <= 0) {
00146         fprintf(stderr,
00147           "TapAgent(%s): recvpkt: maxpkt_ value too low (%d)\n",
00148           name(), maxpkt_);
00149         return;
00150     }
00151 
00152     // allocate packet and a data payload
00153     Packet* p = allocpkt(maxpkt_);
00154 
00155     // fill up payload
00156     sockaddr addr;  // not really used (yet)
00157     double tstamp;
00158     int cc = net_->recv(p->accessdata(), maxpkt_, addr, tstamp);
00159     if (cc <= 0) {
00160         if (cc < 0) {
00161             perror("recv");
00162         }
00163         Packet::free(p);
00164         return;
00165     }
00166 
00167     TDEBUG4("%f: Tap(%s): recvpkt, cc:%d\n", now(), name(), cc);
00168 
00169     // inject into simulator
00170     hdr_cmn* ch = HDR_CMN(p);
00171     ch->size() = cc;
00172 
00173     /*
00174      * if the time-stamp on the pkt is sufficiently far in the future,
00175      * put it in the scheduler instead of forwarding it immediately.
00176      * This can happen if we are pulling packet from a trace file
00177      * and we don't want them to be dispatched until later
00178      *
00179      * this agent assumes that the time stamps are in absolute
00180      * time, so adjust it to relative time here
00181      */
00182 
00183     double when = tstamp - now();
00184 
00185     if (when > 0.0) {
00186         TDEBUG5("%f: Tap(%s): DEFERRED PACKET %f secs, uid: "UID_PRINTF_FORMAT"\n",
00187             now(), name(), when, p->uid_);
00188         ch->timestamp() = when;
00189         Scheduler::instance().schedule(target_, p, when);
00190     } else {
00191         TDEBUG4("%f: Tap(%s): recvpkt, writing to target: %s\n",
00192             now(), name(), target_->name());
00193         ch->timestamp() = now();
00194         target_->recv(p);
00195     }
00196     return;
00197 }
00198 
00199 void
00200 TapAgent::dispatch(int)
00201 {
00202     /*
00203      * Just process one packet.  We could put a loop here
00204      * but instead we allow the dispatcher to call us back
00205      * if there is a queue in the socket buffer; this allows
00206      * other events to get a chance to slip in...
00207      */
00208 #ifdef notdef
00209 Scheduler::instance().sync();   // sim clock gets set to now
00210 #endif
00211     recvpkt();
00212 }
00213 
00214 /*
00215  * SIM -> Live
00216  *
00217  * Receive a packet from the simulation and inject into the network.
00218  * if there is no network attached, call Connector::drop() to send
00219  * to drop target
00220  */
00221 
00222 void
00223 TapAgent::recv(Packet* p, Handler*)
00224 {
00225     (void) sendpkt(p);
00226     Packet::free(p);
00227     return;
00228 }
00229 
00230 int
00231 TapAgent::sendpkt(Packet* p)
00232 {
00233     if (net_->mode() != O_RDWR && net_->mode() != O_WRONLY) {
00234         fprintf(stderr,
00235             "TapAgent(%s): sendpkt called while in read-only mode!\n",
00236             name());
00237         return (-1);
00238     }
00239 
00240     // send packet into the live network
00241     hdr_cmn* hc = HDR_CMN(p);
00242     if (net_ == NULL) {
00243         fprintf(stderr,
00244              "TapAgent(%s): sendpkt attempted with NULL net\n",
00245          name());
00246         drop(p);
00247         return (-1);
00248     }
00249     if (net_->send(p->accessdata(), hc->size()) < 0) {
00250         fprintf(stderr,
00251             "TapAgent(%s): sendpkt (%p, %d): %s\n",
00252             name(), p->accessdata(), hc->size(), strerror(errno));
00253         return (-1);
00254             
00255     }
00256     TDEBUG3("TapAgent(%s): sent packet (sz: %d)\n",
00257         name(), hc->size());
00258     return 0;
00259 }

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