31#include "ns3/assert.h"
32#include "ns3/ipv6-address.h"
34#include "ns3/object-vector.h"
35#include "ns3/trace-source-accessor.h"
36#include "ns3/uinteger.h"
53 .SetGroupName(
"Internet")
54 .AddAttribute(
"ExtensionNumber",
55 "The IPv6 extension number.",
58 MakeUintegerChecker<uint8_t>());
64 m_uvar = CreateObject<UniformRandomVariable>();
96 NS_LOG_FUNCTION(
this << packet << offset << length << ipv6Header << dst << nextHeader
101 malformedPacket->AddHeader(ipv6Header);
105 p->RemoveAtStart(offset);
110 uint8_t processedSize = 0;
112 uint8_t*
data =
new uint8_t[size];
113 p->CopyData(
data, size);
115 uint8_t optionType = 0;
116 uint8_t optionLength = 0;
118 while (length > processedSize && !isDropped)
120 optionType = *(
data + processedSize);
121 ipv6Option = ipv6OptionDemux->GetOption(optionType);
129 optionLength = *(
data + processedSize + 1) + 2;
136 stopProcessing =
true;
142 icmpv6->SendErrorParameterError(malformedPacket,
145 offset + processedSize);
148 stopProcessing =
true;
157 icmpv6->SendErrorParameterError(malformedPacket,
160 offset + processedSize);
164 stopProcessing =
true;
175 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
178 processedSize += optionLength;
179 p->RemoveAtStart(optionLength);
184 return processedSize;
200 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionHopByHop")
202 .SetGroupName(
"Internet")
227 bool& stopProcessing,
231 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
234 p->RemoveAtStart(offset);
237 p->RemoveHeader(hopbyhopHeader);
244 offset += processedSize;
257 return processedSize;
265 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionDestination")
267 .SetGroupName(
"Internet")
292 bool& stopProcessing,
296 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
299 p->RemoveAtStart(offset);
302 p->RemoveHeader(destinationHeader);
309 offset += processedSize;
322 return processedSize;
331 TypeId(
"ns3::Ipv6ExtensionFragment")
333 .SetGroupName(
"Internet")
335 .AddAttribute(
"FragmentExpirationTimeout",
336 "When this timeout expires, the fragments "
337 "will be cleared from the buffer.",
359 it->second =
nullptr;
383 bool& stopProcessing,
387 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
390 p->RemoveAtStart(offset);
393 p->RemoveHeader(fragmentHeader);
401 uint16_t fragmentOffset = fragmentHeader.
GetOffset();
411 MapFragments_t::iterator it =
m_fragments.find(fragmentKey);
414 fragments = Create<Fragments>();
415 m_fragments.insert(std::make_pair(fragmentKey, fragments));
417 << src <<
" IP hdr id " << identification <<
" m_fragments.size() "
418 <<
m_fragments.size() <<
" offset " << fragmentOffset);
420 fragments->SetTimeoutIter(iter);
424 fragments = it->second;
427 if (fragmentOffset == 0)
430 unfragmentablePart->RemoveAtEnd(packet->GetSize() - offset);
431 fragments->SetUnfragmentablePart(unfragmentablePart);
434 NS_LOG_DEBUG(
"Add fragment with IP hdr id " << identification <<
" offset " << fragmentOffset);
435 fragments->AddFragment(p, fragmentOffset, moreFragment);
437 if (fragments->IsEntire())
439 packet = fragments->GetPacket();
443 << fragmentKey.second
444 <<
" erase timeout, m_fragments.size(): " <<
m_fragments.size());
445 stopProcessing =
false;
449 stopProcessing =
true;
459 std::list<Ipv6PayloadHeaderPair>& listFragments)
468 p->CopyData(&type,
sizeof(type));
470 bool moreHeader =
true;
479 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
480 uint32_t unfragmentablePartSize = 0;
484 uint8_t extensionHeaderLength;
491 p->RemoveHeader(*hopbyhopHeader);
494 extensionHeaderLength = hopbyhopHeader->
GetLength();
497 p->CopyData(&type,
sizeof(type));
509 unfragmentablePartSize += extensionHeaderLength;
517 p->CopyData(buf,
sizeof(buf));
518 uint8_t routingType = buf[2];
521 ipv6ExtensionRoutingDemux->GetExtensionRoutingHeaderPtr(routingType);
523 p->RemoveHeader(*routingHeader);
526 extensionHeaderLength = routingHeader->
GetLength();
529 p->CopyData(&type,
sizeof(type));
540 unfragmentablePartSize += extensionHeaderLength;
546 p->RemoveHeader(*destinationHeader);
549 extensionHeaderLength = destinationHeader->
GetLength();
552 p->CopyData(&type,
sizeof(type));
563 unfragmentablePartSize += extensionHeaderLength;
571 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
572 uint32_t currentFragmentablePartSize = 0;
574 bool moreFragment =
true;
580 if (p->GetSize() > offset + maxFragmentablePartSize)
583 currentFragmentablePartSize = maxFragmentablePartSize;
584 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
588 moreFragment =
false;
589 currentFragmentablePartSize = p->GetSize() - offset;
597 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
598 offset += currentFragmentablePartSize;
600 fragment->AddHeader(fragmentHeader);
602 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
603 unfragmentablePart.begin();
604 it != unfragmentablePart.end();
612 fragment->AddHeader(*p);
619 fragment->AddHeader(*p);
626 fragment->AddHeader(*p);
632 std::ostringstream oss;
634 fragment->Print(oss);
636 listFragments.emplace_back(fragment, ipv6Header);
637 }
while (moreFragment);
639 for (std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
640 unfragmentablePart.begin();
641 it != unfragmentablePart.end();
647 unfragmentablePart.clear();
653 NS_LOG_FUNCTION(
this << fragmentKey.first << fragmentKey.second << ipHeader);
656 MapFragments_t::iterator it =
m_fragments.find(fragmentKey);
658 "IPv6 Fragment timeout reached for non-existent fragment");
659 fragments = it->second;
661 Ptr<Packet> packet = fragments->GetPartialPacket();
664 if (packet && packet->GetSize() > 8)
667 p->AddHeader(ipHeader);
686 << key.second <<
" at time "
712 NS_LOG_DEBUG(
"Handle time " << std::get<0>(element).GetSeconds() <<
" IP hdr id "
713 << std::get<1>(element).
second);
728 NS_LOG_DEBUG(
"Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
743 uint16_t fragmentOffset,
747 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
749 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
751 if (it->second > fragmentOffset)
757 if (it == m_packetFragments.end())
759 m_moreFragment = moreFragment;
762 m_packetFragments.insert(it, std::pair<
Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
769 m_unfragmentable = unfragmentablePart;
775 bool ret = !m_moreFragment && !m_packetFragments.empty();
779 uint16_t lastEndOffset = 0;
781 for (std::list<std::pair<
Ptr<Packet>, uint16_t>>::const_iterator it =
782 m_packetFragments.begin();
783 it != m_packetFragments.end();
786 if (lastEndOffset != it->second)
792 lastEndOffset += it->first->GetSize();
804 for (std::list<std::pair<
Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
805 it != m_packetFragments.end();
808 p->AddAtEnd(it->first);
819 if (m_unfragmentable)
821 p = m_unfragmentable->Copy();
828 uint16_t lastEndOffset = 0;
830 for (std::list<std::pair<
Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
831 it != m_packetFragments.end();
834 if (lastEndOffset != it->second)
838 p->AddAtEnd(it->first);
839 lastEndOffset += it->first->GetSize();
849 m_timeoutIter = iter;
855 return m_timeoutIter;
865 .SetGroupName(
"Internet")
902 bool& stopProcessing,
906 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
910 malformedPacket->AddHeader(ipv6Header);
913 p->RemoveAtStart(offset);
916 packet->CopyData(buf,
sizeof(buf));
918 uint8_t routingNextHeader = buf[0];
919 uint8_t routingLength = buf[1];
920 uint8_t routingTypeRouting = buf[2];
921 uint8_t routingSegmentsLeft = buf[3];
925 *nextHeader = routingNextHeader;
933 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
935 if (!ipv6ExtensionRouting)
937 if (routingSegmentsLeft == 0)
945 icmpv6->SendErrorParameterError(malformedPacket,
951 stopProcessing =
true;
954 return routingLength;
957 return ipv6ExtensionRouting->Process(packet,
973 TypeId(
"ns3::Ipv6ExtensionRoutingDemux")
975 .SetGroupName(
"Internet")
976 .AddAttribute(
"RoutingExtensions",
977 "The set of IPv6 Routing extensions registered with this demux.",
980 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
996 for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin();
997 it != m_extensionsRouting.end();
1003 m_extensionsRouting.clear();
1019 m_extensionsRouting.push_back(extensionRouting);
1025 for (
const auto& extRouting : m_extensionsRouting)
1027 if (extRouting->GetTypeRouting() == typeRouting)
1041 for (
const auto& extRouting : m_extensionsRouting)
1043 if (extRouting->GetTypeRouting() == typeRouting)
1045 return extRouting->GetExtensionRoutingHeaderPtr();
1056 m_extensionsRouting.remove(extensionRouting);
1064 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionLooseRouting")
1066 .SetGroupName(
"Internet")
1082 return TYPE_ROUTING;
1096 uint8_t* nextHeader,
1097 bool& stopProcessing,
1101 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1105 malformedPacket->AddHeader(ipv6Header);
1108 p->RemoveAtStart(offset);
1120 p->CopyData(buf,
sizeof(buf));
1122 p->RemoveHeader(routingHeader);
1135 uint8_t length = (routingHeader.
GetLength() >> 3) - 1;
1136 uint8_t nbAddress = length / 2;
1137 uint8_t nextAddressIndex;
1140 if (segmentsLeft == 0)
1146 if (length % 2 != 0)
1149 icmpv6->SendErrorParameterError(malformedPacket,
1155 stopProcessing =
true;
1159 if (segmentsLeft > nbAddress)
1162 icmpv6->SendErrorParameterError(malformedPacket,
1168 stopProcessing =
true;
1173 nextAddressIndex = nbAddress - segmentsLeft;
1180 stopProcessing =
true;
1193 stopProcessing =
true;
1198 p->AddHeader(routingHeader);
1212 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header,
nullptr, err);
1217 ipv6->SendRealOut(rtentry, p, ipv6header);
1237 .SetGroupName(
"Internet")
1261 uint8_t* nextHeader,
1262 bool& stopProcessing,
1266 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1280 .SetGroupName(
"Internet")
1304 uint8_t* nextHeader,
1305 bool& stopProcessing,
1309 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
iterator in a Buffer instance
automatically resized byte buffer
void AddAtStart(uint32_t start)
Buffer::Iterator Begin() const
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
An implementation of the ICMPv6 protocol.
Describes an IPv6 address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
IPv6 Extension AH (Authentication Header)
~Ipv6ExtensionAH() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
static TypeId GetTypeId()
Get the type identificator.
uint8_t GetExtensionNumber() const override
Get the extension number.
Ipv6ExtensionAH()
Constructor.
Demultiplexes IPv6 extensions.
IPv6 Extension Destination.
Ipv6ExtensionDestination()
Constructor.
uint8_t GetExtensionNumber() const override
Get the extension number.
static const uint8_t EXT_NUMBER
Destination extension number.
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionDestination() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
IPv6 Extension ESP (Encapsulating Security Payload)
~Ipv6ExtensionESP() override
Destructor.
Ipv6ExtensionESP()
Constructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
uint8_t GetExtensionNumber() const override
Get the extension number.
static TypeId GetTypeId()
Get the type identificator.
Ptr< Packet > GetPartialPacket() const
Get the packet parts so far received.
Ptr< Packet > GetPacket() const
Get the entire packet.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
void SetUnfragmentablePart(Ptr< Packet > unfragmentablePart)
Set the unfragmentable part of the packet.
bool IsEntire() const
If all fragments have been added.
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
Time m_fragmentExpirationTimeout
Expiration timeout.
void HandleTimeout()
Handles a fragmented packet timeout.
Ipv6ExtensionFragment()
Constructor.
static TypeId GetTypeId()
Get the type identificator.
void GetFragments(Ptr< Packet > packet, Ipv6Header ipv6Header, uint32_t fragmentSize, std::list< Ipv6PayloadHeaderPair > &listFragments)
Fragment a packet.
std::pair< Ipv6Address, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
EventId m_timeoutEvent
Event for the next scheduled timeout.
MapFragments_t m_fragments
The hash of fragmented packets.
void DoDispose() override
Dispose this object.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
std::list< std::tuple< Time, FragmentKey_t, Ipv6Header > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
~Ipv6ExtensionFragment() override
Destructor.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
void HandleFragmentsTimeout(FragmentKey_t key, Ipv6Header ipHeader)
Process the timeout for packet fragments.
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, Ipv6Header ipHeader)
Set a new timeout "event" for a fragmented packet.
uint8_t GetExtensionNumber() const override
Get the extension number.
static const uint8_t EXT_NUMBER
Fragmentation extension number.
IPv6 Extension "Hop By Hop".
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionHopByHop() override
Destructor.
Ipv6ExtensionHopByHop()
Constructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
static const uint8_t EXT_NUMBER
Hop-by-hop extension number.
uint8_t GetExtensionNumber() const override
Get the extension number.
IPv6 Extension base If you want to implement a new IPv6 extension, all you have to do is implement a ...
Ptr< Node > GetNode() const
Get the node.
virtual uint8_t ProcessOptions(Ptr< Packet > &packet, uint8_t offset, uint8_t length, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason)
Process options Called by implementing classes to process the options.
virtual uint8_t GetExtensionNumber() const =0
Get the extension number.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< Node > m_node
The node.
void SetNode(Ptr< Node > node)
Set the node.
Ptr< UniformRandomVariable > m_uvar
Provides uniform random variables.
~Ipv6Extension() override
Destructor.
Ipv6Extension()
Constructor.
static TypeId GetTypeId()
Get the type identificator.
IPv6 Extension Loose Routing.
static TypeId GetTypeId()
Get the type identificator.
~Ipv6ExtensionLooseRouting() override
Destructor.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
uint8_t GetTypeRouting() const override
Get the type of routing.
Ipv6ExtensionLooseRouting()
Constructor.
Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr() override
Get a pointer to a new routing extension header.
IPv6 Extension Routing Demux.
Ipv6ExtensionRoutingDemux()
Constructor.
void DoDispose() override
Dispose this object.
void Insert(Ptr< Ipv6ExtensionRouting > extensionRouting)
Insert a new IPv6 Routing Extension.
static TypeId GetTypeId()
The interface ID.
void SetNode(Ptr< Node > node)
Set the node.
Ptr< Ipv6ExtensionRouting > GetExtensionRouting(uint8_t typeRouting)
Get the routing extension corresponding to typeRouting.
void Remove(Ptr< Ipv6ExtensionRouting > extensionRouting)
Remove a routing extension from this demux.
Ipv6ExtensionRoutingList_t m_extensionsRouting
List of IPv6 Routing Extensions supported.
Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr(uint8_t typeRouting)
Get a pointer to a new routing extension header corresponding to typeRouting.
~Ipv6ExtensionRoutingDemux() override
Destructor.
uint8_t GetExtensionNumber() const override
Get the extension number.
Ipv6ExtensionRouting()
Constructor.
~Ipv6ExtensionRouting() override
Destructor.
virtual Ipv6ExtensionRoutingHeader * GetExtensionRoutingHeaderPtr()
Get a pointer to a new routing extension header.
static TypeId GetTypeId()
Get the type identificator.
virtual uint8_t GetTypeRouting() const
Get the type of routing.
uint8_t Process(Ptr< Packet > &packet, uint8_t offset, const Ipv6Header &ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool &stopProcessing, bool &isDropped, Ipv6L3Protocol::DropReason &dropReason) override
Process method Called from Ipv6L3Protocol::Receive.
IPv6 layer implementation.
DropReason
Reason why a packet has been dropped.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout.
@ DROP_UNKNOWN_OPTION
Unknown option.
@ DROP_MALFORMED_HEADER
Malformed header.
A base class which provides memory management and object aggregation.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
virtual void DoDispose()
Destructor implementation.
uint32_t GetOptionsOffset() const
Get the offset where the options begin, measured from the start of the extension header.
Smart pointer class similar to boost::intrusive_ptr.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
SocketErrno
Enumeration of the possible errors returned by a socket.
Simulation virtual time values and global simulation resolution.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Seconds(double value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.