PPP Class Reference

#include <PPP.h>

Inheritance diagram for PPP:

INotifiable

List of all members.


Detailed Description

PPP implementation.

Public Member Functions

 PPP ()
virtual ~PPP ()

Protected Member Functions

virtual InterfaceEntryregisterInterface (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
IPassiveQueuequeueModule
InterfaceEntryinterfaceEntry
NotificationBoardnb
TxNotifDetails notifDetails
bool hasSubscribers
std::string oldConnColor
long numSent
long numRcvdOK
long numBitErr
long numDroppedIfaceDown

Constructor & Destructor Documentation

PPP::PPP (  ) 

00033 {
00034     endTransmissionEvent = NULL;
00035     nb = NULL;
00036 }

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 }


Member Function Documentation

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, &notifDetails);
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]

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 }

virtual int PPP::numInitStages (  )  const [inline, protected, virtual]

00076 {return 4;}

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, &notifDetails);
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, &notifDetails);
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 }


Member Data Documentation

long PPP::txQueueLimit [protected]

Referenced by handleMessage(), and initialize().

cGate* PPP::physOutGate [protected]

Referenced by initialize(), and startTransmitting().

cChannel* PPP::datarateChannel [protected]

cQueue PPP::txQueue [protected]

cMessage* PPP::endTransmissionEvent [protected]

Referenced by handleMessage(), and initialize().

Referenced by initialize().

NotificationBoard* PPP::nb [protected]

bool PPP::hasSubscribers [protected]

std::string PPP::oldConnColor [protected]

Referenced by displayIdle(), and initialize().

long PPP::numSent [protected]

long PPP::numRcvdOK [protected]

long PPP::numBitErr [protected]

long PPP::numDroppedIfaceDown [protected]


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:20 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5