--- a/doc/modules Wed Jun 11 16:19:28 2008 -0700
+++ b/doc/modules Wed Jun 11 16:20:04 2008 -0700
@@ -42,13 +42,12 @@
*
* @defgroup devices Devices
*
- * @defgroup internetNode InternetNode
+ * @defgroup internetStack InternetStack
*
- * The "internet-node" module contains a set of classes which implement the
- * APIs defined in the "node" module:
- * - an Ipv4/Udp stack with socket support
+ * The "internet-stack" module contains:
+ * - an Ipv4 stack
* - an ARP module
- * - an InternetNode class which is a Node subclass.
+ * - a UDP and a TCP implementation
*
* @defgroup helper Helpers
*
--- a/doc/tutorial/introduction.texi Wed Jun 11 16:19:28 2008 -0700
+++ b/doc/tutorial/introduction.texi Wed Jun 11 16:20:04 2008 -0700
@@ -1272,14 +1272,14 @@
@verbatim
#include "ns3/ptr.h"
- #include "ns3/internet-node.h"
+ #include "ns3/internet-stack.h"
@end verbatim
@cindex include files
The ns-3 build system places the core include files it needs into a
directory called @code{ns-3} and so whenever you need to include one of the
core files you need to explicitly code this. The file @code{ptr.h} defines
-the generic smart pointer that we use. The file @code{internet-node.h}
+the generic smart pointer that we use. The file @code{internet-stack.h}
defines the class InternetNode which, as described above, represents an IP
version 4-based computing element in the simulator.
@@ -1455,7 +1455,7 @@
@verbatim
#include "ns3/log.h"
#include "ns3/ptr.h"
- #include "ns3/internet-node.h"
+ #include "ns3/internet-stack.h"
#include "ns3/csma-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/csma-net-device.h"
@@ -1632,7 +1632,7 @@
@verbatim
#include "ns3/log.h"
#include "ns3/ptr.h"
- #include "ns3/internet-node.h"
+ #include "ns3/internet-stack.h"
#include "ns3/csma-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/csma-net-device.h"
@@ -1883,7 +1883,7 @@
@verbatim
#include "ns3/log.h"
#include "ns3/ptr.h"
- #include "ns3/internet-node.h"
+ #include "ns3/internet-stack.h"
#include "ns3/csma-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/csma-net-device.h"
--- a/doc/tutorial/other.texi Wed Jun 11 16:19:28 2008 -0700
+++ b/doc/tutorial/other.texi Wed Jun 11 16:20:04 2008 -0700
@@ -103,7 +103,7 @@
#include "ns3/log.h"
#include "ns3/ptr.h"
-#include "ns3/internet-node.h"
+#include "ns3/internet-stack.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/point-to-point-net-device.h"
@@ -313,7 +313,7 @@
#include "ns3/log.h"
#include "ns3/ptr.h"
-#include "ns3/internet-node.h"
+#include "ns3/internet-stack.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/point-to-point-net-device.h"
@@ -1846,7 +1846,7 @@
call @code{GetObject} on the resulting smart pointer. Well, I'm afraid that's
not entirely true. It's slightly more complicated.
-Take a look at @code{src/internet-node/internet-node.h} and find the class
+Take a look at @code{src/internet-stack/internet-stack.h} and find the class
declaration for @code{InternetNode}.
@verbatim
@@ -1956,7 +1956,7 @@
methods specified in the @code{Ipv4} class to access the @code{Ipv4 Object}
methods which are, in turn, implemented in the @code{Ipv4Impl} object.
-If you now look in the file, @code{src/internet-node/internet-node.cc} you
+If you now look in the file, @code{src/internet-stack/internet-stack.cc} you
will see the following code in @code{InternetNode::Construct} that creates the
@code{Ipv4} Interface and aggregates it.
@@ -2013,7 +2013,7 @@
In the case of @code{Ipv4Impl}, you know that the class inherits somehow
from @code{Object} since there is a call to @code{AggregateObject} that
refers to an instance of an @code{Ipv4Impl}. You will have to go to
-the header file @code{src/internet-node/ipv4-impl.h} and find that
+the header file @code{src/internet-stack/ipv4-impl.h} and find that
@code{Ipv4Impl} inherits from class @code{Ipv4}. You will then have go to
the file @code{src/node/ipv4.h} and see that it inherits from @code{Object} and
defines a @code{GetTypeId}. Thus the @code{Object} for which you can
--- a/doc/tutorial/routing.texi Wed Jun 11 16:19:28 2008 -0700
+++ b/doc/tutorial/routing.texi Wed Jun 11 16:20:04 2008 -0700
@@ -2,7 +2,7 @@
@chapter ns-3 routing overview
This chapter describes the overall design of routing in the
-@code{src/internet-node}
+@code{src/internet-stack}
module, and some details about the routing approachs currently
implemented.
@@ -97,7 +97,7 @@
void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
int16_t priority);
@end verbatim
-This method is implemented by class Ipv4L3Protocol in the internet-node
+This method is implemented by class Ipv4L3Protocol in the internet-stack
module.
The priority variable above governs the priority in which the routing
@@ -174,7 +174,7 @@
@node Static routing
@section Static routing
-The internet-node module provides one routing protocol (Ipv4StaticRouting)
+The internet-stack module provides one routing protocol (Ipv4StaticRouting)
by default. This routing protocol allows one to add unicast or multicast
static routes to a node.
@@ -193,7 +193,7 @@
@uref{http://www.nsnam.org/doxygen/index.html,,Doxygen} documentation
provides full documentation of these methods. These methods are forwarding
functions to the actual implementation in Ipv4StaticRouting, when using
-the internet-node module.
+the internet-stack module.
@node Multicast routing
@section Multicast routing
--- a/examples/csma-broadcast.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/csma-broadcast.cc Wed Jun 11 16:20:04 2008 -0700
@@ -69,7 +69,7 @@
NS_LOG_INFO ("Build Topology.");
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", DataRateValue (DataRate(5000000)));
+ csma.SetChannelParameter ("DataRate", DataRateValue (DataRate(5000000)));
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds(2)));
NetDeviceContainer n0 = csma.Install (c0);
--- a/examples/csma-multicast.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/csma-multicast.cc Wed Jun 11 16:20:04 2008 -0700
@@ -75,7 +75,7 @@
NS_LOG_INFO ("Build Topology.");
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", DataRateValue (DataRate (5000000)));
+ csma.SetChannelParameter ("DataRate", DataRateValue (DataRate (5000000)));
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
// We will use these NetDevice containers later, for IP addressing
--- a/examples/csma-one-subnet.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/csma-one-subnet.cc Wed Jun 11 16:20:04 2008 -0700
@@ -66,7 +66,7 @@
NS_LOG_INFO ("Build Topology");
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", DataRateValue (5000000));
+ csma.SetChannelParameter ("DataRate", DataRateValue (5000000));
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
//
// Now fill out the topology by creating the net devices required to connect
--- a/examples/csma-packet-socket.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/csma-packet-socket.cc Wed Jun 11 16:20:04 2008 -0700
@@ -67,8 +67,9 @@
// create the shared medium used by all csma devices.
NS_LOG_INFO ("Create channels.");
- Ptr<CsmaChannel> channel = CreateObject<CsmaChannel> ("BitRate", DataRateValue (DataRate(5000000)),
- "Delay", TimeValue (MilliSeconds(2)));
+ Ptr<CsmaChannel> channel = CreateObject<CsmaChannel> (
+ "DataRate", DataRateValue (DataRate(5000000)),
+ "Delay", TimeValue (MilliSeconds(2)));
// use a helper function to connect our nodes to the shared channel.
NS_LOG_INFO ("Build Topology.");
--- a/examples/mixed-global-routing.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/mixed-global-routing.cc Wed Jun 11 16:20:04 2008 -0700
@@ -83,7 +83,7 @@
// We create the channels first without any IP addressing information
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+ csma.SetChannelParameter ("DataRate", StringValue ("5Mbps"));
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
NetDeviceContainer d2345 = csma.Install (n2345);
--- a/examples/mixed-wireless.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/mixed-wireless.cc Wed Jun 11 16:20:04 2008 -0700
@@ -199,7 +199,8 @@
// collection.
//
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", DataRateValue (DataRate (5000000)));
+ csma.SetChannelParameter ("DataRate",
+ DataRateValue (DataRate (5000000)));
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
NetDeviceContainer lanDevices = csma.Install (lan);
//
--- a/examples/tcp-large-transfer.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/tcp-large-transfer.cc Wed Jun 11 16:20:04 2008 -0700
@@ -28,6 +28,10 @@
// "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
// Usage (e.g.): ./waf --run tcp-large-transfer
+//XXX this isn't working as described right now
+//it is just blasting away for 10 seconds, with no fixed amount of data
+//being sent
+
#include <ctype.h>
#include <iostream>
#include <fstream>
@@ -73,39 +77,9 @@
#endif
}
-void CloseConnection (Ptr<Socket> localSocket)
-{
- localSocket->Close ();
-}
-
-void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
- Ipv4Address servAddress,
- uint16_t servPort)
-{
- // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
- localSocket->Connect (InetSocketAddress (servAddress, servPort));//connect
- localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
- Callback<void, Ptr<Socket> > (),
- Callback<void, Ptr<Socket> > ());
- //we want to close as soon as the connection is established
- //the tcp state machine and outgoing buffer will assure that
- //all of the data is delivered
-
- // Perform series of 1040 byte writes (this is a multiple of 26 since
- // we want to detect data splicing in the output stream)
- uint32_t writeSize = 1040;
- uint8_t data[writeSize];
- while (nBytes > 0) {
- uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
- for(uint32_t i = 0; i < curSize; ++i)
- {
- char m = toascii (97 + i % 26);
- data[i] = m;
- }
- localSocket->Send (data, curSize);
- nBytes -= curSize;
- }
-}
+void CloseConnection (Ptr<Socket> localSocket);
+void StartFlow(Ptr<Socket>, uint32_t, Ipv4Address, uint16_t);
+void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
int main (int argc, char *argv[])
{
@@ -195,3 +169,47 @@
Simulator::Run ();
Simulator::Destroy ();
}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+ localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
+ Ipv4Address servAddress,
+ uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress (servAddress, servPort));//connect
+ localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+ Callback<void, Ptr<Socket> > (),
+ Callback<void, Ptr<Socket> > ());
+ //we want to close as soon as the connection is established
+ //the tcp state machine and outgoing buffer will assure that
+ //all of the data is delivered
+ localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
+ WriteUntilBufferFull (localSocket, nBytes);
+}
+
+void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t nBytes)
+{
+ // Perform series of 1040 byte writes (this is a multiple of 26 since
+ // we want to detect data splicing in the output stream)
+ uint32_t writeSize = 1040;
+ uint8_t data[writeSize];
+ while (nBytes > 0) {
+ uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
+ for(uint32_t i = 0; i < curSize; ++i)
+ {
+ char m = toascii (97 + i % 26);
+ data[i] = m;
+ }
+ uint32_t amountSent = localSocket->Send (data, curSize);
+ if(amountSent < curSize)
+ {
+ std::cout << "Socket blocking, returning" << std::endl;
+ return;
+ }
+ nBytes -= curSize;
+ }
+}
--- a/examples/udp-echo.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/udp-echo.cc Wed Jun 11 16:20:04 2008 -0700
@@ -87,7 +87,7 @@
// Explicitly create the channels required by the topology (shown above).
//
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", DataRateValue (DataRate(5000000)));
+ csma.SetChannelParameter ("DataRate", DataRateValue (DataRate(5000000)));
csma.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
NetDeviceContainer d = csma.Install (n);
--- a/examples/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/examples/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -3,51 +3,51 @@
def build(bld):
obj = bld.create_ns3_program('mixed-wireless',
- ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-node'])
+ ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-stack'])
obj.source = 'mixed-wireless.cc'
obj = bld.create_ns3_program('simple-global-routing',
- ['point-to-point', 'internet-node', 'global-routing'])
+ ['point-to-point', 'internet-stack', 'global-routing'])
obj.source = 'simple-global-routing.cc'
obj = bld.create_ns3_program('simple-alternate-routing',
- ['point-to-point', 'internet-node', 'global-routing'])
+ ['point-to-point', 'internet-stack', 'global-routing'])
obj.source = 'simple-alternate-routing.cc'
obj = bld.create_ns3_program('simple-error-model',
- ['point-to-point', 'internet-node'])
+ ['point-to-point', 'internet-stack'])
obj.source = 'simple-error-model.cc'
obj = bld.create_ns3_program('csma-one-subnet',
- ['csma', 'internet-node'])
+ ['csma', 'internet-stack'])
obj.source = 'csma-one-subnet.cc'
obj = bld.create_ns3_program('udp-echo',
- ['csma', 'internet-node'])
+ ['csma', 'internet-stack'])
obj.source = 'udp-echo.cc'
obj = bld.create_ns3_program('csma-broadcast',
- ['csma', 'internet-node'])
+ ['csma', 'internet-stack'])
obj.source = 'csma-broadcast.cc'
obj = bld.create_ns3_program('csma-packet-socket',
- ['csma', 'internet-node'])
+ ['csma', 'internet-stack'])
obj.source = 'csma-packet-socket.cc'
obj = bld.create_ns3_program('csma-multicast',
- ['csma', 'internet-node'])
+ ['csma', 'internet-stack'])
obj.source = 'csma-multicast.cc'
obj = bld.create_ns3_program( 'mixed-global-routing',
- ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
+ ['point-to-point', 'internet-stack', 'global-routing' , 'csma-cd'])
obj.source = 'mixed-global-routing.cc'
obj = bld.create_ns3_program('simple-point-to-point-olsr',
- ['point-to-point', 'internet-node', 'olsr'])
+ ['point-to-point', 'internet-stack', 'olsr'])
obj.source = 'simple-point-to-point-olsr.cc'
obj = bld.create_ns3_program('tcp-large-transfer',
- ['point-to-point', 'internet-node'])
+ ['point-to-point', 'internet-stack'])
obj.source = 'tcp-large-transfer.cc'
obj = bld.create_ns3_program('wifi-adhoc',
--- a/samples/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/samples/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -20,11 +20,11 @@
obj.source = 'main-test.cc'
obj = bld.create_ns3_program('main-simple',
- ['node', 'internet-node', 'onoff'])
+ ['node', 'internet-stack', 'onoff'])
obj.source = 'main-simple.cc'
obj = bld.create_ns3_program('main-grid-topology',
- ['core', 'simulator', 'mobility', 'internet-node'])
+ ['core', 'simulator', 'mobility', 'internet-stack'])
obj.source = 'main-grid-topology.cc'
obj = bld.create_ns3_program('main-random-topology',
--- a/src/applications/udp-echo/udp-echo-client.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/src/applications/udp-echo/udp-echo-client.cc Wed Jun 11 16:20:04 2008 -0700
@@ -37,19 +37,23 @@
static TypeId tid = TypeId ("ns3::UdpEchoClient")
.SetParent<Application> ()
.AddConstructor<UdpEchoClient> ()
- .AddAttribute ("MaxPackets", "XXX",
+ .AddAttribute ("MaxPackets",
+ "The maximum number of packets the application will send",
UintegerValue (100),
MakeUintegerAccessor (&UdpEchoClient::m_count),
MakeUintegerChecker<uint32_t> ())
- .AddAttribute ("Interval", "XXX",
+ .AddAttribute ("Interval",
+ "The time to wait between packets",
TimeValue (Seconds (1.0)),
MakeTimeAccessor (&UdpEchoClient::m_interval),
MakeTimeChecker ())
- .AddAttribute ("RemoteIpv4", "XXX",
+ .AddAttribute ("RemoteIpv4",
+ "The Ipv4Address of the outbound packets",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
MakeIpv4AddressChecker ())
- .AddAttribute ("RemotePort", "XXX",
+ .AddAttribute ("RemotePort",
+ "The destination port of the outbound packets",
UintegerValue (0),
MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
MakeUintegerChecker<uint16_t> ())
--- a/src/applications/udp-echo/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/src/applications/udp-echo/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
- module = bld.create_ns3_module('udp-echo', ['internet-node'])
+ module = bld.create_ns3_module('udp-echo', ['internet-stack'])
module.source = [
'udp-echo-client.cc',
'udp-echo-server.cc',
--- a/src/core/random-variable.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/src/core/random-variable.cc Wed Jun 11 16:20:04 2008 -0700
@@ -156,9 +156,8 @@
{
if (RandomVariableBase::globalSeedSet)
{
- cerr << "Random number generator already initialized!" << endl;
- cerr << "Call to RandomVariableBase::UseGlobalSeed() ignored" << endl;
- return;
+ NS_FATAL_ERROR ("Random number generator already initialized! "
+ "Call to RandomVariableBase::UseGlobalSeed() ignored");
}
RandomVariableBase::globalSeed[0] = s0;
RandomVariableBase::globalSeed[1] = s1;
--- a/src/devices/csma/csma-channel.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/csma/csma-channel.cc Wed Jun 11 16:20:04 2008 -0700
@@ -30,29 +30,15 @@
NS_OBJECT_ENSURE_REGISTERED (CsmaChannel);
-CsmaDeviceRec::CsmaDeviceRec()
-{
- active = false;
-}
-
-CsmaDeviceRec::CsmaDeviceRec(Ptr<CsmaNetDevice> device)
-{
- devicePtr = device;
- active = true;
-}
-
-bool
-CsmaDeviceRec::IsActive() {
- return active;
-}
-
-TypeId
+ TypeId
CsmaChannel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CsmaChannel")
.SetParent<Channel> ()
.AddConstructor<CsmaChannel> ()
- .AddAttribute ("BitRate", "The maximum bitrate of the channel",
+ .AddAttribute ("DataRate",
+ "The transmission data rate to be provided to devices "
+ "connected to the channel",
DataRateValue (DataRate (0xffffffff)),
MakeDataRateAccessor (&CsmaChannel::m_bps),
MakeDataRateChecker ())
@@ -64,10 +50,7 @@
return tid;
}
-//
-// By default, you get a channel with the name "Csma Channel" that
-// has an "infitely" fast transmission speed and zero delay.
-CsmaChannel::CsmaChannel()
+CsmaChannel::CsmaChannel ()
:
Channel ("Csma Channel")
{
@@ -76,26 +59,26 @@
m_deviceList.clear();
}
-int32_t
-CsmaChannel::Attach(Ptr<CsmaNetDevice> device)
+ int32_t
+CsmaChannel::Attach (Ptr<CsmaNetDevice> device)
{
NS_LOG_FUNCTION (this << device);
- NS_ASSERT(device != 0);
+ NS_ASSERT (device != 0);
- CsmaDeviceRec rec(device);
+ CsmaDeviceRec rec (device);
- m_deviceList.push_back(rec);
- return (m_deviceList.size() - 1);
+ m_deviceList.push_back (rec);
+ return (m_deviceList.size () - 1);
}
-bool
-CsmaChannel::Reattach(Ptr<CsmaNetDevice> device)
+ bool
+CsmaChannel::Reattach (Ptr<CsmaNetDevice> device)
{
NS_LOG_FUNCTION (this << device);
- NS_ASSERT(device != 0);
+ NS_ASSERT (device != 0);
std::vector<CsmaDeviceRec>::iterator it;
- for (it = m_deviceList.begin(); it < m_deviceList.end(); it++)
+ for (it = m_deviceList.begin (); it < m_deviceList.end( ); it++)
{
if (it->devicePtr == device)
{
@@ -113,12 +96,12 @@
return false;
}
-bool
-CsmaChannel::Reattach(uint32_t deviceId)
+ bool
+CsmaChannel::Reattach (uint32_t deviceId)
{
NS_LOG_FUNCTION (this << deviceId);
- if (deviceId < m_deviceList.size())
+ if (deviceId < m_deviceList.size ())
{
return false;
}
@@ -134,26 +117,25 @@
}
}
-bool
-CsmaChannel::Detach(uint32_t deviceId)
+ bool
+CsmaChannel::Detach (uint32_t deviceId)
{
NS_LOG_FUNCTION (this << deviceId);
- if (deviceId < m_deviceList.size())
+ if (deviceId < m_deviceList.size ())
{
if (!m_deviceList[deviceId].active)
{
- NS_LOG_WARN ("CsmaChannel::Detach Device is already detached (" <<
- deviceId << ")");
+ NS_LOG_WARN ("CsmaChannel::Detach(): "
+ "Device is already detached (" << deviceId << ")");
return false;
}
m_deviceList[deviceId].active = false;
if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId))
{
- NS_LOG_WARN ("CsmaChannel::Detach Device is currently" <<
+ NS_LOG_WARN ("CsmaChannel::Detach(): Device is currently" <<
"transmitting (" << deviceId << ")");
- // Here we will need to place a warning in the packet
}
return true;
@@ -164,14 +146,14 @@
}
}
-bool
-CsmaChannel::Detach(Ptr<CsmaNetDevice> device)
+ bool
+CsmaChannel::Detach (Ptr<CsmaNetDevice> device)
{
NS_LOG_FUNCTION (this << device);
- NS_ASSERT(device != 0);
+ NS_ASSERT (device != 0);
std::vector<CsmaDeviceRec>::iterator it;
- for (it = m_deviceList.begin(); it < m_deviceList.end(); it++)
+ for (it = m_deviceList.begin (); it < m_deviceList.end (); it++)
{
if ((it->devicePtr == device) && (it->active))
{
@@ -182,21 +164,22 @@
return false;
}
-bool
-CsmaChannel::TransmitStart(Ptr<Packet> p, uint32_t srcId)
+ bool
+CsmaChannel::TransmitStart (Ptr<Packet> p, uint32_t srcId)
{
NS_LOG_FUNCTION (this << p << srcId);
NS_LOG_INFO ("UID is " << p->GetUid () << ")");
if (m_state != IDLE)
{
- NS_LOG_WARN ("state is not IDLE");
+ NS_LOG_WARN ("CsmaChannel::TransmitStart(): State is not IDLE");
return false;
}
if (!IsActive(srcId))
{
- NS_LOG_ERROR ("Seclected source is not currently attached to network");
+ NS_LOG_ERROR ("CsmaChannel::TransmitStart(): "
+ "Seclected source is not currently attached to network");
return false;
}
@@ -207,51 +190,51 @@
return true;
}
-bool
+ bool
CsmaChannel::IsActive(uint32_t deviceId)
{
- return (m_deviceList[deviceId].active);
+ return (m_deviceList[deviceId].active);
}
-bool
+ bool
CsmaChannel::TransmitEnd()
{
NS_LOG_FUNCTION (this << m_currentPkt << m_currentSrc);
NS_LOG_INFO ("UID is " << m_currentPkt->GetUid () << ")");
- NS_ASSERT(m_state == TRANSMITTING);
+ NS_ASSERT (m_state == TRANSMITTING);
m_state = PROPAGATING;
bool retVal = true;
- if (!IsActive(m_currentSrc)) {
- NS_LOG_ERROR ("Seclected source was detached before the end of the"
- "transmission");
- retVal = false;
- }
+ if (!IsActive (m_currentSrc))
+ {
+ NS_LOG_ERROR ("CsmaChannel::TransmitEnd(): "
+ "Seclected source was detached before the end of the transmission");
+ retVal = false;
+ }
NS_LOG_LOGIC ("Schedule event in " << m_delay.GetSeconds () << " sec");
- Simulator::Schedule (m_delay,
- &CsmaChannel::PropagationCompleteEvent,
- this);
+ Simulator::Schedule (m_delay, &CsmaChannel::PropagationCompleteEvent,
+ this);
return retVal;
}
-void
+ void
CsmaChannel::PropagationCompleteEvent()
{
NS_LOG_FUNCTION (this << m_currentPkt);
NS_LOG_INFO ("UID is " << m_currentPkt->GetUid () << ")");
- NS_ASSERT(m_state == PROPAGATING);
+ NS_ASSERT (m_state == PROPAGATING);
NS_LOG_LOGIC ("Receive");
std::vector<CsmaDeviceRec>::iterator it;
- for (it = m_deviceList.begin(); it < m_deviceList.end(); it++)
+ for (it = m_deviceList.begin (); it < m_deviceList.end(); it++)
{
- if (it->IsActive())
+ if (it->IsActive ())
{
it->devicePtr->Receive (m_currentPkt->Copy ());
}
@@ -259,13 +242,12 @@
m_state = IDLE;
}
-
-uint32_t
+ uint32_t
CsmaChannel::GetNumActDevices (void)
{
int numActDevices = 0;
std::vector<CsmaDeviceRec>::iterator it;
- for (it = m_deviceList.begin(); it < m_deviceList.end(); it++)
+ for (it = m_deviceList.begin (); it < m_deviceList.end (); it++)
{
if (it->active)
{
@@ -275,29 +257,29 @@
return numActDevices;
}
+//
// This is not the number of active devices. This is the total number
// of devices even if some were detached after.
-uint32_t
+//
+ uint32_t
CsmaChannel::GetNDevices (void) const
{
- return (m_deviceList.size());
+ return (m_deviceList.size ());
}
-Ptr<CsmaNetDevice>
+ Ptr<CsmaNetDevice>
CsmaChannel::GetCsmaDevice (uint32_t i) const
{
- Ptr< CsmaNetDevice > netDevice;
-
- netDevice = m_deviceList[i].devicePtr;
+ Ptr<CsmaNetDevice> netDevice = m_deviceList[i].devicePtr;
return netDevice;
}
-int32_t
+ int32_t
CsmaChannel::GetDeviceNum (Ptr<CsmaNetDevice> device)
{
std::vector<CsmaDeviceRec>::iterator it;
int i = 0;
- for (it = m_deviceList.begin(); it < m_deviceList.end(); it++)
+ for (it = m_deviceList.begin (); it < m_deviceList.end (); it++)
{
if (it->devicePtr == device)
{
@@ -315,7 +297,7 @@
return -1;
}
-bool
+ bool
CsmaChannel::IsBusy (void)
{
if (m_state == IDLE)
@@ -328,28 +310,45 @@
}
}
-DataRate
+ DataRate
CsmaChannel::GetDataRate (void)
{
return m_bps;
}
-Time
+ Time
CsmaChannel::GetDelay (void)
{
return m_delay;
}
-WireState
-CsmaChannel::GetState(void)
+ WireState
+CsmaChannel::GetState (void)
{
return m_state;
}
-Ptr<NetDevice>
+ Ptr<NetDevice>
CsmaChannel::GetDevice (uint32_t i) const
{
return GetCsmaDevice (i);
}
+CsmaDeviceRec::CsmaDeviceRec ()
+{
+ active = false;
+}
+
+CsmaDeviceRec::CsmaDeviceRec (Ptr<CsmaNetDevice> device)
+{
+ devicePtr = device;
+ active = true;
+}
+
+ bool
+CsmaDeviceRec::IsActive ()
+{
+ return active;
+}
+
} // namespace ns3
--- a/src/devices/csma/csma-channel.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/csma/csma-channel.h Wed Jun 11 16:20:04 2008 -0700
@@ -73,27 +73,14 @@
* flag to indicate if the channel is currently in use. It does not
* take into account the distances between stations or the speed of
* light to determine collisions.
- *
- * Each net device must query the state of the channel and make sure
- * that it is IDLE before writing a packet to the channel.
- *
- * When the channel is instaniated, the constructor takes parameters
- * for a single speed, in bits per second, and a speed-of-light delay
- * time as a Time object. When a net device is attached to a channel,
- * it is assigned a device ID, this is in order to facilitate the
- * check that makes sure that a net device that is trying to send a
- * packet to the channel is really connected to this channel
- *
*/
class CsmaChannel : public Channel
{
public:
static TypeId GetTypeId (void);
+
/**
* \brief Create a CsmaChannel
- *
- * By default, you get a channel with the name "Csma Channel" that
- * has an "infitely" fast transmission speed and zero delay.
*/
CsmaChannel ();
@@ -104,6 +91,7 @@
* \return The assigned device number
*/
int32_t Attach (Ptr<CsmaNetDevice> device);
+
/**
* \brief Detach a given netdevice from this channel
*
@@ -116,6 +104,7 @@
* can't be found.
*/
bool Detach (Ptr<CsmaNetDevice> device);
+
/**
* \brief Detach a given netdevice from this channel
*
@@ -129,6 +118,7 @@
* can't be found.
*/
bool Detach (uint32_t deviceId);
+
/**
* \brief Reattach a previously detached net device to the channel
*
@@ -143,6 +133,7 @@
* channel or can't be found.
*/
bool Reattach(uint32_t deviceId);
+
/**
* \brief Reattach a previously detached net device to the channel
*
@@ -156,6 +147,7 @@
* channel or can't be found.
*/
bool Reattach(Ptr<CsmaNetDevice> device);
+
/**
* \brief Start transmitting a packet over the channel
*
@@ -171,6 +163,7 @@
* device is currently active.
*/
bool TransmitStart (Ptr<Packet> p, uint32_t srcId);
+
/**
* \brief Indicates that the net device has finished transmitting
* the packet over the channel
@@ -186,6 +179,7 @@
* completed its transmission.
*/
bool TransmitEnd ();
+
/**
* \brief Indicates that the channel has finished propagating the
* current packet. The channel is released and becomes free.
@@ -193,7 +187,8 @@
* Calls the receive function of every active net device that is
* attached to the channel.
*/
- void PropagationCompleteEvent();
+ void PropagationCompleteEvent ();
+
/**
* \return Returns the device number assigned to a net device by the
* channel
@@ -202,11 +197,12 @@
* number is needed
*/
int32_t GetDeviceNum (Ptr<CsmaNetDevice> device);
+
/**
* \return Returns the state of the channel (IDLE -- free,
* TRANSMITTING -- busy, PROPAGATING - busy )
*/
- WireState GetState();
+ WireState GetState ();
/**
* \brief Indicates if the channel is busy. The channel will only
@@ -215,7 +211,7 @@
* \return Returns true if the channel is busy and false if it is
* free.
*/
- bool IsBusy();
+ bool IsBusy ();
/**
* \brief Indicates if a net device is currently attached or
@@ -226,19 +222,32 @@
* \return Returns true if the net device is attached to the
* channel, false otherwise.
*/
- bool IsActive(uint32_t deviceId);
+ bool IsActive (uint32_t deviceId);
+
/**
* \return Returns the number of net devices that are currently
* attached to the channel.
*/
uint32_t GetNumActDevices (void);
+
/**
* \return Returns the total number of devices including devices
* that have been detached from the channel.
*/
virtual uint32_t GetNDevices (void) const;
+
+ /**
+ * \return Get a NetDevice pointer to a connected network device.
+ *
+ * \param i The index of the net device.
+ * \return Returns the pointer to the net device that is associated
+ * with deviceId i.
+ */
virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
/**
+ * \return Get a CsmaNetDevice pointer to a connected network device.
+ *
* \param i The deviceId of the net device for which we want the
* pointer.
* \return Returns the pointer to the net device that is associated
@@ -246,13 +255,32 @@
*/
Ptr<CsmaNetDevice> GetCsmaDevice (uint32_t i) const;
+ /**
+ * Get the assigned data rate of the channel
+ *
+ * \return Returns the DataRate to be used by device transmitters.
+ * with deviceId i.
+ */
virtual DataRate GetDataRate (void);
+
+ /**
+ * Get the assigned speed-of-light delay of the channel
+ *
+ * \return Returns the delay used by the channel.
+ */
virtual Time GetDelay (void);
private:
- DataRate m_bps; /// Data rate of the channel
- Time m_delay; /// Delay of the channel.
+ /**
+ * The assigned data rate of the channel
+ */
+ DataRate m_bps;
+
+ /**
+ * The assigned speed-of-light delay of the channel
+ */
+ Time m_delay;
/**
* List of the net devices that have been or are currently connected
@@ -265,19 +293,22 @@
* whole list does not have to be searched when making sure that a
* source is attached to a channel when it is transmitting data.
*/
- std::vector< CsmaDeviceRec > m_deviceList;
+ std::vector<CsmaDeviceRec> m_deviceList;
+
/**
- * Packet that is currently being transmitted on the channel (or last
+ * The Packet that is currently being transmitted on the channel (or last
* packet to have been transmitted on the channel if the channel is
* free.)
*/
- Ptr<Packet> m_currentPkt;
+ Ptr<Packet> m_currentPkt;
+
/**
* Device Id of the source that is currently transmitting on the
* channel. Or last source to have transmitted a packet on the
* channel, if the channel is currently not busy.
*/
uint32_t m_currentSrc;
+
/**
* Current state of the channel
*/
--- a/src/devices/csma/csma-net-device.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/csma/csma-net-device.cc Wed Jun 11 16:20:04 2008 -0700
@@ -32,7 +32,6 @@
#include "csma-net-device.h"
#include "csma-channel.h"
-
NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
namespace ns3 {
@@ -45,40 +44,44 @@
static TypeId tid = TypeId ("ns3::CsmaNetDevice")
.SetParent<NetDevice> ()
.AddConstructor<CsmaNetDevice> ()
- .AddAttribute ("Address", "The address of this device.",
+ .AddAttribute ("Address",
+ "The address of this device.",
Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
MakeMac48AddressAccessor (&CsmaNetDevice::m_address),
MakeMac48AddressChecker ())
- .AddAttribute ("EncapsulationMode", "The mode of link-layer encapsulation to use.",
+ .AddAttribute ("EncapsulationMode",
+ "The link-layer encapsulation type to use.",
EnumValue (LLC),
MakeEnumAccessor (&CsmaNetDevice::m_encapMode),
MakeEnumChecker (ETHERNET_V1, "EthernetV1",
IP_ARP, "IpArp",
RAW, "Raw",
LLC, "Llc"))
- .AddAttribute ("SendEnable", "should tx be enabled ?",
+ .AddAttribute ("SendEnable",
+ "Enable or disable the transmitter section of the device.",
BooleanValue (true),
MakeBooleanAccessor (&CsmaNetDevice::m_sendEnable),
MakeBooleanChecker ())
- .AddAttribute ("ReceiveEnable", "should rx be enabled ?",
+ .AddAttribute ("ReceiveEnable",
+ "Enable or disable the receiver section of the device.",
BooleanValue (true),
MakeBooleanAccessor (&CsmaNetDevice::m_receiveEnable),
MakeBooleanChecker ())
- .AddAttribute ("DataRate", "XXX",
- DataRateValue (DataRate (0xffffffff)),
- MakeDataRateAccessor (&CsmaNetDevice::m_bps),
- MakeDataRateChecker ())
- .AddAttribute ("RxErrorModel", "XXX",
+ .AddAttribute ("RxErrorModel",
+ "The receiver error model used to simulate packet loss",
PointerValue (),
MakePointerAccessor (&CsmaNetDevice::m_receiveErrorModel),
MakePointerChecker<ErrorModel> ())
- .AddAttribute ("TxQueue", "XXX",
+ .AddAttribute ("TxQueue",
+ "A queue to use as the transmit queue in the device.",
PointerValue (),
MakePointerAccessor (&CsmaNetDevice::m_queue),
MakePointerChecker<Queue> ())
- .AddTraceSource ("Rx", "Receive MAC packet.",
+ .AddTraceSource ("Rx",
+ "Trace source to fire on reception of a MAC packet.",
MakeTraceSourceAccessor (&CsmaNetDevice::m_rxTrace))
- .AddTraceSource ("Drop", "Drop MAC packet.",
+ .AddTraceSource ("Drop",
+ "Trace source to fire on when a MAC packet is dropped.",
MakeTraceSourceAccessor (&CsmaNetDevice::m_dropTrace))
;
return tid;
@@ -91,7 +94,7 @@
{
NS_LOG_FUNCTION (this);
m_txMachineState = READY;
- m_tInterframeGap = Seconds(0);
+ m_tInterframeGap = Seconds (0);
m_channel = 0;
}
@@ -101,7 +104,7 @@
m_queue = 0;
}
-void
+ void
CsmaNetDevice::DoDispose ()
{
NS_LOG_FUNCTION_NOARGS ();
@@ -110,61 +113,54 @@
NetDevice::DoDispose ();
}
-void
+ void
CsmaNetDevice::SetAddress (Mac48Address self)
{
m_address = self;
}
-void
+ void
CsmaNetDevice::SetSendEnable (bool sendEnable)
{
NS_LOG_FUNCTION_NOARGS ();
m_sendEnable = sendEnable;
}
-void
+ void
CsmaNetDevice::SetReceiveEnable (bool receiveEnable)
{
NS_LOG_FUNCTION_NOARGS ();
m_receiveEnable = receiveEnable;
}
-bool
+ bool
CsmaNetDevice::IsSendEnabled (void)
{
NS_LOG_FUNCTION_NOARGS ();
return (m_sendEnable);
}
-bool
+ bool
CsmaNetDevice::IsReceiveEnabled (void)
{
NS_LOG_FUNCTION_NOARGS ();
return (m_receiveEnable);
}
-void
-CsmaNetDevice::SetDataRate (DataRate bps)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (!m_channel || bps <= m_channel->GetDataRate ())
- {
- m_bps = bps;
- }
-}
-
-void
+ void
CsmaNetDevice::SetInterframeGap (Time t)
{
NS_LOG_FUNCTION_NOARGS ();
m_tInterframeGap = t;
}
-void
-CsmaNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots,
- uint32_t maxSlots, uint32_t ceiling,
- uint32_t maxRetries)
+ void
+CsmaNetDevice::SetBackoffParams (
+ Time slotTime,
+ uint32_t minSlots,
+ uint32_t maxSlots,
+ uint32_t ceiling,
+ uint32_t maxRetries)
{
NS_LOG_FUNCTION_NOARGS ();
m_backoff.m_slotTime = slotTime;
@@ -174,32 +170,39 @@
m_backoff.m_maxRetries = maxRetries;
}
-void
-CsmaNetDevice::AddHeader (Ptr<Packet> p, Mac48Address dest,
- uint16_t protocolNumber)
+ void
+CsmaNetDevice::AddHeader (
+ Ptr<Packet> p,
+ Mac48Address dest,
+ uint16_t protocolNumber)
{
NS_LOG_FUNCTION_NOARGS ();
+
if (m_encapMode == RAW)
{
return;
}
- EthernetHeader header (false);
- EthernetTrailer trailer;
+
Mac48Address source = Mac48Address::ConvertFrom (GetAddress ());
- header.SetSource(source);
- header.SetDestination(dest);
+ EthernetHeader header (false);
+ header.SetSource (source);
+ header.SetDestination (dest);
+
+ EthernetTrailer trailer;
uint16_t lengthType = 0;
switch (m_encapMode)
{
case ETHERNET_V1:
- lengthType = p->GetSize() + header.GetSerializedSize() + trailer.GetSerializedSize();
+ lengthType = p->GetSize () + header.GetSerializedSize () +
+ trailer.GetSerializedSize ();
break;
case IP_ARP:
lengthType = protocolNumber;
break;
case LLC: {
- lengthType = p->GetSize() + header.GetSerializedSize() + trailer.GetSerializedSize();
+ lengthType = p->GetSize () + header.GetSerializedSize () +
+ trailer.GetSerializedSize ();
LlcSnapHeader llc;
llc.SetType (protocolNumber);
p->AddHeader (llc);
@@ -208,13 +211,15 @@
NS_ASSERT (false);
break;
}
+
header.SetLengthType (lengthType);
- p->AddHeader(header);
- trailer.CalcFcs(p);
- p->AddTrailer(trailer);
+ p->AddHeader (header);
+
+ trailer.CalcFcs (p);
+ p->AddTrailer (trailer);
}
-bool
+ bool
CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -222,15 +227,17 @@
{
return true;
}
- EthernetHeader header (false);
+
EthernetTrailer trailer;
- p->RemoveTrailer(trailer);
- trailer.CheckFcs(p);
- p->RemoveHeader(header);
+ p->RemoveTrailer (trailer);
+ trailer.CheckFcs (p);
- if ((header.GetDestination() != GetBroadcast ()) &&
- (header.GetDestination() != GetAddress ()))
+ EthernetHeader header (false);
+ p->RemoveHeader (header);
+
+ if ((header.GetDestination () != GetBroadcast ()) &&
+ (header.GetDestination () != GetAddress ()))
{
return false;
}
@@ -239,7 +246,7 @@
{
case ETHERNET_V1:
case IP_ARP:
- param = header.GetLengthType();
+ param = header.GetLengthType ();
break;
case LLC: {
LlcSnapHeader llc;
@@ -253,7 +260,7 @@
return true;
}
-void
+ void
CsmaNetDevice::TransmitStart ()
{
NS_LOG_FUNCTION_NOARGS ();
@@ -265,47 +272,58 @@
// schedule an event that will be executed when it's time to tell the
// channel that we're done wiggling the wire.
//
- NS_ASSERT_MSG((m_txMachineState == READY) || (m_txMachineState == BACKOFF),
- "Must be READY to transmit. Tx state is: "
- << m_txMachineState);
+ NS_ASSERT_MSG ((m_txMachineState == READY) || (m_txMachineState == BACKOFF),
+ "Must be READY to transmit. Tx state is: " << m_txMachineState);
+
+//
+// Only transmit if send side of net device is enabled
+//
+ if (IsSendEnabled () == false)
+ {
+ return;
+ }
- // Only transmit if send side of net device is enabled
- if (!IsSendEnabled())
- return;
+ if (m_channel->GetState () != IDLE)
+ {
+//
+// The channel is busy -- backoff and rechedule TransmitStart ()
+//
+ m_txMachineState = BACKOFF;
- if (m_channel->GetState() != IDLE)
- { // Channel busy, backoff and rechedule TransmitStart()
- m_txMachineState = BACKOFF;
- if (m_backoff.MaxRetriesReached())
- { // Too many retries reached, abort transmission of packet
- TransmitAbort();
+ if (m_backoff.MaxRetriesReached ())
+ {
+//
+// Too many retries, abort transmission of packet
+//
+ TransmitAbort ();
}
else
{
- m_backoff.IncrNumRetries();
- Time backoffTime = m_backoff.GetBackoffTime();
+ m_backoff.IncrNumRetries ();
+ Time backoffTime = m_backoff.GetBackoffTime ();
NS_LOG_LOGIC ("Channel busy, backing off for " <<
backoffTime.GetSeconds () << " sec");
- Simulator::Schedule (backoffTime,
- &CsmaNetDevice::TransmitStart,
- this);
+ Simulator::Schedule (backoffTime, &CsmaNetDevice::TransmitStart,
+ this);
}
}
else
{
- // Channel is free, transmit packet
+//
+// The channel is free, transmit the packet
+//
m_txMachineState = BUSY;
- Time tEvent = Seconds (m_bps.CalculateTxTime(m_currentPkt->GetSize()));
+ Time tEvent = Seconds (m_bps.CalculateTxTime (m_currentPkt->GetSize ()));
NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " <<
tEvent.GetSeconds () << "sec");
- Simulator::Schedule (tEvent,
- &CsmaNetDevice::TransmitCompleteEvent,
- this);
- if (!m_channel->TransmitStart (m_currentPkt, m_deviceId))
+ Simulator::Schedule (tEvent, &CsmaNetDevice::TransmitCompleteEvent,
+ this);
+
+ if (m_channel->TransmitStart (m_currentPkt, m_deviceId) == false)
{
NS_LOG_WARN ("Channel transmit start did not work at " <<
tEvent.GetSeconds () << "sec");
@@ -313,28 +331,38 @@
}
else
{
- // Transmission success, reset backoff time parameters.
- m_backoff.ResetBackoffTime();
+//
+// Transmission succeeded, reset the backoff time parameters.
+//
+ m_backoff.ResetBackoffTime ();
}
}
}
-void
+ void
CsmaNetDevice::TransmitAbort (void)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
- // Try to transmit a new packet
+//
+// Since we were transmitting a packet, that packet had better be on the
+// transmit queue.
+//
m_currentPkt = m_queue->Dequeue ();
- NS_ASSERT_MSG(m_currentPkt != 0, "IsEmpty false but no Packet on queue?");
- m_backoff.ResetBackoffTime();
+ NS_ASSERT_MSG (m_currentPkt != 0, "No Packet on queue during"
+ "CsmaNetDevice::TransmitAbort()");
+
+//
+// The last one failed. Let's try to transmit the next one (if there)
+//
+ m_backoff.ResetBackoffTime ();
m_txMachineState = READY;
TransmitStart ();
}
-void
+ void
CsmaNetDevice::TransmitCompleteEvent (void)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -344,9 +372,8 @@
// schedule an event that will be executed when it's time to re-enable
// the transmitter after the interframe gap.
//
- NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
- // Channel should be transmitting
- NS_ASSERT(m_channel->GetState() == TRANSMITTING);
+ NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
+ NS_ASSERT (m_channel->GetState () == TRANSMITTING);
m_txMachineState = GAP;
NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
@@ -355,12 +382,11 @@
NS_LOG_LOGIC ("Schedule TransmitReadyEvent in "
<< m_tInterframeGap.GetSeconds () << "sec");
- Simulator::Schedule (m_tInterframeGap,
- &CsmaNetDevice::TransmitReadyEvent,
- this);
+ Simulator::Schedule (m_tInterframeGap, &CsmaNetDevice::TransmitReadyEvent,
+ this);
}
-void
+ void
CsmaNetDevice::TransmitReadyEvent (void)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -369,18 +395,19 @@
// gap has passed. If there are pending transmissions, we use this opportunity
// to start the next transmit.
//
- NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap");
+ NS_ASSERT_MSG (m_txMachineState == GAP, "Must be in interframe gap");
m_txMachineState = READY;
// Get the next packet from the queue for transmitting
- if (m_queue->IsEmpty())
+ if (m_queue->IsEmpty ())
{
return;
}
else
{
m_currentPkt = m_queue->Dequeue ();
- NS_ASSERT_MSG(m_currentPkt != 0, "IsEmpty false but no Packet on queue?");
+ NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitReadyEvent():"
+ " IsEmpty false but no Packet on queue?");
TransmitStart ();
}
}
@@ -392,47 +419,49 @@
m_channel = ch;
- m_deviceId = m_channel->Attach(this);
+ m_deviceId = m_channel->Attach (this);
+
+//
+// The channel provides us with the transmitter data rate.
+//
m_bps = m_channel->GetDataRate ();
- m_tInterframeGap = m_channel->GetDelay ();
- /*
- * For now, this device is up whenever a channel is attached to it.
- */
+//
+// We use the Ethernet interframe gap of 96 bit times.
+//
+ m_tInterframeGap = Seconds (m_bps.CalculateTxTime (96/8));
+
+//
+// This device is up whenever a channel is attached to it.
+//
NotifyLinkUp ();
return true;
}
-void
+ void
CsmaNetDevice::SetQueue (Ptr<Queue> q)
{
NS_LOG_FUNCTION (this << q);
-
m_queue = q;
}
-void CsmaNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
+ void
+CsmaNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
{
NS_LOG_FUNCTION (em);
-
m_receiveErrorModel = em;
}
-void
+ void
CsmaNetDevice::Receive (Ptr<Packet> packet)
{
NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC ("UID is " << packet->GetUid ());
- EthernetHeader header (false);
- EthernetTrailer trailer;
- Mac48Address broadcast;
- Mac48Address multicast;
- Mac48Address destination;
-
- NS_LOG_LOGIC ("UID is " << packet->GetUid());
-
- // Only receive if send side of net device is enabled
- if (!IsReceiveEnabled())
+//
+// Only receive if the send side of net device is enabled
+//
+ if (IsReceiveEnabled () == false)
{
m_dropTrace (packet);
return;
@@ -443,14 +472,30 @@
if (m_encapMode == RAW)
{
m_rxCallback (this, packet, 0, GetBroadcast ());
- m_dropTrace (packet);
return;
}
- packet->RemoveTrailer(trailer);
- trailer.CheckFcs(packet);
- packet->RemoveHeader(header);
+
+ EthernetTrailer trailer;
+ packet->RemoveTrailer (trailer);
+ trailer.CheckFcs (packet);
+
+ EthernetHeader header (false);
+ packet->RemoveHeader (header);
+
+ NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
+ NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
- NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
+//
+// We never forward up packets that we sent. Real devices don't do this since
+// their receivers are disabled during send, so we don't. Drop the packet
+// silently (no tracing) since it would really never get here in a real device.
+//
+ if (header.GetSource () == GetAddress ())
+ {
+ NS_LOG_LOGIC ("Dropping packet sourced by this device");
+ return;
+ }
+
//
// An IP host group address is mapped to an Ethernet multicast address
// by placing the low-order 23-bits of the IP address into the low-order
@@ -468,9 +513,9 @@
mcBuf[5] = 0;
mcDest.CopyFrom (mcBuf);
- multicast = Mac48Address::ConvertFrom (GetMulticast ());
- broadcast = Mac48Address::ConvertFrom (GetBroadcast ());
- destination = Mac48Address::ConvertFrom (GetAddress ());
+ Mac48Address multicast = Mac48Address::ConvertFrom (GetMulticast ());
+ Mac48Address broadcast = Mac48Address::ConvertFrom (GetBroadcast ());
+ Mac48Address destination = Mac48Address::ConvertFrom (GetAddress ());
if ((header.GetDestination () != broadcast) &&
(mcDest != multicast) &&
@@ -485,13 +530,12 @@
{
NS_LOG_LOGIC ("Dropping pkt due to error model ");
m_dropTrace (packet);
- // Do not forward up; let this packet go
}
else
{
//
-// protocol must be initialized to avoid a compiler warning in the RAW
-// case that breaks the optimized build.
+// variable <protocol> must be initialized to avoid a compiler warning in the
+// RAW case that breaks the optimized build.
//
uint16_t protocol = 0;
@@ -499,7 +543,7 @@
{
case ETHERNET_V1:
case IP_ARP:
- protocol = header.GetLengthType();
+ protocol = header.GetLengthType ();
break;
case LLC:
{
@@ -516,95 +560,109 @@
}
}
-Ptr<Queue>
-CsmaNetDevice::GetQueue(void) const
+ Ptr<Queue>
+CsmaNetDevice::GetQueue (void) const
{
NS_LOG_FUNCTION_NOARGS ();
return m_queue;
}
-void
+ void
CsmaNetDevice::NotifyLinkUp (void)
{
m_linkUp = true;
- if (!m_linkChangeCallback.IsNull ())
+ if (m_linkChangeCallback.IsNull () == false)
{
m_linkChangeCallback ();
}
}
-void
-CsmaNetDevice::SetName(const std::string name)
+ void
+CsmaNetDevice::SetName (const std::string name)
{
m_name = name;
}
-std::string
-CsmaNetDevice::GetName(void) const
+
+ std::string
+CsmaNetDevice::GetName (void) const
{
return m_name;
}
-void
-CsmaNetDevice::SetIfIndex(const uint32_t index)
+
+ void
+CsmaNetDevice::SetIfIndex (const uint32_t index)
{
m_ifIndex = index;
}
-uint32_t
-CsmaNetDevice::GetIfIndex(void) const
+
+ uint32_t
+CsmaNetDevice::GetIfIndex (void) const
{
return m_ifIndex;
}
-Ptr<Channel>
+
+ Ptr<Channel>
CsmaNetDevice::GetChannel (void) const
{
return m_channel;
}
-Address
+
+ Address
CsmaNetDevice::GetAddress (void) const
{
return m_address;
}
-bool
+
+ bool
CsmaNetDevice::SetMtu (const uint16_t mtu)
{
m_mtu = mtu;
return true;
}
-uint16_t
+
+ uint16_t
CsmaNetDevice::GetMtu (void) const
{
return m_mtu;
}
-bool
+
+ bool
CsmaNetDevice::IsLinkUp (void) const
{
return m_linkUp;
}
-void
+
+ void
CsmaNetDevice::SetLinkChangeCallback (Callback<void> callback)
{
m_linkChangeCallback = callback;
}
-bool
+
+ bool
CsmaNetDevice::IsBroadcast (void) const
{
return true;
}
-Address
+
+ Address
CsmaNetDevice::GetBroadcast (void) const
{
return Mac48Address ("ff:ff:ff:ff:ff:ff");
}
-bool
+
+ bool
CsmaNetDevice::IsMulticast (void) const
{
return true;
}
-Address
+
+ Address
CsmaNetDevice::GetMulticast (void) const
{
return Mac48Address ("01:00:5e:00:00:00");
}
-Address
+
+ Address
CsmaNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
{
NS_LOG_FUNCTION (this << multicastGroup);
@@ -655,13 +713,18 @@
return etherAddr;
}
-bool
+
+ bool
CsmaNetDevice::IsPointToPoint (void) const
{
return false;
}
-bool
-CsmaNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+
+ bool
+CsmaNetDevice::Send(
+ Ptr<Packet> packet,
+ const Address& dest,
+ uint16_t protocolNumber)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_LOGIC ("p=" << packet);
@@ -669,43 +732,56 @@
NS_ASSERT (IsLinkUp ());
- // Only transmit if send side of net device is enabled
- if (!IsSendEnabled())
- return false;
-
- Mac48Address destination = Mac48Address::ConvertFrom (dest);
- AddHeader(packet, destination, protocolNumber);
-
- // Place the packet to be sent on the send queue
- if (m_queue->Enqueue(packet) == false )
+//
+// Only transmit if send side of net device is enabled
+//
+ if (IsSendEnabled () == false)
{
return false;
}
- // If the device is idle, we need to start a transmission. Otherwise,
- // the transmission will be started when the current packet finished
- // transmission (see TransmitCompleteEvent)
+
+ Mac48Address destination = Mac48Address::ConvertFrom (dest);
+ AddHeader (packet, destination, protocolNumber);
+
+//
+// Place the packet to be sent on the send queue
+//
+ if (m_queue->Enqueue(packet) == false)
+ {
+ return false;
+ }
+//
+// If the device is idle, we need to start a transmission. Otherwise,
+// the transmission will be started when the current packet finished
+// transmission (see TransmitCompleteEvent)
+//
if (m_txMachineState == READY)
{
- // Store the next packet to be transmitted
+//
+// The next packet to be transmitted goes in m_currentPkt
+//
m_currentPkt = m_queue->Dequeue ();
if (m_currentPkt != 0)
{
- TransmitStart();
+ TransmitStart ();
}
}
return true;
}
-Ptr<Node>
+
+ Ptr<Node>
CsmaNetDevice::GetNode (void) const
{
return m_node;
}
-void
+
+ void
CsmaNetDevice::SetNode (Ptr<Node> node)
{
m_node = node;
}
-bool
+
+ bool
CsmaNetDevice::NeedsArp (void) const
{
if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
@@ -717,7 +793,8 @@
return false;
}
}
-void
+
+ void
CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
{
m_rxCallback = cb;
--- a/src/devices/csma/csma-net-device.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/csma/csma-net-device.h Wed Jun 11 16:20:04 2008 -0700
@@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca
- * Derived from the p2p net device file
*/
#ifndef CSMA_NET_DEVICE_H
@@ -48,18 +47,19 @@
*
* The Csma net device class is analogous to layer 1 and 2 of the
* TCP stack. The NetDevice takes a raw packet of bytes and creates a
- * protocol specific packet from them. The Csma net device class
- * takes this packet and adds and processes the headers/trailers that
- * are associated with EthernetV1, EthernetV2, RAW or LLC
- * protocols. The EthernetV1 packet type adds and removes Ethernet
+ * protocol specific packet from them.
+ *
+ * The Csma net device class takes a packet and adds (or removes) the
+ * headers/trailers that are associated with EthernetV1, EthernetV2, RAW
+ * or LLC protocols. The EthernetV1 packet type adds and removes Ethernet
* destination and source addresses. The LLC packet type adds and
* removes LLC snap headers. The raw packet type does not add or
- * remove any headers. Each Csma net device will receive all
- * packets written to the Csma link. The ProcessHeader function can
- * be used to filter out the packets such that higher level layers
- * only receive packets that are addressed to their associated net
- * devices
+ * remove any headers.
*
+ * Each Csma net device will receive all packets written to the Csma link.
+ * The ProcessHeader function can be used to filter out the packets such that
+ * higher level layers only receive packets that are addressed to their
+ * associated net devices
*/
class CsmaNetDevice : public NetDevice
{
@@ -69,49 +69,36 @@
* Enumeration of the types of packets supported in the class.
*
*/
-enum CsmaEncapsulationMode {
- ETHERNET_V1, /**< Version one ethernet packet, length field */
- IP_ARP, /**< Ethernet packet encapsulates IP/ARP packet */
- RAW, /**< Packet that contains no headers */
- LLC, /**< LLC packet encapsulation */
-};
+ enum CsmaEncapsulationMode {
+ ETHERNET_V1, /**< Version one ethernet packet, length field */
+ IP_ARP, /**< Ethernet packet encapsulates IP/ARP packet */
+ RAW, /**< Packet that contains no headers */
+ LLC, /**< LLC packet encapsulation */
+ };
/**
* Construct a CsmaNetDevice
*
- * This is the constructor for the CsmaNetDevice. It takes as a
- * parameter the Node to which this device is connected. Ownership of the
- * Node pointer is not implied and the node must not be deleted.
- *
+ * This is the default constructor for a CsmaNetDevice.
*/
CsmaNetDevice ();
/**
* Destroy a CsmaNetDevice
*
- * This is the destructor for the CsmaNetDevice.
+ * This is the destructor for a CsmaNetDevice.
*/
- virtual ~CsmaNetDevice();
- /**
- * Set the Data Rate used for transmission of packets. The data rate is
- * set in the Attach () method from the corresponding field in the channel
- * to which the device is attached. It can be overridden using this method.
- *
- * @see Attach ()
- * \param bps the data rate at which this object operates
- */
- void SetDataRate (DataRate bps);
+ virtual ~CsmaNetDevice ();
+
/**
* Set the inteframe gap used to separate packets. The interframe gap
* defines the minimum space required between packets sent by this device.
- * It is usually set in the Attach () method based on the speed of light
- * delay of the channel to which the device is attached. It can be
- * overridden using this method if desired.
+ * As in Ethernet, it defaults to 96 bit times.
*
- * @see Attach ()
* \param t the interframe gap time
*/
void SetInterframeGap (Time t);
+
/**
* Set the backoff parameters used to determine the wait to retry
* transmitting a packet when the channel is busy.
@@ -124,43 +111,43 @@
* \param ceiling Cap on the exponential function when calculating max slots
*/
void SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots,
- uint32_t maxRetries, uint32_t ceiling);
+ uint32_t maxRetries, uint32_t ceiling);
+
/**
* Attach the device to a channel.
*
- * The function Attach is used to add a CsmaNetDevice to a
- * CsmaChannel.
+ * The function Attach is used to add a CsmaNetDevice to a CsmaChannel.
*
* @see SetDataRate ()
* @see SetInterframeGap ()
* \param ch a pointer to the channel to which this object is being attached.
*/
bool Attach (Ptr<CsmaChannel> ch);
+
/**
* Attach a queue to the CsmaNetDevice.
*
- * The CsmaNetDevice "owns" a queue. This queue is created by the
- * CsmaTopology object and implements a queueing method such as
- * DropTail or RED. The CsmaNetDevice assumes ownership of this
- * queue and must delete it when the device is destroyed.
+ * The CsmaNetDevice "owns" a queue. This queue may be set by higher
+ * level topology objects to implement a particular queueing method such as
+ * DropTail or RED.
*
- * @see CsmaTopology::AddCsmaLink ()
* @see Queue
* @see DropTailQueue
- * \param queue a pointer to the queue for which object is assuming
- * ownership.
+ * \param queue a Ptr to the queue for being assigned to the device.
*/
void SetQueue (Ptr<Queue> queue);
+
/**
* Attach a receive ErrorModel to the CsmaNetDevice.
*
* The CsmaNetDevice may optionally include an ErrorModel in
- * the packet receive chain.
+ * the packet receive chain to simulate data errors in during transmission.
*
* @see ErrorModel
* @param em a pointer to the ErrorModel
*/
- void SetReceiveErrorModel(Ptr<ErrorModel> em);
+ void SetReceiveErrorModel (Ptr<ErrorModel> em);
+
/**
* Receive a packet from a connected CsmaChannel.
*
@@ -174,20 +161,48 @@
*/
void Receive (Ptr<Packet> p);
+ /**
+ * Is the send side of the network device enabled?
+ *
+ * \returns True if the send side is enabled, otherwise false.
+ */
bool IsSendEnabled (void);
+
+ /**
+ * Enable or disable the send side of the network device.
+ *
+ * \param enable Enable the send side if true, otherwise disable.
+ */
+ void SetSendEnable (bool enable);
+
+ /**
+ * Is the receive side of the network device enabled?
+ *
+ * \returns True if the receiver side is enabled, otherwise false.
+ */
bool IsReceiveEnabled (void);
- void SetSendEnable (bool);
- void SetReceiveEnable (bool);
-
- void SetAddress (Mac48Address self);
-
+ /**
+ * Enable or disable the receive side of the network device.
+ *
+ * \param enable Enable the receive side if true, otherwise disable.
+ */
+ void SetReceiveEnable (bool enable);
- // inherited from NetDevice base class.
- virtual void SetName(const std::string name);
- virtual std::string GetName(void) const;
- virtual void SetIfIndex(const uint32_t index);
- virtual uint32_t GetIfIndex(void) const;
+ /**
+ * Set the MAC address of the the network device.
+ *
+ * \param addr The Mac48Address to use as the address of the device.
+ */
+ void SetAddress (Mac48Address addr);
+
+//
+// The following methods are inherited from NetDevice base class.
+//
+ virtual void SetName (const std::string name);
+ virtual std::string GetName (void) const;
+ virtual void SetIfIndex (const uint32_t index);
+ virtual uint32_t GetIfIndex (void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
@@ -198,6 +213,7 @@
virtual Address GetBroadcast (void) const;
virtual bool IsMulticast (void) const;
virtual Address GetMulticast (void) const;
+
/**
* @brief Make and return a MAC multicast address using the provided
* multicast group
@@ -221,14 +237,54 @@
* @see Address
*/
virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+
+ /**
+ * Is this a point to point link?
+ * \returns false.
+ */
virtual bool IsPointToPoint (void) const;
- virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+
+ /**
+ * Start sending a packet down the channel.
+ */
+ virtual bool Send (Ptr<Packet> packet, const Address& dest,
+ uint16_t protocolNumber);
+
+ /**
+ * Get the node to which this device is attached.
+ *
+ * \returns Ptr to the Node to which the device is attached.
+ */
virtual Ptr<Node> GetNode (void) const;
+
+ /**
+ * Set the node to which this device is being attached.
+ *
+ * \param node Ptr to the Node to which the device is being attached.
+ */
virtual void SetNode (Ptr<Node> node);
+
+ /**
+ * Does this device need to use the address resolution protocol?
+ *
+ * \returns True if the encapsulation mode is set to a value that requires
+ * ARP (IP_ARP or LLC).
+ */
virtual bool NeedsArp (void) const;
+
+ /**
+ * Set the callback to be used to notify higher layers when a packet has been
+ * received.
+ *
+ * \param cb The callback.
+ */
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
protected:
+ /**
+ * Perform any object release functionality required to break reference
+ * cycles in reference counted objects held by the device.
+ */
virtual void DoDispose (void);
/**
@@ -240,6 +296,7 @@
* \return a pointer to the queue.
*/
Ptr<Queue> GetQueue (void) const;
+
/**
* Adds the necessary headers and trailers to a packet of data in order to
* respect the packet type
@@ -249,8 +306,8 @@
* \param protocolNumber In some protocols, identifies the type of
* payload contained in this packet.
*/
- void AddHeader (Ptr<Packet> p, Mac48Address dest,
- uint16_t protocolNumber);
+ void AddHeader (Ptr<Packet> p, Mac48Address dest, uint16_t protocolNumber);
+
/**
* Removes, from a packet of data, all headers and trailers that
* relate to the packet type
@@ -264,11 +321,21 @@
bool ProcessHeader (Ptr<Packet> p, uint16_t & param);
private:
- // disable copy constructor and operator =
+ /**
+ * Operator = is declared but not implemented. This disables the assigment
+ * operator for CsmaNetDevice objects.
+
+ */
CsmaNetDevice &operator = (const CsmaNetDevice &o);
+
+ /**
+ * Copy constructor is declared but not implemented. This disables the
+ * copy constructor for CsmaNetDevice objects.
+ */
CsmaNetDevice (const CsmaNetDevice &o);
+
/**
- * Initializes variablea when construction object.
+ * Initialization function used during object construction.
*/
void Init (bool sendEnable, bool receiveEnable);
@@ -277,35 +344,38 @@
*
* The TransmitStart method is the method that is used internally in
* the CsmaNetDevice to begin the process of sending a packet
- * out on the channel. The corresponding method is called on the
+ * out on the channel. A corresponding method is called on the
* channel to let it know that the physical device this class
- * represents has virually started sending signals, this causes the
- * channel to become busy. An event is scheduled for the time at
- * which the bits have been completely transmitted. If the channel
- * is busy, the method reschedules itself for a later time (within
- * the backoff period)
+ * represents has actually started sending signals, this causes the
+ * channel to enter the BUSY state. An event is scheduled for the time at
+ * which the bits have been completely transmitted.
+ *
+ * If the channel is found to be BUSY, this method reschedules itself for
+ * execution at a later time (within the backoff period).
*
* @see CsmaChannel::TransmitStart ()
* @see TransmitCompleteEvent ()
*/
void TransmitStart ();
+
/**
* Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
*
* The TransmitCompleteEvent method is used internally to finish the process
* of sending a packet out on the channel. During execution of this method
* the TransmitEnd method is called on the channel to let it know that the
- * physical device this class represents has virually finished sending
+ * physical device this class represents has finished sending simulated
* signals. The channel uses this event to begin its speed of light delay
- * timer after which it notifies the Net Device at the other end of the
- * link that the bits have arrived. During this method, the net device
- * also schedules the TransmitReadyEvent at which time the transmitter
- * becomes ready to send the next packet.
+ * timer after which it notifies the Net Device(s) at the other end of the
+ * link that new bits have arrived (it delivers the Packet). During this
+ * method, the net device also schedules the TransmitReadyEvent at which
+ * time the transmitter becomes ready to send the next packet.
*
* @see CsmaChannel::TransmitEnd ()
* @see TransmitReadyEvent ()
*/
void TransmitCompleteEvent (void);
+
/**
* Cause the Transmitter to Become Ready to Send Another Packet.
*
@@ -328,9 +398,12 @@
* If the net device has tried to transmit a packet for more times
* than the maximum allowed number of retries (channel always busy)
* then the packet is dropped.
- *
*/
void TransmitAbort (void);
+
+ /**
+ * Notify any interested parties that the link has come up.
+ */
void NotifyLinkUp (void);
/**
@@ -344,10 +417,12 @@
* Enable net device to send packets. True by default
*/
bool m_sendEnable;
+
/**
* Enable net device to receive packets. True by default
*/
bool m_receiveEnable;
+
/**
* Enumeration of the states of the transmit machine of the net device.
*/
@@ -358,6 +433,7 @@
GAP, /**< The transmitter is in the interframe gap time */
BACKOFF /**< The transmitter is waiting for the channel to be free */
};
+
/**
* The state of the Net Device transmit state machine.
* @see TxMachineState
@@ -370,36 +446,42 @@
* function.
*/
CsmaEncapsulationMode m_encapMode;
+
/**
* The data rate that the Net Device uses to simulate packet transmission
* timing.
* @see class DataRate
*/
DataRate m_bps;
+
/**
- * The interframe gap that the Net Device uses to throttle packet
+ * The interframe gap that the Net Device uses insert time between packet
* transmission
* @see class Time
*/
Time m_tInterframeGap;
+
/**
* Holds the backoff parameters and is used to calculate the next
* backoff time to use when the channel is busy and the net device
* is ready to transmit
*/
Backoff m_backoff;
+
/**
* Next packet that will be transmitted (if transmitter is not
* currently transmitting) or packet that is currently being
* transmitted.
*/
Ptr<Packet> m_currentPkt;
+
/**
* The CsmaChannel to which this CsmaNetDevice has been
* attached.
* @see class CsmaChannel
*/
Ptr<CsmaChannel> m_channel;
+
/**
* The Queue which this CsmaNetDevice uses as a packet source.
* Management of this Queue has been delegated to the CsmaNetDevice
@@ -415,26 +497,65 @@
Ptr<ErrorModel> m_receiveErrorModel;
/**
- * NOT TESTED
* The trace source for the packet reception events that the device can
* fire.
*
* @see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet> > m_rxTrace;
+
+ /**
+ * The trace source for the packet drop events that the device can
+ * fire.
+ *
+ * @see class CallBackTraceSource
+ */
TracedCallback<Ptr<const Packet> > m_dropTrace;
+ /**
+ * The Node to which this device is attached.
+ */
Ptr<Node> m_node;
+
+ /**
+ * The MAC address which has been assigned to this device.
+ */
Mac48Address m_address;
+
+ /**
+ * The callback used to notify higher layers that a packet has been received.
+ */
NetDevice::ReceiveCallback m_rxCallback;
+
+ /**
+ * The interface index (really net evice index) that has been assigned to
+ * this network device.
+ */
uint32_t m_ifIndex;
+
+ /**
+ * The human readable name of this device.
+ */
std::string m_name;
+
+ /**
+ * Flag indicating whether or not the link is up. In this case,
+ * whether or not the device is connected to a channel.
+ */
bool m_linkUp;
+
+ /**
+ * Callback to fire if the link changes state (up or down).
+ */
Callback<void> m_linkChangeCallback;
+
+ /**
+ * The maximum transmission unit (biggest packet) allowed to be sent or
+ * received by this network device.
+ */
uint16_t m_mtu;
};
}; // namespace ns3
#endif // CSMA_NET_DEVICE_H
-
--- a/src/devices/csma/csma.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/csma/csma.h Wed Jun 11 16:20:04 2008 -0700
@@ -22,8 +22,14 @@
*
* The class ns3::CsmaChannel models the actual transmission medium.
* There is no fixed limit for the number of devices connected to the channel.
- * The ns3::CsmaChannel models a bitrate and a speed-of-light delay which can
- * be accessed via the attributes "BitRate" and "Delay" respectively.
+ * The ns3::CsmaChannel models a data rate and a speed-of-light delay which can
+ * be accessed via the attributes "DataRate" and "Delay" respectively.
+ * The data rate provided to the channel is used to set the data rates
+ * used by the transmitter sections of the CSMA devices connected to the
+ * channel. There is no way to independently set data rates in the
+ * devices. Since the data rate is only used to calculate a delay time, there
+ * is no limitation (other than by the data type holding the value) on the
+ * speed at which CSMA channels and devices can operate.
*
* The ns3::CsmaChannel has three states, IDLE, TRANSMITTING and PROPAGATING.
* These three states are "seen" instantaneously by all devices on the channel.
@@ -62,7 +68,13 @@
*
* The ns3::CsmaChannel models a broadcast medium so the packet is delivered
* to all of the devices on the channel (including the source) at the end of
- * the propagation time.
+ * the propagation time. It is the responsibility of the sending device to
+ * determine whether or not it receives a packet broadcast over the channel.
+ *
+ * The ns3::CsmaChannel provides following Attributes:
+ *
+ * - DataRate: The bitrate for packet transmission on connected devices;
+ * - Delay: The speed of light transmission delay for the channel.
*
* \subsection CSMA Net Device Model
*
@@ -70,7 +82,6 @@
* ns3::CsmaNetDevice provides following Attributes:
*
* - Address: The ns3::Mac48Address of the device;
- * - DataRate: The data rate of the device;
* - SendEnable: Enable packet transmission if true;
* - ReceiveEnable: Enable packet reception if true;
* - EncapsulationMode: Type of link layer encapsulation to use;
--- a/src/devices/point-to-point/point-to-point.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/devices/point-to-point/point-to-point.h Wed Jun 11 16:20:04 2008 -0700
@@ -30,6 +30,19 @@
* - Rx: A trace source for received packets;
* - Drop: A trace source for dropped packets.
*
+ * The ns3::PointToPointNetDevice models a transmitter section that puts bits
+ * on a corresponding channel "wire." THe DataRate attribute specifies the
+ * number of bits per second that the device will simulate sending over the
+ * channel. In reality no bits are sent, but an event is scheduled for an
+ * elapsed time consistent with the number of bits in each packet and the
+ * specified DataRate. The implication here is that the receiving device
+ * models a receiver section that can receive any any data rate. Therefore
+ * there is no need, nor way to set a receive data rate in this model. By
+ * setting the DataRate on the transmitter of both devices connected to a
+ * given ns3::PointToPointChannel one can model a symmetric channel; or by
+ * setting different DataRates one can model an asymmetric channel (e.g.,
+ * ADSL).
+ *
* The ns3::PointToPointNetDevice supports the assignment of a "receive error
* model." This is an ns3::ErrorModel object that is used to simulate data
* corruption on the link.
@@ -40,6 +53,7 @@
* beyond the eight bits per byte of the packet sent. That is, we do not
* model Flag Sequences, Frame Check Sequences nor do we "escape" any data.
*
- * The ns3::PointToPointChannel does model a speed-of-light or transmission
- * delay which can be set and get via the attribute "Delay."
+ * The ns3::PointToPointNetChannel provides following Attributes:
+ *
+ * - Delay: The speed of light transmission delay for the channel.
*/
--- a/src/helper/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/src/helper/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
- helper = bld.create_ns3_module('helper', ['internet-node', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
+ helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
helper.source = [
'node-container.cc',
'net-device-container.cc',
--- a/src/internet-node/arp-cache.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "ns3/assert.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-#include "ns3/log.h"
-
-#include "arp-cache.h"
-#include "arp-header.h"
-#include "ipv4-interface.h"
-
-NS_LOG_COMPONENT_DEFINE ("ArpCache");
-
-namespace ns3 {
-
-TypeId
-ArpCache::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::ArpCache")
- .SetParent<Object> ()
- .AddAttribute ("AliveTimeout",
- "When this timeout expires, the matching cache entry needs refreshing",
- TimeValue (Seconds (120)),
- MakeTimeAccessor (&ArpCache::m_aliveTimeout),
- MakeTimeChecker ())
- .AddAttribute ("DeadTimeout",
- "When this timeout expires, a new attempt to resolve the matching entry is made",
- TimeValue (Seconds (100)),
- MakeTimeAccessor (&ArpCache::m_deadTimeout),
- MakeTimeChecker ())
- .AddAttribute ("WaitReplyTimeout",
- "When this timeout expires, the matching cache entry is marked dead",
- TimeValue (Seconds (1)),
- MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
- MakeTimeChecker ())
- .AddAttribute ("PendingQueueSize",
- "The size of the queue for packets pending an arp reply.",
- UintegerValue (3),
- MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
- MakeUintegerChecker<uint32_t> ())
- ;
- return tid;
-}
-
-ArpCache::ArpCache ()
- : m_device (0),
- m_interface (0)
-{
- NS_LOG_FUNCTION (this);
-}
-
-ArpCache::~ArpCache ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-void
-ArpCache::DoDispose (void)
-{
- NS_LOG_FUNCTION (this);
- Flush ();
- m_device = 0;
- m_interface = 0;
- Object::DoDispose ();
-}
-
-void
-ArpCache::SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
-{
- m_device = device;
- m_interface = interface;
-}
-
-Ptr<NetDevice>
-ArpCache::GetDevice (void) const
-{
- return m_device;
-}
-
-Ptr<Ipv4Interface>
-ArpCache::GetInterface (void) const
-{
- return m_interface;
-}
-
-void
-ArpCache::SetAliveTimeout (Time aliveTimeout)
-{
- m_aliveTimeout = aliveTimeout;
-}
-void
-ArpCache::SetDeadTimeout (Time deadTimeout)
-{
- m_deadTimeout = deadTimeout;
-}
-void
-ArpCache::SetWaitReplyTimeout (Time waitReplyTimeout)
-{
- m_waitReplyTimeout = waitReplyTimeout;
-}
-
-Time
-ArpCache::GetAliveTimeout (void) const
-{
- return m_aliveTimeout;
-}
-Time
-ArpCache::GetDeadTimeout (void) const
-{
- return m_deadTimeout;
-}
-Time
-ArpCache::GetWaitReplyTimeout (void) const
-{
- return m_waitReplyTimeout;
-}
-
-void
-ArpCache::Flush (void)
-{
- for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
- {
- delete (*i).second;
- }
- m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
-}
-
-ArpCache::Entry *
-ArpCache::Lookup (Ipv4Address to)
-{
- if (m_arpCache.find (to) != m_arpCache.end ())
- {
- ArpCache::Entry *entry = m_arpCache[to];
- return entry;
- }
- return 0;
-}
-
-ArpCache::Entry *
-ArpCache::Add (Ipv4Address to)
-{
- NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
-
- ArpCache::Entry *entry = new ArpCache::Entry (this);
- m_arpCache[to] = entry;
- return entry;
-}
-
-ArpCache::Entry::Entry (ArpCache *arp)
- : m_arp (arp),
- m_state (ALIVE)
-{}
-
-
-bool
-ArpCache::Entry::IsDead (void)
-{
- return (m_state == DEAD)?true:false;
-}
-bool
-ArpCache::Entry::IsAlive (void)
-{
- return (m_state == ALIVE)?true:false;
-}
-bool
-ArpCache::Entry::IsWaitReply (void)
-{
- return (m_state == WAIT_REPLY)?true:false;
-}
-
-
-void
-ArpCache::Entry::MarkDead (void)
-{
- m_state = DEAD;
- UpdateSeen ();
-}
-void
-ArpCache::Entry::MarkAlive (Address macAddress)
-{
- NS_ASSERT (m_state == WAIT_REPLY);
- m_macAddress = macAddress;
- m_state = ALIVE;
- UpdateSeen ();
-}
-
-bool
-ArpCache::Entry::UpdateWaitReply (Ptr<Packet> waiting)
-{
- NS_ASSERT (m_state == WAIT_REPLY);
- /* We are already waiting for an answer so
- * we dump the previously waiting packet and
- * replace it with this one.
- */
- if (m_pending.size () >= m_arp->m_pendingQueueSize)
- {
- return false;
- }
- m_pending.push_back (waiting);
- return true;
-}
-void
-ArpCache::Entry::MarkWaitReply (Ptr<Packet> waiting)
-{
- NS_ASSERT (m_state == ALIVE || m_state == DEAD);
- NS_ASSERT (m_pending.empty ());
- m_state = WAIT_REPLY;
- m_pending.push_back (waiting);
- UpdateSeen ();
-}
-
-Address
-ArpCache::Entry::GetMacAddress (void)
-{
- NS_ASSERT (m_state == ALIVE);
- return m_macAddress;
-}
-bool
-ArpCache::Entry::IsExpired (void)
-{
- Time timeout;
- switch (m_state) {
- case ArpCache::Entry::WAIT_REPLY:
- timeout = m_arp->GetWaitReplyTimeout ();
- break;
- case ArpCache::Entry::DEAD:
- timeout = m_arp->GetDeadTimeout ();
- break;
- case ArpCache::Entry::ALIVE:
- timeout = m_arp->GetAliveTimeout ();
- break;
- default:
- NS_ASSERT (false);
- timeout = Seconds (0);
- /* NOTREACHED */
- break;
- }
- Time delta = Simulator::Now () - m_lastSeen;
- if (delta >= timeout)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-Ptr<Packet>
-ArpCache::Entry::DequeuePending (void)
-{
- if (m_pending.empty ())
- {
- return 0;
- }
- else
- {
- Ptr<Packet> p = m_pending.front ();
- m_pending.pop_front ();
- return p;
- }
-}
-void
-ArpCache::Entry::UpdateSeen (void)
-{
- m_lastSeen = Simulator::Now ();
-}
-
-} // namespace ns3
-
--- a/src/internet-node/arp-cache.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef ARP_CACHE_H
-#define ARP_CACHE_H
-
-#include <stdint.h>
-#include <list>
-#include "ns3/packet.h"
-#include "ns3/nstime.h"
-#include "ns3/net-device.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/address.h"
-#include "ns3/ptr.h"
-#include "ns3/object.h"
-#include "sgi-hashmap.h"
-
-namespace ns3 {
-
-class NetDevice;
-class Ipv4Interface;
-
-/**
- * \brief An ARP cache
- *
- * A cached lookup table for translating layer 3 addresses to layer 2.
- * This implementation does lookups from IPv4 to a MAC address
- */
-class ArpCache : public Object
-{
-public:
- static TypeId GetTypeId (void);
- class Entry;
- ArpCache ();
- ~ArpCache ();
-
- /**
- * \param device The hardware NetDevice associated with this ARP chache
- * \param interface the Ipv4Interface associated with this ARP chache
- */
- void SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
- /**
- * \return The NetDevice that this ARP cache is associated with
- */
- Ptr<NetDevice> GetDevice (void) const;
- /**
- * \return the Ipv4Interface that this ARP cache is associated with
- */
- Ptr<Ipv4Interface> GetInterface (void) const;
-
- void SetAliveTimeout (Time aliveTimeout);
- void SetDeadTimeout (Time deadTimeout);
- void SetWaitReplyTimeout (Time waitReplyTimeout);
- Time GetAliveTimeout (void) const;
- Time GetDeadTimeout (void) const;
- Time GetWaitReplyTimeout (void) const;
-
- /**
- * \brief Do lookup in the ARP chache against an IP address
- * \param destination The destination IPv4 address to lookup the MAC address
- * of
- * \return An ArpCache::Entry with info about layer 2
- */
- ArpCache::Entry *Lookup (Ipv4Address destination);
- /**
- * \brief Add an Ipv4Address to this ARP cache
- */
- ArpCache::Entry *Add (Ipv4Address to);
- /**
- * \brief Clear the ArpCache of all entries
- */
- void Flush (void);
-
- /**
- * \brief A record that that holds information about an ArpCache entry
- */
- class Entry {
- public:
- /**
- * \brief Constructor
- * \param arp The ArpCache this entry belongs to
- */
- Entry (ArpCache *arp);
-
- /**
- * \brief Changes the state of this entry to dead
- */
- void MarkDead (void);
- /**
- * \param macAddress
- */
- void MarkAlive (Address macAddress);
- /**
- * \param waiting
- */
- void MarkWaitReply (Ptr<Packet> waiting);
- /**
- * \param waiting
- * \return
- */
- bool UpdateWaitReply (Ptr<Packet> waiting);
- /**
- * \return True if the state of this entry is dead; false otherwise.
- */
- bool IsDead (void);
- /**
- * \return True if the state of this entry is alive; false otherwise.
- */
- bool IsAlive (void);
- /**
- * \return True if the state of this entry is wait_reply; false otherwise.
- */
- bool IsWaitReply (void);
-
- /**
- * \return The MacAddress of this entry
- */
- Address GetMacAddress (void);
- /**
- * \return True if this entry has timedout; false otherwise.
- */
- bool IsExpired (void);
-
- /**
- * \returns 0 is no packet is pending, the next packet to send if
- * packets are pending.
- */
- Ptr<Packet> DequeuePending (void);
- private:
- enum ArpCacheEntryState_e {
- ALIVE,
- WAIT_REPLY,
- DEAD
- };
-
- void UpdateSeen (void);
- ArpCache *m_arp;
- ArpCacheEntryState_e m_state;
- Time m_lastSeen;
- Address m_macAddress;
- std::list<Ptr<Packet> > m_pending;
- };
-
-private:
- typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash> Cache;
- typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash>::iterator CacheI;
-
- virtual void DoDispose (void);
-
- Ptr<NetDevice> m_device;
- Ptr<Ipv4Interface> m_interface;
- Time m_aliveTimeout;
- Time m_deadTimeout;
- Time m_waitReplyTimeout;
- uint32_t m_pendingQueueSize;
- Cache m_arpCache;
-};
-
-
-}; // namespace ns3
-
-#endif /* ARP_CACHE_H */
--- a/src/internet-node/arp-header.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ns3/assert.h"
-#include "ns3/address-utils.h"
-#include "arp-header.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (ArpHeader);
-
-void
-ArpHeader::SetRequest (Address sourceHardwareAddress,
- Ipv4Address sourceProtocolAddress,
- Address destinationHardwareAddress,
- Ipv4Address destinationProtocolAddress)
-{
- m_type = ARP_TYPE_REQUEST;
- m_macSource = sourceHardwareAddress;
- m_macDest = destinationHardwareAddress;
- m_ipv4Source = sourceProtocolAddress;
- m_ipv4Dest = destinationProtocolAddress;
-}
-void
-ArpHeader::SetReply (Address sourceHardwareAddress,
- Ipv4Address sourceProtocolAddress,
- Address destinationHardwareAddress,
- Ipv4Address destinationProtocolAddress)
-{
- m_type = ARP_TYPE_REPLY;
- m_macSource = sourceHardwareAddress;
- m_macDest = destinationHardwareAddress;
- m_ipv4Source = sourceProtocolAddress;
- m_ipv4Dest = destinationProtocolAddress;
-}
-bool
-ArpHeader::IsRequest (void) const
-{
- return (m_type == ARP_TYPE_REQUEST)?true:false;
-}
-bool
-ArpHeader::IsReply (void) const
-{
- return (m_type == ARP_TYPE_REPLY)?true:false;
-}
-Address
-ArpHeader::GetSourceHardwareAddress (void)
-{
- return m_macSource;
-}
-Address
-ArpHeader::GetDestinationHardwareAddress (void)
-{
- return m_macDest;
-}
-Ipv4Address
-ArpHeader::GetSourceIpv4Address (void)
-{
- return m_ipv4Source;
-}
-Ipv4Address
-ArpHeader::GetDestinationIpv4Address (void)
-{
- return m_ipv4Dest;
-}
-
-
-TypeId
-ArpHeader::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::ArpHeader")
- .SetParent<Header> ()
- .AddConstructor<ArpHeader> ()
- ;
- return tid;
-}
-TypeId
-ArpHeader::GetInstanceTypeId (void) const
-{
- return GetTypeId ();
-}
-void
-ArpHeader::Print (std::ostream &os) const
-{
- if (IsRequest ())
- {
- os << "request "
- << "source mac: " << m_macSource << " "
- << "source ipv4: " << m_ipv4Source << " "
- << "dest ipv4: " << m_ipv4Dest
- ;
- }
- else
- {
- NS_ASSERT (IsReply ());
- os << "reply "
- << "source mac: " << m_macSource << " "
- << "source ipv4: " << m_ipv4Source << " "
- << "dest mac: " << m_macDest << " "
- << "dest ipv4: " <<m_ipv4Dest
- ;
- }
-}
-uint32_t
-ArpHeader::GetSerializedSize (void) const
-{
- /* this is the size of an ARP payload. */
- return 28;
-}
-
-void
-ArpHeader::Serialize (Buffer::Iterator start) const
-{
- Buffer::Iterator i = start;
- NS_ASSERT (m_macSource.GetLength () == m_macDest.GetLength ());
-
- /* ethernet */
- i.WriteHtonU16 (0x0001);
- /* ipv4 */
- i.WriteHtonU16 (0x0800);
- i.WriteU8 (m_macSource.GetLength ());
- i.WriteU8 (4);
- i.WriteHtonU16 (m_type);
- WriteTo (i, m_macSource);
- WriteTo (i, m_ipv4Source);
- WriteTo (i, m_macDest);
- WriteTo (i, m_ipv4Dest);
-}
-uint32_t
-ArpHeader::Deserialize (Buffer::Iterator start)
-{
- Buffer::Iterator i = start;
- i.Next (2+2);
- uint32_t hardwareAddressLen = i.ReadU8 ();
- i.Next (1);
- m_type = i.ReadNtohU16 ();
- ReadFrom (i, m_macSource, hardwareAddressLen);
- ReadFrom (i, m_ipv4Source);
- ReadFrom (i, m_macDest, hardwareAddressLen);
- ReadFrom (i, m_ipv4Dest);
- return GetSerializedSize ();
-}
-
-}; // namespace ns3
--- a/src/internet-node/arp-header.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef ARP_HEADER_H
-#define ARP_HEADER_H
-
-#include "ns3/header.h"
-#include "ns3/address.h"
-#include "ns3/ipv4-address.h"
-#include <string>
-
-namespace ns3 {
-/**
- * \brief The packet header for an ARP packet
- */
-class ArpHeader : public Header
-{
-public:
- void SetRequest (Address sourceHardwareAddress,
- Ipv4Address sourceProtocolAddress,
- Address destinationHardwareAddress,
- Ipv4Address destinationProtocolAddress);
- void SetReply (Address sourceHardwareAddress,
- Ipv4Address sourceProtocolAddress,
- Address destinationHardwareAddress,
- Ipv4Address destinationProtocolAddress);
- bool IsRequest (void) const;
- bool IsReply (void) const;
- Address GetSourceHardwareAddress (void);
- Address GetDestinationHardwareAddress (void);
- Ipv4Address GetSourceIpv4Address (void);
- Ipv4Address GetDestinationIpv4Address (void);
-
- static TypeId GetTypeId (void);
- virtual TypeId GetInstanceTypeId (void) const;
- virtual void Print (std::ostream &os) const;
- virtual uint32_t GetSerializedSize (void) const;
- virtual void Serialize (Buffer::Iterator start) const;
- virtual uint32_t Deserialize (Buffer::Iterator start);
-
- enum ArpType_e {
- ARP_TYPE_REQUEST = 1,
- ARP_TYPE_REPLY = 2
- };
- uint16_t m_type;
- Address m_macSource;
- Address m_macDest;
- Ipv4Address m_ipv4Source;
- Ipv4Address m_ipv4Dest;
-};
-
-}; // namespace ns3
-
-#endif /* ARP_HEADER_H */
--- a/src/internet-node/arp-ipv4-interface.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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:
- * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-
-#include "ns3/packet.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/net-device.h"
-#include "ns3/address.h"
-#include "ns3/pointer.h"
-
-#include "arp-ipv4-interface.h"
-#include "ipv4-l3-protocol.h"
-#include "arp-l3-protocol.h"
-#include "arp-cache.h"
-
-NS_LOG_COMPONENT_DEFINE ("ArpIpv4Interface");
-
-namespace ns3 {
-
-TypeId
-ArpIpv4Interface::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::ArpIpv4Interface")
- .SetParent<Ipv4Interface> ()
- .AddAttribute ("ArpCache",
- "The arp cache for this ipv4 interface",
- PointerValue (0),
- MakePointerAccessor (&ArpIpv4Interface::m_cache),
- MakePointerChecker<ArpIpv4Interface> ())
- ;
- return tid;
-}
-
-ArpIpv4Interface::ArpIpv4Interface ()
- : m_node (0),
- m_device (0)
-{
- NS_LOG_FUNCTION (this);
-}
-
-ArpIpv4Interface::~ArpIpv4Interface ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-void
-ArpIpv4Interface::DoDispose (void)
-{
- NS_LOG_FUNCTION (this);
- m_node = 0;
- m_device = 0;
- m_cache = 0;
- Ipv4Interface::DoDispose ();
-}
-
-void
-ArpIpv4Interface::SetNode (Ptr<Node> node)
-{
- m_node = node;
- DoSetup ();
-}
-void
-ArpIpv4Interface::SetDevice (Ptr<NetDevice> device)
-{
- m_device = device;
- DoSetup ();
-}
-
-Ptr<NetDevice>
-ArpIpv4Interface::GetDevice (void) const
-{
- return m_device;
-}
-
-void
-ArpIpv4Interface::DoSetup (void)
-{
- if (m_node == 0 || m_device == 0)
- {
- return;
- }
- Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
- m_cache = arp->CreateCache (m_device, this);
-}
-
-void
-ArpIpv4Interface::SendTo (Ptr<Packet> p, Ipv4Address dest)
-{
- NS_LOG_FUNCTION (this << p << dest);
-
- NS_ASSERT (GetDevice () != 0);
- if (m_device->NeedsArp ())
- {
- NS_LOG_LOGIC ("Needs ARP");
- Ptr<ArpL3Protocol> arp =
- m_node->GetObject<ArpL3Protocol> ();
- Address hardwareDestination;
- bool found;
-
- if (dest.IsBroadcast () ||
- dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) )
- {
- NS_LOG_LOGIC ("IsBroadcast");
- hardwareDestination = GetDevice ()->GetBroadcast ();
- found = true;
- }
- else if (dest.IsMulticast ())
- {
- NS_LOG_LOGIC ("IsMulticast");
- NS_ASSERT_MSG(GetDevice ()->IsMulticast (),
- "ArpIpv4Interface::SendTo (): Sending multicast packet over "
- "non-multicast device");
-
- hardwareDestination = GetDevice ()->MakeMulticastAddress(dest);
- found = true;
- }
- else
- {
- NS_LOG_LOGIC ("ARP Lookup");
- found = arp->Lookup (p, dest, GetDevice (), m_cache, &hardwareDestination);
- }
-
- if (found)
- {
- NS_LOG_LOGIC ("Address Resolved. Send.");
- GetDevice ()->Send (p, hardwareDestination,
- Ipv4L3Protocol::PROT_NUMBER);
- }
- }
- else
- {
- NS_LOG_LOGIC ("Doesn't need ARP");
- GetDevice ()->Send (p, GetDevice ()->GetBroadcast (),
- Ipv4L3Protocol::PROT_NUMBER);
- }
-}
-
-}//namespace ns3
--- a/src/internet-node/arp-ipv4-interface.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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:
- * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-#ifndef ARP_IPV4_INTERFACE_H
-#define ARP_IPV4_INTERFACE_H
-
-#include "ipv4-interface.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Node;
-class ArpCache;
-
-/**
- * \brief an Ipv4 Interface which uses ARP
- *
- * If you need to use ARP on top of a specific NetDevice, you
- * can use this Ipv4Interface subclass to wrap it for the Ipv4 class
- * when calling Ipv4::AggregateObject.
- */
-class ArpIpv4Interface : public Ipv4Interface
-{
-public:
- static TypeId GetTypeId (void);
-
- ArpIpv4Interface ();
- virtual ~ArpIpv4Interface ();
-
- void SetNode (Ptr<Node> node);
- void SetDevice (Ptr<NetDevice> device);
-
- virtual Ptr<NetDevice> GetDevice (void) const;
-
-private:
- virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
- virtual void DoDispose (void);
- void DoSetup (void);
- Ptr<Node> m_node;
- Ptr<NetDevice> m_device;
- Ptr<ArpCache> m_cache;
-};
-
-}//namespace ns3
-
-
-#endif /* ARP_IPV4_INTERFACE_H */
--- a/src/internet-node/arp-l3-protocol.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,303 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "ns3/packet.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/net-device.h"
-#include "ns3/object-vector.h"
-#include "ns3/trace-source-accessor.h"
-
-#include "ipv4-l3-protocol.h"
-#include "arp-l3-protocol.h"
-#include "arp-header.h"
-#include "arp-cache.h"
-#include "ipv4-interface.h"
-
-NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol");
-
-namespace ns3 {
-
-const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806;
-
-NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol);
-
-TypeId
-ArpL3Protocol::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::ArpL3Protocol")
- .SetParent<Object> ()
- .AddAttribute ("CacheList",
- "The list of ARP caches",
- ObjectVectorValue (),
- MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList),
- MakeObjectVectorChecker<ArpCache> ())
- .AddTraceSource ("Drop",
- "Packet dropped because not enough room in pending queue for a specific cache entry.",
- MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace))
- ;
- return tid;
-}
-
-ArpL3Protocol::ArpL3Protocol ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-ArpL3Protocol::~ArpL3Protocol ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-void
-ArpL3Protocol::SetNode (Ptr<Node> node)
-{
- m_node = node;
-}
-
-void
-ArpL3Protocol::DoDispose (void)
-{
- NS_LOG_FUNCTION (this);
- for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
- {
- Ptr<ArpCache> cache = *i;
- cache->Dispose ();
- }
- m_cacheList.clear ();
- m_node = 0;
- Object::DoDispose ();
-}
-
-Ptr<ArpCache>
-ArpL3Protocol::CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
-{
- Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
- Ptr<ArpCache> cache = CreateObject<ArpCache> ();
- cache->SetDevice (device, interface);
- NS_ASSERT (device->IsBroadcast ());
- device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
- m_cacheList.push_back (cache);
- return cache;
-}
-
-Ptr<ArpCache>
-ArpL3Protocol::FindCache (Ptr<NetDevice> device)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
- {
- if ((*i)->GetDevice () == device)
- {
- return *i;
- }
- }
- NS_ASSERT (false);
- // quiet compiler
- return 0;
-}
-
-void
-ArpL3Protocol::Receive(Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ptr<ArpCache> cache = FindCache (device);
- ArpHeader arp;
- packet->RemoveHeader (arp);
-
- NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
- " node="<<m_node->GetId ()<<", got request from " <<
- arp.GetSourceIpv4Address () << " for address " <<
- arp.GetDestinationIpv4Address () << "; we have address " <<
- cache->GetInterface ()->GetAddress ());
-
- /**
- * Note: we do not update the ARP cache when we receive an ARP request
- * from an unknown node. See bug #107
- */
-
- if (arp.IsRequest () &&
- arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " <<
- arp.GetSourceIpv4Address () << " -- send reply");
- SendArpReply (cache, arp.GetSourceIpv4Address (),
- arp.GetSourceHardwareAddress ());
- }
- else if (arp.IsReply () &&
- arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) &&
- arp.GetDestinationHardwareAddress () == device->GetAddress ())
- {
- Ipv4Address from = arp.GetSourceIpv4Address ();
- ArpCache::Entry *entry = cache->Lookup (from);
- if (entry != 0)
- {
- if (entry->IsWaitReply ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply from " <<
- arp.GetSourceIpv4Address ()
- << " for waiting entry -- flush");
- Address from_mac = arp.GetSourceHardwareAddress ();
- entry->MarkAlive (from_mac);
- Ptr<Packet> pending = entry->DequeuePending();
- while (pending != 0)
- {
- cache->GetInterface ()->Send (pending,
- arp.GetSourceIpv4Address ());
- pending = entry->DequeuePending();
- }
- }
- else
- {
- // ignore this reply which might well be an attempt
- // at poisening my arp cache.
- NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " <<
- arp.GetSourceIpv4Address () <<
- " for non-waiting entry -- drop");
- m_dropTrace (packet);
- }
- }
- else
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
- m_dropTrace (packet);
- }
- }
- else
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got request from " <<
- arp.GetSourceIpv4Address () << " for unknown address " <<
- arp.GetDestinationIpv4Address () << " -- drop");
- }
-}
-bool
-ArpL3Protocol::Lookup (Ptr<Packet> packet, Ipv4Address destination,
- Ptr<NetDevice> device,
- Ptr<ArpCache> cache,
- Address *hardwareDestination)
-{
- NS_LOG_FUNCTION_NOARGS ();
- ArpCache::Entry *entry = cache->Lookup (destination);
- if (entry != 0)
- {
- if (entry->IsExpired ())
- {
- if (entry->IsDead ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", dead entry for " << destination << " expired -- send arp request");
- entry->MarkWaitReply (packet);
- SendArpRequest (cache, destination);
- }
- else if (entry->IsAlive ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", alive entry for " << destination << " expired -- send arp request");
- entry->MarkWaitReply (packet);
- SendArpRequest (cache, destination);
- }
- else if (entry->IsWaitReply ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", wait reply for " << destination << " expired -- drop");
- entry->MarkDead ();
- Ptr<Packet> pending = entry->DequeuePending();
- while (pending != 0)
- {
- m_dropTrace (pending);
- pending = entry->DequeuePending();
- }
- m_dropTrace (packet);
- }
- }
- else
- {
- if (entry->IsDead ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", dead entry for " << destination << " valid -- drop");
- m_dropTrace (packet);
- }
- else if (entry->IsAlive ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", alive entry for " << destination << " valid -- send");
- *hardwareDestination = entry->GetMacAddress ();
- return true;
- }
- else if (entry->IsWaitReply ())
- {
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", wait reply for " << destination << " valid -- drop previous");
- if (!entry->UpdateWaitReply (packet))
- {
- m_dropTrace (packet);
- }
- }
- }
- }
- else
- {
- // This is our first attempt to transmit data to this destination.
- NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
- ", no entry for " << destination << " -- send arp request");
- entry = cache->Add (destination);
- entry->MarkWaitReply (packet);
- SendArpRequest (cache, destination);
- }
- return false;
-}
-
-void
-ArpL3Protocol::SendArpRequest (Ptr<const ArpCache> cache, Ipv4Address to)
-{
- NS_LOG_FUNCTION_NOARGS ();
- ArpHeader arp;
- NS_LOG_LOGIC ("ARP: sending request from node "<<m_node->GetId ()<<
- " || src: " << cache->GetDevice ()->GetAddress () <<
- " / " << cache->GetInterface ()->GetAddress () <<
- " || dst: " << cache->GetDevice ()->GetBroadcast () <<
- " / " << to);
- arp.SetRequest (cache->GetDevice ()->GetAddress (),
- cache->GetInterface ()->GetAddress (),
- cache->GetDevice ()->GetBroadcast (),
- to);
- Ptr<Packet> packet = Create<Packet> ();
- packet->AddHeader (arp);
- cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER);
-}
-
-void
-ArpL3Protocol::SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac)
-{
- NS_LOG_FUNCTION_NOARGS ();
- ArpHeader arp;
- NS_LOG_LOGIC ("ARP: sending reply from node "<<m_node->GetId ()<<
- "|| src: " << cache->GetDevice ()->GetAddress () <<
- " / " << cache->GetInterface ()->GetAddress () <<
- " || dst: " << toMac << " / " << toIp);
- arp.SetReply (cache->GetDevice ()->GetAddress (),
- cache->GetInterface ()->GetAddress (),
- toMac, toIp);
- Ptr<Packet> packet = Create<Packet> ();
- packet->AddHeader (arp);
- cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER);
-}
-
-}//namespace ns3
--- a/src/internet-node/arp-l3-protocol.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef ARP_L3_PROTOCOL_H
-#define ARP_L3_PROTOCOL_H
-
-#include <list>
-#include "ns3/ipv4-address.h"
-#include "ns3/address.h"
-#include "ns3/ptr.h"
-#include "ns3/traced-callback.h"
-
-#include "ipv4-interface.h"
-
-namespace ns3 {
-
-class ArpCache;
-class NetDevice;
-class Node;
-class Packet;
-
-/**
- * \brief An implementation of the ARP protocol
- */
-class ArpL3Protocol : public Object
-{
-public:
- static TypeId GetTypeId (void);
- static const uint16_t PROT_NUMBER;
-
- ArpL3Protocol ();
- virtual ~ArpL3Protocol ();
-
- void SetNode (Ptr<Node> node);
-
- Ptr<ArpCache> CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
-
- /**
- * \brief Recieve a packet
- */
- void Receive(Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from);
- /**
- * \brief Perform an ARP lookup
- * \param p
- * \param destination
- * \param device
- * \param cache
- * \param hardwareDestination
- * \return
- */
- bool Lookup (Ptr<Packet> p, Ipv4Address destination,
- Ptr<NetDevice> device,
- Ptr<ArpCache> cache,
- Address *hardwareDestination);
-protected:
- virtual void DoDispose (void);
-private:
- typedef std::list<Ptr<ArpCache> > CacheList;
- Ptr<ArpCache> FindCache (Ptr<NetDevice> device);
- void SendArpRequest (Ptr<const ArpCache>cache, Ipv4Address to);
- void SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac);
- CacheList m_cacheList;
- Ptr<Node> m_node;
- TracedCallback<Ptr<const Packet> > m_dropTrace;
-};
-
-}//namespace ns3
-
-
-#endif /* ARP_L3_PROTOCOL_H */
--- a/src/internet-node/internet-stack.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-#include "ns3/net-device.h"
-#include "ns3/callback.h"
-#include "ns3/node.h"
-
-#include "ipv4-l4-demux.h"
-#include "udp-l4-protocol.h"
-#include "tcp-l4-protocol.h"
-#include "ipv4-l3-protocol.h"
-#include "arp-l3-protocol.h"
-#include "udp-socket-factory-impl.h"
-#include "tcp-socket-factory-impl.h"
-#include "ipv4-impl.h"
-
-namespace ns3 {
-
-void
-AddInternetStack (Ptr<Node> node)
-{
- Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
- Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
- ipv4->SetNode (node);
- arp->SetNode (node);
-
- Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
- Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
- Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
-
- ipv4L4Demux->SetNode (node);
- udp->SetNode (node);
- tcp->SetNode (node);
-
- ipv4L4Demux->Insert (udp);
- ipv4L4Demux->Insert (tcp);
-
- Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
- Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
- Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
-
- udpFactory->SetUdp (udp);
- tcpFactory->SetTcp (tcp);
- ipv4Impl->SetIpv4 (ipv4);
-
- node->AggregateObject (ipv4);
- node->AggregateObject (arp);
- node->AggregateObject (ipv4Impl);
- node->AggregateObject (udpFactory);
- node->AggregateObject (tcpFactory);
- node->AggregateObject (ipv4L4Demux);
-}
-
-}//namespace ns3
--- a/src/internet-node/internet-stack.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-
-#ifndef INTERNET_STACK_H
-#define INTERNET_STACK_H
-
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Node;
-
-void AddInternetStack (Ptr<Node> node);
-
-}//namespace ns3
-
-#endif /* INTERNET_STACK_H */
--- a/src/internet-node/ipv4-checksum.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006,2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "ipv4-checksum.h"
-
-namespace ns3 {
-
-uint16_t
-Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size)
-{
- /* see RFC 1071 to understand this code. */
- uint32_t sum = checksum;
- uint16_t *data = (uint16_t *) buffer;
- for (uint16_t i = 0; i < (size/2); i++) {
- sum += data[i];
- }
- if ((size % 2) != 0) {
- uint8_t tmpBuf[2];
- tmpBuf[0] = buffer[size-1];
- tmpBuf[1] = 0;
- data = (uint16_t *)tmpBuf;
- sum += *data;
- }
- while (sum >> 16) {
- sum = (sum & 0xffff) + (sum >> 16);
- }
- return sum;
-}
-
-uint16_t
-Ipv4ChecksumComplete (uint16_t checksum)
-{
- return ~checksum;
-}
-
-}; //namespace ns3
--- a/src/internet-node/ipv4-checksum.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006,2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef IPV4_CHECKSUM_H
-#define IPV4_CHECKSUM_H
-
-#include <stdint.h>
-
-namespace ns3 {
-
-uint16_t Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size);
-
-uint16_t Ipv4ChecksumComplete (uint16_t checksum);
-
-}; //namespace ns3
-
-#endif /* IPV4_CHECKSUM_H */
--- a/src/internet-node/ipv4-end-point-demux.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ipv4-end-point-demux.h"
-#include "ipv4-end-point.h"
-#include "ns3/log.h"
-
-namespace ns3{
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux");
-
-Ipv4EndPointDemux::Ipv4EndPointDemux ()
- : m_ephemeral (49152)
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-Ipv4EndPointDemux::~Ipv4EndPointDemux ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- Ipv4EndPoint *endPoint = *i;
- delete endPoint;
- }
- m_endPoints.clear ();
-}
-
-bool
-Ipv4EndPointDemux::LookupPortLocal (uint16_t port)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- if ((*i)->GetLocalPort () == port)
- {
- return true;
- }
- }
- return false;
-}
-
-bool
-Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- if ((*i)->GetLocalPort () == port &&
- (*i)->GetLocalAddress () == addr)
- {
- return true;
- }
- }
- return false;
-}
-
-Ipv4EndPoint *
-Ipv4EndPointDemux::Allocate (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- uint16_t port = AllocateEphemeralPort ();
- if (port == 0)
- {
- NS_LOG_WARN ("Ephemeral port allocation failed.");
- return 0;
- }
- Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
- m_endPoints.push_back (endPoint);
- NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
- return endPoint;
-}
-
-Ipv4EndPoint *
-Ipv4EndPointDemux::Allocate (Ipv4Address address)
-{
- NS_LOG_FUNCTION (this << address);
- uint16_t port = AllocateEphemeralPort ();
- if (port == 0)
- {
- NS_LOG_WARN ("Ephemeral port allocation failed.");
- return 0;
- }
- Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
- m_endPoints.push_back (endPoint);
- NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
- return endPoint;
-}
-
-Ipv4EndPoint *
-Ipv4EndPointDemux::Allocate (uint16_t port)
-{
- NS_LOG_FUNCTION (this << port);
-
- return Allocate (Ipv4Address::GetAny (), port);
-}
-
-Ipv4EndPoint *
-Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port)
-{
- NS_LOG_FUNCTION (this << address << port);
- if (LookupLocal (address, port))
- {
- NS_LOG_WARN ("Duplicate address/port; failing.");
- return 0;
- }
- Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
- m_endPoints.push_back (endPoint);
- NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
- return endPoint;
-}
-
-Ipv4EndPoint *
-Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
- Ipv4Address peerAddress, uint16_t peerPort)
-{
- NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- if ((*i)->GetLocalPort () == localPort &&
- (*i)->GetLocalAddress () == localAddress &&
- (*i)->GetPeerPort () == peerPort &&
- (*i)->GetPeerAddress () == peerAddress)
- {
- NS_LOG_WARN ("No way we can allocate this end-point.");
- /* no way we can allocate this end-point. */
- return 0;
- }
- }
- Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
- endPoint->SetPeer (peerAddress, peerPort);
- m_endPoints.push_back (endPoint);
-
- NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
-
- return endPoint;
-}
-
-void
-Ipv4EndPointDemux::DeAllocate (Ipv4EndPoint *endPoint)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- if (*i == endPoint)
- {
- delete endPoint;
- m_endPoints.erase (i);
- break;
- }
- }
-}
-
-/*
- * If we have an exact match, we return it.
- * Otherwise, if we find a generic match, we return it.
- * Otherwise, we return 0.
- */
-Ipv4EndPointDemux::EndPoints
-Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
- Ipv4Address saddr, uint16_t sport,
- Ptr<Ipv4Interface> incomingInterface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- EndPoints retval1; // Matches exact on local port, wildcards on others
- EndPoints retval2; // Matches exact on local port/adder, wildcards on others
- EndPoints retval3; // Matches all but local address
- EndPoints retval4; // Exact match on all 4
-
- NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
- NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
- for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
- {
- Ipv4EndPoint* endP = *i;
- NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
- << " daddr=" << endP->GetLocalAddress ()
- << " sport=" << endP->GetPeerPort ()
- << " saddr=" << endP->GetPeerAddress ());
- if (endP->GetLocalPort () != dport)
- {
- NS_LOG_LOGIC ("Skipping endpoint " << &endP
- << " because endpoint dport "
- << endP->GetLocalPort ()
- << " does not match packet dport " << dport);
- continue;
- }
- bool isBroadcast = (daddr.IsBroadcast () ||
- daddr.IsSubnetDirectedBroadcast (
- incomingInterface->GetNetworkMask ()));
- Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress ();
- NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
- bool localAddressMatchesWildCard =
- endP->GetLocalAddress() == Ipv4Address::GetAny();
- bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
-
- if (isBroadcast)
- {
- NS_LOG_DEBUG("Found bcast, localaddr " << endP->GetLocalAddress());
- }
-
- if (isBroadcast && (endP->GetLocalAddress() != Ipv4Address::GetAny()))
- {
- localAddressMatchesExact = (endP->GetLocalAddress () ==
- incomingInterfaceAddr);
- }
- // if no match here, keep looking
- if (!(localAddressMatchesExact || localAddressMatchesWildCard))
- continue;
- bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
- bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0;
- bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
- bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
- Ipv4Address::GetAny();
- // If remote does not match either with exact or wildcard,
- // skip this one
- if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
- continue;
- if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
- continue;
-
- // Now figure out which return list to add this one to
- if (localAddressMatchesWildCard &&
- remotePeerMatchesWildCard &&
- remoteAddressMatchesWildCard)
- { // Only local port matches exactly
- retval1.push_back(endP);
- }
- if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&&
- remotePeerMatchesWildCard &&
- remoteAddressMatchesWildCard)
- { // Only local port and local address matches exactly
- retval2.push_back(endP);
- }
- if (localAddressMatchesWildCard &&
- remotePeerMatchesExact &&
- remoteAddressMatchesExact)
- { // All but local address
- retval3.push_back(endP);
- }
- if (localAddressMatchesExact &&
- remotePeerMatchesExact &&
- remoteAddressMatchesExact)
- { // All 4 match
- retval4.push_back(endP);
- }
- }
-
- // Here we find the most exact match
- if (!retval4.empty()) return retval4;
- if (!retval3.empty()) return retval3;
- if (!retval2.empty()) return retval2;
- return retval1; // might be empty if no matches
-}
-
-uint16_t
-Ipv4EndPointDemux::AllocateEphemeralPort (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- uint16_t port = m_ephemeral;
- do
- {
- port++;
- if (port == 65535)
- {
- port = 49152;
- }
- if (!LookupPortLocal (port))
- {
- return port;
- }
- } while (port != m_ephemeral);
- return 0;
-}
-
-} //namespace ns3
-
--- a/src/internet-node/ipv4-end-point-demux.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef IPV4_END_POINT_DEMUX_H
-#define IPV4_END_POINT_DEMUX_H
-
-#include <stdint.h>
-#include <list>
-#include "ns3/ipv4-address.h"
-#include "ipv4-interface.h"
-
-namespace ns3 {
-
-class Ipv4EndPoint;
-
-class Ipv4EndPointDemux {
-public:
- typedef std::list<Ipv4EndPoint *> EndPoints;
- typedef std::list<Ipv4EndPoint *>::iterator EndPointsI;
-
- Ipv4EndPointDemux ();
- ~Ipv4EndPointDemux ();
-
- bool LookupPortLocal (uint16_t port);
- bool LookupLocal (Ipv4Address addr, uint16_t port);
- EndPoints Lookup (Ipv4Address daddr,
- uint16_t dport,
- Ipv4Address saddr,
- uint16_t sport,
- Ptr<Ipv4Interface> incomingInterface);
-
- Ipv4EndPoint *Allocate (void);
- Ipv4EndPoint *Allocate (Ipv4Address address);
- Ipv4EndPoint *Allocate (uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address localAddress,
- uint16_t localPort,
- Ipv4Address peerAddress,
- uint16_t peerPort);
-
- void DeAllocate (Ipv4EndPoint *endPoint);
-
- private:
- uint16_t AllocateEphemeralPort (void);
-
- uint16_t m_ephemeral;
- EndPoints m_endPoints;
-};
-
-} // namespace ns3
-
-#endif /* IPV4_END_POINTS_H */
--- a/src/internet-node/ipv4-end-point.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ipv4-end-point.h"
-#include "ns3/packet.h"
-
-namespace ns3 {
-
-Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port)
- : m_localAddr (address),
- m_localPort (port),
- m_peerAddr (Ipv4Address::GetAny ()),
- m_peerPort (0)
-{}
-Ipv4EndPoint::~Ipv4EndPoint ()
-{
- if (!m_destroyCallback.IsNull ())
- {
- m_destroyCallback ();
- }
-}
-
-Ipv4Address
-Ipv4EndPoint::GetLocalAddress (void)
-{
- return m_localAddr;
-}
-
-void
-Ipv4EndPoint::SetLocalAddress (Ipv4Address address)
-{
- m_localAddr = address;
-}
-
-uint16_t
-Ipv4EndPoint::GetLocalPort (void)
-{
- return m_localPort;
-}
-Ipv4Address
-Ipv4EndPoint::GetPeerAddress (void)
-{
- return m_peerAddr;
-}
-uint16_t
-Ipv4EndPoint::GetPeerPort (void)
-{
- return m_peerPort;
-}
-void
-Ipv4EndPoint::SetPeer (Ipv4Address address, uint16_t port)
-{
- m_peerAddr = address;
- m_peerPort = port;
-}
-
-void
-Ipv4EndPoint::SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> callback)
-{
- m_rxCallback = callback;
-}
-
-void
-Ipv4EndPoint::SetDestroyCallback (Callback<void> callback)
-{
- m_destroyCallback = callback;
-}
-
-void
-Ipv4EndPoint::ForwardUp (Ptr<Packet> p, Ipv4Address saddr, uint16_t sport)
-{
- if (!m_rxCallback.IsNull ())
- {
- m_rxCallback (p, saddr, sport);
- }
-}
-
-
-
-}; // namespace ns3
--- a/src/internet-node/ipv4-end-point.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef IPV4_END_POINT_H
-#define IPV4_END_POINT_H
-
-#include <stdint.h>
-#include "ns3/ipv4-address.h"
-#include "ns3/callback.h"
-
-namespace ns3 {
-
-class Header;
-class Packet;
-
-class Ipv4EndPoint {
-public:
- Ipv4EndPoint (Ipv4Address address, uint16_t port);
- ~Ipv4EndPoint ();
-
- Ipv4Address GetLocalAddress (void);
- void SetLocalAddress (Ipv4Address address);
- uint16_t GetLocalPort (void);
- Ipv4Address GetPeerAddress (void);
- uint16_t GetPeerPort (void);
-
- void SetPeer (Ipv4Address address, uint16_t port);
-
- void SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> callback);
- void SetDestroyCallback (Callback<void> callback);
-
- void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, uint16_t sport);
-
-private:
- Ipv4Address m_localAddr;
- uint16_t m_localPort;
- Ipv4Address m_peerAddr;
- uint16_t m_peerPort;
- Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> m_rxCallback;
- Callback<void> m_destroyCallback;
-};
-
-}; // namespace ns3
-
-
-#endif /* IPV4_END_POINT_H */
--- a/src/internet-node/ipv4-impl.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "ipv4-impl.h"
-#include "ipv4-l3-protocol.h"
-#include "ipv4-interface.h"
-#include "ns3/assert.h"
-#include "ns3/net-device.h"
-
-namespace ns3 {
-
-Ipv4Impl::Ipv4Impl ()
- : m_ipv4 (0)
-{}
-Ipv4Impl::~Ipv4Impl ()
-{
- NS_ASSERT (m_ipv4 == 0);
-}
-void
-Ipv4Impl::SetIpv4 (Ptr<Ipv4L3Protocol> ipv4)
-{
- m_ipv4 = ipv4;
-}
-void
-Ipv4Impl::DoDispose (void)
-{
- m_ipv4 = 0;
-}
-
-void
-Ipv4Impl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
- int16_t priority)
-{
- m_ipv4->AddRoutingProtocol (routingProtocol, priority);
-}
-
-void
-Ipv4Impl::AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- m_ipv4->AddHostRouteTo (dest, nextHop, interface);
-}
-void
-Ipv4Impl::AddHostRouteTo (Ipv4Address dest,
- uint32_t interface)
-{
- m_ipv4->AddHostRouteTo (dest, interface);
-}
-void
-Ipv4Impl::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- m_ipv4->AddNetworkRouteTo (network, networkMask, nextHop, interface);
-}
-void
-Ipv4Impl::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface)
-{
- m_ipv4->AddNetworkRouteTo (network, networkMask, interface);
-}
-void
-Ipv4Impl::SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface)
-{
- m_ipv4->SetDefaultRoute (nextHop, interface);
-}
-uint32_t
-Ipv4Impl::GetNRoutes (void)
-{
- return m_ipv4->GetNRoutes ();
-}
-Ipv4Route
-Ipv4Impl::GetRoute (uint32_t i)
-{
- return *m_ipv4->GetRoute (i);
-}
-void
-Ipv4Impl::RemoveRoute (uint32_t i)
-{
- return m_ipv4->RemoveRoute (i);
-}
-
-void
-Ipv4Impl::AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces)
-{
- m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces);
-}
-
-void
-Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface)
-{
- m_ipv4->SetDefaultMulticastRoute (outputInterface);
-}
-
-uint32_t
-Ipv4Impl::GetNMulticastRoutes (void) const
-{
- return m_ipv4->GetNMulticastRoutes ();
-}
-
-Ipv4MulticastRoute
-Ipv4Impl::GetMulticastRoute (uint32_t i) const
-{
- return *m_ipv4->GetMulticastRoute (i);
-}
-
-void
-Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface)
-{
- m_ipv4->RemoveMulticastRoute (origin, group, inputInterface);
-}
-
-void
-Ipv4Impl::RemoveMulticastRoute (uint32_t i)
-{
- return m_ipv4->RemoveMulticastRoute (i);
-}
-
-uint32_t
-Ipv4Impl::AddInterface (Ptr<NetDevice> device)
-{
- return m_ipv4->AddInterface (device);
-}
-
-uint32_t
-Ipv4Impl::GetNInterfaces (void)
-{
- return m_ipv4->GetNInterfaces ();
-}
-
-uint32_t
-Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const
-{
- return m_ipv4->FindInterfaceForAddr (addr);
-}
-
-uint32_t
-Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
-{
- return m_ipv4->FindInterfaceForAddr (addr, mask);
-}
-
-int32_t
-Ipv4Impl::FindInterfaceForDevice (Ptr<NetDevice> device) const
-{
- return m_ipv4->FindInterfaceIndexForDevice (device);
-}
-
-Ptr<NetDevice>
-Ipv4Impl::GetNetDevice (uint32_t i)
-{
- return m_ipv4->GetInterface (i)-> GetDevice ();
-}
-
-void
-Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- m_ipv4->JoinMulticastGroup(origin, group);
-}
-
-void
-Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- m_ipv4->LeaveMulticastGroup(origin, group);
-}
-
-void
-Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address)
-{
- m_ipv4->SetAddress (i, address);
-}
-void
-Ipv4Impl::SetNetworkMask (uint32_t i, Ipv4Mask mask)
-{
- m_ipv4->SetNetworkMask (i, mask);
-}
-Ipv4Mask
-Ipv4Impl::GetNetworkMask (uint32_t i) const
-{
- return m_ipv4->GetNetworkMask (i);
-}
-
-Ipv4Address
-Ipv4Impl::GetAddress (uint32_t i) const
-{
- return m_ipv4->GetAddress (i);
-}
-
-void
-Ipv4Impl::SetMetric (uint32_t i, uint16_t metric)
-{
- m_ipv4->SetMetric (i, metric);
-}
-
-uint16_t
-Ipv4Impl::GetMetric (uint32_t i) const
-{
- return m_ipv4->GetMetric (i);
-}
-
-bool
-Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const
-{
- return m_ipv4->GetIfIndexForDestination (dest, ifIndex);
-}
-
-Ipv4Address
-Ipv4Impl::GetSourceAddress (Ipv4Address destination) const
-{
- uint32_t ifIndex = 0xffffffff;
-
- bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex);
-
- if (result)
- {
- return m_ipv4->GetAddress (ifIndex);
- }
- else
- {
-//
-// If we can't find any address, just leave it 0.0.0.0
-//
- return Ipv4Address::GetAny ();
- }
-}
-
-uint16_t
-Ipv4Impl::GetMtu (uint32_t i) const
-{
- return m_ipv4->GetMtu (i);
-}
-bool
-Ipv4Impl::IsUp (uint32_t i) const
-{
- return m_ipv4->IsUp (i);
-}
-void
-Ipv4Impl::SetUp (uint32_t i)
-{
- m_ipv4->SetUp (i);
-}
-void
-Ipv4Impl::SetDown (uint32_t i)
-{
- m_ipv4->SetDown (i);
-}
-
-}//namespace ns3
--- a/src/internet-node/ipv4-impl.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef IPV4_IMPL_H
-#define IPV4_IMPL_H
-
-#include "ns3/ipv4.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Ipv4L3Protocol;
-
-class Ipv4Impl : public Ipv4
-{
-public:
- Ipv4Impl ();
-
- virtual ~Ipv4Impl ();
-
- void SetIpv4 (Ptr<Ipv4L3Protocol> ipv4);
-
- virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
- int16_t priority);
-
- virtual void AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface);
- virtual void AddHostRouteTo (Ipv4Address dest,
- uint32_t interface);
- virtual void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface);
- virtual void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface);
- virtual void SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface);
- virtual uint32_t GetNRoutes (void);
- virtual Ipv4Route GetRoute (uint32_t i);
- virtual void RemoveRoute (uint32_t i);
-
-
- virtual void AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces);
-
- virtual void SetDefaultMulticastRoute (uint32_t outputInterface);
-
- virtual uint32_t GetNMulticastRoutes (void) const;
- virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const;
-
- virtual void RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface);
- virtual void RemoveMulticastRoute (uint32_t i);
-
- virtual uint32_t AddInterface (Ptr<NetDevice> device);
- virtual uint32_t GetNInterfaces (void);
-
- virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
- virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
- Ipv4Mask mask) const;
-
- virtual int32_t FindInterfaceForDevice (Ptr<NetDevice> device) const;
-
- virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
-
- virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
- virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
-
- virtual void SetAddress (uint32_t i, Ipv4Address address);
- virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
- virtual Ipv4Mask GetNetworkMask (uint32_t t) const;
- virtual Ipv4Address GetAddress (uint32_t i) const;
- virtual void SetMetric (uint32_t i, uint16_t metric);
- virtual uint16_t GetMetric (uint32_t i) const;
- virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const;
- virtual bool GetIfIndexForDestination (Ipv4Address dest,
- uint32_t &ifIndex) const;
-
- virtual uint16_t GetMtu (uint32_t i) const;
- virtual bool IsUp (uint32_t i) const;
- virtual void SetUp (uint32_t i);
- virtual void SetDown (uint32_t i);
-protected:
- virtual void DoDispose (void);
-private:
- Ptr<Ipv4L3Protocol> m_ipv4;
-};
-
-} // namespace ns3
-
-#endif /* IPV4_IMPL_H */
--- a/src/internet-node/ipv4-interface.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006,2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ipv4-interface.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/net-device.h"
-#include "ns3/log.h"
-#include "ns3/packet.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4Interface");
-
-namespace ns3 {
-
-TypeId
-Ipv4Interface::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4Interface")
- .SetParent<Object> ()
- ;
- return tid;
-}
-
- /**
- * By default, Ipv4 interface are created in the "down" state
- * with ip address 192.168.0.1 and a matching mask. Before
- * becoming useable, the user must invoke SetUp on them
- * once the final Ipv4 address and mask has been set.
- */
-Ipv4Interface::Ipv4Interface ()
- : m_ifup(false),
- m_metric(1)
-{
- NS_LOG_FUNCTION (this);
-}
-
-Ipv4Interface::~Ipv4Interface ()
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-void
-Ipv4Interface::DoDispose (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Object::DoDispose ();
-}
-
-void
-Ipv4Interface::SetAddress (Ipv4Address a)
-{
- NS_LOG_FUNCTION (this << a);
- m_address = a;
-}
-
-void
-Ipv4Interface::SetNetworkMask (Ipv4Mask mask)
-{
- NS_LOG_FUNCTION (this << mask);
- m_netmask = mask;
-}
-
-Ipv4Address
-Ipv4Interface::GetBroadcast (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- uint32_t mask = m_netmask.Get ();
- uint32_t address = m_address.Get ();
- Ipv4Address broadcast = Ipv4Address (address | (~mask));
- return broadcast;
-}
-
-Ipv4Mask
-Ipv4Interface::GetNetworkMask (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_netmask;
-}
-
-void
-Ipv4Interface::SetMetric (uint16_t metric)
-{
- NS_LOG_FUNCTION (metric);
- m_metric = metric;
-}
-
-uint16_t
-Ipv4Interface::GetMetric (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_metric;
-}
-
-Ipv4Address
-Ipv4Interface::GetAddress (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_address;
-}
-
-uint16_t
-Ipv4Interface::GetMtu (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (GetDevice () == 0)
- {
- uint32_t mtu = (1<<16) - 1;
- return mtu;
- }
- return GetDevice ()->GetMtu ();
-}
-
-/**
- * These are IP interface states and may be distinct from
- * NetDevice states, such as found in real implementations
- * (where the device may be down but IP interface state is still up).
- */
-bool
-Ipv4Interface::IsUp (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_ifup;
-}
-
-bool
-Ipv4Interface::IsDown (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return !m_ifup;
-}
-
-void
-Ipv4Interface::SetUp (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_ifup = true;
-}
-
-void
-Ipv4Interface::SetDown (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_ifup = false;
-}
-
-// public wrapper on private virtual function
-void
-Ipv4Interface::Send(Ptr<Packet> p, Ipv4Address dest)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (IsUp()) {
- NS_LOG_LOGIC ("SendTo");
- SendTo(p, dest);
- }
-}
-
-}; // namespace ns3
-
--- a/src/internet-node/ipv4-interface.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006,2007 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:
- * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- * Tom Henderson <tomh@tomh.org>
- */
-#ifndef IPV4_INTERFACE_H
-#define IPV4_INTERFACE_H
-
-#include <list>
-#include "ns3/ipv4-address.h"
-#include "ns3/ptr.h"
-#include "ns3/object.h"
-
-namespace ns3 {
-
-class NetDevice;
-class Packet;
-
-/**
- * \brief The IPv4 representation of a network interface
- *
- * This class roughly corresponds to the struct in_device
- * of Linux; the main purpose is to provide address-family
- * specific information (addresses) about an interface.
- *
- * This class defines two APIs:
- * - the public API which is expected to be used by both
- * the IPv4 layer and the user during forwarding and
- * configuration.
- * - the private API which is expected to be implemented
- * by subclasses of this base class. One such subclass
- * will be a Loopback interface which loops every
- * packet sent back to the ipv4 layer. Another such
- * subclass typically contains the Ipv4 <-> MAC address
- * translation logic which will use most of the time the
- * ARP/RARP protocols.
- *
- * By default, Ipv4 interface are created in the "down" state
- * with ip address 192.168.0.1 and a matching mask. Before
- * becoming useable, the user must invoke SetUp on them
- * once the final Ipv4 address and mask has been set.
- *
- * Subclasses must implement the two methods:
- * - Ipv4Interface::SendTo
- */
-class Ipv4Interface : public Object
-{
-public:
- static TypeId GetTypeId (void);
-
- Ipv4Interface ();
- virtual ~Ipv4Interface();
-
- /**
- * \returns the underlying NetDevice. This method can return
- * zero if this interface has no associated NetDevice.
- */
- virtual Ptr<NetDevice> GetDevice (void) const = 0;
-
- /**
- * \param a set the ipv4 address of this interface.
- */
- void SetAddress (Ipv4Address a);
- /**
- * \param mask set the ipv4 netmask of this interface.
- */
- void SetNetworkMask (Ipv4Mask mask);
-
- /**
- * \returns the broadcast ipv4 address associated to this interface
- */
- Ipv4Address GetBroadcast (void) const;
- /**
- * \returns the ipv4 netmask of this interface
- */
- Ipv4Mask GetNetworkMask (void) const;
- /**
- * \param metric configured routing metric (cost) of this interface
- */
- void SetMetric (uint16_t metric);
- /**
- * \returns configured routing metric (cost) of this interface
- */
- uint16_t GetMetric (void) const;
- /**
- * \returns the ipv4 address of this interface
- */
- Ipv4Address GetAddress (void) const;
-
- /**
- * This function a pass-through to NetDevice GetMtu, modulo
- * the LLC/SNAP header i.e., ipv4MTU = NetDeviceMtu - LLCSNAPSIZE
- * \returns the Maximum Transmission Unit associated to this interface.
- */
- uint16_t GetMtu (void) const;
-
- /**
- * These are IP interface states and may be distinct from
- * NetDevice states, such as found in real implementations
- * (where the device may be down but IP interface state is still up).
- */
- /**
- * \returns true if this interface is enabled, false otherwise.
- */
- bool IsUp (void) const;
- /**
- * \returns true if this interface is disabled, false otherwise.
- */
- bool IsDown (void) const;
- /**
- * Enable this interface
- */
- void SetUp (void);
- /**
- * Disable this interface
- */
- void SetDown (void);
-
- /**
- * \param p packet to send
- * \param dest next hop address of packet.
- *
- * This method will eventually call the private
- * SendTo method which must be implemented by subclasses.
- */
- void Send(Ptr<Packet> p, Ipv4Address dest);
-
-protected:
- virtual void DoDispose (void);
-private:
- virtual void SendTo (Ptr<Packet> p, Ipv4Address dest) = 0;
- bool m_ifup;
- Ipv4Address m_address;
- Ipv4Mask m_netmask;
- uint16_t m_metric;
-};
-
-}; // namespace ns3
-
-#endif
--- a/src/internet-node/ipv4-l3-protocol.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,906 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-#include "ns3/packet.h"
-#include "ns3/log.h"
-#include "ns3/callback.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/node.h"
-#include "ns3/socket.h"
-#include "ns3/net-device.h"
-#include "ns3/uinteger.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/object-vector.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/boolean.h"
-#include "arp-l3-protocol.h"
-
-#include "ipv4-l3-protocol.h"
-#include "ipv4-l4-protocol.h"
-#include "ipv4-interface.h"
-#include "ipv4-loopback-interface.h"
-#include "arp-ipv4-interface.h"
-#include "ipv4-l4-demux.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
-
-namespace ns3 {
-
-const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
-
-TypeId
-Ipv4L3Protocol::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
- .SetParent<Object> ()
- .AddConstructor<Ipv4L3Protocol> ()
- .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
- UintegerValue (64),
- MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
- MakeUintegerChecker<uint8_t> ())
- .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets"
- " and verify the checksum of incoming packets.",
- BooleanValue (false),
- MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum),
- MakeBooleanChecker ())
- .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
- MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
- .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
- MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
- .AddTraceSource ("Drop", "Drop ipv4 packet",
- MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
- .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
- ObjectVectorValue (),
- MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
- MakeObjectVectorChecker<Ipv4Interface> ())
- ;
- return tid;
-}
-
-Ipv4L3Protocol::Ipv4L3Protocol()
- : m_nInterfaces (0),
- m_identification (0)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_staticRouting = CreateObject<Ipv4StaticRouting> ();
- AddRoutingProtocol (m_staticRouting, 0);
-}
-
-Ipv4L3Protocol::~Ipv4L3Protocol ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-void
-Ipv4L3Protocol::SetNode (Ptr<Node> node)
-{
- m_node = node;
- SetupLoopback ();
-}
-
-void
-Ipv4L3Protocol::DoDispose (void)
-{
- NS_LOG_FUNCTION (this);
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
- {
- Ptr<Ipv4Interface> interface = *i;
- interface->Dispose ();
- }
- m_interfaces.clear ();
- m_node = 0;
- m_staticRouting->Dispose ();
- m_staticRouting = 0;
- Object::DoDispose ();
-}
-
-void
-Ipv4L3Protocol::SetupLoopback (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
-
- Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
- interface->SetNode (m_node);
- interface->SetAddress (Ipv4Address::GetLoopback ());
- interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
- uint32_t index = AddIpv4Interface (interface);
- AddHostRouteTo (Ipv4Address::GetLoopback (), index);
- interface->SetUp ();
-}
-
-void
-Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_defaultTtl = ttl;
-}
-
-
-void
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << dest << nextHop << interface);
- m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << dest << interface);
- m_staticRouting->AddHostRouteTo (dest, interface);
-}
-
-void
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
- m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << network << networkMask << interface);
- m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
-}
-
-void
-Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << nextHop << interface);
- m_staticRouting->SetDefaultRoute (nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::Lookup (
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
- NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
-
- Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
-}
-
-void
-Ipv4L3Protocol::Lookup (
- uint32_t ifIndex,
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
- NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
-
- for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
- m_routingProtocols.begin ();
- rprotoIter != m_routingProtocols.end ();
- rprotoIter++)
- {
- NS_LOG_LOGIC ("Requesting route");
- if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet,
- routeReply))
- return;
- }
-
- if (ipHeader.GetDestination ().IsMulticast () &&
- ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
- {
- NS_LOG_LOGIC ("Multicast destination with local source");
-//
-// We have a multicast packet originating from the current node and were not
-// able to send it using the usual RequestRoute process. Since the usual
-// process includes trying to use a default multicast route, this means that
-// there was no specific route out of the node found, and there was no default
-// multicast route set.
-//
-// The fallback position is to look for a default unicast route and use that
-// to get the packet off the node if we have one.
-//
- Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
- if (route)
- {
- NS_LOG_LOGIC ("Local source. Using unicast default route for "
- "multicast packet");
-
- routeReply (true, *route, packet, ipHeader);
- return;
- }
- }
-//
-// No route found
-//
- routeReply (false, Ipv4Route (), packet, ipHeader);
-}
-
-void
-Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
- int priority)
-{
- NS_LOG_FUNCTION (this << &routingProtocol << priority);
- m_routingProtocols.push_back
- (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
- m_routingProtocols.sort ();
-}
-
-uint32_t
-Ipv4L3Protocol::GetNRoutes (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_staticRouting->GetNRoutes ();
-}
-
-Ipv4Route *
-Ipv4L3Protocol::GetRoute (uint32_t index)
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_staticRouting->GetRoute (index);
-}
-
-void
-Ipv4L3Protocol::RemoveRoute (uint32_t index)
-{
- NS_LOG_FUNCTION (this << index);
- m_staticRouting->RemoveRoute (index);
-}
-
-void
-Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces)
-{
- NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
-
- m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
- outputInterfaces);
-}
-
-void
-Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
-{
- NS_LOG_FUNCTION (this << outputInterface);
-
- m_staticRouting->SetDefaultMulticastRoute (outputInterface);
-}
-
-uint32_t
-Ipv4L3Protocol::GetNMulticastRoutes (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_staticRouting->GetNMulticastRoutes ();
-}
-
-Ipv4MulticastRoute *
-Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
-{
- NS_LOG_FUNCTION (this << index);
- return m_staticRouting->GetMulticastRoute (index);
-}
-
-void
-Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface)
-{
- NS_LOG_FUNCTION (this << origin << group << inputInterface);
- m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
-}
-
-void
-Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
-{
- NS_LOG_FUNCTION (this << index);
- m_staticRouting->RemoveMulticastRoute (index);
-}
-
-uint32_t
-Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
-{
- NS_LOG_FUNCTION (this << &device);
-
- Ptr<Node> node = GetObject<Node> ();
- node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
- Ipv4L3Protocol::PROT_NUMBER, device);
- node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
- ArpL3Protocol::PROT_NUMBER, device);
-
- Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
- interface->SetNode (m_node);
- interface->SetDevice (device);
- return AddIpv4Interface (interface);
-}
-
-uint32_t
-Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
-{
- NS_LOG_FUNCTION (this << interface);
- uint32_t index = m_nInterfaces;
- m_interfaces.push_back (interface);
- m_nInterfaces++;
- return index;
-}
-
-Ptr<Ipv4Interface>
-Ipv4L3Protocol::GetInterface (uint32_t index) const
-{
- NS_LOG_FUNCTION (this << index);
- uint32_t tmp = 0;
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
- {
- if (index == tmp)
- {
- return *i;
- }
- tmp++;
- }
- return 0;
-}
-
-uint32_t
-Ipv4L3Protocol::GetNInterfaces (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_nInterfaces;
-}
-
-uint32_t
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
-{
- NS_LOG_FUNCTION (this << addr);
-
- uint32_t ifIndex = 0;
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end ();
- i++, ifIndex++)
- {
- if ((*i)->GetAddress () == addr)
- {
- return ifIndex;
- }
- }
-
- NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
- "Interface not found for IP address " << addr);
- return 0;
-}
-
-uint32_t
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
-{
- NS_LOG_FUNCTION (this << addr << mask);
-
- uint32_t ifIndex = 0;
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end ();
- i++, ifIndex++)
- {
- if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
- {
- return ifIndex;
- }
- }
-
- NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
- "Interface not found for masked IP address");
- return 0;
-}
-
-int32_t
-Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const
-{
- NS_LOG_FUNCTION (this << device);
-
- uint32_t ifIndex = 0;
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end ();
- i++, ifIndex++)
- {
- if ((*i)->GetDevice () == device)
- {
- return ifIndex;
- }
- }
-
- return -1;
-}
-
-Ptr<Ipv4Interface>
-Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
-{
- NS_LOG_FUNCTION (this << &device);
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
- {
- if ((*i)->GetDevice () == device)
- {
- return *i;
- }
- }
- return 0;
-}
-
-void
-Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
-{
- NS_LOG_FUNCTION (this << &device << packet << protocol << from);
-
- NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
-
- uint32_t index = 0;
- Ptr<Ipv4Interface> ipv4Interface;
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end ();
- i++)
- {
- ipv4Interface = *i;
- if (ipv4Interface->GetDevice () == device)
- {
- m_rxTrace (packet, index);
- break;
- }
- index++;
- }
- Ipv4Header ipHeader;
- if (m_calcChecksum)
- {
- ipHeader.EnableChecksum ();
- }
- packet->RemoveHeader (ipHeader);
-
- if (!ipHeader.IsChecksumOk ())
- {
- m_dropTrace (packet);
- return;
- }
-
- if (Forwarding (index, packet, ipHeader, device))
- {
- return;
- }
-
- ForwardUp (packet, ipHeader, ipv4Interface);
-}
-
-
-void
-Ipv4L3Protocol::Send (Ptr<Packet> packet,
- Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol)
-{
- NS_LOG_FUNCTION (this << packet << source << destination << protocol);
-
- Ipv4Header ipHeader;
-
- if (m_calcChecksum)
- {
- ipHeader.EnableChecksum ();
- }
-
- ipHeader.SetSource (source);
- ipHeader.SetDestination (destination);
- ipHeader.SetProtocol (protocol);
- ipHeader.SetPayloadSize (packet->GetSize ());
- ipHeader.SetTtl (m_defaultTtl);
- ipHeader.SetMayFragment ();
- ipHeader.SetIdentification (m_identification);
-
- m_identification ++;
-
- // Set TTL to 1 if it is a broadcast packet of any type. Otherwise,
- // possibly override the default TTL if the packet is tagged
- SocketIpTtlTag tag;
- bool found = packet->FindFirstMatchingTag (tag);
-
- if (destination.IsBroadcast ())
- {
- ipHeader.SetTtl (1);
- }
- else if (found)
- {
- ipHeader.SetTtl (tag.GetTtl ());
- // XXX remove tag here?
- }
- else
- {
- uint32_t ifaceIndex = 0;
- for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
- ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
- {
- Ptr<Ipv4Interface> outInterface = *ifaceIter;
- if (destination.IsSubnetDirectedBroadcast (
- outInterface->GetNetworkMask ()))
- {
- ipHeader.SetTtl (1);
- }
- }
- }
- if (destination.IsBroadcast ())
- {
- uint32_t ifaceIndex = 0;
- for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
- ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
- {
- Ptr<Ipv4Interface> outInterface = *ifaceIter;
- Ptr<Packet> packetCopy = packet->Copy ();
-
- NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
- packetCopy->AddHeader (ipHeader);
- m_txTrace (packetCopy, ifaceIndex);
- outInterface->Send (packetCopy, destination);
- }
- }
- else
- {
- // XXX Note here that in most ipv4 stacks in the world,
- // the route calculation for an outgoing packet is not
- // done in the ip layer. It is done within the application
- // socket when the first packet is sent to avoid this
- // costly lookup on a per-packet basis.
- // That would require us to get the route from the packet,
- // most likely with a packet tag. The higher layers do not
- // do this yet for us.
- Lookup (ipHeader, packet,
- MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
- }
-}
-
-void
-Ipv4L3Protocol::SendRealOut (bool found,
- Ipv4Route const &route,
- Ptr<Packet> packet,
- Ipv4Header const &ipHeader)
-{
- NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
-
- packet->AddHeader (ipHeader);
- if (!found)
- {
- NS_LOG_WARN ("No route to host. Drop.");
- m_dropTrace (packet);
- return;
- }
-
- NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
-
- Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
- NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
- m_txTrace (packet, route.GetInterface ());
- if (route.IsGateway ())
- {
- NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
- outInterface->Send (packet, route.GetGateway ());
- }
- else
- {
- NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
- outInterface->Send (packet, ipHeader.GetDestination ());
- }
-}
-
-bool
-Ipv4L3Protocol::Forwarding (
- uint32_t ifIndex,
- Ptr<Packet> packet,
- Ipv4Header &ipHeader,
- Ptr<NetDevice> device)
-{
- NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device);
- NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
-
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end (); i++)
- {
- if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ()))
- {
- NS_LOG_LOGIC ("For me (destination match)");
- return false;
- }
- }
-
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end (); i++)
- {
- Ptr<Ipv4Interface> interface = *i;
- if (interface->GetDevice () == device)
- {
- if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ()))
- {
- NS_LOG_LOGIC ("For me (interface broadcast address)");
- return false;
- }
- break;
- }
- }
-
- if (ipHeader.GetDestination ().IsBroadcast ())
- {
- NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
- return false;
- }
-
- if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ()))
- {
- NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
- return false;
- }
-
- if (ipHeader.GetTtl () == 1)
- {
- // Should send ttl expired here
- // XXX
- NS_LOG_LOGIC ("Not for me (TTL expired). Drop");
- m_dropTrace (packet);
- return true;
- }
- ipHeader.SetTtl (ipHeader.GetTtl () - 1);
-
-//
-// If this is a to a multicast address and this node is a member of the
-// indicated group we need to return false so the multicast is forwarded up.
-//
- for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
- i != m_multicastGroups.end (); i++)
- {
- if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
- (*i).second.IsEqual (ipHeader.GetDestination ()))
- {
- NS_LOG_LOGIC ("For me (Joined multicast group)");
- // We forward with a packet copy, since forwarding may change
- // the packet, affecting our local delivery
- NS_LOG_LOGIC ("Forwarding (multicast).");
- Lookup (ifIndex, ipHeader, packet->Copy (),
- MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
- return false;
- }
- }
- NS_LOG_LOGIC ("Not for me, forwarding.");
- Lookup (ifIndex, ipHeader, packet,
- MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
-
- return true;
-}
-
-void
-Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
- Ptr<Ipv4Interface> incomingInterface)
-{
- NS_LOG_FUNCTION (this << p << &ip);
-
- Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> ();
- Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ());
- protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
-}
-
-void
-Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- NS_LOG_FUNCTION (this << origin << group);
- m_multicastGroups.push_back(
- std::pair<Ipv4Address, Ipv4Address> (origin, group));
-}
-
-void
-Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- NS_LOG_FUNCTION (this << origin << group);
-
- for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
- i != m_multicastGroups.end ();
- i++)
- {
- if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
- {
- m_multicastGroups.erase (i);
- return;
- }
- }
-}
-
-void
-Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
-{
- NS_LOG_FUNCTION (this << i << address);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- interface->SetAddress (address);
-}
-
-void
-Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
-{
- NS_LOG_FUNCTION (this << i << mask);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- interface->SetNetworkMask (mask);
-}
-
-Ipv4Mask
-Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
-{
- NS_LOG_FUNCTION (this << i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- return interface->GetNetworkMask ();
-}
-
-Ipv4Address
-Ipv4L3Protocol::GetAddress (uint32_t i) const
-{
- NS_LOG_FUNCTION (this << i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- return interface->GetAddress ();
-}
-
-void
-Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
-{
- NS_LOG_FUNCTION (i << metric);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- interface->SetMetric (metric);
-}
-
-uint16_t
-Ipv4L3Protocol::GetMetric (uint32_t i) const
-{
- NS_LOG_FUNCTION (i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- return interface->GetMetric ();
-}
-
-bool
-Ipv4L3Protocol::GetIfIndexForDestination (
- Ipv4Address destination, uint32_t& ifIndex) const
-{
- NS_LOG_FUNCTION (this << destination << &ifIndex);
-//
-// The first thing we do in trying to determine a source address is to
-// consult the routing protocols. These will also check for a default route
-// if one has been set.
-//
- for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
- i != m_routingProtocols.end ();
- i++)
- {
- NS_LOG_LOGIC ("Requesting Source Address");
- uint32_t ifIndexTmp;
-
- if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
- {
- NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp);
- ifIndex = ifIndexTmp;
- return true;
- }
- }
-//
-// If there's no routing table entry telling us what *single* interface will
-// be used to send a packet to this destination, we'll have to just pick one.
-// If there's only one interface on this node, a good answer isn't very hard
-// to come up with. Before jumping to any conclusions, remember that the
-// zeroth interface is the loopback interface, so what we actually want is
-// a situation where there are exactly two interfaces on the node, in which
-// case interface one is the "single" interface connected to the outside world.
-//
- if (GetNInterfaces () == 2)
- {
- NS_LOG_LOGIC ("One Interface. Using interface 1.");
- ifIndex = 1;
- return true;
- }
-//
-// If we fall through to here, we have a node with multiple interfaces and
-// no routes to guide us in determining what interface to choose. Either
-// no default route was found (for unicast or multicast), or in the case of a
-// multicast, the default route contained multiple outbound interfaces.
-//
-// The fallback position is to just get the unicast default route and use
-// the outgoing interface specified there. We don't want to leave the source
-// address unset, so we just assert here.
-//
-// N.B. that in the case of a multicast with a route containing multiple
-// outgoing interfaces, the source address of packets from that node will be
-// set to the IP address of the interface set in the default unicast route.
-// Also, in the case of a broadcast, the same will be true.
-//
- NS_LOG_LOGIC ("Using default unicast route");
- Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
- if (route == NULL)
- {
- NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): "
- "Unable to determine outbound interface. No default route set");
- return false;
- }
-
- ifIndex = route->GetInterface ();
-
- NS_LOG_LOGIC ("Default route specifies interface " << ifIndex);
- return true;
-}
-
-uint16_t
-Ipv4L3Protocol::GetMtu (uint32_t i) const
-{
- NS_LOG_FUNCTION (this << i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- return interface->GetMtu ();
-}
-
-bool
-Ipv4L3Protocol::IsUp (uint32_t i) const
-{
- NS_LOG_FUNCTION (this << i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- return interface->IsUp ();
-}
-
-void
-Ipv4L3Protocol::SetUp (uint32_t i)
-{
- NS_LOG_FUNCTION (this << i);
- Ptr<Ipv4Interface> interface = GetInterface (i);
- interface->SetUp ();
-
- // If interface address and network mask have been set, add a route
- // to the network of the interface (like e.g. ifconfig does on a
- // Linux box)
- if ((interface->GetAddress ()) != (Ipv4Address ())
- && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
- {
- AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
- interface->GetNetworkMask (), i);
- }
-}
-
-void
-Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
-{
- NS_LOG_FUNCTION (this << ifaceIndex);
- Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
- interface->SetDown ();
-
- // Remove all routes that are going through this interface
- bool modified = true;
- while (modified)
- {
- modified = false;
- for (uint32_t i = 0; i < GetNRoutes (); i++)
- {
- Ipv4Route *route = GetRoute (i);
- if (route->GetInterface () == ifaceIndex)
- {
- RemoveRoute (i);
- modified = true;
- break;
- }
- }
- }
-}
-
-}//namespace ns3
--- a/src/internet-node/ipv4-l3-protocol.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-#ifndef IPV4_L3_PROTOCOL_H
-#define IPV4_L3_PROTOCOL_H
-
-#include <list>
-#include <stdint.h>
-#include "ns3/ipv4-address.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4.h"
-#include "ns3/traced-callback.h"
-#include "ns3/ipv4-header.h"
-#include "ipv4-static-routing.h"
-
-namespace ns3 {
-
-class Packet;
-class NetDevice;
-class Ipv4Interface;
-class Ipv4Address;
-class Ipv4Header;
-class Ipv4Route;
-class Node;
-
-
-/**
- * \brief Implement the Ipv4 layer.
- */
-class Ipv4L3Protocol : public Object
-{
-public:
- static TypeId GetTypeId (void);
- static const uint16_t PROT_NUMBER;
-
- Ipv4L3Protocol();
- virtual ~Ipv4L3Protocol ();
-
- void SetNode (Ptr<Node> node);
-
- /**
- * \param ttl default ttl to use
- *
- * When we need to send an ipv4 packet, we use this default
- * ttl value.
- */
- void SetDefaultTtl (uint8_t ttl);
-
- /**
- * \param device the device to match
- * \returns the matching interface, zero if not found.
- *
- * Try to find an Ipv4Interface whose NetDevice is equal to
- * the input NetDevice.
- */
- Ptr<Ipv4Interface> FindInterfaceForDevice (Ptr<const NetDevice> device);
-
- /**
- * Lower layer calls this method after calling L3Demux::Lookup
- * The ARP subclass needs to know from which NetDevice this
- * packet is coming to:
- * - implement a per-NetDevice ARP cache
- * - send back arp replies on the right device
- */
- void Receive( Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from);
-
- /**
- * \param packet packet to send
- * \param source source address of packet
- * \param destination address of packet
- * \param protocol number of packet
- *
- * Higher-level layers call this method to send a packet
- * down the stack to the MAC and PHY layers.
- */
- void Send (Ptr<Packet> packet, Ipv4Address source,
- Ipv4Address destination, uint8_t protocol);
-
-
-
- void AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface);
- void AddHostRouteTo (Ipv4Address dest,
- uint32_t interface);
-
- void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface);
- void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface);
- void SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface);
-
- void Lookup (Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply);
-
- uint32_t GetNRoutes (void);
- Ipv4Route *GetRoute (uint32_t i);
- void RemoveRoute (uint32_t i);
-
- void AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces);
-
- void SetDefaultMulticastRoute (uint32_t onputInterface);
-
- uint32_t GetNMulticastRoutes (void) const;
- Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
-
- void RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface);
- void RemoveMulticastRoute (uint32_t i);
-
- uint32_t AddInterface (Ptr<NetDevice> device);
- Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
- uint32_t GetNInterfaces (void) const;
-
- uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
- uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
- int32_t FindInterfaceIndexForDevice (Ptr<NetDevice> device) const;
-
- void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
- void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
-
- void SetAddress (uint32_t i, Ipv4Address address);
- void SetNetworkMask (uint32_t i, Ipv4Mask mask);
- Ipv4Mask GetNetworkMask (uint32_t t) const;
- Ipv4Address GetAddress (uint32_t i) const;
- void SetMetric (uint32_t i, uint16_t metric);
- uint16_t GetMetric (uint32_t i) const;
- bool GetIfIndexForDestination (Ipv4Address destination,
- uint32_t& ifIndex) const;
- uint16_t GetMtu (uint32_t i) const;
- bool IsUp (uint32_t i) const;
- void SetUp (uint32_t i);
- void SetDown (uint32_t i);
-
- void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
- int priority);
-
-protected:
-
- virtual void DoDispose (void);
-
-private:
- void Lookup (uint32_t ifIndex,
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply);
-
- void SendRealOut (bool found,
- Ipv4Route const &route,
- Ptr<Packet> packet,
- Ipv4Header const &ipHeader);
- bool Forwarding (uint32_t ifIndex,
- Ptr<Packet> packet,
- Ipv4Header &ipHeader,
- Ptr<NetDevice> device);
- void ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, Ptr<Ipv4Interface> incomingInterface);
- uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
- void SetupLoopback (void);
-
- typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
- typedef std::list<std::pair<Ipv4Address, Ipv4Address> >
- Ipv4MulticastGroupList;
- typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
-
- Ipv4InterfaceList m_interfaces;
- uint32_t m_nInterfaces;
- uint8_t m_defaultTtl;
- bool m_calcChecksum;
- uint16_t m_identification;
- Ptr<Node> m_node;
- TracedCallback<Ptr<const Packet>, uint32_t> m_txTrace;
- TracedCallback<Ptr<const Packet>, uint32_t> m_rxTrace;
- TracedCallback<Ptr<const Packet> > m_dropTrace;
-
- Ipv4RoutingProtocolList m_routingProtocols;
-
- Ptr<Ipv4StaticRouting> m_staticRouting;
- Ipv4MulticastGroupList m_multicastGroups;
-};
-
-} // Namespace ns3
-
-#endif /* IPV4_L3_PROTOCOL_H */
--- a/src/internet-node/ipv4-l4-demux.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Define the layer 4 demultiplexer object for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-
-#include <sstream>
-#include "ns3/node.h"
-#include "ns3/object-vector.h"
-#include "ipv4-l4-demux.h"
-#include "ipv4-l4-protocol.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Demux);
-
-TypeId
-Ipv4L4Demux::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4L4Demux")
- .SetParent<Object> ()
- .AddAttribute ("Protocols", "The set of protocols registered with this demux.",
- ObjectVectorValue (),
- MakeObjectVectorAccessor (&Ipv4L4Demux::m_protocols),
- MakeObjectVectorChecker<Ipv4L4Protocol> ())
- ;
- return tid;
-}
-
-Ipv4L4Demux::Ipv4L4Demux ()
-{}
-
-Ipv4L4Demux::~Ipv4L4Demux()
-{}
-
-void
-Ipv4L4Demux::SetNode (Ptr<Node> node)
-{
- m_node = node;
-}
-
-void
-Ipv4L4Demux::DoDispose (void)
-{
- for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
- {
- (*i)->Dispose ();
- *i = 0;
- }
- m_protocols.clear ();
- m_node = 0;
- Object::DoDispose ();
-}
-
-void
-Ipv4L4Demux::Insert(Ptr<Ipv4L4Protocol> protocol)
-{
- m_protocols.push_back (protocol);
-}
-Ptr<Ipv4L4Protocol>
-Ipv4L4Demux::GetProtocol(int protocolNumber)
-{
- for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
- {
- if ((*i)->GetProtocolNumber () == protocolNumber)
- {
- return *i;
- }
- }
- return 0;
-}
-void
-Ipv4L4Demux::Remove (Ptr<Ipv4L4Protocol> protocol)
-{
- m_protocols.remove (protocol);
-}
-
-
-
-}//namespace ns3
--- a/src/internet-node/ipv4-l4-demux.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Define the layer 4 demultiplexer object for ns3.
-// George F. Riley, Georgia Tech, Fall 2006
-
-#ifndef IPV4_L4_DEMUX_H
-#define IPV4_L4_DEMUX_H
-
-#include <list>
-#include "ns3/object.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Ipv4L4Protocol;
-class Node;
-
-/**
- * \brief L4 Ipv4 Demux
- */
-class Ipv4L4Demux : public Object
-{
-public:
- static TypeId GetTypeId (void);
- Ipv4L4Demux ();
- virtual ~Ipv4L4Demux();
-
- void SetNode (Ptr<Node> node);
-
- /**
- * \param protocol a template for the protocol to add to this L4 Demux.
- * \returns the L4Protocol effectively added.
- *
- * Invoke Copy on the input template to get a copy of the input
- * protocol which can be used on the Node on which this L4 Demux
- * is running. The new L4Protocol is registered internally as
- * a working L4 Protocol and returned from this method.
- * The caller does not get ownership of the returned pointer.
- */
- void Insert(Ptr<Ipv4L4Protocol> protocol);
- /**
- * \param protocolNumber number of protocol to lookup
- * in this L4 Demux
- * \returns a matching L4 Protocol
- *
- * This method is typically called by lower layers
- * to forward packets up the stack to the right protocol.
- * It is also called from NodeImpl::GetUdp for example.
- */
- Ptr<Ipv4L4Protocol> GetProtocol(int protocolNumber);
- /**
- * \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);
-protected:
- virtual void DoDispose (void);
-private:
- typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
- L4List_t m_protocols;
- Ptr<Node> m_node;
-};
-
-} //namespace ns3
-#endif
--- a/src/internet-node/ipv4-l4-protocol.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 4 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ipv4-l4-protocol.h"
-#include "ns3/uinteger.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol);
-
-TypeId
-Ipv4L4Protocol::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4L4Protocol")
- .SetParent<Object> ()
- .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.",
- UintegerValue (0),
- MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber),
- MakeUintegerChecker<int> ())
- .AddAttribute ("Version", "The version of the protocol.",
- UintegerValue (0),
- MakeUintegerAccessor (&Ipv4L4Protocol::GetVersion),
- MakeUintegerChecker<int> ())
- ;
- return tid;
-}
-
-Ipv4L4Protocol::~Ipv4L4Protocol ()
-{}
-
-}//namespace ns3
--- a/src/internet-node/ipv4-l4-protocol.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 4 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef IPV4_L4_PROTOCOL_H
-#define IPV4_L4_PROTOCOL_H
-
-#include "ns3/object.h"
-#include "ipv4-interface.h"
-
-namespace ns3 {
-
-class Packet;
-class Ipv4Address;
-
-/**
- * \brief L4 Protocol base class
- *
- * If you want to implement a new L4 protocol, all you have to do is
- * implement a subclass of this base class and add it to an L4Demux.
- */
-class Ipv4L4Protocol : public Object
-{
-public:
- static TypeId GetTypeId (void);
-
- virtual ~Ipv4L4Protocol ();
-
- /**
- * \returns the protocol number of this protocol.
- */
- virtual int GetProtocolNumber (void) const = 0;
- /**
- * \returns the version number of this protocol.
- */
- virtual int GetVersion (void) const = 0;
-
- /**
- * \param p packet to forward up
- * \param source source address of packet received
- * \param destination address of packet received
- * \param incomingInterface the Ipv4Interface on which the packet arrived
- *
- * Called from lower-level layers to send the packet up
- * in the stack.
- */
- virtual void Receive(Ptr<Packet> p,
- Ipv4Address const &source,
- Ipv4Address const &destination,
- Ptr<Ipv4Interface> incomingInterface) = 0;
-};
-
-} // Namespace ns3
-
-#endif
--- a/src/internet-node/ipv4-loopback-interface.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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:
- * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-
-#include "ns3/log.h"
-#include "ns3/net-device.h"
-#include "ns3/node.h"
-#include "ns3/mac48-address.h"
-#include "ns3/packet.h"
-#include "ipv4-loopback-interface.h"
-#include "ipv4-l3-protocol.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4LoopbackInterface");
-
-namespace ns3 {
-
-TypeId
-Ipv4LoopbackInterface::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4LoopbackInterface")
- .SetParent<Ipv4Interface> ()
- ;
- return tid;
-}
-
-Ipv4LoopbackInterface::Ipv4LoopbackInterface ()
- : m_node (0)
-{
- NS_LOG_FUNCTION (this);
-}
-
-Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
-{
- NS_LOG_FUNCTION (this);
- NS_ASSERT (m_node != 0);
-}
-
-Ptr<NetDevice>
-Ipv4LoopbackInterface::GetDevice (void) const
-{
- return 0;
-}
-
-void
-Ipv4LoopbackInterface::SetNode (Ptr<Node> node)
-{
- m_node = node;
-}
-
-void
-Ipv4LoopbackInterface::SendTo (Ptr<Packet> packet, Ipv4Address dest)
-{
- NS_LOG_FUNCTION (this << packet << dest);
-
- Ptr<Ipv4L3Protocol> ipv4 =
- m_node->GetObject<Ipv4L3Protocol> ();
-
- ipv4->Receive (0, packet, Ipv4L3Protocol::PROT_NUMBER,
- Mac48Address ("ff:ff:ff:ff:ff:ff"));
-}
-
-}//namespace ns3
--- a/src/internet-node/ipv4-loopback-interface.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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:
- * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-#ifndef IPV4_LOOPBACK_INTERFACE_H
-#define IPV4_LOOPBACK_INTERFACE_H
-
-#include "ipv4-interface.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Node;
-/**
- * \brief An IPv4 loopback interface
- */
-class Ipv4LoopbackInterface : public Ipv4Interface
-{
-public:
- static TypeId GetTypeId (void);
- Ipv4LoopbackInterface ();
- virtual ~Ipv4LoopbackInterface ();
-
- virtual Ptr<NetDevice> GetDevice (void) const;
-
- void SetNode (Ptr<Node> node);
-
- private:
- virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
-
- Ptr<Node> m_node;
-};
-
-}//namespace ns3
-
-
-#endif /* IPV4_LOOPBACK_INTERFACE_H */
--- a/src/internet-node/ipv4-static-routing.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,654 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-// Gustavo Carneiro <gjc@inescporto.pt>
-
-#include "ns3/log.h"
-#include "ipv4-static-routing.h"
-#include "ns3/packet.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRouting");
-
-namespace ns3 {
-
-Ipv4StaticRouting::Ipv4StaticRouting ()
-: m_defaultRoute (0), m_defaultMulticastRoute (0)
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-void
-Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Route *route = new Ipv4Route ();
- *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
- m_hostRoutes.push_back (route);
-}
-
-void
-Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
- uint32_t interface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Route *route = new Ipv4Route ();
- *route = Ipv4Route::CreateHostRouteTo (dest, interface);
- m_hostRoutes.push_back (route);
-}
-
-void
-Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Route *route = new Ipv4Route ();
- *route = Ipv4Route::CreateNetworkRouteTo (network,
- networkMask,
- nextHop,
- interface);
- m_networkRoutes.push_back (route);
-}
-
-void
-Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Route *route = new Ipv4Route ();
- *route = Ipv4Route::CreateNetworkRouteTo (network,
- networkMask,
- interface);
- m_networkRoutes.push_back (route);
-}
-
-void
-Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Route *route = new Ipv4Route ();
- *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
- delete m_defaultRoute;
- m_defaultRoute = route;
-}
-
-void
-Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
- *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
- inputInterface, outputInterfaces);
- m_multicastRoutes.push_back (route);
-}
-
-void
-Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Address origin = Ipv4Address::GetAny ();
- Ipv4Address group = Ipv4Address::GetAny ();
- uint32_t inputInterface = Ipv4RoutingProtocol::IF_INDEX_ANY;
-
- std::vector<uint32_t> outputInterfaces (1);
- outputInterfaces[0] = outputInterface;
-
- Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
- *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
- inputInterface, outputInterfaces);
-
- delete m_defaultMulticastRoute;
- m_defaultMulticastRoute = route;
-}
-
-uint32_t
-Ipv4StaticRouting::GetNMulticastRoutes (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- NS_ASSERT_MSG(index < m_multicastRoutes.size (),
- "Ipv4StaticRouting::GetMulticastRoute (): Index out of range");
-//
-// From an external point of view the default route appears to be in slot 0
-// of the routing table. The implementation, however, puts it in a separate
-// place. So, if a client asks for index 0 and we have a default multicast
-// route, we have to return it from that different place
-// (m_defaultMulticastRoute).
-//
- if (index == 0 && m_defaultMulticastRoute != 0)
- {
- return m_defaultMulticastRoute;
- }
-//
-// If there is a default multicast route present, a client will just assume
-// that it is in slot zero and there is one "extra" zeroth route in the table.
-// To return the correct indexed entry in our list, we have to decrement the
-// index to take into account the default route not being in the actual list.
-// Since we fell through to here, we've taken care of the case where the
-// index was zero.
-//
- if (m_defaultMulticastRoute != 0)
- {
- NS_ASSERT(index > 0);
- index--;
- }
-
- if (index < m_multicastRoutes.size ())
- {
- uint32_t tmp = 0;
- for (MulticastRoutesCI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- if (tmp == index)
- {
- return *i;
- }
- tmp++;
- }
- }
- return 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::GetDefaultMulticastRoute () const
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_defaultMulticastRoute != 0)
- {
- return m_defaultMulticastRoute;
- }
- return 0;
-}
-
-bool
-Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- Ipv4MulticastRoute *route = *i;
- if (origin == route->GetOrigin () &&
- group == route->GetGroup () &&
- inputInterface == route->GetInputInterface ())
- {
- delete *i;
- m_multicastRoutes.erase (i);
- return true;
- }
- }
- return false;
-}
-
-void
-Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index)
-{
- NS_LOG_FUNCTION_NOARGS ();
-//
-// From an external point of view the default route appears to be in slot 0
-// of the routing table. The implementation, however, puts it in a separate
-// place. So, if a client asks to delete index 0 and we have a default
-// multicast route set, we have to delete it from that different place
-// (m_defaultMulticastRoute).
-//
- if (index == 0 && m_defaultMulticastRoute != 0)
- {
- delete m_defaultMulticastRoute;
- m_defaultMulticastRoute = 0;
- }
-//
-// If there is a default multicast route present, a client will just assume
-// that it is in slot zero and there is one "extra" zeroth route in the table.
-// To return the correct indexed entry in our list, we have to decrement the
-// index to take into account the default route not being in the actual list.
-// Since we fell through to here, we've taken care of the case where the
-// index was zero.
-//
- if (m_defaultMulticastRoute != 0)
- {
- NS_ASSERT(index > 0);
- index--;
- }
-
- uint32_t tmp = 0;
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- if (tmp == index)
- {
- delete *i;
- m_multicastRoutes.erase (i);
- return;
- }
- tmp++;
- }
-}
-
-Ipv4Route *
-Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (HostRoutesCI i = m_hostRoutes.begin ();
- i != m_hostRoutes.end ();
- i++)
- {
- NS_ASSERT ((*i)->IsHost ());
- if ((*i)->GetDest ().IsEqual (dest))
- {
- return (*i);
- }
- }
- for (NetworkRoutesI j = m_networkRoutes.begin ();
- j != m_networkRoutes.end ();
- j++)
- {
- NS_ASSERT ((*j)->IsNetwork ());
- Ipv4Mask mask = (*j)->GetDestNetworkMask ();
- Ipv4Address entry = (*j)->GetDestNetwork ();
- if (mask.IsMatch (dest, entry))
- {
- return (*j);
- }
- }
- if (m_defaultRoute != 0)
- {
- NS_ASSERT (m_defaultRoute->IsDefault ());
- return m_defaultRoute;
- }
- return 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::LookupStatic (
- Ipv4Address origin,
- Ipv4Address group,
- uint32_t ifIndex)
-{
- NS_LOG_FUNCTION_NOARGS ();
-//
-// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching
-// scheme.
-//
- Ipv4Address wildcard = Ipv4Address::GetAny ();
-
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- Ipv4MulticastRoute *route = *i;
-//
-// We've been passed an origin address, a multicast group address and an
-// interface index. We have to decide if the current route in the list is
-// a match.
-//
-// The first case is the restrictive case where the origin, group and index
-// matches. This picks up exact routes during forwarded and exact routes from
-// the local node (in which case the ifIndex is a wildcard).
-//
- if (origin == route->GetOrigin () && group == route->GetGroup ())
- {
- if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY ||
- ifIndex == route->GetInputInterface ())
- {
- return *i;
- }
- }
- }
-//
-// If the input interface index is not a wildcard (that means that the packet
-// did not originally come from this node), we're done. We don't
-// just happily forward packets we don't really know what to do with.
-// Multicast storms are not generally considered a good thing.
-//
- if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY)
- {
- return 0;
- }
-//
-// Now, we're going to get a litle less restricive. This only applies in the
-// case where the packet in question is coming from the local node. In order
-// to avoid dependencies on the order in which routes were added, we will
-// actually walk the list two more times, the first time looking for routes
-// with a single wildcard, and the last time looking for the first route
-// with two wildcards.
-//
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- Ipv4MulticastRoute *route = *i;
-//
-// Here we will ignore the origin. We know that a single source address must
-// be picked for a packet, but we may want to send multicast packets out
-// multiple interfaces. To support this case, a user would need to add
-// a Multicast route with the route's origin set to wildcard. N.B As a
-// result, packets sourced from a node with multiple interface may have a
-// source IP address different from that of the interface actually used to
-// send the packet.
-//
- if (route->GetOrigin () == wildcard && group == route->GetGroup ())
- {
- return *i;
- }
- }
-//
-// Finally we want to allow users to specify a default route that specifies
-// sending all multicast packets out multiple interfaces. The standard
-// default multicast route is patterned after other systems and limits the
-// number of outputs to one. If, however a client manually adds a multicast
-// route with the origin, the multicast group and the input interface index
-// all set to wildcard, she has created a default route with multiple output
-// interfaces.
-//
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i++)
- {
- Ipv4MulticastRoute *route = *i;
-
- if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard)
- {
- return *i;
- }
- }
-//
-// We also allow users to specify a typical default multicast route. This
-// default route is limited to specifying a single output interface.
-//
- if (m_defaultMulticastRoute != 0)
- {
- return m_defaultMulticastRoute;
- }
-
- return 0;
-}
-
-uint32_t
-Ipv4StaticRouting::GetNRoutes (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- uint32_t n = 0;
- if (m_defaultRoute != 0)
- {
- n++;
- }
- n += m_hostRoutes.size ();
- n += m_networkRoutes.size ();
- return n;
-}
-
-Ipv4Route *
-Ipv4StaticRouting::GetDefaultRoute ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_defaultRoute != 0)
- {
- return m_defaultRoute;
- }
- else
- {
- return 0;
- }
-}
-
-Ipv4Route *
-Ipv4StaticRouting::GetRoute (uint32_t index)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (index == 0 && m_defaultRoute != 0)
- {
- return m_defaultRoute;
- }
- if (index > 0 && m_defaultRoute != 0)
- {
- index--;
- }
- if (index < m_hostRoutes.size ())
- {
- uint32_t tmp = 0;
- for (HostRoutesCI i = m_hostRoutes.begin ();
- i != m_hostRoutes.end ();
- i++)
- {
- if (tmp == index)
- {
- return *i;
- }
- tmp++;
- }
- }
- index -= m_hostRoutes.size ();
- uint32_t tmp = 0;
- for (NetworkRoutesI j = m_networkRoutes.begin ();
- j != m_networkRoutes.end ();
- j++)
- {
- if (tmp == index)
- {
- return *j;
- }
- tmp++;
- }
- NS_ASSERT (false);
- // quiet compiler.
- return 0;
-}
-void
-Ipv4StaticRouting::RemoveRoute (uint32_t index)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (index == 0 && m_defaultRoute != 0)
- {
- delete m_defaultRoute;
- m_defaultRoute = 0;
- }
- if (index > 0 && m_defaultRoute != 0)
- {
- index--;
- }
- if (index < m_hostRoutes.size ())
- {
- uint32_t tmp = 0;
- for (HostRoutesI i = m_hostRoutes.begin ();
- i != m_hostRoutes.end ();
- i++)
- {
- if (tmp == index)
- {
- delete *i;
- m_hostRoutes.erase (i);
- return;
- }
- tmp++;
- }
- }
- index -= m_hostRoutes.size ();
- uint32_t tmp = 0;
- for (NetworkRoutesI j = m_networkRoutes.begin ();
- j != m_networkRoutes.end ();
- j++)
- {
- if (tmp == index)
- {
- delete *j;
- m_networkRoutes.erase (j);
- return;
- }
- tmp++;
- }
- NS_ASSERT (false);
-}
-
-bool
-Ipv4StaticRouting::RequestRoute (
- uint32_t ifIndex,
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- RouteReplyCallback routeReply)
-{
- NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
-
- NS_LOG_LOGIC ("source = " << ipHeader.GetSource ());
-
- NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ());
-
- if (ipHeader.GetDestination ().IsMulticast ())
- {
- NS_LOG_LOGIC ("Multicast destination");
-
- Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
- ipHeader.GetDestination (), ifIndex);
-
- if (mRoute)
- {
- NS_LOG_LOGIC ("Multicast route found");
-
- for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
- {
- Ptr<Packet> p = packet->Copy ();
- Ipv4Header h = ipHeader;
- Ipv4Route route =
- Ipv4Route::CreateHostRouteTo(h.GetDestination (),
- mRoute->GetOutputInterface(i));
- NS_LOG_LOGIC ( "Send via interface " <<
- mRoute->GetOutputInterface(i));
- routeReply (true, route, p, h);
- }
- return true;
- }
- return false; // Let other routing protocols try to handle this
- }
-//
-// This is a unicast packet. Check to see if we have a route for it.
-//
- NS_LOG_LOGIC ("Unicast destination");
- Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
- if (route != 0)
- {
- routeReply (true, *route, packet, ipHeader);
- return true;
- }
- else
- {
- return false; // Let other routing protocols try to handle this
- // route request.
- }
-}
-
-bool
-Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex)
-{
- NS_LOG_FUNCTION (this << destination << &ifIndex);
-//
-// First, see if this is a multicast packet we have a route for. If we
-// have a route, then send the packet down each of the specified interfaces.
-//
- if (destination.IsMulticast ())
- {
- NS_LOG_LOGIC ("Multicast destination");
-
- Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (),
- destination, Ipv4RoutingProtocol::IF_INDEX_ANY);
-
- if (mRoute)
- {
- NS_LOG_LOGIC ("Multicast route found");
-
- if (mRoute->GetNOutputInterfaces () != 1)
- {
- NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring.");
- return false;
- }
-
- ifIndex = mRoute->GetOutputInterface(0);
- NS_LOG_LOGIC ("Found ifIndex " << ifIndex);
- return true;
- }
- return false; // Let other routing protocols try to handle this
- }
-//
-// See if this is a unicast packet we have a route for.
-//
- NS_LOG_LOGIC ("Unicast destination");
- Ipv4Route *route = LookupStatic (destination);
- if (route)
- {
- ifIndex = route->GetInterface ();
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void
-Ipv4StaticRouting::DoDispose (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- for (HostRoutesI i = m_hostRoutes.begin ();
- i != m_hostRoutes.end ();
- i = m_hostRoutes.erase (i))
- {
- delete (*i);
- }
- for (NetworkRoutesI j = m_networkRoutes.begin ();
- j != m_networkRoutes.end ();
- j = m_networkRoutes.erase (j))
- {
- delete (*j);
- }
- if (m_defaultRoute != 0)
- {
- delete m_defaultRoute;
- m_defaultRoute = 0;
- }
- for (MulticastRoutesI i = m_multicastRoutes.begin ();
- i != m_multicastRoutes.end ();
- i = m_multicastRoutes.erase (i))
- {
- delete (*i);
- }
- if (m_defaultMulticastRoute != 0)
- {
- delete m_defaultMulticastRoute;
- m_defaultMulticastRoute = 0;
- }
- Ipv4RoutingProtocol::DoDispose ();
-}
-
-}//namespace ns3
--- a/src/internet-node/ipv4-static-routing.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,506 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-// Gustavo Carneiro <gjc@inescporto.pt>
-//
-
-#ifndef IPV4_STATIC_ROUTING_H
-#define IPV4_STATIC_ROUTING_H
-
-#include <list>
-#include <stdint.h>
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4.h"
-
-namespace ns3 {
-
-class Packet;
-class NetDevice;
-class Ipv4Interface;
-class Ipv4Address;
-class Ipv4Header;
-class Ipv4Route;
-class Node;
-
-
-/**
- * @brief Static routing protocol for IP version 4 stacks.
- *
- * In ns-3 we have the concept of a pluggable routing protocol. Routing
- * protocols are added to a list maintained by the Ipv4L3Protocol. Every
- * stack gets one routing protocol for free -- the Ipv4StaticRouting routing
- * protocol is added in the constructor of the Ipv4L3Protocol (this is the
- * piece of code that implements the functionality of the IP layer).
- *
- * The Ipv4StaticRouting class inherits from the abstract base class
- * Ipv4RoutingProtocol that defines the interface methods that a routing
- * protocol must support.
- *
- * When a packet arrives in the Ipv4L3Protocol for transmission, it comes
- * either from a local source via Ipv4L3Protocol::Send or from a remote
- * source via Ipv4L3Protocol::Forwarding. In both cases, a function is called
- * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet.
- *
- * The lookup function iterates through the list of routing protocols asking
- * each to see if it can find a route and send the packet. A callback is
- * provided during each of these calls that should be considered a pre-
- * packaged send call. This is done to allow asynchronous calls into
- * routing subsystems in order to support on-demand routing, for example. The
- * method for requesting this operation is Ipv4StaticRouting::RequestRoute for
- * the static routing protocol.
- *
- * Each routing protocol is also free to implement its own methods for managing
- * routes which you will find below. This class manages a set of "static" or
- * manually configured routes for host, network and multicast routes.
- *
- * @see Ipv4RoutingProtocol
- * @see Ipv4L3Protocol::AddRoutingProtocol
- * @see Ipv4L3Protocol::Ipv4L3Protocol
- */
-class Ipv4StaticRouting : public Ipv4RoutingProtocol
-{
-public:
-/**
- * @brief Construct an empty Ipv4StaticRouting routing protocol,
- * @internal
- *
- * The Ipv4StaticRouting class supports host, network and multicast routes.
- * This method initializes the lists containing these routes to empty.
- *
- * @see Ipv4StaticRouting
- */
- Ipv4StaticRouting ();
-
-/**
- * @brief Request that a check for a route bw performed and if a route is found
- * that the packet be sent on its way using the pre-packaged send callback.
- *
- * The source and destination IP addresses for the packet in question are found
- * in the provided Ipv4Header. There are two major processing forks depending
- * on the type of destination address.
- *
- * If the destination address is unicast then the routing table is consulted
- * for a route to the destination and if it is found, the routeReply callback
- * is executed to send the packet (with the found route).
- *
- * If the destination address is a multicast, then the exact processing steps
- * depend on whether or not the packet has been sourced locally. This is
- * determined by the parameter ifIndex. This is the interface index over which
- * this packet was received. If the packet has not been received over a
- * network interface, this index will be set to
- * Ipv4RoutingProtocol::IF_INDEX_ANY (a very large number). In that case,
- * we want to avoid the requirement that an explicit route out of each node
- * must be set, so we don't do anything here.
- *
- * If the packet is a multicast destination and has been received over a
- * network interface, a call to this method implies that the packet is being
- * forwarded. In that case, there must be an explicit route out of the node.
- * A multicast route references the source address, the destination address
- * (the multicast group) and the input interface in order to find a route.
- * We consult the multicast routing table and, if a route is found, send the
- * packet out of as many interfaces as required using the provided callback
- * (think of it as a pre-packaged send call).
- *
- * @param ifIndex The network interface index over which the packed was
- * received. If the packet is from a local source, ifIndex will be set to
- * Ipv4RoutingProtocol::IF_INDEX_ANY.
- * @param ipHeader the Ipv4Header containing the source and destination IP
- * addresses for the packet.
- * @param packet The packet to be sent if a route is found.
- * @param routeReply A callback that packaged up the call to actually send the
- * packet.
- * @return Returns true if a route is found and the packet has been sent,
- * otherwise returns false indicating that the next routing protocol should
- * be consulted. In practice, the static routing protocol is the last chance
- * protocol.
- *
- * @see Ipv4StaticRouting
- * @see Ipv4RoutingProtocol
- */
- virtual bool RequestRoute (uint32_t ifIndex,
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- RouteReplyCallback routeReply);
-
-/**
- * @brief Check to see if we can determine the interface index that will be
- * used if a packet is sent to this destination.
- *
- * This method addresses a problem in the IP stack where a destination address
- * must be present and checksummed into the IP header before the actual
- * interface over which the packet is sent can be determined. The answer is
- * to implement a known and intentional cross-layer violation. This is the
- * endpoint of a call chain that started up quite high in the stack (sockets)
- * and has found its way down to the Ipv4L3Protocol which is consulting the
- * routing protocols for what they would do if presented with a packet of the
- * given destination.
- *
- * Note that the a single interface index is returned. This means that if
- * the destination address is a multicast, and an explicit route is present
- * that includeds multiple output interfaces, that route cannot be used.
- *
- * If there are multiple paths out of the node, the resolution is performed
- * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more
- * contextual information that is useful for making a determination.
- *
- * @param destination The Ipv4Address if the destination of a hypothetical
- * packet. This may be a multicast group address.
- * @param ifIndex A reference to the interface index over which a packet
- * sent to this destination would be sent.
- * @return Returns true if a route is found to the destination that involves
- * a single output interface index, otherwise returns false indicating that
- * the next routing protocol should be consulted. In practice, the static
- * routing protocol is the last chance protocol.
- *
- * @see Ipv4StaticRouting
- * @see Ipv4RoutingProtocol
- * @see Ipv4L3Protocol
- */
- virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex);
-
-/**
- * @brief Add a host route to the static routing table.
- *
- * @param dest The Ipv4Address destination for this route.
- * @param nextHop The Ipv4Address of the next hop in the route.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
- void AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface);
-/**
- * @brief Add a host route to the static routing table.
- *
- * @param dest The Ipv4Address destination for this route.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
- void AddHostRouteTo (Ipv4Address dest,
- uint32_t interface);
-
-/**
- * @brief Add a network route to the static routing table.
- *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param nextHop The next hop in the route to the destination network.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
- void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface);
-
-/**
- * @brief Add a network route to the static routing table.
- *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
- void AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface);
-
-/**
- * @brief Add a default route to the static routing table.
- *
- * This method tells the routing system what to do in the case where a specific
- * route to a destination is not found. The system forwards packets to the
- * specified node in the hope that it knows better how to route the packet.
- *
- * If the default route is set, it is returned as the selected route from
- * LookupStatic irrespective of destination address if no specific route is
- * found.
- *
- * @param nextHop The Ipv4Address to send packets to in the hope that they
- * will be forwarded correctly.
- * @param interface The network interface index used to send packets.
- *
- * @see Ipv4Address
- * @see Ipv4StaticRouting::Lookup
- */
- void SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface);
-
-/**
- * @brief Get the number of individual unicast routes that have been added
- * to the routing table.
- *
- * @warning The default route counts as one of the routes.
- */
- uint32_t GetNRoutes (void);
-
-/**
- * @brief Get the default route from the static routing table.
- *
- * @return If the default route is set, a pointer to that Ipv4Route is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4Route
- */
- Ipv4Route *GetDefaultRoute (void);
-
-/**
- * @brief Get a route from the static unicast routing table.
- *
- * Externally, the unicast static routing table appears simply as a table with
- * n entries. The one sublety of note is that if a default route has been set
- * it will appear as the zeroth entry in the table. This means that if you
- * add only a default route, the table will have one entry that can be accessed
- * either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
- *
- * Similarly, if the default route has been set, calling RemoveRoute (0) will
- * remove the default route.
- *
- * @param i The index (into the routing table) of the route to retrieve. If
- * the default route has been set, it will occupy index zero.
- * @return If route is set, a pointer to that Ipv4Route is returned, otherwise
- * a zero pointer is returned.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::RemoveRoute
- */
- Ipv4Route *GetRoute (uint32_t i);
-
-/**
- * @brief Remove a route from the static unicast routing table.
- *
- * Externally, the unicast static routing table appears simply as a table with
- * n entries. The one sublety of note is that if a default route has been set
- * it will appear as the zeroth entry in the table. This means that if the
- * default route has been set, calling RemoveRoute (0) will remove the
- * default route.
- *
- * @param i The index (into the routing table) of the route to remove. If
- * the default route has been set, it will occupy index zero.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::GetRoute
- * @see Ipv4StaticRouting::AddRoute
- */
- void RemoveRoute (uint32_t i);
-
-/**
- * @brief Add a multicast route to the static routing table.
- *
- * A multicast route must specify an origin IP address, a multicast group and
- * an input network interface index as conditions and provide a vector of
- * output network interface indices over which packets matching the conditions
- * are sent.
- *
- * Typically there are two main types of multicast routes: routes of the
- * first kind are used during forwarding. All of the conditions must be
- * exlicitly provided. The second kind of routes are used to get packets off
- * of a local node. The difference is in the input interface. Routes for
- * forwarding will always have an explicit input interface specified. Routes
- * off of a node will always set the input interface to a wildcard specified
- * by the index Ipv4RoutingProtocol::IF_INDEX_ANY.
- *
- * For routes off of a local node wildcards may be used in the origin and
- * multicast group addresses. The wildcard used for Ipv4Adresses is that
- * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
- * of a wildcard allows one to specify default behavior to varying degrees.
- *
- * For example, making the origin address a wildcard, but leaving the
- * multicast group specific allows one (in the case of a node with multiple
- * interfaces) to create different routes using different output interfaces
- * for each multicast group.
- *
- * If the origin and multicast addresses are made wildcards, you have created
- * essentially a default multicast address that can forward to multiple
- * interfaces. Compare this to the actual default multicast address that is
- * limited to specifying a single output interface for compatibility with
- * existing functionality in other systems.
- *
- * @param origin The Ipv4Address of the origin of packets for this route. May
- * be Ipv4Address:GetAny for open groups.
- * @param group The Ipv4Address of the multicast group or this route.
- * @param inputInterface The input network interface index over which to
- * expect packets destined for this route. May be
- * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin.
- * @param outputInterfaces A vector of network interface indices used to specify
- * how to send packets to the destination(s).
- *
- * @see Ipv4Address
- */
- void AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces);
-
-/**
- * @brief Add a default multicast route to the static routing table.
- *
- * This is the multicast equivalent of the unicast version SetDefaultRoute.
- * We tell the routing system what to do in the case where a specific route
- * to a destination multicast group is not found. The system forwards
- * packets out the specified interface in the hope that "something out there"
- * knows better how to route the packet. This method is only used in
- * initially sending packets off of a host. The default multicast route is
- * not consulted during forwarding -- exact routes must be specified using
- * AddMulticastRoute for that case.
- *
- * Since we're basically sending packets to some entity we think may know
- * better what to do, we don't pay attention to "subtleties" like origin
- * address, nor do we worry about forwarding out multiple interfaces. If the
- * default multicast route is set, it is returned as the selected route from
- * LookupStatic irrespective of origin or multicast group if another specific
- * route is not found.
- *
- * @param outputInterface The network interface index used to specify where
- * to send packets in the case of unknown routes.
- *
- * @see Ipv4Address
- */
- void SetDefaultMulticastRoute (uint32_t outputInterface);
-
-/**
- * @brief Get the number of individual multicast routes that have been added
- * to the routing table.
- *
- * @warning The default multicast route counts as one of the routes.
- */
- uint32_t GetNMulticastRoutes (void) const;
-
-/**
- * @brief Get a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table
- * with n entries. The one sublety of note is that if a default route has
- * been set it will appear as the zeroth entry in the table. This means that
- * if you add only a default route, the table will have one entry that can be
- * accessed either by explicity calling GetDefaultMulticastRoute () or by
- * calling GetMulticastRoute (0).
- *
- * Similarly, if the default route has been set, calling
- * RemoveMulticastRoute (0) will remove the default route.
- *
- * @param i The index (into the routing table) of the multicast route to
- * retrieve. If the default route has been set, it will occupy index zero.
- * @return If route \e i is set, a pointer to that Ipv4MulticastRoute is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4MulticastRoute
- * @see Ipv4StaticRouting::RemoveRoute
- */
- Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
-
-/**
- * @brief Get the default multicast route from the static routing table.
- *
- * @return If the default route is set, a pointer to that Ipv4MulticastRoute is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4Route
- */
- Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
-
-/**
- * @brief Remove a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table
- * with n entries. The one sublety of note is that if a default multicast
- * route has been set it will appear as the zeroth entry in the table. This
- * means that the default route may be removed by calling this method with
- * appropriate wildcard parameters.
- *
- * This method causes the multicast routing table to be searched for the first
- * route that matches the parameters and removes it.
- *
- * Wildcards may be provided to this function, but the wildcards are used to
- * exacly match wildcards in the routes (see AddMulticastRoute). That is,
- * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
- * remove routes with any address in the origin, but will only remove routes
- * with "0.0.0.0" set as the the origin.
- *
- * @param origin The IP address specified as the origin of packets for the
- * route.
- * @param group The IP address specified as the multicast group addres of
- * the route.
- * @param inputInterface The network interface index specified as the expected
- * input interface for the route.
- * @returns true if a route was found and removed, false otherwise.
- *
- * @see Ipv4MulticastRoute
- * @see Ipv4StaticRouting::AddMulticastRoute
- */
- bool RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface);
-
-/**
- * @brief Remove a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table
- * with n entries. The one sublety of note is that if a default multicast
- * route has been set it will appear as the zeroth entry in the table. This
- * means that if the default route has been set, calling
- * RemoveMulticastRoute (0) will remove the default route.
- *
- * @param index The index (into the multicast routing table) of the route to
- * remove. If the default route has been set, it will occupy index zero.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::GetRoute
- * @see Ipv4StaticRouting::AddRoute
- */
- void RemoveMulticastRoute (uint32_t index);
-
-protected:
- void DoDispose (void);
-
-private:
- typedef std::list<Ipv4Route *> HostRoutes;
- typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
- typedef std::list<Ipv4Route *>::iterator HostRoutesI;
- typedef std::list<Ipv4Route *> NetworkRoutes;
- typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
- typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
-
- typedef std::list<Ipv4MulticastRoute *> MulticastRoutes;
- typedef std::list<Ipv4MulticastRoute *>::const_iterator MulticastRoutesCI;
- typedef std::list<Ipv4MulticastRoute *>::iterator MulticastRoutesI;
-
- Ipv4Route *LookupStatic (Ipv4Address dest);
- Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group,
- uint32_t ifIndex);
-
- HostRoutes m_hostRoutes;
- NetworkRoutes m_networkRoutes;
- Ipv4Route *m_defaultRoute;
- Ipv4MulticastRoute *m_defaultMulticastRoute;
- MulticastRoutes m_multicastRoutes;
-};
-
-} // Namespace ns3
-
-#endif /* IPV4_STATIC_ROUTING_H */
--- a/src/internet-node/pending-data.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-
-// This is a port of Data PDU Headers from:
-// Georgia Tech Network Simulator
-// George F. Riley. Georgia Tech, Spring 2002
-
-#include <iostream>
-#include <algorithm>
-
-#include <string.h>
-
-#include "pending-data.h"
-#include "ns3/packet.h"
-#include "ns3/fatal-error.h"
-namespace ns3
-{
-
-namespace Serializable
-{
- uint8_t* GetSize (uint8_t* b, uint32_t& r, uint32_t& s)
- { // Get the size of the next size field
- if (sizeof(s) > r)
- {
- NS_FATAL_ERROR ("Serialization error; remaining " << r
- << " thissize " << sizeof(s) << std::endl);
- }
- r -= sizeof (s); // Reduce remaining for next time
- memcpy (&s, b, sizeof(s));
- return b + sizeof (s);
- }
-}
-
-PendingData::PendingData () : size (0), data (0),
- msgSize (0), responseSize (0)
-{
-}
-
-PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp)
- : size (s), data (0), msgSize (msg), responseSize (resp)
-{ // Make a copy of the data
- if (d)
- {
- data = new uint8_t[s];
- memcpy (data, d, s);
- }
-}
-
-PendingData::PendingData(const std::string& s)
- : size (s.length () + 1), data ((uint8_t*)strdup(s.c_str ())),
- msgSize (0), responseSize (0)
-{
-}
-
-PendingData::PendingData(const PendingData& c)
- : size (c.Size ()), data (0),
- msgSize (c.msgSize), responseSize (c.responseSize)
-{ // Copy constructor
- if (c.Contents())
- { // Has data
- data = new uint8_t[Size ()];
- memcpy(data, c.Contents (), Size ());
- }
-}
-
-PendingData::~PendingData()
-{ // destructor
- if (data)
- {
- delete [] data;
- }
-}
-
-PendingData* PendingData::Copy () const
-{
- return new PendingData (*this);
-};
-
-PendingData* PendingData::CopyS (uint32_t s)
-{ // Copy, but with new size (assumes no associated data);
- return new PendingData (s, 0, msgSize, responseSize);
-}
-
-PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
-{ // Copy, but with new size (assumes no associated data);
- return new PendingData (s, d, msgSize, responseSize);
-}
-
-void PendingData::Clear ()
-{ // Remove all pending data
- if (data)
- {
- delete [] data; // Free memory if used
- }
- data = 0;
- size = 0;
-}
-
-void PendingData::Add (uint32_t s, const uint8_t* d)
-{
- if (data)
- { // PendingData exists, realloc and copy
- uint8_t* n = new uint8_t[Size () + s];
- memcpy(n, data, Size ());
- if (d)
- { // New data specified
- memcpy(n + Size (), d, s); // Append the new data
- }
- else
- {
- memset(n + Size (), 0, s); // Apend zeros
- }
- delete [] data; // Delete the old data
- data = n; // Points to new one
- }
- else
- { // No existing data, see if new data
- if (d)
- {
- data = new uint8_t[s];
- memcpy (data, d, s);
- }
- }
- size += s;
-}
-
-void PendingData::Remove(uint32_t s)
-{
- uint32_t r = s > Size () ? Size () : s;
-
- size -= r; // Reduce size from current
- if (data)
- { // data actually exists, realloc and copy
- if (size)
- {
- uint8_t* d = new uint8_t[Size ()];
- memcpy(d, data, Size ());
- delete [] data;
- data = d;
- }
- else
- { // Zero size, so don't need the data anymore
- delete [] data;
- data = NULL;
- }
- }
-}
-
-uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o)
-{
- uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data
- return SizeFromOffset (o1); // Amount of data after offset
-}
-
-uint32_t PendingData::SizeFromOffset (uint32_t o)
-{ // Find out how much data is available from offset
- if (o > size) return 0; // No data at requested offset
- return size - o; // Available data after offset
-}
-
-uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o)
-{ // f is the first sequence number in this data, o is offset sequence
- if (o < f)
- {
- return 0; // HuH? Shouldn't happen
- }
- return o - f;
-}
-
-Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o)
-{ // Make a copy of data from starting position "o" for "s" bytes
- // Return NULL if results in zero length data
- uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data
- if (s1 == 0)
- {
- return 0; // No data requested
- }
- if (data)
- { // Actual data exists, make copy and return it
- return Create<Packet> (data+o, s1);
- }
- else
- { // No actual data, just return non-data pdu of correct size
- return Create<Packet> (s1);
- }
-}
-
-Ptr<Packet> PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o)
-{
- return CopyFromOffset (s, OffsetFromSeq(f,o));
-}
-
-}//namepsace ns3
--- a/src/internet-node/pending-data.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-// Georgia Tech Network Simulator - Data Descriptors
-// George F. Riley. Georgia Tech, Spring 2002
-
-#ifndef __datapdu_h__
-#define __datapdu_h__
-
-#include "pending-data.h"
-#include "sequence-number.h"
-
-#include "ns3/ptr.h"
-namespace ns3
-{
-class Packet;
-//Doc:ClassXRef
-class PendingData {
-public:
- PendingData ();
- PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0);
- PendingData (const std::string&); // Construct from string
- PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer
- PendingData (const PendingData&); // Copy constructor
- virtual ~PendingData (); // Destructor
- uint32_t Size () const { return size;}
- // Serialization
- uint32_t SSize (); // Size needed for serialization
- uint8_t* Serialize (uint8_t*, uint32_t&); // Serialize to a buffer
- uint8_t* Construct (uint8_t*, uint32_t&); // Construct from buffer
- virtual void Clear ();// Remove all associated data
- virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end
- virtual void Remove (uint32_t); // Remove data from head
- // Inquire available data from (f,o) sequence pair
- virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&);
- // Inquire available data from offset
- virtual uint32_t SizeFromOffset (uint32_t);
- // Available size from sequence difference
- virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&);
- virtual Ptr<Packet> CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret packet
- // Copy data, size, offset specified by sequence difference
- virtual Ptr<Packet> CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
- PendingData* Copy () const; // Create a copy of this header
- PendingData* CopyS (uint32_t); // Copy with new size
- PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data
- virtual uint8_t* Contents() const { return data;}
-public:
- uint32_t size; // Number of data bytes
- uint8_t* data; // Corresponding data (may be null)
- // The next two fields allow simulated applications to exchange some info
- uint32_t msgSize; // Total size of message
- uint32_t responseSize;// Size of response requested
-};
-
-}//namepsace ns3
-#endif
-
--- a/src/internet-node/rtt-estimator.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-
-// Ported from:
-// Georgia Tech Network Simulator - Round Trip Time Estimation Class
-// George F. Riley. Georgia Tech, Spring 2002
-
-// Implements several variations of round trip time estimators
-
-#include <iostream>
-
-#include "rtt-estimator.h"
-#include "ns3/simulator.h"
-#include "ns3/double.h"
-
-namespace ns3{
-
-NS_OBJECT_ENSURE_REGISTERED (RttEstimator);
-
-//RttEstimator iid
-TypeId
-RttEstimator::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::RttEstimator")
- .SetParent<Object> ()
- .AddAttribute ("MaxMultiplier",
- "XXX",
- DoubleValue (64.0),
- MakeDoubleAccessor (&RttEstimator::m_maxMultiplier),
- MakeDoubleChecker<double> ())
- .AddAttribute ("InitialEstimation",
- "XXX",
- TimeValue (Seconds (1.0)),
- MakeTimeAccessor (&RttEstimator::est),
- MakeTimeChecker ())
- ;
- return tid;
-}
-
-//RttHistory methods
-RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t)
- : seq (s), count (c), time (t), retx (false)
- {
- }
-
-RttHistory::RttHistory (const RttHistory& h)
- : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
- {
- }
-
-// Base class methods
-
-RttEstimator::RttEstimator () : next (1), history (),
- nSamples (0), multiplier (1.0)
-{
- //note next=1 everywhere since first segment will have sequence 1
-}
-
-RttEstimator::RttEstimator(const RttEstimator& c)
- : Object (c), next(c.next), history(c.history),
- m_maxMultiplier (c.m_maxMultiplier), est(c.est), nSamples(c.nSamples),
- multiplier(c.multiplier)
-{}
-
-RttEstimator::~RttEstimator ()
-{
-}
-
-void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
-{ // Note that a particular sequence has been sent
- if (s == next)
- { // This is the next expected one, just log at end
- history.push_back (RttHistory (s, c, Simulator::Now () ));
- next = s + SequenceNumber (c); // Update next expected
- }
- else
- { // This is a retransmit, find in list and mark as re-tx
- for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i)
- {
- if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count))))
- { // Found it
- i->retx = true;
- // One final test..be sure this re-tx does not extend "next"
- if ((s + SequenceNumber (c)) > next)
- {
- next = s + SequenceNumber (c);
- i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist
- }
- break;
- }
- }
- }
-}
-
-Time RttEstimator::AckSeq (SequenceNumber a)
-{ // An ack has been received, calculate rtt and log this measurement
- // Note we use a linear search (O(n)) for this since for the common
- // case the ack'ed packet will be at the head of the list
- Time m = Seconds (0.0);
- if (history.size () == 0) return (m); // No pending history, just exit
- RttHistory& h = history.front ();
- if (!h.retx && a >= (h.seq + SequenceNumber (h.count)))
- { // Ok to use this sample
- m = Simulator::Now () - h.time; // Elapsed time
- Measurement(m); // Log the measurement
- ResetMultiplier(); // Reset multiplier on valid measurement
- }
- // Now delete all ack history with seq <= ack
- while(history.size() > 0)
- {
- RttHistory& h = history.front ();
- if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing
- history.pop_front (); // Remove
- }
- return m;
-}
-
-void RttEstimator::ClearSent ()
-{ // Clear all history entries
- next = 1;
- history.clear ();
-}
-
-void RttEstimator::IncreaseMultiplier ()
-{
- double a;
- a = multiplier * 2.0;
- double b;
- b = m_maxMultiplier * 2.0;
- multiplier = std::min (multiplier * 2.0, m_maxMultiplier);
-}
-
-void RttEstimator::ResetMultiplier ()
-{
- multiplier = 1.0;
-}
-
-void RttEstimator::Reset ()
-{ // Reset to initial state
- next = 1;
- est = Seconds (1.0); // XXX: we should go back to the 'initial value' here. Need to add support in Object for this.
- history.clear (); // Remove all info from the history
- nSamples = 0;
- ResetMultiplier ();
-}
-
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// Mean-Deviation Estimator
-
-NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation);
-
-TypeId
-RttMeanDeviation::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::RttMeanDeviation")
- .SetParent<RttEstimator> ()
- .AddConstructor<RttMeanDeviation> ()
- .AddAttribute ("Gain",
- "XXX",
- DoubleValue (0.1),
- MakeDoubleAccessor (&RttMeanDeviation::gain),
- MakeDoubleChecker<double> ())
- ;
- return tid;
-}
-
-RttMeanDeviation::RttMeanDeviation() :
- variance (ns3::Seconds(0))
-{
-}
-
-RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
- : RttEstimator (c), gain (c.gain), variance (c.variance)
-{
-}
-
-void RttMeanDeviation::Measurement (Time m)
-{
- if (nSamples)
- { // Not first
- Time err = m - est;
- est = est + Scalar (gain) * err; // estimated rtt
- err = Abs (err); // absolute value of error
- variance = variance + Scalar (gain) * (err - variance); // variance of rtt
- }
- else
- { // First sample
- est = m; // Set estimate to current
- //variance = m / 2; // And variance to current / 2
- variance = m; // try this
- }
- nSamples++;
-}
-
-Time RttMeanDeviation::RetransmitTimeout ()
-{
- // If not enough samples, justjust return 2 times estimate
- //if (nSamples < 2) return est * 2;
- if (variance < est / Scalar (4.0))
- return est * Scalar (2 * multiplier); // At least twice current est
- return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson
-}
-
-Ptr<RttEstimator> RttMeanDeviation::Copy () const
-{
- return CopyObject<RttMeanDeviation> (this);
-}
-
-void RttMeanDeviation::Reset ()
-{ // Reset to initial state
- variance = Seconds (0.0);
- RttEstimator::Reset ();
-}
-}//namepsace ns3
--- a/src/internet-node/rtt-estimator.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-// Georgia Tech Network Simulator - Round Trip Time Estimation Class
-// George F. Riley. Georgia Tech, Spring 2002
-
-// Implements several variations of round trip time estimators
-
-#ifndef __rtt_estimator_h__
-#define __rtt_estimator_h__
-
-#include <deque>
-#include "sequence-number.h"
-#include "ns3/nstime.h"
-#include "ns3/object.h"
-
-namespace ns3 {
-
-class RttHistory {
-public:
- RttHistory (SequenceNumber s, uint32_t c, Time t);
- RttHistory (const RttHistory& h); // Copy constructor
-public:
- SequenceNumber seq; // First sequence number in packet sent
- uint32_t count; // Number of bytes sent
- Time time; // Time this one was sent
- bool retx; // True if this has been retransmitted
-};
-
-typedef std::deque<RttHistory> RttHistory_t;
-
-class RttEstimator : public Object { // Base class for all RTT Estimators
-public:
- static TypeId GetTypeId (void);
-
- RttEstimator();
- RttEstimator(const RttEstimator&); // Copy constructor
- virtual ~RttEstimator();
-
- virtual void SentSeq(SequenceNumber, uint32_t);
- virtual Time AckSeq(SequenceNumber);
- virtual void ClearSent();
- virtual void Measurement(Time t) = 0;
- virtual Time Estimate() = 0;
- virtual Time RetransmitTimeout() = 0;
- void Init(SequenceNumber s) { next = s;}
- virtual Ptr<RttEstimator> Copy() const = 0;
- virtual void IncreaseMultiplier();
- virtual void ResetMultiplier();
- virtual void Reset();
-
-private:
- SequenceNumber next; // Next expected sequence to be sent
- RttHistory_t history; // List of sent packet
- double m_maxMultiplier;
-public:
- Time est; // Current estimate
- uint32_t nSamples;// Number of samples
- double multiplier; // RTO Multiplier
-};
-
-// The "Mean-Deviation" estimator, as discussed by Van Jacobson
-// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
-
- //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator
- //Doc:Class as described by Van Jacobson
- //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
-class RttMeanDeviation : public RttEstimator {
-public :
- static TypeId GetTypeId (void);
-
- RttMeanDeviation ();
-
-
- //Doc:Method
- RttMeanDeviation (const RttMeanDeviation&); // Copy constructor
- //Doc:Desc Copy constructor.
- //Doc:Arg1 {\tt RttMeanDeviation} object to copy.
-
- void Measurement (Time);
- Time Estimate () { return est;}
- Time Variance () { return variance;}
- Time RetransmitTimeout ();
- Ptr<RttEstimator> Copy () const;
- void Reset ();
- void Gain (double g) { gain = g;}
-
-public:
- double gain; // Filter gain
- Time variance; // Current variance
-};
-}//namespace ns3
-#endif
-
-
-
--- a/src/internet-node/sequence-number.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-
-// Ported from:
-// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
-// George F. Riley. Georgia Tech, Spring 2002
-
-// Class to manage arithmetic operations on sequence numbers (mod 2^32)
-
-#include "sequence-number.h"
-
-bool operator< (const SequenceNumber l, const SequenceNumber r)
-{ // Account for 32 bit rollover
- if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
- return l.seq < r.seq;
-}
-
-bool operator<= (const SequenceNumber l, const SequenceNumber r)
-{ // Account for 32 bit rollover
- if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
- return l.seq <= r.seq;
-}
-
-bool operator> (const SequenceNumber l, const SequenceNumber r)
-{ // Account for 32 bit rollover
- if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
- return l.seq > r.seq;
-}
-
-bool operator>= (const SequenceNumber l, const SequenceNumber r)
-{ // Account for 32 bit rollover
- if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
- return l.seq >= r.seq;
-}
-
-// Non-Member Arithmetic operators
-SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r)
-{
- return SequenceNumber (l.seq + r.seq);
-}
-
-SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r)
-{ // This assumes l is always bigger than r (allows for rollover)
- if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq);
- return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1); // Adjust for rollover
-}
-
--- a/src/internet-node/sequence-number.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
-//
-
-// Ported from:
-// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
-// George F. Riley. Georgia Tech, Spring 2002
-
-// Class to manage arithmetic operations on sequence numbers (mod 2^32)
-
-#ifndef __seq_h__
-#define __seq_h__
-
-#include <stdint.h>
-
-#define MAX_SEQ ((uint32_t)0xffffffff)
-
-class SequenceNumber {
-public:
- SequenceNumber () : seq(0) { }
- SequenceNumber (const uint32_t s) : seq (s) { }
-
- operator uint32_t () const { return seq;}
-
- SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;}
-
- SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;}
- SequenceNumber operator++ () { seq++; return *this;}
- SequenceNumber operator++ (int) { SequenceNumber ss (seq); seq++; return ss;}
- SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;}
- SequenceNumber operator-- () { seq--; return *this;}
- SequenceNumber operator-- (int) { SequenceNumber ss (seq); seq--; return ss;}
-public:
- uint32_t seq;
-};
-
-// Comparison operators
-
-bool operator< (const SequenceNumber l, const SequenceNumber r);
-bool operator<= (const SequenceNumber l, const SequenceNumber r);
-bool operator> (const SequenceNumber l, const SequenceNumber r);
-bool operator>= (const SequenceNumber l, const SequenceNumber r);
-
-// Non-member arithmetic operators
-SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r);
-SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r);
-
-#endif
-
-
--- a/src/internet-node/sgi-hashmap.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* This code snippet was ripped out of the gcc
- * documentation and slightly modified to work
- * with gcc 4.x
- */
-#ifndef SGI_HASHMAP_H
-#define SGI_HASHMAP_H
-
-/* To use gcc extensions.
- */
-#ifdef __GNUC__
- #if __GNUC__ < 3
- #include <hash_map.h>
-namespace sgi { using ::hash_map; }; // inherit globals
- #else
- #if __GNUC__ < 4
- #include <ext/hash_map>
- #if __GNUC_MINOR__ == 0
-namespace sgi = std; // GCC 3.0
- #else
-namespace sgi = ::__gnu_cxx; // GCC 3.1 and later
- #endif
- #else // gcc 4.x and later
- #include <ext/hash_map>
- namespace sgi = ::__gnu_cxx;
- #endif
- #endif
-#else // ... there are other compilers, right?
-namespace sgi = std;
-#endif
-
-
-#endif /* SGI_HASHMAP_H */
--- a/src/internet-node/tcp-header.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-
-#include <stdint.h>
-#include <iostream>
-#include "tcp-socket-impl.h"
-#include "tcp-header.h"
-#include "ns3/buffer.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (TcpHeader);
-
-bool TcpHeader::m_calcChecksum = false;
-
-TcpHeader::TcpHeader ()
- : m_sourcePort (0),
- m_destinationPort (0),
- m_sequenceNumber (0),
- m_ackNumber (0),
- m_length (5),
- m_flags (0),
- m_windowSize (0xffff),
- m_checksum (0),
- m_urgentPointer (0)
-{}
-
-TcpHeader::~TcpHeader ()
-{}
-
-void
-TcpHeader::EnableChecksums (void)
-{
- m_calcChecksum = true;
-}
-
-void TcpHeader::SetSourcePort (uint16_t port)
-{
- m_sourcePort = port;
-}
-void TcpHeader::SetDestinationPort (uint16_t port)
-{
- m_destinationPort = port;
-}
-void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber)
-{
- m_sequenceNumber = sequenceNumber;
-}
-void TcpHeader::SetAckNumber (SequenceNumber ackNumber)
-{
- m_ackNumber = ackNumber;
-}
-void TcpHeader::SetLength (uint8_t length)
-{
- m_length = length;
-}
-void TcpHeader::SetFlags (uint8_t flags)
-{
- m_flags = flags;
-}
-void TcpHeader::SetWindowSize (uint16_t windowSize)
-{
- m_windowSize = windowSize;
-}
-void TcpHeader::SetChecksum (uint16_t checksum)
-{
- m_checksum = checksum;
-}
-void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
-{
- m_urgentPointer = urgentPointer;
-}
-
-uint16_t TcpHeader::GetSourcePort () const
-{
- return m_sourcePort;
-}
-uint16_t TcpHeader::GetDestinationPort () const
-{
- return m_destinationPort;
-}
-SequenceNumber TcpHeader::GetSequenceNumber () const
-{
- return m_sequenceNumber;
-}
-SequenceNumber TcpHeader::GetAckNumber () const
-{
- return m_ackNumber;
-}
-uint8_t TcpHeader::GetLength () const
-{
- return m_length;
-}
-uint8_t TcpHeader::GetFlags () const
-{
- return m_flags;
-}
-uint16_t TcpHeader::GetWindowSize () const
-{
- return m_windowSize;
-}
-uint16_t TcpHeader::GetChecksum () const
-{
- return m_checksum;
-}
-uint16_t TcpHeader::GetUrgentPointer () const
-{
- return m_urgentPointer;
-}
-
-void
-TcpHeader::InitializeChecksum (Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol)
-{
- m_checksum = 0;
-//XXX requires peeking into IP to get length of the TCP segment
-}
-
-TypeId
-TcpHeader::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::TcpHeader")
- .SetParent<Header> ()
- .AddConstructor<TcpHeader> ()
- ;
- return tid;
-}
-TypeId
-TcpHeader::GetInstanceTypeId (void) const
-{
- return GetTypeId ();
-}
-void TcpHeader::Print (std::ostream &os) const
-{
- os << m_sourcePort << " > " << m_destinationPort;
- if(m_flags!=0)
- {
- os<<" [";
- if((m_flags & FIN) != 0)
- {
- os<<" FIN ";
- }
- if((m_flags & SYN) != 0)
- {
- os<<" SYN ";
- }
- if((m_flags & RST) != 0)
- {
- os<<" RST ";
- }
- if((m_flags & PSH) != 0)
- {
- os<<" PSH ";
- }
- if((m_flags & ACK) != 0)
- {
- os<<" ACK ";
- }
- if((m_flags & URG) != 0)
- {
- os<<" URG ";
- }
- os<<"]";
- }
- os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
-}
-uint32_t TcpHeader::GetSerializedSize (void) const
-{
- return 4*m_length;
-}
-void TcpHeader::Serialize (Buffer::Iterator start) const
-{
- start.WriteHtonU16 (m_sourcePort);
- start.WriteHtonU16 (m_destinationPort);
- start.WriteHtonU32 (m_sequenceNumber);
- start.WriteHtonU32 (m_ackNumber);
- start.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
- start.WriteHtonU16 (m_windowSize);
- //XXX calculate checksum here
- start.WriteHtonU16 (m_checksum);
- start.WriteHtonU16 (m_urgentPointer);
-}
-uint32_t TcpHeader::Deserialize (Buffer::Iterator start)
-{
- m_sourcePort = start.ReadNtohU16 ();
- m_destinationPort = start.ReadNtohU16 ();
- m_sequenceNumber = start.ReadNtohU32 ();
- m_ackNumber = start.ReadNtohU32 ();
- uint16_t field = start.ReadNtohU16 ();
- m_flags = field & 0x3F;
- m_length = field>>12;
- m_windowSize = start.ReadNtohU16 ();
- m_checksum = start.ReadNtohU16 ();
- m_urgentPointer = start.ReadNtohU16 ();
- return GetSerializedSize ();
-}
-
-
-}; // namespace ns3
--- a/src/internet-node/tcp-header.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-
-#ifndef TCP_HEADER_H
-#define TCP_HEADER_H
-
-#include <stdint.h>
-#include "ns3/header.h"
-#include "ns3/buffer.h"
-#include "ns3/tcp-socket-factory.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/sequence-number.h"
-
-namespace ns3 {
-
-class TcpHeader : public Header
-{
-public:
- TcpHeader ();
- virtual ~TcpHeader ();
-
- /**
- * \brief Enable checksum calculation for TCP (XXX currently has no effect)
- */
- static void EnableChecksums (void);
-//Setters
- /**
- * \param port The source port for this TcpHeader
- */
- void SetSourcePort (uint16_t port);
- /**
- * \param port the destination port for this TcpHeader
- */
- void SetDestinationPort (uint16_t port);
- /**
- * \param sequenceNumber the sequence number for this TcpHeader
- */
- void SetSequenceNumber (SequenceNumber sequenceNumber);
- /**
- * \param ackNumber the ACK number for this TcpHeader
- */
- void SetAckNumber (SequenceNumber ackNumber);
- /**
- * \param length the length of this TcpHeader
- */
- void SetLength (uint8_t length);
- /**
- * \param flags the flags for this TcpHeader
- */
- void SetFlags (uint8_t flags);
- /**
- * \param windowSize the window size for this TcpHeader
- */
- void SetWindowSize (uint16_t windowSize);
- /**
- * \param checksum the checksum for this TcpHeader
- */
- void SetChecksum (uint16_t checksum);
- /**
- * \param urgentPointer the urgent pointer for this TcpHeader
- */
- void SetUrgentPointer (uint16_t urgentPointer);
-
-
-//Getters
- /**
- * \return The source port for this TcpHeader
- */
- uint16_t GetSourcePort () const;
- /**
- * \return the destination port for this TcpHeader
- */
- uint16_t GetDestinationPort () const;
- /**
- * \return the sequence number for this TcpHeader
- */
- SequenceNumber GetSequenceNumber () const;
- /**
- * \return the ACK number for this TcpHeader
- */
- SequenceNumber GetAckNumber () const;
- /**
- * \return the length of this TcpHeader
- */
- uint8_t GetLength () const;
- /**
- * \return the flags for this TcpHeader
- */
- uint8_t GetFlags () const;
- /**
- * \return the window size for this TcpHeader
- */
- uint16_t GetWindowSize () const;
- /**
- * \return the checksum for this TcpHeader
- */
- uint16_t GetChecksum () const;
- /**
- * \return the urgent pointer for this TcpHeader
- */
- uint16_t GetUrgentPointer () 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 tcp checksums, you should call this
- * method prior to adding the header to a packet.
- */
- void InitializeChecksum (Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol);
-
- typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16,
- URG = 32} Flags_t;
-
- static TypeId GetTypeId (void);
- virtual TypeId GetInstanceTypeId (void) const;
- virtual void Print (std::ostream &os) const;
- virtual uint32_t GetSerializedSize (void) const;
- virtual void Serialize (Buffer::Iterator start) const;
- virtual uint32_t Deserialize (Buffer::Iterator start);
-
-private:
- uint16_t m_sourcePort;
- uint16_t m_destinationPort;
- uint32_t m_sequenceNumber;
- uint32_t m_ackNumber;
- uint8_t m_length; // really a uint4_t
- uint8_t m_flags; // really a uint6_t
- uint16_t m_windowSize;
- uint16_t m_checksum;
- uint16_t m_urgentPointer;
-
- static bool m_calcChecksum;
-};
-
-}; // namespace ns3
-
-#endif /* TCP_HEADER */
--- a/src/internet-node/tcp-l4-protocol.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,526 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-
-#include "ns3/assert.h"
-#include "ns3/log.h"
-#include "ns3/nstime.h"
-
-#include "ns3/packet.h"
-#include "ns3/node.h"
-
-#include "tcp-l4-protocol.h"
-#include "tcp-header.h"
-#include "ipv4-end-point-demux.h"
-#include "ipv4-end-point.h"
-#include "ipv4-l3-protocol.h"
-#include "tcp-socket-impl.h"
-
-#include "tcp-typedefs.h"
-
-#include <vector>
-#include <sstream>
-#include <iomanip>
-
-NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol);
-
-//State Machine things --------------------------------------------------------
-TcpStateMachine::TcpStateMachine()
- : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)),
- eV (MAX_FLAGS)
-{
- NS_LOG_FUNCTION_NOARGS ();
-
- // Create the state table
- // Closed state
- aT[CLOSED][APP_LISTEN] = SA (LISTEN, NO_ACT);
- aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
- aT[CLOSED][APP_SEND] = SA (CLOSED, RST_TX);
- aT[CLOSED][SEQ_RECV] = SA (CLOSED, NO_ACT);
- aT[CLOSED][APP_CLOSE] = SA (CLOSED, NO_ACT);
- aT[CLOSED][TIMEOUT] = SA (CLOSED, RST_TX);
- aT[CLOSED][ACK_RX] = SA (CLOSED, RST_TX);
- aT[CLOSED][SYN_RX] = SA (CLOSED, RST_TX);
- aT[CLOSED][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[CLOSED][FIN_RX] = SA (CLOSED, RST_TX);
- aT[CLOSED][FIN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[CLOSED][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[CLOSED][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // Listen State
- // For the listen state, anything other than CONNECT or SEND
- // is simply ignored....this likely indicates the child TCP
- // has finished and issued unbind call, but the remote end
- // has not yet closed.
- aT[LISTEN][APP_LISTEN] = SA (LISTEN, NO_ACT);
- aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
- aT[LISTEN][APP_SEND] = SA (SYN_SENT, SYN_TX);
- aT[LISTEN][SEQ_RECV] = SA (LISTEN, NO_ACT);
- aT[LISTEN][APP_CLOSE] = SA (CLOSED, NO_ACT);
- aT[LISTEN][TIMEOUT] = SA (LISTEN, NO_ACT);
- aT[LISTEN][ACK_RX] = SA (LISTEN, NO_ACT);
- aT[LISTEN][SYN_RX] = SA (LISTEN, SYN_ACK_TX);//stay in listen and fork
- aT[LISTEN][SYN_ACK_RX] = SA (LISTEN, NO_ACT);
- aT[LISTEN][FIN_RX] = SA (LISTEN, NO_ACT);
- aT[LISTEN][FIN_ACK_RX] = SA (LISTEN, NO_ACT);
- aT[LISTEN][RST_RX] = SA (LISTEN, NO_ACT);
- aT[LISTEN][BAD_FLAGS] = SA (LISTEN, NO_ACT);
-
- // Syn Sent State
- aT[SYN_SENT][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
- aT[SYN_SENT][APP_SEND] = SA (SYN_SENT, NO_ACT);
- aT[SYN_SENT][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
- aT[SYN_SENT][APP_CLOSE] = SA (CLOSED, RST_TX);
- aT[SYN_SENT][TIMEOUT] = SA (CLOSED, NO_ACT);
- aT[SYN_SENT][ACK_RX] = SA (SYN_SENT, NO_ACT);
- aT[SYN_SENT][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
- aT[SYN_SENT][SYN_ACK_RX] = SA (ESTABLISHED, ACK_TX_1);
- aT[SYN_SENT][FIN_RX] = SA (CLOSED, RST_TX);
- aT[SYN_SENT][FIN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[SYN_SENT][RST_RX] = SA (CLOSED, APP_NOTIFY);
- aT[SYN_SENT][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // Syn Recvd State
- aT[SYN_RCVD][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][APP_SEND] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
- aT[SYN_RCVD][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
- aT[SYN_RCVD][TIMEOUT] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][ACK_RX] = SA (ESTABLISHED, SERV_NOTIFY);
- aT[SYN_RCVD][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
- aT[SYN_RCVD][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][FIN_RX] = SA (CLOSED, RST_TX);
- aT[SYN_RCVD][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
- aT[SYN_RCVD][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[SYN_RCVD][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // Established State
- aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED, RST_TX);
- aT[ESTABLISHED][APP_SEND] = SA (ESTABLISHED,TX_DATA);
- aT[ESTABLISHED][SEQ_RECV] = SA (ESTABLISHED,NEW_SEQ_RX);
- aT[ESTABLISHED][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
- aT[ESTABLISHED][TIMEOUT] = SA (ESTABLISHED,RETX);
- aT[ESTABLISHED][ACK_RX] = SA (ESTABLISHED,NEW_ACK);
- aT[ESTABLISHED][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
- aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT);
- aT[ESTABLISHED][FIN_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
- aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
- aT[ESTABLISHED][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[ESTABLISHED][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // Close Wait State
- aT[CLOSE_WAIT][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
- aT[CLOSE_WAIT][APP_SEND] = SA (CLOSE_WAIT, TX_DATA);
- aT[CLOSE_WAIT][SEQ_RECV] = SA (CLOSE_WAIT, NEW_SEQ_RX);
- aT[CLOSE_WAIT][APP_CLOSE] = SA (LAST_ACK, FIN_ACK_TX);
- aT[CLOSE_WAIT][TIMEOUT] = SA (CLOSE_WAIT, NO_ACT);
- aT[CLOSE_WAIT][ACK_RX] = SA (CLOSE_WAIT, NO_ACT);
- aT[CLOSE_WAIT][SYN_RX] = SA (CLOSED, RST_TX);
- aT[CLOSE_WAIT][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[CLOSE_WAIT][FIN_RX] = SA (CLOSE_WAIT, ACK_TX);
- aT[CLOSE_WAIT][FIN_ACK_RX] = SA (CLOSE_WAIT, ACK_TX);
- aT[CLOSE_WAIT][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[CLOSE_WAIT][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // Close Last Ack State
- aT[LAST_ACK][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
- aT[LAST_ACK][APP_SEND] = SA (CLOSED, RST_TX);
- aT[LAST_ACK][SEQ_RECV] = SA (LAST_ACK, NEW_SEQ_RX);
- aT[LAST_ACK][APP_CLOSE] = SA (CLOSED, NO_ACT);
- aT[LAST_ACK][TIMEOUT] = SA (CLOSED, NO_ACT);
- aT[LAST_ACK][ACK_RX] = SA (CLOSED, APP_CLOSED);
- aT[LAST_ACK][SYN_RX] = SA (CLOSED, RST_TX);
- aT[LAST_ACK][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[LAST_ACK][FIN_RX] = SA (LAST_ACK, FIN_ACK_TX);
- aT[LAST_ACK][FIN_ACK_RX] = SA (CLOSED, NO_ACT);
- aT[LAST_ACK][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[LAST_ACK][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // FIN_WAIT_1 state
- aT[FIN_WAIT_1][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_1][APP_SEND] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_1][SEQ_RECV] = SA (FIN_WAIT_1, NEW_SEQ_RX);
- aT[FIN_WAIT_1][APP_CLOSE] = SA (FIN_WAIT_1, NO_ACT);
- aT[FIN_WAIT_1][TIMEOUT] = SA (FIN_WAIT_1, NO_ACT);
- aT[FIN_WAIT_1][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
- aT[FIN_WAIT_1][SYN_RX] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_1][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_1][FIN_RX] = SA (CLOSING, ACK_TX);
- aT[FIN_WAIT_1][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
- aT[FIN_WAIT_1][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[FIN_WAIT_1][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // FIN_WAIT_2 state
- aT[FIN_WAIT_2][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_2][APP_SEND] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_2][SEQ_RECV] = SA (FIN_WAIT_2, NEW_SEQ_RX);
- aT[FIN_WAIT_2][APP_CLOSE] = SA (FIN_WAIT_2, NO_ACT);
- aT[FIN_WAIT_2][TIMEOUT] = SA (FIN_WAIT_2, NO_ACT);
- aT[FIN_WAIT_2][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
- aT[FIN_WAIT_2][SYN_RX] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_2][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[FIN_WAIT_2][FIN_RX] = SA (TIMED_WAIT, ACK_TX);
- aT[FIN_WAIT_2][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
- aT[FIN_WAIT_2][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[FIN_WAIT_2][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // CLOSING state
- aT[CLOSING][APP_LISTEN] = SA (CLOSED, RST_TX);
- aT[CLOSING][APP_CONNECT] = SA (CLOSED, RST_TX);
- aT[CLOSING][APP_SEND] = SA (CLOSED, RST_TX);
- aT[CLOSING][SEQ_RECV] = SA (CLOSED, RST_TX);
- aT[CLOSING][APP_CLOSE] = SA (CLOSED, RST_TX);
- aT[CLOSING][TIMEOUT] = SA (CLOSING, NO_ACT);
- aT[CLOSING][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[CLOSING][SYN_RX] = SA (CLOSED, RST_TX);
- aT[CLOSING][SYN_ACK_RX] = SA (CLOSED, RST_TX);
- aT[CLOSING][FIN_RX] = SA (CLOSED, ACK_TX);
- aT[CLOSING][FIN_ACK_RX] = SA (CLOSED, ACK_TX);
- aT[CLOSING][RST_RX] = SA (CLOSED, CANCEL_TM);
- aT[CLOSING][BAD_FLAGS] = SA (CLOSED, RST_TX);
-
- // TIMED_WAIT state
- aT[TIMED_WAIT][APP_LISTEN] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][APP_SEND] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][SEQ_RECV] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][APP_CLOSE] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][TIMEOUT] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][SYN_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][SYN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][FIN_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][FIN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][RST_RX] = SA (TIMED_WAIT, NO_ACT);
- aT[TIMED_WAIT][BAD_FLAGS] = SA (TIMED_WAIT, NO_ACT);
-
- // Create the flags lookup table
- eV[ 0x00] = SEQ_RECV; // No flags
- eV[ 0x01] = FIN_RX; // Fin
- eV[ 0x02] = SYN_RX; // Syn
- eV[ 0x03] = BAD_FLAGS; // Illegal
- eV[ 0x04] = RST_RX; // Rst
- eV[ 0x05] = BAD_FLAGS; // Illegal
- eV[ 0x06] = BAD_FLAGS; // Illegal
- eV[ 0x07] = BAD_FLAGS; // Illegal
- eV[ 0x08] = SEQ_RECV; // Psh flag is not used
- eV[ 0x09] = FIN_RX; // Fin
- eV[ 0x0a] = SYN_RX; // Syn
- eV[ 0x0b] = BAD_FLAGS; // Illegal
- eV[ 0x0c] = RST_RX; // Rst
- eV[ 0x0d] = BAD_FLAGS; // Illegal
- eV[ 0x0e] = BAD_FLAGS; // Illegal
- eV[ 0x0f] = BAD_FLAGS; // Illegal
- eV[ 0x10] = ACK_RX; // Ack
- eV[ 0x11] = FIN_ACK_RX;// Fin/Ack
- eV[ 0x12] = SYN_ACK_RX;// Syn/Ack
- eV[ 0x13] = BAD_FLAGS; // Illegal
- eV[ 0x14] = RST_RX; // Rst
- eV[ 0x15] = BAD_FLAGS; // Illegal
- eV[ 0x16] = BAD_FLAGS; // Illegal
- eV[ 0x17] = BAD_FLAGS; // Illegal
- eV[ 0x18] = ACK_RX; // Ack
- eV[ 0x19] = FIN_ACK_RX;// Fin/Ack
- eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack
- eV[ 0x1b] = BAD_FLAGS; // Illegal
- eV[ 0x1c] = RST_RX; // Rst
- eV[ 0x1d] = BAD_FLAGS; // Illegal
- eV[ 0x1e] = BAD_FLAGS; // Illegal
- eV[ 0x1f] = BAD_FLAGS; // Illegal
- eV[ 0x20] = SEQ_RECV; // No flags (Urgent not presently used)
- eV[ 0x21] = FIN_RX; // Fin
- eV[ 0x22] = SYN_RX; // Syn
- eV[ 0x23] = BAD_FLAGS; // Illegal
- eV[ 0x24] = RST_RX; // Rst
- eV[ 0x25] = BAD_FLAGS; // Illegal
- eV[ 0x26] = BAD_FLAGS; // Illegal
- eV[ 0x27] = BAD_FLAGS; // Illegal
- eV[ 0x28] = SEQ_RECV; // Psh flag is not used
- eV[ 0x29] = FIN_RX; // Fin
- eV[ 0x2a] = SYN_RX; // Syn
- eV[ 0x2b] = BAD_FLAGS; // Illegal
- eV[ 0x2c] = RST_RX; // Rst
- eV[ 0x2d] = BAD_FLAGS; // Illegal
- eV[ 0x2e] = BAD_FLAGS; // Illegal
- eV[ 0x2f] = BAD_FLAGS; // Illegal
- eV[ 0x30] = ACK_RX; // Ack (Urgent not used)
- eV[ 0x31] = FIN_ACK_RX;// Fin/Ack
- eV[ 0x32] = SYN_ACK_RX;// Syn/Ack
- eV[ 0x33] = BAD_FLAGS; // Illegal
- eV[ 0x34] = RST_RX; // Rst
- eV[ 0x35] = BAD_FLAGS; // Illegal
- eV[ 0x36] = BAD_FLAGS; // Illegal
- eV[ 0x37] = BAD_FLAGS; // Illegal
- eV[ 0x38] = ACK_RX; // Ack
- eV[ 0x39] = FIN_ACK_RX;// Fin/Ack
- eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack
- eV[ 0x3b] = BAD_FLAGS; // Illegal
- eV[ 0x3c] = RST_RX; // Rst
- eV[ 0x3d] = BAD_FLAGS; // Illegal
- eV[ 0x3e] = BAD_FLAGS; // Illegal
- eV[ 0x3f] = BAD_FLAGS; // Illegal
-}
-
-SA TcpStateMachine::Lookup (States_t s, Events_t e)
-{
- NS_LOG_FUNCTION (this << s << e);
- return aT[s][e];
-}
-
-Events_t TcpStateMachine::FlagsEvent (uint8_t f)
-{
- NS_LOG_FUNCTION (this << f);
- // Lookup event from flags
- if (f >= MAX_FLAGS) return BAD_FLAGS;
- return eV[f]; // Look up flags event
-}
-
-static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine
-
-//TcpL4Protocol stuff----------------------------------------------------------
-
-
-/* see http://www.iana.org/assignments/protocol-numbers */
-const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
-
-ObjectFactory
-TcpL4Protocol::GetDefaultRttEstimatorFactory (void)
-{
- ObjectFactory factory;
- factory.SetTypeId (RttMeanDeviation::GetTypeId ());
- return factory;
-}
-
-TypeId
-TcpL4Protocol::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::TcpL4Protocol")
- .SetParent<Ipv4L4Protocol> ()
- .AddAttribute ("RttEstimatorFactory",
- "How RttEstimator objects are created.",
- ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
- MakeObjectFactoryAccessor (&TcpL4Protocol::m_rttFactory),
- MakeObjectFactoryChecker ())
- ;
- return tid;
-}
-
-TcpL4Protocol::TcpL4Protocol ()
- : m_endPoints (new Ipv4EndPointDemux ())
-{
- NS_LOG_FUNCTION_NOARGS ();
- NS_LOG_LOGIC("Made a TcpL4Protocol "<<this);
-}
-
-TcpL4Protocol::~TcpL4Protocol ()
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-void
-TcpL4Protocol::SetNode (Ptr<Node> node)
-{
- m_node = node;
-}
-
-int
-TcpL4Protocol::GetProtocolNumber (void) const
-{
- return PROT_NUMBER;
-}
-int
-TcpL4Protocol::GetVersion (void) const
-{
- return 2;
-}
-
-void
-TcpL4Protocol::DoDispose (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_endPoints != 0)
- {
- delete m_endPoints;
- m_endPoints = 0;
- }
- m_node = 0;
- Ipv4L4Protocol::DoDispose ();
-}
-
-Ptr<Socket>
-TcpL4Protocol::CreateSocket (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
- Ptr<TcpSocketImpl> socket = CreateObject<TcpSocketImpl> ();
- socket->SetNode (m_node);
- socket->SetTcp (this);
- socket->SetRtt (rtt);
- return socket;
-}
-
-Ipv4EndPoint *
-TcpL4Protocol::Allocate (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_endPoints->Allocate ();
-}
-
-Ipv4EndPoint *
-TcpL4Protocol::Allocate (Ipv4Address address)
-{
- NS_LOG_FUNCTION (this << address);
- return m_endPoints->Allocate (address);
-}
-
-Ipv4EndPoint *
-TcpL4Protocol::Allocate (uint16_t port)
-{
- NS_LOG_FUNCTION (this << port);
- return m_endPoints->Allocate (port);
-}
-
-Ipv4EndPoint *
-TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
-{
- NS_LOG_FUNCTION (this << address << port);
- return m_endPoints->Allocate (address, port);
-}
-
-Ipv4EndPoint *
-TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
- Ipv4Address peerAddress, uint16_t peerPort)
-{
- NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
- return m_endPoints->Allocate (localAddress, localPort,
- peerAddress, peerPort);
-}
-
-void
-TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
-{
- NS_LOG_FUNCTION (this << endPoint);
- m_endPoints->DeAllocate (endPoint);
-}
-
-void
-TcpL4Protocol::Receive (Ptr<Packet> packet,
- Ipv4Address const &source,
- Ipv4Address const &destination,
- Ptr<Ipv4Interface> incomingInterface)
-{
- NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
-
- TcpHeader tcpHeader;
- //these two do a peek, so that the packet can be forwarded up
- packet->RemoveHeader (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());
- packet->AddHeader (tcpHeader);
- NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
- Ipv4EndPointDemux::EndPoints endPoints =
- m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
- source, tcpHeader.GetSourcePort (),incomingInterface);
- if (endPoints.empty ())
- {
- NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<<this);
- std::ostringstream oss;
- oss<<" destination IP: ";
- destination.Print (oss);
- oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
- source.Print (oss);
- oss<<" source port: "<<tcpHeader.GetSourcePort ();
- NS_LOG_LOGIC (oss.str ());
- return;
- }
- 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, source, tcpHeader.GetSourcePort ());
-}
-
-void
-TcpL4Protocol::Send (Ptr<Packet> packet,
- Ipv4Address saddr, Ipv4Address daddr,
- uint16_t sport, uint16_t dport)
-{
- NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
-
- TcpHeader tcpHeader;
- tcpHeader.SetDestinationPort (dport);
- tcpHeader.SetSourcePort (sport);
- tcpHeader.InitializeChecksum (saddr,
- daddr,
- PROT_NUMBER);
- tcpHeader.SetFlags (TcpHeader::ACK);
- tcpHeader.SetAckNumber (0);
-
- packet->AddHeader (tcpHeader);
-
- Ptr<Ipv4L3Protocol> ipv4 =
- m_node->GetObject<Ipv4L3Protocol> ();
- if (ipv4 != 0)
- {
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
- }
-}
-
-void
-TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
- Ipv4Address saddr, Ipv4Address daddr)
-{
- NS_LOG_LOGIC("TcpL4Protocol " << this
- << " sending seq " << outgoingHeader.GetSequenceNumber()
- << " ack " << outgoingHeader.GetAckNumber()
- << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec
- << " data size " << packet->GetSize());
- NS_LOG_FUNCTION (this << packet << saddr << daddr);
- // XXX outgoingHeader cannot be logged
-
- outgoingHeader.SetLength (5); //header length in units of 32bit words
- outgoingHeader.SetChecksum (0); //XXX
- outgoingHeader.SetUrgentPointer (0); //XXX
-
- packet->AddHeader (outgoingHeader);
-
- Ptr<Ipv4L3Protocol> ipv4 =
- m_node->GetObject<Ipv4L3Protocol> ();
- if (ipv4 != 0)
- {
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
- }
- else
- NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
-}
-
-}; // namespace ns3
-
--- a/src/internet-node/tcp-l4-protocol.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-
-#ifndef TCP_L4_PROTOCOL_H
-#define TCP_L4_PROTOCOL_H
-
-#include <stdint.h>
-
-#include "ns3/packet.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ptr.h"
-#include "ns3/object-factory.h"
-#include "ipv4-end-point-demux.h"
-#include "ipv4-l4-protocol.h"
-#include "ipv4-interface.h"
-
-#include "tcp-header.h"
-#include "tcp-typedefs.h"
-
-namespace ns3 {
-
-class Node;
-class Socket;
-class TcpHeader;
-/**
- * \brief Implementation of the TCP protocol
- */
-class TcpL4Protocol : public Ipv4L4Protocol {
-public:
- static TypeId GetTypeId (void);
- static const uint8_t PROT_NUMBER;
- /**
- * \brief Constructor
- */
- TcpL4Protocol ();
- virtual ~TcpL4Protocol ();
-
- void SetNode (Ptr<Node> node);
-
- virtual int GetProtocolNumber (void) const;
- virtual int GetVersion (void) const;
-
- /**
- * \return A smart Socket pointer to a TcpSocketImpl, allocated by this instance
- * of the TCP protocol
- */
- Ptr<Socket> CreateSocket (void);
-
- Ipv4EndPoint *Allocate (void);
- Ipv4EndPoint *Allocate (Ipv4Address address);
- Ipv4EndPoint *Allocate (uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
- Ipv4Address peerAddress, uint16_t peerPort);
-
- void DeAllocate (Ipv4EndPoint *endPoint);
-
-// // called by TcpSocketImpl.
-// bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr,
-// uint16_t sport, uint16_t dport);
-
- /**
- * \brief Send a packet via TCP
- * \param packet The packet to send
- * \param saddr The source Ipv4Address
- * \param daddr The destination Ipv4Address
- * \param sport The source port number
- * \param dport The destination port number
- */
- void Send (Ptr<Packet> packet,
- Ipv4Address saddr, Ipv4Address daddr,
- uint16_t sport, uint16_t dport);
- /**
- * \brief Recieve a packet up the protocol stack
- * \param p The Packet to dump the contents into
- * \param source The source's Ipv4Address
- * \param destination The destinations Ipv4Address
- * \param incomingInterface The Ipv4Interface it was received on
- */
- virtual void Receive (Ptr<Packet> p,
- Ipv4Address const &source,
- Ipv4Address const &destination,
- Ptr<Ipv4Interface> incomingInterface);
-
-protected:
- virtual void DoDispose (void);
-private:
- Ptr<Node> m_node;
- Ipv4EndPointDemux *m_endPoints;
- ObjectFactory m_rttFactory;
-private:
- friend class TcpSocketImpl;
- void SendPacket (Ptr<Packet>, TcpHeader,
- Ipv4Address, Ipv4Address);
- static ObjectFactory GetDefaultRttEstimatorFactory (void);
-};
-
-}; // namespace ns3
-
-#endif /* TCP_L4_PROTOCOL_H */
--- a/src/internet-node/tcp-socket-factory-impl.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-#include "tcp-socket-factory-impl.h"
-#include "tcp-l4-protocol.h"
-#include "ns3/socket.h"
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-TcpSocketFactoryImpl::TcpSocketFactoryImpl ()
- : m_tcp (0)
-{}
-TcpSocketFactoryImpl::~TcpSocketFactoryImpl ()
-{
- NS_ASSERT (m_tcp == 0);
-}
-
-void
-TcpSocketFactoryImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
-{
- m_tcp = tcp;
-}
-
-Ptr<Socket>
-TcpSocketFactoryImpl::CreateSocket (void)
-{
- return m_tcp->CreateSocket ();
-}
-
-void
-TcpSocketFactoryImpl::DoDispose (void)
-{
- m_tcp = 0;
- TcpSocketFactory::DoDispose ();
-}
-
-} // namespace ns3
--- a/src/internet-node/tcp-socket-factory-impl.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-#ifndef TCP_SOCKET_FACTORY_IMPL_H
-#define TCP_SOCKET_FACTORY_IMPL_H
-
-#include "ns3/tcp-socket-factory.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class TcpL4Protocol;
-
-/**
- * \ingroup internetNode
- * \defgroup Tcp Tcp
- */
-/**
- * \ingroup Tcp
- * \section Tcp Overview
- *
- * The TCP code in ns3::InternetNode is ported from the
- * <a href="http://www.ece.gatech.edu/research/labs/MANIACS/GTNetS/">
- * Georgia Tech Network Simulator (GTNetS)</a>.
- *
- * Most of the logic is in class ns3::TcpSocketImpl.
- */
-class TcpSocketFactoryImpl : public TcpSocketFactory
-{
-public:
- TcpSocketFactoryImpl ();
- virtual ~TcpSocketFactoryImpl ();
-
- void SetTcp (Ptr<TcpL4Protocol> tcp);
-
- virtual Ptr<Socket> CreateSocket (void);
-
-protected:
- virtual void DoDispose (void);
-private:
- Ptr<TcpL4Protocol> m_tcp;
-};
-
-} // namespace ns3
-
-#endif /* TCP_SOCKET_FACTORY_IMPL_H */
--- a/src/internet-node/tcp-socket-impl.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1435 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-
-
-#include "ns3/node.h"
-#include "ns3/inet-socket-address.h"
-#include "ns3/log.h"
-#include "ns3/ipv4.h"
-#include "tcp-socket-impl.h"
-#include "tcp-l4-protocol.h"
-#include "ipv4-end-point.h"
-#include "ipv4-l4-demux.h"
-#include "ns3/simulation-singleton.h"
-#include "tcp-typedefs.h"
-#include "ns3/simulator.h"
-#include "ns3/packet.h"
-#include "ns3/uinteger.h"
-#include "ns3/trace-source-accessor.h"
-
-#include <algorithm>
-
-NS_LOG_COMPONENT_DEFINE ("TcpSocketImpl");
-
-using namespace std;
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (TcpSocketImpl);
-
-TypeId
-TcpSocketImpl::GetTypeId ()
-{
- static TypeId tid = TypeId("ns3::TcpSocketImpl")
- .SetParent<TcpSocket> ()
- .AddTraceSource ("CongestionWindow",
- "The TCP connection's congestion window",
- MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
- ;
- return tid;
-}
-
- TcpSocketImpl::TcpSocketImpl ()
- : m_skipRetxResched (false),
- m_dupAckCount (0),
- m_delAckCount (0),
- m_endPoint (0),
- m_node (0),
- m_tcp (0),
- m_errno (ERROR_NOTERROR),
- m_shutdownSend (false),
- m_shutdownRecv (false),
- m_connected (false),
- m_state (CLOSED),
- m_closeNotified (false),
- m_closeRequestNotified (false),
- m_closeOnEmpty (false),
- m_pendingClose (false),
- m_nextTxSequence (0),
- m_highTxMark (0),
- m_highestRxAck (0),
- m_lastRxAck (0),
- m_nextRxSequence (0),
- m_pendingData (0),
- m_rtt (0),
- m_lastMeasuredRtt (Seconds(0.0)),
- m_rxAvailable (0),
- m_wouldBlock (false)
-{
- NS_LOG_FUNCTION (this);
-}
-
-TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock)
- : TcpSocket(sock), //copy the base class callbacks
- m_skipRetxResched (sock.m_skipRetxResched),
- m_dupAckCount (sock.m_dupAckCount),
- m_delAckCount (0),
- m_delAckMaxCount (sock.m_delAckMaxCount),
- m_delAckTimeout (sock.m_delAckTimeout),
- m_endPoint (0),
- m_node (sock.m_node),
- m_tcp (sock.m_tcp),
- m_remoteAddress (sock.m_remoteAddress),
- m_remotePort (sock.m_remotePort),
- m_localAddress (sock.m_localAddress),
- m_localPort (sock.m_localPort),
- m_errno (sock.m_errno),
- m_shutdownSend (sock.m_shutdownSend),
- m_shutdownRecv (sock.m_shutdownRecv),
- m_connected (sock.m_connected),
- m_state (sock.m_state),
- m_closeNotified (sock.m_closeNotified),
- m_closeRequestNotified (sock.m_closeRequestNotified),
- m_closeOnEmpty (sock.m_closeOnEmpty),
- m_pendingClose (sock.m_pendingClose),
- m_nextTxSequence (sock.m_nextTxSequence),
- m_highTxMark (sock.m_highTxMark),
- m_highestRxAck (sock.m_highestRxAck),
- m_lastRxAck (sock.m_lastRxAck),
- m_nextRxSequence (sock.m_nextRxSequence),
- m_pendingData (0),
- m_segmentSize (sock.m_segmentSize),
- m_rxWindowSize (sock.m_rxWindowSize),
- m_advertisedWindowSize (sock.m_advertisedWindowSize),
- m_cWnd (sock.m_cWnd),
- m_ssThresh (sock.m_ssThresh),
- m_initialCWnd (sock.m_initialCWnd),
- m_rtt (0),
- m_lastMeasuredRtt (Seconds(0.0)),
- m_cnTimeout (sock.m_cnTimeout),
- m_cnCount (sock.m_cnCount),
- m_rxAvailable (0),
- m_wouldBlock (false),
- m_sndBufSize (sock.m_sndBufSize)
-{
- NS_LOG_FUNCTION_NOARGS ();
- NS_LOG_LOGIC("Invoked the copy constructor");
- //copy the pending data if necessary
- if(sock.m_pendingData)
- {
- m_pendingData = sock.m_pendingData->Copy();
- }
- //copy the rtt if necessary
- if (sock.m_rtt)
- {
- m_rtt = sock.m_rtt->Copy();
- }
- //can't "copy" the endpoint just yes, must do this when we know the peer info
- //too; this is in SYN_ACK_TX
-}
-
-TcpSocketImpl::~TcpSocketImpl ()
-{
- NS_LOG_FUNCTION(this);
- m_node = 0;
- if (m_endPoint != 0)
- {
- NS_ASSERT (m_tcp != 0);
- /**
- * Note that this piece of code is a bit tricky:
- * when DeAllocate is called, it will call into
- * Ipv4EndPointDemux::Deallocate which triggers
- * a delete of the associated endPoint which triggers
- * in turn a call to the method ::Destroy below
- * will will zero the m_endPoint field.
- */
- NS_ASSERT (m_endPoint != 0);
- m_tcp->DeAllocate (m_endPoint);
- NS_ASSERT (m_endPoint == 0);
- }
- m_tcp = 0;
- delete m_pendingData; //prevents leak
- m_pendingData = 0;
-}
-
-void
-TcpSocketImpl::SetNode (Ptr<Node> node)
-{
- m_node = node;
- // Initialize some variables
- m_cWnd = m_initialCWnd * m_segmentSize;
- m_rxWindowSize = m_advertisedWindowSize;
-}
-
-void
-TcpSocketImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
-{
- m_tcp = tcp;
-}
-void
-TcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
-{
- m_rtt = rtt;
-}
-
-
-enum Socket::SocketErrno
-TcpSocketImpl::GetErrno (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_errno;
-}
-
-Ptr<Node>
-TcpSocketImpl::GetNode (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_node;
-}
-
-void
-TcpSocketImpl::Destroy (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_node = 0;
- m_endPoint = 0;
- m_tcp = 0;
- m_retxEvent.Cancel ();
-}
-int
-TcpSocketImpl::FinishBind (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_endPoint == 0)
- {
- return -1;
- }
- m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
- m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
- m_localAddress = m_endPoint->GetLocalAddress ();
- m_localPort = m_endPoint->GetLocalPort ();
- return 0;
-}
-
-int
-TcpSocketImpl::Bind (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_endPoint = m_tcp->Allocate ();
- return FinishBind ();
-}
-int
-TcpSocketImpl::Bind (const Address &address)
-{
- NS_LOG_FUNCTION (this<<address);
- if (!InetSocketAddress::IsMatchingType (address))
- {
- return ERROR_INVAL;
- }
- 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 ();
- NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
- }
- else if (ipv4 == Ipv4Address::GetAny () && port != 0)
- {
- m_endPoint = m_tcp->Allocate (port);
- NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
- }
- else if (ipv4 != Ipv4Address::GetAny () && port == 0)
- {
- m_endPoint = m_tcp->Allocate (ipv4);
- NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
- }
- else if (ipv4 != Ipv4Address::GetAny () && port != 0)
- {
- m_endPoint = m_tcp->Allocate (ipv4, port);
- NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
- }
-
- return FinishBind ();
-}
-
-int
-TcpSocketImpl::ShutdownSend (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownSend = true;
- return 0;
-}
-int
-TcpSocketImpl::ShutdownRecv (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownRecv = false;
- return 0;
-}
-
-int
-TcpSocketImpl::Close (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_state == CLOSED)
- {
- return -1;
- }
- if (m_pendingData && m_pendingData->Size() != 0)
- { // App close with pending data must wait until all data transmitted
- m_closeOnEmpty = true;
- NS_LOG_LOGIC("Socket " << this <<
- " deferring close, state " << m_state);
- return 0;
- }
-
- Actions_t action = ProcessEvent (APP_CLOSE);
- ProcessAction (action);
- ShutdownSend ();
- return 0;
-}
-
-int
-TcpSocketImpl::Connect (const Address & address)
-{
- NS_LOG_FUNCTION (this << address);
- if (m_endPoint == 0)
- {
- if (Bind () == -1)
- {
- NS_ASSERT (m_endPoint == 0);
- return -1;
- }
- NS_ASSERT (m_endPoint != 0);
- }
- InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
- m_remoteAddress = transport.GetIpv4 ();
- m_remotePort = transport.GetPort ();
-
- uint32_t localIfIndex;
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
- if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
- {
- m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
- }
- else
- {
- m_errno = ERROR_NOROUTETOHOST;
- return -1;
- }
-
- Actions_t action = ProcessEvent (APP_CONNECT);
- bool success = ProcessAction (action);
- if (success)
- {
- return 0;
- }
- return -1;
-}
-int
-TcpSocketImpl::Send (const Ptr<Packet> p) //p here is just data, no headers
-{ // TCP Does not deal with packets from app, just data
- return Send(p->PeekData(), p->GetSize());
-}
-
-int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size)
-{
- NS_LOG_FUNCTION (this << buf << size);
- if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
- {
- if (size > GetTxAvailable ())
- {
- m_wouldBlock = true;
- m_errno = ERROR_MSGSIZE;
- return -1;
- }
- if (!m_pendingData)
- {
- m_pendingData = new PendingData (); // Create if non-existent
- m_firstPendingSequence = m_nextTxSequence; // Note seq of first
- }
- //PendingData::Add always copies the data buffer, never modifies
- m_pendingData->Add (size,buf);
- NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() <<
- " state " << m_state);
- Actions_t action = ProcessEvent (APP_SEND);
- NS_LOG_DEBUG(" action " << action);
- if (!ProcessAction (action))
- {
- return -1; // Failed, return zero
- }
- return size;
- }
- else
- {
- m_errno = ERROR_NOTCONN;
- return -1;
- }
-}
-
-int TcpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
-{
- NS_LOG_FUNCTION (this << p << address);
- InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
- Ipv4Address ipv4 = transport.GetIpv4 ();
- uint16_t port = transport.GetPort ();
- return DoSendTo (p, ipv4, port);
-}
-
-int TcpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
-{
- NS_LOG_FUNCTION (this << p << ipv4 << port);
- if (m_endPoint == 0)
- {
- if (Bind () == -1)
- {
- NS_ASSERT (m_endPoint == 0);
- return -1;
- }
- NS_ASSERT (m_endPoint != 0);
- }
- if (m_shutdownSend)
- {
- m_errno = ERROR_SHUTDOWN;
- return -1;
- }
- m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
- m_endPoint->GetLocalPort (), port);
- NotifyDataSent (p->GetSize ());
- return 0;
-}
-
-int
-TcpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
-{
- NS_LOG_FUNCTION (this << address << p);
- if (!m_connected)
- {
- m_errno = ERROR_NOTCONN;
- return -1;
- }
- else
- {
- return Send (p); //drop the address according to BSD manpages
- }
-}
-
-uint32_t
-TcpSocketImpl::GetTxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_pendingData != 0)
- {
- uint32_t unAckedDataSize =
- m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck);
- NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error
- return m_sndBufSize-unAckedDataSize;
- }
- else
- {
- return m_sndBufSize;
- }
-}
-
-int
-TcpSocketImpl::Listen (uint32_t q)
-{
- NS_LOG_FUNCTION (this << q);
- Actions_t action = ProcessEvent (APP_LISTEN);
- ProcessAction (action);
- return 0;
-}
-
-Ptr<Packet>
-TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_deliveryQueue.empty() )
- {
- return 0;
- }
- Ptr<Packet> p = m_deliveryQueue.front ();
- if (p->GetSize () <= maxSize)
- {
- m_deliveryQueue.pop ();
- m_rxAvailable -= p->GetSize ();
- }
- else
- {
- p = 0;
- }
- return p;
-}
-
-uint32_t
-TcpSocketImpl::GetRxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- // We separately maintain this state to avoid walking the queue
- // every time this might be called
- return m_rxAvailable;
-}
-
-void
-TcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
-{
- NS_LOG_DEBUG("Socket " << this << " got forward up" <<
- " dport " << m_endPoint->GetLocalPort() <<
- " daddr " << m_endPoint->GetLocalAddress() <<
- " sport " << m_endPoint->GetPeerPort() <<
- " saddr " << m_endPoint->GetPeerAddress());
-
- NS_LOG_FUNCTION (this << packet << ipv4 << port);
- if (m_shutdownRecv)
- {
- return;
- }
- TcpHeader tcpHeader;
- packet->RemoveHeader (tcpHeader);
-
- if (tcpHeader.GetFlags () & TcpHeader::ACK)
- {
- Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
- if (m != Seconds (0.0))
- {
- m_lastMeasuredRtt = m;
- }
- }
-
- Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
- Actions_t action = ProcessEvent (event); //updates the state
- Address address = InetSocketAddress (ipv4, port);
- NS_LOG_DEBUG("Socket " << this <<
- " processing pkt action, " << action <<
- " current state " << m_state);
- ProcessPacketAction (action, packet, tcpHeader, address);
-}
-
-Actions_t TcpSocketImpl::ProcessEvent (Events_t e)
-{
- NS_LOG_FUNCTION (this << e);
- States_t saveState = m_state;
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " processing event " << e);
- // simulation singleton is a way to get a single global static instance of a
- // class intended to be a singleton; see simulation-singleton.h
- SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
- // debug
- if (stateAction.action == RST_TX)
- {
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " sending RST from state "
- << saveState << " event " << e);
- }
- bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED
- && e != TIMEOUT);
- m_state = stateAction.state;
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " moved from state " << saveState
- << " to state " <<m_state);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " pendingData " << m_pendingData);
-
- //extra event logic is here for RX events
- //e = SYN_ACK_RX
- if (saveState == SYN_SENT && m_state == ESTABLISHED)
- // this means the application side has completed its portion of
- // the handshaking
- {
- Simulator::ScheduleNow(&TcpSocketImpl::ConnectionSucceeded, this);
- //NotifyConnectionSucceeded ();
- m_connected = true;
- m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
- }
-
- if (needCloseNotify && !m_closeNotified)
- {
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from "
- << m_state << " event " << e << " closeNot " << m_closeNotified
- << " action " << stateAction.action);
- NotifyCloseCompleted ();
- m_closeNotified = true;
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " calling Closed from PE"
- << " origState " << saveState
- << " event " << e);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from "
- << m_state << " event " << e
- << " set CloseNotif ");
- }
- return stateAction.action;
-}
-
-void TcpSocketImpl::SendEmptyPacket (uint8_t flags)
-{
- NS_LOG_FUNCTION (this << flags);
- Ptr<Packet> p = Create<Packet> ();
- TcpHeader header;
-
- header.SetFlags (flags);
- header.SetSequenceNumber (m_nextTxSequence);
- header.SetAckNumber (m_nextRxSequence);
- header.SetSourcePort (m_endPoint->GetLocalPort ());
- header.SetDestinationPort (m_remotePort);
- header.SetWindowSize (m_advertisedWindowSize);
- m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
- m_remoteAddress);
- Time rto = m_rtt->RetransmitTimeout ();
- if (flags & TcpHeader::SYN)
- {
- rto = m_cnTimeout;
- m_cnTimeout = m_cnTimeout + m_cnTimeout;
- m_cnCount--;
- }
- if (m_retxEvent.IsExpired () ) //no outstanding timer
- {
- NS_LOG_LOGIC ("Schedule retransmission timeout at time "
- << Simulator::Now ().GetSeconds () << " to expire at time "
- << (Simulator::Now () + rto).GetSeconds ());
- m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this);
- }
-}
-
-bool TcpSocketImpl::ProcessAction (Actions_t a)
-{ // These actions do not require a packet or any TCP Headers
- NS_LOG_FUNCTION (this << a);
- switch (a)
- {
- case NO_ACT:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT");
- break;
- case ACK_TX:
- SendEmptyPacket (TcpHeader::ACK);
- break;
- case ACK_TX_1:
- NS_ASSERT (false); // This should be processed in ProcessPacketAction
- break;
- case RST_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RST_TX");
- SendEmptyPacket (TcpHeader::RST);
- break;
- case SYN_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_TX");
- // TCP SYN Flag consumes one byte
- // is the above correct? we're SENDING a syn, not acking back -- Raj
- // commented out for now
- // m_nextTxSequence+= 1;
- SendEmptyPacket (TcpHeader::SYN);
- break;
- case SYN_ACK_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
- // TCP SYN Flag consumes one byte
- ++m_nextRxSequence;
- SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
- break;
- case FIN_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_TX");
- SendEmptyPacket (TcpHeader::FIN);
- break;
- case FIN_ACK_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_ACK_TX");
- SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
- break;
- case NEW_ACK:
- NS_ASSERT (false); // This should be processed in ProcessPacketAction
- break;
- case NEW_SEQ_RX:
- NS_ASSERT (false); // This should be processed in ProcessPacketAction
- break;
- case RETX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RETX");
- break;
- case TX_DATA:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action TX_DATA");
- SendPendingData ();
- break;
- case PEER_CLOSE:
- NS_ASSERT (false); // This should be processed in ProcessPacketAction
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action PEER_CLOSE");
- break;
- case APP_CLOSED:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_CLOSED");
- break;
- case CANCEL_TM:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action CANCEL_TM");
- break;
- case APP_NOTIFY:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_NOTIFY");
- break;
- case SERV_NOTIFY:
- NS_ASSERT (false); // This should be processed in ProcessPacketAction
- break;
- case LAST_ACTION:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action LAST_ACTION");
- break;
- }
- return true;
-}
-
-bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
- const TcpHeader& tcpHeader,
- const Address& fromAddress)
-{
- NS_LOG_FUNCTION (this << a << p << fromAddress);
- uint32_t localIfIndex;
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
- switch (a)
- {
- case SYN_ACK_TX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
-// m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
-// m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
-// if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
-// {
-// m_localAddress = ipv4->GetAddress (localIfIndex);
-// }
- if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl
- {
- NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
- //notify the server that we got a SYN
- // If server refuses connection do nothing
- if (!NotifyConnectionRequest(fromAddress)) return true;
- // Clone the socket
- Ptr<TcpSocketImpl> newSock = Copy ();
- NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock);
- //this listening socket should do nothing more
- Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock,
- p, tcpHeader,fromAddress);
- return true;
- }
- // This is the cloned endpoint
- m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
- if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
- {
- m_localAddress = ipv4->GetAddress (localIfIndex);
- m_endPoint->SetLocalAddress (m_localAddress);
- // Leave local addr in the portmap to any, as the path from
- // remote can change and packets can arrive on different interfaces
- //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
- }
- // TCP SYN consumes one byte
- m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
- SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
- break;
- case ACK_TX_1:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1");
- // TCP SYN consumes one byte
- m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
- m_nextTxSequence = tcpHeader.GetAckNumber ();
- m_firstPendingSequence = m_nextTxSequence; //bug 166
- NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" <<
- " nextRxSeq " << m_nextRxSequence);
- SendEmptyPacket (TcpHeader::ACK);
- m_rxWindowSize = tcpHeader.GetWindowSize ();
- if (tcpHeader.GetAckNumber () > m_highestRxAck)
- {
- m_highestRxAck = tcpHeader.GetAckNumber ();
- // Data freed from the send buffer; notify any blocked sender
- if (m_wouldBlock)
- {
- NotifySend (GetTxAvailable ());
- m_wouldBlock = false;
- }
- }
- SendPendingData ();
- break;
- case NEW_ACK:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_ACK_TX");
- if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
- {
- break;
- }
- if (tcpHeader.GetAckNumber () == m_highestRxAck &&
- tcpHeader.GetAckNumber () < m_nextTxSequence)
- {
- DupAck (tcpHeader, ++m_dupAckCount);
- break;
- }
- if (tcpHeader.GetAckNumber () > m_highestRxAck)
- {
- m_dupAckCount = 0;
- }
- NewAck (tcpHeader.GetAckNumber ());
- break;
- case NEW_SEQ_RX:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX");
- NewRx (p, tcpHeader, fromAddress); // Process new data received
- break;
- case PEER_CLOSE:
- {
- // First we have to be sure the FIN packet was not received
- // out of sequence. If so, note pending close and process
- // new sequence rx
- if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
- { // process close later
- m_pendingClose = true;
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose"
- << " rxseq " << tcpHeader.GetSequenceNumber ()
- << " nextRxSeq " << m_nextRxSequence);
- NewRx (p, tcpHeader, fromAddress);
- return true;
- }
- // Now we need to see if any data came with the FIN
- // if so, call NewRx
- if (p->GetSize () != 0)
- {
- NewRx (p, tcpHeader, fromAddress);
- }
- States_t saveState = m_state; // Used to see if app responds
- NS_LOG_LOGIC ("TcpSocketImpl " << this
- << " peer close, state " << m_state);
- if (!m_closeRequestNotified)
- {
- NS_LOG_LOGIC ("TCP " << this
- << " calling AppCloseRequest");
- NotifyCloseRequested();
- m_closeRequestNotified = true;
- }
- NS_LOG_LOGIC ("TcpSocketImpl " << this
- << " peer close, state after " << m_state);
- if (m_state == saveState)
- { // Need to ack, the application will close later
- SendEmptyPacket (TcpHeader::ACK);
-// // Also need to re-tx the ack if we
- }
- if (m_state == LAST_ACK)
- {
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " scheduling LATO1");
- m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
- &TcpSocketImpl::LastAckTimeout,this);
- }
- break;
- }
- case SERV_NOTIFY:
- NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY");
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
- NotifyNewConnectionCreated (this, fromAddress);
- m_connected = true; // ! This is bogus; fix when we clone the tcp
- m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
- //treat the connection orientation final ack as a newack
- CommonNewAck (tcpHeader.GetAckNumber (), true);
- break;
- default:
- break;
- }
- return true;
-}
-
-void TcpSocketImpl::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
-{
- // Get port and address from peer (connecting host)
- m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
- m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
- m_endPoint = m_tcp->Allocate (m_localAddress,
- m_localPort,
- m_remoteAddress,
- m_remotePort);
- //the cloned socket with be in listen state, so manually change state
- m_state = SYN_RCVD;
- //equivalent to FinishBind
- m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
- m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
- ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
- }
-
-void TcpSocketImpl::ConnectionSucceeded()
-{ // We would preferred to have scheduled an event directly to
- // NotifyConnectionSucceeded, but (sigh) these are protected
- // and we can get the address of it :(
- NotifyConnectionSucceeded();
-}
-
-bool TcpSocketImpl::SendPendingData (bool withAck)
-{
- NS_LOG_FUNCTION (this << withAck);
- NS_LOG_LOGIC ("ENTERING SendPendingData");
- if (!m_pendingData)
- {
- return false; // No data exists
- }
- uint32_t nPacketsSent = 0;
- while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
- {
- uint32_t w = AvailableWindow ();// Get available window size
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " SendPendingData"
- << " w " << w
- << " rxwin " << m_rxWindowSize
- << " cWnd " << m_cWnd
- << " segsize " << m_segmentSize
- << " nextTxSeq " << m_nextTxSequence
- << " highestRxAck " << m_highestRxAck
- << " pd->Size " << m_pendingData->Size ()
- << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
-
- if (w < m_segmentSize && m_pendingData->Size () > w)
- {
- break; // No more
- }
- uint32_t s = std::min (w, m_segmentSize); // Send no more than window
- Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence,
- m_nextTxSequence);
- NS_LOG_LOGIC("TcpSocketImpl " << this << " sendPendingData"
- << " txseq " << m_nextTxSequence
- << " s " << s
- << " datasize " << p->GetSize() );
- uint8_t flags = 0;
- if (withAck)
- {
- flags |= TcpHeader::ACK;
- }
- uint32_t sz = p->GetSize (); // Size of packet
- uint32_t remainingData = m_pendingData->SizeFromSeq(
- m_firstPendingSequence,
- m_nextTxSequence + SequenceNumber (sz));
- if (m_closeOnEmpty && (remainingData == 0))
- {
- flags = TcpHeader::FIN;
- m_state = FIN_WAIT_1;
- }
-
- TcpHeader header;
- header.SetFlags (flags);
- header.SetSequenceNumber (m_nextTxSequence);
- header.SetAckNumber (m_nextRxSequence);
- header.SetSourcePort (m_endPoint->GetLocalPort());
- header.SetDestinationPort (m_remotePort);
- if (m_shutdownSend)
- {
- m_errno = ERROR_SHUTDOWN;
- return -1;
- }
-
-
- if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
- {
- Time rto = m_rtt->RetransmitTimeout ();
- NS_LOG_LOGIC ("Schedule retransmission timeout at time " <<
- Simulator::Now ().GetSeconds () << " to expire at time " <<
- (Simulator::Now () + rto).GetSeconds () );
- m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this);
- }
- NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
- m_tcp->SendPacket (p, header,
- m_endPoint->GetLocalAddress (),
- m_remoteAddress);
- m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT
- // Notify the application
- Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, p->GetSize ());
- nPacketsSent++; // Count sent this loop
- m_nextTxSequence += sz; // Advance next tx sequence
- // Note the high water mark
- m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
- }
- NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
- NS_LOG_LOGIC("RETURN SendPendingData");
- return (nPacketsSent>0);
-}
-
-uint32_t TcpSocketImpl::UnAckDataCount ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_nextTxSequence - m_highestRxAck;
-}
-
-uint32_t TcpSocketImpl::BytesInFlight ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_highTxMark - m_highestRxAck;
-}
-
-uint32_t TcpSocketImpl::Window ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- NS_LOG_LOGIC ("TcpSocketImpl::Window() "<<this);
- return std::min (m_rxWindowSize, m_cWnd.Get());
-}
-
-uint32_t TcpSocketImpl::AvailableWindow ()
-{
- NS_LOG_FUNCTION_NOARGS ();
- uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
- uint32_t win = Window ();
- if (win < unack)
- {
- return 0; // No space available
- }
- return (win - unack); // Amount of window space available
-}
-
-void TcpSocketImpl::NewRx (Ptr<Packet> p,
- const TcpHeader& tcpHeader,
- const Address& fromAddress)
-{
- NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx,"
- << " seq " << tcpHeader.GetSequenceNumber()
- << " ack " << tcpHeader.GetAckNumber()
- << " p.size is " << p->GetSize () );
- NS_LOG_DEBUG ("TcpSocketImpl " << this <<
- " NewRx," <<
- " seq " << tcpHeader.GetSequenceNumber() <<
- " ack " << tcpHeader.GetAckNumber() <<
- " p.size is " << p->GetSize());
- States_t origState = m_state;
- uint32_t s = p->GetSize (); // Size of associated data
- if (s == 0)
- {// Nothing to do if no associated data
- return;
- }
- // Log sequence received if enabled
- // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
- // Three possibilities
- // 1) Received seq is expected, deliver this and any buffered data
- // 2) Received seq is < expected, just re-ack previous
- // 3) Received seq is > expected, just re-ack previous and buffer data
- if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
- { // If seq is expected seq
- // 1) Update nextRxSeq
- // 2) Deliver to application this packet
- // 3) See if any buffered can be delivered
- // 4) Send the ack
- m_nextRxSequence += s; // Advance next expected sequence
- //bytesReceived += s; // Statistics
- NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
- SocketRxAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
- m_deliveryQueue.push (p);
- m_rxAvailable += p->GetSize ();
- NotifyDataRecv ();
- if (m_closeNotified)
- {
- NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
- }
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " adv rxseq by " << s);
- // Look for buffered data
- UnAckData_t::iterator i;
- // Note that the bufferedData list DOES contain the tcp header
- while (!m_bufferedData.empty ())
- { // Check the buffered data for delivery
- NS_LOG_LOGIC("TCP " << this << " bufferedData.size() "
- << m_bufferedData.size ()
- << " time " << Simulator::Now ());
- i = m_bufferedData.begin ();
- Ptr<Packet> p1 = i->second;
- SequenceNumber s1 = 0;
- if (i->first > m_nextRxSequence)
- {
- break; // Not next expected
- }
- // already have the header as a param
- //TCPHeader* h = dynamic_cast<TCPHeader*>(p1->PopPDU());
- // Check non-null here...
- uint8_t flags = tcpHeader.GetFlags (); // Flags (used below)
- if (i->first < m_nextRxSequence)
- { // remove already delivered data
- // Two cases here.
- // 1) seq + length <= nextRxSeq, just discard
- // 2) seq + length > nextRxSeq, can deliver partial
- s1 = p->GetSize ();
- if (i->first + s1 < m_nextRxSequence)
- { // Just remove from list
- //bufferedData.erase(i);
- p1 = 0; // Nothing to deliver
- }
- else
- { // Remove partial data to prepare for delivery
- uint32_t dup = m_nextRxSequence - i->first;
- i->second = p1->CreateFragment (0, p1->GetSize () - dup);
- p1 = i->second;
- }
- }
- else
- { // At this point i->first must equal nextRxSeq
- if (i->first != m_nextRxSequence)
- {
- NS_FATAL_ERROR ("HuH? NexRx failure, first "
- << i->first << " nextRxSeq " << m_nextRxSequence);
- }
- s1 = p1->GetSize ();
- }
- SocketRxAddressTag tag;
- tag.SetAddress (fromAddress);
- p1->AddTag (tag);
- m_deliveryQueue.push (p1);
- m_rxAvailable += p->GetSize ();
- NotifyDataRecv ();
-
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " adv rxseq1 by " << s1 );
- m_nextRxSequence += s1; // Note data received
- m_bufferedData.erase (i); // Remove from list
- if (flags & TcpHeader::FIN)
- NS_LOG_LOGIC("TcpSocketImpl " << this
- << " found FIN in buffered");
- }
-
- if (m_pendingClose || (origState > ESTABLISHED))
- { // See if we can close now
- if (m_bufferedData.empty())
- {
- ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
- }
- }
- }
- else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
- { // Need to buffer this one
- NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
- UnAckData_t::iterator i =
- m_bufferedData.find (tcpHeader.GetSequenceNumber () );
- if (i != m_bufferedData.end () )
- {
- i->second = 0; // relase reference to already buffered
- }
- // Save for later delivery
- m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
- }
- else
- { // debug
- NS_LOG_LOGIC("TCP " << this
- << " got seq " << tcpHeader.GetSequenceNumber ()
- << " expected " << m_nextRxSequence
- << " flags " << tcpHeader.GetFlags ());
- }
- // Now send a new ack packet acknowledging all received and delivered data
- if(++m_delAckCount >= m_delAckMaxCount)
- {
- m_delAckEvent.Cancel();
- m_delAckCount = 0;
- SendEmptyPacket (TcpHeader::ACK);
- }
- else
- {
- m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketImpl::DelAckTimeout, this);
- }
-}
-
-void TcpSocketImpl::DelAckTimeout ()
-{
- m_delAckCount = 0;
- SendEmptyPacket (TcpHeader::ACK);
-}
-
-void TcpSocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer)
-{ // CommonNewAck is called only for "New" (non-duplicate) acks
- // and MUST be called by any subclass, from the NewAck function
- // Always cancel any pending re-tx timer on new acknowledgement
- NS_LOG_FUNCTION (this << ack << skipTimer);
- //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
- if (!skipTimer)
- {
- m_retxEvent.Cancel ();
- //On recieving a "New" ack we restart retransmission timer .. RFC 2988
- Time rto = m_rtt->RetransmitTimeout ();
- NS_LOG_LOGIC ("Schedule retransmission timeout at time "
- << Simulator::Now ().GetSeconds () << " to expire at time "
- << (Simulator::Now () + rto).GetSeconds ());
- m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this);
- }
- NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack
- << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
- m_highestRxAck = ack; // Note the highest recieved Ack
- if (m_wouldBlock)
- {
- // m_highestRxAck advancing means some data was acked, and the size
- // of free space in the buffer has increased
- NotifySend (GetTxAvailable ());
- m_wouldBlock = false;
- }
- if (ack > m_nextTxSequence)
- {
- m_nextTxSequence = ack; // If advanced
- }
- // See if all pending ack'ed; if so we can delete the data
- if (m_pendingData)
- { // Data exists, see if can be deleted
- if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
- { // All pending acked, can be deleted
- m_pendingData->Clear ();
- delete m_pendingData;
- m_pendingData = 0;
- // Insure no re-tx timer
- m_retxEvent.Cancel ();
- }
- }
- // Try to send more data
- SendPendingData();
-}
-
-Ptr<TcpSocketImpl> TcpSocketImpl::Copy ()
-{
- return CopyObject<TcpSocketImpl> (this);
-}
-
-void TcpSocketImpl::NewAck (SequenceNumber seq)
-{ // New acknowledgement up to sequence number "seq"
- // Adjust congestion window in response to new ack's received
- NS_LOG_FUNCTION (this << seq);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewAck "
- << " seq " << seq
- << " cWnd " << m_cWnd
- << " ssThresh " << m_ssThresh);
- if (m_cWnd < m_ssThresh)
- { // Slow start mode, add one segSize to cWnd
- m_cWnd += m_segmentSize;
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewCWnd SlowStart, cWnd " << m_cWnd
- << " sst " << m_ssThresh);
- }
- else
- { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
- double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd.Get();
- if (adder < 1.0)
- {
- adder = 1.0;
- }
- m_cWnd += (uint32_t) adder;
- NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd
- << " sst " << m_ssThresh);
- }
- CommonNewAck (seq, false); // Complete newAck processing
-}
-
-void TcpSocketImpl::DupAck (const TcpHeader& t, uint32_t count)
-{
- NS_LOG_FUNCTION (this << "t " << count);
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " DupAck " << t.GetAckNumber ()
- << ", count " << count
- << ", time " << Simulator::Now ());
- if (count == 3)
- { // Count of three indicates triple duplicate ack
- m_ssThresh = Window () / 2; // Per RFC2581
- m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
- NS_LOG_LOGIC("TcpSocketImpl " << this << "Tahoe TDA, time " << Simulator::Now ()
- << " seq " << t.GetAckNumber ()
- << " in flight " << BytesInFlight ()
- << " new ssthresh " << m_ssThresh);
-
- m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
- // For Tahoe, we also reset nextTxSeq
- m_nextTxSequence = m_highestRxAck;
- SendPendingData ();
- }
-}
-
-void TcpSocketImpl::ReTxTimeout ()
-{ // Retransmit timeout
- NS_LOG_FUNCTION (this);
- m_ssThresh = Window () / 2; // Per RFC2581
- m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
- // Set cWnd to segSize on timeout, per rfc2581
- // Collapse congestion window (re-enter slowstart)
- m_cWnd = m_segmentSize;
- m_nextTxSequence = m_highestRxAck; // Start from highest Ack
- m_rtt->IncreaseMultiplier (); // DoubleValue timeout value for next retx timer
- Retransmit (); // Retransmit the packet
-}
-
-void TcpSocketImpl::LastAckTimeout ()
-{
- m_lastAckEvent.Cancel ();
- if (m_state == LAST_ACK)
- {
- Actions_t action = ProcessEvent (TIMEOUT);
- ProcessAction (action);
- }
- if (!m_closeNotified)
- {
- m_closeNotified = true;
- }
-}
-
-void TcpSocketImpl::Retransmit ()
-{
- NS_LOG_FUNCTION (this);
- uint8_t flags = TcpHeader::NONE;
- if (m_state == SYN_SENT)
- {
- if (m_cnCount > 0)
- {
- SendEmptyPacket (TcpHeader::SYN);
- return;
- }
- else
- {
- NotifyConnectionFailed ();
- return;
- }
- }
- if (!m_pendingData)
- {
- if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
- { // Must have lost FIN, re-send
- SendEmptyPacket (TcpHeader::FIN);
- }
- return;
- }
- Ptr<Packet> p = m_pendingData->CopyFromSeq (m_segmentSize,
- m_firstPendingSequence,
- m_highestRxAck);
- // Calculate remaining data for COE check
- uint32_t remainingData = m_pendingData->SizeFromSeq (
- m_firstPendingSequence,
- m_nextTxSequence + SequenceNumber(p->GetSize ()));
- if (m_closeOnEmpty && remainingData == 0)
- { // Add the FIN flag
- flags = flags | TcpHeader::FIN;
- }
-
- NS_LOG_LOGIC ("TcpSocketImpl " << this << " retxing seq " << m_highestRxAck);
- if (m_retxEvent.IsExpired () )
- {
- Time rto = m_rtt->RetransmitTimeout ();
- NS_LOG_LOGIC ("Schedule retransmission timeout at time "
- << Simulator::Now ().GetSeconds () << " to expire at time "
- << (Simulator::Now () + rto).GetSeconds ());
- m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this);
- }
- m_rtt->SentSeq (m_highestRxAck,p->GetSize ());
- // And send the packet
- TcpHeader tcpHeader;
- tcpHeader.SetSequenceNumber (m_nextTxSequence);
- tcpHeader.SetAckNumber (m_nextRxSequence);
- tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
- tcpHeader.SetDestinationPort (m_remotePort);
- tcpHeader.SetFlags (flags);
- tcpHeader.SetWindowSize (m_advertisedWindowSize);
-
- m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
- m_remoteAddress);
-}
-
-void
-TcpSocketImpl::SetSndBufSize (uint32_t size)
-{
- m_sndBufSize = size;
-}
-
-uint32_t
-TcpSocketImpl::GetSndBufSize (void) const
-{
- return m_sndBufSize;
-}
-
-void
-TcpSocketImpl::SetRcvBufSize (uint32_t size)
-{
- m_rcvBufSize = size;
-}
-
-uint32_t
-TcpSocketImpl::GetRcvBufSize (void) const
-{
- return m_rcvBufSize;
-}
-
-void
-TcpSocketImpl::SetSegSize (uint32_t size)
-{
- m_segmentSize = size;
-}
-
-uint32_t
-TcpSocketImpl::GetSegSize (void) const
-{
- return m_segmentSize;
-}
-
-void
-TcpSocketImpl::SetAdvWin (uint32_t window)
-{
- m_advertisedWindowSize = window;
-}
-
-uint32_t
-TcpSocketImpl::GetAdvWin (void) const
-{
- return m_advertisedWindowSize;
-}
-
-void
-TcpSocketImpl::SetSSThresh (uint32_t threshold)
-{
- m_ssThresh = threshold;
-}
-
-uint32_t
-TcpSocketImpl::GetSSThresh (void) const
-{
- return m_ssThresh;
-}
-
-void
-TcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
-{
- m_initialCWnd = cwnd;
-}
-
-uint32_t
-TcpSocketImpl::GetInitialCwnd (void) const
-{
- return m_initialCWnd;
-}
-
-void
-TcpSocketImpl::SetConnTimeout (Time timeout)
-{
- m_cnTimeout = timeout;
-}
-
-Time
-TcpSocketImpl::GetConnTimeout (void) const
-{
- return m_cnTimeout;
-}
-
-void
-TcpSocketImpl::SetConnCount (uint32_t count)
-{
- m_cnCount = count;
-}
-
-uint32_t
-TcpSocketImpl::GetConnCount (void) const
-{
- return m_cnCount;
-}
-
-void
-TcpSocketImpl::SetDelAckTimeout (Time timeout)
-{
- m_delAckTimeout = timeout;
-}
-
-Time
-TcpSocketImpl::GetDelAckTimeout (void) const
-{
- return m_delAckTimeout;
-}
-
-void
-TcpSocketImpl::SetDelAckMaxCount (uint32_t count)
-{
- m_delAckMaxCount = count;
-}
-
-uint32_t
-TcpSocketImpl::GetDelAckMaxCount (void) const
-{
- return m_delAckMaxCount;
-}
-
-}//namespace ns3
--- a/src/internet-node/tcp-socket-impl.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- */
-#ifndef TCP_SOCKET_IMPL_H
-#define TCP_SOCKET_IMPL_H
-
-#include <stdint.h>
-#include <queue>
-#include "ns3/callback.h"
-#include "ns3/traced-value.h"
-#include "ns3/tcp-socket.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/event-id.h"
-#include "tcp-typedefs.h"
-#include "pending-data.h"
-#include "sequence-number.h"
-#include "rtt-estimator.h"
-
-
-namespace ns3 {
-
-class Ipv4EndPoint;
-class Node;
-class Packet;
-class TcpL4Protocol;
-class TcpHeader;
-
-class TcpSocketImpl : public TcpSocket
-{
-public:
- static TypeId GetTypeId (void);
- /**
- * Create an unbound tcp socket.
- */
- TcpSocketImpl ();
- TcpSocketImpl (const TcpSocketImpl& sock);
- virtual ~TcpSocketImpl ();
-
- void SetNode (Ptr<Node> node);
- void SetTcp (Ptr<TcpL4Protocol> tcp);
- void SetRtt (Ptr<RttEstimator> rtt);
-
- virtual enum SocketErrno GetErrno (void) const;
- virtual Ptr<Node> GetNode (void) const;
- virtual int Bind (void);
- virtual int Bind (const Address &address);
- virtual int Close (void);
- virtual int ShutdownSend (void);
- virtual int ShutdownRecv (void);
- virtual int Connect(const Address &address);
- virtual int Send (Ptr<Packet> p);
- virtual int Send (const uint8_t* buf, uint32_t size);
- virtual int SendTo(Ptr<Packet> p, const Address &address);
- virtual uint32_t GetTxAvailable (void) const;
- virtual int Listen(uint32_t queueLimit);
-
- virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
- virtual uint32_t GetRxAvailable (void) const;
-
-private:
- friend class Tcp;
- // invoked by Tcp class
- int FinishBind (void);
- void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
- void Destroy (void);
- int DoSendTo (Ptr<Packet> p, const Address &daddr);
- int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
- void SendEmptyPacket(uint8_t flags);
- //methods for state
- bool ProcessAction (Actions_t a);
- bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader,
- Ipv4Address saddr, Ipv4Address daddr);
- bool ProcessPacketAction (Actions_t a, Ptr<Packet> p,
- const TcpHeader& tcpHeader,
- const Address& fromAddress);
- Actions_t ProcessEvent (Events_t e);
- bool SendPendingData(bool withAck = false);
- void CompleteFork(Ptr<Packet>, const TcpHeader&, const Address& fromAddress);
- void ConnectionSucceeded();
-
- //methods for window management
- virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes
- virtual uint32_t BytesInFlight(); // Return total bytes in flight
- virtual uint32_t Window(); // Return window size (integer)
- virtual uint32_t AvailableWindow();// Return unfilled portion of window
-
- // Manage data tx/rx
- void NewRx (Ptr<Packet>, const TcpHeader&, const Address&);
- // XXX This should be virtual and overridden
- Ptr<TcpSocketImpl> Copy ();
- void NewAck (SequenceNumber seq);
- // XXX This should be virtual and overridden
- void DupAck (const TcpHeader& t, uint32_t count);
- void ReTxTimeout ();
- void DelAckTimeout ();
- void LastAckTimeout ();
- void Retransmit ();
- void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
-
- // attribute related
- virtual void SetSndBufSize (uint32_t size);
- virtual uint32_t GetSndBufSize (void) const;
- virtual void SetRcvBufSize (uint32_t size);
- virtual uint32_t GetRcvBufSize (void) const;
- virtual void SetSegSize (uint32_t size);
- virtual uint32_t GetSegSize (void) const;
- virtual void SetAdvWin (uint32_t window);
- virtual uint32_t GetAdvWin (void) const;
- virtual void SetSSThresh (uint32_t threshold);
- virtual uint32_t GetSSThresh (void) const;
- virtual void SetInitialCwnd (uint32_t cwnd);
- virtual uint32_t GetInitialCwnd (void) const;
- virtual void SetConnTimeout (Time timeout);
- virtual Time GetConnTimeout (void) const;
- virtual void SetConnCount (uint32_t count);
- virtual uint32_t GetConnCount (void) const;
- virtual void SetDelAckTimeout (Time timeout);
- virtual Time GetDelAckTimeout (void) const;
- virtual void SetDelAckMaxCount (uint32_t count);
- virtual uint32_t GetDelAckMaxCount (void) const;
-
- bool m_skipRetxResched;
- uint32_t m_dupAckCount;
- EventId m_retxEvent;
- EventId m_lastAckEvent;
-
- EventId m_delAckEvent;
- uint32_t m_delAckCount;
- uint32_t m_delAckMaxCount;
- Time m_delAckTimeout;
-
- Ipv4EndPoint *m_endPoint;
- Ptr<Node> m_node;
- Ptr<TcpL4Protocol> m_tcp;
- Ipv4Address m_remoteAddress;
- uint16_t m_remotePort;
- //these two are so that the socket/endpoint cloning works
- Ipv4Address m_localAddress;
- uint16_t m_localPort;
- enum SocketErrno m_errno;
- bool m_shutdownSend;
- bool m_shutdownRecv;
- bool m_connected;
-
- //manage the state infomation
- States_t m_state;
- bool m_closeNotified;
- bool m_closeRequestNotified;
- bool m_closeOnEmpty;
- bool m_pendingClose;
-
-
- //sequence info, sender side
- SequenceNumber m_nextTxSequence;
- SequenceNumber m_highTxMark;
- SequenceNumber m_highestRxAck;
- SequenceNumber m_lastRxAck;
-
- //sequence info, reciever side
- SequenceNumber m_nextRxSequence;
-
- //history data
- //this is the incoming data buffer which sorts out of sequence data
- UnAckData_t m_bufferedData;
- //this is kind of the tx buffer
- PendingData* m_pendingData;
- SequenceNumber m_firstPendingSequence;
-
- // Window management
- uint32_t m_segmentSize; //SegmentSize
- uint32_t m_rxWindowSize;
- uint32_t m_advertisedWindowSize; //Window to advertise
- TracedValue<uint32_t> m_cWnd; //Congestion window
- uint32_t m_ssThresh; //Slow Start Threshold
- uint32_t m_initialCWnd; //Initial cWnd value
-
- // Round trip time estimation
- Ptr<RttEstimator> m_rtt;
- Time m_lastMeasuredRtt;
-
- // Timer-related members
- Time m_cnTimeout;
- uint32_t m_cnCount;
-
- // Temporary queue for delivering data to application
- std::queue<Ptr<Packet> > m_deliveryQueue;
- uint32_t m_rxAvailable;
-
- bool m_wouldBlock; // set to true whenever socket would block on send()
-
- // Attributes
- uint32_t m_rcvBufSize; // maximum receive socket buffer size
- uint32_t m_sndBufSize; // buffer limit for the outgoing queue
-};
-
-}//namespace ns3
-
-#endif /* TCP_SOCKET_IMPL_H */
--- a/src/internet-node/tcp-typedefs.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Georgia Tech Research Corporation
- *
- * 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: Raj Bhattacharjea <raj.b@gatech.edu>
- * typedefs for tcp state machine
- */
-
-#include <vector>
-#include <map>
-#include "sequence-number.h"
-
-#ifndef TCP_TYPEDEFS_H
-#define TCP_TYPEDEFS_H
-
-namespace ns3 {
-
-typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t; // Flags are 6 bits
-
-typedef enum {
- CLOSED, // 0
- LISTEN, // 1
- SYN_SENT, // 2
- SYN_RCVD, // 3
- ESTABLISHED, // 4
- CLOSE_WAIT, // 5
- LAST_ACK, // 6
- FIN_WAIT_1, // 7
- FIN_WAIT_2, // 8
- CLOSING, // 9
- TIMED_WAIT, // 10
- LAST_STATE } States_t;
-
-typedef enum {
- APP_LISTEN, // 0
- APP_CONNECT, // 1
- APP_SEND, // 2
- SEQ_RECV, // 3
- APP_CLOSE, // 4
- TIMEOUT, // 5
- ACK_RX, // 6
- SYN_RX, // 7
- SYN_ACK_RX, // 8
- FIN_RX, // 9
- FIN_ACK_RX, // 10
- RST_RX, // 11
- BAD_FLAGS, // 12
- LAST_EVENT } Events_t;
-
-typedef enum {
- NO_ACT, // 0
- ACK_TX, // 1
- ACK_TX_1, // ACK response to syn
- RST_TX, // 2
- SYN_TX, // 3
- SYN_ACK_TX, // 4
- FIN_TX, // 5
- FIN_ACK_TX, // 6
- NEW_ACK, // 7
- NEW_SEQ_RX, // 8
- RETX, // 9
- TX_DATA, // 10
- PEER_CLOSE, // 11
- APP_CLOSED, // 12
- CANCEL_TM, // 13
- APP_NOTIFY, // 14 - Notify app that connection failed
- SERV_NOTIFY, // 15 - Notify server tcp that connection completed
- LAST_ACTION } Actions_t;
-
-class SA // State/Action pair
-{
-public:
- SA () : state (LAST_STATE), action (LAST_ACTION) { }
- SA (States_t s, Actions_t a) : state (s), action (a) { }
-public:
- States_t state;
- Actions_t action;
-};
-typedef std::vector<SA> StateActionVec_t;
-typedef std::vector<StateActionVec_t> StateActions_t; // One per current state
-typedef std::vector<Events_t> EventVec_t; // For flag events lookup
-
-//type for managing buffered out of sequence data
-typedef std::map<SequenceNumber, Ptr<Packet> > UnAckData_t;
-
-class TcpStateMachine {
- public:
- TcpStateMachine ();
- SA Lookup (States_t, Events_t);
- Events_t FlagsEvent (uint8_t); // Lookup event from flags
-
- public:
- StateActions_t aT; // Action table
- EventVec_t eV; // Flags event lookup
-};
-
-}//namespace ns3
-#endif //TCP_TYPEDEFS_H
--- a/src/internet-node/udp-header.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "udp-header.h"
-#include "ipv4-checksum.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (UdpHeader);
-
-bool UdpHeader::m_calcChecksum = false;
-
-/* The magic values below are used only for debugging.
- * They can be used to easily detect memory corruption
- * problems so you can see the patterns in memory.
- */
-UdpHeader::UdpHeader ()
- : m_sourcePort (0xfffd),
- m_destinationPort (0xfffd),
- m_payloadSize (0xfffd),
- m_initialChecksum (0)
-{}
-UdpHeader::~UdpHeader ()
-{
- m_sourcePort = 0xfffe;
- m_destinationPort = 0xfffe;
- m_payloadSize = 0xfffe;
-}
-
-void
-UdpHeader::EnableChecksums (void)
-{
- m_calcChecksum = true;
-}
-
-void
-UdpHeader::SetDestinationPort (uint16_t port)
-{
- m_destinationPort = port;
-}
-void
-UdpHeader::SetSourcePort (uint16_t port)
-{
- m_sourcePort = port;
-}
-uint16_t
-UdpHeader::GetSourcePort (void) const
-{
- return m_sourcePort;
-}
-uint16_t
-UdpHeader::GetDestinationPort (void) const
-{
- return m_destinationPort;
-}
-void
-UdpHeader::SetPayloadSize (uint16_t size)
-{
- m_payloadSize = size;
-}
-void
-UdpHeader::InitializeChecksum (Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol)
-{
- uint8_t buf[12];
- source.Serialize (buf);
- destination.Serialize (buf+4);
- buf[8] = 0;
- buf[9] = protocol;
- uint16_t udpLength = m_payloadSize + GetSerializedSize ();
- buf[10] = udpLength >> 8;
- buf[11] = udpLength & 0xff;
-
- m_initialChecksum = Ipv4ChecksumCalculate (0, buf, 12);
-}
-
-TypeId
-UdpHeader::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::UdpHeader")
- .SetParent<Header> ()
- .AddConstructor<UdpHeader> ()
- ;
- return tid;
-}
-TypeId
-UdpHeader::GetInstanceTypeId (void) const
-{
- return GetTypeId ();
-}
-void
-UdpHeader::Print (std::ostream &os) const
-{
- os << "length: " << m_payloadSize + GetSerializedSize ()
- << " "
- << m_sourcePort << " > " << m_destinationPort
- ;
-}
-
-uint32_t
-UdpHeader::GetSerializedSize (void) const
-{
- return 8;
-}
-
-void
-UdpHeader::Serialize (Buffer::Iterator start) const
-{
- Buffer::Iterator i = start;
- i.WriteHtonU16 (m_sourcePort);
- i.WriteHtonU16 (m_destinationPort);
- i.WriteHtonU16 (m_payloadSize + GetSerializedSize ());
- i.WriteU16 (0);
-
- if (m_calcChecksum)
- {
-#if 0
- //XXXX
- uint16_t checksum = Ipv4ChecksumCalculate (m_initialChecksum,
- buffer->PeekData (),
- GetSerializedSize () + m_payloadSize);
- checksum = Ipv4ChecksumComplete (checksum);
- i = buffer->Begin ();
- i.Next (6);
- i.WriteU16 (checksum);
-#endif
- }
-}
-uint32_t
-UdpHeader::Deserialize (Buffer::Iterator start)
-{
- Buffer::Iterator i = start;
- m_sourcePort = i.ReadNtohU16 ();
- m_destinationPort = i.ReadNtohU16 ();
- m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
- if (m_calcChecksum)
- {
- // XXX verify checksum.
- }
- return GetSerializedSize ();
-}
-
-
-}; // namespace ns3
--- a/src/internet-node/udp-header.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef UDP_HEADER_H
-#define UDP_HEADER_H
-
-#include <stdint.h>
-#include <string>
-#include "ns3/header.h"
-#include "ns3/ipv4-address.h"
-
-namespace ns3 {
-/**
- * \brief Packet header for UDP packets
- */
-class UdpHeader : public Header
-{
-public:
-
- /**
- * \brief Constructor
- *
- * Creates a null header
- */
- UdpHeader ();
- ~UdpHeader ();
-
- /**
- * \brief Enable checksum calculation for UDP (XXX currently has no effect)
- */
- static void EnableChecksums (void);
- /**
- * \param port the destination port for this UdpHeader
- */
- void SetDestinationPort (uint16_t port);
- /**
- * \param port The source port for this UdpHeader
- */
- void SetSourcePort (uint16_t port);
- /**
- * \return The source port for this UdpHeader
- */
- uint16_t GetSourcePort (void) const;
- /**
- * \return the destination port for this UdpHeader
- */
- uint16_t GetDestinationPort (void) const;
- /**
- * \param size The payload size in bytes
- */
- void SetPayloadSize (uint16_t size);
-
- /**
- * \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 (Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol);
-
- static TypeId GetTypeId (void);
- virtual TypeId GetInstanceTypeId (void) const;
- virtual void Print (std::ostream &os) const;
- virtual uint32_t GetSerializedSize (void) const;
- virtual void Serialize (Buffer::Iterator start) const;
- virtual uint32_t Deserialize (Buffer::Iterator start);
-
-private:
- uint16_t m_sourcePort;
- uint16_t m_destinationPort;
- uint16_t m_payloadSize;
- uint16_t m_initialChecksum;
-
- static bool m_calcChecksum;
-};
-
-} // namespace ns3
-
-#endif /* UDP_HEADER */
--- a/src/internet-node/udp-l4-protocol.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ns3/log.h"
-#include "ns3/assert.h"
-#include "ns3/packet.h"
-#include "ns3/node.h"
-
-#include "udp-l4-protocol.h"
-#include "udp-header.h"
-#include "ipv4-end-point-demux.h"
-#include "ipv4-end-point.h"
-#include "ipv4-l3-protocol.h"
-#include "udp-socket-impl.h"
-
-NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol);
-
-/* see http://www.iana.org/assignments/protocol-numbers */
-const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
-
-TypeId
-UdpL4Protocol::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::UdpL4Protocol")
- .SetParent<Ipv4L4Protocol> ()
- .AddConstructor<UdpL4Protocol> ()
- ;
- return tid;
-}
-
-UdpL4Protocol::UdpL4Protocol ()
- : m_endPoints (new Ipv4EndPointDemux ())
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-UdpL4Protocol::~UdpL4Protocol ()
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-void
-UdpL4Protocol::SetNode (Ptr<Node> node)
-{
- m_node = node;
-}
-
-int
-UdpL4Protocol::GetProtocolNumber (void) const
-{
- return PROT_NUMBER;
-}
-int
-UdpL4Protocol::GetVersion (void) const
-{
- return 2;
-}
-
-
-void
-UdpL4Protocol::DoDispose (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_endPoints != 0)
- {
- delete m_endPoints;
- m_endPoints = 0;
- }
- m_node = 0;
- Ipv4L4Protocol::DoDispose ();
-}
-
-Ptr<Socket>
-UdpL4Protocol::CreateSocket (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
- socket->SetNode (m_node);
- socket->SetUdp (this);
- return socket;
-}
-
-Ipv4EndPoint *
-UdpL4Protocol::Allocate (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_endPoints->Allocate ();
-}
-
-Ipv4EndPoint *
-UdpL4Protocol::Allocate (Ipv4Address address)
-{
- NS_LOG_FUNCTION (this << address);
- return m_endPoints->Allocate (address);
-}
-
-Ipv4EndPoint *
-UdpL4Protocol::Allocate (uint16_t port)
-{
- NS_LOG_FUNCTION (this << port);
- return m_endPoints->Allocate (port);
-}
-
-Ipv4EndPoint *
-UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
-{
- NS_LOG_FUNCTION (this << address << port);
- return m_endPoints->Allocate (address, port);
-}
-Ipv4EndPoint *
-UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
- Ipv4Address peerAddress, uint16_t peerPort)
-{
- NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
- return m_endPoints->Allocate (localAddress, localPort,
- peerAddress, peerPort);
-}
-
-void
-UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
-{
- NS_LOG_FUNCTION (this << endPoint);
- m_endPoints->DeAllocate (endPoint);
-}
-
-void
-UdpL4Protocol::Receive(Ptr<Packet> packet,
- Ipv4Address const &source,
- Ipv4Address const &destination,
- Ptr<Ipv4Interface> interface)
-{
- NS_LOG_FUNCTION (this << packet << source << destination);
-
- UdpHeader udpHeader;
- packet->RemoveHeader (udpHeader);
- Ipv4EndPointDemux::EndPoints endPoints =
- m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (),
- source, udpHeader.GetSourcePort (), interface);
- for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
- endPoint != endPoints.end (); endPoint++)
- {
- (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ());
- }
-}
-
-void
-UdpL4Protocol::Send (Ptr<Packet> packet,
- Ipv4Address saddr, Ipv4Address daddr,
- uint16_t sport, uint16_t dport)
-{
- NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
-
- UdpHeader udpHeader;
- udpHeader.SetDestinationPort (dport);
- udpHeader.SetSourcePort (sport);
- udpHeader.SetPayloadSize (packet->GetSize ());
- udpHeader.InitializeChecksum (saddr,
- daddr,
- PROT_NUMBER);
-
- packet->AddHeader (udpHeader);
-
- Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
- if (ipv4 != 0)
- {
- NS_LOG_LOGIC ("Sending to IP");
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
- }
-}
-
-
-}; // namespace ns3
-
--- a/src/internet-node/udp-l4-protocol.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006,2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#ifndef UDP_L4_PROTOCOL_H
-#define UDP_L4_PROTOCOL_H
-
-#include <stdint.h>
-
-#include "ns3/packet.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ptr.h"
-#include "ipv4-end-point-demux.h"
-#include "ipv4-l4-protocol.h"
-
-namespace ns3 {
-
-class Node;
-class Socket;
-/**
- * \brief Implementation of the UDP protocol
- */
-class UdpL4Protocol : public Ipv4L4Protocol {
-public:
- static TypeId GetTypeId (void);
- static const uint8_t PROT_NUMBER;
-
- UdpL4Protocol ();
- virtual ~UdpL4Protocol ();
-
- void SetNode (Ptr<Node> node);
-
- virtual int GetProtocolNumber (void) const;
- virtual int GetVersion (void) const;
-
- /**
- * \return A smart Socket pointer to a UdpSocket, allocated by this instance
- * of the UDP protocol
- */
- Ptr<Socket> CreateSocket (void);
-
- Ipv4EndPoint *Allocate (void);
- Ipv4EndPoint *Allocate (Ipv4Address address);
- Ipv4EndPoint *Allocate (uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
- Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
- Ipv4Address peerAddress, uint16_t peerPort);
-
- void DeAllocate (Ipv4EndPoint *endPoint);
-
- // called by UdpSocket.
- /**
- * \brief Send a packet via UDP
- * \param packet The packet to send
- * \param saddr The source Ipv4Address
- * \param daddr The destination Ipv4Address
- * \param sport The source port number
- * \param dport The destination port number
- */
- void Send (Ptr<Packet> packet,
- Ipv4Address saddr, Ipv4Address daddr,
- uint16_t sport, uint16_t dport);
- /**
- * \brief Receive a packet up the protocol stack
- * \param p The Packet to dump the contents into
- * \param source The source's Ipv4Address
- * \param destination The destinations Ipv4Address
- * \param interface the interface from which the packet is coming.
- */
- // inherited from Ipv4L4Protocol
- virtual void Receive(Ptr<Packet> p,
- Ipv4Address const &source,
- Ipv4Address const &destination,
- Ptr<Ipv4Interface> interface);
-protected:
- virtual void DoDispose (void);
-private:
- Ptr<Node> m_node;
- Ipv4EndPointDemux *m_endPoints;
-};
-
-}; // namespace ns3
-
-#endif /* UDP_L4_PROTOCOL_H */
--- a/src/internet-node/udp-socket-factory-impl.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "udp-socket-factory-impl.h"
-#include "udp-l4-protocol.h"
-#include "ns3/socket.h"
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-UdpSocketFactoryImpl::UdpSocketFactoryImpl ()
- : m_udp (0)
-{}
-UdpSocketFactoryImpl::~UdpSocketFactoryImpl ()
-{
- NS_ASSERT (m_udp == 0);
-}
-
-void
-UdpSocketFactoryImpl::SetUdp (Ptr<UdpL4Protocol> udp)
-{
- m_udp = udp;
-}
-
-Ptr<Socket>
-UdpSocketFactoryImpl::CreateSocket (void)
-{
- return m_udp->CreateSocket ();
-}
-
-void
-UdpSocketFactoryImpl::DoDispose (void)
-{
- m_udp = 0;
- UdpSocketFactory::DoDispose ();
-}
-
-} // namespace ns3
--- a/src/internet-node/udp-socket-factory-impl.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef UDP_SOCKET_FACTORY_IMPL_H
-#define UDP_SOCKET_FACTORY_IMPL_H
-
-#include "ns3/udp-socket-factory.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class UdpL4Protocol;
-
-/**
- * \brief Object to create UDP socket instances
- * \internal
- *
- * This class implements the API for creating UDP sockets.
- * It is a socket factory (deriving from class SocketFactory).
- */
-class UdpSocketFactoryImpl : public UdpSocketFactory
-{
-public:
- UdpSocketFactoryImpl ();
- virtual ~UdpSocketFactoryImpl ();
-
- void SetUdp (Ptr<UdpL4Protocol> udp);
-
- /**
- * \brief Implements a method to create a Udp-based socket and return
- * a base class smart pointer to the socket.
- * \internal
- *
- * \return smart pointer to Socket
- */
- virtual Ptr<Socket> CreateSocket (void);
-
-protected:
- virtual void DoDispose (void);
-private:
- Ptr<UdpL4Protocol> m_udp;
-};
-
-} // namespace ns3
-
-#endif /* UDP_SOCKET_FACTORY_IMPL_H */
--- a/src/internet-node/udp-socket-impl.cc Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,694 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/inet-socket-address.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/ipv4.h"
-#include "ns3/udp-socket-factory.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-#include "ns3/boolean.h"
-#include "udp-socket-impl.h"
-#include "udp-l4-protocol.h"
-#include "ipv4-end-point.h"
-#include "ipv4-l4-demux.h"
-
-NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
-
-namespace ns3 {
-
-static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
-
-// Add attributes generic to all UdpSockets to base class UdpSocket
-TypeId
-UdpSocketImpl::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::UdpSocketImpl")
- .SetParent<UdpSocket> ()
- .AddConstructor<UdpSocketImpl> ()
- .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
- MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
- ;
- return tid;
-}
-
-UdpSocketImpl::UdpSocketImpl ()
- : m_endPoint (0),
- m_node (0),
- m_udp (0),
- m_errno (ERROR_NOTERROR),
- m_shutdownSend (false),
- m_shutdownRecv (false),
- m_connected (false),
- m_rxAvailable (0)
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-UdpSocketImpl::~UdpSocketImpl ()
-{
- NS_LOG_FUNCTION_NOARGS ();
-
- m_node = 0;
- if (m_endPoint != 0)
- {
- NS_ASSERT (m_udp != 0);
- /**
- * Note that this piece of code is a bit tricky:
- * when DeAllocate is called, it will call into
- * Ipv4EndPointDemux::Deallocate which triggers
- * a delete of the associated endPoint which triggers
- * in turn a call to the method ::Destroy below
- * will will zero the m_endPoint field.
- */
- NS_ASSERT (m_endPoint != 0);
- m_udp->DeAllocate (m_endPoint);
- NS_ASSERT (m_endPoint == 0);
- }
- m_udp = 0;
-}
-
-void
-UdpSocketImpl::SetNode (Ptr<Node> node)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_node = node;
-
-}
-void
-UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_udp = udp;
-}
-
-
-enum Socket::SocketErrno
-UdpSocketImpl::GetErrno (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_errno;
-}
-
-Ptr<Node>
-UdpSocketImpl::GetNode (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_node;
-}
-
-void
-UdpSocketImpl::Destroy (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_node = 0;
- m_endPoint = 0;
- m_udp = 0;
-}
-
-int
-UdpSocketImpl::FinishBind (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_endPoint == 0)
- {
- return -1;
- }
- m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
- m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
- return 0;
-}
-
-int
-UdpSocketImpl::Bind (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_endPoint = m_udp->Allocate ();
- return FinishBind ();
-}
-
-int
-UdpSocketImpl::Bind (const Address &address)
-{
- NS_LOG_FUNCTION (this << address);
-
- if (!InetSocketAddress::IsMatchingType (address))
- {
- NS_LOG_ERROR ("Not IsMatchingType");
- return ERROR_INVAL;
- }
- 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 ();
-}
-
-int
-UdpSocketImpl::ShutdownSend (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownSend = true;
- return 0;
-}
-
-int
-UdpSocketImpl::ShutdownRecv (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownRecv = false;
- return 0;
-}
-
-int
-UdpSocketImpl::Close(void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- NotifyCloseCompleted ();
- return 0;
-}
-
-int
-UdpSocketImpl::Connect(const Address & address)
-{
- NS_LOG_FUNCTION (this << address);
- InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
- m_defaultAddress = transport.GetIpv4 ();
- m_defaultPort = transport.GetPort ();
- NotifyConnectionSucceeded ();
- m_connected = true;
-
- return 0;
-}
-
-int
-UdpSocketImpl::Listen (uint32_t queueLimit)
-{
- m_errno = Socket::ERROR_OPNOTSUPP;
- return -1;
-}
-
-int
-UdpSocketImpl::Send (Ptr<Packet> p)
-{
- NS_LOG_FUNCTION (this << p);
-
- if (!m_connected)
- {
- m_errno = ERROR_NOTCONN;
- return -1;
- }
- return DoSend (p);
-}
-
-int
-UdpSocketImpl::DoSend (Ptr<Packet> p)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_endPoint == 0)
- {
- if (Bind () == -1)
- {
- NS_ASSERT (m_endPoint == 0);
- return -1;
- }
- NS_ASSERT (m_endPoint != 0);
- }
- if (m_shutdownSend)
- {
- m_errno = ERROR_SHUTDOWN;
- return -1;
- }
-
- return DoSendTo (p, m_defaultAddress, m_defaultPort);
-}
-
-int
-UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
-{
- NS_LOG_FUNCTION (this << p << 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);
- }
- else
- {
- // connected UDP socket must use default addresses
- NS_LOG_LOGIC ("Connected");
- return DoSendTo (p, m_defaultAddress, m_defaultPort);
- }
-}
-
-int
-UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
-{
- NS_LOG_FUNCTION (this << p << dest << port);
-
- if (m_endPoint == 0)
- {
- if (Bind () == -1)
- {
- NS_ASSERT (m_endPoint == 0);
- return -1;
- }
- NS_ASSERT (m_endPoint != 0);
- }
- if (m_shutdownSend)
- {
- m_errno = ERROR_SHUTDOWN;
- return -1;
- }
-
- if (p->GetSize () > GetTxAvailable () )
- {
- m_errno = ERROR_MSGSIZE;
- return -1;
- }
-
- uint32_t localIfIndex;
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
- // 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
- //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
- if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
- {
- SocketIpTtlTag tag;
- tag.SetTtl (m_ipMulticastTtl);
- p->AddTag (tag);
- }
- else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
- {
- SocketIpTtlTag tag;
- tag.SetTtl (m_ipTtl);
- p->AddTag (tag);
- }
- //
- // If dest is sent to the limited broadcast address (all ones),
- // convert it to send a copy of the packet out of every interface
- //
- if (dest.IsBroadcast ())
- {
- NS_LOG_LOGIC ("Limited broadcast start.");
- for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
- {
- Ipv4Address addri = ipv4->GetAddress (i);
- Ipv4Mask maski = ipv4->GetNetworkMask (i);
- Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
- NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
- << " (mask is " << maski << ")");
- m_udp->Send (p->Copy (), addri, bcast,
- m_endPoint->GetLocalPort (), port);
- NotifyDataSent (p->GetSize ());
- }
- NS_LOG_LOGIC ("Limited broadcast end.");
- return p->GetSize();
- }
- else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
- {
- NS_LOG_LOGIC ("Route exists");
- m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest,
- m_endPoint->GetLocalPort (), port);
- NotifyDataSent (p->GetSize ());
- return p->GetSize();;
- }
- 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
-UdpSocketImpl::GetTxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- // No finite send buffer is modelled, but we must respect
- // the maximum size of an IP datagram (65535 bytes - headers).
- return MAX_IPV4_UDP_DATAGRAM_SIZE;
-}
-
-int
-UdpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
-{
- NS_LOG_FUNCTION (this << address << p);
- InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
- Ipv4Address ipv4 = transport.GetIpv4 ();
- uint16_t port = transport.GetPort ();
- return DoSendTo (p, ipv4, port);
-}
-
-Ptr<Packet>
-UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
-{
- NS_LOG_FUNCTION_NOARGS ();
- if (m_deliveryQueue.empty() )
- {
- return 0;
- }
- Ptr<Packet> p = m_deliveryQueue.front ();
- if (p->GetSize () <= maxSize)
- {
- m_deliveryQueue.pop ();
- m_rxAvailable -= p->GetSize ();
- }
- else
- {
- p = 0;
- }
- return p;
-}
-
-uint32_t
-UdpSocketImpl::GetRxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- // We separately maintain this state to avoid walking the queue
- // every time this might be called
- return m_rxAvailable;
-}
-
-void
-UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
-{
- NS_LOG_FUNCTION (this << packet << ipv4 << port);
-
- if (m_shutdownRecv)
- {
- return;
- }
- if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
- {
- Address address = InetSocketAddress (ipv4, port);
- SocketRxAddressTag tag;
- tag.SetAddress (address);
- packet->AddTag (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::SetRcvBufSize (uint32_t size)
-{
- m_rcvBufSize = size;
-}
-
-uint32_t
-UdpSocketImpl::GetRcvBufSize (void) const
-{
- return m_rcvBufSize;
-}
-
-void
-UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
-{
- m_ipTtl = ipTtl;
-}
-
-uint32_t
-UdpSocketImpl::GetIpTtl (void) const
-{
- return m_ipTtl;
-}
-
-void
-UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
-{
- m_ipMulticastTtl = ipTtl;
-}
-
-uint32_t
-UdpSocketImpl::GetIpMulticastTtl (void) const
-{
- return m_ipMulticastTtl;
-}
-
-} //namespace ns3
-
-
-#ifdef RUN_SELF_TESTS
-
-#include "ns3/test.h"
-#include "ns3/socket-factory.h"
-#include "ns3/udp-socket-factory.h"
-#include "ns3/simulator.h"
-#include "ns3/simple-channel.h"
-#include "ns3/simple-net-device.h"
-#include "ns3/drop-tail-queue.h"
-#include "internet-stack.h"
-#include <string>
-
-namespace ns3 {
-
-class UdpSocketImplTest: public Test
-{
- Ptr<Packet> m_receivedPacket;
- Ptr<Packet> m_receivedPacket2;
-
-public:
- virtual bool RunTests (void);
- UdpSocketImplTest ();
-
- 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);
-};
-
-
-UdpSocketImplTest::UdpSocketImplTest ()
- : Test ("UdpSocketImpl")
-{
-}
-
-void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
- m_receivedPacket = packet;
-}
-
-void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
- m_receivedPacket2 = packet;
-}
-
-void UdpSocketImplTest::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 ());
-}
-
-void UdpSocketImplTest::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 ());
-}
-
-bool
-UdpSocketImplTest::RunTests (void)
-{
- bool result = true;
-
- // Create topology
-
- // Receiver Node
- Ptr<Node> rxNode = CreateObject<Node> ();
- AddInternetStack (rxNode);
- Ptr<SimpleNetDevice> rxDev1, rxDev2;
- { // first interface
- rxDev1 = CreateObject<SimpleNetDevice> ();
- rxDev1->SetAddress (Mac48Address::Allocate ());
- rxNode->AddDevice (rxDev1);
- Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
- uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
- ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1"));
- ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
- ipv4->SetUp (netdev_idx);
- }
-
- { // second interface
- rxDev2 = CreateObject<SimpleNetDevice> ();
- rxDev2->SetAddress (Mac48Address::Allocate ());
- rxNode->AddDevice (rxDev2);
- Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
- uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
- ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1"));
- ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
- ipv4->SetUp (netdev_idx);
- }
-
- // Sender Node
- Ptr<Node> txNode = CreateObject<Node> ();
- AddInternetStack (txNode);
- Ptr<SimpleNetDevice> txDev1;
- {
- txDev1 = CreateObject<SimpleNetDevice> ();
- txDev1->SetAddress (Mac48Address::Allocate ());
- txNode->AddDevice (txDev1);
- Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
- uint32_t netdev_idx = ipv4->AddInterface (txDev1);
- ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2"));
- ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
- ipv4->SetUp (netdev_idx);
- }
- Ptr<SimpleNetDevice> txDev2;
- {
- txDev2 = CreateObject<SimpleNetDevice> ();
- txDev2->SetAddress (Mac48Address::Allocate ());
- txNode->AddDevice (txDev2);
- Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
- uint32_t netdev_idx = ipv4->AddInterface (txDev2);
- ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2"));
- ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
- ipv4->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_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
- rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
-
- Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
- rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
- NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
-
- Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
- Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
-
- // ------ Now the tests ------------
-
- // Unicast test
- m_receivedPacket = Create<Packet> ();
- m_receivedPacket2 = Create<Packet> ();
- NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123),
- InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
- Simulator::Run ();
- NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
- NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
-
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
-
- // Simple broadcast test
-
- m_receivedPacket = Create<Packet> ();
- m_receivedPacket2 = Create<Packet> ();
- NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123),
- InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
- Simulator::Run ();
- NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
- // second socket should not receive it (it is bound specifically to the second interface's address
- NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
-
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
-
- // Broadcast test with multiple receiving sockets
-
- // 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 (&UdpSocketImplTest::ReceivePkt2, this));
- NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
-
- m_receivedPacket = Create<Packet> ();
- m_receivedPacket2 = Create<Packet> ();
- NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123),
-InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
- Simulator::Run ();
- NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
- NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
-
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
-
- Simulator::Destroy ();
-
- return result;
-}
-
-static UdpSocketImplTest gUdpSocketImplTest;
-
-}; // namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- a/src/internet-node/udp-socket-impl.h Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef UDP_SOCKET_IMPL_H
-#define UDP_SOCKET_IMPL_H
-
-#include <stdint.h>
-#include <queue>
-#include "ns3/callback.h"
-#include "ns3/traced-callback.h"
-#include "ns3/socket.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/udp-socket.h"
-
-namespace ns3 {
-
-class Ipv4EndPoint;
-class Node;
-class Packet;
-class UdpL4Protocol;
-
-class UdpSocketImpl : public UdpSocket
-{
-public:
- static TypeId GetTypeId (void);
- /**
- * Create an unbound udp socket.
- */
- UdpSocketImpl ();
- virtual ~UdpSocketImpl ();
-
- void SetNode (Ptr<Node> node);
- void SetUdp (Ptr<UdpL4Protocol> udp);
-
- virtual enum SocketErrno GetErrno (void) const;
- virtual Ptr<Node> GetNode (void) const;
- virtual int Bind (void);
- virtual int Bind (const Address &address);
- virtual int Close (void);
- virtual int ShutdownSend (void);
- virtual int ShutdownRecv (void);
- virtual int Connect(const Address &address);
- virtual int Listen (uint32_t queueLimit);
- virtual int Send (Ptr<Packet> p);
- virtual int SendTo (Ptr<Packet> p, const Address &address);
- virtual uint32_t GetTxAvailable (void) const;
-
- virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
- virtual uint32_t GetRxAvailable (void) const;
-
-private:
- // Attributes set through UdpSocket base class
- virtual void SetRcvBufSize (uint32_t size);
- virtual uint32_t GetRcvBufSize (void) const;
- virtual void SetIpTtl (uint32_t ipTtl);
- virtual uint32_t GetIpTtl (void) const;
- virtual void SetIpMulticastTtl (uint32_t ipTtl);
- virtual uint32_t GetIpMulticastTtl (void) const;
-
- friend class UdpSocketFactory;
- // invoked by Udp class
- int FinishBind (void);
- void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, 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);
-
- Ipv4EndPoint *m_endPoint;
- Ptr<Node> m_node;
- Ptr<UdpL4Protocol> m_udp;
- Ipv4Address m_defaultAddress;
- uint16_t m_defaultPort;
- Callback<void,Ptr<Socket>,uint32_t,const Address &> m_dummyRxCallback;
- Callback<void,Ptr<Socket>,uint8_t const*,uint32_t,const Address &> m_rxCallback;
- TracedCallback<Ptr<const Packet> > m_dropTrace;
-
- enum SocketErrno m_errno;
- bool m_shutdownSend;
- bool m_shutdownRecv;
- bool m_connected;
-
- std::queue<Ptr<Packet> > m_deliveryQueue;
- uint32_t m_rxAvailable;
-
- // Socket attributes
- uint32_t m_rcvBufSize;
- uint32_t m_ipTtl;
- uint32_t m_ipMulticastTtl;
-
-};
-
-}//namespace ns3
-
-#endif /* UDP_SOCKET_IMPL_H */
--- a/src/internet-node/waf Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-exec "`dirname "$0"`"/../../waf "$@"
\ No newline at end of file
--- a/src/internet-node/wscript Wed Jun 11 16:19:28 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-
-
-def build(bld):
- obj = bld.create_ns3_module('internet-node', ['node'])
- obj.source = [
- 'internet-stack.cc',
- 'ipv4-l4-demux.cc',
- 'ipv4-l4-protocol.cc',
- 'udp-header.cc',
- 'tcp-header.cc',
- 'ipv4-checksum.cc',
- 'ipv4-interface.cc',
- 'ipv4-l3-protocol.cc',
- 'ipv4-static-routing.cc',
- 'ipv4-end-point.cc',
- 'udp-l4-protocol.cc',
- 'tcp-l4-protocol.cc',
- 'arp-header.cc',
- 'arp-cache.cc',
- 'arp-ipv4-interface.cc',
- 'arp-l3-protocol.cc',
- 'ipv4-loopback-interface.cc',
- 'udp-socket-impl.cc',
- 'tcp-socket-impl.cc',
- 'ipv4-end-point-demux.cc',
- 'ipv4-impl.cc',
- 'udp-socket-factory-impl.cc',
- 'tcp-socket-factory-impl.cc',
- 'pending-data.cc',
- 'sequence-number.cc',
- 'rtt-estimator.cc',
- ]
-
- headers = bld.create_obj('ns3header')
- headers.module = 'internet-node'
- headers.source = [
- 'internet-stack.h',
- 'udp-header.h',
- 'tcp-header.h',
- 'sequence-number.h',
- ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-cache.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,287 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+
+#include "arp-cache.h"
+#include "arp-header.h"
+#include "ipv4-interface.h"
+
+NS_LOG_COMPONENT_DEFINE ("ArpCache");
+
+namespace ns3 {
+
+TypeId
+ArpCache::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ArpCache")
+ .SetParent<Object> ()
+ .AddAttribute ("AliveTimeout",
+ "When this timeout expires, the matching cache entry needs refreshing",
+ TimeValue (Seconds (120)),
+ MakeTimeAccessor (&ArpCache::m_aliveTimeout),
+ MakeTimeChecker ())
+ .AddAttribute ("DeadTimeout",
+ "When this timeout expires, a new attempt to resolve the matching entry is made",
+ TimeValue (Seconds (100)),
+ MakeTimeAccessor (&ArpCache::m_deadTimeout),
+ MakeTimeChecker ())
+ .AddAttribute ("WaitReplyTimeout",
+ "When this timeout expires, the matching cache entry is marked dead",
+ TimeValue (Seconds (1)),
+ MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
+ MakeTimeChecker ())
+ .AddAttribute ("PendingQueueSize",
+ "The size of the queue for packets pending an arp reply.",
+ UintegerValue (3),
+ MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
+ MakeUintegerChecker<uint32_t> ())
+ ;
+ return tid;
+}
+
+ArpCache::ArpCache ()
+ : m_device (0),
+ m_interface (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+ArpCache::~ArpCache ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+ArpCache::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ Flush ();
+ m_device = 0;
+ m_interface = 0;
+ Object::DoDispose ();
+}
+
+void
+ArpCache::SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
+{
+ m_device = device;
+ m_interface = interface;
+}
+
+Ptr<NetDevice>
+ArpCache::GetDevice (void) const
+{
+ return m_device;
+}
+
+Ptr<Ipv4Interface>
+ArpCache::GetInterface (void) const
+{
+ return m_interface;
+}
+
+void
+ArpCache::SetAliveTimeout (Time aliveTimeout)
+{
+ m_aliveTimeout = aliveTimeout;
+}
+void
+ArpCache::SetDeadTimeout (Time deadTimeout)
+{
+ m_deadTimeout = deadTimeout;
+}
+void
+ArpCache::SetWaitReplyTimeout (Time waitReplyTimeout)
+{
+ m_waitReplyTimeout = waitReplyTimeout;
+}
+
+Time
+ArpCache::GetAliveTimeout (void) const
+{
+ return m_aliveTimeout;
+}
+Time
+ArpCache::GetDeadTimeout (void) const
+{
+ return m_deadTimeout;
+}
+Time
+ArpCache::GetWaitReplyTimeout (void) const
+{
+ return m_waitReplyTimeout;
+}
+
+void
+ArpCache::Flush (void)
+{
+ for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
+ {
+ delete (*i).second;
+ }
+ m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
+}
+
+ArpCache::Entry *
+ArpCache::Lookup (Ipv4Address to)
+{
+ if (m_arpCache.find (to) != m_arpCache.end ())
+ {
+ ArpCache::Entry *entry = m_arpCache[to];
+ return entry;
+ }
+ return 0;
+}
+
+ArpCache::Entry *
+ArpCache::Add (Ipv4Address to)
+{
+ NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
+
+ ArpCache::Entry *entry = new ArpCache::Entry (this);
+ m_arpCache[to] = entry;
+ return entry;
+}
+
+ArpCache::Entry::Entry (ArpCache *arp)
+ : m_arp (arp),
+ m_state (ALIVE)
+{}
+
+
+bool
+ArpCache::Entry::IsDead (void)
+{
+ return (m_state == DEAD)?true:false;
+}
+bool
+ArpCache::Entry::IsAlive (void)
+{
+ return (m_state == ALIVE)?true:false;
+}
+bool
+ArpCache::Entry::IsWaitReply (void)
+{
+ return (m_state == WAIT_REPLY)?true:false;
+}
+
+
+void
+ArpCache::Entry::MarkDead (void)
+{
+ m_state = DEAD;
+ UpdateSeen ();
+}
+void
+ArpCache::Entry::MarkAlive (Address macAddress)
+{
+ NS_ASSERT (m_state == WAIT_REPLY);
+ m_macAddress = macAddress;
+ m_state = ALIVE;
+ UpdateSeen ();
+}
+
+bool
+ArpCache::Entry::UpdateWaitReply (Ptr<Packet> waiting)
+{
+ NS_ASSERT (m_state == WAIT_REPLY);
+ /* We are already waiting for an answer so
+ * we dump the previously waiting packet and
+ * replace it with this one.
+ */
+ if (m_pending.size () >= m_arp->m_pendingQueueSize)
+ {
+ return false;
+ }
+ m_pending.push_back (waiting);
+ return true;
+}
+void
+ArpCache::Entry::MarkWaitReply (Ptr<Packet> waiting)
+{
+ NS_ASSERT (m_state == ALIVE || m_state == DEAD);
+ NS_ASSERT (m_pending.empty ());
+ m_state = WAIT_REPLY;
+ m_pending.push_back (waiting);
+ UpdateSeen ();
+}
+
+Address
+ArpCache::Entry::GetMacAddress (void)
+{
+ NS_ASSERT (m_state == ALIVE);
+ return m_macAddress;
+}
+bool
+ArpCache::Entry::IsExpired (void)
+{
+ Time timeout;
+ switch (m_state) {
+ case ArpCache::Entry::WAIT_REPLY:
+ timeout = m_arp->GetWaitReplyTimeout ();
+ break;
+ case ArpCache::Entry::DEAD:
+ timeout = m_arp->GetDeadTimeout ();
+ break;
+ case ArpCache::Entry::ALIVE:
+ timeout = m_arp->GetAliveTimeout ();
+ break;
+ default:
+ NS_ASSERT (false);
+ timeout = Seconds (0);
+ /* NOTREACHED */
+ break;
+ }
+ Time delta = Simulator::Now () - m_lastSeen;
+ if (delta >= timeout)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+Ptr<Packet>
+ArpCache::Entry::DequeuePending (void)
+{
+ if (m_pending.empty ())
+ {
+ return 0;
+ }
+ else
+ {
+ Ptr<Packet> p = m_pending.front ();
+ m_pending.pop_front ();
+ return p;
+ }
+}
+void
+ArpCache::Entry::UpdateSeen (void)
+{
+ m_lastSeen = Simulator::Now ();
+}
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-cache.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef ARP_CACHE_H
+#define ARP_CACHE_H
+
+#include <stdint.h>
+#include <list>
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/address.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "sgi-hashmap.h"
+
+namespace ns3 {
+
+class NetDevice;
+class Ipv4Interface;
+
+/**
+ * \brief An ARP cache
+ *
+ * A cached lookup table for translating layer 3 addresses to layer 2.
+ * This implementation does lookups from IPv4 to a MAC address
+ */
+class ArpCache : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ class Entry;
+ ArpCache ();
+ ~ArpCache ();
+
+ /**
+ * \param device The hardware NetDevice associated with this ARP chache
+ * \param interface the Ipv4Interface associated with this ARP chache
+ */
+ void SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
+ /**
+ * \return The NetDevice that this ARP cache is associated with
+ */
+ Ptr<NetDevice> GetDevice (void) const;
+ /**
+ * \return the Ipv4Interface that this ARP cache is associated with
+ */
+ Ptr<Ipv4Interface> GetInterface (void) const;
+
+ void SetAliveTimeout (Time aliveTimeout);
+ void SetDeadTimeout (Time deadTimeout);
+ void SetWaitReplyTimeout (Time waitReplyTimeout);
+ Time GetAliveTimeout (void) const;
+ Time GetDeadTimeout (void) const;
+ Time GetWaitReplyTimeout (void) const;
+
+ /**
+ * \brief Do lookup in the ARP chache against an IP address
+ * \param destination The destination IPv4 address to lookup the MAC address
+ * of
+ * \return An ArpCache::Entry with info about layer 2
+ */
+ ArpCache::Entry *Lookup (Ipv4Address destination);
+ /**
+ * \brief Add an Ipv4Address to this ARP cache
+ */
+ ArpCache::Entry *Add (Ipv4Address to);
+ /**
+ * \brief Clear the ArpCache of all entries
+ */
+ void Flush (void);
+
+ /**
+ * \brief A record that that holds information about an ArpCache entry
+ */
+ class Entry {
+ public:
+ /**
+ * \brief Constructor
+ * \param arp The ArpCache this entry belongs to
+ */
+ Entry (ArpCache *arp);
+
+ /**
+ * \brief Changes the state of this entry to dead
+ */
+ void MarkDead (void);
+ /**
+ * \param macAddress
+ */
+ void MarkAlive (Address macAddress);
+ /**
+ * \param waiting
+ */
+ void MarkWaitReply (Ptr<Packet> waiting);
+ /**
+ * \param waiting
+ * \return
+ */
+ bool UpdateWaitReply (Ptr<Packet> waiting);
+ /**
+ * \return True if the state of this entry is dead; false otherwise.
+ */
+ bool IsDead (void);
+ /**
+ * \return True if the state of this entry is alive; false otherwise.
+ */
+ bool IsAlive (void);
+ /**
+ * \return True if the state of this entry is wait_reply; false otherwise.
+ */
+ bool IsWaitReply (void);
+
+ /**
+ * \return The MacAddress of this entry
+ */
+ Address GetMacAddress (void);
+ /**
+ * \return True if this entry has timedout; false otherwise.
+ */
+ bool IsExpired (void);
+
+ /**
+ * \returns 0 is no packet is pending, the next packet to send if
+ * packets are pending.
+ */
+ Ptr<Packet> DequeuePending (void);
+ private:
+ enum ArpCacheEntryState_e {
+ ALIVE,
+ WAIT_REPLY,
+ DEAD
+ };
+
+ void UpdateSeen (void);
+ ArpCache *m_arp;
+ ArpCacheEntryState_e m_state;
+ Time m_lastSeen;
+ Address m_macAddress;
+ std::list<Ptr<Packet> > m_pending;
+ };
+
+private:
+ typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash> Cache;
+ typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash>::iterator CacheI;
+
+ virtual void DoDispose (void);
+
+ Ptr<NetDevice> m_device;
+ Ptr<Ipv4Interface> m_interface;
+ Time m_aliveTimeout;
+ Time m_deadTimeout;
+ Time m_waitReplyTimeout;
+ uint32_t m_pendingQueueSize;
+ Cache m_arpCache;
+};
+
+
+}; // namespace ns3
+
+#endif /* ARP_CACHE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-header.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "arp-header.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (ArpHeader);
+
+void
+ArpHeader::SetRequest (Address sourceHardwareAddress,
+ Ipv4Address sourceProtocolAddress,
+ Address destinationHardwareAddress,
+ Ipv4Address destinationProtocolAddress)
+{
+ m_type = ARP_TYPE_REQUEST;
+ m_macSource = sourceHardwareAddress;
+ m_macDest = destinationHardwareAddress;
+ m_ipv4Source = sourceProtocolAddress;
+ m_ipv4Dest = destinationProtocolAddress;
+}
+void
+ArpHeader::SetReply (Address sourceHardwareAddress,
+ Ipv4Address sourceProtocolAddress,
+ Address destinationHardwareAddress,
+ Ipv4Address destinationProtocolAddress)
+{
+ m_type = ARP_TYPE_REPLY;
+ m_macSource = sourceHardwareAddress;
+ m_macDest = destinationHardwareAddress;
+ m_ipv4Source = sourceProtocolAddress;
+ m_ipv4Dest = destinationProtocolAddress;
+}
+bool
+ArpHeader::IsRequest (void) const
+{
+ return (m_type == ARP_TYPE_REQUEST)?true:false;
+}
+bool
+ArpHeader::IsReply (void) const
+{
+ return (m_type == ARP_TYPE_REPLY)?true:false;
+}
+Address
+ArpHeader::GetSourceHardwareAddress (void)
+{
+ return m_macSource;
+}
+Address
+ArpHeader::GetDestinationHardwareAddress (void)
+{
+ return m_macDest;
+}
+Ipv4Address
+ArpHeader::GetSourceIpv4Address (void)
+{
+ return m_ipv4Source;
+}
+Ipv4Address
+ArpHeader::GetDestinationIpv4Address (void)
+{
+ return m_ipv4Dest;
+}
+
+
+TypeId
+ArpHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ArpHeader")
+ .SetParent<Header> ()
+ .AddConstructor<ArpHeader> ()
+ ;
+ return tid;
+}
+TypeId
+ArpHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+void
+ArpHeader::Print (std::ostream &os) const
+{
+ if (IsRequest ())
+ {
+ os << "request "
+ << "source mac: " << m_macSource << " "
+ << "source ipv4: " << m_ipv4Source << " "
+ << "dest ipv4: " << m_ipv4Dest
+ ;
+ }
+ else
+ {
+ NS_ASSERT (IsReply ());
+ os << "reply "
+ << "source mac: " << m_macSource << " "
+ << "source ipv4: " << m_ipv4Source << " "
+ << "dest mac: " << m_macDest << " "
+ << "dest ipv4: " <<m_ipv4Dest
+ ;
+ }
+}
+uint32_t
+ArpHeader::GetSerializedSize (void) const
+{
+ /* this is the size of an ARP payload. */
+ return 28;
+}
+
+void
+ArpHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT (m_macSource.GetLength () == m_macDest.GetLength ());
+
+ /* ethernet */
+ i.WriteHtonU16 (0x0001);
+ /* ipv4 */
+ i.WriteHtonU16 (0x0800);
+ i.WriteU8 (m_macSource.GetLength ());
+ i.WriteU8 (4);
+ i.WriteHtonU16 (m_type);
+ WriteTo (i, m_macSource);
+ WriteTo (i, m_ipv4Source);
+ WriteTo (i, m_macDest);
+ WriteTo (i, m_ipv4Dest);
+}
+uint32_t
+ArpHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ i.Next (2+2);
+ uint32_t hardwareAddressLen = i.ReadU8 ();
+ i.Next (1);
+ m_type = i.ReadNtohU16 ();
+ ReadFrom (i, m_macSource, hardwareAddressLen);
+ ReadFrom (i, m_ipv4Source);
+ ReadFrom (i, m_macDest, hardwareAddressLen);
+ ReadFrom (i, m_ipv4Dest);
+ return GetSerializedSize ();
+}
+
+}; // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-header.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef ARP_HEADER_H
+#define ARP_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/address.h"
+#include "ns3/ipv4-address.h"
+#include <string>
+
+namespace ns3 {
+/**
+ * \brief The packet header for an ARP packet
+ */
+class ArpHeader : public Header
+{
+public:
+ void SetRequest (Address sourceHardwareAddress,
+ Ipv4Address sourceProtocolAddress,
+ Address destinationHardwareAddress,
+ Ipv4Address destinationProtocolAddress);
+ void SetReply (Address sourceHardwareAddress,
+ Ipv4Address sourceProtocolAddress,
+ Address destinationHardwareAddress,
+ Ipv4Address destinationProtocolAddress);
+ bool IsRequest (void) const;
+ bool IsReply (void) const;
+ Address GetSourceHardwareAddress (void);
+ Address GetDestinationHardwareAddress (void);
+ Ipv4Address GetSourceIpv4Address (void);
+ Ipv4Address GetDestinationIpv4Address (void);
+
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ enum ArpType_e {
+ ARP_TYPE_REQUEST = 1,
+ ARP_TYPE_REPLY = 2
+ };
+ uint16_t m_type;
+ Address m_macSource;
+ Address m_macDest;
+ Ipv4Address m_ipv4Source;
+ Ipv4Address m_ipv4Dest;
+};
+
+}; // namespace ns3
+
+#endif /* ARP_HEADER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-ipv4-interface.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/address.h"
+#include "ns3/pointer.h"
+
+#include "arp-ipv4-interface.h"
+#include "ipv4-l3-protocol.h"
+#include "arp-l3-protocol.h"
+#include "arp-cache.h"
+
+NS_LOG_COMPONENT_DEFINE ("ArpIpv4Interface");
+
+namespace ns3 {
+
+TypeId
+ArpIpv4Interface::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ArpIpv4Interface")
+ .SetParent<Ipv4Interface> ()
+ .AddAttribute ("ArpCache",
+ "The arp cache for this ipv4 interface",
+ PointerValue (0),
+ MakePointerAccessor (&ArpIpv4Interface::m_cache),
+ MakePointerChecker<ArpIpv4Interface> ())
+ ;
+ return tid;
+}
+
+ArpIpv4Interface::ArpIpv4Interface ()
+ : m_node (0),
+ m_device (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+ArpIpv4Interface::~ArpIpv4Interface ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+ArpIpv4Interface::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_node = 0;
+ m_device = 0;
+ m_cache = 0;
+ Ipv4Interface::DoDispose ();
+}
+
+void
+ArpIpv4Interface::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+ DoSetup ();
+}
+void
+ArpIpv4Interface::SetDevice (Ptr<NetDevice> device)
+{
+ m_device = device;
+ DoSetup ();
+}
+
+Ptr<NetDevice>
+ArpIpv4Interface::GetDevice (void) const
+{
+ return m_device;
+}
+
+void
+ArpIpv4Interface::DoSetup (void)
+{
+ if (m_node == 0 || m_device == 0)
+ {
+ return;
+ }
+ Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
+ m_cache = arp->CreateCache (m_device, this);
+}
+
+void
+ArpIpv4Interface::SendTo (Ptr<Packet> p, Ipv4Address dest)
+{
+ NS_LOG_FUNCTION (this << p << dest);
+
+ NS_ASSERT (GetDevice () != 0);
+ if (m_device->NeedsArp ())
+ {
+ NS_LOG_LOGIC ("Needs ARP");
+ Ptr<ArpL3Protocol> arp =
+ m_node->GetObject<ArpL3Protocol> ();
+ Address hardwareDestination;
+ bool found;
+
+ if (dest.IsBroadcast () ||
+ dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) )
+ {
+ NS_LOG_LOGIC ("IsBroadcast");
+ hardwareDestination = GetDevice ()->GetBroadcast ();
+ found = true;
+ }
+ else if (dest.IsMulticast ())
+ {
+ NS_LOG_LOGIC ("IsMulticast");
+ NS_ASSERT_MSG(GetDevice ()->IsMulticast (),
+ "ArpIpv4Interface::SendTo (): Sending multicast packet over "
+ "non-multicast device");
+
+ hardwareDestination = GetDevice ()->MakeMulticastAddress(dest);
+ found = true;
+ }
+ else
+ {
+ NS_LOG_LOGIC ("ARP Lookup");
+ found = arp->Lookup (p, dest, GetDevice (), m_cache, &hardwareDestination);
+ }
+
+ if (found)
+ {
+ NS_LOG_LOGIC ("Address Resolved. Send.");
+ GetDevice ()->Send (p, hardwareDestination,
+ Ipv4L3Protocol::PROT_NUMBER);
+ }
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Doesn't need ARP");
+ GetDevice ()->Send (p, GetDevice ()->GetBroadcast (),
+ Ipv4L3Protocol::PROT_NUMBER);
+ }
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-ipv4-interface.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+#ifndef ARP_IPV4_INTERFACE_H
+#define ARP_IPV4_INTERFACE_H
+
+#include "ipv4-interface.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Node;
+class ArpCache;
+
+/**
+ * \brief an Ipv4 Interface which uses ARP
+ *
+ * If you need to use ARP on top of a specific NetDevice, you
+ * can use this Ipv4Interface subclass to wrap it for the Ipv4 class
+ * when calling Ipv4::AggregateObject.
+ */
+class ArpIpv4Interface : public Ipv4Interface
+{
+public:
+ static TypeId GetTypeId (void);
+
+ ArpIpv4Interface ();
+ virtual ~ArpIpv4Interface ();
+
+ void SetNode (Ptr<Node> node);
+ void SetDevice (Ptr<NetDevice> device);
+
+ virtual Ptr<NetDevice> GetDevice (void) const;
+
+private:
+ virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
+ virtual void DoDispose (void);
+ void DoSetup (void);
+ Ptr<Node> m_node;
+ Ptr<NetDevice> m_device;
+ Ptr<ArpCache> m_cache;
+};
+
+}//namespace ns3
+
+
+#endif /* ARP_IPV4_INTERFACE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-l3-protocol.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/object-vector.h"
+#include "ns3/trace-source-accessor.h"
+
+#include "ipv4-l3-protocol.h"
+#include "arp-l3-protocol.h"
+#include "arp-header.h"
+#include "arp-cache.h"
+#include "ipv4-interface.h"
+
+NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol");
+
+namespace ns3 {
+
+const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806;
+
+NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol);
+
+TypeId
+ArpL3Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ArpL3Protocol")
+ .SetParent<Object> ()
+ .AddAttribute ("CacheList",
+ "The list of ARP caches",
+ ObjectVectorValue (),
+ MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList),
+ MakeObjectVectorChecker<ArpCache> ())
+ .AddTraceSource ("Drop",
+ "Packet dropped because not enough room in pending queue for a specific cache entry.",
+ MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace))
+ ;
+ return tid;
+}
+
+ArpL3Protocol::ArpL3Protocol ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+ArpL3Protocol::~ArpL3Protocol ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+ArpL3Protocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+}
+
+void
+ArpL3Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
+ {
+ Ptr<ArpCache> cache = *i;
+ cache->Dispose ();
+ }
+ m_cacheList.clear ();
+ m_node = 0;
+ Object::DoDispose ();
+}
+
+Ptr<ArpCache>
+ArpL3Protocol::CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
+{
+ Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+ Ptr<ArpCache> cache = CreateObject<ArpCache> ();
+ cache->SetDevice (device, interface);
+ NS_ASSERT (device->IsBroadcast ());
+ device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
+ m_cacheList.push_back (cache);
+ return cache;
+}
+
+Ptr<ArpCache>
+ArpL3Protocol::FindCache (Ptr<NetDevice> device)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
+ {
+ if ((*i)->GetDevice () == device)
+ {
+ return *i;
+ }
+ }
+ NS_ASSERT (false);
+ // quiet compiler
+ return 0;
+}
+
+void
+ArpL3Protocol::Receive(Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ptr<ArpCache> cache = FindCache (device);
+ ArpHeader arp;
+ packet->RemoveHeader (arp);
+
+ NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
+ " node="<<m_node->GetId ()<<", got request from " <<
+ arp.GetSourceIpv4Address () << " for address " <<
+ arp.GetDestinationIpv4Address () << "; we have address " <<
+ cache->GetInterface ()->GetAddress ());
+
+ /**
+ * Note: we do not update the ARP cache when we receive an ARP request
+ * from an unknown node. See bug #107
+ */
+
+ if (arp.IsRequest () &&
+ arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " <<
+ arp.GetSourceIpv4Address () << " -- send reply");
+ SendArpReply (cache, arp.GetSourceIpv4Address (),
+ arp.GetSourceHardwareAddress ());
+ }
+ else if (arp.IsReply () &&
+ arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) &&
+ arp.GetDestinationHardwareAddress () == device->GetAddress ())
+ {
+ Ipv4Address from = arp.GetSourceIpv4Address ();
+ ArpCache::Entry *entry = cache->Lookup (from);
+ if (entry != 0)
+ {
+ if (entry->IsWaitReply ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply from " <<
+ arp.GetSourceIpv4Address ()
+ << " for waiting entry -- flush");
+ Address from_mac = arp.GetSourceHardwareAddress ();
+ entry->MarkAlive (from_mac);
+ Ptr<Packet> pending = entry->DequeuePending();
+ while (pending != 0)
+ {
+ cache->GetInterface ()->Send (pending,
+ arp.GetSourceIpv4Address ());
+ pending = entry->DequeuePending();
+ }
+ }
+ else
+ {
+ // ignore this reply which might well be an attempt
+ // at poisening my arp cache.
+ NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " <<
+ arp.GetSourceIpv4Address () <<
+ " for non-waiting entry -- drop");
+ m_dropTrace (packet);
+ }
+ }
+ else
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
+ m_dropTrace (packet);
+ }
+ }
+ else
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got request from " <<
+ arp.GetSourceIpv4Address () << " for unknown address " <<
+ arp.GetDestinationIpv4Address () << " -- drop");
+ }
+}
+bool
+ArpL3Protocol::Lookup (Ptr<Packet> packet, Ipv4Address destination,
+ Ptr<NetDevice> device,
+ Ptr<ArpCache> cache,
+ Address *hardwareDestination)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ ArpCache::Entry *entry = cache->Lookup (destination);
+ if (entry != 0)
+ {
+ if (entry->IsExpired ())
+ {
+ if (entry->IsDead ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", dead entry for " << destination << " expired -- send arp request");
+ entry->MarkWaitReply (packet);
+ SendArpRequest (cache, destination);
+ }
+ else if (entry->IsAlive ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", alive entry for " << destination << " expired -- send arp request");
+ entry->MarkWaitReply (packet);
+ SendArpRequest (cache, destination);
+ }
+ else if (entry->IsWaitReply ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", wait reply for " << destination << " expired -- drop");
+ entry->MarkDead ();
+ Ptr<Packet> pending = entry->DequeuePending();
+ while (pending != 0)
+ {
+ m_dropTrace (pending);
+ pending = entry->DequeuePending();
+ }
+ m_dropTrace (packet);
+ }
+ }
+ else
+ {
+ if (entry->IsDead ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", dead entry for " << destination << " valid -- drop");
+ m_dropTrace (packet);
+ }
+ else if (entry->IsAlive ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", alive entry for " << destination << " valid -- send");
+ *hardwareDestination = entry->GetMacAddress ();
+ return true;
+ }
+ else if (entry->IsWaitReply ())
+ {
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", wait reply for " << destination << " valid -- drop previous");
+ if (!entry->UpdateWaitReply (packet))
+ {
+ m_dropTrace (packet);
+ }
+ }
+ }
+ }
+ else
+ {
+ // This is our first attempt to transmit data to this destination.
+ NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
+ ", no entry for " << destination << " -- send arp request");
+ entry = cache->Add (destination);
+ entry->MarkWaitReply (packet);
+ SendArpRequest (cache, destination);
+ }
+ return false;
+}
+
+void
+ArpL3Protocol::SendArpRequest (Ptr<const ArpCache> cache, Ipv4Address to)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ ArpHeader arp;
+ NS_LOG_LOGIC ("ARP: sending request from node "<<m_node->GetId ()<<
+ " || src: " << cache->GetDevice ()->GetAddress () <<
+ " / " << cache->GetInterface ()->GetAddress () <<
+ " || dst: " << cache->GetDevice ()->GetBroadcast () <<
+ " / " << to);
+ arp.SetRequest (cache->GetDevice ()->GetAddress (),
+ cache->GetInterface ()->GetAddress (),
+ cache->GetDevice ()->GetBroadcast (),
+ to);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (arp);
+ cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER);
+}
+
+void
+ArpL3Protocol::SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ ArpHeader arp;
+ NS_LOG_LOGIC ("ARP: sending reply from node "<<m_node->GetId ()<<
+ "|| src: " << cache->GetDevice ()->GetAddress () <<
+ " / " << cache->GetInterface ()->GetAddress () <<
+ " || dst: " << toMac << " / " << toIp);
+ arp.SetReply (cache->GetDevice ()->GetAddress (),
+ cache->GetInterface ()->GetAddress (),
+ toMac, toIp);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (arp);
+ cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER);
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/arp-l3-protocol.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef ARP_L3_PROTOCOL_H
+#define ARP_L3_PROTOCOL_H
+
+#include <list>
+#include "ns3/ipv4-address.h"
+#include "ns3/address.h"
+#include "ns3/ptr.h"
+#include "ns3/traced-callback.h"
+
+#include "ipv4-interface.h"
+
+namespace ns3 {
+
+class ArpCache;
+class NetDevice;
+class Node;
+class Packet;
+
+/**
+ * \brief An implementation of the ARP protocol
+ */
+class ArpL3Protocol : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ static const uint16_t PROT_NUMBER;
+
+ ArpL3Protocol ();
+ virtual ~ArpL3Protocol ();
+
+ void SetNode (Ptr<Node> node);
+
+ Ptr<ArpCache> CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
+
+ /**
+ * \brief Recieve a packet
+ */
+ void Receive(Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from);
+ /**
+ * \brief Perform an ARP lookup
+ * \param p
+ * \param destination
+ * \param device
+ * \param cache
+ * \param hardwareDestination
+ * \return
+ */
+ bool Lookup (Ptr<Packet> p, Ipv4Address destination,
+ Ptr<NetDevice> device,
+ Ptr<ArpCache> cache,
+ Address *hardwareDestination);
+protected:
+ virtual void DoDispose (void);
+private:
+ typedef std::list<Ptr<ArpCache> > CacheList;
+ Ptr<ArpCache> FindCache (Ptr<NetDevice> device);
+ void SendArpRequest (Ptr<const ArpCache>cache, Ipv4Address to);
+ void SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac);
+ CacheList m_cacheList;
+ Ptr<Node> m_node;
+ TracedCallback<Ptr<const Packet> > m_dropTrace;
+};
+
+}//namespace ns3
+
+
+#endif /* ARP_L3_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/internet-stack.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,71 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/node.h"
+
+#include "ipv4-l4-demux.h"
+#include "udp-l4-protocol.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-l3-protocol.h"
+#include "arp-l3-protocol.h"
+#include "udp-socket-factory-impl.h"
+#include "tcp-socket-factory-impl.h"
+#include "ipv4-impl.h"
+
+namespace ns3 {
+
+void
+AddInternetStack (Ptr<Node> node)
+{
+ Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+ Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+ ipv4->SetNode (node);
+ arp->SetNode (node);
+
+ Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
+ Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+ Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+
+ ipv4L4Demux->SetNode (node);
+ udp->SetNode (node);
+ tcp->SetNode (node);
+
+ ipv4L4Demux->Insert (udp);
+ ipv4L4Demux->Insert (tcp);
+
+ Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+ Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
+ Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
+
+ udpFactory->SetUdp (udp);
+ tcpFactory->SetTcp (tcp);
+ ipv4Impl->SetIpv4 (ipv4);
+
+ node->AggregateObject (ipv4);
+ node->AggregateObject (arp);
+ node->AggregateObject (ipv4Impl);
+ node->AggregateObject (udpFactory);
+ node->AggregateObject (tcpFactory);
+ node->AggregateObject (ipv4L4Demux);
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/internet-stack.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,33 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+
+#ifndef INTERNET_STACK_H
+#define INTERNET_STACK_H
+
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Node;
+
+void AddInternetStack (Ptr<Node> node);
+
+}//namespace ns3
+
+#endif /* INTERNET_STACK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-checksum.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ipv4-checksum.h"
+
+namespace ns3 {
+
+uint16_t
+Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size)
+{
+ /* see RFC 1071 to understand this code. */
+ uint32_t sum = checksum;
+ uint16_t *data = (uint16_t *) buffer;
+ for (uint16_t i = 0; i < (size/2); i++) {
+ sum += data[i];
+ }
+ if ((size % 2) != 0) {
+ uint8_t tmpBuf[2];
+ tmpBuf[0] = buffer[size-1];
+ tmpBuf[1] = 0;
+ data = (uint16_t *)tmpBuf;
+ sum += *data;
+ }
+ while (sum >> 16) {
+ sum = (sum & 0xffff) + (sum >> 16);
+ }
+ return sum;
+}
+
+uint16_t
+Ipv4ChecksumComplete (uint16_t checksum)
+{
+ return ~checksum;
+}
+
+}; //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-checksum.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV4_CHECKSUM_H
+#define IPV4_CHECKSUM_H
+
+#include <stdint.h>
+
+namespace ns3 {
+
+uint16_t Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size);
+
+uint16_t Ipv4ChecksumComplete (uint16_t checksum);
+
+}; //namespace ns3
+
+#endif /* IPV4_CHECKSUM_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-end-point-demux.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ns3/log.h"
+
+namespace ns3{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux");
+
+Ipv4EndPointDemux::Ipv4EndPointDemux ()
+ : m_ephemeral (49152)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv4EndPointDemux::~Ipv4EndPointDemux ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ Ipv4EndPoint *endPoint = *i;
+ delete endPoint;
+ }
+ m_endPoints.clear ();
+}
+
+bool
+Ipv4EndPointDemux::LookupPortLocal (uint16_t port)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ if ((*i)->GetLocalPort () == port)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ if ((*i)->GetLocalPort () == port &&
+ (*i)->GetLocalAddress () == addr)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+Ipv4EndPoint *
+Ipv4EndPointDemux::Allocate (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ uint16_t port = AllocateEphemeralPort ();
+ if (port == 0)
+ {
+ NS_LOG_WARN ("Ephemeral port allocation failed.");
+ return 0;
+ }
+ Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
+ m_endPoints.push_back (endPoint);
+ NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+ return endPoint;
+}
+
+Ipv4EndPoint *
+Ipv4EndPointDemux::Allocate (Ipv4Address address)
+{
+ NS_LOG_FUNCTION (this << address);
+ uint16_t port = AllocateEphemeralPort ();
+ if (port == 0)
+ {
+ NS_LOG_WARN ("Ephemeral port allocation failed.");
+ return 0;
+ }
+ Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
+ m_endPoints.push_back (endPoint);
+ NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+ return endPoint;
+}
+
+Ipv4EndPoint *
+Ipv4EndPointDemux::Allocate (uint16_t port)
+{
+ NS_LOG_FUNCTION (this << port);
+
+ return Allocate (Ipv4Address::GetAny (), port);
+}
+
+Ipv4EndPoint *
+Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << address << port);
+ if (LookupLocal (address, port))
+ {
+ NS_LOG_WARN ("Duplicate address/port; failing.");
+ return 0;
+ }
+ Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
+ m_endPoints.push_back (endPoint);
+ NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+ return endPoint;
+}
+
+Ipv4EndPoint *
+Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort)
+{
+ NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ if ((*i)->GetLocalPort () == localPort &&
+ (*i)->GetLocalAddress () == localAddress &&
+ (*i)->GetPeerPort () == peerPort &&
+ (*i)->GetPeerAddress () == peerAddress)
+ {
+ NS_LOG_WARN ("No way we can allocate this end-point.");
+ /* no way we can allocate this end-point. */
+ return 0;
+ }
+ }
+ Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
+ endPoint->SetPeer (peerAddress, peerPort);
+ m_endPoints.push_back (endPoint);
+
+ NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+
+ return endPoint;
+}
+
+void
+Ipv4EndPointDemux::DeAllocate (Ipv4EndPoint *endPoint)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ if (*i == endPoint)
+ {
+ delete endPoint;
+ m_endPoints.erase (i);
+ break;
+ }
+ }
+}
+
+/*
+ * If we have an exact match, we return it.
+ * Otherwise, if we find a generic match, we return it.
+ * Otherwise, we return 0.
+ */
+Ipv4EndPointDemux::EndPoints
+Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
+ Ipv4Address saddr, uint16_t sport,
+ Ptr<Ipv4Interface> incomingInterface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ EndPoints retval1; // Matches exact on local port, wildcards on others
+ EndPoints retval2; // Matches exact on local port/adder, wildcards on others
+ EndPoints retval3; // Matches all but local address
+ EndPoints retval4; // Exact match on all 4
+
+ NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
+ NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
+ for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+ {
+ Ipv4EndPoint* endP = *i;
+ NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
+ << " daddr=" << endP->GetLocalAddress ()
+ << " sport=" << endP->GetPeerPort ()
+ << " saddr=" << endP->GetPeerAddress ());
+ if (endP->GetLocalPort () != dport)
+ {
+ NS_LOG_LOGIC ("Skipping endpoint " << &endP
+ << " because endpoint dport "
+ << endP->GetLocalPort ()
+ << " does not match packet dport " << dport);
+ continue;
+ }
+ bool isBroadcast = (daddr.IsBroadcast () ||
+ daddr.IsSubnetDirectedBroadcast (
+ incomingInterface->GetNetworkMask ()));
+ Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress ();
+ NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
+ bool localAddressMatchesWildCard =
+ endP->GetLocalAddress() == Ipv4Address::GetAny();
+ bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
+
+ if (isBroadcast)
+ {
+ NS_LOG_DEBUG("Found bcast, localaddr " << endP->GetLocalAddress());
+ }
+
+ if (isBroadcast && (endP->GetLocalAddress() != Ipv4Address::GetAny()))
+ {
+ localAddressMatchesExact = (endP->GetLocalAddress () ==
+ incomingInterfaceAddr);
+ }
+ // if no match here, keep looking
+ if (!(localAddressMatchesExact || localAddressMatchesWildCard))
+ continue;
+ bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
+ bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0;
+ bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
+ bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
+ Ipv4Address::GetAny();
+ // If remote does not match either with exact or wildcard,
+ // skip this one
+ if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
+ continue;
+ if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
+ continue;
+
+ // Now figure out which return list to add this one to
+ if (localAddressMatchesWildCard &&
+ remotePeerMatchesWildCard &&
+ remoteAddressMatchesWildCard)
+ { // Only local port matches exactly
+ retval1.push_back(endP);
+ }
+ if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&&
+ remotePeerMatchesWildCard &&
+ remoteAddressMatchesWildCard)
+ { // Only local port and local address matches exactly
+ retval2.push_back(endP);
+ }
+ if (localAddressMatchesWildCard &&
+ remotePeerMatchesExact &&
+ remoteAddressMatchesExact)
+ { // All but local address
+ retval3.push_back(endP);
+ }
+ if (localAddressMatchesExact &&
+ remotePeerMatchesExact &&
+ remoteAddressMatchesExact)
+ { // All 4 match
+ retval4.push_back(endP);
+ }
+ }
+
+ // Here we find the most exact match
+ if (!retval4.empty()) return retval4;
+ if (!retval3.empty()) return retval3;
+ if (!retval2.empty()) return retval2;
+ return retval1; // might be empty if no matches
+}
+
+uint16_t
+Ipv4EndPointDemux::AllocateEphemeralPort (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ uint16_t port = m_ephemeral;
+ do
+ {
+ port++;
+ if (port == 65535)
+ {
+ port = 49152;
+ }
+ if (!LookupPortLocal (port))
+ {
+ return port;
+ }
+ } while (port != m_ephemeral);
+ return 0;
+}
+
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-end-point-demux.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef IPV4_END_POINT_DEMUX_H
+#define IPV4_END_POINT_DEMUX_H
+
+#include <stdint.h>
+#include <list>
+#include "ns3/ipv4-address.h"
+#include "ipv4-interface.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+
+class Ipv4EndPointDemux {
+public:
+ typedef std::list<Ipv4EndPoint *> EndPoints;
+ typedef std::list<Ipv4EndPoint *>::iterator EndPointsI;
+
+ Ipv4EndPointDemux ();
+ ~Ipv4EndPointDemux ();
+
+ bool LookupPortLocal (uint16_t port);
+ bool LookupLocal (Ipv4Address addr, uint16_t port);
+ EndPoints Lookup (Ipv4Address daddr,
+ uint16_t dport,
+ Ipv4Address saddr,
+ uint16_t sport,
+ Ptr<Ipv4Interface> incomingInterface);
+
+ Ipv4EndPoint *Allocate (void);
+ Ipv4EndPoint *Allocate (Ipv4Address address);
+ Ipv4EndPoint *Allocate (uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address localAddress,
+ uint16_t localPort,
+ Ipv4Address peerAddress,
+ uint16_t peerPort);
+
+ void DeAllocate (Ipv4EndPoint *endPoint);
+
+ private:
+ uint16_t AllocateEphemeralPort (void);
+
+ uint16_t m_ephemeral;
+ EndPoints m_endPoints;
+};
+
+} // namespace ns3
+
+#endif /* IPV4_END_POINTS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-end-point.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv4-end-point.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port)
+ : m_localAddr (address),
+ m_localPort (port),
+ m_peerAddr (Ipv4Address::GetAny ()),
+ m_peerPort (0)
+{}
+Ipv4EndPoint::~Ipv4EndPoint ()
+{
+ if (!m_destroyCallback.IsNull ())
+ {
+ m_destroyCallback ();
+ }
+}
+
+Ipv4Address
+Ipv4EndPoint::GetLocalAddress (void)
+{
+ return m_localAddr;
+}
+
+void
+Ipv4EndPoint::SetLocalAddress (Ipv4Address address)
+{
+ m_localAddr = address;
+}
+
+uint16_t
+Ipv4EndPoint::GetLocalPort (void)
+{
+ return m_localPort;
+}
+Ipv4Address
+Ipv4EndPoint::GetPeerAddress (void)
+{
+ return m_peerAddr;
+}
+uint16_t
+Ipv4EndPoint::GetPeerPort (void)
+{
+ return m_peerPort;
+}
+void
+Ipv4EndPoint::SetPeer (Ipv4Address address, uint16_t port)
+{
+ m_peerAddr = address;
+ m_peerPort = port;
+}
+
+void
+Ipv4EndPoint::SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> callback)
+{
+ m_rxCallback = callback;
+}
+
+void
+Ipv4EndPoint::SetDestroyCallback (Callback<void> callback)
+{
+ m_destroyCallback = callback;
+}
+
+void
+Ipv4EndPoint::ForwardUp (Ptr<Packet> p, Ipv4Address saddr, uint16_t sport)
+{
+ if (!m_rxCallback.IsNull ())
+ {
+ m_rxCallback (p, saddr, sport);
+ }
+}
+
+
+
+}; // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-end-point.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef IPV4_END_POINT_H
+#define IPV4_END_POINT_H
+
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/callback.h"
+
+namespace ns3 {
+
+class Header;
+class Packet;
+
+class Ipv4EndPoint {
+public:
+ Ipv4EndPoint (Ipv4Address address, uint16_t port);
+ ~Ipv4EndPoint ();
+
+ Ipv4Address GetLocalAddress (void);
+ void SetLocalAddress (Ipv4Address address);
+ uint16_t GetLocalPort (void);
+ Ipv4Address GetPeerAddress (void);
+ uint16_t GetPeerPort (void);
+
+ void SetPeer (Ipv4Address address, uint16_t port);
+
+ void SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> callback);
+ void SetDestroyCallback (Callback<void> callback);
+
+ void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, uint16_t sport);
+
+private:
+ Ipv4Address m_localAddr;
+ uint16_t m_localPort;
+ Ipv4Address m_peerAddr;
+ uint16_t m_peerPort;
+ Callback<void,Ptr<Packet>, Ipv4Address, uint16_t> m_rxCallback;
+ Callback<void> m_destroyCallback;
+};
+
+}; // namespace ns3
+
+
+#endif /* IPV4_END_POINT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-impl.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,273 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ipv4-impl.h"
+#include "ipv4-l3-protocol.h"
+#include "ipv4-interface.h"
+#include "ns3/assert.h"
+#include "ns3/net-device.h"
+
+namespace ns3 {
+
+Ipv4Impl::Ipv4Impl ()
+ : m_ipv4 (0)
+{}
+Ipv4Impl::~Ipv4Impl ()
+{
+ NS_ASSERT (m_ipv4 == 0);
+}
+void
+Ipv4Impl::SetIpv4 (Ptr<Ipv4L3Protocol> ipv4)
+{
+ m_ipv4 = ipv4;
+}
+void
+Ipv4Impl::DoDispose (void)
+{
+ m_ipv4 = 0;
+}
+
+void
+Ipv4Impl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+ int16_t priority)
+{
+ m_ipv4->AddRoutingProtocol (routingProtocol, priority);
+}
+
+void
+Ipv4Impl::AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ m_ipv4->AddHostRouteTo (dest, nextHop, interface);
+}
+void
+Ipv4Impl::AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface)
+{
+ m_ipv4->AddHostRouteTo (dest, interface);
+}
+void
+Ipv4Impl::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ m_ipv4->AddNetworkRouteTo (network, networkMask, nextHop, interface);
+}
+void
+Ipv4Impl::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface)
+{
+ m_ipv4->AddNetworkRouteTo (network, networkMask, interface);
+}
+void
+Ipv4Impl::SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface)
+{
+ m_ipv4->SetDefaultRoute (nextHop, interface);
+}
+uint32_t
+Ipv4Impl::GetNRoutes (void)
+{
+ return m_ipv4->GetNRoutes ();
+}
+Ipv4Route
+Ipv4Impl::GetRoute (uint32_t i)
+{
+ return *m_ipv4->GetRoute (i);
+}
+void
+Ipv4Impl::RemoveRoute (uint32_t i)
+{
+ return m_ipv4->RemoveRoute (i);
+}
+
+void
+Ipv4Impl::AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces)
+{
+ m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces);
+}
+
+void
+Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface)
+{
+ m_ipv4->SetDefaultMulticastRoute (outputInterface);
+}
+
+uint32_t
+Ipv4Impl::GetNMulticastRoutes (void) const
+{
+ return m_ipv4->GetNMulticastRoutes ();
+}
+
+Ipv4MulticastRoute
+Ipv4Impl::GetMulticastRoute (uint32_t i) const
+{
+ return *m_ipv4->GetMulticastRoute (i);
+}
+
+void
+Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface)
+{
+ m_ipv4->RemoveMulticastRoute (origin, group, inputInterface);
+}
+
+void
+Ipv4Impl::RemoveMulticastRoute (uint32_t i)
+{
+ return m_ipv4->RemoveMulticastRoute (i);
+}
+
+uint32_t
+Ipv4Impl::AddInterface (Ptr<NetDevice> device)
+{
+ return m_ipv4->AddInterface (device);
+}
+
+uint32_t
+Ipv4Impl::GetNInterfaces (void)
+{
+ return m_ipv4->GetNInterfaces ();
+}
+
+uint32_t
+Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const
+{
+ return m_ipv4->FindInterfaceForAddr (addr);
+}
+
+uint32_t
+Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
+{
+ return m_ipv4->FindInterfaceForAddr (addr, mask);
+}
+
+int32_t
+Ipv4Impl::FindInterfaceForDevice (Ptr<NetDevice> device) const
+{
+ return m_ipv4->FindInterfaceIndexForDevice (device);
+}
+
+Ptr<NetDevice>
+Ipv4Impl::GetNetDevice (uint32_t i)
+{
+ return m_ipv4->GetInterface (i)-> GetDevice ();
+}
+
+void
+Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ m_ipv4->JoinMulticastGroup(origin, group);
+}
+
+void
+Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ m_ipv4->LeaveMulticastGroup(origin, group);
+}
+
+void
+Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address)
+{
+ m_ipv4->SetAddress (i, address);
+}
+void
+Ipv4Impl::SetNetworkMask (uint32_t i, Ipv4Mask mask)
+{
+ m_ipv4->SetNetworkMask (i, mask);
+}
+Ipv4Mask
+Ipv4Impl::GetNetworkMask (uint32_t i) const
+{
+ return m_ipv4->GetNetworkMask (i);
+}
+
+Ipv4Address
+Ipv4Impl::GetAddress (uint32_t i) const
+{
+ return m_ipv4->GetAddress (i);
+}
+
+void
+Ipv4Impl::SetMetric (uint32_t i, uint16_t metric)
+{
+ m_ipv4->SetMetric (i, metric);
+}
+
+uint16_t
+Ipv4Impl::GetMetric (uint32_t i) const
+{
+ return m_ipv4->GetMetric (i);
+}
+
+bool
+Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const
+{
+ return m_ipv4->GetIfIndexForDestination (dest, ifIndex);
+}
+
+Ipv4Address
+Ipv4Impl::GetSourceAddress (Ipv4Address destination) const
+{
+ uint32_t ifIndex = 0xffffffff;
+
+ bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex);
+
+ if (result)
+ {
+ return m_ipv4->GetAddress (ifIndex);
+ }
+ else
+ {
+//
+// If we can't find any address, just leave it 0.0.0.0
+//
+ return Ipv4Address::GetAny ();
+ }
+}
+
+uint16_t
+Ipv4Impl::GetMtu (uint32_t i) const
+{
+ return m_ipv4->GetMtu (i);
+}
+bool
+Ipv4Impl::IsUp (uint32_t i) const
+{
+ return m_ipv4->IsUp (i);
+}
+void
+Ipv4Impl::SetUp (uint32_t i)
+{
+ m_ipv4->SetUp (i);
+}
+void
+Ipv4Impl::SetDown (uint32_t i)
+{
+ m_ipv4->SetDown (i);
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-impl.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,112 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV4_IMPL_H
+#define IPV4_IMPL_H
+
+#include "ns3/ipv4.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Ipv4L3Protocol;
+
+class Ipv4Impl : public Ipv4
+{
+public:
+ Ipv4Impl ();
+
+ virtual ~Ipv4Impl ();
+
+ void SetIpv4 (Ptr<Ipv4L3Protocol> ipv4);
+
+ virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+ int16_t priority);
+
+ virtual void AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface);
+ virtual void AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface);
+ virtual void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface);
+ virtual void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface);
+ virtual void SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface);
+ virtual uint32_t GetNRoutes (void);
+ virtual Ipv4Route GetRoute (uint32_t i);
+ virtual void RemoveRoute (uint32_t i);
+
+
+ virtual void AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces);
+
+ virtual void SetDefaultMulticastRoute (uint32_t outputInterface);
+
+ virtual uint32_t GetNMulticastRoutes (void) const;
+ virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const;
+
+ virtual void RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface);
+ virtual void RemoveMulticastRoute (uint32_t i);
+
+ virtual uint32_t AddInterface (Ptr<NetDevice> device);
+ virtual uint32_t GetNInterfaces (void);
+
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
+ Ipv4Mask mask) const;
+
+ virtual int32_t FindInterfaceForDevice (Ptr<NetDevice> device) const;
+
+ virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
+
+ virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
+ virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
+
+ virtual void SetAddress (uint32_t i, Ipv4Address address);
+ virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
+ virtual Ipv4Mask GetNetworkMask (uint32_t t) const;
+ virtual Ipv4Address GetAddress (uint32_t i) const;
+ virtual void SetMetric (uint32_t i, uint16_t metric);
+ virtual uint16_t GetMetric (uint32_t i) const;
+ virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const;
+ virtual bool GetIfIndexForDestination (Ipv4Address dest,
+ uint32_t &ifIndex) const;
+
+ virtual uint16_t GetMtu (uint32_t i) const;
+ virtual bool IsUp (uint32_t i) const;
+ virtual void SetUp (uint32_t i);
+ virtual void SetDown (uint32_t i);
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<Ipv4L3Protocol> m_ipv4;
+};
+
+} // namespace ns3
+
+#endif /* IPV4_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-interface.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,174 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv4-interface.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/net-device.h"
+#include "ns3/log.h"
+#include "ns3/packet.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4Interface");
+
+namespace ns3 {
+
+TypeId
+Ipv4Interface::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4Interface")
+ .SetParent<Object> ()
+ ;
+ return tid;
+}
+
+ /**
+ * By default, Ipv4 interface are created in the "down" state
+ * with ip address 192.168.0.1 and a matching mask. Before
+ * becoming useable, the user must invoke SetUp on them
+ * once the final Ipv4 address and mask has been set.
+ */
+Ipv4Interface::Ipv4Interface ()
+ : m_ifup(false),
+ m_metric(1)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+Ipv4Interface::~Ipv4Interface ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Ipv4Interface::DoDispose (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Object::DoDispose ();
+}
+
+void
+Ipv4Interface::SetAddress (Ipv4Address a)
+{
+ NS_LOG_FUNCTION (this << a);
+ m_address = a;
+}
+
+void
+Ipv4Interface::SetNetworkMask (Ipv4Mask mask)
+{
+ NS_LOG_FUNCTION (this << mask);
+ m_netmask = mask;
+}
+
+Ipv4Address
+Ipv4Interface::GetBroadcast (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ uint32_t mask = m_netmask.Get ();
+ uint32_t address = m_address.Get ();
+ Ipv4Address broadcast = Ipv4Address (address | (~mask));
+ return broadcast;
+}
+
+Ipv4Mask
+Ipv4Interface::GetNetworkMask (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_netmask;
+}
+
+void
+Ipv4Interface::SetMetric (uint16_t metric)
+{
+ NS_LOG_FUNCTION (metric);
+ m_metric = metric;
+}
+
+uint16_t
+Ipv4Interface::GetMetric (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_metric;
+}
+
+Ipv4Address
+Ipv4Interface::GetAddress (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_address;
+}
+
+uint16_t
+Ipv4Interface::GetMtu (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (GetDevice () == 0)
+ {
+ uint32_t mtu = (1<<16) - 1;
+ return mtu;
+ }
+ return GetDevice ()->GetMtu ();
+}
+
+/**
+ * These are IP interface states and may be distinct from
+ * NetDevice states, such as found in real implementations
+ * (where the device may be down but IP interface state is still up).
+ */
+bool
+Ipv4Interface::IsUp (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifup;
+}
+
+bool
+Ipv4Interface::IsDown (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return !m_ifup;
+}
+
+void
+Ipv4Interface::SetUp (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_ifup = true;
+}
+
+void
+Ipv4Interface::SetDown (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_ifup = false;
+}
+
+// public wrapper on private virtual function
+void
+Ipv4Interface::Send(Ptr<Packet> p, Ipv4Address dest)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (IsUp()) {
+ NS_LOG_LOGIC ("SendTo");
+ SendTo(p, dest);
+ }
+}
+
+}; // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-interface.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 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:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ * Tom Henderson <tomh@tomh.org>
+ */
+#ifndef IPV4_INTERFACE_H
+#define IPV4_INTERFACE_H
+
+#include <list>
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+class NetDevice;
+class Packet;
+
+/**
+ * \brief The IPv4 representation of a network interface
+ *
+ * This class roughly corresponds to the struct in_device
+ * of Linux; the main purpose is to provide address-family
+ * specific information (addresses) about an interface.
+ *
+ * This class defines two APIs:
+ * - the public API which is expected to be used by both
+ * the IPv4 layer and the user during forwarding and
+ * configuration.
+ * - the private API which is expected to be implemented
+ * by subclasses of this base class. One such subclass
+ * will be a Loopback interface which loops every
+ * packet sent back to the ipv4 layer. Another such
+ * subclass typically contains the Ipv4 <-> MAC address
+ * translation logic which will use most of the time the
+ * ARP/RARP protocols.
+ *
+ * By default, Ipv4 interface are created in the "down" state
+ * with ip address 192.168.0.1 and a matching mask. Before
+ * becoming useable, the user must invoke SetUp on them
+ * once the final Ipv4 address and mask has been set.
+ *
+ * Subclasses must implement the two methods:
+ * - Ipv4Interface::SendTo
+ */
+class Ipv4Interface : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+
+ Ipv4Interface ();
+ virtual ~Ipv4Interface();
+
+ /**
+ * \returns the underlying NetDevice. This method can return
+ * zero if this interface has no associated NetDevice.
+ */
+ virtual Ptr<NetDevice> GetDevice (void) const = 0;
+
+ /**
+ * \param a set the ipv4 address of this interface.
+ */
+ void SetAddress (Ipv4Address a);
+ /**
+ * \param mask set the ipv4 netmask of this interface.
+ */
+ void SetNetworkMask (Ipv4Mask mask);
+
+ /**
+ * \returns the broadcast ipv4 address associated to this interface
+ */
+ Ipv4Address GetBroadcast (void) const;
+ /**
+ * \returns the ipv4 netmask of this interface
+ */
+ Ipv4Mask GetNetworkMask (void) const;
+ /**
+ * \param metric configured routing metric (cost) of this interface
+ */
+ void SetMetric (uint16_t metric);
+ /**
+ * \returns configured routing metric (cost) of this interface
+ */
+ uint16_t GetMetric (void) const;
+ /**
+ * \returns the ipv4 address of this interface
+ */
+ Ipv4Address GetAddress (void) const;
+
+ /**
+ * This function a pass-through to NetDevice GetMtu, modulo
+ * the LLC/SNAP header i.e., ipv4MTU = NetDeviceMtu - LLCSNAPSIZE
+ * \returns the Maximum Transmission Unit associated to this interface.
+ */
+ uint16_t GetMtu (void) const;
+
+ /**
+ * These are IP interface states and may be distinct from
+ * NetDevice states, such as found in real implementations
+ * (where the device may be down but IP interface state is still up).
+ */
+ /**
+ * \returns true if this interface is enabled, false otherwise.
+ */
+ bool IsUp (void) const;
+ /**
+ * \returns true if this interface is disabled, false otherwise.
+ */
+ bool IsDown (void) const;
+ /**
+ * Enable this interface
+ */
+ void SetUp (void);
+ /**
+ * Disable this interface
+ */
+ void SetDown (void);
+
+ /**
+ * \param p packet to send
+ * \param dest next hop address of packet.
+ *
+ * This method will eventually call the private
+ * SendTo method which must be implemented by subclasses.
+ */
+ void Send(Ptr<Packet> p, Ipv4Address dest);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ virtual void SendTo (Ptr<Packet> p, Ipv4Address dest) = 0;
+ bool m_ifup;
+ Ipv4Address m_address;
+ Ipv4Mask m_netmask;
+ uint16_t m_metric;
+};
+
+}; // namespace ns3
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l3-protocol.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,906 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/callback.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/node.h"
+#include "ns3/socket.h"
+#include "ns3/net-device.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/object-vector.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/boolean.h"
+#include "arp-l3-protocol.h"
+
+#include "ipv4-l3-protocol.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+#include "ipv4-loopback-interface.h"
+#include "arp-ipv4-interface.h"
+#include "ipv4-l4-demux.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
+
+namespace ns3 {
+
+const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
+
+TypeId
+Ipv4L3Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
+ .SetParent<Object> ()
+ .AddConstructor<Ipv4L3Protocol> ()
+ .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
+ UintegerValue (64),
+ MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
+ MakeUintegerChecker<uint8_t> ())
+ .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets"
+ " and verify the checksum of incoming packets.",
+ BooleanValue (false),
+ MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum),
+ MakeBooleanChecker ())
+ .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
+ MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
+ .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
+ MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
+ .AddTraceSource ("Drop", "Drop ipv4 packet",
+ MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
+ .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
+ ObjectVectorValue (),
+ MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
+ MakeObjectVectorChecker<Ipv4Interface> ())
+ ;
+ return tid;
+}
+
+Ipv4L3Protocol::Ipv4L3Protocol()
+ : m_nInterfaces (0),
+ m_identification (0)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_staticRouting = CreateObject<Ipv4StaticRouting> ();
+ AddRoutingProtocol (m_staticRouting, 0);
+}
+
+Ipv4L3Protocol::~Ipv4L3Protocol ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+Ipv4L3Protocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+ SetupLoopback ();
+}
+
+void
+Ipv4L3Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
+ {
+ Ptr<Ipv4Interface> interface = *i;
+ interface->Dispose ();
+ }
+ m_interfaces.clear ();
+ m_node = 0;
+ m_staticRouting->Dispose ();
+ m_staticRouting = 0;
+ Object::DoDispose ();
+}
+
+void
+Ipv4L3Protocol::SetupLoopback (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
+ interface->SetNode (m_node);
+ interface->SetAddress (Ipv4Address::GetLoopback ());
+ interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
+ uint32_t index = AddIpv4Interface (interface);
+ AddHostRouteTo (Ipv4Address::GetLoopback (), index);
+ interface->SetUp ();
+}
+
+void
+Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_defaultTtl = ttl;
+}
+
+
+void
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << dest << nextHop << interface);
+ m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << dest << interface);
+ m_staticRouting->AddHostRouteTo (dest, interface);
+}
+
+void
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
+ m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << network << networkMask << interface);
+ m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
+}
+
+void
+Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << nextHop << interface);
+ m_staticRouting->SetDefaultRoute (nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::Lookup (
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply)
+{
+ NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
+
+ Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
+}
+
+void
+Ipv4L3Protocol::Lookup (
+ uint32_t ifIndex,
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply)
+{
+ NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
+
+ for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
+ m_routingProtocols.begin ();
+ rprotoIter != m_routingProtocols.end ();
+ rprotoIter++)
+ {
+ NS_LOG_LOGIC ("Requesting route");
+ if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet,
+ routeReply))
+ return;
+ }
+
+ if (ipHeader.GetDestination ().IsMulticast () &&
+ ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
+ {
+ NS_LOG_LOGIC ("Multicast destination with local source");
+//
+// We have a multicast packet originating from the current node and were not
+// able to send it using the usual RequestRoute process. Since the usual
+// process includes trying to use a default multicast route, this means that
+// there was no specific route out of the node found, and there was no default
+// multicast route set.
+//
+// The fallback position is to look for a default unicast route and use that
+// to get the packet off the node if we have one.
+//
+ Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
+
+ if (route)
+ {
+ NS_LOG_LOGIC ("Local source. Using unicast default route for "
+ "multicast packet");
+
+ routeReply (true, *route, packet, ipHeader);
+ return;
+ }
+ }
+//
+// No route found
+//
+ routeReply (false, Ipv4Route (), packet, ipHeader);
+}
+
+void
+Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+ int priority)
+{
+ NS_LOG_FUNCTION (this << &routingProtocol << priority);
+ m_routingProtocols.push_back
+ (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
+ m_routingProtocols.sort ();
+}
+
+uint32_t
+Ipv4L3Protocol::GetNRoutes (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_staticRouting->GetNRoutes ();
+}
+
+Ipv4Route *
+Ipv4L3Protocol::GetRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_staticRouting->GetRoute (index);
+}
+
+void
+Ipv4L3Protocol::RemoveRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION (this << index);
+ m_staticRouting->RemoveRoute (index);
+}
+
+void
+Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces)
+{
+ NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
+
+ m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
+ outputInterfaces);
+}
+
+void
+Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
+{
+ NS_LOG_FUNCTION (this << outputInterface);
+
+ m_staticRouting->SetDefaultMulticastRoute (outputInterface);
+}
+
+uint32_t
+Ipv4L3Protocol::GetNMulticastRoutes (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_staticRouting->GetNMulticastRoutes ();
+}
+
+Ipv4MulticastRoute *
+Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
+{
+ NS_LOG_FUNCTION (this << index);
+ return m_staticRouting->GetMulticastRoute (index);
+}
+
+void
+Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface)
+{
+ NS_LOG_FUNCTION (this << origin << group << inputInterface);
+ m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
+}
+
+void
+Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION (this << index);
+ m_staticRouting->RemoveMulticastRoute (index);
+}
+
+uint32_t
+Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
+{
+ NS_LOG_FUNCTION (this << &device);
+
+ Ptr<Node> node = GetObject<Node> ();
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
+ Ipv4L3Protocol::PROT_NUMBER, device);
+ node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
+ ArpL3Protocol::PROT_NUMBER, device);
+
+ Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
+ interface->SetNode (m_node);
+ interface->SetDevice (device);
+ return AddIpv4Interface (interface);
+}
+
+uint32_t
+Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
+{
+ NS_LOG_FUNCTION (this << interface);
+ uint32_t index = m_nInterfaces;
+ m_interfaces.push_back (interface);
+ m_nInterfaces++;
+ return index;
+}
+
+Ptr<Ipv4Interface>
+Ipv4L3Protocol::GetInterface (uint32_t index) const
+{
+ NS_LOG_FUNCTION (this << index);
+ uint32_t tmp = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+ {
+ if (index == tmp)
+ {
+ return *i;
+ }
+ tmp++;
+ }
+ return 0;
+}
+
+uint32_t
+Ipv4L3Protocol::GetNInterfaces (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_nInterfaces;
+}
+
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
+{
+ NS_LOG_FUNCTION (this << addr);
+
+ uint32_t ifIndex = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, ifIndex++)
+ {
+ if ((*i)->GetAddress () == addr)
+ {
+ return ifIndex;
+ }
+ }
+
+ NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for IP address " << addr);
+ return 0;
+}
+
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
+{
+ NS_LOG_FUNCTION (this << addr << mask);
+
+ uint32_t ifIndex = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, ifIndex++)
+ {
+ if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
+ {
+ return ifIndex;
+ }
+ }
+
+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for masked IP address");
+ return 0;
+}
+
+int32_t
+Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const
+{
+ NS_LOG_FUNCTION (this << device);
+
+ uint32_t ifIndex = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, ifIndex++)
+ {
+ if ((*i)->GetDevice () == device)
+ {
+ return ifIndex;
+ }
+ }
+
+ return -1;
+}
+
+Ptr<Ipv4Interface>
+Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
+{
+ NS_LOG_FUNCTION (this << &device);
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+ {
+ if ((*i)->GetDevice () == device)
+ {
+ return *i;
+ }
+ }
+ return 0;
+}
+
+void
+Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
+{
+ NS_LOG_FUNCTION (this << &device << packet << protocol << from);
+
+ NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
+
+ uint32_t index = 0;
+ Ptr<Ipv4Interface> ipv4Interface;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++)
+ {
+ ipv4Interface = *i;
+ if (ipv4Interface->GetDevice () == device)
+ {
+ m_rxTrace (packet, index);
+ break;
+ }
+ index++;
+ }
+ Ipv4Header ipHeader;
+ if (m_calcChecksum)
+ {
+ ipHeader.EnableChecksum ();
+ }
+ packet->RemoveHeader (ipHeader);
+
+ if (!ipHeader.IsChecksumOk ())
+ {
+ m_dropTrace (packet);
+ return;
+ }
+
+ if (Forwarding (index, packet, ipHeader, device))
+ {
+ return;
+ }
+
+ ForwardUp (packet, ipHeader, ipv4Interface);
+}
+
+
+void
+Ipv4L3Protocol::Send (Ptr<Packet> packet,
+ Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol)
+{
+ NS_LOG_FUNCTION (this << packet << source << destination << protocol);
+
+ Ipv4Header ipHeader;
+
+ if (m_calcChecksum)
+ {
+ ipHeader.EnableChecksum ();
+ }
+
+ ipHeader.SetSource (source);
+ ipHeader.SetDestination (destination);
+ ipHeader.SetProtocol (protocol);
+ ipHeader.SetPayloadSize (packet->GetSize ());
+ ipHeader.SetTtl (m_defaultTtl);
+ ipHeader.SetMayFragment ();
+ ipHeader.SetIdentification (m_identification);
+
+ m_identification ++;
+
+ // Set TTL to 1 if it is a broadcast packet of any type. Otherwise,
+ // possibly override the default TTL if the packet is tagged
+ SocketIpTtlTag tag;
+ bool found = packet->FindFirstMatchingTag (tag);
+
+ if (destination.IsBroadcast ())
+ {
+ ipHeader.SetTtl (1);
+ }
+ else if (found)
+ {
+ ipHeader.SetTtl (tag.GetTtl ());
+ // XXX remove tag here?
+ }
+ else
+ {
+ uint32_t ifaceIndex = 0;
+ for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+ ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+ {
+ Ptr<Ipv4Interface> outInterface = *ifaceIter;
+ if (destination.IsSubnetDirectedBroadcast (
+ outInterface->GetNetworkMask ()))
+ {
+ ipHeader.SetTtl (1);
+ }
+ }
+ }
+ if (destination.IsBroadcast ())
+ {
+ uint32_t ifaceIndex = 0;
+ for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+ ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+ {
+ Ptr<Ipv4Interface> outInterface = *ifaceIter;
+ Ptr<Packet> packetCopy = packet->Copy ();
+
+ NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
+ packetCopy->AddHeader (ipHeader);
+ m_txTrace (packetCopy, ifaceIndex);
+ outInterface->Send (packetCopy, destination);
+ }
+ }
+ else
+ {
+ // XXX Note here that in most ipv4 stacks in the world,
+ // the route calculation for an outgoing packet is not
+ // done in the ip layer. It is done within the application
+ // socket when the first packet is sent to avoid this
+ // costly lookup on a per-packet basis.
+ // That would require us to get the route from the packet,
+ // most likely with a packet tag. The higher layers do not
+ // do this yet for us.
+ Lookup (ipHeader, packet,
+ MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+ }
+}
+
+void
+Ipv4L3Protocol::SendRealOut (bool found,
+ Ipv4Route const &route,
+ Ptr<Packet> packet,
+ Ipv4Header const &ipHeader)
+{
+ NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
+
+ packet->AddHeader (ipHeader);
+ if (!found)
+ {
+ NS_LOG_WARN ("No route to host. Drop.");
+ m_dropTrace (packet);
+ return;
+ }
+
+ NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
+
+ Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
+ NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
+ m_txTrace (packet, route.GetInterface ());
+ if (route.IsGateway ())
+ {
+ NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
+ outInterface->Send (packet, route.GetGateway ());
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
+ outInterface->Send (packet, ipHeader.GetDestination ());
+ }
+}
+
+bool
+Ipv4L3Protocol::Forwarding (
+ uint32_t ifIndex,
+ Ptr<Packet> packet,
+ Ipv4Header &ipHeader,
+ Ptr<NetDevice> device)
+{
+ NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device);
+ NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
+
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end (); i++)
+ {
+ if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ()))
+ {
+ NS_LOG_LOGIC ("For me (destination match)");
+ return false;
+ }
+ }
+
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end (); i++)
+ {
+ Ptr<Ipv4Interface> interface = *i;
+ if (interface->GetDevice () == device)
+ {
+ if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ()))
+ {
+ NS_LOG_LOGIC ("For me (interface broadcast address)");
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (ipHeader.GetDestination ().IsBroadcast ())
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
+ return false;
+ }
+
+ if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ()))
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
+ return false;
+ }
+
+ if (ipHeader.GetTtl () == 1)
+ {
+ // Should send ttl expired here
+ // XXX
+ NS_LOG_LOGIC ("Not for me (TTL expired). Drop");
+ m_dropTrace (packet);
+ return true;
+ }
+ ipHeader.SetTtl (ipHeader.GetTtl () - 1);
+
+//
+// If this is a to a multicast address and this node is a member of the
+// indicated group we need to return false so the multicast is forwarded up.
+//
+ for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
+ i != m_multicastGroups.end (); i++)
+ {
+ if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
+ (*i).second.IsEqual (ipHeader.GetDestination ()))
+ {
+ NS_LOG_LOGIC ("For me (Joined multicast group)");
+ // We forward with a packet copy, since forwarding may change
+ // the packet, affecting our local delivery
+ NS_LOG_LOGIC ("Forwarding (multicast).");
+ Lookup (ifIndex, ipHeader, packet->Copy (),
+ MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+ return false;
+ }
+ }
+ NS_LOG_LOGIC ("Not for me, forwarding.");
+ Lookup (ifIndex, ipHeader, packet,
+ MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+
+ return true;
+}
+
+void
+Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
+ Ptr<Ipv4Interface> incomingInterface)
+{
+ NS_LOG_FUNCTION (this << p << &ip);
+
+ Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> ();
+ Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ());
+ protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
+}
+
+void
+Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ NS_LOG_FUNCTION (this << origin << group);
+ m_multicastGroups.push_back(
+ std::pair<Ipv4Address, Ipv4Address> (origin, group));
+}
+
+void
+Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ NS_LOG_FUNCTION (this << origin << group);
+
+ for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
+ i != m_multicastGroups.end ();
+ i++)
+ {
+ if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
+ {
+ m_multicastGroups.erase (i);
+ return;
+ }
+ }
+}
+
+void
+Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
+{
+ NS_LOG_FUNCTION (this << i << address);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetAddress (address);
+}
+
+void
+Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
+{
+ NS_LOG_FUNCTION (this << i << mask);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetNetworkMask (mask);
+}
+
+Ipv4Mask
+Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetNetworkMask ();
+}
+
+Ipv4Address
+Ipv4L3Protocol::GetAddress (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetAddress ();
+}
+
+void
+Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
+{
+ NS_LOG_FUNCTION (i << metric);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetMetric (metric);
+}
+
+uint16_t
+Ipv4L3Protocol::GetMetric (uint32_t i) const
+{
+ NS_LOG_FUNCTION (i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetMetric ();
+}
+
+bool
+Ipv4L3Protocol::GetIfIndexForDestination (
+ Ipv4Address destination, uint32_t& ifIndex) const
+{
+ NS_LOG_FUNCTION (this << destination << &ifIndex);
+//
+// The first thing we do in trying to determine a source address is to
+// consult the routing protocols. These will also check for a default route
+// if one has been set.
+//
+ for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
+ i != m_routingProtocols.end ();
+ i++)
+ {
+ NS_LOG_LOGIC ("Requesting Source Address");
+ uint32_t ifIndexTmp;
+
+ if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
+ {
+ NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp);
+ ifIndex = ifIndexTmp;
+ return true;
+ }
+ }
+//
+// If there's no routing table entry telling us what *single* interface will
+// be used to send a packet to this destination, we'll have to just pick one.
+// If there's only one interface on this node, a good answer isn't very hard
+// to come up with. Before jumping to any conclusions, remember that the
+// zeroth interface is the loopback interface, so what we actually want is
+// a situation where there are exactly two interfaces on the node, in which
+// case interface one is the "single" interface connected to the outside world.
+//
+ if (GetNInterfaces () == 2)
+ {
+ NS_LOG_LOGIC ("One Interface. Using interface 1.");
+ ifIndex = 1;
+ return true;
+ }
+//
+// If we fall through to here, we have a node with multiple interfaces and
+// no routes to guide us in determining what interface to choose. Either
+// no default route was found (for unicast or multicast), or in the case of a
+// multicast, the default route contained multiple outbound interfaces.
+//
+// The fallback position is to just get the unicast default route and use
+// the outgoing interface specified there. We don't want to leave the source
+// address unset, so we just assert here.
+//
+// N.B. that in the case of a multicast with a route containing multiple
+// outgoing interfaces, the source address of packets from that node will be
+// set to the IP address of the interface set in the default unicast route.
+// Also, in the case of a broadcast, the same will be true.
+//
+ NS_LOG_LOGIC ("Using default unicast route");
+ Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
+
+ if (route == NULL)
+ {
+ NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): "
+ "Unable to determine outbound interface. No default route set");
+ return false;
+ }
+
+ ifIndex = route->GetInterface ();
+
+ NS_LOG_LOGIC ("Default route specifies interface " << ifIndex);
+ return true;
+}
+
+uint16_t
+Ipv4L3Protocol::GetMtu (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetMtu ();
+}
+
+bool
+Ipv4L3Protocol::IsUp (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->IsUp ();
+}
+
+void
+Ipv4L3Protocol::SetUp (uint32_t i)
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetUp ();
+
+ // If interface address and network mask have been set, add a route
+ // to the network of the interface (like e.g. ifconfig does on a
+ // Linux box)
+ if ((interface->GetAddress ()) != (Ipv4Address ())
+ && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
+ {
+ AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
+ interface->GetNetworkMask (), i);
+ }
+}
+
+void
+Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
+{
+ NS_LOG_FUNCTION (this << ifaceIndex);
+ Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
+ interface->SetDown ();
+
+ // Remove all routes that are going through this interface
+ bool modified = true;
+ while (modified)
+ {
+ modified = false;
+ for (uint32_t i = 0; i < GetNRoutes (); i++)
+ {
+ Ipv4Route *route = GetRoute (i);
+ if (route->GetInterface () == ifaceIndex)
+ {
+ RemoveRoute (i);
+ modified = true;
+ break;
+ }
+ }
+ }
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l3-protocol.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,209 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+#ifndef IPV4_L3_PROTOCOL_H
+#define IPV4_L3_PROTOCOL_H
+
+#include <list>
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4.h"
+#include "ns3/traced-callback.h"
+#include "ns3/ipv4-header.h"
+#include "ipv4-static-routing.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4Route;
+class Node;
+
+
+/**
+ * \brief Implement the Ipv4 layer.
+ */
+class Ipv4L3Protocol : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ static const uint16_t PROT_NUMBER;
+
+ Ipv4L3Protocol();
+ virtual ~Ipv4L3Protocol ();
+
+ void SetNode (Ptr<Node> node);
+
+ /**
+ * \param ttl default ttl to use
+ *
+ * When we need to send an ipv4 packet, we use this default
+ * ttl value.
+ */
+ void SetDefaultTtl (uint8_t ttl);
+
+ /**
+ * \param device the device to match
+ * \returns the matching interface, zero if not found.
+ *
+ * Try to find an Ipv4Interface whose NetDevice is equal to
+ * the input NetDevice.
+ */
+ Ptr<Ipv4Interface> FindInterfaceForDevice (Ptr<const NetDevice> device);
+
+ /**
+ * Lower layer calls this method after calling L3Demux::Lookup
+ * The ARP subclass needs to know from which NetDevice this
+ * packet is coming to:
+ * - implement a per-NetDevice ARP cache
+ * - send back arp replies on the right device
+ */
+ void Receive( Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from);
+
+ /**
+ * \param packet packet to send
+ * \param source source address of packet
+ * \param destination address of packet
+ * \param protocol number of packet
+ *
+ * Higher-level layers call this method to send a packet
+ * down the stack to the MAC and PHY layers.
+ */
+ void Send (Ptr<Packet> packet, Ipv4Address source,
+ Ipv4Address destination, uint8_t protocol);
+
+
+
+ void AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface);
+ void AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface);
+
+ void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface);
+ void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface);
+ void SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface);
+
+ void Lookup (Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply);
+
+ uint32_t GetNRoutes (void);
+ Ipv4Route *GetRoute (uint32_t i);
+ void RemoveRoute (uint32_t i);
+
+ void AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces);
+
+ void SetDefaultMulticastRoute (uint32_t onputInterface);
+
+ uint32_t GetNMulticastRoutes (void) const;
+ Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
+
+ void RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface);
+ void RemoveMulticastRoute (uint32_t i);
+
+ uint32_t AddInterface (Ptr<NetDevice> device);
+ Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
+ uint32_t GetNInterfaces (void) const;
+
+ uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
+ uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
+ int32_t FindInterfaceIndexForDevice (Ptr<NetDevice> device) const;
+
+ void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
+ void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
+
+ void SetAddress (uint32_t i, Ipv4Address address);
+ void SetNetworkMask (uint32_t i, Ipv4Mask mask);
+ Ipv4Mask GetNetworkMask (uint32_t t) const;
+ Ipv4Address GetAddress (uint32_t i) const;
+ void SetMetric (uint32_t i, uint16_t metric);
+ uint16_t GetMetric (uint32_t i) const;
+ bool GetIfIndexForDestination (Ipv4Address destination,
+ uint32_t& ifIndex) const;
+ uint16_t GetMtu (uint32_t i) const;
+ bool IsUp (uint32_t i) const;
+ void SetUp (uint32_t i);
+ void SetDown (uint32_t i);
+
+ void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+ int priority);
+
+protected:
+
+ virtual void DoDispose (void);
+
+private:
+ void Lookup (uint32_t ifIndex,
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply);
+
+ void SendRealOut (bool found,
+ Ipv4Route const &route,
+ Ptr<Packet> packet,
+ Ipv4Header const &ipHeader);
+ bool Forwarding (uint32_t ifIndex,
+ Ptr<Packet> packet,
+ Ipv4Header &ipHeader,
+ Ptr<NetDevice> device);
+ void ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, Ptr<Ipv4Interface> incomingInterface);
+ uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
+ void SetupLoopback (void);
+
+ typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
+ typedef std::list<std::pair<Ipv4Address, Ipv4Address> >
+ Ipv4MulticastGroupList;
+ typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
+
+ Ipv4InterfaceList m_interfaces;
+ uint32_t m_nInterfaces;
+ uint8_t m_defaultTtl;
+ bool m_calcChecksum;
+ uint16_t m_identification;
+ Ptr<Node> m_node;
+ TracedCallback<Ptr<const Packet>, uint32_t> m_txTrace;
+ TracedCallback<Ptr<const Packet>, uint32_t> m_rxTrace;
+ TracedCallback<Ptr<const Packet> > m_dropTrace;
+
+ Ipv4RoutingProtocolList m_routingProtocols;
+
+ Ptr<Ipv4StaticRouting> m_staticRouting;
+ Ipv4MulticastGroupList m_multicastGroups;
+};
+
+} // Namespace ns3
+
+#endif /* IPV4_L3_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l4-demux.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,97 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Define the layer 4 demultiplexer object for ns3.
+// George F. Riley, Georgia Tech, Fall 2006
+
+#include <sstream>
+#include "ns3/node.h"
+#include "ns3/object-vector.h"
+#include "ipv4-l4-demux.h"
+#include "ipv4-l4-protocol.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Demux);
+
+TypeId
+Ipv4L4Demux::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4L4Demux")
+ .SetParent<Object> ()
+ .AddAttribute ("Protocols", "The set of protocols registered with this demux.",
+ ObjectVectorValue (),
+ MakeObjectVectorAccessor (&Ipv4L4Demux::m_protocols),
+ MakeObjectVectorChecker<Ipv4L4Protocol> ())
+ ;
+ return tid;
+}
+
+Ipv4L4Demux::Ipv4L4Demux ()
+{}
+
+Ipv4L4Demux::~Ipv4L4Demux()
+{}
+
+void
+Ipv4L4Demux::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+}
+
+void
+Ipv4L4Demux::DoDispose (void)
+{
+ for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ {
+ (*i)->Dispose ();
+ *i = 0;
+ }
+ m_protocols.clear ();
+ m_node = 0;
+ Object::DoDispose ();
+}
+
+void
+Ipv4L4Demux::Insert(Ptr<Ipv4L4Protocol> protocol)
+{
+ m_protocols.push_back (protocol);
+}
+Ptr<Ipv4L4Protocol>
+Ipv4L4Demux::GetProtocol(int protocolNumber)
+{
+ for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ {
+ if ((*i)->GetProtocolNumber () == protocolNumber)
+ {
+ return *i;
+ }
+ }
+ return 0;
+}
+void
+Ipv4L4Demux::Remove (Ptr<Ipv4L4Protocol> protocol)
+{
+ m_protocols.remove (protocol);
+}
+
+
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l4-demux.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,85 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Define the layer 4 demultiplexer object for ns3.
+// George F. Riley, Georgia Tech, Fall 2006
+
+#ifndef IPV4_L4_DEMUX_H
+#define IPV4_L4_DEMUX_H
+
+#include <list>
+#include "ns3/object.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Ipv4L4Protocol;
+class Node;
+
+/**
+ * \brief L4 Ipv4 Demux
+ */
+class Ipv4L4Demux : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ Ipv4L4Demux ();
+ virtual ~Ipv4L4Demux();
+
+ void SetNode (Ptr<Node> node);
+
+ /**
+ * \param protocol a template for the protocol to add to this L4 Demux.
+ * \returns the L4Protocol effectively added.
+ *
+ * Invoke Copy on the input template to get a copy of the input
+ * protocol which can be used on the Node on which this L4 Demux
+ * is running. The new L4Protocol is registered internally as
+ * a working L4 Protocol and returned from this method.
+ * The caller does not get ownership of the returned pointer.
+ */
+ void Insert(Ptr<Ipv4L4Protocol> protocol);
+ /**
+ * \param protocolNumber number of protocol to lookup
+ * in this L4 Demux
+ * \returns a matching L4 Protocol
+ *
+ * This method is typically called by lower layers
+ * to forward packets up the stack to the right protocol.
+ * It is also called from NodeImpl::GetUdp for example.
+ */
+ Ptr<Ipv4L4Protocol> GetProtocol(int protocolNumber);
+ /**
+ * \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);
+protected:
+ virtual void DoDispose (void);
+private:
+ typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
+ L4List_t m_protocols;
+ Ptr<Node> m_node;
+};
+
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l4-protocol.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,51 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// NS3 - Layer 4 Protocol base class
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include "ipv4-l4-protocol.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol);
+
+TypeId
+Ipv4L4Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4L4Protocol")
+ .SetParent<Object> ()
+ .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.",
+ UintegerValue (0),
+ MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber),
+ MakeUintegerChecker<int> ())
+ .AddAttribute ("Version", "The version of the protocol.",
+ UintegerValue (0),
+ MakeUintegerAccessor (&Ipv4L4Protocol::GetVersion),
+ MakeUintegerChecker<int> ())
+ ;
+ return tid;
+}
+
+Ipv4L4Protocol::~Ipv4L4Protocol ()
+{}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l4-protocol.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,74 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// NS3 - Layer 4 Protocol base class
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef IPV4_L4_PROTOCOL_H
+#define IPV4_L4_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ipv4-interface.h"
+
+namespace ns3 {
+
+class Packet;
+class Ipv4Address;
+
+/**
+ * \brief L4 Protocol base class
+ *
+ * If you want to implement a new L4 protocol, all you have to do is
+ * implement a subclass of this base class and add it to an L4Demux.
+ */
+class Ipv4L4Protocol : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+
+ virtual ~Ipv4L4Protocol ();
+
+ /**
+ * \returns the protocol number of this protocol.
+ */
+ virtual int GetProtocolNumber (void) const = 0;
+ /**
+ * \returns the version number of this protocol.
+ */
+ virtual int GetVersion (void) const = 0;
+
+ /**
+ * \param p packet to forward up
+ * \param source source address of packet received
+ * \param destination address of packet received
+ * \param incomingInterface the Ipv4Interface on which the packet arrived
+ *
+ * Called from lower-level layers to send the packet up
+ * in the stack.
+ */
+ virtual void Receive(Ptr<Packet> p,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface) = 0;
+};
+
+} // Namespace ns3
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-loopback-interface.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+
+#include "ns3/log.h"
+#include "ns3/net-device.h"
+#include "ns3/node.h"
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+#include "ipv4-loopback-interface.h"
+#include "ipv4-l3-protocol.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4LoopbackInterface");
+
+namespace ns3 {
+
+TypeId
+Ipv4LoopbackInterface::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4LoopbackInterface")
+ .SetParent<Ipv4Interface> ()
+ ;
+ return tid;
+}
+
+Ipv4LoopbackInterface::Ipv4LoopbackInterface ()
+ : m_node (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_node != 0);
+}
+
+Ptr<NetDevice>
+Ipv4LoopbackInterface::GetDevice (void) const
+{
+ return 0;
+}
+
+void
+Ipv4LoopbackInterface::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+}
+
+void
+Ipv4LoopbackInterface::SendTo (Ptr<Packet> packet, Ipv4Address dest)
+{
+ NS_LOG_FUNCTION (this << packet << dest);
+
+ Ptr<Ipv4L3Protocol> ipv4 =
+ m_node->GetObject<Ipv4L3Protocol> ();
+
+ ipv4->Receive (0, packet, Ipv4L3Protocol::PROT_NUMBER,
+ Mac48Address ("ff:ff:ff:ff:ff:ff"));
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-loopback-interface.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+#ifndef IPV4_LOOPBACK_INTERFACE_H
+#define IPV4_LOOPBACK_INTERFACE_H
+
+#include "ipv4-interface.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Node;
+/**
+ * \brief An IPv4 loopback interface
+ */
+class Ipv4LoopbackInterface : public Ipv4Interface
+{
+public:
+ static TypeId GetTypeId (void);
+ Ipv4LoopbackInterface ();
+ virtual ~Ipv4LoopbackInterface ();
+
+ virtual Ptr<NetDevice> GetDevice (void) const;
+
+ void SetNode (Ptr<Node> node);
+
+ private:
+ virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
+
+ Ptr<Node> m_node;
+};
+
+}//namespace ns3
+
+
+#endif /* IPV4_LOOPBACK_INTERFACE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-static-routing.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,654 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+// Gustavo Carneiro <gjc@inescporto.pt>
+
+#include "ns3/log.h"
+#include "ipv4-static-routing.h"
+#include "ns3/packet.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRouting");
+
+namespace ns3 {
+
+Ipv4StaticRouting::Ipv4StaticRouting ()
+: m_defaultRoute (0), m_defaultMulticastRoute (0)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Route *route = new Ipv4Route ();
+ *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
+ m_hostRoutes.push_back (route);
+}
+
+void
+Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Route *route = new Ipv4Route ();
+ *route = Ipv4Route::CreateHostRouteTo (dest, interface);
+ m_hostRoutes.push_back (route);
+}
+
+void
+Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Route *route = new Ipv4Route ();
+ *route = Ipv4Route::CreateNetworkRouteTo (network,
+ networkMask,
+ nextHop,
+ interface);
+ m_networkRoutes.push_back (route);
+}
+
+void
+Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Route *route = new Ipv4Route ();
+ *route = Ipv4Route::CreateNetworkRouteTo (network,
+ networkMask,
+ interface);
+ m_networkRoutes.push_back (route);
+}
+
+void
+Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Route *route = new Ipv4Route ();
+ *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
+ delete m_defaultRoute;
+ m_defaultRoute = route;
+}
+
+void
+Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
+ *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
+ inputInterface, outputInterfaces);
+ m_multicastRoutes.push_back (route);
+}
+
+void
+Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Address origin = Ipv4Address::GetAny ();
+ Ipv4Address group = Ipv4Address::GetAny ();
+ uint32_t inputInterface = Ipv4RoutingProtocol::IF_INDEX_ANY;
+
+ std::vector<uint32_t> outputInterfaces (1);
+ outputInterfaces[0] = outputInterface;
+
+ Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
+ *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group,
+ inputInterface, outputInterfaces);
+
+ delete m_defaultMulticastRoute;
+ m_defaultMulticastRoute = route;
+}
+
+uint32_t
+Ipv4StaticRouting::GetNMulticastRoutes (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0;
+}
+
+Ipv4MulticastRoute *
+Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_ASSERT_MSG(index < m_multicastRoutes.size (),
+ "Ipv4StaticRouting::GetMulticastRoute (): Index out of range");
+//
+// From an external point of view the default route appears to be in slot 0
+// of the routing table. The implementation, however, puts it in a separate
+// place. So, if a client asks for index 0 and we have a default multicast
+// route, we have to return it from that different place
+// (m_defaultMulticastRoute).
+//
+ if (index == 0 && m_defaultMulticastRoute != 0)
+ {
+ return m_defaultMulticastRoute;
+ }
+//
+// If there is a default multicast route present, a client will just assume
+// that it is in slot zero and there is one "extra" zeroth route in the table.
+// To return the correct indexed entry in our list, we have to decrement the
+// index to take into account the default route not being in the actual list.
+// Since we fell through to here, we've taken care of the case where the
+// index was zero.
+//
+ if (m_defaultMulticastRoute != 0)
+ {
+ NS_ASSERT(index > 0);
+ index--;
+ }
+
+ if (index < m_multicastRoutes.size ())
+ {
+ uint32_t tmp = 0;
+ for (MulticastRoutesCI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ if (tmp == index)
+ {
+ return *i;
+ }
+ tmp++;
+ }
+ }
+ return 0;
+}
+
+Ipv4MulticastRoute *
+Ipv4StaticRouting::GetDefaultMulticastRoute () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_defaultMulticastRoute != 0)
+ {
+ return m_defaultMulticastRoute;
+ }
+ return 0;
+}
+
+bool
+Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ Ipv4MulticastRoute *route = *i;
+ if (origin == route->GetOrigin () &&
+ group == route->GetGroup () &&
+ inputInterface == route->GetInputInterface ())
+ {
+ delete *i;
+ m_multicastRoutes.erase (i);
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+//
+// From an external point of view the default route appears to be in slot 0
+// of the routing table. The implementation, however, puts it in a separate
+// place. So, if a client asks to delete index 0 and we have a default
+// multicast route set, we have to delete it from that different place
+// (m_defaultMulticastRoute).
+//
+ if (index == 0 && m_defaultMulticastRoute != 0)
+ {
+ delete m_defaultMulticastRoute;
+ m_defaultMulticastRoute = 0;
+ }
+//
+// If there is a default multicast route present, a client will just assume
+// that it is in slot zero and there is one "extra" zeroth route in the table.
+// To return the correct indexed entry in our list, we have to decrement the
+// index to take into account the default route not being in the actual list.
+// Since we fell through to here, we've taken care of the case where the
+// index was zero.
+//
+ if (m_defaultMulticastRoute != 0)
+ {
+ NS_ASSERT(index > 0);
+ index--;
+ }
+
+ uint32_t tmp = 0;
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ if (tmp == index)
+ {
+ delete *i;
+ m_multicastRoutes.erase (i);
+ return;
+ }
+ tmp++;
+ }
+}
+
+Ipv4Route *
+Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (HostRoutesCI i = m_hostRoutes.begin ();
+ i != m_hostRoutes.end ();
+ i++)
+ {
+ NS_ASSERT ((*i)->IsHost ());
+ if ((*i)->GetDest ().IsEqual (dest))
+ {
+ return (*i);
+ }
+ }
+ for (NetworkRoutesI j = m_networkRoutes.begin ();
+ j != m_networkRoutes.end ();
+ j++)
+ {
+ NS_ASSERT ((*j)->IsNetwork ());
+ Ipv4Mask mask = (*j)->GetDestNetworkMask ();
+ Ipv4Address entry = (*j)->GetDestNetwork ();
+ if (mask.IsMatch (dest, entry))
+ {
+ return (*j);
+ }
+ }
+ if (m_defaultRoute != 0)
+ {
+ NS_ASSERT (m_defaultRoute->IsDefault ());
+ return m_defaultRoute;
+ }
+ return 0;
+}
+
+Ipv4MulticastRoute *
+Ipv4StaticRouting::LookupStatic (
+ Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t ifIndex)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+//
+// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching
+// scheme.
+//
+ Ipv4Address wildcard = Ipv4Address::GetAny ();
+
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ Ipv4MulticastRoute *route = *i;
+//
+// We've been passed an origin address, a multicast group address and an
+// interface index. We have to decide if the current route in the list is
+// a match.
+//
+// The first case is the restrictive case where the origin, group and index
+// matches. This picks up exact routes during forwarded and exact routes from
+// the local node (in which case the ifIndex is a wildcard).
+//
+ if (origin == route->GetOrigin () && group == route->GetGroup ())
+ {
+ if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY ||
+ ifIndex == route->GetInputInterface ())
+ {
+ return *i;
+ }
+ }
+ }
+//
+// If the input interface index is not a wildcard (that means that the packet
+// did not originally come from this node), we're done. We don't
+// just happily forward packets we don't really know what to do with.
+// Multicast storms are not generally considered a good thing.
+//
+ if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY)
+ {
+ return 0;
+ }
+//
+// Now, we're going to get a litle less restricive. This only applies in the
+// case where the packet in question is coming from the local node. In order
+// to avoid dependencies on the order in which routes were added, we will
+// actually walk the list two more times, the first time looking for routes
+// with a single wildcard, and the last time looking for the first route
+// with two wildcards.
+//
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ Ipv4MulticastRoute *route = *i;
+//
+// Here we will ignore the origin. We know that a single source address must
+// be picked for a packet, but we may want to send multicast packets out
+// multiple interfaces. To support this case, a user would need to add
+// a Multicast route with the route's origin set to wildcard. N.B As a
+// result, packets sourced from a node with multiple interface may have a
+// source IP address different from that of the interface actually used to
+// send the packet.
+//
+ if (route->GetOrigin () == wildcard && group == route->GetGroup ())
+ {
+ return *i;
+ }
+ }
+//
+// Finally we want to allow users to specify a default route that specifies
+// sending all multicast packets out multiple interfaces. The standard
+// default multicast route is patterned after other systems and limits the
+// number of outputs to one. If, however a client manually adds a multicast
+// route with the origin, the multicast group and the input interface index
+// all set to wildcard, she has created a default route with multiple output
+// interfaces.
+//
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i++)
+ {
+ Ipv4MulticastRoute *route = *i;
+
+ if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard)
+ {
+ return *i;
+ }
+ }
+//
+// We also allow users to specify a typical default multicast route. This
+// default route is limited to specifying a single output interface.
+//
+ if (m_defaultMulticastRoute != 0)
+ {
+ return m_defaultMulticastRoute;
+ }
+
+ return 0;
+}
+
+uint32_t
+Ipv4StaticRouting::GetNRoutes (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ uint32_t n = 0;
+ if (m_defaultRoute != 0)
+ {
+ n++;
+ }
+ n += m_hostRoutes.size ();
+ n += m_networkRoutes.size ();
+ return n;
+}
+
+Ipv4Route *
+Ipv4StaticRouting::GetDefaultRoute ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_defaultRoute != 0)
+ {
+ return m_defaultRoute;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+Ipv4Route *
+Ipv4StaticRouting::GetRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (index == 0 && m_defaultRoute != 0)
+ {
+ return m_defaultRoute;
+ }
+ if (index > 0 && m_defaultRoute != 0)
+ {
+ index--;
+ }
+ if (index < m_hostRoutes.size ())
+ {
+ uint32_t tmp = 0;
+ for (HostRoutesCI i = m_hostRoutes.begin ();
+ i != m_hostRoutes.end ();
+ i++)
+ {
+ if (tmp == index)
+ {
+ return *i;
+ }
+ tmp++;
+ }
+ }
+ index -= m_hostRoutes.size ();
+ uint32_t tmp = 0;
+ for (NetworkRoutesI j = m_networkRoutes.begin ();
+ j != m_networkRoutes.end ();
+ j++)
+ {
+ if (tmp == index)
+ {
+ return *j;
+ }
+ tmp++;
+ }
+ NS_ASSERT (false);
+ // quiet compiler.
+ return 0;
+}
+void
+Ipv4StaticRouting::RemoveRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (index == 0 && m_defaultRoute != 0)
+ {
+ delete m_defaultRoute;
+ m_defaultRoute = 0;
+ }
+ if (index > 0 && m_defaultRoute != 0)
+ {
+ index--;
+ }
+ if (index < m_hostRoutes.size ())
+ {
+ uint32_t tmp = 0;
+ for (HostRoutesI i = m_hostRoutes.begin ();
+ i != m_hostRoutes.end ();
+ i++)
+ {
+ if (tmp == index)
+ {
+ delete *i;
+ m_hostRoutes.erase (i);
+ return;
+ }
+ tmp++;
+ }
+ }
+ index -= m_hostRoutes.size ();
+ uint32_t tmp = 0;
+ for (NetworkRoutesI j = m_networkRoutes.begin ();
+ j != m_networkRoutes.end ();
+ j++)
+ {
+ if (tmp == index)
+ {
+ delete *j;
+ m_networkRoutes.erase (j);
+ return;
+ }
+ tmp++;
+ }
+ NS_ASSERT (false);
+}
+
+bool
+Ipv4StaticRouting::RequestRoute (
+ uint32_t ifIndex,
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ RouteReplyCallback routeReply)
+{
+ NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
+
+ NS_LOG_LOGIC ("source = " << ipHeader.GetSource ());
+
+ NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ());
+
+ if (ipHeader.GetDestination ().IsMulticast ())
+ {
+ NS_LOG_LOGIC ("Multicast destination");
+
+ Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
+ ipHeader.GetDestination (), ifIndex);
+
+ if (mRoute)
+ {
+ NS_LOG_LOGIC ("Multicast route found");
+
+ for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
+ {
+ Ptr<Packet> p = packet->Copy ();
+ Ipv4Header h = ipHeader;
+ Ipv4Route route =
+ Ipv4Route::CreateHostRouteTo(h.GetDestination (),
+ mRoute->GetOutputInterface(i));
+ NS_LOG_LOGIC ( "Send via interface " <<
+ mRoute->GetOutputInterface(i));
+ routeReply (true, route, p, h);
+ }
+ return true;
+ }
+ return false; // Let other routing protocols try to handle this
+ }
+//
+// This is a unicast packet. Check to see if we have a route for it.
+//
+ NS_LOG_LOGIC ("Unicast destination");
+ Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
+ if (route != 0)
+ {
+ routeReply (true, *route, packet, ipHeader);
+ return true;
+ }
+ else
+ {
+ return false; // Let other routing protocols try to handle this
+ // route request.
+ }
+}
+
+bool
+Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex)
+{
+ NS_LOG_FUNCTION (this << destination << &ifIndex);
+//
+// First, see if this is a multicast packet we have a route for. If we
+// have a route, then send the packet down each of the specified interfaces.
+//
+ if (destination.IsMulticast ())
+ {
+ NS_LOG_LOGIC ("Multicast destination");
+
+ Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (),
+ destination, Ipv4RoutingProtocol::IF_INDEX_ANY);
+
+ if (mRoute)
+ {
+ NS_LOG_LOGIC ("Multicast route found");
+
+ if (mRoute->GetNOutputInterfaces () != 1)
+ {
+ NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring.");
+ return false;
+ }
+
+ ifIndex = mRoute->GetOutputInterface(0);
+ NS_LOG_LOGIC ("Found ifIndex " << ifIndex);
+ return true;
+ }
+ return false; // Let other routing protocols try to handle this
+ }
+//
+// See if this is a unicast packet we have a route for.
+//
+ NS_LOG_LOGIC ("Unicast destination");
+ Ipv4Route *route = LookupStatic (destination);
+ if (route)
+ {
+ ifIndex = route->GetInterface ();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void
+Ipv4StaticRouting::DoDispose (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (HostRoutesI i = m_hostRoutes.begin ();
+ i != m_hostRoutes.end ();
+ i = m_hostRoutes.erase (i))
+ {
+ delete (*i);
+ }
+ for (NetworkRoutesI j = m_networkRoutes.begin ();
+ j != m_networkRoutes.end ();
+ j = m_networkRoutes.erase (j))
+ {
+ delete (*j);
+ }
+ if (m_defaultRoute != 0)
+ {
+ delete m_defaultRoute;
+ m_defaultRoute = 0;
+ }
+ for (MulticastRoutesI i = m_multicastRoutes.begin ();
+ i != m_multicastRoutes.end ();
+ i = m_multicastRoutes.erase (i))
+ {
+ delete (*i);
+ }
+ if (m_defaultMulticastRoute != 0)
+ {
+ delete m_defaultMulticastRoute;
+ m_defaultMulticastRoute = 0;
+ }
+ Ipv4RoutingProtocol::DoDispose ();
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-static-routing.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,506 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+// Gustavo Carneiro <gjc@inescporto.pt>
+//
+
+#ifndef IPV4_STATIC_ROUTING_H
+#define IPV4_STATIC_ROUTING_H
+
+#include <list>
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4Route;
+class Node;
+
+
+/**
+ * @brief Static routing protocol for IP version 4 stacks.
+ *
+ * In ns-3 we have the concept of a pluggable routing protocol. Routing
+ * protocols are added to a list maintained by the Ipv4L3Protocol. Every
+ * stack gets one routing protocol for free -- the Ipv4StaticRouting routing
+ * protocol is added in the constructor of the Ipv4L3Protocol (this is the
+ * piece of code that implements the functionality of the IP layer).
+ *
+ * The Ipv4StaticRouting class inherits from the abstract base class
+ * Ipv4RoutingProtocol that defines the interface methods that a routing
+ * protocol must support.
+ *
+ * When a packet arrives in the Ipv4L3Protocol for transmission, it comes
+ * either from a local source via Ipv4L3Protocol::Send or from a remote
+ * source via Ipv4L3Protocol::Forwarding. In both cases, a function is called
+ * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet.
+ *
+ * The lookup function iterates through the list of routing protocols asking
+ * each to see if it can find a route and send the packet. A callback is
+ * provided during each of these calls that should be considered a pre-
+ * packaged send call. This is done to allow asynchronous calls into
+ * routing subsystems in order to support on-demand routing, for example. The
+ * method for requesting this operation is Ipv4StaticRouting::RequestRoute for
+ * the static routing protocol.
+ *
+ * Each routing protocol is also free to implement its own methods for managing
+ * routes which you will find below. This class manages a set of "static" or
+ * manually configured routes for host, network and multicast routes.
+ *
+ * @see Ipv4RoutingProtocol
+ * @see Ipv4L3Protocol::AddRoutingProtocol
+ * @see Ipv4L3Protocol::Ipv4L3Protocol
+ */
+class Ipv4StaticRouting : public Ipv4RoutingProtocol
+{
+public:
+/**
+ * @brief Construct an empty Ipv4StaticRouting routing protocol,
+ * @internal
+ *
+ * The Ipv4StaticRouting class supports host, network and multicast routes.
+ * This method initializes the lists containing these routes to empty.
+ *
+ * @see Ipv4StaticRouting
+ */
+ Ipv4StaticRouting ();
+
+/**
+ * @brief Request that a check for a route bw performed and if a route is found
+ * that the packet be sent on its way using the pre-packaged send callback.
+ *
+ * The source and destination IP addresses for the packet in question are found
+ * in the provided Ipv4Header. There are two major processing forks depending
+ * on the type of destination address.
+ *
+ * If the destination address is unicast then the routing table is consulted
+ * for a route to the destination and if it is found, the routeReply callback
+ * is executed to send the packet (with the found route).
+ *
+ * If the destination address is a multicast, then the exact processing steps
+ * depend on whether or not the packet has been sourced locally. This is
+ * determined by the parameter ifIndex. This is the interface index over which
+ * this packet was received. If the packet has not been received over a
+ * network interface, this index will be set to
+ * Ipv4RoutingProtocol::IF_INDEX_ANY (a very large number). In that case,
+ * we want to avoid the requirement that an explicit route out of each node
+ * must be set, so we don't do anything here.
+ *
+ * If the packet is a multicast destination and has been received over a
+ * network interface, a call to this method implies that the packet is being
+ * forwarded. In that case, there must be an explicit route out of the node.
+ * A multicast route references the source address, the destination address
+ * (the multicast group) and the input interface in order to find a route.
+ * We consult the multicast routing table and, if a route is found, send the
+ * packet out of as many interfaces as required using the provided callback
+ * (think of it as a pre-packaged send call).
+ *
+ * @param ifIndex The network interface index over which the packed was
+ * received. If the packet is from a local source, ifIndex will be set to
+ * Ipv4RoutingProtocol::IF_INDEX_ANY.
+ * @param ipHeader the Ipv4Header containing the source and destination IP
+ * addresses for the packet.
+ * @param packet The packet to be sent if a route is found.
+ * @param routeReply A callback that packaged up the call to actually send the
+ * packet.
+ * @return Returns true if a route is found and the packet has been sent,
+ * otherwise returns false indicating that the next routing protocol should
+ * be consulted. In practice, the static routing protocol is the last chance
+ * protocol.
+ *
+ * @see Ipv4StaticRouting
+ * @see Ipv4RoutingProtocol
+ */
+ virtual bool RequestRoute (uint32_t ifIndex,
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ RouteReplyCallback routeReply);
+
+/**
+ * @brief Check to see if we can determine the interface index that will be
+ * used if a packet is sent to this destination.
+ *
+ * This method addresses a problem in the IP stack where a destination address
+ * must be present and checksummed into the IP header before the actual
+ * interface over which the packet is sent can be determined. The answer is
+ * to implement a known and intentional cross-layer violation. This is the
+ * endpoint of a call chain that started up quite high in the stack (sockets)
+ * and has found its way down to the Ipv4L3Protocol which is consulting the
+ * routing protocols for what they would do if presented with a packet of the
+ * given destination.
+ *
+ * Note that the a single interface index is returned. This means that if
+ * the destination address is a multicast, and an explicit route is present
+ * that includeds multiple output interfaces, that route cannot be used.
+ *
+ * If there are multiple paths out of the node, the resolution is performed
+ * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more
+ * contextual information that is useful for making a determination.
+ *
+ * @param destination The Ipv4Address if the destination of a hypothetical
+ * packet. This may be a multicast group address.
+ * @param ifIndex A reference to the interface index over which a packet
+ * sent to this destination would be sent.
+ * @return Returns true if a route is found to the destination that involves
+ * a single output interface index, otherwise returns false indicating that
+ * the next routing protocol should be consulted. In practice, the static
+ * routing protocol is the last chance protocol.
+ *
+ * @see Ipv4StaticRouting
+ * @see Ipv4RoutingProtocol
+ * @see Ipv4L3Protocol
+ */
+ virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex);
+
+/**
+ * @brief Add a host route to the static routing table.
+ *
+ * @param dest The Ipv4Address destination for this route.
+ * @param nextHop The Ipv4Address of the next hop in the route.
+ * @param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * @see Ipv4Address
+ */
+ void AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface);
+/**
+ * @brief Add a host route to the static routing table.
+ *
+ * @param dest The Ipv4Address destination for this route.
+ * @param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * @see Ipv4Address
+ */
+ void AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface);
+
+/**
+ * @brief Add a network route to the static routing table.
+ *
+ * @param network The Ipv4Address network for this route.
+ * @param networkMask The Ipv4Mask to extract the network.
+ * @param nextHop The next hop in the route to the destination network.
+ * @param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * @see Ipv4Address
+ */
+ void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface);
+
+/**
+ * @brief Add a network route to the static routing table.
+ *
+ * @param network The Ipv4Address network for this route.
+ * @param networkMask The Ipv4Mask to extract the network.
+ * @param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * @see Ipv4Address
+ */
+ void AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface);
+
+/**
+ * @brief Add a default route to the static routing table.
+ *
+ * This method tells the routing system what to do in the case where a specific
+ * route to a destination is not found. The system forwards packets to the
+ * specified node in the hope that it knows better how to route the packet.
+ *
+ * If the default route is set, it is returned as the selected route from
+ * LookupStatic irrespective of destination address if no specific route is
+ * found.
+ *
+ * @param nextHop The Ipv4Address to send packets to in the hope that they
+ * will be forwarded correctly.
+ * @param interface The network interface index used to send packets.
+ *
+ * @see Ipv4Address
+ * @see Ipv4StaticRouting::Lookup
+ */
+ void SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface);
+
+/**
+ * @brief Get the number of individual unicast routes that have been added
+ * to the routing table.
+ *
+ * @warning The default route counts as one of the routes.
+ */
+ uint32_t GetNRoutes (void);
+
+/**
+ * @brief Get the default route from the static routing table.
+ *
+ * @return If the default route is set, a pointer to that Ipv4Route is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * @see Ipv4Route
+ */
+ Ipv4Route *GetDefaultRoute (void);
+
+/**
+ * @brief Get a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries. The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table. This means that if you
+ * add only a default route, the table will have one entry that can be accessed
+ * either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
+ *
+ * Similarly, if the default route has been set, calling RemoveRoute (0) will
+ * remove the default route.
+ *
+ * @param i The index (into the routing table) of the route to retrieve. If
+ * the default route has been set, it will occupy index zero.
+ * @return If route is set, a pointer to that Ipv4Route is returned, otherwise
+ * a zero pointer is returned.
+ *
+ * @see Ipv4Route
+ * @see Ipv4StaticRouting::RemoveRoute
+ */
+ Ipv4Route *GetRoute (uint32_t i);
+
+/**
+ * @brief Remove a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries. The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table. This means that if the
+ * default route has been set, calling RemoveRoute (0) will remove the
+ * default route.
+ *
+ * @param i The index (into the routing table) of the route to remove. If
+ * the default route has been set, it will occupy index zero.
+ *
+ * @see Ipv4Route
+ * @see Ipv4StaticRouting::GetRoute
+ * @see Ipv4StaticRouting::AddRoute
+ */
+ void RemoveRoute (uint32_t i);
+
+/**
+ * @brief Add a multicast route to the static routing table.
+ *
+ * A multicast route must specify an origin IP address, a multicast group and
+ * an input network interface index as conditions and provide a vector of
+ * output network interface indices over which packets matching the conditions
+ * are sent.
+ *
+ * Typically there are two main types of multicast routes: routes of the
+ * first kind are used during forwarding. All of the conditions must be
+ * exlicitly provided. The second kind of routes are used to get packets off
+ * of a local node. The difference is in the input interface. Routes for
+ * forwarding will always have an explicit input interface specified. Routes
+ * off of a node will always set the input interface to a wildcard specified
+ * by the index Ipv4RoutingProtocol::IF_INDEX_ANY.
+ *
+ * For routes off of a local node wildcards may be used in the origin and
+ * multicast group addresses. The wildcard used for Ipv4Adresses is that
+ * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage
+ * of a wildcard allows one to specify default behavior to varying degrees.
+ *
+ * For example, making the origin address a wildcard, but leaving the
+ * multicast group specific allows one (in the case of a node with multiple
+ * interfaces) to create different routes using different output interfaces
+ * for each multicast group.
+ *
+ * If the origin and multicast addresses are made wildcards, you have created
+ * essentially a default multicast address that can forward to multiple
+ * interfaces. Compare this to the actual default multicast address that is
+ * limited to specifying a single output interface for compatibility with
+ * existing functionality in other systems.
+ *
+ * @param origin The Ipv4Address of the origin of packets for this route. May
+ * be Ipv4Address:GetAny for open groups.
+ * @param group The Ipv4Address of the multicast group or this route.
+ * @param inputInterface The input network interface index over which to
+ * expect packets destined for this route. May be
+ * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin.
+ * @param outputInterfaces A vector of network interface indices used to specify
+ * how to send packets to the destination(s).
+ *
+ * @see Ipv4Address
+ */
+ void AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces);
+
+/**
+ * @brief Add a default multicast route to the static routing table.
+ *
+ * This is the multicast equivalent of the unicast version SetDefaultRoute.
+ * We tell the routing system what to do in the case where a specific route
+ * to a destination multicast group is not found. The system forwards
+ * packets out the specified interface in the hope that "something out there"
+ * knows better how to route the packet. This method is only used in
+ * initially sending packets off of a host. The default multicast route is
+ * not consulted during forwarding -- exact routes must be specified using
+ * AddMulticastRoute for that case.
+ *
+ * Since we're basically sending packets to some entity we think may know
+ * better what to do, we don't pay attention to "subtleties" like origin
+ * address, nor do we worry about forwarding out multiple interfaces. If the
+ * default multicast route is set, it is returned as the selected route from
+ * LookupStatic irrespective of origin or multicast group if another specific
+ * route is not found.
+ *
+ * @param outputInterface The network interface index used to specify where
+ * to send packets in the case of unknown routes.
+ *
+ * @see Ipv4Address
+ */
+ void SetDefaultMulticastRoute (uint32_t outputInterface);
+
+/**
+ * @brief Get the number of individual multicast routes that have been added
+ * to the routing table.
+ *
+ * @warning The default multicast route counts as one of the routes.
+ */
+ uint32_t GetNMulticastRoutes (void) const;
+
+/**
+ * @brief Get a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table
+ * with n entries. The one sublety of note is that if a default route has
+ * been set it will appear as the zeroth entry in the table. This means that
+ * if you add only a default route, the table will have one entry that can be
+ * accessed either by explicity calling GetDefaultMulticastRoute () or by
+ * calling GetMulticastRoute (0).
+ *
+ * Similarly, if the default route has been set, calling
+ * RemoveMulticastRoute (0) will remove the default route.
+ *
+ * @param i The index (into the routing table) of the multicast route to
+ * retrieve. If the default route has been set, it will occupy index zero.
+ * @return If route \e i is set, a pointer to that Ipv4MulticastRoute is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * @see Ipv4MulticastRoute
+ * @see Ipv4StaticRouting::RemoveRoute
+ */
+ Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
+
+/**
+ * @brief Get the default multicast route from the static routing table.
+ *
+ * @return If the default route is set, a pointer to that Ipv4MulticastRoute is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * @see Ipv4Route
+ */
+ Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
+
+/**
+ * @brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table
+ * with n entries. The one sublety of note is that if a default multicast
+ * route has been set it will appear as the zeroth entry in the table. This
+ * means that the default route may be removed by calling this method with
+ * appropriate wildcard parameters.
+ *
+ * This method causes the multicast routing table to be searched for the first
+ * route that matches the parameters and removes it.
+ *
+ * Wildcards may be provided to this function, but the wildcards are used to
+ * exacly match wildcards in the routes (see AddMulticastRoute). That is,
+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
+ * remove routes with any address in the origin, but will only remove routes
+ * with "0.0.0.0" set as the the origin.
+ *
+ * @param origin The IP address specified as the origin of packets for the
+ * route.
+ * @param group The IP address specified as the multicast group addres of
+ * the route.
+ * @param inputInterface The network interface index specified as the expected
+ * input interface for the route.
+ * @returns true if a route was found and removed, false otherwise.
+ *
+ * @see Ipv4MulticastRoute
+ * @see Ipv4StaticRouting::AddMulticastRoute
+ */
+ bool RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface);
+
+/**
+ * @brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table
+ * with n entries. The one sublety of note is that if a default multicast
+ * route has been set it will appear as the zeroth entry in the table. This
+ * means that if the default route has been set, calling
+ * RemoveMulticastRoute (0) will remove the default route.
+ *
+ * @param index The index (into the multicast routing table) of the route to
+ * remove. If the default route has been set, it will occupy index zero.
+ *
+ * @see Ipv4Route
+ * @see Ipv4StaticRouting::GetRoute
+ * @see Ipv4StaticRouting::AddRoute
+ */
+ void RemoveMulticastRoute (uint32_t index);
+
+protected:
+ void DoDispose (void);
+
+private:
+ typedef std::list<Ipv4Route *> HostRoutes;
+ typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
+ typedef std::list<Ipv4Route *>::iterator HostRoutesI;
+ typedef std::list<Ipv4Route *> NetworkRoutes;
+ typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
+ typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
+
+ typedef std::list<Ipv4MulticastRoute *> MulticastRoutes;
+ typedef std::list<Ipv4MulticastRoute *>::const_iterator MulticastRoutesCI;
+ typedef std::list<Ipv4MulticastRoute *>::iterator MulticastRoutesI;
+
+ Ipv4Route *LookupStatic (Ipv4Address dest);
+ Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group,
+ uint32_t ifIndex);
+
+ HostRoutes m_hostRoutes;
+ NetworkRoutes m_networkRoutes;
+ Ipv4Route *m_defaultRoute;
+ Ipv4MulticastRoute *m_defaultMulticastRoute;
+ MulticastRoutes m_multicastRoutes;
+};
+
+} // Namespace ns3
+
+#endif /* IPV4_STATIC_ROUTING_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/pending-data.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// This is a port of Data PDU Headers from:
+// Georgia Tech Network Simulator
+// George F. Riley. Georgia Tech, Spring 2002
+
+#include <iostream>
+#include <algorithm>
+
+#include <string.h>
+
+#include "pending-data.h"
+#include "ns3/fatal-error.h"
+namespace ns3
+{
+
+PendingData::PendingData () : size (0), data (0),
+ msgSize (0), responseSize (0)
+{
+}
+
+PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp)
+ : size (s), data (0), msgSize (msg), responseSize (resp)
+{
+ if (d)
+ {
+ data.push_back (Create<Packet> (d, size));
+ }
+}
+
+PendingData::PendingData(const std::string& s)
+ : size (s.length () + 1), data (0),
+ msgSize (0), responseSize (0)
+{
+ data.push_back (Create<Packet> ((uint8_t*)s.c_str(), size));
+}
+
+PendingData::PendingData(const PendingData& c)
+ : size (c.Size ()), data (c.data),
+ msgSize (c.msgSize), responseSize (c.responseSize)
+{
+}
+
+PendingData::~PendingData()
+{
+}
+
+PendingData* PendingData::Copy () const
+{
+ return new PendingData (*this);
+};
+
+PendingData* PendingData::CopyS (uint32_t s)
+{ // Copy, but with new size (assumes no associated data);
+ return new PendingData (s, 0, msgSize, responseSize);
+}
+
+PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
+{ // Copy, but with new size (assumes no associated data);
+ return new PendingData (s, d, msgSize, responseSize);
+}
+
+void PendingData::Clear ()
+{ // Remove all pending data
+ data.clear();
+ size = 0;
+}
+
+void PendingData::Add (uint32_t s, const uint8_t* d)
+{
+ if (d == 0)
+ {
+ data.push_back(Create<Packet> (d,s));
+ }
+ else
+ {
+ data.push_back(Create<Packet> (s));
+ }
+ size += s;
+}
+
+void PendingData::Add (Ptr<Packet> p)
+{
+ data.push_back(p);
+ size += p->GetSize();
+}
+
+uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{
+ uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data
+ return SizeFromOffset (o1); // Amount of data after offset
+}
+
+uint32_t PendingData::SizeFromOffset (uint32_t o)
+{ // Find out how much data is available from offset
+ if (o > size) return 0; // No data at requested offset
+ return size - o; // Available data after offset
+}
+
+uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{ // f is the first sequence number in this data, o is offset sequence
+ if (o < f)
+ {
+ return 0; // HuH? Shouldn't happen
+ }
+ return o - f;
+}
+
+Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o)
+{ // Make a copy of data from starting position "o" for "s" bytes
+ // Return NULL if results in zero length data
+ uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data
+ if (s1 == 0)
+ {
+ return 0; // No data requested
+ }
+ if (data.size() != 0)
+ { // Actual data exists, make copy and return it
+ uint32_t count = 0;
+ std::vector<Ptr<Packet> >::size_type begin = 0;
+ bool beginFound = false;
+ std::vector<Ptr<Packet> >::size_type end = 0;
+ Ptr<Packet> outPacket;
+ Ptr<Packet> endFragment;
+ for (std::vector<Ptr<Packet> >::size_type i=0;i<data.size();++i)
+ {
+ count+=data[i]->GetSize();
+ if (!beginFound)
+ {
+ if (count > o)
+ {
+ if (count >= o + s1) //then just copy within this packet
+ {
+ Ptr<Packet> toFragment = data[i];
+ uint32_t packetStart = count - toFragment->GetSize();
+ uint32_t packetOffset = o - packetStart;
+ outPacket = toFragment->CreateFragment (packetOffset, s1);
+ return outPacket;
+ }
+ begin = i;
+ beginFound = true;
+ Ptr<Packet> toFragment = data[begin];
+ uint32_t packetStart = count - toFragment->GetSize();
+ uint32_t packetOffset = o - packetStart;
+ uint32_t fragmentLength = count - o;
+ outPacket = toFragment->CreateFragment (packetOffset, fragmentLength);
+ }
+ }
+ else
+ {
+ if (count >= o + s1)
+ {
+ end = i;
+ Ptr<Packet> toFragment = data[end];
+ uint32_t packetStart = count - toFragment->GetSize();
+ uint32_t fragmentLength = o + s1 - packetStart;
+ endFragment = toFragment->CreateFragment(0, fragmentLength);
+ break;
+ }
+ }
+ }
+ for (std::vector<Ptr<Packet> >::size_type i=begin+1;i<end;++i)
+ {
+ outPacket->AddAtEnd (data[i]);
+ }
+ outPacket->AddAtEnd(endFragment);
+ NS_ASSERT(outPacket->GetSize() == s1);
+ return outPacket;
+ }
+ else
+ { // No actual data, just return dummy-data packet of correct size
+ return Create<Packet> (s1);
+ }
+}
+
+Ptr<Packet> PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o)
+{
+ return CopyFromOffset (s, OffsetFromSeq(f,o));
+}
+
+}//namepsace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/pending-data.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Data Descriptors
+// George F. Riley. Georgia Tech, Spring 2002
+
+#ifndef __datapdu_h__
+#define __datapdu_h__
+
+#include "ns3/packet.h"
+#include "pending-data.h"
+#include "sequence-number.h"
+
+#include "ns3/ptr.h"
+namespace ns3
+{
+class Packet;
+//Doc:ClassXRef
+class PendingData {
+public:
+ PendingData ();
+ PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0);
+ PendingData (const std::string&); // Construct from string
+ PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer
+ PendingData (const PendingData&); // Copy constructor
+ virtual ~PendingData (); // Destructor
+ uint32_t Size () const { return size;}
+ // Serialization
+ uint32_t SSize (); // Size needed for serialization
+ uint8_t* Serialize (uint8_t*, uint32_t&); // Serialize to a buffer
+ uint8_t* Construct (uint8_t*, uint32_t&); // Construct from buffer
+ virtual void Clear ();// Remove all associated data
+ virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end
+ virtual void Add (Ptr<Packet> p);
+ // Inquire available data from (f,o) sequence pair
+ virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&);
+ // Inquire available data from offset
+ virtual uint32_t SizeFromOffset (uint32_t);
+ // Available size from sequence difference
+ virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&);
+ virtual Ptr<Packet> CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret packet
+ // Copy data, size, offset specified by sequence difference
+ virtual Ptr<Packet> CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
+ PendingData* Copy () const; // Create a copy of this header
+ PendingData* CopyS (uint32_t); // Copy with new size
+ PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data
+public:
+ uint32_t size; // Number of data bytes
+ std::vector<Ptr<Packet> > data; // Corresponding data (may be null)
+ // The next two fields allow simulated applications to exchange some info
+ uint32_t msgSize; // Total size of message
+ uint32_t responseSize;// Size of response requested
+};
+
+}//namepsace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/rtt-estimator.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,235 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#include <iostream>
+
+#include "rtt-estimator.h"
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+
+namespace ns3{
+
+NS_OBJECT_ENSURE_REGISTERED (RttEstimator);
+
+//RttEstimator iid
+TypeId
+RttEstimator::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::RttEstimator")
+ .SetParent<Object> ()
+ .AddAttribute ("MaxMultiplier",
+ "XXX",
+ DoubleValue (64.0),
+ MakeDoubleAccessor (&RttEstimator::m_maxMultiplier),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("InitialEstimation",
+ "XXX",
+ TimeValue (Seconds (1.0)),
+ MakeTimeAccessor (&RttEstimator::est),
+ MakeTimeChecker ())
+ ;
+ return tid;
+}
+
+//RttHistory methods
+RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t)
+ : seq (s), count (c), time (t), retx (false)
+ {
+ }
+
+RttHistory::RttHistory (const RttHistory& h)
+ : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
+ {
+ }
+
+// Base class methods
+
+RttEstimator::RttEstimator () : next (1), history (),
+ nSamples (0), multiplier (1.0)
+{
+ //note next=1 everywhere since first segment will have sequence 1
+}
+
+RttEstimator::RttEstimator(const RttEstimator& c)
+ : Object (c), next(c.next), history(c.history),
+ m_maxMultiplier (c.m_maxMultiplier), est(c.est), nSamples(c.nSamples),
+ multiplier(c.multiplier)
+{}
+
+RttEstimator::~RttEstimator ()
+{
+}
+
+void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
+{ // Note that a particular sequence has been sent
+ if (s == next)
+ { // This is the next expected one, just log at end
+ history.push_back (RttHistory (s, c, Simulator::Now () ));
+ next = s + SequenceNumber (c); // Update next expected
+ }
+ else
+ { // This is a retransmit, find in list and mark as re-tx
+ for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i)
+ {
+ if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count))))
+ { // Found it
+ i->retx = true;
+ // One final test..be sure this re-tx does not extend "next"
+ if ((s + SequenceNumber (c)) > next)
+ {
+ next = s + SequenceNumber (c);
+ i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist
+ }
+ break;
+ }
+ }
+ }
+}
+
+Time RttEstimator::AckSeq (SequenceNumber a)
+{ // An ack has been received, calculate rtt and log this measurement
+ // Note we use a linear search (O(n)) for this since for the common
+ // case the ack'ed packet will be at the head of the list
+ Time m = Seconds (0.0);
+ if (history.size () == 0) return (m); // No pending history, just exit
+ RttHistory& h = history.front ();
+ if (!h.retx && a >= (h.seq + SequenceNumber (h.count)))
+ { // Ok to use this sample
+ m = Simulator::Now () - h.time; // Elapsed time
+ Measurement(m); // Log the measurement
+ ResetMultiplier(); // Reset multiplier on valid measurement
+ }
+ // Now delete all ack history with seq <= ack
+ while(history.size() > 0)
+ {
+ RttHistory& h = history.front ();
+ if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing
+ history.pop_front (); // Remove
+ }
+ return m;
+}
+
+void RttEstimator::ClearSent ()
+{ // Clear all history entries
+ next = 1;
+ history.clear ();
+}
+
+void RttEstimator::IncreaseMultiplier ()
+{
+ double a;
+ a = multiplier * 2.0;
+ double b;
+ b = m_maxMultiplier * 2.0;
+ multiplier = std::min (multiplier * 2.0, m_maxMultiplier);
+}
+
+void RttEstimator::ResetMultiplier ()
+{
+ multiplier = 1.0;
+}
+
+void RttEstimator::Reset ()
+{ // Reset to initial state
+ next = 1;
+ est = Seconds (1.0); // XXX: we should go back to the 'initial value' here. Need to add support in Object for this.
+ history.clear (); // Remove all info from the history
+ nSamples = 0;
+ ResetMultiplier ();
+}
+
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Mean-Deviation Estimator
+
+NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation);
+
+TypeId
+RttMeanDeviation::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::RttMeanDeviation")
+ .SetParent<RttEstimator> ()
+ .AddConstructor<RttMeanDeviation> ()
+ .AddAttribute ("Gain",
+ "XXX",
+ DoubleValue (0.1),
+ MakeDoubleAccessor (&RttMeanDeviation::gain),
+ MakeDoubleChecker<double> ())
+ ;
+ return tid;
+}
+
+RttMeanDeviation::RttMeanDeviation() :
+ variance (ns3::Seconds(0))
+{
+}
+
+RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
+ : RttEstimator (c), gain (c.gain), variance (c.variance)
+{
+}
+
+void RttMeanDeviation::Measurement (Time m)
+{
+ if (nSamples)
+ { // Not first
+ Time err = m - est;
+ est = est + Scalar (gain) * err; // estimated rtt
+ err = Abs (err); // absolute value of error
+ variance = variance + Scalar (gain) * (err - variance); // variance of rtt
+ }
+ else
+ { // First sample
+ est = m; // Set estimate to current
+ //variance = m / 2; // And variance to current / 2
+ variance = m; // try this
+ }
+ nSamples++;
+}
+
+Time RttMeanDeviation::RetransmitTimeout ()
+{
+ // If not enough samples, justjust return 2 times estimate
+ //if (nSamples < 2) return est * 2;
+ if (variance < est / Scalar (4.0))
+ return est * Scalar (2 * multiplier); // At least twice current est
+ return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson
+}
+
+Ptr<RttEstimator> RttMeanDeviation::Copy () const
+{
+ return CopyObject<RttMeanDeviation> (this);
+}
+
+void RttMeanDeviation::Reset ()
+{ // Reset to initial state
+ variance = Seconds (0.0);
+ RttEstimator::Reset ();
+}
+}//namepsace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/rtt-estimator.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,113 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#ifndef __rtt_estimator_h__
+#define __rtt_estimator_h__
+
+#include <deque>
+#include "sequence-number.h"
+#include "ns3/nstime.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+class RttHistory {
+public:
+ RttHistory (SequenceNumber s, uint32_t c, Time t);
+ RttHistory (const RttHistory& h); // Copy constructor
+public:
+ SequenceNumber seq; // First sequence number in packet sent
+ uint32_t count; // Number of bytes sent
+ Time time; // Time this one was sent
+ bool retx; // True if this has been retransmitted
+};
+
+typedef std::deque<RttHistory> RttHistory_t;
+
+class RttEstimator : public Object { // Base class for all RTT Estimators
+public:
+ static TypeId GetTypeId (void);
+
+ RttEstimator();
+ RttEstimator(const RttEstimator&); // Copy constructor
+ virtual ~RttEstimator();
+
+ virtual void SentSeq(SequenceNumber, uint32_t);
+ virtual Time AckSeq(SequenceNumber);
+ virtual void ClearSent();
+ virtual void Measurement(Time t) = 0;
+ virtual Time Estimate() = 0;
+ virtual Time RetransmitTimeout() = 0;
+ void Init(SequenceNumber s) { next = s;}
+ virtual Ptr<RttEstimator> Copy() const = 0;
+ virtual void IncreaseMultiplier();
+ virtual void ResetMultiplier();
+ virtual void Reset();
+
+private:
+ SequenceNumber next; // Next expected sequence to be sent
+ RttHistory_t history; // List of sent packet
+ double m_maxMultiplier;
+public:
+ Time est; // Current estimate
+ uint32_t nSamples;// Number of samples
+ double multiplier; // RTO Multiplier
+};
+
+// The "Mean-Deviation" estimator, as discussed by Van Jacobson
+// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+
+ //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator
+ //Doc:Class as described by Van Jacobson
+ //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+class RttMeanDeviation : public RttEstimator {
+public :
+ static TypeId GetTypeId (void);
+
+ RttMeanDeviation ();
+
+
+ //Doc:Method
+ RttMeanDeviation (const RttMeanDeviation&); // Copy constructor
+ //Doc:Desc Copy constructor.
+ //Doc:Arg1 {\tt RttMeanDeviation} object to copy.
+
+ void Measurement (Time);
+ Time Estimate () { return est;}
+ Time Variance () { return variance;}
+ Time RetransmitTimeout ();
+ Ptr<RttEstimator> Copy () const;
+ void Reset ();
+ void Gain (double g) { gain = g;}
+
+public:
+ double gain; // Filter gain
+ Time variance; // Current variance
+};
+}//namespace ns3
+#endif
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/sequence-number.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#include "sequence-number.h"
+
+bool operator< (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+ return l.seq < r.seq;
+}
+
+bool operator<= (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+ return l.seq <= r.seq;
+}
+
+bool operator> (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+ return l.seq > r.seq;
+}
+
+bool operator>= (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+ return l.seq >= r.seq;
+}
+
+// Non-Member Arithmetic operators
+SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r)
+{
+ return SequenceNumber (l.seq + r.seq);
+}
+
+SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r)
+{ // This assumes l is always bigger than r (allows for rollover)
+ if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq);
+ return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1); // Adjust for rollover
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/sequence-number.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#ifndef __seq_h__
+#define __seq_h__
+
+#include <stdint.h>
+
+#define MAX_SEQ ((uint32_t)0xffffffff)
+
+class SequenceNumber {
+public:
+ SequenceNumber () : seq(0) { }
+ SequenceNumber (const uint32_t s) : seq (s) { }
+
+ operator uint32_t () const { return seq;}
+
+ SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;}
+
+ SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;}
+ SequenceNumber operator++ () { seq++; return *this;}
+ SequenceNumber operator++ (int) { SequenceNumber ss (seq); seq++; return ss;}
+ SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;}
+ SequenceNumber operator-- () { seq--; return *this;}
+ SequenceNumber operator-- (int) { SequenceNumber ss (seq); seq--; return ss;}
+public:
+ uint32_t seq;
+};
+
+// Comparison operators
+
+bool operator< (const SequenceNumber l, const SequenceNumber r);
+bool operator<= (const SequenceNumber l, const SequenceNumber r);
+bool operator> (const SequenceNumber l, const SequenceNumber r);
+bool operator>= (const SequenceNumber l, const SequenceNumber r);
+
+// Non-member arithmetic operators
+SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r);
+SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r);
+
+#endif
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/sgi-hashmap.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,32 @@
+/* This code snippet was ripped out of the gcc
+ * documentation and slightly modified to work
+ * with gcc 4.x
+ */
+#ifndef SGI_HASHMAP_H
+#define SGI_HASHMAP_H
+
+/* To use gcc extensions.
+ */
+#ifdef __GNUC__
+ #if __GNUC__ < 3
+ #include <hash_map.h>
+namespace sgi { using ::hash_map; }; // inherit globals
+ #else
+ #if __GNUC__ < 4
+ #include <ext/hash_map>
+ #if __GNUC_MINOR__ == 0
+namespace sgi = std; // GCC 3.0
+ #else
+namespace sgi = ::__gnu_cxx; // GCC 3.1 and later
+ #endif
+ #else // gcc 4.x and later
+ #include <ext/hash_map>
+ namespace sgi = ::__gnu_cxx;
+ #endif
+ #endif
+#else // ... there are other compilers, right?
+namespace sgi = std;
+#endif
+
+
+#endif /* SGI_HASHMAP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-header.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include "tcp-socket-impl.h"
+#include "tcp-header.h"
+#include "ns3/buffer.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpHeader);
+
+bool TcpHeader::m_calcChecksum = false;
+
+TcpHeader::TcpHeader ()
+ : m_sourcePort (0),
+ m_destinationPort (0),
+ m_sequenceNumber (0),
+ m_ackNumber (0),
+ m_length (5),
+ m_flags (0),
+ m_windowSize (0xffff),
+ m_checksum (0),
+ m_urgentPointer (0)
+{}
+
+TcpHeader::~TcpHeader ()
+{}
+
+void
+TcpHeader::EnableChecksums (void)
+{
+ m_calcChecksum = true;
+}
+
+void TcpHeader::SetSourcePort (uint16_t port)
+{
+ m_sourcePort = port;
+}
+void TcpHeader::SetDestinationPort (uint16_t port)
+{
+ m_destinationPort = port;
+}
+void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber)
+{
+ m_sequenceNumber = sequenceNumber;
+}
+void TcpHeader::SetAckNumber (SequenceNumber ackNumber)
+{
+ m_ackNumber = ackNumber;
+}
+void TcpHeader::SetLength (uint8_t length)
+{
+ m_length = length;
+}
+void TcpHeader::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void TcpHeader::SetWindowSize (uint16_t windowSize)
+{
+ m_windowSize = windowSize;
+}
+void TcpHeader::SetChecksum (uint16_t checksum)
+{
+ m_checksum = checksum;
+}
+void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
+{
+ m_urgentPointer = urgentPointer;
+}
+
+uint16_t TcpHeader::GetSourcePort () const
+{
+ return m_sourcePort;
+}
+uint16_t TcpHeader::GetDestinationPort () const
+{
+ return m_destinationPort;
+}
+SequenceNumber TcpHeader::GetSequenceNumber () const
+{
+ return m_sequenceNumber;
+}
+SequenceNumber TcpHeader::GetAckNumber () const
+{
+ return m_ackNumber;
+}
+uint8_t TcpHeader::GetLength () const
+{
+ return m_length;
+}
+uint8_t TcpHeader::GetFlags () const
+{
+ return m_flags;
+}
+uint16_t TcpHeader::GetWindowSize () const
+{
+ return m_windowSize;
+}
+uint16_t TcpHeader::GetChecksum () const
+{
+ return m_checksum;
+}
+uint16_t TcpHeader::GetUrgentPointer () const
+{
+ return m_urgentPointer;
+}
+
+void
+TcpHeader::InitializeChecksum (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol)
+{
+ m_checksum = 0;
+//XXX requires peeking into IP to get length of the TCP segment
+}
+
+TypeId
+TcpHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TcpHeader")
+ .SetParent<Header> ()
+ .AddConstructor<TcpHeader> ()
+ ;
+ return tid;
+}
+TypeId
+TcpHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+void TcpHeader::Print (std::ostream &os) const
+{
+ os << m_sourcePort << " > " << m_destinationPort;
+ if(m_flags!=0)
+ {
+ os<<" [";
+ if((m_flags & FIN) != 0)
+ {
+ os<<" FIN ";
+ }
+ if((m_flags & SYN) != 0)
+ {
+ os<<" SYN ";
+ }
+ if((m_flags & RST) != 0)
+ {
+ os<<" RST ";
+ }
+ if((m_flags & PSH) != 0)
+ {
+ os<<" PSH ";
+ }
+ if((m_flags & ACK) != 0)
+ {
+ os<<" ACK ";
+ }
+ if((m_flags & URG) != 0)
+ {
+ os<<" URG ";
+ }
+ os<<"]";
+ }
+ os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
+}
+uint32_t TcpHeader::GetSerializedSize (void) const
+{
+ return 4*m_length;
+}
+void TcpHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteHtonU16 (m_sourcePort);
+ start.WriteHtonU16 (m_destinationPort);
+ start.WriteHtonU32 (m_sequenceNumber);
+ start.WriteHtonU32 (m_ackNumber);
+ start.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
+ start.WriteHtonU16 (m_windowSize);
+ //XXX calculate checksum here
+ start.WriteHtonU16 (m_checksum);
+ start.WriteHtonU16 (m_urgentPointer);
+}
+uint32_t TcpHeader::Deserialize (Buffer::Iterator start)
+{
+ m_sourcePort = start.ReadNtohU16 ();
+ m_destinationPort = start.ReadNtohU16 ();
+ m_sequenceNumber = start.ReadNtohU32 ();
+ m_ackNumber = start.ReadNtohU32 ();
+ uint16_t field = start.ReadNtohU16 ();
+ m_flags = field & 0x3F;
+ m_length = field>>12;
+ m_windowSize = start.ReadNtohU16 ();
+ m_checksum = start.ReadNtohU16 ();
+ m_urgentPointer = start.ReadNtohU16 ();
+ return GetSerializedSize ();
+}
+
+
+}; // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-header.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_HEADER_H
+#define TCP_HEADER_H
+
+#include <stdint.h>
+#include "ns3/header.h"
+#include "ns3/buffer.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/sequence-number.h"
+
+namespace ns3 {
+
+class TcpHeader : public Header
+{
+public:
+ TcpHeader ();
+ virtual ~TcpHeader ();
+
+ /**
+ * \brief Enable checksum calculation for TCP (XXX currently has no effect)
+ */
+ static void EnableChecksums (void);
+//Setters
+ /**
+ * \param port The source port for this TcpHeader
+ */
+ void SetSourcePort (uint16_t port);
+ /**
+ * \param port the destination port for this TcpHeader
+ */
+ void SetDestinationPort (uint16_t port);
+ /**
+ * \param sequenceNumber the sequence number for this TcpHeader
+ */
+ void SetSequenceNumber (SequenceNumber sequenceNumber);
+ /**
+ * \param ackNumber the ACK number for this TcpHeader
+ */
+ void SetAckNumber (SequenceNumber ackNumber);
+ /**
+ * \param length the length of this TcpHeader
+ */
+ void SetLength (uint8_t length);
+ /**
+ * \param flags the flags for this TcpHeader
+ */
+ void SetFlags (uint8_t flags);
+ /**
+ * \param windowSize the window size for this TcpHeader
+ */
+ void SetWindowSize (uint16_t windowSize);
+ /**
+ * \param checksum the checksum for this TcpHeader
+ */
+ void SetChecksum (uint16_t checksum);
+ /**
+ * \param urgentPointer the urgent pointer for this TcpHeader
+ */
+ void SetUrgentPointer (uint16_t urgentPointer);
+
+
+//Getters
+ /**
+ * \return The source port for this TcpHeader
+ */
+ uint16_t GetSourcePort () const;
+ /**
+ * \return the destination port for this TcpHeader
+ */
+ uint16_t GetDestinationPort () const;
+ /**
+ * \return the sequence number for this TcpHeader
+ */
+ SequenceNumber GetSequenceNumber () const;
+ /**
+ * \return the ACK number for this TcpHeader
+ */
+ SequenceNumber GetAckNumber () const;
+ /**
+ * \return the length of this TcpHeader
+ */
+ uint8_t GetLength () const;
+ /**
+ * \return the flags for this TcpHeader
+ */
+ uint8_t GetFlags () const;
+ /**
+ * \return the window size for this TcpHeader
+ */
+ uint16_t GetWindowSize () const;
+ /**
+ * \return the checksum for this TcpHeader
+ */
+ uint16_t GetChecksum () const;
+ /**
+ * \return the urgent pointer for this TcpHeader
+ */
+ uint16_t GetUrgentPointer () 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 tcp checksums, you should call this
+ * method prior to adding the header to a packet.
+ */
+ void InitializeChecksum (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol);
+
+ typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16,
+ URG = 32} Flags_t;
+
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+ uint16_t m_sourcePort;
+ uint16_t m_destinationPort;
+ uint32_t m_sequenceNumber;
+ uint32_t m_ackNumber;
+ uint8_t m_length; // really a uint4_t
+ uint8_t m_flags; // really a uint6_t
+ uint16_t m_windowSize;
+ uint16_t m_checksum;
+ uint16_t m_urgentPointer;
+
+ static bool m_calcChecksum;
+};
+
+}; // namespace ns3
+
+#endif /* TCP_HEADER */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-l4-protocol.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,526 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "tcp-l4-protocol.h"
+#include "tcp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "tcp-socket-impl.h"
+
+#include "tcp-typedefs.h"
+
+#include <vector>
+#include <sstream>
+#include <iomanip>
+
+NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol);
+
+//State Machine things --------------------------------------------------------
+TcpStateMachine::TcpStateMachine()
+ : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)),
+ eV (MAX_FLAGS)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ // Create the state table
+ // Closed state
+ aT[CLOSED][APP_LISTEN] = SA (LISTEN, NO_ACT);
+ aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[CLOSED][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SEQ_RECV] = SA (CLOSED, NO_ACT);
+ aT[CLOSED][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[CLOSED][TIMEOUT] = SA (CLOSED, RST_TX);
+ aT[CLOSED][ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][FIN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSED][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Listen State
+ // For the listen state, anything other than CONNECT or SEND
+ // is simply ignored....this likely indicates the child TCP
+ // has finished and issued unbind call, but the remote end
+ // has not yet closed.
+ aT[LISTEN][APP_LISTEN] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[LISTEN][APP_SEND] = SA (SYN_SENT, SYN_TX);
+ aT[LISTEN][SEQ_RECV] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[LISTEN][TIMEOUT] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][SYN_RX] = SA (LISTEN, SYN_ACK_TX);//stay in listen and fork
+ aT[LISTEN][SYN_ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][FIN_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][FIN_ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][RST_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][BAD_FLAGS] = SA (LISTEN, NO_ACT);
+
+ // Syn Sent State
+ aT[SYN_SENT][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[SYN_SENT][APP_SEND] = SA (SYN_SENT, NO_ACT);
+ aT[SYN_SENT][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
+ aT[SYN_SENT][APP_CLOSE] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][TIMEOUT] = SA (CLOSED, NO_ACT);
+ aT[SYN_SENT][ACK_RX] = SA (SYN_SENT, NO_ACT);
+ aT[SYN_SENT][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[SYN_SENT][SYN_ACK_RX] = SA (ESTABLISHED, ACK_TX_1);
+ aT[SYN_SENT][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][FIN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][RST_RX] = SA (CLOSED, APP_NOTIFY);
+ aT[SYN_SENT][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Syn Recvd State
+ aT[SYN_RCVD][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
+ aT[SYN_RCVD][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
+ aT[SYN_RCVD][TIMEOUT] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][ACK_RX] = SA (ESTABLISHED, SERV_NOTIFY);
+ aT[SYN_RCVD][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[SYN_RCVD][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[SYN_RCVD][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[SYN_RCVD][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Established State
+ aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED, RST_TX);
+ aT[ESTABLISHED][APP_SEND] = SA (ESTABLISHED,TX_DATA);
+ aT[ESTABLISHED][SEQ_RECV] = SA (ESTABLISHED,NEW_SEQ_RX);
+ aT[ESTABLISHED][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
+ aT[ESTABLISHED][TIMEOUT] = SA (ESTABLISHED,RETX);
+ aT[ESTABLISHED][ACK_RX] = SA (ESTABLISHED,NEW_ACK);
+ aT[ESTABLISHED][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT);
+ aT[ESTABLISHED][FIN_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[ESTABLISHED][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[ESTABLISHED][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Close Wait State
+ aT[CLOSE_WAIT][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[CLOSE_WAIT][APP_SEND] = SA (CLOSE_WAIT, TX_DATA);
+ aT[CLOSE_WAIT][SEQ_RECV] = SA (CLOSE_WAIT, NEW_SEQ_RX);
+ aT[CLOSE_WAIT][APP_CLOSE] = SA (LAST_ACK, FIN_ACK_TX);
+ aT[CLOSE_WAIT][TIMEOUT] = SA (CLOSE_WAIT, NO_ACT);
+ aT[CLOSE_WAIT][ACK_RX] = SA (CLOSE_WAIT, NO_ACT);
+ aT[CLOSE_WAIT][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][FIN_RX] = SA (CLOSE_WAIT, ACK_TX);
+ aT[CLOSE_WAIT][FIN_ACK_RX] = SA (CLOSE_WAIT, ACK_TX);
+ aT[CLOSE_WAIT][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSE_WAIT][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Close Last Ack State
+ aT[LAST_ACK][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[LAST_ACK][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][SEQ_RECV] = SA (LAST_ACK, NEW_SEQ_RX);
+ aT[LAST_ACK][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][TIMEOUT] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][ACK_RX] = SA (CLOSED, APP_CLOSED);
+ aT[LAST_ACK][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][FIN_RX] = SA (LAST_ACK, FIN_ACK_TX);
+ aT[LAST_ACK][FIN_ACK_RX] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[LAST_ACK][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // FIN_WAIT_1 state
+ aT[FIN_WAIT_1][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][SEQ_RECV] = SA (FIN_WAIT_1, NEW_SEQ_RX);
+ aT[FIN_WAIT_1][APP_CLOSE] = SA (FIN_WAIT_1, NO_ACT);
+ aT[FIN_WAIT_1][TIMEOUT] = SA (FIN_WAIT_1, NO_ACT);
+ aT[FIN_WAIT_1][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
+ aT[FIN_WAIT_1][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][FIN_RX] = SA (CLOSING, ACK_TX);
+ aT[FIN_WAIT_1][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_1][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[FIN_WAIT_1][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // FIN_WAIT_2 state
+ aT[FIN_WAIT_2][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][SEQ_RECV] = SA (FIN_WAIT_2, NEW_SEQ_RX);
+ aT[FIN_WAIT_2][APP_CLOSE] = SA (FIN_WAIT_2, NO_ACT);
+ aT[FIN_WAIT_2][TIMEOUT] = SA (FIN_WAIT_2, NO_ACT);
+ aT[FIN_WAIT_2][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
+ aT[FIN_WAIT_2][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][FIN_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_2][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_2][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[FIN_WAIT_2][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // CLOSING state
+ aT[CLOSING][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[CLOSING][SEQ_RECV] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_CLOSE] = SA (CLOSED, RST_TX);
+ aT[CLOSING][TIMEOUT] = SA (CLOSING, NO_ACT);
+ aT[CLOSING][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[CLOSING][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSING][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSING][FIN_RX] = SA (CLOSED, ACK_TX);
+ aT[CLOSING][FIN_ACK_RX] = SA (CLOSED, ACK_TX);
+ aT[CLOSING][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSING][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // TIMED_WAIT state
+ aT[TIMED_WAIT][APP_LISTEN] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_SEND] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SEQ_RECV] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_CLOSE] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][TIMEOUT] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SYN_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SYN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][FIN_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][FIN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][RST_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][BAD_FLAGS] = SA (TIMED_WAIT, NO_ACT);
+
+ // Create the flags lookup table
+ eV[ 0x00] = SEQ_RECV; // No flags
+ eV[ 0x01] = FIN_RX; // Fin
+ eV[ 0x02] = SYN_RX; // Syn
+ eV[ 0x03] = BAD_FLAGS; // Illegal
+ eV[ 0x04] = RST_RX; // Rst
+ eV[ 0x05] = BAD_FLAGS; // Illegal
+ eV[ 0x06] = BAD_FLAGS; // Illegal
+ eV[ 0x07] = BAD_FLAGS; // Illegal
+ eV[ 0x08] = SEQ_RECV; // Psh flag is not used
+ eV[ 0x09] = FIN_RX; // Fin
+ eV[ 0x0a] = SYN_RX; // Syn
+ eV[ 0x0b] = BAD_FLAGS; // Illegal
+ eV[ 0x0c] = RST_RX; // Rst
+ eV[ 0x0d] = BAD_FLAGS; // Illegal
+ eV[ 0x0e] = BAD_FLAGS; // Illegal
+ eV[ 0x0f] = BAD_FLAGS; // Illegal
+ eV[ 0x10] = ACK_RX; // Ack
+ eV[ 0x11] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x12] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x13] = BAD_FLAGS; // Illegal
+ eV[ 0x14] = RST_RX; // Rst
+ eV[ 0x15] = BAD_FLAGS; // Illegal
+ eV[ 0x16] = BAD_FLAGS; // Illegal
+ eV[ 0x17] = BAD_FLAGS; // Illegal
+ eV[ 0x18] = ACK_RX; // Ack
+ eV[ 0x19] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x1b] = BAD_FLAGS; // Illegal
+ eV[ 0x1c] = RST_RX; // Rst
+ eV[ 0x1d] = BAD_FLAGS; // Illegal
+ eV[ 0x1e] = BAD_FLAGS; // Illegal
+ eV[ 0x1f] = BAD_FLAGS; // Illegal
+ eV[ 0x20] = SEQ_RECV; // No flags (Urgent not presently used)
+ eV[ 0x21] = FIN_RX; // Fin
+ eV[ 0x22] = SYN_RX; // Syn
+ eV[ 0x23] = BAD_FLAGS; // Illegal
+ eV[ 0x24] = RST_RX; // Rst
+ eV[ 0x25] = BAD_FLAGS; // Illegal
+ eV[ 0x26] = BAD_FLAGS; // Illegal
+ eV[ 0x27] = BAD_FLAGS; // Illegal
+ eV[ 0x28] = SEQ_RECV; // Psh flag is not used
+ eV[ 0x29] = FIN_RX; // Fin
+ eV[ 0x2a] = SYN_RX; // Syn
+ eV[ 0x2b] = BAD_FLAGS; // Illegal
+ eV[ 0x2c] = RST_RX; // Rst
+ eV[ 0x2d] = BAD_FLAGS; // Illegal
+ eV[ 0x2e] = BAD_FLAGS; // Illegal
+ eV[ 0x2f] = BAD_FLAGS; // Illegal
+ eV[ 0x30] = ACK_RX; // Ack (Urgent not used)
+ eV[ 0x31] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x32] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x33] = BAD_FLAGS; // Illegal
+ eV[ 0x34] = RST_RX; // Rst
+ eV[ 0x35] = BAD_FLAGS; // Illegal
+ eV[ 0x36] = BAD_FLAGS; // Illegal
+ eV[ 0x37] = BAD_FLAGS; // Illegal
+ eV[ 0x38] = ACK_RX; // Ack
+ eV[ 0x39] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x3b] = BAD_FLAGS; // Illegal
+ eV[ 0x3c] = RST_RX; // Rst
+ eV[ 0x3d] = BAD_FLAGS; // Illegal
+ eV[ 0x3e] = BAD_FLAGS; // Illegal
+ eV[ 0x3f] = BAD_FLAGS; // Illegal
+}
+
+SA TcpStateMachine::Lookup (States_t s, Events_t e)
+{
+ NS_LOG_FUNCTION (this << s << e);
+ return aT[s][e];
+}
+
+Events_t TcpStateMachine::FlagsEvent (uint8_t f)
+{
+ NS_LOG_FUNCTION (this << f);
+ // Lookup event from flags
+ if (f >= MAX_FLAGS) return BAD_FLAGS;
+ return eV[f]; // Look up flags event
+}
+
+static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine
+
+//TcpL4Protocol stuff----------------------------------------------------------
+
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
+
+ObjectFactory
+TcpL4Protocol::GetDefaultRttEstimatorFactory (void)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (RttMeanDeviation::GetTypeId ());
+ return factory;
+}
+
+TypeId
+TcpL4Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TcpL4Protocol")
+ .SetParent<Ipv4L4Protocol> ()
+ .AddAttribute ("RttEstimatorFactory",
+ "How RttEstimator objects are created.",
+ ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
+ MakeObjectFactoryAccessor (&TcpL4Protocol::m_rttFactory),
+ MakeObjectFactoryChecker ())
+ ;
+ return tid;
+}
+
+TcpL4Protocol::TcpL4Protocol ()
+ : m_endPoints (new Ipv4EndPointDemux ())
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC("Made a TcpL4Protocol "<<this);
+}
+
+TcpL4Protocol::~TcpL4Protocol ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+TcpL4Protocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+}
+
+int
+TcpL4Protocol::GetProtocolNumber (void) const
+{
+ return PROT_NUMBER;
+}
+int
+TcpL4Protocol::GetVersion (void) const
+{
+ return 2;
+}
+
+void
+TcpL4Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoints != 0)
+ {
+ delete m_endPoints;
+ m_endPoints = 0;
+ }
+ m_node = 0;
+ Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+TcpL4Protocol::CreateSocket (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
+ Ptr<TcpSocketImpl> socket = CreateObject<TcpSocketImpl> ();
+ socket->SetNode (m_node);
+ socket->SetTcp (this);
+ socket->SetRtt (rtt);
+ return socket;
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address)
+{
+ NS_LOG_FUNCTION (this << address);
+ return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (uint16_t port)
+{
+ NS_LOG_FUNCTION (this << port);
+ return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << address << port);
+ return m_endPoints->Allocate (address, port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort)
+{
+ NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+ return m_endPoints->Allocate (localAddress, localPort,
+ peerAddress, peerPort);
+}
+
+void
+TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+ NS_LOG_FUNCTION (this << endPoint);
+ m_endPoints->DeAllocate (endPoint);
+}
+
+void
+TcpL4Protocol::Receive (Ptr<Packet> packet,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface)
+{
+ NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
+
+ TcpHeader tcpHeader;
+ //these two do a peek, so that the packet can be forwarded up
+ packet->RemoveHeader (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());
+ packet->AddHeader (tcpHeader);
+ NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
+ Ipv4EndPointDemux::EndPoints endPoints =
+ m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
+ source, tcpHeader.GetSourcePort (),incomingInterface);
+ if (endPoints.empty ())
+ {
+ NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<<this);
+ std::ostringstream oss;
+ oss<<" destination IP: ";
+ destination.Print (oss);
+ oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
+ source.Print (oss);
+ oss<<" source port: "<<tcpHeader.GetSourcePort ();
+ NS_LOG_LOGIC (oss.str ());
+ return;
+ }
+ 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, source, tcpHeader.GetSourcePort ());
+}
+
+void
+TcpL4Protocol::Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport)
+{
+ NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
+
+ TcpHeader tcpHeader;
+ tcpHeader.SetDestinationPort (dport);
+ tcpHeader.SetSourcePort (sport);
+ tcpHeader.InitializeChecksum (saddr,
+ daddr,
+ PROT_NUMBER);
+ tcpHeader.SetFlags (TcpHeader::ACK);
+ tcpHeader.SetAckNumber (0);
+
+ packet->AddHeader (tcpHeader);
+
+ Ptr<Ipv4L3Protocol> ipv4 =
+ m_node->GetObject<Ipv4L3Protocol> ();
+ if (ipv4 != 0)
+ {
+ ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+ }
+}
+
+void
+TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
+ Ipv4Address saddr, Ipv4Address daddr)
+{
+ NS_LOG_LOGIC("TcpL4Protocol " << this
+ << " sending seq " << outgoingHeader.GetSequenceNumber()
+ << " ack " << outgoingHeader.GetAckNumber()
+ << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec
+ << " data size " << packet->GetSize());
+ NS_LOG_FUNCTION (this << packet << saddr << daddr);
+ // XXX outgoingHeader cannot be logged
+
+ outgoingHeader.SetLength (5); //header length in units of 32bit words
+ outgoingHeader.SetChecksum (0); //XXX
+ outgoingHeader.SetUrgentPointer (0); //XXX
+
+ packet->AddHeader (outgoingHeader);
+
+ Ptr<Ipv4L3Protocol> ipv4 =
+ m_node->GetObject<Ipv4L3Protocol> ();
+ if (ipv4 != 0)
+ {
+ ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+ }
+ else
+ NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
+}
+
+}; // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-l4-protocol.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_L4_PROTOCOL_H
+#define TCP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ns3/object-factory.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+
+#include "tcp-header.h"
+#include "tcp-typedefs.h"
+
+namespace ns3 {
+
+class Node;
+class Socket;
+class TcpHeader;
+/**
+ * \brief Implementation of the TCP protocol
+ */
+class TcpL4Protocol : public Ipv4L4Protocol {
+public:
+ static TypeId GetTypeId (void);
+ static const uint8_t PROT_NUMBER;
+ /**
+ * \brief Constructor
+ */
+ TcpL4Protocol ();
+ virtual ~TcpL4Protocol ();
+
+ void SetNode (Ptr<Node> node);
+
+ virtual int GetProtocolNumber (void) const;
+ virtual int GetVersion (void) const;
+
+ /**
+ * \return A smart Socket pointer to a TcpSocketImpl, allocated by this instance
+ * of the TCP protocol
+ */
+ Ptr<Socket> CreateSocket (void);
+
+ Ipv4EndPoint *Allocate (void);
+ Ipv4EndPoint *Allocate (Ipv4Address address);
+ Ipv4EndPoint *Allocate (uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort);
+
+ void DeAllocate (Ipv4EndPoint *endPoint);
+
+// // called by TcpSocketImpl.
+// bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr,
+// uint16_t sport, uint16_t dport);
+
+ /**
+ * \brief Send a packet via TCP
+ * \param packet The packet to send
+ * \param saddr The source Ipv4Address
+ * \param daddr The destination Ipv4Address
+ * \param sport The source port number
+ * \param dport The destination port number
+ */
+ void Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport);
+ /**
+ * \brief Recieve a packet up the protocol stack
+ * \param p The Packet to dump the contents into
+ * \param source The source's Ipv4Address
+ * \param destination The destinations Ipv4Address
+ * \param incomingInterface The Ipv4Interface it was received on
+ */
+ virtual void Receive (Ptr<Packet> p,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<Node> m_node;
+ Ipv4EndPointDemux *m_endPoints;
+ ObjectFactory m_rttFactory;
+private:
+ friend class TcpSocketImpl;
+ void SendPacket (Ptr<Packet>, TcpHeader,
+ Ipv4Address, Ipv4Address);
+ static ObjectFactory GetDefaultRttEstimatorFactory (void);
+};
+
+}; // namespace ns3
+
+#endif /* TCP_L4_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-socket-factory-impl.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,54 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#include "tcp-socket-factory-impl.h"
+#include "tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+TcpSocketFactoryImpl::TcpSocketFactoryImpl ()
+ : m_tcp (0)
+{}
+TcpSocketFactoryImpl::~TcpSocketFactoryImpl ()
+{
+ NS_ASSERT (m_tcp == 0);
+}
+
+void
+TcpSocketFactoryImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
+{
+ m_tcp = tcp;
+}
+
+Ptr<Socket>
+TcpSocketFactoryImpl::CreateSocket (void)
+{
+ return m_tcp->CreateSocket ();
+}
+
+void
+TcpSocketFactoryImpl::DoDispose (void)
+{
+ m_tcp = 0;
+ TcpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-socket-factory-impl.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_SOCKET_FACTORY_IMPL_H
+#define TCP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class TcpL4Protocol;
+
+/**
+ * \ingroup internetNode
+ * \defgroup Tcp Tcp
+ */
+/**
+ * \ingroup Tcp
+ * \section Tcp Overview
+ *
+ * The TCP code in ns3::InternetNode is ported from the
+ * <a href="http://www.ece.gatech.edu/research/labs/MANIACS/GTNetS/">
+ * Georgia Tech Network Simulator (GTNetS)</a>.
+ *
+ * Most of the logic is in class ns3::TcpSocketImpl.
+ */
+class TcpSocketFactoryImpl : public TcpSocketFactory
+{
+public:
+ TcpSocketFactoryImpl ();
+ virtual ~TcpSocketFactoryImpl ();
+
+ void SetTcp (Ptr<TcpL4Protocol> tcp);
+
+ virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<TcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* TCP_SOCKET_FACTORY_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-socket-impl.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,1448 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "tcp-socket-impl.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+#include "ns3/simulation-singleton.h"
+#include "tcp-typedefs.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("TcpSocketImpl");
+
+using namespace std;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpSocketImpl);
+
+TypeId
+TcpSocketImpl::GetTypeId ()
+{
+ static TypeId tid = TypeId("ns3::TcpSocketImpl")
+ .SetParent<TcpSocket> ()
+ .AddTraceSource ("CongestionWindow",
+ "The TCP connection's congestion window",
+ MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
+ ;
+ return tid;
+}
+
+ TcpSocketImpl::TcpSocketImpl ()
+ : m_skipRetxResched (false),
+ m_dupAckCount (0),
+ m_delAckCount (0),
+ m_endPoint (0),
+ m_node (0),
+ m_tcp (0),
+ m_errno (ERROR_NOTERROR),
+ m_shutdownSend (false),
+ m_shutdownRecv (false),
+ m_connected (false),
+ m_state (CLOSED),
+ m_closeNotified (false),
+ m_closeRequestNotified (false),
+ m_closeOnEmpty (false),
+ m_pendingClose (false),
+ m_nextTxSequence (0),
+ m_highTxMark (0),
+ m_highestRxAck (0),
+ m_lastRxAck (0),
+ m_nextRxSequence (0),
+ m_pendingData (0),
+ m_rtt (0),
+ m_lastMeasuredRtt (Seconds(0.0)),
+ m_rxAvailable (0),
+ m_wouldBlock (false)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock)
+ : TcpSocket(sock), //copy the base class callbacks
+ m_skipRetxResched (sock.m_skipRetxResched),
+ m_dupAckCount (sock.m_dupAckCount),
+ m_delAckCount (0),
+ m_delAckMaxCount (sock.m_delAckMaxCount),
+ m_delAckTimeout (sock.m_delAckTimeout),
+ m_endPoint (0),
+ m_node (sock.m_node),
+ m_tcp (sock.m_tcp),
+ m_remoteAddress (sock.m_remoteAddress),
+ m_remotePort (sock.m_remotePort),
+ m_localAddress (sock.m_localAddress),
+ m_localPort (sock.m_localPort),
+ m_errno (sock.m_errno),
+ m_shutdownSend (sock.m_shutdownSend),
+ m_shutdownRecv (sock.m_shutdownRecv),
+ m_connected (sock.m_connected),
+ m_state (sock.m_state),
+ m_closeNotified (sock.m_closeNotified),
+ m_closeRequestNotified (sock.m_closeRequestNotified),
+ m_closeOnEmpty (sock.m_closeOnEmpty),
+ m_pendingClose (sock.m_pendingClose),
+ m_nextTxSequence (sock.m_nextTxSequence),
+ m_highTxMark (sock.m_highTxMark),
+ m_highestRxAck (sock.m_highestRxAck),
+ m_lastRxAck (sock.m_lastRxAck),
+ m_nextRxSequence (sock.m_nextRxSequence),
+ m_pendingData (0),
+ m_segmentSize (sock.m_segmentSize),
+ m_rxWindowSize (sock.m_rxWindowSize),
+ m_advertisedWindowSize (sock.m_advertisedWindowSize),
+ m_cWnd (sock.m_cWnd),
+ m_ssThresh (sock.m_ssThresh),
+ m_initialCWnd (sock.m_initialCWnd),
+ m_rtt (0),
+ m_lastMeasuredRtt (Seconds(0.0)),
+ m_cnTimeout (sock.m_cnTimeout),
+ m_cnCount (sock.m_cnCount),
+ m_rxAvailable (0),
+ m_wouldBlock (false),
+ m_sndBufSize (sock.m_sndBufSize),
+ m_rcvBufSize(sock.m_rcvBufSize)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC("Invoked the copy constructor");
+ //copy the pending data if necessary
+ if(sock.m_pendingData)
+ {
+ m_pendingData = sock.m_pendingData->Copy();
+ }
+ //copy the rtt if necessary
+ if (sock.m_rtt)
+ {
+ m_rtt = sock.m_rtt->Copy();
+ }
+ //can't "copy" the endpoint just yes, must do this when we know the peer info
+ //too; this is in SYN_ACK_TX
+}
+
+TcpSocketImpl::~TcpSocketImpl ()
+{
+ NS_LOG_FUNCTION(this);
+ m_node = 0;
+ if (m_endPoint != 0)
+ {
+ NS_ASSERT (m_tcp != 0);
+ /**
+ * Note that this piece of code is a bit tricky:
+ * when DeAllocate is called, it will call into
+ * Ipv4EndPointDemux::Deallocate which triggers
+ * a delete of the associated endPoint which triggers
+ * in turn a call to the method ::Destroy below
+ * will will zero the m_endPoint field.
+ */
+ NS_ASSERT (m_endPoint != 0);
+ m_tcp->DeAllocate (m_endPoint);
+ NS_ASSERT (m_endPoint == 0);
+ }
+ m_tcp = 0;
+ delete m_pendingData; //prevents leak
+ m_pendingData = 0;
+}
+
+void
+TcpSocketImpl::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+ // Initialize some variables
+ m_cWnd = m_initialCWnd * m_segmentSize;
+ m_rxWindowSize = m_advertisedWindowSize;
+}
+
+void
+TcpSocketImpl::SetTcp (Ptr<TcpL4Protocol> tcp)
+{
+ m_tcp = tcp;
+}
+void
+TcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
+{
+ m_rtt = rtt;
+}
+
+
+enum Socket::SocketErrno
+TcpSocketImpl::GetErrno (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_errno;
+}
+
+Ptr<Node>
+TcpSocketImpl::GetNode (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+TcpSocketImpl::Destroy (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = 0;
+ m_endPoint = 0;
+ m_tcp = 0;
+ m_retxEvent.Cancel ();
+}
+int
+TcpSocketImpl::FinishBind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoint == 0)
+ {
+ return -1;
+ }
+ m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
+ m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
+ m_localAddress = m_endPoint->GetLocalAddress ();
+ m_localPort = m_endPoint->GetLocalPort ();
+ return 0;
+}
+
+int
+TcpSocketImpl::Bind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_endPoint = m_tcp->Allocate ();
+ return FinishBind ();
+}
+int
+TcpSocketImpl::Bind (const Address &address)
+{
+ NS_LOG_FUNCTION (this<<address);
+ if (!InetSocketAddress::IsMatchingType (address))
+ {
+ return ERROR_INVAL;
+ }
+ 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 ();
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (port);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4, port);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+
+ return FinishBind ();
+}
+
+int
+TcpSocketImpl::ShutdownSend (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownSend = true;
+ return 0;
+}
+int
+TcpSocketImpl::ShutdownRecv (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownRecv = false;
+ return 0;
+}
+
+int
+TcpSocketImpl::Close (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_state == CLOSED)
+ {
+ return -1;
+ }
+ if (m_pendingData && m_pendingData->Size() != 0)
+ { // App close with pending data must wait until all data transmitted
+ m_closeOnEmpty = true;
+ NS_LOG_LOGIC("Socket " << this <<
+ " deferring close, state " << m_state);
+ return 0;
+ }
+
+ Actions_t action = ProcessEvent (APP_CLOSE);
+ ProcessAction (action);
+ ShutdownSend ();
+ return 0;
+}
+
+int
+TcpSocketImpl::Connect (const Address & address)
+{
+ NS_LOG_FUNCTION (this << address);
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ m_remoteAddress = transport.GetIpv4 ();
+ m_remotePort = transport.GetPort ();
+
+ uint32_t localIfIndex;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
+ {
+ m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
+ }
+ else
+ {
+ m_errno = ERROR_NOROUTETOHOST;
+ return -1;
+ }
+
+ Actions_t action = ProcessEvent (APP_CONNECT);
+ bool success = ProcessAction (action);
+ if (success)
+ {
+ return 0;
+ }
+ return -1;
+}
+int
+TcpSocketImpl::Send (const Ptr<Packet> p) //p here is just data, no headers
+{
+ NS_LOG_FUNCTION (this << p);
+ if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+ {
+ if (p->GetSize() > GetTxAvailable ())
+ {
+ m_wouldBlock = true;
+ m_errno = ERROR_MSGSIZE;
+ return -1;
+ }
+ if (!m_pendingData)
+ {
+ m_pendingData = new PendingData (); // Create if non-existent
+ m_firstPendingSequence = m_nextTxSequence; // Note seq of first
+ }
+ //PendingData::Add stores a copy of the Ptr p
+ m_pendingData->Add (p);
+ NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() <<
+ " state " << m_state);
+ Actions_t action = ProcessEvent (APP_SEND);
+ NS_LOG_DEBUG(" action " << action);
+ if (!ProcessAction (action))
+ {
+ return -1; // Failed, return zero
+ }
+ return p->GetSize();
+ }
+ else
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+}
+
+int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size)
+{
+ return Send (Create<Packet> (buf, size));
+}
+
+int TcpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+ NS_LOG_FUNCTION (this << p << address);
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ return DoSendTo (p, ipv4, port);
+}
+
+int TcpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << p << ipv4 << port);
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+ m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p->GetSize ());
+ return 0;
+}
+
+int
+TcpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
+{
+ NS_LOG_FUNCTION (this << address << p);
+ if (!m_connected)
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+ else
+ {
+ return Send (p); //drop the address according to BSD manpages
+ }
+}
+
+uint32_t
+TcpSocketImpl::GetTxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_pendingData != 0)
+ {
+ uint32_t unAckedDataSize =
+ m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck);
+ NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error
+ return m_sndBufSize-unAckedDataSize;
+ }
+ else
+ {
+ return m_sndBufSize;
+ }
+}
+
+int
+TcpSocketImpl::Listen (uint32_t q)
+{
+ NS_LOG_FUNCTION (this << q);
+ Actions_t action = ProcessEvent (APP_LISTEN);
+ ProcessAction (action);
+ return 0;
+}
+
+Ptr<Packet>
+TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if(m_bufferedData.empty())
+ {
+ return 0;
+ }
+ UnAckData_t out; //serves as buffer to return up to the user
+ UnAckData_t::iterator i;
+ while (!m_bufferedData.empty ())
+ { // Check the buffered data for delivery
+ NS_LOG_LOGIC("TCP " << this << " bufferedData.size() "
+ << m_bufferedData.size ()
+ << " time " << Simulator::Now ());
+ i = m_bufferedData.begin ();
+ SequenceNumber s1 = 0;
+ if (i->first > m_nextRxSequence)
+ {
+ break; // we're done, no more in-sequence data exits
+ }
+ else // (i->first <= m_nextRxSequence)
+ { // Two cases here.
+ // 1) seq + length > nextRxSeq, can deliver partial
+ // 2) seq + length <= nextRxSeq, deliver whole
+ s1 = i->second->GetSize ();
+ if (i->first + s1 > m_nextRxSequence)
+ { // Remove partial data to prepare for delivery
+ uint32_t avail = s1 + i->first - m_nextRxSequence;
+ i->second = i->second->CreateFragment (0, avail);
+ }
+ // else this packet is okay to deliver whole
+ // so don't do anything else and output it
+ out[i->first] = i->second;
+ }
+ m_rxAvailable -= i->second->GetSize ();
+ m_bufferedData.erase (i); // Remove from list
+ }
+ if (out.size() == 0)
+ {
+ return 0;
+ }
+ Ptr<Packet> outPacket = Create<Packet>();
+ for(i = out.begin(); i!=out.end(); ++i)
+ {
+ if (outPacket->GetSize() + i->second->GetSize() <= maxSize )
+ {
+ outPacket->AddAtEnd(i->second);
+ }
+ else
+ {
+ //only append as much as will fit
+ uint32_t avail = maxSize - outPacket->GetSize();
+ outPacket->AddAtEnd(i->second->CreateFragment(0,avail));
+ //put the rest back into the buffer
+ m_bufferedData[i->first+SequenceNumber(avail)]
+ = i->second->CreateFragment(avail,i->second->GetSize()-avail);
+ m_rxAvailable += i->second->GetSize()-avail;
+ }
+ }
+ return outPacket;
+}
+
+uint32_t
+TcpSocketImpl::GetRxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ // We separately maintain this state to avoid walking the queue
+ // every time this might be called
+ return m_rxAvailable;
+}
+
+void
+TcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+ NS_LOG_DEBUG("Socket " << this << " got forward up" <<
+ " dport " << m_endPoint->GetLocalPort() <<
+ " daddr " << m_endPoint->GetLocalAddress() <<
+ " sport " << m_endPoint->GetPeerPort() <<
+ " saddr " << m_endPoint->GetPeerAddress());
+
+ NS_LOG_FUNCTION (this << packet << ipv4 << port);
+ if (m_shutdownRecv)
+ {
+ return;
+ }
+ TcpHeader tcpHeader;
+ packet->RemoveHeader (tcpHeader);
+
+ if (tcpHeader.GetFlags () & TcpHeader::ACK)
+ {
+ Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
+ if (m != Seconds (0.0))
+ {
+ m_lastMeasuredRtt = m;
+ }
+ }
+
+ Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
+ Actions_t action = ProcessEvent (event); //updates the state
+ Address address = InetSocketAddress (ipv4, port);
+ NS_LOG_DEBUG("Socket " << this <<
+ " processing pkt action, " << action <<
+ " current state " << m_state);
+ ProcessPacketAction (action, packet, tcpHeader, address);
+}
+
+Actions_t TcpSocketImpl::ProcessEvent (Events_t e)
+{
+ NS_LOG_FUNCTION (this << e);
+ States_t saveState = m_state;
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " processing event " << e);
+ // simulation singleton is a way to get a single global static instance of a
+ // class intended to be a singleton; see simulation-singleton.h
+ SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
+ // debug
+ if (stateAction.action == RST_TX)
+ {
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " sending RST from state "
+ << saveState << " event " << e);
+ }
+ bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED
+ && e != TIMEOUT);
+ m_state = stateAction.state;
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " moved from state " << saveState
+ << " to state " <<m_state);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " pendingData " << m_pendingData);
+
+ //extra event logic is here for RX events
+ //e = SYN_ACK_RX
+ if (saveState == SYN_SENT && m_state == ESTABLISHED)
+ // this means the application side has completed its portion of
+ // the handshaking
+ {
+ Simulator::ScheduleNow(&TcpSocketImpl::ConnectionSucceeded, this);
+ //NotifyConnectionSucceeded ();
+ m_connected = true;
+ m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
+ }
+
+ if (needCloseNotify && !m_closeNotified)
+ {
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from "
+ << m_state << " event " << e << " closeNot " << m_closeNotified
+ << " action " << stateAction.action);
+ NotifyCloseCompleted ();
+ m_closeNotified = true;
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " calling Closed from PE"
+ << " origState " << saveState
+ << " event " << e);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from "
+ << m_state << " event " << e
+ << " set CloseNotif ");
+ }
+ return stateAction.action;
+}
+
+void TcpSocketImpl::SendEmptyPacket (uint8_t flags)
+{
+ NS_LOG_FUNCTION (this << flags);
+ Ptr<Packet> p = Create<Packet> ();
+ TcpHeader header;
+
+ header.SetFlags (flags);
+ header.SetSequenceNumber (m_nextTxSequence);
+ header.SetAckNumber (m_nextRxSequence);
+ header.SetSourcePort (m_endPoint->GetLocalPort ());
+ header.SetDestinationPort (m_remotePort);
+ header.SetWindowSize (m_advertisedWindowSize);
+ m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
+ m_remoteAddress);
+ Time rto = m_rtt->RetransmitTimeout ();
+ if (flags & TcpHeader::SYN)
+ {
+ rto = m_cnTimeout;
+ m_cnTimeout = m_cnTimeout + m_cnTimeout;
+ m_cnCount--;
+ }
+ if (m_retxEvent.IsExpired () ) //no outstanding timer
+ {
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+ << Simulator::Now ().GetSeconds () << " to expire at time "
+ << (Simulator::Now () + rto).GetSeconds ());
+ m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this);
+ }
+}
+
+bool TcpSocketImpl::ProcessAction (Actions_t a)
+{ // These actions do not require a packet or any TCP Headers
+ NS_LOG_FUNCTION (this << a);
+ switch (a)
+ {
+ case NO_ACT:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT");
+ break;
+ case ACK_TX:
+ SendEmptyPacket (TcpHeader::ACK);
+ break;
+ case ACK_TX_1:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case RST_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RST_TX");
+ SendEmptyPacket (TcpHeader::RST);
+ break;
+ case SYN_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_TX");
+ // TCP SYN Flag consumes one byte
+ // is the above correct? we're SENDING a syn, not acking back -- Raj
+ // commented out for now
+ // m_nextTxSequence+= 1;
+ SendEmptyPacket (TcpHeader::SYN);
+ break;
+ case SYN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
+ // TCP SYN Flag consumes one byte
+ ++m_nextRxSequence;
+ SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+ break;
+ case FIN_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_TX");
+ SendEmptyPacket (TcpHeader::FIN);
+ break;
+ case FIN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_ACK_TX");
+ SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+ break;
+ case NEW_ACK:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case NEW_SEQ_RX:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case RETX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RETX");
+ break;
+ case TX_DATA:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action TX_DATA");
+ SendPendingData ();
+ break;
+ case PEER_CLOSE:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action PEER_CLOSE");
+ break;
+ case APP_CLOSED:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_CLOSED");
+ break;
+ case CANCEL_TM:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action CANCEL_TM");
+ break;
+ case APP_NOTIFY:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_NOTIFY");
+ break;
+ case SERV_NOTIFY:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case LAST_ACTION:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action LAST_ACTION");
+ break;
+ }
+ return true;
+}
+
+bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress)
+{
+ NS_LOG_FUNCTION (this << a << p << fromAddress);
+ uint32_t localIfIndex;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+ switch (a)
+ {
+ case SYN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
+// m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+// m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+// if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
+// {
+// m_localAddress = ipv4->GetAddress (localIfIndex);
+// }
+ if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl
+ {
+ NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
+ //notify the server that we got a SYN
+ // If server refuses connection do nothing
+ if (!NotifyConnectionRequest(fromAddress)) return true;
+ // Clone the socket
+ Ptr<TcpSocketImpl> newSock = Copy ();
+ NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock);
+ //this listening socket should do nothing more
+ Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock,
+ p, tcpHeader,fromAddress);
+ return true;
+ }
+ // This is the cloned endpoint
+ m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+ if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
+ {
+ m_localAddress = ipv4->GetAddress (localIfIndex);
+ m_endPoint->SetLocalAddress (m_localAddress);
+ // Leave local addr in the portmap to any, as the path from
+ // remote can change and packets can arrive on different interfaces
+ //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
+ }
+ // TCP SYN consumes one byte
+ m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
+ SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+ break;
+ case ACK_TX_1:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1");
+ // TCP SYN consumes one byte
+ m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
+ m_nextTxSequence = tcpHeader.GetAckNumber ();
+ m_firstPendingSequence = m_nextTxSequence; //bug 166
+ NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" <<
+ " nextRxSeq " << m_nextRxSequence);
+ SendEmptyPacket (TcpHeader::ACK);
+ m_rxWindowSize = tcpHeader.GetWindowSize ();
+ if (tcpHeader.GetAckNumber () > m_highestRxAck)
+ {
+ m_highestRxAck = tcpHeader.GetAckNumber ();
+ // Data freed from the send buffer; notify any blocked sender
+ if (m_wouldBlock)
+ {
+ NotifySend (GetTxAvailable ());
+ m_wouldBlock = false;
+ }
+ }
+ SendPendingData ();
+ break;
+ case NEW_ACK:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_ACK_TX");
+ if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
+ {
+ break;
+ }
+ if (tcpHeader.GetAckNumber () == m_highestRxAck &&
+ tcpHeader.GetAckNumber () < m_nextTxSequence)
+ {
+ DupAck (tcpHeader, ++m_dupAckCount);
+ break;
+ }
+ if (tcpHeader.GetAckNumber () > m_highestRxAck)
+ {
+ m_dupAckCount = 0;
+ }
+ NewAck (tcpHeader.GetAckNumber ());
+ break;
+ case NEW_SEQ_RX:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX");
+ NewRx (p, tcpHeader, fromAddress); // Process new data received
+ break;
+ case PEER_CLOSE:
+ {
+ // First we have to be sure the FIN packet was not received
+ // out of sequence. If so, note pending close and process
+ // new sequence rx
+ if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
+ { // process close later
+ m_pendingClose = true;
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose"
+ << " rxseq " << tcpHeader.GetSequenceNumber ()
+ << " nextRxSeq " << m_nextRxSequence);
+ NewRx (p, tcpHeader, fromAddress);
+ return true;
+ }
+ // Now we need to see if any data came with the FIN
+ // if so, call NewRx
+ if (p->GetSize () != 0)
+ {
+ NewRx (p, tcpHeader, fromAddress);
+ }
+ States_t saveState = m_state; // Used to see if app responds
+ NS_LOG_LOGIC ("TcpSocketImpl " << this
+ << " peer close, state " << m_state);
+ if (!m_closeRequestNotified)
+ {
+ NS_LOG_LOGIC ("TCP " << this
+ << " calling AppCloseRequest");
+ NotifyCloseRequested();
+ m_closeRequestNotified = true;
+ }
+ NS_LOG_LOGIC ("TcpSocketImpl " << this
+ << " peer close, state after " << m_state);
+ if (m_state == saveState)
+ { // Need to ack, the application will close later
+ SendEmptyPacket (TcpHeader::ACK);
+// // Also need to re-tx the ack if we
+ }
+ if (m_state == LAST_ACK)
+ {
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " scheduling LATO1");
+ m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
+ &TcpSocketImpl::LastAckTimeout,this);
+ }
+ break;
+ }
+ case SERV_NOTIFY:
+ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY");
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!");
+ NotifyNewConnectionCreated (this, fromAddress);
+ m_connected = true; // ! This is bogus; fix when we clone the tcp
+ m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+ //treat the connection orientation final ack as a newack
+ CommonNewAck (tcpHeader.GetAckNumber (), true);
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+void TcpSocketImpl::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
+{
+ // Get port and address from peer (connecting host)
+ m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+ m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+ m_endPoint = m_tcp->Allocate (m_localAddress,
+ m_localPort,
+ m_remoteAddress,
+ m_remotePort);
+ //the cloned socket with be in listen state, so manually change state
+ m_state = SYN_RCVD;
+ //equivalent to FinishBind
+ m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr<TcpSocketImpl>(this)));
+ m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr<TcpSocketImpl>(this)));
+ ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
+ }
+
+void TcpSocketImpl::ConnectionSucceeded()
+{ // We would preferred to have scheduled an event directly to
+ // NotifyConnectionSucceeded, but (sigh) these are protected
+ // and we can get the address of it :(
+ NotifyConnectionSucceeded();
+}
+
+bool TcpSocketImpl::SendPendingData (bool withAck)
+{
+ NS_LOG_FUNCTION (this << withAck);
+ NS_LOG_LOGIC ("ENTERING SendPendingData");
+ if (!m_pendingData)
+ {
+ return false; // No data exists
+ }
+ uint32_t nPacketsSent = 0;
+ while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
+ {
+ uint32_t w = AvailableWindow ();// Get available window size
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " SendPendingData"
+ << " w " << w
+ << " rxwin " << m_rxWindowSize
+ << " cWnd " << m_cWnd
+ << " segsize " << m_segmentSize
+ << " nextTxSeq " << m_nextTxSequence
+ << " highestRxAck " << m_highestRxAck
+ << " pd->Size " << m_pendingData->Size ()
+ << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
+
+ if (w < m_segmentSize && m_pendingData->Size () > w)
+ {
+ break; // No more
+ }
+ uint32_t s = std::min (w, m_segmentSize); // Send no more than window
+ Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence,
+ m_nextTxSequence);
+ NS_LOG_LOGIC("TcpSocketImpl " << this << " SendPendingData"
+ << " txseq " << m_nextTxSequence
+ << " s " << s
+ << " datasize " << p->GetSize() );
+ uint8_t flags = 0;
+ if (withAck)
+ {
+ flags |= TcpHeader::ACK;
+ }
+ uint32_t sz = p->GetSize (); // Size of packet
+ uint32_t remainingData = m_pendingData->SizeFromSeq(
+ m_firstPendingSequence,
+ m_nextTxSequence + SequenceNumber (sz));
+ if (m_closeOnEmpty && (remainingData == 0))
+ {
+ flags = TcpHeader::FIN;
+ m_state = FIN_WAIT_1;
+ }
+
+ TcpHeader header;
+ header.SetFlags (flags);
+ header.SetSequenceNumber (m_nextTxSequence);
+ header.SetAckNumber (m_nextRxSequence);
+ header.SetSourcePort (m_endPoint->GetLocalPort());
+ header.SetDestinationPort (m_remotePort);
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+
+
+ if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
+ {
+ Time rto = m_rtt->RetransmitTimeout ();
+ NS_LOG_LOGIC ("SendPendingData Schedule retransmission timeout at time " <<
+ Simulator::Now ().GetSeconds () << " to expire at time " <<
+ (Simulator::Now () + rto).GetSeconds () );
+ m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this);
+ }
+ NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
+ m_tcp->SendPacket (p, header,
+ m_endPoint->GetLocalAddress (),
+ m_remoteAddress);
+ m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT
+ // Notify the application
+ Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, p->GetSize ());
+ nPacketsSent++; // Count sent this loop
+ m_nextTxSequence += sz; // Advance next tx sequence
+ // Note the high water mark
+ m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
+ }
+ NS_LOG_LOGIC ("SendPendingData Sent "<<nPacketsSent<<" packets");
+ NS_LOG_LOGIC("RETURN SendPendingData");
+ return (nPacketsSent>0);
+}
+
+uint32_t TcpSocketImpl::UnAckDataCount ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_nextTxSequence - m_highestRxAck;
+}
+
+uint32_t TcpSocketImpl::BytesInFlight ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_highTxMark - m_highestRxAck;
+}
+
+uint32_t TcpSocketImpl::Window ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC ("TcpSocketImpl::Window() "<<this);
+ return std::min (m_rxWindowSize, m_cWnd.Get());
+}
+
+uint32_t TcpSocketImpl::AvailableWindow ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
+ uint32_t win = Window ();
+ if (win < unack)
+ {
+ return 0; // No space available
+ }
+ return (win - unack); // Amount of window space available
+}
+
+void TcpSocketImpl::NewRx (Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress)
+{
+ NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx,"
+ << " seq " << tcpHeader.GetSequenceNumber()
+ << " ack " << tcpHeader.GetAckNumber()
+ << " p.size is " << p->GetSize () );
+ NS_LOG_DEBUG ("TcpSocketImpl " << this <<
+ " NewRx," <<
+ " seq " << tcpHeader.GetSequenceNumber() <<
+ " ack " << tcpHeader.GetAckNumber() <<
+ " p.size is " << p->GetSize());
+ States_t origState = m_state;
+ uint32_t s = p->GetSize (); // Size of associated data
+ if (s == 0)
+ {// Nothing to do if no associated data
+ return;
+ }
+ // Log sequence received if enabled
+ // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
+ // Three possibilities
+ // 1) Received seq is expected, buffer this, update rxAvailable, and ack
+ // 2) Received seq is < expected, just re-ack previous
+ // 3) Received seq is > expected, just re-ack previous and buffer data
+ if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
+ { // If seq is expected seq
+ // 1) Update nextRxSeq
+ // 2) Buffer this packet so Recv can read it
+ // 3) Send the ack
+ m_nextRxSequence += s; // Advance next expected sequence
+ //bytesReceived += s; // Statistics
+ NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
+ SocketRxAddressTag tag;
+ tag.SetAddress (fromAddress);
+ p->AddTag (tag);
+ //buffer this, it'll be read by call to Recv
+ UnAckData_t::iterator i =
+ m_bufferedData.find (tcpHeader.GetSequenceNumber () );
+ if (i != m_bufferedData.end () ) //we found it already in the buffer
+ {
+ i->second = 0; // relase reference to already buffered
+ }
+ // Save for later delivery
+ m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
+ m_rxAvailable += p->GetSize ();
+ //putting this into the buffer might have filled in a sequence gap
+ //so we have to iterate through the list to find the largest contiguous
+ //sequenced chunk, and update m_rxAvailable appropriately
+ i = m_bufferedData.find (tcpHeader.GetSequenceNumber () );
+ UnAckData_t::iterator next = i;
+ next++;
+ while(next != m_bufferedData.end())
+ {
+ if(i->first + SequenceNumber(i->second->GetSize ()) == next->first)
+ {
+ //next packet is in sequence, count it
+ m_rxAvailable += next->second->GetSize();
+ m_nextRxSequence += next->second->GetSize();
+ }
+ else
+ {
+ break; //no more in this contiguous chunk
+ }
+ ++i;
+ ++next;
+ }
+ NotifyDataRecv ();
+ if (m_closeNotified)
+ {
+ NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
+ }
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " adv rxseq by " << s);
+ if (m_pendingClose || (origState > ESTABLISHED))
+ { // See if we can close now
+ if (m_bufferedData.empty())
+ {
+ ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
+ }
+ }
+ }
+ else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
+ { // Need to buffer this one
+ NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
+ UnAckData_t::iterator i =
+ m_bufferedData.find (tcpHeader.GetSequenceNumber () );
+ if (i != m_bufferedData.end () )
+ {
+ i->second = 0; // relase reference to already buffered
+ }
+ // Save for later delivery
+ SocketRxAddressTag tag;
+ tag.SetAddress (fromAddress);
+ p->AddTag (tag);
+ m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
+ }
+ else
+ { // debug
+ NS_LOG_LOGIC("TCP " << this
+ << " got seq " << tcpHeader.GetSequenceNumber ()
+ << " expected " << m_nextRxSequence
+ << " flags " << tcpHeader.GetFlags ());
+ }
+ // Now send a new ack packet acknowledging all received and delivered data
+ if(++m_delAckCount >= m_delAckMaxCount)
+ {
+ m_delAckEvent.Cancel();
+ m_delAckCount = 0;
+ SendEmptyPacket (TcpHeader::ACK);
+ }
+ else
+ {
+ m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketImpl::DelAckTimeout, this);
+ }
+}
+
+void TcpSocketImpl::DelAckTimeout ()
+{
+ m_delAckCount = 0;
+ SendEmptyPacket (TcpHeader::ACK);
+}
+
+void TcpSocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer)
+{ // CommonNewAck is called only for "New" (non-duplicate) acks
+ // and MUST be called by any subclass, from the NewAck function
+ // Always cancel any pending re-tx timer on new acknowledgement
+ NS_LOG_FUNCTION (this << ack << skipTimer);
+ //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
+ if (!skipTimer)
+ {
+ m_retxEvent.Cancel ();
+ //On recieving a "New" ack we restart retransmission timer .. RFC 2988
+ Time rto = m_rtt->RetransmitTimeout ();
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+ << Simulator::Now ().GetSeconds () << " to expire at time "
+ << (Simulator::Now () + rto).GetSeconds ());
+ m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this);
+ }
+ NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack
+ << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
+ m_highestRxAck = ack; // Note the highest recieved Ack
+ if (m_wouldBlock)
+ {
+ // m_highestRxAck advancing means some data was acked, and the size
+ // of free space in the buffer has increased
+ NotifySend (GetTxAvailable ());
+ m_wouldBlock = false;
+ }
+ if (ack > m_nextTxSequence)
+ {
+ m_nextTxSequence = ack; // If advanced
+ }
+ // See if all pending ack'ed; if so we can delete the data
+ if (m_pendingData)
+ { // Data exists, see if can be deleted
+ if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
+ { // All pending acked, can be deleted
+ m_pendingData->Clear ();
+ delete m_pendingData;
+ m_pendingData = 0;
+ // Insure no re-tx timer
+ m_retxEvent.Cancel ();
+ }
+ }
+ // Try to send more data
+ SendPendingData();
+}
+
+Ptr<TcpSocketImpl> TcpSocketImpl::Copy ()
+{
+ return CopyObject<TcpSocketImpl> (this);
+}
+
+void TcpSocketImpl::NewAck (SequenceNumber seq)
+{ // New acknowledgement up to sequence number "seq"
+ // Adjust congestion window in response to new ack's received
+ NS_LOG_FUNCTION (this << seq);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewAck "
+ << " seq " << seq
+ << " cWnd " << m_cWnd
+ << " ssThresh " << m_ssThresh);
+ if (m_cWnd < m_ssThresh)
+ { // Slow start mode, add one segSize to cWnd
+ m_cWnd += m_segmentSize;
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewCWnd SlowStart, cWnd " << m_cWnd
+ << " sst " << m_ssThresh);
+ }
+ else
+ { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
+ double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd.Get();
+ if (adder < 1.0)
+ {
+ adder = 1.0;
+ }
+ m_cWnd += (uint32_t) adder;
+ NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd
+ << " sst " << m_ssThresh);
+ }
+ CommonNewAck (seq, false); // Complete newAck processing
+}
+
+void TcpSocketImpl::DupAck (const TcpHeader& t, uint32_t count)
+{
+ NS_LOG_FUNCTION (this << "t " << count);
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " DupAck " << t.GetAckNumber ()
+ << ", count " << count
+ << ", time " << Simulator::Now ());
+ if (count == 3)
+ { // Count of three indicates triple duplicate ack
+ m_ssThresh = Window () / 2; // Per RFC2581
+ m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+ NS_LOG_LOGIC("TcpSocketImpl " << this << "Tahoe TDA, time " << Simulator::Now ()
+ << " seq " << t.GetAckNumber ()
+ << " in flight " << BytesInFlight ()
+ << " new ssthresh " << m_ssThresh);
+
+ m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
+ // For Tahoe, we also reset nextTxSeq
+ m_nextTxSequence = m_highestRxAck;
+ SendPendingData ();
+ }
+}
+
+void TcpSocketImpl::ReTxTimeout ()
+{ // Retransmit timeout
+ NS_LOG_FUNCTION (this);
+ m_ssThresh = Window () / 2; // Per RFC2581
+ m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+ // Set cWnd to segSize on timeout, per rfc2581
+ // Collapse congestion window (re-enter slowstart)
+ m_cWnd = m_segmentSize;
+ m_nextTxSequence = m_highestRxAck; // Start from highest Ack
+ m_rtt->IncreaseMultiplier (); // DoubleValue timeout value for next retx timer
+ Retransmit (); // Retransmit the packet
+}
+
+void TcpSocketImpl::LastAckTimeout ()
+{
+ m_lastAckEvent.Cancel ();
+ if (m_state == LAST_ACK)
+ {
+ Actions_t action = ProcessEvent (TIMEOUT);
+ ProcessAction (action);
+ }
+ if (!m_closeNotified)
+ {
+ m_closeNotified = true;
+ }
+}
+
+void TcpSocketImpl::Retransmit ()
+{
+ NS_LOG_FUNCTION (this);
+ uint8_t flags = TcpHeader::NONE;
+ if (m_state == SYN_SENT)
+ {
+ if (m_cnCount > 0)
+ {
+ SendEmptyPacket (TcpHeader::SYN);
+ return;
+ }
+ else
+ {
+ NotifyConnectionFailed ();
+ return;
+ }
+ }
+ if (!m_pendingData)
+ {
+ if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
+ { // Must have lost FIN, re-send
+ SendEmptyPacket (TcpHeader::FIN);
+ }
+ return;
+ }
+ Ptr<Packet> p = m_pendingData->CopyFromSeq (m_segmentSize,
+ m_firstPendingSequence,
+ m_highestRxAck);
+ // Calculate remaining data for COE check
+ uint32_t remainingData = m_pendingData->SizeFromSeq (
+ m_firstPendingSequence,
+ m_nextTxSequence + SequenceNumber(p->GetSize ()));
+ if (m_closeOnEmpty && remainingData == 0)
+ { // Add the FIN flag
+ flags = flags | TcpHeader::FIN;
+ }
+
+ NS_LOG_LOGIC ("TcpSocketImpl " << this << " retxing seq " << m_highestRxAck);
+ if (m_retxEvent.IsExpired () )
+ {
+ Time rto = m_rtt->RetransmitTimeout ();
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+ << Simulator::Now ().GetSeconds () << " to expire at time "
+ << (Simulator::Now () + rto).GetSeconds ());
+ m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this);
+ }
+ m_rtt->SentSeq (m_highestRxAck,p->GetSize ());
+ // And send the packet
+ TcpHeader tcpHeader;
+ tcpHeader.SetSequenceNumber (m_nextTxSequence);
+ tcpHeader.SetAckNumber (m_nextRxSequence);
+ tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
+ tcpHeader.SetDestinationPort (m_remotePort);
+ tcpHeader.SetFlags (flags);
+ tcpHeader.SetWindowSize (m_advertisedWindowSize);
+
+ m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
+ m_remoteAddress);
+}
+
+void
+TcpSocketImpl::SetSndBufSize (uint32_t size)
+{
+ m_sndBufSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetSndBufSize (void) const
+{
+ return m_sndBufSize;
+}
+
+void
+TcpSocketImpl::SetRcvBufSize (uint32_t size)
+{
+ m_rcvBufSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetRcvBufSize (void) const
+{
+ return m_rcvBufSize;
+}
+
+void
+TcpSocketImpl::SetSegSize (uint32_t size)
+{
+ m_segmentSize = size;
+}
+
+uint32_t
+TcpSocketImpl::GetSegSize (void) const
+{
+ return m_segmentSize;
+}
+
+void
+TcpSocketImpl::SetAdvWin (uint32_t window)
+{
+ m_advertisedWindowSize = window;
+}
+
+uint32_t
+TcpSocketImpl::GetAdvWin (void) const
+{
+ return m_advertisedWindowSize;
+}
+
+void
+TcpSocketImpl::SetSSThresh (uint32_t threshold)
+{
+ m_ssThresh = threshold;
+}
+
+uint32_t
+TcpSocketImpl::GetSSThresh (void) const
+{
+ return m_ssThresh;
+}
+
+void
+TcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
+{
+ m_initialCWnd = cwnd;
+}
+
+uint32_t
+TcpSocketImpl::GetInitialCwnd (void) const
+{
+ return m_initialCWnd;
+}
+
+void
+TcpSocketImpl::SetConnTimeout (Time timeout)
+{
+ m_cnTimeout = timeout;
+}
+
+Time
+TcpSocketImpl::GetConnTimeout (void) const
+{
+ return m_cnTimeout;
+}
+
+void
+TcpSocketImpl::SetConnCount (uint32_t count)
+{
+ m_cnCount = count;
+}
+
+uint32_t
+TcpSocketImpl::GetConnCount (void) const
+{
+ return m_cnCount;
+}
+
+void
+TcpSocketImpl::SetDelAckTimeout (Time timeout)
+{
+ m_delAckTimeout = timeout;
+}
+
+Time
+TcpSocketImpl::GetDelAckTimeout (void) const
+{
+ return m_delAckTimeout;
+}
+
+void
+TcpSocketImpl::SetDelAckMaxCount (uint32_t count)
+{
+ m_delAckMaxCount = count;
+}
+
+uint32_t
+TcpSocketImpl::GetDelAckMaxCount (void) const
+{
+ return m_delAckMaxCount;
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-socket-impl.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_SOCKET_IMPL_H
+#define TCP_SOCKET_IMPL_H
+
+#include <stdint.h>
+#include <queue>
+#include "ns3/callback.h"
+#include "ns3/traced-value.h"
+#include "ns3/tcp-socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/event-id.h"
+#include "tcp-typedefs.h"
+#include "pending-data.h"
+#include "sequence-number.h"
+#include "rtt-estimator.h"
+
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class TcpL4Protocol;
+class TcpHeader;
+
+class TcpSocketImpl : public TcpSocket
+{
+public:
+ static TypeId GetTypeId (void);
+ /**
+ * Create an unbound tcp socket.
+ */
+ TcpSocketImpl ();
+ TcpSocketImpl (const TcpSocketImpl& sock);
+ virtual ~TcpSocketImpl ();
+
+ void SetNode (Ptr<Node> node);
+ void SetTcp (Ptr<TcpL4Protocol> tcp);
+ void SetRtt (Ptr<RttEstimator> rtt);
+
+ virtual enum SocketErrno GetErrno (void) const;
+ virtual Ptr<Node> GetNode (void) const;
+ virtual int Bind (void);
+ virtual int Bind (const Address &address);
+ virtual int Close (void);
+ virtual int ShutdownSend (void);
+ virtual int ShutdownRecv (void);
+ virtual int Connect(const Address &address);
+ virtual int Send (Ptr<Packet> p);
+ virtual int Send (const uint8_t* buf, uint32_t size);
+ virtual int SendTo(Ptr<Packet> p, const Address &address);
+ virtual uint32_t GetTxAvailable (void) const;
+ virtual int Listen(uint32_t queueLimit);
+
+ virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+ virtual uint32_t GetRxAvailable (void) const;
+
+private:
+ friend class Tcp;
+ // invoked by Tcp class
+ int FinishBind (void);
+ void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
+ void Destroy (void);
+ int DoSendTo (Ptr<Packet> p, const Address &daddr);
+ int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+ void SendEmptyPacket(uint8_t flags);
+ //methods for state
+ bool ProcessAction (Actions_t a);
+ bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader,
+ Ipv4Address saddr, Ipv4Address daddr);
+ bool ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress);
+ Actions_t ProcessEvent (Events_t e);
+ bool SendPendingData(bool withAck = false);
+ void CompleteFork(Ptr<Packet>, const TcpHeader&, const Address& fromAddress);
+ void ConnectionSucceeded();
+
+ //methods for window management
+ virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes
+ virtual uint32_t BytesInFlight(); // Return total bytes in flight
+ virtual uint32_t Window(); // Return window size (integer)
+ virtual uint32_t AvailableWindow();// Return unfilled portion of window
+
+ // Manage data tx/rx
+ void NewRx (Ptr<Packet>, const TcpHeader&, const Address&);
+ // XXX This should be virtual and overridden
+ Ptr<TcpSocketImpl> Copy ();
+ void NewAck (SequenceNumber seq);
+ // XXX This should be virtual and overridden
+ void DupAck (const TcpHeader& t, uint32_t count);
+ void ReTxTimeout ();
+ void DelAckTimeout ();
+ void LastAckTimeout ();
+ void Retransmit ();
+ void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
+
+ // attribute related
+ virtual void SetSndBufSize (uint32_t size);
+ virtual uint32_t GetSndBufSize (void) const;
+ virtual void SetRcvBufSize (uint32_t size);
+ virtual uint32_t GetRcvBufSize (void) const;
+ virtual void SetSegSize (uint32_t size);
+ virtual uint32_t GetSegSize (void) const;
+ virtual void SetAdvWin (uint32_t window);
+ virtual uint32_t GetAdvWin (void) const;
+ virtual void SetSSThresh (uint32_t threshold);
+ virtual uint32_t GetSSThresh (void) const;
+ virtual void SetInitialCwnd (uint32_t cwnd);
+ virtual uint32_t GetInitialCwnd (void) const;
+ virtual void SetConnTimeout (Time timeout);
+ virtual Time GetConnTimeout (void) const;
+ virtual void SetConnCount (uint32_t count);
+ virtual uint32_t GetConnCount (void) const;
+ virtual void SetDelAckTimeout (Time timeout);
+ virtual Time GetDelAckTimeout (void) const;
+ virtual void SetDelAckMaxCount (uint32_t count);
+ virtual uint32_t GetDelAckMaxCount (void) const;
+
+ bool m_skipRetxResched;
+ uint32_t m_dupAckCount;
+ EventId m_retxEvent;
+ EventId m_lastAckEvent;
+
+ EventId m_delAckEvent;
+ uint32_t m_delAckCount;
+ uint32_t m_delAckMaxCount;
+ Time m_delAckTimeout;
+
+ Ipv4EndPoint *m_endPoint;
+ Ptr<Node> m_node;
+ Ptr<TcpL4Protocol> m_tcp;
+ Ipv4Address m_remoteAddress;
+ uint16_t m_remotePort;
+ //these two are so that the socket/endpoint cloning works
+ Ipv4Address m_localAddress;
+ uint16_t m_localPort;
+ enum SocketErrno m_errno;
+ bool m_shutdownSend;
+ bool m_shutdownRecv;
+ bool m_connected;
+
+ //manage the state infomation
+ States_t m_state;
+ bool m_closeNotified;
+ bool m_closeRequestNotified;
+ bool m_closeOnEmpty;
+ bool m_pendingClose;
+
+
+ //sequence info, sender side
+ SequenceNumber m_nextTxSequence;
+ SequenceNumber m_highTxMark;
+ SequenceNumber m_highestRxAck;
+ SequenceNumber m_lastRxAck;
+
+ //sequence info, reciever side
+ SequenceNumber m_nextRxSequence;
+
+ //history data
+ //this is the incoming data buffer which sorts out of sequence data
+ UnAckData_t m_bufferedData;
+ //this is kind of the tx buffer
+ PendingData* m_pendingData;
+ SequenceNumber m_firstPendingSequence;
+
+ // Window management
+ uint32_t m_segmentSize; //SegmentSize
+ uint32_t m_rxWindowSize;
+ uint32_t m_advertisedWindowSize; //Window to advertise
+ TracedValue<uint32_t> m_cWnd; //Congestion window
+ uint32_t m_ssThresh; //Slow Start Threshold
+ uint32_t m_initialCWnd; //Initial cWnd value
+
+ // Round trip time estimation
+ Ptr<RttEstimator> m_rtt;
+ Time m_lastMeasuredRtt;
+
+ // Timer-related members
+ Time m_cnTimeout;
+ uint32_t m_cnCount;
+
+ // Temporary queue for delivering data to application
+ uint32_t m_rxAvailable;
+
+ bool m_wouldBlock; // set to true whenever socket would block on send()
+
+ // Attributes
+ uint32_t m_sndBufSize; // buffer limit for the outgoing queue
+ uint32_t m_rcvBufSize; // maximum receive socket buffer size
+};
+
+}//namespace ns3
+
+#endif /* TCP_SOCKET_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-typedefs.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ * typedefs for tcp state machine
+ */
+
+#include <vector>
+#include <map>
+#include "sequence-number.h"
+
+#ifndef TCP_TYPEDEFS_H
+#define TCP_TYPEDEFS_H
+
+namespace ns3 {
+
+typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t; // Flags are 6 bits
+
+typedef enum {
+ CLOSED, // 0
+ LISTEN, // 1
+ SYN_SENT, // 2
+ SYN_RCVD, // 3
+ ESTABLISHED, // 4
+ CLOSE_WAIT, // 5
+ LAST_ACK, // 6
+ FIN_WAIT_1, // 7
+ FIN_WAIT_2, // 8
+ CLOSING, // 9
+ TIMED_WAIT, // 10
+ LAST_STATE } States_t;
+
+typedef enum {
+ APP_LISTEN, // 0
+ APP_CONNECT, // 1
+ APP_SEND, // 2
+ SEQ_RECV, // 3
+ APP_CLOSE, // 4
+ TIMEOUT, // 5
+ ACK_RX, // 6
+ SYN_RX, // 7
+ SYN_ACK_RX, // 8
+ FIN_RX, // 9
+ FIN_ACK_RX, // 10
+ RST_RX, // 11
+ BAD_FLAGS, // 12
+ LAST_EVENT } Events_t;
+
+typedef enum {
+ NO_ACT, // 0
+ ACK_TX, // 1
+ ACK_TX_1, // ACK response to syn
+ RST_TX, // 2
+ SYN_TX, // 3
+ SYN_ACK_TX, // 4
+ FIN_TX, // 5
+ FIN_ACK_TX, // 6
+ NEW_ACK, // 7
+ NEW_SEQ_RX, // 8
+ RETX, // 9
+ TX_DATA, // 10
+ PEER_CLOSE, // 11
+ APP_CLOSED, // 12
+ CANCEL_TM, // 13
+ APP_NOTIFY, // 14 - Notify app that connection failed
+ SERV_NOTIFY, // 15 - Notify server tcp that connection completed
+ LAST_ACTION } Actions_t;
+
+class SA // State/Action pair
+{
+public:
+ SA () : state (LAST_STATE), action (LAST_ACTION) { }
+ SA (States_t s, Actions_t a) : state (s), action (a) { }
+public:
+ States_t state;
+ Actions_t action;
+};
+typedef std::vector<SA> StateActionVec_t;
+typedef std::vector<StateActionVec_t> StateActions_t; // One per current state
+typedef std::vector<Events_t> EventVec_t; // For flag events lookup
+
+//type for managing buffered out of sequence data
+typedef std::map<SequenceNumber, Ptr<Packet> > UnAckData_t;
+
+class TcpStateMachine {
+ public:
+ TcpStateMachine ();
+ SA Lookup (States_t, Events_t);
+ Events_t FlagsEvent (uint8_t); // Lookup event from flags
+
+ public:
+ StateActions_t aT; // Action table
+ EventVec_t eV; // Flags event lookup
+};
+
+}//namespace ns3
+#endif //TCP_TYPEDEFS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-header.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "udp-header.h"
+#include "ipv4-checksum.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (UdpHeader);
+
+bool UdpHeader::m_calcChecksum = false;
+
+/* The magic values below are used only for debugging.
+ * They can be used to easily detect memory corruption
+ * problems so you can see the patterns in memory.
+ */
+UdpHeader::UdpHeader ()
+ : m_sourcePort (0xfffd),
+ m_destinationPort (0xfffd),
+ m_payloadSize (0xfffd),
+ m_initialChecksum (0)
+{}
+UdpHeader::~UdpHeader ()
+{
+ m_sourcePort = 0xfffe;
+ m_destinationPort = 0xfffe;
+ m_payloadSize = 0xfffe;
+}
+
+void
+UdpHeader::EnableChecksums (void)
+{
+ m_calcChecksum = true;
+}
+
+void
+UdpHeader::SetDestinationPort (uint16_t port)
+{
+ m_destinationPort = port;
+}
+void
+UdpHeader::SetSourcePort (uint16_t port)
+{
+ m_sourcePort = port;
+}
+uint16_t
+UdpHeader::GetSourcePort (void) const
+{
+ return m_sourcePort;
+}
+uint16_t
+UdpHeader::GetDestinationPort (void) const
+{
+ return m_destinationPort;
+}
+void
+UdpHeader::SetPayloadSize (uint16_t size)
+{
+ m_payloadSize = size;
+}
+void
+UdpHeader::InitializeChecksum (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol)
+{
+ uint8_t buf[12];
+ source.Serialize (buf);
+ destination.Serialize (buf+4);
+ buf[8] = 0;
+ buf[9] = protocol;
+ uint16_t udpLength = m_payloadSize + GetSerializedSize ();
+ buf[10] = udpLength >> 8;
+ buf[11] = udpLength & 0xff;
+
+ m_initialChecksum = Ipv4ChecksumCalculate (0, buf, 12);
+}
+
+TypeId
+UdpHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::UdpHeader")
+ .SetParent<Header> ()
+ .AddConstructor<UdpHeader> ()
+ ;
+ return tid;
+}
+TypeId
+UdpHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+void
+UdpHeader::Print (std::ostream &os) const
+{
+ os << "length: " << m_payloadSize + GetSerializedSize ()
+ << " "
+ << m_sourcePort << " > " << m_destinationPort
+ ;
+}
+
+uint32_t
+UdpHeader::GetSerializedSize (void) const
+{
+ return 8;
+}
+
+void
+UdpHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteHtonU16 (m_sourcePort);
+ i.WriteHtonU16 (m_destinationPort);
+ i.WriteHtonU16 (m_payloadSize + GetSerializedSize ());
+ i.WriteU16 (0);
+
+ if (m_calcChecksum)
+ {
+#if 0
+ //XXXX
+ uint16_t checksum = Ipv4ChecksumCalculate (m_initialChecksum,
+ buffer->PeekData (),
+ GetSerializedSize () + m_payloadSize);
+ checksum = Ipv4ChecksumComplete (checksum);
+ i = buffer->Begin ();
+ i.Next (6);
+ i.WriteU16 (checksum);
+#endif
+ }
+}
+uint32_t
+UdpHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_sourcePort = i.ReadNtohU16 ();
+ m_destinationPort = i.ReadNtohU16 ();
+ m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
+ if (m_calcChecksum)
+ {
+ // XXX verify checksum.
+ }
+ return GetSerializedSize ();
+}
+
+
+}; // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-header.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef UDP_HEADER_H
+#define UDP_HEADER_H
+
+#include <stdint.h>
+#include <string>
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+
+namespace ns3 {
+/**
+ * \brief Packet header for UDP packets
+ */
+class UdpHeader : public Header
+{
+public:
+
+ /**
+ * \brief Constructor
+ *
+ * Creates a null header
+ */
+ UdpHeader ();
+ ~UdpHeader ();
+
+ /**
+ * \brief Enable checksum calculation for UDP (XXX currently has no effect)
+ */
+ static void EnableChecksums (void);
+ /**
+ * \param port the destination port for this UdpHeader
+ */
+ void SetDestinationPort (uint16_t port);
+ /**
+ * \param port The source port for this UdpHeader
+ */
+ void SetSourcePort (uint16_t port);
+ /**
+ * \return The source port for this UdpHeader
+ */
+ uint16_t GetSourcePort (void) const;
+ /**
+ * \return the destination port for this UdpHeader
+ */
+ uint16_t GetDestinationPort (void) const;
+ /**
+ * \param size The payload size in bytes
+ */
+ void SetPayloadSize (uint16_t size);
+
+ /**
+ * \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 (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol);
+
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+ uint16_t m_sourcePort;
+ uint16_t m_destinationPort;
+ uint16_t m_payloadSize;
+ uint16_t m_initialChecksum;
+
+ static bool m_calcChecksum;
+};
+
+} // namespace ns3
+
+#endif /* UDP_HEADER */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-l4-protocol.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "udp-l4-protocol.h"
+#include "udp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "udp-socket-impl.h"
+
+NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol);
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
+
+TypeId
+UdpL4Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::UdpL4Protocol")
+ .SetParent<Ipv4L4Protocol> ()
+ .AddConstructor<UdpL4Protocol> ()
+ ;
+ return tid;
+}
+
+UdpL4Protocol::UdpL4Protocol ()
+ : m_endPoints (new Ipv4EndPointDemux ())
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+UdpL4Protocol::~UdpL4Protocol ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+UdpL4Protocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+}
+
+int
+UdpL4Protocol::GetProtocolNumber (void) const
+{
+ return PROT_NUMBER;
+}
+int
+UdpL4Protocol::GetVersion (void) const
+{
+ return 2;
+}
+
+
+void
+UdpL4Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoints != 0)
+ {
+ delete m_endPoints;
+ m_endPoints = 0;
+ }
+ m_node = 0;
+ Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+UdpL4Protocol::CreateSocket (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
+ socket->SetNode (m_node);
+ socket->SetUdp (this);
+ return socket;
+}
+
+Ipv4EndPoint *
+UdpL4Protocol::Allocate (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+UdpL4Protocol::Allocate (Ipv4Address address)
+{
+ NS_LOG_FUNCTION (this << address);
+ return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+UdpL4Protocol::Allocate (uint16_t port)
+{
+ NS_LOG_FUNCTION (this << port);
+ return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << address << port);
+ return m_endPoints->Allocate (address, port);
+}
+Ipv4EndPoint *
+UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort)
+{
+ NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+ return m_endPoints->Allocate (localAddress, localPort,
+ peerAddress, peerPort);
+}
+
+void
+UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+ NS_LOG_FUNCTION (this << endPoint);
+ m_endPoints->DeAllocate (endPoint);
+}
+
+void
+UdpL4Protocol::Receive(Ptr<Packet> packet,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> interface)
+{
+ NS_LOG_FUNCTION (this << packet << source << destination);
+
+ UdpHeader udpHeader;
+ packet->RemoveHeader (udpHeader);
+ Ipv4EndPointDemux::EndPoints endPoints =
+ m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (),
+ source, udpHeader.GetSourcePort (), interface);
+ for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+ endPoint != endPoints.end (); endPoint++)
+ {
+ (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ());
+ }
+}
+
+void
+UdpL4Protocol::Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport)
+{
+ NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
+
+ UdpHeader udpHeader;
+ udpHeader.SetDestinationPort (dport);
+ udpHeader.SetSourcePort (sport);
+ udpHeader.SetPayloadSize (packet->GetSize ());
+ udpHeader.InitializeChecksum (saddr,
+ daddr,
+ PROT_NUMBER);
+
+ packet->AddHeader (udpHeader);
+
+ Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+ if (ipv4 != 0)
+ {
+ NS_LOG_LOGIC ("Sending to IP");
+ ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+ }
+}
+
+
+}; // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-l4-protocol.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef UDP_L4_PROTOCOL_H
+#define UDP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+
+namespace ns3 {
+
+class Node;
+class Socket;
+/**
+ * \brief Implementation of the UDP protocol
+ */
+class UdpL4Protocol : public Ipv4L4Protocol {
+public:
+ static TypeId GetTypeId (void);
+ static const uint8_t PROT_NUMBER;
+
+ UdpL4Protocol ();
+ virtual ~UdpL4Protocol ();
+
+ void SetNode (Ptr<Node> node);
+
+ virtual int GetProtocolNumber (void) const;
+ virtual int GetVersion (void) const;
+
+ /**
+ * \return A smart Socket pointer to a UdpSocket, allocated by this instance
+ * of the UDP protocol
+ */
+ Ptr<Socket> CreateSocket (void);
+
+ Ipv4EndPoint *Allocate (void);
+ Ipv4EndPoint *Allocate (Ipv4Address address);
+ Ipv4EndPoint *Allocate (uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort);
+
+ void DeAllocate (Ipv4EndPoint *endPoint);
+
+ // called by UdpSocket.
+ /**
+ * \brief Send a packet via UDP
+ * \param packet The packet to send
+ * \param saddr The source Ipv4Address
+ * \param daddr The destination Ipv4Address
+ * \param sport The source port number
+ * \param dport The destination port number
+ */
+ void Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport);
+ /**
+ * \brief Receive a packet up the protocol stack
+ * \param p The Packet to dump the contents into
+ * \param source The source's Ipv4Address
+ * \param destination The destinations Ipv4Address
+ * \param interface the interface from which the packet is coming.
+ */
+ // inherited from Ipv4L4Protocol
+ virtual void Receive(Ptr<Packet> p,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> interface);
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<Node> m_node;
+ Ipv4EndPointDemux *m_endPoints;
+};
+
+}; // namespace ns3
+
+#endif /* UDP_L4_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-socket-factory-impl.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,54 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "udp-socket-factory-impl.h"
+#include "udp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+UdpSocketFactoryImpl::UdpSocketFactoryImpl ()
+ : m_udp (0)
+{}
+UdpSocketFactoryImpl::~UdpSocketFactoryImpl ()
+{
+ NS_ASSERT (m_udp == 0);
+}
+
+void
+UdpSocketFactoryImpl::SetUdp (Ptr<UdpL4Protocol> udp)
+{
+ m_udp = udp;
+}
+
+Ptr<Socket>
+UdpSocketFactoryImpl::CreateSocket (void)
+{
+ return m_udp->CreateSocket ();
+}
+
+void
+UdpSocketFactoryImpl::DoDispose (void)
+{
+ m_udp = 0;
+ UdpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-socket-factory-impl.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef UDP_SOCKET_FACTORY_IMPL_H
+#define UDP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/udp-socket-factory.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class UdpL4Protocol;
+
+/**
+ * \brief Object to create UDP socket instances
+ * \internal
+ *
+ * This class implements the API for creating UDP sockets.
+ * It is a socket factory (deriving from class SocketFactory).
+ */
+class UdpSocketFactoryImpl : public UdpSocketFactory
+{
+public:
+ UdpSocketFactoryImpl ();
+ virtual ~UdpSocketFactoryImpl ();
+
+ void SetUdp (Ptr<UdpL4Protocol> udp);
+
+ /**
+ * \brief Implements a method to create a Udp-based socket and return
+ * a base class smart pointer to the socket.
+ * \internal
+ *
+ * \return smart pointer to Socket
+ */
+ virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<UdpL4Protocol> m_udp;
+};
+
+} // namespace ns3
+
+#endif /* UDP_SOCKET_FACTORY_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-socket-impl.cc Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,694 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/ipv4.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/uinteger.h"
+#include "ns3/boolean.h"
+#include "udp-socket-impl.h"
+#include "udp-l4-protocol.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+
+NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
+
+namespace ns3 {
+
+static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
+
+// Add attributes generic to all UdpSockets to base class UdpSocket
+TypeId
+UdpSocketImpl::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::UdpSocketImpl")
+ .SetParent<UdpSocket> ()
+ .AddConstructor<UdpSocketImpl> ()
+ .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
+ MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
+ ;
+ return tid;
+}
+
+UdpSocketImpl::UdpSocketImpl ()
+ : m_endPoint (0),
+ m_node (0),
+ m_udp (0),
+ m_errno (ERROR_NOTERROR),
+ m_shutdownSend (false),
+ m_shutdownRecv (false),
+ m_connected (false),
+ m_rxAvailable (0)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+UdpSocketImpl::~UdpSocketImpl ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ m_node = 0;
+ if (m_endPoint != 0)
+ {
+ NS_ASSERT (m_udp != 0);
+ /**
+ * Note that this piece of code is a bit tricky:
+ * when DeAllocate is called, it will call into
+ * Ipv4EndPointDemux::Deallocate which triggers
+ * a delete of the associated endPoint which triggers
+ * in turn a call to the method ::Destroy below
+ * will will zero the m_endPoint field.
+ */
+ NS_ASSERT (m_endPoint != 0);
+ m_udp->DeAllocate (m_endPoint);
+ NS_ASSERT (m_endPoint == 0);
+ }
+ m_udp = 0;
+}
+
+void
+UdpSocketImpl::SetNode (Ptr<Node> node)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = node;
+
+}
+void
+UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_udp = udp;
+}
+
+
+enum Socket::SocketErrno
+UdpSocketImpl::GetErrno (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_errno;
+}
+
+Ptr<Node>
+UdpSocketImpl::GetNode (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+UdpSocketImpl::Destroy (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = 0;
+ m_endPoint = 0;
+ m_udp = 0;
+}
+
+int
+UdpSocketImpl::FinishBind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoint == 0)
+ {
+ return -1;
+ }
+ m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
+ m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
+ return 0;
+}
+
+int
+UdpSocketImpl::Bind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_endPoint = m_udp->Allocate ();
+ return FinishBind ();
+}
+
+int
+UdpSocketImpl::Bind (const Address &address)
+{
+ NS_LOG_FUNCTION (this << address);
+
+ if (!InetSocketAddress::IsMatchingType (address))
+ {
+ NS_LOG_ERROR ("Not IsMatchingType");
+ return ERROR_INVAL;
+ }
+ 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 ();
+}
+
+int
+UdpSocketImpl::ShutdownSend (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownSend = true;
+ return 0;
+}
+
+int
+UdpSocketImpl::ShutdownRecv (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownRecv = false;
+ return 0;
+}
+
+int
+UdpSocketImpl::Close(void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NotifyCloseCompleted ();
+ return 0;
+}
+
+int
+UdpSocketImpl::Connect(const Address & address)
+{
+ NS_LOG_FUNCTION (this << address);
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ m_defaultAddress = transport.GetIpv4 ();
+ m_defaultPort = transport.GetPort ();
+ NotifyConnectionSucceeded ();
+ m_connected = true;
+
+ return 0;
+}
+
+int
+UdpSocketImpl::Listen (uint32_t queueLimit)
+{
+ m_errno = Socket::ERROR_OPNOTSUPP;
+ return -1;
+}
+
+int
+UdpSocketImpl::Send (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << p);
+
+ if (!m_connected)
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+ return DoSend (p);
+}
+
+int
+UdpSocketImpl::DoSend (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+
+ return DoSendTo (p, m_defaultAddress, m_defaultPort);
+}
+
+int
+UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+ NS_LOG_FUNCTION (this << p << 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);
+ }
+ else
+ {
+ // connected UDP socket must use default addresses
+ NS_LOG_LOGIC ("Connected");
+ return DoSendTo (p, m_defaultAddress, m_defaultPort);
+ }
+}
+
+int
+UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << p << dest << port);
+
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+
+ if (p->GetSize () > GetTxAvailable () )
+ {
+ m_errno = ERROR_MSGSIZE;
+ return -1;
+ }
+
+ uint32_t localIfIndex;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ // 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
+ //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
+ if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
+ {
+ SocketIpTtlTag tag;
+ tag.SetTtl (m_ipMulticastTtl);
+ p->AddTag (tag);
+ }
+ else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
+ {
+ SocketIpTtlTag tag;
+ tag.SetTtl (m_ipTtl);
+ p->AddTag (tag);
+ }
+ //
+ // If dest is sent to the limited broadcast address (all ones),
+ // convert it to send a copy of the packet out of every interface
+ //
+ if (dest.IsBroadcast ())
+ {
+ NS_LOG_LOGIC ("Limited broadcast start.");
+ for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
+ {
+ Ipv4Address addri = ipv4->GetAddress (i);
+ Ipv4Mask maski = ipv4->GetNetworkMask (i);
+ Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
+ NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
+ << " (mask is " << maski << ")");
+ m_udp->Send (p->Copy (), addri, bcast,
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p->GetSize ());
+ }
+ NS_LOG_LOGIC ("Limited broadcast end.");
+ return p->GetSize();
+ }
+ else if (ipv4->GetIfIndexForDestination(dest, localIfIndex))
+ {
+ NS_LOG_LOGIC ("Route exists");
+ m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest,
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p->GetSize ());
+ return p->GetSize();;
+ }
+ 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
+UdpSocketImpl::GetTxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ // No finite send buffer is modelled, but we must respect
+ // the maximum size of an IP datagram (65535 bytes - headers).
+ return MAX_IPV4_UDP_DATAGRAM_SIZE;
+}
+
+int
+UdpSocketImpl::SendTo (Ptr<Packet> p, const Address &address)
+{
+ NS_LOG_FUNCTION (this << address << p);
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ return DoSendTo (p, ipv4, port);
+}
+
+Ptr<Packet>
+UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_deliveryQueue.empty() )
+ {
+ return 0;
+ }
+ Ptr<Packet> p = m_deliveryQueue.front ();
+ if (p->GetSize () <= maxSize)
+ {
+ m_deliveryQueue.pop ();
+ m_rxAvailable -= p->GetSize ();
+ }
+ else
+ {
+ p = 0;
+ }
+ return p;
+}
+
+uint32_t
+UdpSocketImpl::GetRxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ // We separately maintain this state to avoid walking the queue
+ // every time this might be called
+ return m_rxAvailable;
+}
+
+void
+UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << packet << ipv4 << port);
+
+ if (m_shutdownRecv)
+ {
+ return;
+ }
+ if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
+ {
+ Address address = InetSocketAddress (ipv4, port);
+ SocketRxAddressTag tag;
+ tag.SetAddress (address);
+ packet->AddTag (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::SetRcvBufSize (uint32_t size)
+{
+ m_rcvBufSize = size;
+}
+
+uint32_t
+UdpSocketImpl::GetRcvBufSize (void) const
+{
+ return m_rcvBufSize;
+}
+
+void
+UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
+{
+ m_ipTtl = ipTtl;
+}
+
+uint32_t
+UdpSocketImpl::GetIpTtl (void) const
+{
+ return m_ipTtl;
+}
+
+void
+UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
+{
+ m_ipMulticastTtl = ipTtl;
+}
+
+uint32_t
+UdpSocketImpl::GetIpMulticastTtl (void) const
+{
+ return m_ipMulticastTtl;
+}
+
+} //namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "internet-stack.h"
+#include <string>
+
+namespace ns3 {
+
+class UdpSocketImplTest: public Test
+{
+ Ptr<Packet> m_receivedPacket;
+ Ptr<Packet> m_receivedPacket2;
+
+public:
+ virtual bool RunTests (void);
+ UdpSocketImplTest ();
+
+ 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);
+};
+
+
+UdpSocketImplTest::UdpSocketImplTest ()
+ : Test ("UdpSocketImpl")
+{
+}
+
+void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+ m_receivedPacket = packet;
+}
+
+void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+ m_receivedPacket2 = packet;
+}
+
+void UdpSocketImplTest::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 ());
+}
+
+void UdpSocketImplTest::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 ());
+}
+
+bool
+UdpSocketImplTest::RunTests (void)
+{
+ bool result = true;
+
+ // Create topology
+
+ // Receiver Node
+ Ptr<Node> rxNode = CreateObject<Node> ();
+ AddInternetStack (rxNode);
+ Ptr<SimpleNetDevice> rxDev1, rxDev2;
+ { // first interface
+ rxDev1 = CreateObject<SimpleNetDevice> ();
+ rxDev1->SetAddress (Mac48Address::Allocate ());
+ rxNode->AddDevice (rxDev1);
+ Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
+ ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1"));
+ ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+ ipv4->SetUp (netdev_idx);
+ }
+
+ { // second interface
+ rxDev2 = CreateObject<SimpleNetDevice> ();
+ rxDev2->SetAddress (Mac48Address::Allocate ());
+ rxNode->AddDevice (rxDev2);
+ Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
+ ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1"));
+ ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+ ipv4->SetUp (netdev_idx);
+ }
+
+ // Sender Node
+ Ptr<Node> txNode = CreateObject<Node> ();
+ AddInternetStack (txNode);
+ Ptr<SimpleNetDevice> txDev1;
+ {
+ txDev1 = CreateObject<SimpleNetDevice> ();
+ txDev1->SetAddress (Mac48Address::Allocate ());
+ txNode->AddDevice (txDev1);
+ Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (txDev1);
+ ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2"));
+ ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+ ipv4->SetUp (netdev_idx);
+ }
+ Ptr<SimpleNetDevice> txDev2;
+ {
+ txDev2 = CreateObject<SimpleNetDevice> ();
+ txDev2->SetAddress (Mac48Address::Allocate ());
+ txNode->AddDevice (txDev2);
+ Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (txDev2);
+ ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2"));
+ ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U));
+ ipv4->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_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
+ rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
+
+ Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
+ rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+ NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
+
+ Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+ Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+
+ // ------ Now the tests ------------
+
+ // Unicast test
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123),
+ InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
+
+ m_receivedPacket->RemoveAllTags ();
+ m_receivedPacket2->RemoveAllTags ();
+
+ // Simple broadcast test
+
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123),
+ InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ // second socket should not receive it (it is bound specifically to the second interface's address
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
+
+ m_receivedPacket->RemoveAllTags ();
+ m_receivedPacket2->RemoveAllTags ();
+
+ // Broadcast test with multiple receiving sockets
+
+ // 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 (&UdpSocketImplTest::ReceivePkt2, this));
+ NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
+
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123),
+InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
+
+ m_receivedPacket->RemoveAllTags ();
+ m_receivedPacket2->RemoveAllTags ();
+
+ Simulator::Destroy ();
+
+ return result;
+}
+
+static UdpSocketImplTest gUdpSocketImplTest;
+
+}; // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-socket-impl.h Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef UDP_SOCKET_IMPL_H
+#define UDP_SOCKET_IMPL_H
+
+#include <stdint.h>
+#include <queue>
+#include "ns3/callback.h"
+#include "ns3/traced-callback.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/udp-socket.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class UdpL4Protocol;
+
+class UdpSocketImpl : public UdpSocket
+{
+public:
+ static TypeId GetTypeId (void);
+ /**
+ * Create an unbound udp socket.
+ */
+ UdpSocketImpl ();
+ virtual ~UdpSocketImpl ();
+
+ void SetNode (Ptr<Node> node);
+ void SetUdp (Ptr<UdpL4Protocol> udp);
+
+ virtual enum SocketErrno GetErrno (void) const;
+ virtual Ptr<Node> GetNode (void) const;
+ virtual int Bind (void);
+ virtual int Bind (const Address &address);
+ virtual int Close (void);
+ virtual int ShutdownSend (void);
+ virtual int ShutdownRecv (void);
+ virtual int Connect(const Address &address);
+ virtual int Listen (uint32_t queueLimit);
+ virtual int Send (Ptr<Packet> p);
+ virtual int SendTo (Ptr<Packet> p, const Address &address);
+ virtual uint32_t GetTxAvailable (void) const;
+
+ virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+ virtual uint32_t GetRxAvailable (void) const;
+
+private:
+ // Attributes set through UdpSocket base class
+ virtual void SetRcvBufSize (uint32_t size);
+ virtual uint32_t GetRcvBufSize (void) const;
+ virtual void SetIpTtl (uint32_t ipTtl);
+ virtual uint32_t GetIpTtl (void) const;
+ virtual void SetIpMulticastTtl (uint32_t ipTtl);
+ virtual uint32_t GetIpMulticastTtl (void) const;
+
+ friend class UdpSocketFactory;
+ // invoked by Udp class
+ int FinishBind (void);
+ void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, 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);
+
+ Ipv4EndPoint *m_endPoint;
+ Ptr<Node> m_node;
+ Ptr<UdpL4Protocol> m_udp;
+ Ipv4Address m_defaultAddress;
+ uint16_t m_defaultPort;
+ Callback<void,Ptr<Socket>,uint32_t,const Address &> m_dummyRxCallback;
+ Callback<void,Ptr<Socket>,uint8_t const*,uint32_t,const Address &> m_rxCallback;
+ TracedCallback<Ptr<const Packet> > m_dropTrace;
+
+ enum SocketErrno m_errno;
+ bool m_shutdownSend;
+ bool m_shutdownRecv;
+ bool m_connected;
+
+ std::queue<Ptr<Packet> > m_deliveryQueue;
+ uint32_t m_rxAvailable;
+
+ // Socket attributes
+ uint32_t m_rcvBufSize;
+ uint32_t m_ipTtl;
+ uint32_t m_ipMulticastTtl;
+
+};
+
+}//namespace ns3
+
+#endif /* UDP_SOCKET_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/waf Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../waf "$@"
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -0,0 +1,42 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+ obj = bld.create_ns3_module('internet-stack', ['node'])
+ obj.source = [
+ 'internet-stack.cc',
+ 'ipv4-l4-demux.cc',
+ 'ipv4-l4-protocol.cc',
+ 'udp-header.cc',
+ 'tcp-header.cc',
+ 'ipv4-checksum.cc',
+ 'ipv4-interface.cc',
+ 'ipv4-l3-protocol.cc',
+ 'ipv4-static-routing.cc',
+ 'ipv4-end-point.cc',
+ 'udp-l4-protocol.cc',
+ 'tcp-l4-protocol.cc',
+ 'arp-header.cc',
+ 'arp-cache.cc',
+ 'arp-ipv4-interface.cc',
+ 'arp-l3-protocol.cc',
+ 'ipv4-loopback-interface.cc',
+ 'udp-socket-impl.cc',
+ 'tcp-socket-impl.cc',
+ 'ipv4-end-point-demux.cc',
+ 'ipv4-impl.cc',
+ 'udp-socket-factory-impl.cc',
+ 'tcp-socket-factory-impl.cc',
+ 'pending-data.cc',
+ 'sequence-number.cc',
+ 'rtt-estimator.cc',
+ ]
+
+ headers = bld.create_obj('ns3header')
+ headers.module = 'internet-stack'
+ headers.source = [
+ 'internet-stack.h',
+ 'udp-header.h',
+ 'tcp-header.h',
+ 'sequence-number.h',
+ ]
--- a/src/node/ipv4.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/node/ipv4.h Wed Jun 11 16:20:04 2008 -0700
@@ -74,7 +74,7 @@
typedef Callback<void, bool, const Ipv4Route&, Ptr<Packet>, const Ipv4Header&> RouteReplyCallback;
/**
- * \brief Asynchronously requests a route for a given packet and IP header
+ * \brief Request that a packet be routed.
*
* \param ifIndex The interface index on which the packet was received.
* \param ipHeader IP header of the packet
@@ -94,7 +94,7 @@
* RequestRoute() should return false and the routeReply callback
* must not be invoked.
*
- * If the routing protocol implementations assumes it can provide
+ * If the routing protocol implementation assumes that it can provide
* the requested route, then it should return true, and the
* routeReply callback must be invoked, either immediately before
* returning true (synchronously), or in the future (asynchronous).
@@ -105,6 +105,11 @@
* allowed to add a new header to the packet, which will appear
* immediately after the IP header, although most routing do not
* insert any extra header.
+ *
+ * Multicast routing is expected to be supported in this method. If a
+ * multicast route is encountered, all routes to a given multicast
+ * destination will be serviced by cloning the packet and calling the
+ * route reply callback once for each outgoing interface in the route.
*/
virtual bool RequestRoute (uint32_t ifIndex,
const Ipv4Header &ipHeader,
--- a/src/node/socket.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/src/node/socket.cc Wed Jun 11 16:20:04 2008 -0700
@@ -40,6 +40,13 @@
NS_LOG_FUNCTION_NOARGS ();
}
+void
+Socket::SetCloseUnblocksCallback (Callback<void,Ptr<Socket> > closeUnblocks)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_closeUnblocks = closeUnblocks;
+}
+
Ptr<Socket>
Socket::CreateSocket (Ptr<Node> node, TypeId tid)
{
@@ -103,6 +110,21 @@
m_receivedData = receivedData;
}
+void
+Socket::NotifyCloseUnblocks (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (!m_closeUnblocks.IsNull ())
+ {
+ m_closeUnblocks (this);
+ }
+}
+
+int Socket::Listen (uint32_t queueLimit)
+{
+ return 0; //XXX the base class version does nothing
+}
+
int Socket::Send (const uint8_t* buf, uint32_t size)
{
NS_LOG_FUNCTION_NOARGS ();
--- a/src/node/socket.h Wed Jun 11 16:19:28 2008 -0700
+++ b/src/node/socket.h Wed Jun 11 16:20:04 2008 -0700
@@ -105,6 +105,8 @@
*/
virtual Ptr<Node> GetNode (void) const = 0;
+ void SetCloseUnblocksCallback (Callback<void, Ptr<Socket> > closeUnblocks);
+
/**
* \param closeCompleted Callback invoked when the close operation is
* completed.
@@ -362,6 +364,7 @@
virtual uint32_t GetRxAvailable (void) const = 0;
protected:
+ void NotifyCloseUnblocks (void);
void NotifyCloseCompleted (void);
void NotifyConnectionSucceeded (void);
void NotifyConnectionFailed (void);
@@ -373,6 +376,7 @@
void NotifySend (uint32_t spaceAvailable);
void NotifyDataRecv (void);
+ Callback<void, Ptr<Socket> > m_closeUnblocks;
Callback<void,Ptr<Socket> > m_closeCompleted;
Callback<void, Ptr<Socket> > m_connectionSucceeded;
Callback<void, Ptr<Socket> > m_connectionFailed;
--- a/src/routing/olsr/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/src/routing/olsr/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
- module = bld.create_ns3_module('olsr', ['internet-node', 'contrib'])
+ module = bld.create_ns3_module('olsr', ['internet-stack', 'contrib'])
module.includes = '.'
module.source = [
'olsr-header.cc',
--- a/src/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/src/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -16,7 +16,7 @@
'simulator',
'contrib',
'node',
- 'internet-node',
+ 'internet-stack',
'devices/point-to-point',
'devices/csma',
'applications/onoff',
--- a/tutorial/tutorial-bus-network.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-bus-network.cc Wed Jun 11 16:20:04 2008 -0700
@@ -40,7 +40,7 @@
internet.Install (n);
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("10Mbps"));
+ csma.SetChannelParameter ("DataRate", StringValue ("10Mbps"));
csma.SetChannelParameter ("Delay", StringValue ("10ms"));
NetDeviceContainer nd = csma.Install (n);
--- a/tutorial/tutorial-csma-echo-ascii-trace.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-csma-echo-ascii-trace.cc Wed Jun 11 16:20:04 2008 -0700
@@ -38,7 +38,7 @@
internet.Install (n);
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("5Mpbs"));
+ csma.SetChannelParameter ("DataRate", StringValue ("5Mpbs"));
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
NetDeviceContainer nd = csma.Install (n);
--- a/tutorial/tutorial-csma-echo-pcap-trace.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-csma-echo-pcap-trace.cc Wed Jun 11 16:20:04 2008 -0700
@@ -36,7 +36,7 @@
internet.Install (n);
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+ csma.SetChannelParameter ("DataRate", StringValue ("5Mbps"));
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
NetDeviceContainer nd = csma.Install (n);
--- a/tutorial/tutorial-csma-echo.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-csma-echo.cc Wed Jun 11 16:20:04 2008 -0700
@@ -36,7 +36,7 @@
internet.Install (n);
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+ csma.SetChannelParameter ("DataRate", StringValue ("5Mbps"));
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
NetDeviceContainer nd = csma.Install (n);
--- a/tutorial/tutorial-linear-dumbbell.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-linear-dumbbell.cc Wed Jun 11 16:20:04 2008 -0700
@@ -53,7 +53,7 @@
internet.Install (lan1);
CsmaHelper csma;
- csma.SetChannelParameter ("BitRate", StringValue ("10Mbps"));
+ csma.SetChannelParameter ("DataRate", StringValue ("10Mbps"));
csma.SetChannelParameter ("Delay", StringValue ("2ms"));
NetDeviceContainer dev1 = csma.Install (lan1);
Ipv4AddressHelper ipv4;
@@ -78,7 +78,7 @@
//
NodeContainer backbone = NodeContainer (lan1.Get (3), lan2.Get (0));
PointToPointHelper p2p;
- p2p.SetChannelParameter ("BitRate", StringValue ("38400bps"));
+ p2p.SetChannelParameter ("DataRate", StringValue ("38400bps"));
p2p.SetChannelParameter ("Delay", StringValue ("20ms"));
NetDeviceContainer dev3 = p2p.Install (backbone);
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
--- a/tutorial/tutorial-point-to-point.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-point-to-point.cc Wed Jun 11 16:20:04 2008 -0700
@@ -45,7 +45,7 @@
internet.Install (n);
PointToPointHelper p2p;
- p2p.SetChannelParameter ("BitRate", StringValue ("38400bps"));
+ p2p.SetDeviceParameter ("DataRate", StringValue ("38400bps"));
p2p.SetChannelParameter ("Delay", StringValue ("20ms"));
NetDeviceContainer nd = p2p.Install (n);
--- a/tutorial/tutorial-star-routing.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-star-routing.cc Wed Jun 11 16:20:04 2008 -0700
@@ -56,7 +56,7 @@
internet.Install (n);
PointToPointHelper p2p;
- p2p.SetChannelParameter ("BitRate", StringValue ("38400bps"));
+ p2p.SetDeviceParameter ("DataRate", StringValue ("38400bps"));
p2p.SetChannelParameter ("Delay", StringValue ("20ms"));
NetDeviceContainer d01 = p2p.Install (n01);
--- a/tutorial/tutorial-star.cc Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/tutorial-star.cc Wed Jun 11 16:20:04 2008 -0700
@@ -55,7 +55,7 @@
internet.Install (n);
PointToPointHelper p2p;
- p2p.SetChannelParameter ("BitRate", StringValue ("38400bps"));
+ p2p.SetDeviceParameter ("DataRate", StringValue ("38400bps"));
p2p.SetChannelParameter ("Delay", StringValue ("20ms"));
NetDeviceContainer d01 = p2p.Install (n01);
--- a/tutorial/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/tutorial/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -4,29 +4,29 @@
obj = bld.create_ns3_program('hello-simulator', ['simulator'])
obj.source = 'hello-simulator.cc'
- obj = bld.create_ns3_program('tutorial-csma-echo', ['internet-node', 'csma'])
+ obj = bld.create_ns3_program('tutorial-csma-echo', ['internet-stack', 'csma'])
obj.source = 'tutorial-csma-echo.cc'
- obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', ['internet-node', 'csma'])
+ obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', ['internet-stack', 'csma'])
obj.source = 'tutorial-csma-echo-ascii-trace.cc'
- obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', ['internet-node', 'csma'])
+ obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', ['internet-stack', 'csma'])
obj.source = 'tutorial-csma-echo-pcap-trace.cc'
- obj = bld.create_ns3_program('tutorial-point-to-point', ['internet-node', 'point-to-point'])
+ obj = bld.create_ns3_program('tutorial-point-to-point', ['internet-stack', 'point-to-point'])
obj.source = 'tutorial-point-to-point.cc'
- obj = bld.create_ns3_program('tutorial-star', ['internet-node', 'point-to-point'])
+ obj = bld.create_ns3_program('tutorial-star', ['internet-stack', 'point-to-point'])
obj.source = ['tutorial-star.cc']
- obj = bld.create_ns3_program('tutorial-star-routing', ['internet-node', 'point-to-point'])
+ obj = bld.create_ns3_program('tutorial-star-routing', ['internet-stack', 'point-to-point'])
obj.source = ['tutorial-star-routing.cc']
- obj = bld.create_ns3_program('tutorial-linear-dumbbell', ['internet-node', 'point-to-point'])
+ obj = bld.create_ns3_program('tutorial-linear-dumbbell', ['internet-stack', 'point-to-point'])
obj.source = 'tutorial-linear-dumbbell.cc'
obj = bld.create_ns3_program('testipv4', ['node'])
obj.source = ['testipv4.cc']
- obj = bld.create_ns3_program('tutorial-bus-network', ['internet-node'])
+ obj = bld.create_ns3_program('tutorial-bus-network', ['internet-stack'])
obj.source = ['tutorial-bus-network.cc']
--- a/utils/wscript Wed Jun 11 16:19:28 2008 -0700
+++ b/utils/wscript Wed Jun 11 16:20:04 2008 -0700
@@ -28,14 +28,14 @@
obj.source = 'replay-simulation.cc'
obj = bld.create_ns3_program('print-introspected-doxygen',
- ['internet-node', 'csma-cd', 'point-to-point'])
+ ['internet-stack', 'csma-cd', 'point-to-point'])
obj.source = 'print-introspected-doxygen.cc'
# XXX: disable mobility visualizer code temporarily.
env['ENABLE_MOBILITY_VISUALIZER'] = ''
if env['ENABLE_MOBILITY_VISUALIZER']:
obj = bld.create_ns3_program('mobility-visualizer',
- ['internet-node', 'mobility'])
+ ['internet-stack', 'mobility'])
obj.source = ['mobility-visualizer-model.cc', 'mobility-visualizer-view.cc']
obj.uselib = 'MOBILITY_VISUALIZER'
if os.path.basename(obj.env['CXX']).startswith("g++"):