User Manual, Developers Guide and API Documentation

HARQ.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <WNS/ldk/harq/HARQ.hpp>
00029 #include <WNS/ldk/harq/softcombining/UniformRandomDecoder.hpp>
00030 
00031 #include <WNS/ldk/FUNConfigCreator.hpp>
00032 
00033 using namespace wns::ldk::harq;
00034 
00035 /*
00036 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00037     HARQ,
00038     HARQInterface,
00039     "wns.harq.HARQ",
00040     wns::PyConfigViewCreator);
00041 */
00042 
00043 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00044     HARQFU,
00045     wns::ldk::FunctionalUnit,
00046     "wns.harq.HARQFU",
00047     wns::ldk::FUNConfigCreator);
00048 
00049 /*
00050 // HARQ class as required by scheduler integration
00051 HARQ::HARQ(wns::ldk::fun::FUN* fuNet, const wns::pyconfig::View& config) :
00052     numSenderProcesses_(config.get<int>("numSenderProcesses")),
00053     numReceiverProcesses_(config.len("receiverProcesses")),
00054     numRVs_(config.get<int>("numRVs")),
00055     logger_(config.get("logger"))
00056 {
00057     for (int ii=0; ii < numSenderProcesses_; ++ii)
00058     {
00059         senderProcesses_.push_back(HARQSenderProcess(ii, numRVs_, this, logger_));
00060     }
00061 
00062     for (int ii=0; ii < numReceiverProcesses_; ++ii)
00063     {
00064         receiverProcesses_.push_back(
00065             HARQFU::HARQReceiverProcess(config.get("receiverProcesses", ii), ii, this));
00066     }
00067 }
00068 
00069 HARQ::~HARQ()
00070 {
00071 }
00072 
00073 void
00074 //HARQ::onFUNCreated()
00075 HARQ::initialize()
00076 {
00077     for (int ii=0; ii < numReceiverProcesses_; ++ii)
00078     {
00079         receiverProcesses_[ii].onFUNCreated();
00080     }
00081 } // onFUNCreated
00082 */
00083 
00084 // HARQ as a functional unit
00085 HARQFU::HARQSenderProcess::HARQSenderProcess(int processID,
00086                                              int numRVs,
00087                                              HARQFU* entity,
00088                                              wns::logger::Logger logger):
00089     processID_(processID),
00090     numRVs_(numRVs),
00091     entity_(entity),
00092     logger_(logger),
00093     buffer_(),
00094     waitingForFeedback_(false),
00095     retransmissionCounter_(0)
00096 {
00097     assure(entity_!=NULL, "No HARQ entity available. This should not have happened");
00098 
00099     MESSAGE_BEGIN(NORMAL, logger_, m, "");
00100     m << "Process " << processID_ << " created";
00101     MESSAGE_END();
00102 }
00103 
00104 bool
00105 HARQFU::HARQSenderProcess::hasCapacity() const
00106 {
00107 
00108     if (buffer_ == NULL)
00109     {
00110         return true;
00111     }
00112 
00113     return false;
00114 }
00115 
00116 void
00117 HARQFU::HARQSenderProcess::enqueueTransmission(const wns::ldk::CompoundPtr& compound)
00118 {
00119     assure(entity_!=NULL, "No HARQ entity available. This should not have happened");
00120     HARQCommand* command = entity_->getCommand(compound->getCommandPool());
00121     command->peer.type = HARQCommand::I;
00122     command->peer.NDI = true;
00123     command->peer.processId = processID_;
00124     buffer_ = compound;
00125 
00126     entity_->addToSendQueue(buffer_->copy());
00127 }
00128 
00129 void
00130 HARQFU::HARQSenderProcess::ackReceived()
00131 {
00132     buffer_ = wns::ldk::CompoundPtr();
00133     waitingForFeedback_ = false;
00134     retransmissionCounter_ = 0;
00135 
00136     MESSAGE_BEGIN(NORMAL, logger_, m, "");
00137     m << "Process " << processID_ << " received ACK";
00138     MESSAGE_END();
00139 }
00140 
00141 void
00142 HARQFU::HARQSenderProcess::nackReceived()
00143 {
00144     waitingForFeedback_ = false;
00145     retransmissionCounter_++;
00146 
00147     wns::ldk::CompoundPtr retransmission = buffer_->copy();
00148 
00149     HARQCommand* command = entity_->getCommand(retransmission->getCommandPool());
00150     command->peer.NDI = false;
00151     command->peer.rv = (command->peer.rv + 1) % numRVs_;
00152 
00153     entity_->addToSendQueue(retransmission);
00154 
00155     MESSAGE_BEGIN(NORMAL, logger_, m, "");
00156     m << "Process " << processID_ << " received NACK";
00157     MESSAGE_END();
00158 }
00159 
00160 HARQFU::HARQReceiverProcess::HARQReceiverProcess(wns::pyconfig::View config,
00161                                                int processID,
00162                                                HARQFU* entity):
00163     processID_(processID),
00164     numRVs_(config.get<int>("numRVs")),
00165     entity_(entity),
00166     logger_(config.get("logger")),
00167     receptionBuffer_(config.get<int>("numRVs"))
00168 {
00169     assure(entity_ != NULL, "No HARQ entity available. This should not have happened");
00170 
00171     decoder_ = wns::SmartPtr<softcombining::IDecoder>(
00172         STATIC_FACTORY_NEW_INSTANCE(softcombining::IDecoder,
00173                                     FUNConfigCreator, config.get("decoder"),
00174                                     entity_->getFUN(), config.get("decoder")));
00175 
00176     MESSAGE_BEGIN(NORMAL, logger_, m, "");
00177     m << "Process " << processID_ << " created";
00178     MESSAGE_END();
00179 }
00180 
00181 void
00182 HARQFU::HARQReceiverProcess::onFUNCreated()
00183 {
00184     decoder_->onFUNCreated();
00185 }
00186 
00187 void
00188 HARQFU::HARQReceiverProcess::receive(const wns::ldk::CompoundPtr& compound)
00189 {
00190     assure(entity_ != NULL, "No HARQ entity available. This should not have happened");
00191 
00192     HARQCommand* command = entity_->getCommand(compound->getCommandPool());
00193 
00194     assure(command->peer.type == HARQCommand::I, "Misrouted ACK/NACK");
00195 
00196     if (command->peer.NDI)
00197     {
00198         receptionBuffer_.clear();
00199     }
00200 
00201     receptionBuffer_.appendEntryForRV(0, command->peer.rv, compound);
00202 
00203     CommandPool* ackPCI = entity_->getFUN()->getProxy()->createReply(compound->getCommandPool(), entity_);
00204     wns::ldk::CompoundPtr ack_ = wns::ldk::CompoundPtr(new Compound(ackPCI));
00205     HARQCommand* harqCommand = entity_->activateCommand(ackPCI);
00206     harqCommand->peer.processId = processID_;
00207 
00208     if (decoder_->canDecode(receptionBuffer_))
00209     {
00210         harqCommand->peer.type = HARQCommand::ACK;
00211         entity_->addToSendQueue(ack_);
00212 
00213         if(entity_->getDeliverer()->size())
00214             entity_->getDeliverer()->getAcceptor(compound)->onData(compound);
00215 
00216         receptionBuffer_.clear();
00217     }
00218     else
00219     {
00220         harqCommand->peer.type = HARQCommand::NACK;
00221         entity_->addToSendQueue(ack_);
00222     }
00223 }
00224 
00225 HARQFU::HARQFU(wns::ldk::fun::FUN* fuNet, const wns::pyconfig::View& config) :
00226     fu::Plain<HARQFU, HARQCommand>(fuNet),
00227     numSenderProcesses_(config.get<int>("numSenderProcesses")),
00228     numReceiverProcesses_(config.len("receiverProcesses")),
00229     numRVs_(config.get<int>("numRVs")),
00230     logger_(config.get("logger"))
00231 {
00232     for (int ii=0; ii < numSenderProcesses_; ++ii)
00233     {
00234         senderProcesses_.push_back(HARQSenderProcess(ii, numRVs_, this, logger_));
00235     }
00236 
00237     for (int ii=0; ii < numReceiverProcesses_; ++ii)
00238     {
00239         receiverProcesses_.push_back(
00240             HARQFU::HARQReceiverProcess(config.get("receiverProcesses", ii), ii, this));
00241     }
00242 }
00243 
00244 HARQFU::~HARQFU()
00245 {
00246 }
00247 
00248 void
00249 HARQFU::onFUNCreated()
00250 {
00251     for (int ii=0; ii < numReceiverProcesses_; ++ii)
00252     {
00253         receiverProcesses_[ii].onFUNCreated();
00254     }
00255 }  // onFUNCreated
00256 
00257 bool
00258 HARQFU::hasCapacity() const
00259 {
00260     for (int ii=0; ii < numSenderProcesses_; ++ii)
00261     {
00262         // Any of my send processes idle?
00263         if (senderProcesses_[ii].hasCapacity())
00264         {
00265             return true;
00266         }
00267     }
00268 
00269     // Damn! All busy
00270     return false;
00271 }
00272 
00273 const wns::ldk::CompoundPtr
00274 HARQFU::hasSomethingToSend() const
00275 {
00276     if (!sendQueue_.empty())
00277     {
00278         return sendQueue_.front();
00279     }
00280 
00281     return wns::ldk::CompoundPtr();
00282 }
00283 
00284 wns::ldk::CompoundPtr
00285 HARQFU::getSomethingToSend()
00286 {
00287     if (!sendQueue_.empty())
00288     {
00289         wns::ldk::CompoundPtr it = sendQueue_.front();
00290         sendQueue_.pop_front();
00291 
00292         return it;
00293     }
00294 
00295     return wns::ldk::CompoundPtr();
00296 }
00297 
00298 void
00299 HARQFU::processOutgoing(const wns::ldk::CompoundPtr& compound)
00300 {
00301     activateCommand(compound->getCommandPool());
00302 
00303     for (int ii=0; ii < numSenderProcesses_; ++ii)
00304     {
00305         // Any of my send processes idle?
00306         if (senderProcesses_[ii].hasCapacity())
00307         {
00308             MESSAGE_BEGIN(NORMAL, logger_, m, getFUN()->getName());
00309             m << " HARQ process " << ii << " is now active";
00310             MESSAGE_END();
00311 
00312             HARQCommand* command = getCommand(compound->getCommandPool());
00313             command->peer.NDI = true;
00314             command->peer.processId = ii;
00315             senderProcesses_[ii].enqueueTransmission(compound);
00316             break;
00317         }
00318     }
00319 }
00320 
00321 void
00322 HARQFU::processIncoming(const wns::ldk::CompoundPtr& compound)
00323 {
00324     HARQCommand* command = getCommand(compound->getCommandPool());
00325 
00326     int processId = command->peer.processId;
00327     bool ndi = command->peer.NDI;
00328     HARQCommand::FrameType commandType = command->peer.type;
00329 
00330     switch(commandType)
00331     {
00332     case HARQCommand::I:
00333         MESSAGE_BEGIN(NORMAL, logger_, m, getFUN()->getName());
00334         m << " received compound for process " << processId;
00335         if (ndi)
00336         {
00337             m << " (NDI)";
00338         }
00339         MESSAGE_END();
00340 
00341         assure(processId < numReceiverProcesses_ && processId >= 0, "No receiver process for this ProcessId");
00342 
00343         receiverProcesses_[processId].receive(compound);
00344 
00345         break;
00346 
00347     case HARQCommand::ACK:
00348 
00349         assure(processId < numSenderProcesses_ && processId >= 0, "No receiver process for this ProcessId");
00350 
00351         MESSAGE_BEGIN(NORMAL, logger_, m, getFUN()->getName());
00352         m << " received ACK compound for process " << processId;
00353         if (ndi)
00354         {
00355             m << " (NDI)";
00356         }
00357         MESSAGE_END();
00358 
00359         senderProcesses_[processId].ackReceived();
00360 
00361         break;
00362 
00363     case HARQCommand::NACK:
00364 
00365         assure(processId < numSenderProcesses_ && processId >= 0, "No receiver process for this ProcessId");
00366 
00367         senderProcesses_[processId].nackReceived();
00368     }
00369 }
00370 
00371 void
00372 HARQFU::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const
00373 {
00374     //What are the sizes in the upper Layers
00375     getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this);
00376     //commandPoolSize += checkSumLength;
00377 
00378 } // calculateSizes
00379 
00380 void
00381 HARQFU::addToSendQueue(wns::ldk::CompoundPtr compound)
00382 {
00383     sendQueue_.push_back(compound);
00384 }
00385 
00386 

Generated on Sun May 27 03:31:44 2012 for openWNS by  doxygen 1.5.5