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