![]() |
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/AssociationHandlerBS.hpp> 00029 #include <LTE/controlplane/AssociationsProxy.hpp> 00030 #include <LTE/controlplane/flowmanagement/IFlowManager.hpp> 00031 #include <LTE/macg/MACgCommand.hpp> 00032 #include <LTE/rlc/RLCCommand.hpp> 00033 #include <LTE/helper/Keys.hpp> 00034 00035 #include <WNS/StaticFactory.hpp> 00036 #include <WNS/ldk/tools/Synchronizer.hpp> 00037 #include <WNS/ldk/IConnectorReceptacle.hpp> 00038 #include <DLL/services/control/Association.hpp> 00039 #include <DLL/StationManager.hpp> 00040 00041 #include <boost/bind.hpp> 00042 00043 #define A2N(a) (((a).getInteger()>0) ? layer2->getStationManager()->getStationByMAC(a)->getName() : "DLL<0") 00044 00045 using namespace lte::controlplane::associationHandler; 00046 00047 STATIC_FACTORY_REGISTER_WITH_CREATOR(AssociationHandlerBS, 00048 wns::ldk::FunctionalUnit, 00049 "lte.controlplane.AssociationHandler.BaseStation", 00050 wns::ldk::FUNConfigCreator); 00051 00052 AssociationHandlerBS::AssociationHandlerBS(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) : 00053 AssociationHandler(fun, config), 00054 wns::Cloneable<AssociationHandlerBS>(), 00055 associationsProxy() 00056 { 00057 } 00058 00059 void 00060 AssociationHandlerBS::onFUNCreated() 00061 { 00062 AssociationHandler::onFUNCreated(); 00063 00064 associationsProxy = dynamic_cast<lte::controlplane::AssociationsProxyBS*>(layer2->getControlService<wns::ldk::ControlServiceInterface>("AssociationsProxy")); 00065 00066 // get handles to outgoing FUs 00067 typedef std::list<wns::ldk::IConnectorReceptacle*> FUList; 00068 FUList connectorSet = connector->getFUs(); 00069 for (FUList::const_iterator iter = connectorSet.begin(); 00070 iter != connectorSet.end(); 00071 ++iter) 00072 { 00073 size_t found = (*iter)->getFU()->getName().find("bchBuffer"); 00074 if (found != std::string::npos) 00075 friends.bchBuffer = (*iter); 00076 found = (*iter)->getFU()->getName().find("controlPlaneDispatcher"); 00077 if (found != std::string::npos) 00078 friends.cpDispatcher = (*iter); 00079 } 00080 00081 phyUser = getFUN()->findFriend<lte::macr::PhyUser*>(modeBase + separator + "phyUser"); 00082 } 00083 00084 void 00085 AssociationHandlerBS::doOnData(const wns::ldk::CompoundPtr& compound) 00086 { 00087 lte::controlplane::associationHandler::AssociationCommand* incomingCommand = getCommand(compound->getCommandPool()); 00088 00089 wns::service::dll::UnicastAddress sendingTo = incomingCommand->peer.dst; 00090 00091 if (!(sendingTo == layer2->getDLLAddress())) 00092 return; 00093 00094 wns::service::dll::UnicastAddress comingFrom = incomingCommand->peer.src; 00095 00096 if(incomingCommand->peer.myCompoundType == CompoundType::association_req()) 00097 { 00098 MESSAGE_BEGIN(NORMAL, logger, m, "Received "); 00099 m << incomingCommand->peer.mode << separator 00100 << "association_req from " 00101 << layer2->getStationManager()->getStationByMAC(incomingCommand->peer.src)->getName(); 00102 MESSAGE_END(); 00103 00104 //safe the new users duplex group 00105 duplexGroups[incomingCommand->peer.user] = incomingCommand->peer.duplexGroup; 00106 MESSAGE_SINGLE(NORMAL, logger, "Stored duplex group=" << duplexGroups[incomingCommand->peer.user] << " for user=" << layer2->getStationManager()->getStationByMAC(incomingCommand->peer.user)->getName()); 00107 00108 if(!(incomingCommand->peer.user == comingFrom)) // forwarded 00109 { 00110 // inform associationsProxy 00111 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs = 00112 associationsProxy->associatedPerMode(incomingCommand->peer.user, incomingCommand->peer.src, incomingCommand->peer.mode); 00113 00114 // notify observers 00115 notifyOnAssociated(incomingCommand->peer.user, comingFrom); 00116 00117 // send association_ack 00118 connector->activate(friends.cpDispatcher); 00119 createAssociation_ack(comingFrom, incomingCommand->peer.user, incomingCommand->peer.mode, _controlPlaneFlowIDs); 00120 } 00121 else // directly 00122 { 00123 // inform associationsProxy 00124 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs = 00125 associationsProxy->associatedPerMode(incomingCommand->peer.user, layer2->getDLLAddress(), incomingCommand->peer.mode); 00126 00127 // notify observers 00128 notifyOnAssociated(incomingCommand->peer.user, layer2->getDLLAddress()); 00129 00130 connector->activate(friends.bchBuffer); 00131 createAssociation_ack(comingFrom, incomingCommand->peer.user, mode, _controlPlaneFlowIDs); 00132 } 00133 } 00134 else if(incomingCommand->peer.myCompoundType == CompoundType::disassociation_req()) 00135 { 00136 MESSAGE_BEGIN(NORMAL, logger, m, "received "); 00137 m << incomingCommand->peer.mode << separator << "disassociation_req from DLL address " << incomingCommand->peer.src; 00138 MESSAGE_END(); 00139 00140 bool preserve = false; 00141 if ((incomingCommand->peer.targetRAP).isValid()) 00142 preserve = associationsProxy->inMyREC(incomingCommand->peer.targetRAP); 00143 00144 // inform AssociationsProxy 00145 associationsProxy->disassociatedPerMode(incomingCommand->peer.user, 00146 incomingCommand->peer.targetRAP, 00147 incomingCommand->peer.mode); 00148 00149 if(incomingCommand->peer.user == comingFrom) // UT to BS (directly) 00150 { 00151 // directly 00152 dll::ILayer2* ut = layer2->getStationManager()->getStationByMAC(incomingCommand->peer.user); 00153 //dll::ILayer2* ut = layer2->getStationManager()->getStationByMAC(incomingCommand->peer.user); 00154 associationService->releaseClient(ut); 00155 00156 boost::function<void()> callback; 00157 callback = boost::bind(<e::controlplane::associationHandler::AssociationHandler::notifyOnDisassociated, this, incomingCommand->peer.user, layer2->getDLLAddress()); 00158 connector->activate(friends.cpDispatcher); 00159 createDisassociation_ack(comingFrom, incomingCommand->peer.user, preserve, mode, callback); 00160 } 00161 else // forwarded via a RN (UT->RN->BS) 00162 { 00163 // notify observers 00164 notifyOnDisassociated(incomingCommand->peer.user, comingFrom); 00165 00166 boost::function<void()> callback; 00167 connector->activate(friends.cpDispatcher); 00168 createDisassociation_ack(comingFrom, incomingCommand->peer.user, preserve, incomingCommand->peer.mode, callback); 00169 } 00170 } 00171 else 00172 assure(false, "received association compound with wrong type!"); 00173 } 00174 00175 void 00176 AssociationHandlerBS::createAssociation_ack(wns::service::dll::UnicastAddress destination, 00177 wns::service::dll::UnicastAddress user, 00178 std::string perMode, 00179 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs) const 00180 { 00182 wns::ldk::CompoundPtr associationCompound = 00183 wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool())); 00184 00186 lte::macg::MACgCommand* macgCommand = dynamic_cast<lte::macg::MACgCommand*>(macgReader->activateCommand(associationCompound->getCommandPool())); 00187 macgCommand->peer.source = layer2->getDLLAddress(); 00188 macgCommand->peer.dest = destination; 00189 00190 // activate RLC command 00191 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(associationCompound->getCommandPool())); 00192 rlcCommand->peer.flowID = _controlPlaneFlowIDs[lte::helper::QoSClasses::DCCH()]; 00193 00195 AssociationCommand* outgoingCommand = this->activateCommand(associationCompound->getCommandPool()); 00196 outgoingCommand->peer.myCompoundType = CompoundType::association_ack(); 00197 outgoingCommand->peer.src = layer2->getDLLAddress(); 00198 outgoingCommand->peer.dst = destination; 00199 outgoingCommand->peer.user = user; 00200 outgoingCommand->peer.mode = perMode; 00201 outgoingCommand->peer.duplexGroup = duplexGroups.find(user)->second; 00202 outgoingCommand->peer.controlPlaneFlowIDs = _controlPlaneFlowIDs; 00203 outgoingCommand->magic.bs = layer2->getDLLAddress(); 00204 outgoingCommand->magic.sender = this; // for debugging and assures 00205 00207 if (getConnector()->hasAcceptor(associationCompound)) 00208 { 00209 getConnector()->getAcceptor(associationCompound)->sendData(associationCompound); 00210 MESSAGE_SINGLE(NORMAL, logger, "sent " 00211 << outgoingCommand->peer.mode << separator << "associationAck to " 00212 << A2N(outgoingCommand->peer.dst)); 00213 } 00214 else 00215 assure(false, "Lower FU is not accepting scheduled association_ack compound but is supposed to do so"); 00216 } 00217 00218 int 00219 AssociationHandlerBS::getMyDuplexGroup(int frameNr, bool isDL) 00220 { 00221 int duplexGroup = 0; 00222 if (phyUser->isFddCapable()) 00223 { 00224 for (int i=0; i < frameNr; i++) 00225 { 00226 { 00227 duplexGroup = (duplexGroup + 1) % 2; 00228 //just alternating everytime we are RAP... 00229 } 00230 } 00231 // for UL: 00232 if (!isDL) { 00233 duplexGroup = (duplexGroup + 1) % 2; 00234 // UL will be the other group 00235 } 00236 return duplexGroup+1; 00237 // plus one, because we have defined halfduplex groups as 1 and 2... 00238 } 00239 else 00240 { 00241 return duplexGroup; 00242 } 00243 } 00244 00245 int 00246 AssociationHandlerBS::getPeerDuplexGroup(wns::service::dll::UnicastAddress user) 00247 { 00248 return duplexGroups.find(user)->second; 00249 } 00250 00251 void 00252 AssociationHandlerBS::createDisassociation_ack(wns::service::dll::UnicastAddress destination, 00253 wns::service::dll::UnicastAddress user, 00254 bool preserve, std::string perMode, 00255 boost::function<void()> callback) const 00256 { 00258 wns::ldk::CompoundPtr associationCompound = 00259 wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool())); 00260 00262 lte::macg::MACgCommand* macgCommand = dynamic_cast<lte::macg::MACgCommand*>(macgReader->activateCommand(associationCompound->getCommandPool())); 00263 macgCommand->peer.source = layer2->getDLLAddress(); 00264 macgCommand->peer.dest = destination; 00265 00266 // activate RLC command 00267 lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(associationCompound->getCommandPool())); 00268 lte::controlplane::flowmanagement::IFlowSwitching::ControlPlaneFlowIDs _controlPlaneFlowIDs = 00269 friends.flowManager->getControlPlaneFlowIDs(destination); 00270 rlcCommand->peer.flowID = _controlPlaneFlowIDs[lte::helper::QoSClasses::DCCH()]; 00271 00273 AssociationCommand* outgoingCommand = this->activateCommand(associationCompound->getCommandPool()); 00274 outgoingCommand->peer.myCompoundType = CompoundType::disassociation_ack(); 00275 outgoingCommand->peer.src = layer2->getDLLAddress(); 00276 outgoingCommand->peer.dst = destination; 00277 outgoingCommand->peer.user = user; 00278 outgoingCommand->peer.preserve = preserve; 00279 outgoingCommand->peer.mode = perMode; 00280 outgoingCommand->magic.bs = layer2->getDLLAddress(); 00281 outgoingCommand->magic.sender = this; // for debugging and assures 00282 00283 if (!callback.empty()) 00284 { 00286 lte::macr::PhyCommand* outgoingPhyCommand = phyUser->activateCommand(associationCompound->getCommandPool()); 00287 outgoingPhyCommand->local.onAirCallback = callback; 00288 } 00289 00291 if (getConnector()->hasAcceptor(associationCompound)) 00292 { 00293 getConnector()->getAcceptor(associationCompound)->sendData(associationCompound); 00294 MESSAGE_SINGLE(NORMAL, logger, "Sent " 00295 << outgoingCommand->peer.mode << separator << "disassociation_ack to " 00296 << layer2->getStationManager()->getStationByMAC(outgoingCommand->peer.dst)->getName()); 00297 } 00298 else 00299 assure(false, "Lower FU is not accepting scheduled disassociation_ack compound but is supposed to do so"); 00300 } 00301 00302 void 00303 AssociationHandlerBS::disassociationOnTimeout(const wns::service::dll::UnicastAddress adr, const std::string perMode) 00304 { 00305 // notify observers 00306 wns::service::dll::UnicastAddress rapAdr = associationsProxy->getRAPforUserPerMode(adr, perMode); 00307 notifyOnDisassociated(adr, rapAdr); 00308 00309 // inform AssociationsProxy 00310 associationsProxy->disassociatedPerMode(adr, wns::service::dll::UnicastAddress(), perMode); 00311 }
1.5.5