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 #ifndef lint
00064 static const char rcsid[] =
00065 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-rbp.cc,v 1.22 2005/08/25 18:58:12 johnh Exp $ (NCSU/IBM)";
00066 #endif
00067
00068 #include <stdio.h>
00069 #include <stdlib.h>
00070 #include <sys/types.h>
00071
00072 #include "ip.h"
00073 #include "tcp.h"
00074 #include "flags.h"
00075
00076 #ifndef MIN
00077 #define MIN(x, y) ((x)<(y) ? (x) : (y))
00078 #endif
00079
00080 #if 0
00081 #define RBP_DEBUG_PRINTF(x) printf x
00082 #else
00083 #define RBP_DEBUG_PRINTF(x)
00084 #endif
00085
00086
00087 #define RBP_MIN_SEGMENTS 2
00088
00089 class RBPVegasTcpAgent;
00090
00091 class RBPVegasPaceTimer : public TimerHandler {
00092 public:
00093 RBPVegasPaceTimer(RBPVegasTcpAgent *a) : TimerHandler() { a_ = a; }
00094 protected:
00095 virtual void expire(Event *e);
00096 RBPVegasTcpAgent *a_;
00097 };
00098
00099
00100 class RBPVegasTcpAgent : public virtual VegasTcpAgent {
00101 friend class RBPVegasPaceTimer;
00102 public:
00103 RBPVegasTcpAgent();
00104 virtual void recv(Packet *pkt, Handler *);
00105 virtual void timeout(int tno);
00106 virtual void send_much(int force, int reason, int maxburst);
00107
00108 double rbp_scale_;
00109 enum rbp_rate_algorithms { RBP_NO_ALGORITHM, RBP_VEGAS_RATE_ALGORITHM, RBP_CWND_ALGORITHM };
00110 int rbp_rate_algorithm_;
00111 protected:
00112 void paced_send_one();
00113 int able_to_rbp_send_one();
00114
00115
00116 int rbp_segs_actually_paced_;
00117
00118 enum rbp_modes { RBP_GOING, RBP_POSSIBLE, RBP_OFF };
00119 enum rbp_modes rbp_mode_;
00120 double rbp_inter_pace_delay_;
00121 RBPVegasPaceTimer pace_timer_;
00122 };
00123
00124 static class RBPVegasTcpClass : public TclClass {
00125 public:
00126 RBPVegasTcpClass() : TclClass("Agent/TCP/Vegas/RBP") {}
00127 TclObject* create(int, const char*const*) {
00128 return (new RBPVegasTcpAgent());
00129 }
00130 } class_vegas_rbp;
00131
00132
00133 void RBPVegasPaceTimer::expire(Event *) { a_->paced_send_one(); }
00134
00135
00136 RBPVegasTcpAgent::RBPVegasTcpAgent() : VegasTcpAgent(),
00137 rbp_mode_(RBP_OFF),
00138 pace_timer_(this)
00139 {
00140 bind("rbp_scale_", &rbp_scale_);
00141 bind("rbp_rate_algorithm_", &rbp_rate_algorithm_);
00142 bind("rbp_segs_actually_paced_", &rbp_segs_actually_paced_);
00143 bind("rbp_inter_pace_delay_", &rbp_inter_pace_delay_);
00144 }
00145
00146 void
00147 RBPVegasTcpAgent::recv(Packet *pkt, Handler *hand)
00148 {
00149 if (rbp_mode_ != RBP_OFF) {
00150
00151 rbp_mode_ = RBP_OFF;
00152
00153 };
00154 VegasTcpAgent::recv(pkt, hand);
00155 }
00156
00157 void
00158 RBPVegasTcpAgent::timeout(int tno)
00159 {
00160 if (tno == TCP_TIMER_RTX) {
00161 if (highest_ack_ == maxseq_) {
00162
00163 rbp_mode_ = RBP_POSSIBLE;
00164 return;
00165 };
00166 };
00167 VegasTcpAgent::timeout(tno);
00168 }
00169
00170 void
00171 RBPVegasTcpAgent::send_much(int force, int reason, int maxburst)
00172 {
00173 if (rbp_mode_ == RBP_POSSIBLE && able_to_rbp_send_one()) {
00174
00175 rbp_mode_ = RBP_GOING;
00176 rbp_segs_actually_paced_ = 0;
00177 double rbwin_vegas;
00178 switch (rbp_rate_algorithm_) {
00179 case RBP_VEGAS_RATE_ALGORITHM:
00180
00181
00182
00183 rbwin_vegas = v_actual_ * v_rtt_;
00184 RBP_DEBUG_PRINTF(("-----------------\n"));
00185 RBP_DEBUG_PRINTF(("rbwin_vegas = %g\nv_actual = %g\nv_rtt =%g\nbase_rtt=%g\n",
00186 rbwin_vegas, v_actual_, v_rtt_, v_baseRTT_));
00187
00188 rbwin_vegas *= rbp_scale_;
00189 break;
00190 case RBP_CWND_ALGORITHM:
00191
00192 rbwin_vegas = cwnd_ * rbp_scale_;
00193 break;
00194 default:
00195
00196 rbwin_vegas = 0.0;
00197 abort();
00198 };
00199 rbwin_vegas = int(rbwin_vegas + 0.5);
00200
00201 if (rbwin_vegas <= RBP_MIN_SEGMENTS) {
00202 rbwin_vegas = RBP_MIN_SEGMENTS;
00203 };
00204
00205
00206
00207 RBP_DEBUG_PRINTF(("cwnd before check = %g\n", double(cwnd_)));
00208 cwnd_ = MIN(cwnd_,(TracedDouble) rbwin_vegas);
00209 RBP_DEBUG_PRINTF(("cwnd after check = %g\n", double(cwnd_)));
00210 RBP_DEBUG_PRINTF(("recv win = %g\n", wnd_));
00211
00212
00213
00214
00215
00216
00217 rbp_inter_pace_delay_ = (v_rtt_)/(window() * 1.0);
00218 RBP_DEBUG_PRINTF(("window is %d\n", window()));
00219 RBP_DEBUG_PRINTF(("ipt = %g\n", rbp_inter_pace_delay_));
00220 paced_send_one();
00221 } else {
00222 VegasTcpAgent::send_much(force,reason, maxburst);
00223 }
00224 }
00225
00226 void
00227 RBPVegasTcpAgent::paced_send_one()
00228 {
00229 if (rbp_mode_ == RBP_GOING && able_to_rbp_send_one()) {
00230 RBP_DEBUG_PRINTF(("Sending one rbp packet\n"));
00231
00232 output(t_seqno_++, TCP_REASON_RBP);
00233 rbp_segs_actually_paced_++;
00234
00235 pace_timer_.resched(rbp_inter_pace_delay_);
00236 };
00237 }
00238
00239 int
00240 RBPVegasTcpAgent::able_to_rbp_send_one()
00241 {
00242 return t_seqno_ < curseq_ && t_seqno_ <= highest_ack_ + window();
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 class RBPRenoTcpAgent;
00254
00255 class RBPRenoPaceTimer : public TimerHandler {
00256 public:
00257 RBPRenoPaceTimer(RBPRenoTcpAgent *a) : TimerHandler() { a_ = a; }
00258 protected:
00259 virtual void expire(Event *e);
00260 RBPRenoTcpAgent *a_;
00261 };
00262
00263
00264 class RBPRenoTcpAgent : public virtual RenoTcpAgent {
00265 friend class RBPRenoPaceTimer;
00266 public:
00267 RBPRenoTcpAgent();
00268 virtual void recv(Packet *pkt, Handler *);
00269 virtual void timeout(int tno);
00270 virtual void send_much(int force, int reason, int maxburst);
00271
00272 double rbp_scale_;
00273
00274
00275 protected:
00276 void paced_send_one();
00277 int able_to_rbp_send_one();
00278
00279
00280 int rbp_segs_actually_paced_;
00281
00282 enum rbp_modes { RBP_GOING, RBP_POSSIBLE, RBP_OFF };
00283 enum rbp_modes rbp_mode_;
00284 double rbp_inter_pace_delay_;
00285 RBPRenoPaceTimer pace_timer_;
00286 };
00287
00288 static class RBPRenoTcpClass : public TclClass {
00289 public:
00290 RBPRenoTcpClass() : TclClass("Agent/TCP/Reno/RBP") {}
00291 TclObject* create(int, const char*const*) {
00292 return (new RBPRenoTcpAgent());
00293 }
00294 } class_reno_rbp;
00295
00296
00297 void RBPRenoPaceTimer::expire(Event *) { a_->paced_send_one(); }
00298
00299 RBPRenoTcpAgent::RBPRenoTcpAgent() : TcpAgent(),
00300 rbp_mode_(RBP_OFF),
00301 pace_timer_(this)
00302 {
00303 bind("rbp_scale_", &rbp_scale_);
00304
00305
00306 bind("rbp_segs_actually_paced_", &rbp_segs_actually_paced_);
00307 bind("rbp_inter_pace_delay_", &rbp_inter_pace_delay_);
00308 }
00309
00310 void
00311 RBPRenoTcpAgent::recv(Packet *pkt, Handler *hand)
00312 {
00313 if (rbp_mode_ != RBP_OFF) {
00314
00315 rbp_mode_ = RBP_OFF;
00316
00317
00318 hdr_tcp *tcph = hdr_tcp::access(pkt);
00319 if (tcph->seqno() > last_ack_) {
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 cwnd_ = maxseq_ - last_ack_;
00336 RBP_DEBUG_PRINTF(("\ncwnd-after-first-ack=%g\n", (double)cwnd_));
00337 };
00338
00339 };
00340 RenoTcpAgent::recv(pkt, hand);
00341 }
00342
00343 void
00344 RBPRenoTcpAgent::timeout(int tno)
00345 {
00346 if (tno == TCP_TIMER_RTX) {
00347 if (highest_ack_ == maxseq_) {
00348
00349 rbp_mode_ = RBP_POSSIBLE;
00350 return;
00351 };
00352 };
00353 RenoTcpAgent::timeout(tno);
00354 }
00355
00356 void
00357 RBPRenoTcpAgent::send_much(int force, int reason, int maxburst)
00358 {
00359 if (rbp_mode_ == RBP_POSSIBLE && able_to_rbp_send_one()) {
00360
00361 rbp_mode_ = RBP_GOING;
00362 rbp_segs_actually_paced_ = 0;
00363
00364
00365 double rbwin_reno;
00366 rbwin_reno = cwnd_ * rbp_scale_;
00367
00368 rbwin_reno = int(rbwin_reno + 0.5);
00369
00370 if (rbwin_reno <= RBP_MIN_SEGMENTS) {
00371 rbwin_reno = RBP_MIN_SEGMENTS;
00372 };
00373
00374
00375
00376 RBP_DEBUG_PRINTF(("cwnd before check = %g\n", double(cwnd_)));
00377 cwnd_ = MIN(cwnd_,(TracedDouble) rbwin_reno);
00378 RBP_DEBUG_PRINTF(("cwnd after check = %g\n", double(cwnd_)));
00379 RBP_DEBUG_PRINTF(("recv win = %g\n", wnd_));
00380
00381
00382
00383
00384
00385
00386 static double srtt_scale = 0.0;
00387 if (srtt_scale == 0.0) {
00388 srtt_scale = 1.0;
00389 int i;
00390 for (i = T_SRTT_BITS; i > 0; i--) {
00391 srtt_scale /= 2.0;
00392 };
00393 }
00394 rbp_inter_pace_delay_ = (t_srtt_ * srtt_scale * tcp_tick_) / (window() * 1.0);
00395 RBP_DEBUG_PRINTF(("window is %d\n", window()));
00396 RBP_DEBUG_PRINTF(("ipt = %g\n", rbp_inter_pace_delay_));
00397 paced_send_one();
00398 } else {
00399 RenoTcpAgent::send_much(force,reason, maxburst);
00400 };
00401 }
00402
00403 void
00404 RBPRenoTcpAgent::paced_send_one()
00405 {
00406 if (rbp_mode_ == RBP_GOING && able_to_rbp_send_one()) {
00407 RBP_DEBUG_PRINTF(("Sending one rbp packet\n"));
00408
00409 output(t_seqno_++, TCP_REASON_RBP);
00410 rbp_segs_actually_paced_++;
00411
00412 pace_timer_.resched(rbp_inter_pace_delay_);
00413 };
00414 }
00415
00416 int
00417 RBPRenoTcpAgent::able_to_rbp_send_one()
00418 {
00419 return t_seqno_ < curseq_ && t_seqno_ <= highest_ack_ + window();
00420 }