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 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include "packet.h"
00040 #include "ip.h"
00041 #include "tcp.h"
00042 #include "sctp.h"
00043 #include "rtp.h"
00044 #include "srm.h"
00045 #include "tfrc.h"
00046 #include "flags.h"
00047 #include "address.h"
00048 #include "trace.h"
00049 #include "rap/rap.h"
00050
00051
00052
00053
00054 class TraceClass : public TclClass {
00055 public:
00056 TraceClass() : TclClass("Trace") { }
00057 TclObject* create(int argc, const char*const* argv) {
00058 if (argc >= 5)
00059 return (new Trace(*argv[4]));
00060 return 0;
00061 }
00062 } trace_class;
00063
00064
00065 Trace::Trace(int type)
00066 : Connector(), callback_(0), pt_(0), type_(type)
00067 {
00068 bind("src_", (int*)&src_);
00069 bind("dst_", (int*)&dst_);
00070 bind("callback_", &callback_);
00071 bind("show_tcphdr_", &show_tcphdr_);
00072 bind("show_sctphdr_", &show_sctphdr_);
00073 pt_ = new BaseTrace;
00074 }
00075
00076 Trace::~Trace()
00077 {
00078 }
00079
00080
00081
00082
00083
00084
00085 int Trace::command(int argc, const char*const* argv)
00086 {
00087 Tcl& tcl = Tcl::instance();
00088 if (argc == 2) {
00089 if (strcmp(argv[1], "detach") == 0) {
00090 pt_->channel(0) ;
00091 pt_->namchannel(0) ;
00092 return (TCL_OK);
00093 }
00094 if (strcmp(argv[1], "flush") == 0) {
00095 Tcl_Channel ch = pt_->channel();
00096 Tcl_Channel namch = pt_->namchannel();
00097 if (ch != 0)
00098 pt_->flush(ch);
00099
00100 if (namch != 0)
00101
00102 pt_->flush(namch);
00103 return (TCL_OK);
00104 }
00105 if (strcmp(argv[1], "tagged") == 0) {
00106 tcl.resultf("%d", pt_->tagged());
00107 return (TCL_OK);
00108 }
00109 } else if (argc == 3) {
00110 if (strcmp(argv[1], "annotate") == 0) {
00111 if (pt_->channel() != 0)
00112 annotate(argv[2]);
00113 return (TCL_OK);
00114 }
00115 if (strcmp(argv[1], "attach") == 0) {
00116 int mode;
00117 const char* id = argv[2];
00118 Tcl_Channel ch = Tcl_GetChannel(tcl.interp(), (char*)id,
00119 &mode);
00120 pt_->channel(ch);
00121 if (pt_->channel() == 0) {
00122 tcl.resultf("trace: can't attach %s for writing", id);
00123 return (TCL_ERROR);
00124 }
00125 return (TCL_OK);
00126 }
00127 if (strcmp(argv[1], "namattach") == 0) {
00128 int mode;
00129 const char* id = argv[2];
00130 Tcl_Channel namch = Tcl_GetChannel(tcl.interp(),
00131 (char*)id, &mode);
00132 pt_->namchannel(namch);
00133 if (pt_->namchannel() == 0) {
00134 tcl.resultf("trace: can't attach %s for writing", id);
00135 return (TCL_ERROR);
00136 }
00137 return (TCL_OK);
00138 }
00139 if (strcmp(argv[1], "ntrace") == 0) {
00140 if (pt_->namchannel() != 0)
00141 write_nam_trace(argv[2]);
00142 return (TCL_OK);
00143 }
00144 if (strcmp(argv[1], "tagged") == 0) {
00145 int tag;
00146 if (Tcl_GetBoolean(tcl.interp(),
00147 (char*)argv[2], &tag) == TCL_OK) {
00148 pt_->tagged(tag);
00149 return (TCL_OK);
00150 } else return (TCL_ERROR);
00151 }
00152 }
00153 return (Connector::command(argc, argv));
00154 }
00155
00156 void Trace::write_nam_trace(const char *s)
00157 {
00158 sprintf(pt_->nbuffer(), "%s", s);
00159 pt_->namdump();
00160 }
00161
00162 void Trace::annotate(const char* s)
00163 {
00164 if (pt_->tagged()) {
00165 sprintf(pt_->buffer(),
00166 "v "TIME_FORMAT" -e {sim_annotation %g %s}",
00167 Scheduler::instance().clock(),
00168 Scheduler::instance().clock(), s);
00169 } else {
00170 sprintf(pt_->buffer(),
00171 "v "TIME_FORMAT" eval {set sim_annotation {%s}}",
00172 pt_->round(Scheduler::instance().clock()), s);
00173 }
00174 pt_->dump();
00175 callback();
00176 sprintf(pt_->nbuffer(), "v -t "TIME_FORMAT" -e sim_annotation %g %s",
00177 Scheduler::instance().clock(),
00178 Scheduler::instance().clock(), s);
00179 pt_->namdump();
00180 }
00181
00182
00183 char* srm_names[] = {
00184 SRM_NAMES
00185 };
00186
00187 int
00188 Trace::get_seqno(Packet* p)
00189 {
00190 hdr_cmn *th = hdr_cmn::access(p);
00191 hdr_tcp *tcph = hdr_tcp::access(p);
00192 hdr_rtp *rh = hdr_rtp::access(p);
00193 hdr_rap *raph = hdr_rap::access(p);
00194 hdr_tfrc *tfrch = hdr_tfrc::access(p);
00195 hdr_tfrc_ack *tfrch_ack = hdr_tfrc_ack::access(p);
00196 packet_t t = th->ptype();
00197 int seqno;
00198
00199
00200 if (t == PT_RTP || t == PT_CBR || t == PT_UDP || t == PT_EXP ||
00201 t == PT_PARETO)
00202 seqno = rh->seqno();
00203 else if (t == PT_RAP_DATA || t == PT_RAP_ACK)
00204 seqno = raph->seqno();
00205 else if (t == PT_TCP || t == PT_ACK || t == PT_HTTP || t == PT_FTP ||
00206 t == PT_TELNET || t == PT_XCP)
00207 seqno = tcph->seqno();
00208 else if (t == PT_TFRC)
00209 seqno = tfrch->seqno;
00210 else if (t == PT_TFRC_ACK)
00211 seqno = tfrch_ack->seqno;
00212 else
00213 seqno = -1;
00214 return seqno;
00215 }
00216
00217
00218
00219 void Trace::format(int tt, int s, int d, Packet* p)
00220 {
00221 hdr_cmn *th = hdr_cmn::access(p);
00222 hdr_ip *iph = hdr_ip::access(p);
00223 hdr_tcp *tcph = hdr_tcp::access(p);
00224 hdr_sctp *sctph = hdr_sctp::access(p);
00225 hdr_srm *sh = hdr_srm::access(p);
00226
00227 const char* sname = "null";
00228
00229 packet_t t = th->ptype();
00230 const char* name = packet_info.name(t);
00231
00232
00233 if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
00234 if ( sh->type() < 5 && sh->type() > 0 ) {
00235 sname = srm_names[sh->type()];
00236 }
00237 }
00238
00239 if (name == 0)
00240 abort();
00241
00242 int seqno = get_seqno(p);
00243
00244
00245
00246
00247 char flags[NUMFLAGS+1];
00248 for (int i = 0; i < NUMFLAGS; i++)
00249 flags[i] = '-';
00250 flags[NUMFLAGS] = 0;
00251
00252 hdr_flags* hf = hdr_flags::access(p);
00253 flags[0] = hf->ecn_ ? 'C' : '-';
00254 flags[1] = hf->pri_ ? 'P' : '-';
00255 flags[2] = '-';
00256 flags[3] = hf->cong_action_ ? 'A' : '-';
00257 flags[4] = hf->ecn_to_echo_ ? 'E' : '-';
00258 flags[5] = hf->fs_ ? 'F' : '-';
00259 flags[6] = hf->ecn_capable_ ? 'N' : '-';
00260 flags[7] = 0;
00261
00262 #ifdef notdef
00263 flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
00264 flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
00265 flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
00266 flags[5] = 0;
00267 #endif
00268 char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
00269 char *src_portaddr = Address::instance().print_portaddr(iph->sport());
00270 char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
00271 char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
00272
00273 if (pt_->tagged()) {
00274 sprintf(pt_->buffer(),
00275 "%c "TIME_FORMAT" -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
00276 tt,
00277 Scheduler::instance().clock(),
00278 s,
00279 d,
00280 name,
00281 th->size(),
00282 iph->flowid(),
00283 th->uid(),
00284 iph->flowid(),
00285 src_nodeaddr,
00286 src_portaddr,
00287 dst_nodeaddr,
00288 dst_portaddr,
00289 seqno,flags,sname);
00290 } else if (show_sctphdr_ && t == PT_SCTP) {
00291 double timestamp;
00292 timestamp = Scheduler::instance().clock();
00293
00294 for(unsigned int i = 0; i < sctph->NumChunks(); i++) {
00295 switch(sctph->SctpTrace()[i].eType) {
00296 case SCTP_CHUNK_INIT:
00297 case SCTP_CHUNK_INIT_ACK:
00298 case SCTP_CHUNK_COOKIE_ECHO:
00299 case SCTP_CHUNK_COOKIE_ACK:
00300 flags[7] = 'I';
00301 break;
00302
00303 case SCTP_CHUNK_DATA:
00304 flags[7] = 'D';
00305 break;
00306
00307 case SCTP_CHUNK_SACK:
00308 flags[7] = 'S';
00309 break;
00310
00311 case SCTP_CHUNK_FORWARD_TSN:
00312 flags[7] = 'R';
00313 break;
00314
00315 case SCTP_CHUNK_HB:
00316 flags[7] = 'H';
00317 break;
00318
00319 case SCTP_CHUNK_HB_ACK:
00320 flags[7] = 'B';
00321 break;
00322 default:
00323 assert (false);
00324 }
00325 sprintf(pt_->buffer(),
00326 "%c "TIME_FORMAT" %d %d %s %d %s %d %s.%s %s.%s %d %d %d %d %d",
00327 tt,
00328 pt_->round(timestamp),
00329 s,
00330 d,
00331 name,
00332 th->size(),
00333 flags,
00334 iph->flowid(),
00335 src_nodeaddr,
00336 src_portaddr,
00337 dst_nodeaddr,
00338 dst_portaddr,
00339 sctph->NumChunks(),
00340 sctph->SctpTrace()[i].uiTsn,
00341 th->uid(),
00342 sctph->SctpTrace()[i].usStreamId,
00343 sctph->SctpTrace()[i].usStreamSeqNum);
00344
00345
00346
00347
00348
00349 assert (sctph->NumChunks() >= 1);
00350 if(i < sctph->NumChunks() - 1)
00351 pt_->dump();
00352 }
00353 } else if (!show_tcphdr_) {
00354 sprintf(pt_->buffer(), "%c "TIME_FORMAT" %d %d %s %d %s %d %s.%s %s.%s %d %d",
00355 tt,
00356 pt_->round(Scheduler::instance().clock()),
00357 s,
00358 d,
00359 name,
00360 th->size(),
00361 flags,
00362 iph->flowid() ,
00363
00364
00365
00366
00367 src_nodeaddr,
00368 src_portaddr,
00369 dst_nodeaddr,
00370 dst_portaddr,
00371 seqno,
00372 th->uid() );
00373 } else {
00374 sprintf(pt_->buffer(),
00375 "%c "TIME_FORMAT" %d %d %s %d %s %d %s.%s %s.%s %d %d %d 0x%x %d %d",
00376 tt,
00377 pt_->round(Scheduler::instance().clock()),
00378 s,
00379 d,
00380 name,
00381 th->size(),
00382 flags,
00383 iph->flowid(),
00384
00385
00386
00387
00388 src_nodeaddr,
00389 src_portaddr,
00390 dst_nodeaddr,
00391 dst_portaddr,
00392 seqno,
00393 th->uid(),
00394 tcph->ackno(),
00395 tcph->flags(),
00396 tcph->hlen(),
00397 tcph->sa_length());
00398 }
00399 if (pt_->namchannel() != 0)
00400 sprintf(pt_->nbuffer(),
00401 "%c -t "TIME_FORMAT" -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
00402 tt,
00403 Scheduler::instance().clock(),
00404 s,
00405 d,
00406 name,
00407 th->size(),
00408 iph->flowid(),
00409 th->uid(),
00410 iph->flowid(),
00411 src_nodeaddr,
00412 src_portaddr,
00413 dst_nodeaddr,
00414 dst_portaddr,
00415 seqno,flags,sname);
00416 delete [] src_nodeaddr;
00417 delete [] src_portaddr;
00418 delete [] dst_nodeaddr;
00419 delete [] dst_portaddr;
00420 }
00421
00422 void Trace::recv(Packet* p, Handler* h)
00423 {
00424 format(type_, src_, dst_, p);
00425 pt_->dump();
00426 callback();
00427 pt_->namdump();
00428
00429 if (target_ == 0)
00430 Packet::free(p);
00431 else
00432 send(p, h);
00433 }
00434
00435 void Trace::recvOnly(Packet *p)
00436 {
00437 format(type_, src_, dst_, p);
00438 pt_->dump();
00439 callback();
00440 pt_->namdump();
00441 target_->recvOnly(p);
00442 }
00443
00444 void Trace::trace(TracedVar* var)
00445 {
00446 char tmp[256] = "";
00447 Scheduler& s = Scheduler::instance();
00448 if (&s == 0)
00449 return;
00450
00451 if (pt_->tagged()) {
00452 sprintf(pt_->buffer(), "%c "TIME_FORMAT" -a %s -n %s -v %s",
00453 type_,
00454 pt_->round(s.clock()),
00455 var->owner()->name(),
00456 var->name(),
00457 var->value(tmp, 256));
00458 } else {
00459
00460 sprintf(pt_->buffer(), "%c t"TIME_FORMAT" a%s n%s v%s",
00461 type_,
00462 pt_->round(s.clock()),
00463 var->owner()->name(),
00464 var->name(),
00465 var->value(tmp, 256));
00466 }
00467 pt_->dump();
00468 callback();
00469 }
00470
00471 void Trace::callback()
00472 {
00473 if (callback_) {
00474 Tcl& tcl = Tcl::instance();
00475 tcl.evalf("%s handle { %s }", name(), pt_->buffer());
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484 static class DequeTraceClass : public TclClass {
00485 public:
00486 DequeTraceClass() : TclClass("Trace/Deque") { }
00487 TclObject* create(int args, const char*const* argv) {
00488 if (args >= 5)
00489 return (new DequeTrace(*argv[4]));
00490 return NULL;
00491 }
00492 } dequetrace_class;
00493
00494
00495 DequeTrace::~DequeTrace()
00496 {
00497 }
00498
00499 void
00500 DequeTrace::recv(Packet* p, Handler* h)
00501 {
00502
00503 format(type_, src_, dst_, p);
00504 pt_->dump();
00505 callback();
00506 pt_->namdump();
00507
00508 if (pt_->namchannel() != 0 ||
00509 (pt_->tagged() && pt_->channel() !=0)) {
00510 hdr_cmn *th = hdr_cmn::access(p);
00511 hdr_ip *iph = hdr_ip::access(p);
00512 hdr_srm *sh = hdr_srm::access(p);
00513 const char* sname = "null";
00514
00515 packet_t t = th->ptype();
00516 const char* name = packet_info.name(t);
00517
00518 if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
00519 if ( sh->type() < 5 && sh->type() > 0 ) {
00520 sname = srm_names[sh->type()];
00521 }
00522 }
00523
00524 char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
00525 char *src_portaddr = Address::instance().print_portaddr(iph->sport());
00526 char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
00527 char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
00528
00529 char flags[NUMFLAGS+1];
00530 for (int i = 0; i < NUMFLAGS; i++)
00531 flags[i] = '-';
00532 flags[NUMFLAGS] = 0;
00533
00534 hdr_flags* hf = hdr_flags::access(p);
00535 flags[0] = hf->ecn_ ? 'C' : '-';
00536 flags[1] = hf->pri_ ? 'P' : '-';
00537 flags[2] = '-';
00538 flags[3] = hf->cong_action_ ? 'A' : '-';
00539 flags[4] = hf->ecn_to_echo_ ? 'E' : '-';
00540 flags[5] = hf->fs_ ? 'F' : '-';
00541 flags[6] = hf->ecn_capable_ ? 'N' : '-';
00542 flags[7] = 0;
00543
00544 #ifdef notdef
00545 flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
00546 flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
00547 flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
00548 flags[5] = 0;
00549 #endif
00550
00551 if (pt_->nbuffer() != 0) {
00552 sprintf(pt_->nbuffer(),
00553 "%c -t "TIME_FORMAT" -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
00554 'h',
00555 Scheduler::instance().clock(),
00556 src_,
00557 dst_,
00558 name,
00559 th->size(),
00560 iph->flowid(),
00561 th->uid(),
00562 iph->flowid(),
00563 src_nodeaddr,
00564 src_portaddr,
00565 dst_nodeaddr,
00566 dst_portaddr,
00567 -1, flags, sname);
00568 pt_->namdump();
00569 }
00570 if (pt_->tagged() && pt_->buffer() != 0) {
00571 sprintf(pt_->buffer(),
00572 "%c "TIME_FORMAT" -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
00573 'h',
00574 Scheduler::instance().clock(),
00575 src_,
00576 dst_,
00577 name,
00578 th->size(),
00579 iph->flowid(),
00580 th->uid(),
00581 iph->flowid(),
00582 src_nodeaddr,
00583 src_portaddr,
00584 dst_nodeaddr,
00585 dst_portaddr,
00586 -1, flags, sname);
00587 pt_->dump();
00588 }
00589
00590 delete [] src_nodeaddr;
00591 delete [] src_portaddr;
00592 delete [] dst_nodeaddr;
00593 delete [] dst_portaddr;
00594 }
00595
00596
00597 if (target_ == 0)
00598 Packet::free(p);
00599 else
00600 send(p, h);
00601 }
00602