point-to-point: Update example and documentation to new API

This commit is contained in:
Tom Henderson
2018-08-05 17:10:29 -07:00
parent bccd5a5863
commit 35ba9e2b28
3 changed files with 225 additions and 126 deletions

View File

@@ -263,25 +263,57 @@ Defining Attributes
We provide a way for users to access values deep in the system, without having
to plumb accessors (pointers) through the system and walk pointer chains to get
to them. Consider a class :cpp:class:`DropTailQueue` that has a member variable
that is an unsigned integer :cpp:member:`m_maxPackets`; this member variable controls
the depth of the queue.
to them. Consider a class :cpp:class:`QueueBase` that has a member variable
:cpp:member:`m_maxSize` controlling the depth of the queue.
If we look at the declaration of :cpp:class:`DropTailQueue`, we see
If we look at the declaration of :cpp:class:`QueueBase`, we see
the following::
class DropTailQueue : public Queue {
class QueueBase : public Object {
public:
static TypeId GetTypeId (void);
...
private:
std::queue<Ptr<Packet> > m_packets;
uint32_t m_maxPackets;
...
QueueSize m_maxSize; //!< max queue size
...
};
:cpp:class:`QueueSize` is a special type in |ns3| that allows size
to be represented in different units::
enum QueueSizeUnit
{
PACKETS, /**< Use number of packets for queue size */
BYTES, /**< Use number of bytes for queue size */
};
class QueueSize
{
...
private:
...
QueueSizeUnit m_unit; //!< unit
uint32_t m_value; //!< queue size [bytes or packets]
};
Finally, the class :cpp:class:`DropTailQueue` inherits from this base
class and provides the semantics that packets that are submitted to
a full queue will be dropped from the back of the queue ("drop tail").
::
/**
* \ingroup queue
*
* \brief A FIFO packet queue that drops tail-end packets on overflow
*/
template <typename Item>
class DropTailQueue : public Queue<Item>
Let's consider things that a user may want to do with the value of
:cpp:member:`m_maxPackets`:
:cpp:member:`m_maxSize`:
* Set a default value for the system, such that whenever a new
:cpp:class:`DropTailQueue` is created, this member is initialized
@@ -294,43 +326,45 @@ functions, and some type of global default value.
In the |ns3| attribute system, these value definitions and accessor function
registrations are moved into the :cpp:class:`TypeId` class; *e.g*.::
NS_OBJECT_ENSURE_REGISTERED (DropTailQueue);
NS_OBJECT_ENSURE_REGISTERED (QueueBase);
TypeId
DropTailQueue::GetTypeId (void)
QueueBase::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::DropTailQueue")
.SetParent<Queue> ()
.SetGroupName ("Network")
.AddConstructor<DropTailQueue> ()
.AddAttribute ("MaxPackets",
"The maximum number of packets accepted by this DropTailQueue.",
UintegerValue (100),
MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
MakeUintegerChecker<uint32_t> ())
...
.AddAttribute ("MaxSize",
"The max queue size",
QueueSizeValue (QueueSize ("100p")),
MakeQueueSizeAccessor (&QueueBase::SetMaxSize,
&QueueBase::GetMaxSize),
MakeQueueSizeChecker ())
...
;
return tid;
}
The :cpp:func:`AddAttribute ()` method is performing a number of things for the
:cpp:member:`m_maxPackets` value:
:cpp:member:`m_maxSize` value:
* Binding the (usually private) member variable :cpp:member:`m_maxPackets`
to a public string ``"MaxPackets"``.
* Providing a default value (100 packets).
* Binding the (usually private) member variable :cpp:member:`m_maxSize`
to a public string ``"MaxSize"``.
* Providing a default value (0 packets).
* Providing some help text defining the meaning of the value.
* Providing a "Checker" (not used in this example) that can be used to set
bounds on the allowable range of values.
The key point is that now the value of this variable and its default value are
accessible in the attribute namespace, which is based on strings such as
``"MaxPackets"`` and :cpp:class:`TypeId` name strings. In the next section,
``"MaxSize"`` and :cpp:class:`TypeId` name strings. In the next section,
we will provide an example script that shows how users may manipulate
these values.
Note that initialization of the attribute relies on the macro
``NS_OBJECT_ENSURE_REGISTERED (DropTailQueue)`` being called; if you leave this
``NS_OBJECT_ENSURE_REGISTERED (QueueBase)`` being called; if you leave this
out of your new class implementation, your attributes will not be initialized
correctly.
@@ -359,50 +393,63 @@ script for illustration, with some details stripped out. The ``main``
function begins::
// This is a basic example of how to use the attribute system to
// set and get a value in the underlying system; namely, an unsigned
// integer of the maximum number of packets in a queue
// set and get a value in the underlying system; namely, the maximum
// size of the FIFO queue in the PointToPointNetDevice
//
int
main (int argc, char *argv[])
{
// By default, the MaxPackets attribute has a value of 100 packets
// (this default can be observed in the function DropTailQueue::GetTypeId)
//
// Queues in ns-3 are objects that hold items (other objects) in
// a queue structure. The C++ implementation uses templates to
// allow queues to hold various types of items, but the most
// common is a pointer to a packet (Ptr<Packet>).
//
// The maximum queue size can either be enforced in bytes ('b') or
// packets ('p'). A special type called the ns3::QueueSize can
// hold queue size values in either unit (bytes or packets). The
// queue base class ns3::QueueBase has a MaxSize attribute that can
// be set to a QueueSize.
// By default, the MaxSize attribute has a value of 100 packets ('100p')
// (this default can be observed in the function QueueBase::GetTypeId)
//
// Here, we set it to 80 packets. We could use one of two value types:
// a string-based value or a Uinteger value
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("80"));
// a string-based value or a QueueSizeValue value
Config::SetDefault ("ns3::QueueBase::MaxSize", StringValue ("80p"));
// The below function call is redundant
Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (80));
// Allow the user to override any of the defaults and the above
// SetDefaults () at run-time, via command-line arguments
// For example, via "--ns3::DropTailQueue::MaxPackets=80"
CommandLine cmd;
// This provides yet another way to set the value from the command line:
cmd.AddValue ("maxPackets", "ns3::DropTailQueue::MaxPackets");
cmd.Parse (argc, argv);
Config::SetDefault ("ns3::QueueBase::MaxSize", QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, 80)));
The main thing to notice in the above are the two equivalent calls to
:cpp:func:`Config::SetDefault ()`. This is how we set the default value
for all subsequently instantiated :cpp:class:`DropTailQueue`\s. We illustrate
that two types of ``Value`` classes, a :cpp:class:`StringValue` and
a :cpp:class:`UintegerValue` class, can be used to assign the value
to the attribute named by "ns3::DropTailQueue::MaxPackets".
a :cpp:class:`QueueSizeValue` class, can be used to assign the value
to the attribute named by "ns3::QueueBase::MaxSize".
It's also possible to manipulate Attributes using the :cpp:class:`CommandLine`;
we saw some examples early in the Tutorial. In particular, it is
straightforward to add a shorthand argument name, such as ``--maxPackets``,
It is also possible to manipulate Attributes using the :cpp:class:`CommandLine`;
we saw some examples early in the |ns3| Tutorial. In particular, it is
straightforward to add a shorthand argument name, such as ``--maxSize``,
for an Attribute that is particular relevant for your model, in this case
``"ns3::DropTailQueue::MaxPackets"``. This has the additional feature that
``"ns3::QueueBase::MaxSize"``. This has the additional feature that
the help string for the Attribute will be printed as part of the usage
message for the script. For more information see
the :cpp:class:`CommandLine` API documentation.
::
// Allow the user to override any of the defaults and the above
// SetDefaults() at run-time, via command-line arguments
// For example, via "--ns3::QueueBase::MaxSize=80p"
CommandLine cmd;
// This provides yet another way to set the value from the command line:
cmd.AddValue ("maxSize", "ns3::QueueBase::MaxSize");
cmd.Parse (argc, argv);
Now, we will create a few objects using the low-level API. Our
newly created queues will not have :cpp:member:`m_maxPackets` initialized to
100 packets, as defined in the :cpp:func:`DropTailQueue::GetTypeId ()`
newly created queues will not have :cpp:member:`m_maxSize` initialized to
0 packets, as defined in the :cpp:func:`QueueBase::GetTypeId ()`
function, but to 80 packets, because of what we did above with
default values.::
@@ -411,7 +458,7 @@ default values.::
Ptr<PointToPointNetDevice> net0 = CreateObject<PointToPointNetDevice> ();
n0->AddDevice (net0);
Ptr<Queue> q = CreateObject<DropTailQueue> ();
Ptr<Queue<Packet> > q = CreateObject<DropTailQueue<Packet> > ();
net0->AddQueue(q);
At this point, we have created a single :cpp:class:`Node` (``n0``)
@@ -460,10 +507,9 @@ class instances *to be created in the future:*
But what if you've already created an instance, and you want
to change the value of the attribute? In this example, how can we
manipulate the :cpp:member:`m_maxPackets` value of the already instantiated
manipulate the :cpp:member:`m_maxSize` value of the already instantiated
:cpp:class:`DropTailQueue`? Here are various ways to do that.
Changing Values
+++++++++++++++
@@ -481,39 +527,47 @@ First, we observe that we can get a pointer to the (base class)
:cpp:class:`PointToPointNetDevice` attributes, where it is called
``"TxQueue"``::
PointerValue tmp;
net0->GetAttribute ("TxQueue", tmp);
Ptr<Object> txQueue = tmp.GetObject ();
PointerValue ptr;
net0->GetAttribute ("TxQueue", ptr);
Ptr<Queue<Packet> > txQueue = ptr.Get<Queue<Packet> > ();
Using the :cpp:func:`GetObject ()` function, we can perform a safe downcast
to a :cpp:class:`DropTailQueue`, where ``"MaxPackets"`` is an attribute::
to a :cpp:class:`DropTailQueue`. The `NS_ASSERT` checks that the pointer is
valid.
Ptr<DropTailQueue> dtq = txQueue->GetObject <DropTailQueue> ();
::
Ptr<DropTailQueue<Packet> > dtq = txQueue->GetObject <DropTailQueue<Packet> > ();
NS_ASSERT (dtq != 0);
Next, we can get the value of an attribute on this queue. We have introduced
wrapper ``Value`` classes for the underlying data types, similar
to Java wrappers around these types, since the attribute system stores values
serialized to strings, and not disparate types. Here, the attribute value
is assigned to a :cpp:class:`UintegerValue`, and the :cpp:func:`Get ()`
method on this value produces the (unwrapped) ``uint32_t``.::
is assigned to a :cpp:class:`QueueSizeValue`, and the :cpp:func:`Get ()`
method on this value produces the (unwrapped) ``QueueSize``. That is,
the variable `limit` is written into by the GetAttribute method.::
UintegerValue limit;
dtq->GetAttribute ("MaxPackets", limit);
NS_LOG_INFO ("1. dtq limit: " << limit.Get () << " packets");
QueueSizeValue limit;
dtq->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("1. dtq limit: " << limit.Get ());
Note that the above downcast is not really needed; we could have gotten
the attribute value directly from ``txQueue``, which is an :cpp:class:`Object`::
the attribute value directly from ``txQueue``::
txQueue->GetAttribute ("MaxPackets", limit);
NS_LOG_INFO ("2. txQueue limit: " << limit.Get () << " packets");
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("2. txQueue limit: " << limit.Get ());
Now, let's set it to another value (60 packets)::
Now, let's set it to another value (60 packets). Let's also make
use of the StringValue shorthand notation to set the size by
passing in a string (the string must be a positive integer suffixed
by either the `p` or `b` character).
txQueue->SetAttribute("MaxPackets", UintegerValue (60));
txQueue->GetAttribute ("MaxPackets", limit);
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
::
txQueue->SetAttribute ("MaxSize", StringValue ("60p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get ());
Config Namespace Path
=====================
@@ -523,11 +577,11 @@ namespace. Here, this attribute resides on a known path in this namespace; this
approach is useful if one doesn't have access to the underlying pointers and
would like to configure a specific attribute with a single statement.::
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets",
UintegerValue (25));
txQueue->GetAttribute ("MaxPackets", limit);
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxSize",
StringValue ("25p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("4. txQueue limit changed through namespace: "
<< limit.Get () << " packets");
<< limit.Get ());
The configuration path often has the form of
``".../<container name>/<index>/.../<attribute>/<attribute>"``
@@ -535,18 +589,28 @@ to refer to a specific instance by index of an object in the container.
In this case the first container is the list of all :cpp:class:`Node`\s;
the second container is the list of all :cpp:class:`NetDevice`\s on
the chosen :cpp:class:`Node`. Finally, the configuration path usually
ends with a succession of member attributes, in this case the ``"MaxPackets"``
ends with a succession of member attributes, in this case the ``"MaxSize"``
attribute of the ``"TxQueue"`` of the chosen :cpp:class:`NetDevice`.
We could have also used wildcards to set this value for all nodes and all net
devices (which in this simple example has the same effect as the previous
:cpp:func:`Config::Set ()`)::
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets",
UintegerValue (15));
txQueue->GetAttribute ("MaxPackets", limit);
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxSize",
StringValue ("15p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: "
<< limit.Get () << " packets");
<< limit.Get ());
If you run this program from the command line, you should see the following
output corresponding to the steps we took above::
$ ./waf --run main-attribute-value
1. dtq limit: 80p
2. txQueue limit: 80p
3. txQueue limit changed: 60p
4. txQueue limit changed through namespace: 25p
5. txQueue limit changed through wildcarded namespace: 15p
Object Name Service
===================
@@ -936,32 +1000,37 @@ After running, you can open the ``output-attributes.txt`` file and see:
.. sourcecode:: text
default ns3::RealtimeSimulatorImpl::SynchronizationMode "BestEffort"
default ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns"
default ns3::PcapFileWrapper::CaptureSize "65535"
default ns3::PacketSocket::RcvBufSize "131072"
...
default ns3::ErrorModel::IsEnabled "true"
default ns3::RateErrorModel::ErrorUnit "EU_BYTE"
default ns3::RateErrorModel::ErrorUnit "ERROR_UNIT_BYTE"
default ns3::RateErrorModel::ErrorRate "0"
default ns3::RateErrorModel::RanVar "Uniform:0:1"
default ns3::DropTailQueue::Mode "Packets"
default ns3::DropTailQueue::MaxPackets "100"
default ns3::DropTailQueue::MaxBytes "6553500"
default ns3::Application::StartTime "+0.0ns"
default ns3::Application::StopTime "+0.0ns"
default ns3::RateErrorModel::RanVar "ns3::UniformRandomVariable[Min=0.0|Max=1.0]"
default ns3::BurstErrorModel::ErrorRate "0"
default ns3::BurstErrorModel::BurstStart "ns3::UniformRandomVariable[Min=0.0|Max=1.0]"
default ns3::BurstErrorModel::BurstSize "ns3::UniformRandomVariable[Min=1|Max=4]"
default ns3::PacketSocket::RcvBufSize "131072"
default ns3::PcapFileWrapper::CaptureSize "65535"
default ns3::PcapFileWrapper::NanosecMode "false"
default ns3::SimpleNetDevice::PointToPointMode "false"
default ns3::SimpleNetDevice::TxQueue "ns3::DropTailQueue<Packet>"
default ns3::SimpleNetDevice::DataRate "0bps"
default ns3::PacketSocketClient::MaxPackets "100"
default ns3::PacketSocketClient::Interval "+1000000000.0ns"
default ns3::PacketSocketClient::PacketSize "1024"
default ns3::PacketSocketClient::Priority "0"
default ns3::ConfigStore::Mode "Save"
default ns3::ConfigStore::Filename "output-attributes.txt"
default ns3::ConfigStore::FileFormat "RawText"
default ns3::ConfigExample::TestInt16 "-5"
global RngSeed "1"
global RngRun "1"
global SimulatorImplementationType "ns3::DefaultSimulatorImpl"
global SchedulerType "ns3::MapScheduler"
global RngSeed "1"
global RngRun "1"
global ChecksumEnabled "false"
value /$ns3::ConfigExample/TestInt16 "-3"
In the above, all of the default values for attributes for the core
module are shown. Then, all the values for the |ns3| global values
In the above, several of the default values for attributes for the core
and network modules are shown. Then, all the values for the |ns3| global values
are recorded. Finally, the value of the instance of :cpp:class:`ConfigExample`
that was rooted in the configuration namespace is shown. In a real
|ns3| program, many more models, attributes, and defaults would be shown.
@@ -972,27 +1041,31 @@ An XML version also exists in ``output-attributes.xml``:
<?xml version="1.0" encoding="UTF-8"?>
<ns3>
<default name="ns3::RealtimeSimulatorImpl::SynchronizationMode" value="BestEffort"/>
<default name="ns3::RealtimeSimulatorImpl::HardLimit" value="+100000000.0ns"/>
<default name="ns3::PcapFileWrapper::CaptureSize" value="65535"/>
<default name="ns3::PacketSocket::RcvBufSize" value="131072"/>
<default name="ns3::ErrorModel::IsEnabled" value="true"/>
<default name="ns3::RateErrorModel::ErrorUnit" value="EU_BYTE"/>
<default name="ns3::RateErrorModel::ErrorUnit" value="ERROR_UNIT_BYTE"/>
<default name="ns3::RateErrorModel::ErrorRate" value="0"/>
<default name="ns3::RateErrorModel::RanVar" value="Uniform:0:1"/>
<default name="ns3::DropTailQueue::Mode" value="Packets"/>
<default name="ns3::DropTailQueue::MaxPackets" value="100"/>
<default name="ns3::DropTailQueue::MaxBytes" value="6553500"/>
<default name="ns3::Application::StartTime" value="+0.0ns"/>
<default name="ns3::Application::StopTime" value="+0.0ns"/>
<default name="ns3::RateErrorModel::RanVar" value="ns3::UniformRandomVariable[Min=0.0|Max=1.0]"/>
<default name="ns3::BurstErrorModel::ErrorRate" value="0"/>
<default name="ns3::BurstErrorModel::BurstStart" value="ns3::UniformRandomVariable[Min=0.0|Max=1.0]"/>
<default name="ns3::BurstErrorModel::BurstSize" value="ns3::UniformRandomVariable[Min=1|Max=4]"/>
<default name="ns3::PacketSocket::RcvBufSize" value="131072"/>
<default name="ns3::PcapFileWrapper::CaptureSize" value="65535"/>
<default name="ns3::PcapFileWrapper::NanosecMode" value="false"/>
<default name="ns3::SimpleNetDevice::PointToPointMode" value="false"/>
<default name="ns3::SimpleNetDevice::TxQueue" value="ns3::DropTailQueue&lt;Packet&gt;"/>
<default name="ns3::SimpleNetDevice::DataRate" value="0bps"/>
<default name="ns3::PacketSocketClient::MaxPackets" value="100"/>
<default name="ns3::PacketSocketClient::Interval" value="+1000000000.0ns"/>
<default name="ns3::PacketSocketClient::PacketSize" value="1024"/>
<default name="ns3::PacketSocketClient::Priority" value="0"/>
<default name="ns3::ConfigStore::Mode" value="Save"/>
<default name="ns3::ConfigStore::Filename" value="output-attributes.xml"/>
<default name="ns3::ConfigStore::FileFormat" value="Xml"/>
<default name="ns3::ConfigExample::TestInt16" value="-5"/>
<global name="RngSeed" value="1"/>
<global name="RngRun" value="1"/>
<global name="SimulatorImplementationType" value="ns3::DefaultSimulatorImpl"/>
<global name="SchedulerType" value="ns3::MapScheduler"/>
<global name="RngSeed" value="1"/>
<global name="RngRun" value="1"/>
<global name="ChecksumEnabled" value="false"/>
<value path="/$ns3::ConfigExample/TestInt16" value="-3"/>
</ns3>
@@ -1122,10 +1195,3 @@ Now, when you run the script, a GUI should pop up, allowing you to open menus of
attributes on different nodes/objects, and then launch the simulation execution
when you are done.
Future work
+++++++++++
There are a couple of possible improvements:
* Save a unique version number with date and time at start of file.
* Save rng initial seed somewhere.
* Make each RandomVariable serialize its own initial seed and re-read it later.

View File

@@ -38,8 +38,8 @@ NS_LOG_COMPONENT_DEFINE ("AttributeValueSample");
//
// This is a basic example of how to use the attribute system to
// set and get a value in the underlying system; namely, an unsigned
// integer of the maximum number of packets in a queue
// set and get a value in the underlying system; namely, the maximum
// size of the FIFO queue in the PointToPointNetDevice
//
int
@@ -47,15 +47,25 @@ main (int argc, char *argv[])
{
LogComponentEnable ("AttributeValueSample", LOG_LEVEL_INFO);
// By default, the MaxSize attribute has a value of 100 packets
// (this default can be observed in the function DropTailQueue::GetTypeId)
// Queues in ns-3 are objects that hold items (other objects) in
// a queue structure. The C++ implementation uses templates to
// allow queues to hold various types of items, but the most
// common is a pointer to a packet (Ptr<Packet>).
//
// The maximum queue size can either be enforced in bytes ('b') or
// packets ('p'). A special type called the ns3::QueueSize can
// hold queue size values in either unit (bytes or packets). The
// queue base class ns3::QueueBase has a MaxSize attribute that can
// be set to a QueueSize.
// By default, the MaxSize attribute has a value of 100 packets ('100p')
// (this default can be observed in the function QueueBase::GetTypeId)
//
// Here, we set it to 80 packets. We could use one of two value types:
// a string-based value or a QueueSizeValue value
Config::SetDefault ("ns3::QueueBase::MaxSize", StringValue ("80p"));
// The below function call is redundant
Config::SetDefault ("ns3::QueueBase::MaxSize",
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, 80)));
Config::SetDefault ("ns3::QueueBase::MaxSize", QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, 80)));
// Allow the user to override any of the defaults and the above
// SetDefaults() at run-time, via command-line arguments
@@ -97,7 +107,7 @@ main (int argc, char *argv[])
Ptr<Queue<Packet> > txQueue = ptr.Get<Queue<Packet> > ();
// Using the GetObject function, we can perform a safe downcast
// to a DropTailQueue, where MaxSize is a member
// to a DropTailQueue
Ptr<DropTailQueue<Packet> > dtq = txQueue->GetObject <DropTailQueue<Packet> > ();
NS_ASSERT (dtq);
@@ -105,22 +115,25 @@ main (int argc, char *argv[])
// We have introduced wrapper "Value" classes for the underlying
// data types, similar to Java wrappers around these types, since
// the attribute system stores values and not disparate types.
// Here, the attribute value is assigned to a Uinteger, and
// the Get() method on this value produces the (unwrapped) uint32_t.
// Here, the attribute value is assigned to a QueueSizeValue, and
// the Get() method on this value produces the (unwrapped) QueueSize.
QueueSizeValue limit;
dtq->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("1. dtq limit: " << limit.Get ().GetValue () << " packets");
NS_LOG_INFO ("1. dtq limit: " << limit.Get ());
// Note that the above downcast is not really needed; we could have
// done the same using the Ptr<Queue> even though the attribute
// is a member of the subclass
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("2. txQueue limit: " << limit.Get () << " packets");
NS_LOG_INFO ("2. txQueue limit: " << limit.Get ());
// Now, let's set it to another value (60 packets)
// Now, let's set it to another value (60 packets). Let's also make
// use of the StringValue shorthand notation to set the size by
// passing in a string (the string must be a positive integer suffixed
// by either the 'p' or 'b' character).
txQueue->SetAttribute ("MaxSize", StringValue ("60p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get ());
// 2. Namespace-based access
//
@@ -132,7 +145,7 @@ main (int argc, char *argv[])
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxSize", StringValue ("25p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("4. txQueue limit changed through namespace: " <<
limit.Get () << " packets");
limit.Get ());
// we could have also used wildcards to set this value for all nodes
// and all net devices (which in this simple example has the same
@@ -140,7 +153,7 @@ main (int argc, char *argv[])
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxSize", StringValue ("15p"));
txQueue->GetAttribute ("MaxSize", limit);
NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: " <<
limit.Get () << " packets");
limit.Get ());
Simulator::Destroy ();
}

View File

@@ -0,0 +1,20 @@
#! /usr/bin/env python
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
# A list of C++ examples to run in order to ensure that they remain
# buildable and runnable over time. Each tuple in the list contains
#
# (example_name, do_run, do_valgrind_run).
#
# See test.py for more information.
cpp_examples = [
("main-attribute-value", "True", "True"),
]
# A list of Python examples to run in order to ensure that they remain
# runnable over time. Each tuple in the list contains
#
# (example_name, do_run).
#
# See test.py for more information.
python_examples = []