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