apps/ping.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * ping.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: ping.cc,v 1.8 2005/08/25 18:58:01 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 // $Header: /nfs/jade/vint/CVSROOT/ns-2/apps/ping.cc,v 1.8 2005/08/25 18:58:01 johnh Exp $
00048 
00049 /*
00050  * File: Code for a new 'Ping' Agent Class for the ns
00051  *       network simulator
00052  * Author: Marc Greis (greis@cs.uni-bonn.de), May 1998
00053  *
00054  * IMPORTANT: Incase of any changes made to this file , 
00055  * tutorial/examples/ping.cc file (used in Greis' tutorial) should
00056  * be updated as well.
00057  */
00058 
00059 #include "ping.h"
00060 
00061 int hdr_ping::offset_;
00062 static class PingHeaderClass : public PacketHeaderClass {
00063 public:
00064     PingHeaderClass() : PacketHeaderClass("PacketHeader/Ping", 
00065                           sizeof(hdr_ping)) {
00066         bind_offset(&hdr_ping::offset_);
00067     }
00068 } class_pinghdr;
00069 
00070 
00071 static class PingClass : public TclClass {
00072 public:
00073     PingClass() : TclClass("Agent/Ping") {}
00074     TclObject* create(int, const char*const*) {
00075         return (new PingAgent());
00076     }
00077 } class_ping;
00078 
00079 
00080 PingAgent::PingAgent() : Agent(PT_PING), seq(0), oneway(0)
00081 {
00082     bind("packetSize_", &size_);
00083 }
00084 
00085 int PingAgent::command(int argc, const char*const* argv)
00086 {
00087   if (argc == 2) {
00088     if (strcmp(argv[1], "send") == 0) {
00089       // Create a new packet
00090       Packet* pkt = allocpkt();
00091       // Access the Ping header for the new packet:
00092       hdr_ping* hdr = hdr_ping::access(pkt);
00093       // Set the 'ret' field to 0, so the receiving node
00094       // knows that it has to generate an echo packet
00095       hdr->ret = 0;
00096       hdr->seq = seq++;
00097       // Store the current time in the 'send_time' field
00098       hdr->send_time = Scheduler::instance().clock();
00099       // Send the packet
00100       send(pkt, 0);
00101       // return TCL_OK, so the calling function knows that
00102       // the command has been processed
00103       return (TCL_OK);
00104     
00105     }
00106     
00107     else if (strcmp(argv[1], "start-WL-brdcast") == 0) {
00108       Packet* pkt = allocpkt();
00109       
00110       hdr_ip* iph = HDR_IP(pkt);
00111       hdr_ping* ph = hdr_ping::access(pkt);
00112       
00113       iph->daddr() = IP_BROADCAST;
00114       iph->dport() = iph->sport();
00115       ph->ret = 0;
00116       send(pkt, (Handler*) 0);
00117       return (TCL_OK);
00118     }
00119 
00120     else if (strcmp(argv[1], "oneway") == 0) {
00121       oneway=1;
00122       return (TCL_OK);
00123     }
00124   }
00125   
00126   // If the command hasn't been processed by PingAgent()::command,
00127   // call the command() function for the base class
00128   return (Agent::command(argc, argv));
00129 }
00130 
00131 
00132 void PingAgent::recv(Packet* pkt, Handler*)
00133 {
00134   // Access the IP header for the received packet:
00135   hdr_ip* hdrip = hdr_ip::access(pkt);
00136   
00137   // Access the Ping header for the received packet:
00138   hdr_ping* hdr = hdr_ping::access(pkt);
00139   
00140 
00141   // check if in brdcast mode
00142   if ((u_int32_t)hdrip->daddr() == IP_BROADCAST) {
00143     if (hdr->ret == 0) {
00144       
00145       printf("Recv BRDCAST Ping REQ : at %d.%d from %d.%d\n", here_.addr_, here_.port_, hdrip->saddr(), hdrip->sport());
00146       Packet::free(pkt);
00147       
00148       // create reply
00149       Packet* pktret = allocpkt();
00150 
00151       hdr_ping* hdrret = hdr_ping::access(pktret);
00152       hdr_ip* ipret = hdr_ip::access(pktret);
00153       
00154       hdrret->ret = 1;
00155       
00156       // add brdcast address
00157       ipret->daddr() = IP_BROADCAST;
00158       ipret->dport() = ipret->sport();
00159 
00160       send(pktret, 0);
00161     
00162     } else {
00163       printf("Recv BRDCAST Ping REPLY : at %d.%d from %d.%d\n", here_.addr_, here_.port_, hdrip->saddr(), hdrip->sport());
00164       Packet::free(pkt);
00165     }
00166     return;
00167   }
00168   // Is the 'ret' field = 0 (i.e. the receiving node is being pinged)?
00169   if (hdr->ret == 0) {
00170     // Send an 'echo'. First save the old packet's send_time
00171     double stime = hdr->send_time;
00172     int rcv_seq = hdr->seq;
00173     // Discard the packet
00174     Packet::free(pkt);
00175     // Create a new packet
00176     Packet* pktret = allocpkt();
00177     // Access the Ping header for the new packet:
00178     hdr_ping* hdrret = hdr_ping::access(pktret);
00179     // Set the 'ret' field to 1, so the receiver won't send
00180     // another echo
00181     hdrret->ret = 1;
00182     // Set the send_time field to the correct value
00183     hdrret->send_time = stime;
00184     // Added by Andrei Gurtov for one-way delay measurement.
00185     hdrret->rcv_time = Scheduler::instance().clock();
00186     hdrret->seq = rcv_seq;
00187     // Send the packet
00188     send(pktret, 0);
00189   } else {
00190     // A packet was received. Use tcl.eval to call the Tcl
00191     // interpreter with the ping results.
00192     // Note: In the Tcl code, a procedure
00193     // 'Agent/Ping recv {from rtt}' has to be defined which
00194     // allows the user to react to the ping result.
00195     char out[100];
00196     // Prepare the output to the Tcl interpreter. Calculate the
00197     // round trip time
00198     if (oneway) //AG
00199         sprintf(out, "%s recv %d %d %3.1f %3.1f", name(), 
00200         hdrip->src_.addr_ >> Address::instance().NodeShift_[1],
00201         hdr->seq, (hdr->rcv_time - hdr->send_time) * 1000,
00202         (Scheduler::instance().clock()-hdr->rcv_time) * 1000);
00203     else sprintf(out, "%s recv %d %3.1f", name(), 
00204         hdrip->src_.addr_ >> Address::instance().NodeShift_[1],
00205         (Scheduler::instance().clock()-hdr->send_time) * 1000);
00206     Tcl& tcl = Tcl::instance();
00207     tcl.eval(out);
00208     // Discard the packet
00209     Packet::free(pkt);
00210   }
00211 }
00212 
00213 

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