25 #include "ns3/assert.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/object-vector.h"
28 #include "ns3/ipv6-address.h"
29 #include "ns3/ipv6-header.h"
30 #include "ns3/ipv6-l3-protocol.h"
31 #include "ns3/ipv6-static-routing.h"
32 #include "ns3/ipv6-list-routing.h"
33 #include "ns3/ipv6-route.h"
34 #include "ns3/trace-source-accessor.h"
35 #include "icmpv6-l4-protocol.h"
36 #include "ipv6-extension-demux.h"
37 #include "ipv6-extension.h"
38 #include "ipv6-extension-header.h"
39 #include "ipv6-option-demux.h"
40 #include "ipv6-option.h"
41 #include "udp-header.h"
47 NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension);
53 .AddAttribute (
"ExtensionNumber",
"The IPv6 extension number.",
56 MakeUintegerChecker<uint8_t> ())
57 .AddTraceSource (
"Drop",
"Drop ipv6 packet",
67 m_uvar = CreateObject<UniformRandomVariable> ();
91 NS_LOG_FUNCTION (
this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
104 uint8_t processedSize = 0;
106 uint8_t *data =
new uint8_t[size];
109 uint8_t optionType = 0;
110 uint8_t optionLength = 0;
112 while (length > processedSize && !isDropped)
114 optionType = *(data + processedSize);
115 ipv6Option = ipv6OptionDemux->GetOption (optionType);
123 optionLength = *(data + processedSize + 1) + 2;
135 icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.
GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
146 icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.
GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
165 optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
168 processedSize += optionLength;
174 return processedSize;
189 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionHopByHop")
191 .AddConstructor<Ipv6ExtensionHopByHop> ()
215 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
228 offset += processedSize;
231 processedSize +=
ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
233 return processedSize;
241 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionDestination")
243 .AddConstructor<Ipv6ExtensionDestination> ()
267 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
280 offset += processedSize;
283 processedSize +=
ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
285 return processedSize;
293 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionFragment")
295 .AddConstructor<Ipv6ExtensionFragment> ()
332 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
346 uint16_t fragmentOffset = fragmentHeader.
GetOffset ();
350 std::pair<Ipv6Address, uint32_t> fragmentsId = std::make_pair<Ipv6Address, uint32_t> (src, identification);
356 MapFragments_t::iterator it =
m_fragments.find (fragmentsId);
359 fragments = Create<Fragments> ();
360 m_fragments.insert (std::make_pair (fragmentsId, fragments));
363 fragmentsId, ipHeader);
364 fragments->SetTimeoutEventId (timeout);
368 fragments = it->second;
371 if (fragmentOffset == 0)
375 fragments->SetUnfragmentablePart (unfragmentablePart);
378 fragments->AddFragment (p, fragmentOffset, moreFragment);
380 if (fragments->IsEntire ())
382 packet = fragments->GetPacket ();
383 fragments->CancelTimeout ();
409 bool moreHeader =
true;
410 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
411 || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
414 ipv6Header.
SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
417 std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
418 uint32_t unfragmentablePartSize = 0;
422 uint8_t extensionHeaderLength;
426 if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
432 extensionHeaderLength = hopbyhopHeader->
GetLength ();
437 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
438 || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
441 hopbyhopHeader->
SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
444 unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
445 unfragmentablePartSize += extensionHeaderLength;
447 else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
451 uint8_t numberAddress = buf[1] / 2;
457 extensionHeaderLength = routingHeader->
GetLength ();
461 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
462 || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
465 routingHeader->
SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
468 unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
469 unfragmentablePartSize += extensionHeaderLength;
471 else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
477 extensionHeaderLength = destinationHeader->
GetLength ();
481 if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
482 || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
485 destinationHeader->
SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
488 unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
489 unfragmentablePartSize += extensionHeaderLength;
496 uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
497 uint32_t currentFragmentablePartSize = 0;
499 bool moreFragment =
true;
500 uint32_t identification = (uint32_t)
m_uvar->
GetValue (0, (uint32_t)-1);
505 if (p->
GetSize () > offset + maxFragmentablePartSize)
508 currentFragmentablePartSize = maxFragmentablePartSize;
512 moreFragment =
false;
513 currentFragmentablePartSize = p->
GetSize () - offset;
516 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
519 fragmentHeader.
SetLength (currentFragmentablePartSize);
525 offset += currentFragmentablePartSize;
529 for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
531 if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
533 fragment->
AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first));
535 else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
537 fragment->
AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first));
539 else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
541 fragment->
AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first));
548 std::ostringstream oss;
549 fragment->
Print (oss);
550 listFragments.push_back (fragment);
552 while (moreFragment);
554 for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
559 unfragmentablePart.clear ();
568 MapFragments_t::iterator it =
m_fragments.find (fragmentsId);
570 fragments = it->second;
572 Ptr<Packet> packet = fragments->GetPartialPacket ();
580 icmp->SendErrorTimeExceeded (packet, ipHeader.
GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
599 std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
601 for (it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
603 if (it->second > fragmentOffset)
609 if (it == m_packetFragments.end ())
611 m_moreFragment = moreFragment;
614 m_packetFragments.insert (it, std::make_pair<
Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
619 m_unfragmentable = unfragmentablePart;
624 bool ret = !m_moreFragment && m_packetFragments.size () > 0;
628 uint16_t lastEndOffset = 0;
630 for (std::list<std::pair<
Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
632 if (lastEndOffset != it->second)
638 lastEndOffset += it->first->GetSize ();
649 for (std::list<std::pair<
Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
661 if ( m_unfragmentable )
663 p = m_unfragmentable->
Copy ();
670 uint16_t lastEndOffset = 0;
672 for (std::list<std::pair<
Ptr<Packet>, uint16_t> >::const_iterator it = m_packetFragments.begin (); it != m_packetFragments.end (); it++)
674 if (lastEndOffset != it->second)
679 lastEndOffset += it->first->GetSize ();
687 m_timeoutEventId = event;
693 m_timeoutEventId.Cancel ();
702 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionRouting")
704 .AddConstructor<Ipv6ExtensionRouting> ()
734 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
744 packet->
CopyData (buf,
sizeof(buf));
746 uint8_t routingNextHeader = buf[0];
747 uint8_t routingLength = buf[1];
748 uint8_t routingTypeRouting = buf[2];
749 uint8_t routingSegmentsLeft = buf[3];
753 *nextHeader = routingNextHeader;
761 if (ipv6ExtensionRouting == 0)
763 if (routingSegmentsLeft == 0)
771 icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.
GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
776 return routingLength;
779 return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
787 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionRoutingDemux")
789 .AddAttribute (
"Routing Extensions",
"The set of IPv6 Routing extensions registered with this demux.",
792 MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
807 for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
812 m_extensionsRouting.clear ();
824 m_extensionsRouting.push_back (extensionRouting);
829 for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
831 if ((*i)->GetTypeRouting () == typeRouting)
841 m_extensionsRouting.remove (extensionRouting);
849 static TypeId tid =
TypeId (
"ns3::Ipv6ExtensionLooseRouting")
851 .AddConstructor<Ipv6ExtensionLooseRouting> ()
875 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
895 uint8_t numberAddress = buf[1] / 2;
911 uint8_t length = (routingHeader.
GetLength () >> 3) - 1;
912 uint8_t nbAddress = length / 2;
913 uint8_t nextAddressIndex;
916 if (segmentsLeft == 0)
925 icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
931 if (segmentsLeft > nbAddress)
934 icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
941 nextAddressIndex = nbAddress - segmentsLeft;
957 icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
976 Socket::SocketErrno err;
979 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
984 ipv6->SendRealOut (rtentry, p, ipv6header);
1004 .AddConstructor<Ipv6ExtensionESP> ()
1028 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1042 .AddConstructor<Ipv6ExtensionAH> ()
1066 NS_LOG_FUNCTION (
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
void GetFragments(Ptr< Packet > packet, uint32_t fragmentSize, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
uint32_t RemoveHeader(Header &header)
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
Ptr< UniformRandomVariable > m_uvar
Provides uniform random variables.
IPv6 Extension base If you want to implement a new IPv6 extension, all you have to do is implement a ...
int64_t AssignStreams(int64_t stream)
Ipv6ExtensionLooseRouting()
Constructor.
virtual void DoDispose()
Dispose this object.
#define NS_LOG_FUNCTION(parameters)
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
TracedCallback< Ptr< const Packet > > m_dropTrace
Drop trace callback.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
Ptr< Packet > GetPartialPacket() const
Get the packet parts so far received.
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
IPv6 layer implementation.
Demultiplexes IPv6 extensions.
automatically resized byte buffer
void SetNode(Ptr< Node > node)
Set the node.
#define NS_ASSERT(condition)
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
virtual void DoDispose()
Dispose this object.
#define NS_LOG_COMPONENT_DEFINE(name)
virtual uint8_t GetExtensionNumber() const
Get the extension number.
uint32_t GetSize(void) const
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual void DoDispose(void)
static TypeId GetTypeId()
Get the type identificator.
#define NS_LOG_FUNCTION_NOARGS()
virtual ~Ipv6ExtensionRoutingDemux()
Destructor.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Ipv6ExtensionRoutingDemux()
Constructor.
void Print(std::ostream &os) const
IPv6 Extension Destination.
Ipv6ExtensionFragment()
Constructor.
~Ipv6ExtensionDestination()
Destructor.
iterator in a Buffer instance
virtual uint8_t GetExtensionNumber() const
Get the extension number.
IPv6 Extension Routing If you want to implement a new IPv6 routing extension, all you have to do is i...
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionHopByHop()
Destructor.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
void AddAtEnd(Ptr< const Packet > packet)
~Ipv6ExtensionLooseRouting()
Destructor.
void RemoveAtStart(uint32_t size)
void SetTimeoutEventId(EventId event)
Set the Timeout EventId.
Ipv6ExtensionHopByHop()
Constructor.
void HandleFragmentsTimeout(std::pair< Ipv6Address, uint32_t > key, Ipv6Header &ipHeader)
Process the timeout for packet fragments.
Hold an unsigned integer type.
Ptr< Packet > GetPacket() const
Get the entire packet.
IPv6 Extension ESP (Encapsulating Security Payload)
~Ipv6ExtensionFragment()
Destructor.
void CancelTimeout()
Cancel the timeout event.
An implementation of the ICMPv6 protocol.
~Ipv6ExtensionRouting()
Destructor.
static TypeId GetTypeId()
Get the type identificator.
#define NS_LOG_LOGIC(msg)
Buffer::Iterator Begin(void) const
Ipv6ExtensionDestination()
Constructor.
IPv6 Extension Routing Demux.
void SetUnfragmentablePart(Ptr< Packet > unfragmentablePart)
Set the unfragmentable part of the packet.
bool IsEntire() const
If all fragments have been added.
IPv6 Extension "Hop By Hop".
Ptr< Node > GetNode() const
Get the node.
void Remove(Ptr< Ipv6ExtensionRouting > extensionRouting)
Remove a routing extension from this demux.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ptr< Packet > Copy(void) const
void SetNode(Ptr< Node > node)
Set the node.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t ProcessOptions(Ptr< Packet > &packet, uint8_t offset, uint8_t length, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process options Called by implementing classes to process the options.
static TypeId GetTypeId()
Get the type identificator.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
uint32_t GetOptionsOffset()
Get the offset where the options begin, measured from the start of the extension header.
MapFragments_t m_fragments
The hash of fragmented packets.
void RemoveAtEnd(uint32_t size)
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
static TypeId GetTypeId()
The interface ID.
static TypeId GetTypeId()
Get the type identificator.
Ptr< Ipv6ExtensionRouting > GetExtensionRouting(uint8_t typeRouting)
Get the routing extension corresponding to typeRouting.
~Ipv6ExtensionESP()
Destructor.
Ipv6ExtensionAH()
Constructor.
static TypeId GetTypeId()
Get the type identificator.
IPv6 Extension Loose Routing.
virtual uint8_t GetExtensionNumber() const =0
Get the extension number.
static const uint8_t EXT_NUMBER
Hop-by-hop extension number.
#define NS_ASSERT_MSG(condition, message)
Ipv6Extension()
Constructor.
Describes an IPv6 address.
virtual uint8_t GetTypeRouting() const
Get the type of routing.
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method.
an identifier for simulation events.
Ipv6ExtensionRouting()
Constructor.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t GetExtensionNumber() const
Get the extension number.
virtual uint8_t GetTypeRouting() const
Get the type of routing.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Ipv6ExtensionRoutingList_t m_extensionsRouting
List of IPv6 Routing Extensions supported.
Ipv6ExtensionESP()
Constructor.
bool AddAtStart(uint32_t start)
a base class which provides memory management and object aggregation
static const uint8_t EXT_NUMBER
Destination extension number.
contain a set of ns3::Object pointers.
Ptr< Node > m_node
The node.
Ptr< T > GetObject(void) const
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
static TypeId GetTypeId()
Get the type identificator.
void AddHeader(const Header &header)
~Ipv6ExtensionAH()
Destructor.
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method Called from Ipv6L3Protocol::Receive.
virtual ~Ipv6Extension()
Destructor.
IPv6 Extension AH (Authentication Header)
virtual uint8_t Process(Ptr< Packet > &packet, uint8_t offset, Ipv6Header const &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &isDropped)
Process method.