A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("Ping6Application");
39
41
42TypeId
43Ping6::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
79Ping6::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
90Ping6::~Ping6()
91{
92 NS_LOG_FUNCTION(this);
93 m_socket = nullptr;
94}
95
96void
97Ping6::DoDispose()
98{
99 NS_LOG_FUNCTION(this);
100 Application::DoDispose();
101}
102
103void
104Ping6::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
129void
130Ping6::SetLocal(Ipv6Address ipv6)
131{
132 NS_LOG_FUNCTION(this << ipv6);
133 m_localAddress = ipv6;
134}
135
136void
137Ping6::SetRemote(Ipv6Address ipv6)
138{
139 NS_LOG_FUNCTION(this << ipv6);
140 m_peerAddress = ipv6;
141}
142
143void
144Ping6::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
156void
157Ping6::SetIfIndex(uint32_t ifIndex)
158{
159 m_ifIndex = ifIndex;
160}
161
162void
163Ping6::ScheduleTransmit(Time dt)
164{
165 NS_LOG_FUNCTION(this << dt);
166 m_sendEvent = Simulator::Schedule(dt, &Ping6::Send, this);
167}
168
169void
170Ping6::SetRouters(std::vector<Ipv6Address> routers)
171{
172 m_routers = routers;
173}
174
175void
176Ping6::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
259void
260Ping6::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 {
268 if (Inet6SocketAddress::IsMatchingType(from))
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 {
283 case Icmpv6Header::ICMPV6_ECHO_REPLY:
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;
302 case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE:
303 packet->RemoveHeader(destUnreach);
304
305 NS_LOG_INFO("Received Destination Unreachable from " << address.GetIpv6());
306 break;
307 case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED:
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 */
AttributeValue implementation for Ipv6Address.
#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)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#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
ns address
Definition: first.py:40
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:702
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]