scoreboard.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1996 The Regents of the University of California.
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Network Research
00017  *  Group at Lawrence Berkeley National Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  * 
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00035 
00036 /* 9/96 Pittsburgh Supercomputing Center
00037  *      UpdateScoreBoard, CheckSndNxt, MarkRetran modified for fack
00038  */
00039 
00040 /*  A quick hack version of the scoreboard  */
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 
00044 #include "scoreboard.h"
00045 #include "tcp.h"
00046 
00047 #define ASSERT(x) if (!(x)) {printf ("Assert SB failed\n"); exit(1);}
00048 #define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)\n"); exit(1);}
00049 
00050 #define SBNI SBN[i%sbsize_]
00051 
00052 // last_ack = TCP last ack
00053 int ScoreBoard::UpdateScoreBoard (int last_ack, hdr_tcp* tcph)
00054 {
00055     int i, sack_index, sack_left, sack_right;
00056     int retran_decr = 0;
00057     
00058     changed_ = 0;
00059             
00060     //  Advance the left edge of the block.
00061     if (length_ && SBN[first_%sbsize_].seq_no_ <= last_ack) {
00062         for (i=SBN[first_%sbsize_].seq_no_; i<=last_ack; i++) {
00063             //  Advance the ACK
00064             if (SBNI.seq_no_ <= last_ack) {
00065                 ASSERT(first_ == i);
00066                 first_ = (first_+1);
00067                 length_--;
00068                 ASSERT1(length_ >= 0);
00069                 SBNI.ack_flag_ = 1;
00070                 SBNI.sack_flag_ = 1;
00071                 if (SBNI.retran_) {
00072                     SBNI.retran_ = 0;
00073                     SBNI.snd_nxt_ = 0;
00074                     retran_decr++;
00075                 }
00076                 changed_++;
00077                 if (length_==0) 
00078                     break;
00079             }
00080         }
00081     }
00082 
00083     //  If there is no scoreboard, create one.
00084     if (length_ == 0 && tcph->sa_length()) {
00085         i = last_ack+1;
00086         SBNI.seq_no_ = i;
00087         SBNI.ack_flag_ = 0;
00088         SBNI.sack_flag_ = 0;
00089         SBNI.retran_ = 0;
00090         SBNI.snd_nxt_ = 0;
00091         first_ = i;
00092         length_++;
00093         if (length_ >= sbsize_) {
00094             printf ("Error, scoreboard too large (increase sbsize_ for more space)\n");
00095             exit(1);
00096         }
00097         changed_++;
00098     }   
00099 
00100     for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
00101         sack_left = tcph->sa_left(sack_index);
00102         sack_right = tcph->sa_right(sack_index);
00103         
00104         //  Create new entries off the right side.
00105         if (sack_right > SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_) {
00106 
00107             // Resize the scoreboard if it is going to overrun the length
00108             while((sack_right - last_ack) >= sbsize_ -1 ){
00109                 resizeSB(sbsize_*2);
00110             }
00111 
00112             //  Create new entries
00113             for (i = SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_+1; i<sack_right; i++) {
00114                 SBNI.seq_no_ = i;
00115                 SBNI.ack_flag_ = 0;
00116                 SBNI.sack_flag_ = 0;
00117                 SBNI.retran_ = 0;
00118                 SBNI.snd_nxt_ = 0;
00119                 length_++;
00120                 if (length_ >= sbsize_) {
00121                     fprintf(stderr, "ERROR: Scoreboard got too large!!!\n");
00122                     fprintf(stderr, " SBN[first (mod) sbsize_]: %i, sack_right: %i length_: %i\n", SBN[first_%sbsize_].seq_no_,sack_right , length_);
00123                     fprintf(stderr, "last_ack: %i SBN[(first_+length_+sbsize_-1) (mod) sbsize_].seq_no_: %i, sbsize_: %i\n", last_ack, SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_ , sbsize_);
00124                     exit(1);
00125                 }
00126                 changed_++;
00127             }
00128         }
00129         
00130         for (i=SBN[(first_)%sbsize_].seq_no_; i<sack_right; i++) {
00131             //  Check to see if this segment is now covered by the sack block
00132             if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
00133                 if (! SBNI.sack_flag_) {
00134                     SBNI.sack_flag_ = 1;
00135                     changed_++;
00136                 }
00137                 if (SBNI.retran_) {
00138                     SBNI.retran_ = 0;
00139                     retran_decr++;
00140                 }
00141             }
00142         }
00143     }
00144     return (retran_decr);
00145 }
00146 int ScoreBoard::CheckSndNxt (hdr_tcp* tcph)
00147 {
00148     int i, sack_index, sack_left, sack_right;
00149     int force_timeout = 0;
00150 
00151     for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
00152         sack_left = tcph->sa_left(sack_index);
00153         sack_right = tcph->sa_right(sack_index);
00154 
00155         for (i=SBN[(first_)%sbsize_].seq_no_; i<sack_right; i++) {
00156             //  Check to see if this segment's snd_nxt_ is now covered by the sack block
00157             if (SBNI.retran_ && SBNI.snd_nxt_ < sack_right) {
00158                 // the packet was lost again
00159                 SBNI.retran_ = 0;
00160                 SBNI.snd_nxt_ = 0;
00161                 force_timeout = 1;
00162             }
00163         }
00164     }
00165     return (force_timeout);
00166 }
00167 
00168 void ScoreBoard::ClearScoreBoard()
00169 {
00170     length_ = 0;
00171 }
00172 
00173 /*
00174  * GetNextRetran() returns "-1" if there is no packet that is
00175  *   not acked and not sacked and not retransmitted.
00176  */
00177 int ScoreBoard::GetNextRetran() // Returns sequence number of next pkt...
00178 {
00179     int i;
00180 
00181     if (length_) {
00182         for (i=SBN[(first_)%sbsize_].seq_no_; 
00183              i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00184             if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && !SBNI.retran_) {
00185                 return (i);
00186             }
00187         }
00188     }
00189     return (-1);
00190 }
00191 
00192 
00193 /*
00194  * GetNextUnacked returns sequence number of next unacked pkt,
00195  * starting with seqno.
00196  * Returns -1 if there is no unacked packet in that range.
00197  */
00198 int ScoreBoard::GetNextUnacked (int seqno)
00199 {
00200     int i;
00201     if (!length_) {
00202         return (-1);
00203     } else if (seqno < SBN[(first_)%sbsize_].seq_no_ ||
00204         seqno >= SBN[(first_)%sbsize_].seq_no_+length_) {
00205         return (-1);
00206     } else {
00207         for (i=seqno; i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00208             if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
00209                 return (i);
00210             }
00211         }
00212     }
00213     return (-1);
00214 
00215 }
00216 
00217 void ScoreBoard::MarkRetran (int retran_seqno, int snd_nxt)
00218 {
00219     SBN[retran_seqno%sbsize_].retran_ = 1;
00220     SBN[retran_seqno%sbsize_].snd_nxt_ = snd_nxt;
00221 }
00222 
00223 void ScoreBoard::MarkRetran (int retran_seqno)
00224 {
00225     SBN[retran_seqno%sbsize_].retran_ = 1;
00226 }
00227 
00228 void ScoreBoard::resizeSB(int sz)
00229 {
00230     ScoreBoardNode *newSBN = new ScoreBoardNode[sz+1];
00231 
00232     if(!newSBN){
00233         fprintf(stderr, "Unable to allocate new ScoreBoardNode[%i]\n", sz);
00234         exit(1);
00235     }
00236 
00237     for(int i = SBN[first_%sbsize_].seq_no_;
00238         i<=SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00239         newSBN[i%sz] = SBN[i%sbsize_];
00240     }
00241 
00242     delete[] SBN;
00243     SBN = newSBN;
00244     sbsize_ = sz;
00245 }
00246 
00247 void ScoreBoard::Dump()
00248 {
00249        int i;
00250 
00251        printf("SB len: %d  ", length_);
00252        if (length_) {
00253                for (i=SBN[(first_)%sbsize_].seq_no_; 
00254                     i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00255                        printf("seq: %d  [ ", i);
00256                        if(SBNI.ack_flag_)
00257                                printf("A");
00258                        if(SBNI.sack_flag_)
00259                                printf("S");
00260                        if(SBNI.retran_)
00261                                printf("R");
00262                        printf(" ]");
00263                }
00264        }
00265        printf("\n");
00266 }
00267 

Generated on Tue Mar 6 16:47:50 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6