[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ns] Run-time modifiable NUMDUPACKS



Hi,
Attached to this email is a patch to ns that migrates NUMDUPACKS from a
#defined constant to a run-time modifiable tcl variable in the TCP stack.
This variable defaults to the same value of 3.

The only (moderate) ugliness in this patch is in scoreboard-rh.{h,cc}, where
the scoreboard references NUMDUPACKS.  As the constant NUMDUPACKS is
disappering and numdupacks_ is now a member of Agent/TCP, a pointer to the
scoreboard's parent Agent/TCP's numdupacks_ member had to be installed.
This is less than beautiful, but effective.

This change breaks NO validation tests.  As long as you don't change
numdupacks_, anyway.  ;-)

If whoever owns the respective TCP variants (other than Sack1 and Agent/TCP,
which I think are both OK) would like to verify the correctness of this in
all cases, I would appreciate it.

Thanks,
Ethan
diff -ruN ns-2-snapshot-20000725/chost.cc ns-2-variable_numdupacks/chost.cc
--- ns-2-snapshot-20000725/chost.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/chost.cc	Thu Jul 27 21:25:32 2000
@@ -242,7 +242,7 @@
     }
     /*
      * A pkt is a candidate for retransmission if it is the leftmost one in the
-     * unacked window for the connection AND has at least NUMDUPACKS
+     * unacked window for the connection AND has at least numdupacks_
      * dupacks/later acks AND (at least one dupack OR a later packet also
      * with the threshold number of dup/later acks). A pkt is also a candidate
      * for immediate retransmission if it has partialack_ set, indicating that
@@ -255,7 +255,7 @@
 	     * curArray_ only contains segments that are the first oldest
 	     * unacked segments of their connection (i.e., they are at the left
 	     * edge of their window) and have either received a
-	     * partial ack and/or have received at least NUMDUPACKS
+	     * partial ack and/or have received at least cur->numdupacks_
 	     * dupacks/later acks. Thus, segments in curArray_ have a high
 	     * probability (but not certain) of being eligible for 
 	     * retransmission. Using curArray_ avoids having to scan
@@ -391,7 +391,7 @@
 				dontIncrCwnd_ = 1;
 			} 
 		}
-		if (cur->dupacks_+cur->later_acks_ >= NUMDUPACKS &&
+		if (cur->dupacks_+cur->later_acks_ >= sender->numdupacks_ &&
 		    !cur->thresh_dupacks_) {
 			cur->thresh_dupacks_ = 1;
 			cur->sender_->num_thresh_dupack_segs_++;
@@ -403,7 +403,7 @@
 		   the num_thresh_dupack_segs_ check */
 		if (!remove_flag &&
 		    cur->seqno_ == cur->sender_->highest_ack_ + 1 &&
-		    (cur->dupacks_ + cur->later_acks_ >= NUMDUPACKS ||
+		    (cur->dupacks_ + cur->later_acks_ >= sender->numdupacks_ ||
 		     cur->partialack_)) {
 			curArray_[rexmtSegCount_] = cur;
 			prevArray_[rexmtSegCount_] = prev;
diff -ruN ns-2-snapshot-20000725/scoreboard-rh.cc ns-2-variable_numdupacks/scoreboard-rh.cc
--- ns-2-snapshot-20000725/scoreboard-rh.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/scoreboard-rh.cc	Thu Jul 27 21:25:32 2000
@@ -218,7 +218,7 @@
 		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)) {
+			    && (SBNI.sack_cnt_ >= *numdupacks_)) {
 				return (i);
 			}
 		}
@@ -257,7 +257,7 @@
 			new_holes++;
 		}
 #else
-		if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == NUMDUPACKS) {
+		if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == *numdupacks_) {
 			new_holes++;
 		}
 #endif
@@ -303,7 +303,7 @@
 		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.
+			SBNI.sack_cnt_ = *numdupacks_;  // This forces all holes to be retransmitted.
 		}
 	}
 
@@ -314,7 +314,7 @@
 		SBNI.sack_flag_ = 0;
 		SBNI.retran_ = 0;
 		SBNI.snd_nxt_ = 0;
-		SBNI.sack_cnt_ = NUMDUPACKS;  // This forces it to be retransmitted.
+		SBNI.sack_cnt_ = *numdupacks_;  // This forces it to be retransmitted.
 	}
 }
 
diff -ruN ns-2-snapshot-20000725/scoreboard-rh.h ns-2-variable_numdupacks/scoreboard-rh.h
--- ns-2-snapshot-20000725/scoreboard-rh.h	Thu Jul 27 21:40:36 2000
+++ ns-2-variable_numdupacks/scoreboard-rh.h	Thu Jul 27 21:40:51 2000
@@ -45,7 +45,7 @@
 
 class ScoreBoardRH {
   public:
-	ScoreBoardRH() {first_=0; length_=0; retran_occured_=0;}
+        ScoreBoardRH(int *numdupacks) : numdupacks_(numdupacks) {first_=0; length_=0; retran_occured_=0;}
 	int IsEmpty () {return (length_ == 0);}
 	void ClearScoreBoard (); 
 	int GetNextRetran ();
@@ -65,6 +65,9 @@
 					    in which a retransmission occured  */
 	int retran_sacked_;              /* This variable stores the last adjustment interval
 					    in which a retransmission was sacked  */
+        int *numdupacks_;		 /* I know, it stinks...  But this is numdupacks_ from
+					  * our parent TCP stack. */
+   
 	struct ScoreBoardNode {
 		int seq_no_;		/* Packet number */
 		int ack_flag_;		/* Acked by cumulative ACK */
diff -ruN ns-2-snapshot-20000725/tcl/lib/ns-default.tcl ns-2-variable_numdupacks/tcl/lib/ns-default.tcl
--- ns-2-snapshot-20000725/tcl/lib/ns-default.tcl	Thu Jul 27 21:22:02 2000
+++ ns-2-variable_numdupacks/tcl/lib/ns-default.tcl	Thu Jul 27 21:25:51 2000
@@ -91,6 +91,7 @@
 Agent/TCP set t_seqno_ 0
 Agent/TCP set maxburst_ 0
 Agent/TCP set maxcwnd_ 0
+Agent/TCP set numdupacks_ 3
 Agent/TCP set window_ 20
 Agent/TCP set windowInit_ 1
 Agent/TCP set windowInitOption_ 1
diff -ruN ns-2-snapshot-20000725/tcp-fack.cc ns-2-variable_numdupacks/tcp-fack.cc
--- ns-2-snapshot-20000725/tcp-fack.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-fack.cc	Thu Jul 27 21:25:32 2000
@@ -169,7 +169,7 @@
 			/* 
 			 * a duplicate ACK
 			 */
-			if (dupacks_ >= NUMDUPACKS) {
+			if (dupacks_ >= numdupacks_) {
 				/*
 				 * Assume we dropped just one packet.
 				 * Retransmit last ack + 1
diff -ruN ns-2-snapshot-20000725/tcp-newreno.cc ns-2-variable_numdupacks/tcp-newreno.cc
--- ns-2-snapshot-20000725/tcp-newreno.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-newreno.cc	Thu Jul 27 21:25:32 2000
@@ -219,10 +219,10 @@
 			tcp_eln(pkt);
 			return;
 		}
-		if (++dupacks_ == NUMDUPACKS) {
+		if (++dupacks_ == numdupacks_) {
 			dupack_action();
-			dupwnd_ = NUMDUPACKS;
-		} else if (dupacks_ > NUMDUPACKS) {
+			dupwnd_ = numdupacks_;
+		} else if (dupacks_ > numdupacks_) {
 			++dupwnd_;	// fast recovery
 			/* For every two duplicate ACKs we receive (in the
 			 * "fast retransmit phase"), send one entirely new
@@ -230,7 +230,7 @@
 			 */
 			if (newreno_changes_ > 0 && (dupacks_ % 2) == 1)
 				output (t_seqno_++,0);
-		} else if (dupacks_ < NUMDUPACKS && singledup_ ) {
+		} else if (dupacks_ < numdupacks_ && singledup_ ) {
                         send_one();
                 }
 	}
@@ -250,7 +250,7 @@
 		 *  window of data on exiting Fast Recovery.
 		 */
 		send_much(0, 0, maxburst_);
-	else if (dupacks_ > NUMDUPACKS - 1 && newreno_changes_ == 0)
+	else if (dupacks_ > numdupacks_ - 1 && newreno_changes_ == 0)
 		send_much(0, 0, 2);
 }
 
diff -ruN ns-2-snapshot-20000725/tcp-reno.cc ns-2-variable_numdupacks/tcp-reno.cc
--- ns-2-snapshot-20000725/tcp-reno.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-reno.cc	Thu Jul 27 21:25:32 2000
@@ -83,12 +83,12 @@
 			tcp_eln(pkt);
 			return;
 		}
-		if (++dupacks_ == NUMDUPACKS) {
+		if (++dupacks_ == numdupacks_) {
 			dupack_action();
-			dupwnd_ = NUMDUPACKS;
-		} else if (dupacks_ > NUMDUPACKS) {
+			dupwnd_ = numdupacks_;
+		} else if (dupacks_ > numdupacks_) {
 			++dupwnd_;	// fast recovery
-		} else if (dupacks_ < NUMDUPACKS && singledup_ ) {
+		} else if (dupacks_ < numdupacks_ && singledup_ ) {
 			send_one();
 		}
 	}
@@ -102,7 +102,7 @@
 	 * Try to send more data
 	 */
 
-	if (dupacks_ == 0 || dupacks_ > NUMDUPACKS - 1)
+	if (dupacks_ == 0 || dupacks_ > numdupacks_ - 1)
 		send_much(0, 0, maxburst_);
 }
 
diff -ruN ns-2-snapshot-20000725/tcp-rfc793edu.cc ns-2-variable_numdupacks/tcp-rfc793edu.cc
--- ns-2-snapshot-20000725/tcp-rfc793edu.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-rfc793edu.cc	Thu Jul 27 21:25:32 2000
@@ -227,7 +227,7 @@
                         return;
                 }
 		// fast retransmission
-		if ( (++dupacks_ == NUMDUPACKS) && add793fastrtx_ ) {
+		if ( (++dupacks_ == numdupacks_) && add793fastrtx_ ) {
 			dupack_action();
 		}
 	}
diff -ruN ns-2-snapshot-20000725/tcp-sack-rh.cc ns-2-variable_numdupacks/tcp-sack-rh.cc
--- ns-2-snapshot-20000725/tcp-sack-rh.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-sack-rh.cc	Thu Jul 27 21:25:32 2000
@@ -49,7 +49,7 @@
 
 class SackRHTcpAgent : public TcpAgent {
  public:
-	SackRHTcpAgent();
+        SackRHTcpAgent();
 	virtual int window();
 	virtual void recv(Packet *pkt, Handler*);
 	virtual void timeout(int tno);
@@ -91,7 +91,7 @@
 
 SackRHTcpAgent::SackRHTcpAgent() : fack_(-1), 
 	retran_data_(0), num_dupacks_(0), rh_state_(RH_INCR), rh_id_(0), rh_max_(0),
-	rh_est_hole_state_(0), rh_retran_flag_(0), rh_ecn_flag_(0)
+	rh_est_hole_state_(0), rh_retran_flag_(0), rh_ecn_flag_(0), scb_(&numdupacks_)
 {
 }
 
@@ -127,7 +127,7 @@
        	if (!sackpresent && (old_ack == last_ack_)) {
 		num_dupacks_++;
 		if ((rh_est_hole_state_ == RHEH_COUNTING) && 
-		    (num_dupacks_ == NUMDUPACKS)) {
+		    (num_dupacks_ == numdupacks_)) {
 			rh_est_hole_state_ = RHEH_NEW_HOLE;
 		}
 	}
@@ -180,7 +180,7 @@
 	    && (last_ack_ > old_ack)) {
 		retran_data_ = 0;
 		num_dupacks_ -= (last_ack_ - old_ack - 1);
-		if (num_dupacks_ >= NUMDUPACKS) {
+		if (num_dupacks_ >= numdupacks_) {
 			rh_est_hole_state_ = RHEH_NEW_HOLE;
 		}
 		else {
diff -ruN ns-2-snapshot-20000725/tcp-sack1.cc ns-2-variable_numdupacks/tcp-sack1.cc
--- ns-2-snapshot-20000725/tcp-sack1.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-sack1.cc	Thu Jul 27 21:25:32 2000
@@ -126,14 +126,14 @@
 			 *  acknowledges new data.
  			 */
  		        if(scb_.CheckUpdate()) {
- 			 	if (++dupacks_ == NUMDUPACKS) {
+ 			 	if (++dupacks_ == numdupacks_) {
  					/*
  					 * Assume we dropped just one packet.
  					 * Retransmit last ack + 1
  					 * and try to resume the sequence.
  					 */
  				   	dupack_action();
- 				} else if (dupacks_ < NUMDUPACKS && singledup_ ) {
+ 				} else if (dupacks_ < numdupacks_ && singledup_ ) {
  				         send_one();
  				}
 			}
@@ -204,17 +204,17 @@
 		reset_rtx_timer(1,0);
 		/*
 		 * There are three possibilities: 
-		 * (1) pipe_ = int(cwnd_) - NUMDUPACKS;
-		 * (2) pipe_ = window() - NUMDUPACKS;
-		 * (3) pipe_ = maxseq_ - highest_ack_ - NUMDUPACKS;
+		 * (1) pipe_ = int(cwnd_) - numdupacks_;
+		 * (2) pipe_ = window() - numdupacks_;
+		 * (3) pipe_ = maxseq_ - highest_ack_ - numdupacks_;
 		 * equation (2) takes into account the receiver's
 		 * advertised window, and equation (3) takes into
 		 * accout a data-limited sender.
 		 */
 		if (!singledup_)
-			pipe_ = maxseq_ - highest_ack_ - NUMDUPACKS;
+			pipe_ = maxseq_ - highest_ack_ - numdupacks_;
 		else pipe_ = maxseq_ - highest_ack_ - 1;
-		//pipe_ = int(cwnd_) - NUMDUPACKS;
+		//pipe_ = int(cwnd_) - numdupacks_;
 		fastrecov_ = TRUE;
 		scb_.MarkRetran(highest_ack_+1);
 		output(last_ack_ + 1, TCP_REASON_DUPACK);
@@ -233,10 +233,10 @@
 sack_action:
 	recover_ = maxseq_;
 	last_cwnd_action_ = CWND_ACTION_DUPACK;
-	pipe_ = int(cwnd_) - NUMDUPACKS;
-	//pipe_ = maxseq_ - highest_ack_ - NUMDUPACKS;
+	pipe_ = int(cwnd_) - numdupacks_;
+	//pipe_ = maxseq_ - highest_ack_ - numdupacks_;
 	//if (!singledup_)
-	// 	pipe_ = maxseq_ - highest_ack_ - NUMDUPACKS;
+	// 	pipe_ = maxseq_ - highest_ack_ - numdupacks_;
 	//else pipe_ = maxseq_ - highest_ack_ - 1;
 	slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
 	reset_rtx_timer(1,0);
@@ -244,7 +244,7 @@
 	scb_.MarkRetran(highest_ack_+1);
 	output(last_ack_ + 1, TCP_REASON_DUPACK);	// from top
 	/*
-	 * If dynamically adjusting NUMDUPACKS, record information
+	 * If dynamically adjusting numdupacks_, record information
 	 *  at this point.
 	 */
 	return;
@@ -254,8 +254,8 @@
 {
 	if (tno == TCP_TIMER_RTX) {
 		/*
-		 * IF DSACK and dynamic adjustment of NUMDUPACKS,
-		 *  check whether a smaller value of NUMDUPACKS
+		 * IF DSACK and dynamic adjustment of numdupacks_,
+		 *  check whether a smaller value of numdupacks_
 		 *  would have prevented this retransmit timeout.
 		 * If DSACK and detection of premature retransmit
 		 *  timeouts, then save some info here.
diff -ruN ns-2-snapshot-20000725/tcp-vegas.cc ns-2-variable_numdupacks/tcp-vegas.cc
--- ns-2-snapshot-20000725/tcp-vegas.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp-vegas.cc	Thu Jul 27 21:25:32 2000
@@ -153,7 +153,7 @@
 			cwnd_ = initial_window();
 		}
 		/* check if cwnd has been inflated */
-		if(dupacks_ > NUMDUPACKS &&  cwnd_ > v_newcwnd_) {
+		if(dupacks_ > numdupacks_ &&  cwnd_ > v_newcwnd_) {
 			cwnd_ = v_newcwnd_;
 			// vegas ssthresh is used only during slow-start
 			ssthresh_ = 2;
@@ -300,7 +300,7 @@
 			--v_worried_;
 			int expired=vegas_expire(pkt);
 			if(expired>=0) {
-				dupacks_ = NUMDUPACKS;
+				dupacks_ = numdupacks_;
 				output(expired, TCP_REASON_DUPACK);
 			} else
 				v_worried_ = 0;
@@ -309,7 +309,7 @@
 		/* check if a timeout should happen */
 		++dupacks_; 
 		int expired=vegas_expire(pkt);
-		if (expired>=0 || dupacks_ == NUMDUPACKS) {
+		if (expired>=0 || dupacks_ == numdupacks_) {
 			double sendTime=v_sendtime_[(last_ack_+1) % v_maxwnd_]; 
 			int transmits=v_transmits_[(last_ack_+1) % v_maxwnd_];
        	                /* The line below, for "bug_fix_" true, avoids
@@ -356,9 +356,9 @@
 					output(last_ack_ + 1, TCP_REASON_DUPACK);
 					 
 				if(transmits==1) 
-					dupacks_ = NUMDUPACKS;
+					dupacks_ = numdupacks_;
                         }
-		} else if (dupacks_ > NUMDUPACKS) 
+		} else if (dupacks_ > numdupacks_) 
 			++cwnd_;
 	}
 	Packet::free(pkt);
@@ -370,7 +370,7 @@
 	/*
 	 * Try to send more data
 	 */
-	if (dupacks_ == 0 || dupacks_ > NUMDUPACKS - 1)
+	if (dupacks_ == 0 || dupacks_ > numdupacks_ - 1)
 		send_much(0, 0, maxburst_);
 }
 
diff -ruN ns-2-snapshot-20000725/tcp.cc ns-2-variable_numdupacks/tcp.cc
--- ns-2-snapshot-20000725/tcp.cc	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp.cc	Thu Jul 27 21:25:32 2000
@@ -129,6 +129,7 @@
         delay_bind_init_one("timestamps_");
         delay_bind_init_one("maxburst_");
         delay_bind_init_one("maxcwnd_");
+	delay_bind_init_one("numdupacks_");
         delay_bind_init_one("maxrto_");
         delay_bind_init_one("srtt_init_");
         delay_bind_init_one("rttvar_init_");
@@ -199,6 +200,7 @@
         if (delay_bind_bool(varName, localName, "timestamps_", &ts_option_ , tracer)) return TCL_OK;
         if (delay_bind(varName, localName, "maxburst_", &maxburst_ , tracer)) return TCL_OK;
         if (delay_bind(varName, localName, "maxcwnd_", &maxcwnd_ , tracer)) return TCL_OK;
+	if (delay_bind(varName, localName, "numdupacks_", &numdupacks_, tracer)) return TCL_OK;
         if (delay_bind(varName, localName, "maxrto_", &maxrto_ , tracer)) return TCL_OK;
         if (delay_bind(varName, localName, "srtt_init_", &srtt_init_ , tracer)) return TCL_OK;
         if (delay_bind(varName, localName, "rttvar_init_", &rttvar_init_ , tracer)) return TCL_OK;
@@ -1035,7 +1037,7 @@
  * A first or second duplicate acknowledgement has arrived, and
  * singledup_ is enabled.
  * If the receiver's advertised window permits, and we are exceeding our
- * congestion window by less than NUMDUPACKS, then send a new packet.
+ * congestion window by less than numdupacks_, then send a new packet.
  */
 void
 TcpAgent::send_one()
@@ -1115,9 +1117,9 @@
                         tcp_eln(pkt);
                         return;
                 }
-		if (++dupacks_ == NUMDUPACKS && !noFastRetrans_) {
+		if (++dupacks_ == numdupacks_ && !noFastRetrans_) {
 			dupack_action();
-		} else if (dupacks_ < NUMDUPACKS && singledup_ ) {
+		} else if (dupacks_ < numdupacks_ && singledup_ ) {
 			send_one();
 		}
 	}
@@ -1440,7 +1442,7 @@
 			F_counting = 0 ; 
 		}
 		else {
-			if (dupacks_ == NUMDUPACKS)
+			if (dupacks_ == numdupacks_)
 				RTT_count ++ ;
 		}
 	}
diff -ruN ns-2-snapshot-20000725/tcp.h ns-2-variable_numdupacks/tcp.h
--- ns-2-snapshot-20000725/tcp.h	Thu Jul 27 21:20:51 2000
+++ ns-2-variable_numdupacks/tcp.h	Thu Jul 27 21:25:32 2000
@@ -103,7 +103,8 @@
  * 0.01 for new window algorithms,
  */
 
-#define NUMDUPACKS 3		/* normally 3, sometimes 1 */
+/* #define NUMDUPACKS 3		This is now set in tcl/lib/ns-default.tcl
+ * 				as Agent/Tcp numdupacks_ */
 #define TCP_MAXSEQ 1073741824   /* Number that curseq_ is set to for */
 				/* "infinite send" (2^30)            */
 
@@ -250,6 +251,7 @@
 	int ts_option_;		/* use RFC1323-like timestamps? */
 	int maxburst_;		/* max # packets can send back-2-back */
 	int maxcwnd_;		/* max # cwnd can ever be */
+        int numdupacks_;	/* dup ACKs before fast retransmit */
 	double maxrto_;		/* max value of an RTO */
 	int old_ecn_;		/* For backwards compatibility with the 
 				 * old ECN implementation, which never