![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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 */
1.5.5