![]() |
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-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 <LTE/controlplane/MapHandler.hpp> 00029 00030 #include <LTE/main/Layer2.hpp> 00031 #include <LTE/timing/TimingScheduler.hpp> 00032 #include <LTE/timing/ResourceScheduler.hpp> 00033 #include <LTE/macr/PhyUser.hpp> 00034 00035 #include <DLL/StationManager.hpp> 00036 00037 #include <WNS/ldk/fun/FUN.hpp> 00038 #include <WNS/service/phy/ofdma/Pattern.hpp> 00039 00040 #include <fstream> 00041 00042 using namespace lte; 00043 using namespace lte::controlplane; 00044 using namespace wns; 00045 using namespace wns::ldk; 00046 00047 #define A2N(a) (((a).getInteger()>0) ? layer2->getStationManager()->getStationByMAC(a)->getName() : "DLL<0") 00048 00049 STATIC_FACTORY_REGISTER_WITH_CREATOR(MapHandler, FunctionalUnit, "lte.controlplane.MapHandler", FUNConfigCreator); 00050 00051 MapHandler::MapHandler(wns::ldk::fun::FUN* fun, const pyconfig::View& config) : 00052 CommandTypeSpecifier<MapCommand>(fun), 00053 HasReceptor<>(), 00054 HasConnector<>(), 00055 HasDeliverer<>(), 00056 Cloneable<MapHandler>(), 00057 helper::HasModeName(config), 00058 layer2(NULL), 00059 myUser(NULL), 00060 friends(), 00061 pduSize(config.get<uint32_t>("pduSize")), 00062 lowestSubChannel(config.get<uint32_t>("lowestMapChannel")), 00063 highestSubChannel(config.get<uint32_t>("highestMapChannel")), 00064 framesPerSuperFrame(config.get<int>("framesPerSuperFrame")), 00065 scheduledDLResources(framesPerSuperFrame), 00066 scheduledULResources(framesPerSuperFrame), 00067 phyModePtr(wns::service::phy::phymode::createPhyMode(config.getView("phyMode"))), 00068 txPower(config.get<wns::Power>("txPower")), 00069 writeMapOutput(config.get<bool>("writeMapOutput")), 00070 currentPhase(0), 00071 logger(config.get("logger")) 00072 { 00073 if (writeMapOutput) { 00074 mapOutputFileNameDL = config.get<std::string>("mapOutputFileNameDL"); 00075 mapOutputFileNameUL = config.get<std::string>("mapOutputFileNameUL"); 00076 } // else they are None 00077 } 00078 00079 MapHandler::~MapHandler() 00080 { 00081 // better would be in a method onSimulationEnd() 00082 if (writeMapOutput) closeMapOutput(); 00083 // cleanup: 00084 scheduledDLResources.clear(); 00085 scheduledULResources.clear(); 00086 } 00087 00088 void 00089 MapHandler::onFUNCreated() 00090 { 00091 layer2 = getFUN()->getLayer<dll::ILayer2*>(); 00092 myUser = dynamic_cast<lte::main::Layer2*>(getFUN()->getLayer())->getNode(); 00093 friends.associationService = layer2->getControlService<dll::services::control::Association>("ASSOCIATION"+modeBase); 00094 friends.timer = layer2->getManagementService<lte::timing::TimingScheduler>(mode+separator+"Timer"); 00095 friends.dlrs = getFUN()->findFriend<lte::timing::SchedulerIncoming*>(mode+separator+rsNameSuffix+"TX"); 00096 friends.phyUser = getFUN()->findFriend<lte::macr::PhyUser*>(modeBase+separator+"phyUser"); 00097 // obtain pointers to the schedulers that have prepared DL and UL Maps 00098 // (only needed in RAPs that perform master scheduling) 00099 try { 00100 friends.dlmip = getFUN()->findFriend<wns::scheduler::SchedulingMapProviderInterface*>(mode+separator+rsNameSuffix+"TX"); 00101 } catch(...) { 00102 friends.dlmip = NULL; 00103 } 00104 try { 00105 friends.ulmip = getFUN()->findFriend<wns::scheduler::SchedulingMapProviderInterface*>(mode+separator+rsNameSuffix+"RX"); 00106 } catch(...) { 00107 friends.ulmip = NULL; 00108 } 00109 // remember resource partitioning information service 00110 partInfo = layer2->getControlService<lte::timing::partitioning::PartitioningInfo>("PARTITIONINGINFO"+modeBase); 00111 initSuperFrameMap(); 00112 if (writeMapOutput) prepareMapOutput(); 00113 } 00114 00115 bool 00116 MapHandler::doIsAccepting(const CompoundPtr& /* compound */) const 00117 { 00118 // will never be called since nobody is likely to downconnect on the MapHandler 00119 return false; 00120 } // isAccepting 00121 00122 void 00123 MapHandler::doSendData(const CompoundPtr& /* compound */) 00124 { 00125 assure(false, "sendData of MapHandler"); 00126 } // doSendData 00127 00128 void 00129 MapHandler::saveDLMap(int frameNr, wns::scheduler::SchedulingMapPtr schedulingMap) 00130 { 00131 assure(frameNr < (int)scheduledDLResources.size(), "invalid frameNumber"); 00132 scheduledDLResources[frameNr] = schedulingMap; 00133 MESSAGE_SINGLE(NORMAL, logger, "MapHandler::saveDLMap"); 00134 MESSAGE_SINGLE(VERBOSE, logger, "MapHandler::saveDLMap schedulingMAP=" << scheduledDLResources[frameNr]->toString()); 00135 } 00136 00137 void 00138 MapHandler::saveULMap(int frameNr, wns::scheduler::SchedulingMapPtr schedulingMap) 00139 { 00140 assure(frameNr < (int)scheduledULResources.size(), "invalid frameNumber"); 00141 scheduledULResources[frameNr] = schedulingMap; 00142 MESSAGE_SINGLE(NORMAL, logger, "MapHandler::saveULMap"); 00143 MESSAGE_SINGLE(VERBOSE, logger, "MapHandler::saveULMap schedulingMAP=" << scheduledULResources[frameNr]->toString()); 00144 } 00145 void 00146 MapHandler::resetResources(int frameNr) 00147 { 00148 assure(frameNr < (int)scheduledDLResources.size(), "invalid frameNumber"); 00149 assure(frameNr < (int)scheduledULResources.size(), "invalid frameNumber"); 00150 scheduledDLResources[frameNr] = wns::scheduler::SchedulingMapPtr(); 00151 scheduledULResources[frameNr] = wns::scheduler::SchedulingMapPtr(); 00152 00153 int groupNumber = dynamic_cast<lte::timing::ResourceScheduler*>(friends.dlmip)->getPartitionGroup(); 00154 int phaseNumber = friends.timer->phaseNumberAtFrame(frameNr); 00155 } 00156 00157 void 00158 MapHandler::initSuperFrameMap() 00159 { 00160 MESSAGE_SINGLE(NORMAL, logger,"initSuperFrameMap(frames 0.."<<framesPerSuperFrame-1<<")"); 00161 00162 int groupNumber = dynamic_cast<lte::timing::ResourceScheduler*>(friends.dlmip)->getPartitionGroup(); 00163 assure(friends.timer, "MapHandler requires a friend with name: "+mode+separator+"Timer"); 00164 friends.timer->initStationTaskPhases(); // needed before timer->phaseNumberAtFrame(i) 00165 for (int i=0; i<framesPerSuperFrame; i++) 00166 { 00167 int phaseNumber = friends.timer->phaseNumberAtFrame(i); 00168 scheduledDLResources[i] = wns::scheduler::SchedulingMapPtr(); // empty map 00169 scheduledULResources[i] = wns::scheduler::SchedulingMapPtr(); // empty map 00170 } 00171 } 00172 00173 // incoming MAP from RAP to RUT 00174 void 00175 MapHandler::doOnData(const CompoundPtr& compound) 00176 { 00178 assure (compound, "Invalid Map compound received!"); 00179 00180 MapCommand* myCommand = getCommand( compound->getCommandPool()); 00181 00183 wns::service::dll::UnicastAddress listeningTo; 00184 00185 if (friends.associationService->hasAssociation()) 00186 listeningTo = friends.associationService->getAssociation(); 00187 wns::service::dll::UnicastAddress comingFrom = myCommand->magic.source; 00188 00189 // this is for me... 00190 if (listeningTo == comingFrom && friends.timer->stationTaskAtOffset(0.0/*now*/) == timing::StationTasks::UT() ) 00191 { 00192 MESSAGE_SINGLE(NORMAL, logger,"doOnData(): pdu from "<<A2N(comingFrom)<<" contains MAP"); 00193 using namespace wns::scheduler; 00194 00195 // get latest received UL+DL-MAP: 00196 SchedulingMapCollectionVector scheduledULResourceMAP = myCommand->peer.ulSchedulingMapVector; 00197 SchedulingMapCollectionVector scheduledDLResourceMAP = myCommand->peer.dlSchedulingMapVector; 00198 00199 std::vector<int> dlFrameNumbers = myCommand->peer.dlFrameNumbers; 00200 std::vector<int> ulFrameNumbers = myCommand->peer.ulFrameNumbers; 00201 00202 // check if at least one of the frames contains granted ul resources 00203 bool ulResourcesAvailable = false; 00204 00205 // multi-frame maps (support half duplex FDD [sdr]) 00206 for (size_t i=0; i<dlFrameNumbers.size(); i++) 00207 { 00208 int frameNumber = dlFrameNumbers[i]; 00209 assure(scheduledDLResourceMAP[i]!=wns::scheduler::SchedulingMapPtr(),"empty DLMAP["<<i<<" = frame"<<frameNumber<<"]"); 00210 MESSAGE_SINGLE(NORMAL, logger,"Received DL MAP for frameOffset="<<i 00211 <<", DLsize="<<scheduledDLResourceMAP[i]->getResourceUsage()*100.0<<"%" 00212 <<")"); 00213 // At this point we could make a deep_copy ! (see below) 00214 scheduledDLResources[frameNumber] = scheduledDLResourceMAP[i]; 00215 MESSAGE_SINGLE(NORMAL, logger,"DLMAP[frame="<<frameNumber<<"]="<<scheduledDLResources[frameNumber]->toString()); 00216 } // for all DL frames in MAP 00217 00218 for (size_t i=0; i<ulFrameNumbers.size(); i++) 00219 { 00220 int frameNumber = ulFrameNumbers[i]; 00221 // UL+DL MAPs (ULMAP is important for UT.RS-TX but DLMAP is not needed anymore) 00222 assure(scheduledULResourceMAP[i]!=wns::scheduler::SchedulingMapPtr(),"empty ULMAP["<<i<<" = frame"<<frameNumber<<"]"); 00223 MESSAGE_SINGLE(NORMAL, logger,"Received UL MAP for frameOffset="<<i 00224 <<" (ULsize="<<scheduledULResourceMAP[i]->getResourceUsage()*100.0<<"%" 00225 <<")"); 00226 // At this point we could make a deep_copy ! (see below) 00227 scheduledULResources[frameNumber] = scheduledULResourceMAP[i]; 00228 if (scheduledULResources[frameNumber]->hasResourcesForUser(wns::scheduler::UserID(myUser))) 00229 { 00230 ulResourcesAvailable = true; // assume always true when a MAP comes 00231 // At this point we should make a deep_copy ! 00232 } 00233 MESSAGE_SINGLE(NORMAL, logger,"ULMAP[frame="<<frameNumber<<"]="<<scheduledULResources[frameNumber]->toString()); 00234 } // for all UL frames in MAP 00235 00236 // Inform all interested observers whether or not resources have been granted 00237 if (ulResourcesAvailable) { 00238 MESSAGE_SINGLE(NORMAL, logger, "doOnData(): ulResourcesAvailable => sendNotifies..."); 00239 } 00240 // this calls resourcesGranted(bool) in RRHandler + CQIHandler: 00241 this->sendNotifies(&ResourceGrantNotificationInterface::resourcesGranted, ulResourcesAvailable); 00242 // if (ulResourcesAvailable==true): MapHandler says: "choosing cpDispatcher" instead of RACH 00243 } else { 00244 // received compound from a source (RAP) we are not associated with -> ignore it 00245 return; 00246 } 00247 } // doOnData 00248 00249 // UT asks for allowed resources (old method?). timing/ut/Events.cpp 00250 wns::scheduler::SchedulingMapPtr 00251 MapHandler::getMasterMapForSlaveScheduling(int frameNr) 00252 { 00253 // This is a SmartPtr copy. We are in UT here. 00254 // It is still the original datastructure written by BS-RS-TX 00255 return scheduledULResources[frameNr]; 00256 } 00257 // called for every frame by rap/Events.cpp: rap::StartMap::execute 00258 void 00259 MapHandler::setCurrentPhase() 00260 { 00261 //needed to reset resources at the and of a frame 00262 currentPhase = friends.timer->phaseNumberAtOffset(0.0/*relative to now*/); 00263 } 00264 00265 void 00266 MapHandler::doWakeup() 00267 { 00268 } 00269 00270 void 00271 MapHandler::calculateSizes(const CommandPool* commandPool, Bit& _commandPoolSize, Bit& _dataSize) const 00272 { 00273 getFUN()->getProxy()->calculateSizes(commandPool, _commandPoolSize, _dataSize, this); 00274 _dataSize += this->pduSize; 00275 } 00276 00277 // start sending the (UL+DL) MAPs in DL towards user terminals 00278 void 00279 MapHandler::startMapTx(simTimeType duration, std::vector<int> dlFrameNumbers, std::vector<int> ulFrameNumbers) 00280 { 00281 MESSAGE_SINGLE(NORMAL, logger,"MapHandler::startMapTx(d="<<duration<<"s): sending maps for "<<ulFrameNumbers.size()<<" UL frames, "<< dlFrameNumbers.size()<<" DL frames ..."); 00282 // when Map Tx starts, the phy has to be switched to RAP-like operation 00283 friends.phyUser->rapTuning(); 00284 00285 // prepare vectors with resource information 00286 SchedulingMapCollectionVector dlSchedulingMapVectorInMap; 00287 SchedulingMapCollectionVector ulSchedulingMapVectorInMap; 00288 for (size_t i=0; i<dlFrameNumbers.size(); i++) 00289 { 00290 int frameNumber = dlFrameNumbers[i]; 00291 assure(frameNumber < (int)scheduledDLResources.size(), "invalid frameNumber="<<frameNumber); 00292 MESSAGE_SINGLE(NORMAL, logger,"MapHandler::startMapTx(): frameNumber["<<i<<"]="<<frameNumber 00293 <<": map size: DL="<<scheduledDLResources[frameNumber]->getResourceUsage()*100.0); 00294 // Prepare sufficient copies of the map pdu for all subcarriers assigned to this station 00295 dlSchedulingMapVectorInMap.push_back(scheduledDLResources[frameNumber]); 00296 } 00297 00298 for (size_t i=0; i<ulFrameNumbers.size(); i++) 00299 { 00300 int frameNumber = ulFrameNumbers[i]; 00301 assure(frameNumber < (int)scheduledULResources.size(), "invalid frameNumber="<<frameNumber); 00302 MESSAGE_SINGLE(NORMAL, logger,"MapHandler::startMapTx(): frameNumber["<<i<<"]="<<frameNumber 00303 <<"%, UL="<<scheduledULResources[frameNumber]->getResourceUsage()*100.0<<"%"); 00304 // Prepare sufficient copies of the map pdu for all subcarriers assigned to this station 00305 ulSchedulingMapVectorInMap.push_back(scheduledULResources[frameNumber]); 00306 } 00307 00308 MESSAGE_BEGIN(NORMAL, logger,m,"MapHandler::startMapTx(): dlSchedulingMapVectorInMap.size="<<dlSchedulingMapVectorInMap.size()<<", ulSchedulingMapVectorInMap.size="<<ulSchedulingMapVectorInMap.size()<<"\n"); 00309 { 00310 for (size_t i=0; i<dlSchedulingMapVectorInMap.size(); i++) 00311 { // forall frames that are signaled in a map 00312 m<<"dlSchedulingMapVectorInMap[i="<<i<<"]="<<dlSchedulingMapVectorInMap[i]->getResourceUsage()*100.0<<"%\n"; 00313 } 00314 for (size_t i=0; i<ulSchedulingMapVectorInMap.size(); i++) 00315 { 00316 m<<"ulSchedulingMapVectorInMap[i="<<i<<"]="<<ulSchedulingMapVectorInMap[i]->getResourceUsage()*100.0<<"%\n"; 00317 } 00318 m<<"Map is broadcasted on SubChannels=" << lowestSubChannel << "..." << highestSubChannel; 00319 } 00320 MESSAGE_END(); 00321 // put tempVectors into the commands and pass them to phy 00322 for (uint32_t subBand = lowestSubChannel; subBand <= highestSubChannel; ++subBand){ 00323 CompoundPtr mapCompound = CompoundPtr(new Compound(getFUN()->createCommandPool())); 00324 MapCommand* myCommand = activateCommand(mapCompound->getCommandPool()); 00325 00326 myCommand->peer.dlSchedulingMapVector = dlSchedulingMapVectorInMap; // this is sent to the peer 00327 myCommand->peer.ulSchedulingMapVector = ulSchedulingMapVectorInMap; // this is sent to the peer 00328 myCommand->peer.dlFrameNumbers = dlFrameNumbers; 00329 myCommand->peer.ulFrameNumbers = ulFrameNumbers; 00330 myCommand->magic.source = layer2->getDLLAddress(); 00331 00332 // set PhyUser Command 00333 lte::macr::PhyCommand* phyCommand = dynamic_cast<lte::macr::PhyCommand*>( 00334 getFUN()->getProxy()->activateCommand( mapCompound->getCommandPool(), friends.phyUser )); 00335 00336 simTimeType startTime = wns::simulator::getEventScheduler()->getTime(); // now 00337 00338 phyCommand->local.beamforming = false; 00339 phyCommand->local.pattern = wns::service::phy::ofdma::PatternPtr(); // NULL Pointer 00340 phyCommand->local.start = startTime; 00341 phyCommand->local.stop = startTime + duration; 00342 phyCommand->local.subBand = subBand; 00343 phyCommand->local.modeRxTx = lte::macr::PhyCommand::Tx; 00344 phyCommand->local.phyModePtr = phyModePtr; 00345 phyCommand->magic.txp = txPower; 00346 phyCommand->magic.source = getFUN()->getLayer<dll::ILayer2*>()->getNode(); 00347 phyCommand->magic.destination = NULL; // broadcast 00348 if (getConnector()->hasAcceptor(mapCompound)) { 00349 getConnector()->getAcceptor(mapCompound)->sendData(mapCompound); 00350 MESSAGE_SINGLE(NORMAL, logger, "startMapTx: prepared and sent new outgoing DL/UL MapInfo burst."); 00351 } 00352 else 00353 assure(false, "Lower FU is not accepting scheduled Map PDU but is supposed to do so"); 00354 } 00355 // do this for DL and UL maps 00356 evaluateMaps(); 00357 } // startMapTx() 00358 00359 // prepare UT or RNUT to receive the MAPs from BS or RNBS 00360 void 00361 MapHandler::startMapRx() 00362 { 00363 // when Map Rx starts, the phy has to be switched to UT-like operation 00364 friends.phyUser->utTuning(); 00365 } 00366 00367 void 00368 MapHandler::prepareMapOutput() 00369 { 00370 if (!writeMapOutput) return; // nothing to do 00371 MESSAGE_SINGLE(NORMAL, logger, "prepareMapOutput(): opening output file "<<mapOutputFileNameDL<<" and "<<mapOutputFileNameUL); 00372 mapFileDL = new std::ofstream(mapOutputFileNameDL.c_str()); 00373 mapFileUL = new std::ofstream(mapOutputFileNameUL.c_str()); 00374 assure(mapFileDL!=NULL,"cannot write to mapFile "<<mapOutputFileNameDL); 00375 assure(mapFileUL!=NULL,"cannot write to mapFile "<<mapOutputFileNameUL); 00376 (*mapFileDL) << "% contents=\""<<logger.getLoggerName()<<" DL map\"\n"; 00377 (*mapFileUL) << "% contents=\""<<logger.getLoggerName()<<" UL map\"\n"; 00378 } 00379 00380 // analyze MAPs to get performance values from it. 00381 // Probe output and file output for Matlab 00382 void 00383 MapHandler::evaluateMaps() 00384 { 00385 if (!writeMapOutput) return; // nothing to do 00386 MESSAGE_SINGLE(NORMAL, logger, "evaluateMaps(): writing to "<<mapOutputFileNameDL<<" and "<<mapOutputFileNameUL); 00387 assure(mapFileDL!=NULL,"cannot write to mapFile "<<mapOutputFileNameDL); 00388 assure(mapFileUL!=NULL,"cannot write to mapFile "<<mapOutputFileNameUL); 00389 // problem: we have 1..N maps here for DL/UL. They can overlap. 00390 // TODO: write table output to file for postprocessing with Matlab 00391 // TODO: write a probe "ResourceUsage" here, namely only for frame frameNumbers[0] 00392 } 00393 00394 void 00395 MapHandler::closeMapOutput() 00396 { 00397 if (!writeMapOutput) return; // nothing to do 00398 MESSAGE_SINGLE(NORMAL, logger, "closeMapOutput(): closing "<<mapOutputFileNameDL<<" and "<<mapOutputFileNameUL); 00399 if (*mapFileDL) mapFileDL->close(); 00400 if (*mapFileUL) mapFileUL->close(); 00401 } 00402
1.5.5