sessionhelper.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * Copyright (C) 1997 by the University of Southern California
00005  * $Id: sessionhelper.cc,v 1.22 2005/09/18 23:33:31 tomh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 /* 
00047  * Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
00048  *
00049  */
00050 
00051 #ifndef lint
00052 static const char rcsid[] =
00053     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/sessionhelper.cc,v 1.22 2005/09/18 23:33:31 tomh Exp $ (USC/ISI)";
00054 #endif
00055 
00056 #include "config.h"
00057 #include "tclcl.h"
00058 #include "ip.h"
00059 #include "packet.h"
00060 #include "connector.h"
00061 #include "errmodel.h"
00062 
00063 //Definitions for special reference count events
00064 class RcEvent : public Event {
00065 public:
00066     Packet* packet_;
00067     Handler* real_handler_;
00068 };
00069 
00070 class RcHandler : public Handler {
00071 public:
00072     void handle(Event* event);
00073 } rc_handler;
00074 
00075 void RcHandler::handle(Event* e)
00076 {
00077     RcEvent* rc = (RcEvent*)e;
00078     rc->real_handler_->handle(rc->packet_);
00079     delete rc;
00080 }
00081 
00082 struct dstobj {
00083     double bw;
00084     double delay;
00085     double prev_arrival;
00086     int ttl;
00087     int dropped;
00088     nsaddr_t addr;
00089     NsObject *obj;
00090     dstobj *next;
00091 };
00092 
00093 struct rcv_depobj {
00094     dstobj *obj;
00095     rcv_depobj *next;
00096 };
00097 
00098 
00099 struct loss_depobj {
00100     ErrorModel *obj;
00101     loss_depobj *loss_dep;
00102     rcv_depobj *rcv_dep;
00103     loss_depobj *next;
00104 };
00105 
00106 class SessionHelper : public Connector {
00107 public:
00108     SessionHelper();
00109     int command(int, const char*const*);
00110     void recv(Packet*, Handler*);
00111 protected:
00112     void get_dropped(loss_depobj*, Packet*);
00113     void mark_dropped(loss_depobj*);
00114     void clear_dropped();
00115     dstobj* find_dstobj(NsObject*);
00116     void delete_dstobj(NsObject*);
00117     loss_depobj* find_loss_depobj(ErrorModel*);
00118     void show_dstobj();
00119     void show_loss_depobj(loss_depobj*);
00120     nsaddr_t src_;
00121     dstobj *dstobj_;
00122     loss_depobj *loss_dependency_;
00123     int ndst_;
00124     int rc_; //enable reference count
00125 };
00126 
00127 static class SessionHelperClass : public TclClass {
00128 public:
00129     SessionHelperClass() : TclClass("SessionHelper") {}
00130     TclObject* create(int, const char*const*) {
00131         return (new SessionHelper());
00132     }
00133 } class_sessionhelper;
00134 
00135 SessionHelper::SessionHelper() : dstobj_(0), ndst_(0), rc_(0)
00136 {
00137     bind("rc_", &rc_);
00138     loss_dependency_ = new loss_depobj;
00139     loss_dependency_->obj = 0;
00140     loss_dependency_->loss_dep = 0;
00141     loss_dependency_->rcv_dep = 0;
00142     loss_dependency_->next = 0;
00143 }
00144 
00145 void SessionHelper::recv(Packet* pkt, Handler*)
00146 {
00147     Scheduler& s = Scheduler::instance();
00148     hdr_cmn* th = hdr_cmn::access(pkt);
00149     hdr_ip* iph = hdr_ip::access(pkt);
00150     double tmp_arrival;
00151 
00152     //printf ("src %d,  size %d, iface %d\n", src_, th->size(), th->iface());
00153     clear_dropped();
00154 
00155     get_dropped(loss_dependency_->loss_dep, pkt);
00156 
00157     for (dstobj *tmpdst = dstobj_; tmpdst; tmpdst = tmpdst->next) {
00158         int ttl;
00159         if (tmpdst->dropped 
00160             || (ttl = iph->ttl() - tmpdst->ttl) <= 0)
00161             continue;
00162         
00163         if (tmpdst->bw == 0) {
00164             tmp_arrival = tmpdst->delay;
00165         } else {
00166             tmp_arrival = th->size()*8/tmpdst->bw + tmpdst->delay;
00167         }
00168         if (tmpdst->prev_arrival >= tmp_arrival) {
00169             tmp_arrival = tmpdst->prev_arrival + 0.000001;
00170             /* Assume 1 ns process delay; just to maintain the causality */
00171         }
00172         tmpdst->prev_arrival = tmp_arrival;
00173         if (rc_) {
00174             // reference count
00175             //s.rc_schedule(tmpdst->obj, pkt, tmp_arrival);
00176             RcEvent* rc = new RcEvent;
00177             rc->packet_ = pkt->refcopy();
00178             rc->real_handler_ = tmpdst->obj;
00179             s.schedule(&rc_handler, rc, tmp_arrival);
00180         } else {
00181             Packet* tmppkt = pkt->copy();
00182             hdr_ip* tmpiph = hdr_ip::access(tmppkt);
00183             tmpiph->ttl() = ttl;
00184             s.schedule(tmpdst->obj, tmppkt, tmp_arrival);
00185         }
00186     }
00187     
00188     Packet::free(pkt);
00189 }
00190 
00191 void SessionHelper::get_dropped(loss_depobj* loss_dep, Packet* pkt)
00192 {
00193     if (loss_dep != 0) 
00194         if (loss_dep->obj != 0) {
00195             if (loss_dep->obj->corrupt(pkt)) {
00196                 mark_dropped(loss_dep);
00197             } else {
00198                 get_dropped(loss_dep->loss_dep, pkt);
00199             }
00200             get_dropped(loss_dep->next, pkt);
00201         }
00202 }
00203 
00204 void SessionHelper::mark_dropped(loss_depobj* loss_dep)
00205 {
00206     if (loss_dep != 0) {
00207         rcv_depobj *tmprcv_dep = loss_dep->rcv_dep;
00208         loss_depobj *tmploss_dep = loss_dep->loss_dep;
00209 
00210         while (tmprcv_dep != 0) {
00211             tmprcv_dep->obj->dropped = 1;
00212             tmprcv_dep = tmprcv_dep->next;
00213         }
00214 
00215         while (tmploss_dep != 0) {
00216             mark_dropped(tmploss_dep);
00217             tmploss_dep = tmploss_dep->next;
00218         }
00219     }
00220 }
00221 
00222 void SessionHelper::clear_dropped()
00223 {
00224     dstobj *tmpdst = dstobj_;
00225     while (tmpdst != 0) {
00226         tmpdst->dropped = 0;
00227         tmpdst = tmpdst->next;
00228     }
00229 }
00230 
00231 dstobj* SessionHelper::find_dstobj(NsObject* obj) {
00232     dstobj *tmpdst = dstobj_;
00233     while (tmpdst != 0) {
00234         if (tmpdst->obj == obj) return (tmpdst);
00235         tmpdst = tmpdst->next;
00236     }
00237     return 0;
00238 }
00239 
00240 loss_depobj* SessionHelper::find_loss_depobj(ErrorModel* err) {
00241     struct stackobj {
00242         loss_depobj *loss_obj;
00243         stackobj *next;
00244     };
00245 
00246     if (!loss_dependency_) return 0;
00247 
00248     stackobj *top = new stackobj;
00249     top->loss_obj = loss_dependency_;
00250     top->next = 0;
00251 
00252     while (top != 0) {
00253         if (top->loss_obj->obj == err) {
00254             loss_depobj *tmp_loss_obj = top->loss_obj;
00255             while (top != 0) {
00256                 stackobj *befreed = top;
00257                 top = top->next;
00258                 free(befreed);
00259             }
00260             return (tmp_loss_obj);
00261         }
00262         loss_depobj *tmploss = top->loss_obj->loss_dep;
00263         stackobj *befreed = top;
00264         top = top->next;
00265         free(befreed);
00266         while (tmploss != 0) {
00267             stackobj *new_element = new stackobj;
00268             new_element->loss_obj = tmploss;
00269             new_element->next = top;
00270             top = new_element;
00271             tmploss = tmploss->next;
00272         }
00273     }
00274     return 0;
00275 }
00276 
00277 void SessionHelper::show_dstobj() {
00278     dstobj *tmpdst = dstobj_;
00279     while (tmpdst != 0) {
00280         printf("bw:%.2f, delay:%.2f, ttl:%d, dropped:%d, addr:%d, obj:%s\n", tmpdst->bw, tmpdst->delay, tmpdst->ttl, tmpdst->dropped, tmpdst->addr, tmpdst->obj->name());
00281         tmpdst = tmpdst->next;
00282     }
00283 }
00284 
00285 void SessionHelper::delete_dstobj(NsObject *obj) {
00286     dstobj *tmpdst = dstobj_;
00287     dstobj *tmpprev = 0;
00288 
00289     while (tmpdst != 0) {
00290         if (tmpdst->obj == obj) {
00291             if (tmpprev == 0) dstobj_ = tmpdst->next;
00292             else tmpprev->next = tmpdst->next;
00293             free(tmpdst);
00294             return;
00295         }
00296         tmpprev = tmpdst;
00297         tmpdst = tmpdst->next;
00298     }
00299 }
00300 
00301 void SessionHelper::show_loss_depobj(loss_depobj *loss_obj) {
00302 
00303     loss_depobj *tmploss = loss_obj->loss_dep;
00304     rcv_depobj *tmprcv = loss_obj->rcv_dep;
00305 
00306     while (tmprcv != 0) {
00307         printf("%d ", tmprcv->obj->addr);
00308         tmprcv = tmprcv->next;
00309     }
00310     while (tmploss != 0) {
00311         printf("(%s: ", tmploss->obj->name());
00312         show_loss_depobj(tmploss);
00313         tmploss = tmploss->next;
00314     }
00315 
00316     if (loss_obj == loss_dependency_) {
00317         printf("\n");
00318     } else {
00319         printf(")");
00320     }
00321 }
00322 
00323 
00324 int SessionHelper::command(int argc, const char*const* argv)
00325 {
00326     Tcl& tcl = Tcl::instance();
00327     if (argc == 2) {
00328         if (strcmp(argv[1], "list-mbr") == 0) {
00329             dstobj *tmp = dstobj_;
00330             while (tmp != 0) {
00331                 tcl.resultf("%s %s", tcl.result(),
00332                         tmp->obj->name());
00333                 tmp = tmp->next;
00334             }
00335             return (TCL_OK);
00336         }
00337         if (strcmp(argv[1], "show-loss-depobj") == 0) {
00338             show_loss_depobj(loss_dependency_);
00339             return (TCL_OK);
00340         }
00341         if (strcmp(argv[1], "show-dstobj") == 0) {
00342             show_dstobj();
00343             return (TCL_OK);
00344         }
00345     } else if (argc == 3) {
00346         if (strcmp(argv[1], "set-node") == 0) {
00347             int src = atoi(argv[2]);
00348             src_ = src;
00349             //printf("set node %d\n", src_);
00350             return (TCL_OK);
00351         }
00352         if (strcmp(argv[1], "update-loss-top") == 0) {
00353             loss_depobj *tmploss = (loss_depobj*)(atol(argv[2]));
00354             tmploss->next = loss_dependency_->loss_dep;
00355             loss_dependency_->loss_dep = tmploss;
00356             return (TCL_OK);
00357         }
00358     } else if (argc == 4) {
00359         if (strcmp(argv[1], "update-loss-rcv") == 0) {
00360             ErrorModel *tmperr = (ErrorModel*)TclObject::lookup(argv[2]);
00361             NsObject *tmpobj = (NsObject*)TclObject::lookup(argv[3]);
00362             //printf("errmodel %s, agent %s\n", tmperr->name(), tmpobj->name());
00363             loss_depobj *tmploss = find_loss_depobj(tmperr);
00364             //printf ("%d, loss_dependency_ %d\n", tmploss, loss_dependency_);
00365             if (!tmploss) {
00366                 tmploss = new loss_depobj;
00367                 tmploss->obj = tmperr;
00368                 tmploss->next = 0;
00369                 tmploss->rcv_dep = 0;
00370                 tmploss->loss_dep = 0;
00371                 tcl.resultf("%ld", tmploss);
00372             } else {
00373                 tcl.result("0");
00374             }
00375             rcv_depobj *tmprcv = new rcv_depobj;
00376             tmprcv->obj = find_dstobj(tmpobj);
00377             tmprcv->next = tmploss->rcv_dep;
00378             tmploss->rcv_dep = tmprcv;
00379             return (TCL_OK);
00380         }
00381         if (strcmp(argv[1], "update-loss-loss") == 0) {
00382             ErrorModel *tmperrparent = (ErrorModel*)TclObject::lookup(argv[2]);
00383             loss_depobj *tmplossparent = find_loss_depobj(tmperrparent);
00384             loss_depobj *tmplosschild = (loss_depobj*)(atol(argv[3]));
00385             if (!tmplossparent) {
00386                 tmplossparent = new loss_depobj;
00387                 tmplossparent->obj = tmperrparent;
00388                 tmplossparent->next = 0;
00389                 tmplossparent->loss_dep = 0;
00390                 tmplossparent->rcv_dep = 0;
00391                 tcl.resultf("%ld", tmplossparent);
00392             } else {
00393                 tcl.result("0");
00394             }
00395             tmplosschild->next = tmplossparent->loss_dep;
00396             tmplossparent->loss_dep = tmplosschild;
00397             return (TCL_OK);
00398         }
00399         if (strcmp(argv[1], "delete-dst") == 0) {
00400             int tmpaddr = atoi(argv[2]);
00401             //NsObject *tmpobj = (NsObject*)TclObject::lookup(argv[3]);
00402             printf ("addr = %d\n", tmpaddr);
00403             return (TCL_OK);
00404         }
00405     } else if (argc == 7) {
00406         if (strcmp(argv[1], "add-dst") == 0) {
00407             dstobj *tmp = new dstobj;
00408             tmp->bw = atof(argv[2]);
00409             tmp->delay = atof(argv[3]);
00410             tmp->prev_arrival = 0;
00411             tmp->ttl = atoi(argv[4]);
00412             tmp->addr = atoi(argv[5]);
00413             tmp->obj = (NsObject*)TclObject::lookup(argv[6]);
00414             //printf ("addr = %d, argv3 = %s, obj = %d, ttl=%d\n", tmp->addr, argv[3], tmp->obj, tmp->ttl);
00415             tmp->next = dstobj_;
00416             dstobj_ = tmp;
00417             ndst_ += 1;
00418             return (TCL_OK);
00419         }
00420     }
00421     return (Connector::command(argc, argv));
00422 }
00423 

Generated on Tue Mar 6 16:47:51 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6