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());
722 uint16_t fragmentOffset,
726 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
730 if (it->second > fragmentOffset)
758 uint16_t lastEndOffset = 0;
762 if (lastEndOffset != it->second)
768 lastEndOffset += it->first->GetSize();
782 p->AddAtEnd(it->first);
802 uint16_t lastEndOffset = 0;
806 if (lastEndOffset != it->second)
810 p->AddAtEnd(it->first);
811 lastEndOffset += it->first->GetSize();
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.",
997 if (extRouting->GetTypeRouting() == typeRouting)
1013 if (extRouting->GetTypeRouting() == typeRouting)
1015 return extRouting->GetExtensionRoutingHeaderPtr();
1034 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionLooseRouting")
1036 .SetGroupName(
"Internet")
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
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.
static const uint8_t EXT_NUMBER
AH extension number.
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 const uint8_t EXT_NUMBER
ESP 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.
std::list< std::pair< Ptr< Packet >, uint16_t > > m_packetFragments
The current fragments.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
bool m_moreFragment
If other fragments will be sent.
Ptr< Packet > m_unfragmentable
The unfragmentable part.
FragmentsTimeoutsListI_t m_timeoutIter
Timeout iterator to "event" handler.
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.
static const uint8_t TYPE_ROUTING
Routing type.
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.
Ptr< Node > m_node
The node.
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.
static const uint8_t EXT_NUMBER
Routing 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.
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.