Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

tcp-abs.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /* tcp-abs.cc
00003  * Copyright (C) 1999 by USC/ISI
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms are permitted
00007  * provided that the above copyright notice and this paragraph are
00008  * duplicated in all such forms and that any documentation, advertising
00009  * materials, and other materials related to such distribution and use
00010  * acknowledge that the software was developed by the University of
00011  * Southern California, Information Sciences Institute.  The name of the
00012  * University may not be used to endorse or promote products derived from
00013  * this software without specific prior written permission.
00014  * 
00015  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
00016  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00017  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00018  * 
00019  * Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
00020  * @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-abs.cc,v 1.2 1999/05/31 20:40:46 heideman Exp $ (LBL)";
00021  */
00022 
00023 #include "ip.h"
00024 #include "tcp.h"
00025 #include "tcp-abs.h"
00026 
00027 //AbsTcp
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         //printf("starting fsm tcp, %d\n", connection_size_);
00065         send_batch();
00066 }
00067 
00068 void AbsTcpAgent::send_batch() 
00069 {
00070         int seqno = seqno_lb_;
00071         
00072         offset_ = 0;
00073         //printf("sending batch, %d\n", current_->batch_size_);
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                 //printf("start timer %d\n", current_->transition_[offset_]);
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         //printf("dropped: %d\n", seqno);
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         //printf("finish: sent %d\n", seqno_lb_+1);
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                         //printf("rtt %f\n", rtt_);
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                         // xxx: works best if invoked on a new fsm
00152                         // (otherwise you don't get the whole thing).
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                         // xxx: works best if invoked on a new fsm
00162                         // (otherwise you don't get the whole thing).
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 //AbsTCP/TahoeAck
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 //AbsTCP/RenoAck
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 //AbsTCP/TahoeDelAck
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 //AbsTCP/RenoDelAck
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 //AbsTcpSink
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          * The timer expired so we ACK the last packet seen.
00295          * (shouldn't this check for a particular time out#?  -kf)
00296          */
00297         Packet* p = allocpkt();
00298         send(p, 0);
00299 }
00300 
00301 void AbsDelayTimer::expire(Event */*e*/) {
00302         a_->timeout();
00303 }
00304 
00305 //Special drop target agent
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         //printf("flow %d dropping seqno %d\n", iph->flowid(),tcph->seqno());
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 

Generated on Tue Apr 20 12:14:34 2004 for NS2.26SourcesOriginal by doxygen 1.3.3