NAMTraceWriter.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <omnetpp.h>
00021 #include "NAMTrace.h"
00022 #include "NAMTraceWriter.h"
00023 #include "NotificationBoard.h"
00024 #include "TxNotifDetails.h"
00025 #include "IInterfaceTable.h"
00026 #include "InterfaceTableAccess.h"
00027 
00028 Define_Module(NAMTraceWriter);
00029 
00030 
00031 void NAMTraceWriter::initialize(int stage)
00032 {
00033     if (stage==1)  // let NAMTrace module initialize in stage 0
00034     {
00035         // get pointer to the NAMTrace module
00036         cModule *namMod = simulation.getModuleByPath("nam");
00037         if (!namMod)
00038         {
00039             nt = NULL;
00040             EV << "NAMTraceWriter: nam module not found, no trace will be written\n";
00041             return;
00042         }
00043 
00044         // store ptr to namtrace module
00045         nt = check_and_cast<NAMTrace*>(namMod);
00046 
00047         // register given namid; -1 means autoconfigure
00048         int namid0 = par("namid");
00049         cModule *node = getParentModule();  // the host or router
00050         namid = nt->assignNamId(node, namid0);
00051         if (namid0==-1)
00052             par("namid") = namid;  // let parameter reflect autoconfigured namid
00053 
00054         // write "node" entry to the trace
00055         if (nt->isEnabled())
00056             recordNodeEvent("UP", "circle");
00057 
00058         // subscribe to the interesting notifications
00059         NotificationBoard *nb = NotificationBoardAccess().get();
00060         nb->subscribe(this, NF_NODE_FAILURE);
00061         nb->subscribe(this, NF_NODE_RECOVERY);
00062         nb->subscribe(this, NF_PP_TX_BEGIN);
00063         nb->subscribe(this, NF_PP_RX_END);
00064         nb->subscribe(this, NF_L2_Q_DROP);
00065     }
00066     else if (stage==2 && nt!=NULL && nt->isEnabled())
00067     {
00068         // write "link" entries
00069         IInterfaceTable *ift = InterfaceTableAccess().get();
00070         cModule *node = getParentModule();  // the host or router
00071         for (int i=0; i<ift->getNumInterfaces(); i++)
00072         {
00073             // skip loopback interfaces
00074             InterfaceEntry *ie = ift->getInterface(i);
00075             if (ie->isLoopback()) continue;
00076             if (!ie->isPointToPoint()) continue; // consider pont-to-point links only
00077 
00078             // fill in peerNamIds in InterfaceEntries
00079             cGate *outgate = node->gate(ie->getNodeOutputGateId());
00080             if (!outgate || !outgate->getNextGate()) continue;
00081             cModule *peernode = outgate->getNextGate()->getOwnerModule(); // FIXME not entirely correct: what if a subnet is "boxed"?
00082             cModule *peerwriter = peernode->getSubmodule("namTrace");
00083             if (!peerwriter) error("module %s doesn't have a submodule named namTrace", peernode->getFullPath().c_str());
00084             int peernamid = peerwriter->par("namid");
00085             ie->setPeerNamId(peernamid);
00086 
00087             // find delay
00088             simtime_t delay = 0;
00089             cDatarateChannel *chan = dynamic_cast<cDatarateChannel*>(outgate->getChannel());
00090             if (chan) delay = chan->getDelay();
00091 
00092             // write link entry into trace
00093             recordLinkEvent(peernamid, ie->getDatarate(), delay, "UP");
00094         }
00095     }
00096 }
00097 
00098 NAMTraceWriter::~NAMTraceWriter()
00099 {
00100 /*FIXME this will crash if the "nt" module gets cleaned up sooner than this one
00101     if (nt && nt->isEnabled())
00102     {
00103         recordNodeEvent("DOWN", "circle");
00104     }
00105 */
00106 }
00107 
00108 
00109 void NAMTraceWriter::receiveChangeNotification(int category, const cPolymorphic *details)
00110 {
00111     // don't do anything if global NAMTrace module doesn't exist or does not have a file open
00112     if (!nt || !nt->isEnabled())
00113         return;
00114 
00115     printNotificationBanner(category, details);
00116 
00117     // process notification
00118     if (category==NF_PP_TX_BEGIN || category==NF_PP_RX_END || category==NF_L2_Q_DROP)
00119     {
00120         TxNotifDetails *d = check_and_cast<TxNotifDetails *>(details);
00121         int peernamid = d->getInterfaceEntry()->getPeerNamId();
00122         cPacket *msg = d->getPacket();
00123 
00124         switch(category)
00125         {
00126             case NF_PP_TX_BEGIN: recordPacketEvent('h', peernamid, msg); break;
00127             case NF_PP_RX_END:   recordPacketEvent('r', peernamid, msg); break;
00128             case NF_L2_Q_DROP:   recordPacketEvent('d', peernamid, msg); break;
00129         }
00130     }
00131     else
00132     {
00133         switch(category)
00134         {
00135             case NF_NODE_FAILURE: break; // TODO
00136             case NF_NODE_RECOVERY: break; // TODO
00137         }
00138     }
00139 }
00140 
00141 void NAMTraceWriter::recordNodeEvent(const char *state, const char *shape)
00142 {
00143     ASSERT(nt && nt->isEnabled());
00144     std::ostream& out = nt->out();
00145     out << "n -t ";
00146     if (simTime() == 0.0)
00147         out << "*";
00148     else
00149         out << simTime();
00150     out << " -s " << namid << " -a " << namid << " -S " << state << " -v " << shape << endl;
00151 }
00152 
00153 void NAMTraceWriter::recordLinkEvent(int peernamid, double datarate, simtime_t delay, const char *state)
00154 {
00155     ASSERT(nt && nt->isEnabled());
00156     std::ostream& out = nt->out();
00157 
00158     // link entry (to be registered ON ONE END ONLY! This also means that
00159     // ns2 thinks that datarate and delay must be the same in both directions)
00160     if (namid < peernamid)
00161         out << "l -t * -s " << namid << " -d " << peernamid
00162             << " -S " << state << " -r " << (int)datarate << " -D " << delay << endl;
00163 
00164     // queue entry
00165     out << "q -t * -s " << namid << " -d " << peernamid << " -a 0 " << endl;
00166 }
00167 
00168 void NAMTraceWriter::recordPacketEvent(char event, int peernamid, cPacket *msg)
00169 {
00170     ASSERT(nt && nt->isEnabled());
00171     std::ostream& out = nt->out();
00172 
00173     int size = msg->getByteLength();
00174     int color = 0;
00175     for (cPacket *em = msg; em; em = em->getEncapsulatedMsg())
00176         if (em->hasPar("color"))
00177             {color = em->par("color").longValue(); break;}
00178 
00179     out << event << " -t " << simTime();
00180     if (event=='h')
00181         out << " -s " << namid << " -d " << peernamid;
00182     else
00183         out << " -s " << peernamid << " -d " << namid;
00184 
00185     out << " -e " << size << " -a " << color << endl;
00186 }
00187