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