User Manual, Developers Guide and API Documentation

DSAStrategy.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  * 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/scheduler/strategy/dsastrategy/DSAStrategy.hpp>
00029 #include <WNS/scheduler/strategy/Strategy.hpp>
00030 #include <string>
00031 
00032 using namespace wns::scheduler;
00033 using namespace wns::scheduler::strategy;
00034 using namespace wns::scheduler::strategy::dsastrategy;
00035 
00036 DSAStrategy::DSAStrategy(const wns::pyconfig::View& config)
00037     : logger(config.get("logger")),
00038       oneUserOnOneSubChannel(config.get<bool>("oneUserOnOneSubChannel")),
00039       adjacentSubchannelsOnUplink(config.get<bool>("adjacentSubchannelsOnUplink")),
00040       highestDataRatePerSubChannel(0.0),
00041       phyModeMapper(NULL),
00042       myUserID(NULL),
00043       dsastrategyName(config.get<std::string>("nameInDSAStrategyFactory"))
00044 {
00045     MESSAGE_SINGLE(NORMAL, logger,"DSAStrategy="<<dsastrategyName);
00046 }
00047 
00048 DSAStrategy::~DSAStrategy()
00049 {
00050 }
00051 
00052 void
00053 DSAStrategy::setColleagues(RegistryProxyInterface* _registry)
00054 {
00055     colleagues.registry = _registry;
00056     assure(colleagues.registry!=NULL,"need colleagues.registry");
00057     phyModeMapper = colleagues.registry->getPhyModeMapper();
00058     assure(phyModeMapper!=NULL,"need phyModeMapper");
00059     wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr =
00060         phyModeMapper->getHighestPhyMode();
00061     assure(phyModePtr!=wns::service::phy::phymode::PhyModeInterfacePtr(),"undefined phymode");
00062     assure(phyModePtr->isValid(),"need valid phymode");
00063     assure(phyModePtr->dataRateIsValid(),"need phymode with dataRate feature:"<<*phyModePtr);
00064     highestDataRatePerSubChannel = phyModePtr->getDataRate();
00065     // UL-slave: I may only use those resources (subchannels,slots) where my userID is written into
00066     myUserID = colleagues.registry->getMyUserID(); // that's me
00067     assure(myUserID.isValid(),"cannot get userID");
00068     MESSAGE_SINGLE(NORMAL, logger, "DSAStrategy::setColleagues("<<myUserID.getName()<<"): bestPhyMode="<<*phyModePtr<<", maxrate/sc="<<highestDataRatePerSubChannel/1e6<<"Mbit/s");
00069 } // setColleagues
00070 
00071 // call this before each timeSlot/frame
00072 void
00073 DSAStrategy::initialize(SchedulerStatePtr schedulerState,
00074             SchedulingMapPtr schedulingMap)
00075 {
00076     assure(colleagues.registry!=NULL,"need colleagues.registry");
00077     assure(schedulerState!=SchedulerStatePtr(),"schedulerState must be valid");
00078     MESSAGE_SINGLE(NORMAL, logger, "DSAStrategy::initialize("<<dsastrategyName<<"): maxrate/sc="<<highestDataRatePerSubChannel/1e6<<"Mbit/s");
00079 } // initialize
00080 
00081 simTimeType
00082 DSAStrategy::getCompoundDuration(RequestForResource& request) const
00083 {
00084     // phyMode may be undefined (most cases). Then it is free to choose (later in AMC,APC).
00085     wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr = request.phyModePtr;
00086     simTimeType requestedCompoundDuration = 0;
00087     assure(highestDataRatePerSubChannel>0.0,"highestDataRatePerSubChannel="<<highestDataRatePerSubChannel);
00088     if (phyModePtr==wns::service::phy::phymode::PhyModeInterfacePtr())
00089     { // empty=undefined phyMode
00090         requestedCompoundDuration =
00091           request.bits / highestDataRatePerSubChannel;
00092     } else {
00093         assure(phyModePtr->isValid(),"need valid phymode");
00094         assure(phyModePtr->dataRateIsValid(),"need phymode with dataRate feature:"<<*phyModePtr);
00095         double dataRatePerSubChannel = phyModePtr->getDataRate();
00096         requestedCompoundDuration =
00097           request.bits / dataRatePerSubChannel;
00098     }
00099     MESSAGE_SINGLE(NORMAL, logger, "getCompoundDuration("<<request.toString()<<"): d="<<requestedCompoundDuration*1e6<<"us");
00100     return requestedCompoundDuration;
00101 } // getCompoundDuration
00102 
00103 int
00104 DSAStrategy::getSpatialLayerForSubChannel(int subChannel,
00105                   int timeSlot,
00106                   RequestForResource& request,
00107                   SchedulerStatePtr schedulerState,
00108                   SchedulingMapPtr schedulingMap) const
00109 {
00110     assure(subChannel>=0,"need a valid subChannel");
00111     assure(subChannel<schedulerState->currentState->strategyInput->getFChannels(),"invalid subChannel="<<subChannel);
00112     assure(timeSlot>=0,"need a valid timeSlot");
00113     assure(timeSlot<schedulerState->currentState->strategyInput->getNumberOfTimeSlots(),"invalid timeSlot="<<timeSlot);
00114         assure(channelIsUsable(subChannel, timeSlot, request, schedulerState, schedulingMap),"invalid timeslot");
00115     int numSpatialLayers = schedulerState->currentState->strategyInput->getMaxSpatialLayers();
00116     int getBeam = 0;
00117     bool ok;
00118     for ( int spatialLayer = 0; spatialLayer < numSpatialLayers; ++spatialLayer )
00119     { // only for MIMO. For SISO simply spatialLayer=0
00120         PhysicalResourceBlock& prbDescriptor =
00121             schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[spatialLayer];
00122         // can be different if "sort" has been applied:
00123         assure(subChannel==prbDescriptor.getSubChannelIndex(),
00124                "subChannel="<<subChannel<<" != subChannelIndex="<<prbDescriptor.getSubChannelIndex());
00125         assure(timeSlot==prbDescriptor.getTimeSlotIndex(),
00126                "timeSlot="<<timeSlot<<" !=timeSlotIndex="<<prbDescriptor.getTimeSlotIndex());
00127         assure(spatialLayer==prbDescriptor.getSpatialLayerIndex(),
00128                "spatialLayer="<<spatialLayer<<" != spatialIndex="<<prbDescriptor.getSpatialLayerIndex());
00129         // an empty subChannel can always be used:
00130         if (!prbDescriptor.hasScheduledCompounds())
00131             {
00132                 //check the grouping constraints:
00133                     //other user in the first spatial layer is the same group and not the same user 
00134                     if (schedulerState->currentState->sdmaGroupingIsValid() && (spatialLayer != 0))
00135                     {
00136                         PhysicalResourceBlock& firstPrb = schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[0];
00137                         UserID otherUser = firstPrb.getUserID();
00138                         GroupingPtr grouping = schedulerState->currentState->getGrouping();
00139                         if ((grouping->userGroupNumber[otherUser] != grouping->userGroupNumber[request.user]) 
00140                                 || (otherUser == request.user))
00141                         { continue; }
00142                     }
00143                     return spatialLayer;
00144                 }
00145         // now we are sure that the subChannel is used by at least one packet
00146         // check if another user is blocking the subChannel:
00147         if (oneUserOnOneSubChannel)
00148         {   // checking the first packet is sufficient:
00149             UserID otherUser = prbDescriptor.getUserIDOfScheduledCompounds();
00150             if (otherUser != request.user)
00151                 continue;
00152         }
00153         // check if the PhyMode is already fixed:
00154         wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr =
00155             prbDescriptor.getPhyMode();
00156         RequestForResource requestWithGivenPhyMode = request; // copy
00157         requestWithGivenPhyMode.phyModePtr = phyModePtr;
00158         simTimeType compoundDuration = getCompoundDuration(requestWithGivenPhyMode);
00159         // check if there is enough space (time) left:
00160         simTimeType remainingTimeOnthisChannel = prbDescriptor.getFreeTime();
00161         ok = (remainingTimeOnthisChannel - compoundDuration) >= -wns::scheduler::strategy::slotLengthRoundingTolerance;
00162         if (ok){
00163             getBeam = spatialLayer;
00164             break;
00165         }
00166     }
00167     return getBeam;
00168 }
00169 
00170 bool
00171 DSAStrategy::channelIsUsable(int subChannel,
00172                  int timeSlot,
00173                  RequestForResource& request,
00174                  SchedulerStatePtr schedulerState,
00175                  SchedulingMapPtr schedulingMap) const
00176 {
00177     assure(subChannel>=0,"need a valid subChannel");
00178     assure(subChannel<schedulerState->currentState->strategyInput->getFChannels(),"invalid subChannel="<<subChannel);
00179     assure(timeSlot>=0,"need a valid timeSlot");
00180     assure(timeSlot<schedulerState->currentState->strategyInput->getNumberOfTimeSlots(),"invalid timeSlot="<<timeSlot);
00181         if(schedulerState->currentState->groupingIsValid())
00182             assure(oneUserOnOneSubChannel, "oneUserOnOneSubChannel required for beamforming/SDMA");
00183     if (!schedulingMap->subChannels[subChannel].subChannelIsUsable) return false; // locked sc?
00184     //int numberOfTimeSlots = schedulerState->currentState->strategyInput->getNumberOfTimeSlots();
00185     int numberOfTimeSlots = schedulerState->currentState->strategyInput->getNumberOfTimeSlots();
00186     int numSpatialLayers = schedulerState->currentState->strategyInput->getMaxSpatialLayers();
00187     bool ok;
00188     //for ( int timeSlot = 0; timeSlot < numberOfTimeSlots; ++timeSlot )
00189     //{
00190         for ( int spatialLayer = 0; spatialLayer < numSpatialLayers; ++spatialLayer )
00191         { // only for MIMO. For SISO simply spatialLayer=0
00192             PhysicalResourceBlock& prbDescriptor =
00193                 schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[spatialLayer];
00194             // can be different if "sort" has been applied:
00195             assure(subChannel==prbDescriptor.getSubChannelIndex(),
00196                    "subChannel="<<subChannel<<" != subChannelIndex="<<prbDescriptor.getSubChannelIndex());
00197             assure(spatialLayer==prbDescriptor.getSpatialLayerIndex(),
00198                    "spatialLayer="<<spatialLayer<<" != spatialIndex="<<prbDescriptor.getSpatialLayerIndex());
00199             // TODO: copy code from other channelIsUsable() method...
00200             // an empty subChannel can always be used:
00201             if (!prbDescriptor.hasScheduledCompounds())
00202             {
00203                             //check the grouping constraints:
00204                             //other user in the first spatial layer is the same group and not the same user 
00205                             if (schedulerState->currentState->sdmaGroupingIsValid() && (spatialLayer != 0))
00206                             {
00207                                 PhysicalResourceBlock& firstPrb = schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[0];
00208                                 UserID otherUser = firstPrb.getUserID();
00209                                 GroupingPtr grouping = schedulerState->currentState->getGrouping();
00210                                 if ((grouping->userGroupNumber[otherUser] != grouping->userGroupNumber[request.user]) 
00211                                         || (otherUser == request.user))
00212                                 { return false; }
00213                             } 
00214                             return true;
00215                         }
00216             // now we are sure that the subChannel is used by at least one packet
00217             // check if another user is blocking the subChannel:
00218             if (oneUserOnOneSubChannel)
00219             {   // checking the first packet is sufficient:
00220                 UserID otherUser = prbDescriptor.getUserIDOfScheduledCompounds();
00221                 if (otherUser != request.user)
00222                 {
00223                     MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"): tSlot="<<timeSlot<<", spatialLayer="<<spatialLayer<<": otherUser="<<otherUser.getName()<<" != request.user="<<request.user.getName());
00224                     return false;
00225                 }
00226             }
00227             // check if the PhyMode is already fixed:
00228             wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr =
00229                 prbDescriptor.getPhyMode();
00230             RequestForResource requestWithGivenPhyMode = request; // copy
00231             requestWithGivenPhyMode.phyModePtr = phyModePtr;
00232             simTimeType compoundDuration = getCompoundDuration(requestWithGivenPhyMode);
00233             // check if there is enough space (time) left:
00234             simTimeType remainingTimeOnthisChannel =
00235                 //schedulingMap->subChannels[subChannel].physicalResources[spatialLayer].getFreeTime();
00236                 prbDescriptor.getFreeTime();
00237             ok = (remainingTimeOnthisChannel - compoundDuration) >= -wns::scheduler::strategy::slotLengthRoundingTolerance;
00238             MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"): d="<<compoundDuration*1e6<<"us <= "<<remainingTimeOnthisChannel*1e6<<"us remaining: ok="<<ok);
00239             if (ok) break;
00240         } // forall spatialLayers/streams of this subChannel
00241     //} // forall timeSlots of this subChannel
00242     return ok;
00243 } // channelIsUsable
00244 
00245 bool
00246 DSAStrategy::channelIsUsable(int subChannel,
00247                  int timeSlot,
00248                  int spatialLayer,
00249                  RequestForResource& request,
00250                  SchedulerStatePtr schedulerState,
00251                  SchedulingMapPtr schedulingMap) const
00252 {
00253     assure(subChannel>=0,"need a valid subChannel");
00254     assure(subChannel<schedulerState->currentState->strategyInput->getFChannels(),"invalid subChannel="<<subChannel);
00255     assure(timeSlot>=0,"need a valid timeSlot");
00256     assure(timeSlot<schedulerState->currentState->strategyInput->getNumberOfTimeSlots(),"invalid timeSlot="<<timeSlot);
00257     assure(spatialLayer>=0,"need a valid spatialLayer");
00258     assure(spatialLayer<schedulerState->currentState->strategyInput->getMaxSpatialLayers(),"invalid spatialLayer="<<spatialLayer);
00259         if(schedulerState->currentState->groupingIsValid())
00260         {
00261             assure(oneUserOnOneSubChannel, "oneUserOnOneSubChannel required for beamforming/SDMA");
00262         }
00263         if (!schedulingMap->subChannels[subChannel].subChannelIsUsable)
00264         {
00265             return false; // locked sc?
00266         }
00267     // TODO: should we introduce
00268     // bool allBeamsUsedByOneUserOnly
00269     PhysicalResourceBlock& prbDescriptor =
00270         schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[spatialLayer];
00271     // can be different if "sort" has been applied:
00272     assure(subChannel==prbDescriptor.getSubChannelIndex(),
00273            "subChannel="<<subChannel<<" != subChannelIndex="<<prbDescriptor.getSubChannelIndex());
00274     assure(spatialLayer==prbDescriptor.getSpatialLayerIndex(),
00275            "spatialLayer="<<spatialLayer<<" != spatialIndex="<<prbDescriptor.getSpatialLayerIndex());
00276     // check if another user is blocking the subChannel:
00277     if (oneUserOnOneSubChannel)
00278     {   // checking the first packet is sufficient:
00279         //UserID otherUser = prbDescriptor.scheduledCompounds.begin()->userID;
00280         UserID otherUser = prbDescriptor.getUserID(); // uid of first packet or resource as a whole
00281         const wns::scheduler::SchedulerSpotType& schedulerSpot = schedulerState->schedulerSpot;
00282         if (schedulerSpot==wns::scheduler::SchedulerSpot::ULSlave())
00283         { // uplink: I am slave. is this resource for me?
00284             if (!otherUser.isValid())
00285             {
00286                 // an empty subChannel can always be used:
00287                 MESSAGE_SINGLE(NORMAL, logger, "UL-slave: channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): myUser="<<myUserID.getName()<<", other=NULL => unusableInUL");
00288                 return false;
00289             }
00290             if (otherUser != myUserID)
00291             {
00292                 assure(otherUser.isValid(),"!otherUser.isValid()");
00293                 MESSAGE_SINGLE(NORMAL, logger, "UL-slave: channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): myUser="<<myUserID.getName()<<", other="<<otherUser.getName()<<", request="<<request.user.getName()<<": unusable");
00294                 return false;
00295             }
00296             // at this point I'm sure that this resource is principially usable by me.
00297             MESSAGE_SINGLE(NORMAL, logger, "UL-slave: channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): myUser="<<myUserID.getName()<<", other="<<otherUser.getName()<<" is ok");
00298         } else { // master scheduler (DL|UL)
00299             // an empty subChannel can always be used:
00300             if (!prbDescriptor.hasScheduledCompounds())
00301             {
00302                                 // check the grouping constraints:
00303                                 //other user in the first spatial layers is the same group and not the same user 
00304                                 if (schedulerState->currentState->sdmaGroupingIsValid() && (spatialLayer != 0))
00305                                 {
00306                                     PhysicalResourceBlock& firstPrb = schedulingMap->subChannels[subChannel].temporalResources[timeSlot]->physicalResources[0];
00307                                     UserID otherUser = firstPrb.getUserID();
00308                                     GroupingPtr grouping = schedulerState->currentState->getGrouping();
00309                                     if ((grouping->userGroupNumber[otherUser] != grouping->userGroupNumber[request.user]) 
00310                                             || (otherUser == request.user))
00311                                     {
00312                                         MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): grouping constraints not met myUser= "<<request.user.getName()<<", other="<<otherUser.getName()<<" => unusable" );
00313                                         return false; 
00314                                     }
00315                                     MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): grouping constraints met myUser: "<<request.user.getName()<<", other="<<otherUser.getName()<<" => isusable" );
00316                                 }
00317                 MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): empty channel; can always be used (with SDMA: grouping constraints statisfied)");
00318                 return true;
00319             }
00320                         // We cannot add data to a block that is already protected by HARQ
00321                         if (prbDescriptor.isHARQEnabled())
00322                         {
00323                             return false;
00324                         }
00325 
00326             // now we are sure that the subChannel is used by at least one packet
00327             if (otherUser != request.user)
00328             {
00329                 MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): otherUser="<<otherUser.getName()<<" != request.user="<<request.user.getName());
00330                 return false;
00331             }
00332             // at this point I'm sure that this resource is principially usable by me.
00333         } // slave|master
00334     } else { // oneUserOnOneSubChannel==false
00335         // we will have a problem with different txPower and PhyMode on this subChannel
00336         MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): WARNING: oneUserOnOneSubChannel="<<oneUserOnOneSubChannel<<" is NEW and untested");
00337         // an empty subChannel can always be used:
00338         if (!prbDescriptor.hasScheduledCompounds())
00339         {
00340             MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): empty channel; can always be used");
00341             return true;
00342         }
00343     }
00344     // This is the check if the PhyMode is already fixed:
00345     wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr =
00346         prbDescriptor.getPhyMode();
00347     assure(phyModePtr!=wns::service::phy::phymode::PhyModeInterfacePtr(),"phyModePtr==NULL");
00348     RequestForResource requestWithGivenPhyMode = request; // copy
00349     requestWithGivenPhyMode.phyModePtr = phyModePtr;
00350     simTimeType compoundDuration = getCompoundDuration(requestWithGivenPhyMode);
00351     // check if there is enough space (time) left:
00352     simTimeType remainingTimeOnthisChannel =
00353         //schedulingMap->subChannels[subChannel][spatialLayer].getFreeTime();
00354             prbDescriptor.getFreeTime();
00355     bool ok = (remainingTimeOnthisChannel - compoundDuration) >= -wns::scheduler::strategy::slotLengthRoundingTolerance;
00356     MESSAGE_SINGLE(NORMAL, logger, "channelIsUsable("<<subChannel<<"."<<timeSlot<<"."<<spatialLayer<<"): d="<<compoundDuration*1e6<<"us <=? "<<remainingTimeOnthisChannel*1e6<<"us remaining: ok="<<ok);
00357     return ok;
00358 } // channelIsUsable(subChannel,timeSlot,spatialLayer)
00359 
00360 /*
00361   Local Variables:
00362   mode: c++
00363   fill-column: 80
00364   c-basic-offset: 8
00365   c-comment-only-line-offset: 0
00366   c-tab-always-indent: t
00367   indent-tabs-mode: t
00368   tab-width: 8
00369   End:
00370 */

Generated on Wed May 23 03:31:49 2012 for openWNS by  doxygen 1.5.5