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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #include <stdio.h>
00067 #include <stdlib.h>
00068 #include <sys/types.h>
00069
00070 #include "ip.h"
00071 #include "tcp.h"
00072 #include "flags.h"
00073 #include "hdr_qs.h"
00074 #include "random.h"
00075 #include "tcp-sink.h"
00076
00077 #ifndef MIN
00078 #define MIN(x, y) ((x)<(y) ? (x) : (y))
00079 #endif
00080
00081 #if 0
00082 #define RBP_DEBUG_PRINTF(x) printf x
00083 #else
00084 #define RBP_DEBUG_PRINTF(x)
00085 #endif
00086
00087
00088 #define RBP_MIN_SEGMENTS 2
00089
00090
00091
00092
00093
00094
00095
00096 class QSNewRenoTcpAgent;
00097
00098 class QSNewRenoPaceTimer : public TimerHandler {
00099 public:
00100 QSNewRenoPaceTimer(QSNewRenoTcpAgent *a) : TimerHandler() { a_ = a; }
00101 protected:
00102 virtual void expire(Event *e);
00103 QSNewRenoTcpAgent *a_;
00104 };
00105
00106
00107 class QSNewRenoTcpAgent : public virtual NewRenoTcpAgent {
00108 friend class QSNewRenoPaceTimer;
00109 public:
00110 QSNewRenoTcpAgent();
00111 virtual void recv(Packet *pkt, Handler *);
00112 virtual void timeout(int tno);
00113 virtual void send_much(int force, int reason, int maxburst);
00114 virtual void output(int force, int reason);
00115
00116 double rbp_scale_;
00117
00118
00119 protected:
00120 void paced_send_one();
00121 int able_to_rbp_send_one();
00122
00123
00124 int rbp_segs_actually_paced_;
00125
00126 int ttl_diff_;
00127 int qs_approved_;
00128 int rate_request_;
00129
00130 int session_id_;
00131
00132 static int next_flow_;
00133
00134 enum rbp_modes { RBP_GOING, RBP_POSSIBLE, RBP_OFF };
00135 enum rbp_modes rbp_mode_;
00136 double rbp_inter_pace_delay_;
00137 QSNewRenoPaceTimer pace_timer_;
00138 };
00139
00140 int QSNewRenoTcpAgent::next_flow_ = 0;
00141
00142 static class QSNewRenoTcpClass : public TclClass {
00143 public:
00144 QSNewRenoTcpClass() : TclClass("Agent/TCP/Newreno/QS") {}
00145 TclObject* create(int, const char*const*) {
00146 return (new QSNewRenoTcpAgent());
00147 }
00148 } class_newreno_qs;
00149
00150
00151 void QSNewRenoPaceTimer::expire(Event *) { a_->paced_send_one(); }
00152
00153 QSNewRenoTcpAgent::QSNewRenoTcpAgent() : TcpAgent(),
00154 ttl_diff_(0), qs_approved_(0), rbp_mode_(RBP_OFF), pace_timer_(this)
00155 {
00156 bind("rbp_scale_", &rbp_scale_);
00157
00158
00159 bind("rbp_segs_actually_paced_", &rbp_segs_actually_paced_);
00160 bind("rbp_inter_pace_delay_", &rbp_inter_pace_delay_);
00161 bind("rate_request_", &rate_request_);
00162
00163 session_id_ = next_flow_ % 32;
00164 next_flow_ = session_id_ + 1;
00165 }
00166
00167 void
00168 QSNewRenoTcpAgent::recv(Packet *pkt, Handler *hand)
00169 {
00170 double now = Scheduler::instance().clock();
00171 int app_rate;
00172
00173 hdr_tcp *tcph = hdr_tcp::access(pkt);
00174 if (rbp_mode_ != RBP_OFF) {
00175
00176 rbp_mode_ = RBP_OFF;
00177
00178
00179 if (tcph->seqno() > last_ack_) {
00180 cwnd_ = maxseq_ - last_ack_;
00181 RBP_DEBUG_PRINTF(("\ncwnd-after-first-ack=%g\n", (double)cwnd_));
00182 };
00183
00184 };
00185 if (acked_ == 0) {
00186 hdr_qs *qsh = hdr_qs::access(pkt);
00187
00188 if (qsh->flag() == QS_RESPONSE && qsh->ttl() == ttl_diff_ && qsh->rate() > 0) {
00189 printf("Quick Start approved\t");
00190
00191 app_rate = (int) (hdr_qs::rate_to_Bps(qsh->rate()) *
00192 (now - tcph->ts_echo()) / (size_ + headersize()));
00193 if (app_rate > initial_window()) {
00194 rbp_mode_ = RBP_POSSIBLE;
00195 wnd_init_option_ = 1;
00196 wnd_init_ = app_rate;
00197 printf("%d: rate= %d, rtt = %f\n", addr(), app_rate, (now - tcph->ts_echo()));
00198 qs_approved_ = 1;
00199 }
00200 else {
00201 printf("%d: quick start approved, but rate too low %d, fall-back to slow start\n", addr(), app_rate);
00202 rbp_mode_ = RBP_OFF;
00203 qsh->flag() = QS_DISABLE;
00204 qs_approved_ = 0;
00205 }
00206 } else {
00207 printf("Quick Start rejected\n");
00208 rbp_mode_ = RBP_OFF;
00209 qsh->flag() = QS_DISABLE;
00210 qs_approved_ = 0;
00211 }
00212 } else if (acked_ == 1 && qs_approved_ == 1) {
00213
00214 }
00215 NewRenoTcpAgent::recv(pkt, hand);
00216 }
00217
00218 void
00219 QSNewRenoTcpAgent::timeout(int tno)
00220 {
00221 if (tno == TCP_TIMER_RTX) {
00222 if (highest_ack_ == maxseq_) {
00223
00224
00225 rbp_mode_ = RBP_OFF;
00226 return;
00227 }
00228 else {
00229 rbp_mode_ = RBP_OFF;
00230 cwnd_ = initial_window();
00231 }
00232 }
00233 NewRenoTcpAgent::timeout(tno);
00234 }
00235
00236 void
00237 QSNewRenoTcpAgent::send_much(int force, int reason, int maxburst)
00238 {
00239 if (rbp_mode_ == RBP_POSSIBLE && able_to_rbp_send_one()) {
00240
00241 rbp_mode_ = RBP_GOING;
00242 rbp_segs_actually_paced_ = 0;
00243
00244
00245 double rbwin_reno;
00246 rbwin_reno = cwnd_ * rbp_scale_;
00247
00248 rbwin_reno = int(rbwin_reno + 0.5);
00249
00250 if (rbwin_reno <= RBP_MIN_SEGMENTS) {
00251 rbwin_reno = RBP_MIN_SEGMENTS;
00252 };
00253
00254
00255
00256 RBP_DEBUG_PRINTF(("cwnd before check = %g\n", double(cwnd_)));
00257 cwnd_ = MIN(cwnd_,(TracedDouble) rbwin_reno);
00258 RBP_DEBUG_PRINTF(("cwnd after check = %g\n", double(cwnd_)));
00259 RBP_DEBUG_PRINTF(("recv win = %g\n", wnd_));
00260
00261
00262
00263
00264
00265
00266 static double srtt_scale = 0.0;
00267 if (srtt_scale == 0.0) {
00268 srtt_scale = 1.0;
00269 int i;
00270 for (i = T_SRTT_BITS; i > 0; i--) {
00271 srtt_scale /= 2.0;
00272 };
00273 }
00274 rbp_inter_pace_delay_ = (t_srtt_ * srtt_scale * tcp_tick_) / (window() * 1.0);
00275 RBP_DEBUG_PRINTF(("window is %d\n", window()));
00276 RBP_DEBUG_PRINTF(("ipt = %g\n", rbp_inter_pace_delay_));
00277 paced_send_one();
00278 } else {
00279 NewRenoTcpAgent::send_much(force,reason, maxburst);
00280 };
00281 }
00282
00283 void
00284 QSNewRenoTcpAgent::paced_send_one()
00285 {
00286 if (rbp_mode_ == RBP_GOING && able_to_rbp_send_one()) {
00287 RBP_DEBUG_PRINTF(("Sending one rbp packet\n"));
00288
00289 output(t_seqno_++, TCP_REASON_RBP);
00290 rbp_segs_actually_paced_++;
00291
00292 pace_timer_.resched(rbp_inter_pace_delay_);
00293 };
00294 }
00295
00296 int
00297 QSNewRenoTcpAgent::able_to_rbp_send_one()
00298 {
00299 return t_seqno_ < curseq_ && t_seqno_ <= highest_ack_ + window();
00300 }
00301
00302 void QSNewRenoTcpAgent::output(int seqno, int reason)
00303 {
00304 int force_set_rtx_timer = 0;
00305 Packet* p = allocpkt();
00306 hdr_tcp *tcph = hdr_tcp::access(p);
00307 hdr_ip *iph = hdr_ip::access(p);
00308 hdr_qs *qsh = hdr_qs::access(p);
00309 hdr_flags* hf = hdr_flags::access(p);
00310 int databytes = hdr_cmn::access(p)->size();
00311 tcph->seqno() = seqno;
00312 tcph->ts() = Scheduler::instance().clock();
00313 tcph->ts_echo() = ts_peer_;
00314 tcph->reason() = reason;
00315 tcph->last_rtt() = int(int(t_rtt_)*tcp_tick_*1000);
00316
00317
00318 if (seqno == 0) {
00319 qsh->flag() = QS_REQUEST;
00320 qsh->ttl() = Random::integer(256);
00321 ttl_diff_ = (iph->ttl() - qsh->ttl()) % 256;
00322
00323 qsh->rate() = hdr_qs::Bps_to_rate(rate_request_ * 1024);
00324 }
00325 else {
00326 qsh->flag() = QS_DISABLE;
00327 }
00328
00329 if (ecn_) {
00330 hf->ect() = 1;
00331 }
00332 if (cong_action_) {
00333 hf->cong_action() = TRUE;
00334 cong_action_ = FALSE;
00335 }
00336
00337 if (seqno == 0) {
00338 if (syn_) {
00339 databytes = 0;
00340 curseq_ += 1;
00341 hdr_cmn::access(p)->size() = tcpip_base_hdr_size_;
00342
00343 }
00344 if (ecn_) {
00345 hf->ecnecho() = 1;
00346
00347 hf->ect() = 0;
00348 }
00349 }
00350 else if (useHeaders_ == true) {
00351 hdr_cmn::access(p)->size() += headersize();
00352 }
00353 hdr_cmn::access(p)->size();
00354
00355
00356 if (highest_ack_ == maxseq_)
00357 force_set_rtx_timer = 1;
00358
00359 output_helper(p);
00360
00361 ++ndatapack_;
00362 ndatabytes_ += databytes;
00363 send(p, 0);
00364
00365 if (seqno == curseq_ && seqno > maxseq_)
00366 idle();
00367 if (seqno > maxseq_) {
00368 maxseq_ = seqno;
00369 if (!rtt_active_) {
00370 rtt_active_ = 1;
00371 if (seqno > rtt_seq_) {
00372 rtt_seq_ = seqno;
00373 rtt_ts_ = Scheduler::instance().clock();
00374 }
00375
00376 }
00377 } else {
00378 ++nrexmitpack_;
00379 nrexmitbytes_ += databytes;
00380 }
00381 if (!(rtx_timer_.status() == TIMER_PENDING) || force_set_rtx_timer)
00382
00383 set_rtx_timer();
00384 }
00385
00386 class QSTcpSink;
00387
00388 class QSTcpSink : public TcpSink {
00389 public:
00390 QSTcpSink(Acker *);
00391 virtual void ack(Packet * oPacket);
00392 void recv(Packet* pkt, Handler*);
00393 };
00394
00395 static class QSTcpSinkClass : public TclClass {
00396 public:
00397 QSTcpSinkClass() : TclClass("Agent/TCPSink/QS") {}
00398 TclObject* create(int, const char*const*) {
00399 return (new QSTcpSink(new Acker));
00400 }
00401 } class_sink_qs;
00402
00403 QSTcpSink::QSTcpSink(Acker * acker) : TcpSink(acker) {
00404 }
00405
00406 void QSTcpSink::recv(Packet* pkt, Handler*)
00407 {
00408 int numToDeliver;
00409 int numBytes = hdr_cmn::access(pkt)->size();
00410
00411 hdr_tcp *th = hdr_tcp::access(pkt);
00412
00413 if (th->ts() < lastreset_) {
00414
00415 Packet::free(pkt);
00416 return;
00417 }
00418 acker_->update_ts(th->seqno(),th->ts(),ts_echo_rfc1323_);
00419
00420
00421 numToDeliver = acker_->update(th->seqno(), numBytes);
00422
00423
00424
00425 if (numToDeliver)
00426 recvBytes(numToDeliver);
00427
00428 ack(pkt);
00429
00430 Packet::free(pkt);
00431
00432 }
00433
00434 void QSTcpSink::ack(Packet* opkt)
00435 {
00436 Packet* npkt = allocpkt();
00437
00438
00439 double now = Scheduler::instance().clock();
00440
00441 hdr_tcp *otcp = hdr_tcp::access(opkt);
00442 hdr_tcp *ntcp = hdr_tcp::access(npkt);
00443
00444 hdr_ip *oiph = hdr_ip::access(opkt);
00445
00446 hdr_qs *oqsh = hdr_qs::access(opkt);
00447 hdr_qs *nqsh = hdr_qs::access(npkt);
00448
00449 if (otcp->seqno() == 0 && oqsh->flag() == QS_REQUEST) {
00450 nqsh->flag() = QS_RESPONSE;
00451 nqsh->ttl() = (oiph->ttl() - oqsh->ttl()) % 256;
00452 nqsh->rate() = oqsh->rate();
00453 }
00454 else {
00455 nqsh->flag() = QS_DISABLE;
00456 }
00457
00458
00459 ntcp->seqno() = acker_->Seqno();
00460
00461
00462 ntcp->ts() = now;
00463
00464
00465 if (ts_echo_bugfix_)
00466 ntcp->ts_echo() = acker_->ts_to_echo();
00467 else
00468 ntcp->ts_echo() = otcp->ts();
00469
00470
00471
00472
00473
00474
00475
00476
00477 hdr_flags* of = hdr_flags::access(opkt);
00478 hdr_flags* nf = hdr_flags::access(npkt);
00479 hdr_flags* sf;
00480 if (save_ != NULL) {
00481 sf = hdr_flags::access(save_);
00482 } else {
00483 sf = 0;
00484 }
00485
00486 if ( (sf != 0 && sf->cong_action()) || of->cong_action() )
00487
00488 acker_->update_ecn_unacked(0);
00489 if ( (sf != 0 && sf->ect() && sf->ce()) ||
00490 (of->ect() && of->ce()) )
00491
00492 acker_->update_ecn_unacked(1);
00493 if ( (sf != 0 && sf->ect()) || of->ect() )
00494
00495 nf->ecnecho() = acker_->ecn_unacked();
00496 if (!of->ect() && of->ecnecho() ||
00497 (sf != 0 && !sf->ect() && sf->ecnecho()) )
00498
00499
00500
00501
00502 nf->ecnecho() = 1;
00503 acker_->append_ack(hdr_cmn::access(npkt),
00504 ntcp, otcp->seqno());
00505 add_to_ack(npkt);
00506
00507
00508 send(npkt, 0);
00509
00510 }
00511