![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * Glue * 00003 * __________________________________________________________________________ * 00004 * * 00005 * Copyright (C) 2005-2006 * 00006 * Lehrstuhl fuer Kommunikationsnetze (ComNets) * 00007 * Kopernikusstr. 16, D-52074 Aachen, Germany * 00008 * phone: ++49-241-80-27910 (phone), fax: ++49-241-80-22242 * 00009 * email: wns@comnets.rwth-aachen.de * 00010 * www: http://wns.comnets.rwth-aachen.de * 00011 ******************************************************************************/ 00012 00013 #include <GLUE/convergence/Lower2Copper.hpp> 00014 #include <GLUE/convergence/Upper.hpp> 00015 #include <GLUE/Component.hpp> 00016 00017 #include <WNS/ldk/fun/FUN.hpp> 00018 00019 #include <WNS/pyconfig/View.hpp> 00020 #include <WNS/module/Base.hpp> 00021 00022 #include <WNS/probe/bus/json/probebus.hpp> 00023 #include <WNS/probe/bus/utils.hpp> 00024 00025 #include <cstdlib> 00026 00027 00028 using namespace glue::convergence; 00029 00030 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00031 Lower2Copper, 00032 wns::ldk::FunctionalUnit, 00033 "glue.convergence.Lower2Copper", 00034 wns::ldk::FUNConfigCreator); 00035 00036 Lower2Copper::Lower2Copper(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config) : 00037 wns::ldk::CommandTypeSpecifier<LowerCommand>(fun), 00038 wns::ldk::HasReceptor<>(), 00039 wns::ldk::HasConnector<>(), 00040 wns::ldk::HasDeliverer<>(), 00041 wns::Cloneable<Lower2Copper>(), 00042 00043 config(_config), 00044 logger(_config.get<wns::pyconfig::View>("logger")), 00045 dataTransmission(NULL), 00046 notificationService(NULL), 00047 isBlocking(_config.get<bool>("blocking")) 00048 { 00049 wns::probe::bus::ContextProviderCollection localContext( 00050 &fun->getLayer()->getContextProviderCollection()); 00051 jsonTracing = wns::probe::bus::collector(localContext, config, "phyTraceProbeName"); 00052 } // Lower2Copper 00053 00054 Lower2Copper::~Lower2Copper() 00055 { 00056 } // ~Lower2Copper 00057 00058 void Lower2Copper::onFUNCreated() 00059 { 00060 friends.unicastRouting = 00061 getFUN()->findFriend<glue::convergence::UnicastUpper*>( 00062 config.get<std::string>("unicastRouting")); 00063 00064 friends.broadcastRouting = 00065 getFUN()->findFriend<glue::convergence::BroadcastUpper*>( 00066 config.get<std::string>("broadcastRouting")); 00067 } // onFUNCreated 00068 00069 bool Lower2Copper::doIsAccepting(const wns::ldk::CompoundPtr& /* compound */) const 00070 { 00071 if (this->isBlocking == true) 00072 { 00073 return getDataTransmissionService()->isFree(); 00074 } 00075 else 00076 { 00077 return true; 00078 } 00079 } // isAccepting 00080 00081 void Lower2Copper::onCarrierIdle() 00082 { 00083 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00084 m << ": carrier idle, accepting new transmissions"; 00085 MESSAGE_END(); 00086 00087 getReceptor()->wakeup(); 00088 } 00089 00090 void Lower2Copper::onCarrierBusy() 00091 { 00092 // currently, we do nothing. 00093 } 00094 00095 void Lower2Copper::onCollision() 00096 { 00097 // currently, we do nothing. In future we might stop ongoing transmissions 00098 } // onCollision 00099 00100 void 00101 Lower2Copper::doSendData(const wns::ldk::CompoundPtr& compound) 00102 { 00103 assure(compound, "sendData called with an invalid compound."); 00104 00105 if (hasCommandOf(friends.unicastRouting, compound)) { 00106 UnicastUpperCommand* command = friends.unicastRouting->getCommand(compound->getCommandPool()); 00107 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00108 LowerCommand* lc = activateCommand(compound->getCommandPool()); 00109 lc->magic.txStartTime = now; 00110 00111 /* Only the "real" Glue Layer support getStationType, the stubs in the tests do not*/ 00112 wns::ldk::ILayer* layer = getFUN()->getLayer(); 00113 Component* glueLayer = dynamic_cast<Component*>(layer); 00114 if(glueLayer != NULL) 00115 lc->magic.senderType = glueLayer->getStationType(); 00116 00117 getDataTransmissionService()->sendData(command->peer.targetMACAddress, compound); 00118 } 00119 else if (hasCommandOf(friends.broadcastRouting, compound)) { 00120 BroadcastUpperCommand* command = friends.broadcastRouting->getCommand(compound->getCommandPool()); 00121 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00122 LowerCommand* lc = activateCommand(compound->getCommandPool()); 00123 lc->magic.txStartTime = now; 00124 00125 /* Only the "real" Glue Layer support getStationType, the stubs in the tests do not*/ 00126 wns::ldk::ILayer* layer = getFUN()->getLayer(); 00127 Component* glueLayer = dynamic_cast<Component*>(layer); 00128 if(glueLayer != NULL) 00129 lc->magic.senderType = glueLayer->getStationType(); 00130 00131 getDataTransmissionService()->sendData(command->peer.targetMACAddress, compound); 00132 } 00133 else assure(false, "Not a routing Compound!"); 00134 } // doSendData 00135 00136 void Lower2Copper::doOnData(const wns::ldk::CompoundPtr& compound) 00137 { 00138 assure(compound, "onData called with an invalid compound."); 00139 00140 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00141 m << ": doOnData(), forwading to higher FU"; 00142 MESSAGE_END(); 00143 00144 getDeliverer()->getAcceptor(compound)->onData(compound); 00145 } // doOnData 00146 00147 void 00148 Lower2Copper::doWakeup() 00149 { 00150 // This will never be called ... 00151 } // doWakeup 00152 00153 void 00154 Lower2Copper::onData(const wns::osi::PDUPtr& pdu, double ber, bool collision) 00155 { 00156 assure(wns::dynamicCast<wns::ldk::Compound>(pdu), "not a CompoundPtr"); 00157 00158 // FIRST: create a copy instead of working on the real compound 00159 wns::ldk::CompoundPtr compound = wns::staticCast<wns::ldk::Compound>(pdu)->copy(); 00160 00161 #ifndef NDEBUG 00162 if(jsonTracing->hasObservers()) 00163 traceIncoming(compound, collision); 00164 #endif 00165 00166 // In case of a collision -> throw away ... packet can't be decoded 00167 if (collision) 00168 { 00169 return; 00170 } 00171 00172 if (hasCommandOf(friends.unicastRouting, compound)) { 00173 UnicastUpperCommand* uc = friends.unicastRouting->getCommand(compound->getCommandPool()); 00174 if (uc->peer.targetMACAddress == address) { 00175 pushUp(compound, ber, pdu); 00176 } 00177 } 00178 else if (hasCommandOf(friends.broadcastRouting, compound)) { 00179 pushUp(compound, ber, pdu); 00180 } 00181 // else throw away 00182 // Data was not for us 00183 // should not happen with current copper implementation 00184 } // onData 00185 00186 void 00187 Lower2Copper::setDataTransmissionService(wns::service::Service* phy) 00188 { 00189 assure(phy, "must be non-NULL"); 00190 assureType(phy, wns::service::phy::copper::DataTransmission*); 00191 dataTransmission = dynamic_cast<wns::service::phy::copper::DataTransmission*>(phy); 00192 } // setDataTransmissionService 00193 00194 wns::service::phy::copper::DataTransmission* 00195 Lower2Copper::getDataTransmissionService() const 00196 { 00197 assure(dataTransmission, "no copper::DataTransmission set. Did you call setDataTransmission()?"); 00198 return dataTransmission; 00199 } // getDataTransmissionService 00200 00201 void 00202 Lower2Copper::setNotificationService(wns::service::Service* phy) 00203 { 00204 assure(phy, "must be non-NULL"); 00205 assureType(phy, wns::service::phy::copper::Notification*); 00206 notificationService = dynamic_cast<wns::service::phy::copper::Notification*>(phy); 00207 // attach for both, data handling an carrier sensing 00208 this->wns::Observer<wns::service::phy::copper::Handler>::startObserving(notificationService); 00209 this->wns::Observer<wns::service::phy::copper::CarrierSensing>::startObserving(notificationService); 00210 notificationService->setDLLUnicastAddress(address); 00211 } // setNotificationService 00212 00213 wns::service::phy::copper::Notification* 00214 Lower2Copper::getNotificationService() const 00215 { 00216 assure(notificationService, "no copper::Notification set. Did you call setNotificationService()?"); 00217 return notificationService; 00218 } // getNotificationService 00219 00220 void 00221 Lower2Copper::setMACAddress(const wns::service::dll::UnicastAddress& _address) 00222 { 00223 address = _address; 00224 MESSAGE_SINGLE(NORMAL, logger, "setting MAC address of lowerConvergence to: " << address); 00225 } // setMACAddress 00226 00227 void 00228 Lower2Copper::pushUp(const wns::ldk::CompoundPtr& compound, double ber, const wns::osi::PDUPtr& pdu) 00229 { 00230 LowerCommand* lc = getCommand(compound->getCommandPool()); 00231 lc->local.per = 1.0 - pow(1.0 - ber, pdu->getLengthInBits()); 00232 notifyBERConsumers(ber, pdu->getLengthInBits()); 00233 this->wns::ldk::FunctionalUnit::onData(compound); 00234 } // pushUp 00235 00236 void 00237 Lower2Copper::traceIncoming(wns::ldk::CompoundPtr compound, bool collision) 00238 { 00239 wns::probe::bus::json::Object objdoc; 00240 00241 /* Only the "real" Glue Layer support getStationType, the stubs in the tests do not*/ 00242 wns::ldk::ILayer* layer = getFUN()->getLayer(); 00243 Component* myLayer = dynamic_cast<Component*>(layer); 00244 if(myLayer == NULL) 00245 return; 00246 00247 LowerCommand* lc; 00248 lc = getCommand(compound->getCommandPool()); 00249 00250 UnicastUpperCommand* uc = 00251 friends.unicastRouting->getCommand(compound->getCommandPool()); 00252 00253 wns::service::dll::UnicastAddress dstAdr; 00254 00255 bool isBroadcast; 00256 00257 if (hasCommandOf(friends.unicastRouting, compound)) 00258 { 00259 dstAdr = uc->peer.targetMACAddress; 00260 isBroadcast = false; 00261 } 00262 else 00263 { 00264 isBroadcast = true; 00265 } 00266 00267 std::string src; 00268 std::string dst("Broadcast"); 00269 std::string me; 00270 std::string sender; 00271 00272 std::stringstream s; 00273 std::stringstream m; 00274 std::stringstream d; 00275 std::stringstream snd; 00276 00277 if(myLayer->getStationType() == StationTypes::router()) 00278 { 00279 m << "BS"; 00280 } 00281 else 00282 { 00283 m << "UT"; 00284 } 00285 00286 if(lc->magic.senderType == StationTypes::router()) 00287 { 00288 s << "BS"; 00289 snd << "BS"; 00290 /* For now we assume the destination has the other station type */ 00291 d << "UT"; 00292 } 00293 else 00294 { 00295 s << "UT"; 00296 snd << "UT"; 00297 /* For now we assume the destination has the other station type */ 00298 d << "BS"; 00299 } 00300 00301 s << uc->peer.sourceMACAddress; 00302 sender = s.str(); 00303 00304 m << address; 00305 me = m.str(); 00306 00307 /* Glue does not support L2 multihop, sender always is source */ 00308 snd << uc->peer.sourceMACAddress; 00309 src = snd.str(); 00310 00311 if(!isBroadcast) 00312 { 00313 d << dstAdr; 00314 dst = d.str(); 00315 } 00316 00317 objdoc["Transmission"]["ReceiverID"] = wns::probe::bus::json::String(me); 00318 objdoc["Transmission"]["SenderID"] = wns::probe::bus::json::String(sender); 00319 objdoc["Transmission"]["SourceID"] = wns::probe::bus::json::String(src); 00320 objdoc["Transmission"]["DestinationID"] = wns::probe::bus::json::String(dst); 00321 00322 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00323 00324 objdoc["Transmission"]["Start"] = 00325 wns::probe::bus::json::Number(lc->magic.txStartTime); 00326 00327 objdoc["Transmission"]["Stop"] = wns::probe::bus::json::Number(now); 00328 00329 // We abuse this to watch per station results 00330 objdoc["Transmission"]["Subchannel"] = wns::probe::bus::json::Number( 00331 uc->peer.sourceMACAddress.getInteger()); 00332 00333 objdoc["Transmission"]["TxPower"] = 00334 wns::probe::bus::json::Number(0.0); // Unknown 00335 objdoc["Transmission"]["RxPower"] = 00336 wns::probe::bus::json::Number(0.0); 00337 objdoc["Transmission"]["InterferencePower"] = 00338 wns::probe::bus::json::Number(collision?200.0:-200.0); 00339 00340 wns::probe::bus::json::probeJSON(jsonTracing, objdoc); 00341 } 00342 00343
1.5.5