![]() |
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/timing/TimingScheduler.hpp> 00029 #include <LTE/timing/events/Base.hpp> 00030 #include <LTE/timing/events/rap/Events.hpp> 00031 #include <LTE/timing/events/ut/Events.hpp> 00032 #include <LTE/main/Layer2.hpp> 00033 #include <LTE/controlplane/bch/BCHUnitInterface.hpp> 00034 00035 #include <DLL/StationManager.hpp> 00036 00037 #include <sstream> 00038 #include <boost/bind.hpp> 00039 #include <boost/shared_ptr.hpp> 00040 00041 #define A2N(a) layer2->getStationManager()->getStationByMAC(a)->getName() 00042 00043 using namespace lte::timing; 00044 using namespace lte::timing::events; 00045 00046 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00047 TimingScheduler, 00048 wns::ldk::ManagementServiceInterface, 00049 "lte.timing.TimingScheduler", 00050 wns::ldk::MSRConfigCreator); 00051 00052 TimingScheduler::TimingScheduler(wns::ldk::ManagementServiceRegistry* msr, 00053 wns::pyconfig::View _config) : 00054 wns::ldk::ManagementService(msr), 00055 lte::helper::HasModeName(_config), 00056 layer2(NULL), 00057 fun(NULL), 00058 config(_config), 00059 logger(config.get("logger")), 00060 superFrameLength(config.get<simTimeType>("mac.superFrameLength")), 00061 superFrameStartTime(0.0), 00062 eventContainer(), 00063 stationTaskPhaseContainer(), 00064 peerTiming(), 00065 peerTimingSchedulers(), 00066 es(wns::simulator::getEventScheduler()), 00067 startOfFirstFrame(config.get<simTimeType>("startOfFirstFrame")), 00068 frameLength(config.get<simTimeType>("frameLength")), 00069 schedulingOffset(config.get<int>("mac.schedulingOffset")), 00070 numberOfFramesToSchedule(config.get<int>("mac.numberOfFramesToSchedule")), 00071 framesPerSuperFrame(config.get<int>("mac.framesPerSuperFrame")), 00072 switchingPointOffset(config.get<simTimeType>("mac.switchingPointOffset")), 00073 duplex(DuplexSchemes::fromString(config.get<std::string>("mac.duplex"))) 00074 { 00075 MESSAGE_BEGIN(VERBOSE, logger, m, "TimingScheduler() constructed: "); 00076 m << "superFrameLength=" << superFrameLength << " s\n"; 00077 m << "superFrameStartTime=" << superFrameStartTime << " s\n"; 00078 m << "switchingPointOffset=" << switchingPointOffset << " s"; 00079 MESSAGE_END(); 00080 00081 } // SuperFrameScheduler 00082 00083 TimingScheduler::~TimingScheduler() 00084 { 00085 while (!eventContainer.empty()) 00086 { 00087 delete eventContainer.begin()->event; 00088 eventContainer.erase(eventContainer.begin()); 00089 } 00090 } 00091 00092 void 00093 TimingScheduler::onMSRCreated() 00094 { 00095 MESSAGE_BEGIN(NORMAL, logger, m, "onFUNCreated(): Starting Timing for superFrames with interval of "); 00096 m << superFrameLength << " s"; 00097 MESSAGE_END(); 00098 00099 // Obtain FUN pointer 00100 layer2 = dynamic_cast<dll::ILayer2*>(getMSR()->getLayer()); 00101 assure(layer2, "WinProSt TimingScheduler could not retrieve dll::ILayer2 pointer"); 00102 fun = layer2->getFUN(); 00103 00104 dll::ILayer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode); 00105 dll::ILayer2::AssociationInfoContainer::const_iterator iter = ais.begin(); 00106 for (; iter != ais.end(); ++iter) 00107 this->startObserving(*iter); 00108 00109 // this is my own frame structure (sequence of Events for one superFrameLength) 00110 readStationTaskPhases("stationTaskPhases"); 00111 // ^ too late here for MapHandler::initSuperFrameMap() which needs stationTaskPhases 00112 // NOTE: readEvents has to be re-called each time the Task phases of a 00113 // station are altered 00114 assure(wns::simulator::getEventScheduler()->getTime()==0.0,"this must be called at simTime 0.0"); 00115 readEvents("phases"); 00116 00117 startPeriodicTimeout(superFrameLength, 0); 00118 } 00119 00120 void 00121 TimingScheduler::onWorldCreated() 00122 { 00123 // only for static associations: 00124 for (int i=0; i< config.len("peers"); ++i) // foreach peer 00125 { 00126 wns::service::dll::UnicastAddress peerAddress(config.get<int32_t>("peers",i)); 00127 MESSAGE_SINGLE(NORMAL, logger, "onWorldCreated(): getting timingScheduler of peer "<<A2N(peerAddress)); 00128 dll::ILayer2* peer = layer2->getStationManager()->getStationByMAC(peerAddress); 00129 00130 lte::timing::TimingScheduler* peerTimingScheduler = NULL; 00131 00132 peerTimingScheduler = 00133 peer-> 00134 getManagementService<lte::timing::TimingScheduler>(getTimerName()); 00135 00136 assure(peerTimingScheduler,"No valid peerTimingScheduler!"); 00137 peerTimingSchedulers.insert(peerAddress, peerTimingScheduler); 00138 } 00139 } 00140 00141 // SuperFrameStart; called by simulation event scheduler 00142 void 00143 TimingScheduler::periodically() 00144 { 00145 MESSAGE_SINGLE(NORMAL, logger, "========== Start of SuperFrame =========="); 00146 superFrameStartTime = es->getTime(); 00147 00148 // execution of the stored events 00149 for (unsigned int i = 0; i < eventContainer.size(); ++i) 00150 { 00151 lte::timing::events::Base* event = eventContainer.at(i).event; 00152 simTimeType timeOffset = eventContainer.at(i).timeOffset; 00153 simTimeType at = es->getTime() + timeOffset; 00154 es->schedule(boost::bind(<e::timing::events::Base::operator(), event), at); 00155 } 00156 00157 // tell all observers that new superframe starts now 00158 this->superFrameTrigger(); 00159 } // periodically 00160 00161 int 00162 TimingScheduler::getSchedulingOffset() const 00163 { 00164 return schedulingOffset; 00165 } 00166 00167 int 00168 TimingScheduler::getNumberOfFramesToSchedule() const 00169 { 00170 return numberOfFramesToSchedule; 00171 } 00172 00173 lte::timing::StationTask 00174 TimingScheduler::stationTaskAtFrame(int frameNr /* absolute compared to superFrame start */) const 00175 { 00176 StationTaskPhase taskPhase; 00177 taskPhase = stationTaskPhaseContainer.at( phaseNumberAtFrame(frameNr)/*absolute*/ ); 00178 assure(taskPhase.task != StationTasks::INVALID(),"stationTaskAt called with an offset out of bounds"); 00179 MESSAGE_SINGLE(VERBOSE, logger, "stationTaskAtFrame(frameNr="<<frameNr<<") = "<<StationTasks::toString(taskPhase.task)); 00180 return taskPhase.task; 00181 } 00182 00183 lte::timing::StationTask 00184 TimingScheduler::stationTaskAtOffset(const simTimeType offset/*relative*/) const /* offset compared to now */ 00185 { 00186 assure(offset >= 0.0,"stationTaskAtOffset called with a negative offset"); // only into future 00187 00188 StationTaskPhase taskPhase; 00189 taskPhase = stationTaskPhaseContainer.at( phaseNumberAtOffset(offset)/*relative*/ ); 00190 assure(taskPhase.task != StationTasks::INVALID(),"stationTaskAtOffset called with an offset out of bounds"); 00191 MESSAGE_SINGLE(VERBOSE, logger, "stationTaskAtOffset("<<offset<<") = "<<StationTasks::toString(taskPhase.task)); 00192 return taskPhase.task; 00193 } 00194 00195 uint32_t 00196 TimingScheduler::phaseNumberAtFrame(int frameNr /* absolute compared to superFrame start */) const 00197 { 00198 simTimeType offset = startOfFirstFrame + frameNr * frameLength; 00199 assure(stationTaskPhaseContainer.size()>0, "stationTaskPhaseContainer not ready"); 00200 00201 for (uint32_t index = 0; index < stationTaskPhaseContainer.size(); ++index) 00202 { 00203 StationTaskPhase taskPhase = stationTaskPhaseContainer.at(index); 00204 if (taskPhase.startTime + taskPhase.duration > offset) 00205 { 00206 MESSAGE_SINGLE(VERBOSE, logger, "phaseNumberAtFrame(frameNr="<<frameNr<<",offset=" << offset << "): taskPhase=" << index <<", task=" << lte::timing::StationTasks::toString(stationTaskPhaseContainer.at(index).task)<< ""); 00207 return index; 00208 } 00209 } 00210 assure(false, "phaseNumberAtFrame("<<frameNr<<"): called with an offset out of bounds"); 00211 return 0; // to please the compiler 00212 } 00213 00214 uint32_t 00215 TimingScheduler::phaseNumberAtOffset(const simTimeType offset /* compared to now */) const 00216 { 00217 simTimeType now = es->getTime(); 00218 simTimeType currentOffsetInSuperFrame = now - superFrameStartTime; 00219 simTimeType offsetInSuperFrame = currentOffsetInSuperFrame + offset; 00220 MESSAGE_SINGLE(VERBOSE, logger, "phaseNumber("<<offset<<"=@"<<offsetInSuperFrame<<")"); 00221 assure(stationTaskPhaseContainer.size()>0, "stationTaskPhaseContainer not ready"); 00222 00223 for (uint32_t index = 0; index < stationTaskPhaseContainer.size(); ++index) 00224 { // forall tasks 00225 StationTaskPhase taskPhase = stationTaskPhaseContainer.at(index); 00226 simTimeType endTime = taskPhase.startTime + taskPhase.duration; 00227 if (endTime > offsetInSuperFrame) 00228 { // found 00229 MESSAGE_SINGLE(VERBOSE, logger, "phaseNumberAtOffset(offset=" << offset << "): taskPhase=" << index <<", task=" << lte::timing::StationTasks::toString(stationTaskPhaseContainer.at(index).task)<< ""); 00230 return index; 00231 } 00232 } 00233 assure(false, "phaseNumber("<<offset<<") called with an offset out of bounds"); 00234 return 0; // to please the compiler 00235 } 00236 00237 void 00238 TimingScheduler::addPeerTimingScheduler(wns::service::dll::UnicastAddress peerAddress, TimingScheduler* _timingScheduler) 00239 { 00240 peerTimingSchedulers.insert(peerAddress, _timingScheduler); 00241 MESSAGE_SINGLE(VERBOSE, logger, "Added peer Timing of "<<A2N(peerAddress)); 00242 } 00243 00244 void 00245 TimingScheduler::removePeerTimingScheduler(wns::service::dll::UnicastAddress peerAddress) 00246 { 00247 if (peerTimingSchedulers.knows(peerAddress)) 00248 { 00249 peerTimingSchedulers.erase(peerAddress); 00250 MESSAGE_SINGLE(VERBOSE, logger, "Successfully removed peer Timing of "<<A2N(peerAddress)); 00251 } 00252 else 00253 { 00254 MESSAGE_SINGLE(VERBOSE, logger, "Nothing to be done to remove peer Timing of "<<A2N(peerAddress)); 00255 } 00256 } 00257 00258 // Can a RN receive a map? 00259 bool 00260 TimingScheduler::canReceiveMapNow(const wns::service::dll::UnicastAddress& peerAddress) 00261 { // the station is identified by its DLL Address 00262 assure(peerTimingSchedulers.knows(peerAddress), "No knowledge about requested Peer's ("<<peerAddress<<") timing!"); 00263 bool reachable = (peerTimingSchedulers.find(peerAddress)->stationTaskAtOffset(0.0) == lte::timing::StationTasks::UT()); 00264 MESSAGE_SINGLE(VERBOSE, logger, "canReceiveMapNow(user=" << A2N(peerAddress) << "): " << (reachable ? "Yes" : "No")); 00265 return reachable; 00266 } 00267 00268 // to get info about inferior stations' availability 00269 bool 00270 TimingScheduler::isPeerListeningAt(const wns::service::dll::UnicastAddress& peerAddress, const int frameNr) 00271 { 00272 // the station is identified by its DLL Address 00273 assure(peerTimingSchedulers.knows(peerAddress), "No knowledge about requested Peer's ("<<peerAddress<<") timing!"); 00274 MESSAGE_SINGLE(VERBOSE, logger, "isPeerListeningAt(User="<< A2N(peerAddress) <<",frameNr="<<frameNr<<") ?"); 00275 bool isListening = (peerTimingSchedulers.find(peerAddress)->stationTaskAtFrame(frameNr/*absolute*/) == lte::timing::StationTasks::UT()); 00276 MESSAGE_SINGLE(VERBOSE, logger, "isPeerListeningAt(User="<< A2N(peerAddress) <<",frameNr="<<frameNr<<"): "<< (isListening ? "Yes" : "No")); 00277 return isListening; 00278 } 00279 00280 void 00281 TimingScheduler::readEvents(std::string viewName) 00282 { 00283 /* this is only called at the beginning of the simulation */ 00284 // When it is called, this method assumes that readStationTaskPhases has 00285 // already been called 00286 for(int i = 0; i < config.len(viewName); ++i) 00287 { 00288 wns::pyconfig::View phaseConfig = config.get(viewName, i); 00289 std::string plugin = phaseConfig.get<std::string>("__plugin__"); 00290 // a list of prototypes for events which are generated in pyconfig::Parser will be stored in an array 00291 TimingEvent e; 00292 e.event = NULL; 00293 e.timeOffset = phaseConfig.get<simTimeType>("time"); 00294 // be sure that this is done only at now=superframe start time. 00295 // stationTaskAtOffset(offset is relative to now) 00296 if (this->stationTaskAtOffset(e.timeOffset) == StationTasks::RAP()) 00297 { 00298 lte::timing::events::rap::EventCreator* c = 00299 lte::timing::events::rap::EventFactory::creator(plugin); 00300 e.event = c->create(fun, phaseConfig); 00301 } 00302 else if (this->stationTaskAtOffset(e.timeOffset) == StationTasks::UT()) 00303 { 00304 lte::timing::events::ut::EventCreator* c = 00305 lte::timing::events::ut::EventFactory::creator(plugin); 00306 e.event = c->create(fun, phaseConfig); 00307 } 00308 else if (this->stationTaskAtOffset(e.timeOffset) == StationTasks::IDLE()) 00309 { 00310 // do not create any events 00311 } 00312 else 00313 assure(false, "Unknown StationTask configured!"); 00314 00315 if (e.event!=NULL){ 00316 e.event->setTimer(this); 00317 eventContainer.push_back( e ); 00318 } 00319 00320 MESSAGE_BEGIN(VERBOSE, logger, m, viewName); 00321 // print frame structure. For Winner i is from [0..24], 0=Preamble, + 00322 // 3*8 frames (MapTx, DataTx, DataRx)=BS_view, (MapRx, DataRx, 00323 // DataTx)=UTview 00324 simTimeType duration = phaseConfig.get<simTimeType>("duration"); 00325 m << ": " << i << ", EvType=" << plugin << ", T=" << e.timeOffset << ", D=" << duration; 00326 MESSAGE_END(); 00327 } 00328 } // TimingScheduler::readEvents() 00329 00330 void 00331 TimingScheduler::initStationTaskPhases() 00332 { 00333 if (stationTaskPhaseContainer.size()==0) { 00334 // this is my own frame structure (sequence of Events for one superFrameLength) 00335 readStationTaskPhases("stationTaskPhases"); 00336 // ^ structure needed in MapHandler::initSuperFrameMap() 00337 } 00338 } 00339 00340 void 00341 TimingScheduler::readStationTaskPhases(std::string viewName) 00342 { 00343 if (stationTaskPhaseContainer.size()>0) { 00344 MESSAGE_SINGLE(NORMAL, logger, "readStationTaskPhases(): already processed ("<<stationTaskPhaseContainer.size()<<" elements)"); 00345 return; 00346 } 00347 simTimeType durationSum = 0.0; 00348 // read in all stationTask items. There are (framesPerSuperFrame+1) elements. 00349 for(int i = 0; i < config.len(viewName); ++i) 00350 { 00351 wns::pyconfig::View phaseConfig = config.get(viewName, i); 00352 StationTaskPhase s; 00353 s.startTime = phaseConfig.get<simTimeType>("startTime"); 00354 s.duration = phaseConfig.get<simTimeType>("duration"); 00355 s.task = StationTasks::fromString(phaseConfig.get<std::string>("task")); 00356 stationTaskPhaseContainer.push_back( s ); 00357 durationSum += s.duration; 00358 MESSAGE_BEGIN(NORMAL, logger, m, viewName); 00359 m << ": i=" << i << ", task=" << StationTasks::toString(s.task) << ", T=" << s.startTime << ", D=" << s.duration; 00360 MESSAGE_END(); 00361 } 00362 MESSAGE_SINGLE(NORMAL, logger, "readStationTaskPhases(): "<<stationTaskPhaseContainer.size()<<" StationTaskPhases; duration = "<<durationSum); 00363 assure(fabs(durationSum - superFrameLength) < 1e-9 ,"StationTaskPhase durationSum="<<durationSum<<" does not match superFrameLength="<<superFrameLength); 00364 assure(stationTaskPhaseContainer.size()>0, "stationTaskPhaseContainer is empty"); 00365 } 00366 00367 void 00368 TimingScheduler::onDisassociated(wns::service::dll::UnicastAddress userAdr, wns::service::dll::UnicastAddress dstAdr) 00369 { 00370 //RAP task only, UT do nothing here 00371 if (layer2->getDLLAddress() == dstAdr) 00372 { 00373 removePeerTimingScheduler(userAdr); 00374 MESSAGE_SINGLE(NORMAL, logger, "Successfully removed Peer TimingScheduler for user=" << A2N(userAdr)); 00375 } 00376 } 00377 00378 void 00379 TimingScheduler::onAssociated(wns::service::dll::UnicastAddress userAdr, wns::service::dll::UnicastAddress dstAdr) 00380 { 00381 MESSAGE_SINGLE(NORMAL, logger, "TimingScheduler::onAssociated called (user=" << A2N(userAdr) << " dst=" << A2N(dstAdr) << ")."); 00382 //RAP task only 00383 if (layer2->getDLLAddress() == dstAdr) 00384 { 00385 dll::ILayer2* newUser = layer2->getStationManager()->getStationByMAC(userAdr); 00386 00387 TimingScheduler* userTimingScheduler = NULL; 00388 00389 userTimingScheduler = 00390 newUser-> 00391 getManagementService<lte::timing::TimingScheduler>(getTimerName()); 00392 00393 addPeerTimingScheduler(userAdr, userTimingScheduler); 00394 MESSAGE_SINGLE(NORMAL, logger, "Successfully added Peer TimingScheduler for user=" << A2N(userAdr)); 00395 } 00396 else if (layer2->getDLLAddress() == userAdr) 00397 { 00398 // Notification in UT -> nothing to do 00399 MESSAGE_SINGLE(VERBOSE, logger, "Not adding Peer TimingScheduler for user with address " << A2N(userAdr) << " at Scheduler with Address " << A2N(userAdr)); 00400 } 00401 else 00402 { 00403 // Notification in BS while association is with RN -> nothing to do 00404 MESSAGE_SINGLE(VERBOSE, logger, "Not adding Peer TimingScheduler for user with address " << A2N(userAdr) << " at Scheduler with Address " << A2N(layer2->getDLLAddress())); 00405 } 00406 } 00407 00408 void 00409 TimingScheduler::superFrameTrigger() 00410 { 00411 this->wns::Subject<SuperFrameStartNotificationInterface>::sendNotifies(&SuperFrameStartNotificationInterface::onSuperFrameStart); 00415 try { 00416 lte::controlplane::bch::IBCHTimingTx* bch = NULL; 00417 bch = this->fun->findFriend<lte::controlplane::bch::IBCHTimingTx*>(mode+separator+"bch"); 00418 if (bch != NULL) 00419 { 00420 bch->sendBCH(0.0005); 00421 } 00422 00423 } 00424 catch (wns::ldk::fun::FindFriendException) 00425 { 00426 } 00427 } 00428 00429 void 00430 TimingScheduler::frameTrigger() 00431 { 00432 this->wns::Subject<FrameStartNotificationInterface>::sendNotifies(&FrameStartNotificationInterface::onFrameStart); 00433 } 00434 00435 00436 00437 00438 00439
1.5.5