tcp-abs.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (C) 1999 by the University of Southern California
  4.  * $Id: tcp-abs.cc,v 1.3 2005/08/25 18:58:12 johnh Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. /* 
  46.  * Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
  47.  * @(#) $Header: /cvsroot/nsnam/ns-2/tcp/tcp-abs.cc,v 1.3 2005/08/25 18:58:12 johnh Exp $ (LBL)";
  48.  */
  49. #include "ip.h"
  50. #include "tcp.h"
  51. #include "tcp-abs.h"
  52. //AbsTcp
  53. AbsTcpAgent::AbsTcpAgent() : Agent(PT_TCP), rtt_(0), current_(NULL),offset_(0), seqno_lb_(-1), connection_size_(0), timer_(this), rescheduled_(0)
  54. {
  55. size_ = 1000;
  56. }
  57. void AbsTcpAgent::timeout()
  58. {
  59. if (rescheduled_ == 0 && current_->transition_[offset_]!= current_->transition_[0]) {
  60. set_timer(2*rtt_);
  61. rescheduled_ = 1;
  62. } else {
  63. rescheduled_ = 0;
  64. seqno_lb_ += current_->batch_size_;
  65. if (current_->drop_[offset_] == NULL) {
  66. printf("Error: This fsm can't handle multi losses per connectionn");
  67. exit(0);
  68. }
  69. current_ = current_->drop_[offset_];
  70. send_batch();
  71. }
  72. }
  73. void AbsTcpAgent::sendmsg(int pktcnt)
  74. {
  75. connection_size_ = pktcnt;
  76. start();
  77. }
  78. void AbsTcpAgent::advanceby(int pktcnt)
  79. {
  80. connection_size_ = pktcnt;
  81. start();
  82. }
  83. void AbsTcpAgent::start()
  84. {
  85. //printf("starting fsm tcp, %dn", connection_size_);
  86. send_batch();
  87. }
  88. void AbsTcpAgent::send_batch() 
  89. {
  90. int seqno = seqno_lb_;
  91. offset_ = 0;
  92. //printf("sending batch, %dn", current_->batch_size_);
  93. for (int i=0; i<current_->batch_size_ && seqno < connection_size_-1; i++) {
  94. seqno++;
  95. output(seqno);
  96. }
  97. if (seqno == connection_size_-1) {
  98. finish();
  99. }
  100. else if (seqno < connection_size_-1) {
  101. if (current_->drop_[offset_] == NULL) {
  102. printf("Error: current fsm can't handle this tcp connection flow id %d (possibly too long)n", fid_);
  103. exit(0);
  104. //printf("start timer %dn", current_->transition_[offset_]);
  105. if (current_->transition_[offset_] == 0) {
  106. current_ = current_->drop_[offset_];
  107. send_batch();
  108. } else if (current_->transition_[offset_] == RTT) {
  109. set_timer(rtt_);
  110. } else if (current_->transition_[offset_] == TIMEOUT) {
  111. set_timer(rtt_ * 3);
  112. } else {
  113. printf("Error: weird transition timern");
  114. exit(0);
  115. }
  116. } else {
  117. printf("Error: sending more than %d packetsn", connection_size_);
  118. exit(0);
  119. }
  120. }
  121. void AbsTcpAgent::drop(int seqno)
  122. {
  123. //printf("dropped: %dn", seqno);
  124. if (offset_ != 0) {
  125. printf("Error: Sorry, can't handle multiple drops per batchn");
  126. exit(0);
  127. }
  128. offset_ = seqno - seqno_lb_;
  129. connection_size_++;
  130. }
  131. void AbsTcpAgent::finish()
  132. {
  133. //printf("finish: sent %dn", seqno_lb_+1);
  134. cancel_timer();
  135. }
  136. void AbsTcpAgent::output(int seqno)
  137. {
  138.         Packet* p = allocpkt();
  139.         hdr_tcp *tcph = hdr_tcp::access(p);
  140.         tcph->seqno() = seqno;
  141.         send(p, 0);
  142. }
  143. void AbsTcpAgent::recv(Packet* pkt, Handler*)
  144. {
  145. Packet::free(pkt);
  146. }
  147. int AbsTcpAgent::command(int argc, const char*const* argv)
  148. {
  149.         if (argc == 3 ) {
  150.                 if (strcmp(argv[1], "rtt") == 0) {
  151. rtt_ = atof(argv[2]);
  152. //printf("rtt %fn", rtt_);
  153. return (TCL_OK);
  154. }
  155.                 if (strcmp(argv[1], "advance") == 0) {
  156. advanceby(atoi(argv[2]));
  157. return (TCL_OK);
  158.                 }
  159.                 if (strcmp(argv[1], "advanceby") == 0) {
  160.                         advanceby(atoi(argv[2]));
  161.                         return (TCL_OK);
  162.                 }
  163. if(strcmp(argv[1], "print-stats") == 0) {
  164. // xxx: works best if invoked on a new fsm
  165. // (otherwise you don't get the whole thing).
  166. int n = atoi(argv[2]);
  167. if (n < 0 || n >= 17)
  168. return TCL_ERROR;
  169. FSM::print_FSM_stats(current_, n);
  170.                         return (TCL_OK);
  171. };
  172. } else if (argc == 2) {
  173.                 if (strcmp(argv[1], "print") == 0) {
  174. // xxx: works best if invoked on a new fsm
  175. // (otherwise you don't get the whole thing).
  176. FSM::print_FSM(current_);
  177.                         return (TCL_OK);
  178. };
  179. };
  180. return (Agent::command(argc, argv));
  181. }
  182. void AbsTcpTimer::expire(Event*)
  183. {
  184.         a_->timeout();
  185. }
  186. //AbsTCP/TahoeAck
  187. static class AbsTcpTahoeAckClass : public TclClass {
  188. public:
  189. AbsTcpTahoeAckClass() : TclClass("Agent/AbsTCP/TahoeAck") {}
  190. TclObject* create(int, const char*const*) {
  191. return (new AbsTcpTahoeAckAgent());
  192. }
  193. } class_abstcptahoeack;
  194. AbsTcpTahoeAckAgent::AbsTcpTahoeAckAgent() : AbsTcpAgent()
  195. {
  196. size_ = 1000;
  197. current_ = TahoeAckFSM::instance().start_state();
  198. DropTargetAgent::instance().insert_tcp(this);
  199. }
  200. //AbsTCP/RenoAck
  201. static class AbsTcpRenoAckClass : public TclClass {
  202. public:
  203. AbsTcpRenoAckClass() : TclClass("Agent/AbsTCP/RenoAck") {}
  204. TclObject* create(int, const char*const*) {
  205. return (new AbsTcpRenoAckAgent());
  206. }
  207. } class_abstcprenoack;
  208. AbsTcpRenoAckAgent::AbsTcpRenoAckAgent() : AbsTcpAgent()
  209. {
  210. size_ = 1000;
  211. current_ = RenoAckFSM::instance().start_state();
  212. DropTargetAgent::instance().insert_tcp(this);
  213. }
  214. //AbsTCP/TahoeDelAck
  215. static class AbsTcpTahoeDelAckClass : public TclClass {
  216. public:
  217. AbsTcpTahoeDelAckClass() : TclClass("Agent/AbsTCP/TahoeDelAck") {}
  218. TclObject* create(int, const char*const*) {
  219. return (new AbsTcpTahoeDelAckAgent());
  220. }
  221. } class_abstcptahoedelack;
  222. AbsTcpTahoeDelAckAgent::AbsTcpTahoeDelAckAgent() : AbsTcpAgent()
  223. {
  224. size_ = 1000;
  225. current_ = TahoeDelAckFSM::instance().start_state();
  226. DropTargetAgent::instance().insert_tcp(this);
  227. }
  228. //AbsTCP/RenoDelAck
  229. static class AbsTcpRenoDelAckClass : public TclClass {
  230. public:
  231. AbsTcpRenoDelAckClass() : TclClass("Agent/AbsTCP/RenoDelAck") {}
  232. TclObject* create(int, const char*const*) {
  233. return (new AbsTcpRenoDelAckAgent());
  234. }
  235. } class_abstcprenodelack;
  236. AbsTcpRenoDelAckAgent::AbsTcpRenoDelAckAgent() : AbsTcpAgent()
  237. {
  238. size_ = 1000;
  239. current_ = RenoDelAckFSM::instance().start_state();
  240. DropTargetAgent::instance().insert_tcp(this);
  241. }
  242. //AbsTcpSink
  243. static class AbsTcpSinkClass : public TclClass {
  244. public:
  245.         AbsTcpSinkClass() : TclClass("Agent/AbsTCPSink") {}
  246.         TclObject* create(int, const char*const*) {
  247.                 return (new AbsTcpSink());
  248.         }
  249. } class_abstcpsink;
  250. AbsTcpSink::AbsTcpSink() : Agent(PT_ACK)
  251. {
  252. size_ = 40;
  253. }
  254. void AbsTcpSink::recv(Packet* pkt, Handler*)
  255. {
  256. Packet* p = allocpkt();
  257. send(p, 0);
  258.         Packet::free(pkt);
  259. }
  260. static class AbsDelAckSinkClass : public TclClass {
  261. public:
  262.         AbsDelAckSinkClass() : TclClass("Agent/AbsTCPSink/DelAck") {}
  263.         TclObject* create(int, const char*const*) {
  264.                 return (new AbsDelAckSink());
  265.         }
  266. } class_absdelacksink;
  267. AbsDelAckSink::AbsDelAckSink() : AbsTcpSink(), delay_timer_(this)
  268. {
  269. size_ = 40;
  270. interval_ = 0.1;
  271. }
  272. void AbsDelAckSink::recv(Packet* pkt, Handler*)
  273. {
  274.         if (delay_timer_.status() != TIMER_PENDING) {
  275. delay_timer_.resched(interval_);
  276. } else {
  277.                 delay_timer_.cancel();
  278. Packet* p = allocpkt();
  279. send(p, 0);
  280. }
  281.         Packet::free(pkt);
  282. }
  283. void AbsDelAckSink::timeout()
  284. {
  285.         /*
  286.          * The timer expired so we ACK the last packet seen.
  287.          * (shouldn't this check for a particular time out#?  -kf)
  288.          */
  289. Packet* p = allocpkt();
  290. send(p, 0);
  291. }
  292. void AbsDelayTimer::expire(Event */*e*/) {
  293.         a_->timeout();
  294. }
  295. //Special drop target agent
  296. DropTargetAgent* DropTargetAgent::instance_;
  297. static class DropTargetClass : public TclClass {
  298. public:
  299.         DropTargetClass() : TclClass("DropTargetAgent") {}
  300.         TclObject* create(int, const char*const*) {
  301.                 return (new DropTargetAgent());
  302.         }
  303. } class_droptarget;
  304. DropTargetAgent::DropTargetAgent(): Connector(), dropper_list_(NULL)
  305. {
  306. instance_ = this;
  307. }
  308. void DropTargetAgent::recv(Packet* pkt, Handler*)
  309. {
  310. Dropper* tmp = dropper_list_;
  311.         hdr_tcp *tcph = hdr_tcp::access(pkt);
  312.         hdr_ip *iph = hdr_ip::access(pkt);
  313.         //printf("flow %d dropping seqno %dn", iph->flowid(),tcph->seqno());
  314. while(tmp != NULL) {
  315. if(tmp->agent_->flowid() == iph->flowid())
  316. tmp->agent_->drop(tcph->seqno());
  317. tmp = tmp->next_;
  318. }
  319. Packet::free(pkt);
  320. }
  321. void DropTargetAgent::insert_tcp(AbsTcpAgent* tcp)
  322. {
  323. Dropper* dppr = new Dropper;
  324. dppr->agent_=tcp;
  325. dppr->next_ = dropper_list_;
  326. dropper_list_ = dppr;
  327. }