mmac-csma.cc

Go to the documentation of this file.
00001 /* -*- Mode:C++ -*- */
00002 
00003 /*
00004  * Copyright (c) 2008 Regents of the SIGNET lab, University of Padova.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the University of Padova (SIGNET lab) nor the 
00016  *    names of its contributors may be used to endorse or promote products 
00017  *    derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
00021  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00022  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
00023  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00042 #include<mac.h>
00043 #include"mmac-csma.h"
00044 #include<iostream>
00045 
00046 #define DEBUG_UNEXPECTED_EVENT { std::cerr << showpoint << NOW << " (" << addr << ") unexpected event " << __PRETTY_FUNCTION__ << " in state " << state_name_array[state].name << std::endl ; exit(1); }
00047 #define DEBUG_EVENT {   if (debug_states_) std::cerr << showpoint << NOW << " MMacCsma " << addr << " : event " << __FUNCTION__ << std::endl; }
00048 
00049 packet_t PT_MMAC_ACK;
00050 
00051 struct state_name { 
00052   enum MMAC_CSMA_STATE state;
00053   const char* name;
00054 } state_name_array[NUM_MMAC_CSMA_STATES] = {
00055   {STATE_IDLE, "IDLE"},
00056   {STATE_RX_DATA, "RX_DATA"},
00057   {STATE_TX_ACK, "TX_ACK"},
00058   {STATE_CHK_PENDING_PKT, "CHK_PENDING_PKT"},
00059   {STATE_CHK_FROZEN_BACKOFF, "CHK_FROZEN_BACKOFF"},
00060   {STATE_BACKOFF, "BACKOFF"},
00061   {STATE_FREEZE_BACKOFF, "FREEZE_BACKOFF"},
00062   {STATE_TX_DATA, "TX_DATA"},
00063   {STATE_START_ACK_TIMEOUT, "START_ACK_TIMEOUT"},
00064   {STATE_WAIT_ACK, "WAIT_ACK"},
00065   {STATE_RX_ACK, "RX_ACK"},
00066   {STATE_CHK_ACK_TIMEOUT_EXPIRED, "CHK_ACK_TIMEOUT_EXPIRED"},
00067   {STATE_TX_SUCCESSFUL, "TX_SUCCESSFUL"},
00068   {STATE_TX_FAILED, "TX_FAILED"}
00069 };
00070 
00071 
00072 static class MMacCsmaClass : public TclClass {
00073 public:
00074   MMacCsmaClass() : TclClass("Module/MMac/CSMA") {}
00075   TclObject* create(int, const char*const*) {
00076     return (new MMacCsma);
00077   }
00078 } class_MMacCsma;
00079 
00080 
00081 
00082 int MMacCsma::uidcnt = 1000;
00083 
00084 MMacCsma::MMacCsma()
00085   : backoff_timer(this),
00086     ack_timer(this),
00087     ConsecutiveFailedTxAttempts(0),
00088     PktTx(0),
00089     PktRx(0),
00090     state(STATE_IDLE)
00091 {
00092   bind("HeaderSize_",&HeaderSize_);
00093   bind("BaseBackoffTime_",&BaseBackoffTime_);
00094   bind("AckTimeout_",&AckTimeout_);
00095   bind("debug_states_",&debug_states_);
00096   //  bind("",&);
00097 }
00098 
00099 
00100 bool MMacCsma::FrozenBackoff()
00101 {
00102   return backoff_timer.isFrozen();
00103 }
00104 
00105 
00106 bool MMacCsma::PendingPacket()
00107 {
00108   if (PktTx)
00109     return true;
00110   else if (!Q.empty())
00111     {
00112       PktTx = Q.front();
00113       Q.pop();
00114       return true;
00115     }
00116   else
00117     return false;
00118 }
00119 
00120 void MMacCsma::recvFromUpperLayers(Packet* p)
00121 {  
00122   DEBUG_EVENT;
00123   switch (state) 
00124     {
00125     case STATE_IDLE: 
00126       assert(Q.empty());
00127       assert(PktTx == NULL);
00128       assert(PendingPacket() == false);
00129       PktTx = p;      
00130       enterState_TX_DATA();
00131       break;            
00132     default: 
00133       if (PktTx == NULL)
00134         PktTx = p;
00135       else      
00136         Q.push(p);      
00137       break;
00138     }
00139 }
00140 
00141 void MMacCsma::Phy2MacEndTx(const Packet* p)
00142 {
00143   DEBUG_EVENT;   
00144   switch (state) 
00145     {
00146     case STATE_TX_DATA: 
00147       enterState_START_ACK_TIMEOUT();
00148       break;            
00149     case STATE_TX_ACK: 
00150       enterState_CHK_PENDING_PKT();
00151       break;      
00152     default:
00153       DEBUG_UNEXPECTED_EVENT;
00154       break;
00155     }
00156 }
00157 
00158 void MMacCsma::Phy2MacStartRx(const Packet* p)
00159 {
00160   DEBUG_EVENT;
00161   assert(PktRx == NULL);  
00162   PktRx = p;
00163   switch (state) 
00164     {
00165     case STATE_IDLE: 
00166       enterState_RX_DATA();
00167       break;            
00168     case STATE_WAIT_ACK: 
00169       enterState_RX_ACK();
00170       break;  
00171     case STATE_BACKOFF: 
00172       enterState_FREEZE_BACKOFF();
00173       break;    
00174     default:
00175       DEBUG_UNEXPECTED_EVENT;
00176       break;
00177     }
00178 }
00179 
00180 
00181 void MMacCsma::Phy2MacEndRx(Packet* p)
00182 {
00183   DEBUG_EVENT;
00184 
00185   hdr_cmn* ch = hdr_cmn::access(p);
00186   hdr_mac *mh = HDR_MAC(p);
00187 
00188   assert(PktRx == p); // otherwise we have a strange PHY underneath
00189   PktRx = NULL;       // Rx ended
00190 
00191   if (ch->error())
00192     {
00193       recvWhateverElse(p);
00194     }
00195   else
00196     {
00197       // packet is received correctly
00198       if(mh->macDA() == addr)
00199         {
00200           if(ch->ptype() == PT_MMAC_ACK)
00201             recvAck4Me(p);
00202           else
00203             recvData4Me(p);
00204         }
00205       else
00206         {
00207           // not for me
00208           recvWhateverElse(p);
00209         }
00210     }
00211 }
00212 
00213 void MMacCsma::recvData4Me(Packet* p)
00214 {
00215   DEBUG_EVENT;
00216   hdr_mac *mh = HDR_MAC(p); 
00217   switch (state) 
00218     {
00219     case STATE_RX_DATA:        
00220       enterState_TX_ACK(mh->macSA());
00221       sendUp(p);
00222       break;      
00223     default: 
00224       recvWhateverElse(p);                      
00225       break;
00226     }
00227 }
00228 
00229 void MMacCsma::recvAck4Me(Packet* p)
00230 {
00231   DEBUG_EVENT;
00232   switch (state) 
00233     {
00234     case STATE_RX_ACK: 
00235       Packet::free(p);
00236       enterState_TX_SUCCESSFUL();
00237       break;      
00238     default: 
00239       recvWhateverElse(p);                      
00240       break;
00241     }
00242 }
00243 
00244 
00245 void MMacCsma::recvWhateverElse(Packet* p)
00246 {
00247   DEBUG_EVENT;
00248   Packet::free(p);
00249   switch (state) 
00250     {
00251     case STATE_RX_DATA: 
00252       enterState_CHK_PENDING_PKT();
00253       break;
00254     case STATE_RX_ACK: 
00255       enterState_CHK_ACK_TIMEOUT_EXPIRED();
00256       break;      
00257     default:
00258       DEBUG_UNEXPECTED_EVENT;
00259       break;
00260     }
00261 }
00262 
00263 
00264 void MMacCsma::AckTimeout()
00265 {
00266   DEBUG_EVENT;
00267   switch (state) 
00268     {
00269     case STATE_WAIT_ACK: 
00270       enterState_TX_FAILED();
00271       break;
00272     case STATE_RX_ACK: 
00273       // do nothing, ack_timer.isExpired() will return true
00274       break;      
00275     default:
00276       DEBUG_UNEXPECTED_EVENT;
00277       break;
00278     }
00279 }
00280 
00281 void MMacCsma::BackoffEnded()
00282 {
00283   DEBUG_EVENT;
00284   switch (state) 
00285     {
00286     case STATE_BACKOFF: 
00287       enterState_TX_DATA();
00288       break;
00289     default:
00290       DEBUG_UNEXPECTED_EVENT;
00291       break;
00292     }
00293 }
00294 
00295 void MMacCsma::setState(enum MMAC_CSMA_STATE s)
00296 {
00297   state = s;
00298   if (debug_states_)
00299     std::cerr << showpoint << NOW 
00300               << " MMacCsma " << addr << " : entering state " 
00301               << state_name_array[s].name 
00302       //<< " " << s
00303       //<< " (" << state_name_array[s].state << ")"
00304               << std::endl;  
00305 }
00306 
00307 void MMacCsma::enterState_IDLE()
00308 {
00309   assert(STATE_CHK_PENDING_PKT == state); 
00310   assert(PktRx == NULL);
00311   assert(PktTx == NULL);
00312   setState(STATE_IDLE);
00313 }
00314 
00315 
00316 void MMacCsma::enterState_RX_DATA()
00317 {
00318   assert((STATE_IDLE == state)
00319          ||(STATE_FREEZE_BACKOFF == state));
00320   setState(STATE_RX_DATA);
00321   assert(PktRx != NULL);
00322 }
00323 
00324 void MMacCsma::enterState_TX_ACK(int macSA_of_data_pkt)
00325 {
00326   assert(STATE_RX_DATA == state);
00327   setState(STATE_TX_ACK);
00328   Packet* p = Packet::alloc();
00329   hdr_cmn* ch = hdr_cmn::access(p);
00330   //  ch->uid() = 0;
00331   // ch->ptype() = PT_MMAC_ACK;
00332   ch->size() = HeaderSize_; // no payload
00333   assert(ch->size() > 0);
00334 
00335   hdr_mac *ack_mh = HDR_MAC(p);
00336   ack_mh->macSA() = addr;
00337   ack_mh->macDA() = macSA_of_data_pkt;  
00338   Mac2PhyStartTx(p);
00339 }
00340 
00341 
00342 void MMacCsma::enterState_CHK_PENDING_PKT()
00343 {
00344   assert((STATE_RX_DATA == state)
00345          ||(STATE_TX_ACK == state)
00346          ||(STATE_TX_SUCCESSFUL == state)); 
00347   setState(STATE_CHK_PENDING_PKT);
00348   if(PendingPacket())
00349     enterState_CHK_FROZEN_BACKOFF();
00350   else
00351     enterState_IDLE();
00352 }
00353 
00354 void MMacCsma::enterState_CHK_FROZEN_BACKOFF()
00355 {
00356   assert(STATE_CHK_PENDING_PKT == state); 
00357   setState(STATE_CHK_FROZEN_BACKOFF);
00358   if(FrozenBackoff())
00359     enterState_BACKOFF();
00360   else
00361     enterState_TX_DATA();    
00362 }
00363 
00364 
00365 void MMacCsma::enterState_BACKOFF()
00366 {
00367   assert((STATE_CHK_FROZEN_BACKOFF == state)
00368          ||(STATE_TX_FAILED == state)); 
00369   setState(STATE_BACKOFF);
00370   if (backoff_timer.isFrozen())
00371     backoff_timer.defrost();
00372   else
00373     backoff_timer.start(BaseBackoffTime_*pow(2,ConsecutiveFailedTxAttempts));
00374 }
00375 
00376 
00377 void MMacCsma::enterState_FREEZE_BACKOFF()
00378 {
00379   assert(STATE_BACKOFF == state); 
00380   setState(STATE_FREEZE_BACKOFF);
00381   backoff_timer.freeze();
00382   enterState_RX_DATA();
00383 }
00384 
00385 void MMacCsma::enterState_TX_DATA()
00386 {
00387   assert((STATE_BACKOFF == state)
00388          ||(STATE_CHK_FROZEN_BACKOFF == state)
00389          ||(STATE_IDLE == state)); 
00390   setState(STATE_TX_DATA);
00391   assert(PktTx);
00392   Mac2PhyStartTx(PktTx->copy());
00393 }
00394 
00395 
00396 void MMacCsma::enterState_START_ACK_TIMEOUT()
00397 {
00398   assert(STATE_TX_DATA == state); 
00399   setState(STATE_START_ACK_TIMEOUT);
00400   ack_timer.start(AckTimeout_);
00401   enterState_WAIT_ACK();
00402 }
00403 
00404 
00405 void MMacCsma::enterState_WAIT_ACK()
00406 {
00407   assert((STATE_START_ACK_TIMEOUT == state)
00408          ||(STATE_CHK_ACK_TIMEOUT_EXPIRED == state));
00409   setState(STATE_WAIT_ACK);         
00410 }
00411 
00412 void MMacCsma::enterState_RX_ACK()
00413 {
00414   assert(STATE_WAIT_ACK == state);
00415   setState(STATE_RX_ACK);  
00416 }
00417 
00418 void MMacCsma::enterState_CHK_ACK_TIMEOUT_EXPIRED()
00419 {
00420   assert(STATE_RX_ACK == state); 
00421   setState(STATE_CHK_ACK_TIMEOUT_EXPIRED);
00422   if(ack_timer.isExpired())
00423     enterState_TX_FAILED();
00424   else
00425     enterState_WAIT_ACK();
00426 }
00427 
00428 void MMacCsma::enterState_TX_SUCCESSFUL()
00429 {
00430   assert(STATE_RX_ACK == state); 
00431   setState(STATE_TX_SUCCESSFUL);
00432   ack_timer.stop();
00433   PktTx = NULL;
00434   ConsecutiveFailedTxAttempts = 0;
00435   enterState_CHK_PENDING_PKT();
00436 }
00437 
00438 void MMacCsma::enterState_TX_FAILED()
00439 {
00440   assert((STATE_WAIT_ACK == state)
00441          ||(STATE_WAIT_ACK == state)); 
00442   setState(STATE_TX_FAILED);
00443   //  ack_timer.stop();
00444   ConsecutiveFailedTxAttempts++;
00445   enterState_BACKOFF();
00446 }
00447 
00448 
00449 
00450 Backoff_Timer::Backoff_Timer(MMacCsma *m)
00451   : status(STATUS_STOPPED),
00452     mac(m)
00453 {  
00454 }
00455 
00456 void Backoff_Timer::start(double duration)
00457 {
00458   assert(status == STATUS_STOPPED);
00459   start_time = NOW;
00460   sched(duration);
00461   status = STATUS_RUNNING;
00462 }
00463 
00464 void Backoff_Timer::freeze()
00465 {
00466   assert(status == STATUS_RUNNING);
00467   left_duration = NOW - start_time;
00468   cancel();
00469   status = STATUS_FROZEN;
00470 }
00471 
00472 
00473 void Backoff_Timer::defrost()
00474 { 
00475   assert(status == STATUS_FROZEN);
00476   start_time = NOW;
00477   assert(left_duration > 0);
00478   sched(left_duration);
00479   status = STATUS_RUNNING;
00480 }
00481 
00482 void Backoff_Timer::expire(Event *e)
00483 {
00484   assert(status == STATUS_RUNNING);  
00485   status = STATUS_STOPPED;
00486   mac->BackoffEnded();
00487 
00488 }
00489 
00490 bool Backoff_Timer::isFrozen()
00491 {
00492   return (STATUS_FROZEN == status);
00493 }
00494 
00495 
00496 
00497 
00498 
00499 Ack_Timer::Ack_Timer(MMacCsma *m)
00500   : status(STATUS_STOPPED),
00501     mac(m)
00502 {  
00503 }
00504 
00505 void Ack_Timer::start(double duration)
00506 {
00507   assert(status == STATUS_STOPPED);
00508   sched(duration);
00509   status = STATUS_RUNNING;
00510 }
00511 
00512 void Ack_Timer::expire(Event *e)
00513 {
00514   assert(status == STATUS_RUNNING);  
00515   mac->AckTimeout();
00516   status = STATUS_STOPPED;
00517 }
00518 
00519 bool Ack_Timer::isExpired()
00520 {
00521   return (STATUS_STOPPED == status);
00522 }
00523 
00524 void Ack_Timer::stop()
00525 {
00526   assert(status == STATUS_RUNNING);  
00527   cancel();
00528   status = STATUS_STOPPED;
00529 }

Generated on Wed Nov 26 15:47:28 2008 for NS-MIRACLE library by  doxygen 1.5.2