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
110 uint8_t processedSize = 0;
112 auto data =
new uint8_t[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;
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);
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);
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);
401 uint16_t fragmentOffset = fragmentHeader.
GetOffset();
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);
419 auto iter =
SetTimeout(fragmentKey, ipHeader);
424 fragments = it->second;
427 if (fragmentOffset == 0)
434 NS_LOG_DEBUG(
"Add fragment with IP hdr id " << identification <<
" offset " << fragmentOffset);
435 fragments->
AddFragment(p, fragmentOffset, moreFragment);
443 << fragmentKey.second
444 <<
" erase timeout, m_fragments.size(): " <<
m_fragments.size());
445 stopProcessing =
false;
449 stopProcessing =
true;
458 uint32_t maxFragmentSize,
459 std::list<Ipv6PayloadHeaderPair>& listFragments)
470 bool moreHeader =
true;
479 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
480 uint32_t unfragmentablePartSize = 0;
484 uint8_t extensionHeaderLength;
493 nextHeader = hopbyhopHeader->GetNextHeader();
494 extensionHeaderLength = hopbyhopHeader->GetLength();
509 unfragmentablePartSize += extensionHeaderLength;
518 uint8_t routingType = buf[2];
521 ipv6ExtensionRoutingDemux->GetExtensionRoutingHeaderPtr(routingType);
526 extensionHeaderLength = routingHeader->
GetLength();
540 unfragmentablePartSize += extensionHeaderLength;
547 nextHeader = destinationHeader->GetNextHeader();
548 extensionHeaderLength = destinationHeader->GetLength();
562 unfragmentablePartSize += extensionHeaderLength;
569 uint32_t maxFragmentablePartSize =
570 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
571 uint32_t currentFragmentablePartSize = 0;
573 bool moreFragment =
true;
574 auto identification = (uint32_t)
m_uvar->
GetValue(0, (uint32_t)-1);
579 if (p->
GetSize() > offset + maxFragmentablePartSize)
582 currentFragmentablePartSize = maxFragmentablePartSize;
583 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
587 moreFragment =
false;
588 currentFragmentablePartSize = p->
GetSize() - offset;
597 offset += currentFragmentablePartSize;
601 for (
auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
625 std::ostringstream oss;
627 fragment->
Print(oss);
629 listFragments.emplace_back(fragment, ipv6Header);
630 }
while (moreFragment);
632 for (
auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
637 unfragmentablePart.clear();
643 NS_LOG_FUNCTION(
this << fragmentKey.first << fragmentKey.second << ipHeader);
648 "IPv6 Fragment timeout reached for non-existent fragment");
649 fragments = it->second;
654 if (packet && packet->
GetSize() > 8)
676 << key.second <<
" at time "
702 NS_LOG_DEBUG(
"Handle time " << std::get<0>(element).GetSeconds() <<
" IP hdr id "
703 << std::get<1>(element).
second);
718 NS_LOG_DEBUG(
"Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
723 : m_moreFragment(false)
733 uint16_t fragmentOffset,
737 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
739 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
741 if (it->second > fragmentOffset)
747 if (it == m_packetFragments.end())
749 m_moreFragment = moreFragment;
752 m_packetFragments.insert(it, std::pair<
Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
759 m_unfragmentable = unfragmentablePart;
765 bool ret = !m_moreFragment && !m_packetFragments.empty();
769 uint16_t lastEndOffset = 0;
771 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
773 if (lastEndOffset != it->second)
779 lastEndOffset += it->first->GetSize();
791 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
804 if (m_unfragmentable)
806 p = m_unfragmentable->
Copy();
813 uint16_t lastEndOffset = 0;
815 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
817 if (lastEndOffset != it->second)
822 lastEndOffset += it->first->GetSize();
832 m_timeoutIter = iter;
838 return m_timeoutIter;
848 .SetGroupName(
"Internet")
885 bool& stopProcessing,
889 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
901 uint8_t routingNextHeader = buf[0];
902 uint8_t routingLength = buf[1];
903 uint8_t routingTypeRouting = buf[2];
904 uint8_t routingSegmentsLeft = buf[3];
908 *nextHeader = routingNextHeader;
916 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
918 if (!ipv6ExtensionRouting)
920 if (routingSegmentsLeft == 0)
928 icmpv6->SendErrorParameterError(malformedPacket,
934 stopProcessing =
true;
937 return routingLength;
940 return ipv6ExtensionRouting->Process(packet,
956 TypeId(
"ns3::Ipv6ExtensionRoutingDemux")
958 .SetGroupName(
"Internet")
959 .AddAttribute(
"RoutingExtensions",
960 "The set of IPv6 Routing extensions registered with this demux.",
963 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
979 for (
auto it = m_extensionsRouting.begin(); it != m_extensionsRouting.end(); it++)
984 m_extensionsRouting.clear();
1000 m_extensionsRouting.push_back(extensionRouting);
1006 for (
const auto& extRouting : m_extensionsRouting)
1008 if (extRouting->GetTypeRouting() == typeRouting)
1022 for (
const auto& extRouting : m_extensionsRouting)
1024 if (extRouting->GetTypeRouting() == typeRouting)
1026 return extRouting->GetExtensionRoutingHeaderPtr();
1037 m_extensionsRouting.remove(extensionRouting);
1045 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionLooseRouting")
1047 .SetGroupName(
"Internet")
1063 return TYPE_ROUTING;
1077 uint8_t* nextHeader,
1078 bool& stopProcessing,
1082 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1116 uint8_t length = (routingHeader.
GetLength() >> 3) - 1;
1117 uint8_t nbAddress = length / 2;
1118 uint8_t nextAddressIndex;
1121 if (segmentsLeft == 0)
1127 if (length % 2 != 0)
1130 icmpv6->SendErrorParameterError(malformedPacket,
1136 stopProcessing =
true;
1140 if (segmentsLeft > nbAddress)
1143 icmpv6->SendErrorParameterError(malformedPacket,
1149 stopProcessing =
true;
1154 nextAddressIndex = nbAddress - segmentsLeft;
1161 stopProcessing =
true;
1174 stopProcessing =
true;
1193 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header,
nullptr, err);
1198 ipv6->SendRealOut(rtentry, p, ipv6header);
1218 .SetGroupName(
"Internet")
1242 uint8_t* nextHeader,
1243 bool& stopProcessing,
1247 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1261 .SetGroupName(
"Internet")
1285 uint8_t* nextHeader,
1286 bool& stopProcessing,
1290 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.
std::list< std::tuple< Time, FragmentKey_t, Ipv6Header > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts.
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.
~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.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
void AddHeader(const Header &header)
Add header to this packet.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
void Print(std::ostream &os) const
Print the packet contents.
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.
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...
#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.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)