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"
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"
47 .SetParent<Application>()
48 .SetGroupName(
"Internet-Apps")
49 .AddConstructor<
Ping6>()
52 "The maximum number of packets the application will send (zero means infinite)",
55 MakeUintegerChecker<uint32_t>())
56 .AddAttribute(
"Interval",
57 "The time to wait between packets",
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",
75 MakeUintegerChecker<uint32_t>());
85 m_ipInterfaceIndex = 0;
87 m_sendEvent = EventId();
100 Application::DoDispose();
104Ping6::StartApplication()
110 TypeId tid = TypeId::LookupByName(
"ns3::Ipv6RawSocketFactory");
111 m_socket = Socket::CreateSocket(GetNode(), tid);
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>();
120 if (!m_localAddress.IsAny())
122 m_ipInterfaceIndex = m_ipv6Protocol->GetInterfaceForAddress(m_localAddress);
130Ping6::SetLocal(Ipv6Address ipv6)
133 m_localAddress = ipv6;
137Ping6::SetRemote(Ipv6Address ipv6)
140 m_peerAddress = ipv6;
144Ping6::StopApplication()
150 m_socket->SetRecvCallback(MakeNullCallback<
void, Ptr<Socket>>());
153 Simulator::Cancel(m_sendEvent);
163Ping6::ScheduleTransmit(Time dt)
166 m_sendEvent = Simulator::Schedule(dt, &Ping6::Send,
this);
170Ping6::SetRouters(std::vector<Ipv6Address> routers)
182 Ptr<Ipv6> ipv6 = GetNode()->GetObject<Ipv6>();
189 for (
uint32_t i = 0; i < GetNode()->GetObject<Ipv6>()->GetNAddresses(m_ifIndex); i++)
191 Ipv6InterfaceAddress srcIa;
192 srcIa = GetNode()->GetObject<Ipv6>()->GetAddress(m_ifIndex, i);
194 if (srcIa.IsInSameSubnet(m_peerAddress))
196 src = srcIa.GetAddress();
203 src = m_localAddress;
209 NS_LOG_WARN(
"ICMPv6 echo request payload size must be >= 4");
213 uint8_t*
data =
new uint8_t[size];
214 memset(
data, 0, size);
220 Ptr<Packet> p = Create<Packet>(
data, size);
232 m_socket->Bind(Inet6SocketAddress(src, 0));
235 if (!m_routers.empty())
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));
246 m_socket->SendTo(p, 0, Inet6SocketAddress(m_peerAddress, 0));
249 NS_LOG_INFO(
"Sent " << p->GetSize() <<
" bytes to " << m_peerAddress);
251 if (m_sent < m_count || m_count == 0)
253 ScheduleTransmit(m_interval);
260Ping6::HandleRead(Ptr<Socket> socket)
264 Ptr<Packet> packet =
nullptr;
266 while ((packet = socket->RecvFrom(from)))
268 if (Inet6SocketAddress::IsMatchingType(from))
272 Icmpv6DestinationUnreachable destUnreach;
273 Icmpv6TimeExceeded timeExceeded;
274 Inet6SocketAddress
address = Inet6SocketAddress::ConvertFrom(from);
276 packet->RemoveHeader(hdr);
279 packet->CopyData(&type,
sizeof(type));
283 case Icmpv6Header::ICMPV6_ECHO_REPLY:
284 packet->RemoveHeader(reply);
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()));
294 m_ipv6Protocol->ReachabilityHint(m_ifIndex,
address.GetIpv6());
298 m_ipv6Protocol->ReachabilityHint(m_ipInterfaceIndex,
address.GetIpv6());
302 case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE:
303 packet->RemoveHeader(destUnreach);
307 case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED:
308 packet->RemoveHeader(timeExceeded);
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,...
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#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.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Seconds(double value)
Construct a Time in the indicated unit.
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...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.