1 diff -crbB ns-allinone-2.35/ns-2.35/queue/red.cc ns-2.35/queue/red.cc
2 *** ns-allinone-2.35/ns-2.35/queue/red.cc 2011-10-02 15:32:34.000000000 -0700
3 --- ns-2.35/queue/red.cc 2012-03-19 02:40:10.827778003 -0700
4 ***************
5 *** 559,565 ****
6 edv_.count_bytes = 0;
7 hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
8 if (edp_.setbit && hf->ect() &&
9 ! (!edp_.use_mark_p || edv_.v_prob1 < edp_.mark_p)) {
10 hf->ce() = 1; // mark Congestion Experienced bit
11 // Tell the queue monitor here - call emark(pkt)
12 return (0); // no drop
13 --- 559,565 ----
14 edv_.count_bytes = 0;
15 hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
16 if (edp_.setbit && hf->ect() &&
17 ! (!edp_.use_mark_p || edv_.v_prob1 <= edp_.mark_p)) { // For DCTCP: '<' is changed to '<=' here
18 hf->ce() = 1; // mark Congestion Experienced bit
19 // Tell the queue monitor here - call emark(pkt)
20 return (0); // no drop
21 Only in ns-2.35/queue: red.cc~
22 diff -crbB ns-allinone-2.35/ns-2.35/tcl/lib/ns-default.tcl ns-2.35/tcl/lib/ns-default.tcl
23 *** ns-allinone-2.35/ns-2.35/tcl/lib/ns-default.tcl 2010-07-03 15:45:45.000000000 -0700
24 --- ns-2.35/tcl/lib/ns-default.tcl 2012-03-19 02:40:08.415778003 -0700
25 ***************
26 *** 1026,1031 ****
27 --- 1026,1035 ----
28
29 Agent/TCP set SetCWRonRetransmit_ true ; # added on 2005/06/19.
30 # default changed on 2008/06/05.
31 + # DCTCP
32 + Agent/TCP set dctcp_ false;
33 + Agent/TCP set dctcp_alpha_ 0.0;
34 + Agent/TCP set dctcp_g_ 0.0625;
35
36 # XXX Generate nam trace or plain old text trace for variables.
37 # When it's true, generate nam trace.
38 Only in ns-2.35/tcl/lib: ns-default.tcl~
39 Only in ns-2.35/tcp: .swp
40 diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp.cc ns-2.35/tcp/tcp.cc
41 *** ns-allinone-2.35/ns-2.35/tcp/tcp.cc 2011-06-19 21:51:46.000000000 -0700
42 --- ns-2.35/tcp/tcp.cc 2012-03-19 02:40:09.966778001 -0700
43 ***************
44 *** 101,106 ****
45 --- 101,109 ----
46 bind("necnresponses_", &necnresponses_);
47 bind("ncwndcuts_", &ncwndcuts_);
48 bind("ncwndcuts1_", &ncwndcuts1_);
49 + bind("dctcp_", &dctcp_);
50 + bind("dctcp_alpha_", &dctcp_alpha_);
51 + bind("dctcp_g_", &dctcp_g_);
52 #endif /* TCP_DELAY_BIND_ALL */
53
54 }
55 ***************
56 *** 123,128 ****
57 --- 126,136 ----
58 delay_bind_init_one("overhead_");
59 delay_bind_init_one("tcpTick_");
60 delay_bind_init_one("ecn_");
61 + // DCTCP
62 + delay_bind_init_one("dctcp_");
63 + delay_bind_init_one("dctcp_alpha_");
64 + delay_bind_init_one("dctcp_g_");
65 +
66 delay_bind_init_one("SetCWRonRetransmit_");
67 delay_bind_init_one("old_ecn_");
68 delay_bind_init_one("bugfix_ss_");
69 ***************
70 *** 234,239 ****
71 --- 242,251 ----
72 if (delay_bind(varName, localName, "overhead_", &overhead_, tracer)) return TCL_OK;
73 if (delay_bind(varName, localName, "tcpTick_", &tcp_tick_, tracer)) return TCL_OK;
74 if (delay_bind_bool(varName, localName, "ecn_", &ecn_, tracer)) return TCL_OK;
75 + // Mohammad
76 + if (delay_bind_bool(varName, localName, "dctcp_", &dctcp_, tracer)) return TCL_OK;
77 + if (delay_bind(varName, localName, "dctcp_alpha_", &dctcp_alpha_ , tracer)) return TCL_OK;
78 + if (delay_bind(varName, localName, "dctcp_g_", &dctcp_g_ , tracer)) return TCL_OK;
79 if (delay_bind_bool(varName, localName, "SetCWRonRetransmit_", &SetCWRonRetransmit_, tracer)) return TCL_OK;
80 if (delay_bind_bool(varName, localName, "old_ecn_", &old_ecn_ , tracer)) return TCL_OK;
81 if (delay_bind_bool(varName, localName, "bugfix_ss_", &bugfix_ss_ , tracer)) return TCL_OK;
82 ***************
83 *** 1297,1302 ****
84 --- 1309,1316 ----
85 } else {
86 ssthresh_ = (int) decreasewin;
87 }
88 + else if (how & CLOSE_SSTHRESH_DCTCP)
89 + ssthresh_ = (int) ((1 - dctcp_alpha_/2.0) * windowd());
90 else if (how & THREE_QUARTER_SSTHRESH)
91 if (ssthresh_ < 3*cwnd_/4)
92 ssthresh_ = (int)(3*cwnd_/4);
93 ***************
94 *** 1306,1311 ****
95 --- 1321,1328 ----
96 if (first_decrease_ == 1 || slowstart || decrease_num_ == 0.5) {
97 cwnd_ = halfwin;
98 } else cwnd_ = decreasewin;
99 + else if (how & CLOSE_CWND_DCTCP)
100 + cwnd_ = (1 - dctcp_alpha_/2.0) * windowd();
101 else if (how & CWND_HALF_WITH_MIN) {
102 // We have not thought about how non-standard TCPs, with
103 // non-standard values of decrease_num_, should respond
104 ***************
105 *** 1328,1334 ****
106 }
107 if (ssthresh_ < 2)
108 ssthresh_ = 2;
109 ! if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE))
110 cong_action_ = TRUE;
111
112 fcnt_ = count_ = 0;
113 --- 1345,1353 ----
114 }
115 if (ssthresh_ < 2)
116 ssthresh_ = 2;
117 ! if (cwnd_ < 1)
118 ! cwnd_ = 1;
119 ! if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE|CLOSE_CWND_DCTCP))
120 cong_action_ = TRUE;
121
122 fcnt_ = count_ = 0;
123 ***************
124 *** 1429,1434 ****
125 --- 1448,1456 ----
126 rtt_backoff();
127 else ecn_backoff_ = 1;
128 } else ecn_backoff_ = 0;
129 + if (dctcp_)
130 + slowdown(CLOSE_CWND_DCTCP|CLOSE_SSTHRESH_DCTCP);
131 + else
132 slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);
133 ++necnresponses_ ;
134 // added by sylvia to count number of ecn responses
135 Only in ns-2.35/tcp: tcp.cc~
136 diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp-full.cc ns-2.35/tcp/tcp-full.cc
137 *** ns-allinone-2.35/ns-2.35/tcp/tcp-full.cc 2010-03-07 21:54:54.000000000 -0800
138 --- ns-2.35/tcp/tcp-full.cc 2012-03-19 02:40:10.049778005 -0700
139 ***************
140 *** 871,876 ****
141 --- 871,881 ----
142 /* Set ect() to 0. -M. Weigle 1/19/05 */
143 fh->ect() = 0;
144 }
145 +
146 + // For DCTCP, ect should be set on all packets
147 + if (dctcp_)
148 + fh->ect() = ect_;
149 +
150 if (ecn_ && ect_ && recent_ce_ ) {
151 // This is needed here for the ACK in a SYN, SYN/ACK, ACK
152 // sequence.
153 ***************
154 *** 960,968 ****
155 // Q: how can this happen?
156
157 if (maxseg_ == 0)
158 ! maxseg_ = size_ - headersize();
159 else
160 size_ = maxseg_ + headersize();
161
162 int is_retransmit = (seqno < maxseq_);
163 int quiet = (highest_ack_ == maxseq_);
164 --- 965,976 ----
165 // Q: how can this happen?
166
167 if (maxseg_ == 0)
168 ! maxseg_ = size_; // Mohammad: changed from size_ - headersize();
169 ! /* Mohammad: This else condition is unnecessary and conflates
170 ! * with tcp.cc
171 else
172 size_ = maxseg_ + headersize();
173 + */
174
175 int is_retransmit = (seqno < maxseq_);
176 int quiet = (highest_ack_ == maxseq_);
177 ***************
178 *** 1156,1161 ****
179 --- 1164,1171 ----
180 */
181 flags_ &= ~(TF_ACKNOW|TF_DELACK);
182
183 + delack_timer_.force_cancel();
184 +
185 /*
186 * if we have reacted to congestion recently, the
187 * slowdown() procedure will have set cong_action_ and
188 ***************
189 *** 1178,1183 ****
190 --- 1188,1195 ----
191 // and adjusted for SYNs and FINs which use up one number
192
193 int highest = seqno + reliable;
194 + if (highest > dctcp_maxseq)
195 + dctcp_maxseq = highest;
196 if (highest > maxseq_) {
197 maxseq_ = highest;
198 //
199 ***************
200 *** 1415,1421 ****
201 {
202 // we are now going to fast-retransmit and willtrace that event
203 trace_event("FAST_RETX");
204 -
205 recover_ = maxseq_; // recovery target
206 last_cwnd_action_ = CWND_ACTION_DUPACK;
207 return(foutput(seq, REASON_DUPACK)); // send one pkt
208 --- 1427,1432 ----
209 ***************
210 *** 1564,1574 ****
211 --- 1576,1594 ----
212 * at time t0 = (0.0 + k * interval_) for some k such
213 * that t0 > now
214 */
215 + /*
216 + * Mohammad: commented this out for more efficient
217 + * delayed ack generation.
218 + *
219 if (delack_interval_ > 0.0 &&
220 (delack_timer_.status() != TIMER_PENDING)) {
221 int last = int(now() / delack_interval_);
222 delack_timer_.resched(delack_interval_ * (last + 1.0) - now());
223 }
224 + */
225 +
226 + if (dctcp_)
227 + update_dctcp_alpha(pkt);
228
229 /*
230 * Try header prediction: in seq data or in seq pure ACK
231 ***************
232 *** 1597,1602 ****
233 --- 1617,1641 ----
234 //
235
236 if (ecn_) {
237 + if (dctcp_) { // DCTCP
238 + if (fh->ce() && fh->ect()) {
239 + // no CWR from peer yet... arrange to
240 + // keep sending ECNECHO
241 + if (recent_ce_ == FALSE) {
242 + ce_transition = 1;
243 + recent_ce_ = TRUE;
244 + } else {
245 + ce_transition = 0;
246 + }
247 + } else if (datalen > 0 && !fh->ce() && fh->ect()){
248 + if (recent_ce_ == TRUE) {
249 + ce_transition = 1;
250 + recent_ce_ = FALSE;
251 + } else {
252 + ce_transition = 0;
253 + }
254 + }
255 + } else {
256 if (fh->ce() && fh->ect()) {
257 // no CWR from peer yet... arrange to
258 // keep sending ECNECHO
259 ***************
260 *** 1607,1612 ****
261 --- 1646,1652 ----
262 recent_ce_ = FALSE;
263 }
264 }
265 + }
266
267 // Header predication basically looks to see
268 // if the incoming packet is an expected pure ACK
269 ***************
270 *** 1638,1645 ****
271 --- 1678,1698 ----
272 // this routine scans all tcpcb's looking for
273 // DELACK segments and when it finds them
274 // changes DELACK to ACKNOW and calls tcp_output()
275 +
276 + /* DCTCP receiver state machine */
277 + if (dctcp_ && ce_transition && ((rcv_nxt_ - last_ack_sent_) > 0)) {
278 + // Must send an immediate ACK with with previous ECN state
279 + // before transitioning to new state
280 + flags_ |= TF_ACKNOW;
281 + recent_ce_ = !recent_ce_;
282 + send_much(1, REASON_NORMAL, maxburst_);
283 + recent_ce_ = !recent_ce_;
284 + }
285 +
286 rcv_nxt_ += datalen;
287 flags_ |= TF_DELACK;
288 + // Mohammad
289 + delack_timer_.resched(delack_interval_);
290 recvBytes(datalen); // notify application of "delivery"
291 //
292 // special code here to simulate the operation
293 ***************
294 *** 1816,1821 ****
295 --- 1869,1876 ----
296 */
297 if (datalen > 0) {
298 flags_ |= TF_DELACK; // data there: wait
299 + // Mohammad
300 + delack_timer_.resched(delack_interval_);
301 } else {
302 flags_ |= TF_ACKNOW; // ACK peer's SYN
303 }
304 ***************
305 *** 2131,2140 ****
306 // cong_action bit
307 //
308 if (ecn_) {
309 ! if (fh->ce() && fh->ect())
310 recent_ce_ = TRUE;
311 ! else if (fh->cwr())
312 recent_ce_ = FALSE;
313 }
314
315 //
316 --- 2186,2216 ----
317 // cong_action bit
318 //
319 if (ecn_) {
320 ! if (dctcp_) { // Mohammad
321 ! if (fh->ce() && fh->ect()) {
322 ! // no CWR from peer yet... arrange to
323 ! // keep sending ECNECHO
324 ! if (recent_ce_ == FALSE) {
325 ! ce_transition = 1;
326 recent_ce_ = TRUE;
327 ! } else {
328 ! ce_transition = 0;
329 ! }
330 ! } else if (datalen > 0 && !fh->ce() && fh->ect()){
331 ! if (recent_ce_ == TRUE) {
332 ! ce_transition = 1;
333 recent_ce_ = FALSE;
334 + } else {
335 + ce_transition = 0;
336 + }
337 + }
338 + } else {
339 + if (fh->ce() && fh->ect()) {
340 + recent_ce_ = TRUE;
341 + } else if (fh->cwr()) {
342 + recent_ce_ = FALSE;
343 + }
344 + }
345 }
346
347 //
348 ***************
349 *** 2297,2307 ****
350 if ((!delay_growth_ || (rcv_nxt_ > 0)) &&
351 last_state_ == TCPS_ESTABLISHED) {
352 if (!partial || open_cwnd_on_pack_) {
353 ! if (!ect_ || !hdr_flags::access(pkt)->ecnecho())
354 opencwnd();
355 }
356 }
357
358 if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
359 ourfinisacked = TRUE;
360 }
361 --- 2373,2391 ----
362 if ((!delay_growth_ || (rcv_nxt_ > 0)) &&
363 last_state_ == TCPS_ESTABLISHED) {
364 if (!partial || open_cwnd_on_pack_) {
365 ! if (!ect_ || !hdr_flags::access(pkt)->ecnecho() || ecn_burst_)
366 opencwnd();
367 }
368 }
369
370 + // Mohammad: Detect bursts of ECN marks
371 + if (ect_) {
372 + if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())
373 + ecn_burst_ = TRUE;
374 + else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())
375 + ecn_burst_ = FALSE;
376 + }
377 +
378 if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {
379 ourfinisacked = TRUE;
380 }
381 ***************
382 *** 2395,2401 ****
383 --- 2479,2499 ----
384 // don't really have a process anyhow, just
385 // accept the data here as-is (i.e. don't
386 // require being in ESTABLISHED state)
387 +
388 + /* Mohammad: For DCTCP state machine */
389 + if (dctcp_ && ce_transition && ((rcv_nxt_ - last_ack_sent_) > 0)) {
390 + // Must send an immediate ACK with with previous ECN state
391 + // before transitioning to new state
392 + flags_ |= TF_ACKNOW;
393 + recent_ce_ = !recent_ce_;
394 + send_much(1, REASON_NORMAL, maxburst_);
395 + recent_ce_ = !recent_ce_;
396 + }
397 +
398 flags_ |= TF_DELACK;
399 + // Mohammad
400 + delack_timer_.resched(delack_interval_);
401 +
402 rcv_nxt_ += datalen;
403 tiflags = tcph->flags() & TH_FIN;
404
405 ***************
406 *** 2412,2417 ****
407 --- 2510,2519 ----
408 // segments or hole-fills. Also,
409 // send an ACK (or SACK) to the other side right now.
410 // Note that we may have just a FIN here (datalen = 0)
411 +
412 + /* Note: The DCTCP receiver conveys the ECN-CE
413 + received on each out-of-order data packet */
414 +
415 int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes
416 tiflags = reass(pkt);
417 if (rcv_nxt_ > rcv_nxt_old_) {
418 ***************
419 *** 2608,2616 ****
420 --- 2710,2756 ----
421 }
422 reset_rtx_timer(1);
423 t_seqno_ = (highest_ack_ < 0) ? iss_ : int(highest_ack_);
424 + dctcp_alpha_update_seq = t_seqno_;
425 + dctcp_maxseq = dctcp_alpha_update_seq;
426 fastrecov_ = FALSE;
427 dupacks_ = 0;
428 }
429 +
430 + /*
431 + * Update dctcp alpha based on the ecn bit in the received packet.
432 + * This procedure is called only when dctcp_ is 1.
433 + */
434 + void FullTcpAgent::update_dctcp_alpha(Packet *pkt)
435 + {
436 + int ecnbit = hdr_flags::access(pkt)->ecnecho();
437 + int ackno = hdr_tcp::access(pkt)->ackno();
438 + int acked_bytes = ackno - highest_ack_;
439 +
440 + if (acked_bytes <= 0)
441 + acked_bytes = size_;
442 + dctcp_total += acked_bytes;
443 + if (ecnbit) {
444 + dctcp_marked += acked_bytes;
445 + }
446 +
447 + /* Check for barrier indicating its time to recalculate alpha.
448 + * This code basically updated alpha roughly once per RTT.
449 + */
450 + if (ackno > dctcp_alpha_update_seq) {
451 + double temp_alpha;
452 + dctcp_alpha_update_seq = dctcp_maxseq;
453 + if (dctcp_total > 0)
454 + temp_alpha = ((double) dctcp_marked) / dctcp_total;
455 + else
456 + temp_alpha = 0.0;
457 +
458 + dctcp_alpha_ = (1 - dctcp_g_) * dctcp_alpha_ + dctcp_g_ * temp_alpha;
459 + dctcp_marked = 0;
460 + dctcp_total = 0;
461 + }
462 + }
463 +
464 +
465 /*
466 * deal with timers going off.
467 * 2 types for now:
468 ***************
469 *** 2662,2668 ****
470 flags_ |= TF_ACKNOW;
471 send_much(1, REASON_NORMAL, 0);
472 }
473 ! delack_timer_.resched(delack_interval_);
474 break;
475 default:
476 fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
477 --- 2802,2809 ----
478 flags_ |= TF_ACKNOW;
479 send_much(1, REASON_NORMAL, 0);
480 }
481 ! // Mohammad
482 ! // delack_timer_.resched(delack_interval_);
483 break;
484 default:
485 fprintf(stderr, "%f: FullTcpAgent(%s) Unknown Timeout type %d\n",
486 ***************
487 *** 2874,2879 ****
488 --- 3015,3023 ----
489 * packet. -M. Weigle 6/19/02
490 */
491 last_cwnd_action_ = CWND_ACTION_DUPACK;
492 + /* Mohammad: cut window by half when we have 3 dup ack */
493 + if (dctcp_)
494 + slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);
495 cancel_rtx_timer();
496 rtt_active_ = FALSE;
497 int amt = fast_retransmit(highest_ack_);
498 Only in ns-2.35/tcp: tcp-full.cc~
499 diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp-full.h ns-2.35/tcp/tcp-full.h
500 *** ns-allinone-2.35/ns-2.35/tcp/tcp-full.h 2008-10-14 10:42:52.000000000 -0700
501 --- ns-2.35/tcp/tcp-full.h 2012-03-19 02:40:10.052777998 -0700
502 ***************
503 *** 120,126 ****
504 last_send_time_(-1.0), infinite_send_(FALSE), irs_(-1),
505 delack_timer_(this), flags_(0),
506 state_(TCPS_CLOSED), recent_ce_(FALSE),
507 ! last_state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(-1) { }
508
509 ~FullTcpAgent() { cancel_timers(); rq_.clear(); }
510 virtual void recv(Packet *pkt, Handler*);
511 --- 120,128 ----
512 last_send_time_(-1.0), infinite_send_(FALSE), irs_(-1),
513 delack_timer_(this), flags_(0),
514 state_(TCPS_CLOSED), recent_ce_(FALSE),
515 ! last_state_(TCPS_CLOSED), rq_(rcv_nxt_), last_ack_sent_(-1),
516 ! dctcp_total(0), dctcp_marked(0), dctcp_alpha_update_seq(0),
517 ! dctcp_maxseq(0), ce_transition(0) { }
518
519 ~FullTcpAgent() { cancel_timers(); rq_.clear(); }
520 virtual void recv(Packet *pkt, Handler*);
521 ***************
522 *** 183,188 ****
523 --- 185,192 ----
524 void finish();
525 void reset_rtx_timer(int); // adjust the rtx timer
526
527 + void update_dctcp_alpha(Packet*); // DCTCP alpha update
528 +
529 virtual void timeout_action(); // what to do on rtx timeout
530 virtual void dupack_action(); // what to do on dup acks
531 virtual void pack_action(Packet*); // action on partial acks
532 ***************
533 *** 236,241 ****
534 --- 240,255 ----
535 int last_state_; /* FSM state at last pkt recv */
536 int rcv_nxt_; /* next sequence number expected */
537 ReassemblyQueue rq_; /* TCP reassembly queue */
538 +
539 + /*
540 + * variables for DCTCP
541 + */
542 + int dctcp_total;
543 + int dctcp_marked;
544 + int dctcp_alpha_update_seq;
545 + int dctcp_maxseq;
546 + int ce_transition;
547 +
548 /*
549 * the following are part of a tcpcb in "real" RFC1323 TCP
550 */
551 Only in ns-2.35/tcp: tcp-full.h~
552 diff -crbB ns-allinone-2.35/ns-2.35/tcp/tcp.h ns-2.35/tcp/tcp.h
553 *** ns-allinone-2.35/ns-2.35/tcp/tcp.h 2011-08-26 12:29:57.000000000 -0700
554 --- ns-2.35/tcp/tcp.h 2012-03-19 02:40:10.049778005 -0700
555 ***************
556 *** 104,110 ****
557 #define CWND_HALF_WITH_MIN 0x00000200
558 #define TCP_IDLE 0x00000400
559 #define NO_OUTSTANDING_DATA 0x00000800
560 !
561 /*
562 * tcp_tick_:
563 * default 0.1,
564 --- 104,111 ----
565 #define CWND_HALF_WITH_MIN 0x00000200
566 #define TCP_IDLE 0x00000400
567 #define NO_OUTSTANDING_DATA 0x00000800
568 ! #define CLOSE_SSTHRESH_DCTCP 0x00001000
569 ! #define CLOSE_CWND_DCTCP 0x00002000
570 /*
571 * tcp_tick_:
572 * default 0.1,
573 ***************
574 *** 432,437 ****
575 --- 433,444 ----
576
577 /* Used for ECN */
578 int ecn_; /* Explicit Congestion Notification */
579 +
580 + /* Use for DCTCP */
581 + int dctcp_;
582 + double dctcp_alpha_;
583 + double dctcp_g_;
584 +
585 int cong_action_; /* Congestion Action. True to indicate
586 that the sender responded to congestion. */
587 int ecn_burst_; /* True when the previous ACK packet
588 Only in ns-2.35/tcp: tcp.h~