srm-topo.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) Xerox Corporation 1997. All rights reserved.
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * 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.  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18.  *
  19.  * Linking this file statically or dynamically with other modules is making
  20.  * a combined work based on this file.  Thus, the terms and conditions of
  21.  * the GNU General Public License cover the whole combination.
  22.  *
  23.  * In addition, as a special exception, the copyright holders of this file
  24.  * give you permission to combine this file with free software programs or
  25.  * libraries that are released under the GNU LGPL and with code included in
  26.  * the standard release of ns-2 under the Apache 2.0 license or under
  27.  * otherwise-compatible licenses with advertising requirements (or modified
  28.  * versions of such code, with unchanged license).  You may copy and
  29.  * distribute such a system following the terms of the GNU GPL for this
  30.  * file and the licenses of the other code concerned, provided that you
  31.  * include the source code of that other code when and as the GNU GPL
  32.  * requires distribution of source code.
  33.  *
  34.  * Note that people who make modified versions of this file are not
  35.  * obligated to grant this special exception for their modified versions;
  36.  * it is their choice whether to do so.  The GNU General Public License
  37.  * gives permission to release a modified version without this exception;
  38.  * this exception also makes it possible to release a modified version
  39.  * which carries forward this exception.
  40.  *
  41.  * This file contributed by Suchitra Raman <sraman@parc.xerox.com>, June 1997.
  42.  */
  43. #include <stdlib.h>
  44. #include <math.h>
  45. #include <assert.h>
  46. #include "config.h"
  47. #include "tclcl.h"
  48. #include "srm-topo.h"
  49. #include "scheduler.h"
  50. #define SRM_DEBUG
  51. Topology::Topology(int nn, int src) : idx_(nn), src_(src)
  52. {
  53. node_ = new SrmNode[nn];
  54. for (int i = 0; i < nn; i ++) 
  55. node_[i].id(i);
  56. bind("src_", &src_);
  57. bind("delay_", &delay_);
  58. bind("D_", &D_);
  59. bind("frac_", &frac_);
  60. /* D_ (ms) is the delay of node 1 from node 0 */
  61. bind("det_", &det_);
  62. bind("rtt_est_", &rtt_est_);
  63. bind("rand_", &rand_);
  64. }
  65. Topology::~Topology() {
  66. delete [] node_;
  67. }
  68. int Topology::command(int argc, const char*const* argv) 
  69. {
  70. //Tcl& tcl = Tcl::instance();
  71. if (argc == 3) {
  72. if (strcmp(argv[1], "flood") == 0) {
  73. flood(0, atoi(argv[2]));
  74. return (TCL_OK);
  75. }
  76. }
  77. return (TclObject::command(argc, argv));
  78. }
  79. SrmNode* Topology::node(int nn) 
  80. if (nn < 0 || nn >= idx_) return 0;
  81. return &(node_[nn]); 
  82. }
  83. static class LineClass : public TclClass {
  84. public:
  85. LineClass() : TclClass("Topology/Line") {} 
  86. TclObject* create(int, const char*const* argv) {
  87. int nn = atoi(argv[4]);
  88. return (new Line(nn, 0));
  89. }
  90. } class_line_topo;
  91. double Line::backoff(int dst) 
  92. {
  93. double rtt;
  94. if (topology->rtt_estimated() == 1)
  95. rtt = delay(dst, 0);
  96. else rtt = D_ * frac_;
  97. double b;
  98. double sqroot = sqrt(rtt);
  99. double r = Random::uniform(0.0, 1.0);
  100. switch(c2func_) {
  101. case LOG :
  102. b = rtt * (det_ +  rand_ * r * log(rtt)/log(D_));
  103. break;
  104. case SQRT :
  105. b = rtt * (det_ +  rand_ * r * sqroot/sqrt(D_));
  106. break;
  107. case LINEAR :
  108. b = rtt * (det_ +  rand_ * r * rtt/D_);
  109. break;
  110. case CONSTANT :
  111. b = rtt * (det_ +  rand_ * r * 1.);
  112. break;
  113. default:
  114. // quiet compiler
  115. b = 0.0;
  116. assert (false);
  117. break;
  118. }
  119. return b;
  120. }
  121. #ifdef SRM_BIMODAL
  122. double Line::backoff(int dst) 
  123. {
  124. double rtt;
  125. if (topology->rtt_estimated() == 1) 
  126. rtt = delay(dst, 0);
  127. else rtt = D_ * frac_;
  128. double rbackoff;
  129. double p = Random::uniform(0.0, 1.0);
  130. int bin = 0;
  131. int copies = c_;
  132. int size = topology->idx();
  133. if (p <= copies * 1./size) {
  134. rbackoff = Random::uniform(0.0, alpha_);
  135. bin = 0;
  136. } else {
  137. rbackoff = Random::uniform(beta_, 1.0 + beta_);
  138. bin = 1;
  139. }
  140. return (rtt * (det_ + rand_ * rbackoff));
  141. }
  142. #endif
  143. Interface_List* Line::oif(int node, int iif=SRM_NOIF)
  144. {
  145. //int oif;
  146. Interface_List *ilist = new Interface_List;
  147. /* If there are no more nodes downstream, return -1 */
  148. if ((iif <= node && node >= idx_ - 1) ||  (iif > node && node == 0))
  149. return 0;
  150. if (iif == SRM_NOIF) 
  151. {
  152. ilist->append(node + 1);
  153. ilist->append(node - 1);
  154. } else if (iif <= node) 
  155. ilist->append(node + 1);
  156. else 
  157. ilist->append(node - 1);
  158. return (ilist);
  159. }
  160. double Line::delay(int src, int dst) 
  161. {
  162. if (src == 0 || dst == 0) 
  163. return D_ + delay_ * abs(dst - src - 1);
  164. else
  165. return delay_ * abs(dst - src);
  166. }
  167. double Star::delay(int src, int dst) 
  168. {
  169. if (src == 0 || dst == 0) 
  170. return D_;
  171. else
  172. return delay_;
  173. }
  174. /* 
  175.  * Very simple now, can only send to direct ancestor/descendant 
  176.  */
  177. double BTree::delay(int src, int dst)
  178. {
  179. double src_ht = 0;
  180. double dst_ht = 0;
  181. if (src > 0) 
  182. src_ht = 1 + floor(log(src)/log(2));
  183. if (dst > 0)
  184. dst_ht = 1 + floor(log(dst)/log(2));
  185. if (src == 0 || dst == 0) 
  186. return D_ + delay_ * abs(int (dst_ht - src_ht - 1));
  187. else 
  188. return delay_ * abs(int (dst_ht - src_ht));
  189. }
  190. /* 
  191.  * There is always an outbound interface. We should not 
  192.  * start a flood() from a leaf node. 
  193.  * Change it for other topologies. 
  194.  */
  195. void Line::flood(int start, int seqno)
  196. {
  197. SRM_Event *se = new SRM_Event(seqno, SRM_DATA, start);
  198. node_[start].send(se);
  199. }
  200. /*
  201.  * BTree -
  202.  */
  203. static class BTreeClass : public TclClass {
  204. public:
  205. BTreeClass() : TclClass("Topology/BTree") {} 
  206. TclObject* create(int, const char*const* argv) {
  207. int nn = atoi(argv[4]);
  208. return (new BTree(nn, 0));
  209. }
  210. } class_btree_topo;
  211. /* 
  212.  * The ranges of the different distributions 
  213.  * must be normalized to 1. 
  214.  */
  215. double BTree::backoff(int id) 
  216. {
  217. double rtt;
  218. if (topology->rtt_estimated())
  219. rtt = delay(id, 0);
  220. else rtt = D_ * frac_; 
  221. double r = Random::uniform(0.0, 1.0);
  222. double b;
  223. double sqroot = sqrt(rtt);
  224. double D = topology->D();
  225. switch(c2func_) {
  226. case LOG :
  227. b = rtt * (det_ +  rand_ * r * log(rtt)/log(D));
  228. break;
  229. case SQRT :
  230. b = rtt * (det_ +  rand_ * r * sqroot/sqrt(D));
  231. break;
  232. case LINEAR :
  233. b = rtt * (det_ +  rand_ * r * rtt/D);
  234. break;
  235. case CONSTANT :
  236. b = rtt * (det_ +  rand_ * r * 1.);
  237. break;
  238. default:
  239. // quiet compiler
  240. b = 0.0;
  241. assert (false);
  242. break;
  243. }
  244. return b;
  245. }
  246. Interface_List* BTree::oif(int node, int iif=SRM_NOIF)
  247. {
  248. //int oif;
  249. Interface_List *ilist = new Interface_List;
  250. /* 
  251.  * If the packet comes from the source, 
  252.  * there is only 1 outgoing link.
  253.  * We make the assumption that source = 0 always (YUCK!)
  254.  */
  255. if (iif == SRM_NOIF) {
  256. if (node == 0) {
  257. ilist->append(1);
  258. }
  259. else {
  260. ilist->append(2 * node + 1);
  261. ilist->append(2 * node);
  262. int k = (int)floor(.5 * node);
  263. ilist->append(k);
  264. }
  265. } else if (iif <= node) {
  266. ilist->append(2 * node + 1);
  267. ilist->append(2 * node);
  268. }
  269. // Packet came along 2n + 1 or 2n + 2
  270. else if (iif == 2 * node + 1) {
  271. if (node == 0)
  272. return ilist;
  273. ilist->append(2 * node);
  274. ilist->append((int) floor(.5 * node));
  275. } else if (iif == 2 * node) {
  276. ilist->append(2 * node + 1);
  277. ilist->append((int)floor(.5 * node));
  278. }
  279. return (ilist);
  280. }
  281. /*
  282.  * Star -
  283.  */
  284. static class StarClass : public TclClass {
  285. public:
  286. StarClass() : TclClass("Topology/Star") {} 
  287. TclObject* create(int, const char*const* argv) {
  288. int nn = atoi(argv[4]);
  289. return (new Star(nn, 0));
  290. }
  291. } class_star_topo;
  292. /* 
  293.  * SrmNode -
  294.  */
  295. void SrmNode::dump_packet(SRM_Event *e) 
  296. {
  297. #ifdef SRM_DEBUG
  298. tprintf(("(type %d) (in %d) -- @ %d --> n", e->type(), e->iif(), id_));
  299. #endif
  300. }
  301. /* This forwards an event by making multiple copies of the
  302.  * event 'e'. Does NOT free event 'e'. 
  303.  */
  304. void SrmNode::send(SRM_Event *e) 
  305. {
  306. /* 
  307.  * Copy the packet and send it over to 
  308.  * all the outbound interfaces 
  309.  */
  310. int nn;
  311. Scheduler& s = Scheduler::instance();
  312. SRM_Event *copy;
  313. Interface *p;
  314. Interface_List *ilist = topology->oif(id_, e->iif());
  315. if (e->iif() < 0)
  316. e->iif(id_);
  317. if (ilist) {
  318. for (p=ilist->head_; p; p=p->next_) {
  319. nn = p->in_;
  320. int t = e->type();
  321. //int i = id_; 
  322. int snum = e->seqno();
  323. SrmNode *next = topology->node(nn);
  324. if (next) {
  325. copy = new SRM_Event(snum, t, id_);
  326. s.schedule(next, copy,
  327.    topology->delay(id_, nn));  
  328. }
  329. }
  330. }
  331. delete ilist;
  332. delete e;
  333. }
  334. /* 
  335.  * Demux the two types of events depending on 
  336.  * the type field.
  337.  */ 
  338. void SrmNode::handle(Event* event)
  339. {
  340. SRM_Event *srm_event = (SRM_Event *) event;
  341. int type  = srm_event->type();
  342. int seqno = srm_event->seqno();
  343. //int iif   = srm_event->iif();
  344. //Scheduler& s = Scheduler::instance();
  345. switch (type) {
  346. case SRM_DATA :
  347. if (seqno != expected_) 
  348. sched_nack(seqno);
  349. expected_ = seqno;
  350. break;
  351. case SRM_PENDING_RREQ :
  352. tprintf(("Fired RREQ (node %d)n", id_));
  353. remove(seqno, SRM_NO_SUPPRESS);
  354. srm_event->type(SRM_RREQ);
  355. break;
  356. case SRM_RREQ :
  357. remove(seqno, SRM_SUPPRESS);
  358. break;
  359. default :
  360. tprintf(("panic: node(%d) Unexpected type %dn", id_, type));
  361. return;
  362. }
  363. #ifdef SRM_STAR
  364. if (type == SRM_RREQ || type == SRM_DATA) {
  365. delete srm_event;
  366. return;
  367. }
  368. #endif
  369. send(srm_event);
  370. return;
  371. }
  372. /* 
  373.  * XXX Should take two sequence numbers. The iif field is a dummy. We should be
  374.  * careful not to use it for NACKs 
  375.  */
  376. void SrmNode::sched_nack(int seqno) 
  377. {
  378. double backoff, time;
  379. Scheduler& s = Scheduler::instance();
  380. SRM_Event *event = new SRM_Event(seqno, 
  381.  SRM_PENDING_RREQ, SRM_NOIF);
  382. append(event);
  383. backoff = topology->backoff(id_);
  384. time = backoff + s.clock();
  385. // tprintf(("node(%d) schd rrq after %f sn", id_, backoff));
  386. s.schedule(this, event, backoff);
  387. }
  388. void SrmNode::append(SRM_Event *e) 
  389. {
  390. SRM_Request *req = new SRM_Request(e);
  391. req->next_ = pending_;
  392. pending_ = req;
  393. }
  394. /* If an event identical to e exists, cancel it */
  395. void SrmNode::remove(int seqno, int flag)
  396. {
  397. SRM_Request *curr, *prev;
  398. SRM_Event *ev;
  399. if (!pending_)
  400. return;
  401. for (curr=pending_, prev=0; curr; curr=curr->next_) 
  402. {
  403. ev = curr->event_;
  404. if (ev->seqno() == seqno) {
  405. if (!prev) 
  406. pending_ = curr->next_;
  407. else {
  408. prev->next_ = curr->next_;
  409. prev = curr;
  410. }
  411. if (flag == SRM_SUPPRESS) {
  412. curr->cancel_timer();
  413. }
  414. delete curr;
  415. }
  416. }
  417. }
  418. SRM_Event::SRM_Event(SRM_Event *e) 
  419. {
  420. seqno_ = e->seqno();
  421. type_  = e->type();
  422. iif_   = e->iif();
  423. }
  424. SRM_Request::~SRM_Request() {}
  425. void SRM_Request::cancel_timer() 
  426. {
  427. if (event_) {
  428. Scheduler& s = Scheduler::instance();
  429. s.cancel(event_);
  430. // xxx: should event be free'd?  possible memory leak.
  431. }
  432. }
  433. void Interface_List::append(int in) 
  434. {
  435. Interface *i = new Interface(in);
  436. i->next_ = head_;
  437. head_ = i;
  438. }
  439. Interface_List::~Interface_List() 
  440. {
  441. Interface *p, *next;
  442. for (p=head_; p; p=next)
  443. {
  444. next = p->next_;
  445. delete p;
  446. }
  447. }
  448. void BTree::flood(int start, int seqno)
  449. {
  450. SRM_Event *se = new SRM_Event(seqno, SRM_DATA, SRM_NOIF);
  451. node_[start].send(se);
  452. }
  453. void Star::flood(int start, int seqno)
  454. {
  455. SRM_Event *se = new SRM_Event(seqno, SRM_DATA, start);
  456. node_[start].send(se);
  457. }
  458. Interface_List* Star::oif(int node, int iif=SRM_NOIF)
  459. {
  460. int i;
  461. Interface_List *ilist = new Interface_List;
  462. /* Make a list with every node except myself */
  463. for (i = 0; i < topology->idx(); i ++)
  464. {
  465. if (i != node && i != iif) {
  466. ilist->append(i);
  467. }
  468. }
  469. return (ilist);
  470. }
  471. /* 
  472.  * Distance of source to cluster = D_
  473.  */
  474. double Star::backoff(int id)
  475. {
  476. double rtt = topology->delay(id, 0);
  477. double rbackoff;
  478. double p = Random::uniform(0.0, 1.0);
  479. static int bin = 0;
  480. int copies = c_;
  481. int size = topology->idx();
  482. if (p <= copies * 1./size) {
  483. rbackoff = Random::uniform(0.0, alpha_);
  484. bin ++;
  485. } else {
  486. rbackoff = Random::uniform(beta_, 1.0 + beta_);
  487. }
  488. return (rtt * (det_ + rand_ * rbackoff));
  489. }
  490. #ifdef SRM_BIMODAL
  491. double BTree::backoff(int dst) 
  492. {
  493. double height = floor(log(dst)/log(2));
  494. double D = topology->D();
  495. double rtt = delay_ * height + D;
  496. double p = Random::uniform(0.0, 1.0);
  497. double rbackoff;
  498. static int bin = 0;
  499. int copies = c_;
  500. int size = topology->idx();
  501. if (p <= copies * 1./size) {
  502. rbackoff = Random::uniform(0.0, alpha_);
  503. bin ++;
  504. } else {
  505. rbackoff = Random::uniform(1.0 + alpha_, 2.0);
  506. }
  507. return (rtt * (det_ + rand_ * rbackoff));
  508. }
  509. #endif