From 6e252ada400bb6748206dda89bf96c6b3b7ad3e4 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Wed, 21 Mar 2012 18:51:55 +0100 Subject: [PATCH] Bug 1362 - ICMPv6 does not forward ICMPs to upper layers --- RELEASE_NOTES | 1 + src/internet/model/icmpv6-l4-protocol.cc | 150 +++++-- src/internet/model/icmpv6-l4-protocol.h | 69 ++- src/internet/model/ipv6-end-point-demux.cc | 117 ++--- src/internet/model/ipv6-end-point-demux.h | 23 +- src/internet/model/ipv6-extension.cc | 69 +-- src/internet/model/ipv6-extension.h | 5 +- src/internet/model/ipv6-l3-protocol.cc | 65 +-- src/internet/model/ipv6-list-routing.cc | 34 +- src/internet/model/ipv6-list-routing.h | 16 +- src/internet/model/ipv6-static-routing.cc | 41 +- src/internet/model/ipv6-static-routing.h | 5 +- src/internet/model/tcp-socket-base.cc | 127 ++++-- src/internet/test/ipv6-fragmentation-test.cc | 430 +++++++++++++++++++ src/internet/wscript | 1 + 15 files changed, 902 insertions(+), 251 deletions(-) create mode 100644 src/internet/test/ipv6-fragmentation-test.cc diff --git a/RELEASE_NOTES b/RELEASE_NOTES index c3212bf2f..2193e43a8 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -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 ------------ diff --git a/src/internet/model/icmpv6-l4-protocol.cc b/src/internet/model/icmpv6-l4-protocol.cc index 93a0c1404..14454f28f 100644 --- a/src/internet/model/icmpv6-l4-protocol.cc +++ b/src/internet/model/icmpv6-l4-protocol.cc @@ -18,6 +18,7 @@ * Author: Sebastien Vincent * David Gross * Mehdi Benamor + * Tommaso Pecorella */ #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 ipv6 = this->GetObject (); if (ipv6 != 0) { - this->SetNode (node); + SetNode (node); ipv6->Insert (this); Ptr rawFactory = CreateObject (); ipv6->AggregateObject (rawFactory); - this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6)); + SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6)); } } } @@ -162,9 +162,9 @@ void Icmpv6L4Protocol::DoDAD (Ipv6Address target, Ptr 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, 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, 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, Ipv6A return IpL4Protocol::RX_OK; } +void Icmpv6L4Protocol::Forward (Ipv6Address source, Icmpv6Header icmp, + uint32_t info, Ipv6Header ipHeader, + const uint8_t payload[8]) +{ + Ptr ipv6 = m_node->GetObject (); + + // TODO assuming the ICMP is carrying a extensionless IP packet + + uint8_t nextHeader = ipHeader.GetNextHeader (); + + Ptr 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, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) { NS_LOG_FUNCTION (this << packet << src << dst << interface); @@ -253,7 +278,7 @@ void Icmpv6L4Protocol::HandleEchoRequest (Ptr packet, Ipv6Address const } void Icmpv6L4Protocol::HandleRA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) -{ +{ NS_LOG_FUNCTION (this << packet << src << dst << interface); Ptr p = packet->Copy (); Icmpv6RA raHeader; @@ -276,7 +301,7 @@ void Icmpv6L4Protocol::HandleRA (Ptr 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 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 >::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, Ipv6Address const &src, Ipv hardwareAddress = interface->GetDevice ()->GetAddress (); Ptr 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, 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, Ipv6Address const &src, Ipv waiting = entry->MarkReachable (lla.GetAddress ()); for (std::list >::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, 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, 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, Ipv6Address const } } +void Icmpv6L4Protocol::HandleDestinationUnreachable (Ptr p, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << *p << src << dst); + Ptr pkt = p->Copy (); + + Icmpv6DestinationUnreachable unreach; + pkt->RemoveHeader (unreach); + Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << *p << src << dst); + Ptr pkt = p->Copy (); + + Icmpv6TimeExceeded timeexceeded; + pkt->RemoveHeader (timeexceeded); + Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << *p << src << dst); + Ptr pkt = p->Copy (); + + Icmpv6TooBig tooBig; + pkt->RemoveHeader (tooBig); + Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << *p << src << dst); + Ptr pkt = p->Copy (); + + Icmpv6ParameterError paramErr; + pkt->RemoveHeader (paramErr); + Ptr 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, 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 malformedPacket, Ipv6Address void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr malformedPacket, Ipv6Address dst, uint8_t code) { - NS_LOG_FUNCTION (this<< malformedPacket << dst << code); + NS_LOG_FUNCTION (this << malformedPacket << dst << code); Ptr p = Create (); uint32_t malformedPacketSize = malformedPacket->GetSize (); Icmpv6TimeExceeded header; @@ -938,7 +1030,7 @@ void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr 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 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 redirectedPacket, Ipv6Addres if ((redirectedPacketSize % 8) != 0) { Ptr pad = Create (8 - (redirectedPacketSize % 8)); - redirectedPacket->AddAtEnd (pad); + redirectedPacket->AddAtEnd (pad); } if (redirHardwareTarget.GetLength ()) @@ -1081,7 +1173,7 @@ Ptr 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 p, Ipv6Address dst, Ptr 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 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 icmpv6, Ipv6Int */ Ptr ipv6 = icmpv6->m_node->GetObject (); - 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 ()); diff --git a/src/internet/model/icmpv6-l4-protocol.h b/src/internet/model/icmpv6-l4-protocol.h index 651ed5906..0ef78470c 100644 --- a/src/internet/model/icmpv6-l4-protocol.h +++ b/src/internet/model/icmpv6-l4-protocol.h @@ -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 p, Ipv4Header const &header, Ptr 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 p, Ipv6Address &src, Ipv6Address &dst, Ptr interface); @@ -396,7 +402,6 @@ protected: virtual void DoDispose (); private: - typedef std::list > 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface); + /** * \brief Link layer address option processing. * \param lla LLA option diff --git a/src/internet/model/ipv6-end-point-demux.cc b/src/internet/model/ipv6-end-point-demux.cc index 466426966..97460a5aa 100644 --- a/src/internet/model/ipv6-end-point-demux.cc +++ b/src/internet/model/ipv6-end-point-demux.cc @@ -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 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 diff --git a/src/internet/model/ipv6-end-point-demux.h b/src/internet/model/ipv6-end-point-demux.h index 03d043c80..db7ee6748 100644 --- a/src/internet/model/ipv6-end-point-demux.h +++ b/src/internet/model/ipv6-end-point-demux.h @@ -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. */ diff --git a/src/internet/model/ipv6-extension.cc b/src/internet/model/ipv6-extension.cc index fc16d0aa5..678e5f92d 100644 --- a/src/internet/model/ipv6-extension.cc +++ b/src/internet/model/ipv6-extension.cc @@ -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, uint8_t offset, Ipv std::pair fragmentsId = std::make_pair (src, identification); Ptr fragments; + Ipv6Header ipHeader = ipv6Header; + ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ()); + MapFragments_t::iterator it = m_fragments.find (fragmentsId); if (it == m_fragments.end ()) { fragments = Create (); 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, 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, uint32_t maxFragme Ptr 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, uint32_t maxFragme unfragmentablePart.push_back (std::make_pair (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, uint32_t maxFragme unfragmentablePart.push_back (std::make_pair (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, 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, 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, uint32_t maxFragme { if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP) { - fragment->AddHeader (*dynamic_cast(it->first)); + fragment->AddHeader (*dynamic_cast (it->first)); } else if (it->second == Ipv6Header::IPV6_EXT_ROUTING) { - fragment->AddHeader (*dynamic_cast(it->first)); + fragment->AddHeader (*dynamic_cast (it->first)); } else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION) { - fragment->AddHeader (*dynamic_cast(it->first)); + fragment->AddHeader (*dynamic_cast (it->first)); } } @@ -534,7 +536,8 @@ void Ipv6ExtensionFragment::GetFragments (Ptr packet, uint32_t maxFragme std::ostringstream oss; fragment->Print (oss); listFragments.push_back (fragment); - } while (moreFragment); + } + while (moreFragment); for (std::list >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++) { @@ -549,17 +552,19 @@ void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair packet = fragments->GetPartialPacket (); + packet->AddHeader (ipHeader); + // if we have at least 8 bytes, we can send an ICMP. if ( packet->GetSize () > 8 ) { - Ptr icmp = GetNode()->GetObject (); + Ptr icmp = GetNode ()->GetObject (); 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 fragment, uint16 m_fragments.insert (it, std::make_pair, uint16_t> (fragment, fragmentOffset)); } -void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr unfragmentablePart) +void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr unfragmentablePart) { m_unfragmentable = unfragmentablePart; } @@ -661,14 +666,14 @@ Ptr 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, uint8_t offset, Ipv6 if (nextHeader) { - *nextHeader = routingNextHeader; + *nextHeader = routingNextHeader; } Ptr icmpv6 = GetNode ()->GetObject ()->GetIcmpv6 (); @@ -918,7 +923,7 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr& 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, 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, uint8_t offset, } /* as we directly send packet, mark it as dropped */ - isDropped = true; + isDropped = true; return routingHeader.GetSerializedSize (); } diff --git a/src/internet/model/ipv6-extension.h b/src/internet/model/ipv6-extension.h index 2d433d7d5..3ba9283b3 100644 --- a/src/internet/model/ipv6-extension.h +++ b/src/internet/model/ipv6-extension.h @@ -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; diff --git a/src/internet/model/ipv6-l3-protocol.cc b/src/internet/model/ipv6-l3-protocol.cc index 134e07ca7..624933621 100644 --- a/src/internet/model/ipv6-l3-protocol.cc +++ b/src/internet/model/ipv6-l3-protocol.cc @@ -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 routingProtoco m_routingProtocol->SetIpv6 (this); } -Ptr Ipv6L3Protocol::GetRoutingProtocol () const +Ptr Ipv6L3Protocol::GetRoutingProtocol () const { NS_LOG_FUNCTION_NOARGS (); return m_routingProtocol; @@ -175,7 +174,7 @@ Ptr 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 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 interface = GetInterface (i); @@ -635,12 +634,12 @@ void Ipv6L3Protocol::Send (Ptr 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 device, Ptr p, uint16 socket->ForwardUp (packet, hdr, device); } - Ptr ipv6ExtensionDemux = m_node->GetObject(); + Ptr ipv6ExtensionDemux = m_node->GetObject (); Ptr ipv6Extension = 0; uint8_t nextHeader = hdr.GetNextHeader (); bool isDropped = false; @@ -763,6 +762,12 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 // Router => drop if (m_ipForward) { + Ptr icmpv6 = GetIcmpv6 (); + if ( icmpv6 ) + { + packet->AddHeader(ipHeader); + icmpv6->SendErrorTooBig (packet, ipHeader.GetSourceAddress (), dev->GetMtu ()); + } return; } @@ -771,7 +776,7 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 packet->AddHeader (ipHeader); // To get specific method GetFragments from Ipv6ExtensionFragmentation - Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast(PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION))); + Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION))); ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments); } @@ -858,8 +863,8 @@ void Ipv6L3Protocol::IpForward (Ptr rtentry, Ptr p, con NS_LOG_WARN ("TTL exceeded. Drop."); m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject (), 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 rtentry, Ptr 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 icmpv6 = GetIcmpv6 (); @@ -940,8 +945,8 @@ void Ipv6L3Protocol::LocalDeliver (Ptr packet, Ipv6Header const& i { NS_LOG_FUNCTION (this << packet << ip << iif); Ptr p = packet->Copy (); - Ptr protocol = 0; - Ptr ipv6ExtensionDemux = m_node->GetObject(); + Ptr protocol = 0; + Ptr ipv6ExtensionDemux = m_node->GetObject (); Ptr ipv6Extension = 0; Ipv6Address src = ip.GetSourceAddress (); Ipv6Address dst = ip.GetDestinationAddress (); @@ -961,7 +966,8 @@ void Ipv6L3Protocol::LocalDeliver (Ptr 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 packet, Ipv6Header const& i } } } - } while (ipv6Extension); + } + while (ipv6Extension); } void Ipv6L3Protocol::RouteInputError (Ptr p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno) diff --git a/src/internet/model/ipv6-list-routing.cc b/src/internet/model/ipv6-list-routing.cc index 9e24a8ca4..f6f5a4e4b 100644 --- a/src/internet/model/ipv6-list-routing.cc +++ b/src/internet/model/ipv6-list-routing.cc @@ -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 p, const Ipv6Header &header, Ptr p, const Ipv6Header &header, Ptr idev, - UnicastForwardCallback ucb, MulticastForwardCallback mcb, +bool +Ipv6ListRouting::RouteInput (Ptr p, const Ipv6Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb) { bool retVal = false; @@ -104,9 +104,9 @@ Ipv6ListRouting::RouteInput (Ptr p, const Ipv6Header &header, Ptr< NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv6->GetObject ()->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 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 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) { NS_LOG_FUNCTION (this << ipv6); @@ -296,14 +296,14 @@ Ipv6ListRouting::AddRoutingProtocol (Ptr routingProtocol, i } } -uint32_t +uint32_t Ipv6ListRouting::GetNRoutingProtocols (void) const { NS_LOG_FUNCTION (this); - return m_routingProtocols.size (); + return m_routingProtocols.size (); } -Ptr +Ptr 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; diff --git a/src/internet/model/ipv6-list-routing.h b/src/internet/model/ipv6-list-routing.h index 77b2b18f9..0e01955f5 100644 --- a/src/internet/model/ipv6-list-routing.h +++ b/src/internet/model/ipv6-list-routing.h @@ -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 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 > Ipv6RoutingProtocolEntry; diff --git a/src/internet/model/ipv6-static-routing.cc b/src/internet/model/ipv6-static-routing.cc index 0b762d458..90be08299 100644 --- a/src/internet/model/ipv6-static-routing.cc +++ b/src/internet/model/ipv6-static-routing.cc @@ -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) { 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 Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr 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 (); @@ -294,7 +293,7 @@ Ptr Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr } } - if(rtentry) + if (rtentry) { NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (throught " << rtentry->GetGateway () << ") at the end"); } @@ -364,7 +363,7 @@ Ptr 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 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 */ diff --git a/src/internet/model/ipv6-static-routing.h b/src/internet/model/ipv6-static-routing.h index 8a2112dbc..2fda63097 100644 --- a/src/internet/model/ipv6-static-routing.h +++ b/src/internet/model/ipv6-static-routing.h @@ -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 > NetworkRoutes; diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index e46828282..c4751afce 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -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 (this))); + m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr (this))); m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr (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, 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, 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, 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, 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 newSock = Fork (); NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock); @@ -1108,7 +1130,7 @@ TcpSocketBase::ProcessSynSent (Ptr 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(tcpflags) << std::dec << " received. Reset packet is sent."); + NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast (tcpflags) << std::dec << " received. Reset packet is sent."); SendRST (); } CloseAndNotify (); @@ -1125,9 +1147,9 @@ TcpSocketBase::ProcessSynRcvd (Ptr 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, 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, 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, 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 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 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 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); } diff --git a/src/internet/test/ipv6-fragmentation-test.cc b/src/internet/test/ipv6-fragmentation-test.cc new file mode 100644 index 000000000..629861480 --- /dev/null +++ b/src/internet/test/ipv6-fragmentation-test.cc @@ -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 + */ +/** + * 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 +#include +#include + +namespace ns3 { + +class UdpSocketImpl; + +static void +AddInternetStack (Ptr node) +{ + //IPV6 + Ptr ipv6 = CreateObject (); + + //Routing for Ipv6 + Ptr ipv6Routing = CreateObject (); + ipv6->SetRoutingProtocol (ipv6Routing); + Ptr ipv6staticRouting = CreateObject (); + ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0); + node->AggregateObject (ipv6); + + //ICMPv6 + Ptr icmp6 = CreateObject (); + node->AggregateObject (icmp6); + + //Ipv6 Extensions + ipv6->RegisterExtensions (); + ipv6->RegisterOptions (); + + //UDP + Ptr udp = CreateObject (); + node->AggregateObject (udp); +} + + +class Ipv6FragmentationTest : public TestCase +{ + Ptr m_sentPacketClient; + Ptr m_receivedPacketClient; + Ptr m_receivedPacketServer; + + + Ptr m_socketServer; + Ptr 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 ServerNode); + void HandleReadServer (Ptr socket); + + // client part + void StartClient (Ptr ClientNode); + void HandleReadClient (Ptr 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 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 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 = DynamicCast (m_socketServer); + } + + m_socketServer->SetRecvCallback (MakeCallback (&Ipv6FragmentationTest::HandleReadServer, this)); +} + +void +Ipv6FragmentationTest::HandleReadServer (Ptr socket) +{ + Ptr packet; + Address from; + while ((packet = socket->RecvFrom (from))) + { + if (Inet6SocketAddress::IsMatchingType (from)) + { + packet->RemoveAllPacketTags (); + packet->RemoveAllByteTags (); + + m_receivedPacketServer = packet->Copy (); + } + } +} + +void +Ipv6FragmentationTest::StartClient (Ptr 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) +{ + Ptr 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 Ipv6FragmentationTest::SendClient (void) +{ + Ptr p; + if (m_dataSize) + { + p = Create (m_data, m_dataSize); + } + else + { + p = Create (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 serverNode = CreateObject (); + AddInternetStack (serverNode); + Ptr serverDev; + Ptr serverDevErrorModel = CreateObject (); + { + serverDev = CreateObject (); + serverDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + serverDev->SetMtu (1500); + serverDev->SetReceiveErrorModel (serverDevErrorModel); + serverDevErrorModel->Disable (); + serverNode->AddDevice (serverDev); + Ptr ipv6 = serverNode->GetObject (); + 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 clientNode = CreateObject (); + AddInternetStack (clientNode); + Ptr clientDev; + Ptr clientDevErrorModel = CreateObject (); + { + clientDev = CreateObject (); + clientDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ())); + clientDev->SetMtu (1000); + clientDev->SetReceiveErrorModel (clientDevErrorModel); + clientDevErrorModel->Disable (); + clientNode->AddDevice (clientDev); + Ptr ipv6 = clientNode->GetObject (); + 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 channel = CreateObject (); + 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 (); + 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 (); + 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 (); + 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 diff --git a/src/internet/wscript b/src/internet/wscript index d09f906bb..e250a1e24 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -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'])