![]() |
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/associationHandler/AssociationHandlerUT.hpp> 00029 #include <LTE/controlplane/AssociationsProxy.hpp> 00030 #include <LTE/macg/MACgCommand.hpp> 00031 #include <LTE/rlc/RLCCommand.hpp> 00032 #include <LTE/helper/Keys.hpp> 00033 00034 #include <DLL/services/control/Association.hpp> 00035 #include <DLL/Layer2.hpp> 00036 #include <DLL/StationManager.hpp> 00037 00038 #include <WNS/StaticFactory.hpp> 00039 #include <WNS/ldk/tools/Synchronizer.hpp> 00040 #include <WNS/ldk/IConnectorReceptacle.hpp> 00041 00042 #define A2N(a) layer2->getStationManager()->getStationByMAC(a)->getName() 00043 00044 using namespace lte::controlplane::associationHandler; 00045 00046 STATIC_FACTORY_REGISTER_WITH_CREATOR(AssociationHandlerUT, 00047 wns::ldk::FunctionalUnit, 00048 "lte.controlplane.AssociationHandler.UserTerminal", 00049 wns::ldk::FUNConfigCreator); 00050 00051 AssociationHandlerUT::AssociationHandlerUT(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) : 00052 AssociationHandler(fun, config), 00053 wns::Cloneable<AssociationHandlerUT>(), 00054 timeout(config.get<double>("timeout")), 00055 associationsProxy(), 00056 scheduledRAP(), 00057 duplexGroup(config.get<int>("capabilities.duplexGroup")) 00058 { 00059 MESSAGE_SINGLE(NORMAL, logger, "My duplexGroup=" << duplexGroup); 00060 } 00061 00062 void 00063 AssociationHandlerUT::onFUNCreated() 00064 { 00065 AssociationHandler::onFUNCreated(); 00066 00067 associationsProxy = dynamic_cast<lte::controlplane::AssociationsProxyUT*>(layer2->getControlService<wns::ldk::ControlServiceInterface>("AssociationsProxy")); 00068 00069 // get handles to outgoing FUs 00070 typedef std::list<wns::ldk::IConnectorReceptacle*> FUList; 00071 FUList connectorSet = connector->getFUs(); 00072 for (FUList::const_iterator iter = connectorSet.begin(); 00073 iter != connectorSet.end(); 00074 ++iter) 00075 { 00076 size_t found = (*iter)->getFU()->getName().find("rachDispatcher"); 00077 if (found != std::string::npos) 00078 friends.rachDispatcher = (*iter); 00079 found = (*iter)->getFU()->getName().find("controlPlaneDispatcher"); 00080 if (found != std::string::npos) 00081 friends.cpDispatcher = (*iter); 00082 } 00083 00084 assure(friends.rachDispatcher, "AssociationHandler requires a friend with name: "+mode+separator+"rachDispatcher"); 00085 assure(friends.cpDispatcher, "AssociationHandler requires a friend with name: "+mode+separator+"controlPlaneDispatcher"); 00086 } 00087 00088 void 00089 AssociationHandlerUT::doOnData(const wns::ldk::CompoundPtr& compound) 00090 { 00091 lte::controlplane::associationHandler::AssociationCommand* incomingCommand = getCommand(compound->getCommandPool()); 00092 00093 wns::service::dll::UnicastAddress sendingTo = incomingCommand->peer.dst; 00094 00096 if (!(sendingTo == layer2->getDLLAddress())) 00097 return; 00098 00099 wns::service::dll::UnicastAddress comingFrom = incomingCommand->peer.src; 00100 00101 if (incomingCommand->peer.myCompoundType == CompoundType::disassociation_ack()) 00102 { 00103 MESSAGE_BEGIN(NORMAL, logger, m, "Received " ); 00104 m << mode << separator << "disassociation_ack from " << layer2->getStationManager()->getStationByMAC(incomingCommand->peer.src)->getName(); 00105 MESSAGE_END(); 00106 00107 assure(associationService->hasAssociation(), "Received disassociation_ack for none association!"); 00108 00109 // needed to notify observers after releasing from master 00110 wns::service::dll::UnicastAddress dst = associationService->getAssociation(); 00111 00112 // ignore the unexpected disassociation_ack from unexpected RAP! e.g.: 00113 // send disassociation_req to station 1...timeout, 00114 // release itself from the station 1 and 00115 // send association_req to station 2..., 00116 // received association_ack from station 2..., 00117 // received delayed disassociation_ack from station 1 ! 00118 if (!(dst == comingFrom)) return; 00119 00120 cancelTimeout(); 00121 00122 // get key of flow separators and flow gates 00123 wns::service::dll::UnicastAddress bsAdr = associationsProxy->getBSforMode(mode); 00124 assure(bsAdr.isValid(), "Wrong BS address stored in AssociationsProxy!"); 00125 00126 // notify observers 00127 notifyOnDisassociated(layer2->getDLLAddress(), dst); 00128 00129 // notify Association Service 00130 associationService->releaseFromMaster(); 00131 00132 // inform associationsProxy 00133 associationsProxy->disassociatedPerMode(incomingCommand->peer.src, mode, incomingCommand->peer.preserve); 00134 00135 // Disassociation phase of Intra Mode Handover is done, 00136 // Association phase automatically 00137 if (scheduledRAP.isValid()) 00138 { 00139 createAssociation_req(scheduledRAP); 00140 // set timeout for waiting for the acknowledgement 00141 setTimeout(timeout); 00142 } 00143 } 00144 else if (incomingCommand->peer.myCompoundType == CompoundType::association_ack()) 00145 { 00146 assure(!(associationService->hasAssociation()), "Received association_ack for already existing association!"); 00147 00148 MESSAGE_BEGIN(NORMAL, logger, m, "Received " ); 00149 m << mode << separator << "association_ack from " << layer2->getStationManager()->getStationByMAC(incomingCommand->peer.src)->getName(); 00150 MESSAGE_END(); 00151 00152 cancelTimeout(); 00153 00154 // Intra Mode handover is done, reset the scheduledRAP 00155 if (scheduledRAP.isValid()) 00156 { 00157 assure(comingFrom == scheduledRAP, "Received association_ack from unexpected RAP!"); 00158 00159 // reset scheduledRAP 00160 scheduledRAP = wns::service::dll::UnicastAddress(); 00161 } 00162 00163 // register association 00164 associate(comingFrom); 00165 00166 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs = 00167 incomingCommand->peer.controlPlaneFlowIDs; 00168 00169 // inform associationsProxy 00170 associationsProxy->associatedPerMode(incomingCommand->peer.src, incomingCommand->magic.bs, mode, _controlPlaneFlowIDs); 00171 } 00172 else 00173 assure(false, "received association compound with wrong type!"); 00174 } 00175 00176 void 00177 AssociationHandlerUT::onTimeout() 00178 { 00179 MESSAGE_SINGLE(NORMAL, logger, "Timeout for waiting for acknowledgement!"); 00180 00181 if (associationService->hasAssociation()) 00182 { 00183 wns::service::dll::UnicastAddress dst = associationService->getAssociation(); 00184 wns::service::dll::UnicastAddress bsAdr = associationsProxy->getBSforMode(mode); 00185 00186 // notify observers 00187 notifyOnDisassociated(layer2->getDLLAddress(), dst); 00188 00189 // release the not reachable association 00190 associationService->releaseFromMaster(); 00191 layer2->getControlService<lte::controlplane::AssociationsProxyUT>("AssociationsProxy")->disassociationOnTimeout(dst, mode); 00192 } 00193 00194 if (scheduledRAP.isValid()) 00195 { 00196 createAssociation_req(scheduledRAP); 00197 setTimeout(timeout); 00198 } 00199 } 00200 00201 int 00202 AssociationHandlerUT::getMyDuplexGroup(int /*frameNr*/, bool /*isDL*/) 00203 { 00204 return duplexGroup; 00205 } 00206 int 00207 AssociationHandlerUT::getPeerDuplexGroup(wns::service::dll::UnicastAddress /*user*/) 00208 { 00209 // this is my duplexGroup, 00210 // but we know that the peer's duplexGroup is the same 00211 return duplexGroup; 00212 } 00213 00214 void 00215 AssociationHandlerUT::associateTo(wns::service::dll::UnicastAddress rapAdr) 00216 { 00217 assure(!(associationService->hasAssociation()), "UT has still association!"); 00218 00219 // plain association, must be called without association 00220 createAssociation_req(rapAdr); 00221 setTimeout(timeout); 00222 00223 // enable re-association on timeout 00224 scheduledRAP = rapAdr; 00225 } 00226 00227 void 00228 AssociationHandlerUT::disassociate(wns::service::dll::UnicastAddress rapAdr) 00229 { 00230 assure(associationService->hasAssociation(), "UT has not associated!"); 00231 00232 // no scheduled RAP, plain disassociation 00233 createDisassociation_req(rapAdr); 00234 setTimeout(timeout); 00235 } 00236 00237 void 00238 AssociationHandlerUT::switchAssociationTo(wns::service::dll::UnicastAddress rapAdr) 00239 { 00240 assure(associationService->hasAssociation(), "UT has not associated!"); 00241 00242 // For Intra-Mode Handover, controlled by associationHandler self 00243 createDisassociation_req(rapAdr); 00244 setTimeout(timeout); 00245 00246 // enable association direct after disassociation 00247 scheduledRAP = rapAdr; 00248 } 00249 00250 void 00251 AssociationHandlerUT::bestRAP(wns::service::dll::UnicastAddress destination) 00252 { 00253 MESSAGE_SINGLE(NORMAL, logger, "bestRAP("<<A2N(destination)<<")"); 00254 // Maybe report the Associationsproxy directly... 00255 assure(associationsProxy!=NULL,"invalid associationsProxy"); 00256 associationsProxy->modeDetected(mode, destination); 00257 } 00258 00259 void 00260 AssociationHandlerUT::belowThreshold(wns::service::dll::UnicastAddress destination) 00261 { 00262 // only if this is UT's active association 00263 if ((associationService->hasAssociation()) 00264 && (associationService->getAssociation() == destination)) 00265 { 00266 MESSAGE_SINGLE(NORMAL, logger, "Requesting Disassociation due to bad BCH"); 00267 associationsProxy->disassociationNeeded(mode, destination); 00268 } 00269 else 00270 MESSAGE_SINGLE(NORMAL, logger, "Station in outage. Best BCH is below threshold."); 00271 } 00272 00273 void 00274 AssociationHandlerUT::createAssociation_req(wns::service::dll::UnicastAddress destination) const 00275 { 00277 wns::ldk::CompoundPtr associationCompound = 00278 wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool())); 00279 00281 AssociationCommand* outgoingCommand = this->activateCommand(associationCompound->getCommandPool()); 00282 outgoingCommand->peer.myCompoundType = CompoundType::association_req(); 00283 outgoingCommand->peer.src = layer2->getDLLAddress(); 00284 outgoingCommand->peer.dst = destination; 00285 outgoingCommand->peer.user = layer2->getDLLAddress(); 00286 outgoingCommand->peer.mode = mode; 00287 outgoingCommand->peer.duplexGroup = duplexGroup; 00288 outgoingCommand->magic.sender = this; // for debugging and assures 00289 00290 // activate RLC command 00291 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(associationCompound->getCommandPool())); 00292 rlcCommand->peer.flowID = 0; // over RACH we don't need a correct flowID. Anyway, we don't have it yet. 00293 00295 connector->activate(friends.rachDispatcher); 00296 00297 if (getConnector()->hasAcceptor(associationCompound)) 00298 { 00299 getConnector()->getAcceptor(associationCompound)->sendData(associationCompound); 00300 MESSAGE_SINGLE(NORMAL, logger, "Sent " 00301 << mode+separator << "associationReq to " 00302 << layer2->getStationManager()->getStationByMAC(outgoingCommand->peer.dst)->getName()); 00303 } 00304 else 00305 assure(false, "Lower FU is not accepting scheduled associationReq compound but is supposed to do so"); 00306 } 00307 00308 void 00309 AssociationHandlerUT::createDisassociation_req(wns::service::dll::UnicastAddress target) const 00310 { 00312 wns::ldk::CompoundPtr associationCompound = 00313 wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool())); 00314 00315 wns::service::dll::UnicastAddress destinationAddress = associationService->getAssociation(); 00316 00318 lte::macg::MACgCommand* macgCommand = dynamic_cast<lte::macg::MACgCommand*>(macgReader->activateCommand(associationCompound->getCommandPool())); 00319 macgCommand->peer.source = layer2->getDLLAddress(); 00320 macgCommand->peer.dest = destinationAddress; 00321 00322 // activate RLC command 00323 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(associationCompound->getCommandPool())); 00324 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs = 00325 friends.flowManager->getControlPlaneFlowIDs(destinationAddress); 00326 rlcCommand->peer.flowID = _controlPlaneFlowIDs[lte::helper::QoSClasses::DCCH()]; 00327 00329 connector->activate(friends.cpDispatcher); 00330 00331 AssociationCommand* outgoingCommand = this->activateCommand(associationCompound->getCommandPool()); 00332 outgoingCommand->peer.myCompoundType = CompoundType::disassociation_req(); 00333 outgoingCommand->peer.src = layer2->getDLLAddress(); 00334 outgoingCommand->peer.dst = associationService->getAssociation(); 00335 outgoingCommand->peer.user = layer2->getDLLAddress(); 00336 outgoingCommand->peer.targetRAP = target; 00337 outgoingCommand->peer.mode = mode; 00338 outgoingCommand->magic.sender = this; // for debugging and assures 00339 00341 if (getConnector()->hasAcceptor(associationCompound)) 00342 { 00343 getConnector()->getAcceptor(associationCompound)->sendData(associationCompound); 00344 MESSAGE_SINGLE(NORMAL, logger, "Sent " 00345 << mode+separator << "disassociationReq to " 00346 << layer2->getStationManager()->getStationByMAC(outgoingCommand->peer.dst)->getName()); 00347 } 00348 else 00349 assure(false, "Lower FU is not accepting scheduled disassociationReq compound but is supposed to do so"); 00350 } 00351 00352 void 00353 AssociationHandlerUT::associate(wns::service::dll::UnicastAddress destination) 00354 { 00355 dll::ILayer2* newDestination = layer2->getStationManager()->getStationByMAC(destination); 00356 00357 associationService->associate(layer2, newDestination); 00358 00359 // notify observers 00360 notifyOnAssociated(layer2->getDLLAddress(), destination); 00361 }
1.5.5