![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiMeMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2011 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 5, D-52074 Aachen, Germany 00009 * phone: ++49-241-80-27910, 00010 * fax: ++49-241-80-22242 00011 * email: info@openwns.org 00012 * www: http://www.openwns.org 00013 * _____________________________________________________________________________ 00014 * 00015 * openWNS is free software; you can redistribute it and/or modify it under the 00016 * terms of the GNU Lesser General Public License version 2 as published by the 00017 * Free Software Foundation; 00018 * 00019 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00020 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00021 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00022 * details. 00023 * 00024 * You should have received a copy of the GNU Lesser General Public License 00025 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00026 * 00027 ******************************************************************************/ 00028 00029 #include <WIMEMAC/arq/ARQ.hpp> 00030 #include <DLL/Layer2.hpp> 00031 00032 00033 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00034 wimemac::arq::ARQ, 00035 wns::ldk::FunctionalUnit, 00036 "wimemac.arq.ARQ", 00037 wns::ldk::FUNConfigCreator ); 00038 00039 using namespace wimemac::arq; 00040 00041 ARQ::ARQ( wns::ldk::fun::FUN* _fun, const wns::pyconfig::View& config_ ) : 00042 wns::ldk::fu::Plain<ARQ, ARQCommand>(_fun), 00043 logger(config_.get("logger")), 00044 managerName(config_.get<std::string>("managerName")), 00045 fun(_fun), 00046 retrans(0), 00047 SIFS(10E-6), 00048 AckDuration(13.125E-6) 00049 { 00050 scheduler = wns::simulator::getEventScheduler(); 00051 } 00052 00053 void 00054 ARQ::doOnData( const wns::ldk::CompoundPtr& compound ) 00055 { 00056 dll::UpperCommand* command = fun->getCommandReader("upperConvergence") 00057 ->readCommand<dll::UpperCommand>(compound->getCommandPool()); 00058 00059 if(command->peer.targetMACAddress != ownaddress) 00060 { 00061 MESSAGE_SINGLE(NORMAL, this->logger, "Received compound that is not for me -> drop"); 00062 } 00063 00064 else 00065 { 00066 wns::service::dll::UnicastAddress rx = command->peer.sourceMACAddress; 00067 wns::service::dll::UnicastAddress currentPartner = friends.manager->getCurrentTransmissionTarget(); 00068 00069 // only process compound if it's from the currently active transmission partner or if no transmission is active 00070 if((currentPartner == rx) || (currentPartner == wns::service::dll::UnicastAddress())) 00071 { 00072 if(hasCommandOf(compound) && getCommand(compound->getCommandPool())->peer.Frametype == ARQCommand::Ack) 00073 { 00074 MESSAGE_SINGLE(NORMAL, logger, "ARQ: received an ACK compound "); 00075 00076 if(getCommand(compound->getCommandPool())->peer.ACKpolicy == ARQCommand::ImmACK) 00077 { 00078 MESSAGE_SINGLE(NORMAL, logger, "ARQ: an immediate ack is received from station : " << rx 00079 <<" inform the drp buffer about the acknowledged compound "); 00080 friends.manager->Acknowledgment(rx); 00081 00082 } 00083 } 00084 else 00085 { 00086 MESSAGE_SINGLE(NORMAL, logger, "ARQ: receive a data frame from " << rx << ", create an ACK and forward data frame "); 00087 getDeliverer()->getAcceptor( compound )->onData( compound ); 00088 CreateACK(compound); 00089 } 00090 } 00091 else MESSAGE_SINGLE(NORMAL, logger, "ARQ: Received a compound from " << rx << ", but the current partner is " << currentPartner << ". Dropping the compound."); 00092 } 00093 } 00094 00095 bool 00096 ARQ::doIsAccepting( const wns::ldk::CompoundPtr& ) const 00097 { 00098 return true; 00099 } 00100 00101 void 00102 ARQ::doSendData( const wns::ldk::CompoundPtr& compound ) 00103 { 00104 if(!hasCommandOf(compound)) 00105 { 00106 ARQCommand* ac = activateCommand(compound->getCommandPool()); 00107 ac->peer.ACKpolicy = ARQCommand::ImmACK; 00108 } 00109 else 00110 { 00111 MESSAGE_SINGLE(NORMAL, logger, "ARQ: Command is already activated, ACKPolicy is set to: " 00112 <<getCommand(compound->getCommandPool())->peer.ACKpolicy 00113 <<" Target is : "<< (fun->getCommandReader("upperConvergence") 00114 ->readCommand<dll::UpperCommand>(compound->getCommandPool()))->peer.targetMACAddress); 00115 } 00116 00117 if(!getConnector()->hasAcceptor(compound)){ 00118 if(getCommand(compound->getCommandPool())->peer.Frametype == ARQCommand::Ack) 00119 { 00120 MESSAGE_SINGLE(NORMAL, logger, "ARQ: can't send ACK"); 00121 } 00122 else 00123 { 00124 MESSAGE_SINGLE(NORMAL, logger, "ARQ: can't send Data"); 00125 } 00126 } 00127 else{ 00128 00129 if(getCommand(compound->getCommandPool())->peer.Frametype == ARQCommand::Ack) 00130 { 00131 MESSAGE_SINGLE(NORMAL, logger, "ARQ: send ACK"); 00132 } 00133 else 00134 { 00135 MESSAGE_SINGLE(NORMAL, logger, "ARQ: send Data"); 00136 } 00137 getConnector()->getAcceptor(compound)->sendData(compound); 00138 } 00139 } 00140 00141 00142 void 00143 ARQ::onFUNCreated() 00144 { 00145 ownaddress = getFUN()->findFriend<dll::UpperConvergence*>("upperConvergence")->getMACAddress(); 00146 friends.manager = getFUN()->findFriend<wimemac::lowerMAC::IManagerServices*>(managerName); 00147 } 00148 00149 void 00150 ARQ::doWakeup() 00151 { 00152 } 00153 00154 bool 00155 ARQ::hasCommandOf(const wns::ldk::CompoundPtr& compound) const 00156 { 00157 return (getFUN()->getProxy()->commandIsActivated( compound->getCommandPool(), this )); 00158 } 00159 00160 void 00161 ARQ::CreateACK( const wns::ldk::CompoundPtr& compound) 00162 { 00163 wns::ldk::CommandPool* AckCommand = friends.manager->createReply(compound->getCommandPool(), ACK); 00164 wns::ldk::CompoundPtr AckCompound(new wns::ldk::Compound(AckCommand)); 00165 00166 wns::simulator::Time fxDur = friends.manager->getFrameExchangeDuration(compound->getCommandPool()) - SIFS - AckDuration; 00167 if (fxDur < SIFS) 00168 { 00169 fxDur = 0; 00170 } 00171 friends.manager->setFrameExchangeDuration(AckCommand, fxDur); 00172 MESSAGE_SINGLE(NORMAL, logger, "ARQ: FrameExchangeDuration set to : " << fxDur); 00173 00174 ARQCommand* ac = activateCommand(AckCompound->getCommandPool()); 00175 ac->peer.Frametype = ARQCommand::Ack; 00176 ac->peer.ACKpolicy = ARQCommand::ImmACK; 00177 00178 wns::events::scheduler::Callable call = boost::bind(&ARQ::TransmitAck, this, AckCompound); 00179 scheduler->scheduleDelay(call, SIFS); 00180 } 00181 00182 00183 void 00184 ARQ::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const 00185 { 00186 getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, sduSize,this); 00187 } 00188 void 00189 ARQ::TransmitAck(const wns::ldk::CompoundPtr& compound) 00190 { 00191 MESSAGE_SINGLE(NORMAL, logger, "ARQ: send Ack after SIFS"); 00192 doSendData(compound); 00193 } 00194
1.5.5