![]() |
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/RegistryProxy.hpp> 00029 00030 #include <LTE/macg/MACg.hpp> 00031 #include <LTE/macr/PhyUser.hpp> 00032 #include <LTE/timing/TimingScheduler.hpp> 00033 #include <LTE/controlplane/RRHandler.hpp> 00034 #include <LTE/controlplane/associationHandler/AssociationHandler.hpp> 00035 #include <LTE/controlplane/flowmanagement/FlowManager.hpp> 00036 #include <LTE/macg/MACgCommand.hpp> 00037 #include <LTE/rlc/RLCCommand.hpp> 00038 00039 #include <DLL/StationManager.hpp> 00040 #include <DLL/services/control/Association.hpp> 00041 #include <DLL/services/management/InterferenceCache.hpp> 00042 00043 #include <WNS/StaticFactory.hpp> 00044 #include <WNS/node/Node.hpp> 00045 #include <WNS/ldk/FUNConfigCreator.hpp> 00046 #include <WNS/service/qos/QoSClasses.hpp> 00047 #include <WNS/scheduler/SchedulerTypes.hpp> 00048 #include <WNS/ldk/sar/SAR.hpp> 00049 #include <WNS/Ttos.hpp> 00050 #include <WNS/scheduler/harq/HARQInterface.hpp> 00051 00052 #include <iostream> 00053 #include <string> 00054 #include <vector> 00055 #include <algorithm> 00056 00057 using namespace std; 00058 using namespace lte::timing; 00059 using namespace wns::scheduler; 00060 00061 #define A2N(a) (((a).getInteger()>0) ? layer2->getStationManager()->getStationByMAC(a)->getName() : "DLL<0") 00062 00063 STATIC_FACTORY_REGISTER_WITH_CREATOR(RegistryProxy, wns::scheduler::RegistryProxyInterface, "lte.RegistryProxy", wns::ldk::FUNConfigCreator); 00064 00065 RegistryProxy::RegistryProxy(wns::ldk::fun::FUN* _fun, const wns::pyconfig::View& config) 00066 : HasModeName(config), 00067 fun(_fun), 00068 layer2(NULL), 00069 logger(config.get("logger")), 00070 associationService(NULL), 00071 friends(), 00072 //Colleagues(), 00073 phyModeMapper(wns::service::phy::phymode::PhyModeMapperInterface::getPhyModeMapper(config.getView("phyModeMapper"))), 00074 fakeChannelQualities(), // who sets that SmartPtr content? 00075 queueSize(config.get<uint32_t>("queueSize")), 00076 relaysOnly(false), // TODO: make this obsolete 00077 powerUT(config.get("powerCapabilitiesUT")), 00078 powerBS(config.get("powerCapabilitiesBS")), 00079 eirpLimited(false), 00080 isForDL(true), 00081 myTask(wns::scheduler::TaskBSorUT::TaskBaseStation()), 00082 numberOfPriorities(config.get<int>("numberOfPriorities")), 00083 numberOfQosClasses(config.get<int>("numberOfQosClasses")), 00084 qosToPriorityMapping(numberOfQosClasses), 00085 cidToUserId(), // RN|UT 00086 cidToPrio(), 00087 userIdToConnections(), 00088 connectionsForPriority(numberOfPriorities+1) // vector size from Python 00089 { 00090 MESSAGE_SINGLE(NORMAL, logger, "RegistryProxy() constructor. myTask="<<wns::scheduler::TaskBSorUT::toString(myTask)); 00091 assure(powerBS.nominalPerSubband!=wns::Power(),"undefined power="<<powerBS.nominalPerSubband); 00092 assure(powerUT.nominalPerSubband!=wns::Power(),"undefined power="<<powerUT.nominalPerSubband); 00093 wns::pyconfig::View qosClasses = config.getView("qosClassMapping"); 00094 // see qos.py 00095 assure(numberOfQosClasses == qosClasses.len("mapEntries"),"invalid qos to priority mapping"); 00096 for (int i=0; i<numberOfQosClasses; ++i) { 00097 wns::pyconfig::View mapEntry = qosClasses.getView("mapEntries",i); 00098 int number = mapEntry.get<int>("number"); 00099 assure(number == i,"QoS index mismatch: "<<number<<"!="<<i); 00100 int priority = mapEntry.get<int>("priority"); 00101 // priority is out of [0..MaxPriority-1]: 00102 assure(priority>=0 && priority<numberOfPriorities,"invalid priority="<<priority<<" (numberOfPriorities="<<numberOfPriorities<<")"); 00103 MESSAGE_SINGLE(NORMAL, logger, "RegistryProxy(): QoS="<<i<<"=\""<< mapEntry.get<std::string>("name")<<"\" => priority="<<priority); 00104 qosToPriorityMapping[i] = priority; 00105 } 00106 } // constructor 00107 00108 RegistryProxy::~RegistryProxy() 00109 { 00110 connectionsForPriority.clear(); 00111 userIdToConnections.clear(); 00112 cidToUserId.clear(); 00113 cidToPrio.clear(); 00114 } 00115 00116 void 00117 RegistryProxy::setFriends(const wns::ldk::CommandTypeSpecifierInterface* _classifier) 00118 { 00119 assure(false,"RegistryProxy::setFriends(): obsolete"); 00120 } 00121 00122 void 00123 RegistryProxy::setHARQ(wns::scheduler::harq::HARQInterface* harq) 00124 { 00125 friends.harq = harq; 00126 } 00127 00128 void 00129 RegistryProxy::setFUN(const wns::ldk::fun::FUN* _fun) 00130 { 00131 MESSAGE_SINGLE(NORMAL, logger, "RegistryProxy()::setFUN()"); 00132 // fun already known from constructor 00133 assure (_fun == fun, "invalid fun"); 00134 // rs: why again? 00135 fun = const_cast<wns::ldk::fun::FUN*>(_fun); 00136 assure(fun, "RegistryProxy needs a FUN"); 00137 layer2 = fun->getLayer<dll::Layer2*>(); 00138 assure(layer2, "could not get Layer2 from FUN"); 00139 //dll::StationManager* stationManager = layer2->getStationManager() 00140 00141 associationService = layer2->getControlService<dll::services::control::Association>("ASSOCIATION"+modeBase); 00142 iCache = layer2->getManagementService<dll::services::management::InterferenceCache>("INTERFERENCECACHE"+modeBase); 00143 friends.timer = layer2->getManagementService<lte::timing::TimingScheduler>(mode+separator+"Timer"); 00144 friends.rlcCommandReader = fun->getCommandReader("rlc"); 00145 assure(friends.rlcCommandReader, "Need rlcCommandReader as friend"); 00146 friends.macgCommandReader = fun->getCommandReader("macg"); 00147 assure(friends.macgCommandReader, "Need macgCommandReader as friend"); 00148 00149 // Register as Observer at the association Info providers 00150 dll::Layer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode); 00151 dll::Layer2::AssociationInfoContainer::const_iterator iter = ais.begin(); 00152 for (; iter != ais.end(); ++iter) 00153 this->startObserving(*iter); 00154 00155 // to know in which task the relay node is 00156 if (layer2->getStationType() == wns::service::dll::StationTypes::eNB()) 00157 { 00158 myTask = wns::scheduler::TaskBSorUT::TaskBaseStation(); 00159 friends.flowManager = layer2->getControlService<lte::controlplane::flowmanagement::FlowManager>("FlowManagerBS"); 00160 } else { 00161 myTask = wns::scheduler::TaskBSorUT::TaskUserTerminal(); 00162 friends.flowManager = layer2->getControlService<lte::controlplane::flowmanagement::FlowManager>("FlowManagerUT"); 00163 isForDL = false; 00164 } 00165 00166 assure(friends.flowManager, "FlowManager not set!"); 00167 00168 wns::scheduler::UserID bcUserID; 00169 bcUserID.setBroadcast(); 00170 registerCID(friends.flowManager->getBCHFlowID(), bcUserID); 00171 00172 if ( layer2->getStationType() == wns::service::dll::StationTypes::eNB() || 00173 (layer2->getStationType() == wns::service::dll::StationTypes::FRS() && this->getTaskSuffix()=="BS")) 00174 { 00175 friends.rrHandlerUT = NULL; 00176 friends.rrHandler = fun->findFriend<lte::controlplane::RRHandlerBS*>(mode+separator+"RRHandler"); 00177 } 00178 else 00179 { 00180 friends.rrHandlerUT = fun->findFriend<lte::controlplane::RRHandlerUT*>(mode+separator+"RRHandler"); 00181 friends.rrHandler = NULL; 00182 } 00183 } // setFUN 00184 00185 bool 00186 RegistryProxy::getCQIAvailable() const 00187 { 00188 return false; 00189 } 00190 00191 wns::scheduler::UserID 00192 RegistryProxy::getUserForCID(wns::scheduler::ConnectionID cid) 00193 { 00194 assure(cidToUserId.knows(cid),"unknown cid="<<cid); 00195 wns::scheduler::UserID userID = cidToUserId.find(cid); 00196 MESSAGE_SINGLE(VERBOSE, logger, "getUserForCID(cid="<<cid<<") = "<<getNameForUser(userID)); 00197 // search for cid in list; if not there, add it. 00198 if( find(userIdToConnections[userID].begin(),userIdToConnections[userID].end(), cid ) == userIdToConnections[userID].end()) 00199 { // not found 00200 userIdToConnections[userID].push_back(cid); 00201 // TODO: should better be done only in registerCID 00202 MESSAGE_SINGLE(NORMAL, logger, "getUserForCID(cid="<< cid << "): new cid added into userIdToConnections["<<getNameForUser(userID)<<"] = "<<wns::scheduler::printConnectionVector(userIdToConnections[userID])); 00203 } 00204 return userID; 00205 } 00206 00207 wns::service::dll::UnicastAddress 00208 RegistryProxy::getPeerAddressForCID(wns::scheduler::ConnectionID cid) 00209 { 00210 wns::scheduler::UserID user = getUserForCID(cid); 00211 wns::service::dll::UnicastAddress peerAddress 00212 = layer2->getStationManager()->getStationByNode(user.getNode())->getDLLAddress(); 00213 return peerAddress; 00214 } 00215 00216 ConnectionVector 00217 RegistryProxy::getConnectionsForUser(const wns::scheduler::UserID userID/*nextHop!*/) 00218 { 00219 assure(userIdToConnections.find(userID)!=userIdToConnections.end(),"userIdToConnections["<<getNameForUser(userID)<<"] doesn't exist"); 00220 MESSAGE_SINGLE(NORMAL, logger, "getConnectionsForUser("<<getNameForUser(userID)<<") = "<<wns::scheduler::printConnectionVector(userIdToConnections[userID])); 00221 return userIdToConnections[userID]; 00222 } 00223 00224 // does nothing if already registered 00225 void 00226 RegistryProxy::registerCID(wns::scheduler::ConnectionID cid, wns::scheduler::UserID user /*nextHop!*/) 00227 { 00228 if(!cidToPrio.knows(cid)) { 00229 wns::service::dll::FlowID flowID = cid; 00230 wns::service::qos::QoSClass qosClass; 00231 if (myTask == wns::scheduler::TaskBSorUT::TaskBaseStation()) { 00232 qosClass = friends.flowManager->getQoSClassForBSFlowID(flowID); 00233 } else { 00234 qosClass = friends.flowManager->getQoSClassForUTFlowID(flowID); 00235 } 00236 assure(qosClass>=0 && qosClass<getNumberOfQoSClasses(),"invalid QoS class "<<qosClass); 00237 int priority = mapQoSClassToPriority(qosClass); 00238 // priority is out of [0..MaxPriority-1]: 00239 assure(priority>=0 && priority<numberOfPriorities,"invalid priority="<<priority<<" (numberOfPriorities="<<numberOfPriorities<<")"); 00240 //registerCIDForPriority(cid,priority); 00241 cidToPrio.insert(cid, priority); 00242 connectionsForPriority[priority].push_back(cid); 00243 MESSAGE_SINGLE(NORMAL, logger, "registerCID(cid="<<cid<<",user="<<getNameForUser(user)<<"): QoS="<<lte::helper::QoSClasses::toString(qosClass)<<", prio="<<priority); 00244 } 00245 if(!cidToUserId.knows(cid)) 00246 { 00247 cidToUserId.insert(cid, user); 00248 MESSAGE_SINGLE(NORMAL, logger, "registerCID(cid="<<cid<<",user="<<getNameForUser(user)<<"): cidToUserId["<<cid<<"]="<<getNameForUser(user)); 00249 } 00250 if (userIdToConnections.find(user)==userIdToConnections.end()) // not known 00251 { 00252 userIdToConnections[user] = wns::scheduler::ConnectionVector(); // empty 00253 } 00254 if( find(userIdToConnections[user].begin(),userIdToConnections[user].end(), cid ) == userIdToConnections[user].end()) 00255 { // not found 00256 userIdToConnections[user].push_back(cid); 00257 MESSAGE_SINGLE(NORMAL, logger, "registerCID(cid="<<cid<<",user="<<getNameForUser(user)<<"): userIdToConnections["<<getNameForUser(user)<<"] = "<<wns::scheduler::printConnectionVector(userIdToConnections[user])); 00258 } 00259 // if (!userIdToConnections[user].knows(cid)) gibt's nicht 00260 } 00261 00262 void 00263 RegistryProxy::deregisterCID(wns::scheduler::ConnectionID cid, wns::scheduler::UserID user /*nextHop!*/) 00264 { 00265 MESSAGE_SINGLE(NORMAL, logger, "deregisterCID(cid="<<cid<<",user="<<getNameForUser(user)<<")"); 00266 if (cidToPrio.knows(cid)) 00267 { 00268 int priority = cidToPrio.find(cid); 00269 cidToPrio.erase(cid); 00270 for ( wns::scheduler::ConnectionList::iterator iter = connectionsForPriority[priority].begin(); 00271 iter != connectionsForPriority[priority].end(); ++iter) 00272 { 00273 if (cid == *iter) { 00274 connectionsForPriority[priority].remove(cid); 00275 break; 00276 } 00277 } 00278 } 00279 if(cidToUserId.knows(cid)) 00280 { 00281 assure(cidToUserId.find(cid) == user,"wrong user"); 00282 cidToUserId.erase(cid); 00283 } 00284 // delete cid in userIdToConnections[user] 00285 for(wns::scheduler::ConnectionVector::iterator iter = userIdToConnections[user].begin(); 00286 iter != userIdToConnections[user].end(); ++iter ) 00287 { // forall connections/flows of one nextHop user 00288 wns::scheduler::ConnectionID cidOfUser = *iter; 00289 if (cid == cidOfUser) 00290 { // delete cid in list 00291 userIdToConnections[user].erase(iter); break; // ready 00292 } 00293 } 00294 } 00295 00297 void 00298 RegistryProxy::deregisterUser(const wns::scheduler::UserID user/*nextHop!*/) 00299 { 00300 assure(userIdToConnections.find(user)!=userIdToConnections.end(),"userIdToConnection["<<getNameForUser(user)<<"] unknown"); 00301 MESSAGE_SINGLE(NORMAL, logger, "deregisterUser("<<user.getName()<<")"); 00302 ConnectionVector connectionsForUser = getConnectionsForUser(user); 00303 for(wns::scheduler::ConnectionVector::iterator iter = connectionsForUser.begin(); 00304 iter != connectionsForUser.end(); ++iter ) 00305 { // forall connections/flows of one nextHop user 00306 wns::scheduler::ConnectionID cid = *iter; 00307 deregisterCID(cid, user); 00308 } 00309 userIdToConnections.erase(user); 00310 } 00311 00312 bool 00313 RegistryProxy::hasResourcesGranted() const 00314 { 00315 assure(friends.rrHandlerUT, "No rrHandlerUT in hasGrantedResources(), are you sure you are in a UT?"); 00316 return friends.rrHandlerUT->hasResourcesGranted(); 00317 } 00318 00319 void 00320 RegistryProxy::onAssociated(wns::service::dll::UnicastAddress /*userAdr*/, wns::service::dll::UnicastAddress /*dstAdr*/) 00321 { 00322 //MESSAGE_SINGLE(NORMAL, logger, "onAssociated("<<A2N(userAdr)<<","<<A2N(dstAdr)<<")"); 00323 } 00324 00325 void 00326 RegistryProxy::onDisassociated(wns::service::dll::UnicastAddress userAdr, wns::service::dll::UnicastAddress dstAdr) 00327 { 00328 // userAdr is always UT; dstAdr is always RAP (UT's next hop) 00329 if (layer2->getDLLAddress() == userAdr) // I am UT 00330 { 00331 MESSAGE_SINGLE(NORMAL, logger, "onDisassociated("<<A2N(userAdr)<<","<<A2N(dstAdr)<<"): deleting my old rap="<<A2N(dstAdr)); 00332 wns::node::Interface* rap = layer2->getStationManager()->getStationByMAC(dstAdr)->getNode(); 00333 deregisterUser(wns::scheduler::UserID(rap)/*nextHop!*/); 00334 } 00335 else if (layer2->getDLLAddress() == dstAdr) // user is directly connected to me 00336 { 00337 if (myTask == wns::scheduler::TaskBSorUT::TaskBaseStation()) // I am (BS || RN-BS) 00338 { 00339 MESSAGE_SINGLE(NORMAL, logger, "onDisassociated("<<A2N(userAdr)<<","<<A2N(dstAdr)<<"): deleting my user="<<A2N(userAdr)); 00340 wns::node::Interface* user = layer2->getStationManager()->getStationByMAC(userAdr)->getNode(); 00341 deregisterUser(wns::scheduler::UserID(user)/*nextHop!*/); // user is end-user here (UT), there is no more RN in between 00342 } 00343 } 00344 } // onDisassociated 00345 00346 wns::scheduler::ConnectionID 00347 RegistryProxy::getCIDforPDU(const wns::ldk::CompoundPtr& compound) 00348 { 00349 // cid is flowID here. 00350 wns::ldk::CommandPool* commandPool = compound->getCommandPool(); 00351 assure(friends.rlcCommandReader, "Need rlcCommandReader as friend, please set first"); 00352 lte::rlc::RLCCommand* rlcCommand = friends.rlcCommandReader->readCommand<lte::rlc::RLCCommand>(commandPool); 00353 assure(rlcCommand!=NULL, "couldn't get rlcCommand"); 00354 wns::scheduler::ConnectionID cid = rlcCommand->peer.flowID; // wns::service::dll::FlowID 00355 //wns::scheduler::UserID userID = rlcCommand->peer.destination; // this is end-userID (UT, never RN)! 00356 assure(friends.macgCommandReader, "Need macgCommandReader as friend, please set first"); 00357 lte::macg::MACgCommand* macgCommand = friends.macgCommandReader->readCommand<lte::macg::MACgCommand>(commandPool); 00358 //int destIdInt = macgCommand->peer.dest.getInteger(); // MACg has next hop peer address 00359 //assure(destIdInt > 0, "destIdInt="<<destIdInt); 00360 //UserID destUserID = layer2->getStationManager()->getNodeByID(destIdInt); 00361 wns::service::dll::UnicastAddress nextHop = macgCommand->peer.dest; /*nextHop!*/ 00362 if (nextHop != wns::service::dll::UnicastAddress() ) 00363 { 00364 // Unicast 00365 wns::scheduler::UserID userID = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(nextHop)->getNode()); 00366 registerCID(cid,userID); // does nothing if already registered 00367 } 00368 else 00369 { 00370 wns::scheduler::UserID bcUserID; 00371 bcUserID.setBroadcast(); 00372 // Broadcast 00373 registerCID(cid, bcUserID); 00374 } 00375 // ^ TODO: In the long term someone should register cid from outside; not implicitly like it is done here 00376 return cid; 00377 } 00378 00379 std::string 00380 RegistryProxy::getNameForUser(const UserID user) { 00381 return user.getName(); 00382 } 00383 00384 wns::service::phy::phymode::PhyModeMapperInterface* 00385 RegistryProxy::getPhyModeMapper() const { 00386 assure (phyModeMapper != NULL, "phyModeMapper==NULL"); 00387 return phyModeMapper; 00388 } 00389 00390 wns::service::phy::phymode::PhyModeInterfacePtr 00391 RegistryProxy::getBestPhyMode(const wns::Ratio& sinr) 00392 { 00393 return getPhyModeMapper()->getBestPhyMode(sinr); 00394 } 00395 00396 UserID 00397 RegistryProxy::getMyUserID() { 00398 return wns::scheduler::UserID(layer2->getNode()); 00399 } 00400 00401 // rather old method. CQI should be preferred. 00402 wns::scheduler::ChannelQualityOnOneSubChannel 00403 RegistryProxy::estimateTxSINRAt(const UserID user, int) 00404 { 00405 wns::Power rxPower; 00406 wns::Power interference; 00407 wns::Ratio pathloss; 00408 00409 if (user.isBroadcast()) 00410 { 00411 // Allow at least a transmission with lowest PhyMode 00412 rxPower = wns::Power::from_dBm(-200.0); 00413 if (interference.get_mW() < 1e-18) 00414 rxPower += wns::Ratio::from_dB(getPhyModeMapper()->getMinimumSINR()+1.0); 00415 interference = wns::Power::from_dBm(-200.0); 00416 00417 return wns::scheduler::ChannelQualityOnOneSubChannel(wns::Ratio::from_dB(0.0), interference, rxPower); 00418 } 00419 // lookup the results reported by the user in the local cache 00420 rxPower = iCache->getPerSCAveragedCarrier(user.getNode()); 00421 interference = iCache->getPerSCAveragedInterference(user.getNode()); 00422 pathloss = iCache->getPerSCAveragedPathloss(user.getNode()); 00423 00424 //MESSAGE_SINGLE(NORMAL, logger, "estimateTxSINROf("<<user->getName()<<"): C="<<rxPower.get_mW()<<"mW, I="<<interference.get_mW()<<"mW"); 00425 if (rxPower.get_mW() < 1e-18) 00426 { // allow at least a transmission with lowest PhyMode 00427 rxPower = wns::Power::from_dBm(-200.0); 00428 if (interference.get_mW() < 1e-18) 00429 rxPower += wns::Ratio::from_dB(getPhyModeMapper()->getMinimumSINR()+1.0); 00430 } 00431 if (interference.get_mW() < 1e-18) 00432 interference = wns::Power::from_dBm(-200.0); 00433 //MESSAGE_SINGLE(NORMAL, logger, "estimateTxSINROf("<<user->getName()<<"): C="<<rxPower<<", I="<<interference); 00434 return wns::scheduler::ChannelQualityOnOneSubChannel(pathloss, interference, rxPower); 00435 } 00436 00437 wns::scheduler::ChannelQualityOnOneSubChannel 00438 RegistryProxy::estimateRxSINROf(const UserID user, int) { 00439 00440 // lookup the results previously reported by us to the remote side 00441 dll::services::management::InterferenceCache* remoteCache = 00442 layer2-> 00443 getStationManager()-> 00444 getStationByNode(user.getNode())-> 00445 getManagementService<dll::services::management::InterferenceCache>("INTERFERENCECACHE"+modeBase); 00446 00447 wns::Power rxPower = remoteCache->getPerSCAveragedCarrier(getMyUserID().getNode()); 00448 wns::Power interference = remoteCache->getPerSCAveragedInterference(getMyUserID().getNode()); 00449 wns::Ratio pathloss = remoteCache->getPerSCAveragedPathloss(getMyUserID().getNode()); 00450 00451 /* Ask our cache about the UL interference caused by this node */ 00452 wns::Ratio interferencePathloss = iCache->getAverageEmittedInterferencePathloss(user.getNode()); 00453 00454 return wns::scheduler::ChannelQualityOnOneSubChannel(pathloss, interference, rxPower); 00455 } 00456 00457 wns::Power 00458 RegistryProxy::estimateInterferenceStdDeviation(const UserID /* user */) { 00459 return wns::Power::from_mW(0.0); 00460 } 00461 00462 Bits 00463 RegistryProxy::getQueueSizeLimitPerConnection() { 00464 return queueSize; 00465 } 00466 00467 wns::service::dll::StationType 00468 RegistryProxy::getStationType(const UserID user) { 00469 wns::service::dll::StationType stationType = layer2->getStationManager()->getStationByNode(user.getNode())->getStationType(); 00470 return stationType; 00471 } 00472 00473 // This is obsolete, but RegistryProxyInterface member and required be the old strategies 00474 // accept frameNumber argument instead of using "static" frameNumberToBeScheduled 00475 wns::scheduler::UserSet 00476 RegistryProxy::filterReachable(wns::scheduler::UserSet users) 00477 { 00478 // workaround when frameNr is not given 00479 int frameNr=0; //= frameNumberToBeScheduled 00480 return filterReachable(users, frameNr); 00481 } 00482 00483 // filter those user from a set of users that can be reached at the given frameNr 00484 wns::scheduler::UserSet 00485 RegistryProxy::filterReachable(wns::scheduler::UserSet users, const int frameNr) 00486 { 00487 wns::scheduler::UserSet result; 00488 for (wns::scheduler::UserSet::iterator iter = users.begin(); 00489 iter != users.end(); ++iter) { 00490 00491 if (iter->isBroadcast()) 00492 { 00493 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: broadcast (true)"); 00494 result.insert(*iter); 00495 continue; 00496 } 00497 00498 wns::service::dll::StationType stationType = getStationType(*iter); 00499 // TODO: get rid of "relaysOnly" question. 00500 if (( relaysOnly == true && stationType==wns::service::dll::StationTypes::FRS() ) 00501 || relaysOnly ==false) 00502 { 00503 if (isReachableAt(*iter,frameNr, false)) 00504 { 00505 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: trying user=" << iter->getName() << " type=" << wns::service::dll::StationTypes::toString(stationType)); 00506 if ( (stationType!=wns::service::dll::StationTypes::FRS()) && (stationType!=wns::service::dll::StationTypes::eNB()) ) 00507 { 00508 if (duplexGroupIsReachableAt(*iter, frameNr) == true) 00509 { 00510 result.insert(*iter); 00511 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: "<<iter->getName()<<" is reachable in frame=" << frameNr); 00512 } else { 00513 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: "<<iter->getName()<<" is NOT reachable in frame=" << frameNr); 00514 } 00515 } else { // BS | RN 00516 result.insert(*iter); 00517 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: " << iter->getName() << " is reachable in frame=" << frameNr); 00518 } 00519 } 00520 } 00521 } 00522 MESSAGE_SINGLE(VERBOSE, logger, "filterReachable: " << result.size() << " users reachable in frame=" << frameNr); 00523 return result; 00524 } 00525 00526 wns::scheduler::ConnectionSet 00527 RegistryProxy::filterReachable(wns::scheduler::ConnectionSet connections, const int frameNr, bool useHARQ) 00528 { 00529 wns::scheduler::ConnectionSet result; 00530 00531 for ( wns::scheduler::ConnectionSet::iterator iterConnection = connections.begin(); 00532 iterConnection != connections.end(); ++iterConnection) 00533 { 00534 UserID user = getUserForCID(*iterConnection); 00535 if (user.isBroadcast()) 00536 { 00537 MESSAGE_SINGLE(NORMAL, logger, "filterReachable: broadcast (true)"); 00538 result.insert(*iterConnection); 00539 continue; 00540 } 00541 00542 // user from the connection is reachable 00543 if ( isReachableAt(user,frameNr, useHARQ) ) 00544 { 00545 result.insert(*iterConnection); 00546 } 00547 } 00548 00549 return result; 00550 } 00551 00552 // only true for RS-Tx in BS or RN-BS: 00553 // isForDL should be constant within an object. So why...? 00554 void RegistryProxy::setDL(bool _isForDL) 00555 { 00556 isForDL = _isForDL; 00557 } 00558 00559 // only true for RS-Tx in BS or RN-BS: 00560 bool RegistryProxy::getDL() const 00561 { 00562 return isForDL; 00563 } 00564 00565 void 00566 RegistryProxy::setAssociationHandler(lte::controlplane::associationHandler::AssociationHandler* ah) 00567 { 00568 friends.associationHandler = ah; 00569 } 00570 00571 bool 00572 RegistryProxy::duplexGroupIsReachableAt(const wns::scheduler::UserID user, const int frameNr) const 00573 { 00574 // retrieve id of the target user 00575 wns::service::dll::UnicastAddress targetAddress = layer2->getStationManager()->getStationByNode(user.getNode())->getDLLAddress(); 00576 00577 int peerDuplexGroup = friends.associationHandler->getPeerDuplexGroup(targetAddress); 00578 int myDuplexGroup = friends.associationHandler->getMyDuplexGroup(frameNr, isForDL/*member*/); 00579 // isForDL is set via setDL(downLink) by Lte scheduler. 00580 // at the same time and for FDD: myDuplexGroup is different for DL and UL 00581 // therefore myDuplexGroup differs (1->2, 2->1) for UL compared to DL 00582 00583 // 0=TDD, 3=fullduplexFDD 00584 if ( (peerDuplexGroup == myDuplexGroup) || (peerDuplexGroup == 0) || (peerDuplexGroup == 3) ) 00585 { 00586 MESSAGE_SINGLE(NORMAL, logger, "duplexGroupIsReachableAt(User=" <<A2N(targetAddress)<< ",frameNr="<<frameNr<<"): is reachable, peerDuplexGroup=" << peerDuplexGroup << ", myDuplexGroup=" << myDuplexGroup); 00587 return true; 00588 } else { 00589 MESSAGE_SINGLE(NORMAL, logger, "duplexGroupIsReachableAt(User=" <<A2N(targetAddress)<< ",frameNr="<<frameNr<<"): is NOT reachable, peerDuplexGroup=" << peerDuplexGroup << ", myDuplexGroup=" << myDuplexGroup); 00590 return false; 00591 } 00592 } 00593 00594 // checks if the peer is reachable now and able to receive the map 00595 // needed for RNs 00596 bool 00597 RegistryProxy::isReachableAt(const UserID user, const int frameNr, bool useHARQ) const 00598 { 00599 if (user.isBroadcast()) 00600 { 00601 // Broadcast messages are always being sent, regardless of the target user 00602 return true; 00603 } 00604 00605 // retrieve id of the target user 00606 wns::service::dll::UnicastAddress targetAddress = layer2->getStationManager()->getStationByNode(user.getNode())->getDLLAddress(); 00607 // only perform the subsequent check if we have an association in this mode, 00608 // i.e. we are RN or UT 00609 if (associationService->hasAssociation()){ 00610 // check whether the target station is the one we are associated to, 00611 // because we should always be able to reach our association (i.e. our RAP) once we 00612 // were triggered to do so as "slave" 00613 if (targetAddress == associationService->getAssociation()) 00614 { 00615 // This is an UL packet. Of course, we can reach our RAP 00616 // We have been granted UL resources in the UL map 00617 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): UT UL: Yes"); 00618 00619 bool freeHARQProcesses = true; 00620 if (useHARQ) 00621 { 00622 freeHARQProcesses = friends.harq->hasFreeSenderProcess(user); 00623 } 00624 00625 if(!freeHARQProcesses) 00626 { 00627 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): max HARQ processes reached."); 00628 } 00629 00630 return freeHARQProcesses; 00631 } 00632 else if (friends.timer->stationTaskAtFrame(frameNr) == lte::timing::StationTasks::UT()) 00633 { 00634 // This was a packet of a UT/RN to its old RAP, but the old one is not 00635 // reachable any more due to a reassociation 00636 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): UT assoc lost"); 00637 return false; 00638 } 00639 } 00640 assure(friends.timer->stationTaskAtFrame(frameNr) 00641 == lte::timing::StationTasks::RAP(), "We must be a RAP in this frame!"); 00642 bool ir = (friends.timer->isPeerListeningAt(targetAddress, frameNr) /* for data transmission in future frame */ 00643 && friends.timer->canReceiveMapNow(targetAddress)); 00644 00645 bool freeHARQProcesses = true; 00646 00647 if (useHARQ) 00648 { 00649 if (getDL()) 00650 { 00651 freeHARQProcesses = friends.harq->hasFreeSenderProcess(user); 00652 if(!freeHARQProcesses) 00653 { 00654 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): max HARQ processes reached."); 00655 } 00656 } 00657 else 00658 { 00659 freeHARQProcesses = friends.harq->hasFreeReceiverProcess(user); 00660 if(!freeHARQProcesses) 00661 { 00662 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): max HARQ processes reached."); 00663 } 00664 } 00665 } 00666 00667 MESSAGE_SINGLE(NORMAL, logger, "isReachableAt(User=" << A2N(targetAddress) << ", frameNr=" << frameNr << "): reachable=" << ir); 00668 return ir && (freeHARQProcesses); 00669 } 00670 00674 wns::scheduler::PowerMap 00675 RegistryProxy::calcULResources(const wns::scheduler::UserSet& users, unsigned long int rapResources) const 00676 { 00677 // generate empty container for result 00678 wns::scheduler::PowerMap result; 00679 return result; 00680 } 00681 00682 wns::scheduler::UserSet 00683 RegistryProxy::getActiveULUsers() const 00684 { 00685 assure(friends.rrHandler, "UL Resource Allocation may only be done in uplink"); 00686 return friends.rrHandler->getActiveUsers(); 00687 } 00688 00689 int 00690 RegistryProxy::getTotalNumberOfUsers(wns::scheduler::UserID user) 00691 { 00692 // The purpose of this method is to provide fairness for RNs by the BS 00693 // This way the BS knows how many RUTs are connected to the RN and accordingly 00694 // can consider this when scheduling 00695 if (layer2->getStationType() == wns::service::dll::StationTypes::eNB() && 00696 layer2->getStationManager()->getStationByNode(user.getNode())->getStationType() 00697 == wns::service::dll::StationTypes::FRS()) 00698 { 00699 // We determine the number of user plane flows 00700 // This is an indicator for how many UTs there are, 00701 // if and only if there is exactly one user plane flow per UT 00702 int numUpConnections = 0; 00703 ConnectionVector connections = getConnectionsForUser(user); 00704 wns::service::dll::UnicastAddress userAddress 00705 = layer2->getStationManager()->getStationByNode(user.getNode())->getDLLAddress(); 00706 00707 for(wns::scheduler::ConnectionVector::iterator iter = connections.begin(); 00708 iter != connections.end(); ++iter ) 00709 { // for all connections/flows of the RN 00710 wns::service::dll::FlowID flowID = *iter; 00711 if (!friends.flowManager->isControlPlaneFlowID(userAddress, flowID)) 00712 { 00713 // count user plane flows/connections 00714 ++numUpConnections; 00715 } 00716 } 00717 if (numUpConnections != 0) 00718 { 00719 assure(numUpConnections>0,"numUpConnections(" << user.getName() <<")="<<numUpConnections); 00720 return numUpConnections; 00721 } 00722 } 00723 return 1; 00724 } 00725 00726 int 00727 RegistryProxy::getTotalNumberOfFlows() const 00728 { 00729 return friends.flowManager->countFlows(); 00730 } 00731 00732 int 00733 RegistryProxy::getNumberOfFlowsForUser(const wns::scheduler::UserID user) const 00734 { 00735 wns::service::dll::UnicastAddress peerAdress = layer2->getStationManager()->getStationByNode(user.getNode())->getDLLAddress(); 00736 return friends.flowManager->countFlows(peerAdress); 00737 } 00738 00739 // what is this? Please explain. [rs] 00740 void 00741 RegistryProxy::setRelaysOnly() 00742 { 00743 relaysOnly = true; 00744 } 00745 00746 // what is this? Please explain. [rs] 00747 void 00748 RegistryProxy::setAllStations() 00749 { 00750 relaysOnly = false; 00751 } 00752 00753 // This is CQI related 00754 wns::scheduler::ChannelQualitiesOnAllSubBandsPtr 00755 RegistryProxy::getChannelQualities4UserOnUplink(UserID user, int frameNr) 00756 { 00757 MESSAGE_SINGLE(NORMAL, logger, "getChannelQualities4UserOnUplink("<<user.getName()<<","<<frameNr<<")"); 00758 assure(false, "This should not be called. We disable the use of CQI"); 00759 return fakeChannelQualities; 00760 } 00761 00762 // This is CQI related 00763 wns::scheduler::ChannelQualitiesOnAllSubBandsPtr 00764 RegistryProxy::getChannelQualities4UserOnDownlink(UserID user, int frameNr) 00765 { 00766 MESSAGE_SINGLE(NORMAL, logger, "getChannelQualities4UserOnDownlink("<<user.getName()<<","<<frameNr<<")"); 00767 assure(false, "This should not be called. We disable the use of CQI"); 00768 return fakeChannelQualities; 00769 } // getChannelQualities4UserOnDownlink 00770 00771 // This is CQI related 00772 wns::scheduler::PowerCapabilities 00773 RegistryProxy::getPowerCapabilities(const UserID user) const 00774 { 00775 wns::scheduler::PowerCapabilities result; 00776 // get other station type 00777 wns::service::dll::StationType stationType; 00778 if (user.isValid()) { // peer known 00779 stationType = layer2->getStationManager()->getStationByNode(user.getNode())->getStationType(); 00780 } else { // peer unknown. assume peer=UT 00781 stationType = wns::service::dll::StationTypes::UE(); 00782 } 00783 if ( stationType == wns::service::dll::StationTypes::UE() ) 00784 result=powerUT; // this may be variable in the future (different userTerminal classes) 00785 else if ( stationType == wns::service::dll::StationTypes::eNB() ) 00786 result=powerBS; 00787 else 00788 assure(false, "oops, don't know other station ("<<user.getName()<<") stationType="<<stationType); 00789 00790 assure(result.nominalPerSubband!=wns::Power(),"undefined power nominalPerSubband="<<result.nominalPerSubband); 00791 if (user.isValid()) { 00792 MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities("<<user.getName()<<"): nominal="<<result.nominalPerSubband<<" ("<< wns::service::dll::StationTypes::toString(stationType)<<")"); 00793 } else { 00794 MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(NULL): nominal="<<result.nominalPerSubband<<" ("<< wns::service::dll::StationTypes::toString(stationType)<<")"); 00795 } 00796 return result; 00797 } 00798 00799 wns::scheduler::PowerCapabilities 00800 RegistryProxy::getPowerCapabilities() const 00801 { 00802 wns::scheduler::PowerCapabilities result; 00803 // get my own station type 00804 wns::service::dll::StationType stationType = layer2->getStationType(); 00805 if ( stationType == wns::service::dll::StationTypes::UE() ) 00806 result=powerUT; 00807 else if ( stationType == wns::service::dll::StationTypes::eNB() ) 00808 result=powerBS; 00809 else 00810 assure(false, "oops, don't know my own station stationType="<<stationType); 00811 assure(result.nominalPerSubband!=wns::Power(),"undefined power nominalPerSubband="<<result.nominalPerSubband); 00812 MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(): nominal="<<result.nominalPerSubband); 00813 return result; 00814 } 00815 00816 // This is QoS/priority related 00817 int 00818 RegistryProxy::getNumberOfQoSClasses() 00819 { 00820 return numberOfQosClasses; 00821 } 00822 00823 // This is QoS/priority related 00824 int 00825 RegistryProxy::getNumberOfPriorities() 00826 { 00827 return numberOfPriorities; 00828 } 00829 00830 // This is QoS/priority related 00831 wns::scheduler::ConnectionList& 00832 RegistryProxy::getCIDListForPriority(int priority) 00833 { 00834 MESSAGE_SINGLE(NORMAL, logger, "getCIDListforPriority("<<priority<<")"); 00835 // priority is out of [0..MaxPriority-1]: 00836 assure(priority>=0 && priority<numberOfPriorities,"invalid priority="<<priority<<" (numberOfPriorities="<<numberOfPriorities<<")"); 00837 return connectionsForPriority[priority]; 00838 } 00839 00840 00841 // gets the cids in a set, because the strategy can better handle sorted list of 00842 // cids (a set implicit sorts the cids) 00843 wns::scheduler::ConnectionSet 00844 RegistryProxy::getConnectionsForPriority(int priority) 00845 { 00846 wns::scheduler::ConnectionSet result; 00847 //MESSAGE_SINGLE(NORMAL, logger, "getConnectionsforPriority("<<priority<<")"); 00848 // priority is out of [0..MaxPriority-1]: 00849 assure(priority>=0 && priority<numberOfPriorities,"invalid priority="<<priority<<" (numberOfPriorities="<<numberOfPriorities<<")"); 00850 //MESSAGE_SINGLE(NORMAL, logger, "getConnectionsforPriority("<<priority<<"): count="<<connectionsForPriority[priority].size()); 00851 for ( wns::scheduler::ConnectionList::iterator iter = connectionsForPriority[priority].begin(); 00852 iter != connectionsForPriority[priority].end(); ++iter) 00853 { 00854 ConnectionID cid = *iter; 00855 result.insert(cid); 00856 //MESSAGE_SINGLE(NORMAL, logger, "getConnectionsforPriority("<<priority<<"): added cid=" << cid); 00857 } 00858 MESSAGE_SINGLE(NORMAL, logger, "getConnectionsforPriority("<<priority<<"): "<<wns::scheduler::printConnectionSet(result)); 00859 return result; 00860 } 00861 00862 00863 int 00864 RegistryProxy::mapQoSClassToPriority(wns::service::qos::QoSClass qosClass) 00865 { 00866 assure(qosClass>=0 && qosClass<getNumberOfQoSClasses(),"invalid QoS class "<<qosClass); 00867 int priority=qosToPriorityMapping[qosClass]; 00868 return priority; 00869 } 00870 00871 00872 int 00873 RegistryProxy::getPriorityForConnection(wns::scheduler::ConnectionID cid) 00874 { 00875 assure(cidToPrio.knows(cid),"cid "<<cid<<" is not registered"); 00876 return cidToPrio.find(cid); 00877 } 00878 00879 // this is only complete after OnWorldCreated! 00880 dll::NodeList 00881 RegistryProxy::getNodeList() 00882 { 00883 assure(layer2!=NULL,"layer2==NULL"); 00884 dll::StationManager* stationManager = layer2->getStationManager(); 00885 assure(stationManager!=NULL,"stationManager==NULL"); 00886 return stationManager->getNodeList(); 00887 }
1.5.5