00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <omnetpp.h>
00021 #include "IInterfaceTable.h"
00022 #include "InterfaceTableAccess.h"
00023 #include "PPP.h"
00024 #include "IPassiveQueue.h"
00025 #include "NotificationBoard.h"
00026 #include "NotifierConsts.h"
00027
00028
00029
00030 Define_Module(PPP);
00031
00032 PPP::PPP()
00033 {
00034 endTransmissionEvent = NULL;
00035 nb = NULL;
00036 }
00037
00038 PPP::~PPP()
00039 {
00040
00041 if (nb && nb == findModuleWhereverInNode("notificationBoard", this))
00042 nb->unsubscribe(this, NF_SUBSCRIBERLIST_CHANGED);
00043 cancelAndDelete(endTransmissionEvent);
00044 }
00045
00046 void PPP::initialize(int stage)
00047 {
00048
00049 if (stage==0)
00050 {
00051 txQueue.setName("txQueue");
00052 endTransmissionEvent = new cMessage("pppEndTxEvent");
00053
00054 txQueueLimit = par("txQueueLimit");
00055
00056 interfaceEntry = NULL;
00057
00058 numSent = numRcvdOK = numBitErr = numDroppedIfaceDown = 0;
00059 WATCH(numSent);
00060 WATCH(numRcvdOK);
00061 WATCH(numBitErr);
00062 WATCH(numDroppedIfaceDown);
00063
00064
00065 queueModule = NULL;
00066 if (par("queueModule").stringValue()[0])
00067 {
00068 cModule *mod = getParentModule()->getSubmodule(par("queueModule").stringValue());
00069 queueModule = check_and_cast<IPassiveQueue *>(mod);
00070 }
00071
00072
00073 physOutGate = gate("phys$o");
00074
00075
00076 bool connected = physOutGate->getPathEndGate()->getType()==cGate::INPUT;
00077
00078
00079 datarateChannel = connected ? physOutGate->getTransmissionChannel() : NULL;
00080 double datarate = connected ? datarateChannel->par("datarate").doubleValue() : 0;
00081
00082
00083 interfaceEntry = registerInterface(datarate);
00084
00085
00086 nb = NotificationBoardAccess().get();
00087 notifDetails.setInterfaceEntry(interfaceEntry);
00088 nb->subscribe(this, NF_SUBSCRIBERLIST_CHANGED);
00089 updateHasSubcribers();
00090
00091
00092 if (ev.isGUI())
00093 {
00094 if (connected) {
00095 oldConnColor = datarateChannel->getDisplayString().getTagArg("ls",0);
00096 }
00097 else {
00098
00099 getDisplayString().setTagArg("i",1,"#707070");
00100 getDisplayString().setTagArg("i",2,"100");
00101 }
00102 }
00103
00104
00105 if (queueModule)
00106 {
00107 EV << "Requesting first frame from queue module\n";
00108 queueModule->requestPacket();
00109 }
00110 }
00111
00112
00113 if (stage==3)
00114 {
00115 updateDisplayString();
00116 }
00117 }
00118
00119 InterfaceEntry *PPP::registerInterface(double datarate)
00120 {
00121 InterfaceEntry *e = new InterfaceEntry();
00122
00123
00124 char *interfaceName = new char[strlen(getParentModule()->getFullName())+1];
00125 char *d=interfaceName;
00126 for (const char *s=getParentModule()->getFullName(); *s; s++)
00127 if (isalnum(*s))
00128 *d++ = *s;
00129 *d = '\0';
00130
00131 e->setName(interfaceName);
00132 delete [] interfaceName;
00133
00134
00135 e->setDatarate(datarate);
00136
00137
00138 InterfaceToken token(0, simulation.getUniqueNumber(), 64);
00139 e->setInterfaceToken(token);
00140
00141
00142
00143 e->setMtu(par("mtu"));
00144
00145
00146 e->setMulticast(true);
00147 e->setPointToPoint(true);
00148
00149
00150 IInterfaceTable *ift = InterfaceTableAccess().get();
00151 ift->addInterface(e, this);
00152
00153 return e;
00154 }
00155
00156
00157 void PPP::startTransmitting(cPacket *msg)
00158 {
00159
00160 delete msg->removeControlInfo();
00161 PPPFrame *pppFrame = encapsulate(msg);
00162 if (ev.isGUI()) displayBusy();
00163
00164 if (hasSubscribers)
00165 {
00166
00167 notifDetails.setPacket(pppFrame);
00168 nb->fireChangeNotification(NF_PP_TX_BEGIN, ¬ifDetails);
00169 }
00170
00171
00172 EV << "Starting transmission of " << pppFrame << endl;
00173 send(pppFrame, physOutGate);
00174
00175
00176 simtime_t endTransmissionTime = datarateChannel->getTransmissionFinishTime();
00177 scheduleAt(endTransmissionTime, endTransmissionEvent);
00178 }
00179
00180 void PPP::handleMessage(cMessage *msg)
00181 {
00182 if (datarateChannel==NULL)
00183 {
00184 EV << "Interface is not connected, dropping packet " << msg << endl;
00185 delete msg;
00186 numDroppedIfaceDown++;
00187 }
00188 else if (msg==endTransmissionEvent)
00189 {
00190
00191 EV << "Transmission finished.\n";
00192 if (ev.isGUI()) displayIdle();
00193
00194 if (hasSubscribers)
00195 {
00196
00197 notifDetails.setPacket(NULL);
00198 nb->fireChangeNotification(NF_PP_TX_END, ¬ifDetails);
00199 }
00200
00201 if (!txQueue.empty())
00202 {
00203 cPacket *pk = (cPacket *) txQueue.pop();
00204 startTransmitting(pk);
00205 numSent++;
00206 }
00207 else if (queueModule)
00208 {
00209
00210 queueModule->requestPacket();
00211 }
00212 }
00213 else if (msg->arrivedOn("phys$i"))
00214 {
00215 if (hasSubscribers)
00216 {
00217
00218 notifDetails.setPacket(PK(msg));
00219 nb->fireChangeNotification(NF_PP_RX_END, ¬ifDetails);
00220 }
00221
00222
00223 if (PK(msg)->hasBitError())
00224 {
00225 EV << "Bit error in " << msg << endl;
00226 numBitErr++;
00227 delete msg;
00228 }
00229 else
00230 {
00231
00232 cPacket *payload = decapsulate(check_and_cast<PPPFrame *>(msg));
00233 numRcvdOK++;
00234 send(payload,"netwOut");
00235 }
00236 }
00237 else
00238 {
00239 if (endTransmissionEvent->isScheduled())
00240 {
00241
00242 EV << "Received " << msg << " for transmission but transmitter busy, queueing.\n";
00243 if (ev.isGUI() && txQueue.length()>=3) getDisplayString().setTagArg("i",1,"red");
00244
00245 if (txQueueLimit && txQueue.length()>txQueueLimit)
00246 error("txQueue length exceeds %d -- this is probably due to "
00247 "a bogus app model generating excessive traffic "
00248 "(or if this is normal, increase txQueueLimit!)",
00249 txQueueLimit);
00250
00251 txQueue.insert(msg);
00252 }
00253 else
00254 {
00255
00256 EV << "Received " << msg << " for transmission\n";
00257 startTransmitting(PK(msg));
00258 numSent++;
00259 }
00260 }
00261
00262 if (ev.isGUI())
00263 updateDisplayString();
00264
00265 }
00266
00267 void PPP::displayBusy()
00268 {
00269 getDisplayString().setTagArg("i",1, txQueue.length()>=3 ? "red" : "yellow");
00270 datarateChannel->getDisplayString().setTagArg("ls",0,"yellow");
00271 datarateChannel->getDisplayString().setTagArg("ls",1,"3");
00272 }
00273
00274 void PPP::displayIdle()
00275 {
00276 getDisplayString().setTagArg("i",1,"");
00277 datarateChannel->getDisplayString().setTagArg("ls",0,oldConnColor.c_str());
00278 datarateChannel->getDisplayString().setTagArg("ls",1,"1");
00279 }
00280
00281 void PPP::updateDisplayString()
00282 {
00283 if (ev.isDisabled())
00284 {
00285
00286 getDisplayString().setTagArg("t",0,"");
00287 }
00288 else if (datarateChannel!=NULL)
00289 {
00290 double datarate = datarateChannel->par("datarate").doubleValue();
00291 char datarateText[40];
00292 if (datarate>=1e9) sprintf(datarateText,"%gG", datarate/1e9);
00293 else if (datarate>=1e6) sprintf(datarateText,"%gM", datarate/1e6);
00294 else if (datarate>=1e3) sprintf(datarateText,"%gK", datarate/1e3);
00295 else sprintf(datarateText,"%gbps", datarate);
00296
00297
00298
00299
00300
00301
00302 char buf[80];
00303 sprintf(buf, "%s\nrcv:%ld snt:%ld", datarateText, numRcvdOK, numSent);
00304
00305 if (numBitErr>0)
00306 sprintf(buf+strlen(buf), "\nerr:%ld", numBitErr);
00307
00308 getDisplayString().setTagArg("t",0,buf);
00309 }
00310 else
00311 {
00312 char buf[80];
00313 sprintf(buf, "not connected\ndropped:%ld", numDroppedIfaceDown);
00314 getDisplayString().setTagArg("t",0,buf);
00315 }
00316 }
00317
00318 void PPP::updateHasSubcribers()
00319 {
00320 hasSubscribers = nb->hasSubscribers(NF_PP_TX_BEGIN) ||
00321 nb->hasSubscribers(NF_PP_TX_END) ||
00322 nb->hasSubscribers(NF_PP_RX_END);
00323 }
00324
00325 void PPP::receiveChangeNotification(int category, const cPolymorphic *)
00326 {
00327 if (category==NF_SUBSCRIBERLIST_CHANGED)
00328 updateHasSubcribers();
00329 }
00330
00331 PPPFrame *PPP::encapsulate(cPacket *msg)
00332 {
00333 PPPFrame *pppFrame = new PPPFrame(msg->getName());
00334 pppFrame->setByteLength(PPP_OVERHEAD_BYTES);
00335 pppFrame->encapsulate(msg);
00336 return pppFrame;
00337 }
00338
00339 cPacket *PPP::decapsulate(PPPFrame *pppFrame)
00340 {
00341 cPacket *msg = pppFrame->decapsulate();
00342 delete pppFrame;
00343 return msg;
00344 }
00345
00346