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

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.14 2001/05/15 21:19:27 alefiyah 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: %d\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 Apr 20 12:14:33 2004 for NS2.26SourcesOriginal by doxygen 1.3.3