![]() |
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/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
1.5.5