xcp-end-sys.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) 2004-2006 by the University of Southern California,
  4.  *           Information Sciences Institute
  5.  *                    2002 by Dina Katabi
  6.  * $Id: xcp-end-sys.cc,v 1.12 2006/05/30 20:30:30 pradkin Exp $
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License,
  10.  * version 2, as published by the Free Software Foundation.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License along
  18.  * with this program; if not, write to the Free Software Foundation, Inc.,
  19.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  20.  *
  21.  * All rights reserved.
  22.  *
  23.  * Redistribution and use in source and binary forms are permitted
  24.  * provided that the above copyright notice and this paragraph are
  25.  * duplicated in all such forms and that any documentation, advertising
  26.  * materials, and other materials related to such distribution and use
  27.  * acknowledge that the software was developed by the University of
  28.  * Southern California, Information Sciences Institute.  The name of the
  29.  * University may not be used to endorse or promote products derived from
  30.  * this software without specific prior written permission.
  31.  *
  32.  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  33.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  34.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  35.  *
  36.  */
  37. #ifndef lint
  38. static const char rcsid[] =
  39. "@(#) $Header: /cvsroot/nsnam/ns-2/xcp/xcp-end-sys.cc,v 1.12 2006/05/30 20:30:30 pradkin Exp $";
  40. #endif
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <sys/types.h>
  44. #include "ip.h"
  45. #include "tcp.h"
  46. #include "flags.h"
  47. #include "agent.h"
  48. #include "packet.h"
  49. #include "flags.h"
  50. #include "tcp-sink.h"
  51. #include "xcp-end-sys.h"
  52. #define TRACE 0 // when 0, we don't print any debugging info.
  53. unsigned int XcpEndsys::next_xcp_ = 0;
  54. XcpEndsys::XcpEndsys(TcpAgent *tcp) : tcp_(tcp)
  55. {
  56. init_rtt_vars();
  57. // do not waste sequence numbers on sinks (tcp == 0)
  58. // makes it easier to trace senders
  59. tcpId_ = (tcp == 0) ? 0xffff : next_xcp_++;
  60. current_positive_feedback_ = 0.0;
  61. xcp_srtt_ = 0;
  62. xcp_rev_fb_ = 0;
  63. }
  64. void 
  65. XcpEndsys::trace_var(const char *var_name, double var) const
  66. {
  67. if (tcp_ && tcp_->channel_) {
  68. const size_t SIZE=512;
  69. char wrk[SIZE];
  70. int n = snprintf(wrk, SIZE, "%g x x x x %s %gn", 
  71.  Scheduler::instance().clock(), var_name, var);
  72. (void)Tcl_Write(tcp_->channel_, wrk, n);
  73. }
  74. }
  75. void
  76. XcpEndsys::rtt_init()
  77. {
  78. init_rtt_vars();
  79. }
  80. void XcpEndsys::rtt_update(double tao)
  81. {
  82. if (!tcp_)
  83. return;
  84. #define FIX1 1 /* 1/0 : 1 for experimental XCP changes, works only with timestamps */
  85. double now = Scheduler::instance().clock();
  86. double sendtime = now - tao; // XXX instead, better pass send/recv times as args
  87. int t_rtt;
  88. double tick = tcp_->tcp_tick_;
  89. if (tcp_->ts_option_) {
  90. #if FIX1
  91. int send_tick = int(sendtime/tick);
  92. int recv_tick = int(now/tick);
  93. t_rtt = recv_tick - send_tick;
  94. #else
  95. t_rtt = int(tao / tick + 0.5);
  96. #endif /* FIX1 */
  97. } else {
  98. // XXX I don't understand this business with
  99. // boot_time_, and so not quite sure what FIX1 should
  100. // look like in this case perhaps something like:
  101. //      t_rtt_ = int(now/tcp_tick_) - int((sendtime - tickoff)/tcp_tick_);
  102. // for now FIX1 works only with timestamps.
  103.  
  104. sendtime += tcp_->boot_time_;
  105. double tickoff = fmod(sendtime, tick);
  106. t_rtt = int((tao + tickoff) / tick);
  107. }
  108. assert(t_rtt >= 0);
  109. if (xcp_srtt_ != 0)
  110. xcp_srtt_ = XCP_UPDATE_SRTT(xcp_srtt_, t_rtt);
  111. else 
  112. xcp_srtt_ = XCP_INIT_SRTT(t_rtt);
  113. //if (xcp_srtt_ == 0)
  114. // ++xcp_srtt_; //zero rtts are bad, mkey
  115. srtt_estimate_ = double(xcp_srtt_) * tick / double(1 << XCP_RTT_SHIFT);
  116. if (TRACE) {
  117. printf("%d:  %g  SRTT %g, RTT %g n", tcpId_, now, srtt_estimate_, tao);
  118. }
  119. return;
  120. }
  121. void 
  122. XcpEndsys::recv(Packet *p)
  123. {
  124. hdr_xcp *xh = hdr_xcp::access(p);
  125. if (xh->xcp_enabled_ != hdr_xcp::XCP_DISABLED) {
  126. xcp_rev_fb_ += xh->delta_throughput_;
  127. if (tcp_) {
  128. if (tcp_->channel_) {
  129. trace_var("reverse_feedback_", xh->reverse_feedback_);
  130. trace_var("controlling_hop_", xh->controlling_hop_);
  131. }
  132. double delta_cwnd = 0;
  133. delta_cwnd = (xh->reverse_feedback_
  134.       * srtt_estimate_ 
  135.       / tcp_->size_ );
  136. double newcwnd = (tcp_->cwnd_ + delta_cwnd);
  137. if (tcp_->maxcwnd_ && (newcwnd > tcp_->maxcwnd_))
  138. newcwnd = tcp_->maxcwnd_;
  139. if (newcwnd < 1)
  140. newcwnd = 1;
  141. tcp_->cwnd_ = newcwnd;
  142. if (tcp_->channel_)
  143. trace_var("cwnd", double(tcp_->cwnd_));
  144. }
  145. }
  146. }
  147. void
  148. XcpEndsys::send(Packet *p, int datalen)
  149. {
  150. hdr_xcp *xh = hdr_xcp::access(p);
  151. xh->xcp_enabled_ = (datalen) ? hdr_xcp::XCP_ENABLED : hdr_xcp::XCP_ACK;
  152. xh->rtt_ = srtt_estimate_;
  153. xh->xcpId_ = tcpId_;
  154. xh->reverse_feedback_ = xcp_rev_fb_;
  155. xcp_rev_fb_ = 0;
  156. xh->x_ = 0;
  157. xh->delta_throughput_ = 0;
  158. xh->cwnd_ = 0;
  159. if (!tcp_) return;
  160. xh->cwnd_ = double(tcp_->cwnd_);
  161. double tput = 0;
  162. if (xh->xcp_enabled_) {
  163. #define MAX_THROUGHPUT        1e24
  164. if (srtt_estimate_ != 0) {
  165. tput = tcp_->window() * tcp_->size_ / srtt_estimate_;
  166. xh->x_ = srtt_estimate_/tcp_->window();
  167. xh->delta_throughput_ = (MAX_THROUGHPUT 
  168.  - tput);
  169. } else {
  170. //XXX can do xh->xcp_enabled_ = hdr_xcp::XCP_DISABLED;
  171. xh->x_ = 0;
  172. xh->delta_throughput_ = 0;
  173. }
  174. if (tcp_->channel_) {
  175. trace_var("throughput", tput);
  176. }
  177. }
  178. }
  179. XcpNewRenoFullTcpAgent::XcpNewRenoFullTcpAgent() 
  180. : NewRenoFullTcpAgent(), XcpEndsys(this)
  181. {
  182. type_ = PT_XCP;
  183. }
  184. void 
  185. XcpNewRenoFullTcpAgent::delay_bind_init_all() 
  186. {
  187. NewRenoFullTcpAgent::delay_bind_init_all();
  188. }
  189. int
  190. XcpNewRenoFullTcpAgent::delay_bind_dispatch(const char *varName, 
  191.     const char *localName, 
  192.     TclObject *tracer)
  193. {
  194. return NewRenoFullTcpAgent::delay_bind_dispatch(varName, localName, tracer);
  195. }
  196. void
  197. XcpNewRenoFullTcpAgent::rtt_update(double tao)
  198. {
  199. //order seems unimportant here
  200. XcpEndsys::rtt_update(tao);
  201. NewRenoFullTcpAgent::rtt_update(tao);
  202. }
  203. void 
  204. XcpNewRenoFullTcpAgent::rtt_init()
  205. {
  206. //order seems unimportant here
  207. NewRenoFullTcpAgent::rtt_init();
  208. XcpEndsys::rtt_init();
  209. }
  210. void 
  211. XcpNewRenoFullTcpAgent::recv(Packet *p,  Handler *h)
  212. {
  213. // xcp must be done before tcp because tcp will consume the packet
  214. XcpEndsys::recv(p);
  215. NewRenoFullTcpAgent::recv(p, h);
  216. }
  217. void 
  218. XcpNewRenoFullTcpAgent::sendpacket(int seqno, int ackno, int pflags, 
  219.    int datalen, int reason, Packet *p)
  220. {
  221. // xcp must be done before tcp because tcp will consume the packet
  222. if (!p) p = allocpkt();
  223. XcpEndsys::send(p, datalen);
  224. NewRenoFullTcpAgent::sendpacket(seqno, ackno, pflags, 
  225. datalen, reason, p);
  226. }
  227. XcpRenoTcpAgent::XcpRenoTcpAgent()
  228. : RenoTcpAgent(), XcpEndsys(this)
  229. {
  230. type_ = PT_XCP; 
  231. }
  232. void
  233. XcpRenoTcpAgent::delay_bind_init_all()
  234. {
  235. RenoTcpAgent::delay_bind_init_all();
  236. }
  237. int
  238. XcpRenoTcpAgent::delay_bind_dispatch(const char *varName, 
  239.      const char *localName, 
  240.      TclObject *tracer)
  241. {
  242. return RenoTcpAgent::delay_bind_dispatch(varName, localName, tracer);
  243. }
  244. void
  245. XcpRenoTcpAgent::output_helper(Packet* p)
  246. {
  247. int datalen = hdr_cmn::access(p)->size();
  248. XcpEndsys::send(p, datalen);
  249. }
  250. void
  251. XcpRenoTcpAgent::recv_newack_helper(Packet *p)
  252. {
  253. RenoTcpAgent::recv_newack_helper(p);
  254. XcpEndsys::recv(p);
  255. }
  256. void
  257. XcpRenoTcpAgent::rtt_update(double tao)
  258. {
  259. XcpEndsys::rtt_update(tao);
  260. RenoTcpAgent::rtt_update(tao);
  261. }
  262. void 
  263. XcpRenoTcpAgent::rtt_init()
  264. {
  265. RenoTcpAgent::rtt_init();
  266. XcpEndsys::rtt_init();
  267. }
  268. XcpTcpSink::XcpTcpSink(Acker *a) 
  269. : TcpSink(a), XcpEndsys(0)
  270. {
  271. }
  272. void
  273. XcpTcpSink::delay_bind_init_all()
  274. {
  275. TcpSink::delay_bind_init_all();
  276. }
  277. int
  278. XcpTcpSink::delay_bind_dispatch(const char *varName, 
  279.      const char *localName, 
  280.      TclObject *tracer)
  281. {
  282. return TcpSink::delay_bind_dispatch(varName, localName, tracer);
  283. }
  284. void
  285. XcpTcpSink::recv(Packet* p, Handler *h)
  286. {
  287. XcpEndsys::recv(p);
  288. TcpSink::recv(p, h);
  289. }
  290. void
  291. XcpTcpSink::add_to_ack(Packet *p)
  292. {
  293. int datalen = 0;
  294. XcpEndsys::send(p, datalen);
  295. TcpSink::add_to_ack(p);
  296. }
  297. //static tclcl goo follows
  298. int hdr_xcp::offset_;
  299. static class XCPHeaderClass : public PacketHeaderClass {
  300. public:
  301.         XCPHeaderClass() : PacketHeaderClass("PacketHeader/XCP",
  302.      sizeof(hdr_xcp)) {
  303. bind_offset(&hdr_xcp::offset_);
  304. }
  305. } class_xcphdr;
  306. static class XcpNewRenoFullTcpAgentClass : public TclClass {
  307. public:
  308. XcpNewRenoFullTcpAgentClass() : TclClass("Agent/TCP/FullTcp/Newreno/XCP") {}
  309. virtual TclObject* create(int, const char* const*) {
  310. return (new XcpNewRenoFullTcpAgent());
  311. }
  312. } class_xcp_newreno_full_tcp_agent;
  313. static class XcpRenoTcpAgentClass : public TclClass {
  314. public:
  315. XcpRenoTcpAgentClass() : TclClass("Agent/TCP/Reno/XCP") {}
  316. TclObject* create(int, const char*const*) {
  317. return (new XcpRenoTcpAgent());
  318. }
  319. } class_xcp_reno_tcp_agent;
  320. static class XcpTcpSinkClass : public TclClass {
  321. public:
  322. XcpTcpSinkClass() : TclClass("Agent/TCPSink/XCPSink") {}
  323. TclObject* create(int, const char*const*) {
  324. return (new XcpTcpSink(new Acker));
  325. }
  326. } class_xcp_tcpsink_agent;