in simulation/src/internet/model/ipv6-extension.cc [419:590]
void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Header, uint32_t maxFragmentSize, std::list<Ipv6PayloadHeaderPair>& listFragments)
{
NS_LOG_FUNCTION (this << packet << ipv6Header << maxFragmentSize);
Ptr<Packet> p = packet->Copy ();
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.emplace_back (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.emplace_back (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.emplace_back (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;
uint32_t identification = (uint32_t) m_uvar->GetValue (0, (uint32_t)-1);
uint16_t offset = 0;
do
{
if (p->GetSize () > offset + maxFragmentablePartSize)
{
moreFragment = true;
currentFragmentablePartSize = maxFragmentablePartSize;
currentFragmentablePartSize -= currentFragmentablePartSize % 8;
}
else
{
moreFragment = false;
currentFragmentablePartSize = p->GetSize () - offset;
}
fragmentHeader.SetNextHeader (nextHeader);
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)
{
Ipv6ExtensionHopByHopHeader * p =
dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first);
NS_ASSERT (p != 0);
fragment->AddHeader (*p);
}
else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
{
Ipv6ExtensionLooseRoutingHeader * p =
dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first);
NS_ASSERT (p != 0);
fragment->AddHeader (*p);
}
else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
{
Ipv6ExtensionDestinationHeader * p =
dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first);
NS_ASSERT (p != 0);
fragment->AddHeader (*p);
}
}
ipv6Header.SetPayloadLength (fragment->GetSize ());
std::ostringstream oss;
oss << ipv6Header;
fragment->Print (oss);
listFragments.emplace_back (fragment, ipv6Header);
}
while (moreFragment);
for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
{
delete it->first;
}
unfragmentablePart.clear ();
}