00001 #include "v4ping.h"
00002 #include "ns3/icmpv4.h"
00003 #include "ns3/assert.h"
00004 #include "ns3/log.h"
00005 #include "ns3/ipv4-address.h"
00006 #include "ns3/socket.h"
00007 #include "ns3/uinteger.h"
00008 #include "ns3/inet-socket-address.h"
00009 #include "ns3/packet.h"
00010 #include "ns3/trace-source-accessor.h"
00011 #include "ns3/simulator.h"
00012
00013 namespace ns3 {
00014
00015 NS_LOG_COMPONENT_DEFINE ("V4Ping");
00016 NS_OBJECT_ENSURE_REGISTERED (V4Ping);
00017
00018 TypeId
00019 V4Ping::GetTypeId (void)
00020 {
00021 static TypeId tid = TypeId ("ns3::V4Ping")
00022 .SetParent<Application> ()
00023 .AddConstructor<V4Ping> ()
00024 .AddAttribute ("Remote",
00025 "The address of the machine we want to ping.",
00026 Ipv4AddressValue (),
00027 MakeIpv4AddressAccessor (&V4Ping::m_remote),
00028 MakeIpv4AddressChecker ())
00029 .AddTraceSource ("Rtt",
00030 "The rtt calculated by the ping.",
00031 MakeTraceSourceAccessor (&V4Ping::m_traceRtt));
00032 ;
00033 return tid;
00034 }
00035
00036 V4Ping::V4Ping ()
00037 : m_socket (0),
00038 m_seq (0)
00039 {}
00040 V4Ping::~V4Ping ()
00041 {}
00042
00043 void
00044 V4Ping::DoDispose (void)
00045 {
00046 NS_LOG_FUNCTION (this);
00047 m_socket = 0;
00048 Application::DoDispose ();
00049 }
00050
00051 uint32_t
00052 V4Ping::GetApplicationId (void) const
00053 {
00054 Ptr<Node> node = GetNode ();
00055 for (uint32_t i = 0; i < node->GetNApplications (); ++i)
00056 {
00057 if (node->GetApplication (i) == this)
00058 {
00059 return i;
00060 }
00061 }
00062 NS_ASSERT_MSG (false, "forgot to add application to node");
00063 return 0;
00064 }
00065
00066 void
00067 V4Ping::Receive (Ptr<Socket> socket)
00068 {
00069 NS_LOG_FUNCTION (this << socket);
00070 while (m_socket->GetRxAvailable () > 0)
00071 {
00072 Address from;
00073 Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
00074 NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
00075 NS_ASSERT (InetSocketAddress::IsMatchingType (from));
00076 InetSocketAddress realFrom = InetSocketAddress::ConvertFrom (from);
00077 NS_ASSERT (realFrom.GetPort () == 1);
00078 Ipv4Header ipv4;
00079 p->RemoveHeader (ipv4);
00080 NS_ASSERT (ipv4.GetProtocol () == 1);
00081 Icmpv4Header icmp;
00082 p->RemoveHeader (icmp);
00083 if (icmp.GetType () == Icmpv4Header::ECHO_REPLY)
00084 {
00085 Icmpv4Echo echo;
00086 p->RemoveHeader (echo);
00087 if (echo.GetSequenceNumber () == (m_seq - 1) &&
00088 echo.GetIdentifier () == 0)
00089 {
00090 Ptr<const Packet> data = echo.GetData ();
00091 if (data->GetSize () == 16)
00092 {
00093 uint32_t *buf = (uint32_t *)data->PeekData ();
00094 if (buf[0] == GetNode ()->GetId () &&
00095 buf[1] == GetApplicationId ())
00096 {
00097 int64_t ts = buf[3];
00098 ts <<= 32;
00099 ts |= buf[2];
00100 Time sendTime = TimeStep (ts);
00101 NS_ASSERT (Simulator::Now () > sendTime);
00102 Time delta = Simulator::Now () - sendTime;
00103 m_traceRtt (delta);
00104 }
00105 }
00106 }
00107 }
00108 }
00109 }
00110
00111 void
00112 V4Ping::Write32 (uint8_t *buffer, uint32_t data)
00113 {
00114 buffer[0] = (data >> 0) & 0xff;
00115 buffer[1] = (data >> 8) & 0xff;
00116 buffer[2] = (data >> 16) & 0xff;
00117 buffer[3] = (data >> 24) & 0xff;
00118 }
00119
00120 void
00121 V4Ping::StartApplication (void)
00122 {
00123 NS_LOG_FUNCTION (this);
00124 m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
00125 NS_ASSERT (m_socket != 0);
00126 m_socket->SetAttribute ("Protocol", UintegerValue (1));
00127 m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this));
00128 InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
00129 int status;
00130 status = m_socket->Bind (src);
00131 NS_ASSERT (status != -1);
00132 InetSocketAddress dst = InetSocketAddress (m_remote, 0);
00133 status = m_socket->Connect (dst);
00134 NS_ASSERT (status != -1);
00135 Ptr<Packet> p = Create<Packet> ();
00136 Icmpv4Echo echo;
00137 echo.SetSequenceNumber (m_seq);
00138 m_seq++;
00139 echo.SetIdentifier (0);
00140
00141
00142
00143
00144
00145
00146
00147 uint8_t data[4 * sizeof(uint32_t)];
00148 uint32_t tmp = GetNode ()->GetId ();
00149 Write32 (&data[0 * sizeof(uint32_t)], tmp);
00150
00151 tmp = GetApplicationId ();
00152 Write32 (&data[1 * sizeof(uint32_t)], tmp);
00153
00154 int64_t now = Simulator::Now ().GetTimeStep ();
00155 tmp = now & 0xffffffff;
00156 Write32 (&data[2 * sizeof(uint32_t)], tmp);
00157
00158 now >>= 32;
00159 tmp = now & 0xffffffff;
00160 Write32 (&data[3 * sizeof(uint32_t)], tmp);
00161
00162 Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) &data, 16);
00163 echo.SetData (dataPacket);
00164 p->AddHeader (echo);
00165 Icmpv4Header header;
00166 header.SetType (Icmpv4Header::ECHO);
00167 header.SetCode (0);
00168 p->AddHeader (header);
00169 m_socket->Send (p, 0);
00170
00171 }
00172 void
00173 V4Ping::StopApplication (void)
00174 {
00175 NS_LOG_FUNCTION (this);
00176 m_socket->Close ();
00177 }
00178
00179
00180 }