User Manual, Developers Guide and API Documentation

AssociationHandlerBS.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/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(&lte::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 }

Generated on Mon May 21 03:32:02 2012 for openWNS by  doxygen 1.5.5