Index: src/internet-stack/ipv6-extension.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/internet-stack/ipv6-extension.cc |
@@ -0,0 +1,1084 @@ |
+/* Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) 2007-2009 Strasbourg University |
+ * |
+ * This program is free software; you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 2 as |
+ * published by the Free Software Foundation; |
+ * |
+ * This program is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with this program; if not, write to the Free Software |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
+ * |
+ * Author: David Gross <gdavid.devel@gmail.com> |
+ */ |
+ |
+#include <list> |
+#include <ctime> |
+ |
+#include "ns3/log.h" |
+#include "ns3/assert.h" |
+#include "ns3/uinteger.h" |
+#include "ns3/object-vector.h" |
+#include "ns3/ipv6-address.h" |
+#include "ns3/ipv6-header.h" |
+#include "ns3/ipv6-l3-protocol.h" |
+#include "ns3/ipv6-static-routing.h" |
+#include "ns3/ipv6-list-routing.h" |
+#include "ns3/ipv6-route.h" |
+#include "ns3/trace-source-accessor.h" |
+#include "ns3/random-variable.h" |
+#include "icmpv6-l4-protocol.h" |
+#include "ipv6-extension-demux.h" |
+#include "ipv6-extension.h" |
+#include "ipv6-extension-header.h" |
+#include "ipv6-option-demux.h" |
+#include "ipv6-option.h" |
+#include "udp-header.h" |
+ |
+NS_LOG_COMPONENT_DEFINE ("Ipv6Extension"); |
+ |
+namespace ns3 |
+{ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension); |
+ |
+TypeId Ipv6Extension::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6Extension") |
+ .SetParent<Object> () |
+ .AddAttribute ("ExtensionNumber", "The IPv6 extension number.", |
+ UintegerValue (0), |
+ MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber), |
+ MakeUintegerChecker<uint8_t> ()) |
+ .AddTraceSource ("Drop", "Drop ipv6 packet", |
+ MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace)) |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6Extension::~Ipv6Extension () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+void Ipv6Extension::SetNode (Ptr<Node> node) |
+{ |
+ NS_LOG_FUNCTION (this << node); |
+ |
+ m_node = node; |
+} |
+ |
+Ptr<Node> Ipv6Extension::GetNode () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return m_node; |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHop); |
+ |
+const uint8_t Ipv6ExtensionHopByHop::EXT_NUMBER = 0; |
moatamri
2009/10/30 11:31:30
should be defined in the header
ping67
2009/11/02 17:09:10
Done.
|
+ |
+TypeId Ipv6ExtensionHopByHop::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionHopByHop") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionHopByHop> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionHopByHop::Ipv6ExtensionHopByHop () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionHopByHop::~Ipv6ExtensionHopByHop () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionHopByHop::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ // For ICMPv6 Error packets |
+ Ptr<Packet> malformedPacket = packet->Copy (); |
+ malformedPacket->AddHeader (ipv6Header); |
+ |
+ Ptr<Packet> p = packet->Copy (); |
+ p->RemoveAtStart (offset); |
+ |
+ Ipv6ExtensionHopByHopHeader hopbyhopHeader; |
+ p->RemoveHeader (hopbyhopHeader); |
+ if (nextHeader) |
+ { |
+ *nextHeader = hopbyhopHeader.GetNextHeader (); |
+ } |
+ |
+ Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 (); |
+ |
+ Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> (); |
+ Ptr<Ipv6Option> ipv6Option; |
+ |
+ uint8_t totalSize = hopbyhopHeader.GetLength (); |
+ uint8_t processedSize = hopbyhopHeader.GetSerializedSize (); |
+ const uint8_t *data = p->PeekData (); |
+ uint8_t optionType = 0; |
+ uint8_t optionLength = 0; |
+ isDropped = false; |
+ |
+ while (totalSize > processedSize && !isDropped) |
+ { |
+ optionType = *(data + processedSize); |
+ ipv6Option = ipv6OptionDemux->GetOption (optionType); |
+ |
+ if (ipv6Option == 0) |
moatamri
2009/10/30 11:31:30
some comments about the options type?
|
+ { |
+ optionType >>= 6; |
+ switch (optionType) |
+ { |
+ case 0: |
+ optionLength = *(data + processedSize + 1); |
+ break; |
+ |
+ case 1: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ case 2: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */ |
moatamri
2009/10/30 11:31:30
either remove the commented code or enable it, sam
ping67
2009/11/02 17:09:10
Done.
|
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ case 3: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ |
+ if (!ipv6Header.GetDestinationAddress ().IsMulticast ()) |
+ { |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */ |
+ } |
+ |
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ default: |
+ break; |
moatamri
2009/10/30 11:31:30
should also drop or generate an error this is also
ping67
2009/11/02 17:09:10
Done.
|
+ } |
+ } |
+ else |
+ { |
+ optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped); |
+ } |
+ |
+ processedSize += optionLength; |
+ p->RemoveAtStart (optionLength); |
+ } |
+ |
+ return processedSize; |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionDestination); |
+ |
+const uint8_t Ipv6ExtensionDestination::EXT_NUMBER = 60; |
moatamri
2009/10/30 11:31:30
in header
ping67
2009/11/02 17:09:10
Done.
|
+ |
+TypeId Ipv6ExtensionDestination::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionDestination") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionDestination> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionDestination::Ipv6ExtensionDestination () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionDestination::~Ipv6ExtensionDestination () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionDestination::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
moatamri
2009/10/30 11:31:30
Looks like copy paste function with minor changes,
ping67
2009/11/02 17:09:10
I will think of this at the end of week or next we
ping67
2009/11/11 15:31:33
Done.
|
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ // For ICMPv6 Error packets |
+ Ptr<Packet> malformedPacket = packet->Copy (); |
+ malformedPacket->AddHeader (ipv6Header); |
+ |
+ Ptr<Packet> p = packet->Copy (); |
+ p->RemoveAtStart (offset); |
+ |
+ Ipv6ExtensionDestinationHeader destinationHeader; |
+ p->RemoveHeader (destinationHeader); |
+ if (nextHeader) |
+ { |
+ *nextHeader = destinationHeader.GetNextHeader (); |
+ } |
+ |
+ Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 (); |
+ |
+ Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> (); |
+ Ptr<Ipv6Option> ipv6Option; |
+ |
+ uint8_t totalSize = destinationHeader.GetLength (); |
+ uint8_t processedSize = destinationHeader.GetSerializedSize (); |
+ const uint8_t *data = p->PeekData (); |
+ uint8_t optionType = 0; |
+ uint8_t optionLength = 0; |
+ isDropped = false; |
+ |
+ while (totalSize > processedSize && !isDropped) |
+ { |
+ optionType = *(data + processedSize); |
+ ipv6Option = ipv6OptionDemux->GetOption (optionType); |
+ |
+ if (ipv6Option == 0) |
moatamri
2009/10/30 11:31:30
same comments as the above similar function
ping67
2009/11/11 15:31:33
Done.
|
+ { |
+ optionType >>= 6; |
+ switch (optionType) |
+ { |
+ case 0: |
+ optionLength = *(data + processedSize + 1); |
+ break; |
+ |
+ case 1: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ case 2: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */ |
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ case 3: |
+ NS_LOG_LOGIC ("Unknown Option. Drop!"); |
+ |
+ if (!ipv6Header.GetDestinationAddress ().IsMulticast ()) |
+ { |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize); */ |
+ } |
+ |
+ m_dropTrace (packet); |
+ optionLength = 0; |
+ isDropped = true; |
+ break; |
+ |
+ default: |
+ break; |
+ } |
+ } |
+ else |
+ { |
+ optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped); |
+ } |
+ |
+ processedSize += optionLength; |
+ p->RemoveAtStart (optionLength); |
+ } |
+ |
+ return processedSize; |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionFragment); |
+ |
+const uint8_t Ipv6ExtensionFragment::EXT_NUMBER = 44; |
+ |
+TypeId Ipv6ExtensionFragment::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionFragment") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionFragment> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionFragment::Ipv6ExtensionFragment () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionFragment::~Ipv6ExtensionFragment () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+void Ipv6ExtensionFragment::DoDispose () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++) |
+ { |
+ it->second = 0; |
+ } |
+ |
+ m_fragments.clear (); |
+ Ipv6Extension::DoDispose (); |
+} |
+ |
+uint8_t Ipv6ExtensionFragment::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ Ptr<Packet> p = packet->Copy (); |
+ p->RemoveAtStart (offset); |
+ |
+ Ipv6ExtensionFragmentHeader fragmentHeader; |
+ p->RemoveHeader (fragmentHeader); |
+ |
+ if (nextHeader) |
+ { |
+ *nextHeader = fragmentHeader.GetNextHeader (); |
+ } |
+ |
+ bool moreFragment = fragmentHeader.GetMoreFragment (); |
+ uint16_t fragmentOffset = fragmentHeader.GetOffset (); |
+ uint32_t identification = fragmentHeader.GetIdentification (); |
+ Ipv6Address src = ipv6Header.GetSourceAddress (); |
+ |
+ std::pair<Ipv6Address, uint32_t> fragmentsId = std::make_pair<Ipv6Address, uint32_t> (src, identification); |
+ Ptr<Fragments> fragments; |
+ |
+ MapFragments_t::iterator it = m_fragments.find (fragmentsId); |
+ if (it == m_fragments.end ()) |
+ { |
+ fragments = Create<Fragments> (); |
+ m_fragments.insert (std::make_pair (fragmentsId, fragments)); |
+ } |
+ else |
+ { |
+ fragments = it->second; |
+ } |
+ |
+ if (fragmentOffset == 0) |
+ { |
+ Ptr<Packet> unfragmentablePart = packet->Copy (); |
+ unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset); |
+ fragments->SetUnfragmentablePart (unfragmentablePart); |
+ } |
+ |
+ fragments->AddFragment (p, fragmentOffset, moreFragment); |
+ |
+ if (fragments->IsEntire ()) |
+ { |
+ packet = fragments->GetPacket (); |
+ isDropped = false; |
+ } |
+ else |
+ { |
+ NS_LOG_LOGIC ("Fragment. Drop!"); |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ } |
+ |
+ return 0; |
moatamri
2009/10/30 11:31:30
function doesn't return any other value, this is u
ping67
2009/11/02 17:09:10
It is implementation of virtual function of superc
|
+} |
+ |
+void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments) |
moatamri
2009/10/30 11:31:30
I would recommand to divide this big function into
ping67
2009/11/02 17:09:10
Idem I will think of it end of week or next week.
|
+{ |
+ Ptr<Packet> p = packet->Copy (); |
+ |
+ Ipv6Header ipv6Header; |
+ p->RemoveHeader (ipv6Header); |
+ |
+ uint8_t nextHeader = ipv6Header.GetNextHeader (); |
+ uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize (); |
+ |
+ bool moreHeader = true; |
+ if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING |
+ || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING))) |
+ { |
+ moreHeader = false; |
+ ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); |
+ } |
+ |
+ std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart; |
+ uint32_t unfragmentablePartSize = 0; |
+ |
+ Ptr<Ipv6ExtensionDemux> extensionDemux = GetNode ()->GetObject<Ipv6ExtensionDemux> (); |
+ Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader); |
+ uint8_t extensionHeaderLength; |
+ |
+ while (moreHeader) |
+ { |
+ if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP) |
+ { |
+ Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader (); |
+ p->RemoveHeader (*hopbyhopHeader); |
+ |
+ nextHeader = hopbyhopHeader->GetNextHeader (); |
+ extensionHeaderLength = hopbyhopHeader->GetLength (); |
+ |
+ if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING |
+ || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING))) |
+ { |
+ moreHeader = false; |
+ hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); |
+ } |
+ |
+ unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP)); |
+ unfragmentablePartSize += extensionHeaderLength; |
+ } |
+ else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING) |
+ { |
+ uint8_t numberAddress = (*(p->PeekData () + 1)) / 2; |
+ Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader (); |
+ routingHeader->SetNumberAddress (numberAddress); |
+ p->RemoveHeader (*routingHeader); |
+ |
+ nextHeader = routingHeader->GetNextHeader (); |
+ extensionHeaderLength = routingHeader->GetLength (); |
+ |
+ if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING |
+ || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING))) |
+ { |
+ moreHeader = false; |
+ routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); |
+ } |
+ |
+ unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING)); |
+ unfragmentablePartSize += extensionHeaderLength; |
+ } |
+ else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION) |
+ { |
+ Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader (); |
moatamri
2009/10/30 11:31:30
Please verify that there is a delete somewhere for
ping67
2009/11/02 17:09:10
Deleted in line 576.
|
+ p->RemoveHeader (*destinationHeader); |
+ |
+ nextHeader = destinationHeader->GetNextHeader (); |
+ extensionHeaderLength = destinationHeader->GetLength (); |
+ |
+ if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING |
+ || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING))) |
+ { |
+ moreHeader = false; |
+ destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); |
+ } |
+ |
+ unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION)); |
+ unfragmentablePartSize += extensionHeaderLength; |
+ } |
+ } |
+ |
+ Ipv6ExtensionFragmentHeader fragmentHeader; |
+ uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize (); |
+ |
+ uint32_t maxFragmentablePartSize = maxFragmentSize - ipv6HeaderSize - unfragmentablePartSize - fragmentHeaderSize; |
+ uint32_t currentFragmentablePartSize = 0; |
+ |
+ bool moreFragment = true; |
+ UniformVariable uvar; |
+ uint32_t identification = (uint32_t) uvar.GetValue (0, (uint32_t)-1); |
+ uint16_t offset = 0; |
+ |
+ do |
+ { |
+ if (p->GetSize () > offset + maxFragmentablePartSize) |
+ { |
+ moreFragment = true; |
+ currentFragmentablePartSize = maxFragmentablePartSize; |
+ } |
+ else |
+ { |
+ moreFragment = false; |
+ currentFragmentablePartSize = p->GetSize () - offset; |
+ } |
+ |
+ currentFragmentablePartSize -= currentFragmentablePartSize % 8; |
+ |
+ fragmentHeader.SetNextHeader (nextHeader); |
+ fragmentHeader.SetLength (currentFragmentablePartSize); |
+ fragmentHeader.SetOffset (offset); |
+ fragmentHeader.SetMoreFragment (moreFragment); |
+ fragmentHeader.SetIdentification (identification); |
+ |
+ Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize); |
+ offset += currentFragmentablePartSize; |
+ |
+ fragment->AddHeader (fragmentHeader); |
+ |
+ for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++) |
+ { |
+ if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP) |
+ { |
+ fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first)); |
+ } |
+ else if (it->second == Ipv6Header::IPV6_EXT_ROUTING) |
+ { |
+ fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first)); |
+ } |
+ else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION) |
+ { |
+ fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first)); |
+ } |
+ } |
+ |
+ ipv6Header.SetPayloadLength (fragment->GetSize ()); |
+ fragment->AddHeader (ipv6Header); |
+ |
+ std::ostringstream oss; |
+ fragment->Print (oss); |
+ listFragments.push_back (fragment); |
+ } while (moreFragment); |
+ |
+ for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++) |
+ { |
+ delete it->first; |
+ } |
+ |
+ unfragmentablePart.clear (); |
+} |
+ |
+ Ipv6ExtensionFragment::Fragments::Fragments () |
+: m_moreFragment (0), |
+ m_refCount (1) |
+{ |
+} |
+ |
+Ipv6ExtensionFragment::Fragments::~Fragments () |
+{ |
+} |
+ |
+void Ipv6ExtensionFragment::Fragments::Ref () const |
+{ |
+ m_refCount++; |
+} |
+ |
+void Ipv6ExtensionFragment::Fragments::Unref () const |
+{ |
+ m_refCount--; |
+ |
+ if (m_refCount == 0) |
+ { |
+ delete this; |
+ } |
+} |
+ |
+void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment) |
+{ |
+ std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it; |
+ |
+ for (it = m_fragments.begin (); it != m_fragments.end (); it++) |
+ { |
+ if (it->second > fragmentOffset) |
+ { |
+ break; |
+ } |
+ } |
+ |
+ if (it == m_fragments.end ()) |
+ { |
+ m_moreFragment = moreFragment; |
+ } |
+ |
+ m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset)); |
+} |
+ |
+void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr<Packet> unfragmentablePart) |
+{ |
+ m_unfragmentable = unfragmentablePart; |
+} |
+ |
+bool Ipv6ExtensionFragment::Fragments::IsEntire () const |
+{ |
+ bool ret = !m_moreFragment && m_fragments.size () > 0; |
+ |
+ if (ret) |
+ { |
+ uint16_t lastEndOffset = 0; |
+ |
+ for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++) |
+ { |
+ if (lastEndOffset != it->second) |
+ { |
+ ret = false; |
+ break; |
+ } |
+ |
+ lastEndOffset += it->first->GetSize (); |
+ } |
+ } |
+ |
+ return ret; |
+} |
+ |
+Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPacket () const |
+{ |
+ Ptr<Packet> p = m_unfragmentable->Copy (); |
+ |
+ for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++) |
+ { |
+ p->AddAtEnd (it->first); |
+ } |
+ |
+ /* XXX : FIX THIS BUG (NS_ASSERT WHEN PRINT PACKET INFORMATION */ |
moatamri
2009/10/30 11:31:30
Either fix or remove commented code.
ping67
2009/11/02 17:09:10
Done.
|
+ /* |
+ std::ostringstream oss; |
+ p->Print (oss); |
+ std::cout << oss.str () << std::endl; |
+ */ |
+ |
+ return p; |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRouting); |
+ |
+const uint8_t Ipv6ExtensionRouting::EXT_NUMBER = 43; |
+ |
+TypeId Ipv6ExtensionRouting::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionRouting") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionRouting> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionRouting::Ipv6ExtensionRouting () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionRouting::~Ipv6ExtensionRouting () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionRouting::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionRouting::GetTypeRouting () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ return 0; |
+} |
+ |
+uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ // For ICMPv6 Error Packets |
+ Ptr<Packet> malformedPacket = packet->Copy (); |
+ malformedPacket->AddHeader (ipv6Header); |
+ |
+ Ptr<Packet> p = packet->Copy (); |
+ p->RemoveAtStart (offset); |
+ |
+ const uint8_t *buff = packet->PeekData (); |
+ |
+ uint8_t routingNextHeader = *buff; |
+ uint8_t routingLength = *(buff+1); |
+ uint8_t routingTypeRouting = *(buff+2); |
+ uint8_t routingSegmentsLeft = *(buff+3); |
+ |
+ if (nextHeader) |
+ { |
+ *nextHeader = routingNextHeader; |
+ } |
+ |
+ Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 (); |
+ |
+ Ptr<Ipv6ExtensionRoutingDemux> ipv6ExtensionRoutingDemux = GetNode ()->GetObject<Ipv6ExtensionRoutingDemux> (); |
+ Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting); |
+ |
+ if (ipv6ExtensionRouting == 0) |
+ { |
+ if (routingSegmentsLeft == 0) |
+ { |
+ isDropped = false; |
+ } |
+ else |
+ { |
+ NS_LOG_LOGIC ("Malformed header. Drop!"); |
+ |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */ |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ } |
+ |
+ return routingLength; |
+ } |
+ |
+ return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped); |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRoutingDemux); |
+ |
+TypeId Ipv6ExtensionRoutingDemux::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux") |
+ .SetParent<Object> () |
+ .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.", |
+ ObjectVectorValue (), |
+ MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting), |
+ MakeObjectVectorChecker<Ipv6ExtensionRouting> ()) |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionRoutingDemux::Ipv6ExtensionRoutingDemux () |
+{ |
+} |
+ |
+Ipv6ExtensionRoutingDemux::~Ipv6ExtensionRoutingDemux () |
+{ |
+} |
+ |
+void Ipv6ExtensionRoutingDemux::DoDispose () |
+{ |
+ for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++) |
+ { |
+ (*it)->Dispose (); |
+ *it = 0; |
+ } |
+ m_extensionsRouting.clear (); |
+ m_node = 0; |
+ Object::DoDispose (); |
+} |
+ |
+void Ipv6ExtensionRoutingDemux::SetNode (Ptr<Node> node) |
+{ |
+ m_node = node; |
+} |
+ |
+void Ipv6ExtensionRoutingDemux::Insert (Ptr<Ipv6ExtensionRouting> extensionRouting) |
+{ |
+ m_extensionsRouting.push_back (extensionRouting); |
+} |
+ |
+Ptr<Ipv6ExtensionRouting> Ipv6ExtensionRoutingDemux::GetExtensionRouting (uint8_t typeRouting) |
+{ |
+ for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++) |
+ { |
+ if ((*i)->GetTypeRouting () == typeRouting) |
+ { |
+ return *i; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+void Ipv6ExtensionRoutingDemux::Remove (Ptr<Ipv6ExtensionRouting> extensionRouting) |
+{ |
+ m_extensionsRouting.remove (extensionRouting); |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionLooseRouting); |
+ |
+const uint8_t Ipv6ExtensionLooseRouting::TYPE_ROUTING = 0; |
+ |
+TypeId Ipv6ExtensionLooseRouting::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionLooseRouting") |
+ .SetParent<Ipv6ExtensionRouting> () |
+ .AddConstructor<Ipv6ExtensionLooseRouting> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionLooseRouting::Ipv6ExtensionLooseRouting () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionLooseRouting::~Ipv6ExtensionLooseRouting () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionLooseRouting::GetTypeRouting () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return TYPE_ROUTING; |
+} |
+ |
+uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ // For ICMPv6 Error packets |
+ Ptr<Packet> malformedPacket = packet->Copy (); |
+ malformedPacket->AddHeader (ipv6Header); |
+ |
+ Ptr<Packet> p = packet->Copy (); |
+ p->RemoveAtStart (offset); |
+ |
+ // Copy IPv6 Header : ipv6Header -> ipv6header |
+ Buffer tmp; |
+ tmp.AddAtStart (ipv6Header.GetSerializedSize ()); |
+ Buffer::Iterator it = tmp.Begin (); |
+ Ipv6Header ipv6header; |
+ ipv6Header.Serialize (it); |
+ ipv6header.Deserialize (it); |
+ |
+ // Get the number of routers' address field |
+ uint8_t numberAddress = (*(p->PeekData () + 1)) / 2; |
+ Ipv6ExtensionLooseRoutingHeader routingHeader; |
+ routingHeader.SetNumberAddress (numberAddress); |
+ p->RemoveHeader (routingHeader); |
+ |
+ if (nextHeader) |
+ { |
+ *nextHeader = routingHeader.GetNextHeader (); |
+ } |
+ |
+ Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 (); |
+ |
+ Ipv6Address srcAddress = ipv6header.GetSourceAddress (); |
+ Ipv6Address destAddress = ipv6header.GetDestinationAddress (); |
+ uint8_t hopLimit = ipv6header.GetHopLimit (); |
+ uint8_t segmentsLeft = routingHeader.GetSegmentsLeft (); |
+ uint8_t length = (routingHeader.GetLength () >> 3) - 1; |
+ uint8_t nbAddress = length / 2; |
+ uint8_t nextAddressIndex; |
+ Ipv6Address nextAddress; |
+ |
+ if (segmentsLeft == 0) |
+ { |
+ isDropped = false; |
+ return routingHeader.GetSerializedSize (); |
+ } |
+ |
+ if (length % 2 != 0) |
+ { |
+ NS_LOG_LOGIC ("Malformed header. Drop!"); |
+ /* TODO */ |
moatamri
2009/10/30 11:31:30
same as above
ping67
2009/11/02 17:09:10
Done.
|
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1); */ |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ return routingHeader.GetSerializedSize (); |
+ } |
+ |
+ if (segmentsLeft > nbAddress) |
+ { |
+ NS_LOG_LOGIC ("Malformed header. Drop!"); |
+ /* TODO */ |
+ /* icmpv6->SendErrorParameterError (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3); */ |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ return routingHeader.GetSerializedSize (); |
+ } |
+ |
+ routingHeader.SetSegmentsLeft (segmentsLeft - 1); |
+ nextAddressIndex = nbAddress - segmentsLeft; |
+ nextAddress = routingHeader.GetRouterAddress (nextAddressIndex); |
+ |
+ if (nextAddress.IsMulticast () || destAddress.IsMulticast ()) |
+ { |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ return routingHeader.GetSerializedSize (); |
+ } |
+ |
+ routingHeader.SetRouterAddress (nextAddressIndex, destAddress); |
+ ipv6header.SetDestinationAddress (nextAddress); |
+ |
+ if (hopLimit <= 1) |
+ { |
+ NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!"); |
+ /* TODO */ |
+ /* icmpv6->SendErrorTimeExceeded (malformedPacket, dst, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT); */ |
+ m_dropTrace (packet); |
+ isDropped = true; |
+ return routingHeader.GetSerializedSize (); |
+ } |
+ |
+ routingHeader.SetLength (88); |
+ ipv6header.SetHopLimit (hopLimit - 1); |
+ p->AddHeader (routingHeader); |
+ |
+ /* short-circuiting routing stuff */ |
moatamri
2009/10/30 11:31:30
more explanations?
ping67
2009/11/02 17:09:10
Done.
|
+ |
+ /* XXX taken from src/helper/ipv6-static-rouging.cc |
moatamri
2009/10/30 11:31:30
ipv6-static-routing.cc
ping67
2009/11/02 17:09:10
Done.
|
+ * |
+ * either include (and use) helper (Ipv6StaticRoutingHelper) or |
+ * add a method in Ipv6RoutingProtocol to lookup in routing table |
+ * without callback to Ipv6L3Protocol::LocalDeliver/IpForward/IpMulticastForward |
+ */ |
+ Ptr<Ipv6L3Protocol> ipv6 = GetNode ()->GetObject<Ipv6L3Protocol> (); |
+ Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol (); |
+ Ptr<Ipv6StaticRouting> staticRouting = 0; |
+ |
+ NS_ASSERT_MSG (ipv6rp, "No routing protocol associated with Ipv6"); |
+ if (DynamicCast<Ipv6StaticRouting> (ipv6rp)) |
+ { |
+ staticRouting = DynamicCast<Ipv6StaticRouting> (ipv6rp); |
+ } |
+ else if (DynamicCast<Ipv6ListRouting> (ipv6rp)) |
+ { |
+ Ptr<Ipv6ListRouting> lrp = DynamicCast<Ipv6ListRouting> (ipv6rp); |
+ int16_t priority; |
+ for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) |
+ { |
+ NS_LOG_LOGIC ("Searching for static routing in list"); |
+ Ptr<Ipv6RoutingProtocol> temp = lrp->GetRoutingProtocol (i, priority); |
+ if (DynamicCast<Ipv6StaticRouting> (temp)) |
+ { |
+ NS_LOG_LOGIC ("Found static routing in list"); |
+ staticRouting = DynamicCast<Ipv6StaticRouting> (temp); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ NS_ASSERT (staticRouting); |
+ |
+ Ptr<Ipv6Route> rtentry = staticRouting->LookupStatic (nextAddress, 0); |
+ |
+ if (rtentry) |
+ { |
+ /* we know a route exists so send packet now */ |
+ ipv6->SendRealOut (rtentry, p, ipv6header); |
+ } |
+ else |
+ { |
+ NS_LOG_INFO("No route for next router"); |
+ } |
+ |
+ /* as we directly send packet, mark it as dropped */ |
+ isDropped = true; |
+ |
+ return routingHeader.GetSerializedSize (); |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionESP); |
+ |
+const uint8_t Ipv6ExtensionESP::EXT_NUMBER = 50; |
+ |
+TypeId Ipv6ExtensionESP::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionESP") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionESP> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionESP::Ipv6ExtensionESP () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionESP::~Ipv6ExtensionESP () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionESP::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionESP::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
moatamri
2009/10/30 11:31:30
planning to do it shortly?
ping67
2009/11/02 17:09:10
Shortly ? no. At least not for ns-3.7
|
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ /* TODO */ |
+ |
+ return 0; |
+} |
+ |
+ |
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionAH); |
+ |
+const uint8_t Ipv6ExtensionAH::EXT_NUMBER = 51; |
+ |
+TypeId Ipv6ExtensionAH::GetTypeId () |
+{ |
+ static TypeId tid = TypeId ("ns3::Ipv6ExtensionAH") |
+ .SetParent<Ipv6Extension> () |
+ .AddConstructor<Ipv6ExtensionAH> () |
+ ; |
+ return tid; |
+} |
+ |
+Ipv6ExtensionAH::Ipv6ExtensionAH () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+Ipv6ExtensionAH::~Ipv6ExtensionAH () |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+} |
+ |
+uint8_t Ipv6ExtensionAH::GetExtensionNumber () const |
+{ |
+ NS_LOG_FUNCTION_NOARGS (); |
+ |
+ return EXT_NUMBER; |
+} |
+ |
+uint8_t Ipv6ExtensionAH::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped) |
+{ |
+ NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped); |
+ |
+ /* TODO */ |
+ |
+ return true; |
+} |
+ |
+} /* namespace ns3 */ |
+ |