CSMAMacLayer.cc

00001 
00002 
00003 #include "CSMAMacLayer.h"
00004 #include "FWMath.h"
00005 #include "MacToPhyControlInfo.h"
00006 #include <BaseArp.h>
00007 #include <BaseConnectionManager.h>
00008 
00009 Define_Module( CSMAMacLayer )
00010 
00011 
00015 void CSMAMacLayer::initialize(int stage)
00016 {
00017     BaseMacLayer::initialize(stage);
00018 
00019     if (stage == 0) {
00020 
00021         queueLength = hasPar("queueLength")   ? par("queueLength").longValue()   : 10;
00022         //busyRSSI = hasPar("busyRSSI")       ? par("busyRSSI").doubleValue()    : -90;
00023         slotDuration = hasPar("slotDuration")   ? par("slotDuration").doubleValue()  : 0.1;
00024         difs = hasPar("difs")           ? par("difs").doubleValue()      : 0.001;
00025         maxTxAttempts = hasPar("maxTxAttempts") ? par("maxTxAttempts").longValue()   : 7;
00026         bitrate = hasPar("bitrate")       ? par("bitrate").doubleValue()     : 10000;
00027         txPower = hasPar("txPower")       ? par("txPower").doubleValue()     : 50;
00028         initialCW = hasPar("contentionWindow")  ? par("contentionWindow").longValue(): 31;
00029 
00030         macState = RX;
00031 
00032         //droppedPacket.setReason(DroppedPacket::NONE);
00033 
00034         //nicId = getParentModule()->getId();
00035 
00036         // initialize the timer
00037         backoffTimer = new cMessage("backoff");
00038         minorMsg = new cMessage("minClear");
00039 
00040         nbBackoffs = 0;
00041     backoffValues = 0;
00042     nbTxFrames = 0;
00043 
00044         txAttempts = 0;
00045     }
00046     else if(stage == 1) {
00047       BaseConnectionManager* cc = getConnectionManager();
00048 
00049       if(cc->hasPar("pMax") && txPower > cc->par("pMax").doubleValue())
00050             opp_error("TranmitterPower can't be bigger than pMax in ConnectionManager! "
00051                   "Please adjust your omnetpp.ini file accordingly.");
00052 
00053       if(phy->getRadioState() != Radio::RX) {
00054         opp_error("Initial radio state isn't RX but CSMAMacLayer"
00055               " assumes that the NIC starts in RX state.");
00056       }
00057 
00058       debugEV << "queueLength = " << queueLength
00059            //<< " busyRSSI = " << busyRSSI
00060            << " slotDuration = " << slotDuration
00061            << " difs = " << difs
00062            << " maxTxAttempts = " << maxTxAttempts
00063            << " bitrate = " << bitrate
00064            << " contentionWindow = " << initialCW << endl;
00065 
00066         //busyRSSI = FWMath::dBm2mW(busyRSSI);
00067     }
00068 }
00069 
00070 CSMAMacLayer::~CSMAMacLayer() {
00071   cancelAndDelete(backoffTimer);
00072   cancelAndDelete(minorMsg);
00073 
00074     for(MacQueue::iterator it = macQueue.begin();
00075     it != macQueue.end(); ++it)
00076     {
00077         delete (*it);
00078     }
00079     macQueue.clear();
00080 }
00081 
00082 void CSMAMacLayer::finish() {
00083   recordScalar("nbBackoffs", nbBackoffs);
00084   recordScalar("backoffDurations", backoffValues);
00085   recordScalar("nbTxFrames", nbTxFrames);
00086 
00087 
00088 }
00089 
00103 void CSMAMacLayer::handleUpperMsg(cMessage *msg)
00104 {
00105   cPacket* pkt = static_cast<cPacket*>(msg);
00106 
00107     //MacPkt *mac = encapsMsg(pkt);
00108 
00109     // message has to be queued if another message is waiting to be send
00110     // or if we are already trying to send another message
00111 
00112     if (macQueue.size() <= queueLength)
00113     {
00114         macQueue.push_back(pkt);
00115         debugEV   << "packet putt in queue\n  queue size:" << macQueue.size() << " macState:" << macState
00116       << " (RX=" << RX << ") is scheduled:" << backoffTimer->isScheduled() << endl;;
00117 
00118         if((macQueue.size() == 1) && (macState == RX) && !backoffTimer->isScheduled()) {
00119             scheduleBackoff();
00120         }
00121     }
00122     else {
00123         // queue is full, message has to be deleted
00124       EV << "New packet arrived, but queue is FULL, so new packet is deleted\n";
00125         MacPkt* mac = encapsMsg(pkt);
00126         mac->setName("MAC ERROR");
00127         mac->setKind(PACKET_DROPPED);
00128         sendControlUp(mac);
00129 
00130         //TODO: send packet drop bb info
00131         //droppedPacket.setReason(DroppedPacket::QUEUE);
00132         //utility->publishBBItem(catDroppedPacket, &droppedPacket, nicId);
00133     }
00134 }
00135 
00140 void CSMAMacLayer::handleSelfMsg(cMessage *msg)
00141 {
00142     if(msg == backoffTimer) {
00143       debugEV << "backoffTimer ";
00144 
00145         if(macState == RX) {
00146           debugEV << " RX ";
00147 
00148             if(macQueue.size() != 0) {
00149               macState = CCA;
00150 
00151                 if(phy->getRadioState() == Radio::RX) {
00152 
00153                     if(phy->getChannelState().isIdle()) {
00154                       debugEV << " idle ";
00155                         scheduleAt(simTime()+difs, minorMsg);
00156                     }
00157                     else{
00158                       macState = RX;
00159                       debugEV << " busy ";
00160                         scheduleBackoff();
00161                     }
00162                 }
00163             }
00164         }
00165         else {
00166           debugEV << "" << endl;
00167           debugEV << "state=" << macState << "(TX="<<TX<<", CCA="<<CCA<<")\n";
00168             error("backoffTimer expired, MAC in wrong state");
00169         }
00170     }
00171     else if(msg == minorMsg) {
00172       debugEV << " minorMsg ";
00173 
00174         //TODO: replace with channel sense request
00175         if((macState == CCA) && (phy->getRadioState() == Radio::RX)) {
00176 
00177             if(phy->getChannelState().isIdle()) {
00178               debugEV << " idle -> to send ";
00179                 macState = TX;
00180                 phy->setRadioState(Radio::TX);
00181             }
00182             else {
00183               debugEV << " busy -> backoff ";
00184                 macState = RX;
00185                 if(!backoffTimer->isScheduled())
00186                   scheduleBackoff();
00187             }
00188         }
00189         else {
00190             error("minClearTimer fired -- channel or mac in wrong state");
00191         }
00192     }
00193     debugEV << endl;
00194 }
00195 
00196 
00202 void CSMAMacLayer::handleLowerMsg(cMessage *msg)
00203 {
00204     MacPkt *mac = static_cast<MacPkt *>(msg);
00205     int dest = mac->getDestAddr();
00206 
00207     if(dest == myMacAddr || dest == L2BROADCAST)
00208     {
00209       debugEV << "sending pkt to upper...\n";
00210         sendUp(decapsMsg(mac));
00211     }
00212     else {
00213       debugEV << "packet not for me, deleting...\n";
00214         delete mac;
00215     }
00216 
00217     if(!backoffTimer->isScheduled()) scheduleBackoff();
00218 }
00219 
00220 void CSMAMacLayer::handleLowerControl(cMessage *msg)
00221 {
00222     if(msg->getKind() == MacToPhyInterface::TX_OVER) {
00223       debugEV << " transmission over" << endl;
00224         macState = RX;
00225         phy->setRadioState(Radio::RX);
00226         txAttempts = 0;
00227         if(!backoffTimer->isScheduled()) scheduleBackoff();
00228     }
00229     else if(msg->getKind() == MacToPhyInterface::RADIO_SWITCHING_OVER) {
00230       if((macState == TX) && (phy->getRadioState() == Radio::TX)) {
00231         debugEV << " radio switched to tx, sendDown packet" << endl;
00232             nbTxFrames++;
00233             sendDown(encapsMsg(macQueue.front()));
00234             macQueue.pop_front();
00235         }
00236     }
00237     else {
00238       EV << "control message with wrong kind -- deleting\n";
00239     }
00240     delete msg;
00241 }
00242 
00243 void CSMAMacLayer::scheduleBackoff()
00244 {
00245     if(backoffTimer->isScheduled()) {
00246         std::cerr << " is scheduled: MAC state "
00247                   << macState << " radio state : " << phy->getRadioState() << endl;
00248     }
00249 
00250     if(minorMsg->isScheduled()){
00251     cancelEvent( minorMsg );
00252     macState=RX;
00253   }
00254 
00255     if(txAttempts > maxTxAttempts) {
00256       debugEV << " drop packet " << endl;
00257 
00258         cMessage *mac = encapsMsg(macQueue.front());
00259         mac->setName("MAC ERROR");
00260         mac->setKind(PACKET_DROPPED);
00261         txAttempts = 0;
00262         macQueue.pop_front();
00263         sendControlUp(mac);
00264 
00265         //TODO: send packet drop bb info
00266         //droppedPacket.setReason(DroppedPacket::CHANNEL);
00267         //bb->publishBBItem(catDroppedPacket, &droppedPacket, nicId);
00268     }
00269 
00270     if(macQueue.size() != 0) {
00271       debugEV << " schedule backoff " << endl;
00272 
00273         double slots = intrand(initialCW + txAttempts) + 1.0 + dblrand();
00274         double time = slots * slotDuration;
00275 
00276         txAttempts++;
00277         debugEV << " attempts so far: " << txAttempts  << " " << endl;
00278 
00279     nbBackoffs = nbBackoffs + 1;
00280     backoffValues = backoffValues + time;
00281 
00282         scheduleAt(simTime() + time, backoffTimer);
00283     }
00284 
00285 }
00286 
00287 MacPkt* CSMAMacLayer::encapsMsg(cPacket *pkt)
00288 {
00289   MacPkt* macPkt = BaseMacLayer::encapsMsg(pkt);
00290 
00291   //calc signal duration
00292   simtime_t duration = macPkt->getBitLength() / bitrate;
00293 
00294   if(duration > slotDuration) {
00295     EV << "Warning: Sending packet " << pkt
00296        << " - duration (" << duration
00297        << " ) is bigger than the slot duration (" << slotDuration
00298        <<")." << endl;
00299   }
00300 
00301   //create signal
00302   Signal* s = createSignal(simTime(), duration, txPower, bitrate);
00303 
00304   //create and initialize control info
00305   MacToPhyControlInfo* ctrl = new MacToPhyControlInfo(s);
00306 
00307   macPkt->setControlInfo(ctrl);
00308 
00309   return macPkt;
00310 }
00311 
00312 
00313