EtherBus.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 Andras Varga; CTIE, Monash University, Australia
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 #include "EtherBus.h"
00019 #include "EtherFrame_m.h"  // for EtherAutoconfig only
00020 
00021 Define_Module(EtherBus);
00022 
00023 static cEnvir& operator<< (cEnvir& out, cMessage *msg)
00024 {
00025     out.printf("(%s)%s",msg->getClassName(),msg->getFullName());
00026     return out;
00027 }
00028 
00029 EtherBus::EtherBus()
00030 {
00031     tap = NULL;
00032 }
00033 
00034 EtherBus::~EtherBus()
00035 {
00036     delete [] tap;
00037 }
00038 
00039 void EtherBus::initialize()
00040 {
00041     numMessages = 0;
00042     WATCH(numMessages);
00043 
00044     propagationSpeed = par("propagationSpeed").doubleValue();
00045 
00046     // initialize the positions where the hosts connects to the bus
00047     taps = gateSize("ethg");
00048 
00049     // read positions and check if positions are defined in order (we're lazy to sort...)
00050     std::vector<double> pos;
00051     tokenize(par("positions").stringValue(), pos);
00052     int numPos = pos.size();
00053     if (numPos>taps)
00054         EV << "Note: `positions' parameter contains more values ("<< numPos << ") than "
00055               "the number of taps (" << taps << "), ignoring excess values.\n";
00056     else if (numPos<taps && numPos>=2)
00057         EV << "Note: `positions' parameter contains less values ("<< numPos << ") than "
00058               "the number of taps (" << taps << "), repeating distance between last 2 positions.\n";
00059     else if (numPos<taps && numPos<2)
00060         EV << "Note: `positions' parameter contains too few values, using 5m distances.\n";
00061 
00062     tap = new BusTap[taps];
00063 
00064     int i;
00065     double distance = numPos>=2 ? pos[numPos-1]-pos[numPos-2] : 5;
00066     for (i=0; i<taps; i++)
00067     {
00068         tap[i].id = i;
00069         tap[i].position = i<numPos ? pos[i] : i==0 ? 5 : tap[i-1].position+distance;
00070     }
00071     for (i=0; i<taps-1; i++)
00072     {
00073         if (tap[i].position > tap[i+1].position)
00074             error("Tap positions must be ordered in ascending fashion, modify 'positions' parameter and rerun\n");
00075     }
00076 
00077     // Calculate propagation of delays between tap points on the bus
00078     for (i=0; i<taps; i++)
00079     {
00080         // Propagation delay between adjacent tap points
00081         if (i == 0) {
00082             tap[i].propagationDelay[UPSTREAM] = 0;
00083             tap[i].propagationDelay[DOWNSTREAM] = (tap[i+1].position - tap[i].position)/propagationSpeed;
00084         }
00085         else if (i == taps-1) {
00086             tap[i].propagationDelay[UPSTREAM] = tap[i-1].propagationDelay[DOWNSTREAM];
00087             tap[i].propagationDelay[DOWNSTREAM] = 0;
00088         }
00089         else {
00090             tap[i].propagationDelay[UPSTREAM] = tap[i-1].propagationDelay[DOWNSTREAM];
00091             tap[i].propagationDelay[DOWNSTREAM] = (tap[i+1].position - tap[i].position)/propagationSpeed;;
00092         }
00093     }
00094 
00095     // Prints out data of parameters for parameter checking...
00096     EV << "Parameters of (" << getClassName() << ") " << getFullPath() << "\n";
00097     EV << "propagationSpeed: " << propagationSpeed << "\n";
00098     for (i=0; i<taps; i++)
00099     {
00100         EV << "tap[" << i << "] pos: " << tap[i].position <<
00101               "  upstream delay: " << tap[i].propagationDelay[UPSTREAM] <<
00102               "  downstream delay: " << tap[i].propagationDelay[DOWNSTREAM] << endl;
00103     }
00104     EV << "\n";
00105 
00106     // autoconfig: tell everyone that bus supports only 10Mb half-duplex
00107     EV << "Autoconfig: advertising that we only support 10Mb half-duplex operation\n";
00108     for (i=0; i<taps; i++)
00109     {
00110         EtherAutoconfig *autoconf = new EtherAutoconfig("autoconf-10Mb-halfduplex");
00111         autoconf->setHalfDuplex(true);
00112         autoconf->setTxrate(10000000); // 10Mb
00113         send(autoconf,"ethg$o",i);
00114     }
00115 }
00116 
00117 void EtherBus::handleMessage (cMessage *msg)
00118 {
00119     if (!msg->isSelfMessage())
00120     {
00121         // Handle frame sent down from the network entity
00122         int tapPoint = msg->getArrivalGate()->getIndex();
00123         EV << "Frame " << msg << " arrived on tap " << tapPoint << endl;
00124 
00125         // create upstream and downstream events
00126         if (tapPoint>0)
00127         {
00128             // start UPSTREAM travel
00129             // if goes downstream too, we need to make a copy
00130             cMessage *msg2 = (tapPoint<taps-1) ? (cMessage *)msg->dup() : msg;
00131             msg2->setKind(UPSTREAM);
00132             msg2->setContextPointer(&tap[tapPoint-1]);
00133             scheduleAt(simTime()+tap[tapPoint].propagationDelay[UPSTREAM], msg2);
00134         }
00135         if (tapPoint<taps-1)
00136         {
00137             // start DOWNSTREAM travel
00138             msg->setKind(DOWNSTREAM);
00139             msg->setContextPointer(&tap[tapPoint+1]);
00140             scheduleAt(simTime()+tap[tapPoint].propagationDelay[DOWNSTREAM], msg);
00141         }
00142         if (taps==1)
00143         {
00144             // if there's only one tap, there's nothing to do
00145             delete msg;
00146         }
00147     }
00148     else
00149     {
00150         // handle upstream and downstream events
00151         int direction = msg->getKind();
00152         BusTap *thistap = (BusTap *) msg->getContextPointer();
00153         int tapPoint = thistap->id;
00154 
00155         EV << "Event " << msg << " on tap " << tapPoint << ", sending out frame\n";
00156 
00157         // send out on gate
00158         bool isLast = (direction==UPSTREAM) ? (tapPoint==0) : (tapPoint==taps-1);
00159         cPacket *msg2 = isLast ? PK(msg) : PK(msg->dup());
00160         send(msg2, "ethg$o", tapPoint);
00161 
00162         // if not end of the bus, schedule for next tap
00163         if (isLast)
00164         {
00165             EV << "End of bus reached\n";
00166         }
00167         else
00168         {
00169             EV << "Scheduling for next tap\n";
00170             int nextTap = (direction==UPSTREAM) ? (tapPoint-1) : (tapPoint+1);
00171             msg->setContextPointer(&tap[nextTap]);
00172             scheduleAt(simTime()+tap[tapPoint].propagationDelay[direction], msg);
00173         }
00174     }
00175 }
00176 
00177 void EtherBus::tokenize(const char *str, std::vector<double>& array)
00178 {
00179     char *str2 = opp_strdup(str);
00180     if (!str2) return;
00181         char *s = strtok(str2, " ");
00182     while (s)
00183     {
00184         array.push_back(atof(s));
00185         s = strtok(NULL, " ");
00186     }
00187     delete [] str2;
00188 }
00189 
00190 
00191 void EtherBus::finish ()
00192 {
00193     simtime_t t = simTime();
00194     recordScalar("simulated time", t);
00195     recordScalar("messages handled", numMessages);
00196     if (t>0)
00197         recordScalar("messages/sec", numMessages/t);
00198 }