A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ping6.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/nstime.h"
23 #include "ns3/simulator.h"
24 #include "ns3/socket-factory.h"
25 #include "ns3/packet.h"
26 #include "ns3/socket.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/ipv6.h"
29 #include "ns3/ipv6-address.h"
30 #include "ns3/inet6-socket-address.h"
31 #include "ns3/icmpv6-header.h"
32 #include "ns3/ipv6-raw-socket-factory.h"
33 #include "ns3/ipv6-header.h"
34 #include "ns3/ipv6-extension-header.h"
35 
36 #include "ping6.h"
37 
38 namespace ns3
39 {
40 
41 NS_LOG_COMPONENT_DEFINE ("Ping6Application");
42 
44 
46 {
47  static TypeId tid = TypeId ("ns3::Ping6")
49  .AddConstructor<Ping6>()
50  .AddAttribute ("MaxPackets",
51  "The maximum number of packets the application will send",
52  UintegerValue (100),
53  MakeUintegerAccessor (&Ping6::m_count),
54  MakeUintegerChecker<uint32_t>())
55  .AddAttribute ("Interval",
56  "The time to wait between packets",
57  TimeValue (Seconds (1.0)),
58  MakeTimeAccessor (&Ping6::m_interval),
59  MakeTimeChecker ())
60  .AddAttribute ("RemoteIpv6",
61  "The Ipv6Address of the outbound packets",
63  MakeIpv6AddressAccessor (&Ping6::m_peerAddress),
64  MakeIpv6AddressChecker ())
65  .AddAttribute ("LocalIpv6",
66  "Local Ipv6Address of the sender",
68  MakeIpv6AddressAccessor (&Ping6::m_localAddress),
69  MakeIpv6AddressChecker ())
70  .AddAttribute ("PacketSize",
71  "Size of packets generated",
72  UintegerValue (100),
73  MakeUintegerAccessor (&Ping6::m_size),
74  MakeUintegerChecker<uint32_t>())
75  ;
76  return tid;
77 }
78 
80 {
82  m_sent = 0;
83  m_socket = 0;
84  m_seq = 0;
85  m_sendEvent = EventId ();
86 }
87 
89 {
91  m_socket = 0;
92 }
93 
95 {
98 }
99 
101 {
103 
104  if (!m_socket)
105  {
106  TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
108 
110 
115  }
116 
117  ScheduleTransmit (Seconds (0.));
118 }
119 
121 {
122  NS_LOG_FUNCTION (this << ipv6);
123  m_localAddress = ipv6;
124 }
125 
127 {
128  NS_LOG_FUNCTION (this << ipv6);
129  m_peerAddress = ipv6;
130 }
131 
133 {
135 
136  if (m_socket)
137  {
139  }
140 
142 }
143 
144 void Ping6::SetIfIndex (uint32_t ifIndex)
145 {
146  m_ifIndex = ifIndex;
147 }
148 
150 {
151  NS_LOG_FUNCTION (this << dt);
153 }
154 
155 void Ping6::SetRouters (std::vector<Ipv6Address> routers)
156 {
157  m_routers = routers;
158 }
159 
160 void Ping6::Send ()
161 {
164  Ptr<Packet> p = 0;
165  uint8_t* data = new uint8_t[m_size];
166  Ipv6Address src;
167  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
168 
169  if (m_ifIndex > 0)
170  {
171  /* hack to have ifIndex in Ipv6RawSocketImpl
172  * maybe add a SetIfIndex in Ipv6RawSocketImpl directly
173  */
174  src = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, 0).GetAddress ();
175  }
176  else
177  {
178  src = m_localAddress;
179  }
180 
181  NS_ASSERT_MSG (m_size >= 4, "ICMPv6 echo request payload size must be >= 4");
182  data[0] = 0xDE;
183  data[1] = 0xAD;
184  data[2] = 0xBE;
185  data[3] = 0xEF;
186 
187  p = Create<Packet> (data, 4);
188  p->AddAtEnd (Create<Packet> (m_size - 4));
189  Icmpv6Echo req (1);
190 
191  req.SetId (0xBEEF);
192  req.SetSeq (m_seq);
193  m_seq++;
194 
195  /* we do not calculate pseudo header checksum here, because we are not sure about
196  * source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl.
197  */
198 
199  p->AddHeader (req);
200  m_socket->Bind (Inet6SocketAddress (src, 0));
201 
202  /* use Loose Routing (routing type 0) */
203  if (m_routers.size ())
204  {
205  Ipv6ExtensionLooseRoutingHeader routingHeader;
206  routingHeader.SetNextHeader (Ipv6Header::IPV6_ICMPV6);
207  routingHeader.SetLength (m_routers.size () * 16 + 8);
208  routingHeader.SetTypeRouting (0);
209  routingHeader.SetSegmentsLeft (m_routers.size ());
210  routingHeader.SetRoutersAddress (m_routers);
211  p->AddHeader (routingHeader);
213  }
214 
215  m_socket->Send (p, 0);
216  ++m_sent;
217 
218  NS_LOG_INFO ("Sent " << p->GetSize () << " bytes to " << m_peerAddress);
219 
220  if (m_sent < m_count)
221  {
223  }
224 
225  delete[] data;
226 }
227 
229 {
230  NS_LOG_FUNCTION (this << socket);
231 
232  Ptr<Packet> packet=0;
233  Address from;
234  while ((packet = socket->RecvFrom (from)))
235  {
237  {
238  Ipv6Header hdr;
239  Icmpv6Echo reply (0);
241 
242  packet->RemoveHeader (hdr);
243 
244  uint8_t type;
245  packet->CopyData (&type, sizeof(type));
246 
247  switch (type)
248  {
250  packet->RemoveHeader (reply);
251 
252  NS_LOG_INFO ("Received Echo Reply size = " << std::dec << packet->GetSize () << " bytes from " << address.GetIpv6 () << " id = " << (uint16_t)reply.GetId () << " seq = " << (uint16_t)reply.GetSeq ());
253  break;
254  default:
255  /* other type, discard */
256  break;
257  }
258  }
259  }
260 }
261 
262 } /* namespace ns3 */
263