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 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/agent.cc,v 1.74 2002/06/14 23:15:02 yuri Exp $ (LBL)";
00038 #endif
00039
00040 #include <assert.h>
00041 #include <stdlib.h>
00042
00043 #include "config.h"
00044 #include "agent.h"
00045 #include "ip.h"
00046 #include "flags.h"
00047 #include "address.h"
00048 #include "app.h"
00049 #ifdef HAVE_STL
00050 #include "nix/hdr_nv.h"
00051 #include "nix/nixnode.h"
00052 #endif //HAVE_STL
00053
00054
00055
00056 #ifndef min
00057 #define min(a, b) (((a) < (b)) ? (a) : (b))
00058 #endif
00059
00060 static class AgentClass : public TclClass {
00061 public:
00062 AgentClass() : TclClass("Agent") {}
00063 TclObject* create(int, const char*const*) {
00064 return (new Agent(PT_NTYPE));
00065 }
00066 } class_agent;
00067
00068 int Agent::uidcnt_;
00069
00070 Agent::Agent(packet_t pkttype) :
00071 size_(0), type_(pkttype),
00072 channel_(0), traceName_(NULL),
00073 oldValueList_(NULL), app_(0), et_(0)
00074 {
00075 }
00076
00077 void
00078 Agent::delay_bind_init_all()
00079 {
00080 delay_bind_init_one("agent_addr_");
00081 delay_bind_init_one("agent_port_");
00082 delay_bind_init_one("dst_addr_");
00083 delay_bind_init_one("dst_port_");
00084 delay_bind_init_one("fid_");
00085 delay_bind_init_one("prio_");
00086 delay_bind_init_one("flags_");
00087 delay_bind_init_one("ttl_");
00088 delay_bind_init_one("class_");
00089 Connector::delay_bind_init_all();
00090 }
00091
00092 int
00093 Agent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00094 {
00095 if (delay_bind(varName, localName, "agent_addr_", (int*)&(here_.addr_), tracer)) return TCL_OK;
00096 if (delay_bind(varName, localName, "agent_port_", (int*)&(here_.port_), tracer)) return TCL_OK;
00097 if (delay_bind(varName, localName, "dst_addr_", (int*)&(dst_.addr_), tracer)) return TCL_OK;
00098 if (delay_bind(varName, localName, "dst_port_", (int*)&(dst_.port_), tracer)) return TCL_OK;
00099 if (delay_bind(varName, localName, "fid_", (int*)&fid_, tracer)) return TCL_OK;
00100 if (delay_bind(varName, localName, "prio_", (int*)&prio_, tracer)) return TCL_OK;
00101 if (delay_bind(varName, localName, "flags_", (int*)&flags_, tracer)) return TCL_OK;
00102 if (delay_bind(varName, localName, "ttl_", &defttl_, tracer)) return TCL_OK;
00103 if (delay_bind(varName, localName, "class_", (int*)&fid_, tracer)) return TCL_OK;
00104 return Connector::delay_bind_dispatch(varName, localName, tracer);
00105 }
00106
00107
00108 Agent::~Agent()
00109 {
00110 if (oldValueList_ != NULL) {
00111 OldValue *p = oldValueList_;
00112 while (oldValueList_ != NULL) {
00113 oldValueList_ = oldValueList_->next_;
00114 delete p;
00115 p = oldValueList_;
00116 }
00117 }
00118 }
00119
00120 int Agent::command(int argc, const char*const* argv)
00121 {
00122 Tcl& tcl = Tcl::instance();
00123 if (argc == 2) {
00124 if (strcmp(argv[1], "delete-agent-trace") == 0) {
00125 if ((traceName_ == 0) || (channel_ == 0))
00126 return (TCL_OK);
00127 deleteAgentTrace();
00128 return (TCL_OK);
00129 } else if (strcmp(argv[1], "show-monitor") == 0) {
00130 if ((traceName_ == 0) || (channel_ == 0))
00131 return (TCL_OK);
00132 monitorAgentTrace();
00133 return (TCL_OK);
00134 } else if (strcmp(argv[1], "close") == 0) {
00135 close();
00136 return (TCL_OK);
00137 } else if (strcmp(argv[1], "listen") == 0) {
00138 listen();
00139 return (TCL_OK);
00140 } else if (strcmp(argv[1], "dump-namtracedvars") == 0) {
00141 enum_tracedVars();
00142 return (TCL_OK);
00143 }
00144
00145 }
00146 else if (argc == 3) {
00147 if (strcmp(argv[1], "attach") == 0) {
00148 int mode;
00149 const char* id = argv[2];
00150 channel_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
00151 if (channel_ == 0) {
00152 tcl.resultf("trace: can't attach %s for writing", id);
00153 return (TCL_ERROR);
00154 }
00155 return (TCL_OK);
00156 } else if (strcmp(argv[1], "add-agent-trace") == 0) {
00157
00158 if (channel_ == 0) {
00159 tcl.resultf("agent %s: no trace file attached", name_);
00160 return (TCL_OK);
00161 }
00162 addAgentTrace(argv[2]);
00163 return (TCL_OK);
00164 } else if (strcmp(argv[1], "connect") == 0) {
00165 connect((nsaddr_t)atoi(argv[2]));
00166 return (TCL_OK);
00167 } else if (strcmp(argv[1], "send") == 0) {
00168 sendmsg(atoi(argv[2]));
00169 return (TCL_OK);
00170 } else if (strcmp(argv[1], "set_pkttype") == 0) {
00171 set_pkttype(packet_t(atoi(argv[2])));
00172 return (TCL_OK);
00173 }
00174 }
00175 else if (argc == 4) {
00176 if (strcmp(argv[1], "sendmsg") == 0) {
00177 sendmsg(atoi(argv[2]), argv[3]);
00178 return (TCL_OK);
00179 }
00180 }
00181 else if (argc == 5) {
00182 if (strcmp(argv[1], "sendto") == 0) {
00183 sendto(atoi(argv[2]), argv[3], (nsaddr_t)atoi(argv[4]));
00184 return (TCL_OK);
00185 }
00186 }
00187 if (strcmp(argv[1], "tracevar") == 0) {
00188
00189
00190 const char* args[4];
00191 char tmp[6];
00192 strcpy(tmp, "trace");
00193 args[0] = argv[0];
00194 args[1] = tmp;
00195 args[2] = argv[2];
00196 if (argc > 3)
00197 args[3] = argv[3];
00198 return (Connector::command(argc, args));
00199 }
00200 return (Connector::command(argc, argv));
00201 }
00202
00203 void Agent::flushAVar(TracedVar *v)
00204 {
00205 char wrk[256], value[128];
00206 int n;
00207
00208
00209 v->value(value, 128);
00210 if (strcmp(value, "") == 0)
00211
00212 return;
00213 sprintf(wrk, "f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -o %s -T v -x",
00214 Scheduler::instance().clock(), addr(), dst_.addr_,
00215 v->name(), traceName_, value);
00216 n = strlen(wrk);
00217 wrk[n] = '\n';
00218 wrk[n+1] = 0;
00219 (void)Tcl_Write(channel_, wrk, n+1);
00220 }
00221
00222 void Agent::deleteAgentTrace()
00223 {
00224 char wrk[256];
00225
00226
00227
00228 TracedVar* var = tracedvar_;
00229 for ( ; var != 0; var = var->next_)
00230 flushAVar(var);
00231
00232
00233
00234 sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s -x",
00235 Scheduler::instance().clock(), here_.addr_,
00236 dst_.addr_, traceName_);
00237 if (traceName_ != NULL)
00238 delete[] traceName_;
00239 traceName_ = NULL;
00240 }
00241
00242 OldValue* Agent::lookupOldValue(TracedVar *v)
00243 {
00244 OldValue *p = oldValueList_;
00245 while ((p != NULL) && (p->var_ != v))
00246 p = p->next_;
00247 return p;
00248 }
00249
00250 void Agent::insertOldValue(TracedVar *v, const char *value)
00251 {
00252 OldValue *p = new OldValue;
00253 assert(p != NULL);
00254 strncpy(p->val_, value, min(strlen(value)+1, TRACEVAR_MAXVALUELENGTH));
00255 p->var_ = v;
00256 p->next_ = NULL;
00257 if (oldValueList_ == NULL)
00258 oldValueList_ = p;
00259 else {
00260 p->next_ = oldValueList_;
00261 oldValueList_ = p;
00262 }
00263 }
00264
00265
00266 void Agent::trace(TracedVar* v)
00267 {
00268 if (channel_ == 0)
00269 return;
00270 char wrk[256], value[128];
00271 int n;
00272
00273
00274 v->value(value, 128);
00275
00276
00277
00278 static int started = 0;
00279 if (!started) {
00280 Tcl::instance().evalc("[Simulator instance] is-started");
00281 if (Tcl::instance().result()[0] == '0')
00282
00283 return;
00284
00285 started = 1;
00286 };
00287
00288 OldValue *ov = lookupOldValue(v);
00289 if (ov != NULL) {
00290 sprintf(wrk,
00291 "f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -v %s -o %s -T v",
00292 Scheduler::instance().clock(), here_.addr_,
00293 dst_.addr_, v->name(), traceName_, value, ov->val_);
00294 strncpy(ov->val_,
00295 value,
00296 min(strlen(value)+1, TRACEVAR_MAXVALUELENGTH));
00297 } else {
00298
00299 sprintf(wrk, "f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -v %s -T v",
00300 Scheduler::instance().clock(), here_.addr_,
00301 dst_.addr_, v->name(), traceName_, value);
00302 insertOldValue(v, value);
00303 }
00304 n = strlen(wrk);
00305 wrk[n] = '\n';
00306 wrk[n+1] = 0;
00307 (void)Tcl_Write(channel_, wrk, n+1);
00308 }
00309
00310 void Agent::monitorAgentTrace()
00311 {
00312 char wrk[256];
00313 int n;
00314 double curTime = (&Scheduler::instance() == NULL ? 0 :
00315 Scheduler::instance().clock());
00316
00317 sprintf(wrk, "v -t "TIME_FORMAT" -e monitor_agent %d %s",
00318 curTime, here_.addr_, traceName_);
00319 n = strlen(wrk);
00320 wrk[n] = '\n';
00321 wrk[n+1] = 0;
00322 if (channel_)
00323 (void)Tcl_Write(channel_, wrk, n+1);
00324 }
00325
00326 void Agent::addAgentTrace(const char *name)
00327 {
00328 char wrk[256];
00329 int n;
00330 double curTime = (&Scheduler::instance() == NULL ? 0 :
00331 Scheduler::instance().clock());
00332
00333 sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s",
00334 curTime, here_.addr_, dst_.addr_, name);
00335 n = strlen(wrk);
00336 wrk[n] = '\n';
00337 wrk[n+1] = 0;
00338 if (channel_)
00339 (void)Tcl_Write(channel_, wrk, n+1);
00340
00341 if (traceName_ != NULL)
00342 delete[] traceName_;
00343 traceName_ = new char[strlen(name)+1];
00344 strcpy(traceName_, name);
00345 }
00346
00347 void Agent::timeout(int)
00348 {
00349 }
00350
00351
00352
00353
00354 void Agent::recvBytes(int nbytes)
00355 {
00356 if (app_)
00357 app_->recv(nbytes);
00358 }
00359
00360
00361
00362
00363 void Agent::idle()
00364 {
00365 if (app_)
00366 app_->resume();
00367 }
00368
00369
00370
00371
00372 void Agent::attachApp(Application *app)
00373 {
00374 app_ = app;
00375 }
00376
00377 void Agent::close()
00378 {
00379 }
00380
00381 void Agent::listen()
00382 {
00383 }
00384
00385
00386
00387
00388
00389 void Agent::connect(nsaddr_t )
00390 {
00391
00392
00393
00394 }
00395
00396
00397
00398
00399
00400 void Agent::sendmsg(int , AppData* , const char* )
00401 {
00402 fprintf(stderr,
00403 "Agent::sendmsg(int, AppData*, const char*) not implemented\n");
00404 abort();
00405 }
00406
00407 void Agent::sendto(int , AppData* , const char* ,
00408 nsaddr_t )
00409 {
00410 fprintf(stderr,
00411 "Agent::sendmsg(int, AppData*, const char*) not implemented\n");
00412 abort();
00413 }
00414
00415 void Agent::sendmsg(int , const char* )
00416 {
00417 }
00418
00419
00420
00421
00422
00423 void Agent::sendto(int , const char [], nsaddr_t )
00424 {
00425
00426
00427
00428
00429 }
00430
00431 void Agent::recv(Packet* p, Handler*)
00432 {
00433 if (app_)
00434 app_->recv(hdr_cmn::access(p)->size());
00435
00436
00437
00438 Packet::free(p);
00439 }
00440
00441
00442
00443
00444
00445 void
00446 Agent::initpkt(Packet* p) const
00447 {
00448 hdr_cmn* ch = hdr_cmn::access(p);
00449 ch->uid() = uidcnt_++;
00450 ch->ptype() = type_;
00451 ch->size() = size_;
00452 ch->timestamp() = Scheduler::instance().clock();
00453 ch->iface() = UNKN_IFACE.value();
00454 ch->direction() = hdr_cmn::NONE;
00455
00456 ch->error() = 0;
00457
00458 hdr_ip* iph = hdr_ip::access(p);
00459 iph->saddr() = here_.addr_;
00460 iph->sport() = here_.port_;
00461 iph->daddr() = dst_.addr_;
00462 iph->dport() = dst_.port_;
00463
00464
00465
00466
00467
00468 iph->flowid() = fid_;
00469 iph->prio() = prio_;
00470 iph->ttl() = defttl_;
00471
00472 hdr_flags* hf = hdr_flags::access(p);
00473 hf->ecn_capable_ = 0;
00474 hf->ecn_ = 0;
00475 hf->eln_ = 0;
00476 hf->ecn_to_echo_ = 0;
00477 hf->fs_ = 0;
00478 hf->no_ts_ = 0;
00479 hf->pri_ = 0;
00480 hf->cong_action_ = 0;
00481 #ifdef HAVE_STL
00482
00483 hdr_nv* nv = hdr_nv::access(p);
00484 if (0)
00485 printf("Off hdr_nv %d, ip_hdr %d myaddr %ld\n",
00486 hdr_nv::offset(), hdr_ip::offset(), here_.addr_);
00487 NixNode* pNixNode = NixNode::GetNodeObject(here_.addr_);
00488 if (0)
00489 printf("Node Object %p\n", pNixNode);
00490 if (pNixNode) {
00491
00492
00493
00494 NixVec* pNv = pNixNode->GetNixVector(dst_.addr_);
00495 pNv->Reset();
00496 nv->nv() = pNv;
00497 nv->h_used = 0;
00498 }
00499 #endif //HAVE_STL
00500 }
00501
00502
00503
00504
00505 Packet*
00506 Agent::allocpkt() const
00507 {
00508 Packet* p = Packet::alloc();
00509 initpkt(p);
00510 return (p);
00511 }
00512
00513
00514
00515
00516 Packet*
00517 Agent::allocpkt(int n) const
00518 {
00519 Packet* p = allocpkt();
00520
00521 if (n > 0)
00522 p->allocdata(n);
00523
00524 return(p);
00525 }