Index: CHANGES.html
===================================================================
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -97,6 +97,7 @@
- For the TapBridge device, in UseLocal mode there is a MAC learning function. TapBridge has been waiting for the first packet received from tap interface to set the address of the bridged device to the source address of the first packet. This has caused problems with WiFi. The new behavior is that after connection to the tap interface, ns-3 learns the MAC address of that interface with a system call and immediately sets the address of the bridged device to the learned one. See bug 1777 for more details.
- TapBridge device now correctly implements IsLinkUp() method.
+ - IPv6 addresses and routing tables are printed like in Linux "route -A inet6" command.
Index: RELEASE_NOTES
===================================================================
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -21,6 +21,9 @@
New user-visible features
-------------------------
+- IPv6 addresses and routing tables are printed in a more conventional way,
+ closely matching the Linux "route -A inet6" command.
+
- new SixLowPanNetDevice model, headers and associated helpers. The
SixLowPanNetDevice is able to act as a shim between IPv6 and a NetDevice,
compressing IPv6 headers according to RFCs 4944 and 6262.
Index: src/internet/model/ipv6-interface-address.cc
===================================================================
--- a/src/internet/model/ipv6-interface-address.cc
+++ b/src/internet/model/ipv6-interface-address.cc
@@ -140,8 +140,22 @@
std::ostream& operator<< (std::ostream& os, const Ipv6InterfaceAddress &addr)
{
- os << "address=" << addr.GetAddress () << "; prefix=" <<
- addr.GetPrefix () << "; scope=" << addr.GetScope ();
+ os << "address: " << addr.GetAddress () << addr.GetPrefix () << "; scope: ";
+ switch (addr.GetScope ())
+ {
+ case Ipv6InterfaceAddress::HOST:
+ os << "HOST";
+ break;
+ case Ipv6InterfaceAddress::LINKLOCAL:
+ os << "LINK-LOCAL";
+ break;
+ case Ipv6InterfaceAddress::GLOBAL:
+ os << "GLOBAL";
+ break;
+ default:
+ os << "UNKNOWN";
+ break;
+ }
return os;
}
Index: src/internet/model/ipv6-routing-table-entry.cc
===================================================================
--- a/src/internet/model/ipv6-routing-table-entry.cc
+++ b/src/internet/model/ipv6-routing-table-entry.cc
@@ -208,36 +208,36 @@
if (route.IsDefault ())
{
NS_ASSERT (route.IsGateway ());
- os << "default out =" << route.GetInterface () << ", next hop =" << route.GetGateway ();
+ os << "default out: " << route.GetInterface () << ", next hop: " << route.GetGateway ();
}
else if (route.IsHost ())
{
if (route.IsGateway ())
{
- os << "host ="<< route.GetDest () <<
- ", out =" << route.GetInterface () <<
- ", next hop =" << route.GetGateway ();
+ os << "host: "<< route.GetDest () <<
+ ", out: " << route.GetInterface () <<
+ ", next hop: " << route.GetGateway ();
}
else
{
- os << "host =" << route.GetDest () <<
- ", out =" << route.GetInterface ();
+ os << "host: " << route.GetDest () <<
+ ", out: " << route.GetInterface ();
}
}
else if (route.IsNetwork ())
{
if (route.IsGateway ())
{
- os << "network =" << route.GetDestNetwork () <<
- ", mask =" << route.GetDestNetworkPrefix () <<
- ",out =" << route.GetInterface () <<
- ", next hop =" << route.GetGateway ();
+ os << "network: " << route.GetDestNetwork () <<
+ "/ " << int(route.GetDestNetworkPrefix ().GetPrefixLength ()) <<
+ ", out: " << route.GetInterface () <<
+ ", next hop: " << route.GetGateway ();
}
else
{
- os << "network =" << route.GetDestNetwork () <<
- ", mask =" << route.GetDestNetworkPrefix () <<
- ",out =" << route.GetInterface ();
+ os << "network: " << route.GetDestNetwork () <<
+ "/" << int(route.GetDestNetworkPrefix ().GetPrefixLength ()) <<
+ ", out: " << route.GetInterface ();
}
}
else
@@ -314,10 +314,10 @@
std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoutingTableEntry const& route)
{
- os << "origin =" << route.GetOrigin () <<
- ", group =" << route.GetGroup () <<
- ", input interface =" << route.GetInputInterface () <<
- ", output interfaces =";
+ os << "origin: " << route.GetOrigin () <<
+ ", group: " << route.GetGroup () <<
+ ", input interface: " << route.GetInputInterface () <<
+ ", output interfaces: ";
for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i)
{
Index: src/internet/model/ipv6-static-routing.cc
===================================================================
--- a/src/internet/model/ipv6-static-routing.cc
+++ b/src/internet/model/ipv6-static-routing.cc
@@ -25,6 +25,7 @@
#include "ns3/simulator.h"
#include "ns3/ipv6-route.h"
#include "ns3/net-device.h"
+#include "ns3/names.h"
#include "ipv6-static-routing.h"
#include "ipv6-routing-table-entry.h"
@@ -80,18 +81,48 @@
void
Ipv6StaticRouting::PrintRoutingTable (Ptr stream) const
{
- NS_LOG_FUNCTION (this);
+ NS_LOG_FUNCTION (this << stream);
std::ostream* os = stream->GetStream ();
+
+ *os << "Node: " << m_ipv6->GetObject ()->GetId ()
+ << " Time: " << Simulator::Now ().GetSeconds () << "s "
+ << "Ipv6StaticRouting table" << std::endl;
+
if (GetNRoutes () > 0)
{
- *os << "Node: " << m_ipv6->GetObject ()->GetId ()
- << " Time: " << Simulator::Now ().GetSeconds () << "s "
- << "Ipv6StaticRouting table" << std::endl;
-
+ *os << "Destination Next Hop Flag Met Ref Use If" << std::endl;
for (uint32_t j = 0; j < GetNRoutes (); j++)
{
+ std::ostringstream dest, gw, mask, flags;
Ipv6RoutingTableEntry route = GetRoute (j);
- *os << route << std::endl;
+ dest << route.GetDest () << "/" << int(route.GetDestNetworkPrefix ().GetPrefixLength ());
+ *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str ();
+ gw << route.GetGateway ();
+ *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str ();
+ flags << "U";
+ if (route.IsHost ())
+ {
+ flags << "H";
+ }
+ else if (route.IsGateway ())
+ {
+ flags << "G";
+ }
+ *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str ();
+ *os << std::setiosflags (std::ios::left) << std::setw (4) << GetMetric (j);
+ // Ref ct not implemented
+ *os << "-" << " ";
+ // Use not implemented
+ *os << "-" << " ";
+ if (Names::FindName (m_ipv6->GetNetDevice (route.GetInterface ())) != "")
+ {
+ *os << Names::FindName (m_ipv6->GetNetDevice (route.GetInterface ()));
+ }
+ else
+ {
+ *os << route.GetInterface ();
+ }
+ *os << std::endl;
}
}
}
@@ -724,12 +755,12 @@
else /* default route */
{
/* this case is mainly used by configuring default route following RA processing,
- * in case of multipe prefix in RA, the first will configured default route
+ * in case of multiple prefix in RA, the first will configured default route
*/
/* for the moment, all default route has the same metric
* so according to the longest prefix algorithm,
- * the default route choosen will be the last added
+ * the default route chosen will be the last added
*/
SetDefaultRoute (nextHop, interface, prefixToUse);
}
Index: src/network/utils/ipv6-address.cc
===================================================================
--- a/src/network/utils/ipv6-address.cc
+++ b/src/network/utils/ipv6-address.cc
@@ -18,6 +18,29 @@
* Author: Sebastien Vincent
*/
+// Part of the Ipv6Address::Print function has been adapted from inet_ntop6 Linux function.
+// See http://www.net-snmp.org/dev/agent/inet__ntop_8c_source.html
+// Author: Paul Vixie, 1996.
+// The inet_ntop6 function was under the copyright below, which is
+// compatible with GPLv2, see http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses.
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+
#include
#include
@@ -478,23 +501,96 @@
void Ipv6Address::Print (std::ostream& os) const
{
NS_LOG_FUNCTION (this << &os);
- os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[0]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[1] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[2]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[3] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[4]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[5] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[6]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[7] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[8]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[9] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[10]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[11] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[12]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[13] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[14]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[15]
- << std::dec << std::setfill (' ');
+
+ // note: part of this function has been adapted from inet_ntop6 Linux function.
+ // See http://www.net-snmp.org/dev/agent/inet__ntop_8c_source.html
+ // Author: Paul Vixie, 1996.
+
+ if (IsIpv4MappedAddress ())
+ {
+ os << "::ffff:"
+ << (unsigned int) m_address[12] << "."
+ << (unsigned int) m_address[13] << "."
+ << (unsigned int) m_address[14] << "."
+ << (unsigned int) m_address[15];
+ return;
+ }
+
+ uint16_t address[8];
+ uint8_t i;
+
+ for (i=0; i<8; i++)
+ {
+ address[i] = (uint16_t(m_address[2*i]) << 8) | uint16_t(m_address[2*i+1]);
+ }
+
+ int8_t bestBase = -1;
+ int8_t bestLen = 0;
+ int8_t curBase = -1;
+ int8_t curLen = 0;
+
+ for (i=0; i<8; i++)
+ {
+ if (address[i] == 0)
+ {
+ if (curBase == -1)
+ {
+ curBase = i;
+ curLen = 1;
+ }
+ else
+ {
+ curLen++;
+ }
+ }
+ else
+ {
+ if (curBase != -1)
+ {
+ if (bestBase == -1 || curLen > bestLen)
+ {
+ bestBase = curBase;
+ bestLen = curLen;
+ }
+ curBase = -1;
+ }
+ }
+ }
+ if (curBase != -1)
+ {
+ if (bestBase == -1 || curLen > bestLen)
+ {
+ bestBase = curBase;
+ bestLen = curLen;
+ }
+ }
+ if (bestBase != -1 && bestLen < 2)
+ {
+ bestBase = -1;
+ }
+
+ for (i = 0; i < 8;) {
+ // Are we inside the best run of 0x00's?
+ if (i == bestBase)
+ {
+ os << ':';
+ i += bestLen;
+ continue;
+ }
+ // Are we following an initial run of 0x00s or any real hex?
+ if (i != 0)
+ {
+ os << ':';
+ }
+ os << std::hex << (unsigned int) address[i];
+ i++;
+ }
+ // Was it a trailing run of 0x00's?
+ if (bestBase != -1 && (bestBase + bestLen) == 8)
+ {
+ os << ':';
+ }
+ os << std::dec;
}
bool Ipv6Address::IsLocalhost () const
@@ -524,7 +620,7 @@
return false;
}
-bool Ipv6Address::IsIpv4MappedAddress ()
+bool Ipv6Address::IsIpv4MappedAddress () const
{
NS_LOG_FUNCTION (this);
uint8_t v4MappedPrefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -832,22 +928,8 @@
void Ipv6Prefix::Print (std::ostream &os) const
{
NS_LOG_FUNCTION (this << &os);
- os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[0]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[1] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[2]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[3] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[4]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[5] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[6]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[7] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[8]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[9] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[10]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[11] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[12]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[13] << ":"
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[14]
- << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[15];
+
+ os << "/" << (unsigned int) GetPrefixLength();
}
Ipv6Prefix Ipv6Prefix::GetLoopback ()
Index: src/network/utils/ipv6-address.h
===================================================================
--- a/src/network/utils/ipv6-address.h
+++ b/src/network/utils/ipv6-address.h
@@ -269,7 +269,7 @@
* \brief If the address is an IPv4-mapped address
* \return true if address is an IPv4-mapped address, otherwise false.
*/
- bool IsIpv4MappedAddress();
+ bool IsIpv4MappedAddress() const;
/**
* \brief Convert to Address object