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  */
175  for (uint32_t i = 0; i < GetNode ()->GetObject<Ipv6> ()->GetNAddresses (m_ifIndex); i++)
176  {
177  src = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, i).GetAddress ();
178  Ipv6InterfaceAddress srcIa (src);
179  if ( srcIa.GetScope() == dstIa.GetScope() )
180  {
181  break;
182  }
183  }
184  }
185  else
186  {
187  src = m_localAddress;
188  }
189 
190  NS_ASSERT_MSG (m_size >= 4, "ICMPv6 echo request payload size must be >= 4");
191  data[0] = 0xDE;
192  data[1] = 0xAD;
193  data[2] = 0xBE;
194  data[3] = 0xEF;
195 
196  p = Create<Packet> (data, 4);
197  p->AddAtEnd (Create<Packet> (m_size - 4));
198  Icmpv6Echo req (1);
199 
200  req.SetId (0xBEEF);
201  req.SetSeq (m_seq);
202  m_seq++;
203 
204  /* we do not calculate pseudo header checksum here, because we are not sure about
205  * source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl.
206  */
207 
208  p->AddHeader (req);
209  m_socket->Bind (Inet6SocketAddress (src, 0));
210 
211  /* use Loose Routing (routing type 0) */
212  if (m_routers.size ())
213  {
214  Ipv6ExtensionLooseRoutingHeader routingHeader;
215  routingHeader.SetNextHeader (Ipv6Header::IPV6_ICMPV6);
216  routingHeader.SetLength (m_routers.size () * 16 + 8);
217  routingHeader.SetTypeRouting (0);
218  routingHeader.SetSegmentsLeft (m_routers.size ());
219  routingHeader.SetRoutersAddress (m_routers);
220  p->AddHeader (routingHeader);
222  }
223 
224  m_socket->Send (p, 0);
225  ++m_sent;
226 
227  NS_LOG_INFO ("Sent " << p->GetSize () << " bytes to " << m_peerAddress);
228 
229  if (m_sent < m_count)
230  {
232  }
233 
234  delete[] data;
235 }
236 
238 {
239  NS_LOG_FUNCTION (this << socket);
240 
241  Ptr<Packet> packet=0;
242  Address from;
243  while ((packet = socket->RecvFrom (from)))
244  {
246  {
247  Ipv6Header hdr;
248  Icmpv6Echo reply (0);
250 
251  packet->RemoveHeader (hdr);
252 
253  uint8_t type;
254  packet->CopyData (&type, sizeof(type));
255 
256  switch (type)
257  {
259  packet->RemoveHeader (reply);
260 
261  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 ());
262  break;
263  default:
264  /* other type, discard */
265  break;
266  }
267  }
268  }
269 }
270 
271 } /* namespace ns3 */
272