sattrace.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1999 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the MASH Research
00017  *      Group at the University of California Berkeley.
00018  * 4. Neither the name of the University nor of the Research Group may be
00019  *    used to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
00035  * speedup hack from Lloyd Wood, 11 October 1999 */
00036 
00037 #ifndef lint
00038 static const char rcsid[] =
00039     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/satellite/sattrace.cc,v 1.16 2005/09/21 20:54:21 haldar Exp $";
00040 #endif
00041 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include "packet.h"
00045 #include "ip.h"
00046 #include "tcp.h"
00047 #include "sctp.h"
00048 #include "rtp.h"
00049 #include "srm.h"
00050 #include "flags.h"
00051 #include "address.h"
00052 #include "trace.h"
00053 #include "sattrace.h"
00054 #include "satposition.h"
00055 #include "satnode.h"
00056 #include "sat-hdlc.h"
00057 
00058 class SatTraceClass : public TclClass {
00059 public:
00060     SatTraceClass() : TclClass("Trace/Sat") { }
00061     TclObject* create(int argc, const char*const* argv) {
00062         if (argc >= 5) {
00063             return (new SatTrace(*argv[4]));
00064         }
00065         return 0;
00066     }
00067 } sat_trace_class;
00068 
00069 // XXX this should be moved from trace.cc to trace.h 
00070 char* srm_names_[] = {
00071     SRM_NAMES
00072 };
00073 
00074 void SatTrace::format_hdlc(Packet *p, int offset)
00075 {
00076     struct hdr_hdlc *hh = HDR_HDLC(p);
00077     struct I_frame *ifr = (struct I_frame *)&(hh->hdlc_fc_);
00078     struct S_frame *sf = (struct S_frame *)&(hh->hdlc_fc_);
00079     struct U_frame *uf = (struct U_frame *)&(hh->hdlc_fc_);
00080     
00081     switch(hh->fc_type_) {
00082     case HDLC_I_frame:
00083         if (pt_->tagged()) {
00084             sprintf(pt_->buffer() + offset,
00085                 "-hdlc:sa %d -hdlc:da %d -hdlc:ft I -hdlc:r_seq %d -hdlc:s_seq %d",
00086                 hh->saddr(),
00087                 hh->daddr(),
00088                 ifr->recv_seqno, 
00089                 ifr->send_seqno);
00090             
00091         // } else if (newtrace_) {
00092 //          sprintf(pt_->buffer() + offset,
00093 //              "-P hdlc -Psa %d -Pda %d -Pft I -Pr_seq %d -Ps_seq %d",
00094 //              hh->saddr(),
00095 //              hh->daddr(),
00096 //              ifr->recv_seqno, 
00097 //              ifr->send_seqno);
00098         } else {
00099             sprintf(pt_->buffer() + offset,
00100                 "[%d %d I %d %d]",
00101                 hh->saddr(),
00102                 hh->daddr(),
00103                 ifr->recv_seqno, 
00104                 ifr->send_seqno);
00105         }
00106         break;
00107         
00108     case HDLC_S_frame:
00109         if (pt_->tagged()) {
00110             sprintf(pt_->buffer() + offset,
00111                 "-hdlc:sa %d -hdlc:da %d -hdlc:ft S -hdlc:r_seq %d -hdlc:stype %s",
00112                 hh->saddr(),
00113                 hh->daddr(),
00114                 sf->recv_seqno,
00115                 (sf->stype == RR) ? "RR" :
00116                 (sf->stype == REJ) ? "REJ" :
00117                 (sf->stype == RNR) ? "RNR" :
00118                 (sf->stype == SREJ) ? "SREJ" : "UNKN");
00119             
00120         // } else if (newtrace_) {
00121 //          sprintf(pt_->buffer() + offset,
00122 //              "-P hdlc -Psa %d -Pda %d -Pft S -Pr_seq %d -Pstype %s",
00123 //              hh->saddr(),
00124 //              hh->daddr(),
00125 //              sf->recv_seqno,
00126 //              sf->stype == RR ? "RR" :
00127 //              sf->stype == REJ ? "REJ" :
00128 //              sf->stype == RNR ? "RNR" :
00129 //              sf->stype == SREJ ? "SREJ" : "UNKN");
00130             
00131         } else {
00132             sprintf(pt_->buffer() + offset,
00133                 "[%d %d S %d %s]",
00134                 hh->saddr(),
00135                 hh->daddr(),
00136                 sf->recv_seqno,
00137                 sf->stype == RR ? "RR" :
00138                 sf->stype == REJ ? "REJ" :
00139                 sf->stype == RNR ? "RNR" :
00140                 sf->stype == SREJ ? "SREJ" :
00141                 "UNKN");
00142         }
00143         break;
00144         
00145     case HDLC_U_frame:
00146         if (pt_->tagged()) {
00147             sprintf(pt_->buffer() + offset,
00148                 "-hdlc:sa %d -hdlc:da %d -hdlc:ft U -hdlc:utype %s",
00149                 hh->saddr(),
00150                 hh->daddr(),
00151                 uf->utype == SABME ? "SABME" :
00152                 uf->utype == UA ? "UA" :
00153                 uf->utype == DM ? "DM" :
00154                 uf->utype == DISC ? "DISC" : "UNKN");
00155         
00156         // } else if (newtrace_) {
00157 //          sprintf(pt_->buffer() + offset,
00158 //              "-P hdlc -Psa %d -Pda %d -Pft U -Putype %s",
00159 //              hh->saddr(),
00160 //              hh->daddr(),
00161 //              uf->utype == SABME ? "SABME" :
00162 //              uf->utype == UA ? "UA" :
00163 //              uf->utype == DM ? "DM" :
00164 //              uf->utype == DISC ? "DISC" : "UNKN");
00165             
00166         } else {
00167             sprintf(pt_->buffer() + offset,
00168                 "[%d %d U %s]",
00169                 hh->saddr(),
00170                 hh->daddr(),
00171                 uf->utype == SABME ? "SABME" :
00172                 uf->utype == UA ? "UA" :
00173                 uf->utype == DM ? "DM" :
00174                 uf->utype == DISC ? "DISC" : "UNKN");
00175         }
00176         break;
00177         
00178     default:
00179         
00180         fprintf(stderr, "Unknown HDLC frame type\n");
00181         exit(1);
00182     }
00183     
00184 }
00185 
00186 
00187 
00188 void SatTrace::format(int tt, int s, int d, Packet* p)
00189 {
00190     int offset = 0;
00191     hdr_cmn *th = hdr_cmn::access(p);
00192     hdr_ip *iph = hdr_ip::access(p);
00193     hdr_tcp *tcph = hdr_tcp::access(p);
00194     hdr_sctp *sctph = hdr_sctp::access(p);
00195     hdr_rtp *rh = hdr_rtp::access(p);
00196     hdr_srm *sh = hdr_srm::access(p); 
00197 
00198     const char* sname = "null";
00199     int lasth, nexth, snadd;
00200     Node* n;
00201 
00202     packet_t t = th->ptype();
00203     const char* name = packet_info.name(t);
00204 
00205         /* SRM-specific */
00206     if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
00207             if ( sh->type() < 5 && sh->type() > 0 ) {
00208             sname = srm_names_[sh->type()];
00209         }
00210     }
00211 
00212     if (name == 0)
00213         abort();
00214 
00215     int seqno;
00216     /* UDP's now have seqno's too */
00217     if (t == PT_RTP || t == PT_CBR || t == PT_UDP || t == PT_EXP ||
00218         t == PT_PARETO)
00219         seqno = rh->seqno();
00220     else if (t == PT_TCP || t == PT_ACK || t == PT_HTTP || t == PT_FTP ||
00221         t == PT_TELNET)
00222         seqno = tcph->seqno();
00223     else
00224         seqno = -1;
00225         /* 
00226          * When new flags are added, make sure to change NUMFLAGS
00227          * in trace.h
00228          */
00229         char flags[NUMFLAGS+1];
00230         for (int i = 0; i < NUMFLAGS; i++)
00231         flags[i] = '-';
00232         flags[NUMFLAGS] = 0;
00233 
00234     hdr_flags* hf = hdr_flags::access(p);
00235     flags[0] = hf->ecn_ ? 'C' : '-';          // Ecn Echo
00236     flags[1] = hf->pri_ ? 'P' : '-'; 
00237     flags[2] = '-';
00238     flags[3] = hf->cong_action_ ? 'A' : '-';   // Congestion Action
00239     flags[4] = hf->ecn_to_echo_ ? 'E' : '-';   // Congestion Experienced
00240     flags[5] = hf->fs_ ? 'F' : '-';
00241     flags[6] = hf->ecn_capable_ ? 'N' : '-';
00242     flags[7] = 0; // only for SCTP
00243     
00244 #ifdef notdef
00245     flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
00246     flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
00247     flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
00248     flags[5] = 0;
00249 #endif
00250     char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
00251     char *src_portaddr = Address::instance().print_portaddr(iph->sport());
00252     char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
00253     char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
00254 
00255     // Find position of previous hop and next hop
00256     double s_lat = -999, s_lon = -999, d_lat = -999, d_lon = -999;
00257     n = Node::nodehead_.lh_first;
00258 // XXX what if n is not a SatNode?? Need a dynamic cast here, or make sure that
00259 // only sat tracing elements go between sat nodes.
00260     // SatNode *sn = dynamic_cast<SatNode*>(n);
00261     assert (n != 0);
00262     lasth = th->last_hop_;
00263     nexth = th->next_hop_;
00264     for (; n; n = n->nextnode() ) {
00265         SatNode *sn = (SatNode*) n;
00266         snadd = sn->address();
00267         if (lasth == snadd) {
00268             s_lat = RAD_TO_DEG(SatGeometry::get_latitude(sn->position()->coord()));
00269             s_lon = RAD_TO_DEG(SatGeometry::get_longitude(sn->position()->coord()));
00270             if (d_lat != -999) 
00271                 break; // Have now found both s and d
00272         }
00273         if (nexth == snadd) {
00274             d_lat = RAD_TO_DEG(SatGeometry::get_latitude(sn->position()->coord())); 
00275             d_lon = RAD_TO_DEG(SatGeometry::get_longitude(sn->position()->coord()));
00276             if (s_lat != -999) 
00277                 break; // Have now found both s and d
00278         }
00279     }
00280 
00281     if (show_sctphdr_ && t == PT_SCTP) {
00282        double timestamp;
00283        timestamp = Scheduler::instance().clock();
00284        
00285        for(unsigned int i = 0; i < sctph->NumChunks(); i++) {
00286            switch(sctph->SctpTrace()[i].eType) {
00287             case SCTP_CHUNK_INIT:
00288             case SCTP_CHUNK_INIT_ACK:
00289             case SCTP_CHUNK_COOKIE_ECHO:
00290             case SCTP_CHUNK_COOKIE_ACK:
00291                 flags[7] = 'I';              // connection initialization
00292                 break;
00293 
00294             case SCTP_CHUNK_DATA:
00295                 flags[7] = 'D';
00296                 break;
00297 
00298             case SCTP_CHUNK_SACK:
00299                 flags[7] = 'S';
00300                 break;
00301 
00302             case SCTP_CHUNK_FORWARD_TSN:
00303                 flags[7] = 'R';
00304                 break;
00305 
00306             case SCTP_CHUNK_HB:
00307                 flags[7] = 'H';
00308                 break;
00309 
00310             case SCTP_CHUNK_HB_ACK:
00311                 flags[7] = 'B';
00312                 break;
00313                 default:
00314                 assert (false);
00315                 break;
00316             }
00317            sprintf(pt_->buffer(), "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %d %d %d %.2f %.2f %.2f %.2f",
00318             tt,
00319             pt_->round(Scheduler::instance().clock()),
00320             lasth,
00321             nexth,
00322             name,
00323             th->size(),
00324             flags,
00325             iph->flowid() /* was p->class_ */,
00326             // iph->src() >> (Address::instance().NodeShift_[1]), 
00327                         // iph->src() & (Address::instance().PortMask_), 
00328                         // iph->dst() >> (Address::instance().NodeShift_[1]), 
00329                         // iph->dst() & (Address::instance().PortMask_),
00330             src_nodeaddr,
00331             src_portaddr,
00332             dst_nodeaddr,
00333             dst_portaddr,
00334             sctph->NumChunks(),
00335             sctph->SctpTrace()[i].uiTsn,
00336             th->uid(), /* was p->uid_ */
00337             sctph->SctpTrace()[i].usStreamId,
00338             sctph->SctpTrace()[i].usStreamSeqNum,
00339             s_lat,
00340             s_lon,
00341             d_lat,
00342             d_lon);
00343 
00344            /* The caller already calls pt_->dump() for us, but
00345             * since SCTP needs to dump once per chunk, we call
00346             * dump ourselves for all but the last * chunk.  
00347             */
00348            if(i < sctph->NumChunks() - 1)
00349                pt_->dump();
00350         }
00351     }
00352     else if (pt_->tagged()) {
00353         sprintf(pt_->nbuffer(), 
00354             "%c %g -s %d -d %d -p %s -e %d -c %d -i %d -a %d -x {%s.%s %s.%s %d %s %s}",
00355             tt,
00356             Scheduler::instance().clock(),
00357             s,
00358             d,
00359             name,
00360             th->size(),
00361             iph->flowid(),
00362             th->uid(),
00363             iph->flowid(),
00364             src_nodeaddr,
00365             src_portaddr,
00366             dst_nodeaddr,
00367             dst_portaddr,
00368             seqno,flags,sname);
00369     } else if (!show_tcphdr_) {
00370         sprintf(pt_->buffer(), "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %.2f %.2f %.2f %.2f",
00371             tt,
00372             pt_->round(Scheduler::instance().clock()),
00373             lasth,
00374             nexth,
00375             name,
00376             th->size(),
00377             flags,
00378             iph->flowid() /* was p->class_ */,
00379             // iph->src() >> (Address::instance().NodeShift_[1]), 
00380                         // iph->src() & (Address::instance().PortMask_), 
00381                         // iph->dst() >> (Address::instance().NodeShift_[1]), 
00382                         // iph->dst() & (Address::instance().PortMask_),
00383             src_nodeaddr,
00384             src_portaddr,
00385             dst_nodeaddr,
00386             dst_portaddr,
00387             seqno,
00388             th->uid(), /* was p->uid_ */
00389             s_lat,
00390             s_lon,
00391             d_lat,
00392             d_lon);
00393     } else {
00394         sprintf(pt_->buffer(), 
00395             "%c %.4f %d %d %s %d %s %d %s.%s %s.%s %d %d %d 0x%x %d %d %.2f %.2f %.2f %.2f",
00396             tt,
00397             pt_->round(Scheduler::instance().clock()),
00398             lasth,
00399             nexth,
00400             name,
00401             th->size(),
00402             flags,
00403             iph->flowid(), /* was p->class_ */
00404                 // iph->src() >> (Address::instance().NodeShift_[1]), 
00405             // iph->src() & (Address::instance().PortMask_), 
00406                 // iph->dst() >> (Address::instance().NodeShift_[1]), 
00407                 // iph->dst() & (Address::instance().PortMask_),
00408             src_nodeaddr,
00409             src_portaddr,
00410             dst_nodeaddr,
00411             dst_portaddr,
00412             seqno,
00413             th->uid(), /* was p->uid_ */
00414             tcph->ackno(),
00415             tcph->flags(),
00416             tcph->hlen(),
00417             tcph->sa_length(),
00418             s_lat,
00419             s_lon,
00420             d_lat,
00421             d_lon);
00422     }
00423 
00424     offset = strlen(pt_->buffer());
00425     if (t == PT_HDLC)
00426         format_hdlc(p, offset);
00427     
00428 
00429     if (pt_->namchannel() != 0)
00430         sprintf(pt_->nbuffer(), 
00431             "%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}",
00432             tt,
00433             Scheduler::instance().clock(),
00434             s,
00435             d,
00436             name,
00437             th->size(),
00438             iph->flowid(),
00439             th->uid(),
00440             iph->flowid(),
00441             src_nodeaddr,
00442             src_portaddr,
00443             dst_nodeaddr,
00444             dst_portaddr,
00445             seqno,flags,sname);
00446     delete [] src_nodeaddr;
00447     delete [] src_portaddr;
00448     delete [] dst_nodeaddr;
00449     delete [] dst_portaddr;
00450 }
00451 
00452 void SatTrace::traceonly(Packet* p)
00453 {        
00454     format(type_, src_, dst_, p);
00455     pt_->dump();
00456 }
00457 
00458 //
00459 // we need a DequeTraceClass here because a 'h' event need to go together
00460 // with the '-' event. It's possible to use a postprocessing script, but 
00461 // seems that's inconvient.
00462 //
00463 static class SatDequeTraceClass : public TclClass {
00464 public:
00465     SatDequeTraceClass() : TclClass("Trace/Sat/Deque") { }
00466     TclObject* create(int args, const char*const* argv) {
00467         if (args >= 5)
00468             return (new SatDequeTrace(*argv[4]));
00469         return NULL;
00470     }
00471 } sat_dequetrace_class;
00472 
00473 
00474 void 
00475 SatDequeTrace::recv(Packet* p, Handler* h)
00476 {
00477     // write the '-' event first
00478     format(type_, src_, dst_, p);
00479     pt_->dump();
00480     pt_->namdump();
00481 
00482     if (pt_->namchannel() != 0) {
00483         hdr_cmn *th = hdr_cmn::access(p);
00484         hdr_ip *iph = hdr_ip::access(p);
00485         hdr_srm *sh = hdr_srm::access(p);
00486         const char* sname = "null";   
00487 
00488         packet_t t = th->ptype();
00489         const char* name = packet_info.name(t);
00490         
00491         if (strcmp(name,"SRM") == 0 || strcmp(name,"cbr") == 0 || strcmp(name,"udp") == 0) {
00492             if ( sh->type() < 5 && sh->type() > 0  ) {
00493                 sname = srm_names_[sh->type()];
00494             }
00495         }   
00496 
00497         char *src_nodeaddr = Address::instance().print_nodeaddr(iph->saddr());
00498         char *src_portaddr = Address::instance().print_portaddr(iph->sport());
00499         char *dst_nodeaddr = Address::instance().print_nodeaddr(iph->daddr());
00500         char *dst_portaddr = Address::instance().print_portaddr(iph->dport());
00501 
00502         char flags[NUMFLAGS+1];
00503         for (int i = 0; i < NUMFLAGS; i++)
00504             flags[i] = '-';
00505         flags[NUMFLAGS] = 0;
00506 
00507         hdr_flags* hf = hdr_flags::access(p);
00508         flags[0] = hf->ecn_ ? 'C' : '-';          // Ecn Echo
00509         flags[1] = hf->pri_ ? 'P' : '-'; 
00510         flags[2] = '-';
00511         flags[3] = hf->cong_action_ ? 'A' : '-';   // Congestion Action
00512         flags[4] = hf->ecn_to_echo_ ? 'E' : '-';   // Congestion Experienced
00513         flags[5] = hf->fs_ ? 'F' : '-';
00514         flags[6] = hf->ecn_capable_ ? 'N' : '-';
00515     
00516 #ifdef notdef
00517         flags[1] = (iph->flags() & PF_PRI) ? 'P' : '-';
00518         flags[2] = (iph->flags() & PF_USR1) ? '1' : '-';
00519         flags[3] = (iph->flags() & PF_USR2) ? '2' : '-';
00520         flags[5] = 0;
00521 #endif
00522         
00523         sprintf(pt_->nbuffer(), 
00524             "%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}",
00525             'h',
00526             Scheduler::instance().clock(),
00527             src_,
00528             dst_,
00529             name,
00530             th->size(),
00531             iph->flowid(),
00532             th->uid(),
00533             iph->flowid(),
00534             src_nodeaddr,
00535             src_portaddr,
00536             dst_nodeaddr,
00537             dst_portaddr,
00538             -1, flags, sname);
00539         pt_->namdump();
00540         delete [] src_nodeaddr;
00541         delete [] src_portaddr;
00542         delete [] dst_nodeaddr;
00543         delete [] dst_portaddr;
00544     }
00545 
00546     /* hack: if trace object not attached to anything free packet */
00547     if (target_ == 0)
00548         Packet::free(p);
00549     else
00550         send(p, h);
00551 }

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