User Manual, Developers Guide and API Documentation

ReorderingWindow.cpp

Go to the documentation of this file.
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 }

Generated on Fri May 25 03:31:46 2012 for openWNS by  doxygen 1.5.5