00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <math.h>
00023
00024 #include "config.h"
00025 #include "tclcl.h"
00026 #include "srm-topo.h"
00027 #include "scheduler.h"
00028
00029 #define SRM_DEBUG
00030
00031
00032 Topology::Topology(int nn, int src) : idx_(nn), src_(src)
00033 {
00034 node_ = new SrmNode[nn];
00035 for (int i = 0; i < nn; i ++)
00036 node_[i].id(i);
00037
00038 bind("src_", &src_);
00039 bind("delay_", &delay_);
00040 bind("D_", &D_);
00041 bind("frac_", &frac_);
00042
00043
00044 bind("det_", &det_);
00045 bind("rtt_est_", &rtt_est_);
00046 bind("rand_", &rand_);
00047 }
00048
00049 Topology::~Topology() {
00050 delete [] node_;
00051 }
00052
00053 int Topology::command(int argc, const char*const* argv)
00054 {
00055
00056 if (argc == 3) {
00057 if (strcmp(argv[1], "flood") == 0) {
00058 flood(0, atoi(argv[2]));
00059 return (TCL_OK);
00060 }
00061 }
00062 return (TclObject::command(argc, argv));
00063 }
00064
00065 SrmNode* Topology::node(int nn)
00066 {
00067 if (nn < 0 || nn >= idx_) return 0;
00068 return &(node_[nn]);
00069 }
00070
00071
00072 static class LineClass : public TclClass {
00073 public:
00074 LineClass() : TclClass("Topology/Line") {}
00075 TclObject* create(int, const char*const* argv) {
00076 int nn = atoi(argv[4]);
00077 return (new Line(nn, 0));
00078 }
00079 } class_line_topo;
00080
00081
00082 double Line::backoff(int dst)
00083 {
00084 double rtt;
00085
00086 if (topology->rtt_estimated() == 1)
00087 rtt = delay(dst, 0);
00088 else rtt = D_ * frac_;
00089 double b;
00090 double sqroot = sqrt(rtt);
00091 double r = Random::uniform(0.0, 1.0);
00092
00093 switch(c2func_) {
00094 case LOG :
00095 b = rtt * (det_ + rand_ * r * log(rtt)/log(D_));
00096 break;
00097 case SQRT :
00098 b = rtt * (det_ + rand_ * r * sqroot/sqrt(D_));
00099 break;
00100 case LINEAR :
00101 b = rtt * (det_ + rand_ * r * rtt/D_);
00102 break;
00103 case CONSTANT :
00104 b = rtt * (det_ + rand_ * r * 1.);
00105 break;
00106 }
00107 return b;
00108 }
00109
00110 #ifdef SRM_BIMODAL
00111 double Line::backoff(int dst)
00112 {
00113 double rtt;
00114 if (topology->rtt_estimated() == 1)
00115 rtt = delay(dst, 0);
00116 else rtt = D_ * frac_;
00117
00118 double rbackoff;
00119 double p = Random::uniform(0.0, 1.0);
00120 int bin = 0;
00121 int copies = c_;
00122 int size = topology->idx();
00123
00124 if (p <= copies * 1./size) {
00125 rbackoff = Random::uniform(0.0, alpha_);
00126 bin = 0;
00127 } else {
00128 rbackoff = Random::uniform(beta_, 1.0 + beta_);
00129 bin = 1;
00130 }
00131
00132 return (rtt * (det_ + rand_ * rbackoff));
00133 }
00134 #endif
00135
00136 Interface_List* Line::oif(int node, int iif=SRM_NOIF)
00137 {
00138
00139 Interface_List *ilist = new Interface_List;
00140
00141
00142 if ((iif <= node && node >= idx_ - 1) || (iif > node && node == 0))
00143 return 0;
00144
00145 if (iif == SRM_NOIF)
00146 {
00147 ilist->append(node + 1);
00148 ilist->append(node - 1);
00149 } else if (iif <= node)
00150 ilist->append(node + 1);
00151 else
00152 ilist->append(node - 1);
00153 return (ilist);
00154 }
00155
00156 double Line::delay(int src, int dst)
00157 {
00158 if (src == 0 || dst == 0)
00159 return D_ + delay_ * abs(dst - src - 1);
00160 else
00161 return delay_ * abs(dst - src);
00162 }
00163
00164
00165 double Star::delay(int src, int dst)
00166 {
00167 if (src == 0 || dst == 0)
00168 return D_;
00169 else
00170 return delay_;
00171 }
00172
00173
00174
00175
00176 double BTree::delay(int src, int dst)
00177 {
00178 double src_ht = 0;
00179 double dst_ht = 0;
00180
00181 if (src > 0)
00182 src_ht = 1 + floor(log(src)/log(2));
00183 if (dst > 0)
00184 dst_ht = 1 + floor(log(dst)/log(2));
00185
00186 if (src == 0 || dst == 0)
00187 return D_ + delay_ * abs(int (dst_ht - src_ht - 1));
00188 else
00189 return delay_ * abs(int (dst_ht - src_ht));
00190 }
00191
00192
00193
00194
00195
00196
00197 void Line::flood(int start, int seqno)
00198 {
00199 SRM_Event *se = new SRM_Event(seqno, SRM_DATA, start);
00200 node_[start].send(se);
00201 }
00202
00203
00204
00205
00206
00207 static class BTreeClass : public TclClass {
00208 public:
00209 BTreeClass() : TclClass("Topology/BTree") {}
00210 TclObject* create(int, const char*const* argv) {
00211 int nn = atoi(argv[4]);
00212 return (new BTree(nn, 0));
00213 }
00214 } class_btree_topo;
00215
00216
00217
00218
00219
00220
00221 double BTree::backoff(int id)
00222 {
00223 double rtt;
00224 if (topology->rtt_estimated())
00225 rtt = delay(id, 0);
00226 else rtt = D_ * frac_;
00227
00228 double r = Random::uniform(0.0, 1.0);
00229 double b;
00230 double sqroot = sqrt(rtt);
00231 double D = topology->D();
00232
00233 switch(c2func_) {
00234 case LOG :
00235 b = rtt * (det_ + rand_ * r * log(rtt)/log(D));
00236 break;
00237 case SQRT :
00238 b = rtt * (det_ + rand_ * r * sqroot/sqrt(D));
00239 break;
00240 case LINEAR :
00241 b = rtt * (det_ + rand_ * r * rtt/D);
00242 break;
00243 case CONSTANT :
00244 b = rtt * (det_ + rand_ * r * 1.);
00245 break;
00246 }
00247 return b;
00248 }
00249
00250 Interface_List* BTree::oif(int node, int iif=SRM_NOIF)
00251 {
00252
00253 Interface_List *ilist = new Interface_List;
00254
00255
00256
00257
00258
00259 if (iif == SRM_NOIF) {
00260 if (node == 0) {
00261 ilist->append(1);
00262 }
00263 else {
00264 ilist->append(2 * node + 1);
00265 ilist->append(2 * node);
00266 int k = (int)floor(.5 * node);
00267 ilist->append(k);
00268 }
00269 } else if (iif <= node) {
00270 ilist->append(2 * node + 1);
00271 ilist->append(2 * node);
00272 }
00273
00274
00275 else if (iif == 2 * node + 1) {
00276 if (node == 0)
00277 return ilist;
00278
00279 ilist->append(2 * node);
00280 ilist->append((int) floor(.5 * node));
00281 } else if (iif == 2 * node) {
00282 ilist->append(2 * node + 1);
00283 ilist->append((int)floor(.5 * node));
00284 }
00285 return (ilist);
00286 }
00287
00288
00289
00290
00291
00292 static class StarClass : public TclClass {
00293 public:
00294 StarClass() : TclClass("Topology/Star") {}
00295 TclObject* create(int, const char*const* argv) {
00296 int nn = atoi(argv[4]);
00297 return (new Star(nn, 0));
00298 }
00299 } class_star_topo;
00300
00301
00302
00303
00304
00305
00306 void SrmNode::dump_packet(SRM_Event *e)
00307 {
00308 #ifdef SRM_DEBUG
00309 tprintf(("(type %d) (in %d) -- @ %d --> \n", e->type(), e->iif(), id_));
00310 #endif
00311 }
00312
00313
00314
00315
00316 void SrmNode::send(SRM_Event *e)
00317 {
00318
00319
00320
00321
00322 int nn;
00323 Scheduler& s = Scheduler::instance();
00324 SRM_Event *copy;
00325 Interface *p;
00326 Interface_List *ilist = topology->oif(id_, e->iif());
00327 if (e->iif() < 0)
00328 e->iif(id_);
00329
00330 if (ilist) {
00331 for (p=ilist->head_; p; p=p->next_) {
00332 nn = p->in_;
00333 int t = e->type();
00334
00335 int snum = e->seqno();
00336 SrmNode *next = topology->node(nn);
00337 if (next) {
00338 copy = new SRM_Event(snum, t, id_);
00339 s.schedule(next, copy,
00340 topology->delay(id_, nn));
00341 }
00342 }
00343 }
00344 delete ilist;
00345 delete e;
00346 }
00347
00348
00349
00350
00351
00352
00353 void SrmNode::handle(Event* event)
00354 {
00355 SRM_Event *srm_event = (SRM_Event *) event;
00356 int type = srm_event->type();
00357 int seqno = srm_event->seqno();
00358
00359
00360
00361 switch (type) {
00362 case SRM_DATA :
00363 if (seqno != expected_)
00364 sched_nack(seqno);
00365 expected_ = seqno;
00366 break;
00367
00368 case SRM_PENDING_RREQ :
00369 tprintf(("Fired RREQ (node %d)\n", id_));
00370 remove(seqno, SRM_NO_SUPPRESS);
00371 srm_event->type(SRM_RREQ);
00372 break;
00373
00374 case SRM_RREQ :
00375
00376 remove(seqno, SRM_SUPPRESS);
00377 break;
00378
00379 default :
00380 tprintf(("panic: node(%d) Unexpected type %d\n", id_, type));
00381 return;
00382 }
00383 #ifdef SRM_STAR
00384 if (type == SRM_RREQ || type == SRM_DATA) {
00385 delete srm_event;
00386 return;
00387 }
00388 #endif
00389 send(srm_event);
00390 return;
00391 }
00392
00393
00394
00395
00396
00397 void SrmNode::sched_nack(int seqno)
00398 {
00399 double backoff, time;
00400 Scheduler& s = Scheduler::instance();
00401 SRM_Event *event = new SRM_Event(seqno,
00402 SRM_PENDING_RREQ, SRM_NOIF);
00403 append(event);
00404
00405 backoff = topology->backoff(id_);
00406 time = backoff + s.clock();
00407
00408 s.schedule(this, event, backoff);
00409 }
00410
00411 void SrmNode::append(SRM_Event *e)
00412 {
00413 SRM_Request *req = new SRM_Request(e);
00414 req->next_ = pending_;
00415 pending_ = req;
00416 }
00417
00418
00419 void SrmNode::remove(int seqno, int flag)
00420 {
00421 SRM_Request *curr, *prev;
00422 SRM_Event *ev;
00423
00424 if (!pending_)
00425 return;
00426 for (curr=pending_, prev=0; curr; curr=curr->next_)
00427 {
00428 ev = curr->event_;
00429 if (ev->seqno() == seqno) {
00430 if (!prev)
00431 pending_ = curr->next_;
00432 else {
00433 prev->next_ = curr->next_;
00434 prev = curr;
00435 }
00436 if (flag == SRM_SUPPRESS) {
00437 curr->cancel_timer();
00438 }
00439 delete curr;
00440 }
00441 }
00442 }
00443
00444
00445 SRM_Event::SRM_Event(SRM_Event *e)
00446 {
00447 seqno_ = e->seqno();
00448 type_ = e->type();
00449 iif_ = e->iif();
00450 }
00451
00452 SRM_Request::~SRM_Request() {}
00453
00454 void SRM_Request::cancel_timer()
00455 {
00456 if (event_) {
00457 Scheduler& s = Scheduler::instance();
00458 s.cancel(event_);
00459
00460 }
00461 }
00462
00463 void Interface_List::append(int in)
00464 {
00465 Interface *i = new Interface(in);
00466 i->next_ = head_;
00467 head_ = i;
00468 }
00469
00470 Interface_List::~Interface_List()
00471 {
00472 Interface *p, *next;
00473 for (p=head_; p; p=next)
00474 {
00475 next = p->next_;
00476 delete p;
00477 }
00478 }
00479
00480 void BTree::flood(int start, int seqno)
00481 {
00482 SRM_Event *se = new SRM_Event(seqno, SRM_DATA, SRM_NOIF);
00483 node_[start].send(se);
00484 }
00485
00486 void Star::flood(int start, int seqno)
00487 {
00488 SRM_Event *se = new SRM_Event(seqno, SRM_DATA, start);
00489 node_[start].send(se);
00490 }
00491
00492 Interface_List* Star::oif(int node, int iif=SRM_NOIF)
00493 {
00494 int i;
00495 Interface_List *ilist = new Interface_List;
00496
00497
00498 for (i = 0; i < topology->idx(); i ++)
00499 {
00500 if (i != node && i != iif) {
00501 ilist->append(i);
00502 }
00503 }
00504
00505 return (ilist);
00506 }
00507
00508
00509
00510
00511 double Star::backoff(int id)
00512 {
00513 double rtt = topology->delay(id, 0);
00514 double rbackoff;
00515 double p = Random::uniform(0.0, 1.0);
00516 static int bin = 0;
00517 int copies = c_;
00518 int size = topology->idx();
00519
00520 if (p <= copies * 1./size) {
00521 rbackoff = Random::uniform(0.0, alpha_);
00522 bin ++;
00523 } else {
00524 rbackoff = Random::uniform(beta_, 1.0 + beta_);
00525 }
00526 return (rtt * (det_ + rand_ * rbackoff));
00527 }
00528
00529
00530 #ifdef SRM_BIMODAL
00531 double BTree::backoff(int dst)
00532 {
00533 double height = floor(log(dst)/log(2));
00534
00535 double D = topology->D();
00536 double rtt = delay_ * height + D;
00537 double p = Random::uniform(0.0, 1.0);
00538 double rbackoff;
00539
00540 static int bin = 0;
00541 int copies = c_;
00542 int size = topology->idx();
00543
00544 if (p <= copies * 1./size) {
00545 rbackoff = Random::uniform(0.0, alpha_);
00546 bin ++;
00547 } else {
00548 rbackoff = Random::uniform(1.0 + alpha_, 2.0);
00549 }
00550 return (rtt * (det_ + rand_ * rbackoff));
00551 }
00552 #endif