00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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
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_;
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
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
00171 }
00172 tmpdst->prev_arrival = tmp_arrival;
00173 if (rc_) {
00174
00175
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
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
00363 loss_depobj *tmploss = find_loss_depobj(tmperr);
00364
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
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
00415 tmp->next = dstobj_;
00416 dstobj_ = tmp;
00417 ndst_ += 1;
00418 return (TCL_OK);
00419 }
00420 }
00421 return (Connector::command(argc, argv));
00422 }
00423