am.cc

00001 /*
00002  * Copyright (c) 2003 Ericsson Telecommunicatie B.V.
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *     notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *     notice, this list of conditions and the following disclaimer in the
00012  *     documentation and/or other materials provided with the
00013  *     distribution.
00014  * 3. Neither the name of Ericsson Telecommunicatie B.V. may be used
00015  *     to endorse or promote products derived from this software without
00016  *     specific prior written permission.
00017  * 
00018  * 
00019  * THIS SOFTWARE IS PROVIDED BY ERICSSON TELECOMMUNICATIE B.V. AND
00020  * CONTRIBUTORS "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
00021  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00022  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00023  * IN NO EVENT SHALL ERICSSON TELECOMMUNICATIE B.V., THE AUTHOR OR HIS
00024  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00028  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00030  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  * 
00032  * 
00033  * Contact for feedback on EURANE: eurane@ti-wmc.nl
00034  * EURANE = Enhanced UMTS Radio Access Network Extensions
00035  * website: http://www.ti-wmc.nl/eurane/
00036  */
00037 
00038 /*
00039  * $Id: am.cc,v 1.41 2004/07/01 09:28:30 neill Exp $
00040  */
00041 
00042 
00043 #include "am.h"
00044 #include "mac.h"
00045 #include "flags.h"
00046 #include "random.h"
00047 #include "address.h"
00048 #include <iostream>
00049 #include <exception>
00050 
00051 #ifndef NOW
00052 #define NOW (Scheduler::instance().clock())
00053 #endif
00054 
00055 //int hdr_rlc::offset_;
00056 
00057 // *INDENT-OFF*
00058 static class AMRlcClass:public TclClass {
00059  public:
00060    AMRlcClass():TclClass("UMTS/RLC/AM") {
00061    }
00062    TclObject *create(int, const char *const *) {
00063       return (new AM);
00064    }
00065 } class_am;
00066 // *INDENT-ON*
00067 
00068 AM::AM():RLC(), sent_TTI_PDUs_(0), TTI_PDUs_(0), set_poll_(0), send_ack_(0),
00069          send_status_(0), SDU_size_(-1), dupacks_(0), rtt_seq_(-1),
00070          rtt_active_(0), prohibited_(0), FSN_(-1),  b_bal_(0), maxseq_(-1),
00071          t_seqno_(0), highest_ack_(-1), maxseen_(-1), next_(0), tx_PDUs_before_poll(0), 
00072          TTI_time_(-1), rtx_timer_(this, RLC_TIMER_RTX),
00073          poll_timer_((RLC *) this, RLC_TIMER_POLL), delsnd_timer_(this, RLC_TIMER_DELSND), 
00074          stprob_timer_(this, RLC_TIMER_STPROB), tti_timer_(this, RLC_TIMER_TTI),
00075          mrwack_timer_(this, RLC_TIMER_MRWACK), 
00076          address_(0), d_address_(0), MRW_delta(0),
00077          err_PDUs_(0), rx_PDUs_(0), rx_SDUs_(0), tot_PDUs_(0), ack_PDUs_(0), drop_PDUs_(0), drop_SDUs_(0)
00078 {
00079    bind("win_", &win_);
00080    bind_bw("maxRBSize_", &maxRBSize_);
00081    bind("ack_mode_", &ack_mode_);
00082    bind("poll_PDU_", &poll_PDU_);
00083    bind_time("rtx_timeout_", &rtx_timeout_);
00084    bind_time("poll_timeout_", &poll_timeout_);
00085    bind_time("overhead_", &overhead_);
00086    bind_time("stprob_timeout_", &stprob_timeout_);
00087    bind("noFastRetrans_", &noFastRetrans_);
00088    bind("numdupacks_", &numdupacks_);
00089    bind("payload_", &payload_);
00090    bind_bw("bandwidth_", &bandwidth_);
00091    bind_time("TTI_", &TTI_);
00092    bind("TTI_PDUs_", &TTI_PDUs_);
00093    bind("length_indicator_", &length_indicator_);
00094    bind("ack_pdu_header_", &ack_pdu_header_);
00095    bind("status_pdu_header_", &status_pdu_header_);
00096    bind("min_concat_data_", &min_concat_data_);
00097    bind_time("max_status_delay_", &max_status_delay_);
00098    bind_time("max_ack_delay_", &max_ack_delay_);
00099    bind("maxdat_", &maxdat_);
00100    bind("macDA_", &macDA_);
00101    //bind("debug_", &debug_);
00102    bind("tot_PDUs_",&tot_PDUs_);
00103    bind("err_PDUs_",&err_PDUs_);
00104    bind("ack_PDUs_",&ack_PDUs_);
00105    bind("ack_SDUs_",&ack_SDUs_);
00106    bind("drop_PDUs_",&drop_PDUs_); 
00107    bind("drop_SDUs_",&drop_SDUs_);
00108    bind("sender_debug_",&sender_debug_);
00109    bind("receiver_debug_",&receiver_debug_);
00110 
00111    memset(seen_, 0, sizeof(seen_));
00112    //   memset(ack_, 0, sizeof(seen_));
00113    seqno_ = -1;
00114 
00115    tti_timer_.sched(TTI_ - 0.001);
00116 
00117    set_poll_timer();
00118 
00119 //    for (int i=0; i<MWS; i++)
00120 //      {
00121 //        bitmap_[i]=0;
00122 //        seen_[i]=0;
00123 //        eopno_[i]=0;
00124 //        txcount_[i]=0;
00125 //      }
00126 
00127 }
00128 
00129 int AM::command(int argc, const char *const *argv)
00130 {
00131    if (argc == 2) {
00132       Tcl & tcl = Tcl::instance();
00133       if (strcmp(argv[1], "TTI") == 0) {
00134          tcl.resultf("%f", TTI_);
00135          return TCL_OK;
00136       } else if (strcmp(argv[1], "BW") == 0) {
00137          tcl.resultf("%f", bandwidth_);
00138          return TCL_OK;
00139       } else if (strcmp(argv[1], "start_TTI") == 0) {
00140          tti_timer_.sched(TTI_ - 0.001);
00141          TTI_PDUs_ = (int) (bandwidth_ * TTI_) / (payload_ * 8);
00142          return TCL_OK;
00143       }
00144    } else if (argc == 3) {
00145       if (strcmp(argv[1], "macDA") == 0) {
00146          macDA_ = atoi(argv[2]);
00147          return (TCL_OK);
00148       } else if (strcmp(argv[1], "addr") == 0) {
00149          address_ = Address::instance().str2addr(argv[2]);
00150          return (TCL_OK);
00151       } else if (strcmp(argv[1], "daddr") == 0) {
00152          d_address_ = Address::instance().str2addr(argv[2]);
00153          return (TCL_OK);
00154       }
00155    }
00156    return RLC::command(argc, argv);
00157 }
00158 
00159 void AM::recv(Packet * p, Handler * h)
00160 {
00161   hdr_cmn    *ch = HDR_CMN(p);
00162 
00163   /* If direction = UP, then pass it up the stack
00164    * Otherwise, set direction to DOWN and pass it down the stack */
00165 
00166   if (ch->direction() == hdr_cmn::UP) {
00167 
00168     if (ch->ptype() != PT_AM){
00169       drop(p);               /* Unknown type */
00170       return;
00171     }
00172 
00173     hdr_rlc    *llh = hdr_rlc::access(p);
00174      
00175     if (llh->dst() != address_ || ch->error() > 0) {
00176       assert(0);
00177       Packet::free(p);
00178       /* PDUs with errors, or those meant for another UE */
00179       return;                /* should have been dropped before this. */
00180     }
00181 
00182 
00183     flowID_ = hdr_ip::access(p)->flowid();
00184 
00185     /* This is better performed before all DATA ACKs/NACKs */
00186     if (llh->lltype() & RLC_MRWACK) {
00187 
00188       MRW_delta = std::max((FSN_ - llh->SN_MRW_ACK), 0);
00189 
00190       if (sender_debug_)
00191         {
00192           cerr << NOW 
00193                << " FSN_=" << FSN_
00194                << " llh->SN_MRW_ACK=" << llh->SN_MRW_ACK
00195                << " MRW_delta="  << MRW_delta
00196                << " t_seqno_=" << t_seqno_
00197                << " b_bal_=" << b_bal_
00198                << endl;
00199 
00200         }
00201       
00202       //assert(MRW_delta >= 0);
00203 
00204       if (MRW_delta == 0) 
00205         {
00206           mrwack_timer_.cancel();       
00207           if(sender_debug_)  cerr << "Receiver window moved (" << llh->SN_MRW_ACK << ")" << endl;      
00208         } 
00209       else 
00210         {
00211           if(sender_debug_)  cerr << "Receiver window moved (" << llh->SN_MRW_ACK
00212                                   << ") but not enough (" << FSN_ << ")" << endl;       
00213         }
00214 
00215     }
00216 
00217     if (llh->lltype() & RLC_ACK) {
00218       if (llh->a_seqno() > highest_ack_) {
00219         newack(p);
00220       } else if (llh->a_seqno() == highest_ack_) {
00221         if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
00222           reset_rtx_timer();
00223         }
00224       }
00225     }
00226 
00227     if (llh->lltype() & RLC_BITMAP) {
00228       if (debug_) cerr << NOW << " received BITMAP SUFI" << endl;
00229       newback(p);
00230     }    
00231 
00232     
00233     if (llh->lltype() & RLC_MRW) {
00234       if (next_ < llh->SN_MRW)
00235         {
00236           if (receiver_debug_) 
00237             cerr << NOW << " Moving Receiver Window from "
00238                  << next_ << " to " << llh->SN_MRW << endl;
00239 
00240           next_ =  llh->SN_MRW;
00241           sduB_.dropTill(next_-1);
00242         }
00243       else 
00244         {
00245           if (receiver_debug_) 
00246             cerr << NOW << " NOT moving Receiver Window to " << llh->SN_MRW 
00247                  << " since current RW is " << next_ << endl;
00248         }
00249       send_status_ |= SEND_STATUS_MRWACK;
00250     }    
00251 
00252     /* Should be the last check since after this packet will
00253        eventually have been freed */
00254     if (llh->lltype() & RLC_DATA) 
00255       {
00256         if (debug_>2 ) cerr << NOW << "received data" << endl;
00257 
00258         if ((receiver_debug_)&&(llh->seqno() >= next_ + win_))
00259           {
00260             cerr << NOW << " AM::recv()" 
00261                  << " llh->seqno=" <<  llh->seqno()
00262                  << " next_=" << next_
00263                  << " win_=" << win_ 
00264                  << endl;
00265           }
00266         
00267         //assert(llh->seqno() <= next_ + win_);
00268            
00269         /* Figure out if any SDUs can be handed up. */
00270         int numSDU = update(llh->seqno(), llh->eopno());
00271 
00272         ack(p);
00273 
00274         // if numSDU < 0 then PDU is duplicate
00275         if (llh->seqno() == llh->eopno() && numSDU >= 0)
00276           {
00277             sduB_.orderedEnque(p);
00278           } 
00279         else 
00280           {
00281             Packet::free(p);
00282           }
00283         /* "make" and send up the following SDUs */
00284         if (numSDU > 0) {
00285           makeSDU(numSDU);
00286         }
00287       
00288       } 
00289     else 
00290       {
00291         /* non-data (STATUS) PDU, which now must be freed. Furthermore
00292          * it should not be acked, since in this implementation STATUS
00293          * PDUs don't have a SN 
00294          */
00295           Packet::free(p);
00296       }
00297 
00298 
00299   } else {    
00300     ch->direction() = hdr_cmn::DOWN;
00301     sendDown(p);
00302   }
00303 
00304 }
00305 
00306 bool AM::chk_size(Packet * p)
00307 {
00308    hdr_rlc    *llh = hdr_rlc::access(p);
00309 
00310 
00311    int size = 0;
00312 
00313    size += llh->lengthInd_;
00314    size += llh->payload_[0];
00315    size += llh->payload_[1];
00316    size += llh->payload_[2];
00317    size += llh->padding_;
00318 
00319    if (size != payload_)
00320      std::cerr << "AM::chk_size(p)  size=" << size
00321                << "payload_=" << payload_ << std::endl;
00322 
00323    return size == payload_;
00324 //    if (llh->lengthInd_ == 0) {
00325 //       size = llh->payload_[0];
00326 //    } else {
00327 //       for (int i = 0; i < llh->lengthInd_; i++) {
00328 //          size = size + ((length_indicator_ + 1) / 8) + llh->payload_[i];
00329 //       }
00330 //    }
00331 //    if ((size + llh->padding_) == payload_) {
00332 //       return true;
00333 //    } else {
00334 //       return false;
00335 //    }
00336 }
00337 
00338 
00339 
00340 void AM::sendDown(Packet * p)
00341 {
00342    if ((rcvB_.size() + hdr_cmn::access(p)->size()) <= maxRBSize_) {
00343       rcvB_.enque(p);
00344    } else {
00345       /* No space in recv buffer for this SDU */
00346      //     if (debug_) 
00347        cerr << "AM::sendDown(p) queue full, packet dropped" << endl;
00348       drop(p);
00349    }
00350 
00351    //   if (debug_) cerr << "Packet enqueued for transmission" << endl;
00352 }
00353 
00354 
00355 
00356 Packet     *AM::makePDU(int PB_bytes)
00357 {
00358   hdr_cmn    *ch;
00359   hdr_ip     *iph;
00360   hdr_tcp    *tcph;
00361   hdr_rlc    *llh;
00362   char       *mh;
00363 
00364 
00365   int available = payload_;
00366   int concat_data = 0;
00367   int end_PDU = 0;
00368   int padding = 0;
00369   int force_length_indicator = 0;
00370 
00371   Packet     *c;
00372 
00373   // WARNING: check that this packet is either enqueued in rtxB or
00374   // that it is freed, otherwise you get a memory leak
00375   Packet     *p = rcvB_.dequeCopy();
00376 
00377 
00378   if (PB_bytes != 0) 
00379     {
00380       available = payload_ - ((length_indicator_ + 1) / 8) - PB_bytes;
00381       if (hdr_cmn::access(p)->size() <= available) 
00382         {
00383           end_PDU = 1;
00384           concat_data = available - hdr_cmn::access(p)->size()
00385             - ((length_indicator_ + 1) / 8);
00386           padding = available - hdr_cmn::access(p)->size();
00387           /* This amount of padding IF we dont concat. */
00388         }
00389     } 
00390   else if (hdr_cmn::access(p)->size() < available) 
00391     {
00392       if (hdr_cmn::access(p)->size() <=
00393           available - ((length_indicator_ + 1) / 8)) 
00394         {
00395           end_PDU = 1;
00396           concat_data = available - hdr_cmn::access(p)->size()
00397             - (2 * ((length_indicator_ + 1) / 8));
00398           padding = available - hdr_cmn::access(p)->size()
00399             - ((length_indicator_ + 1) / 8);
00400         }
00401       force_length_indicator = 1;
00402     } 
00403   else if (hdr_cmn::access(p)->size() == available) 
00404     {
00405       end_PDU = 1;
00406     }
00407   if (concat_data < min_concat_data_ || (rcvB_.size(2) <= concat_data)) 
00408     {
00409       concat_data = 0;
00410     } 
00411   else 
00412     {
00413       padding = 0;
00414     }
00415   if (end_PDU) 
00416     {
00417 
00418       // Delete this packet from rcvB
00419       // since all fragments have been created
00420       Packet     *temp = rcvB_.deque();
00421       Packet::free(temp);
00422 
00423       c = p;
00424       ch = HDR_CMN(c);
00425       llh = hdr_rlc::access(c);
00426 
00427       llh->lptype() = ch->ptype();
00428       llh->lerror_ = ch->error();
00429       llh->lts_ = ch->timestamp();
00430 
00431       if (SDU_size_ > 0) {
00432         llh->lsize_ = SDU_size_;
00433       } else {
00434         llh->lsize_ = ch->size();
00435       }
00436 
00437       SDU_size_ = -1;
00438 
00439       llh->lltype() = RLC_DATA;
00440       llh->seqno_ = ++seqno_;
00441       llh->eopno_ = llh->seqno_;
00442       llh->dst() = d_address_;
00443       llh->src() = address_;
00444       llh->lengthInd_ = 0;
00445 
00446       if (PB_bytes || concat_data || padding || force_length_indicator) {
00447         llh->lengthInd_++;
00448       }
00449 
00450       for (int i = 1; i < 3; i++) {
00451         llh->payload_[i] = 0;
00452       }
00453 
00454       llh->payload_[0] = hdr_cmn::access(c)->size();
00455 
00456       if (concat_data) {
00457         llh->lengthInd_++;
00458         llh->payload_[1] = concat_data;
00459 
00460         if (PB_bytes != 0) {
00461           llh->padding_ = PB_bytes;
00462         } else {
00463           llh->padding_ = 0;
00464         }
00465         SDU_size_ = rcvB_.red_size(concat_data);
00466       } else if (PB_bytes != 0) {
00467         llh->padding_ = PB_bytes + padding;
00468       } else {
00469         llh->padding_ = padding;
00470       }
00471       ch->ptype() = PT_AM;
00472       ch->error() = 0;
00473       ch->timestamp() = Scheduler::instance().clock();
00474       ch->size() = payload_;
00475 
00476       mh = (char *) c->access(hdr_mac::offset_);
00477       struct hdr_mac *dh = (struct hdr_mac *) mh;
00478 
00479       dh->macDA_ = macDA_;
00480       dh->macSA_ = -1;
00481       dh->hdr_type() = ETHERTYPE_RLC;
00482 
00483     } 
00484   else 
00485     {
00486       if (SDU_size_ < 0) {
00487         SDU_size_ = hdr_cmn::access(p)->size();
00488       }
00489       c = allocpkt(hdr_cmn::access(p)->uid());
00490       ch = HDR_CMN(c);
00491       iph = hdr_ip::access(c);
00492       tcph = hdr_tcp::access(c);
00493       llh = hdr_rlc::access(c);
00494       hdr_ip     *piph = hdr_ip::access(p);
00495       hdr_tcp    *ptcph = hdr_tcp::access(p);
00496       hdr_flags  *phf = hdr_flags::access(p);
00497 
00498       llh->lltype() = RLC_DATA;
00499       llh->seqno_ = ++seqno_;
00500       llh->eopno_ = -1;
00501       llh->dst() = d_address_;
00502       llh->src() = address_;
00503       llh->padding_ = 0;
00504       llh->lengthInd_ = 0;
00505 
00506       if (PB_bytes || force_length_indicator) {
00507         llh->lengthInd_++;
00508       }
00509 
00510       for (int i = 1; i < 3; i++) {
00511         llh->payload_[i] = 0;
00512       }
00513       if (force_length_indicator) {
00514         llh->payload_[0] = payload_ - ((length_indicator_ + 1) / 8);
00515       } else if (PB_bytes != 0) {
00516         llh->payload_[0] = payload_ - ((length_indicator_ + 1) / 8) - PB_bytes;
00517         llh->padding_ = PB_bytes;
00518       } else {
00519         llh->payload_[0] = payload_;
00520       }
00521 
00522       /* WILD HACK!!!
00523        * Fragmentation is implemented by reducing the size of the
00524        * packet under examination, while leaving it into the rcvB_
00525        * buffer. In this way next PDU will be created using the
00526        * remaining size... what a hack!
00527        */
00528       rcvB_.red_size(llh->payload_[0]);
00529 
00530       ch->ptype() = PT_AM;
00531       ch->size() = payload_;
00532 
00533       iph->flowid() = piph->flowid();
00534       iph->saddr() = piph->saddr();
00535       iph->sport() = piph->sport();
00536       iph->daddr() = piph->daddr();
00537       iph->dport() = piph->dport();
00538       iph->ttl() = piph->ttl();
00539 
00540       tcph->seqno() = ptcph->seqno();
00541 
00542       hdr_flags  *hf = hdr_flags::access(c);
00543 
00544       hf->ecn_ = phf->ecn_;
00545       hf->cong_action_ = phf->cong_action_;
00546       hf->ecn_to_echo_ = phf->ecn_to_echo_;
00547       hf->fs_ = phf->fs_;
00548       hf->ecn_capable_ = phf->ecn_capable_;
00549 
00550       mh = (char *) c->access(hdr_mac::offset_);
00551       struct hdr_mac *dh = (struct hdr_mac *) mh;
00552 
00553       dh->macDA_ = macDA_;
00554       dh->macSA_ = -1;
00555       dh->hdr_type() = ETHERTYPE_RLC;
00556 
00557       // packet 'c' was newly allocated and is the one which will be
00558       // enqueued in rxtB, so packet 'p' (which is a copy of the first packet
00559       // in rcvB) is not needed any more and must be freed otherwise
00560       // we get a memory leak!
00561       Packet::free(p);
00562     }
00563 
00564   assert(llh == hdr_rlc::access(c));
00565   assert(llh->seqno_ >= FSN_); 
00566   eopno_[(llh->seqno_) & MWM] = llh->eopno_;
00567    
00568   return c;
00569 }
00570 
00571 
00572 /* 
00573  * Return the most suitable position in the 
00574  */
00575 int AM::PB_S_PDU()
00576 {
00577    int position = 0;
00578 
00579    if ((payload_ - StatusPDUSize() - (2 * ((length_indicator_ + 1) / 8)))
00580        < min_concat_data_) {
00581       return 0;                 /* Status PDU is too large to piggy back with */
00582       /* enough data to meet minimum criteria. */
00583    }
00584    if (t_seqno_ > highest_ack_ + win_ - b_bal_ - MRW_delta) {
00585       return 0;                 /* Cant send Data PDUs because window is full. */
00586       /* Send status with padding immediately. */
00587    }
00588    
00589    //Neill: checking indexing
00590 
00591    for (int i = 1; i <= b_bal_; i++) {
00592    //for (int i = 0; i < b_bal_; i++) {
00593       Packet     *p = rxtB_.dequeCopy(bRxtSeq(i));
00594 
00595       if ((debug_ >1)&&(!p)) {
00596         cerr << "FSN_=" << FSN_ 
00597              << " bitmap_["<<length_<<"]:";
00598         for (int j=0; j<length_; j++)
00599           cerr << seen_[j];
00600         cerr<<endl;
00601         for (int j=0; j<i; j++) {
00602           cerr << "bRxtSeq(" << j <<")=" <<bRxtSeq(j)
00603                << " corresponding sn in rxtB_ queue: " ;
00604           if (Packet *q = rxtB_.dequeCopy(bRxtSeq(i))) 
00605             {
00606               cerr << hdr_rlc::access(q)->seqno() << " "
00607                    << hdr_rlc::access(q)->a_seqno()  
00608                    <<  endl;      
00609               Packet::free(q);
00610             }
00611           else 
00612             cerr << "NULL" << endl;
00613         }
00614         rxtB_.dump();
00615         
00616       }
00617 
00618       assert(p);
00619       if (S_Piggybackable(p)) {
00620         Packet::free(p);
00621         return ++position;
00622       }      
00623       position++;
00624       Packet::free(p);
00625    }
00626 
00627    if (rcvB_.size() != 0) {
00628       return ++position;
00629    }
00630    return 0;
00631 }
00632 
00633 
00634 int AM::PB_PA_PDU()
00635 {
00636    int position = 0;
00637 
00638    if (payload_ - AckPDUSize() - (2 * ((length_indicator_ + 1) / 8)) <
00639        min_concat_data_) {
00640       return 0;
00641    } else if (t_seqno_ > highest_ack_ + win_) {
00642       return 0;
00643    } else if (t_seqno_ <= maxseq_) {
00644       for (int i = t_seqno_; i <= maxseq_; i++) {
00645          Packet     *p = rxtB_.dequeCopy(i);
00646 
00647          if (PA_Piggybackable(p)) {
00648             Packet::free(p);
00649             return ++position;
00650          }
00651          position++;
00652          Packet::free(p);
00653       }
00654    }
00655 
00656    if (rcvB_.size() != 0) {
00657       return ++position;
00658    }
00659    return 0;
00660 }
00661 
00662 
00663 bool AM::PA_Piggybackable(Packet * p)
00664 {
00665    if (hdr_rlc::access(p)->padding()) {
00666       if (hdr_rlc::access(p)->padding() >=
00667           (AckPDUSize() + ((length_indicator_ + 1) / 8))) {
00668          return true;
00669       }
00670    }
00671    return false;
00672 }
00673 
00674 
00675 int AM::AckPDUSize()
00676 {
00677    int bytes;
00678 
00679    if (ack_pdu_header_ % 8) {
00680       bytes = ack_pdu_header_ / 8 + 1;
00681    } else {
00682       bytes = ack_pdu_header_ / 8;
00683    }
00684    return bytes;
00685 }
00686 
00687 
00688 bool AM::S_Piggybackable(Packet * p)
00689 {
00690    if (hdr_rlc::access(p)->padding()) {
00691       if (hdr_rlc::access(p)->padding() >=
00692           (StatusPDUSize() + ((length_indicator_ + 1) / 8))) {
00693          return true;
00694       }
00695    }
00696    return false;
00697 }
00698 
00699 
00700 /* returns size in bytes */
00701 int AM::StatusPDUSize()
00702 {
00703   /* don't want to use status_pdu_header_ */
00704   /* fields:    D/C  +  TYPE              */ 
00705   int bits =     1   +   4; 
00706 
00707   if (send_status_ & SEND_STATUS_BITMAP) {
00708     bits += SUFI_bitmap_size();
00709   }
00710 
00711   if (send_status_ & SEND_STATUS_MRW) {
00712     bits += SUFI_mrw_size();
00713   }
00714 
00715   int bytes;  
00716   if (bits % 8) {
00717     bytes = bits / 8 + 1;
00718   } else {
00719     bytes = bits / 8;
00720   }
00721   
00722   return bytes;  
00723 }
00724 
00725 
00726 
00727 /* returns size of BITMAP SUFI in bits */
00728 int AM::SUFI_bitmap_size()
00729 {
00730     int first_missing = next_;
00731 
00732     while (seen_[first_missing & MWM]) {
00733       ++first_missing;
00734     }
00735 
00736     int fsn = first_missing - 1;
00737 
00738     int bitmapoctets = ((maxseen_-fsn)/8) +1;
00739     assert(bitmapoctets>0);
00740     if (bitmapoctets>16)
00741       bitmapoctets = 16;
00742    
00743     /* fields: TYPE + FSN +  BITMAP    */
00744     return  (   4   + 12  + bitmapoctets*8);    
00745 
00746 }
00747 
00748 
00749 /* returns size of MRW SUFI in bits */
00750 int AM::SUFI_mrw_size()
00751 {
00752   /*fields: TYPE + LENGTH + SN_MRWlast + NLENGTHlast    */
00753   return (    4  +   4    +     12     +   4);  
00754 
00755   /*
00756    * Note that optional (SN_MRWi, NLLENGTHi) entries 
00757    * have not been considered 
00758    */
00759 }
00760 
00761 
00762 
00763 
00764 double AM::send_time(int position)
00765 {
00766   int PDUs_left_in_current_TTI = TTI_PDUs_ - sent_TTI_PDUs_;
00767   int i = 0;
00768   
00769   while (1) {
00770     if (position <= (i * TTI_PDUs_ + PDUs_left_in_current_TTI)) {
00771       return (tti_timer_.timeOfExpiry() + TTI_ * i);
00772     }
00773     i++;
00774   }
00775 }
00776 
00777 
00778 /*
00779  *
00780  */
00781 void AM::send_much(int force)
00782 {
00783    Packet     *p = NULL;
00784 
00785    if (!force && delsnd_timer_.status() == TIMER_PENDING) {
00786       return;
00787    }
00788 
00789 //    while (((t_seqno_ <= highest_ack_ + win_ - b_bal_ - MRW_delta)
00790 //            || set_poll_ || send_status_ || send_ack_)) {
00791    while (((t_seqno_ < FSN_ + win_ - b_bal_ - MRW_delta)
00792            || set_poll_ || send_status_ || send_ack_)) {
00793 
00794      if (debug_>2) cerr << NOW << " New send_much() cycle" << endl;
00795      
00796 
00797       if ((rcvB_.size() == 0) && (b_bal_ == 0)
00798           && (!set_poll_) && (!send_status_)
00799           && (!send_ack_) && (t_seqno_ > maxseq_)) {
00800          sent_TTI_PDUs_ = 0;
00801          return;
00802          /* There are no new PDUs to send or retransmitt */
00803       } else if (sent_TTI_PDUs_ == TTI_PDUs_) {
00804          sent_TTI_PDUs_ = 0;
00805          return;
00806       }
00807 
00808      if (debug_>2) cerr << "send_status_ " << hex << send_status_ << dec << endl;
00809 
00810 
00811       if (overhead_ == 0 || force) 
00812         {
00813           
00814           if (send_status_) {
00815             int position = PB_S_PDU();     
00816             if (position && ((send_time(position) - earliest_status_send_)
00817                              <= max_status_delay_)) {
00818               /* DO nothing. The Status report 
00819                * will be piggybacked later. */
00820             } else {
00821               Packet     *pkt = make_status(NULL);
00822               sent_TTI_PDUs_++;
00823               send_status_ = SEND_STATUS_NONE;
00824               set_status_prohibit_timer();
00825               downtarget_->recv(pkt);
00826               delsnd_timer_.resched(Random::uniform(overhead_));
00827               return;
00828             }
00829             
00830           } else if (send_ack_) {
00831             int position = PB_PA_PDU();
00832             if (position && ((send_time(position) - earliest_ack_send_)
00833                              <= max_ack_delay_)) {
00834               /* DO nothing. The ack will be piggybacked later. */
00835             } else {
00836               Packet     *pkt = make_positive_ack(NULL);
00837               sent_TTI_PDUs_++;
00838               send_ack_ = 0;
00839               downtarget_->recv(pkt);
00840                delsnd_timer_.resched(Random::uniform(overhead_));
00841                return;
00842             }
00843           }
00844 
00845 
00846          int force_set_rtx_timer = 0;
00847 
00848          if (set_poll_ && (rcvB_.size() == 0) && (b_bal_ == 0))         
00849            {
00850 
00851              // no outstanding data, POLL not needed
00852              return;
00853 
00854              //assert(rxtB_.size()>0);
00855 //           if(rxtB_.size()==0)
00856 //             {
00857 //               if (sender_debug_>1)
00858 //                 cerr << NOW << " AM::send_much() (set_poll_ && (rcvB_.size() == 0) && (b_bal_ == 0) && (rxtB_.size()==0) " << endl;
00859 //               return;
00860 //             }
00861 //           p = rxtB_.dequeTailCopy();
00862 //           assert(p);
00863 //           if (send_status_ && S_Piggybackable(p)) {
00864 //             make_status(p);
00865 //             set_status_prohibit_timer();
00866 //             send_status_ = SEND_STATUS_NONE;
00867 //           }
00868 
00869            } 
00870          else if (b_bal_ != 0) 
00871            {
00872              /* retransmit DATA PDU */
00873              int sn = bRxtSeq(0);   
00874              txcount_[sn & MWM]++ ;
00875              p = rxtB_.dequeCopy(sn);
00876              if ((debug_ >1)&&(!p)) 
00877                {
00878                  cerr << "FSN_=" << FSN_ << "sn=" <<sn <<endl;
00879                  cerr << "    bitmap_[]:";
00880                  for (int j=0; j<length_; j++)
00881                    cerr << seen_[j];
00882                  cerr<<endl;
00883                  for (int j=0; j<100; j++)
00884                    cerr << "bRxtSeq(" << j <<")=" <<bRxtSeq(j)<<endl;
00885                  cerr<<endl;
00886                }
00887              assert(p);
00888              if (send_status_ && S_Piggybackable(p)) {
00889                make_status(p);
00890                set_status_prohibit_timer();
00891                send_status_ = SEND_STATUS_NONE;
00892              }
00893              b_bal_--; 
00894              // for last PDU to be re-transmitted be sure 
00895              // to trigger polling function
00896              if (b_bal_ == 0) {
00897                set_poll_ = 1;
00898              }
00899            } 
00900          else if (t_seqno_ > maxseq_) 
00901            {
00902              // for bitmap this is always true
00903              /* transmit new DATA PDU */
00904 
00905              if ((sender_debug_)&&(t_seqno_ >= FSN_ + win_ - MRW_delta))
00906                   {
00907                     cerr << NOW << " AM::send_much()" 
00908                          << " t_seqno_=" <<  t_seqno_
00909                          << " FSN_="  << FSN_
00910                          << " highest_ack_=" << highest_ack_
00911                          << " win_=" << win_ 
00912                          << " MRW_delta=" << MRW_delta 
00913                          << endl;
00914 
00915                     return;
00916                   }
00917 
00918              if (send_status_) {
00919                p = makePDU(StatusPDUSize()
00920                            + ((length_indicator_ + 1) / 8));
00921              } else if (send_ack_) {
00922                p = makePDU(AckPDUSize()
00923                            + ((length_indicator_ + 1) / 8));
00924              } else {
00925                p = makePDU(0);
00926              }
00927              assert(p);
00928 
00929              // 'p' was created extracting a packet from sduB
00930              // now we store a copy in rtxB for eventual retransmissions
00931              rxtB_.enque(p->copy());
00932 
00933              if (send_status_) {
00934                make_status(p);
00935                set_status_prohibit_timer();
00936                send_status_ = SEND_STATUS_NONE;
00937              } else if (send_ack_) {
00938                make_positive_ack(p);
00939                send_ack_ = 0;
00940              }
00941 
00942              assert(t_seqno_ == hdr_rlc::access(p)->seqno());
00943              txcount_[t_seqno_ & MWM] = 1;
00944 
00945              // for last PDU in rcv buffer, 
00946              // be sure to trigger polling function
00947              if (rcvB_.size() == 0) {
00948                set_poll_ = 1;
00949              }
00950              if (highest_ack_ == maxseq_) {
00951                force_set_rtx_timer = 1;
00952              }
00953              maxseq_ = t_seqno_;
00954              t_seqno_++;
00955            } 
00956          else 
00957            {
00958              if (t_seqno_ !=0)
00959                std::cerr << "AM::send_much() maxseq_=" << maxseq_ 
00960                          << " t_seqno_" << t_seqno_
00961                          << std::endl;;
00962              return;
00963 //           assert(0);
00964 //           // Might happen only for positive ACK mode
00965 //           p = rxtB_.dequeCopy(t_seqno_);
00966 //           assert(p);
00967 //           if (send_ack_ && PA_Piggybackable(p)) {
00968 //             make_positive_ack(p);
00969 //             send_ack_ = 0;
00970 //           }
00971 //           t_seqno_++;
00972            }
00973 
00974          assert(p);
00975          tx_PDUs_before_poll++;
00976          tot_PDUs_++;
00977 
00978          if (ack_mode_ == 1) 
00979            {
00980              // positive ACK mode unsupported
00981              assert(0); 
00982              set_poll_ = 0;
00983              if (!rtt_active_) {
00984                rtt_active_ = 1;
00985                if (t_seqno_ > rtt_seq_) {
00986                  rtt_seq_ = t_seqno_;
00987                }
00988              }
00989              if (!(rtx_timer_.status() == TIMER_PENDING)
00990                  || force_set_rtx_timer) {
00991                set_rtx_timer();
00992                /* No timer pending.  Schedule one. */
00993              }
00994            } 
00995          else if (ack_mode_ == 2)  
00996            {
00997              // Bitmap ACK mode
00998              
00999              if ((poll_PDU_ > 0)&&(tx_PDUs_before_poll >= poll_PDU_))
01000                {
01001                  set_poll_ = 1;
01002                  
01003                }
01004 
01005              if (set_poll_) 
01006                {
01007                  hdr_rlc::access(p)->poll() = true;
01008                                  
01009                  set_poll_ = 0;
01010                  tx_PDUs_before_poll = 0;
01011                  set_poll_timer();
01012 
01013                  if (sender_debug_)
01014                    cerr << NOW << " AM::send_much() sending POLL" << endl;
01015              }
01016            }
01017 
01018 
01019          sent_TTI_PDUs_++;
01020          downtarget_->recv(p);
01021          delsnd_timer_.resched(Random::uniform(overhead_));
01022          return;
01023       } else if (!(delsnd_timer_.status() == TIMER_PENDING)) {
01024          /*
01025           * Set a delayed send timeout.
01026           */
01027          delsnd_timer_.resched(Random::uniform(overhead_));
01028          return;
01029       }
01030 
01031    }
01032    sent_TTI_PDUs_ = 0;
01033 }
01034 
01035 
01036 /*
01037  * returns number of SDUs that can be "delivered" to the Agent
01038  * also updates the receive window (i.e. next_, maxseen, and seen_ array)
01039  */
01040 int AM::update(int seq, int eopno)
01041 {
01042    int numSDU = 0;
01043 
01044    // start by assuming the segment hasn't been received before
01045    bool just_marked_as_seen = false;
01046 
01047 
01048    if (receiver_debug_)
01049        cerr << NOW << " AM::update(" << seq << "," << eopno << ")"  
01050             << " MWM=" << MWM
01051             << " maxseen_=" << maxseen_
01052             << " next_="  << next_ ;
01053 
01054 
01055    if (seq - next_ >= MWM) {
01056       // next_ is next PDU expected; MWM is the maximum
01057       // window size minus 1; if somehow the seqno of the
01058       // PDU is greater than the one we're expecting+MWM,
01059       // then ignore it.
01060 
01061         if (receiver_debug_)
01062           cerr << " MWM" << endl;
01063 
01064       return -1;
01065    }
01066 
01067    if (seq < next_) {
01068      // the PDU is to the left edge of the receive window; 
01069      // therefore either we have seen it before 
01070      // or it has been discarded due to a MRW command
01071 
01072         if (receiver_debug_)
01073           cerr << " LEFT" << endl;
01074 
01075       return -1;
01076    }
01077 
01078    if (seq > maxseen_) {
01079       // the PDU is the highest one we've seen so far
01080       int i;
01081  
01082 
01083       // we record the PDUs between the old maximum and
01084       // the new max as being "unseen" i.e. 0
01085       for (i = maxseen_ + 1; i < seq; ++i) {
01086          seen_[i & MWM] = 0;
01087          if (receiver_debug_)
01088            cerr << " U" ;
01089       }     
01090       
01091       // set this PDU as being "seen",
01092       // regardless of the previous value of seen_[seq & MWM]
01093       if (seq == eopno) {
01094          seen_[seq & MWM] = 1;
01095       } else {
01096          seen_[seq & MWM] = 2;
01097       }
01098 
01099       // clear the array entry for the PDU immediately
01100       // after this one
01101       seen_[(seq + 1) & MWM] = 0;
01102 
01103       // record that this PDU is the highest we've seen so far
01104       maxseen_ = seq;
01105 
01106       // necessary so this PDU isn't confused as being a duplicate
01107       just_marked_as_seen = true;
01108 
01109    } else {
01110 
01111      assert(seq >= next_ && seq <= maxseen_);
01112 
01113       // next is the left edge of the recv window; maxseen_
01114       // is the right edge; execute this block if there are
01115       // missing PDUs in the recv window AND if current
01116       // PDU falls within those gaps
01117 
01118       if (seen_[seq & MWM] && !just_marked_as_seen) {
01119          // Duplicate case: the segment has already been
01120          // recorded as being received (AND not because we just
01121          // marked it as such)
01122          return -1;
01123       }
01124 
01125       // record the PDU as being seen
01126       if (seq == eopno) {
01127          seen_[seq & MWM] = 1;
01128       } else {
01129          seen_[seq & MWM] = 2;
01130       }
01131 
01132    }
01133 
01134    if (receiver_debug_)
01135      cerr << " seen_[next_]=" << seen_[next_ & MWM]
01136           << " seen_:";
01137 
01138    while (seen_[next_ & MWM] > 0) {
01139      // This loop sees if any SDUs can now be deliver to
01140      // the Agent due to this PDU arriving
01141 
01142      if (receiver_debug_)
01143        cerr << " " << next_ ;
01144 
01145      //if ((seen_[(next_ - 1) & MWM] == 1)) {
01146 
01147      if ((seen_[next_ & MWM] == 1)) {
01148        // Remember that if pkt i has seq != eopno
01149        // then seen_[i] == 2
01150        // so this block is not executed
01151        numSDU++;
01152 
01153        if (receiver_debug_)
01154          cerr << " S";
01155      }
01156 
01157      // advance the left edge of the receiver window
01158      next_++;      
01159    }
01160 
01161 
01162    if (receiver_debug_)
01163          cerr   << " numSDU=" <<  numSDU    << endl;
01164 
01165 
01166    return numSDU;
01167 }
01168 
01169 
01170 /*
01171  * Process an Positive ACK of previously unacknowleged data.
01172  */
01173 void AM::newack(Packet * pkt)
01174 {
01175    hdr_rlc    *llh = hdr_rlc::access(pkt);
01176 
01177    dupacks_ = 0;
01178    highest_ack_ = llh->a_seqno();
01179 
01180    /* delete all the Acked PDUs from RXT Buff i.e. PDUs till highest_ack_ */
01181    rxtB_.dropTill(highest_ack_);
01182 
01183    if (t_seqno_ < highest_ack_ + 1) {
01184       t_seqno_ = highest_ack_ + 1;
01185    }
01186    if (rtt_active_ && llh->a_seqno() >= rtt_seq_) {
01187       rtt_active_ = 0;
01188    }
01189    /* Set new retransmission timer if not all outstanding data acked.
01190     * Otherwise, if a timer is still outstanding, cancel it. */
01191    if (llh->a_seqno() < maxseq_) {
01192       set_rtx_timer();
01193    } else {
01194       cancel_rtx_timer();
01195    }
01196 }
01197 
01198 
01199 /*
01200  * Process a Bitmap ACK.
01201  */
01202 void AM::newback(Packet * pkt)
01203 {
01204    hdr_rlc    *llh = hdr_rlc::access(pkt);
01205 
01206    b_bal_ = 0;
01207    length_ = llh->length();
01208 
01209    if (FSN_ > llh->FSN())     { 
01210      /* This happens if the sender has dropped some SDU 
01211         in between */
01212      return;
01213    }
01214    
01215    ackSDU(FSN_, llh->FSN());
01216    FSN_ = llh->FSN();
01217    rxtB_.dropTill(FSN_);
01218 
01219 
01220    if (sender_debug_)
01221      {
01222        cerr << NOW << " AM::newback()" 
01223             << " FSN_=" << FSN_
01224             << " llh->FSN=" << llh->FSN()
01225             << " MRW_delta="  << MRW_delta
01226             << " t_seqno_=" << t_seqno_
01227             << " b_bal_=" << b_bal_
01228             << endl;
01229      }
01230 
01231    if (debug_ > 1) {
01232      cerr << NOW << " AM::newback() Queue after pruning:";
01233      rxtB_.dump();
01234    }
01235      
01236 
01237    assert(highest_ack_ <= FSN_ + length_ - 1); /* Don't want to
01238                                                   accidentally lower
01239                                                   highest_ack_ */
01240    highest_ack_ = FSN_ + length_ - 1;
01241 
01242 
01243    if (debug_) cerr << NOW << " processing BITMAP acknowledgement " << endl;
01244 
01245   // Copying the bit fields into the new array
01246    assert(length_<=BITMAP_LENGTH);
01247    for (int i = 0; i < length_; i++) {    
01248      bitmap_[i] = llh->bitmap(i);
01249    }
01250 
01251 
01252    if (debug_ >1) {
01253      cerr << NOW << " AM::newback()"
01254           << " FSN_=" << FSN_ 
01255           << " length_=" << length_
01256           <<  " bitmap_[]:" 
01257           << endl;
01258      for (int j=0; j<length_; j++)
01259        cerr << bitmap_[j];
01260      cerr<<endl;
01261    }
01262 
01263 
01264    int dropsn[length_];
01265    for (int j=0; j<length_; j++ ) 
01266      dropsn[j] = -1;
01267 
01268    int ndropped=0;
01269 
01270    for (int i = 0; i < length_; i++) {
01271       if (bitmap_[i] == 0) 
01272         { /* This PDU is NACKed */
01273              err_PDUs_++;
01274           if (txcount_[(FSN_ + i) & MWM] ==  maxdat_)
01275             { /* retx limit exceeded */
01276               dropsn[ndropped] = FSN_+i;
01277               ndropped++;
01278             }
01279           else /* we are going to retrasmit this PDU */ 
01280             { 
01281               b_bal_++;
01282             }
01283         }       
01284       else {    
01285         /* This PDU is acked, we can forget it */
01286         Packet     *r = rxtB_.deque(FSN_ + i);
01287         if (r)  Packet::free(r);          
01288         //ack_[(FSN_ + i) & MWM] = 1;   
01289       }
01290    }
01291 
01292 
01293 
01294    for (int j=0; j<ndropped; j++) {
01295      if (debug_ > 1) {
01296        cerr <<  NOW << " AM::newback() Current queue: ";
01297        rxtB_.dump();
01298      }
01299      discardSDU(dropsn[j]); // Side effect: updates FSN_,
01300                            // bitmap_  and b_bal_
01301      rxtB_.dropTill(FSN_);              
01302      if (debug_ > 1) {
01303        cerr << NOW << " AM::newback() Queue after pruning:";
01304        rxtB_.dump();
01305      }
01306    }
01307 
01308 
01309    assert(t_seqno_ > highest_ack_);
01310 
01311 
01312 }
01313 
01314 
01315 int AM::bRxtSeq(int position)
01316 {
01317    int counter = 0;
01318 
01319    for (int i = 0; i < length_; i++) {
01320       if (bitmap_[i] == 0) {
01321          counter++;
01322          if (position == 0) {
01323             bitmap_[i] = 1;
01324             // Neill(16/07/04): Increment of 1 seems to be wrong here
01325             // return (i + FSN_ + 1);
01326             return (i + FSN_);
01327          } else if (counter == position) {
01328            // return (i + FSN_ + 1);
01329             return (i + FSN_);
01330          }
01331       }
01332    }
01333    return -1;
01334 }
01335 
01336 
01337 void AM::ack(Packet * opkt)
01338 {
01339    int first_missing = next_;
01340 
01341    while (seen_[first_missing & MWM]) {
01342       ++first_missing;
01343    }
01344    if (ack_mode_ == 1) {
01345       /* Do you want to set a timer so you dont send an ack every PDU? */
01346       if (send_ack_ == 1) {
01347          /* Do nothing since an ack is already pending. */
01348       } else {
01349          if (delsnd_timer_.status() == TIMER_PENDING
01350              && sent_TTI_PDUs_ < TTI_PDUs_) {
01351             earliest_ack_send_ = tti_timer_.timeOfExpiry();
01352          } else {
01353             earliest_ack_send_ = tti_timer_.timeOfExpiry() + TTI_;
01354          }
01355          send_ack_ = 1;
01356       }
01357    } else if (ack_mode_ == 2) {
01358       if (prohibited_) {
01359          return;
01360       }
01361       /* opkt is the "old" PDU that was received */
01362 
01363       if (stprob_timer_.status() == TIMER_PENDING) {
01364          if (hdr_rlc::access(opkt)->poll()) {
01365             prohibited_ = 1;
01366          }
01367          return;
01368       }
01369 
01370       if (first_missing < maxseen_ || hdr_rlc::access(opkt)->poll()) {
01371          if (send_status_ & SEND_STATUS_BITMAP) {
01372             /* Do nothing since a status report is already pending. */
01373          } else {
01374             if (delsnd_timer_.status()
01375                 == TIMER_PENDING && sent_TTI_PDUs_ < TTI_PDUs_) {
01376                earliest_status_send_ = tti_timer_.timeOfExpiry();
01377             } else {
01378                earliest_status_send_ = tti_timer_.timeOfExpiry() + TTI_;
01379             }
01380             send_status_ |= SEND_STATUS_BITMAP;
01381          }
01382       }
01383    }
01384 }
01385 
01386 
01387 Packet     *AM::make_positive_ack(Packet * p)
01388 {
01389    Packet     *npkt;
01390    hdr_rlc    *nrlc;
01391    hdr_cmn    *nch;
01392 
01393    assert(0);    /* Positive ACK is likely broken since the inclusion
01394                   * in this NS module of standard SUFIs in AM STATUS
01395                   * PDU. In order to fix this, a POSITIVE ACK SUFI
01396                   * should be added. Eurane documentation says it is not compatible
01397                   * with the standard, but more recent 3GPP releases (TS 25.322-5d0) actually
01398                   * include an ACK SUFI which might be the same thing. 
01399                   */
01400 
01401    int first_missing = next_;
01402 
01403    while (seen_[first_missing & MWM]) {
01404       ++first_missing;
01405    }
01406 
01407    if (p == NULL) {
01408       npkt = allocpkt(0);
01409       nrlc = hdr_rlc::access(npkt);
01410       nch = hdr_cmn::access(npkt);
01411       hdr_ip     *niph = hdr_ip::access(npkt);
01412       hdr_tcp    *ntcp = hdr_tcp::access(npkt);
01413 
01414       nrlc->lltype() = RLC_ACK;
01415       nrlc->dst() = d_address_;
01416       nrlc->src() = address_;
01417       nrlc->a_seqno() = first_missing - 1;   /* cumulative sequence number */
01418       nrlc->seqno() = nrlc->a_seqno(); /* For trace plotting. */
01419       nrlc->lengthInd_ = 0;
01420       nrlc->padding_ = payload_ - AckPDUSize();
01421 
01422       for (int i = 1; i < 3; i++) {
01423          nrlc->payload_[i] = 0;
01424       }
01425 
01426       nrlc->payload_[0] = AckPDUSize();
01427 
01428 
01429       nch->ptype() = PT_AM;
01430       nch->size() = payload_;
01431 
01432       niph->flowid() = -1;
01433       niph->saddr() = -1;
01434       niph->sport() = -1;
01435       niph->daddr() = -1;
01436       niph->dport() = -1;
01437       niph->ttl() = 32;
01438 
01439       ntcp->seqno() = -1;
01440 
01441       char       *mh = (char *) npkt->access(hdr_mac::offset_);
01442       struct hdr_mac *dh = (struct hdr_mac *) mh;
01443 
01444       dh->macDA_ = macDA_;
01445       dh->macSA_ = -1;
01446       dh->hdr_type() = ETHERTYPE_RLC;
01447 
01448       return npkt;
01449    }
01450    npkt = p;
01451 
01452    nrlc = hdr_rlc::access(npkt);
01453    nch = hdr_cmn::access(npkt);
01454 
01455    nrlc->lengthInd_++;
01456    nrlc->padding_ = nrlc->padding_ - AckPDUSize()
01457          - ((length_indicator_ + 1) / 8);
01458    nrlc->payload_[nrlc->lengthInd_ - 1] = AckPDUSize();
01459 
01460    nrlc->a_seqno() = first_missing - 1;   /* cumulative sequence number */
01461 
01462    // nrlc->lltype() = RLC_ACK;     
01463 
01464    nch->size() = payload_;
01465    nch->ptype() = PT_AM;
01466 
01467    return npkt;
01468 }
01469 
01470 
01471 
01472 Packet     *AM::make_status(Packet * p)
01473 {
01474    Packet     *npkt;
01475    hdr_rlc    *nllh;
01476    hdr_cmn    *nch;
01477 
01478  
01479 
01480    if (p == NULL) {
01481      /* Creating a stand-alone status PDU */
01482 
01483       npkt = allocpkt(0);
01484 
01485       nllh = hdr_rlc::access(npkt);
01486       nch = hdr_cmn::access(npkt);
01487       hdr_ip     *niph = hdr_ip::access(npkt);
01488       hdr_tcp    *ntcp = hdr_tcp::access(npkt);
01489       char       *mh = (char *) npkt->access(hdr_mac::offset_);
01490 
01491       nllh->lltype() = RLC_STATUS;
01492       nllh->dst() = d_address_;
01493       nllh->src() = address_;
01494       nllh->seqno() = -1;           /* STATUS PDUs don't have SN, do they? */
01495       nllh->lengthInd_ = 0;
01496       nllh->padding_ = payload_ - StatusPDUSize();
01497 
01498       for (int i = 1; i < 3; i++) {
01499          nllh->payload_[i] = 0;
01500       }
01501 
01502       nllh->payload_[0] = StatusPDUSize();
01503 
01504       niph->flowid() = flowID_;
01505       niph->saddr() = -1;
01506       niph->sport() = -1;
01507       niph->daddr() = -1;
01508       niph->dport() = -1;
01509       niph->ttl() = 32;
01510 
01511       ntcp->seqno() = -1;
01512 
01513       nch->ptype() = PT_AM;
01514       nch->size() = payload_;
01515 
01516       struct hdr_mac *dh = (struct hdr_mac *) mh;
01517 
01518       dh->macDA_ = macDA_;
01519       dh->macSA_ = -1;
01520       dh->hdr_type() = ETHERTYPE_RLC;
01521 
01522    } else {
01523 
01524      /* Piggyback status PDU */
01525       npkt = p;
01526       
01527       nch = hdr_cmn::access(npkt);
01528       nllh = hdr_rlc::access(npkt);
01529 
01530       nch->ptype() = PT_AM;
01531       
01532       nllh->lengthInd_++;
01533       nllh->padding_ = nllh->padding_ - StatusPDUSize()
01534         -((length_indicator_ + 1) / 8);
01535       nllh->payload_[nllh->lengthInd_ - 1] = StatusPDUSize();            
01536    }
01537 
01538    /* Include all needed SUFIs */
01539 
01540    if (send_status_ & SEND_STATUS_BITMAP) make_bitmap_SUFI(npkt);
01541    if (send_status_ & SEND_STATUS_MRW)    make_mrw_SUFI(npkt);
01542    if (send_status_ & SEND_STATUS_MRWACK) make_mrwack_SUFI(npkt);
01543     
01544    return npkt;
01545 }
01546 
01547 
01548 
01549 Packet     *AM::make_bitmap_SUFI(Packet * p)
01550 {
01551    Packet     *npkt;
01552    hdr_rlc    *nllh;
01553    hdr_cmn    *nch;
01554 
01555    int first_missing = next_;
01556 
01557    while (seen_[first_missing & MWM]) {
01558       ++first_missing;
01559    }
01560 
01561    int fsn = first_missing - 1;
01562 
01563    if (fsn < 0) {
01564       // When the first packet ever gets a nack we shouldn't try to ack
01565       // everything until then.
01566       fsn = 0;
01567    }
01568 
01569    npkt = p;
01570    nllh = hdr_rlc::access(npkt);
01571    nch = hdr_cmn::access(npkt);
01572 
01573    nllh->lltype() |= RLC_BITMAP;
01574 
01575    
01576    nllh->FSN() = fsn;
01577 //    if ((maxseen_ - fsn + 1) > BITMAP_LENGTH) {
01578 //      nllh->length() = BITMAP_LENGTH;
01579 //    } else {
01580 //      nllh->length() = maxseen_ - fsn + 1;
01581 //    }
01582    nllh->length() = std::min(maxseen_ - fsn + 1, BITMAP_LENGTH);
01583 
01584    if (debug_) cerr << NOW << " AM::make_bitmap_SUFI() adding BITMAP SUFI: " 
01585                     << hex << nllh->lltype() << dec 
01586                     << " length_:" <<  maxseen_ << "-" 
01587                     << fsn << "+1=" <<  nllh->length()              
01588                     << endl;
01589    if (debug_>1) {     
01590      cerr << NOW << " AM::make_bitmap_SUFI() seen_[]:" << endl;
01591      for (int j=fsn; j<=maxseen_; j++)
01592        cerr << seen_[j];
01593      cerr<<endl;
01594    }
01595 
01596 
01597    for (int i = 0; i < nllh->length(); i++) {
01598      if (seen_[(fsn + i) & MWM])
01599        nllh->setbitmap(i);
01600    }
01601 
01602 
01603    if (debug_>1) {     
01604      cerr << NOW << " AM::make_bitmap_SUFI() bitmap:"<< endl;
01605      for (int j=0; j<nllh->length(); j++)
01606        cerr << nllh->bitmap(j);
01607      cerr<<endl;
01608    }
01609 
01610 
01611 
01612    return npkt;
01613 }
01614 
01615 
01616 
01617 
01618 
01619 Packet     *AM::make_mrw_SUFI(Packet * p)
01620 {
01621    hdr_rlc    *nllh;
01622 
01623    nllh = hdr_rlc::access(p);
01624    nllh->lltype() |= RLC_MRW;   
01625    nllh->SN_MRW = FSN_; 
01626 
01627    /* Schedule retransmission timer for MRW request */   
01628    mrwack_timer_.resched(rtx_timeout_);
01629 
01630    return p;
01631 }
01632 
01633 
01634 
01635 
01636 Packet     *AM::make_mrwack_SUFI(Packet * p)
01637 {
01638    hdr_rlc    *nllh;
01639 
01640    nllh = hdr_rlc::access(p);
01641    nllh->lltype() |= RLC_MRWACK;
01642    nllh->SN_MRW_ACK = next_; 
01643 
01644    return p;
01645 }
01646 
01647 
01648 
01649 /*
01650  * allocate a PDU and fill in required fields
01651  */
01652 Packet     *AM::allocpkt(int uid)
01653 {
01654    Packet     *p = Packet::alloc();
01655    hdr_cmn    *ch = hdr_cmn::access(p);
01656 
01657 /*      ch->ptype() = PT_AMDA; */
01658    ch->uid() = uid;
01659    ch->error() = 0;
01660    ch->timestamp() = Scheduler::instance().clock();
01661    ch->iface() = UNKN_IFACE.value();
01662    ch->direction() = hdr_cmn::DOWN;
01663    //ch->ref_count() = 0;
01664 
01665    return (p);
01666 }
01667 
01668 
01669 void AM::makeSDU(int numSDU)
01670 {
01671 
01672    Packet     *p;
01673    hdr_cmn    *ch;
01674    hdr_rlc    *llh;
01675 
01676    if (debug_>1)
01677      {
01678        cerr << NOW << " AM::makeSDU() SDU Queue before pruning:";
01679        sduB_.dump();
01680      }  
01681 
01682    for (int i = 0; i < numSDU; i++) {
01683 
01684 
01685       p = sduB_.deque();
01686       assert(p);
01687       ch = HDR_CMN(p);
01688       llh = hdr_rlc::access(p);
01689 
01690                                         
01691           
01692       ch->ptype() = llh->lptype();
01693       ch->error() = llh->lerror();
01694       ch->timestamp() = llh->lts();
01695       ch->size() = llh->lsize();
01696 
01697       uptarget_ ? sendUp(p) : Packet::free(p);
01698    }
01699    
01700    if (debug_>1)
01701      {
01702        cerr << NOW << " AM::makeSDU() SDU Queue after pruning:";
01703        sduB_.dump();
01704      }
01705 }
01706 
01707 void AM::CSwitch(double bandwidth, double TTI)
01708 {
01709    bandwidth_ = bandwidth;
01710    TTI_ = TTI;
01711 }
01712 
01713 /* 
01714  * Process timeout events.
01715  */
01716 void AM::timeout(int tno, int flowID)
01717 {
01718   /* a switch(tno) { case:.. } statement 
01719      would have been MUCH cleaner  */
01720  
01721    /* retransmit timer */
01722    if (tno == RLC_TIMER_POLL) {
01723      
01724      // 3GPP says POLL timer should always be rescheduled
01725      set_poll_timer();
01726 
01727       if (maxseq_ == FSN_ && b_bal_ == 0) {
01728          /*
01729           * If no outstanding data, then don't do anything.  
01730           */
01731         if (sender_debug_)
01732           cerr << NOW << " AM::timeout(RLC_TIMER_POLL) not sending POLL, no outstanding data" << endl;
01733         
01734          return;
01735       }
01736 
01737       set_poll_ = 1;
01738       if (sender_debug_)
01739         cerr << NOW << " AM::timeout(RLC_TIMER_POLL) sending POLL" << endl;
01740 
01741    } else if (tno == RLC_TIMER_RTX) {
01742       if (highest_ack_ == maxseq_) {
01743          /*
01744           * If no outstanding data, then don't do anything.  
01745           */
01746          return;
01747       }
01748       reset_rtx_timer();
01749 
01750    } else if (tno == RLC_TIMER_STPROB) {
01751 
01752       if (prohibited_) 
01753         {
01754           send_status_ |= SEND_STATUS_BITMAP;
01755           if (receiver_debug_)
01756             cerr << NOW << " AM::timeout(RLC_TIMER_STPROB) SEND_STATUS_BITMAP" << endl;
01757           prohibited_ = 0;
01758           if (delsnd_timer_.status() == TIMER_PENDING
01759               && sent_TTI_PDUs_ < TTI_PDUs_) {
01760             earliest_status_send_ = tti_timer_.timeOfExpiry();
01761           } else {
01762             earliest_status_send_ = tti_timer_.timeOfExpiry() + TTI_;
01763           }      
01764         } 
01765       else 
01766         {
01767           if (receiver_debug_)
01768             cerr << NOW << " AM::timeout(RLC_TIMER_STPROB) NOT sending BITMAP" 
01769                  << " prohibited_=" << prohibited_
01770                  << endl;
01771         }
01772 
01773 
01774 
01775    } else if (tno == RLC_TIMER_DELSND) {
01776       send_much(1);
01777 
01778    } else if (tno == RLC_TIMER_TTI) {
01779       TTI_time_ = Scheduler::instance().clock();
01780       TTI_PDUs_ = (int) (bandwidth_ * TTI_) / (payload_ * 8);
01781       tti_timer_.resched(TTI_);
01782       send_much(0);
01783    } else if (tno == RLC_TIMER_MRWACK) {
01784      send_status_ |= SEND_STATUS_MRW;
01785    }
01786 }
01787 
01788 
01789 /*
01790  * Set retransmit timer using current provided rtt estimate.  By calling  
01791  * resched(),it does not matter whether the timer was already running.
01792  */
01793 void AM::set_rtx_timer()
01794 {
01795    rtx_timer_.resched(rtx_timeout_);
01796 }
01797 
01798 
01799 /*
01800  * We got a timeout or too many duplicate acks.  Clear the retransmit timer.
01801  * Resume the sequence one past the highest packet acked.
01802  */
01803 void AM::reset_rtx_timer()
01804 {
01805    cancel_rtx_timer();
01806    t_seqno_ = highest_ack_ + 1;
01807 
01808    rtt_active_ = 0;
01809 }
01810 
01811 
01812 void AM::cancel_rtx_timer()
01813 {
01814    rtx_timer_.force_cancel();
01815 }
01816 
01817 
01818 void AM::set_poll_timer()
01819 {
01820    poll_timer_.resched(poll_timeout_);
01821 }
01822 
01823 
01824 void AM::cancel_poll_timer()
01825 {
01826    poll_timer_.force_cancel();
01827 }
01828 
01829 
01830 void AM::set_status_prohibit_timer()
01831 {
01832    stprob_timer_.resched(stprob_timeout_ -
01833                          (Scheduler::instance().clock() - TTI_time_)
01834          );
01835 }
01836 
01837 
01838 int AM::buff_size()
01839 {
01840    return (rcvB_.size() + rxtB_.size());
01841 }
01842 
01843 
01844 
01845 void AM::discardSDU(int dsn)
01846 {
01847   /* As for AM::ackSDU(), we're sure that all
01848    * PDUs belonging to X which have SN < FSN_ have already been
01849    * acknowledged. Moreover, all PDUs in [FSN_, dsn-1] are acked.
01850    */
01851   bool sdu_ok = true;
01852   int sdu_begin;
01853   int sn;
01854 
01855   if (debug_)  cerr << "Discarding PDU " << dsn << endl;
01856 
01857   if (debug_>1) {  
01858     cerr << "FSN_ = " << FSN_ <<endl;
01859     cerr << "    bitmap_[]:";
01860     for (int j=0; j<length_; j++)
01861       cerr << bitmap_[j];
01862     cerr<<endl;
01863   }
01864 
01865   if (dsn < FSN_)
01866     {
01867       if (debug_)  cerr << "WARNING -- AM::discardSDU(int dsn) -- dsn < FSN_ = " << FSN_ << endl;
01868       return;
01869     }
01870 
01871   for (sn = FSN_; sn < dsn; sn++) 
01872     {
01873       ack_PDUs_++;      
01874       if (eopno_[sn & MWM] == sn)
01875         { /* this PDU is the end of a SDU*/
01876           ack_SDUs_++;
01877           sdu_begin = sn+1; /* Actually a fragment of new SDU could be
01878                                in PDU sn...*/
01879         }         
01880     }
01881 
01882   /* now sn == dsn */
01883   assert(sn == dsn);
01884   while (!(eopno_[sn & MWM] == sn))    
01885     {
01886       drop_PDUs_++;
01887       sn++;
01888       assert(sn-dsn < MWM + 1);
01889     }
01890 
01891   /* now sn is the end of the dropped SDU */
01892   MRW_delta = sn+1 - FSN_;
01893   FSN_ = sn+1;
01894   length_ -= MRW_delta;
01895   drop_SDUs_++;
01896   send_status_ |= SEND_STATUS_MRW;
01897 
01898   if (sender_debug_) 
01899     {
01900     cerr << "FSN_ incremented by " << MRW_delta << " -> " << FSN_ <<endl;
01901     cerr << "TOTAL:" << "PDUs " << ack_PDUs_ << "/" << ack_PDUs_ + drop_PDUs_
01902          << " SDUs " << ack_SDUs_ << "/" <<  ack_SDUs_ + drop_SDUs_ << endl;
01903     }
01904 
01905 
01906   b_bal_ = 0;
01907   for (int i = 0; i < length_; i++)
01908     {
01909       assert(i+MRW_delta < BITMAP_LENGTH);
01910       bitmap_[i] = bitmap_[i+MRW_delta];
01911       if (bitmap_[i] == 0) 
01912         b_bal_++;
01913     }
01914 
01915    if (sender_debug_>1) { 
01916      cerr << "FSN_ = " << FSN_ <<endl;
01917      cerr << "new bitmap_[]:";
01918      for (int j=0; j<length_; j++)
01919        cerr << bitmap_[j];
01920      cerr<< " b_bal_=" << b_bal_ 
01921          << " t_seqno_=" << t_seqno_  << endl;
01922      cerr << "   txcount_[]:";
01923      for (int j=FSN_; j<FSN_+100; j++)
01924        cerr << txcount_[j & MWM];
01925      cerr<<endl;
01926           
01927    }
01928 
01929 }
01930 
01931 
01932 
01933 
01934 /* Counts how many SDUs have been acknowledge so far */
01935 void AM::ackSDU(int oldFSN, int newFSN)
01936 {
01937   /* Let X be the SDU which PDU oldFSN belongs to. We're sure that all
01938    * PDUs belonging to X which have SN < oldFSN have already been
01939    * acknowledged, since FSN_ - 1 is cumulatively acknowledged by the
01940    * server, and STATUS_MRW issued when SDU are dropped moves the
01941    * receiver window only on SDU boundaries.
01942    */
01943   for (int sn = oldFSN; sn < newFSN; sn++)
01944     {
01945       ack_PDUs_++;         
01946       if (eopno_[sn & MWM] == sn)
01947         { /* this PDU is the end of a SDU*/
01948           ack_SDUs_++;
01949         }         
01950     } 
01951   if (debug_) {
01952     cerr << "TOTAL:" << "PDUs " << ack_PDUs_ << "/" << ack_PDUs_ + drop_PDUs_
01953          << " SDUs " << ack_SDUs_ << "/" <<  ack_SDUs_ + drop_SDUs_
01954          << endl;
01955   }
01956 }
01957 
01958 
01959 

Generated on Wed Nov 26 15:47:29 2008 for NS-MIRACLE library by  doxygen 1.5.2