Bug 1362 - ICMPv6 does not forward ICMPs to upper layers
This commit is contained in:
@@ -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
|
||||
------------
|
||||
|
||||
@@ -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 ());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
430
src/internet/test/ipv6-fragmentation-test.cc
Normal file
430
src/internet/test/ipv6-fragmentation-test.cc
Normal 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
|
||||
@@ -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'])
|
||||
|
||||
Reference in New Issue
Block a user