Add support for IPv6 transport protocols
This commit is contained in:
68
CHANGES.html
68
CHANGES.html
@@ -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>
|
||||
|
||||
@@ -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
|
||||
----------
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ private:
|
||||
|
||||
uint16_t m_port;
|
||||
Ptr<Socket> m_socket;
|
||||
Ptr<Socket> m_socket6;
|
||||
Address m_local;
|
||||
};
|
||||
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/>`_.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -122,6 +122,11 @@ int Ipv6RawSocketImpl::Bind ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Ipv6RawSocketImpl::Bind6 ()
|
||||
{
|
||||
return(Bind());
|
||||
}
|
||||
|
||||
int Ipv6RawSocketImpl::GetSockName (Address& address) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
@@ -116,6 +116,7 @@ public:
|
||||
* \return 0 if success, -1 otherwise
|
||||
*/
|
||||
virtual int Bind ();
|
||||
virtual int Bind6 ();
|
||||
|
||||
/**
|
||||
* \brief Get socket address.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ());
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
312
src/internet/test/ipv6-dual-stack-test-suite.cc
Normal file
312
src/internet/test/ipv6-dual-stack-test-suite.cc
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -112,6 +112,12 @@ PacketSocket::Bind (void)
|
||||
return DoBind (address);
|
||||
}
|
||||
|
||||
int
|
||||
PacketSocket::Bind6 (void)
|
||||
{
|
||||
return(Bind());
|
||||
}
|
||||
|
||||
int
|
||||
PacketSocket::Bind (const Address &address)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user