User Manual, Developers Guide and API Documentation

TransmissionQueue.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  * WiFiMac                                                                    *
00003  * This file is part of openWNS (open Wireless Network Simulator)
00004  * _____________________________________________________________________________
00005  *
00006  * Copyright (C) 2004-2007
00007  * Chair of Communication Networks (ComNets)
00008  * Kopernikusstr. 16, D-52074 Aachen, Germany
00009  * phone: ++49-241-80-27910,
00010  * fax: ++49-241-80-22242
00011  * email: info@openwns.org
00012  * www: http://www.openwns.org
00013  * _____________________________________________________________________________
00014  *
00015  * openWNS is free software; you can redistribute it and/or modify it under the
00016  * terms of the GNU Lesser General Public License version 2 as published by the
00017  * Free Software Foundation;
00018  *
00019  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00020  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00021  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00022  * details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00026  *
00027  ******************************************************************************/
00028 
00029 #include <WIFIMAC/draftn/BlockACK.hpp>
00030 #include <WIFIMAC/draftn/TransmissionQueue.hpp>
00031 
00032 
00033 using namespace wifimac::draftn;
00034 
00035 TransmissionQueue::TransmissionQueue(BlockACK* parent_,
00036                                      size_t maxOnAir_,
00037                                      wns::simulator::Time maxDelay_,
00038                                      wns::service::dll::UnicastAddress adr_,
00039                                      BlockACKCommand::SequenceNumber sn_,
00040                                      wifimac::management::PERInformationBase* perMIB_,
00041                                      std::auto_ptr<wns::ldk::buffer::SizeCalculator> *sizeCalculator_) :
00042     parent(parent_),
00043     maxOnAir(maxOnAir_),
00044     maxDelay(maxDelay_),
00045     adr(adr_),
00046     txQueue(),
00047     onAirQueue(),
00048     nextSN(sn_),
00049     baREQ(),
00050     waitForACK(false),
00051     baReqRequired(false),
00052     perMIB(perMIB_),
00053     sizeCalculator(sizeCalculator_),
00054     oldestTimestamp()
00055 {
00056     MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << " created");
00057 
00058     // prepare Block ACK request
00059     this->baREQ = parent->friends.manager->createCompound(parent->friends.manager->getMACAddress(),
00060                                                           adr,
00061                                                           DATA,
00062                                                           parent->sifsDuration + parent->maximumACKDuration,
00063                                                           parent->ackTimeout);
00064     // block ack settings
00065     BlockACKCommand* baReqCommand = parent->activateCommand(this->baREQ->getCommandPool());
00066     baReqCommand->peer.type = BAREQ;
00067     baReqCommand->localTransmissionCounter = 1;
00068 
00069 } // TransmissionQueue
00070 
00071 TransmissionQueue::~TransmissionQueue()
00072 {
00073     onAirQueue.clear();
00074     this->baREQ = wns::ldk::CompoundPtr();
00075 } // TransmissionQueue::~TransmissionQueue
00076 
00077 
00078 const unsigned int
00079 TransmissionQueue::onAirQueueSize() const
00080 {
00081     unsigned int size = 0;
00082     for(std::deque<CompoundPtrWithTime>::const_iterator it = onAirQueue.begin();
00083         it != onAirQueue.end();
00084         it++)
00085     {
00086         size += (*(*sizeCalculator))(it->first);
00087     }
00088     return(size);
00089 }
00090 
00091 const unsigned int
00092 TransmissionQueue::txQueueSize() const
00093 {
00094     unsigned int size = 0;
00095     for(std::deque<CompoundPtrWithTime>::const_iterator it = txQueue.begin();
00096         it != txQueue.end();
00097         it++)
00098     {
00099        size += (*(*sizeCalculator))(it->first);
00100     }
00101     return(size);
00102 }
00103 
00104 
00105 const unsigned int
00106 TransmissionQueue::storageSize() const
00107 {
00108     return(this->onAirQueueSize() + this->txQueueSize());
00109 }
00110 
00111 void
00112 TransmissionQueue::processOutgoing(const wns::ldk::CompoundPtr& compound)
00113 {
00114     BlockACKCommand* baCommand = parent->activateCommand(compound->getCommandPool());
00115     baCommand->peer.type = I;
00116     baCommand->peer.sn = this->nextSN++;
00117     baCommand->localTransmissionCounter = 1;
00118 
00119     MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": Queue outgoing compound with sn " << baCommand->peer.sn);
00120     MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": send time for compound is " << wns::simulator::getEventScheduler()->getTime()+this->maxDelay << " maxDelay is " << this->maxDelay << " oldest is " << oldestTimestamp);
00121     txQueue.push_back(CompoundPtrWithTime(compound, wns::simulator::getEventScheduler()->getTime()));
00122 
00123     if ((oldestTimestamp == wns::simulator::Time()) or
00124         (wns::simulator::getEventScheduler()->getTime() < oldestTimestamp))
00125     {
00126         oldestTimestamp = wns::simulator::getEventScheduler()->getTime();
00127     }
00128 } // TransmissionQueue::processOutgoing
00129 
00130 const
00131 wns::ldk::CompoundPtr TransmissionQueue::hasData() const
00132 {
00133     if(waitForACK)
00134     {
00135         MESSAGE_SINGLE(VERBOSE, parent->logger, "TxQ" << adr << ": hasData: Waiting for ACK -> no other transmissions");
00136         // no other transmissions during waiting for ACK
00137         return(wns::ldk::CompoundPtr());
00138     }
00139     if((not txQueue.empty()) and (onAirQueueSize()+(*(*sizeCalculator))(txQueue.front().first) <= this->maxOnAir))
00140     {
00141         // regular frame pending
00142         MESSAGE_SINGLE(VERBOSE, parent->logger, "TxQ" << adr << ": hasData: Regular frame is pending");
00143         return(txQueue.front().first);
00144     }
00145 
00146     // baReq pending
00147     if(this->baReqRequired)
00148     {
00149         // impatient BAreq -> send as soon as required
00150         if(parent->impatientBAreqTransmission)
00151         {
00152             return(this->baREQ);
00153         }
00154 
00155         // next compound would exceed on air limit -> send
00156         if((not txQueue.empty()) and
00157            (onAirQueueSize()+(*(*sizeCalculator))(txQueue.front().first) > this->maxOnAir))
00158         {
00159             return(this->baREQ);
00160         }
00161 
00162         // no next compound, but nothing would match anyway -> send
00163         if((txQueue.empty()) and
00164            (onAirQueueSize() == this->maxOnAir))
00165         {
00166             return(this->baREQ);
00167         }
00168     }
00169 
00170     return(wns::ldk::CompoundPtr());
00171 
00172 } // TransmissionQueue::hasData
00173 
00174 wns::ldk::CompoundPtr
00175 TransmissionQueue::getData()
00176 {
00177     assure(this->hasData(), "Called getData although hasData is false");
00178 
00179     // compound pending?
00180     if((not txQueue.empty()) and
00181        (onAirQueueSize()+(*(*sizeCalculator))(txQueue.front().first) <= this->maxOnAir))
00182     {
00183         // transmit another frame
00184         onAirQueue.push_back(txQueue.front());
00185         wns::ldk::CompoundPtr it = txQueue.front().first;
00186         txQueue.pop_front();
00187 
00188         MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": Transmit pending frame with sn " << parent->getCommand(it->getCommandPool())->peer.sn);
00189         this->baReqRequired = true;
00190 
00191         return(it->copy());
00192     }
00193 
00194     // no compound pending --> BAreq must be pending
00195     assure(this->baReqRequired,
00196            "No compound pending and no baReqRequired, but hasData is true");
00197     if(txQueue.empty())
00198     {
00199         MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": No more frames to tx, send BAreq with start-sn " << parent->getCommand(onAirQueue.front().first)->peer.sn);
00200         oldestTimestamp = wns::simulator::Time();
00201     }
00202     else
00203     {
00204         MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": Reached tx window, send BAreq with start-sn " << parent->getCommand(onAirQueue.front().first)->peer.sn);
00205         oldestTimestamp = txQueue.front().second;
00206     }
00207 
00208     wns::ldk::CompoundPtr it = this->baREQ->copy();
00209     // no more BAreq required until next regular frame transmission
00210     this->baReqRequired = false;
00211     // now set start-sn of BA-req to sn of first compound in transmission queue
00212     parent->getCommand(it->getCommandPool())->peer.sn = parent->getCommand(onAirQueue.front().first)->peer.sn;
00213     // stop future transmissions until ACK (or timeout of it) arrives
00214     this->waitForACK = true;
00215     MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": Set waitForACK to true");
00216     return(it);
00217 
00218 } // TransmissionQueue::getData
00219 
00220 void
00221 TransmissionQueue::processIncomingACK(std::set<BlockACKCommand::SequenceNumber> ackSNs)
00222 {
00223     assure(not onAirQueue.empty(), "Received ACK but onAirQueue is empy");
00224     assure(this->waitForACK, "Received ACK but not waiting for one");
00225     this->waitForACK = false;
00226     MESSAGE_SINGLE(NORMAL, parent->logger, "TxQ" << adr << ": Received ACK, iterate through compounds on air");
00227 
00228     bool insertBack = false;
00229     bool blockACKsuccess = true;
00230     std::deque<CompoundPtrWithTime>::iterator txQueueFirst;
00231     unsigned long transmittedBits =0;
00232 
00233     if(txQueue.empty())
00234     {
00235         insertBack = true;
00236     }
00237     else
00238     {
00239         txQueueFirst = txQueue.begin();
00240     }
00241 
00242     std::set<wifimac::draftn::BlockACKCommand::SequenceNumber>::iterator snIt = ackSNs.begin();
00243     assure(isSortedBySN(onAirQueue),
00244            "onAirQueue is not sorted by SN!");
00245 
00246     for(std::deque<CompoundPtrWithTime>::iterator onAirIt = onAirQueue.begin();
00247         onAirIt != onAirQueue.end();
00248         onAirIt++)
00249     {
00250         wifimac::draftn::BlockACKCommand::SequenceNumber onAirSN = parent->getCommand((onAirIt->first)->getCommandPool())->peer.sn;
00251 
00252         if((snIt == ackSNs.end()) or (*snIt != onAirSN))
00253         {
00254              // retransmission
00255             int txCounter = ++(parent->getCommand((onAirIt->first)->getCommandPool())->localTransmissionCounter);
00256             blockACKsuccess = false;
00257             if(parent->getManager()->lifetimeExpired((onAirIt->first)->getCommandPool()))
00258             {
00259                 MESSAGE_BEGIN(NORMAL, parent->logger, m, "TxQ" << adr << ":   Compound " << onAirSN);
00260                 m << ", ackSN " << ((snIt == ackSNs.end()) ? -1 : (*snIt));
00261                 m << " -> " << txCounter;
00262                 m << " transmissions, lifetime expired --> drop!";
00263                 MESSAGE_END();
00264 
00265                 parent->numTxAttemptsProbe->put(onAirIt->first, txCounter);
00266             } // lifetime expired
00267             else
00268             {
00269                 // BlockACK does not drop frames due to their number of
00270                 // retransmissions, see IEEE 802.11-2007, 9.10.3
00271                 MESSAGE_BEGIN(NORMAL, parent->logger, m, "TxQ" << adr << ":   Compound " << onAirSN);
00272                 m << ", ackSN " << ((snIt == ackSNs.end()) ? -1 : (*snIt));
00273                 m << " -> " << txCounter;
00274                 m << " transmissions, retransmit";
00275                 MESSAGE_END();
00276 
00277                 if(insertBack)
00278                 {
00279                     txQueue.push_back(*onAirIt);
00280                 }
00281                 else
00282                 {
00283                     txQueueFirst = txQueue.insert(txQueueFirst, *onAirIt);
00284                     txQueueFirst++;
00285                 }
00286             } // lifetime not expired
00287         } // SN does not match
00288         else
00289         {
00290             // *snIt is equal to sn from *onAirIt --> success, go to next sn
00291             MESSAGE_BEGIN(NORMAL, parent->logger, m, "TxQ" << adr << ":   Compound " << onAirSN);
00292             m << ", ackSN " << (*snIt) << " -> success";
00293             MESSAGE_END();
00294             snIt++;
00295 
00296             parent->numTxAttemptsProbe->put(onAirIt->first, parent->getCommand((onAirIt->first)->getCommandPool())->localTransmissionCounter);
00297             transmittedBits+=(onAirIt->first)->getCommandPool()->getSDU()->getLengthInBits();
00298         } // SN matches
00299     } // for-loop over onAirQueue
00300 
00301     // signal once per BlockACK
00302     if(blockACKsuccess)
00303     {
00304         perMIB->onSuccessfullTransmission(adr);
00305     }
00306     else
00307     {
00308         perMIB->onFailedTransmission(adr);
00309     }
00310 
00311     // nothing is onAir now
00312     for (int i=0; i < parent->observers.size(); i++)
00313     {
00314         parent->observers[i]->onBlockACKReception(blockACKsuccess,transmittedBits);
00315     }
00316     onAirQueue.clear();
00317 
00318    // find oldest timestamp
00319    oldestTimestamp = wns::simulator::Time();
00320    if (txQueueSize() > 0)
00321    {
00322        oldestTimestamp = txQueue.begin()->second;
00323        for (std::deque<CompoundPtrWithTime>::iterator itr = txQueue.begin(); itr != txQueue.end(); itr++)
00324        {
00325            if (itr->second < oldestTimestamp)
00326            {
00327                oldestTimestamp = itr->second;
00328            }
00329        }
00330    }
00331 } // TransmissionQueue::processACK
00332 
00333 bool
00334 TransmissionQueue::isSortedBySN(const std::deque<CompoundPtrWithTime> q) const
00335 {
00336     if(q.empty())
00337     {
00338         return true;
00339     }
00340     std::deque<CompoundPtrWithTime>::const_iterator it = q.begin();
00341     wifimac::draftn::BlockACKCommand::SequenceNumber lastSN = parent->getCommand((it->first)->getCommandPool())->peer.sn;
00342     ++it;
00343     MESSAGE_SINGLE(NORMAL,parent->logger,"SN: (+)" << lastSN);
00344 
00345     for(;
00346         it != q.end();
00347         it++)
00348     {
00349         wifimac::draftn::BlockACKCommand::SequenceNumber curSN = parent->getCommand((it->first)->getCommandPool())->peer.sn;
00350         MESSAGE_SINGLE(NORMAL,parent->logger,"SN: " << curSN);
00351         if(curSN < lastSN)
00352         {
00353             return false;
00354         }
00355         lastSN = curSN;
00356     }
00357     return true;
00358 }
00359 
00360 const bool
00361 TransmissionQueue::waitsForACK() const
00362 {
00363     return(this->waitForACK);
00364 }
00365 
00366 wns::ldk::CompoundPtr 
00367 TransmissionQueue::getTxFront()
00368 {
00369     if (txQueue.empty())
00370     {
00371         return wns::ldk::CompoundPtr();
00372     }
00373     return txQueue.front().first;
00374 }
00375 
00376 
00377 std::list<wns::ldk::CompoundPtr> 
00378 TransmissionQueue::getAirableCompounds() 
00379 {
00380     std::list<wns::ldk::CompoundPtr> ret;
00381     size_t retSize = 0;
00382     for (std::deque<CompoundPtrWithTime>::iterator itr = txQueue.begin(); itr != txQueue.end(); itr++)
00383     {
00384         if (retSize + (*(*sizeCalculator))(itr->first) > maxOnAir)
00385         {
00386             break;
00387         }
00388         ret.push_back(itr->first);
00389         retSize += (*(*sizeCalculator))(itr->first);
00390     }
00391     return ret;
00392 }

Generated on Sat May 26 03:32:06 2012 for openWNS by  doxygen 1.5.5