00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <sys/types.h>
00038 #include <math.h>
00039
00040
00041 #include "ip.h"
00042 #include "tcp-rfc793edu.h"
00043 #include "flags.h"
00044
00045
00046
00047
00048
00049
00050 static class RFC793eduTcpClass : public TclClass {
00051 public:
00052 RFC793eduTcpClass() : TclClass("Agent/TCP/RFC793edu") {}
00053 TclObject* create(int, const char*const*) {
00054 return (new RFC793eduTcpAgent());
00055 }
00056 } class_rfc793edu;
00057
00058
00059 RFC793eduTcpAgent::RFC793eduTcpAgent() : TcpAgent()
00060 {
00061 }
00062
00063 void
00064 RFC793eduTcpAgent::delay_bind_init_all()
00065 {
00066 delay_bind_init_one("add793expbackoff_");
00067 delay_bind_init_one("add793jacobsonrtt_");
00068 delay_bind_init_one("add793fastrtx_");
00069 delay_bind_init_one("add793slowstart_");
00070 delay_bind_init_one("add793additiveinc_");
00071 delay_bind_init_one("add793karnrtt_");
00072 delay_bind_init_one("add793exponinc_");
00073 delay_bind_init_one("rto_");
00074 TcpAgent::delay_bind_init_all();
00075 reset();
00076 }
00077
00078 int
00079 RFC793eduTcpAgent::delay_bind_dispatch(const char *varName,
00080 const char *localName,TclObject *tracer)
00081 {
00082 if (delay_bind_bool(varName, localName, "add793expbackoff_",
00083 &add793expbackoff_, tracer))
00084 return TCL_OK;
00085 if (delay_bind_bool(varName, localName, "add793jacobsonrtt_",
00086 &add793jacobsonrtt_, tracer))
00087 return TCL_OK;
00088 if (delay_bind_bool(varName, localName, "add793fastrtx_",
00089 &add793fastrtx_, tracer))
00090 return TCL_OK;
00091 if (delay_bind_bool(varName, localName, "add793slowstart_",
00092 &add793slowstart_, tracer))
00093 return TCL_OK;
00094 if (delay_bind_bool(varName, localName, "add793slowstart_",
00095 &add793slowstart_, tracer))
00096 return TCL_OK;
00097 if (delay_bind_bool(varName, localName, "add793additiveinc_",
00098 &add793additiveinc_, tracer))
00099 return TCL_OK;
00100 if (delay_bind_bool(varName, localName, "add793karnrtt_",
00101 &add793karnrtt_, tracer))
00102 return TCL_OK;
00103 if (delay_bind_bool(varName, localName, "add793exponinc_",
00104 &add793exponinc_, tracer))
00105 return TCL_OK;
00106 if (delay_bind(varName, localName, "rto_",
00107 &rto_, tracer))
00108 return TCL_OK;
00109 return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
00110 }
00111
00112 void RFC793eduTcpAgent::reset()
00113 {
00114
00115
00116 rto_ = rtxcur_init_ / tcp_tick_;
00117 TcpAgent::reset();
00118 }
00119
00120
00121 void RFC793eduTcpAgent::rtt_update(double tao)
00122 {
00123 double now = Scheduler::instance().clock();
00124 if (ts_option_)
00125 t_rtt_ = int(tao /tcp_tick_ + 0.5);
00126 else {
00127 double sendtime = now - tao;
00128 sendtime += boot_time_;
00129 double tickoff = fmod(sendtime, tcp_tick_);
00130 t_rtt_ = int((tao + tickoff) / tcp_tick_);
00131 }
00132 if (t_rtt_ < 1)
00133 t_rtt_ = 1;
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 if (t_srtt_ != 0) {
00145 register short delta;
00146 delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);
00147 if ((t_srtt_ += delta) <= 0)
00148 t_srtt_ = 1;
00149 if (delta < 0)
00150 delta = -delta;
00151 delta -= (t_rttvar_ >> T_RTTVAR_BITS);
00152 if ((t_rttvar_ += delta) <= 0)
00153 t_rttvar_ = 1;
00154 } else {
00155 t_srtt_ = t_rtt_ << T_SRTT_BITS;
00156 t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);
00157 }
00158
00159 if (add793jacobsonrtt_)
00160 {
00161
00162
00163
00164
00165
00166 rto_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) + t_srtt_) >> T_SRTT_BITS );
00167 }
00168 else {
00169
00170 rto_ = (t_srtt_ >> ( T_SRTT_BITS - 1) );
00171 }
00172 t_rtxcur_ = rto_ * tcp_tick_;
00173 return;
00174 }
00175
00176
00177 void RFC793eduTcpAgent::rtt_backoff()
00178 {
00179 if (add793expbackoff_) {
00180
00181
00182 if (t_backoff_ < 64)
00183 t_backoff_ <<= 1;
00184
00185 if (t_backoff_ > 8) {
00186
00187
00188
00189
00190
00191 t_rttvar_ += (t_srtt_ >> T_SRTT_BITS);
00192 t_srtt_ = 0;
00193 }
00194 }
00195
00196 else
00197 t_backoff_ = 1;
00198 }
00199
00200
00201 void RFC793eduTcpAgent::recv(Packet *pkt, Handler*)
00202 {
00203 hdr_tcp *tcph = hdr_tcp::access(pkt);
00204 #ifdef notdef
00205 if (pkt->type_ != PT_ACK) {
00206 Tcl::instance().evalf("%s error \"received non-ack\"",
00207 name());
00208 Packet::free(pkt);
00209 return;
00210 }
00211 #endif
00212 ++nackpack_;
00213 ts_peer_ = tcph->ts();
00214 int ecnecho = hdr_flags::access(pkt)->ecnecho();
00215 if (ecnecho && ecn_)
00216 ecn(tcph->seqno());
00217 recv_helper(pkt);
00218
00219 if (tcph->seqno() > last_ack_) {
00220 recv_newack_helper(pkt);
00221 if (last_ack_ == 0 && delay_growth_) {
00222 cwnd_ = initial_window();
00223 }
00224 } else if (tcph->seqno() == last_ack_) {
00225 if (hdr_flags::access(pkt)->eln_ && eln_) {
00226 tcp_eln(pkt);
00227 return;
00228 }
00229
00230 if ( (++dupacks_ == numdupacks_) && add793fastrtx_ ) {
00231 dupack_action();
00232 }
00233 }
00234 Packet::free(pkt);
00235
00236
00237
00238 send_much(0, 0, maxburst_);
00239 }
00240
00241
00242
00243 void RFC793eduTcpAgent::opencwnd()
00244 {
00245 if ( !(add793slowstart_ || add793exponinc_ || add793additiveinc_)) {
00246 cwnd_ = wnd_;
00247 } else if (((cwnd_ < ssthresh_) && (!add793additiveinc_))
00248 || add793exponinc_)
00249 {
00250
00251 if (add793exponinc_ && (cwnd_ < ssthresh_))
00252 cwnd_ = ssthresh_;
00253 else cwnd_ += 1;
00254 } else {
00255
00256 double f;
00257
00258 if (add793additiveinc_ && (cwnd_ < ssthresh_))
00259 cwnd_ = ssthresh_;
00260 else {
00261 switch (wnd_option_) {
00262 case 0:
00263 if (++count_ >= cwnd_) {
00264 count_ = 0;
00265 ++cwnd_;
00266 }
00267 break;
00268
00269 case 1:
00270
00271 cwnd_ += 1 / cwnd_;
00272 break;
00273
00274 case 2:
00275
00276
00277 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
00278 f *= f;
00279 f *= wnd_const_;
00280 f += fcnt_;
00281 if (f > cwnd_) {
00282 fcnt_ = 0;
00283 ++cwnd_;
00284 } else
00285 fcnt_ = f;
00286 break;
00287
00288 case 3:
00289 f = awnd_;
00290 f *= f;
00291 f *= wnd_const_;
00292 f += fcnt_;
00293 if (f > cwnd_) {
00294 fcnt_ = 0;
00295 ++cwnd_;
00296 } else
00297 fcnt_ = f;
00298 break;
00299
00300 case 4:
00301 f = awnd_;
00302 f *= wnd_const_;
00303 f += fcnt_;
00304 if (f > cwnd_) {
00305 fcnt_ = 0;
00306 ++cwnd_;
00307 } else
00308 fcnt_ = f;
00309 break;
00310 case 5:
00311 f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;
00312 f *= wnd_const_;
00313 f += fcnt_;
00314 if (f > cwnd_) {
00315 fcnt_ = 0;
00316 ++cwnd_;
00317 } else
00318 fcnt_ = f;
00319 break;
00320
00321 default:
00322 #ifdef notdef
00323
00324 error("illegal window option %d", wnd_option_);
00325 #endif
00326 abort();
00327 }
00328 }
00329 }
00330
00331 if (maxcwnd_ && (int(cwnd_) > maxcwnd_))
00332 cwnd_ = maxcwnd_;
00333
00334 return;
00335 }
00336
00337
00338 void RFC793eduTcpAgent::output(int seqno, int reason)
00339 {
00340 int force_set_rtx_timer = 0;
00341 Packet* p = allocpkt();
00342 hdr_tcp *tcph = hdr_tcp::access(p);
00343 hdr_flags* hf = hdr_flags::access(p);
00344 tcph->seqno() = seqno;
00345 tcph->ts() = Scheduler::instance().clock();
00346 tcph->ts_echo() = ts_peer_;
00347 tcph->reason() = reason;
00348 if (ecn_) {
00349 hf->ect() = 1;
00350 }
00351 if (cong_action_) {
00352 hf->cong_action() = TRUE;
00353 cong_action_ = FALSE;
00354 }
00355
00356 if (seqno == 0) {
00357 if (syn_) {
00358 hdr_cmn::access(p)->size() = tcpip_base_hdr_size_;
00359 }
00360 if (ecn_) {
00361 hf->ecnecho() = 1;
00362
00363 hf->ect() = 0;
00364 }
00365 }
00366 int bytes = hdr_cmn::access(p)->size();
00367
00368
00369 if (highest_ack_ == maxseq_)
00370 force_set_rtx_timer = 1;
00371
00372 output_helper(p);
00373
00374 ++ndatapack_;
00375 ndatabytes_ += bytes;
00376 send(p, 0);
00377 if (seqno == curseq_ && seqno > maxseq_)
00378 idle();
00379 if (seqno > maxseq_) {
00380 maxseq_ = seqno;
00381 if (!rtt_active_) {
00382 rtt_active_ = 1;
00383 if (seqno > rtt_seq_) {
00384 rtt_seq_ = seqno;
00385 rtt_ts_ = Scheduler::instance().clock();
00386 }
00387
00388 }
00389 } else {
00390 if (!add793karnrtt_) {
00391 rtt_active_ = 1;
00392 rtt_seq_ = seqno;
00393 rtt_ts_ = Scheduler::instance().clock();
00394 }
00395 ++nrexmitpack_;
00396 nrexmitbytes_ += bytes;
00397 }
00398 if (!(rtx_timer_.status() == TIMER_PENDING) || force_set_rtx_timer)
00399
00400 set_rtx_timer();
00401 }
00402
00403 void RFC793eduTcpAgent::recv_newack_helper(Packet *pkt) {
00404
00405 newack(pkt);
00406 if (!ect_ || !hdr_flags::access(pkt)->ecnecho() ||
00407 (old_ecn_ && ecn_burst_))
00408
00409
00410
00411 opencwnd();
00412 if (ect_) {
00413 if (!hdr_flags::access(pkt)->ecnecho())
00414 ecn_backoff_ = 0;
00415 if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())
00416 ecn_burst_ = TRUE;
00417 else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())
00418 ecn_burst_ = FALSE;
00419 }
00420 if (!ect_ && hdr_flags::access(pkt)->ecnecho() &&
00421 !hdr_flags::access(pkt)->cong_action())
00422 ect_ = 1;
00423
00424 if ((highest_ack_ >= curseq_-1) && !closed_) {
00425 closed_ = 1;
00426 finish();
00427 }
00428 }
00429
00430 void RFC793eduTcpAgent::newack(Packet* pkt)
00431 {
00432 double now = Scheduler::instance().clock();
00433 hdr_tcp *tcph = hdr_tcp::access(pkt);
00434
00435
00436
00437
00438 newtimer(pkt);
00439 dupacks_ = 0;
00440 last_ack_ = tcph->seqno();
00441 highest_ack_ = last_ack_;
00442
00443 if (t_seqno_ < last_ack_ + 1)
00444 t_seqno_ = last_ack_ + 1;
00445
00446
00447
00448
00449
00450
00451 hdr_flags *fh = hdr_flags::access(pkt);
00452 if (!fh->no_ts_) {
00453 if (ts_option_)
00454 rtt_update(now - tcph->ts_echo());
00455
00456 if (rtt_active_ && tcph->seqno() >= rtt_seq_) {
00457 if (!ect_ || !ecn_backoff_ ||
00458 !hdr_flags::access(pkt)->ecnecho()) {
00459
00460
00461
00462
00463 t_backoff_ = 1;
00464 ecn_backoff_ = 0;
00465 }
00466 rtt_active_ = 0;
00467 if (!ts_option_)
00468 rtt_update(now - rtt_ts_);
00469 }
00470 }
00471
00472 awnd_ *= 1.0 - wnd_th_;
00473 awnd_ += wnd_th_ * cwnd_;
00474 }
00475
00476