User Manual, Developers Guide and API Documentation

AssociationHandlerUT.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/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 }

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