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 #include <stdio.h>
00063 #include <stdlib.h>
00064 #include <sys/types.h>
00065
00066 #include "packet.h"
00067 #include "ip.h"
00068 #include "tcp.h"
00069 #include "flags.h"
00070 #include "nilist.h"
00071 #include "tcp-int.h"
00072 #include "chost.h"
00073 #include "tcp-session.h"
00074 #include "random.h"
00075
00076 Islist<TcpSessionAgent> TcpSessionAgent::sessionList_;
00077
00078 static class IntTcpClass : public TclClass {
00079 public:
00080 IntTcpClass() : TclClass("Agent/TCP/Int") {}
00081 TclObject* create(int, const char*const*) {
00082 return (new IntTcpAgent());
00083 }
00084 } class_tcp_int;
00085
00086 IntTcpAgent::IntTcpAgent() : TcpAgent(), slink(),
00087 session_(0), closecwTS_(0), lastTS_(-1), count_(0),
00088 wt_(1), wndIncSeqno_(0), num_thresh_dupack_segs_(0)
00089 {
00090 bind("rightEdge_", &rightEdge_);
00091 bind("uniqTS_", &uniqTS_);
00092 bind("winInc_", &winInc_);
00093 bind("winMult_", &winMult_);
00094 }
00095
00096 int
00097 IntTcpAgent::command(int argc, const char*const* argv)
00098 {
00099 Tcl& tcl = Tcl::instance();
00100
00101 if (argc == 3) {
00102 if (!strcmp(argv[1], "setwt")) {
00103 if (!session_)
00104 createTcpSession();
00105 session_->set_weight(this,atoi(argv[2]));
00106 return (TCL_OK);
00107 }
00108 }
00109 else if (argc == 2) {
00110 if (!strcmp(argv[1], "session")) {
00111 if (!session_)
00112 createTcpSession();
00113 tcl.resultf("%s", session_->name());
00114 return (TCL_OK);
00115 }
00116 }
00117 return (TcpAgent::command(argc,argv));
00118 }
00119
00120
00121
00122
00123
00124 void
00125 IntTcpAgent::newack(Packet* pkt)
00126 {
00127 hdr_tcp *tcph = hdr_tcp::access(pkt);
00128 last_ack_ = tcph->seqno();
00129 highest_ack_ = last_ack_;
00130
00131 if (t_seqno_ < last_ack_ + 1)
00132 t_seqno_ = last_ack_ + 1;
00133
00134 if ((highest_ack_ >= curseq_-1) && !closed_) {
00135 closed_ = 1;
00136 finish();
00137 }
00138 }
00139
00140 void
00141 IntTcpAgent::recv(Packet *pkt, Handler *)
00142 {
00143 hdr_tcp *tcph = hdr_tcp::access(pkt);
00144 int amt_data_acked = 0;
00145
00146 if (tcph->seqno() > last_ack_) {
00147 amt_data_acked = tcph->seqno() - last_ack_;
00148 newack(pkt);
00149 }
00150 session_->recv(this, pkt, amt_data_acked);
00151 }
00152
00153 void
00154 IntTcpAgent::createTcpSession()
00155 {
00156 Tcl& tcl = Tcl::instance();
00157
00158 tcl.evalf("%s set node_", name());
00159 tcl.evalf("%s createTcpSession %d", tcl.result(), daddr());
00160 Islist_iter<TcpSessionAgent> session_iter(TcpSessionAgent::sessionList_);
00161 TcpSessionAgent *cur;
00162
00163 while ((cur = session_iter()) != NULL) {
00164 if (cur->addr()/256 == addr() && cur->daddr() == daddr()) {
00165 session_ = cur;
00166 break;
00167 }
00168 }
00169 if (!session_) {
00170 printf("In IntTcpAgent::createTcpSession(): failed\n");
00171 abort();
00172 }
00173 session_->add_agent(this, size_, winMult_, winInc_, ssthresh_);
00174 }
00175
00176 void
00177 IntTcpAgent::output(int seqno, int reason)
00178 {
00179 Packet *pkt = allocpkt();
00180 hdr_tcp *tcph = hdr_tcp::access(pkt);
00181 tcph->seqno() = seqno;
00182 tcph->ts() = Scheduler::instance().clock();
00183 tcph->ts_echo() = ts_peer_;
00184 tcph->reason() = reason;
00185
00186 session_->setflags(pkt);
00187
00188 int bytes = hdr_cmn::access(pkt)->size();
00189
00190
00191 output_helper(pkt);
00192
00193 ++ndatapack_;
00194 ndatabytes_ += bytes;
00195 send(pkt, 0);
00196 if (seqno == curseq_ && seqno > maxseq_)
00197 idle();
00198 if (seqno > maxseq_) {
00199 maxseq_ = seqno;
00200 }
00201 else {
00202 ++nrexmitpack_;
00203 nrexmitbytes_ += bytes;
00204 }
00205 if (wndIncSeqno_ == 0)
00206 wndIncSeqno_ = maxseq_;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216 void
00217 IntTcpAgent::send_much(int force, int reason, int )
00218 {
00219 if (!session_)
00220 createTcpSession();
00221 if (!force && delsnd_timer_.status() == TIMER_PENDING)
00222 return;
00223 if (overhead_ && !force) {
00224 delsnd_timer_.resched(Random::uniform(overhead_));
00225 return;
00226 }
00227 session_->send_much(this, force,reason);
00228 }
00229
00230
00231
00232
00233 void
00234 IntTcpAgent::send_one(int sessionSeqno)
00235 {
00236 int dst_addr = daddr();
00237 int dst_port = dport();
00238 int sport = port();
00239
00240 if (!session_)
00241 createTcpSession();
00242
00243
00244
00245
00246 output(t_seqno_++);
00247 session_->add_pkts(size_, t_seqno_ - 1, sessionSeqno,
00248 dst_addr, dst_port, sport, lastTS_, this);
00249 }
00250
00251
00252
00253
00254
00255 void
00256 IntTcpAgent::opencwnd()
00257 {
00258 session_->opencwnd(size_, this);
00259 }
00260
00261
00262
00263
00264 void
00265 IntTcpAgent::closecwnd(int how)
00266 {
00267 session_->closecwnd(how, this);
00268 }
00269
00270 Segment *
00271 IntTcpAgent::rxmit_last(int reason, int seqno, int sessionSeqno, double )
00272 {
00273 session_->agent_rcov(this);
00274
00275
00276
00277
00278 session_->reset_rtx_timer(1,0);
00279 output(seqno, reason);
00280 daddr_ = daddr();
00281 dport_ = dport();
00282 sport_ = port();
00283 return (session_->add_pkts(size_, seqno, sessionSeqno, daddr_,
00284 dport_, sport_, lastTS_, this));
00285 return NULL;
00286 }
00287 unsigned long output_helper_count=0;
00288 double last_clock=0;
00289 void
00290 IntTcpAgent::output_helper(Packet *p)
00291 {
00292 double now = Scheduler::instance().clock();
00293 output_helper_count++;
00294 last_clock = now;
00295 hdr_tcp *tcph = hdr_tcp::access(p);
00296
00297
00298 while (uniqTS_ && now <= lastTS_) {
00299 now += 0.000001;
00300 }
00301
00302 lastTS_ = now;
00303 tcph->ts() = now;
00304
00305 if (session_->fs_pkt() && tcph->seqno() > maxseq_)
00306 hdr_flags::access(p)->fs_ = 1;
00307 return;
00308 }
00309
00310 int
00311 IntTcpAgent::data_left_to_send() {
00312 return (curseq_ > t_seqno_);
00313 }