20#include "ns3/assert.h"
21#include "ns3/ipv6-address.h"
23#include "ns3/object-vector.h"
24#include "ns3/trace-source-accessor.h"
25#include "ns3/uinteger.h"
42 .SetGroupName(
"Internet")
43 .AddAttribute(
"ExtensionNumber",
44 "The IPv6 extension number.",
85 NS_LOG_FUNCTION(
this << packet << offset << length << ipv6Header << dst << nextHeader
90 malformedPacket->AddHeader(ipv6Header);
94 p->RemoveAtStart(offset);
99 uint8_t processedSize = 0;
101 auto data =
new uint8_t[size];
102 p->CopyData(
data, size);
104 uint8_t optionType = 0;
105 uint8_t optionLength = 0;
107 while (length > processedSize && !isDropped)
109 optionType = *(
data + processedSize);
110 ipv6Option = ipv6OptionDemux->GetOption(optionType);
118 optionLength = *(
data + processedSize + 1) + 2;
125 stopProcessing =
true;
131 icmpv6->SendErrorParameterError(malformedPacket,
134 offset + processedSize);
137 stopProcessing =
true;
146 icmpv6->SendErrorParameterError(malformedPacket,
149 offset + processedSize);
153 stopProcessing =
true;
164 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
167 processedSize += optionLength;
168 p->RemoveAtStart(optionLength);
173 return processedSize;
180 m_uvar->SetStream(stream);
189 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionHopByHop")
191 .SetGroupName(
"Internet")
216 bool& stopProcessing,
220 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
223 p->RemoveAtStart(offset);
226 p->RemoveHeader(hopbyhopHeader);
233 offset += processedSize;
246 return processedSize;
254 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionDestination")
256 .SetGroupName(
"Internet")
281 bool& stopProcessing,
285 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
288 p->RemoveAtStart(offset);
291 p->RemoveHeader(destinationHeader);
298 offset += processedSize;
311 return processedSize;
320 TypeId(
"ns3::Ipv6ExtensionFragment")
322 .SetGroupName(
"Internet")
324 .AddAttribute(
"FragmentExpirationTimeout",
325 "When this timeout expires, the fragments "
326 "will be cleared from the buffer.",
348 it->second =
nullptr;
372 bool& stopProcessing,
376 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
379 p->RemoveAtStart(offset);
382 p->RemoveHeader(fragmentHeader);
390 uint16_t fragmentOffset = fragmentHeader.
GetOffset();
404 m_fragments.insert(std::make_pair(fragmentKey, fragments));
406 << src <<
" IP hdr id " << identification <<
" m_fragments.size() "
407 <<
m_fragments.size() <<
" offset " << fragmentOffset);
408 auto iter =
SetTimeout(fragmentKey, ipHeader);
409 fragments->SetTimeoutIter(iter);
413 fragments = it->second;
416 if (fragmentOffset == 0)
419 unfragmentablePart->RemoveAtEnd(packet->GetSize() - offset);
420 fragments->SetUnfragmentablePart(unfragmentablePart);
423 NS_LOG_DEBUG(
"Add fragment with IP hdr id " << identification <<
" offset " << fragmentOffset);
424 fragments->AddFragment(p, fragmentOffset, moreFragment);
426 if (fragments->IsEntire())
428 packet = fragments->GetPacket();
432 << fragmentKey.second
433 <<
" erase timeout, m_fragments.size(): " <<
m_fragments.size());
434 stopProcessing =
false;
438 stopProcessing =
true;
448 std::list<Ipv6PayloadHeaderPair>& listFragments)
457 p->CopyData(&type,
sizeof(type));
459 bool moreHeader =
true;
468 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
469 uint32_t unfragmentablePartSize = 0;
473 uint8_t extensionHeaderLength;
480 p->RemoveHeader(*hopbyhopHeader);
482 nextHeader = hopbyhopHeader->GetNextHeader();
483 extensionHeaderLength = hopbyhopHeader->GetLength();
486 p->CopyData(&type,
sizeof(type));
498 unfragmentablePartSize += extensionHeaderLength;
506 p->CopyData(buf,
sizeof(buf));
507 uint8_t routingType = buf[2];
510 ipv6ExtensionRoutingDemux->GetExtensionRoutingHeaderPtr(routingType);
512 p->RemoveHeader(*routingHeader);
515 extensionHeaderLength = routingHeader->
GetLength();
518 p->CopyData(&type,
sizeof(type));
529 unfragmentablePartSize += extensionHeaderLength;
534 p->RemoveHeader(*destinationHeader);
536 nextHeader = destinationHeader->GetNextHeader();
537 extensionHeaderLength = destinationHeader->GetLength();
540 p->CopyData(&type,
sizeof(type));
551 unfragmentablePartSize += extensionHeaderLength;
559 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
560 uint32_t currentFragmentablePartSize = 0;
562 bool moreFragment =
true;
568 if (p->GetSize() > offset + maxFragmentablePartSize)
571 currentFragmentablePartSize = maxFragmentablePartSize;
572 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
576 moreFragment =
false;
577 currentFragmentablePartSize = p->GetSize() - offset;
585 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
586 offset += currentFragmentablePartSize;
588 fragment->AddHeader(fragmentHeader);
590 for (
auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
596 fragment->AddHeader(*p);
602 fragment->AddHeader(*p);
608 fragment->AddHeader(*p);
614 std::ostringstream oss;
616 fragment->Print(oss);
618 listFragments.emplace_back(fragment, ipv6Header);
619 }
while (moreFragment);
621 for (
auto it = unfragmentablePart.begin(); it != unfragmentablePart.end(); it++)
626 unfragmentablePart.clear();
632 NS_LOG_FUNCTION(
this << fragmentKey.first << fragmentKey.second << ipHeader);
637 "IPv6 Fragment timeout reached for non-existent fragment");
638 fragments = it->second;
640 Ptr<Packet> packet = fragments->GetPartialPacket();
643 if (packet && packet->GetSize() > 8)
646 p->AddHeader(ipHeader);
665 << key.second <<
" at time "
691 NS_LOG_DEBUG(
"Handle time " << std::get<0>(element).GetSeconds() <<
" IP hdr id "
692 << std::get<1>(element).
second);
707 NS_LOG_DEBUG(
"Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
712 : m_moreFragment(false)
722 uint16_t fragmentOffset,
726 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
728 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
730 if (it->second > fragmentOffset)
736 if (it == m_packetFragments.end())
738 m_moreFragment = moreFragment;
741 m_packetFragments.insert(it, std::pair<
Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
748 m_unfragmentable = unfragmentablePart;
754 bool ret = !m_moreFragment && !m_packetFragments.empty();
758 uint16_t lastEndOffset = 0;
760 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
762 if (lastEndOffset != it->second)
768 lastEndOffset += it->first->GetSize();
780 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
782 p->AddAtEnd(it->first);
793 if (m_unfragmentable)
795 p = m_unfragmentable->Copy();
802 uint16_t lastEndOffset = 0;
804 for (
auto it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
806 if (lastEndOffset != it->second)
810 p->AddAtEnd(it->first);
811 lastEndOffset += it->first->GetSize();
821 m_timeoutIter = iter;
827 return m_timeoutIter;
837 .SetGroupName(
"Internet")
874 bool& stopProcessing,
878 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
882 malformedPacket->AddHeader(ipv6Header);
885 p->RemoveAtStart(offset);
888 packet->CopyData(buf,
sizeof(buf));
890 uint8_t routingNextHeader = buf[0];
891 uint8_t routingLength = buf[1];
892 uint8_t routingTypeRouting = buf[2];
893 uint8_t routingSegmentsLeft = buf[3];
897 *nextHeader = routingNextHeader;
905 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
907 if (!ipv6ExtensionRouting)
909 if (routingSegmentsLeft == 0)
917 icmpv6->SendErrorParameterError(malformedPacket,
923 stopProcessing =
true;
926 return routingLength;
929 return ipv6ExtensionRouting->Process(packet,
945 TypeId(
"ns3::Ipv6ExtensionRoutingDemux")
947 .SetGroupName(
"Internet")
948 .AddAttribute(
"RoutingExtensions",
949 "The set of IPv6 Routing extensions registered with this demux.",
968 for (
auto it = m_extensionsRouting.begin(); it != m_extensionsRouting.end(); it++)
973 m_extensionsRouting.clear();
989 m_extensionsRouting.push_back(extensionRouting);
995 for (
const auto& extRouting : m_extensionsRouting)
997 if (extRouting->GetTypeRouting() == typeRouting)
1011 for (
const auto& extRouting : m_extensionsRouting)
1013 if (extRouting->GetTypeRouting() == typeRouting)
1015 return extRouting->GetExtensionRoutingHeaderPtr();
1026 m_extensionsRouting.remove(extensionRouting);
1034 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionLooseRouting")
1036 .SetGroupName(
"Internet")
1052 return TYPE_ROUTING;
1066 uint8_t* nextHeader,
1067 bool& stopProcessing,
1071 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1075 malformedPacket->AddHeader(ipv6Header);
1078 p->RemoveAtStart(offset);
1090 p->CopyData(buf,
sizeof(buf));
1092 p->RemoveHeader(routingHeader);
1105 uint8_t length = (routingHeader.
GetLength() >> 3) - 1;
1106 uint8_t nbAddress = length / 2;
1107 uint8_t nextAddressIndex;
1110 if (segmentsLeft == 0)
1116 if (length % 2 != 0)
1119 icmpv6->SendErrorParameterError(malformedPacket,
1125 stopProcessing =
true;
1129 if (segmentsLeft > nbAddress)
1132 icmpv6->SendErrorParameterError(malformedPacket,
1138 stopProcessing =
true;
1143 nextAddressIndex = nbAddress - segmentsLeft;
1150 stopProcessing =
true;
1163 stopProcessing =
true;
1168 p->AddHeader(routingHeader);
1182 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header,
nullptr, err);
1187 ipv6->SendRealOut(rtentry, p, ipv6header);
1207 .SetGroupName(
"Internet")
1231 uint8_t* nextHeader,
1232 bool& stopProcessing,
1236 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1250 .SetGroupName(
"Internet")
1274 uint8_t* nextHeader,
1275 bool& stopProcessing,
1279 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 IsPending() 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.
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.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
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 AttributeChecker > MakeUintegerChecker()
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Ptr< const AttributeChecker > MakeObjectVectorChecker()
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.