A Discrete-Event Network Simulator
API
ping6.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009 Strasbourg University
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18  */
19 
20 #include "ping6.h"
21 
22 #include "ns3/icmpv6-header.h"
23 #include "ns3/inet6-socket-address.h"
24 #include "ns3/ipv6-extension-header.h"
25 #include "ns3/ipv6-header.h"
26 #include "ns3/ipv6-raw-socket-factory.h"
27 #include "ns3/log.h"
28 #include "ns3/nstime.h"
29 #include "ns3/packet.h"
30 #include "ns3/simulator.h"
31 #include "ns3/socket-factory.h"
32 #include "ns3/socket.h"
33 #include "ns3/uinteger.h"
34 
35 namespace ns3
36 {
37 
38 NS_LOG_COMPONENT_DEFINE("Ping6Application");
39 
41 
42 TypeId
43 Ping6::GetTypeId()
44 {
45  static TypeId tid =
46  TypeId("ns3::Ping6")
47  .SetParent<Application>()
48  .SetGroupName("Internet-Apps")
49  .AddConstructor<Ping6>()
50  .AddAttribute(
51  "MaxPackets",
52  "The maximum number of packets the application will send (zero means infinite)",
53  UintegerValue(100),
54  MakeUintegerAccessor(&Ping6::m_count),
55  MakeUintegerChecker<uint32_t>())
56  .AddAttribute("Interval",
57  "The time to wait between packets",
58  TimeValue(Seconds(1.0)),
59  MakeTimeAccessor(&Ping6::m_interval),
61  .AddAttribute("RemoteIpv6",
62  "The Ipv6Address of the outbound packets",
64  MakeIpv6AddressAccessor(&Ping6::m_peerAddress),
65  MakeIpv6AddressChecker())
66  .AddAttribute("LocalIpv6",
67  "Local Ipv6Address of the sender",
69  MakeIpv6AddressAccessor(&Ping6::m_localAddress),
70  MakeIpv6AddressChecker())
71  .AddAttribute("PacketSize",
72  "Size of packets generated",
73  UintegerValue(100),
74  MakeUintegerAccessor(&Ping6::m_size),
75  MakeUintegerChecker<uint32_t>());
76  return tid;
77 }
78 
79 Ping6::Ping6()
80 {
81  NS_LOG_FUNCTION(this);
82  m_sent = 0;
83  m_socket = nullptr;
84  m_seq = 0;
85  m_ipInterfaceIndex = 0;
86  m_ifIndex = 0;
87  m_sendEvent = EventId();
88 }
89 
90 Ping6::~Ping6()
91 {
92  NS_LOG_FUNCTION(this);
93  m_socket = nullptr;
94 }
95 
96 void
97 Ping6::DoDispose()
98 {
99  NS_LOG_FUNCTION(this);
101 }
102 
103 void
104 Ping6::StartApplication()
105 {
106  NS_LOG_FUNCTION(this);
107 
108  if (!m_socket)
109  {
110  TypeId tid = TypeId::LookupByName("ns3::Ipv6RawSocketFactory");
111  m_socket = Socket::CreateSocket(GetNode(), tid);
112 
113  NS_ASSERT(m_socket);
114 
115  m_socket->Bind(Inet6SocketAddress(m_localAddress, 0));
116  m_socket->SetAttribute("Protocol", UintegerValue(Ipv6Header::IPV6_ICMPV6));
117  m_socket->SetRecvCallback(MakeCallback(&Ping6::HandleRead, this));
118  m_ipv6Protocol = m_node->GetObject<Ipv6L3Protocol>();
119 
120  if (!m_localAddress.IsAny())
121  {
122  m_ipInterfaceIndex = m_ipv6Protocol->GetInterfaceForAddress(m_localAddress);
123  }
124  }
125 
126  ScheduleTransmit(Seconds(0.));
127 }
128 
129 void
130 Ping6::SetLocal(Ipv6Address ipv6)
131 {
132  NS_LOG_FUNCTION(this << ipv6);
133  m_localAddress = ipv6;
134 }
135 
136 void
137 Ping6::SetRemote(Ipv6Address ipv6)
138 {
139  NS_LOG_FUNCTION(this << ipv6);
140  m_peerAddress = ipv6;
141 }
142 
143 void
144 Ping6::StopApplication()
145 {
146  NS_LOG_FUNCTION(this);
147 
148  if (m_socket)
149  {
150  m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
151  }
152 
153  Simulator::Cancel(m_sendEvent);
154 }
155 
156 void
157 Ping6::SetIfIndex(uint32_t ifIndex)
158 {
159  m_ifIndex = ifIndex;
160 }
161 
162 void
163 Ping6::ScheduleTransmit(Time dt)
164 {
165  NS_LOG_FUNCTION(this << dt);
166  m_sendEvent = Simulator::Schedule(dt, &Ping6::Send, this);
167 }
168 
169 void
170 Ping6::SetRouters(std::vector<Ipv6Address> routers)
171 {
172  m_routers = routers;
173 }
174 
175 void
176 Ping6::Send()
177 {
178  NS_LOG_FUNCTION(this);
179  NS_ASSERT(m_sendEvent.IsExpired());
180 
181  Ipv6Address src;
182  Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
183 
184  if (m_ifIndex > 0)
185  {
186  /* hack to have ifIndex in Ipv6RawSocketImpl
187  * maybe add a SetIfIndex in Ipv6RawSocketImpl directly
188  */
189  for (uint32_t i = 0; i < GetNode()->GetObject<Ipv6>()->GetNAddresses(m_ifIndex); i++)
190  {
191  Ipv6InterfaceAddress srcIa;
192  srcIa = GetNode()->GetObject<Ipv6>()->GetAddress(m_ifIndex, i);
193 
194  if (srcIa.IsInSameSubnet(m_peerAddress))
195  {
196  src = srcIa.GetAddress();
197  break;
198  }
199  }
200  }
201  else
202  {
203  src = m_localAddress;
204  }
205 
206  uint32_t size = m_size;
207  if (m_size < 4)
208  {
209  NS_LOG_WARN("ICMPv6 echo request payload size must be >= 4");
210  size = 4;
211  }
212 
213  uint8_t* data = new uint8_t[size];
214  memset(data, 0, size);
215  data[0] = 0xDE;
216  data[1] = 0xAD;
217  data[2] = 0xBE;
218  data[3] = 0xEF;
219 
220  Ptr<Packet> p = Create<Packet>(data, size);
221  Icmpv6Echo req(1);
222 
223  req.SetId(0xBEEF);
224  req.SetSeq(m_seq);
225  m_seq++;
226 
227  /* we do not calculate pseudo header checksum here, because we are not sure about
228  * source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl.
229  */
230 
231  p->AddHeader(req);
232  m_socket->Bind(Inet6SocketAddress(src, 0));
233 
234  /* use Loose Routing (routing type 0) */
235  if (!m_routers.empty())
236  {
237  Ipv6ExtensionLooseRoutingHeader routingHeader;
238  routingHeader.SetNextHeader(Ipv6Header::IPV6_ICMPV6);
239  routingHeader.SetTypeRouting(0);
240  routingHeader.SetSegmentsLeft(m_routers.size());
241  routingHeader.SetRoutersAddress(m_routers);
242  p->AddHeader(routingHeader);
243  m_socket->SetAttribute("Protocol", UintegerValue(Ipv6Header::IPV6_EXT_ROUTING));
244  }
245 
246  m_socket->SendTo(p, 0, Inet6SocketAddress(m_peerAddress, 0));
247  ++m_sent;
248 
249  NS_LOG_INFO("Sent " << p->GetSize() << " bytes to " << m_peerAddress);
250 
251  if (m_sent < m_count || m_count == 0)
252  {
253  ScheduleTransmit(m_interval);
254  }
255 
256  delete[] data;
257 }
258 
259 void
260 Ping6::HandleRead(Ptr<Socket> socket)
261 {
262  NS_LOG_FUNCTION(this << socket);
263 
264  Ptr<Packet> packet = nullptr;
265  Address from;
266  while ((packet = socket->RecvFrom(from)))
267  {
269  {
270  Ipv6Header hdr;
271  Icmpv6Echo reply(0);
272  Icmpv6DestinationUnreachable destUnreach;
273  Icmpv6TimeExceeded timeExceeded;
274  Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom(from);
275 
276  packet->RemoveHeader(hdr);
277 
278  uint8_t type;
279  packet->CopyData(&type, sizeof(type));
280 
281  switch (type)
282  {
284  packet->RemoveHeader(reply);
285 
286  NS_LOG_INFO("Received Echo Reply size = "
287  << std::dec << packet->GetSize() << " bytes from " << address.GetIpv6()
288  << " id = " << (uint16_t)reply.GetId()
289  << " seq = " << (uint16_t)reply.GetSeq()
290  << " Hop Count = " << (uint16_t)(64 - hdr.GetHopLimit()));
291 
292  if (m_ifIndex)
293  {
294  m_ipv6Protocol->ReachabilityHint(m_ifIndex, address.GetIpv6());
295  }
296  else
297  {
298  m_ipv6Protocol->ReachabilityHint(m_ipInterfaceIndex, address.GetIpv6());
299  }
300 
301  break;
303  packet->RemoveHeader(destUnreach);
304 
305  NS_LOG_INFO("Received Destination Unreachable from " << address.GetIpv6());
306  break;
308  packet->RemoveHeader(timeExceeded);
309 
310  NS_LOG_INFO("Received Time Exceeded from " << address.GetIpv6());
311  break;
312  default:
313  break;
314  }
315  }
316  }
317 }
318 
319 } /* namespace ns3 */
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:45
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
AttributeValue implementation for Ipv6Address.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:276
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:72
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:750
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
address
Definition: first.py:40
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
uint8_t data[writeSize]