Add support for IPv6 transport protocols

This commit is contained in:
Ken Renard
2012-02-20 14:05:07 +01:00
parent 4e460e6d51
commit cf2e9f8212
77 changed files with 3331 additions and 557 deletions

View File

@@ -51,6 +51,74 @@ us a note on ns-developers mailing list. </p>
<li> The Ipv6RawSocketImpl "IcmpFilter" attribute has been removed. Six
new member functions have been added to enable the same functionality.
</li>
<li> IPv6 support for TCP and UDP has been implemented. Socket functions
that take an address [e.g. Send (), Connect (), Bind ()] can accept an
ns3::Ipv6Address or a ns3::Address in addition to taking an ns3::Ipv4Address.
(Note that the ns3::Address must contain a ns3::Ipv6Address or a ns3::Ipv4Address,
otherwise these functions will return an error).
Internally, the socket now stores the remote address as a type "ns3::Address"
instead of a type "ns3::Ipv4Address". The IPv6 Routing Header extension is not
currently supported in ns3 and will not be reflected in the TCP and UDP checksum
calculations per RFC 2460. Also note that UDP checksums for IPv6 packets are
required per RFC, but remain optional and disabled by default in ns3 (in the
interest of performance).
</li>
<li>
When calling Bind () on a socket without an address, the behavior remains the
same: it will bind to the IPv4 "any" address (0.0.0.0). In order to Bind () to
the IPv6 "any" address in a similar fashion, use "Bind6 ()".
</li>
<li>
The prototype for the RxCallback function in the Ipv6EndPoint was changed.
It now includes the destination IPv6 address of the end point which was
needed for TCP. This lead to a small change in the UDP and ICMPv6 L4
protocols as well.
</li>
</ul>
<h2>Changes to build system:</h2>
<ul>
<li> The following files are removed:
<pre>
src/internet/model/ipv4-l4-protocol.cc
src/internet/model/ipv4-l4-protocol.h
src/internet/model/ipv6-l4-protocol.cc
src/internet/model/ipv6-l4-protocol.h
</pre>
and replaced with:
<pre>
src/internet/model/ip-l4-protocol.cc
src/internet/model/ip-l4-protocol.h
</pre>
</li>
</ul>
<h2>Changed behavior:</h2>
<ul>
<li> Dual-stacked IPv6 sockets are implemented. An IPv6 socket can accept
an IPv4 connection, returning the senders address as an IPv4-mapped address
(IPV6_V6ONLY socket option is not implemented).
</li>
<li>
The following examples/application/helpers were modified to support IPv6:
<pre>
csma-layout/examples/csma-star [*]
netanim/examples/star-animation [*]
point-to-point-layout/model/point-to-point-star.cc
point-to-point-layout/model/point-to-point-grid.cc
point-to-point-layout/model/point-to-point-dumbbell.cc
examples/udp/udp-echo [*]
examples/udp-client-server/udp-client-server [*]
examples/udp-client-server/udp-trace-client-server [*]
applications/helper/udp-echo-helper
applications/model/udp-client
applications/model/udp-echo-client
applications/model/udp-echo-server
applications/model/udp-server
applications/model/udp-trace-client
[*] Added '--useIpv6' flag to switch between IPv4 and IPv6
</pre>
</li>
</ul>
<hr>

View File

@@ -21,6 +21,9 @@ Supported platforms
New user-visible features
-------------------------
- Dual-stacked IPv6 sockets are implemented. An IPv6 socket can accept an IPv4
connection, returning the senders address as an IPv4-mapped address
(IPV6_V6ONLY socket option is not implemented).
Bugs fixed
----------

View File

@@ -43,6 +43,13 @@ main (int argc, char *argv[])
LogComponentEnable ("UdpClient", LOG_LEVEL_INFO);
LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
bool useV6 = false;
Address serverAddress;
CommandLine cmd;
cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
cmd.Parse (argc, argv);
//
// Explicitly create the nodes required by the topology (shown above).
//
@@ -63,13 +70,24 @@ main (int argc, char *argv[])
csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
NetDeviceContainer d = csma.Install (n);
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
if (useV6 == false)
{
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
serverAddress = Address (i.GetAddress (1));
}
else
{
Ipv6AddressHelper ipv6;
ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
Ipv6InterfaceContainer i6 = ipv6.Assign (d);
serverAddress = Address(i6.GetAddress (1,1));
}
NS_LOG_INFO ("Create Applications.");
//
@@ -88,7 +106,7 @@ main (int argc, char *argv[])
uint32_t MaxPacketSize = 1024;
Time interPacketInterval = Seconds (0.05);
uint32_t maxPacketCount = 320;
UdpClientHelper client (i.GetAddress (1), port);
UdpClientHelper client (serverAddress, port);
client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));

View File

@@ -42,6 +42,13 @@ main (int argc, char *argv[])
LogComponentEnable ("UdpTraceClient", LOG_LEVEL_INFO);
LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
bool useV6 = false;
Address serverAddress;
CommandLine cmd;
cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
cmd.Parse (argc, argv);
//
// Explicitly create the nodes required by the topology (shown above).
//
@@ -62,13 +69,24 @@ main (int argc, char *argv[])
csma.SetDeviceAttribute ("Mtu", UintegerValue (1500));
NetDeviceContainer d = csma.Install (n);
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
if (useV6 == false)
{
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
serverAddress = Address (i.GetAddress (1));
}
else
{
Ipv6AddressHelper ipv6;
ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
Ipv6InterfaceContainer i6 = ipv6.Assign (d);
serverAddress = Address(i6.GetAddress (1,1));
}
NS_LOG_INFO ("Create Applications.");
//
@@ -85,7 +103,7 @@ main (int argc, char *argv[])
// node one.
//
uint32_t MaxPacketSize = 1472; // Back off 20 (IP) + 8 (UDP) bytes from MTU
UdpTraceClientHelper client (i.GetAddress (1), port,"");
UdpTraceClientHelper client (serverAddress, port,"");
client.SetAttribute ("MaxPacketSize", UintegerValue (MaxPacketSize));
apps = client.Install (n.Get (0));
apps.Start (Seconds (2.0));

View File

@@ -51,7 +51,11 @@ main (int argc, char *argv[])
// Allow the user to override any of the defaults and the above Bind() at
// run-time, via command-line arguments
//
bool useV6 = false;
Address serverAddress;
CommandLine cmd;
cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
cmd.Parse (argc, argv);
//
// Explicitly create the nodes required by the topology (shown above).
@@ -73,13 +77,24 @@ main (int argc, char *argv[])
csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
NetDeviceContainer d = csma.Install (n);
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
if (useV6 == false)
{
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
serverAddress = Address(i.GetAddress (1));
}
else
{
Ipv6AddressHelper ipv6;
ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
Ipv6InterfaceContainer i6 = ipv6.Assign (d);
serverAddress = Address(i6.GetAddress (1,1));
}
NS_LOG_INFO ("Create Applications.");
//
@@ -98,7 +113,7 @@ main (int argc, char *argv[])
uint32_t packetSize = 1024;
uint32_t maxPacketCount = 1;
Time interPacketInterval = Seconds (1.);
UdpEchoClientHelper client (i.GetAddress (1), port);
UdpEchoClientHelper client (serverAddress, port);
client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (packetSize));

View File

@@ -68,10 +68,24 @@ UdpClientHelper::UdpClientHelper ()
{
}
UdpClientHelper::UdpClientHelper (Address address, uint16_t port)
{
m_factory.SetTypeId (UdpClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (address));
SetAttribute ("RemotePort", UintegerValue (port));
}
UdpClientHelper::UdpClientHelper (Ipv4Address address, uint16_t port)
{
m_factory.SetTypeId (UdpClient::GetTypeId ());
SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
SetAttribute ("RemoteAddress", AddressValue (Address(address)));
SetAttribute ("RemotePort", UintegerValue (port));
}
UdpClientHelper::UdpClientHelper (Ipv6Address address, uint16_t port)
{
m_factory.SetTypeId (UdpClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (Address(address)));
SetAttribute ("RemotePort", UintegerValue (port));
}
@@ -99,10 +113,26 @@ UdpTraceClientHelper::UdpTraceClientHelper ()
{
}
UdpTraceClientHelper::UdpTraceClientHelper (Address address, uint16_t port, std::string filename)
{
m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (address));
SetAttribute ("RemotePort", UintegerValue (port));
SetAttribute ("TraceFilename", StringValue (filename));
}
UdpTraceClientHelper::UdpTraceClientHelper (Ipv4Address address, uint16_t port, std::string filename)
{
m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
SetAttribute ("RemoteAddress", AddressValue (Address (address)));
SetAttribute ("RemotePort", UintegerValue (port));
SetAttribute ("TraceFilename", StringValue (filename));
}
UdpTraceClientHelper::UdpTraceClientHelper (Ipv6Address address, uint16_t port, std::string filename)
{
m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (Address (address)));
SetAttribute ("RemotePort", UintegerValue (port));
SetAttribute ("TraceFilename", StringValue (filename));
}

View File

@@ -100,6 +100,8 @@ public:
*/
UdpClientHelper (Ipv4Address ip, uint16_t port);
UdpClientHelper (Ipv6Address ip, uint16_t port);
UdpClientHelper (Address ip, uint16_t port);
/**
* Record an attribute to be set in each Application after it is is created.
@@ -150,7 +152,9 @@ public:
* \param port The port number of the remote udp server
* \param filename the file from which packet traces will be loaded
*/
UdpTraceClientHelper (Address ip, uint16_t port, std::string filename);
UdpTraceClientHelper (Ipv4Address ip, uint16_t port, std::string filename);
UdpTraceClientHelper (Ipv6Address ip, uint16_t port, std::string filename);
/**
* Record an attribute to be set in each Application after it is is created.

View File

@@ -73,10 +73,24 @@ UdpEchoServerHelper::InstallPriv (Ptr<Node> node) const
return app;
}
UdpEchoClientHelper::UdpEchoClientHelper (Address address, uint16_t port)
{
m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (address));
SetAttribute ("RemotePort", UintegerValue (port));
}
UdpEchoClientHelper::UdpEchoClientHelper (Ipv4Address address, uint16_t port)
{
m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
SetAttribute ("RemoteAddress", AddressValue (Address(address)));
SetAttribute ("RemotePort", UintegerValue (port));
}
UdpEchoClientHelper::UdpEchoClientHelper (Ipv6Address address, uint16_t port)
{
m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
SetAttribute ("RemoteAddress", AddressValue (Address(address)));
SetAttribute ("RemotePort", UintegerValue (port));
}

View File

@@ -25,6 +25,7 @@
#include "ns3/node-container.h"
#include "ns3/object-factory.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
namespace ns3 {
@@ -106,7 +107,9 @@ public:
* \param ip The IP address of the remote udp echo server
* \param port The port number of the remote udp echo server
*/
UdpEchoClientHelper (Address ip, uint16_t port);
UdpEchoClientHelper (Ipv4Address ip, uint16_t port);
UdpEchoClientHelper (Ipv6Address ip, uint16_t port);
/**
* Record an attribute to be set in each Application after it is is created.

View File

@@ -21,6 +21,7 @@
#include "ns3/address-utils.h"
#include "ns3/log.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/node.h"
#include "ns3/socket.h"
#include "ns3/udp-socket.h"
@@ -178,6 +179,17 @@ void PacketSink::HandleRead (Ptr<Socket> socket)
m_totalRx += packet->GetSize ();
NS_LOG_INFO (PrintStats (from, packet->GetSize (), m_totalRx));
}
else if (Inet6SocketAddress::IsMatchingType (from))
{
m_totalRx += packet->GetSize ();
Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from);
NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
address.GetIpv6 () << " [" << address << "]"
<< " total Rx " << m_totalRx);
//cast address to void , to suppress 'address' set but not used
//compiler warning in optimized builds
(void) address;
}
m_rxTrace (packet, from);
}
}

View File

@@ -22,6 +22,7 @@
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
@@ -54,10 +55,10 @@ UdpClient::GetTypeId (void)
MakeTimeChecker ())
.AddAttribute (
"RemoteAddress",
"The destination Ipv4Address of the outbound packets",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&UdpClient::m_peerAddress),
MakeIpv4AddressChecker ())
"The destination Address of the outbound packets",
AddressValue (),
MakeAddressAccessor (&UdpClient::m_peerAddress),
MakeAddressChecker ())
.AddAttribute ("RemotePort", "The destination port of the outbound packets",
UintegerValue (100),
MakeUintegerAccessor (&UdpClient::m_peerPort),
@@ -86,6 +87,20 @@ UdpClient::~UdpClient ()
void
UdpClient::SetRemote (Ipv4Address ip, uint16_t port)
{
m_peerAddress = Address(ip);
m_peerPort = port;
}
void
UdpClient::SetRemote (Ipv6Address ip, uint16_t port)
{
m_peerAddress = Address(ip);
m_peerPort = port;
}
void
UdpClient::SetRemote (Address ip, uint16_t port)
{
m_peerAddress = ip;
m_peerPort = port;
@@ -107,8 +122,16 @@ UdpClient::StartApplication (void)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket = Socket::CreateSocket (GetNode (), tid);
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort));
}
else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind6 ();
m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort));
}
}
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
@@ -132,18 +155,29 @@ UdpClient::Send (void)
Ptr<Packet> p = Create<Packet> (m_size-(8+4)); // 8+4 : the size of the seqTs header
p->AddHeader (seqTs);
std::stringstream peerAddressStringStream;
if (Ipv4Address::IsMatchingType (m_peerAddress))
{
peerAddressStringStream << Ipv4Address::ConvertFrom (m_peerAddress);
}
else if (Ipv6Address::IsMatchingType (m_peerAddress))
{
peerAddressStringStream << Ipv6Address::ConvertFrom (m_peerAddress);
}
if ((m_socket->Send (p)) >= 0)
{
++m_sent;
NS_LOG_INFO ("TraceDelay TX " << m_size << " bytes to "
<< m_peerAddress << " Uid: " << p->GetUid ()
<< " Time: " << (Simulator::Now ()).GetSeconds ());
<< peerAddressStringStream.str () << " Uid: "
<< p->GetUid () << " Time: "
<< (Simulator::Now ()).GetSeconds ());
}
else
{
NS_LOG_INFO ("Error while sending " << m_size << " bytes to "
<< m_peerAddress);
<< peerAddressStringStream.str ());
}
if (m_sent < m_count)

View File

@@ -56,6 +56,8 @@ public:
* \param port remote port
*/
void SetRemote (Ipv4Address ip, uint16_t port);
void SetRemote (Ipv6Address ip, uint16_t port);
void SetRemote (Address ip, uint16_t port);
protected:
virtual void DoDispose (void);
@@ -74,7 +76,7 @@ private:
uint32_t m_sent;
Ptr<Socket> m_socket;
Ipv4Address m_peerAddress;
Address m_peerAddress;
uint16_t m_peerPort;
EventId m_sendEvent;

View File

@@ -17,8 +17,10 @@
*/
#include "ns3/log.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/nstime.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
@@ -49,10 +51,10 @@ UdpEchoClient::GetTypeId (void)
MakeTimeAccessor (&UdpEchoClient::m_interval),
MakeTimeChecker ())
.AddAttribute ("RemoteAddress",
"The destination Ipv4Address of the outbound packets",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
MakeIpv4AddressChecker ())
"The destination Address of the outbound packets",
AddressValue (),
MakeAddressAccessor (&UdpEchoClient::m_peerAddress),
MakeAddressChecker ())
.AddAttribute ("RemotePort",
"The destination port of the outbound packets",
UintegerValue (0),
@@ -90,12 +92,26 @@ UdpEchoClient::~UdpEchoClient()
}
void
UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
UdpEchoClient::SetRemote (Address ip, uint16_t port)
{
m_peerAddress = ip;
m_peerPort = port;
}
void
UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
{
m_peerAddress = Address (ip);
m_peerPort = port;
}
void
UdpEchoClient::SetRemote (Ipv6Address ip, uint16_t port)
{
m_peerAddress = Address (ip);
m_peerPort = port;
}
void
UdpEchoClient::DoDispose (void)
{
@@ -112,8 +128,16 @@ UdpEchoClient::StartApplication (void)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket = Socket::CreateSocket (GetNode (), tid);
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind();
m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort));
}
else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind6();
m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort));
}
}
m_socket->SetRecvCallback (MakeCallback (&UdpEchoClient::HandleRead, this));
@@ -281,7 +305,16 @@ UdpEchoClient::Send (void)
++m_sent;
NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
if (InetSocketAddress::IsMatchingType (m_peerAddress))
{
NS_LOG_INFO ("Sent " << m_size << " bytes to " <<
InetSocketAddress::ConvertFrom (m_peerAddress));
}
else if (Inet6SocketAddress::IsMatchingType (m_peerAddress))
{
NS_LOG_INFO ("Sent " << m_size << " bytes to " <<
Inet6SocketAddress::ConvertFrom (m_peerAddress));
}
if (m_sent < m_count)
{
@@ -302,6 +335,11 @@ UdpEchoClient::HandleRead (Ptr<Socket> socket)
NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
InetSocketAddress::ConvertFrom (from).GetIpv4 ());
}
else if (Inet6SocketAddress::IsMatchingType (from))
{
NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
Inet6SocketAddress::ConvertFrom (from).GetIpv6 ());
}
}
}

View File

@@ -49,7 +49,9 @@ public:
* \param ip destination ipv4 address
* \param port destination port
*/
void SetRemote (Address ip, uint16_t port);
void SetRemote (Ipv4Address ip, uint16_t port);
void SetRemote (Ipv6Address ip, uint16_t port);
/**
* Set the data size of the packet (the number of bytes that are sent as data
@@ -142,7 +144,7 @@ private:
uint32_t m_sent;
Ptr<Socket> m_socket;
Ipv4Address m_peerAddress;
Address m_peerAddress;
uint16_t m_peerPort;
EventId m_sendEvent;
/// Callbacks for tracing the packet Tx events

View File

@@ -18,9 +18,11 @@
#include "ns3/log.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/address-utils.h"
#include "ns3/nstime.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/socket.h"
#include "ns3/udp-socket.h"
#include "ns3/simulator.h"
@@ -58,6 +60,7 @@ UdpEchoServer::~UdpEchoServer()
{
NS_LOG_FUNCTION_NOARGS ();
m_socket = 0;
m_socket6 = 0;
}
void
@@ -88,12 +91,34 @@ UdpEchoServer::StartApplication (void)
}
else
{
NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket");
NS_FATAL_ERROR ("Error: Failed to join multicast group");
}
}
}
if (m_socket6 == 0)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket6 = Socket::CreateSocket (GetNode (), tid);
Inet6SocketAddress local6 = Inet6SocketAddress (Ipv6Address::GetAny (), m_port);
m_socket6->Bind (local6);
if (addressUtils::IsMulticast (local6))
{
Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket6);
if (udpSocket)
{
// equivalent to setsockopt (MCAST_JOIN_GROUP)
udpSocket->MulticastJoinGroup (0, local6);
}
else
{
NS_FATAL_ERROR ("Error: Failed to join multicast group");
}
}
}
m_socket->SetRecvCallback (MakeCallback (&UdpEchoServer::HandleRead, this));
m_socket6->SetRecvCallback (MakeCallback (&UdpEchoServer::HandleRead, this));
}
void
@@ -106,6 +131,11 @@ UdpEchoServer::StopApplication ()
m_socket->Close ();
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
}
if (m_socket6 != 0)
{
m_socket6->Close ();
m_socket6->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
}
}
void
@@ -123,6 +153,17 @@ UdpEchoServer::HandleRead (Ptr<Socket> socket)
packet->RemoveAllPacketTags ();
packet->RemoveAllByteTags ();
NS_LOG_LOGIC ("Echoing packet");
socket->SendTo (packet, 0, from);
}
else if (Inet6SocketAddress::IsMatchingType (from))
{
NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
Inet6SocketAddress::ConvertFrom (from).GetIpv6 ());
packet->RemoveAllPacketTags ();
packet->RemoveAllByteTags ();
NS_LOG_LOGIC ("Echoing packet");
socket->SendTo (packet, 0, from);
}

View File

@@ -59,6 +59,7 @@ private:
uint16_t m_port;
Ptr<Socket> m_socket;
Ptr<Socket> m_socket6;
Address m_local;
};

View File

@@ -23,6 +23,7 @@
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
@@ -121,6 +122,17 @@ UdpServer::StartApplication (void)
m_socket->SetRecvCallback (MakeCallback (&UdpServer::HandleRead, this));
if (m_socket6 == 0)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket6 = Socket::CreateSocket (GetNode (), tid);
Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address::GetAny (),
m_port);
m_socket6->Bind (local);
}
m_socket6->SetRecvCallback (MakeCallback (&UdpServer::HandleRead, this));
}
void
@@ -147,13 +159,26 @@ UdpServer::HandleRead (Ptr<Socket> socket)
SeqTsHeader seqTs;
packet->RemoveHeader (seqTs);
uint32_t currentSequenceNumber = seqTs.GetSeq ();
NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
" bytes from "<< InetSocketAddress::ConvertFrom (from).GetIpv4 () <<
" Sequence Number: " << currentSequenceNumber <<
" Uid: " << packet->GetUid () <<
" TXtime: " << seqTs.GetTs () <<
" RXtime: " << Simulator::Now () <<
" Delay: " << Simulator::Now () - seqTs.GetTs ());
if (InetSocketAddress::IsMatchingType (from))
{
NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
" bytes from "<< InetSocketAddress::ConvertFrom (from).GetIpv4 () <<
" Sequence Number: " << currentSequenceNumber <<
" Uid: " << packet->GetUid () <<
" TXtime: " << seqTs.GetTs () <<
" RXtime: " << Simulator::Now () <<
" Delay: " << Simulator::Now () - seqTs.GetTs ());
}
else if (Inet6SocketAddress::IsMatchingType (from))
{
NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
" bytes from "<< Inet6SocketAddress::ConvertFrom (from).GetIpv6 () <<
" Sequence Number: " << currentSequenceNumber <<
" Uid: " << packet->GetUid () <<
" TXtime: " << seqTs.GetTs () <<
" RXtime: " << Simulator::Now () <<
" Delay: " << Simulator::Now () - seqTs.GetTs ());
}
m_lossCounter.NotifyReceived (currentSequenceNumber);
m_received++;

View File

@@ -84,6 +84,7 @@ private:
uint16_t m_port;
Ptr<Socket> m_socket;
Ptr<Socket> m_socket6;
Address m_local;
uint32_t m_received;
PacketLossCounter m_lossCounter;

View File

@@ -22,6 +22,7 @@
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
@@ -59,10 +60,10 @@ UdpTraceClient::GetTypeId (void)
.SetParent<Application> ()
.AddConstructor<UdpTraceClient> ()
.AddAttribute ("RemoteAddress",
"The destination Ipv4Address of the outbound packets",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&UdpTraceClient::m_peerAddress),
MakeIpv4AddressChecker ())
"The destination Address of the outbound packets",
AddressValue (),
MakeAddressAccessor (&UdpTraceClient::m_peerAddress),
MakeAddressChecker ())
.AddAttribute ("RemotePort",
"The destination port of the outbound packets",
UintegerValue (100),
@@ -116,13 +117,29 @@ UdpTraceClient::~UdpTraceClient ()
}
void
UdpTraceClient::SetRemote (Ipv4Address ip, uint16_t port)
UdpTraceClient::SetRemote (Address ip, uint16_t port)
{
m_entries.clear ();
m_peerAddress = ip;
m_peerPort = port;
}
void
UdpTraceClient::SetRemote (Ipv4Address ip, uint16_t port)
{
m_entries.clear ();
m_peerAddress = Address (ip);
m_peerPort = port;
}
void
UdpTraceClient::SetRemote (Ipv6Address ip, uint16_t port)
{
m_entries.clear ();
m_peerAddress = Address (ip);
m_peerPort = port;
}
void
UdpTraceClient::SetTraceFile (std::string traceFile)
{
@@ -223,8 +240,16 @@ UdpTraceClient::StartApplication (void)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
m_socket = Socket::CreateSocket (GetNode (), tid);
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind ();
m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom (m_peerAddress), m_peerPort));
}
else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
{
m_socket->Bind6 ();
m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom (m_peerAddress), m_peerPort));
}
}
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
m_sendEvent = Simulator::Schedule (Seconds (0.0), &UdpTraceClient::Send, this);
@@ -255,16 +280,31 @@ UdpTraceClient::SendPacket (uint32_t size)
SeqTsHeader seqTs;
seqTs.SetSeq (m_sent);
p->AddHeader (seqTs);
std::stringstream addressString;
if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
{
addressString << Ipv4Address::ConvertFrom (m_peerAddress);
}
else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
{
addressString << Ipv6Address::ConvertFrom (m_peerAddress);
}
else
{
addressString << m_peerAddress;
}
if ((m_socket->Send (p)) >= 0)
{
++m_sent;
NS_LOG_INFO ("Sent " << size << " bytes to "
<< m_peerAddress);
<< addressString.str ());
}
else
{
NS_LOG_INFO ("Error while sending " << size << " bytes to "
<< m_peerAddress);
<< addressString.str ());
}
}

View File

@@ -80,7 +80,9 @@ public:
* \param ip the destination ip address to which the stream will be sent
* \param port the destination udp port to which the stream will be sent
*/
void SetRemote (Address ip, uint16_t port);
void SetRemote (Ipv4Address ip, uint16_t port);
void SetRemote (Ipv6Address ip, uint16_t port);
/**
* \brief set the trace file to be used by the application
@@ -122,7 +124,7 @@ private:
};
uint32_t m_sent;
Ptr<Socket> m_socket;
Ipv4Address m_peerAddress;
Address m_peerAddress;
uint16_t m_peerPort;
EventId m_sendEvent;
std::vector<struct TraceEntry> m_entries;

View File

@@ -22,6 +22,7 @@
#include "ns3/applications-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/ipv6-address-generator.h"
// Network topology (default)
//
@@ -61,9 +62,13 @@ main (int argc, char *argv[])
// Default number of nodes in the star. Overridable by command line argument.
//
uint32_t nSpokes = 7;
uint32_t useIpv6 = 0;
Ipv6Address ipv6AddressBase = Ipv6Address("2001::");
Ipv6Prefix ipv6AddressPrefix = Ipv6Prefix(64);
CommandLine cmd;
cmd.AddValue ("nSpokes", "Number of spoke nodes to place in the star", nSpokes);
cmd.AddValue ("useIpv6", "Use Ipv6", useIpv6);
cmd.Parse (argc, argv);
NS_LOG_INFO ("Build star topology.");
@@ -98,7 +103,14 @@ main (int argc, char *argv[])
internet.Install (fillNodes);
NS_LOG_INFO ("Assign IP Addresses.");
star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
if (useIpv6 == 0)
{
star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
}
else
{
star.AssignIpv6Addresses (ipv6AddressBase, ipv6AddressPrefix);
}
//
// We assigned addresses to the logical hub and the first "drop" of the
@@ -111,16 +123,31 @@ main (int argc, char *argv[])
// etc.
//
Ipv4AddressHelper address;
Ipv6AddressHelper address6;
for(uint32_t i = 0; i < star.SpokeCount (); ++i)
{
std::ostringstream subnet;
subnet << "10.1." << i << ".0";
NS_LOG_INFO ("Assign IP Addresses for CSMA subnet " << subnet.str ());
address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
for (uint32_t j = 0; j < nFill; ++j)
if (useIpv6 == 0)
{
address.Assign (fillDevices.Get (i * nFill + j));
std::ostringstream subnet;
subnet << "10.1." << i << ".0";
NS_LOG_INFO ("Assign IP Addresses for CSMA subnet " << subnet.str ());
address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
for (uint32_t j = 0; j < nFill; ++j)
{
address.Assign (fillDevices.Get (i * nFill + j));
}
}
else
{
Ipv6AddressGenerator::Init (ipv6AddressBase, ipv6AddressPrefix);
Ipv6Address v6network = Ipv6AddressGenerator::GetNetwork (ipv6AddressPrefix);
address6.NewNetwork(v6network, ipv6AddressPrefix);
for (uint32_t j = 0; j < nFill; ++j)
{
address6.Assign(fillDevices.Get (i * nFill + j));
}
}
}
@@ -129,11 +156,23 @@ main (int argc, char *argv[])
// Create a packet sink on the star "hub" to receive packets.
//
uint16_t port = 50000;
Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
hubApp.Start (Seconds (1.0));
hubApp.Stop (Seconds (10.0));
if (useIpv6 == 0)
{
Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
hubApp.Start (Seconds (1.0));
hubApp.Stop (Seconds (10.0));
}
else
{
Address hubLocalAddress6 (Inet6SocketAddress (Ipv6Address::GetAny (), port));
PacketSinkHelper packetSinkHelper6 ("ns3::TcpSocketFactory", hubLocalAddress6);
ApplicationContainer hubApp6 = packetSinkHelper6.Install (star.GetHub ());
hubApp6.Start (Seconds (1.0));
hubApp6.Stop (Seconds (10.0));
}
//
// Create OnOff applications to send TCP to the hub, one on each spoke node.
@@ -146,8 +185,16 @@ main (int argc, char *argv[])
for (uint32_t i = 0; i < star.SpokeCount (); ++i)
{
AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
onOffHelper.SetAttribute ("Remote", remoteAddress);
if (useIpv6 == 0)
{
AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
onOffHelper.SetAttribute ("Remote", remoteAddress);
}
else
{
AddressValue remoteAddress (Inet6SocketAddress (star.GetHubIpv6Address (i), port));
onOffHelper.SetAttribute ("Remote", remoteAddress);
}
spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
}
@@ -166,7 +213,15 @@ main (int argc, char *argv[])
for (uint32_t i = 0; i < fillNodes.GetN (); ++i)
{
AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
AddressValue remoteAddress;
if (useIpv6 == 0)
{
remoteAddress = AddressValue(InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
}
else
{
remoteAddress = AddressValue(Inet6SocketAddress (star.GetHubIpv6Address (i / nFill), port));
}
onOffHelper.SetAttribute ("Remote", remoteAddress);
fillApps.Add (onOffHelper.Install (fillNodes.Get (i)));
}
@@ -178,7 +233,10 @@ main (int argc, char *argv[])
//
// Turn on global static routing so we can actually be routed across the star.
//
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
if (useIpv6 == 0)
{
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
}
NS_LOG_INFO ("Enable pcap tracing.");
//

View File

@@ -83,6 +83,18 @@ CsmaStarHelper::GetSpokeIpv4Address (uint32_t i) const
return m_spokeInterfaces.GetAddress (i);
}
Ipv6Address
CsmaStarHelper::GetHubIpv6Address (uint32_t i) const
{
return m_hubInterfaces6.GetAddress (i, 1);
}
Ipv6Address
CsmaStarHelper::GetSpokeIpv6Address (uint32_t i) const
{
return m_spokeInterfaces6.GetAddress (i, 1);
}
uint32_t
CsmaStarHelper::SpokeCount () const
{
@@ -107,4 +119,25 @@ CsmaStarHelper::AssignIpv4Addresses (Ipv4AddressHelper address)
}
}
void
CsmaStarHelper::AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix)
{
Ipv6AddressGenerator::Init(network, prefix);
Ipv6Address v6network;
Ipv6AddressHelper addressHelper;
for (uint32_t i = 0; i < m_spokes.GetN (); ++i)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addressHelper.NewNetwork(v6network, prefix);
Ipv6InterfaceContainer ic = addressHelper.Assign (m_hubDevices.Get (i));
m_hubInterfaces6.Add (ic);
ic = addressHelper.Assign (m_spokeDevices.Get (i));
m_spokeInterfaces6.Add (ic);
Ipv6AddressGenerator::NextNetwork (prefix);
}
}
} // namespace ns3

View File

@@ -23,8 +23,11 @@
#include "csma-helper.h"
#include "ipv4-address-helper.h"
#include "ipv6-address-helper.h"
#include "internet-stack-helper.h"
#include "ipv4-interface-container.h"
#include "ipv6-interface-container.h"
#include "ipv6-address-generator.h"
namespace ns3 {
@@ -91,6 +94,13 @@ public:
*/
Ipv4Address GetHubIpv4Address (uint32_t i) const;
/**
* \param i index into the hub interfaces
*
* \returns Ipv6Address according to indexed hub interface
*/
Ipv6Address GetHubIpv6Address (uint32_t i) const;
/**
* \param i index into the spoke interfaces
*
@@ -98,6 +108,13 @@ public:
*/
Ipv4Address GetSpokeIpv4Address (uint32_t i) const;
/**
* \param i index into the spoke interfaces
*
* \returns Ipv6Address according to indexed spoke interface
*/
Ipv6Address GetSpokeIpv6Address (uint32_t i) const;
/**
* \returns the total number of spokes in the star
*/
@@ -116,6 +133,13 @@ public:
*/
void AssignIpv4Addresses (Ipv4AddressHelper address);
/**
* \param network an IPv6 Address representing the network portion
* of the Ipv6 Address
* \param prefix the prefix length
*/
void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
private:
NodeContainer m_hub;
NetDeviceContainer m_hubDevices;
@@ -123,6 +147,8 @@ private:
NetDeviceContainer m_spokeDevices;
Ipv4InterfaceContainer m_hubInterfaces;
Ipv4InterfaceContainer m_spokeInterfaces;
Ipv6InterfaceContainer m_hubInterfaces6;
Ipv6InterfaceContainer m_spokeInterfaces6;
};
} // namespace ns3

View File

@@ -70,7 +70,7 @@ Layer-3 protocols
~~~~~~~~~~~~~~~~~
At the lowest layer, sitting above the NetDevices, are the "layer 3" protocols,
including IPv4, IPv6 (in the future), and ARP. The class
including IPv4, IPv6, and ARP. The class
:cpp:class:`Ipv4L3Protocol` is an implementation class whose public interface is
typically class :cpp:class:`Ipv4`, but the
Ipv4L3Protocol public API is also used internally at present.
@@ -137,7 +137,12 @@ pending size to a proper value, e.g.:::
Config::SetDefault ("ns3::ArpCache::PendingQueueSize", UintegerValue (MAX_BURST_SIZE/L2MTU*3));
The IPv6 implementation follows a similar architecture.
The IPv6 implementation follows a similar architecture. Dual-stacked nodes (one with
support for both IPv4 and IPv6) will allow an IPv6 socket to receive IPv4 connections
as a standard dual-stacked system does. A socket bound and listening to an IPv6 endpoint
can receive an IPv4 connection and will return the remote address as an IPv4-mapped address.
Support for the IPV6_V6ONLY socket option does not currently exist.
Layer-4 protocols and sockets
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -156,8 +161,14 @@ such as the following:::
The above will query the node to get a pointer to its UDP socket factory, will
create one such socket, and will use the socket with an API similar to the
C-based sockets API, such as ``Connect ()`` and ``Send ()``. See the chapter on
|ns3| sockets for more information.
C-based sockets API, such as ``Connect ()`` and ``Send ()``. The address passed
to the ``Bind ()``, ``Connect ()``, or ``Send ()`` functions may be a
:cpp:class:`Ipv4Address`, :cpp:class:`Ipv6Address`, or :cpp:class:`Address`.
If a :cpp:class:`Address` is passed in and contains anything other than
a :cpp:class:`Ipv4Address` or :cpp:class:`Ipv6Address`, these functions will
return an error. The ``Bind (void)`` and ``Bind6 (void)`` functions bind to
"0.0.0.0" and "::" respectively.
See the chapter on |ns3| sockets for more information.
We have described so far a socket factory (e.g. ``class Udp``) and a socket,
which may be specialized (e.g., class :cpp:class:`UdpSocket`). There are a few

View File

@@ -5,6 +5,3 @@ IPv6
*Placeholder chapter*
IPv6 models are being added to ns-3. A paper on the IPv6 models was published in
WNS2 2008: `<http://lsiit.u-strasbg.fr/Publications/2008/VMM08/>`_.

View File

@@ -22,7 +22,7 @@ TypeId
Icmpv4L4Protocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol")
.SetParent<Ipv4L4Protocol> ()
.SetParent<IpL4Protocol> ()
.AddConstructor<Icmpv4L4Protocol> ()
;
return tid;
@@ -180,7 +180,7 @@ Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp,
const uint8_t payload[8])
{
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
Ptr<Ipv4L4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
Ptr<IpL4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
if (l4 != 0)
{
l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (),
@@ -219,7 +219,7 @@ Icmpv4L4Protocol::HandleTimeExceeded (Ptr<Packet> p,
Forward (source, icmp, 0, ipHeader, payload);
}
enum Ipv4L4Protocol::RxStatus
enum IpL4Protocol::RxStatus
Icmpv4L4Protocol::Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface)
@@ -242,7 +242,16 @@ Icmpv4L4Protocol::Receive (Ptr<Packet> p,
NS_LOG_DEBUG (icmp << " " << *p);
break;
}
return Ipv4L4Protocol::RX_OK;
return IpL4Protocol::RX_OK;
}
enum IpL4Protocol::RxStatus
Icmpv4L4Protocol::Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> incomingInterface)
{
NS_LOG_FUNCTION (this << p << src << dst << incomingInterface);
return IpL4Protocol::RX_ENDPOINT_UNREACH;
}
void
Icmpv4L4Protocol::DoDispose (void)
@@ -250,19 +259,30 @@ Icmpv4L4Protocol::DoDispose (void)
NS_LOG_FUNCTION (this);
m_node = 0;
m_downTarget.Nullify ();
Ipv4L4Protocol::DoDispose ();
IpL4Protocol::DoDispose ();
}
void
Icmpv4L4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
Icmpv4L4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
{
m_downTarget = callback;
}
Ipv4L4Protocol::DownTargetCallback
void
Icmpv4L4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
{
}
IpL4Protocol::DownTargetCallback
Icmpv4L4Protocol::GetDownTarget (void) const
{
return m_downTarget;
}
IpL4Protocol::DownTargetCallback6
Icmpv4L4Protocol::GetDownTarget6 (void) const
{
return (IpL4Protocol::DownTargetCallback6)NULL;
}
} // namespace ns3

View File

@@ -1,7 +1,7 @@
#ifndef ICMPV4_L4_PROTOCOL_H
#define ICMPV4_L4_PROTOCOL_H
#include "ipv4-l4-protocol.h"
#include "ip-l4-protocol.h"
#include "icmpv4.h"
#include "ns3/ipv4-address.h"
@@ -11,7 +11,7 @@ class Node;
class Ipv4Interface;
class Ipv4Route;
class Icmpv4L4Protocol : public Ipv4L4Protocol
class Icmpv4L4Protocol : public IpL4Protocol
{
public:
static TypeId GetTypeId (void);
@@ -24,18 +24,24 @@ public:
static uint16_t GetStaticProtocolNumber (void);
virtual int GetProtocolNumber (void) const;
virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface);
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> incomingInterface);
void SendDestUnreachFragNeeded (Ipv4Header header, Ptr<const Packet> orgData, uint16_t nextHopMtu);
void SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData);
void SendDestUnreachPort (Ipv4Header header, Ptr<const Packet> orgData);
// From Ipv4L4Protocol
virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
// From Ipv4L4Protocol
virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
// From IpL4Protocol
virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
// From IpL4Protocol
virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
protected:
/*
* This function will notify other components connected to the node that a new stack member is now connected
@@ -66,7 +72,7 @@ private:
virtual void DoDispose (void);
Ptr<Node> m_node;
Ipv4L4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback m_downTarget;
};
} // namespace ns3

View File

@@ -66,7 +66,7 @@ const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5;
TypeId Icmpv6L4Protocol::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
.SetParent<Ipv6L4Protocol> ()
.SetParent<IpL4Protocol> ()
.AddConstructor<Icmpv6L4Protocol> ()
.AddAttribute ("DAD", "Always do DAD check.",
BooleanValue (true),
@@ -97,9 +97,10 @@ void Icmpv6L4Protocol::DoDispose ()
cache = 0;
}
m_cacheList.clear ();
m_downTarget.Nullify();
m_node = 0;
Ipv6L4Protocol::DoDispose ();
IpL4Protocol::DoDispose ();
}
void Icmpv6L4Protocol::NotifyNewAggregate ()
@@ -117,6 +118,7 @@ void Icmpv6L4Protocol::NotifyNewAggregate ()
ipv6->Insert (this);
Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
ipv6->AggregateObject (rawFactory);
this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
}
}
}
@@ -174,7 +176,13 @@ void Icmpv6L4Protocol::DoDAD (Ipv6Address target, Ptr<Ipv6Interface> interface)
interface->Send (p, Ipv6Address::MakeSolicitedAddress (target));
}
enum Ipv6L4Protocol::RxStatus_e Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv4Header const &header, Ptr<Ipv4Interface> interface)
{
NS_LOG_FUNCTION (this << packet << header);
return IpL4Protocol::RX_ENDPOINT_UNREACH;
}
enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << packet << src << dst << interface);
Ptr<Packet> p = packet->Copy ();
@@ -225,7 +233,7 @@ enum Ipv6L4Protocol::RxStatus_e Icmpv6L4Protocol::Receive (Ptr<Packet> packet, I
break;
}
return Ipv6L4Protocol::RX_OK;
return IpL4Protocol::RX_OK;
}
void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
@@ -751,7 +759,7 @@ void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address src, Ipv6Add
tag.SetTtl (ttl);
packet->AddPacketTag (tag);
ipv6->Send (packet, src, dst, PROT_NUMBER, 0);
m_downTarget (packet, src, dst, PROT_NUMBER, 0);
}
void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
@@ -777,7 +785,7 @@ void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6H
icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
packet->AddHeader (icmpv6Hdr);
ipv6->Send (packet, src, dst, PROT_NUMBER, route);
m_downTarget (packet, src, dst, PROT_NUMBER, route);
}
else
{
@@ -1244,5 +1252,28 @@ void Icmpv6L4Protocol::FunctionDadTimeout (Ptr<Icmpv6L4Protocol> icmpv6, Ipv6Int
}
}
void
Icmpv6L4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
{
}
void
Icmpv6L4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
{
m_downTarget = callback;
}
IpL4Protocol::DownTargetCallback
Icmpv6L4Protocol::GetDownTarget (void) const
{
return (IpL4Protocol::DownTargetCallback)NULL;
}
IpL4Protocol::DownTargetCallback6
Icmpv6L4Protocol::GetDownTarget6 (void) const
{
return m_downTarget;
}
} /* namespace ns3 */

View File

@@ -27,7 +27,7 @@
#include "ns3/ipv6-address.h"
#include "icmpv6-header.h"
#include "ipv6-l4-protocol.h"
#include "ip-l4-protocol.h"
namespace ns3
{
@@ -42,7 +42,7 @@ class NdiscCache;
* \class Icmpv6L4Protocol
* \brief An implementation of the ICMPv6 protocol.
*/
class Icmpv6L4Protocol : public Ipv6L4Protocol
class Icmpv6L4Protocol : public IpL4Protocol
{
public:
/**
@@ -329,7 +329,12 @@ public:
* \param dst destination address
* \param interface the interface from which the packet is coming
*/
virtual enum Ipv6L4Protocol::RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> interface);
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src, Ipv6Address &dst,
Ptr<Ipv6Interface> interface);
/**
* \brief Function called when DAD timeout.
@@ -477,6 +482,16 @@ private:
* \param device the device
*/
Ptr<NdiscCache> FindCache (Ptr<NetDevice> device);
// From IpL4Protocol
virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
// From IpL4Protocol
virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
IpL4Protocol::DownTargetCallback6 m_downTarget;
};
} /* namespace ns3 */

View File

@@ -1,4 +1,4 @@
// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
@@ -21,35 +21,41 @@
// NS3 - Layer 4 Protocol base class
// George F. Riley, Georgia Tech, Spring 2007
#include "ipv4-l4-protocol.h"
#include "ip-l4-protocol.h"
#include "ns3/uinteger.h"
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol);
NS_OBJECT_ENSURE_REGISTERED (IpL4Protocol);
TypeId
Ipv4L4Protocol::GetTypeId (void)
IpL4Protocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Ipv4L4Protocol")
static TypeId tid = TypeId ("ns3::IpL4Protocol")
.SetParent<Object> ()
.AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.",
.AddAttribute ("ProtocolNumber", "The Ip protocol number.",
UintegerValue (0),
MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber),
MakeUintegerAccessor (&IpL4Protocol::GetProtocolNumber),
MakeUintegerChecker<int> ())
;
return tid;
}
Ipv4L4Protocol::~Ipv4L4Protocol ()
IpL4Protocol::~IpL4Protocol ()
{
}
void
Ipv4L4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv4Address payloadSource,Ipv4Address payloadDestination,
const uint8_t payload[8])
IpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv4Address payloadSource,Ipv4Address payloadDestination,
const uint8_t payload[8])
{}
void
IpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource, Ipv6Address payloadDestination,
const uint8_t payload[8])
{}
} // namespace ns3
} //namespace ns3

View File

@@ -1,4 +1,4 @@
// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
@@ -21,12 +21,14 @@
// NS3 - Layer 4 Protocol base class
// George F. Riley, Georgia Tech, Spring 2007
#ifndef IPV4_L4_PROTOCOL_H
#define IPV4_L4_PROTOCOL_H
#ifndef IP_L4_PROTOCOL_H
#define IP_L4_PROTOCOL_H
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv6-header.h"
#include "ns3/ipv6-interface.h"
namespace ns3 {
@@ -34,14 +36,15 @@ class Packet;
class Ipv4Address;
class Ipv4Interface;
class Ipv4Route;
class Ipv6Route;
/**
* \brief L4 Protocol abstract base class
*
* This is an abstract base class for layer four protocols which use IPv4 as
* This is an abstract base class for layer four protocols which use IP as
* the network layer.
*/
class Ipv4L4Protocol : public Object
class IpL4Protocol : public Object
{
public:
enum RxStatus {
@@ -53,7 +56,7 @@ public:
static TypeId GetTypeId (void);
virtual ~Ipv4L4Protocol ();
virtual ~IpL4Protocol ();
/**
* \returns the protocol number of this protocol.
@@ -71,6 +74,10 @@ public:
virtual enum RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface) = 0;
virtual enum RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> incomingInterface) = 0;
/**
* \param icmpSource the source address of the icmp message
@@ -90,8 +97,13 @@ public:
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv4Address payloadSource, Ipv4Address payloadDestination,
const uint8_t payload[8]);
virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource, Ipv6Address payloadDestination,
const uint8_t payload[8]);
typedef Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > DownTargetCallback;
typedef Callback<void,Ptr<Packet>, Ipv6Address, Ipv6Address, uint8_t, Ptr<Ipv6Route> > DownTargetCallback6;
/**
* This method allows a caller to set the current down target callback
* set for this L4 protocol
@@ -99,6 +111,7 @@ public:
* \param cb current Callback for the L4 protocol
*/
virtual void SetDownTarget (DownTargetCallback cb) = 0;
virtual void SetDownTarget6 (DownTargetCallback6 cb) = 0;
/**
* This method allows a caller to get the current down target callback
* set for this L4 protocol, for
@@ -106,6 +119,7 @@ public:
* \return current Callback for the L4 protocol
*/
virtual DownTargetCallback GetDownTarget (void) const = 0;
virtual DownTargetCallback6 GetDownTarget6 (void) const = 0;
};
} // Namespace ns3

View File

@@ -36,7 +36,6 @@
#include "loopback-net-device.h"
#include "arp-l3-protocol.h"
#include "ipv4-l3-protocol.h"
#include "ipv4-l4-protocol.h"
#include "icmpv4-l4-protocol.h"
#include "ipv4-interface.h"
#include "ipv4-raw-socket-impl.h"
@@ -98,11 +97,11 @@ Ipv4L3Protocol::~Ipv4L3Protocol ()
}
void
Ipv4L3Protocol::Insert (Ptr<Ipv4L4Protocol> protocol)
Ipv4L3Protocol::Insert (Ptr<IpL4Protocol> protocol)
{
m_protocols.push_back (protocol);
}
Ptr<Ipv4L4Protocol>
Ptr<IpL4Protocol>
Ipv4L3Protocol::GetProtocol (int protocolNumber) const
{
for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
@@ -115,7 +114,7 @@ Ipv4L3Protocol::GetProtocol (int protocolNumber) const
return 0;
}
void
Ipv4L3Protocol::Remove (Ptr<Ipv4L4Protocol> protocol)
Ipv4L3Protocol::Remove (Ptr<IpL4Protocol> protocol)
{
m_protocols.remove (protocol);
}
@@ -512,7 +511,7 @@ Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t p
Ptr<Icmpv4L4Protocol>
Ipv4L3Protocol::GetIcmp (void) const
{
Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
Ptr<IpL4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
if (prot != 0)
{
return prot->GetObject<Icmpv4L4Protocol> ();
@@ -863,22 +862,22 @@ Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uin
m_localDeliverTrace (ip, packet, iif);
Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ());
if (protocol != 0)
{
// we need to make a copy in the unlikely event we hit the
// RX_ENDPOINT_UNREACH codepath
Ptr<Packet> copy = p->Copy ();
enum Ipv4L4Protocol::RxStatus status =
enum IpL4Protocol::RxStatus status =
protocol->Receive (p, ip, GetInterface (iif));
switch (status) {
case Ipv4L4Protocol::RX_OK:
case IpL4Protocol::RX_OK:
// fall through
case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
case IpL4Protocol::RX_ENDPOINT_CLOSED:
// fall through
case Ipv4L4Protocol::RX_CSUM_FAILED:
case IpL4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
case IpL4Protocol::RX_ENDPOINT_UNREACH:
if (ip.GetDestination ().IsBroadcast () == true ||
ip.GetDestination ().IsMulticast () == true)
{

View File

@@ -47,7 +47,7 @@ class Ipv4Route;
class Node;
class Socket;
class Ipv4RawSocketImpl;
class Ipv4L4Protocol;
class IpL4Protocol;
class Icmpv4L4Protocol;
@@ -117,7 +117,7 @@ public:
* a working L4 Protocol and returned from this method.
* The caller does not get ownership of the returned pointer.
*/
void Insert (Ptr<Ipv4L4Protocol> protocol);
void Insert (Ptr<IpL4Protocol> protocol);
/**
* \param protocolNumber number of protocol to lookup
* in this L4 Demux
@@ -127,14 +127,14 @@ public:
* to forward packets up the stack to the right protocol.
* It is also called from NodeImpl::GetUdp for example.
*/
Ptr<Ipv4L4Protocol> GetProtocol (int protocolNumber) const;
Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
/**
* \param protocol protocol to remove from this demux.
*
* The input value to this method should be the value
* returned from the Ipv4L4Protocol::Insert method.
*/
void Remove (Ptr<Ipv4L4Protocol> protocol);
void Remove (Ptr<IpL4Protocol> protocol);
/**
* \param ttl default ttl to use
@@ -292,7 +292,7 @@ private:
typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
typedef std::list<Ptr<IpL4Protocol> > L4List_t;
bool m_ipForward;
bool m_weakEsModel;

View File

@@ -116,6 +116,11 @@ Ipv4RawSocketImpl::Bind (void)
return 0;
}
int
Ipv4RawSocketImpl::Bind6 (void)
{
return (-1);
}
int
Ipv4RawSocketImpl::GetSockName (Address &address) const
{
address = InetSocketAddress (m_src, 0);

View File

@@ -27,6 +27,7 @@ public:
virtual Ptr<Node> GetNode (void) const;
virtual int Bind (const Address &address);
virtual int Bind ();
virtual int Bind6 ();
virtual int GetSockName (Address &address) const;
virtual int Close (void);
virtual int ShutdownSend (void);

View File

@@ -24,7 +24,7 @@
#include "ns3/object.h"
#include "ns3/socket.h"
#include "ns3/callback.h"
#include "ns3/ipv4-l4-protocol.h"
#include "ns3/ip-l4-protocol.h"
#include "ns3/ipv4-address.h"
#include "ipv4-route.h"
#include "ipv4-interface-address.h"
@@ -149,7 +149,7 @@ public:
* Adds a protocol to an internal list of L4 protocols.
*
*/
virtual void Insert (Ptr<Ipv4L4Protocol> protocol) = 0;
virtual void Insert (Ptr<IpL4Protocol> protocol) = 0;
/**
* \brief Determine whether address and interface corresponding to

View File

@@ -81,7 +81,7 @@ void Ipv6EndPoint::SetPeer (Ipv6Address addr, uint16_t port)
m_peerPort = port;
}
void Ipv6EndPoint::SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback)
void Ipv6EndPoint::SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> callback)
{
m_rxCallback = callback;
}
@@ -96,11 +96,11 @@ void Ipv6EndPoint::SetDestroyCallback (Callback<void> callback)
m_destroyCallback = callback;
}
void Ipv6EndPoint::ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port)
void Ipv6EndPoint::ForwardUp (Ptr<Packet> p, Ipv6Address srcAddr, Ipv6Address dstAddr, uint16_t port)
{
if (!m_rxCallback.IsNull ())
{
m_rxCallback (p, addr, port);
m_rxCallback (p, srcAddr, dstAddr, port);
}
}
@@ -114,9 +114,9 @@ void Ipv6EndPoint::ForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type,
}
}
void Ipv6EndPoint::DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport)
void Ipv6EndPoint::DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t sport)
{
m_rxCallback (p, saddr, sport);
m_rxCallback (p, saddr, daddr, sport);
}
void Ipv6EndPoint::DoForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type,

View File

@@ -98,7 +98,7 @@ public:
* \brief Set the reception callback.
* \param callback callback function
*/
void SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback);
void SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> callback);
/**
* \brief Set the ICMP callback.
@@ -115,10 +115,11 @@ public:
/**
* \brief Forward the packet to the upper level.
* \param p the packet
* \param addr source address
* \param srcAddr source address
* \param dstAddr source address
* \param port source port
*/
void ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port);
void ForwardUp (Ptr<Packet> p, Ipv6Address srcAddr, Ipv6Address dstAddr, uint16_t port);
/**
* \brief Function called from an L4Protocol implementation
@@ -137,9 +138,10 @@ private:
* \brief ForwardUp wrapper.
* \param p packet
* \param saddr source IPv6 address
* \param daddr dest IPv6 address
* \param sport source port
*/
void DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport);
void DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t sport);
/**
* \brief ForwardIcmp wrapper.
@@ -175,7 +177,7 @@ private:
/**
* \brief The RX callback.
*/
Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> m_rxCallback;
Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> m_rxCallback;
/**
* \brief The ICMPv6 callback.

View File

@@ -30,7 +30,6 @@
#include "loopback-net-device.h"
#include "ipv6-l3-protocol.h"
#include "ipv6-l4-protocol.h"
#include "ipv6-interface.h"
#include "ipv6-raw-socket-impl.h"
#include "ipv6-autoconfigured-prefix.h"
@@ -519,19 +518,19 @@ void Ipv6L3Protocol::SetNode (Ptr<Node> node)
SetupLoopback ();
}
void Ipv6L3Protocol::Insert (Ptr<Ipv6L4Protocol> protocol)
void Ipv6L3Protocol::Insert (Ptr<IpL4Protocol> protocol)
{
NS_LOG_FUNCTION (this << protocol);
m_protocols.push_back (protocol);
}
void Ipv6L3Protocol::Remove (Ptr<Ipv6L4Protocol> protocol)
void Ipv6L3Protocol::Remove (Ptr<IpL4Protocol> protocol)
{
NS_LOG_FUNCTION (this << protocol);
m_protocols.remove (protocol);
}
Ptr<Ipv6L4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
Ptr<IpL4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
{
NS_LOG_FUNCTION (this << protocolNumber);
@@ -571,7 +570,7 @@ void Ipv6L3Protocol::DeleteRawSocket (Ptr<Socket> socket)
Ptr<Icmpv6L4Protocol> Ipv6L3Protocol::GetIcmpv6 () const
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<Ipv6L4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
Ptr<IpL4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
if (protocol)
{
@@ -941,7 +940,7 @@ void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& i
{
NS_LOG_FUNCTION (this << packet << ip << iif);
Ptr<Packet> p = packet->Copy ();
Ptr<Ipv6L4Protocol> protocol = 0;
Ptr<IpL4Protocol> protocol = 0;
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
Ptr<Ipv6Extension> ipv6Extension = 0;
Ipv6Address src = ip.GetSourceAddress ();
@@ -1009,15 +1008,17 @@ void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& i
/* L4 protocol */
Ptr<Packet> copy = p->Copy ();
enum Ipv6L4Protocol::RxStatus_e status = protocol->Receive (p, ip.GetSourceAddress (), ip.GetDestinationAddress (), GetInterface (iif));
enum IpL4Protocol::RxStatus status = protocol->Receive (p, src, dst, GetInterface (iif));
switch (status)
{
case Ipv6L4Protocol::RX_OK:
case IpL4Protocol::RX_OK:
break;
case Ipv6L4Protocol::RX_CSUM_FAILED:
case IpL4Protocol::RX_CSUM_FAILED:
break;
case Ipv6L4Protocol::RX_ENDPOINT_UNREACH:
case IpL4Protocol::RX_ENDPOINT_CLOSED:
break;
case IpL4Protocol::RX_ENDPOINT_UNREACH:
if (ip.GetDestinationAddress ().IsMulticast ())
{
/* do not rely on multicast address */

View File

@@ -34,7 +34,7 @@ namespace ns3
class Node;
class Ipv6Interface;
class Ipv6L4Protocol;
class IpL4Protocol;
class Ipv6Route;
class Ipv6MulticastRoute;
class Ipv6RawSocketImpl;
@@ -102,20 +102,20 @@ public:
* \brief Add an L4 protocol.
* \param protocol L4 protocol
*/
void Insert (Ptr<Ipv6L4Protocol> protocol);
void Insert (Ptr<IpL4Protocol> protocol);
/**
* \brief Remove an L4 protocol.
* \param protocol L4 protocol to remove
*/
void Remove (Ptr<Ipv6L4Protocol> protocol);
void Remove (Ptr<IpL4Protocol> protocol);
/**
* \brief Get L4 protocol by protocol number.
* \param protocolNumber protocol number
* \return corresponding Ipv6L4Protocol or 0 if not found
*/
Ptr<Ipv6L4Protocol> GetProtocol (int protocolNumber) const;
Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
/**
* \brief Create raw IPv6 socket.
@@ -360,7 +360,7 @@ private:
typedef std::list<Ptr<Ipv6Interface> > Ipv6InterfaceList;
typedef std::list<Ptr<Ipv6RawSocketImpl> > SocketList;
typedef std::list<Ptr<Ipv6L4Protocol> > L4List_t;
typedef std::list<Ptr<IpL4Protocol> > L4List_t;
typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> > Ipv6AutoconfiguredPrefixList;
typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> >::iterator Ipv6AutoconfiguredPrefixListI;

View File

@@ -1,53 +0,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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
*/
#include "ns3/uinteger.h"
#include "ipv6-l4-protocol.h"
namespace ns3
{
NS_OBJECT_ENSURE_REGISTERED (Ipv6L4Protocol);
TypeId Ipv6L4Protocol::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::Ipv6L4Protocol")
.SetParent<Object> ()
.AddAttribute ("ProtocolNumber", "The IPv6 protocol number.",
UintegerValue (0),
MakeUintegerAccessor (&Ipv6L4Protocol::GetProtocolNumber),
MakeUintegerChecker<int> ())
;
return tid;
}
Ipv6L4Protocol::~Ipv6L4Protocol ()
{
}
void Ipv6L4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource, Ipv6Address payloadDestination,
const uint8_t* payload)
{}
} /* namespace ns3 */

View File

@@ -1,109 +0,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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
*/
#ifndef IPV6_L4_PROTOCOL_H
#define IPV6_L4_PROTOCOL_H
#include "ns3/object.h"
#include "ns3/ipv6-header.h"
namespace ns3
{
class Packet;
class Ipv6Address;
class Ipv6Interface;
/**
* \class Ipv6L4Protocol
* \brief IPv6 L4 protocol abstract class
*/
class Ipv6L4Protocol : public Object
{
public:
/**
* \enum RxStatus_e
* \brief Status of receive.
*/
enum RxStatus_e
{
RX_OK, /**< Receive OK */
RX_CSUM_FAILED, /**< Checksum of layer 4 protocol failed */
RX_ENDPOINT_UNREACH /**< Destination unreachable */
};
/**
* \brief Get the type identifier.
* \return type identifier
*/
static TypeId GetTypeId (void);
/**
* \brief Destructor.
*/
virtual ~Ipv6L4Protocol ();
/**
* \brief Get the protocol number.
* \return protocol number
*/
virtual int GetProtocolNumber () const = 0;
/**
* \brief Receive method.
*
* Called from lower-level layers to send the packet up
* in the stack.
* \param p packet to forward up
* \param src source address of packet received
* \param dst address of packet received
* \param incomingInterface the Ipv6Interface on which the packet arrived
* \return status (OK, destination unreachable or checksum failed)
*/
virtual enum RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src,
Ipv6Address const &dst,
Ptr<Ipv6Interface> incomingInterface) = 0;
/**
* \brief ICMPv6 receive method.
* \param icmpSource the source address of the ICMPv6 message
* \param icmpTtl the ttl of the ICMPv6 message
* \param icmpType the 'type' field of the ICMPv6 message
* \param icmpCode the 'code' field of the ICMPv6 message
* \param icmpInfo extra information dependent on the ICMPv6 message
* generated by Icmpv6L4Protocol
* \param payloadSource the source address of the packet which triggered
* the ICMPv6 message
* \param payloadDestination the destination address of the packet which
* triggered the ICMPv6 message.
* \param payload the first 8 bytes of the UDP header of the packet
* which triggered the ICMPv6 message.
*/
virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource, Ipv6Address payloadDestination,
const uint8_t* payload);
};
} /* namespace ns3 */
#endif /* IPV6_L4_PROTOCOL_H */

View File

@@ -122,6 +122,11 @@ int Ipv6RawSocketImpl::Bind ()
return 0;
}
int Ipv6RawSocketImpl::Bind6 ()
{
return(Bind());
}
int Ipv6RawSocketImpl::GetSockName (Address& address) const
{
NS_LOG_FUNCTION_NOARGS ();

View File

@@ -116,6 +116,7 @@ public:
* \return 0 if success, -1 otherwise
*/
virtual int Bind ();
virtual int Bind6 ();
/**
* \brief Get socket address.

View File

@@ -96,7 +96,7 @@ TypeId
NscTcpL4Protocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
.SetParent<Ipv4L4Protocol> ()
.SetParent<IpL4Protocol> ()
.AddConstructor<NscTcpL4Protocol>()
.AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
ObjectVectorValue (),
@@ -242,7 +242,7 @@ NscTcpL4Protocol::DoDispose (void)
delete m_nscInterface;
m_nscInterface = 0;
m_downTarget.Nullify ();
Ipv4L4Protocol::DoDispose ();
IpL4Protocol::DoDispose ();
}
Ptr<Socket>
@@ -301,7 +301,7 @@ NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
// NSC m_endPoints->DeAllocate (endPoint);
}
Ipv4L4Protocol::RxStatus
IpL4Protocol::RxStatus
NscTcpL4Protocol::Receive (Ptr<Packet> packet,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface)
@@ -335,7 +335,13 @@ NscTcpL4Protocol::Receive (Ptr<Packet> packet,
delete[] buf;
wakeup ();
return Ipv4L4Protocol::RX_OK;
return IpL4Protocol::RX_OK;
}
IpL4Protocol::RxStatus
NscTcpL4Protocol::Receive(Ptr<Packet>, Ipv6Address&, Ipv6Address&, Ptr<Ipv6Interface>)
{
return IpL4Protocol::RX_ENDPOINT_UNREACH;
}
void NscTcpL4Protocol::SoftInterrupt (void)
@@ -457,16 +463,27 @@ void NscTcpL4Protocol::AddInterface (void)
}
void
NscTcpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
NscTcpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
{
m_downTarget = callback;
}
Ipv4L4Protocol::DownTargetCallback
void
NscTcpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
{
}
IpL4Protocol::DownTargetCallback
NscTcpL4Protocol::GetDownTarget (void) const
{
return m_downTarget;
}
IpL4Protocol::DownTargetCallback6
NscTcpL4Protocol::GetDownTarget6 (void) const
{
return (IpL4Protocol::DownTargetCallback6)0;
}
} // namespace ns3

View File

@@ -24,7 +24,7 @@
#include "ns3/ptr.h"
#include "ns3/object-factory.h"
#include "ns3/timer.h"
#include "ipv4-l4-protocol.h"
#include "ip-l4-protocol.h"
struct INetStack;
@@ -43,7 +43,7 @@ class NscInterfaceImpl;
*
* \brief Nsc wrapper glue, to interface with the Ipv4 protocol underneath.
*/
class NscTcpL4Protocol : public Ipv4L4Protocol {
class NscTcpL4Protocol : public IpL4Protocol {
public:
static const uint8_t PROT_NUMBER;
static TypeId GetTypeId (void);
@@ -80,14 +80,20 @@ public:
* \param header IPv4 Header information
* \param incomingInterface The Ipv4Interface it was received on
*/
virtual Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
virtual IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface);
virtual IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> interface);
// From Ipv4L4Protocol
virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
// From Ipv4L4Protocol
virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
// From IpL4Protocol
virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
// From IpL4Protocol
virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
protected:
virtual void DoDispose (void);
virtual void NotifyNewAggregate ();
@@ -123,7 +129,7 @@ private:
std::string m_nscLibrary;
Timer m_softTimer;
std::vector<Ptr<NscTcpSocketImpl> > m_sockets;
Ipv4L4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback m_downTarget;
};
} // namespace ns3

View File

@@ -214,6 +214,13 @@ NscTcpSocketImpl::Bind (void)
m_endPoint = m_tcp->Allocate ();
return FinishBind ();
}
int
NscTcpSocketImpl::Bind6 ()
{
NS_LOG_LOGIC ("NscTcpSocketImpl: ERROR_AFNOSUPPORT - Bind6 not supported".);
m_errno = ERROR_AFNOSUPPORT;
return (-1);
}
int
NscTcpSocketImpl::Bind (const Address &address)
{

View File

@@ -68,6 +68,7 @@ public:
virtual enum SocketType GetSocketType (void) const;
virtual Ptr<Node> GetNode (void) const;
virtual int Bind (void);
virtual int Bind6 (void);
virtual int Bind (const Address &address);
virtual int Close (void);
virtual int ShutdownSend (void);

View File

@@ -128,23 +128,67 @@ TcpHeader::InitializeChecksum (Ipv4Address source,
m_protocol = protocol;
}
void
TcpHeader::InitializeChecksum (Ipv6Address source,
Ipv6Address destination,
uint8_t protocol)
{
m_source = source;
m_destination = destination;
m_protocol = protocol;
}
void
TcpHeader::InitializeChecksum (Address source,
Address destination,
uint8_t protocol)
{
m_source = source;
m_destination = destination;
m_protocol = protocol;
}
uint16_t
TcpHeader::CalculateHeaderChecksum (uint16_t size) const
{
Buffer buf = Buffer (12);
buf.AddAtStart (12);
/* Buffer size must be at least as large as the largest IP pseudo-header */
/* [per RFC2460, but without consideration for IPv6 extension hdrs] */
/* Src address 16 bytes (more generally, Address::MAX_SIZE) */
/* Dst address 16 bytes (more generally, Address::MAX_SIZE) */
/* Upper layer pkt len 4 bytes */
/* Zero 3 bytes */
/* Next header 1 byte */
uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
Buffer buf = Buffer (maxHdrSz);
buf.AddAtStart (maxHdrSz);
Buffer::Iterator it = buf.Begin ();
uint32_t hdrSize = 0;
WriteTo (it, m_source);
WriteTo (it, m_destination);
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
if (Ipv4Address::IsMatchingType(m_source))
{
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
hdrSize = 12;
}
else
{
it.WriteU16 (0);
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
it.WriteU16 (0);
it.WriteU8 (0);
it.WriteU8 (m_protocol); /* protocol */
hdrSize = 40;
}
it = buf.Begin ();
/* we don't CompleteChecksum ( ~ ) now */
return ~(it.CalculateIpChecksum (12));
return ~(it.CalculateIpChecksum (hdrSize));
}
bool

View File

@@ -26,6 +26,7 @@
#include "ns3/buffer.h"
#include "ns3/tcp-socket-factory.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/sequence-number.h"
namespace ns3 {
@@ -132,6 +133,12 @@ public:
void InitializeChecksum (Ipv4Address source,
Ipv4Address destination,
uint8_t protocol);
void InitializeChecksum (Ipv6Address source,
Ipv6Address destination,
uint8_t protocol);
void InitializeChecksum (Address source,
Address destination,
uint8_t protocol);
typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16,
URG = 32, ECE = 64, CWR = 128} Flags_t;
@@ -160,8 +167,8 @@ private:
uint16_t m_windowSize;
uint16_t m_urgentPointer;
Ipv4Address m_source;
Ipv4Address m_destination;
Address m_source;
Address m_destination;
uint8_t m_protocol;
uint16_t m_initialChecksum;

View File

@@ -28,12 +28,17 @@
#include "ns3/node.h"
#include "ns3/simulator.h"
#include "ns3/ipv4-route.h"
#include "ns3/ipv6-route.h"
#include "tcp-l4-protocol.h"
#include "tcp-header.h"
#include "ipv4-end-point-demux.h"
#include "ipv6-end-point-demux.h"
#include "ipv4-end-point.h"
#include "ipv6-end-point.h"
#include "ipv4-l3-protocol.h"
#include "ipv6-l3-protocol.h"
#include "ipv6-routing-protocol.h"
#include "tcp-socket-factory-impl.h"
#include "tcp-newreno.h"
#include "rtt-estimator.h"
@@ -61,7 +66,7 @@ TypeId
TcpL4Protocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpL4Protocol")
.SetParent<Ipv4L4Protocol> ()
.SetParent<IpL4Protocol> ()
.AddConstructor<TcpL4Protocol> ()
.AddAttribute ("RttEstimatorType",
"Type of RttEstimator objects.",
@@ -82,7 +87,7 @@ TcpL4Protocol::GetTypeId (void)
}
TcpL4Protocol::TcpL4Protocol ()
: m_endPoints (new Ipv4EndPointDemux ())
: m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_LOGIC ("Made a TcpL4Protocol "<<this);
@@ -107,23 +112,36 @@ TcpL4Protocol::SetNode (Ptr<Node> node)
void
TcpL4Protocol::NotifyNewAggregate ()
{
Ptr<Node> node = this->GetObject<Node> ();
Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol> ();
if (m_node == 0)
{
Ptr<Node> node = this->GetObject<Node> ();
if (node != 0)
if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
{
Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
if (ipv4 != 0)
{
this->SetNode (node);
ipv4->Insert (this);
Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
tcpFactory->SetTcp (this);
node->AggregateObject (tcpFactory);
this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
}
this->SetNode (node);
Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
tcpFactory->SetTcp (this);
node->AggregateObject (tcpFactory);
}
}
// We set at least one of our 2 down targets to the IPv4/IPv6 send
// functions. Since these functions have different prototypes, we
// need to keep track of whether we are connected to an IPv4 or
// IPv6 lower layer and call the appropriate one.
if (ipv4 != 0)
{
ipv4->Insert(this);
this->SetDownTarget(MakeCallback(&Ipv4::Send, ipv4));
}
if (ipv6 != 0)
{
ipv6->Insert(this);
this->SetDownTarget6(MakeCallback(&Ipv6L3Protocol::Send, ipv6));
}
Object::NotifyNewAggregate ();
}
@@ -145,9 +163,16 @@ TcpL4Protocol::DoDispose (void)
m_endPoints = 0;
}
if (m_endPoints6 != 0)
{
delete m_endPoints6;
m_endPoints6 = 0;
}
m_node = 0;
m_downTarget.Nullify ();
Ipv4L4Protocol::DoDispose ();
m_downTarget6.Nullify ();
IpL4Protocol::DoDispose ();
}
Ptr<Socket>
@@ -216,7 +241,51 @@ TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
m_endPoints->DeAllocate (endPoint);
}
enum Ipv4L4Protocol::RxStatus
Ipv6EndPoint *
TcpL4Protocol::Allocate6 (void)
{
NS_LOG_FUNCTION_NOARGS ();
return m_endPoints6->Allocate ();
}
Ipv6EndPoint *
TcpL4Protocol::Allocate6 (Ipv6Address address)
{
NS_LOG_FUNCTION (this << address);
return m_endPoints6->Allocate (address);
}
Ipv6EndPoint *
TcpL4Protocol::Allocate6 (uint16_t port)
{
NS_LOG_FUNCTION (this << port);
return m_endPoints6->Allocate (port);
}
Ipv6EndPoint *
TcpL4Protocol::Allocate6 (Ipv6Address address, uint16_t port)
{
NS_LOG_FUNCTION (this << address << port);
return m_endPoints6->Allocate (address, port);
}
Ipv6EndPoint *
TcpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
Ipv6Address peerAddress, uint16_t peerPort)
{
NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
return m_endPoints6->Allocate (localAddress, localPort,
peerAddress, peerPort);
}
void
TcpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
{
NS_LOG_FUNCTION (this << endPoint);
m_endPoints6->DeAllocate (endPoint);
}
enum IpL4Protocol::RxStatus
TcpL4Protocol::Receive (Ptr<Packet> packet,
Ipv4Header const &ipHeader,
Ptr<Ipv4Interface> incomingInterface)
@@ -241,7 +310,7 @@ TcpL4Protocol::Receive (Ptr<Packet> packet,
if(!tcpHeader.IsChecksumOk ())
{
NS_LOG_INFO ("Bad checksum, dropping packet!");
return Ipv4L4Protocol::RX_CSUM_FAILED;
return IpL4Protocol::RX_CSUM_FAILED;
}
NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
@@ -250,6 +319,15 @@ TcpL4Protocol::Receive (Ptr<Packet> packet,
ipHeader.GetSource (), tcpHeader.GetSourcePort (),incomingInterface);
if (endPoints.empty ())
{
if (this->GetObject<Ipv6L3Protocol> () != 0)
{
NS_LOG_LOGIC (" No Ipv4 endpoints matched on TcpL4Protocol, trying Ipv6 "<<this);
Ptr<Ipv6Interface> fakeInterface;
Ipv6Address src = Ipv6Address::MakeIpv4MappedAddress (ipHeader.GetSource ());
Ipv6Address dst = Ipv6Address::MakeIpv4MappedAddress (ipHeader.GetDestination ());
return (this->Receive (packet, src, dst, fakeInterface));
}
NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<<this);
std::ostringstream oss;
oss<<" destination IP: ";
@@ -279,18 +357,100 @@ TcpL4Protocol::Receive (Ptr<Packet> packet,
header.SetSourcePort (tcpHeader.GetDestinationPort ());
header.SetDestinationPort (tcpHeader.GetSourcePort ());
SendPacket (rstPacket, header, ipHeader.GetDestination (), ipHeader.GetSource ());
return Ipv4L4Protocol::RX_ENDPOINT_CLOSED;
return IpL4Protocol::RX_ENDPOINT_CLOSED;
}
else
{
return Ipv4L4Protocol::RX_ENDPOINT_CLOSED;
return IpL4Protocol::RX_ENDPOINT_CLOSED;
}
}
NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
(*endPoints.begin ())->ForwardUp (packet, ipHeader, tcpHeader.GetSourcePort (),
incomingInterface);
return Ipv4L4Protocol::RX_OK;
return IpL4Protocol::RX_OK;
}
enum IpL4Protocol::RxStatus
TcpL4Protocol::Receive (Ptr<Packet> packet,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << packet << src << dst);
TcpHeader tcpHeader;
// If we are receving a v4-mapped packet, we will re-calculate the TCP checksum
// Is it worth checking every received "v6" packet to see if it is v4-mapped in
// order to avoid re-calculating TCP checksums for v4-mapped packets?
if(Node::ChecksumEnabled ())
{
tcpHeader.EnableChecksums ();
tcpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
}
packet->PeekHeader (tcpHeader);
NS_LOG_LOGIC ("TcpL4Protocol " << this
<< " receiving seq " << tcpHeader.GetSequenceNumber ()
<< " ack " << tcpHeader.GetAckNumber ()
<< " flags "<< std::hex << (int)tcpHeader.GetFlags () << std::dec
<< " data size " << packet->GetSize ());
if(!tcpHeader.IsChecksumOk ())
{
NS_LOG_INFO ("Bad checksum, dropping packet!");
return IpL4Protocol::RX_CSUM_FAILED;
}
NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
Ipv6EndPointDemux::EndPoints endPoints =
m_endPoints6->Lookup (dst, tcpHeader.GetDestinationPort (),
src, tcpHeader.GetSourcePort (),interface);
if (endPoints.empty ())
{
NS_LOG_LOGIC (" No IPv6 endpoints matched on TcpL4Protocol "<<this);
std::ostringstream oss;
oss<<" destination IP: ";
dst.Print (oss);
oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
src.Print (oss);
oss<<" source port: "<<tcpHeader.GetSourcePort ();
NS_LOG_LOGIC (oss.str ());
if (!(tcpHeader.GetFlags () & TcpHeader::RST))
{
// build a RST packet and send
Ptr<Packet> rstPacket = Create<Packet> ();
TcpHeader header;
if (tcpHeader.GetFlags () & TcpHeader::ACK)
{
// ACK bit was set
header.SetFlags (TcpHeader::RST);
header.SetSequenceNumber (header.GetAckNumber ());
}
else
{
header.SetFlags (TcpHeader::RST | TcpHeader::ACK);
header.SetSequenceNumber (SequenceNumber32 (0));
header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber32 (1));
}
header.SetSourcePort (tcpHeader.GetDestinationPort ());
header.SetDestinationPort (tcpHeader.GetSourcePort ());
SendPacket (rstPacket, header, dst, src);
return IpL4Protocol::RX_ENDPOINT_CLOSED;
}
else
{
return IpL4Protocol::RX_ENDPOINT_CLOSED;
}
}
NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
(*endPoints.begin ())->ForwardUp (packet, src, dst, tcpHeader.GetSourcePort ());
return IpL4Protocol::RX_OK;
}
void
@@ -337,6 +497,50 @@ TcpL4Protocol::Send (Ptr<Packet> packet,
}
}
void
TcpL4Protocol::Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport, Ptr<NetDevice> oif)
{
NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << oif);
TcpHeader tcpHeader;
tcpHeader.SetDestinationPort (dport);
tcpHeader.SetSourcePort (sport);
if(Node::ChecksumEnabled ())
{
tcpHeader.EnableChecksums ();
}
tcpHeader.InitializeChecksum (saddr,
daddr,
PROT_NUMBER);
tcpHeader.SetFlags (TcpHeader::ACK);
tcpHeader.SetAckNumber (SequenceNumber32 (0));
packet->AddHeader (tcpHeader);
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
if (ipv6 != 0)
{
Ipv6Header header;
header.SetDestinationAddress (daddr);
header.SetNextHeader (PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv6Route> route;
Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
if (ipv6->GetRoutingProtocol () != 0)
{
route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
}
else
{
NS_LOG_ERROR ("No IPV6 Routing Protocol");
route = 0;
}
ipv6->Send (packet, saddr, daddr, PROT_NUMBER, route);
}
}
void
TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
Ipv4Address saddr, Ipv4Address daddr, Ptr<NetDevice> oif)
@@ -385,16 +589,79 @@ TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
}
void
TcpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
Ipv6Address saddr, Ipv6Address daddr, Ptr<NetDevice> oif)
{
NS_LOG_LOGIC ("TcpL4Protocol " << this
<< " sending seq " << outgoing.GetSequenceNumber ()
<< " ack " << outgoing.GetAckNumber ()
<< " flags " << std::hex << (int)outgoing.GetFlags () << std::dec
<< " data size " << packet->GetSize ());
NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
// XXX outgoingHeader cannot be logged
if (daddr.IsIpv4MappedAddress ())
{
return (SendPacket (packet, outgoing, saddr.GetIpv4MappedAddress(), daddr.GetIpv4MappedAddress(), oif));
}
TcpHeader outgoingHeader = outgoing;
outgoingHeader.SetLength (5); //header length in units of 32bit words
/* outgoingHeader.SetUrgentPointer (0); //XXX */
if(Node::ChecksumEnabled ())
{
outgoingHeader.EnableChecksums ();
}
outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
packet->AddHeader (outgoingHeader);
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
if (ipv6 != 0)
{
Ipv6Header header;
header.SetDestinationAddress (daddr);
header.SetSourceAddress (saddr);
header.SetNextHeader (PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv6Route> route;
if (ipv6->GetRoutingProtocol () != 0)
{
route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
}
else
{
NS_LOG_ERROR ("No IPV6 Routing Protocol");
route = 0;
}
m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
}
else
NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv6 interface");
}
void
TcpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
{
m_downTarget = callback;
}
Ipv4L4Protocol::DownTargetCallback
IpL4Protocol::DownTargetCallback
TcpL4Protocol::GetDownTarget (void) const
{
return m_downTarget;
}
void
TcpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
{
m_downTarget6 = callback;
}
IpL4Protocol::DownTargetCallback6
TcpL4Protocol::GetDownTarget6 (void) const
{
return m_downTarget6;
}
} // namespace ns3

View File

@@ -25,9 +25,10 @@
#include "ns3/packet.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/ptr.h"
#include "ns3/object-factory.h"
#include "ipv4-l4-protocol.h"
#include "ip-l4-protocol.h"
#include "ns3/net-device.h"
namespace ns3 {
@@ -36,9 +37,11 @@ class Node;
class Socket;
class TcpHeader;
class Ipv4EndPointDemux;
class Ipv6EndPointDemux;
class Ipv4Interface;
class TcpSocketBase;
class Ipv4EndPoint;
class Ipv6EndPoint;
/**
* \ingroup tcp
@@ -50,7 +53,7 @@ class Ipv4EndPoint;
* packets from IP, and forwards them up to the endpoints.
*/
class TcpL4Protocol : public Ipv4L4Protocol {
class TcpL4Protocol : public IpL4Protocol {
public:
static TypeId GetTypeId (void);
static const uint8_t PROT_NUMBER;
@@ -77,8 +80,15 @@ public:
Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort);
Ipv6EndPoint *Allocate6 (void);
Ipv6EndPoint *Allocate6 (Ipv6Address address);
Ipv6EndPoint *Allocate6 (uint16_t port);
Ipv6EndPoint *Allocate6 (Ipv6Address address, uint16_t port);
Ipv6EndPoint *Allocate6 (Ipv6Address localAddress, uint16_t localPort,
Ipv6Address peerAddress, uint16_t peerPort);
void DeAllocate (Ipv4EndPoint *endPoint);
void DeAllocate (Ipv6EndPoint *endPoint);
/**
* \brief Send a packet via TCP
@@ -92,20 +102,29 @@ public:
void Send (Ptr<Packet> packet,
Ipv4Address saddr, Ipv4Address daddr,
uint16_t sport, uint16_t dport, Ptr<NetDevice> oif = 0);
void Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport, Ptr<NetDevice> oif = 0);
/**
* \brief Receive a packet up the protocol stack
* \param p The Packet to dump the contents into
* \param header IPv4 Header information
* \param incomingInterface The Ipv4Interface it was received on
*/
virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> incomingInterface);
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> interface);
// From Ipv4L4Protocol
virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
// From Ipv4L4Protocol
virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
// From IpL4Protocol
virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
// From IpL4Protocol
virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
protected:
virtual void DoDispose (void);
@@ -117,17 +136,21 @@ protected:
private:
Ptr<Node> m_node;
Ipv4EndPointDemux *m_endPoints;
Ipv6EndPointDemux *m_endPoints6;
TypeId m_rttTypeId;
TypeId m_socketTypeId;
private:
friend class TcpSocketBase;
void SendPacket (Ptr<Packet>, const TcpHeader &,
Ipv4Address, Ipv4Address, Ptr<NetDevice> oif = 0);
void SendPacket (Ptr<Packet>, const TcpHeader &,
Ipv6Address, Ipv6Address, Ptr<NetDevice> oif = 0);
TcpL4Protocol (const TcpL4Protocol &o);
TcpL4Protocol &operator = (const TcpL4Protocol &o);
std::vector<Ptr<TcpSocketBase> > m_sockets;
Ipv4L4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback6 m_downTarget6;
};
} // namespace ns3

View File

@@ -25,11 +25,15 @@
#include "ns3/abort.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/log.h"
#include "ns3/ipv4.h"
#include "ns3/ipv6.h"
#include "ns3/ipv4-interface-address.h"
#include "ns3/ipv4-route.h"
#include "ns3/ipv6-route.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/ipv6-routing-protocol.h"
#include "ns3/simulation-singleton.h"
#include "ns3/simulator.h"
#include "ns3/packet.h"
@@ -39,6 +43,8 @@
#include "tcp-socket-base.h"
#include "tcp-l4-protocol.h"
#include "ipv4-end-point.h"
#include "ipv6-end-point.h"
#include "ipv6-l3-protocol.h"
#include "tcp-header.h"
#include "rtt-estimator.h"
@@ -95,6 +101,7 @@ TcpSocketBase::TcpSocketBase (void)
: m_dupAckCount (0),
m_delAckCount (0),
m_endPoint (0),
m_endPoint6 (0),
m_node (0),
m_tcp (0),
m_rtt (0),
@@ -126,6 +133,7 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
m_persistTimeout (sock.m_persistTimeout),
m_cnTimeout (sock.m_cnTimeout),
m_endPoint (0),
m_endPoint6 (0),
m_node (sock.m_node),
m_tcp (sock.m_tcp),
m_rtt (0),
@@ -180,6 +188,13 @@ TcpSocketBase::~TcpSocketBase (void)
m_tcp->DeAllocate (m_endPoint);
NS_ASSERT (m_endPoint == 0);
}
if (m_endPoint6 != 0)
{
NS_ASSERT (m_tcp != 0);
NS_ASSERT (m_endPoint6 != 0);
m_tcp->DeAllocate (m_endPoint6);
NS_ASSERT (m_endPoint6 == 0);
}
m_tcp = 0;
CancelAllTimers ();
}
@@ -233,7 +248,8 @@ TcpSocketBase::Bind (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_endPoint = m_tcp->Allocate ();
if (0 == m_endPoint)
m_endPoint6 = m_tcp->Allocate6 ();
if (0 == m_endPoint || 0 == m_endPoint6)
{
m_errno = ERROR_ADDRNOTAVAIL;
return -1;
@@ -242,40 +258,76 @@ TcpSocketBase::Bind (void)
return SetupCallback ();
}
int
TcpSocketBase::Bind6 (void)
{
return Bind ();
}
/** Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
int
TcpSocketBase::Bind (const Address &address)
{
NS_LOG_FUNCTION (this << address);
if (!InetSocketAddress::IsMatchingType (address))
if (InetSocketAddress::IsMatchingType (address))
{
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
if (ipv4 == Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate ();
}
else if (ipv4 == Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (port);
}
else if (ipv4 != Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate (ipv4);
}
else if (ipv4 != Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (ipv4, port);
}
if (0 == m_endPoint)
{
m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
return -1;
}
}
else if (Inet6SocketAddress::IsMatchingType (address))
{
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
Ipv6Address ipv6 = transport.GetIpv6 ();
uint16_t port = transport.GetPort ();
if (ipv6 == Ipv6Address::GetAny () && port == 0)
{
m_endPoint6 = m_tcp->Allocate6 ();
}
else if (ipv6 == Ipv6Address::GetAny () && port != 0)
{
m_endPoint6 = m_tcp->Allocate6 (port);
}
else if (ipv6 != Ipv6Address::GetAny () && port == 0)
{
m_endPoint6 = m_tcp->Allocate6 (ipv6);
}
else if (ipv6 != Ipv6Address::GetAny () && port != 0)
{
m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
}
if (0 == m_endPoint6)
{
m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
return -1;
}
}
else
{
m_errno = ERROR_INVAL;
return -1;
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
if (ipv4 == Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate ();
}
else if (ipv4 == Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (port);
}
else if (ipv4 != Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_tcp->Allocate (ipv4);
}
else if (ipv4 != Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_tcp->Allocate (ipv4, port);
}
if (0 == m_endPoint)
{
m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
return -1;
}
m_tcp->m_sockets.push_back (this);
NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
@@ -289,22 +341,60 @@ TcpSocketBase::Connect (const Address & address)
NS_LOG_FUNCTION (this << address);
// If haven't do so, Bind() this socket first
if (m_endPoint == 0)
if (InetSocketAddress::IsMatchingType (address))
{
if (Bind () == -1)
if (m_endPoint == 0)
{
NS_ASSERT (m_endPoint == 0);
return -1; // Bind() failed
if (Bind () == -1)
{
NS_ASSERT (m_endPoint == 0);
return -1; // Bind() failed
}
NS_ASSERT (m_endPoint != 0);
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
m_endPoint6 = 0;
// Get the appropriate local address and port number from the routing protocol and set up endpoint
if (SetupEndpoint () != 0)
{ // Route to destination does not exist
return -1;
}
NS_ASSERT (m_endPoint != 0);
}
else if (Inet6SocketAddress::IsMatchingType (address) )
{
// If we are operating on a v4-mapped address, translate the address to
// a v4 address and re-call this function
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
Ipv6Address v6Addr = transport.GetIpv6 ();
if (v6Addr.IsIpv4MappedAddress () == true)
{
Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
return Connect(InetSocketAddress(v4Addr, transport.GetPort ()));
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
if (m_endPoint6 == 0)
{
if (Bind6 () == -1)
{
NS_ASSERT (m_endPoint6 == 0);
return -1; // Bind() failed
}
NS_ASSERT (m_endPoint6 != 0);
}
m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
m_endPoint = 0;
// Get the appropriate local address and port number from the routing protocol and set up endpoint
if (SetupEndpoint () != 0)
{ // Route to destination does not exist
// Get the appropriate local address and port number from the routing protocol and set up endpoint
if (SetupEndpoint6 () != 0)
{ // Route to destination does not exist
return -1;
}
}
else
{
m_errno = ERROR_INVAL;
return -1;
}
@@ -427,7 +517,14 @@ TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags)
if (outPacket != 0 && outPacket->GetSize () != 0)
{
SocketAddressTag tag;
tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ()));
if (m_endPoint != 0)
{
tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ()));
}
else if (m_endPoint6 != 0)
{
tag.SetAddress (Inet6SocketAddress (m_endPoint6->GetPeerAddress (), m_endPoint6->GetPeerPort ()));
}
outPacket->AddPacketTag (tag);
}
return outPacket;
@@ -446,6 +543,10 @@ TcpSocketBase::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
{
fromAddress = InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ());
}
else if (m_endPoint6 != 0)
{
fromAddress = Inet6SocketAddress (m_endPoint6->GetPeerAddress (), m_endPoint6->GetPeerPort ());
}
else
{
fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
@@ -479,9 +580,14 @@ TcpSocketBase::GetSockName (Address &address) const
{
address = InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->GetLocalPort ());
}
else if (m_endPoint6 != 0)
{
address = Inet6SocketAddress (m_endPoint6->GetLocalAddress (), m_endPoint6->GetLocalPort ());
}
else
{ // It is possible to call this method on a socket without a name
// in which case, behavior is unspecified
// Should this return an InetSocketAddress or an Inet6SocketAddress?
address = InetSocketAddress (Ipv4Address::GetZero (), 0);
}
return 0;
@@ -493,16 +599,21 @@ TcpSocketBase::BindToNetDevice (Ptr<NetDevice> netdevice)
{
NS_LOG_FUNCTION (netdevice);
Socket::BindToNetDevice (netdevice); // Includes sanity check
if (m_endPoint == 0)
if (m_endPoint == 0 && m_endPoint6 == 0)
{
if (Bind () == -1)
{
NS_ASSERT (m_endPoint == 0);
NS_ASSERT ((m_endPoint == 0 && m_endPoint6 == 0));
return;
}
NS_ASSERT (m_endPoint != 0);
NS_ASSERT ((m_endPoint != 0 && m_endPoint6 != 0));
}
m_endPoint->BindToNetDevice (netdevice);
if (m_endPoint != 0)
{
m_endPoint->BindToNetDevice (netdevice);
}
// No BindToNetDevice() for Ipv6EndPoint
return;
}
@@ -511,12 +622,22 @@ int
TcpSocketBase::SetupCallback (void)
{
NS_LOG_FUNCTION (this);
if (m_endPoint == 0)
if (m_endPoint == 0 && m_endPoint6 == 0)
{
return -1;
}
m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
if (m_endPoint != 0)
{
m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
}
if (m_endPoint6 != 0)
{
m_endPoint6->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp6, Ptr<TcpSocketBase> (this)));
m_endPoint6->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
}
return 0;
}
@@ -629,6 +750,12 @@ TcpSocketBase::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
DoForwardUp (packet, header, port, incomingInterface);
}
void
TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
{
DoForwardUp (packet, saddr, daddr, port);
}
/** The real function to handle the incoming packet from lower layers. This is
wrapped by ForwardUp() so that this function can be overloaded by daughter
classes. */
@@ -728,6 +855,101 @@ TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port
}
}
void
TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
{
NS_LOG_LOGIC ("Socket " << this << " forward up " <<
m_endPoint6->GetPeerAddress () <<
":" << m_endPoint6->GetPeerPort () <<
" to " << m_endPoint6->GetLocalAddress () <<
":" << m_endPoint6->GetLocalPort ());
Address fromAddress = Inet6SocketAddress (saddr, port);
Address toAddress = Inet6SocketAddress (daddr, m_endPoint6->GetLocalPort ());
// Peel off TCP header and do validity checking
TcpHeader tcpHeader;
packet->RemoveHeader (tcpHeader);
if (tcpHeader.GetFlags () & TcpHeader::ACK)
{
EstimateRtt (tcpHeader);
}
ReadOptions (tcpHeader);
// Update Rx window size, i.e. the flow control window
if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0)
{ // persist probes end
NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
m_persistEvent.Cancel ();
}
m_rWnd = tcpHeader.GetWindowSize ();
// Discard fully out of range packets
if (packet->GetSize () &&
OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
{
NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
" received packet of seq [" << tcpHeader.GetSequenceNumber () <<
":" << tcpHeader.GetSequenceNumber () + packet->GetSize() <<
") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
m_rxBuffer.MaxRxSequence () << ")");
// Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
{
SendEmptyPacket (TcpHeader::ACK);
}
return;
}
// TCP state machine code in different process functions
// C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
switch (m_state)
{
case ESTABLISHED:
ProcessEstablished (packet, tcpHeader);
break;
case LISTEN:
ProcessListen (packet, tcpHeader, fromAddress, toAddress);
break;
case TIME_WAIT:
// Do nothing
break;
case CLOSED:
// Send RST if the incoming packet is not a RST
if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
{ // Since m_endPoint is not configured yet, we cannot use SendRST here
TcpHeader h;
h.SetFlags (TcpHeader::RST);
h.SetSequenceNumber (m_nextTxSequence);
h.SetAckNumber (m_rxBuffer.NextRxSequence ());
h.SetSourcePort (tcpHeader.GetDestinationPort ());
h.SetDestinationPort (tcpHeader.GetSourcePort ());
h.SetWindowSize (AdvertisedWindowSize ());
AddOptions (h);
m_tcp->SendPacket (Create<Packet> (), h, daddr, saddr, m_boundnetdevice);
}
break;
case SYN_SENT:
ProcessSynSent (packet, tcpHeader);
break;
case SYN_RCVD:
ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
break;
case FIN_WAIT_1:
case FIN_WAIT_2:
case CLOSE_WAIT:
ProcessWait (packet, tcpHeader);
break;
case CLOSING:
ProcessClosing (packet, tcpHeader);
break;
case LAST_ACK:
ProcessLastAck (packet, tcpHeader);
break;
default: // mute compiler
break;
}
}
/** Received a packet upon ESTABLISHED state. This function is mimicking the
role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
void
@@ -915,8 +1137,16 @@ TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader,
m_retxEvent.Cancel ();
m_highTxMark = ++m_nextTxSequence;
m_txBuffer.SetHeadSequence (m_nextTxSequence);
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
if (m_endPoint)
{
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
}
else if (m_endPoint6)
{
m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
}
// Always respond to first data packet to speed up the connection.
// Remove to get the behaviour of old NS-3 code.
m_delAckCount = m_delAckMaxCount;
@@ -941,8 +1171,16 @@ TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader,
m_retxEvent.Cancel ();
m_highTxMark = ++m_nextTxSequence;
m_txBuffer.SetHeadSequence (m_nextTxSequence);
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
if (m_endPoint)
{
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
}
else if (m_endPoint6)
{
m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
}
PeerClose (packet, tcpHeader);
}
}
@@ -951,8 +1189,16 @@ TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader,
if (tcpflags != TcpHeader::RST)
{ // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
if (m_endPoint)
{
m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
}
else if (m_endPoint6)
{
m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
}
SendRST ();
}
CloseAndNotify ();
@@ -1178,13 +1424,17 @@ TcpSocketBase::Destroy (void)
NS_LOG_FUNCTION (this);
m_node = 0;
m_endPoint = 0;
std::vector<Ptr<TcpSocketBase> >::iterator it
= std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
if (it != m_tcp->m_sockets.end ())
m_endPoint6 = 0;
if (m_tcp != 0)
{
m_tcp->m_sockets.erase (it);
std::vector<Ptr<TcpSocketBase> >::iterator it
= std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
if (it != m_tcp->m_sockets.end ())
{
m_tcp->m_sockets.erase (it);
}
m_tcp = 0;
}
m_tcp = 0;
NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
(Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
CancelAllTimers ();
@@ -1199,7 +1449,7 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags)
TcpHeader header;
SequenceNumber32 s = m_nextTxSequence;
if (m_endPoint == 0)
if (m_endPoint == 0 && m_endPoint6 == 0)
{
NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
return;
@@ -1216,8 +1466,16 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags)
header.SetFlags (flags);
header.SetSequenceNumber (s);
header.SetAckNumber (m_rxBuffer.NextRxSequence ());
header.SetSourcePort (m_endPoint->GetLocalPort ());
header.SetDestinationPort (m_endPoint->GetPeerPort ());
if (m_endPoint != 0)
{
header.SetSourcePort (m_endPoint->GetLocalPort ());
header.SetDestinationPort (m_endPoint->GetPeerPort ());
}
else
{
header.SetSourcePort (m_endPoint6->GetLocalPort ());
header.SetDestinationPort (m_endPoint6->GetPeerPort ());
}
header.SetWindowSize (AdvertisedWindowSize ());
AddOptions (header);
m_rto = m_rtt->RetransmitTimeout ();
@@ -1239,7 +1497,16 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags)
m_cnCount--;
}
}
m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), m_endPoint->GetPeerAddress (), m_boundnetdevice);
if (m_endPoint != 0)
{
m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
m_endPoint->GetPeerAddress (), m_boundnetdevice);
}
else
{
m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
m_endPoint6->GetPeerAddress (), m_boundnetdevice);
}
if (flags & TcpHeader::ACK)
{ // If sending an ACK, cancel the delay ACK as well
m_delAckEvent.Cancel ();
@@ -1281,6 +1548,19 @@ TcpSocketBase::DeallocateEndPoint (void)
}
CancelAllTimers ();
}
if (m_endPoint6 != 0)
{
m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
m_tcp->DeAllocate (m_endPoint6);
m_endPoint6 = 0;
std::vector<Ptr<TcpSocketBase> >::iterator it
= std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
if (it != m_tcp->m_sockets.end ())
{
m_tcp->m_sockets.erase (it);
}
CancelAllTimers ();
}
}
/** Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
@@ -1314,6 +1594,36 @@ TcpSocketBase::SetupEndpoint ()
return 0;
}
int
TcpSocketBase::SetupEndpoint6 ()
{
NS_LOG_FUNCTION (this);
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
NS_ASSERT (ipv6 != 0);
if (ipv6->GetRoutingProtocol () == 0)
{
NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
}
// Create a dummy packet, then ask the routing function for the best output
// interface's address
Ipv6Header header;
header.SetDestinationAddress (m_endPoint6->GetPeerAddress ());
Socket::SocketErrno errno_;
Ptr<Ipv6Route> route;
Ptr<NetDevice> oif = m_boundnetdevice;
route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
if (route == 0)
{
NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
NS_LOG_ERROR (errno_);
m_errno = errno_;
return -1;
}
NS_LOG_LOGIC ("Route exists");
m_endPoint6->SetLocalAddress (route->GetSource ());
return 0;
}
/** This function is called only if a SYN received in LISTEN state. After
TcpSocketBase cloned, allocate a new end point to handle the incoming
connection and send a SYN+ACK to complete the handshake. */
@@ -1322,10 +1632,22 @@ TcpSocketBase::CompleteFork (Ptr<Packet> p, const TcpHeader& h,
const Address& fromAddress, const Address& toAddress)
{
// Get port and address from peer (connecting host)
m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (toAddress).GetPort (),
InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
if (InetSocketAddress::IsMatchingType (toAddress))
{
m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (toAddress).GetPort (),
InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
m_endPoint6 = 0;
}
else if (Inet6SocketAddress::IsMatchingType (toAddress))
{
m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
m_endPoint = 0;
}
m_tcp->m_sockets.push_back (this);
// Change the cloned socket from LISTEN state to SYN_RCVD
@@ -1381,8 +1703,16 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
header.SetFlags (flags);
header.SetSequenceNumber (seq);
header.SetAckNumber (m_rxBuffer.NextRxSequence ());
header.SetSourcePort (m_endPoint->GetLocalPort ());
header.SetDestinationPort (m_endPoint->GetPeerPort ());
if (m_endPoint)
{
header.SetSourcePort (m_endPoint->GetLocalPort ());
header.SetDestinationPort (m_endPoint->GetPeerPort ());
}
else
{
header.SetSourcePort (m_endPoint6->GetLocalPort ());
header.SetDestinationPort (m_endPoint6->GetPeerPort ());
}
header.SetWindowSize (AdvertisedWindowSize ());
AddOptions (header);
if (m_retxEvent.IsExpired () )
@@ -1394,8 +1724,16 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, this);
}
NS_LOG_LOGIC ("Send packet via TcpL4Protocol with flags 0x" << std::hex << static_cast<uint32_t> (flags) << std::dec);
m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
m_endPoint->GetPeerAddress (), m_boundnetdevice);
if (m_endPoint)
{
m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
m_endPoint->GetPeerAddress (), m_boundnetdevice);
}
else
{
m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
m_endPoint6->GetPeerAddress (), m_boundnetdevice);
}
m_rtt->SentSeq (seq, sz); // notify the RTT
// Notify the application of the data being sent unless this is a retransmit
if (seq == m_nextTxSequence)
@@ -1415,7 +1753,8 @@ TcpSocketBase::SendPendingData (bool withAck)
{
NS_LOG_FUNCTION (this << withAck);
if (m_txBuffer.Size () == 0) return false; // Nothing to send
if (m_endPoint == 0)
if (m_endPoint == 0 && m_endPoint6 == 0)
{
NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
return false; // Is this the right way to handle this condition?
@@ -1438,7 +1777,7 @@ TcpSocketBase::SendPendingData (bool withAck)
m_errno = ERROR_SHUTDOWN;
return false;
}
// Stop sending if we need to wait for a larger Tx window
// Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
if (w < m_segmentSize && m_txBuffer.SizeFromSequence (m_nextTxSequence) > w)
{
break; // No more
@@ -1664,13 +2003,29 @@ TcpSocketBase::PersistTimeout ()
TcpHeader tcpHeader;
tcpHeader.SetSequenceNumber (m_nextTxSequence);
tcpHeader.SetAckNumber (m_rxBuffer.NextRxSequence ());
tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
tcpHeader.SetWindowSize (AdvertisedWindowSize ());
if (m_endPoint != 0)
{
tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
}
else
{
tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
}
AddOptions (tcpHeader);
m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
m_endPoint->GetPeerAddress (), m_boundnetdevice);
if (m_endPoint != 0)
{
m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
m_endPoint->GetPeerAddress (), m_boundnetdevice);
}
else
{
m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
m_endPoint6->GetPeerAddress (), m_boundnetdevice);
}
NS_LOG_LOGIC ("Schedule persist timeout at time "
<< Simulator::Now ().GetSeconds () << " to expire at time "
<< (Simulator::Now () + m_persistTimeout).GetSeconds ());

View File

@@ -38,6 +38,7 @@
namespace ns3 {
class Ipv4EndPoint;
class Ipv6EndPoint;
class Node;
class Packet;
class TcpL4Protocol;
@@ -81,6 +82,7 @@ public:
virtual enum SocketType GetSocketType (void) const; // returns socket type
virtual Ptr<Node> GetNode (void) const; // returns m_node
virtual int Bind (void); // Bind a socket by setting up endpoint in TcpL4Protocol
virtual int Bind6 (void); // Bind a socket by setting up endpoint in TcpL4Protocol
virtual int Bind (const Address &address); // ... endpoint of specific addr or port
virtual int Connect (const Address &address); // Setup endpoint and call ProcessAction() to connect
virtual int Listen (void); // Verify the socket is in a correct state and call ProcessAction() to listen
@@ -128,11 +130,14 @@ protected:
int DoConnect (void); // Sending a SYN packet to make a connection if the state allows
void ConnectionSucceeded (void); // Schedule-friendly wrapper for Socket::NotifyConnectionSucceeded()
int SetupEndpoint (void); // Configure m_endpoint for local addr for given remote addr
int SetupEndpoint6 (void); // Configure m_endpoint6 for local addr for given remote addr
void CompleteFork (Ptr<Packet>, const TcpHeader&, const Address& fromAddress, const Address& toAdress);
// Helper functions: Transfer operation
void ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface);
void ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port);
virtual void DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface); //Get a pkt from L3
virtual void DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port); // Ipv6 version
bool SendPendingData (bool withAck = false); // Send as much as the window allows
uint32_t SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck); // Send a data packet
void SendEmptyPacket (uint8_t flags); // Send a empty packet that carries a flag, e.g. ACK
@@ -202,6 +207,7 @@ protected:
// Connections to other layers of TCP/IP
Ipv4EndPoint* m_endPoint;
Ipv6EndPoint* m_endPoint6;
Ptr<Node> m_node;
Ptr<TcpL4Protocol> m_tcp;

View File

@@ -70,8 +70,17 @@ UdpHeader::GetDestinationPort (void) const
{
return m_destinationPort;
}
void
UdpHeader::InitializeChecksum (Ipv4Address source,
void
UdpHeader::InitializeChecksum (Address source,
Address destination,
uint8_t protocol)
{
m_source = source;
m_destination = destination;
m_protocol = protocol;
}
void
UdpHeader::InitializeChecksum (Ipv4Address source,
Ipv4Address destination,
uint8_t protocol)
{
@@ -79,23 +88,47 @@ UdpHeader::InitializeChecksum (Ipv4Address source,
m_destination = destination;
m_protocol = protocol;
}
void
UdpHeader::InitializeChecksum (Ipv6Address source,
Ipv6Address destination,
uint8_t protocol)
{
m_source = source;
m_destination = destination;
m_protocol = protocol;
}
uint16_t
UdpHeader::CalculateHeaderChecksum (uint16_t size) const
{
Buffer buf = Buffer (12);
buf.AddAtStart (12);
Buffer buf = Buffer ((2 * Address::MAX_SIZE) + 8);
buf.AddAtStart ((2 * Address::MAX_SIZE) + 8);
Buffer::Iterator it = buf.Begin ();
uint32_t hdrSize = 0;
WriteTo (it, m_source);
WriteTo (it, m_destination);
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
if (Ipv4Address::IsMatchingType(m_source))
{
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
hdrSize = 12;
}
else if (Ipv6Address::IsMatchingType(m_source))
{
it.WriteU16 (0);
it.WriteU8 (size >> 8); /* length */
it.WriteU8 (size & 0xff); /* length */
it.WriteU16 (0);
it.WriteU8 (0);
it.WriteU8 (m_protocol); /* protocol */
hdrSize = 40;
}
it = buf.Begin ();
/* we don't CompleteChecksum ( ~ ) now */
return ~(it.CalculateIpChecksum (12));
return ~(it.CalculateIpChecksum (hdrSize));
}
bool

View File

@@ -25,6 +25,7 @@
#include <string>
#include "ns3/header.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
namespace ns3 {
/**
@@ -68,6 +69,21 @@ public:
*/
uint16_t GetDestinationPort (void) const;
/**
* \param source the ip source to use in the underlying
* ip packet.
* \param destination the ip destination to use in the
* underlying ip packet.
* \param protocol the protocol number to use in the underlying
* ip packet.
*
* If you want to use udp checksums, you should call this
* method prior to adding the header to a packet.
*/
void InitializeChecksum (Address source,
Address destination,
uint8_t protocol);
/**
* \param source the ip source to use in the underlying
* ip packet.
@@ -83,6 +99,21 @@ public:
Ipv4Address destination,
uint8_t protocol);
/**
* \param source the ip source to use in the underlying
* ip packet.
* \param destination the ip destination to use in the
* underlying ip packet.
* \param protocol the protocol number to use in the underlying
* ip packet.
*
* If you want to use udp checksums, you should call this
* method prior to adding the header to a packet.
*/
void InitializeChecksum (Ipv6Address source,
Ipv6Address destination,
uint8_t protocol);
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
virtual void Print (std::ostream &os) const;
@@ -102,8 +133,8 @@ private:
uint16_t m_destinationPort;
uint16_t m_payloadSize;
Ipv4Address m_source;
Ipv4Address m_destination;
Address m_source;
Address m_destination;
uint8_t m_protocol;
bool m_calcChecksum;
bool m_goodChecksum;

View File

@@ -24,14 +24,20 @@
#include "ns3/node.h"
#include "ns3/boolean.h"
#include "ns3/object-vector.h"
#include "ns3/ipv6.h"
#include "ns3/ipv4-route.h"
#include "ns3/ipv6-route.h"
#include "ns3/ipv6-header.h"
#include "udp-l4-protocol.h"
#include "udp-header.h"
#include "udp-socket-factory-impl.h"
#include "ipv4-end-point-demux.h"
#include "ipv4-end-point.h"
#include "ipv6-end-point-demux.h"
#include "ipv6-end-point.h"
#include "ipv4-l3-protocol.h"
#include "ipv6-l3-protocol.h"
#include "udp-socket-impl.h"
NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
@@ -47,7 +53,7 @@ TypeId
UdpL4Protocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::UdpL4Protocol")
.SetParent<Ipv4L4Protocol> ()
.SetParent<IpL4Protocol> ()
.AddConstructor<UdpL4Protocol> ()
.AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
ObjectVectorValue (),
@@ -58,7 +64,7 @@ UdpL4Protocol::GetTypeId (void)
}
UdpL4Protocol::UdpL4Protocol ()
: m_endPoints (new Ipv4EndPointDemux ())
: m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
{
NS_LOG_FUNCTION_NOARGS ();
}
@@ -82,23 +88,36 @@ UdpL4Protocol::SetNode (Ptr<Node> node)
void
UdpL4Protocol::NotifyNewAggregate ()
{
Ptr<Node> node = this->GetObject<Node> ();
Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol> ();
if (m_node == 0)
{
Ptr<Node> node = this->GetObject<Node> ();
if (node != 0)
if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
{
Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
if (ipv4 != 0)
{
this->SetNode (node);
ipv4->Insert (this);
Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
udpFactory->SetUdp (this);
node->AggregateObject (udpFactory);
this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
}
this->SetNode (node);
Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
udpFactory->SetUdp (this);
node->AggregateObject (udpFactory);
}
}
// We set at least one of our 2 down targets to the IPv4/IPv6 send
// functions. Since these functions have different prototypes, we
// need to keep track of whether we are connected to an IPv4 or
// IPv6 lower layer and call the appropriate one.
if (ipv4 != 0)
{
ipv4->Insert (this);
this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
}
if (ipv6 != 0)
{
ipv6->Insert (this);
this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
}
Object::NotifyNewAggregate ();
}
@@ -124,12 +143,18 @@ UdpL4Protocol::DoDispose (void)
delete m_endPoints;
m_endPoints = 0;
}
if (m_endPoints6 != 0)
{
delete m_endPoints6;
m_endPoints6 = 0;
}
m_node = 0;
m_downTarget.Nullify ();
m_downTarget6.Nullify ();
/*
= MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
*/
Ipv4L4Protocol::DoDispose ();
IpL4Protocol::DoDispose ();
}
Ptr<Socket>
@@ -186,6 +211,49 @@ UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
m_endPoints->DeAllocate (endPoint);
}
Ipv6EndPoint *
UdpL4Protocol::Allocate6 (void)
{
NS_LOG_FUNCTION_NOARGS ();
return m_endPoints6->Allocate ();
}
Ipv6EndPoint *
UdpL4Protocol::Allocate6 (Ipv6Address address)
{
NS_LOG_FUNCTION (this << address);
return m_endPoints6->Allocate (address);
}
Ipv6EndPoint *
UdpL4Protocol::Allocate6 (uint16_t port)
{
NS_LOG_FUNCTION (this << port);
return m_endPoints6->Allocate (port);
}
Ipv6EndPoint *
UdpL4Protocol::Allocate6 (Ipv6Address address, uint16_t port)
{
NS_LOG_FUNCTION (this << address << port);
return m_endPoints6->Allocate (address, port);
}
Ipv6EndPoint *
UdpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
Ipv6Address peerAddress, uint16_t peerPort)
{
NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
return m_endPoints6->Allocate (localAddress, localPort,
peerAddress, peerPort);
}
void
UdpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
{
NS_LOG_FUNCTION (this << endPoint);
m_endPoints6->DeAllocate (endPoint);
}
void
UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
@@ -213,7 +281,34 @@ UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
}
}
enum Ipv4L4Protocol::RxStatus
void
UdpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource,Ipv6Address payloadDestination,
const uint8_t payload[8])
{
NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
<< payloadSource << payloadDestination);
uint16_t src, dst;
src = payload[0] << 8;
src |= payload[1];
dst = payload[2] << 8;
dst |= payload[3];
Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
if (endPoint != 0)
{
endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
}
else
{
NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
", destination="<<payloadDestination<<
", src=" << src << ", dst=" << dst);
}
}
enum IpL4Protocol::RxStatus
UdpL4Protocol::Receive (Ptr<Packet> packet,
Ipv4Header const &header,
Ptr<Ipv4Interface> interface)
@@ -227,12 +322,17 @@ UdpL4Protocol::Receive (Ptr<Packet> packet,
udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
packet->RemoveHeader (udpHeader);
// We only peek at the header for now (instead of removing it) so that it will be intact
// if we have to pass it to a IPv6 endpoint via:
//
// UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
packet->PeekHeader (udpHeader);
if(!udpHeader.IsChecksumOk ())
{
NS_LOG_INFO ("Bad checksum : dropping packet!");
return Ipv4L4Protocol::RX_CSUM_FAILED;
return IpL4Protocol::RX_CSUM_FAILED;
}
NS_LOG_DEBUG ("Looking up dst " << header.GetDestination () << " port " << udpHeader.GetDestinationPort ());
@@ -241,16 +341,67 @@ UdpL4Protocol::Receive (Ptr<Packet> packet,
header.GetSource (), udpHeader.GetSourcePort (), interface);
if (endPoints.empty ())
{
if (this->GetObject<Ipv6L3Protocol> () != 0)
{
NS_LOG_LOGIC (" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 "<<this);
Ptr<Ipv6Interface> fakeInterface;
Ipv6Address src = Ipv6Address::MakeIpv4MappedAddress (header.GetSource ());
Ipv6Address dst = Ipv6Address::MakeIpv4MappedAddress (header.GetDestination ());
return (this->Receive (packet, src, dst, fakeInterface));
}
NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
return IpL4Protocol::RX_ENDPOINT_UNREACH;
}
packet->RemoveHeader(udpHeader);
for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
endPoint != endPoints.end (); endPoint++)
{
(*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (),
interface);
}
return Ipv4L4Protocol::RX_OK;
return IpL4Protocol::RX_OK;
}
enum IpL4Protocol::RxStatus
UdpL4Protocol::Receive (Ptr<Packet> packet,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> interface)
{
NS_LOG_FUNCTION (this << packet << src << dst);
UdpHeader udpHeader;
if(Node::ChecksumEnabled ())
{
udpHeader.EnableChecksums ();
}
udpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
packet->RemoveHeader (udpHeader);
if(!udpHeader.IsChecksumOk () && !src.IsIpv4MappedAddress ())
{
NS_LOG_INFO ("Bad checksum : dropping packet!");
return IpL4Protocol::RX_CSUM_FAILED;
}
NS_LOG_DEBUG ("Looking up dst " << dst << " port " << udpHeader.GetDestinationPort ());
Ipv6EndPointDemux::EndPoints endPoints =
m_endPoints6->Lookup (dst, udpHeader.GetDestinationPort (),
src, udpHeader.GetSourcePort (), interface);
if (endPoints.empty ())
{
NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
return IpL4Protocol::RX_ENDPOINT_UNREACH;
}
for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin ();
endPoint != endPoints.end (); endPoint++)
{
(*endPoint)->ForwardUp (packet->Copy (), src, dst, udpHeader.GetSourcePort ());
}
return IpL4Protocol::RX_OK;
}
void
@@ -300,16 +451,74 @@ UdpL4Protocol::Send (Ptr<Packet> packet,
}
void
UdpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
UdpL4Protocol::Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport)
{
NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
UdpHeader udpHeader;
if(Node::ChecksumEnabled ())
{
udpHeader.EnableChecksums ();
udpHeader.InitializeChecksum (saddr,
daddr,
PROT_NUMBER);
}
udpHeader.SetDestinationPort (dport);
udpHeader.SetSourcePort (sport);
packet->AddHeader (udpHeader);
m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, 0);
}
void
UdpL4Protocol::Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route)
{
NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
UdpHeader udpHeader;
if(Node::ChecksumEnabled ())
{
udpHeader.EnableChecksums ();
udpHeader.InitializeChecksum (saddr,
daddr,
PROT_NUMBER);
}
udpHeader.SetDestinationPort (dport);
udpHeader.SetSourcePort (sport);
packet->AddHeader (udpHeader);
m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
}
void
UdpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
{
m_downTarget = callback;
}
Ipv4L4Protocol::DownTargetCallback
IpL4Protocol::DownTargetCallback
UdpL4Protocol::GetDownTarget (void) const
{
return m_downTarget;
}
void
UdpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
{
m_downTarget6 = callback;
}
IpL4Protocol::DownTargetCallback6
UdpL4Protocol::GetDownTarget6 (void) const
{
return m_downTarget6;
}
} // namespace ns3

View File

@@ -25,8 +25,11 @@
#include "ns3/packet.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv6-address.h"
#include "ns3/ptr.h"
#include "ipv4-l4-protocol.h"
#include "ns3/ip-l4-protocol.h"
#include "ipv6-interface.h"
#include "ipv6-header.h"
namespace ns3 {
@@ -34,13 +37,15 @@ class Node;
class Socket;
class Ipv4EndPointDemux;
class Ipv4EndPoint;
class Ipv6EndPointDemux;
class Ipv6EndPoint;
class UdpSocketImpl;
/**
* \ingroup udp
* \brief Implementation of the UDP protocol
*/
class UdpL4Protocol : public Ipv4L4Protocol {
class UdpL4Protocol : public IpL4Protocol {
public:
static TypeId GetTypeId (void);
static const uint8_t PROT_NUMBER;
@@ -64,8 +69,15 @@ public:
Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
Ipv4Address peerAddress, uint16_t peerPort);
Ipv6EndPoint *Allocate6 (void);
Ipv6EndPoint *Allocate6 (Ipv6Address address);
Ipv6EndPoint *Allocate6 (uint16_t port);
Ipv6EndPoint *Allocate6 (Ipv6Address address, uint16_t port);
Ipv6EndPoint *Allocate6 (Ipv6Address localAddress, uint16_t localPort,
Ipv6Address peerAddress, uint16_t peerPort);
void DeAllocate (Ipv4EndPoint *endPoint);
void DeAllocate (Ipv6EndPoint *endPoint);
// called by UdpSocket.
/**
@@ -82,6 +94,12 @@ public:
void Send (Ptr<Packet> packet,
Ipv4Address saddr, Ipv4Address daddr,
uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route);
void Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport);
void Send (Ptr<Packet> packet,
Ipv6Address saddr, Ipv6Address daddr,
uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route);
/**
* \brief Receive a packet up the protocol stack
* \param p The Packet to dump the contents into
@@ -89,9 +107,13 @@ public:
* \param interface the interface from which the packet is coming.
*/
// inherited from Ipv4L4Protocol
virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv4Header const &header,
Ptr<Ipv4Interface> interface);
virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
Ipv6Address &src,
Ipv6Address &dst,
Ptr<Ipv6Interface> interface);
/**
* \brief Receive an ICMP packet
@@ -108,11 +130,17 @@ public:
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv4Address payloadSource,Ipv4Address payloadDestination,
const uint8_t payload[8]);
virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
Ipv6Address payloadSource,Ipv6Address payloadDestination,
const uint8_t payload[8]);
// From Ipv4L4Protocol
virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
// From Ipv4L4Protocol
virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
// From IpL4Protocol
virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
// From IpL4Protocol
virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
protected:
virtual void DoDispose (void);
@@ -124,10 +152,12 @@ protected:
private:
Ptr<Node> m_node;
Ipv4EndPointDemux *m_endPoints;
Ipv6EndPointDemux *m_endPoints6;
UdpL4Protocol (const UdpL4Protocol &o);
UdpL4Protocol &operator = (const UdpL4Protocol &o);
std::vector<Ptr<UdpSocketImpl> > m_sockets;
Ipv4L4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback m_downTarget;
IpL4Protocol::DownTargetCallback6 m_downTarget6;
};
} // namespace ns3

View File

@@ -21,16 +21,21 @@
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/ipv4-route.h"
#include "ns3/ipv6-route.h"
#include "ns3/ipv4.h"
#include "ns3/ipv6.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/ipv6-routing-protocol.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/ipv4-packet-info-tag.h"
#include "udp-socket-impl.h"
#include "udp-l4-protocol.h"
#include "ipv4-end-point.h"
#include "ipv6-end-point.h"
#include <limits>
NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
@@ -52,12 +57,17 @@ UdpSocketImpl::GetTypeId (void)
CallbackValue (),
MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
MakeCallbackChecker ())
.AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
CallbackValue (),
MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
MakeCallbackChecker ())
;
return tid;
}
UdpSocketImpl::UdpSocketImpl ()
: m_endPoint (0),
m_endPoint6 (0),
m_node (0),
m_udp (0),
m_errno (ERROR_NOTERROR),
@@ -142,14 +152,21 @@ int
UdpSocketImpl::FinishBind (void)
{
NS_LOG_FUNCTION_NOARGS ();
if (m_endPoint == 0)
if (m_endPoint != 0)
{
return -1;
m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
return 0;
}
m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
return 0;
else if (m_endPoint6 != 0)
{
m_endPoint6->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp6, Ptr<UdpSocketImpl> (this)));
m_endPoint6->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp6, Ptr<UdpSocketImpl> (this)));
m_endPoint6->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
return 0;
}
return -1;
}
int
@@ -160,36 +177,69 @@ UdpSocketImpl::Bind (void)
return FinishBind ();
}
int
UdpSocketImpl::Bind6 (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_endPoint6 = m_udp->Allocate6 ();
return FinishBind ();
}
int
UdpSocketImpl::Bind (const Address &address)
{
NS_LOG_FUNCTION (this << address);
if (!InetSocketAddress::IsMatchingType (address))
if (InetSocketAddress::IsMatchingType (address))
{
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
if (ipv4 == Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_udp->Allocate ();
}
else if (ipv4 == Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_udp->Allocate (port);
}
else if (ipv4 != Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_udp->Allocate (ipv4);
}
else if (ipv4 != Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_udp->Allocate (ipv4, port);
}
}
else if (Inet6SocketAddress::IsMatchingType (address))
{
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
Ipv6Address ipv6 = transport.GetIpv6 ();
uint16_t port = transport.GetPort ();
if (ipv6 == Ipv6Address::GetAny () && port == 0)
{
m_endPoint6 = m_udp->Allocate6 ();
}
else if (ipv6 == Ipv6Address::GetAny () && port != 0)
{
m_endPoint6 = m_udp->Allocate6 (port);
}
else if (ipv6 != Ipv6Address::GetAny () && port == 0)
{
m_endPoint6 = m_udp->Allocate6 (ipv6);
}
else if (ipv6 != Ipv6Address::GetAny () && port != 0)
{
m_endPoint6 = m_udp->Allocate6 (ipv6, port);
}
}
else
{
NS_LOG_ERROR ("Not IsMatchingType");
m_errno = ERROR_INVAL;
return -1;
}
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
if (ipv4 == Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_udp->Allocate ();
}
else if (ipv4 == Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_udp->Allocate (port);
}
else if (ipv4 != Ipv4Address::GetAny () && port == 0)
{
m_endPoint = m_udp->Allocate (ipv4);
}
else if (ipv4 != Ipv4Address::GetAny () && port != 0)
{
m_endPoint = m_udp->Allocate (ipv4, port);
}
return FinishBind ();
}
@@ -228,11 +278,26 @@ int
UdpSocketImpl::Connect (const Address & address)
{
NS_LOG_FUNCTION (this << address);
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_defaultAddress = transport.GetIpv4 ();
m_defaultPort = transport.GetPort ();
m_connected = true;
NotifyConnectionSucceeded ();
if (InetSocketAddress::IsMatchingType(address) == true)
{
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
m_defaultAddress = Address(transport.GetIpv4 ());
m_defaultPort = transport.GetPort ();
m_connected = true;
NotifyConnectionSucceeded ();
}
else if (Inet6SocketAddress::IsMatchingType(address) == true)
{
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
m_defaultAddress = Address(transport.GetIpv6 ());
m_defaultPort = transport.GetPort ();
m_connected = true;
NotifyConnectionSucceeded ();
}
else
{
return -1;
}
return 0;
}
@@ -261,7 +326,7 @@ int
UdpSocketImpl::DoSend (Ptr<Packet> p)
{
NS_LOG_FUNCTION (this << p);
if (m_endPoint == 0)
if ((m_endPoint == 0) && (InetSocketAddress::IsMatchingType(m_defaultAddress) == true))
{
if (Bind () == -1)
{
@@ -270,13 +335,22 @@ UdpSocketImpl::DoSend (Ptr<Packet> p)
}
NS_ASSERT (m_endPoint != 0);
}
else if ((m_endPoint6 == 0) && (Inet6SocketAddress::IsMatchingType(m_defaultAddress) == true))
{
if (Bind6 () == -1)
{
NS_ASSERT (m_endPoint6 == 0);
return -1;
}
NS_ASSERT (m_endPoint6 != 0);
}
if (m_shutdownSend)
{
m_errno = ERROR_SHUTDOWN;
return -1;
}
return DoSendTo (p, m_defaultAddress, m_defaultPort);
return DoSendTo (p, (const Address)m_defaultAddress);
}
int
@@ -287,17 +361,40 @@ UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
if (!m_connected)
{
NS_LOG_LOGIC ("Not connected");
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv4, port);
if (InetSocketAddress::IsMatchingType(address) == true)
{
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv4, port);
}
else if (Inet6SocketAddress::IsMatchingType(address) == true)
{
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
Ipv6Address ipv6 = transport.GetIpv6 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv6, port);
}
else
{
return -1;
}
}
else
{
// connected UDP socket must use default addresses
NS_LOG_LOGIC ("Connected");
return DoSendTo (p, m_defaultAddress, m_defaultPort);
if (Ipv4Address::IsMatchingType(m_defaultAddress))
{
return DoSendTo (p, Ipv4Address::ConvertFrom(m_defaultAddress), m_defaultPort);
}
else if (Ipv6Address::IsMatchingType(m_defaultAddress))
{
return DoSendTo (p, Ipv6Address::ConvertFrom(m_defaultAddress), m_defaultPort);
}
}
m_errno = ERROR_AFNOSUPPORT;
return(-1);
}
int
@@ -483,6 +580,113 @@ UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
return 0;
}
int
UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address dest, uint16_t port)
{
NS_LOG_FUNCTION (this << p << dest << port);
if (dest.IsIpv4MappedAddress ())
{
return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
}
if (m_boundnetdevice)
{
NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
}
if (m_endPoint6 == 0)
{
if (Bind6 () == -1)
{
NS_ASSERT (m_endPoint6 == 0);
return -1;
}
NS_ASSERT (m_endPoint6 != 0);
}
if (m_shutdownSend)
{
m_errno = ERROR_SHUTDOWN;
return -1;
}
if (p->GetSize () > GetTxAvailable () )
{
m_errno = ERROR_MSGSIZE;
return -1;
}
Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
// Locally override the IP TTL for this socket
// We cannot directly modify the TTL at this stage, so we set a Packet tag
// The destination can be either multicast, unicast/anycast, or
// either all-hosts broadcast or limited (subnet-directed) broadcast.
// For the latter two broadcast types, the TTL will later be set to one
// irrespective of what is set in these socket options. So, this tagging
// may end up setting the TTL of a limited broadcast packet to be
// the same as a unicast, but it will be fixed further down the stack
if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipMulticastTtl);
p->AddPacketTag (tag);
}
else if (m_ipTtl != 0 && !dest.IsMulticast ())
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipTtl);
p->AddPacketTag (tag);
}
// There is no analgous to an IPv4 broadcast address in IPv6.
// Instead, we use a set of link-local, site-local, and global
// multicast addresses. The Ipv6 routing layers should all
// provide an interface-specific route to these addresses such
// that we can treat these multicast addresses as "not broadcast"
if (m_endPoint6->GetLocalAddress () != Ipv6Address::GetAny ())
{
m_udp->Send (p->Copy (), m_endPoint6->GetLocalAddress (), dest,
m_endPoint6->GetLocalPort (), port, 0);
NotifyDataSent (p->GetSize ());
NotifySend (GetTxAvailable ());
return p->GetSize ();
}
else if (ipv6->GetRoutingProtocol () != 0)
{
Ipv6Header header;
header.SetDestinationAddress (dest);
header.SetNextHeader (UdpL4Protocol::PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv6Route> route;
Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
// TBD-- we could cache the route and just check its validity
route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
if (route != 0)
{
NS_LOG_LOGIC ("Route exists");
header.SetSourceAddress (route->GetSource ());
m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
m_endPoint6->GetLocalPort (), port, route);
NotifyDataSent (p->GetSize ());
return p->GetSize ();
}
else
{
NS_LOG_LOGIC ("No route to destination");
NS_LOG_ERROR (errno_);
m_errno = errno_;
return -1;
}
}
else
{
NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
m_errno = ERROR_NOROUTETOHOST;
return -1;
}
return 0;
}
// XXX maximum message size for UDP broadcast is limited by MTU
// size of underlying link; we are not checking that now.
uint32_t
@@ -498,10 +702,21 @@ int
UdpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
{
NS_LOG_FUNCTION (this << p << flags << address);
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv4, port);
if (InetSocketAddress::IsMatchingType (address))
{
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv4, port);
}
else if (Inet6SocketAddress::IsMatchingType (address))
{
Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
Ipv6Address ipv6 = transport.GetIpv6 ();
uint16_t port = transport.GetPort ();
return DoSendTo (p, ipv6, port);
}
return -1;
}
uint32_t
@@ -657,6 +872,38 @@ UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
}
}
void
UdpSocketImpl::ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
{
NS_LOG_FUNCTION (this << packet << saddr << port);
if (m_shutdownRecv)
{
return;
}
if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
{
Address address = Inet6SocketAddress (saddr, port);
SocketAddressTag tag;
tag.SetAddress (address);
packet->AddPacketTag (tag);
m_deliveryQueue.push (packet);
m_rxAvailable += packet->GetSize ();
NotifyDataRecv ();
}
else
{
// In general, this case should not occur unless the
// receiving application reads data from this socket slowly
// in comparison to the arrival rate
//
// drop and trace packet
NS_LOG_WARN ("No receive buffer space available. Drop.");
m_dropTrace (packet);
}
}
void
UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode,
@@ -670,6 +917,19 @@ UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
}
}
void
UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode,
uint32_t icmpInfo)
{
NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
(uint32_t)icmpCode << icmpInfo);
if (!m_icmpCallback6.IsNull ())
{
m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
}
}
void
UdpSocketImpl::SetRcvBufSize (uint32_t size)

View File

@@ -34,6 +34,7 @@
namespace ns3 {
class Ipv4EndPoint;
class Ipv6EndPoint;
class Node;
class Packet;
class UdpL4Protocol;
@@ -63,6 +64,7 @@ public:
virtual enum SocketType GetSocketType (void) const;
virtual Ptr<Node> GetNode (void) const;
virtual int Bind (void);
virtual int Bind6 (void);
virtual int Bind (const Address &address);
virtual int Close (void);
virtual int ShutdownSend (void);
@@ -104,18 +106,24 @@ private:
int FinishBind (void);
void ForwardUp (Ptr<Packet> p, Ipv4Header header, uint16_t port,
Ptr<Ipv4Interface> incomingInterface);
void ForwardUp6 (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t port);
void Destroy (void);
int DoSend (Ptr<Packet> p);
int DoSendTo (Ptr<Packet> p, const Address &daddr);
int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
int DoSendTo (Ptr<Packet> p, Ipv6Address daddr, uint16_t dport);
void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode,
uint32_t icmpInfo);
void ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
uint8_t icmpType, uint8_t icmpCode,
uint32_t icmpInfo);
Ipv4EndPoint *m_endPoint;
Ipv6EndPoint *m_endPoint6;
Ptr<Node> m_node;
Ptr<UdpL4Protocol> m_udp;
Ipv4Address m_defaultAddress;
Address m_defaultAddress;
uint16_t m_defaultPort;
TracedCallback<Ptr<const Packet> > m_dropTrace;
@@ -136,6 +144,7 @@ private:
bool m_ipMulticastLoop;
bool m_mtuDiscover;
Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
Callback<void, Ipv6Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback6;
};
} // namespace ns3

View File

@@ -61,7 +61,7 @@ void
ErrorNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
Mac48Address to, Mac48Address from)
{
NS_LOG_FUNCTION (packet << protocol << to << from);
NS_LOG_FUNCTION (packet << protocol << to << from << *packet);
NetDevice::PacketType packetType;
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
@@ -194,7 +194,7 @@ ErrorNetDevice::IsBridge (void) const
bool
ErrorNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (packet << dest << protocolNumber);
NS_LOG_FUNCTION (packet << dest << protocolNumber << *packet);
Mac48Address to = Mac48Address::ConvertFrom (dest);
m_channel->Send (packet, protocolNumber, to, m_address, this);
return true;
@@ -202,6 +202,7 @@ ErrorNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolN
bool
ErrorNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
{
NS_LOG_FUNCTION (packet << source << dest << protocolNumber << *packet);
Mac48Address to = Mac48Address::ConvertFrom (dest);
Mac48Address from = Mac48Address::ConvertFrom (source);
m_channel->Send (packet, protocolNumber, to, from, this);

View File

@@ -0,0 +1,312 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 Georgia Tech Research Corporation
* Copyright (c) 2009 INRIA
*
* 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
*
* Authors: Ken Renard <kenneth.d.renard.ctr@mail.mil>
*
*/
#include "ns3/test.h"
#include "ns3/socket-factory.h"
#include "ns3/tcp-socket-factory.h"
#include "ns3/simulator.h"
#include "ns3/simple-channel.h"
#include "ns3/simple-net-device.h"
#include "ns3/config.h"
#include "ns3/ipv4-static-routing.h"
#include "ns3/ipv4-list-routing.h"
#include "ns3/ipv6-static-routing.h"
#include "ns3/ipv6-list-routing.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/uinteger.h"
#include "ns3/log.h"
#include "ns3/ipv4-end-point.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/icmpv6-l4-protocol.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/tcp-l4-protocol.h"
#include <string>
NS_LOG_COMPONENT_DEFINE ("Ipv6DualStackTestSuite");
namespace ns3 {
class DualStackTestCase : public TestCase
{
public:
DualStackTestCase ();
private:
virtual void DoRun (void);
virtual void DoTeardown (void);
void SetUpSim ();
Ptr<Node> node0;
Ptr<Node> node1;
void ServerHandleConnectionCreated1 (Ptr<Socket> s, const Address & addr);
void ServerHandleConnectionCreated2 (Ptr<Socket> s, const Address & addr);
void ServerHandleConnectionCreated3 (Ptr<Socket> s, const Address & addr);
void ServerHandleConnectionCreated4 (Ptr<Socket> s, const Address & addr);
Ptr<Socket> server1;
Ptr<Socket> server2;
Ptr<Socket> server3;
Ptr<Socket> server4;
Ptr<Socket> source1;
Ptr<Socket> source2;
Ptr<Socket> source3;
Ptr<Socket> source4;
Address receivedAddr1;
Address receivedAddr2;
Address receivedAddr3;
Address receivedAddr4;
};
Ptr<Node>
CreateDualStackNode ()
{
Ptr<Node> node = CreateObject<Node> ();
//ARP
Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
node->AggregateObject (arp);
//IPV4
Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
//Routing for Ipv4
Ptr<Ipv4ListRouting> ipv4Routing = CreateObject<Ipv4ListRouting> ();
ipv4->SetRoutingProtocol (ipv4Routing);
Ptr<Ipv4StaticRouting> ipv4staticRouting = CreateObject<Ipv4StaticRouting> ();
ipv4Routing->AddRoutingProtocol (ipv4staticRouting, 0);
node->AggregateObject (ipv4);
//ICMPv4
Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
node->AggregateObject (icmp);
//UDP
Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
node->AggregateObject (udp);
//TCP
Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
node->AggregateObject (tcp);
//IPV6
Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
//Routing for Ipv6
Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
ipv6->SetRoutingProtocol (ipv6Routing);
Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
node->AggregateObject (ipv6);
//ICMPv6
Ptr<Icmpv6L4Protocol> icmp6 = CreateObject<Icmpv6L4Protocol> ();
node->AggregateObject (icmp6);
//Ipv6 Extensions
ipv6->RegisterExtensions ();
ipv6->RegisterOptions ();
return node;
}
Ptr<SimpleNetDevice>
AddSimpleNetDevice (Ptr<Node> node, Ipv4Address v4Addr, Ipv4Mask v4Mask,
Ipv6Address v6Addr, Ipv6Prefix v6Prefix)
{
Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
node->AddDevice (dev);
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
uint32_t ndid = ipv4->AddInterface (dev);
Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (v4Addr, v4Mask);
ipv4->AddAddress (ndid, ipv4Addr);
ipv4->SetUp (ndid);
Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
ndid = ipv6->AddInterface (dev);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (v6Addr, v6Prefix);
ipv6->AddAddress (ndid, ipv6Addr);
ipv6->SetUp (ndid);
return dev;
}
void
DualStackTestCase::SetUpSim ()
{
node0 = CreateDualStackNode ();
node1 = CreateDualStackNode ();
Ptr<SimpleNetDevice> dev0 = AddSimpleNetDevice(node0, Ipv4Address("10.0.0.1"),
Ipv4Mask(0xffffff00), Ipv6Address("2001::1"), Ipv6Prefix(64));
Ptr<SimpleNetDevice> dev1 = AddSimpleNetDevice(node1, Ipv4Address("10.0.0.2"),
Ipv4Mask(0xffffff00), Ipv6Address("2001::2"), Ipv6Prefix(64));
Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
dev0->SetChannel (channel);
dev1->SetChannel (channel);
Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
server1 = sockFactory0->CreateSocket ();
server2 = sockFactory0->CreateSocket ();
server3 = sockFactory0->CreateSocket ();
server4 = sockFactory0->CreateSocket ();
source1 = sockFactory1->CreateSocket ();
source2 = sockFactory1->CreateSocket ();
source3 = sockFactory1->CreateSocket ();
source4 = sockFactory1->CreateSocket ();
return;
}
void
DualStackTestCase::ServerHandleConnectionCreated1 (Ptr<Socket> s, const Address & addr)
{
receivedAddr1 = addr;
return;
}
void
DualStackTestCase::ServerHandleConnectionCreated2 (Ptr<Socket> s, const Address & addr)
{
receivedAddr2 = addr;
return;
}
void
DualStackTestCase::ServerHandleConnectionCreated3 (Ptr<Socket> s, const Address & addr)
{
receivedAddr3 = addr;
return;
}
void
DualStackTestCase::ServerHandleConnectionCreated4 (Ptr<Socket> s, const Address & addr)
{
receivedAddr4 = addr;
return;
}
DualStackTestCase::DualStackTestCase ()
: TestCase ("DualStackTestCase")
{
receivedAddr1 = Address ();
receivedAddr2 = Address ();
receivedAddr3 = Address ();
receivedAddr4 = Address ();
}
void
DualStackTestCase::DoRun (void)
{
SetUpSim ();
uint16_t port1 = 5000;
uint16_t port2 = 5001;
uint16_t port3 = 5002;
uint16_t port4 = 5003;
/* Server 1: listen on 0.0.0.0 for IPv4 connection */
server1->Bind (InetSocketAddress(Ipv4Address::GetAny(), port1));
server1->Listen ();
server1->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated1, this));
/* Server 2: listen on 0.0.0.0 for IPv4 connection - should reject IPv6 */
server2->Bind (InetSocketAddress(Ipv4Address::GetAny(), port2));
server2->Listen ();
server2->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated2, this));
/* Server 3: listen on :: for IPv4 (mapped into IPv6 address) connection */
server3->Bind (Inet6SocketAddress(Ipv6Address::GetAny(), port3));
server3->Listen ();
server3->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated3, this));
/* Server 4: listen on :: for IPv6 connection */
server4->Bind (Inet6SocketAddress(Ipv6Address::GetAny(), port4));
server4->Listen ();
server4->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated4, this));
/* Source 1: connect to server 1 via IPv4 */
source1->Connect(InetSocketAddress(Ipv4Address("10.0.0.1"), port1));
/* Source 2: connect to server 2 via IPv6 */
source2->Connect(Inet6SocketAddress(Ipv6Address("2001::1"), port2));
/* Source 3: connect to server 3 via IPv4 */
source3->Connect(InetSocketAddress(Ipv4Address("10.0.0.1"), port3));
/* Source 4: connect to server 4 via IPv6 */
source4->Connect(Inet6SocketAddress(Ipv6Address("2001::1"), port4));
Simulator::Run();
/* Server 1: should have connection from Ipv4 address of Node 1 */
NS_TEST_EXPECT_MSG_EQ (InetSocketAddress::IsMatchingType(receivedAddr1), true, "Accepted address is of proper type");
NS_TEST_EXPECT_MSG_EQ(InetSocketAddress::ConvertFrom(receivedAddr1).GetIpv4 (), Ipv4Address("10.0.0.2"), "Accepted address is correct");
/* Server 2: should have no connection */
NS_TEST_EXPECT_MSG_EQ(receivedAddr2.IsInvalid(), true, "IPv4 socket correctly ignored IPv6 connection");
/* Server 3: should have connection from Ipv4-mapped IPv6 address of Node 1 */
NS_TEST_EXPECT_MSG_EQ (Inet6SocketAddress::IsMatchingType(receivedAddr3), true, "Accepted address is of proper type");
NS_TEST_EXPECT_MSG_EQ(Inet6SocketAddress::ConvertFrom(receivedAddr3).GetIpv6 (), Ipv6Address("::ffff:0a00:0002"), "Accepted address is correct");
/* Server 4: should have connection from IPv6 address of Node 1 */
NS_TEST_EXPECT_MSG_EQ (Inet6SocketAddress::IsMatchingType(receivedAddr4), true, "Accepted address is of proper type");
NS_TEST_EXPECT_MSG_EQ(Inet6SocketAddress::ConvertFrom(receivedAddr4).GetIpv6 (), Ipv6Address("2001::2"), "Accepted address is correct");
}
void
DualStackTestCase::DoTeardown (void)
{
}
static class Ipv6DualStackTestSuite : public TestSuite
{
public:
Ipv6DualStackTestSuite ()
: TestSuite ("ipv6-dual-stack", UNIT)
{
AddTestCase (new DualStackTestCase());
}
} g_ipv6DualStackTestSuite;
} // namespace ns3

View File

@@ -30,15 +30,20 @@
#include "ns3/config.h"
#include "ns3/ipv4-static-routing.h"
#include "ns3/ipv4-list-routing.h"
#include "ns3/ipv6-static-routing.h"
#include "ns3/ipv6-list-routing.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/uinteger.h"
#include "ns3/log.h"
#include "ns3/ipv4-end-point.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/icmpv6-l4-protocol.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/tcp-l4-protocol.h"
@@ -55,14 +60,18 @@ public:
uint32_t sourceWriteSize,
uint32_t sourceReadSize,
uint32_t serverWriteSize,
uint32_t serverReadSize);
uint32_t serverReadSize,
bool useIpv6);
private:
virtual void DoRun (void);
virtual void DoTeardown (void);
void SetupDefaultSim (void);
void SetupDefaultSim6 (void);
Ptr<Node> CreateInternetNode (void);
Ptr<Node> CreateInternetNode6 (void);
Ptr<SimpleNetDevice> AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask);
Ptr<SimpleNetDevice> AddSimpleNetDevice6 (Ptr<Node> node, Ipv6Address ipaddr, Ipv6Prefix prefix);
void ServerHandleConnectionCreated (Ptr<Socket> s, const Address & addr);
void ServerHandleRecv (Ptr<Socket> sock);
void ServerHandleSend (Ptr<Socket> sock, uint32_t available);
@@ -81,18 +90,21 @@ private:
uint8_t *m_sourceTxPayload;
uint8_t *m_sourceRxPayload;
uint8_t* m_serverRxPayload;
bool m_useIpv6;
};
static std::string Name (std::string str, uint32_t totalStreamSize,
uint32_t sourceWriteSize,
uint32_t serverReadSize,
uint32_t serverWriteSize,
uint32_t sourceReadSize)
uint32_t sourceReadSize,
bool useIpv6)
{
std::ostringstream oss;
oss << str << " total=" << totalStreamSize << " sourceWrite=" << sourceWriteSize
<< " sourceRead=" << sourceReadSize << " serverRead=" << serverReadSize
<< " serverWrite=" << serverWriteSize;
<< " serverWrite=" << serverWriteSize << " useIpv6=" << useIpv6;
return oss.str ();
}
@@ -109,18 +121,21 @@ TcpTestCase::TcpTestCase (uint32_t totalStreamSize,
uint32_t sourceWriteSize,
uint32_t sourceReadSize,
uint32_t serverWriteSize,
uint32_t serverReadSize)
uint32_t serverReadSize,
bool useIpv6)
: TestCase (Name ("Send string data from client to server and back",
totalStreamSize,
sourceWriteSize,
serverReadSize,
serverWriteSize,
sourceReadSize)),
sourceReadSize,
useIpv6)),
m_totalBytes (totalStreamSize),
m_sourceWriteSize (sourceWriteSize),
m_sourceReadSize (sourceReadSize),
m_serverWriteSize (serverWriteSize),
m_serverReadSize (serverReadSize)
m_serverReadSize (serverReadSize),
m_useIpv6 (useIpv6)
{
}
@@ -142,7 +157,14 @@ TcpTestCase::DoRun (void)
memset (m_sourceRxPayload, 0, m_totalBytes);
memset (m_serverRxPayload, 0, m_totalBytes);
SetupDefaultSim ();
if (m_useIpv6 == true)
{
SetupDefaultSim6 ();
}
else
{
SetupDefaultSim ();
}
Simulator::Run ();
@@ -326,6 +348,83 @@ TcpTestCase::SetupDefaultSim (void)
source->Connect (serverremoteaddr);
}
void
TcpTestCase::SetupDefaultSim6 (void)
{
Ipv6Prefix prefix = Ipv6Prefix(64);
Ipv6Address ipaddr0 = Ipv6Address("2001:0100:f00d:cafe::1");
Ipv6Address ipaddr1 = Ipv6Address("2001:0100:f00d:cafe::2");
Ptr<Node> node0 = CreateInternetNode6 ();
Ptr<Node> node1 = CreateInternetNode6 ();
Ptr<SimpleNetDevice> dev0 = AddSimpleNetDevice6 (node0, ipaddr0, prefix);
Ptr<SimpleNetDevice> dev1 = AddSimpleNetDevice6 (node1, ipaddr1, prefix);
Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
dev0->SetChannel (channel);
dev1->SetChannel (channel);
Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
Ptr<Socket> server = sockFactory0->CreateSocket ();
Ptr<Socket> source = sockFactory1->CreateSocket ();
uint16_t port = 50000;
Inet6SocketAddress serverlocaladdr (Ipv6Address::GetAny (), port);
Inet6SocketAddress serverremoteaddr (ipaddr0, port);
server->Bind (serverlocaladdr);
server->Listen ();
server->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
MakeCallback (&TcpTestCase::ServerHandleConnectionCreated,this));
source->SetRecvCallback (MakeCallback (&TcpTestCase::SourceHandleRecv, this));
source->SetSendCallback (MakeCallback (&TcpTestCase::SourceHandleSend, this));
source->Connect (serverremoteaddr);
}
Ptr<Node>
TcpTestCase::CreateInternetNode6 ()
{
Ptr<Node> node = CreateObject<Node> ();
//IPV6
Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
//Routing for Ipv6
Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
ipv6->SetRoutingProtocol (ipv6Routing);
Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
node->AggregateObject (ipv6);
//ICMP
Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
node->AggregateObject (icmp);
//Ipv6 Extensions
ipv6->RegisterExtensions ();
ipv6->RegisterOptions ();
//UDP
Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
node->AggregateObject (udp);
//TCP
Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
node->AggregateObject (tcp);
return node;
}
Ptr<SimpleNetDevice>
TcpTestCase::AddSimpleNetDevice6 (Ptr<Node> node, Ipv6Address ipaddr, Ipv6Prefix prefix)
{
Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
node->AddDevice (dev);
Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
uint32_t ndid = ipv6->AddInterface (dev);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (ipaddr, prefix);
ipv6->AddAddress (ndid, ipv6Addr);
ipv6->SetUp (ndid);
return dev;
}
static class TcpTestSuite : public TestSuite
{
public:
@@ -336,9 +435,13 @@ public:
// 2) source write size, 3) source read size
// 4) server write size, and 5) server read size
// with units of bytes
AddTestCase (new TcpTestCase (13, 200, 200, 200, 200));
AddTestCase (new TcpTestCase (13, 1, 1, 1, 1));
AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20));
AddTestCase (new TcpTestCase (13, 200, 200, 200, 200, false));
AddTestCase (new TcpTestCase (13, 1, 1, 1, 1, false));
AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20, false));
AddTestCase (new TcpTestCase (13, 200, 200, 200, 200, true));
AddTestCase (new TcpTestCase (13, 1, 1, 1, 1, true));
AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20, true));
}
} g_tcpTestSuite;

View File

@@ -34,14 +34,19 @@
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/icmpv6-l4-protocol.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/tcp-l4-protocol.h"
#include "ns3/ipv4-list-routing.h"
#include "ns3/ipv4-static-routing.h"
#include "ns3/ipv6-list-routing.h"
#include "ns3/ipv6-static-routing.h"
#include <string>
#include <limits>
@@ -72,6 +77,31 @@ AddInternetStack (Ptr<Node> node)
node->AggregateObject (tcp);
}
static void
AddInternetStack6 (Ptr<Node> node)
{
//IPV6
Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
//Routing for Ipv6
Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
ipv6->SetRoutingProtocol (ipv6Routing);
Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
node->AggregateObject (ipv6);
//ICMP
Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
node->AggregateObject (icmp);
//Ipv6 Extensions
ipv6->RegisterExtensions ();
ipv6->RegisterOptions ();
//UDP
Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
node->AggregateObject (udp);
//TCP
Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
node->AggregateObject (tcp);
}
class UdpSocketLoopbackTest : public TestCase
{
@@ -114,6 +144,50 @@ UdpSocketLoopbackTest::DoRun ()
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 246, "first socket should not receive it (it is bound specifically to the second interface's address");
}
class Udp6SocketLoopbackTest : public TestCase
{
public:
Udp6SocketLoopbackTest ();
virtual void DoRun (void);
void ReceivePkt (Ptr<Socket> socket);
Ptr<Packet> m_receivedPacket;
};
Udp6SocketLoopbackTest::Udp6SocketLoopbackTest ()
: TestCase ("UDP6 loopback test")
{
}
void Udp6SocketLoopbackTest::ReceivePkt (Ptr<Socket> socket)
{
uint32_t availableData;
availableData = socket->GetRxAvailable ();
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
NS_ASSERT (availableData == m_receivedPacket->GetSize ());
//cast availableData to void, to suppress 'availableData' set but not used
//compiler warning
(void) availableData;
}
void
Udp6SocketLoopbackTest::DoRun ()
{
Ptr<Node> rxNode = CreateObject<Node> ();
AddInternetStack6 (rxNode);
Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
rxSocket->Bind (Inet6SocketAddress (Ipv6Address::GetAny (), 80));
rxSocket->SetRecvCallback (MakeCallback (&Udp6SocketLoopbackTest::ReceivePkt, this));
Ptr<Socket> txSocket = rxSocketFactory->CreateSocket ();
txSocket->SendTo (Create<Packet> (246), 0, Inet6SocketAddress ("::1", 80));
Simulator::Run ();
Simulator::Destroy ();
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 246, "first socket should not receive it (it is bound specifically to the second interface's address");
}
class UdpSocketImplTest : public TestCase
{
Ptr<Packet> m_receivedPacket;
@@ -311,6 +385,190 @@ UdpSocketImplTest::DoRun (void)
}
class Udp6SocketImplTest : public TestCase
{
Ptr<Packet> m_receivedPacket;
Ptr<Packet> m_receivedPacket2;
void DoSendData (Ptr<Socket> socket, std::string to);
void SendData (Ptr<Socket> socket, std::string to);
public:
virtual void DoRun (void);
Udp6SocketImplTest ();
void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
void ReceivePkt (Ptr<Socket> socket);
void ReceivePkt2 (Ptr<Socket> socket);
};
Udp6SocketImplTest::Udp6SocketImplTest ()
: TestCase ("UDP6 socket implementation")
{
}
void Udp6SocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
{
m_receivedPacket = packet;
}
void Udp6SocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
{
m_receivedPacket2 = packet;
}
void Udp6SocketImplTest::ReceivePkt (Ptr<Socket> socket)
{
uint32_t availableData;
availableData = socket->GetRxAvailable ();
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
NS_ASSERT (availableData == m_receivedPacket->GetSize ());
//cast availableData to void, to suppress 'availableData' set but not used
//compiler warning
(void) availableData;
}
void Udp6SocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
{
uint32_t availableData;
availableData = socket->GetRxAvailable ();
m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
//cast availableData to void, to suppress 'availableData' set but not used
//compiler warning
(void) availableData;
}
void
Udp6SocketImplTest::DoSendData (Ptr<Socket> socket, std::string to)
{
Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234);
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
123, "XXX");
}
void
Udp6SocketImplTest::SendData (Ptr<Socket> socket, std::string to)
{
m_receivedPacket = Create<Packet> ();
m_receivedPacket2 = Create<Packet> ();
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
&Udp6SocketImplTest::DoSendData, this, socket, to);
Simulator::Run ();
}
void
Udp6SocketImplTest::DoRun (void)
{
// Create topology
// Receiver Node
Ptr<Node> rxNode = CreateObject<Node> ();
AddInternetStack6 (rxNode);
Ptr<SimpleNetDevice> rxDev1, rxDev2;
{ // first interface
rxDev1 = CreateObject<SimpleNetDevice> ();
rxDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
rxNode->AddDevice (rxDev1);
Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (rxDev1);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
{ // second interface
rxDev2 = CreateObject<SimpleNetDevice> ();
rxDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
rxNode->AddDevice (rxDev2);
Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (rxDev2);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100:1::1"), Ipv6Prefix (64));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
// Sender Node
Ptr<Node> txNode = CreateObject<Node> ();
AddInternetStack6 (txNode);
Ptr<SimpleNetDevice> txDev1;
{
txDev1 = CreateObject<SimpleNetDevice> ();
txDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
txNode->AddDevice (txDev1);
Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (txDev1);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
Ptr<SimpleNetDevice> txDev2;
{
txDev2 = CreateObject<SimpleNetDevice> ();
txDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
txNode->AddDevice (txDev2);
Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
uint32_t netdev_idx = ipv6->AddInterface (txDev2);
Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100:1::2"), Ipv6Prefix (64));
ipv6->AddAddress (netdev_idx, ipv6Addr);
ipv6->SetUp (netdev_idx);
}
// link the two nodes
Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
rxDev1->SetChannel (channel1);
txDev1->SetChannel (channel1);
Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
rxDev2->SetChannel (channel2);
txDev2->SetChannel (channel2);
// Create the UDP sockets
Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 1234)), 0, "trivial");
rxSocket->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt, this));
Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
rxSocket2->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt2, this));
NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100:1::1"), 1234)), 0, "trivial");
Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
txSocket->SetAllowBroadcast (true);
// ------ Now the tests ------------
// Unicast test
SendData (txSocket, "2001:0100::1");
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "trivial");
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 0, "second interface should receive it");
m_receivedPacket->RemoveAllByteTags ();
m_receivedPacket2->RemoveAllByteTags ();
// Simple Link-local multicast test
// When receiving broadcast packets, all sockets sockets bound to
// the address/port should receive a copy of the same packet -- if
// the socket address matches.
rxSocket2->Dispose ();
rxSocket2 = rxSocketFactory->CreateSocket ();
rxSocket2->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt2, this));
NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (Inet6SocketAddress (Ipv6Address ("::"), 1234)), 0, "trivial");
txSocket->BindToNetDevice (txDev1);
SendData (txSocket, "ff02::1");
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 0, "first socket should not receive it (it is bound specifically to the second interface's address");
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 123, "recv2: ff02::1");
m_receivedPacket->RemoveAllByteTags ();
m_receivedPacket2->RemoveAllByteTags ();
Simulator::Destroy ();
}
//-----------------------------------------------------------------------------
class UdpTestSuite : public TestSuite
{
@@ -319,6 +577,8 @@ public:
{
AddTestCase (new UdpSocketImplTest);
AddTestCase (new UdpSocketLoopbackTest);
AddTestCase (new Udp6SocketImplTest);
AddTestCase (new Udp6SocketLoopbackTest);
}
} g_udpTestSuite;

View File

@@ -94,7 +94,7 @@ def build(bld):
# bridge and mpi dependencies are due to global routing
obj = bld.create_ns3_module('internet', ['bridge', 'mpi', 'network', 'core'])
obj.source = [
'model/ipv4-l4-protocol.cc',
'model/ip-l4-protocol.cc',
'model/udp-header.cc',
'model/tcp-header.cc',
'model/ipv4-interface.cc',
@@ -122,7 +122,6 @@ def build(bld):
'model/ipv6-l3-protocol.cc',
'model/ipv6-end-point.cc',
'model/ipv6-end-point-demux.cc',
'model/ipv6-l4-protocol.cc',
'model/ipv6-raw-socket-factory-impl.cc',
'model/ipv6-raw-socket-impl.cc',
'model/ipv6-autoconfigured-prefix.cc',
@@ -206,6 +205,7 @@ def build(bld):
'test/tcp-test.cc',
'test/udp-test.cc',
'test/ipv6-address-generator-test-suite.cc',
'test/ipv6-dual-stack-test-suite.cc',
]
headers = bld.new_task_gen(features=['ns3header'])
@@ -226,11 +226,10 @@ def build(bld):
'model/udp-l4-protocol.h',
'model/tcp-l4-protocol.h',
'model/icmpv4-l4-protocol.h',
'model/ipv4-l4-protocol.h',
'model/ip-l4-protocol.h',
'model/arp-header.h',
'model/arp-cache.h',
'model/icmpv6-l4-protocol.h',
'model/ipv6-l4-protocol.h',
'model/ipv6-interface.h',
'model/ndisc-cache.h',
'model/loopback-net-device.h',

View File

@@ -56,10 +56,14 @@ main (int argc, char *argv[])
//
uint32_t nSpokes = 8;
std::string animFile = "star-animation.xml";
uint8_t useIpv6 = 0;
Ipv6Address ipv6AddressBase = Ipv6Address("2001::");
Ipv6Prefix ipv6AddressPrefix = Ipv6Prefix(64);
CommandLine cmd;
cmd.AddValue ("nSpokes", "Number of spoke nodes to place in the star", nSpokes);
cmd.AddValue ("animFile", "File Name for Animation Output", animFile);
cmd.AddValue ("useIpv6", "use Ipv6", useIpv6);
cmd.Parse (argc, argv);
@@ -74,14 +78,29 @@ main (int argc, char *argv[])
star.InstallStack (internet);
NS_LOG_INFO ("Assign IP Addresses.");
star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"));
if (useIpv6 == 0)
{
star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"));
}
else
{
star.AssignIpv6Addresses (ipv6AddressBase, ipv6AddressPrefix);
}
NS_LOG_INFO ("Create applications.");
//
// Create a packet sink on the star "hub" to receive packets.
//
uint16_t port = 50000;
Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
Address hubLocalAddress;
if (useIpv6 == 0)
{
hubLocalAddress = InetSocketAddress (Ipv4Address::GetAny (), port);
}
else
{
hubLocalAddress = Inet6SocketAddress (Ipv6Address::GetAny (), port);
}
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
hubApp.Start (Seconds (1.0));
@@ -98,7 +117,15 @@ main (int argc, char *argv[])
for (uint32_t i = 0; i < star.SpokeCount (); ++i)
{
AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
AddressValue remoteAddress;
if (useIpv6 == 0)
{
remoteAddress = AddressValue(InetSocketAddress (star.GetHubIpv4Address (i), port));
}
else
{
remoteAddress = AddressValue(Inet6SocketAddress (star.GetHubIpv6Address (i), port));
}
onOffHelper.SetAttribute ("Remote", remoteAddress);
spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
}
@@ -109,7 +136,10 @@ main (int argc, char *argv[])
//
// Turn on global static routing so we can actually be routed across the star.
//
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
if (useIpv6 == 0)
{
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
}
// Set the bounding box for animation
star.BoundingBox (1, 1, 100, 100);

View File

@@ -202,20 +202,25 @@ public:
*/
void SetRecvCallback (Callback<void, Ptr<Socket> >);
/**
* \brief Allocate a local endpoint for this socket.
* \param address the address to try to allocate
* \returns 0 on success, -1 on failure.
*
* Allocate a local endpoint for this socket.
*/
virtual int Bind (const Address &address) = 0;
/**
* Allocate a local endpoint for this socket.
*
* \brief Allocate a local IPv4 endpoint for this socket.
* \returns 0 on success, -1 on failure.
*/
virtual int Bind () = 0;
/**
* \brief Allocate a local IPv6 endpoint for this socket.
* \returns 0 on success, -1 on failure.
*/
virtual int Bind6 () = 0;
/**
* \brief Close a socket.
* \returns zero on success, -1 on failure.

View File

@@ -301,6 +301,24 @@ Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
return ipv6;
}
Ipv6Address Ipv6Address::MakeIpv4MappedAddress(Ipv4Address addr)
{
uint8_t buf[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
addr.Serialize (&buf[12]);
return (Ipv6Address (buf));
}
Ipv4Address Ipv6Address::GetIpv4MappedAddress() const
{
uint8_t buf[16];
Ipv4Address v4Addr;
Serialize (buf);
v4Addr = Ipv4Address::Deserialize (&buf[12]);
return (v4Addr);
}
Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix)
{
Ipv6Address ret;
@@ -398,6 +416,26 @@ bool Ipv6Address::IsMulticast () const
return false;
}
bool Ipv6Address::IsLinkLocalMulticast () const
{
if (m_address[0] == 0xff && m_address[1] == 0x02)
{
return true;
}
return false;
}
bool Ipv6Address::IsIpv4MappedAddress ()
{
uint8_t v4MappedPrefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff };
if (memcmp(m_address, v4MappedPrefix, sizeof(v4MappedPrefix)) == 0)
{
return (true);
}
return (false);
}
Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const& prefix)
{
Ipv6Address ipv6;

View File

@@ -28,6 +28,7 @@
#include "ns3/attribute-helper.h"
#include "ns3/address.h"
#include "ns3/ipv4-address.h"
namespace ns3 {
@@ -121,6 +122,19 @@ public:
*/
static Ipv6Address MakeSolicitedAddress (Ipv6Address addr);
/**
* \brief Make the Ipv4-mapped IPv6 address.
* \param addr the IPv4 address
* \return Ipv4-mapped IPv6 address
*/
static Ipv6Address MakeIpv4MappedAddress (Ipv4Address addr);
/**
* \brief Return the Ipv4 address.
* \return Ipv4 address
*/
Ipv4Address GetIpv4MappedAddress () const;
/**
* \brief Make the autoconfigured IPv6 address with Mac48Address.
* \param addr the MAC address (48 bits).
@@ -156,6 +170,12 @@ public:
*/
bool IsMulticast () const;
/**
* \brief If the IPv6 address is link-local multicast (ff02::/16).
* \return true if link-local multicast, false otherwise
*/
bool IsLinkLocalMulticast () const;
/**
* \brief If the IPv6 address is "all nodes multicast" (ff02::1/8).
* \return true if "all nodes multicast", false otherwise
@@ -207,6 +227,12 @@ public:
*/
static bool IsMatchingType (const Address& address);
/**
* \brief If the address is an IPv4-mapped address
* \return true if address is an IPv4-mapped address, otherwise false.
*/
bool IsIpv4MappedAddress();
/**
* \brief Convert to Address object
*/

View File

@@ -112,6 +112,12 @@ PacketSocket::Bind (void)
return DoBind (address);
}
int
PacketSocket::Bind6 (void)
{
return(Bind());
}
int
PacketSocket::Bind (const Address &address)
{

View File

@@ -89,6 +89,7 @@ public:
virtual enum SocketType GetSocketType (void) const;
virtual Ptr<Node> GetNode (void) const;
virtual int Bind (void);
virtual int Bind6 (void);
virtual int Bind (const Address & address);
virtual int Close (void);
virtual int ShutdownSend (void);

View File

@@ -29,6 +29,7 @@
#include "ns3/node-list.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/vector.h"
#include "ns3/ipv6-address-generator.h"
NS_LOG_COMPONENT_DEFINE ("PointToPointDumbbellHelper");
@@ -100,6 +101,16 @@ Ipv4Address PointToPointDumbbellHelper::GetRightIpv4Address (uint32_t i) const
return m_rightLeafInterfaces.GetAddress (i);
}
Ipv6Address PointToPointDumbbellHelper::GetLeftIpv6Address (uint32_t i) const
{
return m_leftLeafInterfaces6.GetAddress (i, 1);
}
Ipv6Address PointToPointDumbbellHelper::GetRightIpv6Address (uint32_t i) const
{
return m_rightLeafInterfaces6.GetAddress (i, 1);
}
uint32_t PointToPointDumbbellHelper::LeftCount () const
{ // Number of left side nodes
return m_leftLeaf.GetN ();
@@ -147,6 +158,52 @@ void PointToPointDumbbellHelper::AssignIpv4Addresses (Ipv4AddressHelper leftIp,
}
}
void PointToPointDumbbellHelper::AssignIpv6Addresses (Ipv6Address addrBase, Ipv6Prefix prefix)
{
// Assign the router network
Ipv6AddressGenerator::Init (addrBase, prefix);
Ipv6Address v6network;
Ipv6AddressHelper addressHelper;
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addressHelper.NewNetwork (v6network, prefix);
m_routerInterfaces6 = addressHelper.Assign (m_routerDevices);
Ipv6AddressGenerator::NextNetwork (prefix);
// Assign to left side
for (uint32_t i = 0; i < LeftCount (); ++i)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addressHelper.NewNetwork (v6network, prefix);
NetDeviceContainer ndc;
ndc.Add (m_leftLeafDevices.Get (i));
ndc.Add (m_leftRouterDevices.Get (i));
Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
m_leftLeafInterfaces6.Add ((*it).first, (*it).second);
it++;
m_leftRouterInterfaces6.Add ((*it).first, (*it).second);
Ipv6AddressGenerator::NextNetwork (prefix);
}
// Assign to right side
for (uint32_t i = 0; i < RightCount (); ++i)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addressHelper.NewNetwork (v6network, prefix);
NetDeviceContainer ndc;
ndc.Add (m_rightLeafDevices.Get (i));
ndc.Add (m_rightRouterDevices.Get (i));
Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
m_rightLeafInterfaces6.Add ((*it).first, (*it).second);
it++;
m_rightRouterInterfaces6.Add ((*it).first, (*it).second);
Ipv6AddressGenerator::NextNetwork (prefix);
}
}
void PointToPointDumbbellHelper::BoundingBox (double ulx, double uly, // Upper left x/y
double lrx, double lry) // Lower right y

View File

@@ -25,8 +25,10 @@
#include "point-to-point-helper.h"
#include "ipv4-address-helper.h"
#include "ipv6-address-helper.h"
#include "internet-stack-helper.h"
#include "ipv4-interface-container.h"
#include "ipv6-interface-container.h"
namespace ns3 {
@@ -100,6 +102,16 @@ public:
*/
Ipv4Address GetRightIpv4Address (uint32_t i) const; // Get right leaf address
/**
* \returns an Ipv6Address of the i'th left leaf
*/
Ipv6Address GetLeftIpv6Address (uint32_t i ) const; // Get left leaf address
/**
* \returns an Ipv6Address of the i'th right leaf
*/
Ipv6Address GetRightIpv6Address (uint32_t i) const; // Get right leaf address
/**
* \returns total number of left side leaf nodes
*/
@@ -130,6 +142,13 @@ public:
Ipv4AddressHelper rightIp,
Ipv4AddressHelper routerIp);
/**
* \param network an IPv6 address representing the network portion
* of the IPv6 Address
* \param prefix the prefix length
*/
void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
/**
* Sets up the node canvas locations for every node in the dumbbell.
* This is needed for use with the animation interface
@@ -155,6 +174,11 @@ private:
Ipv4InterfaceContainer m_rightLeafInterfaces;
Ipv4InterfaceContainer m_rightRouterInterfaces;
Ipv4InterfaceContainer m_routerInterfaces;
Ipv6InterfaceContainer m_leftLeafInterfaces6;
Ipv6InterfaceContainer m_leftRouterInterfaces6;
Ipv6InterfaceContainer m_rightLeafInterfaces6;
Ipv6InterfaceContainer m_rightRouterInterfaces6;
Ipv6InterfaceContainer m_routerInterfaces6;
};
} // namespace ns3

View File

@@ -24,6 +24,7 @@
#include "ns3/string.h"
#include "ns3/vector.h"
#include "ns3/log.h"
#include "ns3/ipv6-address-generator.h"
NS_LOG_COMPONENT_DEFINE ("PointToPointGridHelper");
@@ -130,6 +131,56 @@ PointToPointGridHelper::AssignIpv4Addresses (Ipv4AddressHelper rowIp, Ipv4Addres
}
}
void
PointToPointGridHelper::AssignIpv6Addresses(Ipv6Address addrBase, Ipv6Prefix prefix)
{
Ipv6AddressGenerator::Init(addrBase, prefix);
Ipv6Address v6network;
Ipv6AddressHelper addrHelper;
// Assign addresses to all row devices in the grid.
// These devices are stored in a vector. Each row
// of the grid has all the row devices in one entry
// of the vector. These entries come in pairs.
for (uint32_t i = 0; i < m_rowDevices.size (); ++i)
{
Ipv6InterfaceContainer rowInterfaces;
NetDeviceContainer rowContainer = m_rowDevices[i];
for (uint32_t j = 0; j < rowContainer.GetN (); j+=2)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addrHelper.NewNetwork(v6network, prefix);
Ipv6InterfaceContainer ic = addrHelper.Assign (rowContainer.Get (j));
rowInterfaces.Add (ic);
ic = addrHelper.Assign (rowContainer.Get (j+1));
rowInterfaces.Add (ic);
Ipv6AddressGenerator::NextNetwork (prefix);
}
m_rowInterfaces6.push_back (rowInterfaces);
}
// Assign addresses to all col devices in the grid.
// These devices are stored in a vector. Each col
// of the grid has all the col devices in one entry
// of the vector. These entries come in pairs.
for (uint32_t i = 0; i < m_colDevices.size (); ++i)
{
Ipv6InterfaceContainer colInterfaces;
NetDeviceContainer colContainer = m_colDevices[i];
for (uint32_t j = 0; j < colContainer.GetN (); j+=2)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addrHelper.NewNetwork(v6network, prefix);
Ipv6InterfaceContainer ic = addrHelper.Assign (colContainer.Get (j));
colInterfaces.Add (ic);
ic = addrHelper.Assign (colContainer.Get (j+1));
colInterfaces.Add (ic);
Ipv6AddressGenerator::NextNetwork (prefix);
}
m_colInterfaces6.push_back (colInterfaces);
}
}
void
PointToPointGridHelper::BoundingBox (double ulx, double uly,
double lrx, double lry)
@@ -214,4 +265,30 @@ PointToPointGridHelper::GetIpv4Address (uint32_t row, uint32_t col)
}
}
Ipv6Address
PointToPointGridHelper::GetIpv6Address (uint32_t row, uint32_t col)
{
if (row > m_nodes.size () - 1 ||
col > m_nodes.at (row).GetN () - 1)
{
NS_FATAL_ERROR ("Index out of bounds in PointToPointGridHelper::GetIpv4Address.");
}
// Right now this just gets one of the addresses of the
// specified node. The exact device can't be specified.
// If you picture the grid, the address returned is the
// address of the left (row) device of all nodes, with
// the exception of the left-most nodes in the grid;
// in which case the right (row) device address is
// returned
if (col == 0)
{
return (m_rowInterfaces6.at (row)).GetAddress (0, 1);
}
else
{
return (m_rowInterfaces6.at (row)).GetAddress ((2*col)-1, 1);
}
}
} // namespace ns3

View File

@@ -24,7 +24,9 @@
#include "internet-stack-helper.h"
#include "point-to-point-helper.h"
#include "ipv4-address-helper.h"
#include "ipv6-address-helper.h"
#include "ipv4-interface-container.h"
#include "ipv6-interface-container.h"
#include "net-device-container.h"
namespace ns3 {
@@ -84,6 +86,24 @@ public:
*/
Ipv4Address GetIpv4Address (uint32_t row, uint32_t col);
/**
* This returns an Ipv6 address at the node specified by
* the (row, col) address. Technically, a node will have
* multiple interfaces in the grid; therefore, it also has
* multiple Ipv6 addresses. This method only returns one of
* the addresses. If you picture the grid, the address returned
* is the left row device of all the nodes, except the left-most
* grid nodes, which returns the right row device.
*
* \param row the row address of the node desired
*
* \param col the column address of the node desired
*
* \returns Ipv6Address of one of the interfaces of the node
* specified by the (row, col) address
*/
Ipv6Address GetIpv6Address (uint32_t row, uint32_t col);
/**
* \param stack an InternetStackHelper which is used to install
* on every node in the grid
@@ -101,6 +121,15 @@ public:
*/
void AssignIpv4Addresses (Ipv4AddressHelper rowIp, Ipv4AddressHelper colIp);
/**
* Assigns Ipv6 addresses to all the row and column interfaces
*
* \param network an IPv6 address representing the network portion
* of the IPv6 Address
* \param prefix the prefix length
*/
void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
/**
* Sets up the node canvas locations for every node in the grid.
* This is needed for use with the animation interface
@@ -119,6 +148,8 @@ private:
std::vector<NetDeviceContainer> m_colDevices;
std::vector<Ipv4InterfaceContainer> m_rowInterfaces;
std::vector<Ipv4InterfaceContainer> m_colInterfaces;
std::vector<Ipv6InterfaceContainer> m_rowInterfaces6;
std::vector<Ipv6InterfaceContainer> m_colInterfaces6;
std::vector<NodeContainer> m_nodes;
};

View File

@@ -25,6 +25,7 @@
#include "ns3/node-list.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/vector.h"
#include "ns3/ipv6-address-generator.h"
NS_LOG_COMPONENT_DEFINE ("PointToPointStarHelper");
@@ -72,6 +73,18 @@ PointToPointStarHelper::GetSpokeIpv4Address (uint32_t i) const
return m_spokeInterfaces.GetAddress (i);
}
Ipv6Address
PointToPointStarHelper::GetHubIpv6Address (uint32_t i) const
{
return m_hubInterfaces6.GetAddress (i, 1);
}
Ipv6Address
PointToPointStarHelper::GetSpokeIpv6Address (uint32_t i) const
{
return m_spokeInterfaces6.GetAddress (i, 1);
}
uint32_t
PointToPointStarHelper::SpokeCount () const
{
@@ -96,6 +109,27 @@ PointToPointStarHelper::AssignIpv4Addresses (Ipv4AddressHelper address)
}
}
void
PointToPointStarHelper::AssignIpv6Addresses (Ipv6Address addrBase, Ipv6Prefix prefix)
{
Ipv6AddressGenerator::Init (addrBase, prefix);
Ipv6Address v6network;
Ipv6AddressHelper addressHelper;
for (uint32_t i = 0; i < m_spokes.GetN (); ++i)
{
v6network = Ipv6AddressGenerator::GetNetwork (prefix);
addressHelper.NewNetwork(v6network, prefix);
Ipv6InterfaceContainer ic = addressHelper.Assign (m_hubDevices.Get (i));
m_hubInterfaces6.Add (ic);
ic = addressHelper.Assign (m_spokeDevices.Get (i));
m_spokeInterfaces6.Add (ic);
Ipv6AddressGenerator::NextNetwork (prefix);
}
}
void
PointToPointStarHelper::BoundingBox (double ulx, double uly,
double lrx, double lry)

View File

@@ -23,8 +23,10 @@
#include "point-to-point-helper.h"
#include "ipv4-address-helper.h"
#include "ipv6-address-helper.h"
#include "internet-stack-helper.h"
#include "ipv4-interface-container.h"
#include "ipv6-interface-container.h"
namespace ns3 {
@@ -86,6 +88,20 @@ public:
*/
Ipv4Address GetSpokeIpv4Address (uint32_t i) const;
/**
* \param i index into the hub interfaces
*
* \returns Ipv6Address according to indexed hub interface
*/
Ipv6Address GetHubIpv6Address (uint32_t i) const;
/**
* \param i index into the spoke interfaces
*
* \returns Ipv6Address according to indexed spoke interface
*/
Ipv6Address GetSpokeIpv6Address (uint32_t i) const;
/**
* \returns the total number of spokes in the star
*/
@@ -104,6 +120,13 @@ public:
*/
void AssignIpv4Addresses (Ipv4AddressHelper address);
/**
* \param network an IPv6 address representing the network portion
* of the IPv6 Address
* \param prefix the prefix length
*/
void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
/**
* Sets up the node canvas locations for every node in the star.
* This is needed for use with the animation interface
@@ -122,6 +145,8 @@ private:
NetDeviceContainer m_spokeDevices;
Ipv4InterfaceContainer m_hubInterfaces;
Ipv4InterfaceContainer m_spokeInterfaces;
Ipv6InterfaceContainer m_hubInterfaces6;
Ipv6InterfaceContainer m_spokeInterfaces6;
};
} // namespace ns3