![]() |
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 <WNS/ldk/sar/reassembly/ReorderingWindow.hpp> 00029 00030 #include <boost/lambda/lambda.hpp> 00031 #include <boost/lambda/bind.hpp> 00032 #include <boost/bind.hpp> 00033 00034 #include <math.h> 00035 00036 boost::lambda::placeholder1_type Arg1; 00037 boost::lambda::placeholder2_type Arg2; 00038 00039 using namespace wns::ldk::sar::reassembly; 00040 00041 ReorderingWindow::Segment::Segment(long sn, wns::ldk::CompoundPtr compound): 00042 sn_(sn), 00043 compound_(compound) 00044 { 00045 } 00046 00047 long 00048 ReorderingWindow::Segment::sn() const 00049 { 00050 return sn_; 00051 } 00052 00053 wns::ldk::CompoundPtr 00054 ReorderingWindow::Segment::compound() const 00055 { 00056 return compound_; 00057 } 00058 00059 ReorderingWindow::ReorderingWindow(wns::pyconfig::View config): 00060 snFieldLength_(config.get<int>("snFieldLength")), 00061 windowSize_(pow(2, config.get<int>("snFieldLength") - 1)), 00062 tReordering_(config.get<double>("tReordering")), 00063 vrUH_(0), 00064 vrUR_(0), 00065 vrUX_(0), 00066 reorderingTimer_(), 00067 logger_(config.get("logger")) 00068 { 00069 MESSAGE_BEGIN(NORMAL, logger_, m, "ReorderingWindow (snFieldLength=" << snFieldLength_); 00070 m << ", windowSize_ = " << windowSize_ << ")"; 00071 MESSAGE_END(); 00072 assure(windowSize_ > 0, "Missconfigured windowSize (possible overflow). Try decreasing snFieldLength"); 00073 assure(tReordering_ > 0, "tReordering must be positive"); 00074 } 00075 00076 ReorderingWindow::ReorderingWindow(const ReorderingWindow& other): 00077 snFieldLength_(other.snFieldLength_), 00078 windowSize_(other.windowSize_), 00079 tReordering_(other.tReordering_), 00080 vrUH_(other.vrUH_), 00081 vrUR_(other.vrUR_), 00082 vrUX_(other.vrUX_), 00083 reorderingTimer_(other.reorderingTimer_), 00084 logger_(other.logger_) 00085 { 00086 } 00087 00088 boost::signals::connection 00089 ReorderingWindow::connectToReassemblySignal(const reassemblySlotType& slot) 00090 { 00091 return reassemble_.connect(slot); 00092 } 00093 00094 boost::signals::connection 00095 ReorderingWindow::connectToDiscardSignal(const discardSlotType& slot) 00096 { 00097 return discard_.connect(slot); 00098 } 00099 00100 void 00101 ReorderingWindow::onSegment(long sn, wns::ldk::CompoundPtr compound) 00102 { 00103 Segment s(sn, compound); 00104 00105 MESSAGE_BEGIN(NORMAL, logger_, m, "onSegment: "); 00106 m << "New segment " << s.sn() << " (vrUH_ = " << vrUH_ << " vrUR_=" << vrUR_ << " vrUX_ = " << vrUX_ << ")"; 00107 MESSAGE_END(); 00108 00109 // 3GPP TS 36.322 Section 5.1.2.2.2 (V8.5.0 2009-03) 00110 // Actions when an UMD PDU is received from lower layer 00111 if (isExpired(s) || (isConsideredForReordering(s) && isDuplicate(s))) 00112 { 00113 discard(s); 00114 return; 00115 } 00116 00117 // place the received UMD PDU in the reception buffer 00118 insert(s); 00119 00120 // 3GPP TS 36.322 Section 5.1.2.2.3 (V8.5.0 2009-03) 00121 // Actions when an UMD PDU is placed in the reception buffer 00122 if (!isWithinReorderingWindow(s)) 00123 { 00124 vrUH_ = s.sn() + 1; 00125 MESSAGE_SINGLE(VERBOSE, logger_, "onSegment: Updated vrUH_=" << vrUH_); 00126 updateReassemblyBuffer(vrUH_ - windowSize_); 00127 00128 // If VR(UR) falls outside of the reordering window 00129 if (!isWithinReorderingWindow(Segment(vrUR_, wns::ldk::CompoundPtr()))) 00130 { 00131 vrUR_ = vrUH_ - windowSize_; 00132 MESSAGE_SINGLE(VERBOSE, logger_, "onSegment: Updated vrUR_=" << vrUR_); 00133 } 00134 } 00135 00136 ContainerType::iterator it; 00137 { 00138 using namespace boost::lambda; 00139 it = find_if(reorderWindow_.begin(), reorderWindow_.end(), (bind(&Segment::sn, Arg1) == vrUR_)); 00140 } 00141 00142 if(it!=reorderWindow_.end()) 00143 { 00144 vrUR_ = nextMissingSegment(Segment(vrUR_, wns::ldk::CompoundPtr())).sn(); 00145 MESSAGE_SINGLE(VERBOSE, logger_, "onSegment: Updated vrUR_=" << vrUR_); 00146 00147 updateReassemblyBuffer(vrUR_); 00148 } 00149 00150 // t-Reordering Processing 00151 if (reorderingTimer_ != wns::events::scheduler::IEventPtr() && reorderingTimer_->isQueued()) 00152 { 00153 // t-Reordering is running 00154 if ( (vrUX_ <= vrUR_) || 00155 (!isWithinReorderingWindow(Segment(vrUX_, wns::ldk::CompoundPtr())) && 00156 vrUX_ != vrUH_ 00157 )) 00158 { 00159 MESSAGE_SINGLE(NORMAL, logger_, "onSegment: tReordering stopped"); 00160 reorderingTimer_->cancel(); 00161 reorderingTimer_ = wns::events::scheduler::IEventPtr(); 00162 } 00163 } 00164 00165 if (reorderingTimer_ == wns::events::scheduler::IEventPtr()) 00166 { 00167 // t-Reordering is not running 00168 if (vrUH_ > vrUR_) 00169 { 00170 reorderingTimer_ = wns::simulator::getEventScheduler()->scheduleDelay(boost::lambda::bind(&ReorderingWindow::onTReorderingExpired, this), tReordering_); 00171 vrUX_ = vrUH_; 00172 MESSAGE_SINGLE(NORMAL, logger_, "onSegment: tReordering started (vrUX = " << vrUX_ << ")"); 00173 } 00174 } 00175 MESSAGE_SINGLE(NORMAL, logger_, "onSegment: finished (vrUH_ = " << vrUH_ << " vrUR_=" << vrUR_ << " vrUX_ = " << vrUX_ << ")"); 00176 } // onSegment 00177 00178 void 00179 ReorderingWindow::onTReorderingExpired() 00180 { 00181 // 3GPP TS 36.322 Section 5.1.2.2.4 (V8.5.0 2009-03) 00182 00183 MESSAGE_SINGLE(NORMAL, logger_, "onTReorderingExpired: (vrUR = " << vrUR_ << " vrUX = " << vrUX_ << ")"); 00184 vrUR_ = nextMissingSegment(Segment(vrUX_ - 1, wns::ldk::CompoundPtr())).sn(); 00185 00186 updateReassemblyBuffer(vrUR_); 00187 00188 if (vrUH_ > vrUR_) 00189 { 00190 reorderingTimer_ = wns::simulator::getEventScheduler()->scheduleDelay(boost::lambda::bind(&ReorderingWindow::onTReorderingExpired, this), tReordering_); 00191 vrUX_ = vrUH_; 00192 MESSAGE_SINGLE(NORMAL, logger_, "onTReorderingExpired: tReordering started (vrUX = " << vrUX_ << ")"); 00193 } 00194 else 00195 { 00196 MESSAGE_SINGLE(VERBOSE, logger_, "onTReorderingExpired: Clearing reorderingTimer handle"); 00197 reorderingTimer_ = wns::events::scheduler::IEventPtr(); 00198 } 00199 00200 } 00201 00202 void 00203 ReorderingWindow::insert(Segment s) 00204 { 00205 MESSAGE_SINGLE(VERBOSE, logger_, "insert: New segment " << s.sn()); 00206 00207 using namespace boost::lambda; 00208 00209 ContainerType::iterator it; 00210 00211 // Find position to insert new segment. reorderWindow is sorted ascending by SN 00212 // See bosst:lambda documentation for bind and Arg1 00213 it = find_if(this->reorderWindow_.begin(), 00214 this->reorderWindow_.end(), 00215 (bind(&Segment::sn, Arg1) > s.sn())); 00216 00217 MESSAGE_SINGLE(VERBOSE, logger_, "insert: Inserting New segment " << s.sn()); 00218 this->reorderWindow_.insert(it, s); 00219 } 00220 00221 bool 00222 ReorderingWindow::isDuplicate(Segment s) 00223 { 00224 using namespace boost::lambda; 00225 00226 ContainerType::iterator it; 00227 00228 // Find segment. reorderWindow is sorted ascending by SN 00229 // See bosst:lambda documentation for bind and Arg1 00230 it = find_if(this->reorderWindow_.begin(), 00231 this->reorderWindow_.end(), 00232 (bind(&Segment::sn, Arg1) == s.sn())); 00233 00234 if (it!=this->reorderWindow_.end()) 00235 { 00236 MESSAGE_SINGLE(VERBOSE, logger_, "isDuplicate: Segment " << s.sn() << " is duplicate"); 00237 return true; 00238 } 00239 00240 MESSAGE_SINGLE(VERBOSE, logger_, "isDuplicate: Segment " << s.sn() << " is not duplicate"); 00241 return false; 00242 } 00243 00244 bool 00245 ReorderingWindow::isExpired(Segment s) 00246 { 00247 00248 bool expired = (s.sn() >= (this->vrUH_ - this->windowSize_)) && 00249 (s.sn() < this->vrUR_); 00250 00251 if (expired) 00252 { 00253 MESSAGE_SINGLE(VERBOSE, logger_, "isExpired: Segment " << s.sn() << " is expired (vrUH_ = " << vrUH_ << " vrUR_ = " << vrUR_ << ")"); 00254 return true; 00255 } 00256 00257 MESSAGE_SINGLE(VERBOSE, logger_, "isExpired: Segment " << s.sn() << " is not expired"); 00258 return false; 00259 } 00260 00261 bool 00262 ReorderingWindow::isConsideredForReordering(Segment s) 00263 { 00264 bool aboveEarliestEdge = s.sn() > this->vrUR_; 00265 bool belowUpperEdge = s.sn() < this->vrUH_; 00266 00267 bool considered = aboveEarliestEdge && belowUpperEdge; 00268 00269 if (considered) 00270 { 00271 MESSAGE_SINGLE(VERBOSE, logger_, "isConsideredForReordering: Segment " << s.sn() << " is considered"); 00272 return true; 00273 } 00274 00275 MESSAGE_SINGLE(VERBOSE, logger_, "isConsideredForReordering: Segment " << s.sn() << " is not considered"); 00276 return false; 00277 } 00278 00279 bool 00280 ReorderingWindow::isWithinReorderingWindow(Segment s) 00281 { 00282 bool aboveLowerEdge = s.sn() >= (vrUH_ - windowSize_); 00283 bool belowUpperEdge = s.sn() < vrUH_; 00284 00285 bool inWindow = aboveLowerEdge && belowUpperEdge; 00286 00287 if (inWindow) 00288 { 00289 MESSAGE_SINGLE(VERBOSE, logger_, "isWithinReorderingWindow: Segment " << s.sn() << " is in window"); 00290 return true; 00291 } 00292 00293 MESSAGE_SINGLE(VERBOSE, logger_, "isWithinReorderingWindow: Segment " << s.sn() << " is not in window"); 00294 return false; 00295 } 00296 00297 void 00298 ReorderingWindow::discard(Segment s) 00299 { 00300 MESSAGE_SINGLE(NORMAL, logger_, "Discarding segment " << s.sn()); 00301 00302 // Send discard signal 00303 discard_(s.sn(), s.compound()); 00304 } 00305 00306 ReorderingWindow::Segment 00307 ReorderingWindow::nextMissingSegment(Segment s) 00308 { 00309 long ii=(s.sn() + 1); 00310 while(true) 00311 { 00312 if (!isDuplicate(Segment(ii, wns::ldk::CompoundPtr()))) 00313 { 00314 return Segment(ii, wns::ldk::CompoundPtr()); 00315 } 00316 ii += 1; 00317 } 00318 } 00319 00320 void 00321 ReorderingWindow::updateReassemblyBuffer(long lower) 00322 { 00323 { 00324 using namespace boost::lambda; 00325 sort(reorderWindow_.begin(), reorderWindow_.end(), 00326 (bind(&Segment::sn, Arg1) < bind(&Segment::sn, Arg2))); 00327 } 00328 00329 ContainerType::iterator it; 00330 for(it = reorderWindow_.begin(); it != reorderWindow_.end(); /* noop */) 00331 { 00332 if (it->sn() < lower) 00333 { 00334 MESSAGE_SINGLE(VERBOSE, logger_, "Moving segment " << it->sn() << " to reassembly Buffer"); 00335 00336 // Fire reassemble signal 00337 reassemble_(it->sn(), it->compound()); 00338 00339 // Now remove from list and adjust iterator 00340 it = reorderWindow_.erase(it); 00341 } 00342 else 00343 { 00344 ++it; 00345 } 00346 } 00347 }
1.5.5