#include <PPP.h>
Public Member Functions | |
PPP () | |
virtual | ~PPP () |
Protected Member Functions | |
InterfaceEntry * | registerInterface (double datarate) |
void | startTransmitting (cMessage *msg) |
PPPFrame * | encapsulate (cMessage *msg) |
cMessage * | decapsulate (PPPFrame *pppFrame) |
void | displayBusy () |
void | displayIdle () |
void | updateDisplayString () |
virtual int | numInitStages () const |
virtual void | initialize (int stage) |
virtual void | handleMessage (cMessage *msg) |
Protected Attributes | |
bool | connected |
long | txQueueLimit |
cGate * | gateToWatch |
cQueue | txQueue |
cMessage * | endTransmissionEvent |
IPassiveQueue * | queueModule |
InterfaceEntry * | interfaceEntry |
double | datarate |
NotificationBoard * | nb |
TxNotifDetails | notifDetails |
std::string | oldConnColor |
long | numSent |
long | numRcvdOK |
long | numBitErr |
long | numDroppedIfaceDown |
PPP::PPP | ( | ) |
PPP::~PPP | ( | ) | [virtual] |
cMessage * PPP::decapsulate | ( | PPPFrame * | pppFrame | ) | [protected] |
void PPP::displayBusy | ( | ) | [protected] |
00279 { 00280 displayString().setTagArg("i",1, txQueue.length()>=3 ? "red" : "yellow"); 00281 gateToWatch->displayString().setTagArg("o",0,"yellow"); 00282 gateToWatch->displayString().setTagArg("o",1,"3"); 00283 gate("physOut")->displayString().setTagArg("o",0,"yellow"); 00284 gate("physOut")->displayString().setTagArg("o",1,"3"); 00285 }
void PPP::displayIdle | ( | ) | [protected] |
00288 { 00289 displayString().setTagArg("i",1,""); 00290 gateToWatch->displayString().setTagArg("o",0,oldConnColor.c_str()); 00291 gateToWatch->displayString().setTagArg("o",1,"1"); 00292 gate("physOut")->displayString().setTagArg("o",0,"black"); 00293 gate("physOut")->displayString().setTagArg("o",1,"1"); 00294 }
PPPFrame * PPP::encapsulate | ( | cMessage * | msg | ) | [protected] |
00331 { 00332 PPPFrame *pppFrame = new PPPFrame(msg->name()); 00333 pppFrame->setByteLength(PPP_OVERHEAD_BYTES); 00334 pppFrame->encapsulate(msg); 00335 return pppFrame; 00336 }
void PPP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
00193 { 00194 if (!connected) 00195 { 00196 EV << "Interface is not connected, dropping packet " << msg << endl; 00197 delete msg; 00198 numDroppedIfaceDown++; 00199 } 00200 else if (msg==endTransmissionEvent) 00201 { 00202 // Transmission finished, we can start next one. 00203 EV << "Transmission finished.\n"; 00204 if (ev.isGUI()) displayIdle(); 00205 00206 // fire notification 00207 notifDetails.setMessage(NULL); 00208 nb->fireChangeNotification(NF_PP_TX_END, ¬ifDetails); 00209 00210 if (!txQueue.empty()) 00211 { 00212 msg = (cMessage *) txQueue.getTail(); 00213 startTransmitting(msg); 00214 numSent++; 00215 } 00216 else if (queueModule) 00217 { 00218 // tell queue module that we've become idle 00219 queueModule->requestPacket(); 00220 } 00221 } 00222 else if (msg->arrivedOn("physIn")) 00223 { 00224 // fire notification 00225 notifDetails.setMessage(msg); 00226 nb->fireChangeNotification(NF_PP_RX_END, ¬ifDetails); 00227 00228 // check for bit errors 00229 if (msg->hasBitError()) 00230 { 00231 EV << "Bit error in " << msg << endl; 00232 numBitErr++; 00233 delete msg; 00234 } 00235 else 00236 { 00237 // pass up payload 00238 cMessage *payload = decapsulate(check_and_cast<PPPFrame *>(msg)); 00239 numRcvdOK++; 00240 00241 #ifndef _MAX_SPEED 00242 send(payload,"netwOut"); 00243 #else 00244 send(payload, gateIndexNetwOut); 00245 #endif 00246 } 00247 } 00248 else // arrived on gate "netwIn" 00249 { 00250 if (endTransmissionEvent->isScheduled()) 00251 { 00252 // We are currently busy, so just queue up the packet. 00253 EV << "Received " << msg << " for transmission but transmitter busy, queueing.\n"; 00254 if (ev.isGUI() && txQueue.length()>=3) displayString().setTagArg("i",1,"red"); 00255 00256 if (txQueueLimit && txQueue.length()>txQueueLimit) 00257 error("txQueue length exceeds %d -- this is probably due to " 00258 "a bogus app model generating excessive traffic " 00259 "(or if this is normal, increase txQueueLimit!)", 00260 txQueueLimit); 00261 00262 txQueue.insert(msg); 00263 } 00264 else 00265 { 00266 // We are idle, so we can start transmitting right away. 00267 EV << "Received " << msg << " for transmission\n"; 00268 startTransmitting(msg); 00269 numSent++; 00270 } 00271 } 00272 00273 if (ev.isGUI()) 00274 updateDisplayString(); 00275 00276 }
void PPP::initialize | ( | int | stage | ) | [protected, virtual] |
00044 { 00045 if (stage==3) 00046 { 00047 // update display string when addresses have been autoconfigured etc. 00048 updateDisplayString(); 00049 return; 00050 } 00051 00052 // all initialization is done in the first stage 00053 if (stage!=0) 00054 return; 00055 00056 txQueue.setName("txQueue"); 00057 endTransmissionEvent = new cMessage("pppEndTxEvent"); 00058 00059 txQueueLimit = par("txQueueLimit"); 00060 00061 interfaceEntry = NULL; 00062 00063 numSent = numRcvdOK = numBitErr = numDroppedIfaceDown = 0; 00064 WATCH(numSent); 00065 WATCH(numRcvdOK); 00066 WATCH(numBitErr); 00067 WATCH(numDroppedIfaceDown); 00068 00069 // find queueModule 00070 queueModule = NULL; 00071 if (par("queueModule").stringValue()[0]) 00072 { 00073 cModule *mod = parentModule()->submodule(par("queueModule").stringValue()); 00074 queueModule = check_and_cast<IPassiveQueue *>(mod); 00075 } 00076 00077 // we're connected if other end of connection path is an input gate 00078 cGate *physOut = gate("physOut"); 00079 connected = physOut->destinationGate()->type()=='I'; 00080 00081 // if we're connected, get the gate with transmission rate 00082 gateToWatch = physOut; 00083 datarate = 0; 00084 if (connected) 00085 { 00086 while (gateToWatch) 00087 { 00088 // does this gate have data rate? 00089 cSimpleChannel *chan = dynamic_cast<cSimpleChannel*>(gateToWatch->channel()); 00090 if (chan && (datarate=chan->datarate())>0) 00091 break; 00092 // otherwise just check next connection in path 00093 gateToWatch = gateToWatch->toGate(); 00094 } 00095 if (!gateToWatch) 00096 error("gate physOut must be connected (directly or indirectly) to a link with data rate"); 00097 00098 #ifdef _MAX_SPEED 00099 gateIndexPhysOut = gate("physOut")->id(); 00100 gateIndexNetwOut = gate("netwOut")->id(); 00101 #endif 00102 } 00103 00104 // register our interface entry in InterfaceTable 00105 interfaceEntry = registerInterface(datarate); 00106 00107 // prepare to fire notifications 00108 nb = NotificationBoardAccess().get(); 00109 notifDetails.setInterfaceEntry(interfaceEntry); 00110 00111 // if not connected, make it gray 00112 if (ev.isGUI()) 00113 { 00114 if (!connected) 00115 { 00116 displayString().setTagArg("i",1,"#707070"); 00117 displayString().setTagArg("i",2,"100"); 00118 } 00119 oldConnColor = gateToWatch->displayString().getTagArg("o",0); 00120 } 00121 00122 // request first frame to send 00123 if (queueModule) 00124 { 00125 EV << "Requesting first frame from queue module\n"; 00126 queueModule->requestPacket(); 00127 } 00128 }
InterfaceEntry * PPP::registerInterface | ( | double | datarate | ) | [protected] |
00131 { 00132 InterfaceEntry *e = new InterfaceEntry(); 00133 00134 // interface name: our module name without special characters ([]) 00135 char *interfaceName = new char[strlen(parentModule()->fullName())+1]; 00136 char *d=interfaceName; 00137 for (const char *s=parentModule()->fullName(); *s; s++) 00138 if (isalnum(*s)) 00139 *d++ = *s; 00140 *d = '\0'; 00141 00142 e->setName(interfaceName); 00143 delete [] interfaceName; 00144 00145 // data rate 00146 e->setDatarate(datarate); 00147 00148 // generate a link-layer address to be used as interface token for IPv6 00149 InterfaceToken token(0, simulation.getUniqueNumber(), 64); 00150 e->setInterfaceToken(token); 00151 00152 // MTU: typical values are 576 (Internet de facto), 1500 (Ethernet-friendly), 00153 // 4000 (on some point-to-point links), 4470 (Cisco routers default, FDDI compatible) 00154 e->setMtu(4470); 00155 00156 // capabilities 00157 e->setMulticast(true); 00158 e->setPointToPoint(true); 00159 00160 // add 00161 InterfaceTable *ift = InterfaceTableAccess().get(); 00162 ift->addInterface(e, this); 00163 00164 return e; 00165 }
void PPP::startTransmitting | ( | cMessage * | msg | ) | [protected] |
00169 { 00170 // if there's any control info, remove it; then encapsulate the packet 00171 delete msg->removeControlInfo(); 00172 PPPFrame *pppFrame = encapsulate(msg); 00173 if (ev.isGUI()) displayBusy(); 00174 00175 // fire notification 00176 notifDetails.setMessage(pppFrame); 00177 nb->fireChangeNotification(NF_PP_TX_BEGIN, ¬ifDetails); 00178 00179 // send 00180 #ifndef _MAX_SPEED 00181 EV << "Starting transmission of " << pppFrame << endl; 00182 send(pppFrame, "physOut"); 00183 #else 00184 send(pppFrame, gateIndexPhysOut); 00185 #endif 00186 00187 // schedule an event for the time when last bit will leave the gate. 00188 simtime_t endTransmission = gateToWatch->transmissionFinishes(); 00189 scheduleAt(endTransmission, endTransmissionEvent); 00190 }
void PPP::updateDisplayString | ( | ) | [protected] |
00297 { 00298 char buf[80]; 00299 if (ev.disabled()) 00300 { 00301 // speed up things 00302 displayString().setTagArg("t",0,""); 00303 } 00304 else if (connected) 00305 { 00306 char drate[40]; 00307 if (datarate>=1e9) sprintf(drate,"%gG", datarate/1e9); 00308 else if (datarate>=1e6) sprintf(drate,"%gM", datarate/1e6); 00309 else if (datarate>=1e3) sprintf(drate,"%gK", datarate/1e3); 00310 else sprintf(drate,"%gbps", datarate); 00311 00312 /* TBD FIXME find solution for displaying IP address without dependence on IPv6 or IPv6 00313 IPAddress addr = interfaceEntry->ipv4()->inetAddress(); 00314 sprintf(buf, "%s / %s\nrcv:%ld snt:%ld", addr.isUnspecified()?"-":addr.str().c_str(), drate, numRcvdOK, numSent); 00315 */ 00316 sprintf(buf, "%s\nrcv:%ld snt:%ld", drate, numRcvdOK, numSent); 00317 00318 if (numBitErr>0) 00319 sprintf(buf+strlen(buf), "\nerr:%ld", numBitErr); 00320 00321 displayString().setTagArg("t",0,buf); 00322 } 00323 else 00324 { 00325 sprintf(buf, "not connected\ndropped:%ld", numDroppedIfaceDown); 00326 displayString().setTagArg("t",0,buf); 00327 } 00328 }
bool PPP::connected [protected] |
double PPP::datarate [protected] |
cMessage* PPP::endTransmissionEvent [protected] |
cGate* PPP::gateToWatch [protected] |
InterfaceEntry* PPP::interfaceEntry [protected] |
NotificationBoard* PPP::nb [protected] |
TxNotifDetails PPP::notifDetails [protected] |
long PPP::numBitErr [protected] |
long PPP::numDroppedIfaceDown [protected] |
long PPP::numRcvdOK [protected] |
long PPP::numSent [protected] |
std::string PPP::oldConnColor [protected] |
IPassiveQueue* PPP::queueModule [protected] |
cQueue PPP::txQueue [protected] |
long PPP::txQueueLimit [protected] |