diff --git a/src/internet/model/ipv4-l3-protocol.cc b/src/internet/model/ipv4-l3-protocol.cc index e18256446..2e53db543 100644 --- a/src/internet/model/ipv4-l3-protocol.cc +++ b/src/internet/model/ipv4-l3-protocol.cc @@ -114,6 +114,11 @@ Ipv4L3Protocol::GetTypeId (void) "and is being forwarded to another node", MakeTraceSourceAccessor (&Ipv4L3Protocol::m_unicastForwardTrace), "ns3::Ipv4L3Protocol::SentTracedCallback") + .AddTraceSource ("MulticastForward", + "A multicast IPv4 packet was received by this node " + "and is being forwarded to another node", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_multicastForwardTrace), + "ns3::Ipv4L3Protocol::SentTracedCallback") .AddTraceSource ("LocalDeliver", "An IPv4 packet was received by/for this node, " "and it is being forward up the stack", @@ -750,73 +755,100 @@ Ipv4L3Protocol::Send (Ptr packet, { NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route); - Ipv4Header ipHeader; bool mayFragment = true; + + // we need a copy of the packet with its tags in case we need to invoke recursion. + Ptr pktCopyWithTags = packet->Copy (); + uint8_t ttl = m_defaultTtl; - SocketIpTtlTag tag; - bool found = packet->RemovePacketTag (tag); - if (found) + SocketIpTtlTag ipTtlTag; + bool ipTtlTagFound = packet->RemovePacketTag (ipTtlTag); + if (ipTtlTagFound) { - ttl = tag.GetTtl (); + ttl = ipTtlTag.GetTtl (); } uint8_t tos = 0; SocketIpTosTag ipTosTag; - found = packet->RemovePacketTag (ipTosTag); - if (found) + bool ipTosTagFound = packet->RemovePacketTag (ipTosTag); + if (ipTosTagFound) { tos = ipTosTag.GetTos (); } - // Handle a few cases: - // 1) packet is destined to limited broadcast address - // 2) packet is destined to a subnet-directed broadcast address - // 3) packet is not broadcast, and is passed in with a route entry - // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand) - // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP) + // can construct the header here + Ipv4Header ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment); - // 1) packet is destined to limited broadcast address or link-local multicast address + // Handle a few cases: + // 1) packet is passed in with a route entry + // 1a) packet is passed in with a route entry but route->GetGateway is not set (e.g., on-demand) + // 1b) packet is passed in with a route entry and valid gateway + // 2) packet is passed without a route and packet is destined to limited broadcast address + // 3) packet is passed without a route and packet is destined to a subnet-directed broadcast address + // 4) packet is passed without a route, packet is not broadcast (e.g., a raw socket call, or ICMP) + + // 1) packet is passed in with route entry + if (route) + { + // 1a) route->GetGateway is not set (e.g., on-demand) + if (!route->GetGateway ().IsInitialized ()) + { + // This could arise because the synchronous RouteOutput() call + // returned to the transport protocol with a source address but + // there was no next hop available yet (since a route may need + // to be queried). + NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 1a: packet passed with a route but the Gateway address is uninitialized. This case not yet implemented."); + } + + // 1b) with a valid gateway + NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1b: passed in with route and valid gateway"); + int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ()); + m_sendOutgoingTrace (ipHeader, packet, interface); + SendRealOut (route, packet->Copy (), ipHeader); + return; + } + + // 2) packet is destined to limited broadcast address or link-local multicast address if (destination.IsBroadcast () || destination.IsLocalMulticast ()) { - NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast"); - ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment); + NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: limited broadcast - no route"); uint32_t ifaceIndex = 0; for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) { Ptr outInterface = *ifaceIter; - bool sendIt = false; - if (source == Ipv4Address::GetAny ()) - { - sendIt = true; - } - for (uint32_t index = 0; index < outInterface->GetNAddresses (); index++) + // ANY source matches any interface + bool sendIt = source.IsAny (); + // check if some specific address on outInterface matches + for (uint32_t index = 0; !sendIt && index < outInterface->GetNAddresses (); index++) { if (outInterface->GetAddress (index).GetLocal () == source) { sendIt = true; } } + if (sendIt) { - Ptr packetCopy = packet->Copy (); - - NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ()); - - m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); - CallTxTrace (ipHeader, packetCopy, m_node->GetObject (), ifaceIndex); - outInterface->Send (packetCopy, ipHeader, destination); + // create a proxy route for this interface + Ptr route = Create (); + route->SetDestination (destination); + route->SetGateway (Ipv4Address::GetAny ()); + route->SetSource (source); + route->SetOutputDevice (outInterface->GetDevice ()); + DecreaseIdentification (source, destination, protocol); + Send (pktCopyWithTags, source, destination, protocol, route); } } return; } - // 2) check: packet is destined to a subnet-directed broadcast address - uint32_t ifaceIndex = 0; + // 3) check: packet is destined to a subnet-directed broadcast address for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); - ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) + ifaceIter != m_interfaces.end (); ifaceIter++) { Ptr outInterface = *ifaceIter; + uint32_t ifaceIndex = GetInterfaceForDevice (outInterface->GetDevice ()); for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++) { Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j); @@ -824,42 +856,24 @@ Ipv4L3Protocol::Send (Ptr packet, if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) && destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) ) { - NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ()); - ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment); - Ptr packetCopy = packet->Copy (); - m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); - CallTxTrace (ipHeader, packetCopy, m_node->GetObject (), ifaceIndex); - outInterface->Send (packetCopy, ipHeader, destination); + NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: subnet directed bcast to " << ifAddr.GetLocal () << " - no route"); + // create a proxy route for this interface + Ptr route = Create (); + route->SetDestination (destination); + route->SetGateway (Ipv4Address::GetAny ()); + route->SetSource (source); + route->SetOutputDevice (outInterface->GetDevice ()); + DecreaseIdentification (source, destination, protocol); + Send (pktCopyWithTags, source, destination, protocol, route); return; } } } - // 3) packet is not broadcast, and is passed in with a route entry - // with a valid Ipv4Address as the gateway - if (route && route->GetGateway () != Ipv4Address ()) - { - NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route"); - ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment); - int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ()); - m_sendOutgoingTrace (ipHeader, packet, interface); - SendRealOut (route, packet->Copy (), ipHeader); - return; - } - // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand) - if (route && route->GetGateway () == Ipv4Address ()) - { - // This could arise because the synchronous RouteOutput() call - // returned to the transport protocol with a source address but - // there was no next hop available yet (since a route may need - // to be queried). - NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 4: This case not yet implemented"); - } - // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call) - NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 5: passed in with no route " << destination); + // 4) packet is not broadcast, and route is NULL (e.g., a raw socket call) + NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: not broadcast and passed in with no route " << destination); Socket::SocketErrno errno_; Ptr oif (0); // unused for now - ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment); Ptr newRoute; if (m_routingProtocol != 0) { @@ -871,20 +885,29 @@ Ipv4L3Protocol::Send (Ptr packet, } if (newRoute) { - int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ()); - m_sendOutgoingTrace (ipHeader, packet, interface); - SendRealOut (newRoute, packet->Copy (), ipHeader); + DecreaseIdentification (source, destination, protocol); + Send (pktCopyWithTags, source, destination, protocol, newRoute); } else { NS_LOG_WARN ("No route to host. Drop."); m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject (), 0); + DecreaseIdentification (source, destination, protocol); } } -// \todo when should we set ip_id? check whether we are incrementing -// m_identification on packets that may later be dropped in this stack -// and whether that deviates from Linux +void +Ipv4L3Protocol::DecreaseIdentification (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol) +{ + uint64_t src = source.Get (); + uint64_t dst = destination.Get (); + uint64_t srcDst = dst | (src << 32); + std::pair key = std::make_pair (srcDst, protocol); + m_identification[key]--; +} + Ipv4Header Ipv4L3Protocol::BuildHeader ( Ipv4Address source, @@ -950,59 +973,37 @@ Ipv4L3Protocol::SendRealOut (Ptr route, Ptr outInterface = GetInterface (interface); NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface); - if (route->GetGateway () != Ipv4Address ("0.0.0.0")) + Ipv4Address target; + std::string targetLabel; + if (route->GetGateway ().IsAny ()) { - if (outInterface->IsUp ()) + target = ipHeader.GetDestination (); + targetLabel = "destination"; + } + else + { + target = route->GetGateway (); + targetLabel = "gateway"; + } + + if (outInterface->IsUp ()) + { + NS_LOG_LOGIC ("Send to " << targetLabel << " " << target); + if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () ) { - NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ()); - if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () ) + std::list listFragments; + DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments); + for ( std::list::iterator it = listFragments.begin (); it != listFragments.end (); it++ ) { - std::list listFragments; - DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments); - for ( std::list::iterator it = listFragments.begin (); it != listFragments.end (); it++ ) - { - CallTxTrace (it->second, it->first, m_node->GetObject (), interface); - outInterface->Send (it->first, it->second, route->GetGateway ()); - } - } - else - { - CallTxTrace (ipHeader, packet, m_node->GetObject (), interface); - outInterface->Send (packet, ipHeader, route->GetGateway ()); + NS_LOG_LOGIC ("Sending fragment " << *(it->first) ); + CallTxTrace (it->second, it->first, m_node->GetObject (), interface); + outInterface->Send (it->first, it->second, target); } } else { - NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ()); - m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject (), interface); - } - } - else - { - if (outInterface->IsUp ()) - { - NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); - if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () ) - { - std::list listFragments; - DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments); - for ( std::list::iterator it = listFragments.begin (); it != listFragments.end (); it++ ) - { - NS_LOG_LOGIC ("Sending fragment " << *(it->first) ); - CallTxTrace (it->second, it->first, m_node->GetObject (), interface); - outInterface->Send (it->first, it->second, ipHeader.GetDestination ()); - } - } - else - { - CallTxTrace (ipHeader, packet, m_node->GetObject (), interface); - outInterface->Send (packet, ipHeader, ipHeader.GetDestination ()); - } - } - else - { - NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ()); - m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject (), interface); + CallTxTrace (ipHeader, packet, m_node->GetObject (), interface); + outInterface->Send (packet, ipHeader, target); } } } @@ -1019,25 +1020,27 @@ Ipv4L3Protocol::IpMulticastForward (Ptr mrtentry, Ptrfirst; + uint32_t interface = mapIter->first; //uint32_t outputTtl = mapIter->second; // Unused for now Ptr packet = p->Copy (); - Ipv4Header h = header; - h.SetTtl (header.GetTtl () - 1); - if (h.GetTtl () == 0) + Ipv4Header ipHeader = header; + ipHeader.SetTtl (header.GetTtl () - 1); + if (ipHeader.GetTtl () == 0) { NS_LOG_WARN ("TTL exceeded. Drop."); - m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject (), interfaceId); + m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject (), interface); return; } - NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId); + NS_LOG_LOGIC ("Forward multicast via interface " << interface); Ptr rtentry = Create (); - rtentry->SetSource (h.GetSource ()); - rtentry->SetDestination (h.GetDestination ()); + rtentry->SetSource (ipHeader.GetSource ()); + rtentry->SetDestination (ipHeader.GetDestination ()); rtentry->SetGateway (Ipv4Address::GetAny ()); - rtentry->SetOutputDevice (GetNetDevice (interfaceId)); - SendRealOut (rtentry, packet, h); + rtentry->SetOutputDevice (GetNetDevice (interface)); + + m_multicastForwardTrace (ipHeader, packet, interface); + SendRealOut (rtentry, packet, ipHeader); continue; } } diff --git a/src/internet/model/ipv4-l3-protocol.h b/src/internet/model/ipv4-l3-protocol.h index e3a0ff3f8..5a9ab5c22 100644 --- a/src/internet/model/ipv4-l3-protocol.h +++ b/src/internet/model/ipv4-l3-protocol.h @@ -297,6 +297,16 @@ private: virtual void SetWeakEsModel (bool model); virtual bool GetWeakEsModel (void) const; + /** + * \brief Decrease the identification value for a dropped or recursed packet + * \param source source IPv4 address + * \param destination destination IPv4 address + * \param protocol L4 protocol + */ + void DecreaseIdentification (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol); + /** * \brief Construct an IPv4 header. * \param source source IPv4 address @@ -463,6 +473,8 @@ private: TracedCallback, uint32_t> m_sendOutgoingTrace; /// Trace of unicast forwarded packets TracedCallback, uint32_t> m_unicastForwardTrace; + /// Trace of multicast forwarded packets + TracedCallback, uint32_t> m_multicastForwardTrace; /// Trace of locally delivered packets TracedCallback, uint32_t> m_localDeliverTrace; diff --git a/src/internet/test/ipv4-fragmentation-test.cc b/src/internet/test/ipv4-fragmentation-test.cc index db4b2b5ea..5a0ccd24e 100644 --- a/src/internet/test/ipv4-fragmentation-test.cc +++ b/src/internet/test/ipv4-fragmentation-test.cc @@ -109,10 +109,11 @@ class Ipv4FragmentationTest: public TestCase uint8_t *m_data; //!< Data. uint32_t m_size; //!< packet size. uint8_t m_icmpType; //!< ICMP type. + bool m_broadcast; //!< broadcast packets public: virtual void DoRun (void); - Ipv4FragmentationTest (); + Ipv4FragmentationTest (bool broadcast); ~Ipv4FragmentationTest (); // server part @@ -167,14 +168,16 @@ public: }; -Ipv4FragmentationTest::Ipv4FragmentationTest () - : TestCase ("Verify the IPv4 layer 3 protocol fragmentation and reassembly") +Ipv4FragmentationTest::Ipv4FragmentationTest (bool broadcast) + : TestCase (std::string ("Verify the IPv4 layer 3 protocol fragmentation and reassembly: ") + + (broadcast? "broadcast": "unicast")) { m_socketServer = 0; m_data = 0; m_dataSize = 0; m_size = 0; m_icmpType = 0; + m_broadcast = broadcast; } Ipv4FragmentationTest::~Ipv4FragmentationTest () @@ -235,6 +238,7 @@ Ipv4FragmentationTest::StartClient (Ptr ClientNode) m_socketClient->Connect (InetSocketAddress (Ipv4Address ("10.0.0.1"), 9)); CallbackValue cbValue = MakeCallback(&Ipv4FragmentationTest::HandleReadIcmpClient, this); m_socketClient->SetAttribute ("IcmpCallback", cbValue); + m_socketClient->SetAllowBroadcast (m_broadcast); } m_socketClient->SetRecvCallback(MakeCallback(&Ipv4FragmentationTest::HandleReadClient, this)); @@ -306,7 +310,18 @@ Ptr Ipv4FragmentationTest::SendClient (void) p->AddPacketTag (tag); p->AddByteTag (tag); - m_socketClient->Send (p); + if (m_broadcast) + { + Address address; + m_socketClient->GetPeerName (address); + InetSocketAddress saddress = InetSocketAddress::ConvertFrom (address); + saddress.SetIpv4 (Ipv4Address::GetBroadcast ()); + m_socketClient->SendTo (p, 0, saddress); + } + else + { + m_socketClient->Send (p); + } return p; } @@ -527,7 +542,8 @@ public: Ipv4FragmentationTestSuite::Ipv4FragmentationTestSuite () : TestSuite ("ipv4-fragmentation", UNIT) { - AddTestCase (new Ipv4FragmentationTest, TestCase::QUICK); + AddTestCase (new Ipv4FragmentationTest(false), TestCase::QUICK); + AddTestCase (new Ipv4FragmentationTest(true), TestCase::QUICK); } static Ipv4FragmentationTestSuite g_ipv4fragmentationTestSuite; //!< Static variable for test initialization diff --git a/src/network/utils/ipv4-address.cc b/src/network/utils/ipv4-address.cc index d71c11b61..6b628ff47 100644 --- a/src/network/utils/ipv4-address.cc +++ b/src/network/utils/ipv4-address.cc @@ -197,9 +197,10 @@ Ipv4Mask::GetPrefixLength (void) const return tmp; } +static constexpr uint32_t UNINITIALIZED = 0x66666666U; Ipv4Address::Ipv4Address () - : m_address (0x66666666) + : m_address (UNINITIALIZED), m_initialized (false) { NS_LOG_FUNCTION (this); } @@ -207,11 +208,13 @@ Ipv4Address::Ipv4Address (uint32_t address) { NS_LOG_FUNCTION (this << address); m_address = address; + m_initialized = true; } Ipv4Address::Ipv4Address (char const *address) { NS_LOG_FUNCTION (this << address); m_address = AsciiToIpv4Host (address); + m_initialized = true; } uint32_t @@ -225,12 +228,14 @@ Ipv4Address::Set (uint32_t address) { NS_LOG_FUNCTION (this << address); m_address = address; + m_initialized = true; } void Ipv4Address::Set (char const *address) { NS_LOG_FUNCTION (this << address); m_address = AsciiToIpv4Host (address); + m_initialized = true; } Ipv4Address @@ -264,6 +269,13 @@ Ipv4Address::IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const return ( (Get () | mask.GetInverse ()) == Get () ); } +bool +Ipv4Address::IsInitialized (void) const +{ + NS_LOG_FUNCTION (this); + return (m_initialized); +} + bool Ipv4Address::IsAny (void) const { @@ -326,6 +338,8 @@ Ipv4Address::Deserialize (const uint8_t buf[4]) ipv4.m_address |= buf[2]; ipv4.m_address <<= 8; ipv4.m_address |= buf[3]; + ipv4.m_initialized = true; + return ipv4; } diff --git a/src/network/utils/ipv4-address.h b/src/network/utils/ipv4-address.h index a22f9c9fc..9cc3ab1d6 100644 --- a/src/network/utils/ipv4-address.h +++ b/src/network/utils/ipv4-address.h @@ -110,6 +110,11 @@ public: * \param os The output stream to which this Ipv4Address is printed */ void Print (std::ostream &os) const; + + /** + * \return true if address is initialized (i.e., set to something), false otherwise + */ + bool IsInitialized (void) const; /** * \return true if address is 0.0.0.0; false otherwise */ @@ -220,6 +225,7 @@ private: */ static uint8_t GetType (void); uint32_t m_address; //!< IPv4 address + bool m_initialized; //!< IPv4 address has been explicitly initialized to a valid value. /** * \brief Equal to operator. diff --git a/src/network/utils/ipv6-address.cc b/src/network/utils/ipv6-address.cc index 34c429064..a97938f20 100644 --- a/src/network/utils/ipv6-address.cc +++ b/src/network/utils/ipv6-address.cc @@ -282,24 +282,28 @@ Ipv6Address::Ipv6Address () { NS_LOG_FUNCTION (this); memset (m_address, 0x00, 16); + m_initialized = false; } Ipv6Address::Ipv6Address (Ipv6Address const& addr) { // Do not add function logging here, to avoid stack overflow memcpy (m_address, addr.m_address, 16); + m_initialized = true; } Ipv6Address::Ipv6Address (Ipv6Address const* addr) { // Do not add function logging here, to avoid stack overflow memcpy (m_address, addr->m_address, 16); + m_initialized = true; } Ipv6Address::Ipv6Address (char const* address) { NS_LOG_FUNCTION (this << address); AsciiToIpv6Host (address, m_address); + m_initialized = true; } Ipv6Address::Ipv6Address (uint8_t address[16]) @@ -307,6 +311,7 @@ Ipv6Address::Ipv6Address (uint8_t address[16]) NS_LOG_FUNCTION (this << &address); /* 128 bit => 16 bytes */ memcpy (m_address, address, 16); + m_initialized = true; } Ipv6Address::~Ipv6Address () @@ -319,6 +324,7 @@ void Ipv6Address::Set (char const* address) { NS_LOG_FUNCTION (this << address); AsciiToIpv6Host (address, m_address); + m_initialized = true; } void Ipv6Address::Set (uint8_t address[16]) @@ -326,6 +332,7 @@ void Ipv6Address::Set (uint8_t address[16]) /* 128 bit => 16 bytes */ NS_LOG_FUNCTION (this << &address); memcpy (m_address, address, 16); + m_initialized = true; } void Ipv6Address::Serialize (uint8_t buf[16]) const @@ -338,6 +345,7 @@ Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16]) { NS_LOG_FUNCTION (&buf); Ipv6Address ipv6 ((uint8_t*)buf); + ipv6.m_initialized = true; return ipv6; } @@ -353,12 +361,12 @@ Ipv6Address Ipv6Address::MakeIpv4MappedAddress(Ipv4Address addr) Ipv4Address Ipv6Address::GetIpv4MappedAddress() const { NS_LOG_FUNCTION (this); - uint8_t buf[16]; - Ipv4Address v4Addr; + uint8_t buf[16]; + Ipv4Address v4Addr; - Serialize (buf); - v4Addr = Ipv4Address::Deserialize (&buf[12]); - return (v4Addr); + Serialize (buf); + v4Addr = Ipv4Address::Deserialize (&buf[12]); + return (v4Addr); } Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Address addr, Ipv6Address prefix) diff --git a/src/network/utils/ipv6-address.h b/src/network/utils/ipv6-address.h index da65542fa..d0a723058 100644 --- a/src/network/utils/ipv6-address.h +++ b/src/network/utils/ipv6-address.h @@ -344,6 +344,11 @@ public: */ static Ipv6Address ConvertFrom (const Address& address); + /** + * \return true if address is initialized (i.e., set to something), false otherwise + */ + bool IsInitialized (void) const; + /** * \brief Get the 0 (::) Ipv6Address. * \return the :: Ipv6Address representation @@ -410,6 +415,7 @@ private: * \brief The address representation on 128 bits (16 bytes). */ uint8_t m_address[16]; + bool m_initialized; //!< IPv6 address has been explicitly initialized to a valid value. /** * \brief Equal to operator.