[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[ns] fix to "bad ACK for our SYN"--a possible FullTcp bug
Hi,
I found something could be a bug in tcp-full.cc.
When to establish a two-way data channel using FullTcp like
a client/server model, error occurs during client actively connects
to the server.
My configuration is like this
server---client
Tcl code:
$ns attach-agent $server $stcp ;#stcp and ctcp are FullTcp agents
$ns attache-agent $client $ctcp
$ctcp set fid_ 0
$stcp set fid_ 0
$ns connect $ctcp $stcp
set ctarget $ctcp target
set starget $stcp target
$ctcp target $stcp ;# seldom used in this way, but needed in
connector::send/recv
$stcp target $ctcp
$stcp listen
$ctcp connection ;# my exported command from tcp-full.cc, just call
connect() in it.
# when connecting, the above mentioned error occurs
$ctcp target $ctarget ;#purely for trace....
$stcp target $starget
$ctcp advanceby 1 ;# client request
$stcp advanceby 1 ;#server response
That just mimics the real world code.
In tcp-full.cc, the sendpacket() in output() is placed above maxseq_ =
highest, which
is fine in real systems, but incorrect in simulations. the sendpacket()
actually calls the target_->recv()
(in agent.h), and in turn comes into FullTcp::recv() which checks the
maxseq_ with the incoming ack.
So the update of maxseq_ should come before sendpacket().
The modification to 2.1b7 is:
tcp-full.cc line616:
-----------------------------------------
// sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
/*
* if we have reacted to congestion recently, the
* slowdown() procedure will have set cong_action_ and
* sendpacket will have copied that to the outgoing pkt
* CACT field. If that packet contains data, then
* it will be reliably delivered, so we are free to turn off the
* cong_action_ state now If only a pure ACK, we keep the state
* around until we actually send a segment
*/
int reliable = datalen + syn + fin; // seq #'s reliably sent
if (cong_action_ && reliable > 0)
cong_action_ = FALSE;
/*
* SYNs and FINs each use up one sequence number, but
* there's no reason to advance t_seqno_ by one for a FIN
*/
if (!fin && seqno == t_seqno_) {
t_seqno_ += reliable;
}
// highest: greatest sequence number sent + 1
// and adjusted for SYNs and FINs which use up one number
int highest = seqno + reliable;
if (highest > maxseq_) {
maxseq_ = highest;
//
// if we are using conventional RTT estimation,
// establish timing on this segment
//
if (!ts_option_ && rtt_active_ == FALSE) {
rtt_active_ = TRUE; // set timer
rtt_seq_ = seqno; // timed seq #
rtt_ts_ = now(); // when set
}
}
/*sendpacket moved here*/
sendpacket(seqno, rcv_nxt_, pflags, datalen, reason);
/*
* Data sent (as far as we can tell).
* Any pending ACK has now been sent.
*/
flags_ &= ~(TF_ACKNOW|TF_DELACK);
------------------------------
This works for 2.1b7.
Cheers
Huamin