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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *  This product includes software developed by the Daedalus Research
  17.  *  Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * Contributed by the Daedalus Research Group, U.C.Berkeley
  35.  * http://daedalus.cs.berkeley.edu
  36.  *
  37.  * $Header: /cvsroot/nsnam/ns-2/tcp/tcp-int.cc,v 1.15 2000/09/01 03:04:07 haoboy Exp $
  38.  */
  39. /*
  40.  * We separate TCP functionality into two parts: that having to do with 
  41.  * providing a reliable, ordered byte-stream service, and that having to do with
  42.  * congestion control and loss recovery. The former is done on a per-connection
  43.  * basis and is implemented as part of IntTcpAgent ("integrated TCP"). The 
  44.  * latter is done in an integrated fashion across multiple TCP connections, and
  45.  * is implemented as part of TcpSessionAgent ("TCP session"). TcpSessionAgent is
  46.  * derived from CorresHost ("correspondent host"), which keeps track of the 
  47.  * state of all TCP (TCP/Int) connections to a host that it is corresponding 
  48.  * with.
  49.  *
  50.  * The motivation for this separation of functionality is to make an ensemble of
  51.  * connection more well-behaved than a set of independent TCP connections.
  52.  * The packet loss rate is cut down and the chances of losses being recovered 
  53.  * via data-driven techniques (rather than via timeouts) is improved. At the 
  54.  * same time, we do not introduce any unnecessary coupling between the 
  55.  * logically-independent byte-streams that the set of connections represents. 
  56.  * This is in contrast to the coupling that is inherent in the multiplexing at 
  57.  * the application layer of multiple byte-streams onto a single TCP connection.
  58.  */
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <sys/types.h>
  62. #include "packet.h"
  63. #include "ip.h"
  64. #include "tcp.h"
  65. #include "flags.h"
  66. #include "nilist.h"
  67. #include "tcp-int.h"
  68. #include "chost.h"
  69. #include "tcp-session.h"
  70. #include "random.h"
  71. Islist<TcpSessionAgent> TcpSessionAgent::sessionList_;
  72. static class IntTcpClass : public TclClass {
  73. public:
  74. IntTcpClass() : TclClass("Agent/TCP/Int") {}
  75. TclObject* create(int, const char*const*) {
  76. return (new IntTcpAgent());
  77. }
  78. } class_tcp_int;
  79. IntTcpAgent::IntTcpAgent() : TcpAgent(), slink(), 
  80. session_(0), closecwTS_(0), lastTS_(-1), count_(0), 
  81. wt_(1), wndIncSeqno_(0), num_thresh_dupack_segs_(0)
  82. {
  83. bind("rightEdge_", &rightEdge_);
  84. bind("uniqTS_", &uniqTS_);
  85. bind("winInc_", &winInc_);
  86. bind("winMult_", &winMult_);
  87. }
  88. int
  89. IntTcpAgent::command(int argc, const char*const* argv)
  90. {
  91. Tcl& tcl = Tcl::instance();
  92. if (argc == 3) {
  93. if (!strcmp(argv[1], "setwt")) {
  94. if (!session_)
  95. createTcpSession();
  96. session_->set_weight(this,atoi(argv[2]));
  97. return (TCL_OK);
  98. }
  99. }
  100. else if (argc == 2) {
  101. if (!strcmp(argv[1], "session")) {
  102. if (!session_)
  103. createTcpSession();
  104. tcl.resultf("%s", session_->name());
  105. return (TCL_OK);
  106. }
  107. }
  108. return (TcpAgent::command(argc,argv));
  109. }
  110. /* 
  111.  * Update the ack information and reset the timer. RTT update is done in 
  112.  * TcpSessionAgent.
  113.  */
  114. void
  115. IntTcpAgent::newack(Packet* pkt)
  116. {
  117. hdr_tcp *tcph = hdr_tcp::access(pkt);
  118. last_ack_ = tcph->seqno();
  119. highest_ack_ = last_ack_;
  120. if (t_seqno_ < last_ack_ + 1)
  121. t_seqno_ = last_ack_ + 1;
  122. /* if the connection is done, call finish() */
  123. if ((highest_ack_ >= curseq_-1) && !closed_) {
  124. closed_ = 1;
  125. finish();
  126. }
  127. }
  128. void 
  129. IntTcpAgent::recv(Packet *pkt, Handler *)
  130. {
  131. hdr_tcp *tcph = hdr_tcp::access(pkt);
  132. int amt_data_acked = 0;
  133. if (tcph->seqno() > last_ack_) {
  134. amt_data_acked = tcph->seqno() - last_ack_;
  135. newack(pkt);
  136. session_->recv(this, pkt, amt_data_acked);
  137. }
  138. void
  139. IntTcpAgent::createTcpSession()
  140. {
  141. Tcl& tcl = Tcl::instance();
  142. tcl.evalf("%s set node_", name());
  143. tcl.evalf("%s createTcpSession %d", tcl.result(), daddr());
  144. Islist_iter<TcpSessionAgent> session_iter(TcpSessionAgent::sessionList_);
  145. TcpSessionAgent *cur;
  146. while ((cur = session_iter()) != NULL) {
  147. if (cur->addr()/256 == addr() && cur->daddr() == daddr()) {
  148. session_ = cur;
  149. break;
  150. }
  151. }
  152. if (!session_) {
  153. printf("In IntTcpAgent::createTcpSession(): failedn");
  154. abort();
  155. }
  156. session_->add_agent(this, size_, winMult_, winInc_, ssthresh_);
  157. }
  158. void
  159. IntTcpAgent::output(int seqno, int reason)
  160. {
  161. Packet *pkt = allocpkt();
  162. hdr_tcp *tcph = hdr_tcp::access(pkt);
  163. tcph->seqno() = seqno;
  164. tcph->ts() = Scheduler::instance().clock();
  165. tcph->ts_echo() = ts_peer_;
  166. tcph->reason() = reason;
  167. session_->setflags(pkt);
  168. int bytes = hdr_cmn::access(pkt)->size();
  169. /* call helper function to fill in additional fields */
  170. output_helper(pkt);
  171.         ++ndatapack_;
  172. ndatabytes_ += bytes;
  173. send(pkt, 0);
  174. if (seqno == curseq_ && seqno > maxseq_)
  175. idle();  // Tell application I have sent everything so far
  176. if (seqno > maxseq_) {
  177. maxseq_ = seqno;
  178. }
  179. else {
  180.          ++nrexmitpack_;
  181.          nrexmitbytes_ += bytes;
  182. }
  183. if (wndIncSeqno_ == 0)
  184. wndIncSeqno_ = maxseq_;
  185. }
  186. /*
  187.  * Unlike in other flavors of TCP, IntTcpAgent does not decide when to send 
  188.  * packets and how many of them to send. That decision is made by 
  189.  * TcpSessionAgent. So send_much() does little more than defer to 
  190.  * TcpSessionAgent.
  191.  */
  192. void
  193. IntTcpAgent::send_much(int force, int reason, int /*maxburst*/)
  194. {
  195. if (!session_)
  196. createTcpSession();
  197. if (!force && delsnd_timer_.status() == TIMER_PENDING)
  198. return;
  199. if (overhead_ && !force) {
  200. delsnd_timer_.resched(Random::uniform(overhead_));
  201. return;
  202. }
  203. session_->send_much(this, force,reason);
  204. }
  205. /*
  206.  * Send one new packet.
  207.  */
  208. void
  209. IntTcpAgent::send_one(int sessionSeqno)
  210. {
  211. int dst_addr = daddr();
  212. int dst_port = dport();
  213. int sport = port();
  214. if (!session_)
  215. createTcpSession();
  216. /* 
  217.  * XXX We assume that the session layer has already made sure that
  218.  * we have data to send.
  219.  */
  220. output(t_seqno_++); 
  221. session_->add_pkts(size_, t_seqno_ - 1, sessionSeqno,
  222.    dst_addr, dst_port, sport, lastTS_, this); 
  223. }
  224. /*
  225.  * open up the congestion window
  226.  */
  227. void 
  228. IntTcpAgent::opencwnd()
  229. {
  230. session_->opencwnd(size_, this);
  231. }
  232. /*
  233.  * close down the congestion window
  234.  */
  235. void 
  236. IntTcpAgent::closecwnd(int how)
  237. {   
  238. session_->closecwnd(how, this);
  239. }
  240. Segment *
  241. IntTcpAgent::rxmit_last(int reason, int seqno, int sessionSeqno, double /*ts*/)
  242. {
  243. session_->agent_rcov(this);
  244. /* 
  245.  * XXX kludge -- IntTcpAgent is not supposed to deal with 
  246.  * rtx timer 
  247.  */
  248. session_->reset_rtx_timer(1,0); 
  249. output(seqno, reason);
  250. daddr_ = daddr();
  251. dport_ = dport();
  252. sport_ = port();
  253. return (session_->add_pkts(size_, seqno, sessionSeqno, daddr_, 
  254.    dport_, sport_, lastTS_, this));
  255. return NULL;
  256. }
  257. unsigned long output_helper_count=0;
  258. double last_clock=0;
  259. void
  260. IntTcpAgent::output_helper(Packet *p)
  261. {
  262. double now = Scheduler::instance().clock();
  263. output_helper_count++;
  264. last_clock = now;
  265. hdr_tcp *tcph = hdr_tcp::access(p);
  266. /* This is to make sure that we get unique times for each xmission */
  267. while (uniqTS_ && now <= lastTS_) {
  268. now += 0.000001; // something arbitrarily small
  269. }
  270. lastTS_ = now;
  271. tcph->ts() = now;
  272. /* if this is a fast start pkt and not a retransmission, mark it */
  273. if (session_->fs_pkt() && tcph->seqno() > maxseq_)
  274. hdr_flags::access(p)->fs_ = 1;
  275. return;
  276. }
  277. int 
  278. IntTcpAgent::data_left_to_send() {
  279. return (curseq_ > t_seqno_);
  280. }