User Manual, Developers Guide and API Documentation

ULCallback.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-2009
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * email: info@openwns.org
00009  * www: http://www.openwns.org
00010  * _____________________________________________________________________________
00011  *
00012  * openWNS is free software; you can redistribute it and/or modify it under the
00013  * terms of the GNU Lesser General Public License version 2 as published by the
00014  * Free Software Foundation;
00015  *
00016  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00017  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00018  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00019  * details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023  *
00024  ******************************************************************************/
00025 
00026 #include <WIMAC/scheduler/ULCallback.hpp>
00027 #include <WNS/ldk/Layer.hpp>
00028 #include <WNS/scheduler/RegistryProxyInterface.hpp>
00029 
00030 #include <WIMAC/Component.hpp>
00031 #include <WIMAC/Logger.hpp>
00032 #include <WIMAC/PhyAccessFunc.hpp>
00033 #include <WIMAC/PhyUserCommand.hpp>
00034 #include <WIMAC/PhyUser.hpp>
00035 #include <WIMAC/Utilities.hpp>
00036 #include <WIMAC/scheduler/RegistryProxyWiMAC.hpp>
00037 #include <boost/bind.hpp> 
00038 
00039 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00040     wimac::scheduler::ULCallback,
00041     wimac::scheduler::Callback,
00042     "wimac.scheduler.ULCallback",
00043     wns::ldk::FUNConfigCreator );
00044 
00045 using namespace wimac::scheduler;
00046 
00047 ULCallback::ULCallback(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) :
00048     Callback(fun, config),
00049     fun_(fun),
00050     slotLength_(config.get<wns::simulator::Time>("slotLength")),
00051     tbCounter_(0),
00052     beamforming(config.get<bool>("beamforming"))
00053 {}
00054 
00055 void
00056 ULCallback::callBack(wns::scheduler::SchedulingMapPtr schedulingMap)
00057 {
00058     wimac::scheduler::RegistryProxyWiMAC* registry = dynamic_cast<wimac::scheduler::RegistryProxyWiMAC*>(colleagues.registry);
00059     bool isMaster = registry->getStationType(registry->getMyUserID()) == wns::service::dll::StationTypes::AP();
00060     if (isMaster && !beamforming)
00061         return;
00062 
00063     tbCounter_++;
00064     LOG_INFO(fun_->getLayer()->getName(), " ULCallback::callBack(): ");
00065     lastScheduling_ = wns::simulator::getEventScheduler()->getTime();
00066 
00067     //send only own bursts?
00068     for(wns::scheduler::SubChannelVector::iterator iterSubChannel = 
00069             schedulingMap->subChannels.begin();
00070         iterSubChannel != schedulingMap->subChannels.end(); 
00071         ++iterSubChannel)
00072     {
00073         wns::scheduler::SchedulingSubChannel& subChannel = *iterSubChannel;
00074         for(wns::scheduler::SchedulingTimeSlotPtrVector::iterator iterTimeSlot = 
00075                 subChannel.temporalResources.begin();
00076             iterTimeSlot != subChannel.temporalResources.end(); 
00077             ++iterTimeSlot)
00078         {
00079             wns::scheduler::SchedulingTimeSlotPtr timeSlotPtr = *iterTimeSlot;
00080             for(wns::scheduler::PhysicalResourceBlockVector::iterator iterPRB = 
00081                     timeSlotPtr->physicalResources.begin();
00082                 iterPRB != timeSlotPtr->physicalResources.end(); 
00083                 ++iterPRB)
00084             {
00085                 if ( iterPRB->hasScheduledCompounds() )
00086                 {
00087                     wns::scheduler::ScheduledCompoundsList::const_iterator it;
00088                     
00089                     for(it = iterPRB->scheduledCompoundsBegin();
00090                         it != iterPRB->scheduledCompoundsEnd();
00091                         it++)
00092                     { // for every compound in subchannel:
00093                         /* Put estimated CQI in*/
00094                         it->estimatedCQI = iterPRB->getEstimatedCQI();
00095                         processPacket(*it, timeSlotPtr);
00096                     } // for (all scheduledCompounds)
00097                     iterPRB->clearScheduledCompounds();
00098                 } // if there were compounds in this resource
00099             } // forall beams
00100         } // end for ( timeSlots )
00101     } // forall subChannels
00102 }
00103 
00104 //ULSlave processPacket, setting omnidirectional transmit phy access functor
00105 void
00106 ULCallback::processPacket(const wns::scheduler::SchedulingCompound & compound,
00107     wns::scheduler::SchedulingTimeSlotPtr& timeSlotPtr)
00108 {
00109     simTimeType startTime = compound.startTime;
00110     simTimeType endTime = compound.endTime;
00111     wns::scheduler::UserID user = compound.userID;
00112     int userID = user.getNodeID();
00113     wns::service::phy::ofdma::PatternPtr pattern = compound.pattern;
00114 
00115     int fSlot = compound.subChannel;
00116     int timeSlot = compound.timeSlot;
00117     int beam = compound.spatialLayer; //beam;
00118     wns::Power txPower = compound.txPower;
00119     wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr = compound.phyModePtr;
00120 
00121 
00122     simTimeType timeSlotOffset = timeSlot * slotLength_;
00123     startTime += timeSlotOffset;
00124     endTime += timeSlotOffset - Utilities::getComputationalAccuracyFactor();
00125     wns::scheduler::ChannelQualityOnOneSubChannel estimatedCQI = compound.estimatedCQI;
00126 
00127     double rate = phyModePtr->getDataRate();
00128     wns::ldk::CompoundPtr pdu  = compound.compoundPtr;
00129     simTimeType pduDuration = pdu->getLengthInBits() / rate;
00130     // TODO
00131     assure(pdu != wns::ldk::CompoundPtr(), "Invalid empty PDU");
00132     //assure(beam < maxBeams, "Too many beams");
00133     assure(endTime > startTime, "Scheduled PDU must end after it starts");
00134     //assure(endTime <= this->getDuration(), "PDU overun the maximum duration of the frame phase!");
00135     //assure(fSlot < freqChannels, "Invalid frequency channel");
00136 
00137 #ifndef WNS_NO_LOGGING
00138     std::stringstream m;
00139     m <<     ":  direction: UL \n"
00140       << "        PDU scheduled for user (destination): " << colleagues.registry->getNameForUser(user) << "\n"
00141       << "        Frequency Slot: " << fSlot << "\n"
00142       << "        Time Slot: " << timeSlot << " slotLength: "<<slotLength_<< "\n"
00143       << "        StartTime:      " << startTime << "\n"
00144       << "        EndTime:        " << endTime<< "\n"
00145       << "        Beamforming:    " << beamforming << "\n"
00146       << "        Beam:           " << beam << "\n"
00147       << "        Tx Power:       " << txPower;
00148     LOG_INFO(fun_->getLayer()->getName(), m.str());
00149 #endif
00150 
00151     PhyAccessFunc* func = 0;
00152 
00153      //in beamforming case ((currently) = uplink master possible) the receive pattern need to be set
00154     if(compound.pattern != wns::service::phy::ofdma::PatternPtr())
00155     {
00156         assure(beamforming," set pattern without beamforming");
00157         LOG_INFO(fun_->getLayer()->getName(), " ULCallback::processPacket() create PatternSetterPhyAccessFunc " );
00158         PatternSetterPhyAccessFunc* patternFunc =
00159             new PatternSetterPhyAccessFunc;
00160         //patternFunc->destination_ is the mobile station in uplink master, as required for sdma reception. Specific receive pattern can only be distinguished by the source id.
00161         patternFunc->destination_ = user.getNode();
00162         patternFunc->transmissionStart_= startTime;
00163         patternFunc->transmissionStop_= endTime;
00164         patternFunc->pattern_ = pattern;
00165         func = patternFunc;
00166     }
00167     else if(user.isValid())
00168     {
00169         LOG_INFO(fun_->getLayer()->getName(), " ULCallback::processPacket() create OmniUnicastPhyAccessFunc");
00170         OmniUnicastPhyAccessFunc* omniUnicastFunc = new OmniUnicastPhyAccessFunc;
00171         omniUnicastFunc->destination_ = user.getNode();
00172         omniUnicastFunc->transmissionStart_ = startTime;
00173         omniUnicastFunc->transmissionStop_ = endTime;
00174         omniUnicastFunc->subBand_ = fSlot;
00175         omniUnicastFunc->beam_ = beam;
00176         omniUnicastFunc->timeSlot_ = timeSlot;
00177         omniUnicastFunc->requestedTxPower_ = txPower;
00178         func = omniUnicastFunc;
00179     }else
00180     {
00181         throw wns::Exception( "destination address missing, UT is not supposed to broadcast" );
00182     }
00183     // set PhyUser command
00184     wimac::PhyUserCommand* phyCommand = dynamic_cast<wimac::PhyUserCommand*>(
00185         fun_->getProxy()->activateCommand( pdu->getCommandPool(), friends_.phyUser ) );
00186     phyCommand->local.pAFunc_.reset( func );
00187     phyCommand->local.pAFunc_->phyMode_ = phyModePtr;
00188     phyCommand->peer.destination_ = user.getNode();
00189     wimac::Component* wimacComponent = dynamic_cast<wimac::Component*>(fun_->getLayer());
00190     phyCommand->peer.cellID_ = wimacComponent->getCellID();
00191     phyCommand->peer.source_ = wimacComponent->getNode();
00192     phyCommand->peer.phyModePtr = phyModePtr;
00193     phyCommand->peer.measureInterference_ = true; // measureInterference;
00194     phyCommand->peer.estimatedCQI = estimatedCQI;
00195     phyCommand->magic.sourceComponent_ = wimacComponent;
00196     colleagues.harq->storeSchedulingTimeSlot(tbCounter_, timeSlotPtr);
00197 
00198     phyCommand->magic.schedulingTimeSlot = wns::scheduler::SchedulingTimeSlotPtr(
00199         new wns::scheduler::SchedulingTimeSlot(*timeSlotPtr));
00200   
00201     scheduledPDUs.push(pdu);
00202 }
00203 
00204 void ULCallback::deliverNow(wns::ldk::Connector* connector)
00205 {
00206     LOG_INFO(fun_->getLayer()->getName(), " ULCallback::deliverNow() ");
00207     wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime();
00208 
00209     while (!scheduledPDUs.empty())
00210     {
00211         wns::ldk::CompoundPtr compound =
00212             scheduledPDUs.front();
00213         PhyUserCommand* phyUserCommand =
00214             friends_.phyUser->getCommand(compound->getCommandPool());
00215 
00216         PhyAccessFunc* func =
00217             dynamic_cast<PhyAccessFunc*>(phyUserCommand->local.pAFunc_.get());
00218 
00219         func->transmissionStart_ += now;
00220         func->transmissionStop_ += now;
00221         wimac::scheduler::RegistryProxyWiMAC* registry = dynamic_cast<wimac::scheduler::RegistryProxyWiMAC*>(colleagues.registry);
00222         bool isSlave = registry->getStationType(registry->getMyUserID()) == wns::service::dll::StationTypes::UT();
00223         if(isSlave)
00224         {
00225             frameOffsetDelayProbe_->put(compound, func->transmissionStart_ - lastScheduling_);
00226             transmissionDelayProbe_->put(compound, func->transmissionStop_ - func->transmissionStart_);
00227         }
00228         if(connector->hasAcceptor(scheduledPDUs.front()))
00229         {
00230             connector->getAcceptor(scheduledPDUs.front())->sendData(scheduledPDUs.front());
00231             scheduledPDUs.pop();
00232         }
00233         else
00234         {
00235             throw wns::Exception( "Lower FU is not accepting scheduled PDU but is supposed to do so" );
00236         }
00237     }
00238 }

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