sattrace.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1999 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *      This product includes software developed by the MASH Research
  17.  *      Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
  35.  * speedup hack from Lloyd Wood, 11 October 1999 */
  36. #ifndef lint
  37. static const char rcsid[] =
  38.     "@(#) $Header: /cvsroot/nsnam/ns-2/satellite/sattrace.cc,v 1.16 2005/09/21 20:54:21 haldar Exp $";
  39. #endif
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include "packet.h"
  43. #include "ip.h"
  44. #include "tcp.h"
  45. #include "sctp.h"
  46. #include "rtp.h"
  47. #include "srm.h"
  48. #include "flags.h"
  49. #include "address.h"
  50. #include "trace.h"
  51. #include "sattrace.h"
  52. #include "satposition.h"
  53. #include "satnode.h"
  54. #include "sat-hdlc.h"
  55. class SatTraceClass : public TclClass {
  56. public:
  57. SatTraceClass() : TclClass("Trace/Sat") { }
  58. TclObject* create(int argc, const char*const* argv) {
  59. if (argc >= 5) {
  60. return (new SatTrace(*argv[4]));
  61. }
  62. return 0;
  63. }
  64. } sat_trace_class;
  65. // XXX this should be moved from trace.cc to trace.h 
  66. char* srm_names_[] = {
  67. SRM_NAMES
  68. };
  69. void SatTrace::format_hdlc(Packet *p, int offset)
  70. {
  71. struct hdr_hdlc *hh = HDR_HDLC(p);
  72. struct I_frame *ifr = (struct I_frame *)&(hh->hdlc_fc_);
  73. struct S_frame *sf = (struct S_frame *)&(hh->hdlc_fc_);
  74. struct U_frame *uf = (struct U_frame *)&(hh->hdlc_fc_);
  75. switch(hh->fc_type_) {
  76. case HDLC_I_frame:
  77. if (pt_->tagged()) {
  78. sprintf(pt_->buffer() + offset,
  79. "-hdlc:sa %d -hdlc:da %d -hdlc:ft I -hdlc:r_seq %d -hdlc:s_seq %d",
  80. hh->saddr(),
  81. hh->daddr(),
  82. ifr->recv_seqno, 
  83. ifr->send_seqno);
  84. // } else if (newtrace_) {
  85. //  sprintf(pt_->buffer() + offset,
  86. //  "-P hdlc -Psa %d -Pda %d -Pft I -Pr_seq %d -Ps_seq %d",
  87. //  hh->saddr(),
  88. //  hh->daddr(),
  89. //  ifr->recv_seqno, 
  90. //  ifr->send_seqno);
  91. } else {
  92. sprintf(pt_->buffer() + offset,
  93. "[%d %d I %d %d]",
  94. hh->saddr(),
  95. hh->daddr(),
  96. ifr->recv_seqno, 
  97. ifr->send_seqno);
  98. }
  99. break;
  100. case HDLC_S_frame:
  101. if (pt_->tagged()) {
  102. sprintf(pt_->buffer() + offset,
  103. "-hdlc:sa %d -hdlc:da %d -hdlc:ft S -hdlc:r_seq %d -hdlc:stype %s",
  104. hh->saddr(),
  105. hh->daddr(),
  106. sf->recv_seqno,
  107. (sf->stype == RR) ? "RR" :
  108. (sf->stype == REJ) ? "REJ" :
  109. (sf->stype == RNR) ? "RNR" :
  110. (sf->stype == SREJ) ? "SREJ" : "UNKN");
  111. // } else if (newtrace_) {
  112. //  sprintf(pt_->buffer() + offset,
  113. //  "-P hdlc -Psa %d -Pda %d -Pft S -Pr_seq %d -Pstype %s",
  114. //  hh->saddr(),
  115. //  hh->daddr(),
  116. //  sf->recv_seqno,
  117. //  sf->stype == RR ? "RR" :
  118. //  sf->stype == REJ ? "REJ" :
  119. //  sf->stype == RNR ? "RNR" :
  120. //  sf->stype == SREJ ? "SREJ" : "UNKN");
  121. } else {
  122. sprintf(pt_->buffer() + offset,
  123. "[%d %d S %d %s]",
  124. hh->saddr(),
  125. hh->daddr(),
  126. sf->recv_seqno,
  127. sf->stype == RR ? "RR" :
  128. sf->stype == REJ ? "REJ" :
  129. sf->stype == RNR ? "RNR" :
  130. sf->stype == SREJ ? "SREJ" :
  131. "UNKN");
  132. }
  133. break;
  134. case HDLC_U_frame:
  135. if (pt_->tagged()) {
  136. sprintf(pt_->buffer() + offset,
  137. "-hdlc:sa %d -hdlc:da %d -hdlc:ft U -hdlc:utype %s",
  138. hh->saddr(),
  139. hh->daddr(),
  140. uf->utype == SABME ? "SABME" :
  141. uf->utype == UA ? "UA" :
  142. uf->utype == DM ? "DM" :
  143. uf->utype == DISC ? "DISC" : "UNKN");
  144. // } else if (newtrace_) {
  145. //  sprintf(pt_->buffer() + offset,
  146. //  "-P hdlc -Psa %d -Pda %d -Pft U -Putype %s",
  147. //  hh->saddr(),
  148. //  hh->daddr(),
  149. //  uf->utype == SABME ? "SABME" :
  150. //  uf->utype == UA ? "UA" :
  151. //  uf->utype == DM ? "DM" :
  152. //  uf->utype == DISC ? "DISC" : "UNKN");
  153. } else {
  154. sprintf(pt_->buffer() + offset,
  155. "[%d %d U %s]",
  156. hh->saddr(),
  157. hh->daddr(),
  158. uf->utype == SABME ? "SABME" :
  159. uf->utype == UA ? "UA" :
  160. uf->utype == DM ? "DM" :
  161. uf->utype == DISC ? "DISC" : "UNKN");
  162. }
  163. break;
  164. default:
  165. fprintf(stderr, "Unknown HDLC frame typen");
  166. exit(1);
  167. }
  168. }
  169. void SatTrace::format(int tt, int s, int d, Packet* p)
  170. {
  171. int offset = 0;
  172. hdr_cmn *th = hdr_cmn::access(p);
  173. hdr_ip *iph = hdr_ip::access(p);
  174. hdr_tcp *tcph = hdr_tcp::access(p);
  175. hdr_sctp *sctph = hdr_sctp::access(p);
  176. hdr_rtp *rh = hdr_rtp::access(p);
  177. hdr_srm *sh = hdr_srm::access(p); 
  178. const char* sname = "null";
  179. int lasth, nexth, snadd;
  180. Node* n;
  181. packet_t t = th->ptype();
  182. const char* name = packet_info.name(t);
  183.         /* SRM-specific */
  184. if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
  185.             if ( sh->type() < 5 && sh->type() > 0 ) {
  186.         sname = srm_names_[sh->type()];
  187.     }
  188. }
  189. if (name == 0)
  190. abort();
  191. int seqno;
  192. /* UDP's now have seqno's too */
  193. if (t == PT_RTP || t == PT_CBR || t == PT_UDP || t == PT_EXP ||
  194.     t == PT_PARETO)
  195. seqno = rh->seqno();
  196. else if (t == PT_TCP || t == PT_ACK || t == PT_HTTP || t == PT_FTP ||
  197.     t == PT_TELNET)
  198. seqno = tcph->seqno();
  199. else
  200. seqno = -1;
  201.         /* 
  202.          * When new flags are added, make sure to change NUMFLAGS
  203.          * in trace.h
  204.          */
  205.         char flags[NUMFLAGS+1];
  206.         for (int i = 0; i < NUMFLAGS; i++)
  207. flags[i] = '-';
  208.         flags[NUMFLAGS] = 0;
  209. hdr_flags* hf = hdr_flags::access(p);
  210. flags[0] = hf->ecn_ ? 'C' : '-';          // Ecn Echo
  211. flags[1] = hf->pri_ ? 'P' : '-'; 
  212. flags[2] = '-';
  213. flags[3] = hf->cong_action_ ? 'A' : '-';   // Congestion Action
  214. flags[4] = hf->ecn_to_echo_ ? 'E' : '-';   // Congestion Experienced
  215. flags[5] = hf->fs_ ? 'F' : '-';
  216. flags[6] = hf->ecn_capable_ ? 'N' : '-';
  217. flags[7] = 0; // only for SCTP
  218. #ifdef notdef
  219. flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
  220. flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
  221. flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
  222. flags[5] = 0;
  223. #endif
  224. char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
  225. char *src_portaddr = Address::instance().print_portaddr(iph->sport());
  226. char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
  227. char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
  228. // Find position of previous hop and next hop
  229. double s_lat = -999, s_lon = -999, d_lat = -999, d_lon = -999;
  230. n = Node::nodehead_.lh_first;
  231. // XXX what if n is not a SatNode?? Need a dynamic cast here, or make sure that
  232. // only sat tracing elements go between sat nodes.
  233. // SatNode *sn = dynamic_cast<SatNode*>(n);
  234. assert (n != 0);
  235. lasth = th->last_hop_;
  236. nexth = th->next_hop_;
  237. for (; n; n = n->nextnode() ) {
  238. SatNode *sn = (SatNode*) n;
  239. snadd = sn->address();
  240. if (lasth == snadd) {
  241. s_lat = RAD_TO_DEG(SatGeometry::get_latitude(sn->position()->coord()));
  242. s_lon = RAD_TO_DEG(SatGeometry::get_longitude(sn->position()->coord()));
  243. if (d_lat != -999) 
  244. break; // Have now found both s and d
  245. }
  246. if (nexth == snadd) {
  247. d_lat = RAD_TO_DEG(SatGeometry::get_latitude(sn->position()->coord())); 
  248. d_lon = RAD_TO_DEG(SatGeometry::get_longitude(sn->position()->coord()));
  249. if (s_lat != -999) 
  250. break; // Have now found both s and d
  251. }
  252. }
  253. if (show_sctphdr_ && t == PT_SCTP) {
  254.    double timestamp;
  255.    timestamp = Scheduler::instance().clock();
  256.    
  257.    for(unsigned int i = 0; i < sctph->NumChunks(); i++) {
  258.    switch(sctph->SctpTrace()[i].eType) {
  259. case SCTP_CHUNK_INIT:
  260. case SCTP_CHUNK_INIT_ACK:
  261. case SCTP_CHUNK_COOKIE_ECHO:
  262. case SCTP_CHUNK_COOKIE_ACK:
  263. flags[7] = 'I';              // connection initialization
  264. break;
  265. case SCTP_CHUNK_DATA:
  266. flags[7] = 'D';
  267. break;
  268. case SCTP_CHUNK_SACK:
  269. flags[7] = 'S';
  270. break;
  271. case SCTP_CHUNK_FORWARD_TSN:
  272. flags[7] = 'R';
  273. break;
  274. case SCTP_CHUNK_HB:
  275. flags[7] = 'H';
  276. break;
  277. case SCTP_CHUNK_HB_ACK:
  278. flags[7] = 'B';
  279. break;
  280.         default:
  281. assert (false);
  282. break;
  283. }
  284.    sprintf(pt_->buffer(), "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %d %d %d %.2f %.2f %.2f %.2f",
  285. tt,
  286. pt_->round(Scheduler::instance().clock()),
  287. lasth,
  288. nexth,
  289. name,
  290. th->size(),
  291. flags,
  292. iph->flowid() /* was p->class_ */,
  293. // iph->src() >> (Address::instance().NodeShift_[1]), 
  294.                         // iph->src() & (Address::instance().PortMask_), 
  295.                         // iph->dst() >> (Address::instance().NodeShift_[1]), 
  296.                         // iph->dst() & (Address::instance().PortMask_),
  297. src_nodeaddr,
  298. src_portaddr,
  299. dst_nodeaddr,
  300. dst_portaddr,
  301. sctph->NumChunks(),
  302. sctph->SctpTrace()[i].uiTsn,
  303. th->uid(), /* was p->uid_ */
  304. sctph->SctpTrace()[i].usStreamId,
  305. sctph->SctpTrace()[i].usStreamSeqNum,
  306. s_lat,
  307. s_lon,
  308. d_lat,
  309. d_lon);
  310.    /* The caller already calls pt_->dump() for us, but
  311.     * since SCTP needs to dump once per chunk, we call
  312.     * dump ourselves for all but the last * chunk.  
  313.     */
  314.    if(i < sctph->NumChunks() - 1)
  315.    pt_->dump();
  316. }
  317. }
  318. else if (pt_->tagged()) {
  319. sprintf(pt_->nbuffer(), 
  320. "%c %g -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
  321. tt,
  322. Scheduler::instance().clock(),
  323. s,
  324.   d,
  325. name,
  326. th->size(),
  327. iph->flowid(),
  328. th->uid(),
  329. iph->flowid(),
  330. src_nodeaddr,
  331. src_portaddr,
  332. dst_nodeaddr,
  333. dst_portaddr,
  334. seqno,flags,sname);
  335. } else if (!show_tcphdr_) {
  336. sprintf(pt_->buffer(), "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %.2f %.2f %.2f %.2f",
  337. tt,
  338. pt_->round(Scheduler::instance().clock()),
  339. lasth,
  340. nexth,
  341. name,
  342. th->size(),
  343. flags,
  344. iph->flowid() /* was p->class_ */,
  345. // iph->src() >> (Address::instance().NodeShift_[1]), 
  346.                         // iph->src() & (Address::instance().PortMask_), 
  347.                         // iph->dst() >> (Address::instance().NodeShift_[1]), 
  348.                         // iph->dst() & (Address::instance().PortMask_),
  349. src_nodeaddr,
  350. src_portaddr,
  351. dst_nodeaddr,
  352. dst_portaddr,
  353. seqno,
  354. th->uid(), /* was p->uid_ */
  355. s_lat,
  356. s_lon,
  357. d_lat,
  358. d_lon);
  359. } else {
  360. sprintf(pt_->buffer(), 
  361. "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %d 0x%x %d %d %.2f %.2f %.2f %.2f",
  362. tt,
  363. pt_->round(Scheduler::instance().clock()),
  364. lasth,
  365. nexth,
  366. name,
  367. th->size(),
  368. flags,
  369. iph->flowid(), /* was p->class_ */
  370.         // iph->src() >> (Address::instance().NodeShift_[1]), 
  371. // iph->src() & (Address::instance().PortMask_), 
  372.            // iph->dst() >> (Address::instance().NodeShift_[1]), 
  373.            // iph->dst() & (Address::instance().PortMask_),
  374. src_nodeaddr,
  375. src_portaddr,
  376. dst_nodeaddr,
  377. dst_portaddr,
  378. seqno,
  379. th->uid(), /* was p->uid_ */
  380. tcph->ackno(),
  381. tcph->flags(),
  382. tcph->hlen(),
  383. tcph->sa_length(),
  384. s_lat,
  385. s_lon,
  386. d_lat,
  387. d_lon);
  388. }
  389. offset = strlen(pt_->buffer());
  390. if (t == PT_HDLC)
  391. format_hdlc(p, offset);
  392. if (pt_->namchannel() != 0)
  393. sprintf(pt_->nbuffer(), 
  394. "%c -t %g -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
  395. tt,
  396. Scheduler::instance().clock(),
  397. s,
  398.   d,
  399. name,
  400. th->size(),
  401. iph->flowid(),
  402. th->uid(),
  403. iph->flowid(),
  404. src_nodeaddr,
  405. src_portaddr,
  406. dst_nodeaddr,
  407. dst_portaddr,
  408. seqno,flags,sname);
  409. delete [] src_nodeaddr;
  410.    delete [] src_portaddr;
  411.    delete [] dst_nodeaddr;
  412.     delete [] dst_portaddr;
  413. }
  414. void SatTrace::traceonly(Packet* p)
  415. {        
  416. format(type_, src_, dst_, p);
  417. pt_->dump();
  418. }
  419. //
  420. // we need a DequeTraceClass here because a 'h' event need to go together
  421. // with the '-' event. It's possible to use a postprocessing script, but 
  422. // seems that's inconvient.
  423. //
  424. static class SatDequeTraceClass : public TclClass {
  425. public:
  426. SatDequeTraceClass() : TclClass("Trace/Sat/Deque") { }
  427. TclObject* create(int args, const char*const* argv) {
  428. if (args >= 5)
  429. return (new SatDequeTrace(*argv[4]));
  430. return NULL;
  431. }
  432. } sat_dequetrace_class;
  433. void 
  434. SatDequeTrace::recv(Packet* p, Handler* h)
  435. {
  436. // write the '-' event first
  437. format(type_, src_, dst_, p);
  438. pt_->dump();
  439. pt_->namdump();
  440. if (pt_->namchannel() != 0) {
  441. hdr_cmn *th = hdr_cmn::access(p);
  442. hdr_ip *iph = hdr_ip::access(p);
  443. hdr_srm *sh = hdr_srm::access(p);
  444. const char* sname = "null";   
  445. packet_t t = th->ptype();
  446. const char* name = packet_info.name(t);
  447. if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
  448.     if ( sh->type() < 5 && sh->type() > 0  ) {
  449.         sname = srm_names_[sh->type()];
  450.     }
  451. }   
  452. char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
  453. char *src_portaddr = Address::instance().print_portaddr(iph->sport());
  454. char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
  455. char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
  456. char flags[NUMFLAGS+1];
  457. for (int i = 0; i < NUMFLAGS; i++)
  458. flags[i] = '-';
  459. flags[NUMFLAGS] = 0;
  460. hdr_flags* hf = hdr_flags::access(p);
  461. flags[0] = hf->ecn_ ? 'C' : '-';          // Ecn Echo
  462. flags[1] = hf->pri_ ? 'P' : '-'; 
  463. flags[2] = '-';
  464. flags[3] = hf->cong_action_ ? 'A' : '-';   // Congestion Action
  465. flags[4] = hf->ecn_to_echo_ ? 'E' : '-';   // Congestion Experienced
  466. flags[5] = hf->fs_ ? 'F' : '-';
  467. flags[6] = hf->ecn_capable_ ? 'N' : '-';
  468. #ifdef notdef
  469. flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
  470. flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
  471. flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
  472. flags[5] = 0;
  473. #endif
  474. sprintf(pt_->nbuffer(), 
  475. "%c -t %g -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
  476. 'h',
  477. Scheduler::instance().clock(),
  478. src_,
  479.    dst_,
  480. name,
  481. th->size(),
  482. iph->flowid(),
  483. th->uid(),
  484. iph->flowid(),
  485. src_nodeaddr,
  486. src_portaddr,
  487. dst_nodeaddr,
  488. dst_portaddr,
  489. -1, flags, sname);
  490. pt_->namdump();
  491. delete [] src_nodeaddr;
  492. delete [] src_portaddr;
  493. delete [] dst_nodeaddr;
  494. delete [] dst_portaddr;
  495. }
  496. /* hack: if trace object not attached to anything free packet */
  497. if (target_ == 0)
  498. Packet::free(p);
  499. else
  500. send(p, h);
  501. }