Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

srm-topo.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) Xerox Corporation 1997. All rights reserved.
00004  *  
00005  * License is granted to copy, to use, and to make and to use derivative
00006  * works for research and evaluation purposes, provided that Xerox is
00007  * acknowledged in all documentation pertaining to any such copy or derivative
00008  * work. Xerox grants no other licenses expressed or implied. The Xerox trade
00009  * name should not be used in any advertising without its written permission.
00010  *  
00011  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00012  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00013  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00014  * express or implied warranty of any kind.
00015  *  
00016  * These notices must be retained in any copies of any part of this software.
00017  *
00018  * This file contributed by Suchitra Raman <sraman@parc.xerox.com>, June 1997.
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         /* D_ (ms) is the delay of node 1 from node 0 */
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         //Tcl& tcl = Tcl::instance();
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         //int oif;
00139         Interface_List *ilist = new Interface_List;
00140 
00141         /* If there are no more nodes downstream, return -1 */
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  * Very simple now, can only send to direct ancestor/descendant 
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  * There is always an outbound interface. We should not 
00194  * start a flood() from a leaf node. 
00195  * Change it for other topologies. 
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  * BTree -
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  * The ranges of the different distributions 
00219  * must be normalized to 1. 
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         //int oif;
00253         Interface_List *ilist = new Interface_List;
00254         /* 
00255          * If the packet comes from the source, 
00256          * there is only 1 outgoing link.
00257          * We make the assumption that source = 0 always (YUCK!)
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         // Packet came along 2n + 1 or 2n + 2
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  * Star -
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  * SrmNode -
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 /* This forwards an event by making multiple copies of the
00314  * event 'e'. Does NOT free event 'e'. 
00315  */
00316 void SrmNode::send(SRM_Event *e) 
00317 {
00318         /* 
00319          * Copy the packet and send it over to 
00320          * all the outbound interfaces 
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                         //int i = id_; 
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  * Demux the two types of events depending on 
00351  * the type field.
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         //int iif   = srm_event->iif();
00359         //Scheduler& s = Scheduler::instance();
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  * XXX Should take two sequence numbers. The iif field is a dummy. We should be
00395  * careful not to use it for NACKs 
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 //      tprintf(("node(%d) schd rrq after %f s\n", id_, backoff));
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 /* If an event identical to e exists, cancel it */
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                 // xxx: should event be free'd?  possible memory leak.
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         /* Make a list with every node except myself */
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  * Distance of source to cluster = D_
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

Generated on Tue Apr 20 12:14:33 2004 for NS2.26SourcesOriginal by doxygen 1.3.3