User Manual, Developers Guide and API Documentation

BCHService.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/bch/BCHService.hpp>
00029 #include <LTE/controlplane/associationHandler/AssociationHandlerUT.hpp>
00030 
00031 #include <WNS/distribution/DiscreteUniform.hpp>
00032 
00033 #include <DLL/Layer2.hpp>
00034 #include <DLL/StationManager.hpp>
00035 
00036 #include <boost/lambda/lambda.hpp>
00037 
00038 #define A2N(a) (((a).getInteger()>0) ? layer2->getStationManager()->getStationByMAC(a)->getName() : "DLL<0")
00039 
00040 using namespace lte::controlplane;
00041 using namespace lte::controlplane::bch;
00042 
00043 STATIC_FACTORY_REGISTER_WITH_CREATOR(lte::controlplane::bch::BCHService,
00044                      wns::ldk::ControlServiceInterface,
00045                      "lte.controlplane.BCHService",
00046                      wns::ldk::CSRConfigCreator);
00047 
00048 BCHService::BCHService(wns::ldk::ControlServiceRegistry* csr,
00049                        const wns::pyconfig::View& config) :
00050     wns::ldk::ControlService(csr),
00051     lte::helper::HasModeName(config),
00052 
00053     bchStorage(),
00054     criterion(config.get("criterion")),
00055 
00056     upperThreshold(config.get<double>("upperThreshold")),
00057     lowerThreshold(config.get<double>("lowerThreshold")),
00058     layer2(NULL),
00059     associationHandler(NULL),
00060     logger(config.get("logger")),
00061     timeout(config.get<simTimeType>("timeout")),
00062     triggersAssociation(config.get<bool>("triggersAssociation")),
00063     triggersReAssociation(config.get<bool>("triggersReAssociation"))
00064 {
00065     bchStorage.reset();
00066     startPeriodicTimeout(timeout, 0.01);
00067 }
00068 
00069 lte::controlplane::bch::Best
00070 BCHService::getBest() const
00071 {
00072     lte::controlplane::bch::BCHRecordPtr best;
00073 
00074     double observedValue = 0;
00075 
00076     if (criterion.name == "SINR"){
00077         best = bchStorage.getBest<compare::BestSINR>();
00078         if (best != BCHRecordPtr())
00079         {
00080             if(criterion.ratioMargin > wns::Ratio::from_dB(0.0))
00081             {
00082                 wns::Ratio lowerBoundpl = best->sinr - criterion.ratioMargin;
00083                 wns::Ratio upperBoundpl = best->sinr;
00084 
00085                 using namespace boost::lambda;
00086                 boost::function<bool (wns::Ratio, wns::Ratio)> cmpr = _1 <= _2;
00087                 boost::function<wns::Ratio (BCHRecord*)> gettersinr = (_1 ->* &BCHRecord::sinr);
00088 
00089                 std::vector<BCHRecordPtr> r;
00090                 r = bchStorage.getBestInRange(lowerBoundpl, upperBoundpl, gettersinr, cmpr);
00091 
00092                 wns::distribution::DiscreteUniform rng(0, r.size() - 1);
00093                 best = r[rng()];                
00094             }
00095             observedValue = best->sinr.get_dB();
00096         }
00097         
00098     }
00099     else if (criterion.name == "RxPower"){
00100         best = bchStorage.getBest<compare::BestRXPWR>();
00101         if (best != BCHRecordPtr())
00102         {
00103             if(criterion.powerMargin > wns::Power::from_dBm(0.0))
00104             {
00105                 wns::Power lowerBoundpl = best->rxpower - criterion.powerMargin;
00106                 wns::Power upperBoundpl = best->rxpower;
00107 
00108                 using namespace boost::lambda;
00109                 boost::function<bool (wns::Power, wns::Power)> cmpp = _1 <= _2;
00110                 boost::function<wns::Power (BCHRecord*)> getterrxp = (_1 ->* &BCHRecord::rxpower);
00111 
00112                 std::vector<BCHRecordPtr> r;
00113                 r = bchStorage.getBestInRange(lowerBoundpl, upperBoundpl, getterrxp, cmpp);
00114 
00115                 wns::distribution::DiscreteUniform rng(0, r.size() - 1);
00116                 best = r[rng()];                
00117             }
00118             observedValue = best->rxpower.get_dBm();
00119         }
00120     }
00121     else if (criterion.name == "Distance"){
00122         best = bchStorage.getBest<compare::BestDIST>();
00123         if (best != BCHRecordPtr())
00124         {
00125             if(criterion.distanceMargin > 0.0)
00126             {
00127                 double lowerBoundpl = best->distance;
00128                 double upperBoundpl = best->distance + criterion.distanceMargin;
00129 
00130                 using namespace boost::lambda;
00131                 boost::function<bool (double, double)> cmpd = _1 <= _2;
00132                 boost::function<double (BCHRecord*)> getterdist = (_1 ->* &BCHRecord::distance);
00133 
00134                 std::vector<BCHRecordPtr> r;
00135                 r = bchStorage.getBestInRange(lowerBoundpl, upperBoundpl, getterdist, cmpd);
00136 
00137                 wns::distribution::DiscreteUniform rng(0, r.size() - 1);
00138                 best = r[rng()];                
00139             }
00140             observedValue = (-1) * best->distance;
00141         }
00142     }
00143     else if (criterion.name == "Pathloss"){
00144         best = bchStorage.getBest<compare::BestPathloss>();
00145         if (best != BCHRecordPtr())
00146         {
00147             if(criterion.ratioMargin > wns::Ratio::from_dB(0.0))
00148             {
00149                 wns::Ratio lowerBoundpl = best->pathloss;
00150                 wns::Ratio upperBoundpl = best->pathloss + criterion.ratioMargin;
00151 
00152                 using namespace boost::lambda;
00153                 boost::function<bool (wns::Ratio, wns::Ratio)> cmpr = _1 <= _2;
00154                 boost::function<wns::Ratio (BCHRecord*)> getterpl = (_1 ->* &BCHRecord::pathloss);
00155 
00156                 std::vector<BCHRecordPtr> r;
00157                 r = bchStorage.getBestInRange(lowerBoundpl, upperBoundpl, getterpl, cmpr);
00158 
00159                 wns::distribution::DiscreteUniform rng(0, r.size() - 1);
00160                 best = r[rng()];                
00161             }
00162             observedValue = (-1) * best->pathloss.get_dB();
00163         }
00164     }
00165     else if (criterion.name == "MAC_ID")
00166     {
00167         best = bchStorage.get(criterion.address);
00168 
00169         // We did not yet receive a BCH but associate anyways
00170         // this is needed because relays do not receive BCH from their serving BS
00171         // since they have to transmit their own BCH
00172         if(best == BCHRecordPtr())
00173         {
00174             best = BCHRecordPtr(new BCHRecord(criterion.address, wns::Ratio(), wns::Ratio(), 
00175                                                 wns::Power(), 0.0, 0));
00176         }
00177 
00178         observedValue = upperThreshold;
00179     }
00180     else
00181     {
00182         throw wns::Exception("Unsupported BCH Storage criterion");
00183         best = BCHRecordPtr();
00184     }
00185 
00186     Best retVal;
00187     retVal.entry = best;
00188     retVal.value = observedValue;
00189     return retVal;
00190 }
00191 
00192 
00193 void
00194 BCHService::periodically()
00195 {
00196     if(!triggersAssociation)
00197     {
00198         MESSAGE_SINGLE(NORMAL, logger, "BCHService does not trigger actions (any more).");
00199         return;
00200     }
00201 
00202     if (!layer2){
00203         layer2 = dynamic_cast<dll::ILayer2*>(getCSR()->getLayer());
00204     }
00205     assure(layer2!=NULL,"invalid layer2");
00206     if (!associationHandler){
00207         associationHandler = dynamic_cast<dll::ILayer2*>(getCSR()->getLayer())
00208           ->getFUN()
00209           ->findFriend<lte::controlplane::associationHandler::AssociationHandlerUT*>(mode+separator+ "associationHandler");
00210     }
00211     assure(associationHandler!=NULL,"invalid associationHandler");
00212 
00213     lte::controlplane::bch::Best bestEntry = getBest();
00214     lte::controlplane::bch::BCHRecordPtr best = bestEntry.entry;
00215     double observedValue = bestEntry.value;
00216 
00217     if (best != BCHRecordPtr())
00218     {
00219         MESSAGE_BEGIN(NORMAL, logger, m, "Best BCH currently received from ");
00220         m << A2N(best->source)
00221           << " with: \n"
00222           << "SINR: " << best->sinr.get_dB() << "\n"
00223           << "PL: " << best->pathloss.get_dB() << "\n"
00224           << "RxPwr: " << best->rxpower.get_dBm() << "\n"
00225           << "Dist.: " << best->distance << "\n"
00226           << "Active Criterion is '"<< criterion.name << "'\n";
00227         MESSAGE_END();
00228 
00229         if (triggersAssociation)
00230         {
00231             // report to associationHandler
00232             if (observedValue >= upperThreshold)
00233             {
00234                 MESSAGE_SINGLE(NORMAL, logger, "BCHService detected " << criterion.name << " value above threshold (" << upperThreshold << ")");
00235                 associationHandler->bestRAP(best->source);
00236             }
00237             else if (observedValue <= lowerThreshold)
00238             {
00239                 if (bchStorage.getBCHKeys().size() != 1)
00240                 {
00241                     MESSAGE_SINGLE(NORMAL, logger, "BCHService detected " << criterion.name
00242                                << " value below threshold (actual=" << observedValue <<
00243                                ", threshold="<< lowerThreshold << ")");
00244                     associationHandler->belowThreshold(best->source);
00245                 }
00246                 else
00247                 {
00248                     // if only one BS, do not do disassociation
00249                     MESSAGE_SINGLE(NORMAL, logger, "BCHService detected " << criterion.name
00250                                    << " value below threshold (actual=" << observedValue <<
00251                                    ", threshold="<< lowerThreshold << ")");
00252                     MESSAGE_SINGLE(NORMAL, logger, "Only one AP ("<<A2N(best->source)<<") is detected. Disassociation isn't needed");
00253                     associationHandler->bestRAP(best->source);
00254                 }
00255             }
00256             else
00257                 MESSAGE_SINGLE(NORMAL, logger, "BCHService not triggering any action.");
00258 
00259             if (triggersReAssociation == false) // do this only once
00260             {
00261                 MESSAGE_SINGLE(NORMAL, logger, "Stopping the triggering of further Re-Associations");
00262                 triggersAssociation = false;
00263             }
00264         }
00265     }
00266     else
00267     {
00268         MESSAGE_BEGIN(NORMAL, logger, m, "No BCH measured yet.");
00269         MESSAGE_END();
00270     }
00271 }
00272 
00273 void
00274 BCHService::storeMeasurement(const wns::service::dll::UnicastAddress& source,
00275                              const wns::service::phy::power::PowerMeasurementPtr&  phyMeasurementPtr, int subband)
00276 {
00277     if (!layer2){
00278         layer2 = dynamic_cast<dll::ILayer2*>(getCSR()->getLayer());
00279     }
00280     assure(layer2!=NULL,"invalid layer2");
00281     BCHRecordPtr _bchRecord = BCHRecordPtr(
00282         new BCHRecord(source,
00283                   phyMeasurementPtr->getSINR(),
00284                   phyMeasurementPtr->getPathLoss(),
00285                   phyMeasurementPtr->getRxPower(),
00286                   phyMeasurementPtr->getDistance(),
00287                   subband));
00288 
00289     // store data
00290     bchStorage.store(source,_bchRecord);
00291 
00292     MESSAGE_BEGIN(NORMAL, logger, m, "measured and stored BCH from " );
00293     m << A2N(source) << " with:\n"
00294       << "SINR: " << _bchRecord->sinr.get_dB() << "\n"
00295       << "PL: "   << _bchRecord->pathloss.get_dB() << "\n"
00296       << "RxPwr: " << _bchRecord->rxpower.get_dBm() << "\n"
00297       << "SubBand: " << _bchRecord->subBand << "\n"
00298       << "Dist.: " << _bchRecord->distance << "\n";
00299     MESSAGE_END();
00300 }
00301 
00302 void
00303 BCHService::storeMeasurement(const wns::service::dll::UnicastAddress& source,
00304                  const lte::macr::PhyCommand& phyCommand)
00305 {
00306     if (!layer2){
00307         layer2 = dynamic_cast<dll::ILayer2*>(getCSR()->getLayer());
00308     }
00309     assure(layer2!=NULL,"invalid layer2");
00310     wns::service::phy::power::PowerMeasurementPtr phyMeasurementPtr = phyCommand.local.rxPowerMeasurementPtr;
00311     this->storeMeasurement(source, phyMeasurementPtr, phyCommand.local.subBand);
00312 }
00313 
00314 uint32_t
00315 BCHService::getSubBand(const wns::service::dll::UnicastAddress& source) const
00316 {
00317     BCHRecordPtr entry = bchStorage.get(source);
00318 
00319     assure(entry != BCHRecordPtr(), "You may not retrieve the subBand for an address that's unknown to you(" << source << ")" );
00320 
00321     return entry->subBand;
00322 }
00323 
00324 
00325 

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