Bug 1362 - ICMPv6 does not forward ICMPs to upper layers

This commit is contained in:
Gustavo J. A. M. Carneiro
2012-03-21 18:51:55 +01:00
parent 3f9ddebd87
commit 6e252ada40
15 changed files with 902 additions and 251 deletions

View File

@@ -32,6 +32,7 @@ Bugs fixed
- bug 1357 - IPv6 fragmentation fails due to checks about malformed extensions
- bug 1378 - UdpEchoClient::SetFill () does not set packet size correctly
- bug 1351 and 1333 - TCP not able to take RTT samples on long delay network
- bug 1362 - ICMPv6 does not forward ICMPs to upper layers (and minor fixes to ICMPv6)
Known issues
------------

View File

@@ -18,6 +18,7 @@
* Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
* David Gross <gdavid.devel@gmail.com>
* Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
* Tommaso Pecorella <tommaso.pecorella@unifi.it>
*/
#include "ns3/log.h"
@@ -34,8 +35,7 @@
#include "icmpv6-l4-protocol.h"
#include "ndisc-cache.h"
namespace ns3
{
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
@@ -97,7 +97,7 @@ void Icmpv6L4Protocol::DoDispose ()
cache = 0;
}
m_cacheList.clear ();
m_downTarget.Nullify();
m_downTarget.Nullify ();
m_node = 0;
IpL4Protocol::DoDispose ();
@@ -114,11 +114,11 @@ void Icmpv6L4Protocol::NotifyNewAggregate ()
Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
if (ipv6 != 0)
{
this->SetNode (node);
SetNode (node);
ipv6->Insert (this);
Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
ipv6->AggregateObject (rawFactory);
this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
}
}
}
@@ -162,9 +162,9 @@ void Icmpv6L4Protocol::DoDAD (Ipv6Address target, Ptr<Ipv6Interface> interface)
NS_ASSERT (ipv6);
if(!m_alwaysDad)
if (!m_alwaysDad)
{
return;
return;
}
/* TODO : disable multicast loopback to prevent NS probing to be received by the sender */
@@ -192,7 +192,7 @@ enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6A
uint8_t type;
p->CopyData (&type, sizeof(type));
switch (type)
switch (type)
{
case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION:
if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
@@ -219,14 +219,21 @@ enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6A
HandleEchoRequest (p, src, dst, interface);
break;
case Icmpv6Header::ICMPV6_ECHO_REPLY:
// EchoReply does not contain any info about L4
// so we can not forward it up.
// TODO: implement request / reply consistency check.
break;
case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE:
HandleDestinationUnreachable (p, src, dst, interface);
break;
case Icmpv6Header::ICMPV6_ERROR_PACKET_TOO_BIG:
HandlePacketTooBig (p, src, dst, interface);
break;
case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED:
HandleTimeExceeded (p, src, dst, interface);
break;
case Icmpv6Header::ICMPV6_ERROR_PARAMETER_ERROR:
HandleParameterError (p, src, dst, interface);
break;
default:
NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
@@ -236,6 +243,24 @@ enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6A
return IpL4Protocol::RX_OK;
}
void Icmpv6L4Protocol::Forward (Ipv6Address source, Icmpv6Header icmp,
uint32_t info, Ipv6Header ipHeader,
const uint8_t payload[8])
{
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
// TODO assuming the ICMP is carrying a extensionless IP packet
uint8_t nextHeader = ipHeader.GetNextHeader ();
Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
if (l4 != 0)
{
l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
info, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress (), payload);
}
}
void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << packet << src << dst << interface);
@@ -253,7 +278,7 @@ void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const
}
void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
{
NS_LOG_FUNCTION (this << packet << src << dst << interface);
Ptr<Packet> p = packet->Copy ();
Icmpv6RA raHeader;
@@ -276,7 +301,7 @@ void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv
{
case Icmpv6Header::ICMPV6_OPT_PREFIX:
p->RemoveHeader (prefixHdr);
ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), src);
break;
case Icmpv6Header::ICMPV6_OPT_MTU:
@@ -312,7 +337,7 @@ void Icmpv6L4Protocol::ReceiveLLA (Icmpv6OptionLinkLayerAddress lla, Ipv6Address
NdiscCache::Entry* entry = 0;
Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
/* check if we have this address in our cache */
/* check if we have this address in our cache */
entry = cache->Lookup (src);
if (!entry)
@@ -329,11 +354,11 @@ void Icmpv6L4Protocol::ReceiveLLA (Icmpv6OptionLinkLayerAddress lla, Ipv6Address
if (entry->IsIncomplete ())
{
entry->StopRetransmitTimer ();
// mark it to reachable
// mark it to reachable
waiting = entry->MarkReachable (lla.GetAddress ());
entry->StopReachableTimer ();
entry->StartReachableTimer ();
// send out waiting packet
// send out waiting packet
for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
{
cache->GetInterface ()->Send (*it, src);
@@ -342,7 +367,7 @@ void Icmpv6L4Protocol::ReceiveLLA (Icmpv6OptionLinkLayerAddress lla, Ipv6Address
}
else
{
if (entry->GetMacAddress ()!=lla.GetAddress ())
if (entry->GetMacAddress () != lla.GetAddress ())
{
entry->SetMacAddress (lla.GetAddress ());
entry->MarkStale ();
@@ -497,7 +522,7 @@ void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv
hardwareAddress = interface->GetDevice ()->GetAddress ();
Ptr<Packet> p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags );
interface->Send (p, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
interface->Send (p, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
/* not a NS for us discard it */
}
@@ -633,7 +658,7 @@ void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv
entry->StopDelayTimer ();
/* if the Flag O is clear and mac address differs from the cache */
if (!naHeader.GetFlagO () && lla.GetAddress ()!=entry->GetMacAddress ())
if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
{
if (entry->IsReachable ())
{
@@ -656,7 +681,7 @@ void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv
waiting = entry->MarkReachable (lla.GetAddress ());
for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
{
cache->GetInterface ()->Send (*it, src);
cache->GetInterface ()->Send (*it, src);
}
entry->ClearWaitingPacket ();
}
@@ -668,7 +693,7 @@ void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv
entry->StopReachableTimer ();
entry->StartReachableTimer ();
}
else if (lla.GetAddress ()!=entry->GetMacAddress ())
else if (lla.GetAddress () != entry->GetMacAddress ())
{
entry->MarkStale ();
}
@@ -723,7 +748,7 @@ void Icmpv6L4Protocol::HandleRedirection (Ptr<Packet> packet, Ipv6Address const
if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
{
/* update entry to STALE */
if (entry->GetMacAddress ()!=llOptionHeader.GetAddress ())
if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
{
entry->SetMacAddress (llOptionHeader.GetAddress ());
entry->MarkStale ();
@@ -750,6 +775,73 @@ void Icmpv6L4Protocol::HandleRedirection (Ptr<Packet> packet, Ipv6Address const
}
}
void Icmpv6L4Protocol::HandleDestinationUnreachable (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << *p << src << dst);
Ptr<Packet> pkt = p->Copy ();
Icmpv6DestinationUnreachable unreach;
pkt->RemoveHeader (unreach);
Ptr<Packet> origPkt = unreach.GetPacket ();
Ipv6Header ipHeader;
if ( origPkt->GetSerializedSize () > ipHeader.GetSerializedSize () )
{
origPkt->RemoveHeader (ipHeader);
uint8_t payload[8];
origPkt->CopyData (payload, 8);
Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
}
}
void Icmpv6L4Protocol::HandleTimeExceeded (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << *p << src << dst);
Ptr<Packet> pkt = p->Copy ();
Icmpv6TimeExceeded timeexceeded;
pkt->RemoveHeader (timeexceeded);
Ptr<Packet> origPkt = timeexceeded.GetPacket ();
Ipv6Header ipHeader;
uint8_t payload[8];
origPkt->RemoveHeader (ipHeader);
origPkt->CopyData (payload, 8);
Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
}
void Icmpv6L4Protocol::HandlePacketTooBig (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << *p << src << dst);
Ptr<Packet> pkt = p->Copy ();
Icmpv6TooBig tooBig;
pkt->RemoveHeader (tooBig);
Ptr<Packet> origPkt = tooBig.GetPacket ();
Ipv6Header ipHeader;
origPkt->RemoveHeader (ipHeader);
uint8_t payload[8];
origPkt->CopyData (payload, 8);
Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
}
void Icmpv6L4Protocol::HandleParameterError (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << *p << src << dst);
Ptr<Packet> pkt = p->Copy ();
Icmpv6ParameterError paramErr;
pkt->RemoveHeader (paramErr);
Ptr<Packet> origPkt = paramErr.GetPacket ();
Ipv6Header ipHeader;
origPkt->RemoveHeader (ipHeader);
uint8_t payload[8];
origPkt->CopyData (payload, 8);
Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
}
void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
{
NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
@@ -851,7 +943,7 @@ void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address tar
dst = Ipv6Address::GetAllNodesMulticast ();
}
NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
p->AddHeader (llOption);
ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
@@ -930,7 +1022,7 @@ void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address
void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
{
NS_LOG_FUNCTION (this<< malformedPacket << dst << code);
NS_LOG_FUNCTION (this << malformedPacket << dst << code);
Ptr<Packet> p = Create<Packet> ();
uint32_t malformedPacketSize = malformedPacket->GetSize ();
Icmpv6TimeExceeded header;
@@ -938,7 +1030,7 @@ void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6A
NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
/* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
if (malformedPacketSize <= 1280 - 48)
if (malformedPacketSize <= 1280 - 48)
{
header.SetPacket (malformedPacket);
}
@@ -962,7 +1054,7 @@ void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv
NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
/* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
if (malformedPacketSize <= 1280 -48 )
if (malformedPacketSize <= 1280 - 48 )
{
header.SetPacket (malformedPacket);
}
@@ -992,7 +1084,7 @@ void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Addres
if ((redirectedPacketSize % 8) != 0)
{
Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
redirectedPacket->AddAtEnd (pad);
redirectedPacket->AddAtEnd (pad);
}
if (redirHardwareTarget.GetLength ())
@@ -1081,7 +1173,7 @@ Ptr<Packet> Icmpv6L4Protocol::ForgeNS (Ipv6Address src, Ipv6Address dst, Ipv6Add
dst = Ipv6Address::GetAllNodesMulticast ();
}
NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
p->AddHeader (llOption);
ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
@@ -1196,7 +1288,7 @@ bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, Ipv6Address dst, Ptr<NetDevice> de
else
{
/* find source address that match destination */
addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
}
SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
@@ -1229,7 +1321,7 @@ void Icmpv6L4Protocol::FunctionDadTimeout (Ptr<Icmpv6L4Protocol> icmpv6, Ipv6Int
}
}
/* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
/* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
* and we do not set it to PREFERRED
*/
if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
@@ -1242,9 +1334,9 @@ void Icmpv6L4Protocol::FunctionDadTimeout (Ptr<Icmpv6L4Protocol> icmpv6, Ipv6Int
*/
Ptr<Ipv6> ipv6 = icmpv6->m_node->GetObject<Ipv6> ();
if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
{
/* XXX because all nodes start at the same time, there will be many of RS arround 1 second of simulation time
/* XXX because all nodes start at the same time, there will be many of RS arround 1 second of simulation time
* TODO Add random delays before sending RS
*/
Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, PeekPointer (icmpv6), ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());

View File

@@ -29,8 +29,7 @@
#include "icmpv6-header.h"
#include "ip-l4-protocol.h"
namespace ns3
{
namespace ns3 {
class NetDevice;
class Node;
@@ -194,7 +193,7 @@ public:
* \brief Send a packet via ICMPv6.
* \param packet the packet to send
* \param dst destination address
* \param icmpv6Hdr ICMPv6 header (needed to calculate checksum
* \param icmpv6Hdr ICMPv6 header (needed to calculate checksum
* after source address is determined by routing stuff
* \param ttl next hop limit
*/
@@ -202,8 +201,8 @@ public:
/**
* \brief Do the Duplication Address Detection (DAD).
* It consists in sending a NS with our IPv6 as target. If
* we received a NA with matched target address, we could not use
* It consists in sending a NS with our IPv6 as target. If
* we received a NA with matched target address, we could not use
* the address, else the address pass from TENTATIVE to PERMANENT.
*
* \param target target address
@@ -325,13 +324,20 @@ public:
/**
* \brief Receive method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param header the IPv4 header
* \param interface the interface from which the packet is coming
*/
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> interface);
/**
* \brief Receive method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src, Ipv6Address &dst,
Ptr<Ipv6Interface> interface);
@@ -396,7 +402,6 @@ protected:
virtual void DoDispose ();
private:
typedef std::list<Ptr<NdiscCache> > CacheList;
/**
@@ -414,6 +419,18 @@ private:
*/
bool m_alwaysDad;
/**
* \brief Notify an ICMPv6 reception to upper layers (if requested).
* \param source the ICMP source
* \param icmp the ICMP header
* \param info information about the ICMP
* \param ipHeader the IP header carried by the ICMP
* \param payload the data carried by the ICMP
*/
void Forward (Ipv6Address source, Icmpv6Header icmp,
uint32_t info, Ipv6Header ipHeader,
const uint8_t payload[8]);
/**
* \brief Receive Neighbor Solicitation method.
* \param p the packet
@@ -468,6 +485,42 @@ private:
*/
void HandleRedirection (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Receive Destination Unreachable method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
void HandleDestinationUnreachable (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Receive Time Exceeded method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
void HandleTimeExceeded (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Receive Packet Too Big method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
void HandlePacketTooBig (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Receive Parameter Error method.
* \param p the packet
* \param src source address
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
void HandleParameterError (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
/**
* \brief Link layer address option processing.
* \param lla LLA option

View File

@@ -22,13 +22,14 @@
#include "ipv6-end-point.h"
#include "ns3/log.h"
namespace ns3
{
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("Ipv6EndPointDemux");
Ipv6EndPointDemux::Ipv6EndPointDemux ()
: m_ephemeral (49152)
: m_ephemeral (49152),
m_portFirst (49152),
m_portLast (65535)
{
NS_LOG_FUNCTION_NOARGS ();
}
@@ -36,7 +37,7 @@ Ipv6EndPointDemux::Ipv6EndPointDemux ()
Ipv6EndPointDemux::~Ipv6EndPointDemux ()
{
NS_LOG_FUNCTION_NOARGS ();
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
Ipv6EndPoint *endPoint = *i;
delete endPoint;
@@ -47,9 +48,9 @@ Ipv6EndPointDemux::~Ipv6EndPointDemux ()
bool Ipv6EndPointDemux::LookupPortLocal (uint16_t port)
{
NS_LOG_FUNCTION (this << port);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port)
if ((*i)->GetLocalPort () == port)
{
return true;
}
@@ -60,10 +61,10 @@ bool Ipv6EndPointDemux::LookupPortLocal (uint16_t port)
bool Ipv6EndPointDemux::LookupLocal (Ipv6Address addr, uint16_t port)
{
NS_LOG_FUNCTION (this << addr << port);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == port &&
(*i)->GetLocalAddress () == addr)
if ((*i)->GetLocalPort () == port
&& (*i)->GetLocalAddress () == addr)
{
return true;
}
@@ -75,7 +76,7 @@ Ipv6EndPoint* Ipv6EndPointDemux::Allocate ()
{
NS_LOG_FUNCTION_NOARGS ();
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
if (port == 0)
{
NS_LOG_WARN ("Ephemeral port allocation failed.");
return 0;
@@ -90,7 +91,7 @@ Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address address)
{
NS_LOG_FUNCTION (this << address);
uint16_t port = AllocateEphemeralPort ();
if (port == 0)
if (port == 0)
{
NS_LOG_WARN ("Ephemeral port allocation failed.");
return 0;
@@ -111,7 +112,7 @@ Ipv6EndPoint* Ipv6EndPointDemux::Allocate (uint16_t port)
Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address address, uint16_t port)
{
NS_LOG_FUNCTION (this << address << port);
if (LookupLocal (address, port))
if (LookupLocal (address, port))
{
NS_LOG_WARN ("Duplicate address/port; failing.");
return 0;
@@ -126,12 +127,12 @@ Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address localAddress, uint16_t lo
Ipv6Address peerAddress, uint16_t peerPort)
{
NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if ((*i)->GetLocalPort () == localPort &&
(*i)->GetLocalAddress () == localAddress &&
(*i)->GetPeerPort () == peerPort &&
(*i)->GetPeerAddress () == peerAddress)
if ((*i)->GetLocalPort () == localPort
&& (*i)->GetLocalAddress () == localAddress
&& (*i)->GetPeerPort () == peerPort
&& (*i)->GetPeerAddress () == peerAddress)
{
NS_LOG_WARN ("No way we can allocate this end-point.");
/* no way we can allocate this end-point. */
@@ -150,7 +151,7 @@ Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address localAddress, uint16_t lo
void Ipv6EndPointDemux::DeAllocate (Ipv6EndPoint *endPoint)
{
NS_LOG_FUNCTION_NOARGS ();
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
if (*i == endPoint)
{
@@ -166,7 +167,7 @@ void Ipv6EndPointDemux::DeAllocate (Ipv6EndPoint *endPoint)
* Otherwise, if we find a generic match, we return it.
* Otherwise, we return 0.
*/
Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint16_t dport,
Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint16_t dport,
Ipv6Address saddr, uint16_t sport,
Ptr<Ipv6Interface> incomingInterface)
{
@@ -178,14 +179,14 @@ Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint1
EndPoints retval4; /* Exact match on all 4 */
NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
{
Ipv6EndPoint* endP = *i;
NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
<< " daddr=" << endP->GetLocalAddress ()
<< " sport=" << endP->GetPeerPort ()
<< " saddr=" << endP->GetPeerAddress ());
if (endP->GetLocalPort () != dport)
if (endP->GetLocalPort () != dport)
{
NS_LOG_LOGIC ("Skipping endpoint " << &endP
<< " because endpoint dport "
@@ -203,7 +204,9 @@ Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint1
/* if no match here, keep looking */
if (!(localAddressMatchesExact || localAddressMatchesWildCard))
continue;
{
continue;
}
bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
@@ -212,41 +215,54 @@ Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint1
/* If remote does not match either with exact or wildcard,i
skip this one */
if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
continue;
{
continue;
}
if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
continue;
{
continue;
}
/* Now figure out which return list to add this one to */
if (localAddressMatchesWildCard &&
remotePeerMatchesWildCard &&
remoteAddressMatchesWildCard)
if (localAddressMatchesWildCard
&& remotePeerMatchesWildCard
&& remoteAddressMatchesWildCard)
{ /* Only local port matches exactly */
retval1.push_back (endP);
}
if ((localAddressMatchesExact || (localAddressMatchesAllRouters))&&
remotePeerMatchesWildCard &&
remoteAddressMatchesWildCard)
if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
&& remotePeerMatchesWildCard
&& remoteAddressMatchesWildCard)
{ /* Only local port and local address matches exactly */
retval2.push_back (endP);
}
if (localAddressMatchesWildCard &&
remotePeerMatchesExact &&
remoteAddressMatchesExact)
if (localAddressMatchesWildCard
&& remotePeerMatchesExact
&& remoteAddressMatchesExact)
{ /* All but local address */
retval3.push_back (endP);
}
if (localAddressMatchesExact &&
remotePeerMatchesExact &&
remoteAddressMatchesExact)
if (localAddressMatchesExact
&& remotePeerMatchesExact
&& remoteAddressMatchesExact)
{ /* All 4 match */
retval4.push_back (endP);
}
}
/* Here we find the most exact match */
if (!retval4.empty ()) return retval4;
if (!retval3.empty ()) return retval3;
if (!retval2.empty ()) return retval2;
if (!retval4.empty ())
{
return retval4;
}
if (!retval3.empty ())
{
return retval3;
}
if (!retval2.empty ())
{
return retval2;
}
return retval1; /* might be empty if no matches */
}
@@ -264,8 +280,8 @@ Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport,
continue;
}
if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport &&
(*i)->GetPeerAddress () == src)
if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport
&& (*i)->GetPeerAddress () == src)
{
/* this is an exact match. */
return *i;
@@ -294,19 +310,22 @@ uint16_t Ipv6EndPointDemux::AllocateEphemeralPort ()
{
NS_LOG_FUNCTION_NOARGS ();
uint16_t port = m_ephemeral;
do
int count = m_portLast - m_portFirst;
do
{
port++;
if (port == 65535)
if (count-- < 0)
{
port = 49152;
return 0;
}
if (!LookupPortLocal (port))
++port;
if (port < m_portFirst || port > m_portLast)
{
return port;
port = m_portFirst;
}
} while (port != m_ephemeral);
return 0;
}
while (LookupPortLocal (port));
m_ephemeral = port;
return port;
}
Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::GetEndPoints () const

View File

@@ -26,8 +26,7 @@
#include "ns3/ipv6-address.h"
#include "ipv6-interface.h"
namespace ns3
{
namespace ns3 {
class Ipv6EndPoint;
@@ -91,21 +90,21 @@ public:
* \brief Allocate a Ipv6EndPoint.
* \return an empty Ipv6EndPoint instance
*/
Ipv6EndPoint *Allocate (void);
Ipv6EndPoint * Allocate (void);
/**
* \brief Allocate a Ipv6EndPoint.
* \param address IPv6 address
* \return an Ipv6EndPoint instance
*/
Ipv6EndPoint *Allocate (Ipv6Address address);
Ipv6EndPoint * Allocate (Ipv6Address address);
/**
* \brief Allocate a Ipv6EndPoint.
* \param port local port
* \return an Ipv6EndPoint instance
*/
Ipv6EndPoint *Allocate (uint16_t port);
Ipv6EndPoint * Allocate (uint16_t port);
/**
* \brief Allocate a Ipv6EndPoint.
@@ -113,7 +112,7 @@ public:
* \param port local port
* \return an Ipv6EndPoint instance
*/
Ipv6EndPoint *Allocate (Ipv6Address address, uint16_t port);
Ipv6EndPoint * Allocate (Ipv6Address address, uint16_t port);
/**
* \brief Allocate a Ipv6EndPoint.
@@ -123,7 +122,7 @@ public:
* \param peerPort peer port
* \return an Ipv6EndPoint instance
*/
Ipv6EndPoint *Allocate (Ipv6Address localAddress, uint16_t localPort, Ipv6Address peerAddress, uint16_t peerPort);
Ipv6EndPoint * Allocate (Ipv6Address localAddress, uint16_t localPort, Ipv6Address peerAddress, uint16_t peerPort);
/**
* \brief Remove a end point.
@@ -149,6 +148,16 @@ private:
*/
uint16_t m_ephemeral;
/**
* \brief The first ephemeral port.
*/
uint16_t m_portFirst;
/**
* \brief The last ephemeral port.
*/
uint16_t m_portLast;
/**
* \brief A list of IPv6 end points.
*/

View File

@@ -43,8 +43,7 @@
NS_LOG_COMPONENT_DEFINE ("Ipv6Extension");
namespace ns3
{
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension);
@@ -338,14 +337,17 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
std::pair<Ipv6Address, uint32_t> fragmentsId = std::make_pair<Ipv6Address, uint32_t> (src, identification);
Ptr<Fragments> fragments;
Ipv6Header ipHeader = ipv6Header;
ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
MapFragments_t::iterator it = m_fragments.find (fragmentsId);
if (it == m_fragments.end ())
{
fragments = Create<Fragments> ();
m_fragments.insert (std::make_pair (fragmentsId, fragments));
EventId timeout = Simulator::Schedule (Seconds(60),
EventId timeout = Simulator::Schedule (Seconds (60),
&Ipv6ExtensionFragment::HandleFragmentsTimeout, this,
fragmentsId, fragments, ipv6Header);
fragmentsId, fragments, ipHeader);
fragments->SetTimeoutEventId (timeout);
}
else
@@ -365,11 +367,11 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
if (fragments->IsEntire ())
{
packet = fragments->GetPacket ();
fragments->CancelTimeout();
m_fragments.erase(fragmentsId);
fragments->CancelTimeout ();
m_fragments.erase (fragmentsId);
isDropped = false;
}
else
else
{
// the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
isDropped = true;
@@ -406,9 +408,9 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
uint8_t extensionHeaderLength;
while (moreHeader)
while (moreHeader)
{
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
p->RemoveHeader (*hopbyhopHeader);
@@ -429,7 +431,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
unfragmentablePartSize += extensionHeaderLength;
}
else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
{
uint8_t buf[2];
p->CopyData (buf, sizeof(buf));
@@ -453,7 +455,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
unfragmentablePartSize += extensionHeaderLength;
}
else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
{
Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
p->RemoveHeader (*destinationHeader);
@@ -463,7 +465,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
uint8_t type;
p->CopyData (&type, sizeof(type));
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
@@ -486,14 +488,14 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
uint32_t identification = (uint32_t) uvar.GetValue (0, (uint32_t)-1);
uint16_t offset = 0;
do
do
{
if (p->GetSize () > offset + maxFragmentablePartSize)
{
moreFragment = true;
currentFragmentablePartSize = maxFragmentablePartSize;
}
else
else
{
moreFragment = false;
currentFragmentablePartSize = p->GetSize () - offset;
@@ -516,15 +518,15 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
{
if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first));
}
}
@@ -534,7 +536,8 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
std::ostringstream oss;
fragment->Print (oss);
listFragments.push_back (fragment);
} while (moreFragment);
}
while (moreFragment);
for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
{
@@ -549,17 +552,19 @@ void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint3
{
Ptr<Packet> packet = fragments->GetPartialPacket ();
packet->AddHeader (ipHeader);
// if we have at least 8 bytes, we can send an ICMP.
if ( packet->GetSize () > 8 )
{
Ptr<Icmpv6L4Protocol> icmp = GetNode()->GetObject<Icmpv6L4Protocol> ();
Ptr<Icmpv6L4Protocol> icmp = GetNode ()->GetObject<Icmpv6L4Protocol> ();
icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
}
m_dropTrace (packet);
// clear the buffers
m_fragments.erase(fragmentsId);
m_fragments.erase (fragmentsId);
}
Ipv6ExtensionFragment::Fragments::Fragments ()
@@ -591,7 +596,7 @@ void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16
m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
}
void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr<Packet> unfragmentablePart)
void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr<Packet> unfragmentablePart)
{
m_unfragmentable = unfragmentablePart;
}
@@ -661,14 +666,14 @@ Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPartialPacket () const
void Ipv6ExtensionFragment::Fragments::SetTimeoutEventId (EventId event)
{
m_timeoutEventId = event;
return;
m_timeoutEventId = event;
return;
}
void Ipv6ExtensionFragment::Fragments::CancelTimeout()
void Ipv6ExtensionFragment::Fragments::CancelTimeout ()
{
m_timeoutEventId.Cancel ();
return;
m_timeoutEventId.Cancel ();
return;
}
@@ -727,7 +732,7 @@ uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6
if (nextHeader)
{
*nextHeader = routingNextHeader;
*nextHeader = routingNextHeader;
}
Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
@@ -918,7 +923,7 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
nextAddressIndex = nbAddress - segmentsLeft;
nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
{
m_dropTrace (packet);
isDropped = true;
@@ -941,10 +946,10 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
ipv6header.SetHopLimit (hopLimit - 1);
p->AddHeader (routingHeader);
/* short-circuiting routing stuff
*
/* short-circuiting routing stuff
*
* If we process this option,
* the packet was for us so we resend it to
* the packet was for us so we resend it to
* the new destination (modified in the header above).
*/
@@ -966,7 +971,7 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
}
/* as we directly send packet, mark it as dropped */
isDropped = true;
isDropped = true;
return routingHeader.GetSerializedSize ();
}

View File

@@ -35,8 +35,7 @@
#include "ns3/traced-callback.h"
namespace ns3
{
namespace ns3 {
/**
* \class Ipv6Extension
@@ -309,7 +308,7 @@ public:
/**
* \brief If all fragments have been added.
* \returns true if the packet is entire
* \returns true if the packet is entire
*/
bool IsEntire () const;

View File

@@ -41,8 +41,7 @@
#include "icmpv6-l4-protocol.h"
#include "ndisc-cache.h"
namespace ns3
{
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
@@ -130,7 +129,7 @@ void Ipv6L3Protocol::SetRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtoco
m_routingProtocol->SetIpv6 (this);
}
Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const
Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const
{
NS_LOG_FUNCTION_NOARGS ();
return m_routingProtocol;
@@ -175,7 +174,7 @@ Ptr<Ipv6Interface> Ipv6L3Protocol::GetInterface (uint32_t index) const
return 0;
}
uint32_t Ipv6L3Protocol::GetNInterfaces () const
uint32_t Ipv6L3Protocol::GetNInterfaces () const
{
NS_LOG_FUNCTION_NOARGS ();
return m_nInterfaces;
@@ -183,7 +182,7 @@ uint32_t Ipv6L3Protocol::GetNInterfaces () const
int32_t Ipv6L3Protocol::GetInterfaceForAddress (Ipv6Address address) const
{
NS_LOG_FUNCTION (this << address);
NS_LOG_FUNCTION (this << address);
int32_t index = 0;
for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
@@ -193,7 +192,7 @@ int32_t Ipv6L3Protocol::GetInterfaceForAddress (Ipv6Address address) const
for (j = 0; j < max; j++)
{
if ((*it)->GetAddress (j).GetAddress () == address)
if ((*it)->GetAddress (j).GetAddress () == address)
{
return index;
}
@@ -252,7 +251,7 @@ void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address n
Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
if (flags & (1<< 6)) /* auto flag */
if (flags & (1 << 6)) /* auto flag */
{
/* XXX : add other L2 address case */
if (Mac48Address::IsMatchingType (addr))
@@ -282,7 +281,7 @@ void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address n
AddAddress (interface, address);
/* add default router
* if a previous default route exists, the new ones is simply added
* if a previous default route exists, the new ones is simply added
*/
GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
@@ -304,7 +303,7 @@ void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Addres
for (i = 0; i < max; i++)
{
if (iface->GetAddress (i).GetAddress () == toFound)
if (iface->GetAddress (i).GetAddress () == toFound)
{
RemoveAddress (interface, i);
break;
@@ -369,14 +368,14 @@ bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
return false;
}
void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
{
NS_LOG_FUNCTION (this << i << metric);
Ptr<Ipv6Interface> interface = GetInterface (i);
interface->SetMetric (metric);
}
uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv6Interface> interface = GetInterface (i);
@@ -635,12 +634,12 @@ void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address d
hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
//for link-local traffic, we need to determine the interface
if (source.IsLinkLocal () ||
destination.IsLinkLocal () ||
destination.IsAllNodesMulticast () ||
destination.IsAllRoutersMulticast () ||
destination.IsAllHostsMulticast () ||
destination.IsSolicitedMulticast ())
if (source.IsLinkLocal ()
|| destination.IsLinkLocal ()
|| destination.IsAllNodesMulticast ()
|| destination.IsAllRoutersMulticast ()
|| destination.IsAllHostsMulticast ()
|| destination.IsSolicitedMulticast ())
{
int32_t index = GetInterfaceForAddress (source);
NS_ASSERT (index >= 0);
@@ -707,7 +706,7 @@ void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16
socket->ForwardUp (packet, hdr, device);
}
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
Ptr<Ipv6Extension> ipv6Extension = 0;
uint8_t nextHeader = hdr.GetNextHeader ();
bool isDropped = false;
@@ -763,6 +762,12 @@ void Ipv6L3Protocol::SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6
// Router => drop
if (m_ipForward)
{
Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
if ( icmpv6 )
{
packet->AddHeader(ipHeader);
icmpv6->SendErrorTooBig (packet, ipHeader.GetSourceAddress (), dev->GetMtu ());
}
return;
}
@@ -771,7 +776,7 @@ void Ipv6L3Protocol::SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6
packet->AddHeader (ipHeader);
// To get specific method GetFragments from Ipv6ExtensionFragmentation
Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *>(PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments);
}
@@ -858,8 +863,8 @@ void Ipv6L3Protocol::IpForward (Ptr<Ipv6Route> rtentry, Ptr<const Packet> p, con
NS_LOG_WARN ("TTL exceeded. Drop.");
m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), 0);
// Do not reply to ICMPv6 or to multicast IPv6 address
if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER &&
ipHeader.GetDestinationAddress ().IsMulticast () == false)
if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER
&& ipHeader.GetDestinationAddress ().IsMulticast () == false)
{
packet->AddHeader (ipHeader);
GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT);
@@ -869,12 +874,12 @@ void Ipv6L3Protocol::IpForward (Ptr<Ipv6Route> rtentry, Ptr<const Packet> p, con
/* ICMPv6 Redirect */
/* if we forward to a machine on the same network as the source,
* we send him an ICMPv6 redirect message to notify him that a short route
/* if we forward to a machine on the same network as the source,
* we send him an ICMPv6 redirect message to notify him that a short route
* exists.
*/
if ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))) ||
(rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))))
if ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64)))
|| (rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))))
{
NS_LOG_LOGIC ("ICMPv6 redirect!");
Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
@@ -940,8 +945,8 @@ void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& i
{
NS_LOG_FUNCTION (this << packet << ip << iif);
Ptr<Packet> p = packet->Copy ();
Ptr<IpL4Protocol> protocol = 0;
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
Ptr<IpL4Protocol> protocol = 0;
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
Ptr<Ipv6Extension> ipv6Extension = 0;
Ipv6Address src = ip.GetSourceAddress ();
Ipv6Address dst = ip.GetDestinationAddress ();
@@ -961,7 +966,8 @@ void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& i
}
/* process all the extensions found and the layer 4 protocol */
do {
do
{
/* it return 0 for non-extension (i.e. layer 4 protocol) */
ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
@@ -1030,7 +1036,8 @@ void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& i
}
}
}
} while (ipv6Extension);
}
while (ipv6Extension);
}
void Ipv6L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno)

View File

@@ -41,13 +41,13 @@ Ipv6ListRouting::GetTypeId (void)
}
Ipv6ListRouting::Ipv6ListRouting ()
Ipv6ListRouting::Ipv6ListRouting ()
: m_ipv6 (0)
{
NS_LOG_FUNCTION_NOARGS ();
}
Ipv6ListRouting::~Ipv6ListRouting ()
Ipv6ListRouting::~Ipv6ListRouting ()
{
NS_LOG_FUNCTION_NOARGS ();
}
@@ -94,9 +94,9 @@ Ipv6ListRouting::RouteOutput (Ptr<Packet> p, const Ipv6Header &header, Ptr<NetDe
}
// Patterned after Linux ip_route_input and ip_route_input_slow
bool
Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
bool
Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb)
{
bool retVal = false;
@@ -104,9 +104,9 @@ Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<
NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv6->GetObject<Node> ()->GetId ());
NS_ASSERT (m_ipv6 != 0);
// Check if input device supports IP
// Check if input device supports IP
NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
Ipv6Address dst = header.GetDestinationAddress ();
// Multicast recognition; handle local delivery here
@@ -171,7 +171,7 @@ Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<
lcb (p, header, iif);
return true;
}
NS_LOG_LOGIC ("Address "<< addr << " not a match");
NS_LOG_LOGIC ("Address " << addr << " not a match");
}
}
// Check if input device supports IP forwarding
@@ -196,7 +196,7 @@ Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<
return retVal;
}
void
void
Ipv6ListRouting::NotifyInterfaceUp (uint32_t interface)
{
NS_LOG_FUNCTION (this << interface);
@@ -208,7 +208,7 @@ Ipv6ListRouting::NotifyInterfaceUp (uint32_t interface)
(*rprotoIter).second->NotifyInterfaceUp (interface);
}
}
void
void
Ipv6ListRouting::NotifyInterfaceDown (uint32_t interface)
{
NS_LOG_FUNCTION (this << interface);
@@ -220,7 +220,7 @@ Ipv6ListRouting::NotifyInterfaceDown (uint32_t interface)
(*rprotoIter).second->NotifyInterfaceDown (interface);
}
}
void
void
Ipv6ListRouting::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address)
{
NS_LOG_FUNCTION (this << interface << address);
@@ -232,7 +232,7 @@ Ipv6ListRouting::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress addr
(*rprotoIter).second->NotifyAddAddress (interface, address);
}
}
void
void
Ipv6ListRouting::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address)
{
NS_LOG_FUNCTION (this << interface << address);
@@ -269,7 +269,7 @@ void Ipv6ListRouting::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6A
}
}
void
void
Ipv6ListRouting::SetIpv6 (Ptr<Ipv6> ipv6)
{
NS_LOG_FUNCTION (this << ipv6);
@@ -296,14 +296,14 @@ Ipv6ListRouting::AddRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol, i
}
}
uint32_t
uint32_t
Ipv6ListRouting::GetNRoutingProtocols (void) const
{
NS_LOG_FUNCTION (this);
return m_routingProtocols.size ();
return m_routingProtocols.size ();
}
Ptr<Ipv6RoutingProtocol>
Ptr<Ipv6RoutingProtocol>
Ipv6ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
{
NS_LOG_FUNCTION (index);
@@ -324,7 +324,7 @@ Ipv6ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
return 0;
}
bool
bool
Ipv6ListRouting::Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b)
{
return a.first > b.first;

View File

@@ -25,7 +25,7 @@
namespace ns3 {
/**
* \ingroup internet
* \ingroup internet
* \defgroup ipv6ListRouting Ipv6 List Routing
*/
@@ -34,15 +34,15 @@ namespace ns3 {
* \class Ipv6ListRouting
* \brief Hold list of Ipv6RoutingProtocol objects.
*
* This class is a specialization of Ipv6RoutingProtocol that allows
* other instances of Ipv6RoutingProtocol to be inserted in a
* This class is a specialization of Ipv6RoutingProtocol that allows
* other instances of Ipv6RoutingProtocol to be inserted in a
* prioritized list. Routing protocols in the list are consulted one
* by one, from highest to lowest priority, until a routing protocol
* is found that will take the packet (this corresponds to a non-zero
* return value to RouteOutput, or a return value of true to RouteInput).
* The order by which routing protocols with the same priority value
* The order by which routing protocols with the same priority value
* are consulted is undefined.
*
*
*/
class Ipv6ListRouting : public Ipv6RoutingProtocol
{
@@ -78,7 +78,7 @@ public:
virtual uint32_t GetNRoutingProtocols (void) const;
/**
* \brief Get pointer to routing protocol stored at index,
* \brief Get pointer to routing protocol stored at index,
*
* The first protocol (index 0) the highest priority, the next one (index 1)
* the second highest priority, and so on. The priority parameter is an
@@ -86,7 +86,7 @@ public:
* \param index index of protocol to return
* \param priority output parameter, set to the priority of the protocol
* being returned
* \return pointer to routing protocol indexed by
* \return pointer to routing protocol indexed by
*/
virtual Ptr<Ipv6RoutingProtocol> GetRoutingProtocol (uint32_t index, int16_t& priority) const;
@@ -108,7 +108,7 @@ protected:
/**
* \brief Dispose this object.
*/
void DoDispose (void);
virtual void DoDispose (void);
private:
typedef std::pair<int16_t, Ptr<Ipv6RoutingProtocol> > Ipv6RoutingProtocolEntry;

View File

@@ -26,8 +26,7 @@
#include "ipv6-static-routing.h"
#include "ipv6-routing-table-entry.h"
namespace ns3
{
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("Ipv6StaticRouting");
NS_OBJECT_ENSURE_REGISTERED (Ipv6StaticRouting);
@@ -56,7 +55,7 @@ void Ipv6StaticRouting::SetIpv6 (Ptr<Ipv6> ipv6)
{
NS_LOG_FUNCTION (this << ipv6);
NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
uint32_t i = 0;
uint32_t i = 0;
m_ipv6 = ipv6;
for (i = 0; i < m_ipv6->GetNInterfaces (); i++)
@@ -164,9 +163,9 @@ bool Ipv6StaticRouting::RemoveMulticastRoute (Ipv6Address origin, Ipv6Address gr
for (MulticastRoutesI i = m_multicastRoutes.begin (); i != m_multicastRoutes.end (); i++)
{
Ipv6MulticastRoutingTableEntry *route = *i;
if (origin == route->GetOrigin () &&
group == route->GetGroup () &&
inputInterface == route->GetInputInterface ())
if (origin == route->GetOrigin ()
&& group == route->GetGroup ()
&& inputInterface == route->GetInputInterface ())
{
delete *i;
m_multicastRoutes.erase (i);
@@ -222,8 +221,8 @@ Ptr<Ipv6Route> Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr<NetDevice>
uint32_t shortestMetric = 0xffffffff;
/* when sending on link-local multicast, there have to be interface specified */
if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast () ||
dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast ()
|| dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
{
NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!");
rtentry = Create<Ipv6Route> ();
@@ -294,7 +293,7 @@ Ptr<Ipv6Route> Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr<NetDevice>
}
}
if(rtentry)
if (rtentry)
{
NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (throught " << rtentry->GetGateway () << ") at the end");
}
@@ -364,7 +363,7 @@ Ptr<Ipv6MulticastRoute> Ipv6StaticRouting::LookupStatic (Ipv6Address origin, Ipv
}
}
return mrtentry;
}
}
}
}
return mrtentry;
@@ -474,8 +473,8 @@ void Ipv6StaticRouting::RemoveRoute (Ipv6Address network, Ipv6Prefix prefix, uin
for (NetworkRoutesI it = m_networkRoutes.begin (); it != m_networkRoutes.end (); it++)
{
Ipv6RoutingTableEntry* rtentry = it->first;
if (network == rtentry->GetDest () && rtentry->GetInterface () == ifIndex &&
rtentry->GetPrefixToUse () == prefixToUse)
if (network == rtentry->GetDest () && rtentry->GetInterface () == ifIndex
&& rtentry->GetPrefixToUse () == prefixToUse)
{
delete it->first;
m_networkRoutes.erase (it);
@@ -568,7 +567,7 @@ bool Ipv6StaticRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &heade
lcb (p, header, iif);
return true;
}
NS_LOG_LOGIC ("Address "<< addr << " not a match");
NS_LOG_LOGIC ("Address " << addr << " not a match");
}
}
// Check if input device supports IP forwarding
@@ -599,8 +598,8 @@ void Ipv6StaticRouting::NotifyInterfaceUp (uint32_t i)
{
for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
{
if (m_ipv6->GetAddress (i, j).GetAddress () != Ipv6Address () &&
m_ipv6->GetAddress (i, j).GetPrefix () != Ipv6Prefix ())
if (m_ipv6->GetAddress (i, j).GetAddress () != Ipv6Address ()
&& m_ipv6->GetAddress (i, j).GetPrefix () != Ipv6Prefix ())
{
if (m_ipv6->GetAddress (i, j).GetPrefix () == Ipv6Prefix (128))
{
@@ -670,10 +669,10 @@ void Ipv6StaticRouting::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAd
{
Ipv6RoutingTableEntry route = GetRoute (j);
if (route.GetInterface () == interface &&
route.IsNetwork () &&
route.GetDestNetwork () == networkAddress &&
route.GetDestNetworkPrefix () == networkMask)
if (route.GetInterface () == interface
&& route.IsNetwork ()
&& route.GetDestNetwork () == networkAddress
&& route.GetDestNetworkPrefix () == networkMask)
{
RemoveRoute (j);
}
@@ -716,7 +715,7 @@ void Ipv6StaticRouting::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv
{
delete j->first;
m_networkRoutes.erase (j);
}
}
}
}
else
@@ -736,7 +735,7 @@ Ipv6Address Ipv6StaticRouting::SourceAddressSelection (uint32_t interface, Ipv6A
if (dest == Ipv6Address::GetAllNodesMulticast () || dest == Ipv6Address::GetAllRoutersMulticast () || dest == Ipv6Address::GetAllHostsMulticast ())
{
return ret;
return ret;
}
/* useally IPv6 interfaces have one link-local address and one global address */

View File

@@ -31,8 +31,7 @@
#include "ns3/ipv6-header.h"
#include "ns3/ipv6-routing-protocol.h"
namespace ns3
{
namespace ns3 {
class Packet;
class NetDevice;
@@ -241,7 +240,7 @@ protected:
/**
* \brief Dispose this object.
*/
void DoDispose ();
virtual void DoDispose ();
private:
typedef std::list<std::pair <Ipv6RoutingTableEntry *, uint32_t> > NetworkRoutes;

View File

@@ -105,7 +105,8 @@ TcpSocketBase::TcpSocketBase (void)
m_node (0),
m_tcp (0),
m_rtt (0),
m_nextTxSequence (0), // Change this for non-zero initial sequence number
m_nextTxSequence (0),
// Change this for non-zero initial sequence number
m_highTxMark (0),
m_rxBuffer (0),
m_txBuffer (0),
@@ -116,14 +117,16 @@ TcpSocketBase::TcpSocketBase (void)
m_shutdownSend (false),
m_shutdownRecv (false),
m_connected (false),
m_segmentSize (0), // For attribute initialization consistency (quiet valgrind)
m_segmentSize (0),
// For attribute initialization consistency (quiet valgrind)
m_rWnd (0)
{
NS_LOG_FUNCTION (this);
}
TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
: TcpSocket (sock), //copy object::m_tid and socket::callbacks
: TcpSocket (sock),
//copy object::m_tid and socket::callbacks
m_dupAckCount (sock.m_dupAckCount),
m_delAckCount (0),
m_delAckMaxCount (sock.m_delAckMaxCount),
@@ -246,10 +249,9 @@ TcpSocketBase::GetNode (void) const
int
TcpSocketBase::Bind (void)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_FUNCTION (this);
m_endPoint = m_tcp->Allocate ();
m_endPoint6 = m_tcp->Allocate6 ();
if (0 == m_endPoint || 0 == m_endPoint6)
if (0 == m_endPoint)
{
m_errno = ERROR_ADDRNOTAVAIL;
return -1;
@@ -261,7 +263,15 @@ TcpSocketBase::Bind (void)
int
TcpSocketBase::Bind6 (void)
{
return Bind ();
NS_LOG_FUNCTION (this);
m_endPoint6 = m_tcp->Allocate6 ();
if (0 == m_endPoint6)
{
m_errno = ERROR_ADDRNOTAVAIL;
return -1;
}
m_tcp->m_sockets.push_back (this);
return SetupCallback ();
}
/** Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
@@ -341,7 +351,7 @@ TcpSocketBase::Connect (const Address & address)
NS_LOG_FUNCTION (this << address);
// If haven't do so, Bind() this socket first
if (InetSocketAddress::IsMatchingType (address))
if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
{
if (m_endPoint == 0)
{
@@ -362,7 +372,7 @@ TcpSocketBase::Connect (const Address & address)
return -1;
}
}
else if (Inet6SocketAddress::IsMatchingType (address) )
else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0)
{
// If we are operating on a v4-mapped address, translate the address to
// a v4 address and re-call this function
@@ -371,7 +381,7 @@ TcpSocketBase::Connect (const Address & address)
if (v6Addr.IsIpv4MappedAddress () == true)
{
Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
return Connect(InetSocketAddress(v4Addr, transport.GetPort ()));
return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
}
if (m_endPoint6 == 0)
@@ -629,7 +639,7 @@ TcpSocketBase::SetupCallback (void)
}
if (m_endPoint != 0)
{
m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
}
if (m_endPoint6 != 0)
@@ -712,8 +722,14 @@ TcpSocketBase::CloseAndNotify (void)
{
NS_LOG_FUNCTION (this);
if (!m_closeNotified) NotifyNormalClose ();
if (m_state != TIME_WAIT) DeallocateEndPoint ();
if (!m_closeNotified)
{
NotifyNormalClose ();
}
if (m_state != TIME_WAIT)
{
DeallocateEndPoint ();
}
m_closeNotified = true;
NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSED");
CancelAllTimers ();
@@ -734,7 +750,7 @@ TcpSocketBase::OutOfRange (SequenceNumber32 head, SequenceNumber32 tail) const
{ // In LAST_ACK and CLOSING states, it only wait for an ACK and the
// sequence number must equals to m_rxBuffer.NextRxSequence ()
return (m_rxBuffer.NextRxSequence () != head);
};
}
// In all other cases, check if the sequence number is in range
return (tail < m_rxBuffer.NextRxSequence () || m_rxBuffer.MaxRxSequence () <= head);
@@ -775,7 +791,7 @@ TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port
TcpHeader tcpHeader;
packet->RemoveHeader (tcpHeader);
if (tcpHeader.GetFlags () & TcpHeader::ACK)
{
{
EstimateRtt (tcpHeader);
}
ReadOptions (tcpHeader);
@@ -789,12 +805,12 @@ TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port
m_rWnd = tcpHeader.GetWindowSize ();
// Discard fully out of range data packets
if (packet->GetSize () &&
OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
if (packet->GetSize ()
&& OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
{
NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
" received packet of seq [" << tcpHeader.GetSequenceNumber () <<
":" << tcpHeader.GetSequenceNumber () + packet->GetSize() <<
":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
m_rxBuffer.MaxRxSequence () << ")");
// Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
@@ -884,12 +900,12 @@ TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address d
m_rWnd = tcpHeader.GetWindowSize ();
// Discard fully out of range packets
if (packet->GetSize () &&
OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
if (packet->GetSize ()
&& OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
{
NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
" received packet of seq [" << tcpHeader.GetSequenceNumber () <<
":" << tcpHeader.GetSequenceNumber () + packet->GetSize() <<
":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
m_rxBuffer.MaxRxSequence () << ")");
// Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
@@ -1045,11 +1061,17 @@ TcpSocketBase::ProcessListen (Ptr<Packet> packet, const TcpHeader& tcpHeader,
// Fork a socket if received a SYN. Do nothing otherwise.
// C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
if (tcpflags != TcpHeader::SYN) return;
if (tcpflags != TcpHeader::SYN)
{
return;
}
// Call socket's notify function to let the server app know we got a SYN
// If the server app refuses the connection, do nothing
if (!NotifyConnectionRequest (fromAddress)) return;
if (!NotifyConnectionRequest (fromAddress))
{
return;
}
// Clone the socket, simulate fork
Ptr<TcpSocketBase> newSock = Fork ();
NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
@@ -1108,7 +1130,7 @@ TcpSocketBase::ProcessSynSent (Ptr<Packet> packet, const TcpHeader& tcpHeader)
{ // Other in-sequence input
if (tcpflags != TcpHeader::RST)
{ // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t>(tcpflags) << std::dec << " received. Reset packet is sent.");
NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t> (tcpflags) << std::dec << " received. Reset packet is sent.");
SendRST ();
}
CloseAndNotify ();
@@ -1125,9 +1147,9 @@ TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader,
// Extract the flags. PSH and URG are not honoured.
uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
if (tcpflags == 0 ||
(tcpflags == TcpHeader::ACK
&& m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
if (tcpflags == 0
|| (tcpflags == TcpHeader::ACK
&& m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
{ // If it is bare data, accept it and move to ESTABLISHED state. This is
// possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
// handshake is completed nicely.
@@ -1221,8 +1243,8 @@ TcpSocketBase::ProcessWait (Ptr<Packet> packet, const TcpHeader& tcpHeader)
else if (tcpflags == TcpHeader::ACK)
{ // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
ReceivedAck (packet, tcpHeader);
if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0 &&
tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0
&& tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
{ // This ACK corresponds to the FIN sent
NS_LOG_INFO ("FIN_WAIT_1 -> FIN_WAIT_2");
m_state = FIN_WAIT_2;
@@ -1258,8 +1280,8 @@ TcpSocketBase::ProcessWait (Ptr<Packet> packet, const TcpHeader& tcpHeader)
{
NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
m_state = CLOSING;
if (m_txBuffer.Size () == 0 &&
tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
if (m_txBuffer.Size () == 0
&& tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
{ // This ACK corresponds to the FIN sent
TimeWait ();
}
@@ -1267,9 +1289,12 @@ TcpSocketBase::ProcessWait (Ptr<Packet> packet, const TcpHeader& tcpHeader)
else if (m_state == FIN_WAIT_2)
{
TimeWait ();
};
}
SendEmptyPacket (TcpHeader::ACK);
if (!m_shutdownRecv) NotifyDataRecv ();
if (!m_shutdownRecv)
{
NotifyDataRecv ();
}
}
}
@@ -1348,11 +1373,11 @@ TcpSocketBase::PeerClose (Ptr<Packet> p, const TcpHeader& tcpHeader)
NS_LOG_FUNCTION (this << tcpHeader);
// Ignore all out of range packets
if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence () ||
tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ())
if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence ()
|| tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ())
{
return;
};
}
// For any case, remember the FIN position in rx buffer first
m_rxBuffer.SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
@@ -1365,7 +1390,7 @@ TcpSocketBase::PeerClose (Ptr<Packet> p, const TcpHeader& tcpHeader)
if (!m_rxBuffer.Finished ())
{
return;
};
}
// Simultaneous close: Application invoked Close() when we are processing this FIN packet
if (m_state == FIN_WAIT_1)
@@ -1770,8 +1795,11 @@ bool
TcpSocketBase::SendPendingData (bool withAck)
{
NS_LOG_FUNCTION (this << withAck);
if (m_txBuffer.Size () == 0) return false; // Nothing to send
if (m_txBuffer.Size () == 0)
{
return false; // Nothing to send
}
if (m_endPoint == 0 && m_endPoint6 == 0)
{
NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
@@ -1802,8 +1830,8 @@ TcpSocketBase::SendPendingData (bool withAck)
}
// Nagle's algorithm (RFC896): Hold off sending if there is unacked data
// in the buffer and the amount of data to send is less than one segment
if (!m_noDelay && UnAckDataCount () > 0 &&
m_txBuffer.SizeFromSequence (m_nextTxSequence) < m_segmentSize)
if (!m_noDelay && UnAckDataCount () > 0
&& m_txBuffer.SizeFromSequence (m_nextTxSequence) < m_segmentSize)
{
NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
break;
@@ -1893,7 +1921,10 @@ TcpSocketBase::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader)
// Notify app to receive if necessary
if (expectedSeq < m_rxBuffer.NextRxSequence ())
{ // NextRxSeq advanced, we have something to send to the app
if (!m_shutdownRecv) NotifyDataRecv ();
if (!m_shutdownRecv)
{
NotifyDataRecv ();
}
// Handle exceptions
if (m_closeNotified)
{
@@ -1916,7 +1947,7 @@ TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader)
// (which should be ignored) is handled by m_rtt. Once timestamp option
// is implemented, this function would be more elaborated.
m_lastRtt = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
};
}
// Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
// when the three-way handshake completed. This cancels retransmission timer
@@ -1979,9 +2010,15 @@ TcpSocketBase::ReTxTimeout ()
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
// If erroneous timeout in closed/timed-wait state, just return
if (m_state == CLOSED || m_state == TIME_WAIT) return;
if (m_state == CLOSED || m_state == TIME_WAIT)
{
return;
}
// If all data are received (non-closing socket and nothing to send), just return
if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return;
if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark)
{
return;
}
Retransmit ();
}
@@ -2112,7 +2149,7 @@ TcpSocketBase::TimeWait ()
CancelAllTimers ();
// Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
// according to RFC793, p.28
m_timewaitEvent = Simulator::Schedule (Seconds (2*m_msl),
m_timewaitEvent = Simulator::Schedule (Seconds (2 * m_msl),
&TcpSocketBase::CloseAndNotify, this);
}

View File

@@ -0,0 +1,430 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 Universita' di Firenze, Italy
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
*/
/**
* This is the test code for ipv6-l3protocol.cc (only the fragmentation and reassembly part).
*/
#define NS3_LOG_ENABLE 1
#include "ns3/test.h"
#include "ns3/config.h"
#include "ns3/uinteger.h"
#include "ns3/socket-factory.h"
#include "ns3/ipv4-raw-socket-factory.h"
#include "ns3/ipv6-raw-socket-factory.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/simulator.h"
#include "error-channel.h"
#include "error-net-device.h"
#include "ns3/drop-tail-queue.h"
#include "ns3/socket.h"
#include "ns3/udp-socket.h"
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/boolean.h"
#include "ns3/ipv6-static-routing.h"
#include "ns3/ipv6-list-routing.h"
#include "ns3/inet6-socket-address.h"
#
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/ipv4-list-routing.h"
#include "ns3/ipv4-static-routing.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/icmpv6-l4-protocol.h"
#include <string>
#include <limits>
#include <netinet/in.h>
namespace ns3 {
class UdpSocketImpl;
static void
AddInternetStack (Ptr<Node> node)
{
//IPV6
Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
//Routing for Ipv6
Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
ipv6->SetRoutingProtocol (ipv6Routing);
Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
node->AggregateObject (ipv6);
//ICMPv6
Ptr<Icmpv6L4Protocol> icmp6 = CreateObject<Icmpv6L4Protocol> ();
node->AggregateObject (icmp6);
//Ipv6 Extensions
ipv6->RegisterExtensions ();
ipv6->RegisterOptions ();
//UDP
Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
node->AggregateObject (udp);
}
class Ipv6FragmentationTest : public TestCase
{
Ptr<Packet> m_sentPacketClient;
Ptr<Packet> m_receivedPacketClient;
Ptr<Packet> m_receivedPacketServer;
Ptr<Socket> m_socketServer;
Ptr<Socket> m_socketClient;
uint32_t m_dataSize;
uint8_t *m_data;
uint32_t m_size;
uint8_t m_icmpType;
uint8_t m_icmpCode;
public:
virtual void DoRun (void);
Ipv6FragmentationTest ();
~Ipv6FragmentationTest ();
// server part
void StartServer (Ptr<Node> ServerNode);
void HandleReadServer (Ptr<Socket> socket);
// client part
void StartClient (Ptr<Node> ClientNode);
void HandleReadClient (Ptr<Socket> socket);
void HandleReadIcmpClient (Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType,
uint8_t icmpCode,uint32_t icmpInfo);
void SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize);
Ptr<Packet> SendClient (void);
};
Ipv6FragmentationTest::Ipv6FragmentationTest ()
: TestCase ("Verify the IPv6 layer 3 protocol fragmentation and reassembly")
{
m_socketServer = 0;
m_data = 0;
m_dataSize = 0;
}
Ipv6FragmentationTest::~Ipv6FragmentationTest ()
{
if ( m_data )
{
delete[] m_data;
}
m_data = 0;
m_dataSize = 0;
}
void
Ipv6FragmentationTest::StartServer (Ptr<Node> ServerNode)
{
if (m_socketServer == 0)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socketServer = Socket::CreateSocket (ServerNode, tid);
Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address ("2001::1"), 9);
m_socketServer->Bind (local);
Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socketServer);
}
m_socketServer->SetRecvCallback (MakeCallback (&Ipv6FragmentationTest::HandleReadServer, this));
}
void
Ipv6FragmentationTest::HandleReadServer (Ptr<Socket> socket)
{
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom (from)))
{
if (Inet6SocketAddress::IsMatchingType (from))
{
packet->RemoveAllPacketTags ();
packet->RemoveAllByteTags ();
m_receivedPacketServer = packet->Copy ();
}
}
}
void
Ipv6FragmentationTest::StartClient (Ptr<Node> ClientNode)
{
if (m_socketClient == 0)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socketClient = Socket::CreateSocket (ClientNode, tid);
m_socketClient->Bind (Inet6SocketAddress (Ipv6Address::GetAny (), 9));
m_socketClient->Connect (Inet6SocketAddress (Ipv6Address ("2001::1"), 9));
CallbackValue cbValue = MakeCallback (&Ipv6FragmentationTest::HandleReadIcmpClient, this);
m_socketClient->SetAttribute ("IcmpCallback6", cbValue);
}
m_socketClient->SetRecvCallback (MakeCallback (&Ipv6FragmentationTest::HandleReadClient, this));
}
void
Ipv6FragmentationTest::HandleReadClient (Ptr<Socket> socket)
{
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom (from)))
{
if (Inet6SocketAddress::IsMatchingType (from))
{
m_receivedPacketClient = packet->Copy ();
}
}
}
void
Ipv6FragmentationTest::HandleReadIcmpClient (Ipv6Address icmpSource,
uint8_t icmpTtl, uint8_t icmpType,
uint8_t icmpCode, uint32_t icmpInfo)
{
m_icmpType = icmpType;
m_icmpCode = icmpCode;
}
void
Ipv6FragmentationTest::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
{
if (dataSize != m_dataSize)
{
delete [] m_data;
m_data = new uint8_t [dataSize];
m_dataSize = dataSize;
}
if (fillSize >= dataSize)
{
memcpy (m_data, fill, dataSize);
return;
}
uint32_t filled = 0;
while (filled + fillSize < dataSize)
{
memcpy (&m_data[filled], fill, fillSize);
filled += fillSize;
}
memcpy (&m_data[filled], fill, dataSize - filled);
m_size = dataSize;
}
Ptr<Packet> Ipv6FragmentationTest::SendClient (void)
{
Ptr<Packet> p;
if (m_dataSize)
{
p = Create<Packet> (m_data, m_dataSize);
}
else
{
p = Create<Packet> (m_size);
}
m_socketClient->Send (p);
return p;
}
void
Ipv6FragmentationTest::DoRun (void)
{
// set the arp cache to something quite high
// we shouldn't need because the NetDevice used doesn't need arp, but still
// Config::SetDefault ("ns3::ArpCache::PendingQueueSize", UintegerValue (100));
// LogComponentEnable ("ErrorNetDevice", LOG_LEVEL_ALL);
// LogComponentEnableAll(LOG_LEVEL_ALL);
// Create topology
// Receiver Node
Ptr<Node> serverNode = CreateObject<Node> ();
AddInternetStack (serverNode);
Ptr<ErrorNetDevice> serverDev;
Ptr<BinaryErrorModel> serverDevErrorModel = CreateObject<BinaryErrorModel> ();
{
serverDev = CreateObject<ErrorNetDevice> ();
serverDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
serverDev->SetMtu (1500);
serverDev->SetReceiveErrorModel (serverDevErrorModel);
serverDevErrorModel->Disable ();
serverNode->AddDevice (serverDev);
Ptr<Ipv6> ipv6 = serverNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (serverDev);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001::1"), Ipv6Prefix (32));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
StartServer (serverNode);
// Sender Node
Ptr<Node> clientNode = CreateObject<Node> ();
AddInternetStack (clientNode);
Ptr<ErrorNetDevice> clientDev;
Ptr<BinaryErrorModel> clientDevErrorModel = CreateObject<BinaryErrorModel> ();
{
clientDev = CreateObject<ErrorNetDevice> ();
clientDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
clientDev->SetMtu (1000);
clientDev->SetReceiveErrorModel (clientDevErrorModel);
clientDevErrorModel->Disable ();
clientNode->AddDevice (clientDev);
Ptr<Ipv6> ipv6 = clientNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (clientDev);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001::2"), Ipv6Prefix (32));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
StartClient (clientNode);
// link the two nodes
Ptr<ErrorChannel> channel = CreateObject<ErrorChannel> ();
serverDev->SetChannel (channel);
clientDev->SetChannel (channel);
channel->SetJumpingTime (Seconds (0.5));
// some small packets, some rather big ones
uint32_t packetSizes[5] = {1000, 2000, 5000, 10000, 65000};
// using the alphabet
uint8_t fillData[78];
for ( uint32_t k = 48; k <= 125; k++ )
{
fillData[k - 48] = k;
}
// First test: normal channel, no errors, no delays
for ( int i = 0; i < 5; i++)
{
uint32_t packetSize = packetSizes[i];
SetFill (fillData, 78, packetSize);
m_receivedPacketServer = Create<Packet> ();
Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
&Ipv6FragmentationTest::SendClient, this);
Simulator::Run ();
uint8_t recvBuffer[65000];
uint16_t recvSize = m_receivedPacketServer->GetSize ();
NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
"Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
m_receivedPacketServer->CopyData (recvBuffer, 65000);
NS_TEST_EXPECT_MSG_EQ (memcmp (m_data, recvBuffer, m_receivedPacketServer->GetSize ()),
0, "Packet content differs");
}
// Second test: normal channel, no errors, delays each 2 packets.
// Each other fragment will arrive out-of-order.
// The packets should be received correctly since reassembly will reorder the fragments.
channel->SetJumpingMode (true);
for ( int i = 0; i < 5; i++)
{
uint32_t packetSize = packetSizes[i];
SetFill (fillData, 78, packetSize);
m_receivedPacketServer = Create<Packet> ();
Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
&Ipv6FragmentationTest::SendClient, this);
Simulator::Run ();
uint8_t recvBuffer[65000];
uint16_t recvSize = m_receivedPacketServer->GetSize ();
NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
"Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
m_receivedPacketServer->CopyData (recvBuffer, 65000);
NS_TEST_EXPECT_MSG_EQ (memcmp (m_data, recvBuffer, m_receivedPacketServer->GetSize ()),
0, "Packet content differs");
}
channel->SetJumpingMode (false);
// Third test: normal channel, some errors, no delays.
// The reassembly procedure should fire a timeout after 30 seconds (as specified in the RFCs).
// Upon the timeout, the fragments received so far are discarded and an ICMP should be sent back
// to the sender (if the first fragment has been received).
// In this test case the first fragment is received, so we do expect an ICMP.
// Client -> Server : errors enabled
// Server -> Client : errors disabled (we want to have back the ICMP)
clientDevErrorModel->Disable ();
serverDevErrorModel->Enable ();
for ( int i = 1; i < 5; i++)
{
uint32_t packetSize = packetSizes[i];
SetFill (fillData, 78, packetSize);
// reset the model, we want to receive the very first fragment.
serverDevErrorModel->Reset ();
m_receivedPacketServer = Create<Packet> ();
m_icmpType = 0;
m_icmpCode = 0;
Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
&Ipv6FragmentationTest::SendClient, this);
Simulator::Run ();
uint16_t recvSize = m_receivedPacketServer->GetSize ();
NS_TEST_EXPECT_MSG_EQ ((recvSize == 0), true, "Server got a packet, something wrong");
NS_TEST_EXPECT_MSG_EQ ((m_icmpType == Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED)
&& (m_icmpCode == Icmpv6Header::ICMPV6_FRAGTIME),
true, "Client did not receive ICMPv6::TIME_EXCEEDED " << int(m_icmpType) << int(m_icmpCode) );
}
Simulator::Destroy ();
}
//-----------------------------------------------------------------------------
class Ipv6FragmentationTestSuite : public TestSuite
{
public:
Ipv6FragmentationTestSuite () : TestSuite ("ipv6-fragmentation", UNIT)
{
AddTestCase (new Ipv6FragmentationTest);
}
} g_ipv6fragmentationTestSuite;
}; // namespace ns3

View File

@@ -206,6 +206,7 @@ def build(bld):
'test/udp-test.cc',
'test/ipv6-address-generator-test-suite.cc',
'test/ipv6-dual-stack-test-suite.cc',
'test/ipv6-fragmentation-test.cc',
]
headers = bld.new_task_gen(features=['ns3header'])