User Manual, Developers Guide and API Documentation

RegistryProxy.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-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 }

Generated on Fri May 25 03:32:06 2012 for openWNS by  doxygen 1.5.5