![]() |
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-2009 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * email: info@openwns.org 00009 * www: http://www.openwns.org 00010 * _____________________________________________________________________________ 00011 * 00012 * openWNS is free software; you can redistribute it and/or modify it under the 00013 * terms of the GNU Lesser General Public License version 2 as published by the 00014 * Free Software Foundation; 00015 * 00016 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00017 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00018 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00019 * details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 * 00024 ******************************************************************************/ 00025 00026 #include <WIMAC/scheduler/ULCallback.hpp> 00027 #include <WNS/ldk/Layer.hpp> 00028 #include <WNS/scheduler/RegistryProxyInterface.hpp> 00029 00030 #include <WIMAC/Component.hpp> 00031 #include <WIMAC/Logger.hpp> 00032 #include <WIMAC/PhyAccessFunc.hpp> 00033 #include <WIMAC/PhyUserCommand.hpp> 00034 #include <WIMAC/PhyUser.hpp> 00035 #include <WIMAC/Utilities.hpp> 00036 #include <WIMAC/scheduler/RegistryProxyWiMAC.hpp> 00037 #include <boost/bind.hpp> 00038 00039 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00040 wimac::scheduler::ULCallback, 00041 wimac::scheduler::Callback, 00042 "wimac.scheduler.ULCallback", 00043 wns::ldk::FUNConfigCreator ); 00044 00045 using namespace wimac::scheduler; 00046 00047 ULCallback::ULCallback(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) : 00048 Callback(fun, config), 00049 fun_(fun), 00050 slotLength_(config.get<wns::simulator::Time>("slotLength")), 00051 tbCounter_(0), 00052 beamforming(config.get<bool>("beamforming")) 00053 {} 00054 00055 void 00056 ULCallback::callBack(wns::scheduler::SchedulingMapPtr schedulingMap) 00057 { 00058 wimac::scheduler::RegistryProxyWiMAC* registry = dynamic_cast<wimac::scheduler::RegistryProxyWiMAC*>(colleagues.registry); 00059 bool isMaster = registry->getStationType(registry->getMyUserID()) == wns::service::dll::StationTypes::AP(); 00060 if (isMaster && !beamforming) 00061 return; 00062 00063 tbCounter_++; 00064 LOG_INFO(fun_->getLayer()->getName(), " ULCallback::callBack(): "); 00065 lastScheduling_ = wns::simulator::getEventScheduler()->getTime(); 00066 00067 //send only own bursts? 00068 for(wns::scheduler::SubChannelVector::iterator iterSubChannel = 00069 schedulingMap->subChannels.begin(); 00070 iterSubChannel != schedulingMap->subChannels.end(); 00071 ++iterSubChannel) 00072 { 00073 wns::scheduler::SchedulingSubChannel& subChannel = *iterSubChannel; 00074 for(wns::scheduler::SchedulingTimeSlotPtrVector::iterator iterTimeSlot = 00075 subChannel.temporalResources.begin(); 00076 iterTimeSlot != subChannel.temporalResources.end(); 00077 ++iterTimeSlot) 00078 { 00079 wns::scheduler::SchedulingTimeSlotPtr timeSlotPtr = *iterTimeSlot; 00080 for(wns::scheduler::PhysicalResourceBlockVector::iterator iterPRB = 00081 timeSlotPtr->physicalResources.begin(); 00082 iterPRB != timeSlotPtr->physicalResources.end(); 00083 ++iterPRB) 00084 { 00085 if ( iterPRB->hasScheduledCompounds() ) 00086 { 00087 wns::scheduler::ScheduledCompoundsList::const_iterator it; 00088 00089 for(it = iterPRB->scheduledCompoundsBegin(); 00090 it != iterPRB->scheduledCompoundsEnd(); 00091 it++) 00092 { // for every compound in subchannel: 00093 /* Put estimated CQI in*/ 00094 it->estimatedCQI = iterPRB->getEstimatedCQI(); 00095 processPacket(*it, timeSlotPtr); 00096 } // for (all scheduledCompounds) 00097 iterPRB->clearScheduledCompounds(); 00098 } // if there were compounds in this resource 00099 } // forall beams 00100 } // end for ( timeSlots ) 00101 } // forall subChannels 00102 } 00103 00104 //ULSlave processPacket, setting omnidirectional transmit phy access functor 00105 void 00106 ULCallback::processPacket(const wns::scheduler::SchedulingCompound & compound, 00107 wns::scheduler::SchedulingTimeSlotPtr& timeSlotPtr) 00108 { 00109 simTimeType startTime = compound.startTime; 00110 simTimeType endTime = compound.endTime; 00111 wns::scheduler::UserID user = compound.userID; 00112 int userID = user.getNodeID(); 00113 wns::service::phy::ofdma::PatternPtr pattern = compound.pattern; 00114 00115 int fSlot = compound.subChannel; 00116 int timeSlot = compound.timeSlot; 00117 int beam = compound.spatialLayer; //beam; 00118 wns::Power txPower = compound.txPower; 00119 wns::service::phy::phymode::PhyModeInterfacePtr phyModePtr = compound.phyModePtr; 00120 00121 00122 simTimeType timeSlotOffset = timeSlot * slotLength_; 00123 startTime += timeSlotOffset; 00124 endTime += timeSlotOffset - Utilities::getComputationalAccuracyFactor(); 00125 wns::scheduler::ChannelQualityOnOneSubChannel estimatedCQI = compound.estimatedCQI; 00126 00127 double rate = phyModePtr->getDataRate(); 00128 wns::ldk::CompoundPtr pdu = compound.compoundPtr; 00129 simTimeType pduDuration = pdu->getLengthInBits() / rate; 00130 // TODO 00131 assure(pdu != wns::ldk::CompoundPtr(), "Invalid empty PDU"); 00132 //assure(beam < maxBeams, "Too many beams"); 00133 assure(endTime > startTime, "Scheduled PDU must end after it starts"); 00134 //assure(endTime <= this->getDuration(), "PDU overun the maximum duration of the frame phase!"); 00135 //assure(fSlot < freqChannels, "Invalid frequency channel"); 00136 00137 #ifndef WNS_NO_LOGGING 00138 std::stringstream m; 00139 m << ": direction: UL \n" 00140 << " PDU scheduled for user (destination): " << colleagues.registry->getNameForUser(user) << "\n" 00141 << " Frequency Slot: " << fSlot << "\n" 00142 << " Time Slot: " << timeSlot << " slotLength: "<<slotLength_<< "\n" 00143 << " StartTime: " << startTime << "\n" 00144 << " EndTime: " << endTime<< "\n" 00145 << " Beamforming: " << beamforming << "\n" 00146 << " Beam: " << beam << "\n" 00147 << " Tx Power: " << txPower; 00148 LOG_INFO(fun_->getLayer()->getName(), m.str()); 00149 #endif 00150 00151 PhyAccessFunc* func = 0; 00152 00153 //in beamforming case ((currently) = uplink master possible) the receive pattern need to be set 00154 if(compound.pattern != wns::service::phy::ofdma::PatternPtr()) 00155 { 00156 assure(beamforming," set pattern without beamforming"); 00157 LOG_INFO(fun_->getLayer()->getName(), " ULCallback::processPacket() create PatternSetterPhyAccessFunc " ); 00158 PatternSetterPhyAccessFunc* patternFunc = 00159 new PatternSetterPhyAccessFunc; 00160 //patternFunc->destination_ is the mobile station in uplink master, as required for sdma reception. Specific receive pattern can only be distinguished by the source id. 00161 patternFunc->destination_ = user.getNode(); 00162 patternFunc->transmissionStart_= startTime; 00163 patternFunc->transmissionStop_= endTime; 00164 patternFunc->pattern_ = pattern; 00165 func = patternFunc; 00166 } 00167 else if(user.isValid()) 00168 { 00169 LOG_INFO(fun_->getLayer()->getName(), " ULCallback::processPacket() create OmniUnicastPhyAccessFunc"); 00170 OmniUnicastPhyAccessFunc* omniUnicastFunc = new OmniUnicastPhyAccessFunc; 00171 omniUnicastFunc->destination_ = user.getNode(); 00172 omniUnicastFunc->transmissionStart_ = startTime; 00173 omniUnicastFunc->transmissionStop_ = endTime; 00174 omniUnicastFunc->subBand_ = fSlot; 00175 omniUnicastFunc->beam_ = beam; 00176 omniUnicastFunc->timeSlot_ = timeSlot; 00177 omniUnicastFunc->requestedTxPower_ = txPower; 00178 func = omniUnicastFunc; 00179 }else 00180 { 00181 throw wns::Exception( "destination address missing, UT is not supposed to broadcast" ); 00182 } 00183 // set PhyUser command 00184 wimac::PhyUserCommand* phyCommand = dynamic_cast<wimac::PhyUserCommand*>( 00185 fun_->getProxy()->activateCommand( pdu->getCommandPool(), friends_.phyUser ) ); 00186 phyCommand->local.pAFunc_.reset( func ); 00187 phyCommand->local.pAFunc_->phyMode_ = phyModePtr; 00188 phyCommand->peer.destination_ = user.getNode(); 00189 wimac::Component* wimacComponent = dynamic_cast<wimac::Component*>(fun_->getLayer()); 00190 phyCommand->peer.cellID_ = wimacComponent->getCellID(); 00191 phyCommand->peer.source_ = wimacComponent->getNode(); 00192 phyCommand->peer.phyModePtr = phyModePtr; 00193 phyCommand->peer.measureInterference_ = true; // measureInterference; 00194 phyCommand->peer.estimatedCQI = estimatedCQI; 00195 phyCommand->magic.sourceComponent_ = wimacComponent; 00196 colleagues.harq->storeSchedulingTimeSlot(tbCounter_, timeSlotPtr); 00197 00198 phyCommand->magic.schedulingTimeSlot = wns::scheduler::SchedulingTimeSlotPtr( 00199 new wns::scheduler::SchedulingTimeSlot(*timeSlotPtr)); 00200 00201 scheduledPDUs.push(pdu); 00202 } 00203 00204 void ULCallback::deliverNow(wns::ldk::Connector* connector) 00205 { 00206 LOG_INFO(fun_->getLayer()->getName(), " ULCallback::deliverNow() "); 00207 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00208 00209 while (!scheduledPDUs.empty()) 00210 { 00211 wns::ldk::CompoundPtr compound = 00212 scheduledPDUs.front(); 00213 PhyUserCommand* phyUserCommand = 00214 friends_.phyUser->getCommand(compound->getCommandPool()); 00215 00216 PhyAccessFunc* func = 00217 dynamic_cast<PhyAccessFunc*>(phyUserCommand->local.pAFunc_.get()); 00218 00219 func->transmissionStart_ += now; 00220 func->transmissionStop_ += now; 00221 wimac::scheduler::RegistryProxyWiMAC* registry = dynamic_cast<wimac::scheduler::RegistryProxyWiMAC*>(colleagues.registry); 00222 bool isSlave = registry->getStationType(registry->getMyUserID()) == wns::service::dll::StationTypes::UT(); 00223 if(isSlave) 00224 { 00225 frameOffsetDelayProbe_->put(compound, func->transmissionStart_ - lastScheduling_); 00226 transmissionDelayProbe_->put(compound, func->transmissionStop_ - func->transmissionStart_); 00227 } 00228 if(connector->hasAcceptor(scheduledPDUs.front())) 00229 { 00230 connector->getAcceptor(scheduledPDUs.front())->sendData(scheduledPDUs.front()); 00231 scheduledPDUs.pop(); 00232 } 00233 else 00234 { 00235 throw wns::Exception( "Lower FU is not accepting scheduled PDU but is supposed to do so" ); 00236 } 00237 } 00238 }
1.5.5