00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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"
00026 #include "utils.h"
00027
00028
00029 #define UPSTREAM 0
00030 #define DOWNSTREAM 1
00031
00032
00033
00034
00035 struct BusTap
00036 {
00037 int id;
00038 double position;
00039 simtime_t propagationDelay[2];
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
00054 void tokenize(const char *str, std::vector<double>& array);
00055
00056 private:
00057 double propagationSpeed;
00058
00059 BusTap *tap;
00060 int taps;
00061
00062 long numMessages;
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
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
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
00114 for (i=0; i<taps; i++)
00115 {
00116
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
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
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);
00149 send(autoconf,"out",i);
00150 }
00151 }
00152
00153 void EtherBus::handleMessage (cMessage *msg)
00154 {
00155 if (!msg->isSelfMessage())
00156 {
00157
00158 int tapPoint = msg->arrivalGate()->index();
00159 EV << "Frame " << msg << " arrived on tap " << tapPoint << endl;
00160
00161
00162 if (tapPoint>0)
00163 {
00164
00165 cMessage *event = new cMessage("upstream", UPSTREAM);
00166 event->setContextPointer(&tap[tapPoint-1]);
00167
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
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
00183 delete msg;
00184 }
00185 }
00186 else
00187 {
00188
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
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
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 }