Merge distributed simulation code

This commit is contained in:
Josh Pelkey
2010-03-08 21:07:31 -05:00
parent c62514bb74
commit 5afc6bd374
57 changed files with 4616 additions and 266 deletions

View File

@@ -49,6 +49,7 @@ us a note on ns-developers mailing list. </p>
<h2>Changes to build system:</h2>
<h2>New API:</h2>
<ul>
<li><b>WiMAX net device</b>: The developed WiMAX model attempts to provide an accurate MAC and
PHY level implementation of the 802.16 specification with the Point-to-Multipoint (PMP) mode and the WirelessMAN-OFDM
@@ -65,10 +66,22 @@ interact with the Wimax models is through the helper API and through
the publicly visible attributes of the model.
The helper API is defined in src/helper/wimax-helper.{cc,h}.
Three examples containing some code that shows how to setup a 802.16 network are located under examples/wimax/
<li><b>MPI Interface for distributed simulation:</b> Enables access
to necessary MPI information such as MPI rank and size.
<li><b>Point-to-point remote channel:</b> Enables point-to-point
connection between net-devices on different simulators, for use
with distributed simulation.
<li><b>GetSystemId in simulator:</b> For use with distributed
simulation, GetSystemId returns zero by non-distributed
simulators. For the distributed simulator, it returns the
MPI rank.
</ul>
<h2>Changes to existing API:</h2>
<ul>
</pre>
<li><b>Tracing Helpers</b>: The organization of helpers for both pcap and ascii
tracing, in devices and protocols, has been reworked. Instead of each device
and protocol helper re-implementing trace enable methods, classes have been
@@ -114,6 +127,52 @@ After:
</pre>
<li><b>Serialization and Deserialization</b> in buffer, nix-vector,
packet-metadata, and packet has been modified to use raw character
buffers, rather than the Buffer class
<pre>
+ uint32_t Buffer::GetSerializedSize (void) const;
+ uint32_t Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const;
+ uint32_t Buffer::Deserialize (uint8_t* buffer, uint32_t size);
- void NixVector::Serialize (Buffer::Iterator i, uint32_t size) const;
+ uint32_t NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const;
- uint32_t NixVector::Deserialize (Buffer::Iterator i);
+ uint32_t NixVector::Deserialize (uint32_t* buffer, uint32_t size);
- void PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const;
+ uint32_t PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const;
- uint32_t PacketMetadata::Deserialize (Buffer::Iterator i);
+ uint32_t PacketMetadata::Deserialize (uint8_t* buffer, uint32_t size);
+ uint32_t Packet::GetSerializedSize (void) const;
- Buffer Packet::Serialize (void) const;
+ uint32_t Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const;
- void Packet::Deserialize (Buffer buffer);
+ Packet::Packet (uint8_t const*buffer, uint32_t size, bool magic);
</pre>
<li><b>PacketMetadata uid</b> has been changed to a 64-bit value. The
lower 32 bits give the uid, while the upper 32-bits give the MPI rank
for distributed simulations. For non-distributed simulations, the
upper 32 bits are simply zero.
<pre>
- inline PacketMetadata (uint32_t uid, uint32_t size);
+ inline PacketMetadata (uint64_t uid, uint32_t size);
- uint32_t GetUid (void) const;
+ uint64_t GetUid (void) const;
- PacketMetadata::PacketMetadata (uint32_t uid, uint32_t size);
+ PacketMetadata::PacketMetadata (uint64_t uid, uint32_t size);
- uint32_t Packet::GetUid (void) const;
+ uint64_t Packet::GetUid (void) const;
</pre>
</ul>
<h2>Changed behavior:</h2>
<ul>
</ul>
<hr>
<h1>Changes from ns-3.6 to ns-3.7</h1>

View File

@@ -36,7 +36,8 @@ New user-visible features
-------------------------
a) WiMAX net device: Allow to simulated IEEE 802.16 point to multi-point based networks
b)
b) Distributed simulation for point-to-point networks using the Message
Passing Interface (MPI) standard.
c)

View File

@@ -265,6 +265,10 @@ def register_Ns3Buffer_methods(root_module, cls):
'ns3::Buffer',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::Deserialize(uint8_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
## buffer.h: ns3::Buffer::Iterator ns3::Buffer::End() const [member function]
cls.add_method('End',
'ns3::Buffer::Iterator',
@@ -280,6 +284,11 @@ def register_Ns3Buffer_methods(root_module, cls):
'int32_t',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::GetSerializedSize() const [member function]
cls.add_method('GetSerializedSize',
'uint32_t',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
@@ -298,6 +307,11 @@ def register_Ns3Buffer_methods(root_module, cls):
cls.add_method('RemoveAtStart',
'void',
[param('uint32_t', 'start')])
## buffer.h: uint32_t ns3::Buffer::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
def register_Ns3BufferIterator_methods(root_module, cls):
@@ -583,8 +597,8 @@ def register_Ns3DataRate_methods(root_module, cls):
return
def register_Ns3PacketMetadata_methods(root_module, cls):
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint32_t uid, uint32_t size) [constructor]
cls.add_constructor([param('uint32_t', 'uid'), param('uint32_t', 'size')])
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint64_t uid, uint32_t size) [constructor]
cls.add_constructor([param('uint64_t', 'uid'), param('uint32_t', 'size')])
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(ns3::PacketMetadata const & o) [copy constructor]
cls.add_constructor([param('ns3::PacketMetadata const &', 'o')])
## packet-metadata.h: void ns3::PacketMetadata::AddAtEnd(ns3::PacketMetadata const & o) [member function]
@@ -613,10 +627,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
'ns3::PacketMetadata',
[param('uint32_t', 'start'), param('uint32_t', 'end')],
is_const=True)
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(ns3::Buffer::Iterator i) [member function]
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(uint8_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('ns3::Buffer::Iterator', 'i')])
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
## packet-metadata.h: static void ns3::PacketMetadata::Enable() [member function]
cls.add_method('Enable',
'void',
@@ -632,9 +646,9 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
'uint32_t',
[],
is_const=True)
## packet-metadata.h: uint32_t ns3::PacketMetadata::GetUid() const [member function]
## packet-metadata.h: uint64_t ns3::PacketMetadata::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
'uint64_t',
[],
is_const=True)
## packet-metadata.h: void ns3::PacketMetadata::RemoveAtEnd(uint32_t end) [member function]
@@ -653,10 +667,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
cls.add_method('RemoveTrailer',
'void',
[param('ns3::Trailer const &', 'trailer'), param('uint32_t', 'size')])
## packet-metadata.h: void ns3::PacketMetadata::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
## packet-metadata.h: uint32_t ns3::PacketMetadata::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'void',
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
@@ -1523,10 +1537,10 @@ def register_Ns3NixVector_methods(root_module, cls):
'ns3::Ptr< ns3::NixVector >',
[],
is_const=True)
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(ns3::Buffer::Iterator i) [member function]
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(uint32_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('ns3::Buffer::Iterator', 'i')])
[param('uint32_t *', 'buffer'), param('uint32_t', 'size')])
## nix-vector.h: void ns3::NixVector::DumpNixVector(std::ostream & os) const [member function]
cls.add_method('DumpNixVector',
'void',
@@ -1550,10 +1564,10 @@ def register_Ns3NixVector_methods(root_module, cls):
'ns3::TypeId',
[],
is_static=True)
## nix-vector.h: void ns3::NixVector::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
## nix-vector.h: uint32_t ns3::NixVector::Serialize(uint32_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'void',
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
'uint32_t',
[param('uint32_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
@@ -1580,6 +1594,8 @@ def register_Ns3Packet_methods(root_module, cls):
cls.add_constructor([param('ns3::Packet const &', 'o')])
## packet.h: ns3::Packet::Packet(uint32_t size) [constructor]
cls.add_constructor([param('uint32_t', 'size')])
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size, bool magic) [constructor]
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size'), param('bool', 'magic')])
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size) [constructor]
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size')])
## packet.h: void ns3::Packet::AddAtEnd(ns3::Ptr<ns3::Packet const> packet) [member function]
@@ -1633,10 +1649,6 @@ def register_Ns3Packet_methods(root_module, cls):
'ns3::Ptr< ns3::Packet >',
[param('uint32_t', 'start'), param('uint32_t', 'length')],
is_const=True)
## packet.h: void ns3::Packet::Deserialize(ns3::Buffer buffer) [member function]
cls.add_method('Deserialize',
'void',
[param('ns3::Buffer', 'buffer')])
## packet.h: static void ns3::Packet::EnableChecking() [member function]
cls.add_method('EnableChecking',
'void',
@@ -1667,14 +1679,19 @@ def register_Ns3Packet_methods(root_module, cls):
'ns3::PacketTagIterator',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetSerializedSize() const [member function]
cls.add_method('GetSerializedSize',
'uint32_t',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
## packet.h: uint64_t ns3::Packet::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
'uint64_t',
[],
is_const=True)
## packet.h: uint8_t const * ns3::Packet::PeekData() const [member function]
@@ -1739,10 +1756,10 @@ def register_Ns3Packet_methods(root_module, cls):
cls.add_method('RemoveTrailer',
'uint32_t',
[param('ns3::Trailer &', 'trailer')])
## packet.h: ns3::Buffer ns3::Packet::Serialize() const [member function]
## packet.h: uint32_t ns3::Packet::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'ns3::Buffer',
[],
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
## packet.h: void ns3::Packet::SetNixVector(ns3::Ptr<ns3::NixVector> arg0) [member function]
cls.add_method('SetNixVector',

View File

@@ -3075,7 +3075,7 @@ def register_functions(root_module):
module.add_function('TypeNameGet',
'std::string',
[],
template_parameters=['long'])
template_parameters=['long long'])
## type-name.h: extern std::string ns3::TypeNameGet() [free function]
module.add_function('TypeNameGet',
'std::string',

View File

@@ -1202,6 +1202,10 @@ def register_Ns3NodeContainer_methods(root_module, cls):
cls.add_method('Create',
'void',
[param('uint32_t', 'n')])
## node-container.h: void ns3::NodeContainer::Create(uint32_t n, uint32_t systemId) [member function]
cls.add_method('Create',
'void',
[param('uint32_t', 'n'), param('uint32_t', 'systemId')])
## node-container.h: __gnu_cxx::__normal_iterator<const ns3::Ptr<ns3::Node>*,std::vector<ns3::Ptr<ns3::Node>, std::allocator<ns3::Ptr<ns3::Node> > > > ns3::NodeContainer::End() const [member function]
cls.add_method('End',
'__gnu_cxx::__normal_iterator< ns3::Ptr< ns3::Node > const, std::vector< ns3::Ptr< ns3::Node > > >',

View File

@@ -0,0 +1,355 @@
from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
def register_types(module):
root_module = module.get_root()
## distributed-simulator-impl.h: ns3::LbtsMessage [class]
module.add_class('LbtsMessage')
## mpi-interface.h: ns3::MpiInterface [class]
module.add_class('MpiInterface')
## mpi-interface.h: ns3::SentBuffer [class]
module.add_class('SentBuffer')
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl [class]
module.add_class('DistributedSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
## Register a nested module for the namespace Config
nested_module = module.add_cpp_namespace('Config')
register_types_ns3_Config(nested_module)
## Register a nested module for the namespace TimeStepPrecision
nested_module = module.add_cpp_namespace('TimeStepPrecision')
register_types_ns3_TimeStepPrecision(nested_module)
## Register a nested module for the namespace addressUtils
nested_module = module.add_cpp_namespace('addressUtils')
register_types_ns3_addressUtils(nested_module)
## Register a nested module for the namespace aodv
nested_module = module.add_cpp_namespace('aodv')
register_types_ns3_aodv(nested_module)
## Register a nested module for the namespace dot11s
nested_module = module.add_cpp_namespace('dot11s')
register_types_ns3_dot11s(nested_module)
## Register a nested module for the namespace flame
nested_module = module.add_cpp_namespace('flame')
register_types_ns3_flame(nested_module)
## Register a nested module for the namespace internal
nested_module = module.add_cpp_namespace('internal')
register_types_ns3_internal(nested_module)
## Register a nested module for the namespace olsr
nested_module = module.add_cpp_namespace('olsr')
register_types_ns3_olsr(nested_module)
def register_types_ns3_Config(module):
root_module = module.get_root()
def register_types_ns3_TimeStepPrecision(module):
root_module = module.get_root()
def register_types_ns3_addressUtils(module):
root_module = module.get_root()
def register_types_ns3_aodv(module):
root_module = module.get_root()
def register_types_ns3_dot11s(module):
root_module = module.get_root()
def register_types_ns3_flame(module):
root_module = module.get_root()
def register_types_ns3_internal(module):
root_module = module.get_root()
def register_types_ns3_olsr(module):
root_module = module.get_root()
def register_methods(root_module):
register_Ns3LbtsMessage_methods(root_module, root_module['ns3::LbtsMessage'])
register_Ns3MpiInterface_methods(root_module, root_module['ns3::MpiInterface'])
register_Ns3SentBuffer_methods(root_module, root_module['ns3::SentBuffer'])
register_Ns3DistributedSimulatorImpl_methods(root_module, root_module['ns3::DistributedSimulatorImpl'])
return
def register_Ns3LbtsMessage_methods(root_module, cls):
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(ns3::LbtsMessage const & arg0) [copy constructor]
cls.add_constructor([param('ns3::LbtsMessage const &', 'arg0')])
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage() [constructor]
cls.add_constructor([])
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, ns3::Time const & t) [constructor]
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('ns3::Time const &', 't')])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetMyId() [member function]
cls.add_method('GetMyId',
'uint32_t',
[])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetRxCount() [member function]
cls.add_method('GetRxCount',
'uint32_t',
[])
## distributed-simulator-impl.h: ns3::Time ns3::LbtsMessage::GetSmallestTime() [member function]
cls.add_method('GetSmallestTime',
'ns3::Time',
[])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetTxCount() [member function]
cls.add_method('GetTxCount',
'uint32_t',
[])
return
def register_Ns3MpiInterface_methods(root_module, cls):
## mpi-interface.h: ns3::MpiInterface::MpiInterface() [constructor]
cls.add_constructor([])
## mpi-interface.h: ns3::MpiInterface::MpiInterface(ns3::MpiInterface const & arg0) [copy constructor]
cls.add_constructor([param('ns3::MpiInterface const &', 'arg0')])
## mpi-interface.h: static void ns3::MpiInterface::Destroy() [member function]
cls.add_method('Destroy',
'void',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::Enable(int * arg0, char * * * arg1) [member function]
cls.add_method('Enable',
'void',
[param('int *', 'arg0'), param('char * * *', 'arg1')],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetRxCount() [member function]
cls.add_method('GetRxCount',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSize() [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSystemId() [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetTxCount() [member function]
cls.add_method('GetTxCount',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static bool ns3::MpiInterface::IsEnabled() [member function]
cls.add_method('IsEnabled',
'bool',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::ReceiveMessages() [member function]
cls.add_method('ReceiveMessages',
'void',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::SendPacket(ns3::Ptr<ns3::Packet> arg0, ns3::Time const & arg1, uint32_t arg2, uint32_t arg3) [member function]
cls.add_method('SendPacket',
'void',
[param('ns3::Ptr< ns3::Packet >', 'arg0'), param('ns3::Time const &', 'arg1'), param('uint32_t', 'arg2'), param('uint32_t', 'arg3')],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::TestSendComplete() [member function]
cls.add_method('TestSendComplete',
'void',
[],
is_static=True)
return
def register_Ns3SentBuffer_methods(root_module, cls):
## mpi-interface.h: ns3::SentBuffer::SentBuffer(ns3::SentBuffer const & arg0) [copy constructor]
cls.add_constructor([param('ns3::SentBuffer const &', 'arg0')])
## mpi-interface.h: ns3::SentBuffer::SentBuffer() [constructor]
cls.add_constructor([])
## mpi-interface.h: uint8_t * ns3::SentBuffer::GetBuffer() [member function]
cls.add_method('GetBuffer',
'uint8_t *',
[])
## mpi-interface.h: MPI_Request * ns3::SentBuffer::GetRequest() [member function]
cls.add_method('GetRequest',
'MPI_Request *',
[])
## mpi-interface.h: void ns3::SentBuffer::SetBuffer(uint8_t * arg0) [member function]
cls.add_method('SetBuffer',
'void',
[param('uint8_t *', 'arg0')])
return
def register_Ns3DistributedSimulatorImpl_methods(root_module, cls):
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl(ns3::DistributedSimulatorImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::DistributedSimulatorImpl const &', 'arg0')])
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl() [constructor]
cls.add_constructor([])
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Cancel(ns3::EventId const & ev) [member function]
cls.add_method('Cancel',
'void',
[param('ns3::EventId const &', 'ev')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Destroy() [member function]
cls.add_method('Destroy',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetContext() const [member function]
cls.add_method('GetContext',
'uint32_t',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetDelayLeft(ns3::EventId const & id) const [member function]
cls.add_method('GetDelayLeft',
'ns3::Time',
[param('ns3::EventId const &', 'id')],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetMaximumSimulationTime() const [member function]
cls.add_method('GetMaximumSimulationTime',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: static ns3::TypeId ns3::DistributedSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
[],
is_static=True)
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
cls.add_method('IsExpired',
'bool',
[param('ns3::EventId const &', 'ev')],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsFinished() const [member function]
cls.add_method('IsFinished',
'bool',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Next() const [member function]
cls.add_method('Next',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Now() const [member function]
cls.add_method('Now',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Remove(ns3::EventId const & ev) [member function]
cls.add_method('Remove',
'void',
[param('ns3::EventId const &', 'ev')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Run() [member function]
cls.add_method('Run',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::RunOneEvent() [member function]
cls.add_method('RunOneEvent',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::Schedule(ns3::Time const & time, ns3::EventImpl * event) [member function]
cls.add_method('Schedule',
'ns3::EventId',
[param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleDestroy(ns3::EventImpl * event) [member function]
cls.add_method('ScheduleDestroy',
'ns3::EventId',
[param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleNow(ns3::EventImpl * event) [member function]
cls.add_method('ScheduleNow',
'ns3::EventId',
[param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::ScheduleWithContext(uint32_t context, ns3::Time const & time, ns3::EventImpl * event) [member function]
cls.add_method('ScheduleWithContext',
'void',
[param('uint32_t', 'context'), param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::SetScheduler(ns3::ObjectFactory schedulerFactory) [member function]
cls.add_method('SetScheduler',
'void',
[param('ns3::ObjectFactory', 'schedulerFactory')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop() [member function]
cls.add_method('Stop',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop(ns3::Time const & time) [member function]
cls.add_method('Stop',
'void',
[param('ns3::Time const &', 'time')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::DoDispose() [member function]
cls.add_method('DoDispose',
'void',
[],
visibility='private', is_virtual=True)
return
def register_functions(root_module):
module = root_module
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
register_functions_ns3_aodv(module.get_submodule('aodv'), root_module)
register_functions_ns3_dot11s(module.get_submodule('dot11s'), root_module)
register_functions_ns3_flame(module.get_submodule('flame'), root_module)
register_functions_ns3_internal(module.get_submodule('internal'), root_module)
register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
return
def register_functions_ns3_Config(module, root_module):
return
def register_functions_ns3_TimeStepPrecision(module, root_module):
return
def register_functions_ns3_addressUtils(module, root_module):
return
def register_functions_ns3_aodv(module, root_module):
return
def register_functions_ns3_dot11s(module, root_module):
return
def register_functions_ns3_flame(module, root_module):
return
def register_functions_ns3_internal(module, root_module):
return
def register_functions_ns3_olsr(module, root_module):
return

View File

@@ -9,6 +9,8 @@ def register_types(module):
module.add_class('PointToPointChannel', parent=root_module['ns3::Channel'])
## point-to-point-net-device.h: ns3::PointToPointNetDevice [class]
module.add_class('PointToPointNetDevice', parent=root_module['ns3::NetDevice'])
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel [class]
module.add_class('PointToPointRemoteChannel', parent=root_module['ns3::PointToPointChannel'])
## Register a nested module for the namespace Config
@@ -94,6 +96,7 @@ def register_methods(root_module):
register_Ns3PppHeader_methods(root_module, root_module['ns3::PppHeader'])
register_Ns3PointToPointChannel_methods(root_module, root_module['ns3::PointToPointChannel'])
register_Ns3PointToPointNetDevice_methods(root_module, root_module['ns3::PointToPointNetDevice'])
register_Ns3PointToPointRemoteChannel_methods(root_module, root_module['ns3::PointToPointRemoteChannel'])
return
def register_Ns3PppHeader_methods(root_module, cls):
@@ -173,7 +176,28 @@ def register_Ns3PointToPointChannel_methods(root_module, cls):
## point-to-point-channel.h: bool ns3::PointToPointChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
cls.add_method('TransmitStart',
'bool',
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')])
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
is_virtual=True)
## point-to-point-channel.h: ns3::Time ns3::PointToPointChannel::GetDelay() const [member function]
cls.add_method('GetDelay',
'ns3::Time',
[],
is_const=True, visibility='protected')
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetDestination(uint32_t i) const [member function]
cls.add_method('GetDestination',
'ns3::Ptr< ns3::PointToPointNetDevice >',
[param('uint32_t', 'i')],
is_const=True, visibility='protected')
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetSource(uint32_t i) const [member function]
cls.add_method('GetSource',
'ns3::Ptr< ns3::PointToPointNetDevice >',
[param('uint32_t', 'i')],
is_const=True, visibility='protected')
## point-to-point-channel.h: bool ns3::PointToPointChannel::IsInitialized() const [member function]
cls.add_method('IsInitialized',
'bool',
[],
is_const=True, visibility='protected')
return
def register_Ns3PointToPointNetDevice_methods(root_module, cls):
@@ -351,6 +375,23 @@ def register_Ns3PointToPointNetDevice_methods(root_module, cls):
visibility='private', is_virtual=True)
return
def register_Ns3PointToPointRemoteChannel_methods(root_module, cls):
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel(ns3::PointToPointRemoteChannel const & arg0) [copy constructor]
cls.add_constructor([param('ns3::PointToPointRemoteChannel const &', 'arg0')])
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel() [constructor]
cls.add_constructor([])
## point-to-point-remote-channel.h: static ns3::TypeId ns3::PointToPointRemoteChannel::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
[],
is_static=True)
## point-to-point-remote-channel.h: bool ns3::PointToPointRemoteChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
cls.add_method('TransmitStart',
'bool',
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
is_virtual=True)
return
def register_functions(root_module):
module = root_module
register_functions_ns3_Config(module.get_submodule('Config'), root_module)

View File

@@ -317,6 +317,11 @@ def register_Ns3Simulator_methods(root_module, cls):
'ns3::Time',
[],
is_static=True)
## simulator.h: static uint32_t ns3::Simulator::GetSystemId() [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_static=True)
## simulator.h: static bool ns3::Simulator::IsExpired(ns3::EventId const & id) [member function]
cls.add_method('IsExpired',
'bool',
@@ -795,6 +800,11 @@ def register_Ns3SimulatorImpl_methods(root_module, cls):
'ns3::Time',
[],
is_pure_virtual=True, is_const=True, is_virtual=True)
## simulator-impl.h: uint32_t ns3::SimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_pure_virtual=True, is_const=True, is_virtual=True)
## simulator-impl.h: bool ns3::SimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
cls.add_method('IsExpired',
'bool',
@@ -1129,6 +1139,11 @@ def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
'ns3::Time',
[],
is_const=True, is_virtual=True)
## default-simulator-impl.h: uint32_t ns3::DefaultSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## default-simulator-impl.h: static ns3::TypeId ns3::DefaultSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
@@ -1423,6 +1438,11 @@ def register_Ns3RealtimeSimulatorImpl_methods(root_module, cls):
'ns3::RealtimeSimulatorImpl::SynchronizationMode',
[],
is_const=True)
## realtime-simulator-impl.h: uint32_t ns3::RealtimeSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## realtime-simulator-impl.h: static ns3::TypeId ns3::RealtimeSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',

View File

@@ -17,6 +17,7 @@ import ns3_module_simulator
import ns3_module_test
import ns3_module_common
import ns3_module_mobility
import ns3_module_mpi
import ns3_module_contrib
import ns3_module_node
import ns3_module_bridge
@@ -109,6 +110,17 @@ def register_types(module):
ns3_module_mobility__local.register_types(module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_types(module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_types(module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_types(module)
@@ -572,6 +584,17 @@ def register_methods(root_module):
ns3_module_mobility__local.register_methods(root_module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_methods(root_module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_methods(root_module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_methods(root_module)
@@ -950,6 +973,17 @@ def register_functions(root_module):
ns3_module_mobility__local.register_functions(root_module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_functions(root_module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_functions(root_module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_functions(root_module)

View File

@@ -265,6 +265,10 @@ def register_Ns3Buffer_methods(root_module, cls):
'ns3::Buffer',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::Deserialize(uint8_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
## buffer.h: ns3::Buffer::Iterator ns3::Buffer::End() const [member function]
cls.add_method('End',
'ns3::Buffer::Iterator',
@@ -280,6 +284,11 @@ def register_Ns3Buffer_methods(root_module, cls):
'int32_t',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::GetSerializedSize() const [member function]
cls.add_method('GetSerializedSize',
'uint32_t',
[],
is_const=True)
## buffer.h: uint32_t ns3::Buffer::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
@@ -298,6 +307,11 @@ def register_Ns3Buffer_methods(root_module, cls):
cls.add_method('RemoveAtStart',
'void',
[param('uint32_t', 'start')])
## buffer.h: uint32_t ns3::Buffer::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
def register_Ns3BufferIterator_methods(root_module, cls):
@@ -583,8 +597,8 @@ def register_Ns3DataRate_methods(root_module, cls):
return
def register_Ns3PacketMetadata_methods(root_module, cls):
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint32_t uid, uint32_t size) [constructor]
cls.add_constructor([param('uint32_t', 'uid'), param('uint32_t', 'size')])
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint64_t uid, uint32_t size) [constructor]
cls.add_constructor([param('uint64_t', 'uid'), param('uint32_t', 'size')])
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(ns3::PacketMetadata const & o) [copy constructor]
cls.add_constructor([param('ns3::PacketMetadata const &', 'o')])
## packet-metadata.h: void ns3::PacketMetadata::AddAtEnd(ns3::PacketMetadata const & o) [member function]
@@ -613,10 +627,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
'ns3::PacketMetadata',
[param('uint32_t', 'start'), param('uint32_t', 'end')],
is_const=True)
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(ns3::Buffer::Iterator i) [member function]
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(uint8_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('ns3::Buffer::Iterator', 'i')])
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
## packet-metadata.h: static void ns3::PacketMetadata::Enable() [member function]
cls.add_method('Enable',
'void',
@@ -632,9 +646,9 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
'uint32_t',
[],
is_const=True)
## packet-metadata.h: uint32_t ns3::PacketMetadata::GetUid() const [member function]
## packet-metadata.h: uint64_t ns3::PacketMetadata::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
'uint64_t',
[],
is_const=True)
## packet-metadata.h: void ns3::PacketMetadata::RemoveAtEnd(uint32_t end) [member function]
@@ -653,10 +667,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
cls.add_method('RemoveTrailer',
'void',
[param('ns3::Trailer const &', 'trailer'), param('uint32_t', 'size')])
## packet-metadata.h: void ns3::PacketMetadata::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
## packet-metadata.h: uint32_t ns3::PacketMetadata::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'void',
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
@@ -1523,10 +1537,10 @@ def register_Ns3NixVector_methods(root_module, cls):
'ns3::Ptr< ns3::NixVector >',
[],
is_const=True)
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(ns3::Buffer::Iterator i) [member function]
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(uint32_t * buffer, uint32_t size) [member function]
cls.add_method('Deserialize',
'uint32_t',
[param('ns3::Buffer::Iterator', 'i')])
[param('uint32_t *', 'buffer'), param('uint32_t', 'size')])
## nix-vector.h: void ns3::NixVector::DumpNixVector(std::ostream & os) const [member function]
cls.add_method('DumpNixVector',
'void',
@@ -1550,10 +1564,10 @@ def register_Ns3NixVector_methods(root_module, cls):
'ns3::TypeId',
[],
is_static=True)
## nix-vector.h: void ns3::NixVector::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
## nix-vector.h: uint32_t ns3::NixVector::Serialize(uint32_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'void',
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
'uint32_t',
[param('uint32_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
return
@@ -1580,6 +1594,8 @@ def register_Ns3Packet_methods(root_module, cls):
cls.add_constructor([param('ns3::Packet const &', 'o')])
## packet.h: ns3::Packet::Packet(uint32_t size) [constructor]
cls.add_constructor([param('uint32_t', 'size')])
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size, bool magic) [constructor]
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size'), param('bool', 'magic')])
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size) [constructor]
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size')])
## packet.h: void ns3::Packet::AddAtEnd(ns3::Ptr<ns3::Packet const> packet) [member function]
@@ -1633,10 +1649,6 @@ def register_Ns3Packet_methods(root_module, cls):
'ns3::Ptr< ns3::Packet >',
[param('uint32_t', 'start'), param('uint32_t', 'length')],
is_const=True)
## packet.h: void ns3::Packet::Deserialize(ns3::Buffer buffer) [member function]
cls.add_method('Deserialize',
'void',
[param('ns3::Buffer', 'buffer')])
## packet.h: static void ns3::Packet::EnableChecking() [member function]
cls.add_method('EnableChecking',
'void',
@@ -1667,14 +1679,19 @@ def register_Ns3Packet_methods(root_module, cls):
'ns3::PacketTagIterator',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetSerializedSize() const [member function]
cls.add_method('GetSerializedSize',
'uint32_t',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_const=True)
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
## packet.h: uint64_t ns3::Packet::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
'uint64_t',
[],
is_const=True)
## packet.h: uint8_t const * ns3::Packet::PeekData() const [member function]
@@ -1739,10 +1756,10 @@ def register_Ns3Packet_methods(root_module, cls):
cls.add_method('RemoveTrailer',
'uint32_t',
[param('ns3::Trailer &', 'trailer')])
## packet.h: ns3::Buffer ns3::Packet::Serialize() const [member function]
## packet.h: uint32_t ns3::Packet::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
cls.add_method('Serialize',
'ns3::Buffer',
[],
'uint32_t',
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
is_const=True)
## packet.h: void ns3::Packet::SetNixVector(ns3::Ptr<ns3::NixVector> arg0) [member function]
cls.add_method('SetNixVector',

View File

@@ -1202,6 +1202,10 @@ def register_Ns3NodeContainer_methods(root_module, cls):
cls.add_method('Create',
'void',
[param('uint32_t', 'n')])
## node-container.h: void ns3::NodeContainer::Create(uint32_t n, uint32_t systemId) [member function]
cls.add_method('Create',
'void',
[param('uint32_t', 'n'), param('uint32_t', 'systemId')])
## node-container.h: __gnu_cxx::__normal_iterator<const ns3::Ptr<ns3::Node>*,std::vector<ns3::Ptr<ns3::Node>, std::allocator<ns3::Ptr<ns3::Node> > > > ns3::NodeContainer::End() const [member function]
cls.add_method('End',
'__gnu_cxx::__normal_iterator< ns3::Ptr< ns3::Node > const, std::vector< ns3::Ptr< ns3::Node > > >',

View File

@@ -0,0 +1,355 @@
from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
def register_types(module):
root_module = module.get_root()
## distributed-simulator-impl.h: ns3::LbtsMessage [class]
module.add_class('LbtsMessage')
## mpi-interface.h: ns3::MpiInterface [class]
module.add_class('MpiInterface')
## mpi-interface.h: ns3::SentBuffer [class]
module.add_class('SentBuffer')
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl [class]
module.add_class('DistributedSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
## Register a nested module for the namespace Config
nested_module = module.add_cpp_namespace('Config')
register_types_ns3_Config(nested_module)
## Register a nested module for the namespace TimeStepPrecision
nested_module = module.add_cpp_namespace('TimeStepPrecision')
register_types_ns3_TimeStepPrecision(nested_module)
## Register a nested module for the namespace addressUtils
nested_module = module.add_cpp_namespace('addressUtils')
register_types_ns3_addressUtils(nested_module)
## Register a nested module for the namespace aodv
nested_module = module.add_cpp_namespace('aodv')
register_types_ns3_aodv(nested_module)
## Register a nested module for the namespace dot11s
nested_module = module.add_cpp_namespace('dot11s')
register_types_ns3_dot11s(nested_module)
## Register a nested module for the namespace flame
nested_module = module.add_cpp_namespace('flame')
register_types_ns3_flame(nested_module)
## Register a nested module for the namespace internal
nested_module = module.add_cpp_namespace('internal')
register_types_ns3_internal(nested_module)
## Register a nested module for the namespace olsr
nested_module = module.add_cpp_namespace('olsr')
register_types_ns3_olsr(nested_module)
def register_types_ns3_Config(module):
root_module = module.get_root()
def register_types_ns3_TimeStepPrecision(module):
root_module = module.get_root()
def register_types_ns3_addressUtils(module):
root_module = module.get_root()
def register_types_ns3_aodv(module):
root_module = module.get_root()
def register_types_ns3_dot11s(module):
root_module = module.get_root()
def register_types_ns3_flame(module):
root_module = module.get_root()
def register_types_ns3_internal(module):
root_module = module.get_root()
def register_types_ns3_olsr(module):
root_module = module.get_root()
def register_methods(root_module):
register_Ns3LbtsMessage_methods(root_module, root_module['ns3::LbtsMessage'])
register_Ns3MpiInterface_methods(root_module, root_module['ns3::MpiInterface'])
register_Ns3SentBuffer_methods(root_module, root_module['ns3::SentBuffer'])
register_Ns3DistributedSimulatorImpl_methods(root_module, root_module['ns3::DistributedSimulatorImpl'])
return
def register_Ns3LbtsMessage_methods(root_module, cls):
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(ns3::LbtsMessage const & arg0) [copy constructor]
cls.add_constructor([param('ns3::LbtsMessage const &', 'arg0')])
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage() [constructor]
cls.add_constructor([])
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, ns3::Time const & t) [constructor]
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('ns3::Time const &', 't')])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetMyId() [member function]
cls.add_method('GetMyId',
'uint32_t',
[])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetRxCount() [member function]
cls.add_method('GetRxCount',
'uint32_t',
[])
## distributed-simulator-impl.h: ns3::Time ns3::LbtsMessage::GetSmallestTime() [member function]
cls.add_method('GetSmallestTime',
'ns3::Time',
[])
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetTxCount() [member function]
cls.add_method('GetTxCount',
'uint32_t',
[])
return
def register_Ns3MpiInterface_methods(root_module, cls):
## mpi-interface.h: ns3::MpiInterface::MpiInterface() [constructor]
cls.add_constructor([])
## mpi-interface.h: ns3::MpiInterface::MpiInterface(ns3::MpiInterface const & arg0) [copy constructor]
cls.add_constructor([param('ns3::MpiInterface const &', 'arg0')])
## mpi-interface.h: static void ns3::MpiInterface::Destroy() [member function]
cls.add_method('Destroy',
'void',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::Enable(int * arg0, char * * * arg1) [member function]
cls.add_method('Enable',
'void',
[param('int *', 'arg0'), param('char * * *', 'arg1')],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetRxCount() [member function]
cls.add_method('GetRxCount',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSize() [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSystemId() [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetTxCount() [member function]
cls.add_method('GetTxCount',
'uint32_t',
[],
is_static=True)
## mpi-interface.h: static bool ns3::MpiInterface::IsEnabled() [member function]
cls.add_method('IsEnabled',
'bool',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::ReceiveMessages() [member function]
cls.add_method('ReceiveMessages',
'void',
[],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::SendPacket(ns3::Ptr<ns3::Packet> arg0, ns3::Time const & arg1, uint32_t arg2, uint32_t arg3) [member function]
cls.add_method('SendPacket',
'void',
[param('ns3::Ptr< ns3::Packet >', 'arg0'), param('ns3::Time const &', 'arg1'), param('uint32_t', 'arg2'), param('uint32_t', 'arg3')],
is_static=True)
## mpi-interface.h: static void ns3::MpiInterface::TestSendComplete() [member function]
cls.add_method('TestSendComplete',
'void',
[],
is_static=True)
return
def register_Ns3SentBuffer_methods(root_module, cls):
## mpi-interface.h: ns3::SentBuffer::SentBuffer(ns3::SentBuffer const & arg0) [copy constructor]
cls.add_constructor([param('ns3::SentBuffer const &', 'arg0')])
## mpi-interface.h: ns3::SentBuffer::SentBuffer() [constructor]
cls.add_constructor([])
## mpi-interface.h: uint8_t * ns3::SentBuffer::GetBuffer() [member function]
cls.add_method('GetBuffer',
'uint8_t *',
[])
## mpi-interface.h: MPI_Request * ns3::SentBuffer::GetRequest() [member function]
cls.add_method('GetRequest',
'MPI_Request *',
[])
## mpi-interface.h: void ns3::SentBuffer::SetBuffer(uint8_t * arg0) [member function]
cls.add_method('SetBuffer',
'void',
[param('uint8_t *', 'arg0')])
return
def register_Ns3DistributedSimulatorImpl_methods(root_module, cls):
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl(ns3::DistributedSimulatorImpl const & arg0) [copy constructor]
cls.add_constructor([param('ns3::DistributedSimulatorImpl const &', 'arg0')])
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl() [constructor]
cls.add_constructor([])
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Cancel(ns3::EventId const & ev) [member function]
cls.add_method('Cancel',
'void',
[param('ns3::EventId const &', 'ev')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Destroy() [member function]
cls.add_method('Destroy',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetContext() const [member function]
cls.add_method('GetContext',
'uint32_t',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetDelayLeft(ns3::EventId const & id) const [member function]
cls.add_method('GetDelayLeft',
'ns3::Time',
[param('ns3::EventId const &', 'id')],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetMaximumSimulationTime() const [member function]
cls.add_method('GetMaximumSimulationTime',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: static ns3::TypeId ns3::DistributedSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
[],
is_static=True)
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
cls.add_method('IsExpired',
'bool',
[param('ns3::EventId const &', 'ev')],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsFinished() const [member function]
cls.add_method('IsFinished',
'bool',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Next() const [member function]
cls.add_method('Next',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Now() const [member function]
cls.add_method('Now',
'ns3::Time',
[],
is_const=True, is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Remove(ns3::EventId const & ev) [member function]
cls.add_method('Remove',
'void',
[param('ns3::EventId const &', 'ev')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Run() [member function]
cls.add_method('Run',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::RunOneEvent() [member function]
cls.add_method('RunOneEvent',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::Schedule(ns3::Time const & time, ns3::EventImpl * event) [member function]
cls.add_method('Schedule',
'ns3::EventId',
[param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleDestroy(ns3::EventImpl * event) [member function]
cls.add_method('ScheduleDestroy',
'ns3::EventId',
[param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleNow(ns3::EventImpl * event) [member function]
cls.add_method('ScheduleNow',
'ns3::EventId',
[param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::ScheduleWithContext(uint32_t context, ns3::Time const & time, ns3::EventImpl * event) [member function]
cls.add_method('ScheduleWithContext',
'void',
[param('uint32_t', 'context'), param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::SetScheduler(ns3::ObjectFactory schedulerFactory) [member function]
cls.add_method('SetScheduler',
'void',
[param('ns3::ObjectFactory', 'schedulerFactory')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop() [member function]
cls.add_method('Stop',
'void',
[],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop(ns3::Time const & time) [member function]
cls.add_method('Stop',
'void',
[param('ns3::Time const &', 'time')],
is_virtual=True)
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::DoDispose() [member function]
cls.add_method('DoDispose',
'void',
[],
visibility='private', is_virtual=True)
return
def register_functions(root_module):
module = root_module
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
register_functions_ns3_aodv(module.get_submodule('aodv'), root_module)
register_functions_ns3_dot11s(module.get_submodule('dot11s'), root_module)
register_functions_ns3_flame(module.get_submodule('flame'), root_module)
register_functions_ns3_internal(module.get_submodule('internal'), root_module)
register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
return
def register_functions_ns3_Config(module, root_module):
return
def register_functions_ns3_TimeStepPrecision(module, root_module):
return
def register_functions_ns3_addressUtils(module, root_module):
return
def register_functions_ns3_aodv(module, root_module):
return
def register_functions_ns3_dot11s(module, root_module):
return
def register_functions_ns3_flame(module, root_module):
return
def register_functions_ns3_internal(module, root_module):
return
def register_functions_ns3_olsr(module, root_module):
return

View File

@@ -9,6 +9,8 @@ def register_types(module):
module.add_class('PointToPointChannel', parent=root_module['ns3::Channel'])
## point-to-point-net-device.h: ns3::PointToPointNetDevice [class]
module.add_class('PointToPointNetDevice', parent=root_module['ns3::NetDevice'])
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel [class]
module.add_class('PointToPointRemoteChannel', parent=root_module['ns3::PointToPointChannel'])
## Register a nested module for the namespace Config
@@ -94,6 +96,7 @@ def register_methods(root_module):
register_Ns3PppHeader_methods(root_module, root_module['ns3::PppHeader'])
register_Ns3PointToPointChannel_methods(root_module, root_module['ns3::PointToPointChannel'])
register_Ns3PointToPointNetDevice_methods(root_module, root_module['ns3::PointToPointNetDevice'])
register_Ns3PointToPointRemoteChannel_methods(root_module, root_module['ns3::PointToPointRemoteChannel'])
return
def register_Ns3PppHeader_methods(root_module, cls):
@@ -173,7 +176,28 @@ def register_Ns3PointToPointChannel_methods(root_module, cls):
## point-to-point-channel.h: bool ns3::PointToPointChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
cls.add_method('TransmitStart',
'bool',
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')])
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
is_virtual=True)
## point-to-point-channel.h: ns3::Time ns3::PointToPointChannel::GetDelay() const [member function]
cls.add_method('GetDelay',
'ns3::Time',
[],
is_const=True, visibility='protected')
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetDestination(uint32_t i) const [member function]
cls.add_method('GetDestination',
'ns3::Ptr< ns3::PointToPointNetDevice >',
[param('uint32_t', 'i')],
is_const=True, visibility='protected')
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetSource(uint32_t i) const [member function]
cls.add_method('GetSource',
'ns3::Ptr< ns3::PointToPointNetDevice >',
[param('uint32_t', 'i')],
is_const=True, visibility='protected')
## point-to-point-channel.h: bool ns3::PointToPointChannel::IsInitialized() const [member function]
cls.add_method('IsInitialized',
'bool',
[],
is_const=True, visibility='protected')
return
def register_Ns3PointToPointNetDevice_methods(root_module, cls):
@@ -351,6 +375,23 @@ def register_Ns3PointToPointNetDevice_methods(root_module, cls):
visibility='private', is_virtual=True)
return
def register_Ns3PointToPointRemoteChannel_methods(root_module, cls):
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel(ns3::PointToPointRemoteChannel const & arg0) [copy constructor]
cls.add_constructor([param('ns3::PointToPointRemoteChannel const &', 'arg0')])
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel() [constructor]
cls.add_constructor([])
## point-to-point-remote-channel.h: static ns3::TypeId ns3::PointToPointRemoteChannel::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
[],
is_static=True)
## point-to-point-remote-channel.h: bool ns3::PointToPointRemoteChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
cls.add_method('TransmitStart',
'bool',
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
is_virtual=True)
return
def register_functions(root_module):
module = root_module
register_functions_ns3_Config(module.get_submodule('Config'), root_module)

View File

@@ -317,6 +317,11 @@ def register_Ns3Simulator_methods(root_module, cls):
'ns3::Time',
[],
is_static=True)
## simulator.h: static uint32_t ns3::Simulator::GetSystemId() [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_static=True)
## simulator.h: static bool ns3::Simulator::IsExpired(ns3::EventId const & id) [member function]
cls.add_method('IsExpired',
'bool',
@@ -795,6 +800,11 @@ def register_Ns3SimulatorImpl_methods(root_module, cls):
'ns3::Time',
[],
is_pure_virtual=True, is_const=True, is_virtual=True)
## simulator-impl.h: uint32_t ns3::SimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_pure_virtual=True, is_const=True, is_virtual=True)
## simulator-impl.h: bool ns3::SimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
cls.add_method('IsExpired',
'bool',
@@ -1129,6 +1139,11 @@ def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
'ns3::Time',
[],
is_const=True, is_virtual=True)
## default-simulator-impl.h: uint32_t ns3::DefaultSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## default-simulator-impl.h: static ns3::TypeId ns3::DefaultSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',
@@ -1423,6 +1438,11 @@ def register_Ns3RealtimeSimulatorImpl_methods(root_module, cls):
'ns3::RealtimeSimulatorImpl::SynchronizationMode',
[],
is_const=True)
## realtime-simulator-impl.h: uint32_t ns3::RealtimeSimulatorImpl::GetSystemId() const [member function]
cls.add_method('GetSystemId',
'uint32_t',
[],
is_const=True, is_virtual=True)
## realtime-simulator-impl.h: static ns3::TypeId ns3::RealtimeSimulatorImpl::GetTypeId() [member function]
cls.add_method('GetTypeId',
'ns3::TypeId',

View File

@@ -17,6 +17,7 @@ import ns3_module_simulator
import ns3_module_test
import ns3_module_common
import ns3_module_mobility
import ns3_module_mpi
import ns3_module_contrib
import ns3_module_node
import ns3_module_bridge
@@ -109,6 +110,17 @@ def register_types(module):
ns3_module_mobility__local.register_types(module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_types(module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_types(module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_types(module)
@@ -572,6 +584,17 @@ def register_methods(root_module):
ns3_module_mobility__local.register_methods(root_module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_methods(root_module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_methods(root_module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_methods(root_module)
@@ -950,6 +973,17 @@ def register_functions(root_module):
ns3_module_mobility__local.register_functions(root_module)
root_module.end_section('ns3_module_mobility')
root_module.begin_section('ns3_module_mpi')
ns3_module_mpi.register_functions(root_module)
try:
import ns3_module_mpi__local
except ImportError:
pass
else:
ns3_module_mpi__local.register_functions(root_module)
root_module.end_section('ns3_module_mpi')
root_module.begin_section('ns3_module_contrib')
ns3_module_contrib.register_functions(root_module)

View File

@@ -58,6 +58,7 @@ CHAPTERS = \
python.texi \
random.texi \
realtime.texi \
distributed.texi \
routing.texi \
simple.texi \
sockets.texi \

225
doc/manual/distributed.texi Normal file
View File

@@ -0,0 +1,225 @@
@node Distributed
@chapter Distributed Simulation with MPI
@anchor{chap:Distributed}
@menu
* Current Implementation Details::
* Running Distributed Simulations::
* Tracing During Distributed Simulations::
@end menu
Parallel and distributed discrete event simulation allows the execution of a
single simulation program on multiple processors. By splitting up the
simulation into logical processes, LPs, each LP can be executed by a different
processor. This simulation methodology enables very large-scale simulations by
leveraging increased processing power and memory availability. In order to
ensure proper execution of a distributed simulation, message passing between
LPs is required. To support distributed simulation in ns-3, the standard
Message Passing Interface (MPI) is used, along with a new distributed simulator
class. Currently, dividing a simulation for distributed purposes in ns-3 can
only occur across point-to-point links.
@node Current Implementation Details
@section Current Implementation Details
During the course of a distributed simulation, many packets must cross
simulator boundaries. In other words, a packet that originated on one LP
is destined for a different LP, and in order to make this transition, a message
containing the packet contents must be sent to the remote LP. Upon receiving
this message, the remote LP can rebuild the packet and proceed as normal. The
process of sending an receiving messages between LPs is handled easily by the
new MPI interface in ns-3.
Along with simple message passing between LPs, a distributed simulator is used
on each LP to determine which events to process. It is important to process
events in time-stamped order to ensure proper simulation execution. If a
LP receives a message containing an event from the past, clearly this is an
issue, since this event could change other events which have already been
executed. To address this problem, a conservative synchronization algorithm with
lookahead is used in ns-3. For more information on different synchronization
approaches and parallel and distributed simulation in general, please refer to
"Parallel and Distributed Simulation Systems" by Richard Fujimoto.
@subsection Remote point-to-point links
As described in the introduction, dividing a simulation for distributed purposes
in ns-3 currently can only occur across point-to-point links; therefore, the idea
of remote point-to-point links is very important for distributed simulation in ns-3.
When a point-to-point link is installed, connecting two nodes, the point-to-point
helper checks the system id, or rank, of both nodes. The rank should be assigned
during node creation for distributed simulation and is intended to signify on which
LP a node belongs. If the two nodes are on the same rank, a regular point-to-point
link is created. If, however, the two nodes are on different ranks, then these nodes
are intended for different LPs, and a remote point-to-point link is used. If a packet
is to be sent across a remote point-to-point link, MPI is used to send the message to
the remote LP.
@subsection Distributing the topology
Currently, the full topology is created on each rank, regardless of the individual node
system ids. Only the applications are specific to a rank. For example, consider
node 1 on LP 1 and node 2 on LP 2, with a traffic generator on node 1. Both node
1 and node 2 will be created on both LP1 and LP2; however, the traffic generator
will only be installed on LP1. While this is not optimal for memory efficiency, it
does simplify routing, since all current routing implementations in ns-3 will work
with distributed simulation.
@node Running Distributed Simulations
@section Running Distributed Simulations
@subsection Prerequisites
Ensure that MPI is installed, as well as mpic++. In Ubuntu repositories,
these are openmpi-bin, openmpi-common, openmpi-doc, libopenmpi-dev. In
Fedora, these are openmpi and openmpi-devel.
Note:
There is a conflict on some Fedora systems between libotf and openmpi. A
possible "quick-fix" is to yum remove libotf before installing openmpi.
This will remove conflict, but it will also remove emacs. Alternatively,
these steps could be followed to resolve the conflict:
@verbatim
1) Rename the tiny otfdump which emacs says it needs:
mv /usr/bin/otfdump /usr/bin/otfdump.emacs-version
2) Manually resolve openmpi dependencies:
sudo yum install libgfortran libtorque numactl
3) Download rpm packages:
openmpi-1.3.1-1.fc11.i586.rpm
openmpi-devel-1.3.1-1.fc11.i586.rpm
openmpi-libs-1.3.1-1.fc11.i586.rpm
openmpi-vt-1.3.1-1.fc11.i586.rpm
from
http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/
4) Force the packages in:
sudo rpm -ivh --force openmpi-1.3.1-1.fc11.i586.rpm
openmpi-libs-1.3.1-1.fc11.i586.rpm openmpi-devel-1.3.1-1.fc11.i586.rpm
openmpi-vt-1.3.1-1.fc11.i586.rpm
@end verbatim
Also, it may be necessary to add the openmpi bin directory to PATH in order to
execute mpic++ and mpirun from the command line. Alternatively, the full path
to these executables can be used. Finally, if openmpi complains about the
inablility to open shared libraries, such as libmpi_cxx.so.0, it may be
necessary to add the openmpi lib directory to LD_LIBRARY_PATH.
@subsection Building and Running Examples
If you already built ns-3 without MPI enabled, you must re-build:
@verbatim
./waf distclean
@end verbatim
Configure ns-3 with the --enable-mpi option:
@verbatim
./waf -d debug configure --enable-mpi
@end verbatim
Ensure that MPI is enabled by checking the optional features shown from the
output of configure.
Next, build ns-3:
@verbatim
./waf
@end verbatim
After building ns-3 with mpi enabled, the example programs are now ready to
run with mpirun. Here are a few examples (from the root ns-3 directory):
@verbatim
mpirun -np 2 ./waf --run simple-distributed
mpirun -np 4 -machinefile mpihosts ./waf --run 'nms-udp-nix --LAN=2 --CN=4 --nix=1 --tracing=0'
@end verbatim
The np switch is the number of logical processors to use. The
machinefile switch is which machines to use. In order to use machinefile,
the target file must exist (in this case mpihosts). This can simply contain
something like:
@verbatim
localhost
localhost
localhost
...
@endverbatim
Or if you have a cluster of machines, you can name them.
** NOTE: Some users have experienced issues using mpirun and waf together.
An alternative way to run distributed examples is shown below:
@verbatim
./waf shell
cd build/debug
mpirun -np 2 examples/mpi/simple-distributed
@end verbatim
@subsection Creating custom topologies
The example programs in examples/mpi give a good idea of how to create
different topologies for distributed simulation. The main points are
assigning system ids to individual nodes, creating point-to-point
links where the simulation should be divided, and installing
applications only on the LP associated with the target node.
Assigning system ids to nodes is simple and can be handled two different
ways. First, a NodeContainer can be used to create the nodes and assign
system ids:
@verbatim
NodeContainer nodes;
nodes.Create (5, 1); // Creates 5 nodes with system id 1.
@end verbatim
Alternatively, nodes can be created individually, assigned system ids, and
added to a NodeContainer. This is useful if a NodeContainer holds nodes with
different system ids:
@verbatim
NodeContainer nodes;
Ptr<Node> node1 = CreateObject<Node> (0); // Create node1 with system id 0
Ptr<Node> node2 = CreateObject<Node> (1); // Create node2 with system id 1
nodes.Add (node1);
nodes.Add (node2);
@end verbatim
Next, where the simulation is divided is determined by the placement of
point-to-point links. If a point-to-point link is created between two
nodes with different system ids, a remote point-to-point link is created,
as described in @ref{Current Implementation Details}.
Finally, installing applications only on the LP associated with the target
node is very important. For example, if a traffic generator is to be placed
on node 0, which is on LP0, only LP0 should install this application.
This is easily accomplished by first checking the simulator system id, and
ensuring that it matches the system id of the target node before installing
the application.
@node Tracing During Distributed Simulations
@section Tracing During Distributed Simulations
Depending on the system id (rank) of the simulator, the information traced
will be different, since traffic originating on one simulator is not seen
by another simulator until it reaches nodes specific to that simulator. The
easiest way to keep track of different traces is to just name the trace files
or pcaps differently, based on the system id of the simulator. For example,
something like this should work well, assuming all of these local variables
were previously defined:
@verbatim
if (MpiInterface::GetSystemId () == 0)
{
pointToPoint.EnablePcapAll ("distributed-rank0");
phy.EnablePcap ("distributed-rank0", apDevices.Get (0));
csma.EnablePcap ("distributed-rank0", csmaDevices.Get (0), true);
}
else if (MpiInterface::GetSystemId () == 1)
{
pointToPoint.EnablePcapAll ("distributed-rank1");
phy.EnablePcap ("distributed-rank1", apDevices.Get (0));
csma.EnablePcap ("distributed-rank1", csmaDevices.Get (0), true);
}
@end verbatim

View File

@@ -96,6 +96,7 @@ Simulator version:
* Logging::
* Tracing::
* RealTime::
* Distributed::
* Packets::
* Helpers::
* Python::
@@ -140,6 +141,7 @@ Simulator version:
@include log.texi
@include tracing.texi
@include realtime.texi
@include distributed.texi
@include packets.texi
@include helpers.texi
@include python.texi

614
examples/mpi/nms-udp-nix.cc Normal file
View File

@@ -0,0 +1,614 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* (c) 2009, GTech Systems, Inc. - Alfred Park <park@gtech-systems.com>
*
* DARPA NMS Campus Network Model
*
* This topology replicates the original NMS Campus Network model
* with the exception of chord links (which were never utilized in the
* original model)
* Link Bandwidths and Delays may not be the same as the original
* specifications
*
* Modified for distributed simulation by Josh Pelkey <jpelkey@gatech.edu>
*
* The fundamental unit of the NMS model consists of a campus network. The
* campus network topology can been seen here:
* http://www.nsnam.org/~jpelkey3/nms.png
* The number of hosts (default 42) is variable. Finally, an arbitrary
* number of these campus networks can be connected together (default 2)
* to make very large simulations.
*/
// for timing functions
#include <cstdlib>
#include <sys/time.h>
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/global-routing-module.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/mpi-interface.h"
#ifdef NS3_MPI
#include <mpi.h>
#endif
using namespace std;
using namespace ns3;
typedef struct timeval TIMER_TYPE;
#define TIMER_NOW(_t) gettimeofday (&_t,NULL);
#define TIMER_SECONDS(_t) ((double)(_t).tv_sec + (_t).tv_usec * 1e-6)
#define TIMER_DIFF(_t1, _t2) (TIMER_SECONDS (_t1) - TIMER_SECONDS (_t2))
NS_LOG_COMPONENT_DEFINE ("CampusNetworkModel");
int
main (int argc, char *argv[])
{
#ifdef NS3_MPI
// Enable MPI with the command line arguments
MpiInterface::Enable (&argc, &argv);
TIMER_TYPE t0, t1, t2;
TIMER_NOW (t0);
cout << " ==== DARPA NMS CAMPUS NETWORK SIMULATION ====" << endl;
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::DistributedSimulatorImpl"));
uint32_t systemId = MpiInterface::GetSystemId ();
uint32_t systemCount = MpiInterface::GetSize ();
uint32_t nCN = 2, nLANClients = 42;
int32_t single = 0;
int nBytes = 500000; // Bytes for each on/off app
bool nix = true;
CommandLine cmd;
cmd.AddValue ("CN", "Number of total CNs [2]", nCN);
cmd.AddValue ("LAN", "Number of nodes per LAN [42]", nLANClients);
cmd.AddValue ("single", "1 if use single flow", single);
cmd.AddValue ("nBytes", "Number of bytes for each on/off app", nBytes);
cmd.AddValue ("nix", "Toggle the use of nix-vector or global routing", nix);
cmd.Parse (argc,argv);
if (nCN < 2)
{
cout << "Number of total CNs (" << nCN << ") lower than minimum of 2"
<< endl;
return 1;
}
if (systemCount > nCN)
{
cout << "Number of total CNs (" << nCN << ") should be >= systemCount ("
<< systemCount << ")." << endl;
return 1;
}
cout << "Number of CNs: " << nCN << ", LAN nodes: " << nLANClients << endl;
NodeContainer nodes_net0[nCN][3], nodes_net1[nCN][6], nodes_netLR[nCN],
nodes_net2[nCN][14], nodes_net2LAN[nCN][7][nLANClients],
nodes_net3[nCN][9], nodes_net3LAN[nCN][5][nLANClients];
PointToPointHelper p2p_2gb200ms, p2p_1gb5ms, p2p_100mb1ms;
InternetStackHelper stack;
Ipv4InterfaceContainer ifs, ifs0[nCN][3], ifs1[nCN][6], ifs2[nCN][14],
ifs3[nCN][9], ifs2LAN[nCN][7][nLANClients],
ifs3LAN[nCN][5][nLANClients];
Ipv4AddressHelper address;
std::ostringstream oss;
p2p_1gb5ms.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
p2p_1gb5ms.SetChannelAttribute ("Delay", StringValue ("5ms"));
p2p_2gb200ms.SetDeviceAttribute ("DataRate", StringValue ("2Gbps"));
p2p_2gb200ms.SetChannelAttribute ("Delay", StringValue ("200ms"));
p2p_100mb1ms.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
p2p_100mb1ms.SetChannelAttribute ("Delay", StringValue ("1ms"));
Ipv4NixVectorHelper nixRouting;
Ipv4StaticRoutingHelper staticRouting;
Ipv4ListRoutingHelper list;
list.Add (staticRouting, 0);
list.Add (nixRouting, 10);
if (nix)
{
stack.SetRoutingHelper (list);
}
// Create Campus Networks
for (uint32_t z = 0; z < nCN; ++z)
{
cout << "Creating Campus Network " << z << ":" << endl;
// Create Net0
cout << " SubNet [ 0";
for (int i = 0; i < 3; ++i)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net0[z][i].Add (node);
stack.Install (nodes_net0[z][i]);
}
nodes_net0[z][0].Add (nodes_net0[z][1].Get (0));
nodes_net0[z][1].Add (nodes_net0[z][2].Get (0));
nodes_net0[z][2].Add (nodes_net0[z][0].Get (0));
NetDeviceContainer ndc0[3];
for (int i = 0; i < 3; ++i)
{
ndc0[i] = p2p_1gb5ms.Install (nodes_net0[z][i]);
}
// Create Net1
cout << " 1";
for (int i = 0; i < 6; ++i)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net1[z][i].Add (node);
stack.Install (nodes_net1[z][i]);
}
nodes_net1[z][0].Add (nodes_net1[z][1].Get (0));
nodes_net1[z][2].Add (nodes_net1[z][0].Get (0));
nodes_net1[z][3].Add (nodes_net1[z][0].Get (0));
nodes_net1[z][4].Add (nodes_net1[z][1].Get (0));
nodes_net1[z][5].Add (nodes_net1[z][1].Get (0));
NetDeviceContainer ndc1[6];
for (int i = 0; i < 6; ++i)
{
if (i == 1)
{
continue;
}
ndc1[i] = p2p_1gb5ms.Install (nodes_net1[z][i]);
}
// Connect Net0 <-> Net1
NodeContainer net0_1;
net0_1.Add (nodes_net0[z][2].Get (0));
net0_1.Add (nodes_net1[z][0].Get (0));
NetDeviceContainer ndc0_1;
ndc0_1 = p2p_1gb5ms.Install (net0_1);
oss.str ("");
oss << 10 + z << ".1.252.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_1);
// Create Net2
cout << " 2";
for (int i = 0; i < 14; ++i)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net2[z][i].Add (node);
stack.Install (nodes_net2[z][i]);
}
nodes_net2[z][0].Add (nodes_net2[z][1].Get (0));
nodes_net2[z][2].Add (nodes_net2[z][0].Get (0));
nodes_net2[z][1].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][3].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][4].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][5].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][6].Add (nodes_net2[z][5].Get (0));
nodes_net2[z][7].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][8].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][9].Add (nodes_net2[z][4].Get (0));
nodes_net2[z][10].Add (nodes_net2[z][5].Get (0));
nodes_net2[z][11].Add (nodes_net2[z][6].Get (0));
nodes_net2[z][12].Add (nodes_net2[z][6].Get (0));
nodes_net2[z][13].Add (nodes_net2[z][6].Get (0));
NetDeviceContainer ndc2[14];
for (int i = 0; i < 14; ++i)
{
ndc2[i] = p2p_1gb5ms.Install (nodes_net2[z][i]);
}
NetDeviceContainer ndc2LAN[7][nLANClients];
for (int i = 0; i < 7; ++i)
{
oss.str ("");
oss << 10 + z << ".4." << 15 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
for (uint32_t j = 0; j < nLANClients; ++j)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net2LAN[z][i][j].Add (node);
stack.Install (nodes_net2LAN[z][i][j]);
nodes_net2LAN[z][i][j].Add (nodes_net2[z][i + 7].Get (0));
ndc2LAN[i][j] = p2p_100mb1ms.Install (nodes_net2LAN[z][i][j]);
ifs2LAN[z][i][j] = address.Assign (ndc2LAN[i][j]);
}
}
// Create Net3
cout << " 3 ]" << endl;
for (int i = 0; i < 9; ++i)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net3[z][i].Add (node);
stack.Install (nodes_net3[z][i]);
}
nodes_net3[z][0].Add (nodes_net3[z][1].Get (0));
nodes_net3[z][1].Add (nodes_net3[z][2].Get (0));
nodes_net3[z][2].Add (nodes_net3[z][3].Get (0));
nodes_net3[z][3].Add (nodes_net3[z][1].Get (0));
nodes_net3[z][4].Add (nodes_net3[z][0].Get (0));
nodes_net3[z][5].Add (nodes_net3[z][0].Get (0));
nodes_net3[z][6].Add (nodes_net3[z][2].Get (0));
nodes_net3[z][7].Add (nodes_net3[z][3].Get (0));
nodes_net3[z][8].Add (nodes_net3[z][3].Get (0));
NetDeviceContainer ndc3[9];
for (int i = 0; i < 9; ++i)
{
ndc3[i] = p2p_1gb5ms.Install (nodes_net3[z][i]);
}
NetDeviceContainer ndc3LAN[5][nLANClients];
for (int i = 0; i < 5; ++i)
{
oss.str ("");
oss << 10 + z << ".5." << 10 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.255");
for (uint32_t j = 0; j < nLANClients; ++j)
{
Ptr<Node> node = CreateObject<Node> (z % systemCount);
nodes_net3LAN[z][i][j].Add (node);
stack.Install (nodes_net3LAN[z][i][j]);
nodes_net3LAN[z][i][j].Add (nodes_net3[z][i + 4].Get (0));
ndc3LAN[i][j] = p2p_100mb1ms.Install (nodes_net3LAN[z][i][j]);
ifs3LAN[z][i][j] = address.Assign (ndc3LAN[i][j]);
}
}
cout << " Connecting Subnets..." << endl;
// Create Lone Routers (Node 4 & 5)
Ptr<Node> node1 = CreateObject<Node> (z % systemCount);
Ptr<Node> node2 = CreateObject<Node> (z % systemCount);
nodes_netLR[z].Add (node1);
nodes_netLR[z].Add (node2);
stack.Install (nodes_netLR[z]);
NetDeviceContainer ndcLR;
ndcLR = p2p_1gb5ms.Install (nodes_netLR[z]);
// Connect Net2/Net3 through Lone Routers to Net0
NodeContainer net0_4, net0_5, net2_4a, net2_4b, net3_5a, net3_5b;
net0_4.Add (nodes_netLR[z].Get (0));
net0_4.Add (nodes_net0[z][0].Get (0));
net0_5.Add (nodes_netLR[z].Get (1));
net0_5.Add (nodes_net0[z][1].Get (0));
net2_4a.Add (nodes_netLR[z].Get (0));
net2_4a.Add (nodes_net2[z][0].Get (0));
net2_4b.Add (nodes_netLR[z].Get (1));
net2_4b.Add (nodes_net2[z][1].Get (0));
net3_5a.Add (nodes_netLR[z].Get (1));
net3_5a.Add (nodes_net3[z][0].Get (0));
net3_5b.Add (nodes_netLR[z].Get (1));
net3_5b.Add (nodes_net3[z][1].Get (0));
NetDeviceContainer ndc0_4, ndc0_5, ndc2_4a, ndc2_4b, ndc3_5a, ndc3_5b;
ndc0_4 = p2p_1gb5ms.Install (net0_4);
oss.str ("");
oss << 10 + z << ".1.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_4);
ndc0_5 = p2p_1gb5ms.Install (net0_5);
oss.str ("");
oss << 10 + z << ".1.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_5);
ndc2_4a = p2p_1gb5ms.Install (net2_4a);
oss.str ("");
oss << 10 + z << ".4.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc2_4a);
ndc2_4b = p2p_1gb5ms.Install (net2_4b);
oss.str ("");
oss << 10 + z << ".4.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc2_4b);
ndc3_5a = p2p_1gb5ms.Install (net3_5a);
oss.str ("");
oss << 10 + z << ".5.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc3_5a);
ndc3_5b = p2p_1gb5ms.Install (net3_5b);
oss.str ("");
oss << 10 + z << ".5.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc3_5b);
// Assign IP addresses
cout << " Assigning IP addresses..." << endl;
for (int i = 0; i < 3; ++i)
{
oss.str ("");
oss << 10 + z << ".1." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs0[z][i] = address.Assign (ndc0[i]);
}
for (int i = 0; i < 6; ++i)
{
if (i == 1)
{
continue;
}
oss.str ("");
oss << 10 + z << ".2." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs1[z][i] = address.Assign (ndc1[i]);
}
oss.str ("");
oss << 10 + z << ".3.1.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndcLR);
for (int i = 0; i < 14; ++i)
{
oss.str ("");
oss << 10 + z << ".4." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs2[z][i] = address.Assign (ndc2[i]);
}
for (int i = 0; i < 9; ++i)
{
oss.str ("");
oss << 10 + z << ".5." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs3[z][i] = address.Assign (ndc3[i]);
}
}
// Create Ring Links
if (nCN > 1)
{
cout << "Forming Ring Topology..." << endl;
NodeContainer nodes_ring[nCN];
for (uint32_t z = 0; z < nCN - 1; ++z)
{
nodes_ring[z].Add (nodes_net0[z][0].Get (0));
nodes_ring[z].Add (nodes_net0[z + 1][0].Get (0));
}
nodes_ring[nCN - 1].Add (nodes_net0[nCN - 1][0].Get (0));
nodes_ring[nCN - 1].Add (nodes_net0[0][0].Get (0));
NetDeviceContainer ndc_ring[nCN];
for (uint32_t z = 0; z < nCN; ++z)
{
ndc_ring[z] = p2p_2gb200ms.Install (nodes_ring[z]);
oss.str ("");
oss << "254.1." << z + 1 << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc_ring[z]);
}
}
// Create Traffic Flows
cout << "Creating UDP Traffic Flows:" << endl;
Config::SetDefault ("ns3::OnOffApplication::MaxBytes",
UintegerValue (nBytes));
Config::SetDefault ("ns3::OnOffApplication::OnTime",
RandomVariableValue (ConstantVariable (1)));
Config::SetDefault ("ns3::OnOffApplication::OffTime",
RandomVariableValue (ConstantVariable (0)));
if (single)
{
if (systemCount == 1)
{
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (),
9999));
ApplicationContainer sinkApp = sinkHelper.Install (nodes_net1[0][2].Get (0));
sinkApp.Start (Seconds (0.0));
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress (InetSocketAddress (ifs1[0][2].GetAddress (0), 9999));
cout << "Remote Address is " << ifs1[0][2].GetAddress (0) << endl;
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net2LAN[0][0][0].Get (0)));
clientApp.Start (Seconds (0));
}
else if (systemId == 1)
{
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (),
9999));
ApplicationContainer sinkApp =
sinkHelper.Install (nodes_net1[1][0].Get (0));
sinkApp.Start (Seconds (0.0));
}
else if (systemId == 0)
{
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress
(InetSocketAddress (ifs1[1][0].GetAddress (0), 9999));
cout << "Remote Address is " << ifs1[1][0].GetAddress (0) << endl;
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net2LAN[0][0][0].Get (0)));
clientApp.Start (Seconds (0));
}
}
else
{
UniformVariable urng;
int r1;
double r2;
for (uint32_t z = 0; z < nCN; ++z)
{
uint32_t x = z + 1;
if (z == nCN - 1)
{
x = 0;
}
// Subnet 2 LANs
cout << " Campus Network " << z << " Flows [ Net2 ";
for (int i = 0; i < 7; ++i)
{
for (uint32_t j = 0; j < nLANClients; ++j)
{
// Sinks
if (systemCount == 1)
{
PacketSinkHelper sinkHelper
("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp =
sinkHelper.Install (nodes_net2LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
}
else if (systemId == z % systemCount)
{
PacketSinkHelper sinkHelper
("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp =
sinkHelper.Install (nodes_net2LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
}
// Sources
if (systemCount == 1)
{
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
else if (systemId == x % systemCount)
{
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
}
}
// Subnet 3 LANs
cout << "Net3 ]" << endl;
for (int i = 0; i < 5; ++i)
{
for (uint32_t j = 0; j < nLANClients; ++j)
{
// Sinks
if (systemCount == 1)
{
PacketSinkHelper sinkHelper
("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp =
sinkHelper.Install (nodes_net3LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
}
else if (systemId == z % systemCount)
{
PacketSinkHelper sinkHelper
("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp =
sinkHelper.Install (nodes_net3LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
}
// Sources
if (systemCount == 1)
{
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
else if (systemId == x % systemCount)
{
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
AddressValue remoteAddress
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
}
}
}
}
cout << "Created " << NodeList::GetNNodes () << " nodes." << endl;
TIMER_TYPE routingStart;
TIMER_NOW (routingStart);
if (nix)
{
cout << "Using Nix-vectors..." << endl;
}
else
{
// Calculate routing tables
cout << "Populating Routing tables..." << endl;
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
}
TIMER_TYPE routingEnd;
TIMER_NOW (routingEnd);
cout << "Routing tables population took "
<< TIMER_DIFF (routingEnd, routingStart) << endl;
cout << "Running simulator..." << endl;
TIMER_NOW (t1);
Simulator::Stop (Seconds (200.0));
Simulator::Run ();
TIMER_NOW (t2);
cout << "Simulator finished." << endl;
Simulator::Destroy ();
double d1 = TIMER_DIFF (t1, t0), d2 = TIMER_DIFF (t2, t1);
cout << "-----" << endl << "Runtime Stats:" << endl;
cout << "Simulator init time: " << d1 << endl;
cout << "Simulator run time: " << d2 << endl;
cout << "Total elapsed time: " << d1 + d2 << endl;
return 0;
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}

View File

@@ -0,0 +1,245 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* TestDistributed creates a dumbbell topology and logically splits it in
* half. The left half is placed on logical processor 0 and the right half
* is placed on logical processor 1.
*
* ------- -------
* RANK 0 RANK 1
* ------- | -------
* |
* n0 ---------| | |---------- n6
* | | |
* n1 -------\ | | | /------- n7
* n4 ----------|---------- n5
* n2 -------/ | | | \------- n8
* | | |
* n3 ---------| | |---------- n9
*
*
* OnOff clients are placed on each left leaf node. Each right leaf node
* is a packet sink for a left leaf node. As a packet travels from one
* logical processor to another (the link between n4 and n5), MPI messages
* are passed containing the serialized packet. The message is then
* deserialized into a new packet and sent on as normal.
*
* One packet is sent from each left leaf node. The packet sinks on the
* right leaf nodes output logging information when they receive the packet.
*/
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/mpi-interface.h"
#ifdef NS3_MPI
#include <mpi.h>
#endif
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SimpleDistributed");
int
main (int argc, char *argv[])
{
#ifdef NS3_MPI
// Distributed simulation setup
MpiInterface::Enable (&argc, &argv);
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::DistributedSimulatorImpl"));
LogComponentEnable ("PacketSink", LOG_LEVEL_INFO);
uint32_t systemId = MpiInterface::GetSystemId ();
uint32_t systemCount = MpiInterface::GetSize ();
// Check for valid distributed parameters.
// Must have 2 and only 2 Logical Processors (LPs)
if (systemCount != 2)
{
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
return 1;
}
// Some default values
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (512));
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("1Mbps"));
Config::SetDefault ("ns3::OnOffApplication::MaxBytes", UintegerValue (512));
bool nix = true;
// Parse command line
CommandLine cmd;
cmd.AddValue ("nix", "Enable the use of nix-vector or global routing", nix);
cmd.Parse (argc, argv);
// Create leaf nodes on left with system id 0
NodeContainer leftLeafNodes;
leftLeafNodes.Create (4, 0);
// Create router nodes. Left router
// with system id 0, right router with
// system id 1
NodeContainer routerNodes;
Ptr<Node> routerNode1 = CreateObject<Node> (0);
Ptr<Node> routerNode2 = CreateObject<Node> (1);
routerNodes.Add (routerNode1);
routerNodes.Add (routerNode2);
// Create leaf nodes on left with system id 1
NodeContainer rightLeafNodes;
rightLeafNodes.Create (4, 1);
PointToPointHelper routerLink;
routerLink.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
routerLink.SetChannelAttribute ("Delay", StringValue ("5ms"));
PointToPointHelper leafLink;
leafLink.SetDeviceAttribute ("DataRate", StringValue ("1Mbps"));
leafLink.SetChannelAttribute ("Delay", StringValue ("2ms"));
// Add link connecting routers
NetDeviceContainer routerDevices;
routerDevices = routerLink.Install (routerNodes);
// Add links for left side leaf nodes to left router
NetDeviceContainer leftRouterDevices;
NetDeviceContainer leftLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer temp = leafLink.Install (leftLeafNodes.Get (i), routerNodes.Get (0));
leftLeafDevices.Add (temp.Get (0));
leftRouterDevices.Add (temp.Get (1));
}
// Add links for right side leaf nodes to right router
NetDeviceContainer rightRouterDevices;
NetDeviceContainer rightLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer temp = leafLink.Install (rightLeafNodes.Get (i), routerNodes.Get (1));
rightLeafDevices.Add (temp.Get (0));
rightRouterDevices.Add (temp.Get (1));
}
InternetStackHelper stack;
Ipv4NixVectorHelper nixRouting;
Ipv4StaticRoutingHelper staticRouting;
Ipv4ListRoutingHelper list;
list.Add (staticRouting, 0);
list.Add (nixRouting, 10);
if (nix)
{
stack.SetRoutingHelper (list);
}
stack.InstallAll ();
Ipv4InterfaceContainer routerInterfaces;
Ipv4InterfaceContainer leftLeafInterfaces;
Ipv4InterfaceContainer leftRouterInterfaces;
Ipv4InterfaceContainer rightLeafInterfaces;
Ipv4InterfaceContainer rightRouterInterfaces;
Ipv4AddressHelper leftAddress;
leftAddress.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4AddressHelper routerAddress;
routerAddress.SetBase ("10.2.1.0", "255.255.255.0");
Ipv4AddressHelper rightAddress;
rightAddress.SetBase ("10.3.1.0", "255.255.255.0");
// Router-to-Router interfaces
routerInterfaces = routerAddress.Assign (routerDevices);
// Left interfaces
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer ndc;
ndc.Add (leftLeafDevices.Get (i));
ndc.Add (leftRouterDevices.Get (i));
Ipv4InterfaceContainer ifc = leftAddress.Assign (ndc);
leftLeafInterfaces.Add (ifc.Get (0));
leftRouterInterfaces.Add (ifc.Get (1));
leftAddress.NewNetwork ();
}
// Right interfaces
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer ndc;
ndc.Add (rightLeafDevices.Get (i));
ndc.Add (rightRouterDevices.Get (i));
Ipv4InterfaceContainer ifc = rightAddress.Assign (ndc);
rightLeafInterfaces.Add (ifc.Get (0));
rightRouterInterfaces.Add (ifc.Get (1));
rightAddress.NewNetwork ();
}
if (!nix)
{
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
}
// Create a packet sink on the right leafs to receive packets from left leafs
uint16_t port = 50000;
if (systemId == 1)
{
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp;
for (uint32_t i = 0; i < 4; ++i)
{
sinkApp.Add (sinkHelper.Install (rightLeafNodes.Get (i)));
}
sinkApp.Start (Seconds (1.0));
sinkApp.Stop (Seconds (5));
}
// Create the OnOff applications to send
if (systemId == 0)
{
OnOffHelper clientHelper ("ns3::UdpSocketFactory", Address ());
clientHelper.SetAttribute
("OnTime", RandomVariableValue (ConstantVariable (1)));
clientHelper.SetAttribute
("OffTime", RandomVariableValue (ConstantVariable (0)));
ApplicationContainer clientApps;
for (uint32_t i = 0; i < 4; ++i)
{
AddressValue remoteAddress
(InetSocketAddress (rightLeafInterfaces.GetAddress (i), port));
clientHelper.SetAttribute ("Remote", remoteAddress);
clientApps.Add (clientHelper.Install (leftLeafNodes.Get (i)));
}
clientApps.Start (Seconds (1.0));
clientApps.Stop (Seconds (5));
}
Simulator::Stop (Seconds (5));
Simulator::Run ();
Simulator::Destroy ();
return 0;
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}

View File

@@ -0,0 +1,244 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/wifi-module.h"
#include "ns3/mobility-module.h"
#include "ns3/mpi-interface.h"
#ifdef NS3_MPI
#include <mpi.h>
#endif
// Default Network Topology (same as third.cc from tutorial)
// Distributed simulation, split along the p2p link
// Number of wifi or csma nodes can be increased up to 250
//
// Wifi 10.1.3.0
// AP
// * * * *
// | | | | 10.1.1.0
// n5 n6 n7 n0 -------------- n1 n2 n3 n4
// point-to-point | | | |
// ================
// | LAN 10.1.2.0
// |
// Rank 0 | Rank 1
// -------------------------|----------------------------
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("ThirdExampleDistributed");
int
main (int argc, char *argv[])
{
#ifdef NS3_MPI
// Distributed simulation setup
MpiInterface::Enable (&argc, &argv);
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::DistributedSimulatorImpl"));
uint32_t systemId = MpiInterface::GetSystemId ();
uint32_t systemCount = MpiInterface::GetSize ();
// Check for valid distributed parameters.
// Must have 2 and only 2 Logical Processors (LPs)
if (systemCount != 2)
{
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
return 1;
}
bool verbose = true;
uint32_t nCsma = 3;
uint32_t nWifi = 3;
bool tracing = false;
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
cmd.AddValue ("tracing", "Enable pcap tracing", tracing);
cmd.Parse (argc,argv);
// Check for valid number of csma or wifi nodes
// 250 should be enough, otherwise IP addresses
// soon become an issue
if (nWifi > 250 || nCsma > 250)
{
std::cout << "Too many wifi or csma nodes, max 200 each." << std::endl;
return 1;
}
if (verbose)
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
NodeContainer p2pNodes;
Ptr<Node> p2pNode1 = CreateObject<Node> (0); // Create node with rank 0
Ptr<Node> p2pNode2 = CreateObject<Node> (1); // Create node with rank 1
p2pNodes.Add (p2pNode1);
p2pNodes.Add (p2pNode2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma , 1); // Create csma nodes with rank 1
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
NodeContainer wifiStaNodes;
wifiStaNodes.Create (nWifi, 0); // Create wifi nodes with rank 0
NodeContainer wifiApNode = p2pNodes.Get (0);
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
phy.SetChannel (channel.Create ());
WifiHelper wifi = WifiHelper::Default ();
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
Ssid ssid = Ssid ("ns-3-ssid");
mac.SetType ("ns3::NqstaWifiMac",
"Ssid", SsidValue (ssid),
"ActiveProbing", BooleanValue (false));
NetDeviceContainer staDevices;
staDevices = wifi.Install (phy, mac, wifiStaNodes);
mac.SetType ("ns3::NqapWifiMac",
"Ssid", SsidValue (ssid),
"BeaconGeneration", BooleanValue (true),
"BeaconInterval", TimeValue (Seconds (2.5)));
NetDeviceContainer apDevices;
apDevices = wifi.Install (phy, mac, wifiApNode);
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (5.0),
"GridWidth", UintegerValue (10),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-250, 250, -250, 250)));
mobility.Install (wifiStaNodes);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiApNode);
InternetStackHelper stack;
stack.Install (csmaNodes);
stack.Install (wifiApNode);
stack.Install (wifiStaNodes);
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
address.SetBase ("10.1.3.0", "255.255.255.0");
address.Assign (staDevices);
address.Assign (apDevices);
// If this simulator has system id 1, then
// it should contain the server application,
// since it is on one of the csma nodes
if (systemId == 1)
{
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
}
// If the simulator has sytem id 0, then
// it should contain the client application,
// since it is on one of the wifi nodes
if (systemId == 0)
{
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps =
echoClient.Install (wifiStaNodes.Get (nWifi - 1));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
}
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Simulator::Stop (Seconds (10.0));
if (tracing == true)
{
// Depending on the system Id (rank), the pcap information
// traced will be different. For example, the ethernet pcap
// will be empty for rank0, since these nodes are placed on
// on rank 1. All ethernet traffic will take place on rank 1.
// Similar differences are seen in the p2p and wirless pcaps.
if (systemId == 0)
{
pointToPoint.EnablePcapAll ("third-distributed-rank0");
phy.EnablePcap ("third-distributed-rank0", apDevices.Get (0));
csma.EnablePcap ("third-distributed-rank0", csmaDevices.Get (0), true);
}
else
{
pointToPoint.EnablePcapAll ("third-distributed-rank1");
phy.EnablePcap ("third-distributed-rank1", apDevices.Get (0));
csma.EnablePcap ("third-distributed-rank1", csmaDevices.Get (0), true);
}
}
Simulator::Run ();
Simulator::Destroy ();
return 0;
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}

1
examples/mpi/waf vendored Executable file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../waf "$@"

14
examples/mpi/wscript Normal file
View File

@@ -0,0 +1,14 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
obj = bld.create_ns3_program('simple-distributed',
['point-to-point', 'internet-stack'])
obj.source = 'simple-distributed.cc'
obj = bld.create_ns3_program('third-distributed',
['point-to-point', 'internet-stack'])
obj.source = 'third-distributed.cc'
obj = bld.create_ns3_program('nms-udp-nix',
['point-to-point', 'internet-stack'])
obj.source = 'nms-udp-nix.cc'

View File

@@ -268,6 +268,15 @@ Buffer::Buffer (uint32_t dataSize)
Initialize (dataSize);
}
Buffer::Buffer (uint32_t dataSize, bool initialize)
{
NS_LOG_FUNCTION (this << dataSize << initialize);
if (initialize == true)
{
Initialize (dataSize);
}
}
bool
Buffer::CheckInternalState (void) const
{
@@ -667,6 +676,139 @@ Buffer::CreateFullCopy (void) const
return *this;
}
uint32_t
Buffer::GetSerializedSize (void) const
{
uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
// total size 4-bytes for dataStart length
// + X number of bytes for dataStart
// + 4-bytes for dataEnd length
// + X number of bytes for dataEnd
uint32_t sz = sizeof (uint32_t)
+ sizeof (uint32_t)
+ dataStart
+ sizeof (uint32_t)
+ dataEnd;
return sz;
}
uint32_t
Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
{
uint32_t* p = (uint32_t*)buffer;
uint32_t size = 0;
NS_LOG_FUNCTION (this);
// Add the zero data length
if (size + 4 <= maxSize)
{
size += 4;
*p++ = m_zeroAreaEnd - m_zeroAreaStart;
}
else
{
return 0;
}
// Add the length of actual start data
uint32_t dataStartLength = m_zeroAreaStart - m_start;
if (size + 4 <= maxSize)
{
size += 4;
*p++ = dataStartLength;
}
else
{
return 0;
}
// Add the actual data
if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
{
size += (dataStartLength + 3) & (~3);
memcpy(p, m_data->m_data + m_start, dataStartLength);
p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
}
else
{
return 0;
}
// Add the length of the actual end data
uint32_t dataEndLength = m_end - m_zeroAreaEnd;
if (size + 4 <= maxSize)
{
size += 4;
*p++ = dataEndLength;
}
else
{
return 0;
}
// Add the actual data
if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
{
size += (dataEndLength + 3) & (~3);
memcpy(p, m_data->m_data+m_zeroAreaStart,dataEndLength);
p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
}
else
{
return 0;
}
// Serialzed everything successfully
return 1;
}
uint32_t
Buffer::Deserialize (uint8_t *buffer, uint32_t size)
{
uint32_t* p = (uint32_t*)buffer;
uint32_t sizeCheck = size-4;
NS_ASSERT (sizeCheck >= 4);
uint32_t zeroDataLength = *p++;
sizeCheck -= 4;
// Create zero bytes
Initialize (zeroDataLength);
// Add start data
NS_ASSERT (sizeCheck >= 4);
uint32_t dataStartLength = *p++;
sizeCheck -= 4;
AddAtStart (dataStartLength);
NS_ASSERT (sizeCheck >= dataStartLength);
Begin ().Write ((uint8_t*)p, dataStartLength);
p += (((dataStartLength+3)&(~3))/4);
sizeCheck -= ((dataStartLength+3)&(~3));
// Add end data
NS_ASSERT (sizeCheck >= 4);
uint32_t dataEndLength = *p++;
sizeCheck -= 4;
AddAtEnd (dataEndLength);
NS_ASSERT (sizeCheck >= dataEndLength);
Buffer::Iterator tmp = End ();
tmp.Prev (dataEndLength);
tmp.Write ((uint8_t*)p, dataEndLength);
p += (((dataEndLength+3)&(~3))/4);
sizeCheck -= ((dataEndLength+3)&(~3));
NS_ASSERT (sizeCheck == 0);
// return zero if buffer did not
// contain a complete message
return (sizeCheck != 0) ? 0 : 1;
}
int32_t
Buffer::GetCurrentStartOffset (void) const
{

View File

@@ -476,6 +476,33 @@ public:
Buffer CreateFullCopy (void) const;
/**
* \return the number of bytes required for serialization
*/
uint32_t GetSerializedSize (void) const;
/**
* \return zero if buffer not large enough
* \param buffer points to serialization buffer
* \param maxSize max number of bytes to write
*
* This buffer's contents are serialized into the raw
* character buffer parameter. Note: The zero length
* data is not copied entirely. Only the length of
* zero byte data is serialized.
*/
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
/**
* \return zero if a complete buffer is not deserialized
* \param buffer points to buffer for deserialization
* \param size number of bytes to deserialize
*
* The raw character buffer is deserialized and all the
* data is placed into this buffer.
*/
uint32_t Deserialize (uint8_t* buffer, uint32_t size);
int32_t GetCurrentStartOffset (void) const;
int32_t GetCurrentEndOffset (void) const;
@@ -493,6 +520,7 @@ public:
Buffer &operator = (Buffer const &o);
Buffer ();
Buffer (uint32_t dataSize);
Buffer (uint32_t dataSize, bool initialize);
~Buffer ();
private:

View File

@@ -222,74 +222,105 @@ NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
uint32_t
NixVector::GetSerializedSize (void) const
{
uint32_t totalSizeInBytes;
uint32_t totalSizeInBytes = 0;
totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
// add four to this to account
// for the nix-vector length
// entry
return totalSizeInBytes+4;
}
void
NixVector::Serialize (Buffer::Iterator i, uint32_t size) const
{
uint32_t bytesWritten = 0;
i.WriteU32 (size);
bytesWritten += 4;
i.WriteU32 (m_used);
bytesWritten += 4;
i.WriteU32 (m_currentVectorBitSize);
bytesWritten += 4;
i.WriteU32 (m_totalBitSize);
bytesWritten += 4;
for (uint32_t j = 0; j < m_nixVector.size (); j++)
{
i.WriteU32 (m_nixVector.at(j));
bytesWritten += 4;
}
NS_ASSERT (bytesWritten == size);
return totalSizeInBytes;
}
uint32_t
NixVector::Deserialize (Buffer::Iterator i)
NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
{
NS_LOG_FUNCTION (this);
uint32_t totalSize = i.ReadU32 ();
uint32_t size = totalSize;
size -= 4;
uint32_t* p = buffer;
uint32_t size = 0;
NS_ASSERT (size >= 4);
m_used = i.ReadU32 ();
size -=4;
if (size + 4 <= maxSize)
{
size += 4;
// grab number of used bits
*p++ = m_used;
}
else
{
return 0;
}
NS_ASSERT (size >= 4);
m_currentVectorBitSize = i.ReadU32 ();
size -=4;
if (size + 4 <= maxSize)
{
size += 4;
// grab number of current used bits
// for the front vector
*p++ = m_currentVectorBitSize;
}
else
{
return 0;
}
NS_ASSERT (size >= 4);
m_totalBitSize = i.ReadU32 ();
size -=4;
if (size + 4 <= maxSize)
{
size += 4;
// grab total bit size
*p++ = m_totalBitSize;
}
else
{
return 0;
}
for (uint32_t j = 0; j < m_nixVector.size (); j++)
{
if (size + 4 <= maxSize)
{
size += 4;
*p++ = m_nixVector.at(j);
}
else
{
return 0;
}
}
// Serialized successfully
return 1;
}
uint32_t
NixVector::Deserialize (uint32_t* buffer, uint32_t size)
{
NS_LOG_FUNCTION (this);
uint32_t* p = buffer;
uint32_t sizeCheck = size - 4;
NS_ASSERT (sizeCheck >= 4);
m_used = *p++;
sizeCheck -= 4;
NS_ASSERT (sizeCheck >= 4);
m_currentVectorBitSize = *p++;
sizeCheck -= 4;
NS_ASSERT (sizeCheck >= 4);
m_totalBitSize = *p++;
sizeCheck -= 4;
// make sure the nix-vector
// is empty
m_nixVector.clear ();
while (size > 0)
while (sizeCheck > 0)
{
NS_ASSERT (size >= 4);
m_nixVector.push_back (i.ReadU32 ());
size -=4;
NS_ASSERT (sizeCheck >= 4);
uint32_t nix = *p++;
m_nixVector.push_back (nix);
sizeCheck -= 4;
}
NS_ASSERT (size == 0);
return totalSize;
NS_ASSERT (sizeCheck == 0);
// return zero if an entire nix-vector was
// not deserialized
return (sizeCheck != 0) ? 0 : 1;
}
void

View File

@@ -105,17 +105,27 @@ class NixVector : public Object
*/
uint32_t GetSerializedSize (void) const;
/**
* \param i Buffer iterator for writing
* \return zero if buffer not large enough
*
* \param size number of bytes to write
* \param buffer points to serialization buffer
*
* \param maxSize max number of bytes to write
*
* This nix-vector is serialized into the raw character
* buffer parameter.
*/
void Serialize (Buffer::Iterator i, uint32_t size) const;
uint32_t Serialize (uint32_t* buffer, uint32_t maxSize) const;
/**
* \return the number of bytes deserialized
* \return zero if a complete nix-vector is not deserialized
*
* \param i Buffer iterator for reading
* \param buffer points to buffer for deserialization
*
* \param size number of bytes to deserialize
*
* The raw character buffer containing all the nix-vector
* information is deserialized into this nix-vector.
*/
uint32_t Deserialize (Buffer::Iterator i);
uint32_t Deserialize (uint32_t* buffer, uint32_t size);
/**
* \return number of bits of numberOfNeighbors
*

View File

@@ -353,42 +353,43 @@ PacketMetadataTest::CheckHistory (Ptr<Packet> p, const char *file, int line, uin
return false;
}
#define ADD_HEADER(p, n) \
{ \
HistoryHeader<n> header; \
p->AddHeader (header); \
#define ADD_HEADER(p, n) \
{ \
HistoryHeader<n> header; \
p->AddHeader (header); \
}
#define ADD_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
p->AddTrailer (trailer); \
#define ADD_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
p->AddTrailer (trailer); \
}
#define REM_HEADER(p, n) \
{ \
HistoryHeader<n> header; \
p->RemoveHeader (header); \
#define REM_HEADER(p, n) \
{ \
HistoryHeader<n> header; \
p->RemoveHeader (header); \
}
#define REM_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
p->RemoveTrailer (trailer); \
#define REM_TRAILER(p, n) \
{ \
HistoryTrailer<n> trailer; \
p->RemoveTrailer (trailer); \
}
#define CHECK_HISTORY(p, ...) \
{ \
if (!CheckHistory (p, __FILE__, \
__LINE__, __VA_ARGS__)) \
{ \
result = false; \
} \
Buffer buffer; \
buffer = p->Serialize (); \
Ptr<Packet> otherPacket = Create<Packet> ();\
otherPacket->Deserialize (buffer); \
if (!CheckHistory (otherPacket, __FILE__, \
__LINE__, __VA_ARGS__)) \
{ \
result = false; \
} \
#define CHECK_HISTORY(p, ...) \
{ \
if (!CheckHistory (p, __FILE__, \
__LINE__, __VA_ARGS__)) \
{ \
result = false; \
} \
uint32_t size = p->GetSerializedSize (); \
uint8_t* buffer = new uint8_t[size]; \
p->Serialize (buffer, size); \
Ptr<Packet> otherPacket = Create<Packet> (buffer, size, true); \
delete [] buffer; \
if (!CheckHistory (otherPacket, __FILE__, \
__LINE__, __VA_ARGS__)) \
{ \
result = false; \
} \
}
@@ -413,6 +414,7 @@ PacketMetadataTest::DoRun (void)
ADD_TRAILER (p, 100);
CHECK_HISTORY (p, 2, 10, 100);
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);

View File

@@ -959,7 +959,7 @@ PacketMetadata::GetTotalSize (void) const
return totalSize;
}
uint32_t
uint64_t
PacketMetadata::GetUid (void) const
{
return m_packetUid;
@@ -1055,11 +1055,18 @@ PacketMetadata::GetSerializedSize (void) const
{
NS_LOG_FUNCTION (this);
uint32_t totalSize = 0;
totalSize += 4;
// add 8 bytes for the packet uid
totalSize += 8;
// if packet-metadata not enabled, total size
// is simply 4-bytes for itself plus 8-bytes
// for packet uid
if (!m_enable)
{
return totalSize;
}
struct PacketMetadata::SmallItem item;
struct PacketMetadata::ExtraItem extraItem;
uint32_t current = m_head;
@@ -1077,7 +1084,7 @@ PacketMetadata::GetSerializedSize (void) const
tid.SetUid (uid);
totalSize += 4 + tid.GetName ().size ();
}
totalSize += 1 + 4 + 2 + 4 + 4 + 4;
totalSize += 1 + 4 + 2 + 4 + 4 + 8;
if (current == m_tail)
{
break;
@@ -1087,52 +1094,95 @@ PacketMetadata::GetSerializedSize (void) const
}
return totalSize;
}
void
PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
uint32_t
PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const
{
NS_LOG_FUNCTION (this);
uint32_t bytesWritten = 0;
i.WriteU32 (size);
bytesWritten += 4;
uint8_t* start = buffer;
buffer = AddToRawU64 (m_packetUid, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
struct PacketMetadata::SmallItem item;
struct PacketMetadata::ExtraItem extraItem;
uint32_t current = m_head;
while (current != 0xffff)
{
ReadItems (current, &item, &extraItem);
NS_LOG_LOGIC ("bytesWritten=" << bytesWritten << ", typeUid="<<
NS_LOG_LOGIC ("bytesWritten=" << (uint32_t)(buffer - start) << ", typeUid="<<
item.typeUid << ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
if (uid != 0)
{
TypeId tid;
tid.SetUid (uid);
std::string uidString = tid.GetName ();
i.WriteU32 (uidString.size ());
bytesWritten += 4;
i.Write ((uint8_t *)uidString.c_str (), uidString.size ());
bytesWritten += uidString.size ();
uint32_t uidStringSize = uidString.size ();
buffer = AddToRawU32 (uidStringSize, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRaw ((uint8_t *)uidString.c_str (),
uidStringSize, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
}
else
{
i.WriteU32 (0);
bytesWritten += 4;
buffer = AddToRawU32 (0, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
}
uint8_t isBig = item.typeUid & 0x1;
i.WriteU8 (isBig);
bytesWritten += 1;
i.WriteU32 (item.size);
bytesWritten += 4;
i.WriteU16 (item.chunkUid);
bytesWritten += 2;
i.WriteU32 (extraItem.fragmentStart);
bytesWritten += 4;
i.WriteU32 (extraItem.fragmentEnd);
bytesWritten += 4;
i.WriteU32 (extraItem.packetUid);
bytesWritten += 4;
buffer = AddToRawU8 (isBig, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRawU32 (item.size, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRawU16 (item.chunkUid, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRawU32 (extraItem.fragmentStart, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRawU32 (extraItem.fragmentEnd, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
buffer = AddToRawU64 (extraItem.packetUid, start, buffer, maxSize);
if (buffer == 0)
{
return 0;
}
if (current == m_tail)
{
break;
@@ -1141,21 +1191,28 @@ PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
NS_ASSERT (current != item.next);
current = item.next;
}
NS_ASSERT (bytesWritten == size);
NS_ASSERT ((uint32_t)(buffer - start) == maxSize);
return 1;
}
uint32_t
PacketMetadata::Deserialize (Buffer::Iterator i)
PacketMetadata::Deserialize (uint8_t* buffer, uint32_t size)
{
NS_LOG_FUNCTION (this);
uint8_t* start = buffer;
uint32_t desSize = size - 4;
buffer = ReadFromRawU64 (m_packetUid, start, buffer, size);
desSize -= 8;
struct PacketMetadata::SmallItem item;
struct PacketMetadata::ExtraItem extraItem;
uint32_t totalSize = i.ReadU32 ();
uint32_t size = totalSize;
size -= 4;
while (size > 0)
while (desSize > 0)
{
uint32_t uidStringSize = i.ReadU32 ();
size -= 4;
uint32_t uidStringSize = 0;
buffer = ReadFromRawU32 (uidStringSize, start, buffer, size);
desSize -= 4;
uint32_t uid;
if (uidStringSize == 0)
{
@@ -1167,25 +1224,28 @@ PacketMetadata::Deserialize (Buffer::Iterator i)
std::string uidString;
for (uint32_t j = 0; j < uidStringSize; j++)
{
uidString.push_back (i.ReadU8 ());
size --;
uint8_t ch = 0;
buffer = ReadFromRawU8 (ch, start, buffer, size);
uidString.push_back (ch);
desSize --;
}
TypeId tid = TypeId::LookupByName (uidString);
uid = tid.GetUid ();
}
uint8_t isBig = i.ReadU8 ();
size --;
uint8_t isBig = 0;
buffer = ReadFromRawU8 (isBig, start, buffer, size);
desSize --;
item.typeUid = (uid << 1) | isBig;
item.size = i.ReadU32 ();
size -= 4;
item.chunkUid = i.ReadU16 ();
size -= 2;
extraItem.fragmentStart = i.ReadU32 ();
size -= 4;
extraItem.fragmentEnd = i.ReadU32 ();
size -= 4;
extraItem.packetUid = i.ReadU32 ();
size -= 4;
buffer = ReadFromRawU32 (item.size, start, buffer, size);
desSize -= 4;
buffer = ReadFromRawU16 (item.chunkUid, start, buffer, size);
desSize -= 2;
buffer = ReadFromRawU32 (extraItem.fragmentStart, start, buffer, size);
desSize -= 4;
buffer = ReadFromRawU32 (extraItem.fragmentEnd, start, buffer, size);
desSize -= 4;
buffer = ReadFromRawU64 (extraItem.packetUid, start, buffer, size);
desSize -= 8;
NS_LOG_LOGIC ("size=" << size << ", typeUid="<<item.typeUid <<
", size="<<item.size<<", chunkUid="<<item.chunkUid<<
", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
@@ -1193,8 +1253,144 @@ PacketMetadata::Deserialize (Buffer::Iterator i)
uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
UpdateTail (tmp);
}
NS_ASSERT (size == 0);
return totalSize;
NS_ASSERT (desSize == 0);
return (desSize !=0) ? 0 : 1;
}
uint8_t*
PacketMetadata::AddToRawU8 (const uint8_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer overflow
if ((uint32_t)((current + sizeof (uint8_t) - start)) > maxSize)
{
return 0;
}
memcpy (current, &data, sizeof (uint8_t));
return current + sizeof (uint8_t);
}
uint8_t*
PacketMetadata::AddToRawU16 (const uint16_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer overflow
if ((uint32_t)((current + sizeof (uint16_t) - start)) > maxSize)
{
return 0;
}
memcpy (current, &data, sizeof (uint16_t));
return current + sizeof (uint16_t);
}
uint8_t*
PacketMetadata::AddToRawU32 (const uint32_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer overflow
if ((uint32_t)((current + sizeof (uint32_t) - start)) > maxSize)
{
return 0;
}
memcpy (current, &data, sizeof (uint32_t));
return current + sizeof (uint32_t);
}
uint8_t*
PacketMetadata::AddToRawU64 (const uint64_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer overflow
if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
{
return 0;
}
memcpy (current, &data, sizeof (uint64_t));
return current + sizeof (uint64_t);
}
uint8_t*
PacketMetadata::AddToRaw (const uint8_t* data,
uint32_t dataSize,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer overflow
if ((uint32_t)((current + dataSize - start)) > maxSize)
{
return 0;
}
memcpy (current, data, dataSize);
return current + dataSize;
}
uint8_t*
PacketMetadata::ReadFromRawU8 (uint8_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer underflow
if ((uint32_t)((current + sizeof (uint8_t) - start)) > maxSize)
{
return 0;
}
memcpy(&data, current, sizeof (uint8_t));
return current + sizeof (uint8_t);
}
uint8_t*
PacketMetadata::ReadFromRawU16 (uint16_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer underflow
if ((uint32_t)((current + sizeof (uint16_t) - start)) > maxSize)
{
return 0;
}
memcpy(&data, current, sizeof (uint16_t));
return current + sizeof (uint16_t);
}
uint8_t*
PacketMetadata::ReadFromRawU32 (uint32_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer underflow
if ((uint32_t)((current + sizeof (uint32_t) - start)) > maxSize)
{
return 0;
}
memcpy(&data, current, sizeof (uint32_t));
return current + sizeof (uint32_t);
}
uint8_t*
PacketMetadata::ReadFromRawU64 (uint64_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize)
{
// First check buffer underflow
if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
{
return 0;
}
memcpy(&data, current, sizeof (uint64_t));
return current + sizeof (uint64_t);
}

View File

@@ -127,7 +127,7 @@ public:
static void Enable (void);
static void EnableChecking (void);
inline PacketMetadata (uint32_t uid, uint32_t size);
inline PacketMetadata (uint64_t uid, uint32_t size);
inline PacketMetadata (PacketMetadata const &o);
inline PacketMetadata &operator = (PacketMetadata const& o);
inline ~PacketMetadata ();
@@ -151,15 +151,63 @@ public:
void RemoveAtStart (uint32_t start);
void RemoveAtEnd (uint32_t end);
uint32_t GetUid (void) const;
uint64_t GetUid (void) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator i, uint32_t size) const;
uint32_t Deserialize (Buffer::Iterator i);
ItemIterator BeginItem (Buffer buffer) const;
// Serialization to/from raw uint8_t*
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
uint32_t Deserialize (uint8_t* buffer, uint32_t size);
private:
// Helper for the raw serilization/deserialization
static uint8_t* AddToRawU8 (const uint8_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* AddToRawU16 (const uint16_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* AddToRawU32 (const uint32_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* AddToRawU64 (const uint64_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* AddToRaw (const uint8_t* data,
uint32_t dataSize,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* ReadFromRawU8 (uint8_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* ReadFromRawU16 (uint16_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* ReadFromRawU32 (uint32_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
static uint8_t* ReadFromRawU64 (uint64_t& data,
uint8_t* start,
uint8_t* current,
uint32_t maxSize);
struct Data {
/* number of references to this struct Data instance. */
uint16_t m_count;
@@ -231,9 +279,9 @@ private:
/* the packetUid of the packet in which this header or trailer
was first added. It could be different from the m_packetUid
field if the user has aggregated multiple packets into one.
stored as a fixed-size 32 bit integer.
stored as a fixed-size 64 bit integer.
*/
uint32_t packetUid;
uint64_t packetUid;
};
class DataFreeList : public std::vector<struct Data *>
@@ -297,15 +345,15 @@ private:
uint16_t m_head;
uint16_t m_tail;
uint16_t m_used;
uint32_t m_packetUid;
uint64_t m_packetUid;
};
}; // namespace ns3
namespace ns3 {
PacketMetadata::PacketMetadata (uint32_t uid, uint32_t size)
: m_data (PacketMetadata::Create (10)),
PacketMetadata::PacketMetadata (uint64_t uid, uint32_t size)
: m_data (m_data = PacketMetadata::Create (10)),
m_head (0xffff),
m_tail (0xffff),
m_used (0),

View File

@@ -20,6 +20,7 @@
#include "packet.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/test.h"
#include <string>
#include <stdarg.h>
@@ -125,7 +126,7 @@ Packet::Packet ()
: m_buffer (),
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, 0),
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, 0),
m_nixVector (0)
{
m_globalUid++;
@@ -161,16 +162,27 @@ Packet::Packet (uint32_t size)
: m_buffer (size),
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, size),
m_nixVector (0)
{
m_globalUid++;
}
Packet::Packet (uint8_t const *buffer, uint32_t size, bool magic)
: m_buffer (0, false),
m_byteTagList (),
m_packetTagList (),
m_metadata (0,0),
m_nixVector (0)
{
NS_ASSERT (magic);
Deserialize (buffer, size);
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, size),
m_nixVector (0)
{
m_globalUid++;
@@ -359,7 +371,7 @@ Packet::CopyData(std::ostream *os, uint32_t size) const
return m_buffer.CopyData (os, size);
}
uint32_t
uint64_t
Packet::GetUid (void) const
{
return m_metadata.GetUid ();
@@ -532,48 +544,197 @@ Packet::EnableChecking (void)
PacketMetadata::EnableChecking ();
}
Buffer
Packet::Serialize (void) const
uint32_t Packet::GetSerializedSize (void) const
{
NS_LOG_FUNCTION (this);
Buffer buffer;
uint32_t reserve;
uint32_t size = 0;
// write metadata
reserve = m_metadata.GetSerializedSize ();
buffer.AddAtStart (reserve);
m_metadata.Serialize (buffer.Begin (), reserve);
if (m_nixVector)
{
// increment total size by the size of the nix-vector
// ensuring 4-byte boundary
size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
// write tags
// add 4-bytes for entry of total length of nix-vector
size += 4;
}
else
{
// if no nix-vector, still have to add 4-bytes
// to account for the entry of total size for
// nix-vector in the buffer
size += 4;
}
//Tag size
//XXX
//reserve = m_tags.GetSerializedSize ();
//buffer.AddAtStart (reserve);
//m_tags.Serialize (buffer.Begin (), reserve);
// aggregate byte buffer, metadata, and tags
Buffer tmp = m_buffer.CreateFullCopy ();
tmp.AddAtEnd (buffer);
// write byte buffer size.
tmp.AddAtStart (4);
tmp.Begin ().WriteU32 (m_buffer.GetSize ());
//size += m_tags.GetSerializedSize ();
return tmp;
// increment total size by size of meta-data
// ensuring 4-byte boundary
size += ((m_metadata.GetSerializedSize () + 3) & (~3));
// add 4-bytes for entry of total length of meta-data
size += 4;
// increment total size by size of buffer
// ensuring 4-byte boundary
size += ((m_buffer.GetSerializedSize () + 3) & (~3));
// add 4-bytes for entry of total length of buffer
size += 4;
return size;
}
void
Packet::Deserialize (Buffer buffer)
uint32_t
Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
{
uint32_t* p = (uint32_t*)buffer;
uint32_t size = 0;
// if nix-vector exists, serialize it
if (m_nixVector)
{
uint32_t nixSize = m_nixVector->GetSerializedSize ();
if (size + nixSize <= maxSize)
{
// put the total length of nix-vector in the
// buffer. this includes 4-bytes for total
// length itself
*p++ = nixSize + 4;
size += nixSize;
// serialize the nix-vector
uint32_t serialized =
m_nixVector->Serialize (p, nixSize);
if (serialized)
{
// increment p by nixSize bytes
// ensuring 4-byte boundary
p += ((nixSize+3) & (~3)) / 4;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
else
{
// no nix vector, set zero length,
// ie 4-bytes, since it must include
// length for itself
if (size + 4 <= maxSize)
{
size += 4;
*p++ = 4;
}
else
{
return 0;
}
}
// Serialize Tags
// XXX
// Serialize Metadata
uint32_t metaSize = m_metadata.GetSerializedSize ();
if (size + metaSize <= maxSize)
{
// put the total length of metadata in the
// buffer. this includes 4-bytes for total
// length itself
*p++ = metaSize + 4;
size += metaSize;
// serialize the metadata
uint32_t serialized =
m_metadata.Serialize ((uint8_t*)p, metaSize);
if (serialized)
{
// increment p by metaSize bytes
// ensuring 4-byte boundary
p += ((metaSize+3) & (~3)) / 4;
}
else
{
return 0;
}
}
else
{
return 0;
}
// Serialize the packet contents
uint32_t bufSize = m_buffer.GetSerializedSize ();
if (size + bufSize <= maxSize)
{
// put the total length of the buffer in the
// buffer. this includes 4-bytes for total
// length itself
*p++ = bufSize + 4;
size += bufSize;
// serialize the buffer
uint32_t serialized =
m_buffer.Serialize ((uint8_t*)p, bufSize);
if (serialized)
{
// increment p by bufSize bytes
// ensuring 4-byte boundary
p += ((bufSize+3) & (~3)) / 4;
}
else
{
return 0;
}
}
else
{
return 0;
}
// Serialized successfully
return 1;
}
uint32_t
Packet::Deserialize (uint8_t const*buffer, uint32_t size)
{
NS_LOG_FUNCTION (this);
Buffer buf = buffer;
// read size
uint32_t packetSize = buf.Begin ().ReadU32 ();
buf.RemoveAtStart (4);
// read buffer.
buf.RemoveAtEnd (buf.GetSize () - packetSize);
m_buffer = buf;
buffer.RemoveAtStart (4 + packetSize);
uint32_t* p = (uint32_t*)buffer;
// read nix-vector
NS_ASSERT (!m_nixVector);
uint32_t nixSize = *p++;
size -= nixSize;
// if size less than zero, the buffer
// will be overrun, assert
NS_ASSERT (size >= 0);
if (nixSize > 4)
{
Ptr<NixVector> nix = CreateObject<NixVector> ();
uint32_t nixDeserialized = nix->Deserialize (p, nixSize);
if (!nixDeserialized)
{
// nix-vector not deserialized
// completely
return 0;
}
m_nixVector = nix;
// increment p by nixSize ensuring
// 4-byte boundary
p += ((((nixSize - 4) + 3) & (~3)) / 4);
}
// read tags
//XXX
@@ -581,9 +742,45 @@ Packet::Deserialize (Buffer buffer)
//buffer.RemoveAtStart (tagsDeserialized);
// read metadata
uint32_t metaSize = *p++;
size -= metaSize;
// if size less than zero, the buffer
// will be overrun, assert
NS_ASSERT (size >= 0);
uint32_t metadataDeserialized =
m_metadata.Deserialize (buffer.Begin ());
buffer.RemoveAtStart (metadataDeserialized);
m_metadata.Deserialize ((uint8_t*)p, metaSize);
if (!metadataDeserialized)
{
// meta-data not deserialized
// completely
return 0;
}
// increment p by metaSize ensuring
// 4-byte boundary
p += ((((metaSize - 4) + 3) & (~3)) / 4);
// read buffer contents
uint32_t bufSize = *p++;
size -= bufSize;
// if size less than zero, the buffer
// will be overrun, assert
NS_ASSERT (size >= 0);
uint32_t bufferDeserialized =
m_buffer.Deserialize ((uint8_t*)p, bufSize);
if (!bufferDeserialized)
{
// buffer not deserialized
// completely
return 0;
}
// return zero if did not deserialize the
// number of expected bytes
return (size == 0);
}
void

View File

@@ -221,6 +221,17 @@ public:
* \param size the size of the zero-filled payload
*/
Packet (uint32_t size);
/**
* Create a new packet from the serialized buffer. This new packet
* is identical to the serialized packet contained in the buffer
* and is magically deserialized for you
*
* \param buffer the serialized packet to be created
* \param size the size of the packet for deserialization
* \param magic allows packet deserialization;
* asserts when set to false
*/
Packet (uint8_t const*buffer, uint32_t size, bool magic);
/**
* Create a packet with payload filled with the content
* of this buffer. The input data is copied: the input
@@ -379,7 +390,7 @@ public:
* \returns an integer identifier which uniquely
* identifies this packet.
*/
uint32_t GetUid (void) const;
uint64_t GetUid (void) const;
/**
* \param os output stream in which the data should be printed.
@@ -420,36 +431,24 @@ public:
static void EnableChecking (void);
/**
* \returns a byte buffer
* For packet serializtion, the total size is checked
* in order to determine the size of the buffer
* required for serialization
*
* This method creates a serialized representation of a Packet object
* ready to be transmitted over a network to another system. This
* serialized representation contains a copy of the packet byte buffer,
* the tag list, and the packet metadata (if there is one).
*
* This method will trigger calls to the Serialize and GetSerializedSize
* methods of each tag stored in this packet.
*
* This method will typically be used by parallel simulations where
* the simulated system is partitioned and each partition runs on
* a different CPU.
* \returns number of bytes required for packet
* serialization
*/
Buffer Serialize (void) const;
/**
* \param buffer a byte buffer
uint32_t GetSerializedSize (void) const;
/*
* \param buffer a raw byte buffer to which the packet will be serialized
* \param maxSize the max size of the buffer for bounds checking
*
* This method reads a byte buffer as created by Packet::Serialize
* and restores the state of the Packet to what it was prior to
* calling Serialize.
* A packet is completely serialized and placed into the raw byte buffer
*
* This method will trigger calls to the Deserialize method
* of each tag stored in this packet.
*
* This method will typically be used by parallel simulations where
* the simulated system is partitioned and each partition runs on
* a different CPU.
* \returns zero if buffer size was too small
*/
void Deserialize (Buffer buffer);
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
/**
* \param tag the new tag to add to this packet
@@ -556,6 +555,9 @@ public:
private:
Packet (const Buffer &buffer, const ByteTagList &byteTagList,
const PacketTagList &packetTagList, const PacketMetadata &metadata);
uint32_t Deserialize (uint8_t const*buffer, uint32_t size);
Buffer m_buffer;
ByteTagList m_byteTagList;
PacketTagList m_packetTagList;

View File

@@ -124,4 +124,30 @@ PointToPointChannel::GetDevice (uint32_t i) const
return GetPointToPointDevice (i);
}
Time
PointToPointChannel::GetDelay (void) const
{
return m_delay;
}
Ptr<PointToPointNetDevice>
PointToPointChannel::GetSource (uint32_t i) const
{
return m_link[i].m_src;
}
Ptr<PointToPointNetDevice>
PointToPointChannel::GetDestination (uint32_t i) const
{
return m_link[i].m_dst;
}
bool
PointToPointChannel::IsInitialized (void) const
{
NS_ASSERT (m_link[0].m_state != INITIALIZING);
NS_ASSERT (m_link[1].m_state != INITIALIZING);
return true;
}
} // namespace ns3

View File

@@ -69,7 +69,7 @@ public:
* \param txTime Transmit time to apply
* \returns true if successful (currently always true)
*/
bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
virtual bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
/**
* \brief Get number of devices on this channel
@@ -91,6 +91,35 @@ public:
*/
virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
protected:
/*
* \brief Get the delay associated with this channel
* \returns Time delay
*/
Time GetDelay (void) const;
/*
* \brief Check to make sure the link is initialized
* \returns true if initialized, asserts otherwise
*/
bool IsInitialized (void) const;
/*
* \brief Get the net-device source
* \param i the link requested
* \returns Ptr to PointToPointNetDevice source for the
* specified link
*/
Ptr<PointToPointNetDevice> GetSource (uint32_t i) const;
/*
* \brief Get the net-device destination
* \param i the link requested
* \returns Ptr to PointToPointNetDevice destination for
* the specifed link
*/
Ptr<PointToPointNetDevice> GetDestination (uint32_t i) const;
private:
// Each point to point link has exactly two net devices
static const int N_DEVICES = 2;

View File

@@ -0,0 +1,80 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007, 2008 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
#include <iostream>
#include "point-to-point-remote-channel.h"
#include "point-to-point-net-device.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/mpi-interface.h"
using namespace std;
NS_LOG_COMPONENT_DEFINE ("PointToPointRemoteChannel");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (PointToPointRemoteChannel);
TypeId
PointToPointRemoteChannel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PointToPointRemoteChannel")
.SetParent<PointToPointChannel> ()
.AddConstructor<PointToPointRemoteChannel> ()
;
return tid;
}
PointToPointRemoteChannel::PointToPointRemoteChannel ()
{
}
PointToPointRemoteChannel::~PointToPointRemoteChannel ()
{
}
bool
PointToPointRemoteChannel::TransmitStart (
Ptr<Packet> p,
Ptr<PointToPointNetDevice> src,
Time txTime)
{
NS_LOG_FUNCTION (this << p << src);
NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
IsInitialized ();
uint32_t wire = src == GetSource (0) ? 0 : 1;
Ptr<PointToPointNetDevice> dst = GetDestination (wire);
// Calculate the rxTime (absolute)
Time rxTime = Simulator::Now () + txTime + GetDelay ();
#ifdef NS3_MPI
MpiInterface::SendPacket (p, rxTime, dst->GetNode ()->GetId (), dst->GetIfIndex ());
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
return true;
}
} // namespace ns3

View File

@@ -0,0 +1,44 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
// This object connects two point-to-point net devices where at least one
// is not local to this simulator object. It simply over-rides the transmit
// method and uses an MPI Send operation instead.
#ifndef POINT_TO_POINT_REMOTE_CHANNEL_H
#define POINT_TO_POINT_REMOTE_CHANNEL_H
#include "point-to-point-channel.h"
namespace ns3 {
class PointToPointRemoteChannel : public PointToPointChannel
{
public:
static TypeId GetTypeId (void);
PointToPointRemoteChannel ();
~PointToPointRemoteChannel ();
virtual bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
};
}
#endif

View File

@@ -6,6 +6,7 @@ def build(bld):
module.source = [
'point-to-point-net-device.cc',
'point-to-point-channel.cc',
'point-to-point-remote-channel.cc',
'point-to-point-test.cc',
'ppp-header.cc',
]
@@ -14,6 +15,7 @@ def build(bld):
headers.source = [
'point-to-point-net-device.h',
'point-to-point-channel.h',
'point-to-point-remote-channel.h',
'ppp-header.h',
]

View File

@@ -97,6 +97,14 @@ NodeContainer::Create (uint32_t n)
}
}
void
NodeContainer::Create (uint32_t n, uint32_t systemId)
{
for (uint32_t i = 0; i < n; i++)
{
m_nodes.push_back (CreateObject<Node> (systemId));
}
}
void
NodeContainer::Add (NodeContainer other)
{
for (Iterator i = other.Begin (); i != other.End (); i++)

View File

@@ -236,6 +236,20 @@ public:
*/
void Create (uint32_t n);
/**
* \brief Create n nodes with specifiec systemId for distributed simulations
* and append pointers to them to the end of this NodeContainer.
*
* Nodes are at the heart of any ns-3 simulation. One of the first tasks that
* any simulation needs to do is to create a number of nodes. This method
* automates that task, and adds the ability to specifiy systemId for
* distributed simulations.
*
* \param n The number of Nodes to create
* \param systemId The system id or rank associated with this node
*/
void Create (uint32_t n, uint32_t systemId);
/**
* \brief Append the contents of another NodeContainer to the end of
* this container.

View File

@@ -23,10 +23,12 @@
#include "ns3/simulator.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/point-to-point-remote-channel.h"
#include "ns3/queue.h"
#include "ns3/config.h"
#include "ns3/packet.h"
#include "ns3/names.h"
#include "ns3/mpi-interface.h"
#include "trace-helper.h"
#include "point-to-point-helper.h"
@@ -40,6 +42,7 @@ PointToPointHelper::PointToPointHelper ()
m_queueFactory.SetTypeId ("ns3::DropTailQueue");
m_deviceFactory.SetTypeId ("ns3::PointToPointNetDevice");
m_channelFactory.SetTypeId ("ns3::PointToPointChannel");
m_remoteChannelFactory.SetTypeId ("ns3::PointToPointRemoteChannel");
}
void
@@ -66,6 +69,7 @@ void
PointToPointHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
{
m_channelFactory.Set (n1, v1);
m_remoteChannelFactory.Set (n1, v1);
}
void
@@ -223,7 +227,30 @@ PointToPointHelper::Install (Ptr<Node> a, Ptr<Node> b)
b->AddDevice (devB);
Ptr<Queue> queueB = m_queueFactory.Create<Queue> ();
devB->SetQueue (queueB);
Ptr<PointToPointChannel> channel = m_channelFactory.Create<PointToPointChannel> ();
// If MPI is enabled, we need to see if both nodes have the same system id
// (rank), and the rank is the same as this instance. If both are true,
//use a normal p2p channel, otherwise use a remote channel
bool useNormalChannel = true;
Ptr<PointToPointChannel> channel = 0;
if (MpiInterface::IsEnabled())
{
uint32_t n1SystemId = a->GetSystemId ();
uint32_t n2SystemId = b->GetSystemId ();
uint32_t currSystemId = MpiInterface::GetSystemId ();
if (n1SystemId != currSystemId || n2SystemId != currSystemId)
{
useNormalChannel = false;
}
}
if (useNormalChannel)
{
channel = m_channelFactory.Create<PointToPointChannel> ();
}
else
{
channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
}
devA->Attach (channel);
devB->Attach (channel);
container.Add (devA);

View File

@@ -116,7 +116,9 @@ public:
* \param a first node
* \param b second node
*
* Saves you from having to construct a temporary NodeContainer.
* Saves you from having to construct a temporary NodeContainer.
* Also, if MPI is enabled, for distributed simulations,
* appropriate remote point-to-point channels are created.
*/
NetDeviceContainer Install (Ptr<Node> a, Ptr<Node> b);
@@ -177,6 +179,7 @@ private:
ObjectFactory m_queueFactory;
ObjectFactory m_channelFactory;
ObjectFactory m_remoteChannelFactory;
ObjectFactory m_deviceFactory;
};

View File

@@ -0,0 +1,521 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
#include "distributed-simulator-impl.h"
#include "mpi-interface.h"
#include "ns3/simulator.h"
#include "ns3/scheduler.h"
#include "ns3/event-impl.h"
#include "ns3/channel.h"
#include "ns3/node-container.h"
#include "ns3/ptr.h"
#include "ns3/pointer.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include <math.h>
#ifdef NS3_MPI
#include <mpi.h>
#endif
NS_LOG_COMPONENT_DEFINE ("DistributedSimulatorImpl");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (DistributedSimulatorImpl);
LbtsMessage::~LbtsMessage ()
{
}
Time
LbtsMessage::GetSmallestTime ()
{
return m_smallestTime;
}
uint32_t
LbtsMessage::GetTxCount ()
{
return m_txCount;
}
uint32_t
LbtsMessage::GetRxCount ()
{
return m_rxCount;
}
uint32_t
LbtsMessage::GetMyId ()
{
return m_myId;
}
Time DistributedSimulatorImpl::m_lookAhead = Seconds (0);
TypeId
DistributedSimulatorImpl::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::DistributedSimulatorImpl")
.SetParent<Object> ()
.AddConstructor<DistributedSimulatorImpl> ()
;
return tid;
}
DistributedSimulatorImpl::DistributedSimulatorImpl ()
{
#ifdef NS3_MPI
m_myId = MpiInterface::GetSystemId ();
m_systemCount = MpiInterface::GetSize ();
// Allocate the LBTS message buffer
m_pLBTS = new LbtsMessage[m_systemCount];
m_grantedTime = Seconds (0);
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
m_stop = false;
// uids are allocated from 4.
// uid 0 is "invalid" events
// uid 1 is "now" events
// uid 2 is "destroy" events
m_uid = 4;
// before ::Run is entered, the m_currentUid will be zero
m_currentUid = 0;
m_currentTs = 0;
m_currentContext = 0xffffffff;
m_unscheduledEvents = 0;
m_events = 0;
}
DistributedSimulatorImpl::~DistributedSimulatorImpl ()
{
}
void
DistributedSimulatorImpl::DoDispose (void)
{
while (!m_events->IsEmpty ())
{
Scheduler::Event next = m_events->RemoveNext ();
next.impl->Unref ();
}
m_events = 0;
delete [] m_pLBTS;
SimulatorImpl::DoDispose ();
}
void
DistributedSimulatorImpl::Destroy ()
{
while (!m_destroyEvents.empty ())
{
Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
m_destroyEvents.pop_front ();
NS_LOG_LOGIC ("handle destroy " << ev);
if (!ev->IsCancelled ())
{
ev->Invoke ();
}
}
MpiInterface::Destroy ();
}
void
DistributedSimulatorImpl::CalculateLookAhead (void)
{
#ifdef NS3_MPI
if (MpiInterface::GetSize () <= 1)
{
DistributedSimulatorImpl::m_lookAhead = Seconds (0);
m_grantedTime = Seconds (0);
}
else
{
NodeContainer c = NodeContainer::GetGlobal ();
for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
{
if ((*iter)->GetSystemId () != MpiInterface::GetSystemId ())
{
continue;
}
for (uint32_t i = 0; i < (*iter)->GetNDevices (); ++i)
{
Ptr<NetDevice> localNetDevice = (*iter)->GetDevice (i);
// only works for p2p links currently
if (!localNetDevice->IsPointToPoint ())
{
continue;
}
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
{
continue;
}
// grab the adjacent node
Ptr<Node> remoteNode;
if (channel->GetDevice (0) == localNetDevice)
{
remoteNode = (channel->GetDevice (1))->GetNode ();
}
else
{
remoteNode = (channel->GetDevice (0))->GetNode ();
}
// if it's not remote, don't consider it
if (remoteNode->GetSystemId () == MpiInterface::GetSystemId ())
{
continue;
}
// compare delay on the channel with current value of
// m_lookAhead. if delay on channel is smaller, make
// it the new lookAhead.
TimeValue delay;
channel->GetAttribute ("Delay", delay);
if (DistributedSimulatorImpl::m_lookAhead.IsZero ())
{
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
m_grantedTime = delay.Get ();
}
if (delay.Get ().GetSeconds () < DistributedSimulatorImpl::m_lookAhead.GetSeconds ())
{
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
m_grantedTime = delay.Get ();
}
}
}
}
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
void
DistributedSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
{
Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
if (m_events != 0)
{
while (!m_events->IsEmpty ())
{
Scheduler::Event next = m_events->RemoveNext ();
scheduler->Insert (next);
}
}
m_events = scheduler;
}
void
DistributedSimulatorImpl::ProcessOneEvent (void)
{
Scheduler::Event next = m_events->RemoveNext ();
NS_ASSERT (next.key.m_ts >= m_currentTs);
m_unscheduledEvents--;
NS_LOG_LOGIC ("handle " << next.key.m_ts);
m_currentTs = next.key.m_ts;
m_currentContext = next.key.m_context;
m_currentUid = next.key.m_uid;
next.impl->Invoke ();
next.impl->Unref ();
}
bool
DistributedSimulatorImpl::IsFinished (void) const
{
return m_events->IsEmpty () || m_stop;
}
uint64_t
DistributedSimulatorImpl::NextTs (void) const
{
NS_ASSERT (!m_events->IsEmpty ());
Scheduler::Event ev = m_events->PeekNext ();
return ev.key.m_ts;
}
Time
DistributedSimulatorImpl::Next (void) const
{
return TimeStep (NextTs ());
}
void
DistributedSimulatorImpl::Run (void)
{
#ifdef NS3_MPI
CalculateLookAhead ();
m_stop = false;
while (!m_events->IsEmpty () && !m_stop)
{
Time nextTime = Next ();
if (nextTime > m_grantedTime)
{ // Can't process, calculate a new LBTS
// First receive any pending messages
MpiInterface::ReceiveMessages ();
// reset next time
nextTime = Next ();
// And check for send completes
MpiInterface::TestSendComplete ();
// Finally calculate the lbts
LbtsMessage lMsg (MpiInterface::GetRxCount (), MpiInterface::GetTxCount (), m_myId, nextTime);
m_pLBTS[m_myId] = lMsg;
MPI_Allgather (&lMsg, sizeof (LbtsMessage), MPI_BYTE, m_pLBTS,
sizeof (LbtsMessage), MPI_BYTE, MPI_COMM_WORLD);
Time smallestTime = m_pLBTS[0].GetSmallestTime ();
// The totRx and totTx counts insure there are no transient
// messages; If totRx != totTx, there are transients,
// so we don't update the granted time.
uint32_t totRx = m_pLBTS[0].GetRxCount ();
uint32_t totTx = m_pLBTS[0].GetTxCount ();
for (uint32_t i = 1; i < m_systemCount; ++i)
{
if (m_pLBTS[i].GetSmallestTime () < smallestTime)
{
smallestTime = m_pLBTS[i].GetSmallestTime ();
}
totRx += m_pLBTS[i].GetRxCount ();
totTx += m_pLBTS[i].GetTxCount ();
}
if (totRx == totTx)
{
m_grantedTime = smallestTime + DistributedSimulatorImpl::m_lookAhead;
}
}
if (nextTime <= m_grantedTime)
{ // Save to process
ProcessOneEvent ();
}
}
// If the simulator stopped naturally by lack of events, make a
// consistency test to check that we didn't lose any events along the way.
NS_ASSERT (!m_events->IsEmpty () || m_unscheduledEvents == 0);
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
uint32_t DistributedSimulatorImpl::GetSystemId () const
{
return m_myId;
}
void
DistributedSimulatorImpl::RunOneEvent (void)
{
ProcessOneEvent ();
}
void
DistributedSimulatorImpl::Stop (void)
{
m_stop = true;
}
void
DistributedSimulatorImpl::Stop (Time const &time)
{
Simulator::Schedule (time, &Simulator::Stop);
}
//
// Schedule an event for a _relative_ time in the future.
//
EventId
DistributedSimulatorImpl::Schedule (Time const &time, EventImpl *event)
{
Time tAbsolute = time + TimeStep (m_currentTs);
NS_ASSERT (tAbsolute.IsPositive ());
NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
Scheduler::Event ev;
ev.impl = event;
ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
ev.key.m_context = GetContext ();
ev.key.m_uid = m_uid;
m_uid++;
m_unscheduledEvents++;
m_events->Insert (ev);
return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
}
void
DistributedSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event)
{
NS_LOG_FUNCTION (this << context << time.GetTimeStep () << m_currentTs << event);
Scheduler::Event ev;
ev.impl = event;
ev.key.m_ts = m_currentTs + time.GetTimeStep ();
ev.key.m_context = context;
ev.key.m_uid = m_uid;
m_uid++;
m_unscheduledEvents++;
m_events->Insert (ev);
}
EventId
DistributedSimulatorImpl::ScheduleNow (EventImpl *event)
{
Scheduler::Event ev;
ev.impl = event;
ev.key.m_ts = m_currentTs;
ev.key.m_context = GetContext ();
ev.key.m_uid = m_uid;
m_uid++;
m_unscheduledEvents++;
m_events->Insert (ev);
return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
}
EventId
DistributedSimulatorImpl::ScheduleDestroy (EventImpl *event)
{
EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
m_destroyEvents.push_back (id);
m_uid++;
return id;
}
Time
DistributedSimulatorImpl::Now (void) const
{
return TimeStep (m_currentTs);
}
Time
DistributedSimulatorImpl::GetDelayLeft (const EventId &id) const
{
if (IsExpired (id))
{
return TimeStep (0);
}
else
{
return TimeStep (id.GetTs () - m_currentTs);
}
}
void
DistributedSimulatorImpl::Remove (const EventId &id)
{
if (id.GetUid () == 2)
{
// destroy events.
for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
{
if (*i == id)
{
m_destroyEvents.erase (i);
break;
}
}
return;
}
if (IsExpired (id))
{
return;
}
Scheduler::Event event;
event.impl = id.PeekEventImpl ();
event.key.m_ts = id.GetTs ();
event.key.m_context = id.GetContext ();
event.key.m_uid = id.GetUid ();
m_events->Remove (event);
event.impl->Cancel ();
// whenever we remove an event from the event list, we have to unref it.
event.impl->Unref ();
m_unscheduledEvents--;
}
void
DistributedSimulatorImpl::Cancel (const EventId &id)
{
if (!IsExpired (id))
{
id.PeekEventImpl ()->Cancel ();
}
}
bool
DistributedSimulatorImpl::IsExpired (const EventId &ev) const
{
if (ev.GetUid () == 2)
{
if (ev.PeekEventImpl () == 0
|| ev.PeekEventImpl ()->IsCancelled ())
{
return true;
}
// destroy events.
for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
{
if (*i == ev)
{
return false;
}
}
return true;
}
if (ev.PeekEventImpl () == 0
|| ev.GetTs () < m_currentTs
|| (ev.GetTs () == m_currentTs
&& ev.GetUid () <= m_currentUid)
|| ev.PeekEventImpl ()->IsCancelled ())
{
return true;
}
else
{
return false;
}
}
Time
DistributedSimulatorImpl::GetMaximumSimulationTime (void) const
{
// XXX: I am fairly certain other compilers use other non-standard
// post-fixes to indicate 64 bit constants.
return TimeStep (0x7fffffffffffffffLL);
}
uint32_t
DistributedSimulatorImpl::GetContext (void) const
{
return m_currentContext;
}
} // namespace ns3

View File

@@ -0,0 +1,124 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
#ifndef DISTRIBUTED_SIMULATOR_IMPL_H
#define DISTRIBUTED_SIMULATOR_IMPL_H
#include "ns3/simulator-impl.h"
#include "ns3/scheduler.h"
#include "ns3/event-impl.h"
#include "ns3/ptr.h"
#include <list>
namespace ns3 {
// Structure used for all-reduce LBTS computation
class LbtsMessage
{
public:
LbtsMessage ()
: m_txCount (0),
m_rxCount (0),
m_myId (0)
{
}
LbtsMessage (uint32_t rxc, uint32_t txc, uint32_t id, const Time& t)
: m_txCount (txc),
m_rxCount (rxc),
m_myId (id),
m_smallestTime (t)
{
}
~LbtsMessage ();
Time GetSmallestTime ();
uint32_t GetTxCount ();
uint32_t GetRxCount ();
uint32_t GetMyId ();
private:
uint32_t m_txCount;
uint32_t m_rxCount;
uint32_t m_myId;
Time m_smallestTime;
};
class DistributedSimulatorImpl : public SimulatorImpl
{
public:
static TypeId GetTypeId (void);
DistributedSimulatorImpl ();
~DistributedSimulatorImpl ();
virtual void Destroy ();
virtual bool IsFinished (void) const;
virtual Time Next (void) const;
virtual void Stop (void);
virtual void Stop (Time const &time);
virtual EventId Schedule (Time const &time, EventImpl *event);
virtual void ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event);
virtual EventId ScheduleNow (EventImpl *event);
virtual EventId ScheduleDestroy (EventImpl *event);
virtual void Remove (const EventId &ev);
virtual void Cancel (const EventId &ev);
virtual bool IsExpired (const EventId &ev) const;
virtual void Run (void);
virtual void RunOneEvent (void);
virtual Time Now (void) const;
virtual Time GetDelayLeft (const EventId &id) const;
virtual Time GetMaximumSimulationTime (void) const;
virtual void SetScheduler (ObjectFactory schedulerFactory);
virtual uint32_t GetSystemId (void) const;
virtual uint32_t GetContext (void) const;
private:
virtual void DoDispose (void);
void CalculateLookAhead (void);
void ProcessOneEvent (void);
uint64_t NextTs (void) const;
typedef std::list<EventId> DestroyEvents;
DestroyEvents m_destroyEvents;
bool m_stop;
Ptr<Scheduler> m_events;
uint32_t m_uid;
uint32_t m_currentUid;
uint64_t m_currentTs;
uint32_t m_currentContext;
// number of events that have been inserted but not yet scheduled,
// not counting the "destroy" events; this is used for validation
int m_unscheduledEvents;
LbtsMessage* m_pLBTS; // Allocated once we know how many systems
uint32_t m_myId; // MPI Rank
uint32_t m_systemCount; // MPI Size
Time m_grantedTime; // Last LBTS
static Time m_lookAhead; // Lookahead value
};
} // namespace ns3
#endif /* DISTRIBUTED_SIMULATOR_IMPL_H */

287
src/mpi/mpi-interface.cc Normal file
View File

@@ -0,0 +1,287 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
// This object contains static methods that provide an easy interface
// to the necessary MPI information.
#include <iostream>
#include <iomanip>
#include <list>
#include "mpi-interface.h"
#include "ns3/node.h"
#include "ns3/node-list.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/simulator.h"
#include "ns3/simulator-impl.h"
#include "ns3/nstime.h"
#ifdef NS3_MPI
#include <mpi.h>
#endif
namespace ns3 {
SentBuffer::SentBuffer ()
{
m_buffer = 0;
m_request = 0;
}
SentBuffer::~SentBuffer ()
{
delete [] m_buffer;
}
uint8_t*
SentBuffer::GetBuffer ()
{
return m_buffer;
}
void
SentBuffer::SetBuffer (uint8_t* buffer)
{
m_buffer = buffer;
}
#ifdef NS3_MPI
MPI_Request*
SentBuffer::GetRequest ()
{
return &m_request;
}
#endif
uint32_t MpiInterface::m_sid = 0;
uint32_t MpiInterface::m_size = 1;
bool MpiInterface::m_initialized = false;
bool MpiInterface::m_enabled = false;
uint32_t MpiInterface::m_rxCount = 0;
uint32_t MpiInterface::m_txCount = 0;
std::list<SentBuffer> MpiInterface::m_pendingTx;
#ifdef NS3_MPI
MPI_Request* MpiInterface::m_requests;
char** MpiInterface::m_pRxBuffers;
#endif
void
MpiInterface::Destroy ()
{
#ifdef NS3_MPI
for (uint32_t i = 0; i < GetSize (); ++i)
{
delete [] m_pRxBuffers[i];
}
delete [] m_pRxBuffers;
delete [] m_requests;
m_pendingTx.clear ();
#endif
}
uint32_t
MpiInterface::GetRxCount ()
{
return m_rxCount;
}
uint32_t
MpiInterface::GetTxCount ()
{
return m_txCount;
}
uint32_t
MpiInterface::GetSystemId ()
{
if (!m_initialized)
{
Simulator::GetImplementation ();
m_initialized = true;
}
return m_sid;
}
uint32_t
MpiInterface::GetSize ()
{
if (!m_initialized)
{
Simulator::GetImplementation ();
m_initialized = true;
}
return m_size;
}
bool
MpiInterface::IsEnabled ()
{
if (!m_initialized)
{
Simulator::GetImplementation ();
m_initialized = true;
}
return m_enabled;
}
void
MpiInterface::Enable (int* pargc, char*** pargv)
{
#ifdef NS3_MPI
// Initialize the MPI interface
MPI_Init (pargc, pargv);
MPI_Barrier (MPI_COMM_WORLD);
MPI_Comm_rank (MPI_COMM_WORLD, (int*)&m_sid);
MPI_Comm_size (MPI_COMM_WORLD, (int*)&m_size);
m_enabled = true;
m_initialized = true;
// Post a non-blocking receive for all peers
m_pRxBuffers = new char*[m_size];
m_requests = new MPI_Request[m_size];
for (uint32_t i = 0; i < GetSize (); ++i)
{
m_pRxBuffers[i] = new char[MAX_MPI_MSG_SIZE];
MPI_Irecv (m_pRxBuffers[i], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
MPI_COMM_WORLD, &m_requests[i]);
}
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
void
MpiInterface::SendPacket (Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev)
{
#ifdef NS3_MPI
SentBuffer sendBuf;
m_pendingTx.push_back (sendBuf);
std::list<SentBuffer>::reverse_iterator i = m_pendingTx.rbegin (); // Points to the last element
uint32_t serializedSize = p->GetSerializedSize ();
uint8_t* buffer = new uint8_t[serializedSize + 16];
i->SetBuffer (buffer);
// Add the time, dest node and dest device
uint64_t t = rxTime.GetNanoSeconds ();
uint64_t* pTime = (uint64_t*)buffer;
*pTime++ = t;
uint32_t* pData = (uint32_t*)pTime;
*pData++ = node;
*pData++ = dev;
// Serialize the packet
p->Serialize ((uint8_t*)pData, serializedSize);
// Find the system id for the destination node
Ptr<Node> destNode = NodeList::GetNode (node);
uint32_t nodeSysId = destNode->GetSystemId ();
MPI_Isend ((void*)i->GetBuffer (), serializedSize + 16, MPI_CHAR, nodeSysId,
0, MPI_COMM_WORLD, (i->GetRequest ()));
m_txCount++;
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
void
MpiInterface::ReceiveMessages ()
{ // Poll the non-block reads to see if data arrived
#ifdef NS3_MPI
while (true)
{
int flag = 0;
int index = 0;
MPI_Status status;
MPI_Testany (GetSize (), m_requests, &index, &flag, &status);
if (!flag)
{
break; // No more messages
}
int count;
MPI_Get_count (&status, MPI_CHAR, &count);
m_rxCount++; // Count this receive
// Get the meta data first
uint64_t* pTime = (uint64_t*)m_pRxBuffers[index];
uint64_t nanoSeconds = *pTime++;
uint32_t* pData = (uint32_t*)pTime;
uint32_t node = *pData++;
uint32_t dev = *pData++;
Time rxTime = NanoSeconds (nanoSeconds);
count -= sizeof (nanoSeconds) + sizeof (node) + sizeof (dev);
Ptr<Packet> p = Create<Packet> ((uint8_t*)pData, count, true);
// Find the correct node/device to schedule receive event
Ptr<Node> pNode = NodeList::GetNode (node);
uint32_t nDevices = pNode->GetNDevices ();
Ptr<PointToPointNetDevice> pDev = 0;
for (uint32_t i = 0; i < nDevices; ++i)
{
Ptr<NetDevice> pThisDev = pNode->GetDevice (i);
if (pThisDev->GetIfIndex () == dev)
{
pDev = DynamicCast<PointToPointNetDevice> (pThisDev);
break;
}
}
NS_ASSERT (pNode && pDev);
// Schedule the rx event
Simulator::ScheduleWithContext (pNode->GetId (), rxTime - Simulator::Now (),
&PointToPointNetDevice::Receive,
pDev, p);
// Re-queue the next read
MPI_Irecv (m_pRxBuffers[index], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
MPI_COMM_WORLD, &m_requests[index]);
}
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
void
MpiInterface::TestSendComplete ()
{
#ifdef NS3_MPI
std::list<SentBuffer>::iterator i = m_pendingTx.begin ();
while (i != m_pendingTx.end ())
{
MPI_Status status;
int flag = 0;
MPI_Test (i->GetRequest (), &flag, &status);
std::list<SentBuffer>::iterator current = i; // Save current for erasing
i++; // Advance to next
if (flag)
{ // This message is complete
m_pendingTx.erase (current);
}
}
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
}
} // namespace ns3

85
src/mpi/mpi-interface.h Normal file
View File

@@ -0,0 +1,85 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*/
// This object contains static methods that provide an easy interface
// to the necessary MPI information.
#ifndef NS3_MPI_INTERFACE_H
#define NS3_MPI_INTERFACE_H
#include <stdint.h>
#include <list>
#include "ns3/nstime.h"
#include "ns3/buffer.h"
struct ompi_request_t;
typedef struct ompi_request_t* MPI_Request;
namespace ns3 {
const uint32_t MAX_MPI_MSG_SIZE = 2000;
// Define a class for tracking the non-block sends
class SentBuffer
{
public:
SentBuffer ();
~SentBuffer ();
uint8_t* GetBuffer ();
void SetBuffer (uint8_t*);
MPI_Request* GetRequest ();
private:
uint8_t* m_buffer;
MPI_Request m_request;
};
class Packet;
class MpiInterface
{
public:
static void Destroy ();
static uint32_t GetSystemId (); // Get the MPI Rank (system id)
static uint32_t GetSize (); // Get the MPI Size (number of systems)
static bool IsEnabled (); // True if using MPI
static void Enable (int*, char***); // Called by ns3 main program
// Serialize and send a packet to the specified node and net device
static void SendPacket (Ptr<Packet>, const Time &, uint32_t, uint32_t);
static void ReceiveMessages (); // Check for received messages complete
static void TestSendComplete (); // Check for completed sends
static uint32_t GetRxCount ();
static uint32_t GetTxCount ();
private:
static uint32_t m_sid;
static uint32_t m_size;
static uint32_t m_rxCount; // Total packets received
static uint32_t m_txCount; // Total packets sent
static bool m_initialized;
static bool m_enabled;
static MPI_Request* m_requests; // Pending non-blocking receives
static char** m_pRxBuffers; // Data buffers for non-blocking reads
static std::list<SentBuffer> m_pendingTx; // List of pending non-blocking sends
};
} // namespace ns3
#endif /* NS3_MPI_INTERFACE_H */

1
src/mpi/waf vendored Executable file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../waf "$@"

23
src/mpi/wscript Normal file
View File

@@ -0,0 +1,23 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import sys
import Options
def build(bld):
env = bld.env_of_name('default')
sim = bld.create_ns3_module('mpi', ['core', 'simulator'])
sim.source = [
'distributed-simulator-impl.cc',
'mpi-interface.cc',
]
headers = bld.new_task_gen('ns3header')
headers.module = 'mpi'
headers.source = [
'distributed-simulator-impl.h',
'mpi-interface.h',
]
if env['ENABLE_MPI']:
sim.uselib = 'MPI'

View File

@@ -34,6 +34,7 @@
#include "ns3/ipv4.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/ipv4-list-routing.h"
#include "ns3/mpi-interface.h"
#include "global-router-interface.h"
#include "global-route-manager-impl.h"
#include "candidate-queue.h"
@@ -697,6 +698,13 @@ GlobalRouteManagerImpl::InitializeRoutes ()
//
Ptr<GlobalRouter> rtr =
node->GetObject<GlobalRouter> ();
// Ignore nodes that are not assigned to our systemId (distributed sim)
if (node->GetSystemId () != MpiInterface::GetSystemId ())
{
continue;
}
//
// if the node has a global router interface, then run the global routing
// algorithms.

View File

@@ -106,6 +106,13 @@ DefaultSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
m_events = scheduler;
}
// System ID for non-distributed simulation is always zero
uint32_t
DefaultSimulatorImpl::GetSystemId (void) const
{
return 0;
}
void
DefaultSimulatorImpl::ProcessOneEvent (void)
{

View File

@@ -57,6 +57,7 @@ public:
virtual Time GetDelayLeft (const EventId &id) const;
virtual Time GetMaximumSimulationTime (void) const;
virtual void SetScheduler (ObjectFactory schedulerFactory);
virtual uint32_t GetSystemId (void) const;
virtual uint32_t GetContext (void) const;
private:

View File

@@ -827,6 +827,13 @@ RealtimeSimulatorImpl::GetMaximumSimulationTime (void) const
return TimeStep (0x7fffffffffffffffLL);
}
// System ID for non-distributed simulation is always zero
uint32_t
RealtimeSimulatorImpl::GetSystemId (void) const
{
return 0;
}
uint32_t
RealtimeSimulatorImpl::GetContext (void) const
{

View File

@@ -69,6 +69,7 @@ public:
virtual Time GetDelayLeft (const EventId &id) const;
virtual Time GetMaximumSimulationTime (void) const;
virtual void SetScheduler (ObjectFactory schedulerFactory);
virtual uint32_t GetSystemId (void) const;
virtual uint32_t GetContext (void) const;
void ScheduleRealtimeWithContext (uint32_t context, Time const &time, EventImpl *event);

View File

@@ -53,6 +53,7 @@ public:
virtual Time GetDelayLeft (const EventId &id) const = 0;
virtual Time GetMaximumSimulationTime (void) const = 0;
virtual void SetScheduler (ObjectFactory schedulerFactory) = 0;
virtual uint32_t GetSystemId () const = 0;
virtual uint32_t GetContext (void) const = 0;
};

View File

@@ -339,6 +339,21 @@ Simulator::GetContext (void)
return GetImpl ()->GetContext ();
}
uint32_t
Simulator::GetSystemId (void)
{
NS_LOG_FUNCTION_NOARGS ();
if (*PeekImpl () != 0)
{
return GetImpl ()->GetSystemId ();
}
else
{
return 0;
}
}
void
Simulator::SetImplementation (Ptr<SimulatorImpl> impl)
{

View File

@@ -770,6 +770,12 @@ public:
* to delegate events to their own subclass of the EventImpl base class.
*/
static EventId ScheduleNow (const Ptr<EventImpl> &event);
/**
* \returns the system id for this simulator; used for
* MPI or other distributed simulations
*/
static uint32_t GetSystemId (void);
private:
Simulator ();
~Simulator ();

View File

@@ -50,6 +50,7 @@ all_modules = (
'contrib/flow-monitor',
'applications/udp-client-server',
'devices/wimax',
'mpi',
)
def set_options(opt):

25
wscript
View File

@@ -195,6 +195,10 @@ def set_options(opt):
help=('Compile NS-3 statically: works only on linux, without python'),
dest='enable_static', action='store_true',
default=False)
opt.add_option('--enable-mpi',
help=('Compile NS-3 with MPI and distributed simulation support'),
dest='enable_mpi', action='store_true',
default=False)
opt.add_option('--doxygen-no-build',
help=('Run doxygen to generate html documentation from source comments, '
'but do not wait for ns-3 to finish the full build.'),
@@ -319,6 +323,27 @@ def configure(conf):
if Options.options.enable_modules:
conf.env['NS3_ENABLED_MODULES'] = ['ns3-'+mod for mod in
Options.options.enable_modules.split(',')]
# for MPI
conf.find_program('mpic++', var='MPI')
if Options.options.enable_mpi and conf.env['MPI']:
p = subprocess.Popen([conf.env['MPI'], '-showme:compile'], stdout=subprocess.PIPE)
flags = p.stdout.read().rstrip().split()
p.wait()
env.append_value("CXXFLAGS_MPI", flags)
p = subprocess.Popen([conf.env['MPI'], '-showme:link'], stdout=subprocess.PIPE)
flags = p.stdout.read().rstrip().split()
p.wait()
env.append_value("LINKFLAGS_MPI", flags)
env.append_value('CXXDEFINES', 'NS3_MPI')
conf.report_optional_feature("mpi", "MPI Support", True, '')
conf.env['ENABLE_MPI'] = True
else:
if Options.options.enable_mpi:
conf.report_optional_feature("mpi", "MPI Support", False, 'mpic++ not found')
else:
conf.report_optional_feature("mpi", "MPI Support", False, 'option --enable-mpi not selected')
# for suid bits
conf.find_program('sudo', var='SUDO')