00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 #include "BMacLayer.h"
00017 #include "FWMath.h"
00018 #include "MacToPhyControlInfo.h"
00019 #include <BaseArp.h>
00020 #include <BaseConnectionManager.h>
00021 #include <SimpleAddress.h>
00022 #include <NetwToMacControlInfo.h>
00023 
00024 Define_Module( BMacLayer )
00025 
00026 
00029 void BMacLayer::initialize(int stage)
00030 {
00031   BaseMacLayer::initialize(stage);
00032 
00033     if (stage == 0) {
00034 
00035         queueLength = hasPar("queueLength") ? par("queueLength") : 10;
00036     animation = hasPar("animation") ? par("animation") : true;
00037         slotDuration = hasPar("slotDuration") ? par("slotDuration") : 1;
00038         bitrate = hasPar("bitrate") ? par("bitrate") : 15360;
00039     headerLength = hasPar("headerLength") ? par("headerLength") : 10;
00040     checkInterval = hasPar("checkInterval") ? par("checkInterval") : 0.1;
00041     txPower = hasPar("txPower") ? par("txPower") : 50;
00042     useMacAcks = hasPar("useMACAcks") ? par("useMACAcks") : false;
00043     maxTxAttempts = hasPar("maxTxAttempts") ? par("maxTxAttempts") : 2;
00044     debugEV << "headerLength: " << headerLength << ", bitrate: " << bitrate << endl;
00045 
00046     stats = par("stats");
00047     nbTxDataPackets = 0;
00048     nbTxPreambles = 0;
00049     nbRxDataPackets = 0;
00050     nbRxPreambles = 0;
00051     nbMissedAcks = 0;
00052     nbRecvdAcks=0;
00053     nbDroppedDataPackets=0;
00054     nbTxAcks=0;
00055 
00056     txAttempts = 0;
00057     lastDataPktDestAddr = L2BROADCAST;
00058     lastDataPktSrcAddr = L2BROADCAST;
00059 
00060     macState = INIT;
00061 
00062     
00063     droppedPacket.setReason(DroppedPacket::NONE);
00064     nicId = getParentModule()->getId();
00065 
00066     catDroppedPacket = utility->getCategory(&droppedPacket);
00067     WATCH(macState);
00068     }
00069 
00070     else if(stage == 1) {
00071 
00072     wakeup = new cMessage("wakeup");
00073     wakeup->setKind(BMAC_WAKE_UP);
00074 
00075     data_timeout = new cMessage("data_timeout");
00076     data_timeout->setKind(BMAC_DATA_TIMEOUT);
00077     data_timeout->setSchedulingPriority(100);
00078 
00079     data_tx_over = new cMessage("data_tx_over");
00080     data_tx_over->setKind(BMAC_DATA_TX_OVER);
00081 
00082     stop_preambles = new cMessage("stop_preambles");
00083     stop_preambles->setKind(BMAC_STOP_PREAMBLES);
00084 
00085     send_preamble = new cMessage("send_preamble");
00086     send_preamble->setKind(BMAC_SEND_PREAMBLE);
00087 
00088     ack_tx_over = new cMessage("ack_tx_over");
00089     ack_tx_over->setKind(BMAC_ACK_TX_OVER);
00090 
00091     cca_timeout = new cMessage("cca_timeout");
00092     cca_timeout->setKind(BMAC_CCA_TIMEOUT);
00093     cca_timeout->setSchedulingPriority(100);
00094 
00095     send_ack = new cMessage("send_ack");
00096     send_ack->setKind(BMAC_SEND_ACK);
00097 
00098     start_bmac = new cMessage("start_bmac");
00099     start_bmac->setKind(BMAC_START_BMAC);
00100 
00101     ack_timeout = new cMessage("ack_timeout");
00102     ack_timeout->setKind(BMAC_ACK_TIMEOUT);
00103 
00104     resend_data = new cMessage("resend_data");
00105     resend_data->setKind(BMAC_RESEND_DATA);
00106     resend_data->setSchedulingPriority(100);
00107 
00108     scheduleAt(0.0, start_bmac);
00109     }
00110 }
00111 
00112 BMacLayer::~BMacLayer()
00113 {
00114   cancelAndDelete(wakeup);
00115   cancelAndDelete(data_timeout);
00116   cancelAndDelete(data_tx_over);
00117   cancelAndDelete(stop_preambles);
00118   cancelAndDelete(send_preamble);
00119   cancelAndDelete(ack_tx_over);
00120   cancelAndDelete(cca_timeout);
00121   cancelAndDelete(send_ack);
00122   cancelAndDelete(start_bmac);
00123   cancelAndDelete(ack_timeout);
00124   cancelAndDelete(resend_data);
00125 
00126   MacQueue::iterator it;
00127   for(it = macQueue.begin(); it != macQueue.end(); ++it)
00128   {
00129     delete (*it);
00130   }
00131   macQueue.clear();
00132 }
00133 
00134 void BMacLayer::finish()
00135 {
00136     BaseMacLayer::finish();
00137 
00138     
00139     if (stats)
00140     {
00141       recordScalar("nbTxDataPackets", nbTxDataPackets);
00142       recordScalar("nbTxPreambles", nbTxPreambles);
00143       recordScalar("nbRxDataPackets", nbRxDataPackets);
00144       recordScalar("nbRxPreambles", nbRxPreambles);
00145       recordScalar("nbMissedAcks", nbMissedAcks);
00146       recordScalar("nbRecvdAcks", nbRecvdAcks);
00147       recordScalar("nbTxAcks", nbTxAcks);
00148       recordScalar("nbDroppedDataPackets", nbDroppedDataPackets);
00149       
00150       
00151       
00152     }
00153 }
00154 
00160 void BMacLayer::handleUpperMsg(cMessage *msg)
00161 {
00162   bool pktAdded = addToQueue(msg);
00163   if (!pktAdded)
00164     return;
00165   
00166   if (wakeup->isScheduled() && (macState == SLEEP))
00167   {
00168     cancelEvent(wakeup);
00169     scheduleAt(simTime() + dblrand()*0.1f, wakeup);
00170   }
00171 }
00172 
00176 void BMacLayer::sendPreamble()
00177 {
00178   MacPkt* preamble = new MacPkt();
00179   preamble->setSrcAddr(myMacAddr);
00180   preamble->setDestAddr(L2BROADCAST);
00181   preamble->setKind(BMAC_PREAMBLE);
00182   preamble->setBitLength(headerLength);
00183 
00184   
00185   attachSignal(preamble);
00186   sendDown(preamble);
00187   nbTxPreambles++;
00188 }
00189 
00193 void BMacLayer::sendMacAck()
00194 {
00195   MacPkt* ack = new MacPkt();
00196   ack->setSrcAddr(myMacAddr);
00197   ack->setDestAddr(lastDataPktSrcAddr);
00198   ack->setKind(BMAC_ACK);
00199   ack->setBitLength(headerLength);
00200 
00201   
00202   attachSignal(ack);
00203   sendDown(ack);
00204   nbTxAcks++;
00205   
00206 }
00207 
00208 
00209 
00223 void BMacLayer::handleSelfMsg(cMessage *msg)
00224 {
00225   switch (macState)
00226   {
00227   case INIT:
00228     if (msg->getKind() == BMAC_START_BMAC)
00229     {
00230       debugEV << "State INIT, message BMAC_START, new state SLEEP" << endl;
00231       changeDisplayColor(BLACK);
00232       phy->setRadioState(Radio::SLEEP);
00233       macState = SLEEP;
00234       scheduleAt(simTime()+dblrand()*slotDuration, wakeup);
00235       return;
00236     }
00237     break;
00238   case SLEEP:
00239     if (msg->getKind() == BMAC_WAKE_UP)
00240     {
00241       debugEV << "State SLEEP, message BMAC_WAKEUP, new state CCA" << endl;
00242       scheduleAt(simTime() + checkInterval, cca_timeout);
00243       phy->setRadioState(Radio::RX);
00244       changeDisplayColor(GREEN);
00245       macState = CCA;
00246       return;
00247     }
00248     break;
00249   case CCA:
00250     if (msg->getKind() == BMAC_CCA_TIMEOUT)
00251     {
00252       
00253       
00254       if (macQueue.size() > 0)
00255       {
00256         debugEV << "State CCA, message CCA_TIMEOUT, new state"
00257               " SEND_PREAMBLE" << endl;
00258         phy->setRadioState(Radio::TX);
00259         changeDisplayColor(YELLOW);
00260         macState = SEND_PREAMBLE;
00261         scheduleAt(simTime() + slotDuration, stop_preambles);
00262         return;
00263       }
00264       
00265       else
00266       {
00267         debugEV << "State CCA, message CCA_TIMEOUT, new state SLEEP"
00268              << endl;
00269         scheduleAt(simTime() + slotDuration, wakeup);
00270         macState = SLEEP;
00271         phy->setRadioState(Radio::SLEEP);
00272         changeDisplayColor(BLACK);
00273         return;
00274       }
00275     }
00276     
00277     
00278     if (msg->getKind() == BMAC_PREAMBLE)
00279     {
00280       nbRxPreambles++;
00281       debugEV << "State CCA, message BMAC_PREAMBLE received, new state"
00282             " WAIT_DATA" << endl;
00283       macState = WAIT_DATA;
00284       cancelEvent(cca_timeout);
00285       scheduleAt(simTime() + slotDuration + checkInterval, data_timeout);
00286       delete msg;
00287       return;
00288     }
00289     
00290     
00291     
00292     if (msg->getKind() == BMAC_DATA)
00293     {
00294       nbRxDataPackets++;
00295       debugEV << "State CCA, message BMAC_DATA, new state WAIT_DATA"
00296            << endl;
00297       macState = WAIT_DATA;
00298       cancelEvent(cca_timeout);
00299       scheduleAt(simTime() + slotDuration + checkInterval, data_timeout);
00300       scheduleAt(simTime(), msg);
00301       return;
00302     }
00303     
00304     
00305     if (msg->getKind() == BMAC_ACK)
00306     {
00307       debugEV << "State CCA, message BMAC_ACK, new state CCA" << endl;
00308       delete msg;
00309       return;
00310     }
00311     break;
00312 
00313   case SEND_PREAMBLE:
00314     if (msg->getKind() == BMAC_SEND_PREAMBLE)
00315     {
00316       debugEV << "State SEND_PREAMBLE, message BMAC_SEND_PREAMBLE, new"
00317             " state SEND_PREAMBLE" << endl;
00318       sendPreamble();
00319       scheduleAt(simTime() + 0.5f*checkInterval, send_preamble);
00320       macState = SEND_PREAMBLE;
00321       return;
00322     }
00323     
00324     if (msg->getKind() == BMAC_STOP_PREAMBLES)
00325     {
00326       debugEV << "State SEND_PREAMBLE, message BMAC_STOP_PREAMBLES, new"
00327             " state SEND_DATA" << endl;
00328       macState = SEND_DATA;
00329       txAttempts = 1;
00330       return;
00331     }
00332     break;
00333 
00334   case SEND_DATA:
00335     if ((msg->getKind() == BMAC_SEND_PREAMBLE)
00336       || (msg->getKind() == BMAC_RESEND_DATA))
00337     {
00338       debugEV << "State SEND_DATA, message BMAC_SEND_PREAMBLE or"
00339             " BMAC_RESEND_DATA, new state WAIT_TX_DATA_OVER" << endl;
00340       
00341       sendDataPacket();
00342       macState = WAIT_TX_DATA_OVER;
00343       return;
00344     }
00345     break;
00346 
00347   case WAIT_TX_DATA_OVER:
00348     if (msg->getKind() == BMAC_DATA_TX_OVER)
00349     {
00350       if ((useMacAcks) && (lastDataPktDestAddr != L2BROADCAST))
00351       {
00352         debugEV << "State WAIT_TX_DATA_OVER, message BMAC_DATA_TX_OVER,"
00353               " new state WAIT_ACK" << endl;
00354         macState = WAIT_ACK;
00355         phy->setRadioState(Radio::RX);
00356         changeDisplayColor(GREEN);
00357         scheduleAt(simTime()+checkInterval, ack_timeout);
00358       }
00359       else
00360       {
00361         debugEV << "State WAIT_TX_DATA_OVER, message BMAC_DATA_TX_OVER,"
00362               " new state  SLEEP" << endl;
00363         delete macQueue.front();
00364         macQueue.pop_front();
00365         
00366         if (macQueue.size() > 0)
00367           scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00368         else
00369           scheduleAt(simTime() + slotDuration, wakeup);
00370         macState = SLEEP;
00371         phy->setRadioState(Radio::SLEEP);
00372         changeDisplayColor(BLACK);
00373       }
00374       return;
00375     }
00376     break;
00377   case WAIT_ACK:
00378     if (msg->getKind() == BMAC_ACK_TIMEOUT)
00379     {
00380       
00381       if (txAttempts < maxTxAttempts)
00382       {
00383         debugEV << "State WAIT_ACK, message BMAC_ACK_TIMEOUT, new state"
00384               " SEND_DATA" << endl;
00385         txAttempts++;
00386         macState = SEND_PREAMBLE;
00387         scheduleAt(simTime() + slotDuration, stop_preambles);
00388         phy->setRadioState(Radio::TX);
00389         changeDisplayColor(YELLOW);
00390       }
00391       else
00392       {
00393         debugEV << "State WAIT_ACK, message BMAC_ACK_TIMEOUT, new state"
00394               " SLEEP" << endl;
00395         
00396         delete macQueue.front();
00397         macQueue.pop_front();
00398         
00399         if (macQueue.size() > 0)
00400           scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00401         else
00402           scheduleAt(simTime() + slotDuration, wakeup);
00403         macState = SLEEP;
00404         phy->setRadioState(Radio::SLEEP);
00405         changeDisplayColor(BLACK);
00406         nbMissedAcks++;
00407       }
00408       return;
00409     }
00410     
00411     if ((msg->getKind() == BMAC_DATA) || (msg->getKind() == BMAC_PREAMBLE))
00412     {
00413       debugEV << "State WAIT_ACK, message BMAC_DATA or BMAC_PREMABLE, new"
00414             " state WAIT_ACK" << endl;
00415       delete msg;
00416       return;
00417     }
00418     if (msg->getKind() == BMAC_ACK)
00419     {
00420       debugEV << "State WAIT_ACK, message BMAC_ACK" << endl;
00421       MacPkt *mac = static_cast<MacPkt *>(msg);
00422       int src = mac->getSrcAddr();
00423       
00424       debugEV << "We are waiting for ACK from : " << lastDataPktDestAddr
00425            << ", and ACK came from : " << src << endl;
00426       if (src == lastDataPktDestAddr)
00427       {
00428         debugEV << "New state SLEEP" << endl;
00429         nbRecvdAcks++;
00430         lastDataPktDestAddr = L2BROADCAST;
00431         cancelEvent(ack_timeout);
00432         delete macQueue.front();
00433         macQueue.pop_front();
00434         
00435         if (macQueue.size() > 0)
00436           scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00437         else
00438           scheduleAt(simTime() + slotDuration, wakeup);
00439         macState = SLEEP;
00440         phy->setRadioState(Radio::SLEEP);
00441         changeDisplayColor(BLACK);
00442         lastDataPktDestAddr = L2BROADCAST;
00443       }
00444       delete msg;
00445       return;
00446     }
00447     break;
00448   case WAIT_DATA:
00449     if(msg->getKind() == BMAC_PREAMBLE)
00450     {
00451       
00452       debugEV << "State WAIT_DATA, message BMAC_PREAMBLE, new state"
00453             " WAIT_DATA" << endl;
00454       nbRxPreambles++;
00455       delete msg;
00456       return;
00457     }
00458     if(msg->getKind() == BMAC_ACK)
00459     {
00460       
00461       debugEV << "State WAIT_DATA, message BMAC_ACK, new state WAIT_DATA"
00462            << endl;
00463       delete msg;
00464       return;
00465     }
00466     if (msg->getKind() == BMAC_DATA)
00467     {
00468       nbRxDataPackets++;
00469       MacPkt *mac = static_cast<MacPkt *>(msg);
00470       int dest = mac->getDestAddr();
00471       int src = mac->getSrcAddr();
00472       if ((dest == myMacAddr) || (dest == L2BROADCAST)) {
00473         sendUp(decapsMsg(mac));
00474       } else {
00475         delete msg;
00476         msg = NULL;
00477         mac = NULL;
00478       }
00479 
00480       cancelEvent(data_timeout);
00481       if ((useMacAcks) && (dest == myMacAddr))
00482       {
00483         debugEV << "State WAIT_DATA, message BMAC_DATA, new state"
00484               " SEND_ACK" << endl;
00485         macState = SEND_ACK;
00486         lastDataPktSrcAddr = src;
00487         phy->setRadioState(Radio::TX);
00488         changeDisplayColor(YELLOW);
00489       }
00490       else
00491       {
00492         debugEV << "State WAIT_DATA, message BMAC_DATA, new state SLEEP"
00493              << endl;
00494         
00495         if (macQueue.size() > 0)
00496           scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00497         else
00498           scheduleAt(simTime() + slotDuration, wakeup);
00499         macState = SLEEP;
00500         phy->setRadioState(Radio::SLEEP);
00501         changeDisplayColor(BLACK);
00502       }
00503       return;
00504     }
00505     if (msg->getKind() == BMAC_DATA_TIMEOUT)
00506     {
00507       debugEV << "State WAIT_DATA, message BMAC_DATA_TIMEOUT, new state"
00508             " SLEEP" << endl;
00509       
00510       if (macQueue.size() > 0)
00511         scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00512       else
00513         scheduleAt(simTime() + slotDuration, wakeup);
00514       macState = SLEEP;
00515       phy->setRadioState(Radio::SLEEP);
00516       changeDisplayColor(BLACK);
00517       return;
00518     }
00519     break;
00520   case SEND_ACK:
00521     if (msg->getKind() == BMAC_SEND_ACK)
00522     {
00523       debugEV << "State SEND_ACK, message BMAC_SEND_ACK, new state"
00524             " WAIT_ACK_TX" << endl;
00525       
00526       sendMacAck();
00527       macState = WAIT_ACK_TX;
00528       return;
00529     }
00530     break;
00531   case WAIT_ACK_TX:
00532     if (msg->getKind() == BMAC_ACK_TX_OVER)
00533     {
00534       debugEV << "State WAIT_ACK_TX, message BMAC_ACK_TX_OVER, new state"
00535             " SLEEP" << endl;
00536       
00537       
00538       if (macQueue.size() > 0)
00539         scheduleAt(simTime() + dblrand()*checkInterval, wakeup);
00540       else
00541         scheduleAt(simTime() + slotDuration, wakeup);
00542       macState = SLEEP;
00543       phy->setRadioState(Radio::SLEEP);
00544       changeDisplayColor(BLACK);
00545       lastDataPktSrcAddr = L2BROADCAST;
00546       return;
00547     }
00548     break;
00549   }
00550   opp_error("Undefined event of type %d in state %d (Radio state %d)!",
00551         msg->getKind(), macState, phy->getRadioState());
00552 }
00553 
00554 
00558 void BMacLayer::handleLowerMsg(cMessage *msg)
00559 {
00560   
00561   handleSelfMsg(msg);
00562 }
00563 
00564 void BMacLayer::sendDataPacket()
00565 {
00566   nbTxDataPackets++;
00567   MacPkt *pkt = macQueue.front()->dup();
00568   attachSignal(pkt);
00569   lastDataPktDestAddr = pkt->getDestAddr();
00570   pkt->setKind(BMAC_DATA);
00571   sendDown(pkt);
00572 }
00573 
00578 void BMacLayer::handleLowerControl(cMessage *msg)
00579 {
00580   
00581     if(msg->getKind() == MacToPhyInterface::TX_OVER) {
00582       if (macState == WAIT_TX_DATA_OVER)
00583       {
00584         scheduleAt(simTime(), data_tx_over);
00585       }
00586       if (macState == WAIT_ACK_TX)
00587       {
00588         scheduleAt(simTime(), ack_tx_over);
00589       }
00590     }
00591     
00592     else if(msg->getKind() == MacToPhyInterface::RADIO_SWITCHING_OVER) {
00593       
00594       
00595       if ((macState == SEND_PREAMBLE) && (phy->getRadioState() == Radio::TX))
00596       {
00597         scheduleAt(simTime(), send_preamble);
00598       }
00599       if ((macState == SEND_ACK) && (phy->getRadioState() == Radio::TX))
00600       {
00601         scheduleAt(simTime(), send_ack);
00602       }
00603       
00604       
00605       if ((macState == SEND_DATA) && (phy->getRadioState() == Radio::TX))
00606       {
00607         scheduleAt(simTime(), resend_data);
00608       }
00609 
00610     }
00611     else {
00612         debugEV << "control message with wrong kind -- deleting\n";
00613     }
00614     delete msg;
00615 }
00616 
00617 
00618 
00619 
00624 bool BMacLayer::addToQueue(cMessage *msg)
00625 {
00626   if (macQueue.size() >= queueLength) {
00627     
00628     debugEV << "New packet arrived, but queue is FULL, so new packet is"
00629           " deleted\n";
00630     msg->setName("MAC ERROR");
00631     msg->setKind(PACKET_DROPPED);
00632     sendControlUp(msg);
00633     droppedPacket.setReason(DroppedPacket::QUEUE);
00634     utility->publishBBItem(catDroppedPacket, &droppedPacket, nicId);
00635     nbDroppedDataPackets++;
00636 
00637     return false;
00638   }
00639 
00640   MacPkt *macPkt = new MacPkt(msg->getName());
00641   macPkt->setBitLength(headerLength);
00642   NetwToMacControlInfo* cInfo
00643       = static_cast<NetwToMacControlInfo*> (msg->removeControlInfo());
00644   
00645   
00646   
00647   int dest = cInfo->getNextHopMac();
00648   macPkt->setDestAddr(dest);
00649   delete cInfo;
00650   macPkt->setSrcAddr(myMacAddr);
00651 
00652   assert(static_cast<cPacket*>(msg));
00653   macPkt->encapsulate(static_cast<cPacket*>(msg));
00654 
00655   macQueue.push_back(macPkt);
00656   debugEV << "Max queue length: " << queueLength << ", packet put in queue"
00657         "\n  queue size: " << macQueue.size() << " macState: "
00658         << macState << endl;
00659   return true;
00660 }
00661 
00662 void BMacLayer::attachSignal(MacPkt *macPkt)
00663 {
00664   
00665   simtime_t duration = macPkt->getBitLength() / bitrate;
00666   
00667   Signal* s = createSignal(simTime(), duration, txPower, bitrate);
00668   
00669   MacToPhyControlInfo* ctrl = new MacToPhyControlInfo(s);
00670   macPkt->setControlInfo(ctrl);
00671 }
00672 
00677 void BMacLayer::changeDisplayColor(BMAC_COLORS color)
00678 {
00679   if (!animation)
00680     return;
00681   cDisplayString& dispStr
00682       = findHost()->getDisplayString();
00683   
00684   if (color == GREEN)
00685     dispStr.setTagArg("b", 3, "green");
00686     
00687   if (color == BLUE)
00688     dispStr.setTagArg("b", 3, "blue");
00689         
00690   if (color == RED)
00691     dispStr.setTagArg("b", 3, "red");
00692         
00693   if (color == BLACK)
00694     dispStr.setTagArg("b", 3, "black");
00695         
00696   if (color == YELLOW)
00697     dispStr.setTagArg("b", 3, "yellow");
00698         
00699 }
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736