merge with HEAD
This commit is contained in:
@@ -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
|
||||
*
|
||||
|
||||
@@ -1272,14 +1272,14 @@ files. Put the following code after the include statement in @code{simple.cc}.
|
||||
|
||||
@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 @@ something like the following,
|
||||
@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 @@ following (let's change the log component name and program banner from
|
||||
@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 @@ source code for the script should look like the following:
|
||||
@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"
|
||||
|
||||
@@ -103,7 +103,7 @@ convenience:
|
||||
|
||||
#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 @@ The file @code{tutorial-star.cc} is reproduced here for your convenience:
|
||||
|
||||
#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 @@ provided to the template function @code{CreateObject} means that
|
||||
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 @@ immediately cast to an @code{Ipv4} pointer. Clients will then use the
|
||||
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 @@ of course).
|
||||
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
|
||||
|
||||
@@ -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 @@ method that allows one to add a routing protocol:
|
||||
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 @@ There are presently no roadmap plans for IPv6.
|
||||
@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 @@ Ipv4Route Ipv4::GetRoute ()
|
||||
@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
|
||||
|
||||
@@ -69,7 +69,7 @@ main (int argc, char *argv[])
|
||||
|
||||
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);
|
||||
|
||||
@@ -75,7 +75,7 @@ main (int argc, char *argv[])
|
||||
|
||||
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
|
||||
|
||||
@@ -66,7 +66,7 @@ main (int argc, char *argv[])
|
||||
|
||||
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
|
||||
|
||||
@@ -67,8 +67,9 @@ main (int argc, char *argv[])
|
||||
|
||||
// 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.");
|
||||
|
||||
@@ -83,7 +83,7 @@ main (int argc, char *argv[])
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -199,7 +199,8 @@ main (int argc, char *argv[])
|
||||
// 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);
|
||||
//
|
||||
|
||||
@@ -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 @@ ApplicationTraceSink (Ptr<const Packet> packet,
|
||||
#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 @@ int main (int argc, char *argv[])
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ main (int argc, char *argv[])
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -20,11 +20,11 @@ def build(bld):
|
||||
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',
|
||||
|
||||
@@ -37,19 +37,23 @@ UdpEchoClient::GetTypeId (void)
|
||||
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> ())
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -156,9 +156,8 @@ void RandomVariableBase::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2,
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -30,29 +30,15 @@ namespace ns3 {
|
||||
|
||||
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 @@ CsmaChannel::GetTypeId (void)
|
||||
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 @@ CsmaChannel::CsmaChannel()
|
||||
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 @@ CsmaChannel::Reattach(Ptr<CsmaNetDevice> device)
|
||||
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 @@ CsmaChannel::Reattach(uint32_t deviceId)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ CsmaChannel::Detach(uint32_t deviceId)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ CsmaChannel::Detach(Ptr<CsmaNetDevice> device)
|
||||
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 @@ CsmaChannel::TransmitStart(Ptr<Packet> p, uint32_t srcId)
|
||||
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 @@ CsmaChannel::PropagationCompleteEvent()
|
||||
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 @@ CsmaChannel::GetNumActDevices (void)
|
||||
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 @@ CsmaChannel::GetDeviceNum (Ptr<CsmaNetDevice> device)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
bool
|
||||
CsmaChannel::IsBusy (void)
|
||||
{
|
||||
if (m_state == IDLE)
|
||||
@@ -328,28 +310,45 @@ CsmaChannel::IsBusy (void)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -73,27 +73,14 @@ class CsmaNetDevice;
|
||||
* 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 @@ public:
|
||||
* \return The assigned device number
|
||||
*/
|
||||
int32_t Attach (Ptr<CsmaNetDevice> device);
|
||||
|
||||
/**
|
||||
* \brief Detach a given netdevice from this channel
|
||||
*
|
||||
@@ -116,6 +104,7 @@ public:
|
||||
* can't be found.
|
||||
*/
|
||||
bool Detach (Ptr<CsmaNetDevice> device);
|
||||
|
||||
/**
|
||||
* \brief Detach a given netdevice from this channel
|
||||
*
|
||||
@@ -129,6 +118,7 @@ public:
|
||||
* can't be found.
|
||||
*/
|
||||
bool Detach (uint32_t deviceId);
|
||||
|
||||
/**
|
||||
* \brief Reattach a previously detached net device to the channel
|
||||
*
|
||||
@@ -143,6 +133,7 @@ public:
|
||||
* 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 @@ public:
|
||||
* channel or can't be found.
|
||||
*/
|
||||
bool Reattach(Ptr<CsmaNetDevice> device);
|
||||
|
||||
/**
|
||||
* \brief Start transmitting a packet over the channel
|
||||
*
|
||||
@@ -171,6 +163,7 @@ public:
|
||||
* 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 @@ public:
|
||||
* 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 @@ public:
|
||||
* 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 @@ public:
|
||||
* 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 @@ public:
|
||||
* \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 @@ public:
|
||||
* \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;
|
||||
virtual Ptr<NetDevice> GetDevice (uint32_t i) 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 @@ public:
|
||||
*/
|
||||
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 @@ private:
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "csma-net-device.h"
|
||||
#include "csma-channel.h"
|
||||
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
|
||||
|
||||
namespace ns3 {
|
||||
@@ -45,40 +44,44 @@ CsmaNetDevice::GetTypeId (void)
|
||||
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 @@ CsmaNetDevice::CsmaNetDevice ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_txMachineState = READY;
|
||||
m_tInterframeGap = Seconds(0);
|
||||
m_tInterframeGap = Seconds (0);
|
||||
m_channel = 0;
|
||||
}
|
||||
|
||||
@@ -101,7 +104,7 @@ CsmaNetDevice::~CsmaNetDevice()
|
||||
m_queue = 0;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
CsmaNetDevice::DoDispose ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
@@ -110,61 +113,54 @@ CsmaNetDevice::DoDispose ()
|
||||
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 @@ CsmaNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots,
|
||||
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 @@ CsmaNetDevice::AddHeader (Ptr<Packet> p, Mac48Address dest,
|
||||
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 @@ CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
|
||||
{
|
||||
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 @@ CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
|
||||
{
|
||||
case ETHERNET_V1:
|
||||
case IP_ARP:
|
||||
param = header.GetLengthType();
|
||||
param = header.GetLengthType ();
|
||||
break;
|
||||
case LLC: {
|
||||
LlcSnapHeader llc;
|
||||
@@ -253,7 +260,7 @@ CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
CsmaNetDevice::TransmitStart ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
@@ -265,47 +272,58 @@ CsmaNetDevice::TransmitStart ()
|
||||
// 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())
|
||||
return;
|
||||
//
|
||||
// Only transmit if send side of net device is enabled
|
||||
//
|
||||
if (IsSendEnabled () == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_channel->GetState() != IDLE)
|
||||
{ // Channel busy, backoff and rechedule TransmitStart()
|
||||
if (m_channel->GetState () != IDLE)
|
||||
{
|
||||
//
|
||||
// The channel is 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 @@ CsmaNetDevice::TransmitStart ()
|
||||
}
|
||||
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 @@ CsmaNetDevice::TransmitCompleteEvent (void)
|
||||
// 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 @@ CsmaNetDevice::TransmitCompleteEvent (void)
|
||||
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 @@ CsmaNetDevice::TransmitReadyEvent (void)
|
||||
// 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 @@ CsmaNetDevice::Attach (Ptr<CsmaChannel> ch)
|
||||
|
||||
m_channel = ch;
|
||||
|
||||
m_deviceId = m_channel->Attach(this);
|
||||
m_bps = m_channel->GetDataRate ();
|
||||
m_tInterframeGap = m_channel->GetDelay ();
|
||||
m_deviceId = m_channel->Attach (this);
|
||||
|
||||
/*
|
||||
* For now, this device is up whenever a channel is attached to it.
|
||||
*/
|
||||
//
|
||||
// The channel provides us with the transmitter data rate.
|
||||
//
|
||||
m_bps = m_channel->GetDataRate ();
|
||||
|
||||
//
|
||||
// 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 @@ CsmaNetDevice::Receive (Ptr<Packet> packet)
|
||||
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 ());
|
||||
|
||||
//
|
||||
// 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 @@ CsmaNetDevice::Receive (Ptr<Packet> packet)
|
||||
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 @@ CsmaNetDevice::Receive (Ptr<Packet> packet)
|
||||
{
|
||||
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 @@ CsmaNetDevice::Receive (Ptr<Packet> packet)
|
||||
{
|
||||
case ETHERNET_V1:
|
||||
case IP_ARP:
|
||||
protocol = header.GetLengthType();
|
||||
protocol = header.GetLengthType ();
|
||||
break;
|
||||
case LLC:
|
||||
{
|
||||
@@ -516,95 +560,109 @@ CsmaNetDevice::Receive (Ptr<Packet> packet)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ CsmaNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
|
||||
|
||||
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 @@ CsmaNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNu
|
||||
|
||||
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 @@ CsmaNetDevice::NeedsArp (void) const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void
|
||||
|
||||
void
|
||||
CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
|
||||
{
|
||||
m_rxCallback = cb;
|
||||
|
||||
@@ -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 @@ class ErrorModel;
|
||||
*
|
||||
* 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 @@ public:
|
||||
* 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 @@ enum CsmaEncapsulationMode {
|
||||
* \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 @@ enum CsmaEncapsulationMode {
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Enable or disable the receive side of the network device.
|
||||
*
|
||||
* \param enable Enable the receive side if true, otherwise disable.
|
||||
*/
|
||||
void SetReceiveEnable (bool enable);
|
||||
|
||||
void SetAddress (Mac48Address self);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
// 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;
|
||||
//
|
||||
// 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 @@ enum CsmaEncapsulationMode {
|
||||
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 @@ enum CsmaEncapsulationMode {
|
||||
* @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 @@ protected:
|
||||
* \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 @@ protected:
|
||||
* \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 @@ protected:
|
||||
bool ProcessHeader (Ptr<Packet> p, uint16_t & param);
|
||||
|
||||
private:
|
||||
// disable copy constructor and operator =
|
||||
CsmaNetDevice &operator = (const CsmaNetDevice &o);
|
||||
CsmaNetDevice (const CsmaNetDevice &o);
|
||||
/**
|
||||
* Initializes variablea when construction object.
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Initialization function used during object construction.
|
||||
*/
|
||||
void Init (bool sendEnable, bool receiveEnable);
|
||||
|
||||
@@ -277,35 +344,38 @@ private:
|
||||
*
|
||||
* 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 @@ private:
|
||||
* 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 @@ private:
|
||||
* 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 @@ private:
|
||||
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 @@ private:
|
||||
* 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 @@ private:
|
||||
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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -29,26 +29,10 @@
|
||||
#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)
|
||||
{
|
||||
@@ -56,37 +40,28 @@ PendingData::PendingData () : size (0), data (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);
|
||||
data.push_back (Create<Packet> (d, size));
|
||||
}
|
||||
}
|
||||
|
||||
PendingData::PendingData(const std::string& s)
|
||||
: size (s.length () + 1), data ((uint8_t*)strdup(s.c_str ())),
|
||||
: 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 (0),
|
||||
: size (c.Size ()), data (c.data),
|
||||
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
|
||||
@@ -106,62 +81,27 @@ PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
|
||||
|
||||
void PendingData::Clear ()
|
||||
{ // Remove all pending data
|
||||
if (data)
|
||||
{
|
||||
delete [] data; // Free memory if used
|
||||
}
|
||||
data = 0;
|
||||
data.clear();
|
||||
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
|
||||
}
|
||||
if (d == 0)
|
||||
{
|
||||
data.push_back(Create<Packet> (d,s));
|
||||
}
|
||||
else
|
||||
{ // No existing data, see if new data
|
||||
if (d)
|
||||
{
|
||||
data = new uint8_t[s];
|
||||
memcpy (data, d, s);
|
||||
}
|
||||
}
|
||||
{
|
||||
data.push_back(Create<Packet> (s));
|
||||
}
|
||||
size += s;
|
||||
}
|
||||
|
||||
void PendingData::Remove(uint32_t s)
|
||||
void PendingData::Add (Ptr<Packet> p)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
data.push_back(p);
|
||||
size += p->GetSize();
|
||||
}
|
||||
|
||||
uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o)
|
||||
@@ -193,12 +133,61 @@ Ptr<Packet> PendingData::CopyFromOffset (uint32_t s, uint32_t o)
|
||||
{
|
||||
return 0; // No data requested
|
||||
}
|
||||
if (data)
|
||||
if (data.size() != 0)
|
||||
{ // Actual data exists, make copy and return it
|
||||
return Create<Packet> (data+o, s1);
|
||||
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 non-data pdu of correct size
|
||||
{ // No actual data, just return dummy-data packet of correct size
|
||||
return Create<Packet> (s1);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef __datapdu_h__
|
||||
#define __datapdu_h__
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "pending-data.h"
|
||||
#include "sequence-number.h"
|
||||
|
||||
@@ -47,7 +48,7 @@ public:
|
||||
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
|
||||
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
|
||||
@@ -60,10 +61,9 @@ public:
|
||||
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)
|
||||
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
|
||||
@@ -127,7 +127,8 @@ TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock)
|
||||
m_cnCount (sock.m_cnCount),
|
||||
m_rxAvailable (0),
|
||||
m_wouldBlock (false),
|
||||
m_sndBufSize (sock.m_sndBufSize)
|
||||
m_sndBufSize (sock.m_sndBufSize),
|
||||
m_rcvBufSize(sock.m_rcvBufSize)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
NS_LOG_LOGIC("Invoked the copy constructor");
|
||||
@@ -347,38 +348,33 @@ TcpSocketImpl::Connect (const Address & address)
|
||||
}
|
||||
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);
|
||||
NS_LOG_FUNCTION (this << p);
|
||||
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;
|
||||
{
|
||||
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;
|
||||
@@ -386,6 +382,11 @@ int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -463,21 +464,63 @@ Ptr<Packet>
|
||||
TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
if (m_deliveryQueue.empty() )
|
||||
if(m_bufferedData.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Ptr<Packet> p = m_deliveryQueue.front ();
|
||||
if (p->GetSize () <= maxSize)
|
||||
{
|
||||
m_deliveryQueue.pop ();
|
||||
m_rxAvailable -= p->GetSize ();
|
||||
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
|
||||
}
|
||||
else
|
||||
if (out.size() == 0)
|
||||
{
|
||||
p = 0;
|
||||
return 0;
|
||||
}
|
||||
return p;
|
||||
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
|
||||
@@ -883,7 +926,7 @@ bool TcpSocketImpl::SendPendingData (bool withAck)
|
||||
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"
|
||||
NS_LOG_LOGIC("TcpSocketImpl " << this << " SendPendingData"
|
||||
<< " txseq " << m_nextTxSequence
|
||||
<< " s " << s
|
||||
<< " datasize " << p->GetSize() );
|
||||
@@ -918,7 +961,7 @@ bool TcpSocketImpl::SendPendingData (bool withAck)
|
||||
if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
|
||||
{
|
||||
Time rto = m_rtt->RetransmitTimeout ();
|
||||
NS_LOG_LOGIC ("Schedule retransmission timeout at time " <<
|
||||
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);
|
||||
@@ -935,7 +978,7 @@ bool TcpSocketImpl::SendPendingData (bool withAck)
|
||||
// Note the high water mark
|
||||
m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
|
||||
}
|
||||
NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
|
||||
NS_LOG_LOGIC ("SendPendingData Sent "<<nPacketsSent<<" packets");
|
||||
NS_LOG_LOGIC("RETURN SendPendingData");
|
||||
return (nPacketsSent>0);
|
||||
}
|
||||
@@ -994,90 +1037,57 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
|
||||
// Log sequence received if enabled
|
||||
// NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
|
||||
// Three possibilities
|
||||
// 1) Received seq is expected, deliver this and any buffered data
|
||||
// 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) Deliver to application this packet
|
||||
// 3) See if any buffered can be delivered
|
||||
// 4) Send the ack
|
||||
// 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);
|
||||
m_deliveryQueue.push (p);
|
||||
//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);
|
||||
// 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())
|
||||
@@ -1096,6 +1106,9 @@ void TcpSocketImpl::NewRx (Ptr<Packet> p,
|
||||
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
|
||||
@@ -198,16 +198,15 @@ private:
|
||||
// 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
|
||||
uint32_t m_rcvBufSize; // maximum receive socket buffer size
|
||||
};
|
||||
|
||||
}//namespace ns3
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_module('internet-node', ['node'])
|
||||
obj = bld.create_ns3_module('internet-stack', ['node'])
|
||||
obj.source = [
|
||||
'internet-stack.cc',
|
||||
'ipv4-l4-demux.cc',
|
||||
@@ -33,7 +33,7 @@ def build(bld):
|
||||
]
|
||||
|
||||
headers = bld.create_obj('ns3header')
|
||||
headers.module = 'internet-node'
|
||||
headers.module = 'internet-stack'
|
||||
headers.source = [
|
||||
'internet-stack.h',
|
||||
'udp-header.h',
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
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 @@ public:
|
||||
* 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 @@ public:
|
||||
* 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,
|
||||
|
||||
@@ -40,6 +40,13 @@ Socket::~Socket ()
|
||||
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 @@ Socket::SetRecvCallback (Callback<void, Ptr<Socket> > receivedData)
|
||||
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 ();
|
||||
|
||||
@@ -105,6 +105,8 @@ public:
|
||||
*/
|
||||
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 @@ public:
|
||||
virtual uint32_t GetRxAvailable (void) const = 0;
|
||||
|
||||
protected:
|
||||
void NotifyCloseUnblocks (void);
|
||||
void NotifyCloseCompleted (void);
|
||||
void NotifyConnectionSucceeded (void);
|
||||
void NotifyConnectionFailed (void);
|
||||
@@ -373,6 +376,7 @@ protected:
|
||||
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;
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -16,7 +16,7 @@ all_modules = (
|
||||
'simulator',
|
||||
'contrib',
|
||||
'node',
|
||||
'internet-node',
|
||||
'internet-stack',
|
||||
'devices/point-to-point',
|
||||
'devices/csma',
|
||||
'applications/onoff',
|
||||
|
||||
@@ -40,7 +40,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ main (int argc, char *argv[])
|
||||
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 @@ main (int argc, char *argv[])
|
||||
//
|
||||
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");
|
||||
|
||||
@@ -45,7 +45,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
@@ -55,7 +55,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
|
||||
@@ -4,29 +4,29 @@ def build(bld):
|
||||
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']
|
||||
|
||||
@@ -28,14 +28,14 @@ def build(bld):
|
||||
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++"):
|
||||
|
||||
Reference in New Issue
Block a user