Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "EtherBus.h"
00019 #include "EtherFrame_m.h"
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
00047 taps = gateSize("ethg");
00048
00049
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
00078 for (i=0; i<taps; i++)
00079 {
00080
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
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
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);
00113 send(autoconf,"ethg$o",i);
00114 }
00115 }
00116
00117 void EtherBus::handleMessage (cMessage *msg)
00118 {
00119 if (!msg->isSelfMessage())
00120 {
00121
00122 int tapPoint = msg->getArrivalGate()->getIndex();
00123 EV << "Frame " << msg << " arrived on tap " << tapPoint << endl;
00124
00125
00126 if (tapPoint>0)
00127 {
00128
00129
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
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
00145 delete msg;
00146 }
00147 }
00148 else
00149 {
00150
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
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
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 }