--- a/CHANGES.html Mon Mar 08 15:24:22 2010 -0800
+++ b/CHANGES.html Mon Mar 08 21:07:31 2010 -0500
@@ -49,6 +49,7 @@
<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 @@
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 @@
</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>
--- a/RELEASE_NOTES Mon Mar 08 15:24:22 2010 -0800
+++ b/RELEASE_NOTES Mon Mar 08 21:07:31 2010 -0500
@@ -36,7 +36,8 @@
-------------------------
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)
--- a/bindings/python/apidefs/gcc-ILP32/ns3_module_common.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_common.py Mon Mar 08 21:07:31 2010 -0500
@@ -265,6 +265,10 @@
'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 @@
'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 @@
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 @@
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 @@
'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 @@
'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 @@
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 @@
'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 @@
'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 @@
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 @@
'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 @@
'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 @@
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',
--- a/bindings/python/apidefs/gcc-ILP32/ns3_module_core.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_core.py Mon Mar 08 21:07:31 2010 -0500
@@ -3075,7 +3075,7 @@
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',
--- a/bindings/python/apidefs/gcc-ILP32/ns3_module_helper.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_helper.py Mon Mar 08 21:07:31 2010 -0500
@@ -1202,6 +1202,10 @@
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 > > >',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_mpi.py Mon Mar 08 21:07:31 2010 -0500
@@ -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
+
--- a/bindings/python/apidefs/gcc-ILP32/ns3_module_point_to_point.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_point_to_point.py Mon Mar 08 21:07:31 2010 -0500
@@ -9,6 +9,8 @@
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 @@
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 @@
## 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 @@
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)
--- a/bindings/python/apidefs/gcc-ILP32/ns3_module_simulator.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3_module_simulator.py Mon Mar 08 21:07:31 2010 -0500
@@ -317,6 +317,11 @@
'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 @@
'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 @@
'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 @@
'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',
--- a/bindings/python/apidefs/gcc-ILP32/ns3modulegen_generated.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-ILP32/ns3modulegen_generated.py Mon Mar 08 21:07:31 2010 -0500
@@ -17,6 +17,7 @@
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 @@
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 @@
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 @@
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)
--- a/bindings/python/apidefs/gcc-LP64/ns3_module_common.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-LP64/ns3_module_common.py Mon Mar 08 21:07:31 2010 -0500
@@ -265,6 +265,10 @@
'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 @@
'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 @@
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 @@
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 @@
'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 @@
'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 @@
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 @@
'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 @@
'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 @@
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 @@
'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 @@
'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 @@
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',
--- a/bindings/python/apidefs/gcc-LP64/ns3_module_helper.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-LP64/ns3_module_helper.py Mon Mar 08 21:07:31 2010 -0500
@@ -1202,6 +1202,10 @@
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 > > >',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/python/apidefs/gcc-LP64/ns3_module_mpi.py Mon Mar 08 21:07:31 2010 -0500
@@ -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
+
--- a/bindings/python/apidefs/gcc-LP64/ns3_module_point_to_point.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-LP64/ns3_module_point_to_point.py Mon Mar 08 21:07:31 2010 -0500
@@ -9,6 +9,8 @@
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 @@
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 @@
## 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 @@
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)
--- a/bindings/python/apidefs/gcc-LP64/ns3_module_simulator.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-LP64/ns3_module_simulator.py Mon Mar 08 21:07:31 2010 -0500
@@ -317,6 +317,11 @@
'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 @@
'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 @@
'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 @@
'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',
--- a/bindings/python/apidefs/gcc-LP64/ns3modulegen_generated.py Mon Mar 08 15:24:22 2010 -0800
+++ b/bindings/python/apidefs/gcc-LP64/ns3modulegen_generated.py Mon Mar 08 21:07:31 2010 -0500
@@ -17,6 +17,7 @@
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 @@
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 @@
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 @@
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)
--- a/doc/manual/Makefile Mon Mar 08 15:24:22 2010 -0800
+++ b/doc/manual/Makefile Mon Mar 08 21:07:31 2010 -0500
@@ -58,6 +58,7 @@
python.texi \
random.texi \
realtime.texi \
+ distributed.texi \
routing.texi \
simple.texi \
sockets.texi \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/manual/distributed.texi Mon Mar 08 21:07:31 2010 -0500
@@ -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
--- a/doc/manual/manual.texi Mon Mar 08 15:24:22 2010 -0800
+++ b/doc/manual/manual.texi Mon Mar 08 21:07:31 2010 -0500
@@ -96,6 +96,7 @@
* Logging::
* Tracing::
* RealTime::
+* Distributed::
* Packets::
* Helpers::
* Python::
@@ -140,6 +141,7 @@
@include log.texi
@include tracing.texi
@include realtime.texi
+@include distributed.texi
@include packets.texi
@include helpers.texi
@include python.texi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mpi/nms-udp-nix.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mpi/simple-distributed.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mpi/third-distributed.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mpi/waf Mon Mar 08 21:07:31 2010 -0500
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mpi/wscript Mon Mar 08 21:07:31 2010 -0500
@@ -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'
--- a/src/common/buffer.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/buffer.cc Mon Mar 08 21:07:31 2010 -0500
@@ -268,6 +268,15 @@
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 @@
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
{
--- a/src/common/buffer.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/buffer.h Mon Mar 08 21:07:31 2010 -0500
@@ -476,6 +476,33 @@
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 @@
Buffer &operator = (Buffer const &o);
Buffer ();
Buffer (uint32_t dataSize);
+ Buffer (uint32_t dataSize, bool initialize);
~Buffer ();
private:
--- a/src/common/nix-vector.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/nix-vector.cc Mon Mar 08 21:07:31 2010 -0500
@@ -222,74 +222,105 @@
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;
+ }
+
+ 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_currentVectorBitSize = 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;
+ }
+ }
- NS_ASSERT (size >= 4);
- m_totalBitSize = i.ReadU32 ();
- size -=4;
+ // 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
--- a/src/common/nix-vector.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/nix-vector.h Mon Mar 08 21:07:31 2010 -0500
@@ -105,17 +105,27 @@
*/
uint32_t GetSerializedSize (void) const;
/**
- * \param i Buffer iterator for writing
+ * \return zero if buffer not large enough
+ *
+ * \param buffer points to serialization buffer
*
- * \param size number of bytes to write
+ * \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 buffer points to buffer for deserialization
*
- * \param i Buffer iterator for reading
+ * \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
*
--- a/src/common/packet-metadata-test.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/packet-metadata-test.cc Mon Mar 08 21:07:31 2010 -0500
@@ -353,42 +353,43 @@
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 @@
ADD_TRAILER (p, 100);
CHECK_HISTORY (p, 2, 10, 100);
+
p = Create<Packet> (10);
ADD_HEADER (p, 1);
ADD_HEADER (p, 2);
--- a/src/common/packet-metadata.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/packet-metadata.cc Mon Mar 08 21:07:31 2010 -0500
@@ -959,7 +959,7 @@
return totalSize;
}
-uint32_t
+uint64_t
PacketMetadata::GetUid (void) const
{
return m_packetUid;
@@ -1055,11 +1055,18 @@
{
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 @@
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 @@
}
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 @@
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 @@
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 @@
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);
}
--- a/src/common/packet-metadata.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/packet-metadata.h Mon Mar 08 21:07:31 2010 -0500
@@ -127,7 +127,7 @@
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 @@
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 @@
/* 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 @@
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),
--- a/src/common/packet.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/packet.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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 @@
: 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 @@
: 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 @@
return m_buffer.CopyData (os, size);
}
-uint32_t
+uint64_t
Packet::GetUid (void) const
{
return m_metadata.GetUid ();
@@ -532,48 +544,197 @@
PacketMetadata::EnableChecking ();
}
-Buffer
-Packet::Serialize (void) const
+uint32_t Packet::GetSerializedSize (void) const
+{
+ uint32_t size = 0;
+
+ if (m_nixVector)
+ {
+ // increment total size by the size of the nix-vector
+ // ensuring 4-byte boundary
+ size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
+
+ // 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
+ //size += m_tags.GetSerializedSize ();
+
+ // 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;
+}
+
+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 buffer;
- uint32_t reserve;
+
+ uint32_t* p = (uint32_t*)buffer;
- // write metadata
- reserve = m_metadata.GetSerializedSize ();
- buffer.AddAtStart (reserve);
- m_metadata.Serialize (buffer.Begin (), reserve);
+ // 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);
- // write tags
- //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 ());
-
- return tmp;
-}
-void
-Packet::Deserialize (Buffer buffer)
-{
- 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);
-
+ 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 @@
//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
--- a/src/common/packet.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/common/packet.h Mon Mar 08 21:07:31 2010 -0500
@@ -222,6 +222,17 @@
*/
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
* buffer is untouched.
@@ -379,7 +390,7 @@
* \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 @@
static void EnableChecking (void);
/**
- * \returns a byte buffer
- *
- * 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).
+ * For packet serializtion, the total size is checked
+ * in order to determine the size of the buffer
+ * required for serialization
*
- * 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
- *
- * 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.
+ 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 will trigger calls to the Deserialize method
- * of each tag stored in this packet.
+ * A packet is completely serialized and placed into the raw byte buffer
*
- * 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 @@
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;
--- a/src/devices/point-to-point/point-to-point-channel.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/devices/point-to-point/point-to-point-channel.cc Mon Mar 08 21:07:31 2010 -0500
@@ -124,4 +124,30 @@
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
--- a/src/devices/point-to-point/point-to-point-channel.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/devices/point-to-point/point-to-point-channel.h Mon Mar 08 21:07:31 2010 -0500
@@ -69,7 +69,7 @@
* \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 @@
*/
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-remote-channel.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-remote-channel.h Mon Mar 08 21:07:31 2010 -0500
@@ -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
+
+
--- a/src/devices/point-to-point/wscript Mon Mar 08 15:24:22 2010 -0800
+++ b/src/devices/point-to-point/wscript Mon Mar 08 21:07:31 2010 -0500
@@ -6,6 +6,7 @@
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 @@
headers.source = [
'point-to-point-net-device.h',
'point-to-point-channel.h',
+ 'point-to-point-remote-channel.h',
'ppp-header.h',
]
--- a/src/helper/node-container.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/helper/node-container.cc Mon Mar 08 21:07:31 2010 -0500
@@ -97,6 +97,14 @@
}
}
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++)
--- a/src/helper/node-container.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/helper/node-container.h Mon Mar 08 21:07:31 2010 -0500
@@ -237,6 +237,20 @@
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.
*
--- a/src/helper/point-to-point-helper.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/helper/point-to-point-helper.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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 @@
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 @@
PointToPointHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
{
m_channelFactory.Set (n1, v1);
+ m_remoteChannelFactory.Set (n1, v1);
}
void
@@ -223,7 +227,30 @@
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);
--- a/src/helper/point-to-point-helper.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/helper/point-to-point-helper.h Mon Mar 08 21:07:31 2010 -0500
@@ -116,7 +116,9 @@
* \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 @@
ObjectFactory m_queueFactory;
ObjectFactory m_channelFactory;
+ ObjectFactory m_remoteChannelFactory;
ObjectFactory m_deviceFactory;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/distributed-simulator-impl.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/distributed-simulator-impl.h Mon Mar 08 21:07:31 2010 -0500
@@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/mpi-interface.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/mpi-interface.h Mon Mar 08 21:07:31 2010 -0500
@@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/waf Mon Mar 08 21:07:31 2010 -0500
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../waf "$@"
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mpi/wscript Mon Mar 08 21:07:31 2010 -0500
@@ -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'
--- a/src/routing/global-routing/global-route-manager-impl.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/routing/global-routing/global-route-manager-impl.cc Mon Mar 08 21:07:31 2010 -0500
@@ -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 @@
//
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.
--- a/src/simulator/default-simulator-impl.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/default-simulator-impl.cc Mon Mar 08 21:07:31 2010 -0500
@@ -106,6 +106,13 @@
m_events = scheduler;
}
+// System ID for non-distributed simulation is always zero
+uint32_t
+DefaultSimulatorImpl::GetSystemId (void) const
+{
+ return 0;
+}
+
void
DefaultSimulatorImpl::ProcessOneEvent (void)
{
--- a/src/simulator/default-simulator-impl.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/default-simulator-impl.h Mon Mar 08 21:07:31 2010 -0500
@@ -57,6 +57,7 @@
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:
--- a/src/simulator/realtime-simulator-impl.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/realtime-simulator-impl.cc Mon Mar 08 21:07:31 2010 -0500
@@ -827,6 +827,13 @@
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
{
--- a/src/simulator/realtime-simulator-impl.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/realtime-simulator-impl.h Mon Mar 08 21:07:31 2010 -0500
@@ -69,6 +69,7 @@
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);
--- a/src/simulator/simulator-impl.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/simulator-impl.h Mon Mar 08 21:07:31 2010 -0500
@@ -53,6 +53,7 @@
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;
};
--- a/src/simulator/simulator.cc Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/simulator.cc Mon Mar 08 21:07:31 2010 -0500
@@ -339,6 +339,21 @@
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)
{
--- a/src/simulator/simulator.h Mon Mar 08 15:24:22 2010 -0800
+++ b/src/simulator/simulator.h Mon Mar 08 21:07:31 2010 -0500
@@ -770,6 +770,12 @@
* 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 ();
--- a/src/wscript Mon Mar 08 15:24:22 2010 -0800
+++ b/src/wscript Mon Mar 08 21:07:31 2010 -0500
@@ -50,6 +50,7 @@
'contrib/flow-monitor',
'applications/udp-client-server',
'devices/wimax',
+ 'mpi',
)
def set_options(opt):
--- a/wscript Mon Mar 08 15:24:22 2010 -0800
+++ b/wscript Mon Mar 08 21:07:31 2010 -0500
@@ -195,6 +195,10 @@
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 @@
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')