/src/internet/model/ipv6-extension.cc
C++ | 1056 lines | 802 code | 217 blank | 37 comment | 111 complexity | f6a352eac5faf9a931e046b1067d036a MD5 | raw file
Possible License(s): GPL-2.0
- /* -*- 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;
- }
- uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint8_t length, Ipv6Header const& ipv6Header, Ipv6Address dst, uint8_t *nextHeader, bool& isDropped)
- {
- NS_LOG_FUNCTION (this << packet << offset << length << ipv6Header << dst << nextHeader << isDropped);
- // For ICMPv6 Error packets
- Ptr<Packet> malformedPacket = packet->Copy ();
- malformedPacket->AddHeader (ipv6Header);
- Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
- Ptr<Packet> p = packet->Copy ();
- p->RemoveAtStart (offset);
- Ptr<Ipv6OptionDemux> ipv6OptionDemux = GetNode ()->GetObject<Ipv6OptionDemux> ();
- Ptr<Ipv6Option> ipv6Option;
- uint8_t processedSize = 0;
- uint32_t size = p->GetSize ();
- uint8_t *data = new uint8_t[size];
- p->CopyData (data, size);
- uint8_t optionType = 0;
- uint8_t optionLength = 0;
- while (length > processedSize && !isDropped)
- {
- optionType = *(data + processedSize);
- ipv6Option = ipv6OptionDemux->GetOption (optionType);
- if (ipv6Option == 0)
- {
- optionType >>= 6;
- switch (optionType)
- {
- case 0:
- optionLength = *(data + processedSize + 1) + 2;
- 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!");
- icmpv6->SendErrorParameterError (malformedPacket, 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 ())
- {
- icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
- m_dropTrace (packet);
- optionLength = 0;
- isDropped = true;
- break;
- }
- m_dropTrace (packet);
- optionLength = 0;
- isDropped = true;
- break;
- default:
- break;
- }
- }
- else
- {
- optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
- }
- processedSize += optionLength;
- p->RemoveAtStart (optionLength);
- }
- delete [] data;
- return processedSize;
- }
- NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionHopByHop);
- 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);
- Ptr<Packet> p = packet->Copy ();
- p->RemoveAtStart (offset);
- Ipv6ExtensionHopByHopHeader hopbyhopHeader;
- p->RemoveHeader (hopbyhopHeader);
- if (nextHeader)
- {
- *nextHeader = hopbyhopHeader.GetNextHeader ();
- }
- uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
- offset += processedSize;
- uint8_t length = hopbyhopHeader.GetLength () - hopbyhopHeader.GetOptionsOffset ();
- processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
- return processedSize;
- }
- NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionDestination);
- 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)
- {
- NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
- Ptr<Packet> p = packet->Copy ();
- p->RemoveAtStart (offset);
- Ipv6ExtensionDestinationHeader destinationHeader;
- p->RemoveHeader (destinationHeader);
- if (nextHeader)
- {
- *nextHeader = destinationHeader.GetNextHeader ();
- }
- uint8_t processedSize = destinationHeader.GetOptionsOffset ();
- offset += processedSize;
- uint8_t length = destinationHeader.GetLength () - destinationHeader.GetOptionsOffset ();
- processedSize += ProcessOptions (packet, offset, length, ipv6Header, dst, nextHeader, isDropped);
- return processedSize;
- }
- NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionFragment);
- 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;
- Ipv6Header ipHeader = ipv6Header;
- ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
- MapFragments_t::iterator it = m_fragments.find (fragmentsId);
- if (it == m_fragments.end ())
- {
- fragments = Create<Fragments> ();
- m_fragments.insert (std::make_pair (fragmentsId, fragments));
- EventId timeout = Simulator::Schedule (Seconds (60),
- &Ipv6ExtensionFragment::HandleFragmentsTimeout, this,
- fragmentsId, fragments, ipHeader);
- fragments->SetTimeoutEventId (timeout);
- }
- 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 ();
- fragments->CancelTimeout ();
- m_fragments.erase (fragmentsId);
- isDropped = false;
- }
- else
- {
- // the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
- isDropped = true;
- }
- return 0;
- }
- void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragmentSize, std::list<Ptr<Packet> >& listFragments)
- {
- Ptr<Packet> p = packet->Copy ();
- Ipv6Header ipv6Header;
- p->RemoveHeader (ipv6Header);
- uint8_t nextHeader = ipv6Header.GetNextHeader ();
- uint8_t ipv6HeaderSize = ipv6Header.GetSerializedSize ();
- uint8_t type;
- p->CopyData (&type, sizeof(type));
- bool moreHeader = true;
- if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
- || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == 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 ();
- uint8_t type;
- p->CopyData (&type, sizeof(type));
- if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
- || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == 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 buf[2];
- p->CopyData (buf, sizeof(buf));
- uint8_t numberAddress = buf[1] / 2;
- Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader ();
- routingHeader->SetNumberAddress (numberAddress);
- p->RemoveHeader (*routingHeader);
- nextHeader = routingHeader->GetNextHeader ();
- extensionHeaderLength = routingHeader->GetLength ();
- uint8_t type;
- p->CopyData (&type, sizeof(type));
- if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
- || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == 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 ();
- p->RemoveHeader (*destinationHeader);
- nextHeader = destinationHeader->GetNextHeader ();
- extensionHeaderLength = destinationHeader->GetLength ();
- uint8_t type;
- p->CopyData (&type, sizeof(type));
- if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
- || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == 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 ();
- }
- void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId, Ptr<Fragments> fragments, Ipv6Header & ipHeader)
- {
- Ptr<Packet> packet = fragments->GetPartialPacket ();
- packet->AddHeader (ipHeader);
- // if we have at least 8 bytes, we can send an ICMP.
- if ( packet->GetSize () > 8 )
- {
- Ptr<Icmpv6L4Protocol> icmp = GetNode ()->GetObject<Icmpv6L4Protocol> ();
- icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
- }
- m_dropTrace (packet);
- // clear the buffers
- m_fragments.erase (fragmentsId);
- }
- Ipv6ExtensionFragment::Fragments::Fragments ()
- : m_moreFragment (0)
- {
- }
- Ipv6ExtensionFragment::Fragments::~Fragments ()
- {
- }
- 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);
- }
- return p;
- }
- Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPartialPacket () const
- {
- Ptr<Packet> p;
- if ( m_unfragmentable )
- {
- p = m_unfragmentable->Copy ();
- }
- else
- {
- return p;
- }
- 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)
- {
- break;
- }
- p->AddAtEnd (it->first);
- lastEndOffset += it->first->GetSize ();
- }
- return p;
- }
- void Ipv6ExtensionFragment::Fragments::SetTimeoutEventId (EventId event)
- {
- m_timeoutEventId = event;
- return;
- }
- void Ipv6ExtensionFragment::Fragments::CancelTimeout ()
- {
- m_timeoutEventId.Cancel ();
- return;
- }
- NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRouting);
- 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);
- uint8_t buf[4];
- packet->CopyData (buf, sizeof(buf));
- uint8_t routingNextHeader = buf[0];
- uint8_t routingLength = buf[1];
- uint8_t routingTypeRouting = buf[2];
- uint8_t routingSegmentsLeft = buf[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!");
- icmpv6->SendErrorParameterError (malformedPacket, 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);
- 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 buf[2];
- p->CopyData (buf, sizeof(buf));
- uint8_t numberAddress = buf[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!");
- icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
- m_dropTrace (packet);
- isDropped = true;
- return routingHeader.GetSerializedSize ();
- }
- if (segmentsLeft > nbAddress)
- {
- NS_LOG_LOGIC ("Malformed header. Drop!");
- icmpv6->SendErrorParameterError (malformedPacket, 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!");
- icmpv6->SendErrorTimeExceeded (malformedPacket, 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
- *
- * If we process this option,
- * the packet was for us so we resend it to
- * the new destination (modified in the header above).
- */
- Ptr<Ipv6L3Protocol> ipv6 = GetNode ()->GetObject<Ipv6L3Protocol> ();
- Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
- Socket::SocketErrno err;
- NS_ASSERT (ipv6rp);
- Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
- 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);
- 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)
- {
- NS_LOG_FUNCTION (this << packet << offset << ipv6Header << dst << nextHeader << isDropped);
- /* TODO */
- return 0;
- }
- NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionAH);
- 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 */