Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

EtherBus.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 CTIE, Monash University
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef _MSC_VER
00020 #pragma warning(disable:4786)
00021 #endif
00022 
00023 #include <omnetpp.h>
00024 #include <vector>
00025 #include "EtherFrame_m.h"  // for EtherAutoconfig only
00026 #include "utils.h"
00027 
00028 // Direction of frame travel on bus; also used as selfmessage kind
00029 #define UPSTREAM        0
00030 #define DOWNSTREAM      1
00031 
00032 
00033 
00034 // Implements the physical locations on the bus where each network entity is connected to on the bus
00035 struct BusTap
00036 {
00037     int id;                         // which tap is this
00038     double position;                // Physical location of where each entity is connected to on the bus, (physical location of the tap on the bus)
00039     simtime_t propagationDelay[2];  // Propagation delays to the adjacent tap points on the bus: 0:upstream, 1:downstream
00040 };
00041 
00045 class EtherBus : public cSimpleModule
00046 {
00047     Module_Class_Members(EtherBus,cSimpleModule,0);
00048 
00049     virtual void initialize();
00050     virtual void handleMessage(cMessage*);
00051     virtual void finish();
00052 
00053     // tokenize string containing space-separated numbers into the array
00054     void tokenize(const char *str, std::vector<double>& array);
00055 
00056 private:
00057     double  propagationSpeed;  // propagation speed of electrical signals through copper
00058 
00059     BusTap *tap;  // physical locations of where the hosts is connected to the bus
00060     int taps;     // number of tap points on the bus
00061 
00062     long numMessages;             // number of messages handled
00063 };
00064 
00065 Define_Module(EtherBus);
00066 
00067 static cEnvir& operator<< (cEnvir& ev, cMessage *msg)
00068 {
00069     ev.printf("(%s)%s",msg->className(),msg->fullName());
00070     return ev;
00071 }
00072 
00073 void EtherBus::initialize()
00074 {
00075     numMessages = 0;
00076     WATCH(numMessages);
00077 
00078     propagationSpeed = par("propagationSpeed").doubleValue();
00079 
00080     // initialize the positions where the hosts connects to the bus
00081     taps = gate("in",0)->size();
00082     if (gate("out",0)->size()!=taps)
00083         error("the sizes of the in[] and out[] gate vectors must be the same");
00084 
00085     // read positions and check if positions are defined in order (we're lazy to sort...)
00086     std::vector<double> pos;
00087     tokenize(par("positions").stringValue(), pos);
00088     int numPos = pos.size();
00089     if (numPos>taps)
00090         ev << "Note: `positions' parameter contains more values ("<< numPos << ") than "
00091               "the number of taps (" << taps << "), ignoring excess values.\n";
00092     else if (numPos<taps && numPos>=2)
00093         ev << "Note: `positions' parameter contains less values ("<< numPos << ") than "
00094               "the number of taps (" << taps << "), repeating distance between last 2 positions.\n";
00095     else if (numPos<taps && numPos<2)
00096         ev << "Note: `positions' parameter contains too few values, using 5m distances.\n";
00097 
00098     tap = new BusTap[taps];
00099 
00100     int i;
00101     double distance = numPos>=2 ? pos[numPos-1]-pos[numPos-2] : 5;
00102     for (i=0; i<taps; i++)
00103     {
00104         tap[i].id = i;
00105         tap[i].position = i<numPos ? pos[i] : i==0 ? 5 : tap[i-1].position+distance;
00106     }
00107     for (i=0; i<taps-1; i++)
00108     {
00109         if (tap[i].position > tap[i+1].position)
00110             error("Tap positions must be ordered in ascending fashion, modify 'positions' parameter and rerun\n");
00111     }
00112 
00113     // Calculate propagation of delays between tap points on the bus
00114     for (i=0; i<taps; i++)
00115     {
00116         // Propagation delay between adjacent tap points
00117         if (i == 0) {
00118             tap[i].propagationDelay[UPSTREAM] = 0;
00119             tap[i].propagationDelay[DOWNSTREAM] = (tap[i+1].position - tap[i].position)/propagationSpeed;
00120         }
00121         else if (i == taps-1) {
00122             tap[i].propagationDelay[UPSTREAM] = tap[i-1].propagationDelay[DOWNSTREAM];
00123             tap[i].propagationDelay[DOWNSTREAM] = 0;
00124         }
00125         else {
00126             tap[i].propagationDelay[UPSTREAM] = tap[i-1].propagationDelay[DOWNSTREAM];
00127             tap[i].propagationDelay[DOWNSTREAM] = (tap[i+1].position - tap[i].position)/propagationSpeed;;
00128         }
00129     }
00130 
00131     // Prints out data of parameters for parameter checking...
00132     EV << "Parameters of (" << className() << ") " << fullPath() << "\n";
00133     EV << "propagationSpeed: " << propagationSpeed << "\n";
00134     for (i=0; i<taps; i++)
00135     {
00136         EV << "tap[" << i << "] pos: " << tap[i].position <<
00137               "  upstream delay: " << tap[i].propagationDelay[UPSTREAM] <<
00138               "  downstream delay: " << tap[i].propagationDelay[DOWNSTREAM] << endl;
00139     }
00140     EV << "\n";
00141 
00142     // autoconfig: tell everyone that bus supports only 10Mb half-duplex
00143     EV << "Autoconfig: advertising that we only support 10Mb half-duplex operation\n";
00144     for (i=0; i<taps; i++)
00145     {
00146         EtherAutoconfig *autoconf = new EtherAutoconfig("autoconf-10Mb-halfduplex");
00147         autoconf->setHalfDuplex(true);
00148         autoconf->setTxrate(10000000); // 10Mb
00149         send(autoconf,"out",i);
00150     }
00151 }
00152 
00153 void EtherBus::handleMessage (cMessage *msg)
00154 {
00155     if (!msg->isSelfMessage())
00156     {
00157         // Handle frame sent down from the network entity
00158         int tapPoint = msg->arrivalGate()->index();
00159         EV << "Frame " << msg << " arrived on tap " << tapPoint << endl;
00160 
00161         // create upstream and downstream events
00162         if (tapPoint>0)
00163         {
00164             // start UPSTREAM travel
00165             cMessage *event = new cMessage("upstream", UPSTREAM);
00166             event->setContextPointer(&tap[tapPoint-1]);
00167             // if goes downstream too, we need to make a copy
00168             cMessage *msg2 = (tapPoint<taps-1) ? (cMessage *)msg->dup() : msg;
00169             event->encapsulate(msg2);
00170             scheduleAt(simTime()+tap[tapPoint].propagationDelay[UPSTREAM], event);
00171         }
00172         if (tapPoint<taps-1)
00173         {
00174             // start DOWNSTREAM travel
00175             cMessage *event = new cMessage("downstream", DOWNSTREAM);
00176             event->setContextPointer(&tap[tapPoint+1]);
00177             event->encapsulate(msg);
00178             scheduleAt(simTime()+tap[tapPoint].propagationDelay[DOWNSTREAM], event);
00179         }
00180         if (taps==1)
00181         {
00182             // if there's only one tap, there's nothing to do
00183             delete msg;
00184         }
00185     }
00186     else
00187     {
00188         // handle upstream and downstream events
00189         int direction = msg->kind();
00190         BusTap *thistap = (BusTap *) msg->contextPointer();
00191         int tapPoint = thistap->id;
00192 
00193         EV << "Event " << msg << " on tap " << tapPoint << ", sending out frame\n";
00194 
00195         // send out on gate
00196         bool isLast = (direction==UPSTREAM) ? (tapPoint==0) : (tapPoint==taps-1);
00197         cMessage *msg2 = isLast ? msg->decapsulate() : (cMessage *)msg->encapsulatedMsg()->dup();
00198         send(msg2, "out", tapPoint);
00199 
00200         // if not end of the bus, schedule for next tap
00201         if (isLast)
00202         {
00203             EV << "End of bus reached\n";
00204             delete msg;
00205         }
00206         else
00207         {
00208             EV << "Scheduling for next tap\n";
00209             int nextTap = (direction==UPSTREAM) ? (tapPoint-1) : (tapPoint+1);
00210             msg->setContextPointer(&tap[nextTap]);
00211             scheduleAt(simTime()+tap[tapPoint].propagationDelay[direction], msg);
00212         }
00213     }
00214 }
00215 
00216 void EtherBus::tokenize(const char *str, std::vector<double>& array)
00217 {
00218     char *str2 = opp_strdup(str);
00219     char *s = strtok(str2, " ");
00220     while (s)
00221     {
00222         array.push_back(atof(s));
00223         s = strtok(NULL, " ");
00224     }
00225     delete [] str2;
00226 }
00227 
00228 
00229 void EtherBus::finish ()
00230 {
00231     if (par("writeScalars").boolValue())
00232     {
00233         double t = simTime();
00234         recordScalar("simulated time", t);
00235         recordScalar("messages handled", numMessages);
00236         if (t>0)
00237             recordScalar("messages/sec", numMessages/t);
00238     }
00239 }

Generated on Sat May 15 20:30:42 2004 for Ethernet by doxygen1.2.17