📄 scoreboard-rh.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1996 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Network Research * Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* 9/96 Pittsburgh Supercomputing Center * UpdateScoreBoard, CheckSndNxt, MarkRetran modified for fack */#ifndef lintstatic const char rcsid[] = "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/scoreboard-rh.cc,v 1.2 2000/08/12 21:45:39 sfloyd Exp $ (LBL)";#endif/* A quick hack version of the scoreboard */#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <math.h>#include "packet.h"#include "scoreboard-rh.h"#include "tcp.h"#define ASSERT(x) if (!(x)) {printf ("Assert SB failed\n"); exit(1);}#define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)\n"); exit(1);}#define SBNI SBN[i%SBSIZE]// last_ack = TCP last ackint ScoreBoardRH::UpdateScoreBoard (int last_ack, hdr_tcp* tcph, int rh_id){ int i, sack_index, sack_left, sack_right; int sack_max = 0; int retran_decr = 0; /* Can't do this, because we need to process out the retran_decr */#if 0 if (tcph->sa_length() == 0) { // There are no SACK blocks, so clear the scoreboard. this->ClearScoreBoard(); return(0); }#endif /* What we do need to do is not create a scoreboard if we don't need one. */ if ((tcph->sa_length() == 0) && (length_ == 0)) { return(0); } // If there is no scoreboard, create one. if (length_ == 0) { i = last_ack+1; SBNI.seq_no_ = i; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 0; SBNI.rh_id_ = 0; first_ = i%SBSIZE; length_++; if (length_ >= SBSIZE) { printf ("Error, scoreboard too large (increase SBSIZE for more space)\n"); exit(1); } } // Advance the left edge of the block. if (SBN[first_].seq_no_ <= last_ack) { for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) { // Advance the ACK if (SBNI.seq_no_ <= last_ack) { ASSERT(first_ == i%SBSIZE); first_ = (first_+1)%SBSIZE; length_--; ASSERT1(length_ >= 0); SBNI.ack_flag_ = 1; SBNI.sack_flag_ = 1; if (SBNI.retran_) { SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; retran_decr++; retran_sacked_ = rh_id; } if (length_==0) break; } } } for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) { sack_left = tcph->sa_left(sack_index); sack_right = tcph->sa_right(sack_index); /* Remember the highest segment SACKed by this packet */ if (sack_right > sack_max) { sack_max = sack_right; } // Create new entries off the right side. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) { // Create new entries for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) { SBNI.seq_no_ = i; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 0; SBNI.rh_id_ = 0; length_++; if (length_ >= SBSIZE) { printf ("Error, scoreboard too large (increase SBSIZE for more space)\n"); exit(1); } } } for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) { // Check to see if this segment is now covered by the sack block if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) { if (! SBNI.sack_flag_) { SBNI.sack_flag_ = 1; } if (SBNI.retran_) { SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; retran_decr++; retran_sacked_ = rh_id; } } } } /* Now go through the whole scoreboard and update sack_cnt on holes which still exist. */ if (length_ != 0) { for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) { // Check to see if this segment is a hole if (!SBNI.ack_flag_ && !SBNI.sack_flag_) { SBNI.sack_cnt_++; } } } retran_decr += CheckSndNxt(sack_max); return (retran_decr);}int ScoreBoardRH::CheckSndNxt (int sack_max){ int i; int num_lost = 0; if (length_ != 0) { for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) { // Check to see if this segment's snd_nxt_ is now covered by the sack block if (SBNI.retran_ && SBNI.snd_nxt_ < sack_max) { // the packet was lost again SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 1; num_lost++; } } } return (num_lost);}void ScoreBoardRH::ClearScoreBoard(){ length_ = 0;}/* * GetNextRetran() returns "-1" if there is no packet that is * not acked and not sacked and not retransmitted. */int ScoreBoardRH::GetNextRetran() // Returns sequence number of next pkt...{ int i; if (length_) { for (i=SBN[(first_)%SBSIZE].seq_no_; i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) { if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && !SBNI.retran_ && (SBNI.sack_cnt_ >= *numdupacks_)) { return (i); } } } return (-1);}void ScoreBoardRH::MarkRetran (int retran_seqno, int snd_nxt, int rh_id){ SBN[retran_seqno%SBSIZE].retran_ = 1; SBN[retran_seqno%SBSIZE].snd_nxt_ = snd_nxt; SBN[retran_seqno%SBSIZE].rh_id_ = rh_id; retran_occured_ = rh_id;}int ScoreBoardRH::GetFack (int last_ack){ if (length_) { return(SBN[(first_)%SBSIZE].seq_no_+length_-1); } else { return(last_ack); }}int ScoreBoardRH::GetNewHoles (){ int i, new_holes=0; for (i=SBN[(first_)%SBSIZE].seq_no_; i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) { // Check to see if this segment is a new hole#if 1 if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == 1) { new_holes++; }#else if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == *numdupacks_) { new_holes++; }#endif } return (new_holes);}void ScoreBoardRH::TimeoutScoreBoard (int snd_nxt){ int i, sack_right; if (length_ == 0) { // No need to do anything! return; } sack_right = snd_nxt; // Use this to know how far to extend. // Create new entries off the right side. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) { // Create new entries for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) { SBNI.seq_no_ = i; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 0; SBNI.rh_id_ = 0; length_++; if (length_ >= SBSIZE) { printf ("Error, scoreboard too large (increase SBSIZE for more space)\n"); exit(1); } } } /* Now go through the whole scoreboard and update sack_cnt on holes; clear retran flag on everything. */ for (i=SBN[(first_)%SBSIZE].seq_no_; i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) { // Check to see if this segment is a hole if (!SBNI.ack_flag_ && !SBNI.sack_flag_) { SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = *numdupacks_; // This forces all holes to be retransmitted. } } /* And, finally, check the first segment in case of a renege. */ i=SBN[(first_)%SBSIZE].seq_no_; if (!SBNI.ack_flag_ && SBNI.sack_flag_) { printf ("Renege!!! seqno = %d\n", SBNI.seq_no_); SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = *numdupacks_; // This forces it to be retransmitted. }}#if 0/* This routine inserts a fake sack block of length num_dupacks, starting at last_ack+1. It is for use during NewReno recovery.*/int ScoreBoardRH::FakeSack (int last_ack, int num_dupacks){ int i, sack_left, sack_right; int retran_decr = 0; // If there is no scoreboard, create one. if (length_ == 0) { i = last_ack+1; SBNI.seq_no_ = i; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 0; SBNI.rh_id_ = 0; first_ = i%SBSIZE; length_++; if (length_ >= SBSIZE) { printf ("Error, scoreboard too large (increase SBSIZE for more space)\n"); exit(1); } } // Advance the left edge of the scoreboard. if (SBN[first_].seq_no_ <= last_ack) { for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) { // Advance the ACK if (SBNI.seq_no_ <= last_ack) { ASSERT(first_ == i%SBSIZE); first_ = (first_+1)%SBSIZE; length_--; ASSERT1(length_ >= 0); SBNI.ack_flag_ = 1; SBNI.sack_flag_ = 1; if (SBNI.retran_) { SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; retran_decr++; } if (length_==0) break; } } /* Now create a new hole in the first position */ i=SBN[(first_)%SBSIZE].seq_no_; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.rh_id_ = 0; SBNI.sack_cnt_ = num_dupacks; } sack_left = last_ack + 1; sack_right = sack_left + num_dupacks - 1; // Create new entries off the right side. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) { // Create new entries for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) { SBNI.seq_no_ = i; SBNI.ack_flag_ = 0; SBNI.sack_flag_ = 0; SBNI.retran_ = 0; SBNI.snd_nxt_ = 0; SBNI.sack_cnt_ = 0; SBNI.rh_id_ = 0; length_++; if (length_ >= SBSIZE) { printf ("Error, scoreboard too large (increase SBSIZE for more space)\n"); exit(1); } } } for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) { // Check to see if this segment is now covered by the sack block if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) { if (! SBNI.sack_flag_) { SBNI.sack_flag_ = 1; } if (SBNI.retran_) { SBNI.retran_ = 0; retran_decr++; } } } /* Now go through the whole scoreboard and update sack_cnt on holes which still exist. In this case the only possible case is the first hole. */ i=SBN[(first_)%SBSIZE].seq_no_; // Check to see if this segment is a hole if (!SBNI.ack_flag_ && !SBNI.sack_flag_) { SBNI.sack_cnt_++; } return (retran_decr);}#endifint ScoreBoardRH::RetranSacked (int rh_id) { return (retran_sacked_ == rh_id);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -