![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 #include <LTE/controlplane/RRHandler.hpp> 00029 #include <LTE/controlplane/flowmanagement/FlowManager.hpp> 00030 #include <LTE/timing/ResourceSchedulerUT.hpp> 00031 #include <LTE/timing/ResourceSchedulerBS.hpp> 00032 #include <LTE/macg/MACg.hpp> 00033 #include <LTE/rlc/RLCCommand.hpp> 00034 #include <LTE/helper/QoSClasses.hpp> 00035 00036 #include <DLL/StationManager.hpp> 00037 #include <DLL/Layer2.hpp> 00038 00039 #include <WNS/StaticFactory.hpp> 00040 #include <WNS/ldk/helper/FakePDU.hpp> 00041 #include <WNS/service/dll/StationTypes.hpp> 00042 00043 #include <vector> 00044 00045 #define A2N(a) layer2->getStationManager()->getStationByMAC(a)->getName() 00046 00047 using namespace lte::controlplane; 00048 00049 STATIC_FACTORY_REGISTER_WITH_CREATOR(RRHandlerBS, 00050 wns::ldk::FunctionalUnit, 00051 "lte.controlplane.RRHandler.BS", 00052 wns::ldk::FUNConfigCreator); 00053 00054 STATIC_FACTORY_REGISTER_WITH_CREATOR(RRHandlerUT, 00055 wns::ldk::FunctionalUnit, 00056 "lte.controlplane.RRHandler.UT", 00057 wns::ldk::FUNConfigCreator); 00058 00059 RRHandler::RRHandler(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) : 00060 wns::ldk::CommandTypeSpecifier<RRCommand>(fun), 00061 wns::ldk::HasReceptor<>(), 00062 wns::ldk::HasConnector<lte::helper::SwitchConnector>(), 00063 wns::ldk::HasDeliverer<>(), 00064 helper::HasModeName(config), 00065 connector(dynamic_cast<lte::helper::SwitchConnector*>(getConnector())), 00066 commandSize(config.get<Bit>("commandSize")), 00067 pcchSize(config.get<Bit>("pcchSize")), 00068 logger(config.get("logger")), 00069 layer2(NULL), 00070 pyco(config), 00071 usesShortcut(config.get<bool>("usesShortcut")) 00072 { 00073 MESSAGE_SINGLE(VERBOSE, logger, "RRHandler::RRHandler()"); 00074 rlcReader = NULL; 00075 } 00076 00077 RRHandler::~RRHandler() 00078 { 00079 MESSAGE_SINGLE(NORMAL, logger, "RRHandler::~RRHandler()"); 00080 // cleanup: see derived classes 00081 } 00082 00083 void 00084 RRHandler::onFUNCreated() 00085 { 00086 wns::ldk::fun::FUN* fun = getFUN(); 00087 00088 layer2 = fun->getLayer<dll::Layer2*>(); 00089 associationService = layer2->getControlService<dll::services::control::Association>("ASSOCIATION"+modeBase); 00090 00091 // get handles to outgoing FUs (for sending the ResourceRequests) 00092 typedef std::list<wns::ldk::IConnectorReceptacle*> FUList; 00093 FUList connectorSet = connector->getFUs(); 00094 for (FUList::const_iterator iter = connectorSet.begin(); 00095 iter != connectorSet.end(); 00096 ++iter) 00097 { 00098 size_t found = (*iter)->getFU()->getName().find("rachDispatcher"); 00099 if (found != std::string::npos) 00100 friends.rachDispatcher = (*iter); 00101 found = (*iter)->getFU()->getName().find(pyco.get<std::string>("cpDispatcherName")); 00102 if (found != std::string::npos) 00103 friends.cpDispatcher = (*iter); 00104 } 00105 assure(friends.rachDispatcher, "RRHandler requires a Dispatcher/OpcodeSetter friend with name: "+mode+separator+"rachDispatcher"); 00106 assure(friends.cpDispatcher, "RRHandler requires a Dispatcher/OpcodeSetter friend with name: "+mode+separator+pyco.get<std::string>("cpDispatcherName")); 00107 00108 std::string flowmanagername="FlowManager"; 00109 00110 if (layer2->getStationType() == wns::service::dll::StationTypes::UE()) { 00111 // For UTs, initially activate the RACH as outgoing Data Connection 00112 if (usesShortcut) 00113 { 00114 connector->activate(friends.cpDispatcher); 00115 } 00116 else 00117 { 00118 connector->activate(friends.rachDispatcher); 00119 } 00120 flowmanagername += "UT"; 00121 } else { // BS 00122 flowmanagername += "BS"; 00123 } 00124 // in the BS we don't activate the connector since we don't send anything 00125 00126 friends.flowManager = layer2->getControlService<lte::controlplane::flowmanagement::FlowManager>(flowmanagername); 00127 assure(friends.flowManager, "FlowManager not set."); 00128 rlcReader = fun->getCommandReader("rlc"); 00129 // The macg command needs to be manipulated 00130 if (mode == modeBase) { 00131 friends.macg = fun->findFriend<lte::macg::MACg*>("macg"); 00132 } else { 00133 // taskID is inherited from HasModeName class 00134 friends.macg = fun->findFriend<lte::macg::MACg*>("macg"+separator+taskID); 00135 } 00136 } 00137 00138 void 00139 RRHandler::setColleagues(wns::scheduler::RegistryProxyInterface* registry) 00140 { 00141 // only required in BS: RegistryProxy of RS-RX (uplink master). Never for RS-TX. 00142 assure((friends.registry == NULL) || (registry == friends.registry),"failed attempt to overload friends.registry"); 00143 friends.registry = registry; 00144 assure(friends.registry != NULL,"friends.registry==NULL"); 00145 } 00146 00147 void 00148 RRHandler::doSendData(const wns::ldk::CompoundPtr&) 00149 { 00150 assure(false, "Should never be called!"); 00151 } 00152 00153 bool 00154 RRHandler::doIsAccepting(const wns::ldk::CompoundPtr& /* compound */) const 00155 { 00156 assure(false,"nobody may downconnect on the MapHandler"); 00157 // will never be called since nobody is likely to downconnect on the MapHandler 00158 return false; 00159 } // doIsAccepting 00160 00161 RRHandlerUT::~RRHandlerUT() 00162 { 00163 // cleanup: 00164 allRelayedRequestedResources.clear(); 00165 } 00166 00167 void 00168 RRHandlerUT::doOnData(const wns::ldk::CompoundPtr& 00169 #ifndef NDEBUG 00170 compound 00171 #endif 00172 ) 00173 { 00174 assure(false, "RRHandlerUT does not expect incoming compounds. This compound's journey:\n"<<compound->dumpJourney()); 00175 } 00176 00177 00178 void 00179 RRHandlerUT::onFUNCreated() 00180 { 00181 RRHandler::onFUNCreated(); 00182 00183 // The RRHandler needs to listen to the Notification about granted resources 00184 this->startObserving(getFUN()->findFriend<wns::Subject<ResourceGrantNotificationInterface>*>(mode+separator+"mapHandler")); 00185 00186 // a tx scheduler friend is needed to request queue occupancy levels 00187 rstx = getFUN()->findFriend<lte::timing::ResourceSchedulerUT*>(mode+separator+rsNameSuffix+"TX"); 00188 } 00189 00190 // notified by MapHandler if we got resources granted (indicated in the map) 00191 void 00192 RRHandlerUT::resourcesGranted(bool state) 00193 { 00194 resourceGrantState = state; 00195 if (state == true) 00196 { 00197 MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(true): choosing cpDispatcher connector"); 00198 connector->activate(friends.cpDispatcher); 00199 // activate another signaling of requested resources 00200 this->createRRCompound(); 00201 } 00202 else 00203 { 00204 if (usesShortcut) 00205 { 00206 MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(false), useShortcut(true): choosing cpDispatcher connector"); 00207 connector->activate(friends.cpDispatcher); 00208 } 00209 else 00210 { 00211 MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(false): choosing rachDispatcher connector"); 00212 connector->activate(friends.rachDispatcher); 00213 } 00214 // if we are a relay then... 00215 // assure(false,"resourcesGranted(false) must not happen anymore"); 00216 // take care that at least one RRCompound is still in the Queue 00217 // and that it will be delivered soon in the future 00223 this->createRRCompound(); 00224 } 00225 } 00226 00227 void 00228 RRHandlerUT::createRRCompound() 00229 { 00230 // We can not send a Request if we don't know where to send it. 00231 if (! associationService->hasAssociation()) 00232 return; 00233 00239 wns::ldk::CompoundPtr requestCompound = 00240 wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool(), 00241 wns::ldk::helper::FakePDUPtr(new wns::ldk::helper::FakePDU()))); 00242 00244 lte::macg::MACgCommand* macgCommand = friends.macg->activateCommand(requestCompound->getCommandPool()); 00245 macgCommand->peer.source = layer2->getDLLAddress(); 00246 wns::service::dll::UnicastAddress peerAddress = associationService->getAssociation(); 00247 macgCommand->peer.dest = peerAddress; 00248 00249 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(requestCompound->getCommandPool())); 00250 rlcCommand->peer.source = layer2->getDLLAddress(); 00251 //rlcCommand->peer.destination = ? 00252 if (layer2->getStationType() == wns::service::dll::StationTypes::UE()) 00253 { 00254 lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs = 00255 friends.flowManager->getControlPlaneFlowIDs(peerAddress); 00256 pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()]; 00257 } 00258 rlcCommand->peer.flowID = pcchFlowID; 00259 assure(pcchFlowID>0, "PCCH FlowID must be > 0"); 00260 00261 MESSAGE_SINGLE(NORMAL, logger, "createRRCompound() to "<<A2N(peerAddress)<<", PCCH FlowID="<<pcchFlowID); 00262 00263 // Node pointer of the peer node is needed 00264 wns::scheduler::UserID peer = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(peerAddress)->getNode()); 00265 00267 RRCommand* outgoingCommand = this->activateCommand(requestCompound->getCommandPool()); 00268 00269 outgoingCommand->peer.request.user = wns::scheduler::UserID(layer2->getNode()); 00270 outgoingCommand->magic.source = macgCommand->peer.source; 00271 00272 // reserve at least resources for the next UL resource request: 00273 wns::scheduler::QueueStatusContainer totalQueueStatus = rstx->getQueueStatus();// QueueStatusContainer 00274 // reserve UL resources for the PCCH which is generated at the end of this method, but only if we do not use the magic shortcut below: 00275 if (!usesShortcut) 00276 { 00277 wns::scheduler::QueueStatus pcchRequestedResources; 00278 pcchRequestedResources.numOfCompounds = 1; 00279 pcchRequestedResources.numOfBits = pcchSize; 00280 if (totalQueueStatus.knows(pcchFlowID)) 00281 { 00282 totalQueueStatus.update(pcchFlowID, pcchRequestedResources); 00283 } 00284 else 00285 { 00286 totalQueueStatus.insert(pcchFlowID, pcchRequestedResources); 00287 } 00288 00289 assure(totalQueueStatus.size()>0,"totalQueueStatus must contain at least one element for following resource requests"); 00290 } 00291 else 00292 { // UT 00293 for(wns::scheduler::QueueStatusContainer::const_iterator iter = totalQueueStatus.begin(); 00294 iter != totalQueueStatus.end(); ++iter) 00295 { 00296 wns::service::dll::FlowID flowId = iter->first; 00297 00298 MESSAGE_SINGLE(NORMAL, logger, "requestedResources[FlowID="<<flowId<<"]="<<iter->second.numOfCompounds<<"pdus, "<<iter->second.numOfBits<<"bits"); 00299 } 00300 } 00301 00302 outgoingCommand->peer.request.allRequestedResources = totalQueueStatus; 00303 outgoingCommand->magic.source = layer2->getDLLAddress(); 00304 00306 if (getConnector()->hasAcceptor(requestCompound)) 00307 { 00308 MESSAGE_BEGIN(NORMAL, logger, m, "createRRCompound(): prepared ResourceRequest ("); 00309 int bitsWaiting=0, compoundsWaiting=0, numFlows=0; 00310 for(wns::scheduler::QueueStatusContainer::const_iterator iter = totalQueueStatus.begin(); 00311 iter != totalQueueStatus.end(); ++iter) 00312 { 00313 bitsWaiting += iter->second.numOfBits; 00314 compoundsWaiting += iter->second.numOfCompounds; 00315 ++numFlows; 00316 } 00317 m << bitsWaiting << " bits, "; 00318 m << compoundsWaiting << " compounds, "; 00319 m << numFlows << " flows)"; 00320 assure(compoundsWaiting>0 || usesShortcut,"compounds==0 in forwarded resource request"); 00321 MESSAGE_END(); 00322 getConnector()->getAcceptor(requestCompound)->sendData(requestCompound); 00323 } 00324 else 00325 { 00326 MESSAGE_SINGLE(NORMAL, logger, "createRRCompound(): Failed to send ResourceRequest Compound to "<< A2N(outgoingCommand->magic.source)); 00327 assure(false, "Lower FU is not accepting scheduled ResourceRequest but is supposed to do so"); 00328 } 00329 } 00330 00331 int 00332 RRHandler::getTotalNumberOfUsers(const wns::scheduler::UserID /*user*/) const 00333 { 00334 return 1; 00335 } 00336 00337 // this method is called for each createFakePDU. 00338 void 00339 RRHandler::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const 00340 { 00341 getFUN()->calculateSizes(commandPool, commandPoolSize, dataSize, this); 00342 // now we have the size of all previous Commands and of the original Compound 00343 00344 // add my commandSize. No Data to add. 00345 commandPoolSize += this->commandSize; 00346 } 00347 /***************************************************************************/ 00348 RRHandlerBS::RRHandlerBS(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) : 00349 RRHandler(fun, config), 00350 wns::Cloneable<RRHandlerBS>(), 00351 firstWakeup(true), 00352 rrStorage(new RequestStorage(logger)), 00353 rnUplinkRRHandler(NULL), 00354 rsrx(NULL), 00355 ulSegmentSize(config.get<int>("ulSegmentSize")) 00356 { 00357 } 00358 00359 RRHandlerBS::~RRHandlerBS() 00360 { 00361 delete rrStorage; rrStorage=NULL; 00362 } 00363 00364 void 00365 RRHandlerBS::onFUNCreated() 00366 { 00367 // Do the general stuff 00368 RRHandler::onFUNCreated(); 00369 00370 // The rx scheduler is needed to queue the resource requests 00371 rsrx = getFUN()->findFriend<lte::timing::ResourceSchedulerBS*>(mode+separator+rsNameSuffix+"RX"); 00372 00373 // Register as Observer at the association Info providers 00374 dll::Layer2* layer2 = getFUN()->getLayer<dll::Layer2*>(); 00375 dll::Layer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode); 00376 dll::Layer2::AssociationInfoContainer::const_iterator iter = ais.begin(); 00377 //dll::ILayer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode); 00378 //dll::ILayer2::AssociationInfoContainer::const_iterator iter = ais.begin(); 00379 for (; iter != ais.end(); ++iter) 00380 this->dll::services::control::AssociationObserver::startObserving(*iter); 00381 00382 lte::timing::TimingScheduler* timing = layer2->getManagementService<lte::timing::TimingScheduler>(mode+separator+"Timer"); 00383 this->wns::Observer<SuperFrameStartNotificationInterface>::startObserving(timing); 00384 } 00385 00386 int 00387 RRHandlerBS::getDefaultBitsPerPDU() 00388 { 00389 return ulSegmentSize; 00390 } 00391 00392 wns::ldk::CompoundPtr 00393 RRHandlerBS::createFakePDU(wns::service::dll::UnicastAddress destinationAddress, wns::scheduler::Bits bits, wns::service::dll::FlowID flowID) 00394 { 00395 MESSAGE_SINGLE(NORMAL, logger, "createFakePDU(flowID="<<flowID<<","<<bits<<"bits)"); 00396 wns::ldk::CompoundPtr pdu = wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool(),wns::ldk::helper::FakePDUPtr(new wns::ldk::helper::FakePDU( bits )))); 00397 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(pdu->getCommandPool())); 00398 rlcCommand->peer.flowID = flowID; 00399 lte::macg::MACgCommand* macgCommand = friends.macg->activateCommand(pdu->getCommandPool()); 00400 macgCommand->peer.source = layer2->getDLLAddress(); 00401 macgCommand->peer.dest = destinationAddress; 00402 return pdu; 00403 } 00404 00405 // only called once at simulation start 00406 void 00407 RRHandlerBS::fakeRelayRRs() const 00408 { 00409 typedef std::vector<wns::service::dll::UnicastAddress> IDList; 00410 // all associated users (RN, UT): 00411 IDList allUsers = associationService->getAssociated(); 00412 MESSAGE_SINGLE(NORMAL, logger, "fakeRelayRRs(): "<<allUsers.size()<<" associated users"); 00413 00414 // fake requests for every user and hand them down to the lower layer 00415 for (IDList::iterator iter = allUsers.begin(); iter != allUsers.end(); ++iter) 00416 { 00417 ResourceRequest request; 00418 wns::service::dll::UnicastAddress peerAddress = *iter; 00419 wns::node::Interface* peerUserID = layer2->getStationManager()->getStationByMAC(peerAddress)->getNode(); 00420 request.user = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(peerAddress)->getNode()); 00421 lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs = 00422 friends.flowManager->getControlPlaneFlowIDs(peerAddress); 00423 wns::service::dll::FlowID pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()]; 00424 00425 wns::scheduler::QueueStatus initialPcchResourceRequest; 00426 initialPcchResourceRequest.numOfBits = pcchSize; 00427 initialPcchResourceRequest.numOfCompounds = 1; 00428 wns::scheduler::QueueStatusContainer rnResourceRequests; 00429 rnResourceRequests.insert(pcchFlowID, initialPcchResourceRequest); 00430 rrStorage->storeRequest(wns::scheduler::UserID(peerUserID),rnResourceRequests); 00431 assure(friends.registry!=NULL,"registry==NULL"); 00432 friends.registry->registerCID(pcchFlowID,wns::scheduler::UserID(peerUserID)); 00433 } // for all users 00434 MESSAGE_SINGLE(NORMAL, logger, "ResourceRequests="<<rrStorage->printQueueStatus()); 00435 } // fakeRelayRRs() 00436 00437 void 00438 RRHandler::doWakeup() 00439 {} // doWakeup 00440 00441 void 00442 RRHandlerBS::doWakeup() 00443 { 00444 if (firstWakeup == true) 00445 { 00446 MESSAGE_SINGLE(NORMAL, logger, "doWakeup(): firstWakeup"); 00447 fakeRelayRRs(); 00448 firstWakeup = false; 00449 } 00450 } // doWakeup 00451 00452 void 00453 RRHandlerBS::onSuperFrameStart() 00454 { 00455 if (firstWakeup == true) 00456 { 00457 MESSAGE_SINGLE(NORMAL, logger, "onSuperFrameStart(): firstWakeup"); 00458 fakeRelayRRs(); 00459 firstWakeup = false; 00460 } 00461 } 00462 00463 // incoming ResourceRequests (from UT/RN to BS task) 00464 void 00465 RRHandlerBS::doOnData(const wns::ldk::CompoundPtr& compound) 00466 { 00470 RRCommand* incomingCommand = getCommand(compound->getCommandPool()); 00471 wns::service::dll::UnicastAddress rapAddress = layer2->getDLLAddress(); // invariant -> member 00472 wns::service::dll::UnicastAddress userAddress = incomingCommand->magic.source; // the requester 00473 00474 // If the originator of the request is not associated with us, we ignore the request 00475 if (!associationService->hasAssociated(userAddress)) 00476 return; 00477 00478 wns::scheduler::UserID peer = incomingCommand->peer.request.user; 00479 00480 wns::scheduler::QueueStatusContainer requestedResources = incomingCommand->peer.request.allRequestedResources; 00481 lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs = 00482 friends.flowManager->getControlPlaneFlowIDs(userAddress); 00483 wns::service::dll::FlowID pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()]; 00484 // alternatively we could read the rlc command here: rlcCommand->peer.flowID 00485 00486 MESSAGE_BEGIN(NORMAL, logger, m, "doOnData(): Received Resource Request from: "); 00487 m << peer.getName(); 00488 m << " ("<<A2N(userAddress)<<")"; 00489 m << " for "<<requestedResources.size()<<" flows"; 00490 m << " (PCCH FlowID="<<pcchFlowID<<")"; 00491 MESSAGE_END(); 00492 00493 uint32_t assumedBitsPerPDU = ulSegmentSize; 00494 if (requestedResources.size() > 0) 00495 { 00496 rrStorage->storeRequest(peer,requestedResources); 00497 00498 wns::node::Interface* peerUserID = layer2->getStationManager()->getStationByMAC(userAddress)->getNode(); 00499 for( wns::scheduler::QueueStatusContainer::const_iterator iter = requestedResources.begin(); iter != requestedResources.end(); ++iter) 00500 { 00501 wns::scheduler::ConnectionID flowId = iter->first; 00502 assure(friends.registry!=NULL,"registry==NULL"); 00503 friends.registry->registerCID(flowId, wns::scheduler::UserID(peerUserID)); 00504 // manipulations in the numbers to adjust for inaccuracies: 00505 int pdus = iter->second.numOfCompounds; 00506 int bits = iter->second.numOfBits; 00507 if (bits<pdus*assumedBitsPerPDU) { 00508 // adjust bits to be at least a multiple of assumedBitsPerPDU 00509 MESSAGE_SINGLE(NORMAL, logger, "doOnData(): adjusting flowId="<<flowId<<": "<<iter->second.numOfCompounds<<" pdus, "<<iter->second.numOfBits<<" bits -> "<<pdus*assumedBitsPerPDU<<" bits"); 00510 //iter->second.numOfBits = pdus*assumedBitsPerPDU; // add bits 00511 wns::scheduler::QueueStatus modifiedQueueStatus = iter->second; 00512 modifiedQueueStatus.numOfBits = pdus*assumedBitsPerPDU; // add bits 00513 requestedResources.update(flowId,modifiedQueueStatus); 00514 } 00515 } 00516 MESSAGE_SINGLE(NORMAL, logger, "ResourceRequests("<<peer.getName()<<")="<<rrStorage->printQueueStatus()); 00517 } 00518 } 00519 00520 ResourceShares 00521 RRHandlerBS::getResourceShares(const wns::scheduler::UserSet& users) const 00522 { 00523 return rrStorage->getResourceShares(users); 00524 } 00525 00526 wns::scheduler::UserSet 00527 RRHandlerBS::getActiveUsers() const 00528 { 00529 wns::scheduler::UserSet result = rrStorage->getActiveUsers(); 00530 00531 MESSAGE_BEGIN(VERBOSE, logger, m, "Active Users are: "); 00532 for (wns::scheduler::UserSet::const_iterator iter = result.begin(); iter != result.end(); ++iter) 00533 m << iter->getName() << ", "; 00534 MESSAGE_END(); 00535 00536 return result; 00537 } 00538 00539 RequestStorageInterface* 00540 RRHandlerBS::getRRStorage() 00541 { 00542 return rrStorage; 00543 } 00544 00545 void 00546 RRHandlerBS::reset(const wns::scheduler::UserSet& users) 00547 { 00548 rrStorage->reset(users); 00549 } 00550 00551 void 00552 RRHandlerBS::onAssociated(wns::service::dll::UnicastAddress userAdr, 00553 wns::service::dll::UnicastAddress dstAdr) 00554 { 00555 } 00556 00557 void 00558 RRHandlerBS::onDisassociated(wns::service::dll::UnicastAddress userAdr, 00559 wns::service::dll::UnicastAddress dstAdr) 00560 { 00561 // If we received forwarded association Info, there's nothing to do 00562 if (layer2->getDLLAddress() != dstAdr) 00563 return; 00564 00565 wns::scheduler::UserID peer = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(userAdr)->getNode()); 00566 00567 // Else remove the disassociating user from the rrStorage 00568 MESSAGE_BEGIN(NORMAL, logger, m, "onDisassociated("<<A2N(userAdr)<<","<<A2N(dstAdr)<<"): removing user "); 00569 m << A2N(userAdr) << " from Resource Request rrStorage (peer="<<peer.getName()<<")"; 00570 MESSAGE_END(); 00571 00572 rrStorage->resetUser(peer); 00573 } 00574 00575 /***************************************************************************/ 00576 00577 RequestStorage::RequestStorage(wns::logger::Logger& _logger) 00578 : logger(_logger) 00579 { 00580 MESSAGE_SINGLE(VERBOSE, logger, "RequestStorage::RequestStorage()"); 00581 } 00582 00583 RequestStorage::~RequestStorage() 00584 { 00585 } 00586 00587 void 00588 RequestStorage::storeRequest(const wns::scheduler::UserID user, wns::scheduler::QueueStatusContainer& partialQueueStatusContainer) 00589 { 00590 //resetUser(user); 00591 for( wns::scheduler::QueueStatusContainer::const_iterator iter = partialQueueStatusContainer.begin(); iter != partialQueueStatusContainer.end(); ++iter) 00592 { 00593 wns::scheduler::ConnectionID flowId = iter->first; 00594 if (queueStatusContainer.knows(flowId)) { 00595 queueStatusContainer.update(flowId,iter->second); 00596 } else { 00597 queueStatusContainer.insert(flowId,iter->second); 00598 } 00599 if (!connectionUserMapping.knows(flowId)) { 00600 connectionUserMapping.insert(flowId,user); 00601 } 00602 } 00603 // insert user that has requested resources into the set of active users 00604 activeULUsers.insert(user); 00605 } 00606 00607 void 00608 RequestStorage::resetFlow(const wns::scheduler::ConnectionID flowId) 00609 { 00610 if (queueStatusContainer.knows(flowId)) { 00611 wns::scheduler::QueueStatus emptyQueueStatus; // =0 00612 queueStatusContainer.update(flowId,emptyQueueStatus); 00613 } 00614 } 00615 00616 void 00617 RequestStorage::resetUser(const wns::scheduler::UserID user) 00618 { 00619 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter) 00620 { 00621 wns::scheduler::ConnectionID flowId = iter->first; 00622 wns::scheduler::QueueStatus queueStatus = iter->second; 00623 if (connectionUserMapping.find(flowId) == user) { 00624 queueStatus.numOfCompounds = 0; 00625 queueStatus.numOfBits = 0; 00626 queueStatusContainer.update(flowId,queueStatus); 00627 } 00628 } 00629 // remove user from set of active users 00630 activeULUsers.erase(user); 00631 } 00632 00633 void 00634 RequestStorage::deleteUser(const wns::scheduler::UserID user) 00635 { 00636 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ) 00637 { 00638 wns::scheduler::QueueStatusContainer::const_iterator nextIter = iter; 00639 ++nextIter; 00640 wns::scheduler::ConnectionID flowId = iter->first; 00641 if (connectionUserMapping.find(flowId) == user) { 00642 queueStatusContainer.erase(flowId); 00643 } 00644 iter=nextIter; 00645 } 00646 // remove user from set of active users 00647 activeULUsers.erase(user); 00648 } 00649 00650 void 00651 RequestStorage::reset(const wns::scheduler::UserSet& users) 00652 { 00653 wns::scheduler::QueueStatusContainer tmpQueueStatusContainer = queueStatusContainer; 00654 queueStatusContainer.clear(); 00655 for( wns::scheduler::QueueStatusContainer::const_iterator iter = tmpQueueStatusContainer.begin(); iter != tmpQueueStatusContainer.end(); ++iter) 00656 { 00657 wns::scheduler::ConnectionID flowId = iter->first; 00658 wns::scheduler::UserID userID = connectionUserMapping.find(flowId); 00659 if (users.find(userID)==users.end()) // not in list of users to delete 00660 queueStatusContainer.insert(flowId,iter->second); 00661 } 00662 // remove users from set of active users 00663 for (wns::scheduler::UserSet::const_iterator iter = users.begin(); 00664 iter != users.end(); 00665 ++iter) 00666 { 00667 activeULUsers.erase(*iter); 00668 } 00669 } 00670 00671 // used only in unitTest: 00672 ResourceShares 00673 RequestStorage::getResourceShares(const wns::scheduler::UserSet& users) const 00674 { 00675 typedef std::map<wns::scheduler::UserID, uint32_t> RequestCounter; 00676 RequestCounter compoundsPerUser; 00677 uint32_t totalCompounds = 0; 00678 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter) 00679 { 00680 wns::scheduler::ConnectionID flowId = iter->first; 00681 wns::scheduler::UserID userID = connectionUserMapping.find(flowId); 00682 if (users.find(userID) != users.end()) 00683 { 00684 wns::scheduler::QueueStatus queueStatus = iter->second; 00685 int compoundsWaiting = queueStatus.numOfCompounds; 00686 totalCompounds += compoundsWaiting; 00687 if ( compoundsPerUser.find(userID) != compoundsPerUser.end() ) // found 00688 { 00689 compoundsPerUser[userID] += compoundsWaiting; 00690 } else { // new entry 00691 compoundsPerUser[userID] = compoundsWaiting; 00692 } 00693 } // else: Ignore requests from all users not in the given userset 00694 } 00695 00696 ResourceShares shares; 00697 00698 for (RequestCounter::const_iterator iter = compoundsPerUser.begin(); 00699 iter != compoundsPerUser.end(); 00700 ++iter) 00701 { 00702 wns::scheduler::UserID user = iter->first; 00703 uint32_t compoundsThisUser = iter->second; 00704 shares[user] = double(compoundsThisUser) / double(totalCompounds); 00705 } 00706 00707 return shares; 00708 } 00709 00710 std::string 00711 RequestStorage::printQueueStatus() const 00712 { 00713 std::stringstream s; 00714 s << "QueueStatus("; 00715 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter) 00716 { 00717 wns::scheduler::ConnectionID flowId = iter->first; 00718 s << "flowID="<<flowId<<": p="<<iter->second.numOfCompounds<<", b="<<iter->second.numOfBits<<"; "; 00719 } 00720 s << ")"; 00721 return s.str(); 00722 } 00723 00724 wns::scheduler::UserSet 00725 RequestStorage::getActiveUsers() const 00726 { 00727 return activeULUsers; 00728 } 00729 00730 wns::scheduler::ConnectionSet 00731 RequestStorage::getActiveConnections() const 00732 { 00733 wns::scheduler::ConnectionSet result; 00734 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter) 00735 { 00736 if (iter->second.numOfCompounds > 0) 00737 result.insert(iter->first); 00738 } 00739 return result; 00740 } 00741 00742 wns::scheduler::ConnectionSet 00743 RequestStorage::filterActiveConnections(wns::scheduler::ConnectionSet& inputConnectionSet) const 00744 { 00745 wns::scheduler::ConnectionSet result; 00746 for (wns::scheduler::ConnectionSet::const_iterator iter = inputConnectionSet.begin(); iter != inputConnectionSet.end(); ++iter) 00747 { 00748 wns::scheduler::ConnectionID flowId = (*iter); 00749 if (queueStatusContainer.knows(flowId)) { 00750 const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(flowId); 00751 if (queueStatus.numOfCompounds > 0) 00752 result.insert(flowId); 00753 } 00754 } 00755 return result; 00756 } 00757 00758 bool 00759 RequestStorage::knowsFlow(wns::scheduler::ConnectionID flowId) const 00760 { 00761 return queueStatusContainer.knows(flowId); 00762 } 00763 00764 bool 00765 RequestStorage::isEmpty() const 00766 { 00767 for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter) 00768 if (iter->second.numOfCompounds > 0) 00769 return false; 00770 return true; 00771 } 00772 00773 uint32_t 00774 RequestStorage::numBitsForCid(wns::scheduler::ConnectionID cid) const 00775 { 00776 if (queueStatusContainer.knows(cid)) 00777 { 00778 const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(cid); 00779 return queueStatus.numOfBits; 00780 } else { 00781 return 0; 00782 } 00783 } 00784 00785 uint32_t 00786 RequestStorage::numCompoundsForCid(wns::scheduler::ConnectionID cid) const 00787 { 00788 if (queueStatusContainer.knows(cid)) 00789 { 00790 const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(cid); 00791 return queueStatus.numOfCompounds; 00792 } else { 00793 return 0; 00794 } 00795 } 00796 00797 wns::scheduler::Bits 00798 RequestStorage::decrementRequest(wns::scheduler::ConnectionID cid, wns::scheduler::Bits bits) 00799 { 00800 if (queueStatusContainer.knows(cid)) 00801 { 00802 assure(bits>0,"decrementRequest(cid="<<cid<<",bits="<<bits<<") must request bits>0"); 00803 wns::scheduler::QueueStatus queueStatus = queueStatusContainer.find(cid); 00804 int queuedPdus = queueStatus.numOfCompounds; 00805 int queuedBits = queueStatus.numOfBits; 00806 MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<",bits="<<bits<<"): queued: "<<queuedPdus<<" pdus, "<<queuedBits<<" bits"); 00807 if ((queuedPdus>0) && (queuedBits>0)) { 00808 queueStatus.numOfCompounds --; 00809 if (queuedBits>=bits) { 00810 queueStatus.numOfBits -= bits; 00811 } else { // not enough bits in queue 00812 bits = queuedBits; 00813 queueStatus.numOfBits = 0; 00814 } 00815 // any remaining bits or compounds? 00816 queuedPdus = queueStatus.numOfCompounds; 00817 queuedBits = queueStatus.numOfBits; 00818 if (((queuedPdus>0) && (queuedBits>0)) 00819 || (queuedPdus==0) && (queuedBits==0)) { // ok 00820 } else if (queuedPdus>0) { // but queuedBits=0 00821 MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<"): last "<<bits<<" bits served. Leftover "<<queuedPdus<<" pdus set to zero"); 00822 queueStatus.numOfCompounds = 0; 00823 } else if (queuedBits>0) { // but queuedPdus=0 00824 MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<"): "<<bits<<" bits served but zero="<<queuedPdus<<" pdus. Assuming one pdu."); 00825 queueStatus.numOfCompounds += 1; 00826 } 00827 queueStatusContainer.update(cid,queueStatus); 00828 } else { 00829 assure(false,"decrementRequest(cid="<<cid<<",bits="<<bits<<") for empty RR queue"); 00830 return 0; 00831 } 00832 } else { 00833 assure(false,"decrementRequest(cid="<<cid<<",bits="<<bits<<") for unknown cid"); 00834 throw wns::Exception("decrementRequest for unknown cid"); 00835 return 0; 00836 } 00837 return bits; 00838 } 00839 00840 wns::scheduler::QueueStatusContainer 00841 RequestStorage::getQueueStatus() const 00842 { 00843 return queueStatusContainer; 00844 }
1.5.5