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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1996-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 Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    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. #ifndef lint
  35. static const char rcsid[] =
  36.     "@(#) $Header: /cvsroot/nsnam/ns-2/common/ivs.cc,v 1.16 2000/09/01 03:04:05 haoboy Exp $ (LBL)";
  37. #endif
  38. #include <stdlib.h>
  39. #include <math.h>
  40. #include "message.h"
  41. #include "trace.h"
  42. #include "agent.h"
  43. /* ivs data packet; ctrl packets are sent back as "messages" */
  44. struct hdr_ivs {
  45. double ts_; /* timestamp sent at source */
  46. u_int8_t S_;
  47. u_int8_t R_;
  48. u_int8_t state_;
  49. u_int8_t rshft_;
  50. u_int8_t kshft_;
  51. u_int16_t key_;
  52. double maxrtt_;
  53. int seqno_;
  54. static int offset_;
  55. inline static int& offset() { return offset_; }
  56. inline static hdr_ivs* access(Packet* p) {
  57. return (hdr_ivs*) p->access(offset_);
  58. }
  59. /* per-field member functions */
  60. double& ts() { return (ts_); }
  61. u_int8_t& S() { return (S_); }
  62. u_int8_t& R() { return (R_); }
  63. u_int8_t& state() { return (state_); }
  64. u_int8_t& rshft() { return (rshft_); }
  65. u_int8_t& kshft() { return (kshft_); }
  66. u_int16_t& key() { return (key_); }
  67. double& maxrtt() { return (maxrtt_); }
  68. int& seqno() { return (seqno_); }
  69. };
  70. int hdr_ivs::offset_;
  71. static class IvsHeaderClass : public PacketHeaderClass {
  72. public:
  73. IvsHeaderClass() : PacketHeaderClass("PacketHeader/IVS",
  74.      sizeof(hdr_ivs)) {
  75. bind_offset(&hdr_ivs::offset_);
  76. }
  77. } class_ivshdr;
  78. class IvsSource : public Agent {
  79. public:
  80. IvsSource();
  81. protected:
  82. void reset();
  83. void recv(Packet *pkt, Handler*);
  84. void sendpkt();
  85. int S_;
  86. int R_;
  87. int state_;
  88. #define ST_U 0
  89. #define ST_L 1
  90. #define ST_C 2
  91. int rttShift_;
  92. int keyShift_;
  93. int key_;
  94. double maxrtt_;
  95. };
  96. struct Mc_Hole {
  97. int start;
  98. int end;
  99. double time;
  100. Mc_Hole* next;
  101. };
  102. class IvsReceiver : public Agent {
  103. public:
  104. IvsReceiver();
  105. int command(int argc, const char*const* argv);
  106. protected:
  107. void recv(Packet *pkt, Handler*);
  108. void update_ipg(double now);
  109. int lossMeter(double timeDiff, u_int32_t seq, double maxrtt);
  110. void upcall_respond(double ts, int matchS);
  111. void upcall_rtt_solicit(double ts, int rshift);
  112. int state_;
  113. u_int32_t nextSeq_;
  114. double timeMean_;
  115. double timeVar_;
  116. double ipg_; /* interpkt gap (estimator) */
  117. Mc_Hole* head_;
  118. Mc_Hole* tail_;
  119. double lastPktTime_;
  120. int ignoreR_;
  121. double lastTime_; /* last time a resp pkt sent */
  122. int key_;
  123. };
  124. static class IvsSourceClass : public TclClass {
  125. public:
  126. IvsSourceClass() : TclClass("Agent/IVS/Source") {}
  127. TclObject* create(int, const char*const*) {
  128. return (new IvsSource());
  129. }
  130. } class_ivs_source;
  131. static class IvsReceiverClass : public TclClass {
  132. public:
  133. IvsReceiverClass() : TclClass("Agent/IVS/Receiver") {}
  134. TclObject* create(int, const char*const*) {
  135. return (new IvsReceiver());
  136. }
  137. } class_ivs_receiver;
  138. IvsSource::IvsSource() : Agent(PT_MESSAGE), S_(0), R_(0), state_(ST_U),
  139. rttShift_(0), keyShift_(0), key_(0), maxrtt_(0)
  140. {
  141. bind("S_", &S_);
  142. bind("R_", &R_);
  143. bind("state_", &state_);
  144. bind("rttShift_", &rttShift_);
  145. bind("keyShift_", &keyShift_);
  146. bind("key_", &key_);
  147. bind("maxrtt_", &maxrtt_);
  148. }
  149. void IvsSource::reset()
  150. {
  151. }
  152. /*
  153.  * main reception path - should only see acks, otherwise the
  154.  * network connections are misconfigured
  155.  */
  156. void IvsSource::recv(Packet* pkt, Handler*)
  157. {
  158. char wrk[128];/*XXX*/
  159. Tcl& tcl = Tcl::instance();
  160. hdr_msg *q = hdr_msg::access(pkt);
  161. sprintf(wrk, "%s handle {%s}", name(), q->msg());
  162. tcl.eval(wrk);
  163. Packet::free(pkt);
  164. }
  165. #ifdef notdef
  166. void IvsSource::probe_timeout()
  167. {
  168. rndStart_ = now;
  169. if (keyShift_ == 15) {
  170. if (key_ == 0) {
  171. if (solicitedResponses_ == 0)
  172. estReceivers_ = 0;
  173. /*
  174.  * Got through a round without being LOADED.
  175.  * increase send rate.
  176.  */
  177. if (state_ == ST_U)
  178. increase();
  179. /* Reset keys et al */
  180. S_ = 1;
  181. state_ = ST_U;
  182. /*XXX*/
  183. setRttSolicit(mcstate);
  184. solicitedResponses_ = 0;
  185. keyShift_ = startShift_;
  186. /*XXX do all this in tcl? */
  187. setkey();
  188. } else { mcstate->hdr.key = 0; }
  189. } else {
  190. if (probeTimeout_ > 0)
  191. ++keyShift_;
  192. }
  193. sched(pktTime + 2 * maxrtt_, IVS_TIMER_PROBE);
  194. }
  195. #endif
  196. void IvsSource::sendpkt()
  197. {
  198. Packet* pkt = allocpkt();
  199. hdr_ivs *p = hdr_ivs::access(pkt);
  200. /*fill in ivs fields */
  201. p->ts() = Scheduler::instance().clock();
  202. p->S() = S_;
  203. p->R() = R_;
  204. p->state() = state_;
  205. p->rshft() = rttShift_;
  206. p->kshft() = keyShift_;
  207. p->key() = key_;
  208. p->maxrtt() = maxrtt_;
  209. target_->recv(pkt, (Handler *)0);
  210. }
  211. IvsReceiver::IvsReceiver() : Agent(PT_MESSAGE), state_(ST_U),
  212. nextSeq_(0),
  213. timeMean_(0.), timeVar_(0.),/*XXX*/
  214. ipg_(0.),
  215. head_(0),
  216. tail_(0),
  217. lastPktTime_(0.),
  218. ignoreR_(0),
  219. lastTime_(0.),
  220. key_(0)
  221. {
  222. bind("ignoreR_", &ignoreR_);
  223. bind("key_", &key_);
  224. bind("state_", &state_);
  225. bind("packetSize_", &size_);
  226. }
  227. inline void IvsReceiver::update_ipg(double v)
  228. {
  229. /* Update the estimated interpacket gap */
  230. ipg_ = (15 * ipg_ + v) / 16;
  231. }
  232. /*
  233.  * timestamp comes in milliseconds since start of connection according to
  234.  * remote clock
  235.  * now is milliseconds since start of connection
  236.  * rtt in milliseconds
  237.  * This congestion meter is not terribly good at figuring out when the net is 
  238.  * loaded, since the loss of a packet over a rtt is a transitory event
  239.  * Eventually we ought to have a memory thing, that records state once a 
  240.  * maxrtt, with thresholds to decide current state
  241.  */
  242. int IvsReceiver::lossMeter(double timeDiff, u_int32_t seq, double maxrtt)
  243. {
  244. /*
  245.  * The congestion signal is calculated here by measuring the loss in a 
  246.  * given period of packets - if the threshold for lost packets is
  247.  * passed then signal Congested.  If there are no lost packets,
  248.  * then we are at UNLOADED, else LOADED
  249.  */
  250. /* if sequence number is next, increase expected number */
  251. double now = Scheduler::instance().clock();
  252. if (nextSeq_ == 0)
  253. nextSeq_ = seq + 1;
  254. else if (seq == nextSeq_)
  255. nextSeq_++;
  256. else if (seq > nextSeq_) {
  257. #ifdef notdef
  258. if (trace_ != 0) {
  259. sprintf(trace_->buffer(), "d %g %d",
  260. lastPktTime_, seq - nextSeq_);
  261. trace_->dump();
  262. }
  263. #endif
  264. /* This is definitely a hole */
  265. Mc_Hole* hole = new Mc_Hole;
  266. hole->time = now;
  267. hole->start = nextSeq_;
  268. hole->end = seq - 1;
  269. hole->next = 0;
  270. /* Now add it to the list */
  271. if (head_ == NULL) {
  272. head_ = hole;
  273. tail_ = hole;
  274. } else {
  275. tail_->next = hole;
  276. tail_ = hole;
  277. }
  278. nextSeq_ = seq + 1;
  279. } else {
  280. /* XXX can't happen in current ns simulations */
  281. fprintf(stderr, "ns: ivs rcvr: seq number went backwardn");
  282. abort();
  283. }
  284. /* update the calculation of the variance in the rtt */
  285. /* get the time averaged mean of the difference */
  286. if (timeMean_ == 0)
  287. timeMean_ = timeDiff;
  288. else
  289. timeMean_ = (7 * timeMean_ + timeDiff) / 8;
  290. timeDiff -= timeMean_;
  291. if (timeDiff < 0)
  292. timeDiff = -timeDiff;
  293. timeVar_ = (7 * timeVar_ + timeDiff) / 8;
  294. int lostPkts = 0;
  295. /* 
  296.  * Check down the list of holes, discarding those that before
  297.  * now-rttvar-rtt, counting those that fall within
  298.  * now-rttvar to now-rttvar-rtt
  299.  */
  300. if (head_ == 0)
  301. return (ST_U);
  302. Mc_Hole *cur = head_, *prev = NULL;
  303. double validEnd = now - 2 * timeVar_;
  304. double validStart = validEnd - maxrtt;
  305. /* for each hole, if it is older than required, dump it */
  306. /* If it is valid, add the size to the loss count */
  307. /* Go to the next hole */
  308. while (cur != NULL) {
  309. if (cur->time < validStart) {
  310. if (prev == NULL)
  311. head_ = cur->next;
  312. else
  313. prev->next = cur->next;
  314. delete cur;
  315. if (prev == NULL)
  316. cur = head_;
  317. else
  318. cur = prev->next;
  319. } else {
  320. if (cur->time < validEnd)
  321. lostPkts += cur->end - cur->start + 1;
  322. prev = cur;
  323. cur = cur->next;
  324. }
  325. }
  326. /*
  327.  * Update the moving average calculation of the number of holes, if
  328.  * nowMs is another rtt away
  329.  */
  330. double pps = (ipg_ != 0) ? maxrtt / ipg_ : 0.;
  331. /*XXX*/
  332. #ifdef notdef
  333. if (trace_ != 0) {
  334. double now = Scheduler::instance().clock();
  335. sprintf(trace_->buffer(), "%.17g %g", now,
  336. (double)lostPkts / pps);
  337. trace_->dump();
  338. }
  339. #endif
  340. /*XXX*/
  341. #define LOSSCONGTH 15
  342. #define LOSSLOADTH 5
  343. /* If the rtt is smaller than the ipg, set the thresholds to 0,1,2 */
  344. if ((pps * LOSSCONGTH) / 100 < 2)
  345. pps = 200 / LOSSCONGTH;
  346. if (lostPkts <= (LOSSLOADTH * pps) / 100)
  347. return (ST_U);
  348. else if (lostPkts <= (LOSSCONGTH * pps) / 100)
  349. return (ST_L);
  350. else
  351. return (ST_C);
  352. }
  353. void IvsReceiver::recv(Packet* pkt, Handler*)
  354. {
  355. hdr_ivs *p = hdr_ivs::access(pkt);
  356. double now = Scheduler::instance().clock();
  357. if (lastPktTime_ == 0.) {
  358. lastPktTime_ = now;
  359. Packet::free(pkt);
  360. return;
  361. }
  362. update_ipg(now - lastPktTime_);
  363. double ts = p->ts();
  364. int prevState = state_;
  365. state_ = lossMeter(now - ts, p->seqno(), p->maxrtt());
  366. lastPktTime_ = now;
  367. /* If soliciting rtt */
  368. if (p->R() && !ignoreR_)
  369. /* upcall into tcl */
  370. upcall_rtt_solicit(ts, p->rshft());
  371. /*
  372.  * send a response if we're congested and its over an rtt since
  373.  * we last sent one OR
  374.  * any response is solicited to estimate size and we match the key OR
  375.  * we're LOADED and we match the key and its over an rtt since we last
  376.  * sent a response
  377.  */
  378. if (now - lastTime_ < p->maxrtt() && state_ <= prevState) {
  379. Packet::free(pkt);
  380. return;
  381. }
  382. int shift = p->kshft();
  383. int match;
  384. if (p->key() == 0)
  385. match = 1;
  386. else
  387. match = (key_ >> shift) == (p->key() >> shift);
  388. int matchS = match ? p->S() : 0;
  389. if (state_ == ST_C || matchS || (match && state_ == ST_L)) {
  390. upcall_respond(ts, matchS);
  391. lastTime_ = now;
  392. }
  393. Packet::free(pkt);
  394. }
  395. void IvsReceiver::upcall_respond(double ts, int matchS)
  396. {
  397. Tcl::instance().evalf("%s respond %.17g %d", name(), ts, matchS);
  398. }
  399. void IvsReceiver::upcall_rtt_solicit(double ts, int rshift)
  400. {
  401. Tcl::instance().evalf("%s solicit-rtt %.17g %d", name(), ts, rshift);
  402. }
  403. int IvsReceiver::command(int argc, const char*const* argv)
  404. {
  405. Tcl& tcl = Tcl::instance();
  406. if (argc == 3) {
  407. if (strcmp(argv[1], "send") == 0) {
  408. Packet* pkt = allocpkt();
  409. hdr_msg* p = hdr_msg::access(pkt);
  410. const char* s = argv[2];
  411. int n = strlen(s);
  412. if (n >= p->maxmsg()) {
  413. tcl.result("message too big");
  414. Packet::free(pkt);
  415. return (TCL_ERROR);
  416. }
  417. strcpy(p->msg(), s);
  418. target_->recv(pkt, (Handler*)0);
  419. return (TCL_OK);
  420. }
  421. }
  422. return (Agent::command(argc, argv));
  423. }