void Ping6::Send () { NS_LOG_FUNCTION_NOARGS (); NS_ASSERT (m_sendEvent.IsExpired ()); Ptr<Packet> p = 0; uint8_t* data = new uint8_t[m_size]; Ipv6Address src; Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> (); if (m_ifIndex > 0) { /* hack to have ifIndex in Ipv6RawSocketImpl * maybe add a SetIfIndex in Ipv6RawSocketImpl directly */ Ipv6InterfaceAddress dstIa (m_peerAddress); for (uint32_t i = 0; i < GetNode ()->GetObject<Ipv6> ()->GetNAddresses (m_ifIndex); i++) { src = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, i).GetAddress (); Ipv6InterfaceAddress srcIa (src); if ( srcIa.GetScope() == dstIa.GetScope() ) { break; } } } else { src = m_localAddress; } NS_ASSERT_MSG (m_size >= 4, "ICMPv6 echo request payload size must be >= 4"); data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; p = Create<Packet> (data, 4); p->AddAtEnd (Create<Packet> (m_size - 4)); Icmpv6Echo req (1); req.SetId (0xBEEF); req.SetSeq (m_seq); m_seq++; /* we do not calculate pseudo header checksum here, because we are not sure about * source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl. */ p->AddHeader (req); m_socket->Bind (Inet6SocketAddress (src, 0)); /* use Loose Routing (routing type 0) */ if (m_routers.size ()) { Ipv6ExtensionLooseRoutingHeader routingHeader; routingHeader.SetNextHeader (Ipv6Header::IPV6_ICMPV6); routingHeader.SetLength (m_routers.size () * 16 + 8); routingHeader.SetTypeRouting (0); routingHeader.SetSegmentsLeft (m_routers.size ()); routingHeader.SetRoutersAddress (m_routers); p->AddHeader (routingHeader); m_socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_EXT_ROUTING)); } m_socket->Send (p, 0); ++m_sent; NS_LOG_INFO ("Sent " << p->GetSize () << " bytes to " << m_peerAddress); if (m_sent < m_count) { ScheduleTransmit (m_interval); } delete[] data; }
Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o) { // Make a copy of data from starting position "o" for "s" bytes // Return NULL if results in zero length data NS_LOG_FUNCTION (this << s << o); uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data if (s1 == 0) { return Create<Packet> (); // No data requested } if (data.size () != 0) { // Actual data exists, make copy and return it uint32_t count = 0; std::vector<Ptr<Packet> >::size_type begin = 0; bool beginFound = false; std::vector<Ptr<Packet> >::size_type end = 0; Ptr<Packet> outPacket; Ptr<Packet> endFragment; for (std::vector<Ptr<Packet> >::size_type i=0; i<data.size (); ++i) { count+=data[i]->GetSize (); if (!beginFound) { if (count > o) { if (count >= o + s1) //then just copy within this packet { Ptr<Packet> toFragment = data[i]; uint32_t packetStart = count - toFragment->GetSize (); uint32_t packetOffset = o - packetStart; outPacket = toFragment->CreateFragment (packetOffset, s1); return outPacket; } begin = i; beginFound = true; Ptr<Packet> toFragment = data[begin]; uint32_t packetStart = count - toFragment->GetSize (); uint32_t packetOffset = o - packetStart; uint32_t fragmentLength = count - o; outPacket = toFragment->CreateFragment (packetOffset, fragmentLength); } } else { if (count >= o + s1) { end = i; Ptr<Packet> toFragment = data[end]; uint32_t packetStart = count - toFragment->GetSize (); uint32_t fragmentLength = o + s1 - packetStart; endFragment = toFragment->CreateFragment (0, fragmentLength); break; } } } for (std::vector<Ptr<Packet> >::size_type i=begin+1; i<end; ++i) { outPacket->AddAtEnd (data[i]); } if (endFragment) { outPacket->AddAtEnd (endFragment); } NS_ASSERT (outPacket->GetSize () == s1); return outPacket; } else { // No actual data, just return dummy-data packet of correct size return Create<Packet> (s1); } }