diff -crbB ns-allinone-2.35/ns-2.35/queue/red.cc ns-2.35/queue/red.cc
*** ns-allinone-2.35/ns-2.35/queue/red.cc -- ::34.000000000 -
--- ns-2.35/queue/red.cc -- ::10.827778003 -
***************
*** , ****
edv_.count_bytes = ;
hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
if (edp_.setbit && hf->ect() &&
! (!edp_.use_mark_p || edv_.v_prob1 < edp_.mark_p)) {
hf->ce() = ; // mark Congestion Experienced bit
// Tell the queue monitor here - call emark(pkt)
return (); // no drop
--- , ----
edv_.count_bytes = ;
hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
if (edp_.setbit && hf->ect() &&
! (!edp_.use_mark_p || edv_.v_prob1 <= edp_.mark_p)) { // For DCTCP: '<' is changed to '<=' here
hf->ce() = ; // mark Congestion Experienced bit
// Tell the queue monitor here - call emark(pkt)
return (); // no drop
Only in ns-2.35/queue: red.cc~
diff -crbB ns-allinone-2.35/ns-2.35/tcl/lib/ns-default.tcl ns-2.35/tcl/lib/ns-default.tcl
*** ns-allinone-2.35/ns-2.35/tcl/lib/ns-default.tcl -- ::45.000000000 -
--- ns-2.35/tcl/lib/ns-default.tcl -- ::08.415778003 -
***************
*** , ****
--- , ---- Agent/TCP set SetCWRonRetransmit_ true ; # added on //.
# default changed on //.
+ # DCTCP
+ Agent/TCP set dctcp_ false;
+ Agent/TCP set dctcp_alpha_ 0.0;
+ Agent/TCP set dctcp_g_ 0.0625; # XXX Generate nam trace or plain old text trace for variables.
# When it's true, generate nam trace.
Only in ns-2.35/tcl/lib: ns-default.tcl~
Only in ns-2.35/tcp: .swp
diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp.cc ns-2.35/tcp/tcp.cc
*** ns-allinone-2.35/ns-2.35/tcp/tcp.cc -- ::46.000000000 -
--- ns-2.35/tcp/tcp.cc -- ::09.966778001 -
***************
*** , ****
--- , ----
bind("necnresponses_", &necnresponses_);
bind("ncwndcuts_", &ncwndcuts_);
bind("ncwndcuts1_", &ncwndcuts1_);
+ bind("dctcp_", &dctcp_);
+ bind("dctcp_alpha_", &dctcp_alpha_);
+ bind("dctcp_g_", &dctcp_g_);
#endif /* TCP_DELAY_BIND_ALL */ }
***************
*** , ****
--- , ----
delay_bind_init_one("overhead_");
delay_bind_init_one("tcpTick_");
delay_bind_init_one("ecn_");
+ // DCTCP
+ delay_bind_init_one("dctcp_");
+ delay_bind_init_one("dctcp_alpha_");
+ delay_bind_init_one("dctcp_g_");
+
delay_bind_init_one("SetCWRonRetransmit_");
delay_bind_init_one("old_ecn_");
delay_bind_init_one("bugfix_ss_");
***************
*** , ****
--- , ----
if (delay_bind(varName, localName, "overhead_", &overhead_, tracer)) return TCL_OK;
if (delay_bind(varName, localName, "tcpTick_", &tcp_tick_, tracer)) return TCL_OK;
if (delay_bind_bool(varName, localName, "ecn_", &ecn_, tracer)) return TCL_OK;
+ // Mohammad
+ if (delay_bind_bool(varName, localName, "dctcp_", &dctcp_, tracer)) return TCL_OK;
+ if (delay_bind(varName, localName, "dctcp_alpha_", &dctcp_alpha_ , tracer)) return TCL_OK;
+ if (delay_bind(varName, localName, "dctcp_g_", &dctcp_g_ , tracer)) return TCL_OK;
if (delay_bind_bool(varName, localName, "SetCWRonRetransmit_", &SetCWRonRetransmit_, tracer)) return TCL_OK;
if (delay_bind_bool(varName, localName, "old_ecn_", &old_ecn_ , tracer)) return TCL_OK;
if (delay_bind_bool(varName, localName, "bugfix_ss_", &bugfix_ss_ , tracer)) return TCL_OK;
***************
*** , ****
--- , ----
} else {
ssthresh_ = (int) decreasewin;
}
+ else if (how & CLOSE_SSTHRESH_DCTCP)
+ ssthresh_ = (int) (( - dctcp_alpha_/2.0) * windowd());
else if (how & THREE_QUARTER_SSTHRESH)
if (ssthresh_ < *cwnd_/)
ssthresh_ = (int)(*cwnd_/);
***************
*** , ****
--- , ----
if (first_decrease_ == || slowstart || decrease_num_ == 0.5) {
cwnd_ = halfwin;
} else cwnd_ = decreasewin;
+ else if (how & CLOSE_CWND_DCTCP)
+ cwnd_ = ( - dctcp_alpha_/2.0) * windowd();
else if (how & CWND_HALF_WITH_MIN) {
// We have not thought about how non-standard TCPs, with
// non-standard values of decrease_num_, should respond
***************
*** , ****
}
if (ssthresh_ < )
ssthresh_ = ;
! if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE))
cong_action_ = TRUE; fcnt_ = count_ = ;
--- , ----
}
if (ssthresh_ < )
ssthresh_ = ;
! if (cwnd_ < )
! cwnd_ = ;
! if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE|CLOSE_CWND_DCTCP))
cong_action_ = TRUE; fcnt_ = count_ = ;
***************
*** , ****
--- , ----
rtt_backoff();
else ecn_backoff_ = ;
} else ecn_backoff_ = ;
+ if (dctcp_)
+ slowdown(CLOSE_CWND_DCTCP|CLOSE_SSTHRESH_DCTCP);
+ else
slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);
++necnresponses_ ;
// added by sylvia to count number of ecn responses
Only in ns-2.35/tcp: tcp.cc~
diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp-full.cc ns-2.35/tcp/tcp-full.cc
*** ns-allinone-2.35/ns-2.35/tcp/tcp-full.cc -- ::54.000000000 -
--- ns-2.35/tcp/tcp-full.cc -- ::10.049778005 -
***************
*** , ****
--- , ----
/* Set ect() to 0. -M. Weigle 1/19/05 */
fh->ect() = ;
}
+
+ // For DCTCP, ect should be set on all packets
+ if (dctcp_)
+ fh->ect() = ect_;
+
if (ecn_ && ect_ && recent_ce_ ) {
// This is needed here for the ACK in a SYN, SYN/ACK, ACK
// sequence.
***************
*** , ****
// Q: how can this happen? if (maxseg_ == )
! maxseg_ = size_ - headersize();
else
size_ = maxseg_ + headersize(); int is_retransmit = (seqno < maxseq_);
int quiet = (highest_ack_ == maxseq_);
--- , ----
// Q: how can this happen? if (maxseg_ == )
! maxseg_ = size_; // Mohammad: changed from size_ - headersize();
! /* Mohammad: This else condition is unnecessary and conflates
! * with tcp.cc
else
size_ = maxseg_ + headersize();
+ */ int is_retransmit = (seqno < maxseq_);
int quiet = (highest_ack_ == maxseq_);
***************
*** , ****
--- , ----
*/
flags_ &= ~(TF_ACKNOW|TF_DELACK); + delack_timer_.force_cancel();
+
/*
* if we have reacted to congestion recently, the
* slowdown() procedure will have set cong_action_ and
***************
*** 1178,1183 ****
--- 1188,1195 ----
// and adjusted for SYNs and FINs which use up one number int highest = seqno + reliable;
+ if (highest > dctcp_maxseq)
+ dctcp_maxseq = highest;
if (highest > maxseq_) {
maxseq_ = highest;
//
***************
*** 1415,1421 ****
{
// we are now going to fast-retransmit and willtrace that event
trace_event("FAST_RETX");
-
recover_ = maxseq_; // recovery target
last_cwnd_action_ = CWND_ACTION_DUPACK;
return(foutput(seq, REASON_DUPACK)); // send one pkt
--- 1427,1432 ----
***************
*** 1564,1574 ****
--- 1576,1594 ----
* at time t0 = (0.0 + k * interval_) for some k such
* that t0 > now
*/
+ /*
+ * Mohammad: commented this out for more efficient
+ * delayed ack generation.
+ *
if (delack_interval_ > 0.0 &&
(delack_timer_.status() != TIMER_PENDING)) {
int last = int(now() / delack_interval_);
delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
}
+ */
+
+ if (dctcp_)
+ update_dctcp_alpha(pkt); /*
* Try header prediction: in seq data or in seq pure ACK
***************
*** 1597,1602 ****
--- 1617,1641 ----
// if (ecn_) {
+ if (dctcp_) { // DCTCP
+ if (fh->ce() && fh->ect()) {
+ // no CWR from peer yet... arrange to
+ // keep sending ECNECHO
+ if (recent_ce_ == FALSE) {
+ ce_transition = 1;
+ recent_ce_ = TRUE;
+ } else {
+ ce_transition = 0;
+ }
+ } else if (datalen > 0 && !fh->ce() && fh->ect()){
+ if (recent_ce_ == TRUE) {
+ ce_transition = 1;
+ recent_ce_ = FALSE;
+ } else {
+ ce_transition = 0;
+ }
+ }
+ } else {
if (fh->ce() && fh->ect()) {
// no CWR from peer yet... arrange to
// keep sending ECNECHO
***************
*** 1607,1612 ****
--- 1646,1652 ----
recent_ce_ = FALSE;
}
}
+ } // Header predication basically looks to see
// if the incoming packet is an expected pure ACK
***************
*** 1638,1645 ****
--- 1678,1698 ----
// this routine scans all tcpcb's looking for
// DELACK segments and when it finds them
// changes DELACK to ACKNOW and calls tcp_output()
+
+ /* DCTCP receiver state machine */
+ if (dctcp_ && ce_transition && ((rcv_nxt_ - last_ack_sent_) > )) {
+ // Must send an immediate ACK with with previous ECN state
+ // before transitioning to new state
+ flags_ |= TF_ACKNOW;
+ recent_ce_ = !recent_ce_;
+ send_much(, REASON_NORMAL, maxburst_);
+ recent_ce_ = !recent_ce_;
+ }
+
rcv_nxt_ += datalen;
flags_ |= TF_DELACK;
+ // Mohammad
+ delack_timer_.resched(delack_interval_);
recvBytes(datalen); // notify application of "delivery"
//
// special code here to simulate the operation
***************
*** , ****
--- , ----
*/
if (datalen > ) {
flags_ |= TF_DELACK; // data there: wait
+ // Mohammad
+ delack_timer_.resched(delack_interval_);
} else {
flags_ |= TF_ACKNOW; // ACK peer's SYN
}
***************
*** , ****
// cong_action bit
//
if (ecn_) {
! if (fh->ce() && fh->ect())
recent_ce_ = TRUE;
! else if (fh->cwr())
recent_ce_ = FALSE;
} //
--- , ----
// cong_action bit
//
if (ecn_) {
! if (dctcp_) { // Mohammad
! if (fh->ce() && fh->ect()) {
! // no CWR from peer yet... arrange to
! // keep sending ECNECHO
! if (recent_ce_ == FALSE) {
! ce_transition = ;
recent_ce_ = TRUE;
! } else {
! ce_transition = ;
! }
! } else if (datalen > && !fh->ce() && fh->ect()){
! if (recent_ce_ == TRUE) {
! ce_transition = ;
recent_ce_ = FALSE;
+ } else {
+ ce_transition = ;
+ }
+ }
+ } else {
+ if (fh->ce() && fh->ect()) {
+ recent_ce_ = TRUE;
+ } else if (fh->cwr()) {
+ recent_ce_ = FALSE;
+ }
+ }
} //
***************
*** , ****
if ((!delay_growth_ || (rcv_nxt_ > )) &&
last_state_ == TCPS_ESTABLISHED) {
if (!partial || open_cwnd_on_pack_) {
! if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
opencwnd();
}
} if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
ourfinisacked = TRUE;
}
--- , ----
if ((!delay_growth_ || (rcv_nxt_ > )) &&
last_state_ == TCPS_ESTABLISHED) {
if (!partial || open_cwnd_on_pack_) {
! if (!ect_ || !hdr_flags::access(pkt)->ecnecho() || ecn_burst_)
opencwnd();
}
} + // Mohammad: Detect bursts of ECN marks
+ if (ect_) {
+ if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())
+ ecn_burst_ = TRUE;
+ else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())
+ ecn_burst_ = FALSE;
+ }
+
if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
ourfinisacked = TRUE;
}
***************
*** , ****
--- , ----
// don't really have a process anyhow, just
// accept the data here as-is (i.e. don't
// require being in ESTABLISHED state)
+
+ /* Mohammad: For DCTCP state machine */
+ if (dctcp_ && ce_transition && ((rcv_nxt_ - last_ack_sent_) > )) {
+ // Must send an immediate ACK with with previous ECN state
+ // before transitioning to new state
+ flags_ |= TF_ACKNOW;
+ recent_ce_ = !recent_ce_;
+ send_much(, REASON_NORMAL, maxburst_);
+ recent_ce_ = !recent_ce_;
+ }
+
flags_ |= TF_DELACK;
+ // Mohammad
+ delack_timer_.resched(delack_interval_);
+
rcv_nxt_ += datalen;
tiflags = tcph->flags() & TH_FIN; ***************
*** , ****
--- , ----
// segments or hole-fills. Also,
// send an ACK (or SACK) to the other side right now.
// Note that we may have just a FIN here (datalen = 0)
+
+ /* Note: The DCTCP receiver conveys the ECN-CE
+ received on each out-of-order data packet */
+
int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes
tiflags = reass(pkt);
if (rcv_nxt_ > rcv_nxt_old_) {
***************
*** , ****
--- , ----
}
reset_rtx_timer();
t_seqno_ = (highest_ack_ < ) ? iss_ : int(highest_ack_);
+ dctcp_alpha_update_seq = t_seqno_;
+ dctcp_maxseq = dctcp_alpha_update_seq;
fastrecov_ = FALSE;
dupacks_ = ;
}
+
+ /*
+ * Update dctcp alpha based on the ecn bit in the received packet.
+ * This procedure is called only when dctcp_ is 1.
+ */
+ void FullTcpAgent::update_dctcp_alpha(Packet *pkt)
+ {
+ int ecnbit = hdr_flags::access(pkt)->ecnecho();
+ int ackno = hdr_tcp::access(pkt)->ackno();
+ int acked_bytes = ackno - highest_ack_;
+
+ if (acked_bytes <= )
+ acked_bytes = size_;
+ dctcp_total += acked_bytes;
+ if (ecnbit) {
+ dctcp_marked += acked_bytes;
+ }
+
+ /* Check for barrier indicating its time to recalculate alpha.
+ * This code basically updated alpha roughly once per RTT.
+ */
+ if (ackno > dctcp_alpha_update_seq) {
+ double temp_alpha;
+ dctcp_alpha_update_seq = dctcp_maxseq;
+ if (dctcp_total > )
+ temp_alpha = ((double) dctcp_marked) / dctcp_total;
+ else
+ temp_alpha = 0.0;
+
+ dctcp_alpha_ = ( - dctcp_g_) * dctcp_alpha_ + dctcp_g_ * temp_alpha;
+ dctcp_marked = ;
+ dctcp_total = ;
+ }
+ }
+
+
/*
* deal with timers going off.
* 2 types for now:
***************
*** 2662,2668 ****
flags_ |= TF_ACKNOW;
send_much(1, REASON_NORMAL, 0);
}
! delack_timer_.resched(delack_interval_);
break;
default:
fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
--- 2802,2809 ----
flags_ |= TF_ACKNOW;
send_much(1, REASON_NORMAL, 0);
}
! // Mohammad
! // delack_timer_.resched(delack_interval_);
break;
default:
fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
***************
*** 2874,2879 ****
--- 3015,3023 ----
* packet. -M. Weigle 6/19/02
*/
last_cwnd_action_ = CWND_ACTION_DUPACK;
+ /* Mohammad: cut window by half when we have 3 dup ack */
+ if (dctcp_)
+ slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
cancel_rtx_timer();
rtt_active_ = FALSE;
int amt = fast_retransmit(highest_ack_);
Only in ns-2.35/tcp: tcp-full.cc~
diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp-full.h ns-2.35/tcp/tcp-full.h
*** ns-allinone-2.35/ns-2.35/tcp/tcp-full.h -- ::52.000000000 -
--- ns-2.35/tcp/tcp-full.h -- ::10.052777998 -
***************
*** , ****
last_send_time_(-1.0), infinite_send_(FALSE), irs_(-),
delack_timer_(this), flags_(),
state_(TCPS_CLOSED), recent_ce_(FALSE),
! last_state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(-) { } ~FullTcpAgent() { cancel_timers(); rq_.clear(); }
virtual void recv(Packet *pkt, Handler*);
--- , ----
last_send_time_(-1.0), infinite_send_(FALSE), irs_(-),
delack_timer_(this), flags_(),
state_(TCPS_CLOSED), recent_ce_(FALSE),
! last_state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(-),
! dctcp_total(), dctcp_marked(), dctcp_alpha_update_seq(),
! dctcp_maxseq(), ce_transition() { } ~FullTcpAgent() { cancel_timers(); rq_.clear(); }
virtual void recv(Packet *pkt, Handler*);
***************
*** , ****
--- , ----
void finish();
void reset_rtx_timer(int); // adjust the rtx timer + void update_dctcp_alpha(Packet*); // DCTCP alpha update
+
virtual void timeout_action(); // what to do on rtx timeout
virtual void dupack_action(); // what to do on dup acks
virtual void pack_action(Packet*); // action on partial acks
***************
*** , ****
--- , ----
int last_state_; /* FSM state at last pkt recv */
int rcv_nxt_; /* next sequence number expected */
ReassemblyQueue rq_; /* TCP reassembly queue */
+
+ /*
+ * variables for DCTCP
+ */
+ int dctcp_total;
+ int dctcp_marked;
+ int dctcp_alpha_update_seq;
+ int dctcp_maxseq;
+ int ce_transition;
+
/*
* the following are part of a tcpcb in "real" RFC1323 TCP
*/
Only in ns-2.35/tcp: tcp-full.h~
diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp.h ns-2.35/tcp/tcp.h
*** ns-allinone-2.35/ns-2.35/tcp/tcp.h -- ::57.000000000 -
--- ns-2.35/tcp/tcp.h -- ::10.049778005 -
***************
*** , ****
#define CWND_HALF_WITH_MIN 0x00000200
#define TCP_IDLE 0x00000400
#define NO_OUTSTANDING_DATA 0x00000800
!
/*
* tcp_tick_:
* default 0.1,
--- 104,111 ----
#define CWND_HALF_WITH_MIN 0x00000200
#define TCP_IDLE 0x00000400
#define NO_OUTSTANDING_DATA 0x00000800
! #define CLOSE_SSTHRESH_DCTCP 0x00001000
! #define CLOSE_CWND_DCTCP 0x00002000
/*
* tcp_tick_:
* default 0.1,
***************
*** 432,437 ****
--- 433,444 ---- /* Used for ECN */
int ecn_; /* Explicit Congestion Notification */
+
+ /* Use for DCTCP */
+ int dctcp_;
+ double dctcp_alpha_;
+ double dctcp_g_;
+
int cong_action_; /* Congestion Action. True to indicate
that the sender responded to congestion. */
int ecn_burst_; /* True when the previous ACK packet
Only in ns-2.35/tcp: tcp.h~