29 #include "ns3/assert.h"
30 #include "ns3/ipv6-address.h"
31 #include "ns3/ipv6-header.h"
32 #include "ns3/ipv6-l3-protocol.h"
33 #include "ns3/ipv6-list-routing.h"
34 #include "ns3/ipv6-route.h"
35 #include "ns3/ipv6-static-routing.h"
37 #include "ns3/object-vector.h"
38 #include "ns3/trace-source-accessor.h"
39 #include "ns3/uinteger.h"
56 .SetGroupName(
"Internet")
57 .AddAttribute(
"ExtensionNumber",
58 "The IPv6 extension number.",
61 MakeUintegerChecker<uint8_t>());
67 m_uvar = CreateObject<UniformRandomVariable>();
99 NS_LOG_FUNCTION(
this << packet << offset << length << ipv6Header << dst << nextHeader
113 uint8_t processedSize = 0;
115 uint8_t*
data =
new uint8_t[size];
118 uint8_t optionType = 0;
119 uint8_t optionLength = 0;
121 while (length > processedSize && !isDropped)
123 optionType = *(
data + processedSize);
124 ipv6Option = ipv6OptionDemux->GetOption(optionType);
132 optionLength = *(
data + processedSize + 1) + 2;
139 stopProcessing =
true;
145 icmpv6->SendErrorParameterError(malformedPacket,
148 offset + processedSize);
151 stopProcessing =
true;
160 icmpv6->SendErrorParameterError(malformedPacket,
163 offset + processedSize);
167 stopProcessing =
true;
178 ipv6Option->Process(packet, offset + processedSize, ipv6Header, isDropped);
181 processedSize += optionLength;
187 return processedSize;
203 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionHopByHop")
205 .SetGroupName(
"Internet")
230 bool& stopProcessing,
234 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
247 offset += processedSize;
260 return processedSize;
268 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionDestination")
270 .SetGroupName(
"Internet")
295 bool& stopProcessing,
299 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
312 offset += processedSize;
325 return processedSize;
334 TypeId(
"ns3::Ipv6ExtensionFragment")
336 .SetGroupName(
"Internet")
338 .AddAttribute(
"FragmentExpirationTimeout",
339 "When this timeout expires, the fragments "
340 "will be cleared from the buffer.",
362 it->second =
nullptr;
386 bool& stopProcessing,
390 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
404 uint16_t fragmentOffset = fragmentHeader.
GetOffset();
414 MapFragments_t::iterator it =
m_fragments.find(fragmentKey);
417 fragments = Create<Fragments>();
418 m_fragments.insert(std::make_pair(fragmentKey, fragments));
420 << src <<
" IP hdr id " << identification <<
" m_fragments.size() "
421 <<
m_fragments.size() <<
" offset " << fragmentOffset);
427 fragments = it->second;
430 if (fragmentOffset == 0)
437 NS_LOG_DEBUG(
"Add fragment with IP hdr id " << identification <<
" offset " << fragmentOffset);
438 fragments->
AddFragment(p, fragmentOffset, moreFragment);
446 << fragmentKey.second
447 <<
" erase timeout, m_fragments.size(): " <<
m_fragments.size());
448 stopProcessing =
false;
452 stopProcessing =
true;
461 uint32_t maxFragmentSize,
462 std::list<Ipv6PayloadHeaderPair>& listFragments)
473 bool moreHeader =
true;
482 std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>> unfragmentablePart;
483 uint32_t unfragmentablePartSize = 0;
487 uint8_t extensionHeaderLength;
497 extensionHeaderLength = hopbyhopHeader->
GetLength();
512 unfragmentablePartSize += extensionHeaderLength;
518 uint8_t numberAddress = buf[1] / 2;
524 extensionHeaderLength = routingHeader->
GetLength();
538 unfragmentablePartSize += extensionHeaderLength;
547 extensionHeaderLength = destinationHeader->
GetLength();
561 unfragmentablePartSize += extensionHeaderLength;
568 uint32_t maxFragmentablePartSize =
569 maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize;
570 uint32_t currentFragmentablePartSize = 0;
572 bool moreFragment =
true;
573 uint32_t identification = (uint32_t)
m_uvar->
GetValue(0, (uint32_t)-1);
578 if (p->
GetSize() > offset + maxFragmentablePartSize)
581 currentFragmentablePartSize = maxFragmentablePartSize;
582 currentFragmentablePartSize -= currentFragmentablePartSize % 8;
586 moreFragment =
false;
587 currentFragmentablePartSize = p->
GetSize() - offset;
596 offset += currentFragmentablePartSize;
600 for (
std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
601 unfragmentablePart.begin();
602 it != unfragmentablePart.end();
630 std::ostringstream oss;
632 fragment->
Print(oss);
634 listFragments.emplace_back(fragment, ipv6Header);
635 }
while (moreFragment);
637 for (
std::list<std::pair<Ipv6ExtensionHeader*, uint8_t>>::iterator it =
638 unfragmentablePart.begin();
639 it != unfragmentablePart.end();
645 unfragmentablePart.clear();
651 NS_LOG_FUNCTION(
this << fragmentKey.first << fragmentKey.second << ipHeader);
654 MapFragments_t::iterator it =
m_fragments.find(fragmentKey);
656 "IPv6 Fragment timeout reached for non-existent fragment");
657 fragments = it->second;
662 if (packet && packet->
GetSize() > 8)
684 << key.second <<
" at time "
710 NS_LOG_DEBUG(
"Handle time " << std::get<0>(element).GetSeconds() <<
" IP hdr id "
711 << std::get<1>(element).
second);
726 NS_LOG_DEBUG(
"Scheduling later HandleTimeout at " << (now + difference).GetSeconds());
741 uint16_t fragmentOffset,
745 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
747 for (it = m_packetFragments.begin(); it != m_packetFragments.end(); it++)
749 if (it->second > fragmentOffset)
755 if (it == m_packetFragments.end())
757 m_moreFragment = moreFragment;
760 m_packetFragments.insert(it, std::pair<
Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
767 m_unfragmentable = unfragmentablePart;
773 bool ret = !m_moreFragment && !m_packetFragments.empty();
777 uint16_t lastEndOffset = 0;
780 m_packetFragments.begin();
781 it != m_packetFragments.end();
784 if (lastEndOffset != it->second)
790 lastEndOffset += it->first->GetSize();
802 for (
std::list<std::pair<
Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
803 it != m_packetFragments.end();
817 if (m_unfragmentable)
819 p = m_unfragmentable->
Copy();
826 uint16_t lastEndOffset = 0;
828 for (
std::list<std::pair<
Ptr<Packet>, uint16_t>>::const_iterator it = m_packetFragments.begin();
829 it != m_packetFragments.end();
832 if (lastEndOffset != it->second)
837 lastEndOffset += it->first->GetSize();
847 m_timeoutIter = iter;
853 return m_timeoutIter;
863 .SetGroupName(
"Internet")
894 bool& stopProcessing,
898 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
910 uint8_t routingNextHeader = buf[0];
911 uint8_t routingLength = buf[1];
912 uint8_t routingTypeRouting = buf[2];
913 uint8_t routingSegmentsLeft = buf[3];
917 *nextHeader = routingNextHeader;
925 ipv6ExtensionRoutingDemux->GetExtensionRouting(routingTypeRouting);
927 if (!ipv6ExtensionRouting)
929 if (routingSegmentsLeft == 0)
937 icmpv6->SendErrorParameterError(malformedPacket,
943 stopProcessing =
true;
946 return routingLength;
949 return ipv6ExtensionRouting->Process(packet,
965 TypeId(
"ns3::Ipv6ExtensionRoutingDemux")
967 .SetGroupName(
"Internet")
968 .AddAttribute(
"RoutingExtensions",
969 "The set of IPv6 Routing extensions registered with this demux.",
972 MakeObjectVectorChecker<Ipv6ExtensionRouting>());
988 for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin();
989 it != m_extensionsRouting.end();
995 m_extensionsRouting.clear();
1011 m_extensionsRouting.push_back(extensionRouting);
1017 for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin();
1018 i != m_extensionsRouting.end();
1021 if ((*i)->GetTypeRouting() == typeRouting)
1033 m_extensionsRouting.remove(extensionRouting);
1041 static TypeId tid =
TypeId(
"ns3::Ipv6ExtensionLooseRouting")
1043 .SetGroupName(
"Internet")
1059 return TYPE_ROUTING;
1067 uint8_t* nextHeader,
1068 bool& stopProcessing,
1072 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1092 uint8_t numberAddress = buf[1] / 2;
1108 uint8_t length = (routingHeader.
GetLength() >> 3) - 1;
1109 uint8_t nbAddress = length / 2;
1110 uint8_t nextAddressIndex;
1113 if (segmentsLeft == 0)
1119 if (length % 2 != 0)
1122 icmpv6->SendErrorParameterError(malformedPacket,
1128 stopProcessing =
true;
1132 if (segmentsLeft > nbAddress)
1135 icmpv6->SendErrorParameterError(malformedPacket,
1141 stopProcessing =
true;
1146 nextAddressIndex = nbAddress - segmentsLeft;
1153 stopProcessing =
true;
1166 stopProcessing =
true;
1185 Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput(p, ipv6header,
nullptr, err);
1190 ipv6->SendRealOut(rtentry, p, ipv6header);
1210 .SetGroupName(
"Internet")
1234 uint8_t* nextHeader,
1235 bool& stopProcessing,
1239 NS_LOG_FUNCTION(
this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
1253 .SetGroupName(
"Internet")
1277 uint8_t* nextHeader,
1278 bool& stopProcessing,
1282 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.
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.
~Ipv6ExtensionRoutingDemux() override
Destructor.
uint8_t GetExtensionNumber() const override
Get the extension number.
Ipv6ExtensionRouting()
Constructor.
~Ipv6ExtensionRouting() override
Destructor.
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.
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 AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#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 AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.