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 #include "ip.h"
00052 #include "tcp.h"
00053 #include "tcp-abs.h"
00054
00055
00056 AbsTcpAgent::AbsTcpAgent() : Agent(PT_TCP), rtt_(0), current_(NULL),offset_(0), seqno_lb_(-1), connection_size_(0), timer_(this), rescheduled_(0)
00057 {
00058 size_ = 1000;
00059 }
00060
00061 void AbsTcpAgent::timeout()
00062 {
00063 if (rescheduled_ == 0 && current_->transition_[offset_]!= current_->transition_[0]) {
00064 set_timer(2*rtt_);
00065 rescheduled_ = 1;
00066 } else {
00067 rescheduled_ = 0;
00068 seqno_lb_ += current_->batch_size_;
00069 if (current_->drop_[offset_] == NULL) {
00070 printf("Error: This fsm can't handle multi losses per connection\n");
00071 exit(0);
00072 }
00073 current_ = current_->drop_[offset_];
00074 send_batch();
00075 }
00076 }
00077
00078 void AbsTcpAgent::sendmsg(int pktcnt)
00079 {
00080 connection_size_ = pktcnt;
00081 start();
00082 }
00083
00084 void AbsTcpAgent::advanceby(int pktcnt)
00085 {
00086 connection_size_ = pktcnt;
00087 start();
00088 }
00089
00090 void AbsTcpAgent::start()
00091 {
00092
00093 send_batch();
00094 }
00095
00096 void AbsTcpAgent::send_batch()
00097 {
00098 int seqno = seqno_lb_;
00099
00100 offset_ = 0;
00101
00102 for (int i=0; i<current_->batch_size_ && seqno < connection_size_-1; i++) {
00103 seqno++;
00104 output(seqno);
00105 }
00106 if (seqno == connection_size_-1) {
00107 finish();
00108 }
00109 else if (seqno < connection_size_-1) {
00110 if (current_->drop_[offset_] == NULL) {
00111 printf("Error: current fsm can't handle this tcp connection flow id %d (possibly too long)\n", fid_);
00112 exit(0);
00113 }
00114
00115 if (current_->transition_[offset_] == 0) {
00116 current_ = current_->drop_[offset_];
00117 send_batch();
00118 } else if (current_->transition_[offset_] == RTT) {
00119 set_timer(rtt_);
00120 } else if (current_->transition_[offset_] == TIMEOUT) {
00121 set_timer(rtt_ * 3);
00122 } else {
00123 printf("Error: weird transition timer\n");
00124 exit(0);
00125 }
00126 } else {
00127 printf("Error: sending more than %d packets\n", connection_size_);
00128 exit(0);
00129 }
00130 }
00131
00132 void AbsTcpAgent::drop(int seqno)
00133 {
00134
00135 if (offset_ != 0) {
00136 printf("Error: Sorry, can't handle multiple drops per batch\n");
00137 exit(0);
00138 }
00139 offset_ = seqno - seqno_lb_;
00140 connection_size_++;
00141 }
00142
00143 void AbsTcpAgent::finish()
00144 {
00145
00146 cancel_timer();
00147 }
00148
00149 void AbsTcpAgent::output(int seqno)
00150 {
00151 Packet* p = allocpkt();
00152 hdr_tcp *tcph = hdr_tcp::access(p);
00153 tcph->seqno() = seqno;
00154 send(p, 0);
00155 }
00156
00157 void AbsTcpAgent::recv(Packet* pkt, Handler*)
00158 {
00159 Packet::free(pkt);
00160 }
00161
00162 int AbsTcpAgent::command(int argc, const char*const* argv)
00163 {
00164 if (argc == 3 ) {
00165 if (strcmp(argv[1], "rtt") == 0) {
00166 rtt_ = atof(argv[2]);
00167
00168 return (TCL_OK);
00169 }
00170 if (strcmp(argv[1], "advance") == 0) {
00171 advanceby(atoi(argv[2]));
00172 return (TCL_OK);
00173 }
00174 if (strcmp(argv[1], "advanceby") == 0) {
00175 advanceby(atoi(argv[2]));
00176 return (TCL_OK);
00177 }
00178 if(strcmp(argv[1], "print-stats") == 0) {
00179
00180
00181 int n = atoi(argv[2]);
00182 if (n < 0 || n >= 17)
00183 return TCL_ERROR;
00184 FSM::print_FSM_stats(current_, n);
00185 return (TCL_OK);
00186 };
00187 } else if (argc == 2) {
00188 if (strcmp(argv[1], "print") == 0) {
00189
00190
00191 FSM::print_FSM(current_);
00192 return (TCL_OK);
00193 };
00194 };
00195 return (Agent::command(argc, argv));
00196 }
00197
00198 void AbsTcpTimer::expire(Event*)
00199 {
00200 a_->timeout();
00201 }
00202
00203
00204
00205 static class AbsTcpTahoeAckClass : public TclClass {
00206 public:
00207 AbsTcpTahoeAckClass() : TclClass("Agent/AbsTCP/TahoeAck") {}
00208 TclObject* create(int, const char*const*) {
00209 return (new AbsTcpTahoeAckAgent());
00210 }
00211 } class_abstcptahoeack;
00212
00213 AbsTcpTahoeAckAgent::AbsTcpTahoeAckAgent() : AbsTcpAgent()
00214 {
00215 size_ = 1000;
00216 current_ = TahoeAckFSM::instance().start_state();
00217 DropTargetAgent::instance().insert_tcp(this);
00218 }
00219
00220
00221
00222 static class AbsTcpRenoAckClass : public TclClass {
00223 public:
00224 AbsTcpRenoAckClass() : TclClass("Agent/AbsTCP/RenoAck") {}
00225 TclObject* create(int, const char*const*) {
00226 return (new AbsTcpRenoAckAgent());
00227 }
00228 } class_abstcprenoack;
00229
00230 AbsTcpRenoAckAgent::AbsTcpRenoAckAgent() : AbsTcpAgent()
00231 {
00232 size_ = 1000;
00233 current_ = RenoAckFSM::instance().start_state();
00234 DropTargetAgent::instance().insert_tcp(this);
00235 }
00236
00237
00238
00239 static class AbsTcpTahoeDelAckClass : public TclClass {
00240 public:
00241 AbsTcpTahoeDelAckClass() : TclClass("Agent/AbsTCP/TahoeDelAck") {}
00242 TclObject* create(int, const char*const*) {
00243 return (new AbsTcpTahoeDelAckAgent());
00244 }
00245 } class_abstcptahoedelack;
00246
00247 AbsTcpTahoeDelAckAgent::AbsTcpTahoeDelAckAgent() : AbsTcpAgent()
00248 {
00249 size_ = 1000;
00250 current_ = TahoeDelAckFSM::instance().start_state();
00251 DropTargetAgent::instance().insert_tcp(this);
00252 }
00253
00254
00255
00256 static class AbsTcpRenoDelAckClass : public TclClass {
00257 public:
00258 AbsTcpRenoDelAckClass() : TclClass("Agent/AbsTCP/RenoDelAck") {}
00259 TclObject* create(int, const char*const*) {
00260 return (new AbsTcpRenoDelAckAgent());
00261 }
00262 } class_abstcprenodelack;
00263
00264 AbsTcpRenoDelAckAgent::AbsTcpRenoDelAckAgent() : AbsTcpAgent()
00265 {
00266 size_ = 1000;
00267 current_ = RenoDelAckFSM::instance().start_state();
00268 DropTargetAgent::instance().insert_tcp(this);
00269 }
00270
00271
00272
00273 static class AbsTcpSinkClass : public TclClass {
00274 public:
00275 AbsTcpSinkClass() : TclClass("Agent/AbsTCPSink") {}
00276 TclObject* create(int, const char*const*) {
00277 return (new AbsTcpSink());
00278 }
00279 } class_abstcpsink;
00280
00281 AbsTcpSink::AbsTcpSink() : Agent(PT_ACK)
00282 {
00283 size_ = 40;
00284 }
00285
00286 void AbsTcpSink::recv(Packet* pkt, Handler*)
00287 {
00288 Packet* p = allocpkt();
00289 send(p, 0);
00290 Packet::free(pkt);
00291 }
00292
00293 static class AbsDelAckSinkClass : public TclClass {
00294 public:
00295 AbsDelAckSinkClass() : TclClass("Agent/AbsTCPSink/DelAck") {}
00296 TclObject* create(int, const char*const*) {
00297 return (new AbsDelAckSink());
00298 }
00299 } class_absdelacksink;
00300
00301 AbsDelAckSink::AbsDelAckSink() : AbsTcpSink(), delay_timer_(this)
00302 {
00303 size_ = 40;
00304 interval_ = 0.1;
00305 }
00306
00307 void AbsDelAckSink::recv(Packet* pkt, Handler*)
00308 {
00309 if (delay_timer_.status() != TIMER_PENDING) {
00310 delay_timer_.resched(interval_);
00311 } else {
00312 delay_timer_.cancel();
00313 Packet* p = allocpkt();
00314 send(p, 0);
00315 }
00316 Packet::free(pkt);
00317 }
00318
00319 void AbsDelAckSink::timeout()
00320 {
00321
00322
00323
00324
00325 Packet* p = allocpkt();
00326 send(p, 0);
00327 }
00328
00329 void AbsDelayTimer::expire(Event *) {
00330 a_->timeout();
00331 }
00332
00333
00334 DropTargetAgent* DropTargetAgent::instance_;
00335
00336 static class DropTargetClass : public TclClass {
00337 public:
00338 DropTargetClass() : TclClass("DropTargetAgent") {}
00339 TclObject* create(int, const char*const*) {
00340 return (new DropTargetAgent());
00341 }
00342 } class_droptarget;
00343
00344 DropTargetAgent::DropTargetAgent(): Connector(), dropper_list_(NULL)
00345 {
00346 instance_ = this;
00347 }
00348
00349 void DropTargetAgent::recv(Packet* pkt, Handler*)
00350 {
00351 Dropper* tmp = dropper_list_;
00352
00353 hdr_tcp *tcph = hdr_tcp::access(pkt);
00354 hdr_ip *iph = hdr_ip::access(pkt);
00355
00356 while(tmp != NULL) {
00357 if(tmp->agent_->flowid() == iph->flowid())
00358 tmp->agent_->drop(tcph->seqno());
00359 tmp = tmp->next_;
00360 }
00361 Packet::free(pkt);
00362 }
00363
00364 void DropTargetAgent::insert_tcp(AbsTcpAgent* tcp)
00365 {
00366 Dropper* dppr = new Dropper;
00367 dppr->agent_=tcp;
00368 dppr->next_ = dropper_list_;
00369 dropper_list_ = dppr;
00370 }
00371