#include <PPP.h>
Public Member Functions | |
PPP () | |
virtual | ~PPP () |
Protected Member Functions | |
virtual InterfaceEntry * | registerInterface (double datarate) |
virtual void | startTransmitting (cPacket *msg) |
virtual PPPFrame * | encapsulate (cPacket *msg) |
virtual cPacket * | decapsulate (PPPFrame *pppFrame) |
virtual void | displayBusy () |
virtual void | displayIdle () |
virtual void | updateDisplayString () |
virtual void | updateHasSubcribers () |
virtual void | receiveChangeNotification (int category, const cPolymorphic *details) |
virtual int | numInitStages () const |
virtual void | initialize (int stage) |
virtual void | handleMessage (cMessage *msg) |
Protected Attributes | |
long | txQueueLimit |
cGate * | physOutGate |
cChannel * | datarateChannel |
cQueue | txQueue |
cMessage * | endTransmissionEvent |
IPassiveQueue * | queueModule |
InterfaceEntry * | interfaceEntry |
NotificationBoard * | nb |
TxNotifDetails | notifDetails |
bool | hasSubscribers |
std::string | oldConnColor |
long | numSent |
long | numRcvdOK |
long | numBitErr |
long | numDroppedIfaceDown |
PPP::PPP | ( | ) |
PPP::~PPP | ( | ) | [virtual] |
00039 { 00040 // kludgy way to check that nb is not deleted yet 00041 if (nb && nb == NotificationBoardAccess().getIfExists()) 00042 nb->unsubscribe(this, NF_SUBSCRIBERLIST_CHANGED); 00043 cancelAndDelete(endTransmissionEvent); 00044 }
InterfaceEntry * PPP::registerInterface | ( | double | datarate | ) | [protected, virtual] |
Referenced by initialize().
00120 { 00121 InterfaceEntry *e = new InterfaceEntry(); 00122 00123 // interface name: our module name without special characters ([]) 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 // data rate 00135 e->setDatarate(datarate); 00136 00137 // generate a link-layer address to be used as interface token for IPv6 00138 InterfaceToken token(0, simulation.getUniqueNumber(), 64); 00139 e->setInterfaceToken(token); 00140 00141 // MTU: typical values are 576 (Internet de facto), 1500 (Ethernet-friendly), 00142 // 4000 (on some point-to-point links), 4470 (Cisco routers default, FDDI compatible) 00143 e->setMtu(par("mtu")); 00144 00145 // capabilities 00146 e->setMulticast(true); 00147 e->setPointToPoint(true); 00148 00149 // add 00150 IInterfaceTable *ift = InterfaceTableAccess().get(); 00151 ift->addInterface(e, this); 00152 00153 return e; 00154 }
void PPP::startTransmitting | ( | cPacket * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
00158 { 00159 // if there's any control info, remove it; then encapsulate the packet 00160 delete msg->removeControlInfo(); 00161 PPPFrame *pppFrame = encapsulate(msg); 00162 if (ev.isGUI()) displayBusy(); 00163 00164 if (hasSubscribers) 00165 { 00166 // fire notification 00167 notifDetails.setPacket(pppFrame); 00168 nb->fireChangeNotification(NF_PP_TX_BEGIN, ¬ifDetails); 00169 } 00170 00171 // send 00172 EV << "Starting transmission of " << pppFrame << endl; 00173 send(pppFrame, physOutGate); 00174 00175 // schedule an event for the time when last bit will leave the gate. 00176 simtime_t endTransmissionTime = datarateChannel->getTransmissionFinishTime(); 00177 scheduleAt(endTransmissionTime, endTransmissionEvent); 00178 }
PPPFrame * PPP::encapsulate | ( | cPacket * | msg | ) | [protected, virtual] |
Referenced by startTransmitting().
00332 { 00333 PPPFrame *pppFrame = new PPPFrame(msg->getName()); 00334 pppFrame->setByteLength(PPP_OVERHEAD_BYTES); 00335 pppFrame->encapsulate(msg); 00336 return pppFrame; 00337 }
cPacket * PPP::decapsulate | ( | PPPFrame * | pppFrame | ) | [protected, virtual] |
Referenced by handleMessage().
00340 { 00341 cPacket *msg = pppFrame->decapsulate(); 00342 delete pppFrame; 00343 return msg; 00344 }
void PPP::displayBusy | ( | ) | [protected, virtual] |
Referenced by startTransmitting().
00268 { 00269 getDisplayString().setTagArg("i",1, txQueue.length()>=3 ? "red" : "yellow"); 00270 datarateChannel->getDisplayString().setTagArg("o",0,"yellow"); 00271 datarateChannel->getDisplayString().setTagArg("o",1,"3"); 00272 }
void PPP::displayIdle | ( | ) | [protected, virtual] |
Referenced by handleMessage().
00275 { 00276 getDisplayString().setTagArg("i",1,""); 00277 datarateChannel->getDisplayString().setTagArg("o",0,oldConnColor.c_str()); 00278 datarateChannel->getDisplayString().setTagArg("o",1,"1"); 00279 }
void PPP::updateDisplayString | ( | ) | [protected, virtual] |
Referenced by handleMessage(), and initialize().
00282 { 00283 if (ev.isDisabled()) 00284 { 00285 // speed up things 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 /* TBD find solution for displaying IP address without dependence on IPv6 or IPv6 00298 IPAddress addr = interfaceEntry->ipv4Data()->getIPAddress(); 00299 sprintf(buf, "%s / %s\nrcv:%ld snt:%ld", addr.isUnspecified()?"-":addr.str().c_str(), datarateText, numRcvdOK, numSent); 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 }
void PPP::updateHasSubcribers | ( | ) | [protected, virtual] |
Referenced by initialize(), and receiveChangeNotification().
00319 { 00320 hasSubscribers = nb->hasSubscribers(NF_PP_TX_BEGIN) || 00321 nb->hasSubscribers(NF_PP_TX_END) || 00322 nb->hasSubscribers(NF_PP_RX_END); 00323 }
void PPP::receiveChangeNotification | ( | int | category, | |
const cPolymorphic * | details | |||
) | [protected, virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
00326 { 00327 if (category==NF_SUBSCRIBERLIST_CHANGED) 00328 updateHasSubcribers(); 00329 }
void PPP::initialize | ( | int | stage | ) | [protected, virtual] |
00047 { 00048 // all initialization is done in the first stage 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 // find queueModule 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 // remember the output gate now, to speed up send() 00073 physOutGate = gate("phys$o"); 00074 00075 // we're connected if other end of connection path is an input gate 00076 bool connected = physOutGate->getPathEndGate()->getType()==cGate::INPUT; 00077 00078 // if we're connected, get the gate with transmission rate 00079 datarateChannel = connected ? physOutGate->getTransmissionChannel() : NULL; 00080 double datarate = connected ? datarateChannel->par("datarate").doubleValue() : 0; 00081 00082 // register our interface entry in IInterfaceTable 00083 interfaceEntry = registerInterface(datarate); 00084 00085 // prepare to fire notifications 00086 nb = NotificationBoardAccess().get(); 00087 notifDetails.setInterfaceEntry(interfaceEntry); 00088 nb->subscribe(this, NF_SUBSCRIBERLIST_CHANGED); 00089 updateHasSubcribers(); 00090 00091 // display string stuff 00092 if (ev.isGUI()) 00093 { 00094 if (connected) { 00095 oldConnColor = datarateChannel->getDisplayString().getTagArg("o",0); 00096 } 00097 else { 00098 // we are not connected: gray out our icon 00099 getDisplayString().setTagArg("i",1,"#707070"); 00100 getDisplayString().setTagArg("i",2,"100"); 00101 } 00102 } 00103 00104 // request first frame to send 00105 if (queueModule) 00106 { 00107 EV << "Requesting first frame from queue module\n"; 00108 queueModule->requestPacket(); 00109 } 00110 } 00111 00112 // update display string when addresses have been autoconfigured etc. 00113 if (stage==3) 00114 { 00115 updateDisplayString(); 00116 } 00117 }
void PPP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
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 // Transmission finished, we can start next one. 00191 EV << "Transmission finished.\n"; 00192 if (ev.isGUI()) displayIdle(); 00193 00194 if (hasSubscribers) 00195 { 00196 // fire notification 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 // tell queue module that we've become idle 00210 queueModule->requestPacket(); 00211 } 00212 } 00213 else if (msg->arrivedOn("phys$i")) 00214 { 00215 if (hasSubscribers) 00216 { 00217 // fire notification 00218 notifDetails.setPacket(PK(msg)); 00219 nb->fireChangeNotification(NF_PP_RX_END, ¬ifDetails); 00220 } 00221 00222 // check for bit errors 00223 if (PK(msg)->hasBitError()) 00224 { 00225 EV << "Bit error in " << msg << endl; 00226 numBitErr++; 00227 delete msg; 00228 } 00229 else 00230 { 00231 // pass up payload 00232 cPacket *payload = decapsulate(check_and_cast<PPPFrame *>(msg)); 00233 numRcvdOK++; 00234 send(payload,"netwOut"); 00235 } 00236 } 00237 else // arrived on gate "netwIn" 00238 { 00239 if (endTransmissionEvent->isScheduled()) 00240 { 00241 // We are currently busy, so just queue up the packet. 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 // We are idle, so we can start transmitting right away. 00256 EV << "Received " << msg << " for transmission\n"; 00257 startTransmitting(PK(msg)); 00258 numSent++; 00259 } 00260 } 00261 00262 if (ev.isGUI()) 00263 updateDisplayString(); 00264 00265 }
long PPP::txQueueLimit [protected] |
Referenced by handleMessage(), and initialize().
cGate* PPP::physOutGate [protected] |
Referenced by initialize(), and startTransmitting().
cChannel* PPP::datarateChannel [protected] |
Referenced by displayBusy(), displayIdle(), handleMessage(), initialize(), startTransmitting(), and updateDisplayString().
cQueue PPP::txQueue [protected] |
Referenced by displayBusy(), handleMessage(), and initialize().
cMessage* PPP::endTransmissionEvent [protected] |
Referenced by handleMessage(), initialize(), PPP(), startTransmitting(), and ~PPP().
IPassiveQueue* PPP::queueModule [protected] |
Referenced by handleMessage(), and initialize().
InterfaceEntry* PPP::interfaceEntry [protected] |
Referenced by initialize().
NotificationBoard* PPP::nb [protected] |
Referenced by handleMessage(), initialize(), PPP(), startTransmitting(), updateHasSubcribers(), and ~PPP().
TxNotifDetails PPP::notifDetails [protected] |
Referenced by handleMessage(), initialize(), and startTransmitting().
bool PPP::hasSubscribers [protected] |
Referenced by handleMessage(), startTransmitting(), and updateHasSubcribers().
std::string PPP::oldConnColor [protected] |
Referenced by displayIdle(), and initialize().
long PPP::numSent [protected] |
Referenced by handleMessage(), initialize(), and updateDisplayString().
long PPP::numRcvdOK [protected] |
Referenced by handleMessage(), initialize(), and updateDisplayString().
long PPP::numBitErr [protected] |
Referenced by handleMessage(), initialize(), and updateDisplayString().
long PPP::numDroppedIfaceDown [protected] |
Referenced by handleMessage(), initialize(), and updateDisplayString().