Merge distributed simulation code
This commit is contained in:
61
CHANGES.html
61
CHANGES.html
@@ -49,6 +49,7 @@ us a note on ns-developers mailing list. </p>
|
||||
<h2>Changes to build system:</h2>
|
||||
|
||||
<h2>New API:</h2>
|
||||
|
||||
<ul>
|
||||
<li><b>WiMAX net device</b>: The developed WiMAX model attempts to provide an accurate MAC and
|
||||
PHY level implementation of the 802.16 specification with the Point-to-Multipoint (PMP) mode and the WirelessMAN-OFDM
|
||||
@@ -65,10 +66,22 @@ interact with the Wimax models is through the helper API and through
|
||||
the publicly visible attributes of the model.
|
||||
The helper API is defined in src/helper/wimax-helper.{cc,h}.
|
||||
Three examples containing some code that shows how to setup a 802.16 network are located under examples/wimax/
|
||||
|
||||
<li><b>MPI Interface for distributed simulation:</b> Enables access
|
||||
to necessary MPI information such as MPI rank and size.
|
||||
|
||||
<li><b>Point-to-point remote channel:</b> Enables point-to-point
|
||||
connection between net-devices on different simulators, for use
|
||||
with distributed simulation.
|
||||
|
||||
<li><b>GetSystemId in simulator:</b> For use with distributed
|
||||
simulation, GetSystemId returns zero by non-distributed
|
||||
simulators. For the distributed simulator, it returns the
|
||||
MPI rank.
|
||||
</ul>
|
||||
|
||||
<h2>Changes to existing API:</h2>
|
||||
<ul>
|
||||
</pre>
|
||||
<li><b>Tracing Helpers</b>: The organization of helpers for both pcap and ascii
|
||||
tracing, in devices and protocols, has been reworked. Instead of each device
|
||||
and protocol helper re-implementing trace enable methods, classes have been
|
||||
@@ -114,6 +127,52 @@ After:
|
||||
</pre>
|
||||
|
||||
|
||||
<li><b>Serialization and Deserialization</b> in buffer, nix-vector,
|
||||
packet-metadata, and packet has been modified to use raw character
|
||||
buffers, rather than the Buffer class
|
||||
<pre>
|
||||
+ uint32_t Buffer::GetSerializedSize (void) const;
|
||||
+ uint32_t Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
+ uint32_t Buffer::Deserialize (uint8_t* buffer, uint32_t size);
|
||||
|
||||
- void NixVector::Serialize (Buffer::Iterator i, uint32_t size) const;
|
||||
+ uint32_t NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const;
|
||||
- uint32_t NixVector::Deserialize (Buffer::Iterator i);
|
||||
+ uint32_t NixVector::Deserialize (uint32_t* buffer, uint32_t size);
|
||||
|
||||
- void PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const;
|
||||
+ uint32_t PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
- uint32_t PacketMetadata::Deserialize (Buffer::Iterator i);
|
||||
+ uint32_t PacketMetadata::Deserialize (uint8_t* buffer, uint32_t size);
|
||||
|
||||
+ uint32_t Packet::GetSerializedSize (void) const;
|
||||
- Buffer Packet::Serialize (void) const;
|
||||
+ uint32_t Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
- void Packet::Deserialize (Buffer buffer);
|
||||
+ Packet::Packet (uint8_t const*buffer, uint32_t size, bool magic);
|
||||
</pre>
|
||||
<li><b>PacketMetadata uid</b> has been changed to a 64-bit value. The
|
||||
lower 32 bits give the uid, while the upper 32-bits give the MPI rank
|
||||
for distributed simulations. For non-distributed simulations, the
|
||||
upper 32 bits are simply zero.
|
||||
<pre>
|
||||
- inline PacketMetadata (uint32_t uid, uint32_t size);
|
||||
+ inline PacketMetadata (uint64_t uid, uint32_t size);
|
||||
- uint32_t GetUid (void) const;
|
||||
+ uint64_t GetUid (void) const;
|
||||
- PacketMetadata::PacketMetadata (uint32_t uid, uint32_t size);
|
||||
+ PacketMetadata::PacketMetadata (uint64_t uid, uint32_t size);
|
||||
|
||||
- uint32_t Packet::GetUid (void) const;
|
||||
+ uint64_t Packet::GetUid (void) const;
|
||||
</pre>
|
||||
</ul>
|
||||
|
||||
<h2>Changed behavior:</h2>
|
||||
<ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<h1>Changes from ns-3.6 to ns-3.7</h1>
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ New user-visible features
|
||||
-------------------------
|
||||
a) WiMAX net device: Allow to simulated IEEE 802.16 point to multi-point based networks
|
||||
|
||||
b)
|
||||
b) Distributed simulation for point-to-point networks using the Message
|
||||
Passing Interface (MPI) standard.
|
||||
|
||||
c)
|
||||
|
||||
|
||||
@@ -265,6 +265,10 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
'ns3::Buffer',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::Deserialize(uint8_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## buffer.h: ns3::Buffer::Iterator ns3::Buffer::End() const [member function]
|
||||
cls.add_method('End',
|
||||
'ns3::Buffer::Iterator',
|
||||
@@ -280,6 +284,11 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
'int32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::GetSerializedSize() const [member function]
|
||||
cls.add_method('GetSerializedSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::GetSize() const [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
@@ -298,6 +307,11 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
cls.add_method('RemoveAtStart',
|
||||
'void',
|
||||
[param('uint32_t', 'start')])
|
||||
## buffer.h: uint32_t ns3::Buffer::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
def register_Ns3BufferIterator_methods(root_module, cls):
|
||||
@@ -583,8 +597,8 @@ def register_Ns3DataRate_methods(root_module, cls):
|
||||
return
|
||||
|
||||
def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint32_t uid, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'uid'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint64_t uid, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint64_t', 'uid'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(ns3::PacketMetadata const & o) [copy constructor]
|
||||
cls.add_constructor([param('ns3::PacketMetadata const &', 'o')])
|
||||
## packet-metadata.h: void ns3::PacketMetadata::AddAtEnd(ns3::PacketMetadata const & o) [member function]
|
||||
@@ -613,10 +627,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
'ns3::PacketMetadata',
|
||||
[param('uint32_t', 'start'), param('uint32_t', 'end')],
|
||||
is_const=True)
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(ns3::Buffer::Iterator i) [member function]
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(uint8_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('ns3::Buffer::Iterator', 'i')])
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: static void ns3::PacketMetadata::Enable() [member function]
|
||||
cls.add_method('Enable',
|
||||
'void',
|
||||
@@ -632,9 +646,9 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::GetUid() const [member function]
|
||||
## packet-metadata.h: uint64_t ns3::PacketMetadata::GetUid() const [member function]
|
||||
cls.add_method('GetUid',
|
||||
'uint32_t',
|
||||
'uint64_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet-metadata.h: void ns3::PacketMetadata::RemoveAtEnd(uint32_t end) [member function]
|
||||
@@ -653,10 +667,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
cls.add_method('RemoveTrailer',
|
||||
'void',
|
||||
[param('ns3::Trailer const &', 'trailer'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: void ns3::PacketMetadata::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'void',
|
||||
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
@@ -1523,10 +1537,10 @@ def register_Ns3NixVector_methods(root_module, cls):
|
||||
'ns3::Ptr< ns3::NixVector >',
|
||||
[],
|
||||
is_const=True)
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(ns3::Buffer::Iterator i) [member function]
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(uint32_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('ns3::Buffer::Iterator', 'i')])
|
||||
[param('uint32_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## nix-vector.h: void ns3::NixVector::DumpNixVector(std::ostream & os) const [member function]
|
||||
cls.add_method('DumpNixVector',
|
||||
'void',
|
||||
@@ -1550,10 +1564,10 @@ def register_Ns3NixVector_methods(root_module, cls):
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## nix-vector.h: void ns3::NixVector::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Serialize(uint32_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'void',
|
||||
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
|
||||
'uint32_t',
|
||||
[param('uint32_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
@@ -1580,6 +1594,8 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
cls.add_constructor([param('ns3::Packet const &', 'o')])
|
||||
## packet.h: ns3::Packet::Packet(uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'size')])
|
||||
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size, bool magic) [constructor]
|
||||
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size'), param('bool', 'magic')])
|
||||
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size')])
|
||||
## packet.h: void ns3::Packet::AddAtEnd(ns3::Ptr<ns3::Packet const> packet) [member function]
|
||||
@@ -1633,10 +1649,6 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
'ns3::Ptr< ns3::Packet >',
|
||||
[param('uint32_t', 'start'), param('uint32_t', 'length')],
|
||||
is_const=True)
|
||||
## packet.h: void ns3::Packet::Deserialize(ns3::Buffer buffer) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'void',
|
||||
[param('ns3::Buffer', 'buffer')])
|
||||
## packet.h: static void ns3::Packet::EnableChecking() [member function]
|
||||
cls.add_method('EnableChecking',
|
||||
'void',
|
||||
@@ -1667,14 +1679,19 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
'ns3::PacketTagIterator',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetSerializedSize() const [member function]
|
||||
cls.add_method('GetSerializedSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
|
||||
## packet.h: uint64_t ns3::Packet::GetUid() const [member function]
|
||||
cls.add_method('GetUid',
|
||||
'uint32_t',
|
||||
'uint64_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint8_t const * ns3::Packet::PeekData() const [member function]
|
||||
@@ -1739,10 +1756,10 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
cls.add_method('RemoveTrailer',
|
||||
'uint32_t',
|
||||
[param('ns3::Trailer &', 'trailer')])
|
||||
## packet.h: ns3::Buffer ns3::Packet::Serialize() const [member function]
|
||||
## packet.h: uint32_t ns3::Packet::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'ns3::Buffer',
|
||||
[],
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
## packet.h: void ns3::Packet::SetNixVector(ns3::Ptr<ns3::NixVector> arg0) [member function]
|
||||
cls.add_method('SetNixVector',
|
||||
|
||||
@@ -3075,7 +3075,7 @@ def register_functions(root_module):
|
||||
module.add_function('TypeNameGet',
|
||||
'std::string',
|
||||
[],
|
||||
template_parameters=['long'])
|
||||
template_parameters=['long long'])
|
||||
## type-name.h: extern std::string ns3::TypeNameGet() [free function]
|
||||
module.add_function('TypeNameGet',
|
||||
'std::string',
|
||||
|
||||
@@ -1202,6 +1202,10 @@ def register_Ns3NodeContainer_methods(root_module, cls):
|
||||
cls.add_method('Create',
|
||||
'void',
|
||||
[param('uint32_t', 'n')])
|
||||
## node-container.h: void ns3::NodeContainer::Create(uint32_t n, uint32_t systemId) [member function]
|
||||
cls.add_method('Create',
|
||||
'void',
|
||||
[param('uint32_t', 'n'), param('uint32_t', 'systemId')])
|
||||
## node-container.h: __gnu_cxx::__normal_iterator<const ns3::Ptr<ns3::Node>*,std::vector<ns3::Ptr<ns3::Node>, std::allocator<ns3::Ptr<ns3::Node> > > > ns3::NodeContainer::End() const [member function]
|
||||
cls.add_method('End',
|
||||
'__gnu_cxx::__normal_iterator< ns3::Ptr< ns3::Node > const, std::vector< ns3::Ptr< ns3::Node > > >',
|
||||
|
||||
355
bindings/python/apidefs/gcc-ILP32/ns3_module_mpi.py
Normal file
355
bindings/python/apidefs/gcc-ILP32/ns3_module_mpi.py
Normal file
@@ -0,0 +1,355 @@
|
||||
from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
|
||||
|
||||
def register_types(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage [class]
|
||||
module.add_class('LbtsMessage')
|
||||
## mpi-interface.h: ns3::MpiInterface [class]
|
||||
module.add_class('MpiInterface')
|
||||
## mpi-interface.h: ns3::SentBuffer [class]
|
||||
module.add_class('SentBuffer')
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl [class]
|
||||
module.add_class('DistributedSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
|
||||
|
||||
## Register a nested module for the namespace Config
|
||||
|
||||
nested_module = module.add_cpp_namespace('Config')
|
||||
register_types_ns3_Config(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace TimeStepPrecision
|
||||
|
||||
nested_module = module.add_cpp_namespace('TimeStepPrecision')
|
||||
register_types_ns3_TimeStepPrecision(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace addressUtils
|
||||
|
||||
nested_module = module.add_cpp_namespace('addressUtils')
|
||||
register_types_ns3_addressUtils(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace aodv
|
||||
|
||||
nested_module = module.add_cpp_namespace('aodv')
|
||||
register_types_ns3_aodv(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace dot11s
|
||||
|
||||
nested_module = module.add_cpp_namespace('dot11s')
|
||||
register_types_ns3_dot11s(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace flame
|
||||
|
||||
nested_module = module.add_cpp_namespace('flame')
|
||||
register_types_ns3_flame(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace internal
|
||||
|
||||
nested_module = module.add_cpp_namespace('internal')
|
||||
register_types_ns3_internal(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace olsr
|
||||
|
||||
nested_module = module.add_cpp_namespace('olsr')
|
||||
register_types_ns3_olsr(nested_module)
|
||||
|
||||
|
||||
def register_types_ns3_Config(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_TimeStepPrecision(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_addressUtils(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_aodv(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_dot11s(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_flame(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_internal(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_olsr(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_methods(root_module):
|
||||
register_Ns3LbtsMessage_methods(root_module, root_module['ns3::LbtsMessage'])
|
||||
register_Ns3MpiInterface_methods(root_module, root_module['ns3::MpiInterface'])
|
||||
register_Ns3SentBuffer_methods(root_module, root_module['ns3::SentBuffer'])
|
||||
register_Ns3DistributedSimulatorImpl_methods(root_module, root_module['ns3::DistributedSimulatorImpl'])
|
||||
return
|
||||
|
||||
def register_Ns3LbtsMessage_methods(root_module, cls):
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(ns3::LbtsMessage const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::LbtsMessage const &', 'arg0')])
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage() [constructor]
|
||||
cls.add_constructor([])
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, ns3::Time const & t) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('ns3::Time const &', 't')])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetMyId() [member function]
|
||||
cls.add_method('GetMyId',
|
||||
'uint32_t',
|
||||
[])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetRxCount() [member function]
|
||||
cls.add_method('GetRxCount',
|
||||
'uint32_t',
|
||||
[])
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::LbtsMessage::GetSmallestTime() [member function]
|
||||
cls.add_method('GetSmallestTime',
|
||||
'ns3::Time',
|
||||
[])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetTxCount() [member function]
|
||||
cls.add_method('GetTxCount',
|
||||
'uint32_t',
|
||||
[])
|
||||
return
|
||||
|
||||
def register_Ns3MpiInterface_methods(root_module, cls):
|
||||
## mpi-interface.h: ns3::MpiInterface::MpiInterface() [constructor]
|
||||
cls.add_constructor([])
|
||||
## mpi-interface.h: ns3::MpiInterface::MpiInterface(ns3::MpiInterface const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::MpiInterface const &', 'arg0')])
|
||||
## mpi-interface.h: static void ns3::MpiInterface::Destroy() [member function]
|
||||
cls.add_method('Destroy',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::Enable(int * arg0, char * * * arg1) [member function]
|
||||
cls.add_method('Enable',
|
||||
'void',
|
||||
[param('int *', 'arg0'), param('char * * *', 'arg1')],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetRxCount() [member function]
|
||||
cls.add_method('GetRxCount',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSize() [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSystemId() [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetTxCount() [member function]
|
||||
cls.add_method('GetTxCount',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static bool ns3::MpiInterface::IsEnabled() [member function]
|
||||
cls.add_method('IsEnabled',
|
||||
'bool',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::ReceiveMessages() [member function]
|
||||
cls.add_method('ReceiveMessages',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::SendPacket(ns3::Ptr<ns3::Packet> arg0, ns3::Time const & arg1, uint32_t arg2, uint32_t arg3) [member function]
|
||||
cls.add_method('SendPacket',
|
||||
'void',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'arg0'), param('ns3::Time const &', 'arg1'), param('uint32_t', 'arg2'), param('uint32_t', 'arg3')],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::TestSendComplete() [member function]
|
||||
cls.add_method('TestSendComplete',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
return
|
||||
|
||||
def register_Ns3SentBuffer_methods(root_module, cls):
|
||||
## mpi-interface.h: ns3::SentBuffer::SentBuffer(ns3::SentBuffer const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::SentBuffer const &', 'arg0')])
|
||||
## mpi-interface.h: ns3::SentBuffer::SentBuffer() [constructor]
|
||||
cls.add_constructor([])
|
||||
## mpi-interface.h: uint8_t * ns3::SentBuffer::GetBuffer() [member function]
|
||||
cls.add_method('GetBuffer',
|
||||
'uint8_t *',
|
||||
[])
|
||||
## mpi-interface.h: MPI_Request * ns3::SentBuffer::GetRequest() [member function]
|
||||
cls.add_method('GetRequest',
|
||||
'MPI_Request *',
|
||||
[])
|
||||
## mpi-interface.h: void ns3::SentBuffer::SetBuffer(uint8_t * arg0) [member function]
|
||||
cls.add_method('SetBuffer',
|
||||
'void',
|
||||
[param('uint8_t *', 'arg0')])
|
||||
return
|
||||
|
||||
def register_Ns3DistributedSimulatorImpl_methods(root_module, cls):
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl(ns3::DistributedSimulatorImpl const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::DistributedSimulatorImpl const &', 'arg0')])
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl() [constructor]
|
||||
cls.add_constructor([])
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Cancel(ns3::EventId const & ev) [member function]
|
||||
cls.add_method('Cancel',
|
||||
'void',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Destroy() [member function]
|
||||
cls.add_method('Destroy',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetContext() const [member function]
|
||||
cls.add_method('GetContext',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetDelayLeft(ns3::EventId const & id) const [member function]
|
||||
cls.add_method('GetDelayLeft',
|
||||
'ns3::Time',
|
||||
[param('ns3::EventId const &', 'id')],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetMaximumSimulationTime() const [member function]
|
||||
cls.add_method('GetMaximumSimulationTime',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: static ns3::TypeId ns3::DistributedSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsFinished() const [member function]
|
||||
cls.add_method('IsFinished',
|
||||
'bool',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Next() const [member function]
|
||||
cls.add_method('Next',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Now() const [member function]
|
||||
cls.add_method('Now',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Remove(ns3::EventId const & ev) [member function]
|
||||
cls.add_method('Remove',
|
||||
'void',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Run() [member function]
|
||||
cls.add_method('Run',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::RunOneEvent() [member function]
|
||||
cls.add_method('RunOneEvent',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::Schedule(ns3::Time const & time, ns3::EventImpl * event) [member function]
|
||||
cls.add_method('Schedule',
|
||||
'ns3::EventId',
|
||||
[param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleDestroy(ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleDestroy',
|
||||
'ns3::EventId',
|
||||
[param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleNow(ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleNow',
|
||||
'ns3::EventId',
|
||||
[param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::ScheduleWithContext(uint32_t context, ns3::Time const & time, ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleWithContext',
|
||||
'void',
|
||||
[param('uint32_t', 'context'), param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::SetScheduler(ns3::ObjectFactory schedulerFactory) [member function]
|
||||
cls.add_method('SetScheduler',
|
||||
'void',
|
||||
[param('ns3::ObjectFactory', 'schedulerFactory')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop() [member function]
|
||||
cls.add_method('Stop',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop(ns3::Time const & time) [member function]
|
||||
cls.add_method('Stop',
|
||||
'void',
|
||||
[param('ns3::Time const &', 'time')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::DoDispose() [member function]
|
||||
cls.add_method('DoDispose',
|
||||
'void',
|
||||
[],
|
||||
visibility='private', is_virtual=True)
|
||||
return
|
||||
|
||||
def register_functions(root_module):
|
||||
module = root_module
|
||||
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
|
||||
register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
|
||||
register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
|
||||
register_functions_ns3_aodv(module.get_submodule('aodv'), root_module)
|
||||
register_functions_ns3_dot11s(module.get_submodule('dot11s'), root_module)
|
||||
register_functions_ns3_flame(module.get_submodule('flame'), root_module)
|
||||
register_functions_ns3_internal(module.get_submodule('internal'), root_module)
|
||||
register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
|
||||
return
|
||||
|
||||
def register_functions_ns3_Config(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_TimeStepPrecision(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_addressUtils(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_aodv(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_dot11s(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_flame(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_internal(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_olsr(module, root_module):
|
||||
return
|
||||
|
||||
@@ -9,6 +9,8 @@ def register_types(module):
|
||||
module.add_class('PointToPointChannel', parent=root_module['ns3::Channel'])
|
||||
## point-to-point-net-device.h: ns3::PointToPointNetDevice [class]
|
||||
module.add_class('PointToPointNetDevice', parent=root_module['ns3::NetDevice'])
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel [class]
|
||||
module.add_class('PointToPointRemoteChannel', parent=root_module['ns3::PointToPointChannel'])
|
||||
|
||||
## Register a nested module for the namespace Config
|
||||
|
||||
@@ -94,6 +96,7 @@ def register_methods(root_module):
|
||||
register_Ns3PppHeader_methods(root_module, root_module['ns3::PppHeader'])
|
||||
register_Ns3PointToPointChannel_methods(root_module, root_module['ns3::PointToPointChannel'])
|
||||
register_Ns3PointToPointNetDevice_methods(root_module, root_module['ns3::PointToPointNetDevice'])
|
||||
register_Ns3PointToPointRemoteChannel_methods(root_module, root_module['ns3::PointToPointRemoteChannel'])
|
||||
return
|
||||
|
||||
def register_Ns3PppHeader_methods(root_module, cls):
|
||||
@@ -173,7 +176,28 @@ def register_Ns3PointToPointChannel_methods(root_module, cls):
|
||||
## point-to-point-channel.h: bool ns3::PointToPointChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
|
||||
cls.add_method('TransmitStart',
|
||||
'bool',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')])
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
|
||||
is_virtual=True)
|
||||
## point-to-point-channel.h: ns3::Time ns3::PointToPointChannel::GetDelay() const [member function]
|
||||
cls.add_method('GetDelay',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetDestination(uint32_t i) const [member function]
|
||||
cls.add_method('GetDestination',
|
||||
'ns3::Ptr< ns3::PointToPointNetDevice >',
|
||||
[param('uint32_t', 'i')],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetSource(uint32_t i) const [member function]
|
||||
cls.add_method('GetSource',
|
||||
'ns3::Ptr< ns3::PointToPointNetDevice >',
|
||||
[param('uint32_t', 'i')],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: bool ns3::PointToPointChannel::IsInitialized() const [member function]
|
||||
cls.add_method('IsInitialized',
|
||||
'bool',
|
||||
[],
|
||||
is_const=True, visibility='protected')
|
||||
return
|
||||
|
||||
def register_Ns3PointToPointNetDevice_methods(root_module, cls):
|
||||
@@ -351,6 +375,23 @@ def register_Ns3PointToPointNetDevice_methods(root_module, cls):
|
||||
visibility='private', is_virtual=True)
|
||||
return
|
||||
|
||||
def register_Ns3PointToPointRemoteChannel_methods(root_module, cls):
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel(ns3::PointToPointRemoteChannel const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::PointToPointRemoteChannel const &', 'arg0')])
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel() [constructor]
|
||||
cls.add_constructor([])
|
||||
## point-to-point-remote-channel.h: static ns3::TypeId ns3::PointToPointRemoteChannel::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## point-to-point-remote-channel.h: bool ns3::PointToPointRemoteChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
|
||||
cls.add_method('TransmitStart',
|
||||
'bool',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
|
||||
is_virtual=True)
|
||||
return
|
||||
|
||||
def register_functions(root_module):
|
||||
module = root_module
|
||||
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
|
||||
|
||||
@@ -317,6 +317,11 @@ def register_Ns3Simulator_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_static=True)
|
||||
## simulator.h: static uint32_t ns3::Simulator::GetSystemId() [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## simulator.h: static bool ns3::Simulator::IsExpired(ns3::EventId const & id) [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
@@ -795,6 +800,11 @@ def register_Ns3SimulatorImpl_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_pure_virtual=True, is_const=True, is_virtual=True)
|
||||
## simulator-impl.h: uint32_t ns3::SimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_pure_virtual=True, is_const=True, is_virtual=True)
|
||||
## simulator-impl.h: bool ns3::SimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
@@ -1129,6 +1139,11 @@ def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## default-simulator-impl.h: uint32_t ns3::DefaultSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## default-simulator-impl.h: static ns3::TypeId ns3::DefaultSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
@@ -1423,6 +1438,11 @@ def register_Ns3RealtimeSimulatorImpl_methods(root_module, cls):
|
||||
'ns3::RealtimeSimulatorImpl::SynchronizationMode',
|
||||
[],
|
||||
is_const=True)
|
||||
## realtime-simulator-impl.h: uint32_t ns3::RealtimeSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## realtime-simulator-impl.h: static ns3::TypeId ns3::RealtimeSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
|
||||
@@ -17,6 +17,7 @@ import ns3_module_simulator
|
||||
import ns3_module_test
|
||||
import ns3_module_common
|
||||
import ns3_module_mobility
|
||||
import ns3_module_mpi
|
||||
import ns3_module_contrib
|
||||
import ns3_module_node
|
||||
import ns3_module_bridge
|
||||
@@ -109,6 +110,17 @@ def register_types(module):
|
||||
ns3_module_mobility__local.register_types(module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_types(module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_types(module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_types(module)
|
||||
|
||||
@@ -572,6 +584,17 @@ def register_methods(root_module):
|
||||
ns3_module_mobility__local.register_methods(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_methods(root_module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_methods(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_methods(root_module)
|
||||
|
||||
@@ -950,6 +973,17 @@ def register_functions(root_module):
|
||||
ns3_module_mobility__local.register_functions(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_functions(root_module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_functions(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_functions(root_module)
|
||||
|
||||
|
||||
@@ -265,6 +265,10 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
'ns3::Buffer',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::Deserialize(uint8_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## buffer.h: ns3::Buffer::Iterator ns3::Buffer::End() const [member function]
|
||||
cls.add_method('End',
|
||||
'ns3::Buffer::Iterator',
|
||||
@@ -280,6 +284,11 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
'int32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::GetSerializedSize() const [member function]
|
||||
cls.add_method('GetSerializedSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## buffer.h: uint32_t ns3::Buffer::GetSize() const [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
@@ -298,6 +307,11 @@ def register_Ns3Buffer_methods(root_module, cls):
|
||||
cls.add_method('RemoveAtStart',
|
||||
'void',
|
||||
[param('uint32_t', 'start')])
|
||||
## buffer.h: uint32_t ns3::Buffer::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
def register_Ns3BufferIterator_methods(root_module, cls):
|
||||
@@ -583,8 +597,8 @@ def register_Ns3DataRate_methods(root_module, cls):
|
||||
return
|
||||
|
||||
def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint32_t uid, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'uid'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(uint64_t uid, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint64_t', 'uid'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: ns3::PacketMetadata::PacketMetadata(ns3::PacketMetadata const & o) [copy constructor]
|
||||
cls.add_constructor([param('ns3::PacketMetadata const &', 'o')])
|
||||
## packet-metadata.h: void ns3::PacketMetadata::AddAtEnd(ns3::PacketMetadata const & o) [member function]
|
||||
@@ -613,10 +627,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
'ns3::PacketMetadata',
|
||||
[param('uint32_t', 'start'), param('uint32_t', 'end')],
|
||||
is_const=True)
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(ns3::Buffer::Iterator i) [member function]
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Deserialize(uint8_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('ns3::Buffer::Iterator', 'i')])
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: static void ns3::PacketMetadata::Enable() [member function]
|
||||
cls.add_method('Enable',
|
||||
'void',
|
||||
@@ -632,9 +646,9 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::GetUid() const [member function]
|
||||
## packet-metadata.h: uint64_t ns3::PacketMetadata::GetUid() const [member function]
|
||||
cls.add_method('GetUid',
|
||||
'uint32_t',
|
||||
'uint64_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet-metadata.h: void ns3::PacketMetadata::RemoveAtEnd(uint32_t end) [member function]
|
||||
@@ -653,10 +667,10 @@ def register_Ns3PacketMetadata_methods(root_module, cls):
|
||||
cls.add_method('RemoveTrailer',
|
||||
'void',
|
||||
[param('ns3::Trailer const &', 'trailer'), param('uint32_t', 'size')])
|
||||
## packet-metadata.h: void ns3::PacketMetadata::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
|
||||
## packet-metadata.h: uint32_t ns3::PacketMetadata::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'void',
|
||||
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
@@ -1523,10 +1537,10 @@ def register_Ns3NixVector_methods(root_module, cls):
|
||||
'ns3::Ptr< ns3::NixVector >',
|
||||
[],
|
||||
is_const=True)
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(ns3::Buffer::Iterator i) [member function]
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Deserialize(uint32_t * buffer, uint32_t size) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'uint32_t',
|
||||
[param('ns3::Buffer::Iterator', 'i')])
|
||||
[param('uint32_t *', 'buffer'), param('uint32_t', 'size')])
|
||||
## nix-vector.h: void ns3::NixVector::DumpNixVector(std::ostream & os) const [member function]
|
||||
cls.add_method('DumpNixVector',
|
||||
'void',
|
||||
@@ -1550,10 +1564,10 @@ def register_Ns3NixVector_methods(root_module, cls):
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## nix-vector.h: void ns3::NixVector::Serialize(ns3::Buffer::Iterator i, uint32_t size) const [member function]
|
||||
## nix-vector.h: uint32_t ns3::NixVector::Serialize(uint32_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'void',
|
||||
[param('ns3::Buffer::Iterator', 'i'), param('uint32_t', 'size')],
|
||||
'uint32_t',
|
||||
[param('uint32_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
return
|
||||
|
||||
@@ -1580,6 +1594,8 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
cls.add_constructor([param('ns3::Packet const &', 'o')])
|
||||
## packet.h: ns3::Packet::Packet(uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'size')])
|
||||
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size, bool magic) [constructor]
|
||||
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size'), param('bool', 'magic')])
|
||||
## packet.h: ns3::Packet::Packet(uint8_t const * buffer, uint32_t size) [constructor]
|
||||
cls.add_constructor([param('uint8_t const *', 'buffer'), param('uint32_t', 'size')])
|
||||
## packet.h: void ns3::Packet::AddAtEnd(ns3::Ptr<ns3::Packet const> packet) [member function]
|
||||
@@ -1633,10 +1649,6 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
'ns3::Ptr< ns3::Packet >',
|
||||
[param('uint32_t', 'start'), param('uint32_t', 'length')],
|
||||
is_const=True)
|
||||
## packet.h: void ns3::Packet::Deserialize(ns3::Buffer buffer) [member function]
|
||||
cls.add_method('Deserialize',
|
||||
'void',
|
||||
[param('ns3::Buffer', 'buffer')])
|
||||
## packet.h: static void ns3::Packet::EnableChecking() [member function]
|
||||
cls.add_method('EnableChecking',
|
||||
'void',
|
||||
@@ -1667,14 +1679,19 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
'ns3::PacketTagIterator',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetSerializedSize() const [member function]
|
||||
cls.add_method('GetSerializedSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
|
||||
## packet.h: uint64_t ns3::Packet::GetUid() const [member function]
|
||||
cls.add_method('GetUid',
|
||||
'uint32_t',
|
||||
'uint64_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## packet.h: uint8_t const * ns3::Packet::PeekData() const [member function]
|
||||
@@ -1739,10 +1756,10 @@ def register_Ns3Packet_methods(root_module, cls):
|
||||
cls.add_method('RemoveTrailer',
|
||||
'uint32_t',
|
||||
[param('ns3::Trailer &', 'trailer')])
|
||||
## packet.h: ns3::Buffer ns3::Packet::Serialize() const [member function]
|
||||
## packet.h: uint32_t ns3::Packet::Serialize(uint8_t * buffer, uint32_t maxSize) const [member function]
|
||||
cls.add_method('Serialize',
|
||||
'ns3::Buffer',
|
||||
[],
|
||||
'uint32_t',
|
||||
[param('uint8_t *', 'buffer'), param('uint32_t', 'maxSize')],
|
||||
is_const=True)
|
||||
## packet.h: void ns3::Packet::SetNixVector(ns3::Ptr<ns3::NixVector> arg0) [member function]
|
||||
cls.add_method('SetNixVector',
|
||||
|
||||
@@ -1202,6 +1202,10 @@ def register_Ns3NodeContainer_methods(root_module, cls):
|
||||
cls.add_method('Create',
|
||||
'void',
|
||||
[param('uint32_t', 'n')])
|
||||
## node-container.h: void ns3::NodeContainer::Create(uint32_t n, uint32_t systemId) [member function]
|
||||
cls.add_method('Create',
|
||||
'void',
|
||||
[param('uint32_t', 'n'), param('uint32_t', 'systemId')])
|
||||
## node-container.h: __gnu_cxx::__normal_iterator<const ns3::Ptr<ns3::Node>*,std::vector<ns3::Ptr<ns3::Node>, std::allocator<ns3::Ptr<ns3::Node> > > > ns3::NodeContainer::End() const [member function]
|
||||
cls.add_method('End',
|
||||
'__gnu_cxx::__normal_iterator< ns3::Ptr< ns3::Node > const, std::vector< ns3::Ptr< ns3::Node > > >',
|
||||
|
||||
355
bindings/python/apidefs/gcc-LP64/ns3_module_mpi.py
Normal file
355
bindings/python/apidefs/gcc-LP64/ns3_module_mpi.py
Normal file
@@ -0,0 +1,355 @@
|
||||
from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
|
||||
|
||||
def register_types(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage [class]
|
||||
module.add_class('LbtsMessage')
|
||||
## mpi-interface.h: ns3::MpiInterface [class]
|
||||
module.add_class('MpiInterface')
|
||||
## mpi-interface.h: ns3::SentBuffer [class]
|
||||
module.add_class('SentBuffer')
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl [class]
|
||||
module.add_class('DistributedSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
|
||||
|
||||
## Register a nested module for the namespace Config
|
||||
|
||||
nested_module = module.add_cpp_namespace('Config')
|
||||
register_types_ns3_Config(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace TimeStepPrecision
|
||||
|
||||
nested_module = module.add_cpp_namespace('TimeStepPrecision')
|
||||
register_types_ns3_TimeStepPrecision(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace addressUtils
|
||||
|
||||
nested_module = module.add_cpp_namespace('addressUtils')
|
||||
register_types_ns3_addressUtils(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace aodv
|
||||
|
||||
nested_module = module.add_cpp_namespace('aodv')
|
||||
register_types_ns3_aodv(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace dot11s
|
||||
|
||||
nested_module = module.add_cpp_namespace('dot11s')
|
||||
register_types_ns3_dot11s(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace flame
|
||||
|
||||
nested_module = module.add_cpp_namespace('flame')
|
||||
register_types_ns3_flame(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace internal
|
||||
|
||||
nested_module = module.add_cpp_namespace('internal')
|
||||
register_types_ns3_internal(nested_module)
|
||||
|
||||
|
||||
## Register a nested module for the namespace olsr
|
||||
|
||||
nested_module = module.add_cpp_namespace('olsr')
|
||||
register_types_ns3_olsr(nested_module)
|
||||
|
||||
|
||||
def register_types_ns3_Config(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_TimeStepPrecision(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_addressUtils(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_aodv(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_dot11s(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_flame(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_internal(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_types_ns3_olsr(module):
|
||||
root_module = module.get_root()
|
||||
|
||||
|
||||
def register_methods(root_module):
|
||||
register_Ns3LbtsMessage_methods(root_module, root_module['ns3::LbtsMessage'])
|
||||
register_Ns3MpiInterface_methods(root_module, root_module['ns3::MpiInterface'])
|
||||
register_Ns3SentBuffer_methods(root_module, root_module['ns3::SentBuffer'])
|
||||
register_Ns3DistributedSimulatorImpl_methods(root_module, root_module['ns3::DistributedSimulatorImpl'])
|
||||
return
|
||||
|
||||
def register_Ns3LbtsMessage_methods(root_module, cls):
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(ns3::LbtsMessage const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::LbtsMessage const &', 'arg0')])
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage() [constructor]
|
||||
cls.add_constructor([])
|
||||
## distributed-simulator-impl.h: ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, ns3::Time const & t) [constructor]
|
||||
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('ns3::Time const &', 't')])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetMyId() [member function]
|
||||
cls.add_method('GetMyId',
|
||||
'uint32_t',
|
||||
[])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetRxCount() [member function]
|
||||
cls.add_method('GetRxCount',
|
||||
'uint32_t',
|
||||
[])
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::LbtsMessage::GetSmallestTime() [member function]
|
||||
cls.add_method('GetSmallestTime',
|
||||
'ns3::Time',
|
||||
[])
|
||||
## distributed-simulator-impl.h: uint32_t ns3::LbtsMessage::GetTxCount() [member function]
|
||||
cls.add_method('GetTxCount',
|
||||
'uint32_t',
|
||||
[])
|
||||
return
|
||||
|
||||
def register_Ns3MpiInterface_methods(root_module, cls):
|
||||
## mpi-interface.h: ns3::MpiInterface::MpiInterface() [constructor]
|
||||
cls.add_constructor([])
|
||||
## mpi-interface.h: ns3::MpiInterface::MpiInterface(ns3::MpiInterface const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::MpiInterface const &', 'arg0')])
|
||||
## mpi-interface.h: static void ns3::MpiInterface::Destroy() [member function]
|
||||
cls.add_method('Destroy',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::Enable(int * arg0, char * * * arg1) [member function]
|
||||
cls.add_method('Enable',
|
||||
'void',
|
||||
[param('int *', 'arg0'), param('char * * *', 'arg1')],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetRxCount() [member function]
|
||||
cls.add_method('GetRxCount',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSize() [member function]
|
||||
cls.add_method('GetSize',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetSystemId() [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static uint32_t ns3::MpiInterface::GetTxCount() [member function]
|
||||
cls.add_method('GetTxCount',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static bool ns3::MpiInterface::IsEnabled() [member function]
|
||||
cls.add_method('IsEnabled',
|
||||
'bool',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::ReceiveMessages() [member function]
|
||||
cls.add_method('ReceiveMessages',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::SendPacket(ns3::Ptr<ns3::Packet> arg0, ns3::Time const & arg1, uint32_t arg2, uint32_t arg3) [member function]
|
||||
cls.add_method('SendPacket',
|
||||
'void',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'arg0'), param('ns3::Time const &', 'arg1'), param('uint32_t', 'arg2'), param('uint32_t', 'arg3')],
|
||||
is_static=True)
|
||||
## mpi-interface.h: static void ns3::MpiInterface::TestSendComplete() [member function]
|
||||
cls.add_method('TestSendComplete',
|
||||
'void',
|
||||
[],
|
||||
is_static=True)
|
||||
return
|
||||
|
||||
def register_Ns3SentBuffer_methods(root_module, cls):
|
||||
## mpi-interface.h: ns3::SentBuffer::SentBuffer(ns3::SentBuffer const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::SentBuffer const &', 'arg0')])
|
||||
## mpi-interface.h: ns3::SentBuffer::SentBuffer() [constructor]
|
||||
cls.add_constructor([])
|
||||
## mpi-interface.h: uint8_t * ns3::SentBuffer::GetBuffer() [member function]
|
||||
cls.add_method('GetBuffer',
|
||||
'uint8_t *',
|
||||
[])
|
||||
## mpi-interface.h: MPI_Request * ns3::SentBuffer::GetRequest() [member function]
|
||||
cls.add_method('GetRequest',
|
||||
'MPI_Request *',
|
||||
[])
|
||||
## mpi-interface.h: void ns3::SentBuffer::SetBuffer(uint8_t * arg0) [member function]
|
||||
cls.add_method('SetBuffer',
|
||||
'void',
|
||||
[param('uint8_t *', 'arg0')])
|
||||
return
|
||||
|
||||
def register_Ns3DistributedSimulatorImpl_methods(root_module, cls):
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl(ns3::DistributedSimulatorImpl const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::DistributedSimulatorImpl const &', 'arg0')])
|
||||
## distributed-simulator-impl.h: ns3::DistributedSimulatorImpl::DistributedSimulatorImpl() [constructor]
|
||||
cls.add_constructor([])
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Cancel(ns3::EventId const & ev) [member function]
|
||||
cls.add_method('Cancel',
|
||||
'void',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Destroy() [member function]
|
||||
cls.add_method('Destroy',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetContext() const [member function]
|
||||
cls.add_method('GetContext',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetDelayLeft(ns3::EventId const & id) const [member function]
|
||||
cls.add_method('GetDelayLeft',
|
||||
'ns3::Time',
|
||||
[param('ns3::EventId const &', 'id')],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::GetMaximumSimulationTime() const [member function]
|
||||
cls.add_method('GetMaximumSimulationTime',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: uint32_t ns3::DistributedSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: static ns3::TypeId ns3::DistributedSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: bool ns3::DistributedSimulatorImpl::IsFinished() const [member function]
|
||||
cls.add_method('IsFinished',
|
||||
'bool',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Next() const [member function]
|
||||
cls.add_method('Next',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::Time ns3::DistributedSimulatorImpl::Now() const [member function]
|
||||
cls.add_method('Now',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Remove(ns3::EventId const & ev) [member function]
|
||||
cls.add_method('Remove',
|
||||
'void',
|
||||
[param('ns3::EventId const &', 'ev')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Run() [member function]
|
||||
cls.add_method('Run',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::RunOneEvent() [member function]
|
||||
cls.add_method('RunOneEvent',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::Schedule(ns3::Time const & time, ns3::EventImpl * event) [member function]
|
||||
cls.add_method('Schedule',
|
||||
'ns3::EventId',
|
||||
[param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleDestroy(ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleDestroy',
|
||||
'ns3::EventId',
|
||||
[param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: ns3::EventId ns3::DistributedSimulatorImpl::ScheduleNow(ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleNow',
|
||||
'ns3::EventId',
|
||||
[param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::ScheduleWithContext(uint32_t context, ns3::Time const & time, ns3::EventImpl * event) [member function]
|
||||
cls.add_method('ScheduleWithContext',
|
||||
'void',
|
||||
[param('uint32_t', 'context'), param('ns3::Time const &', 'time'), param('ns3::EventImpl *', 'event')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::SetScheduler(ns3::ObjectFactory schedulerFactory) [member function]
|
||||
cls.add_method('SetScheduler',
|
||||
'void',
|
||||
[param('ns3::ObjectFactory', 'schedulerFactory')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop() [member function]
|
||||
cls.add_method('Stop',
|
||||
'void',
|
||||
[],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::Stop(ns3::Time const & time) [member function]
|
||||
cls.add_method('Stop',
|
||||
'void',
|
||||
[param('ns3::Time const &', 'time')],
|
||||
is_virtual=True)
|
||||
## distributed-simulator-impl.h: void ns3::DistributedSimulatorImpl::DoDispose() [member function]
|
||||
cls.add_method('DoDispose',
|
||||
'void',
|
||||
[],
|
||||
visibility='private', is_virtual=True)
|
||||
return
|
||||
|
||||
def register_functions(root_module):
|
||||
module = root_module
|
||||
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
|
||||
register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
|
||||
register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
|
||||
register_functions_ns3_aodv(module.get_submodule('aodv'), root_module)
|
||||
register_functions_ns3_dot11s(module.get_submodule('dot11s'), root_module)
|
||||
register_functions_ns3_flame(module.get_submodule('flame'), root_module)
|
||||
register_functions_ns3_internal(module.get_submodule('internal'), root_module)
|
||||
register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
|
||||
return
|
||||
|
||||
def register_functions_ns3_Config(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_TimeStepPrecision(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_addressUtils(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_aodv(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_dot11s(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_flame(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_internal(module, root_module):
|
||||
return
|
||||
|
||||
def register_functions_ns3_olsr(module, root_module):
|
||||
return
|
||||
|
||||
@@ -9,6 +9,8 @@ def register_types(module):
|
||||
module.add_class('PointToPointChannel', parent=root_module['ns3::Channel'])
|
||||
## point-to-point-net-device.h: ns3::PointToPointNetDevice [class]
|
||||
module.add_class('PointToPointNetDevice', parent=root_module['ns3::NetDevice'])
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel [class]
|
||||
module.add_class('PointToPointRemoteChannel', parent=root_module['ns3::PointToPointChannel'])
|
||||
|
||||
## Register a nested module for the namespace Config
|
||||
|
||||
@@ -94,6 +96,7 @@ def register_methods(root_module):
|
||||
register_Ns3PppHeader_methods(root_module, root_module['ns3::PppHeader'])
|
||||
register_Ns3PointToPointChannel_methods(root_module, root_module['ns3::PointToPointChannel'])
|
||||
register_Ns3PointToPointNetDevice_methods(root_module, root_module['ns3::PointToPointNetDevice'])
|
||||
register_Ns3PointToPointRemoteChannel_methods(root_module, root_module['ns3::PointToPointRemoteChannel'])
|
||||
return
|
||||
|
||||
def register_Ns3PppHeader_methods(root_module, cls):
|
||||
@@ -173,7 +176,28 @@ def register_Ns3PointToPointChannel_methods(root_module, cls):
|
||||
## point-to-point-channel.h: bool ns3::PointToPointChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
|
||||
cls.add_method('TransmitStart',
|
||||
'bool',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')])
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
|
||||
is_virtual=True)
|
||||
## point-to-point-channel.h: ns3::Time ns3::PointToPointChannel::GetDelay() const [member function]
|
||||
cls.add_method('GetDelay',
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetDestination(uint32_t i) const [member function]
|
||||
cls.add_method('GetDestination',
|
||||
'ns3::Ptr< ns3::PointToPointNetDevice >',
|
||||
[param('uint32_t', 'i')],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: ns3::Ptr<ns3::PointToPointNetDevice> ns3::PointToPointChannel::GetSource(uint32_t i) const [member function]
|
||||
cls.add_method('GetSource',
|
||||
'ns3::Ptr< ns3::PointToPointNetDevice >',
|
||||
[param('uint32_t', 'i')],
|
||||
is_const=True, visibility='protected')
|
||||
## point-to-point-channel.h: bool ns3::PointToPointChannel::IsInitialized() const [member function]
|
||||
cls.add_method('IsInitialized',
|
||||
'bool',
|
||||
[],
|
||||
is_const=True, visibility='protected')
|
||||
return
|
||||
|
||||
def register_Ns3PointToPointNetDevice_methods(root_module, cls):
|
||||
@@ -351,6 +375,23 @@ def register_Ns3PointToPointNetDevice_methods(root_module, cls):
|
||||
visibility='private', is_virtual=True)
|
||||
return
|
||||
|
||||
def register_Ns3PointToPointRemoteChannel_methods(root_module, cls):
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel(ns3::PointToPointRemoteChannel const & arg0) [copy constructor]
|
||||
cls.add_constructor([param('ns3::PointToPointRemoteChannel const &', 'arg0')])
|
||||
## point-to-point-remote-channel.h: ns3::PointToPointRemoteChannel::PointToPointRemoteChannel() [constructor]
|
||||
cls.add_constructor([])
|
||||
## point-to-point-remote-channel.h: static ns3::TypeId ns3::PointToPointRemoteChannel::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
[],
|
||||
is_static=True)
|
||||
## point-to-point-remote-channel.h: bool ns3::PointToPointRemoteChannel::TransmitStart(ns3::Ptr<ns3::Packet> p, ns3::Ptr<ns3::PointToPointNetDevice> src, ns3::Time txTime) [member function]
|
||||
cls.add_method('TransmitStart',
|
||||
'bool',
|
||||
[param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ptr< ns3::PointToPointNetDevice >', 'src'), param('ns3::Time', 'txTime')],
|
||||
is_virtual=True)
|
||||
return
|
||||
|
||||
def register_functions(root_module):
|
||||
module = root_module
|
||||
register_functions_ns3_Config(module.get_submodule('Config'), root_module)
|
||||
|
||||
@@ -317,6 +317,11 @@ def register_Ns3Simulator_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_static=True)
|
||||
## simulator.h: static uint32_t ns3::Simulator::GetSystemId() [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_static=True)
|
||||
## simulator.h: static bool ns3::Simulator::IsExpired(ns3::EventId const & id) [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
@@ -795,6 +800,11 @@ def register_Ns3SimulatorImpl_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_pure_virtual=True, is_const=True, is_virtual=True)
|
||||
## simulator-impl.h: uint32_t ns3::SimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_pure_virtual=True, is_const=True, is_virtual=True)
|
||||
## simulator-impl.h: bool ns3::SimulatorImpl::IsExpired(ns3::EventId const & ev) const [member function]
|
||||
cls.add_method('IsExpired',
|
||||
'bool',
|
||||
@@ -1129,6 +1139,11 @@ def register_Ns3DefaultSimulatorImpl_methods(root_module, cls):
|
||||
'ns3::Time',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## default-simulator-impl.h: uint32_t ns3::DefaultSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## default-simulator-impl.h: static ns3::TypeId ns3::DefaultSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
@@ -1423,6 +1438,11 @@ def register_Ns3RealtimeSimulatorImpl_methods(root_module, cls):
|
||||
'ns3::RealtimeSimulatorImpl::SynchronizationMode',
|
||||
[],
|
||||
is_const=True)
|
||||
## realtime-simulator-impl.h: uint32_t ns3::RealtimeSimulatorImpl::GetSystemId() const [member function]
|
||||
cls.add_method('GetSystemId',
|
||||
'uint32_t',
|
||||
[],
|
||||
is_const=True, is_virtual=True)
|
||||
## realtime-simulator-impl.h: static ns3::TypeId ns3::RealtimeSimulatorImpl::GetTypeId() [member function]
|
||||
cls.add_method('GetTypeId',
|
||||
'ns3::TypeId',
|
||||
|
||||
@@ -17,6 +17,7 @@ import ns3_module_simulator
|
||||
import ns3_module_test
|
||||
import ns3_module_common
|
||||
import ns3_module_mobility
|
||||
import ns3_module_mpi
|
||||
import ns3_module_contrib
|
||||
import ns3_module_node
|
||||
import ns3_module_bridge
|
||||
@@ -109,6 +110,17 @@ def register_types(module):
|
||||
ns3_module_mobility__local.register_types(module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_types(module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_types(module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_types(module)
|
||||
|
||||
@@ -572,6 +584,17 @@ def register_methods(root_module):
|
||||
ns3_module_mobility__local.register_methods(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_methods(root_module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_methods(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_methods(root_module)
|
||||
|
||||
@@ -950,6 +973,17 @@ def register_functions(root_module):
|
||||
ns3_module_mobility__local.register_functions(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mobility')
|
||||
root_module.begin_section('ns3_module_mpi')
|
||||
ns3_module_mpi.register_functions(root_module)
|
||||
|
||||
try:
|
||||
import ns3_module_mpi__local
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
ns3_module_mpi__local.register_functions(root_module)
|
||||
|
||||
root_module.end_section('ns3_module_mpi')
|
||||
root_module.begin_section('ns3_module_contrib')
|
||||
ns3_module_contrib.register_functions(root_module)
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ CHAPTERS = \
|
||||
python.texi \
|
||||
random.texi \
|
||||
realtime.texi \
|
||||
distributed.texi \
|
||||
routing.texi \
|
||||
simple.texi \
|
||||
sockets.texi \
|
||||
|
||||
225
doc/manual/distributed.texi
Normal file
225
doc/manual/distributed.texi
Normal file
@@ -0,0 +1,225 @@
|
||||
@node Distributed
|
||||
@chapter Distributed Simulation with MPI
|
||||
@anchor{chap:Distributed}
|
||||
|
||||
@menu
|
||||
* Current Implementation Details::
|
||||
* Running Distributed Simulations::
|
||||
* Tracing During Distributed Simulations::
|
||||
@end menu
|
||||
|
||||
Parallel and distributed discrete event simulation allows the execution of a
|
||||
single simulation program on multiple processors. By splitting up the
|
||||
simulation into logical processes, LPs, each LP can be executed by a different
|
||||
processor. This simulation methodology enables very large-scale simulations by
|
||||
leveraging increased processing power and memory availability. In order to
|
||||
ensure proper execution of a distributed simulation, message passing between
|
||||
LPs is required. To support distributed simulation in ns-3, the standard
|
||||
Message Passing Interface (MPI) is used, along with a new distributed simulator
|
||||
class. Currently, dividing a simulation for distributed purposes in ns-3 can
|
||||
only occur across point-to-point links.
|
||||
|
||||
@node Current Implementation Details
|
||||
@section Current Implementation Details
|
||||
During the course of a distributed simulation, many packets must cross
|
||||
simulator boundaries. In other words, a packet that originated on one LP
|
||||
is destined for a different LP, and in order to make this transition, a message
|
||||
containing the packet contents must be sent to the remote LP. Upon receiving
|
||||
this message, the remote LP can rebuild the packet and proceed as normal. The
|
||||
process of sending an receiving messages between LPs is handled easily by the
|
||||
new MPI interface in ns-3.
|
||||
|
||||
Along with simple message passing between LPs, a distributed simulator is used
|
||||
on each LP to determine which events to process. It is important to process
|
||||
events in time-stamped order to ensure proper simulation execution. If a
|
||||
LP receives a message containing an event from the past, clearly this is an
|
||||
issue, since this event could change other events which have already been
|
||||
executed. To address this problem, a conservative synchronization algorithm with
|
||||
lookahead is used in ns-3. For more information on different synchronization
|
||||
approaches and parallel and distributed simulation in general, please refer to
|
||||
"Parallel and Distributed Simulation Systems" by Richard Fujimoto.
|
||||
|
||||
@subsection Remote point-to-point links
|
||||
As described in the introduction, dividing a simulation for distributed purposes
|
||||
in ns-3 currently can only occur across point-to-point links; therefore, the idea
|
||||
of remote point-to-point links is very important for distributed simulation in ns-3.
|
||||
When a point-to-point link is installed, connecting two nodes, the point-to-point
|
||||
helper checks the system id, or rank, of both nodes. The rank should be assigned
|
||||
during node creation for distributed simulation and is intended to signify on which
|
||||
LP a node belongs. If the two nodes are on the same rank, a regular point-to-point
|
||||
link is created. If, however, the two nodes are on different ranks, then these nodes
|
||||
are intended for different LPs, and a remote point-to-point link is used. If a packet
|
||||
is to be sent across a remote point-to-point link, MPI is used to send the message to
|
||||
the remote LP.
|
||||
|
||||
@subsection Distributing the topology
|
||||
Currently, the full topology is created on each rank, regardless of the individual node
|
||||
system ids. Only the applications are specific to a rank. For example, consider
|
||||
node 1 on LP 1 and node 2 on LP 2, with a traffic generator on node 1. Both node
|
||||
1 and node 2 will be created on both LP1 and LP2; however, the traffic generator
|
||||
will only be installed on LP1. While this is not optimal for memory efficiency, it
|
||||
does simplify routing, since all current routing implementations in ns-3 will work
|
||||
with distributed simulation.
|
||||
|
||||
@node Running Distributed Simulations
|
||||
@section Running Distributed Simulations
|
||||
|
||||
@subsection Prerequisites
|
||||
Ensure that MPI is installed, as well as mpic++. In Ubuntu repositories,
|
||||
these are openmpi-bin, openmpi-common, openmpi-doc, libopenmpi-dev. In
|
||||
Fedora, these are openmpi and openmpi-devel.
|
||||
|
||||
Note:
|
||||
There is a conflict on some Fedora systems between libotf and openmpi. A
|
||||
possible "quick-fix" is to yum remove libotf before installing openmpi.
|
||||
This will remove conflict, but it will also remove emacs. Alternatively,
|
||||
these steps could be followed to resolve the conflict:
|
||||
|
||||
@verbatim
|
||||
1) Rename the tiny otfdump which emacs says it needs:
|
||||
|
||||
mv /usr/bin/otfdump /usr/bin/otfdump.emacs-version
|
||||
|
||||
2) Manually resolve openmpi dependencies:
|
||||
|
||||
sudo yum install libgfortran libtorque numactl
|
||||
|
||||
3) Download rpm packages:
|
||||
|
||||
openmpi-1.3.1-1.fc11.i586.rpm
|
||||
openmpi-devel-1.3.1-1.fc11.i586.rpm
|
||||
openmpi-libs-1.3.1-1.fc11.i586.rpm
|
||||
openmpi-vt-1.3.1-1.fc11.i586.rpm
|
||||
|
||||
from
|
||||
|
||||
http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/
|
||||
|
||||
4) Force the packages in:
|
||||
|
||||
sudo rpm -ivh --force openmpi-1.3.1-1.fc11.i586.rpm
|
||||
openmpi-libs-1.3.1-1.fc11.i586.rpm openmpi-devel-1.3.1-1.fc11.i586.rpm
|
||||
openmpi-vt-1.3.1-1.fc11.i586.rpm
|
||||
|
||||
@end verbatim
|
||||
|
||||
Also, it may be necessary to add the openmpi bin directory to PATH in order to
|
||||
execute mpic++ and mpirun from the command line. Alternatively, the full path
|
||||
to these executables can be used. Finally, if openmpi complains about the
|
||||
inablility to open shared libraries, such as libmpi_cxx.so.0, it may be
|
||||
necessary to add the openmpi lib directory to LD_LIBRARY_PATH.
|
||||
|
||||
@subsection Building and Running Examples
|
||||
If you already built ns-3 without MPI enabled, you must re-build:
|
||||
@verbatim
|
||||
./waf distclean
|
||||
@end verbatim
|
||||
|
||||
Configure ns-3 with the --enable-mpi option:
|
||||
@verbatim
|
||||
./waf -d debug configure --enable-mpi
|
||||
@end verbatim
|
||||
|
||||
Ensure that MPI is enabled by checking the optional features shown from the
|
||||
output of configure.
|
||||
|
||||
Next, build ns-3:
|
||||
@verbatim
|
||||
./waf
|
||||
@end verbatim
|
||||
|
||||
After building ns-3 with mpi enabled, the example programs are now ready to
|
||||
run with mpirun. Here are a few examples (from the root ns-3 directory):
|
||||
|
||||
@verbatim
|
||||
mpirun -np 2 ./waf --run simple-distributed
|
||||
mpirun -np 4 -machinefile mpihosts ./waf --run 'nms-udp-nix --LAN=2 --CN=4 --nix=1 --tracing=0'
|
||||
@end verbatim
|
||||
|
||||
The np switch is the number of logical processors to use. The
|
||||
machinefile switch is which machines to use. In order to use machinefile,
|
||||
the target file must exist (in this case mpihosts). This can simply contain
|
||||
something like:
|
||||
|
||||
@verbatim
|
||||
localhost
|
||||
localhost
|
||||
localhost
|
||||
...
|
||||
@endverbatim
|
||||
|
||||
Or if you have a cluster of machines, you can name them.
|
||||
|
||||
** NOTE: Some users have experienced issues using mpirun and waf together.
|
||||
An alternative way to run distributed examples is shown below:
|
||||
|
||||
@verbatim
|
||||
./waf shell
|
||||
cd build/debug
|
||||
mpirun -np 2 examples/mpi/simple-distributed
|
||||
@end verbatim
|
||||
|
||||
@subsection Creating custom topologies
|
||||
The example programs in examples/mpi give a good idea of how to create
|
||||
different topologies for distributed simulation. The main points are
|
||||
assigning system ids to individual nodes, creating point-to-point
|
||||
links where the simulation should be divided, and installing
|
||||
applications only on the LP associated with the target node.
|
||||
|
||||
Assigning system ids to nodes is simple and can be handled two different
|
||||
ways. First, a NodeContainer can be used to create the nodes and assign
|
||||
system ids:
|
||||
|
||||
@verbatim
|
||||
NodeContainer nodes;
|
||||
nodes.Create (5, 1); // Creates 5 nodes with system id 1.
|
||||
@end verbatim
|
||||
|
||||
Alternatively, nodes can be created individually, assigned system ids, and
|
||||
added to a NodeContainer. This is useful if a NodeContainer holds nodes with
|
||||
different system ids:
|
||||
|
||||
@verbatim
|
||||
NodeContainer nodes;
|
||||
Ptr<Node> node1 = CreateObject<Node> (0); // Create node1 with system id 0
|
||||
Ptr<Node> node2 = CreateObject<Node> (1); // Create node2 with system id 1
|
||||
nodes.Add (node1);
|
||||
nodes.Add (node2);
|
||||
@end verbatim
|
||||
|
||||
Next, where the simulation is divided is determined by the placement of
|
||||
point-to-point links. If a point-to-point link is created between two
|
||||
nodes with different system ids, a remote point-to-point link is created,
|
||||
as described in @ref{Current Implementation Details}.
|
||||
|
||||
Finally, installing applications only on the LP associated with the target
|
||||
node is very important. For example, if a traffic generator is to be placed
|
||||
on node 0, which is on LP0, only LP0 should install this application.
|
||||
This is easily accomplished by first checking the simulator system id, and
|
||||
ensuring that it matches the system id of the target node before installing
|
||||
the application.
|
||||
|
||||
@node Tracing During Distributed Simulations
|
||||
@section Tracing During Distributed Simulations
|
||||
Depending on the system id (rank) of the simulator, the information traced
|
||||
will be different, since traffic originating on one simulator is not seen
|
||||
by another simulator until it reaches nodes specific to that simulator. The
|
||||
easiest way to keep track of different traces is to just name the trace files
|
||||
or pcaps differently, based on the system id of the simulator. For example,
|
||||
something like this should work well, assuming all of these local variables
|
||||
were previously defined:
|
||||
|
||||
@verbatim
|
||||
if (MpiInterface::GetSystemId () == 0)
|
||||
{
|
||||
pointToPoint.EnablePcapAll ("distributed-rank0");
|
||||
phy.EnablePcap ("distributed-rank0", apDevices.Get (0));
|
||||
csma.EnablePcap ("distributed-rank0", csmaDevices.Get (0), true);
|
||||
}
|
||||
else if (MpiInterface::GetSystemId () == 1)
|
||||
{
|
||||
pointToPoint.EnablePcapAll ("distributed-rank1");
|
||||
phy.EnablePcap ("distributed-rank1", apDevices.Get (0));
|
||||
csma.EnablePcap ("distributed-rank1", csmaDevices.Get (0), true);
|
||||
}
|
||||
@end verbatim
|
||||
@@ -96,6 +96,7 @@ Simulator version:
|
||||
* Logging::
|
||||
* Tracing::
|
||||
* RealTime::
|
||||
* Distributed::
|
||||
* Packets::
|
||||
* Helpers::
|
||||
* Python::
|
||||
@@ -140,6 +141,7 @@ Simulator version:
|
||||
@include log.texi
|
||||
@include tracing.texi
|
||||
@include realtime.texi
|
||||
@include distributed.texi
|
||||
@include packets.texi
|
||||
@include helpers.texi
|
||||
@include python.texi
|
||||
|
||||
614
examples/mpi/nms-udp-nix.cc
Normal file
614
examples/mpi/nms-udp-nix.cc
Normal file
@@ -0,0 +1,614 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* (c) 2009, GTech Systems, Inc. - Alfred Park <park@gtech-systems.com>
|
||||
*
|
||||
* DARPA NMS Campus Network Model
|
||||
*
|
||||
* This topology replicates the original NMS Campus Network model
|
||||
* with the exception of chord links (which were never utilized in the
|
||||
* original model)
|
||||
* Link Bandwidths and Delays may not be the same as the original
|
||||
* specifications
|
||||
*
|
||||
* Modified for distributed simulation by Josh Pelkey <jpelkey@gatech.edu>
|
||||
*
|
||||
* The fundamental unit of the NMS model consists of a campus network. The
|
||||
* campus network topology can been seen here:
|
||||
* http://www.nsnam.org/~jpelkey3/nms.png
|
||||
* The number of hosts (default 42) is variable. Finally, an arbitrary
|
||||
* number of these campus networks can be connected together (default 2)
|
||||
* to make very large simulations.
|
||||
*/
|
||||
|
||||
// for timing functions
|
||||
#include <cstdlib>
|
||||
#include <sys/time.h>
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-routing-module.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
|
||||
#ifdef NS3_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace ns3;
|
||||
|
||||
typedef struct timeval TIMER_TYPE;
|
||||
#define TIMER_NOW(_t) gettimeofday (&_t,NULL);
|
||||
#define TIMER_SECONDS(_t) ((double)(_t).tv_sec + (_t).tv_usec * 1e-6)
|
||||
#define TIMER_DIFF(_t1, _t2) (TIMER_SECONDS (_t1) - TIMER_SECONDS (_t2))
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CampusNetworkModel");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
// Enable MPI with the command line arguments
|
||||
MpiInterface::Enable (&argc, &argv);
|
||||
|
||||
TIMER_TYPE t0, t1, t2;
|
||||
TIMER_NOW (t0);
|
||||
cout << " ==== DARPA NMS CAMPUS NETWORK SIMULATION ====" << endl;
|
||||
|
||||
GlobalValue::Bind ("SimulatorImplementationType",
|
||||
StringValue ("ns3::DistributedSimulatorImpl"));
|
||||
|
||||
uint32_t systemId = MpiInterface::GetSystemId ();
|
||||
uint32_t systemCount = MpiInterface::GetSize ();
|
||||
|
||||
uint32_t nCN = 2, nLANClients = 42;
|
||||
int32_t single = 0;
|
||||
int nBytes = 500000; // Bytes for each on/off app
|
||||
bool nix = true;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("CN", "Number of total CNs [2]", nCN);
|
||||
cmd.AddValue ("LAN", "Number of nodes per LAN [42]", nLANClients);
|
||||
cmd.AddValue ("single", "1 if use single flow", single);
|
||||
cmd.AddValue ("nBytes", "Number of bytes for each on/off app", nBytes);
|
||||
cmd.AddValue ("nix", "Toggle the use of nix-vector or global routing", nix);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
if (nCN < 2)
|
||||
{
|
||||
cout << "Number of total CNs (" << nCN << ") lower than minimum of 2"
|
||||
<< endl;
|
||||
return 1;
|
||||
}
|
||||
if (systemCount > nCN)
|
||||
{
|
||||
cout << "Number of total CNs (" << nCN << ") should be >= systemCount ("
|
||||
<< systemCount << ")." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cout << "Number of CNs: " << nCN << ", LAN nodes: " << nLANClients << endl;
|
||||
|
||||
NodeContainer nodes_net0[nCN][3], nodes_net1[nCN][6], nodes_netLR[nCN],
|
||||
nodes_net2[nCN][14], nodes_net2LAN[nCN][7][nLANClients],
|
||||
nodes_net3[nCN][9], nodes_net3LAN[nCN][5][nLANClients];
|
||||
PointToPointHelper p2p_2gb200ms, p2p_1gb5ms, p2p_100mb1ms;
|
||||
InternetStackHelper stack;
|
||||
Ipv4InterfaceContainer ifs, ifs0[nCN][3], ifs1[nCN][6], ifs2[nCN][14],
|
||||
ifs3[nCN][9], ifs2LAN[nCN][7][nLANClients],
|
||||
ifs3LAN[nCN][5][nLANClients];
|
||||
Ipv4AddressHelper address;
|
||||
std::ostringstream oss;
|
||||
p2p_1gb5ms.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
|
||||
p2p_1gb5ms.SetChannelAttribute ("Delay", StringValue ("5ms"));
|
||||
p2p_2gb200ms.SetDeviceAttribute ("DataRate", StringValue ("2Gbps"));
|
||||
p2p_2gb200ms.SetChannelAttribute ("Delay", StringValue ("200ms"));
|
||||
p2p_100mb1ms.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
p2p_100mb1ms.SetChannelAttribute ("Delay", StringValue ("1ms"));
|
||||
|
||||
Ipv4NixVectorHelper nixRouting;
|
||||
Ipv4StaticRoutingHelper staticRouting;
|
||||
|
||||
Ipv4ListRoutingHelper list;
|
||||
list.Add (staticRouting, 0);
|
||||
list.Add (nixRouting, 10);
|
||||
|
||||
if (nix)
|
||||
{
|
||||
stack.SetRoutingHelper (list);
|
||||
}
|
||||
|
||||
// Create Campus Networks
|
||||
for (uint32_t z = 0; z < nCN; ++z)
|
||||
{
|
||||
cout << "Creating Campus Network " << z << ":" << endl;
|
||||
// Create Net0
|
||||
cout << " SubNet [ 0";
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net0[z][i].Add (node);
|
||||
stack.Install (nodes_net0[z][i]);
|
||||
}
|
||||
nodes_net0[z][0].Add (nodes_net0[z][1].Get (0));
|
||||
nodes_net0[z][1].Add (nodes_net0[z][2].Get (0));
|
||||
nodes_net0[z][2].Add (nodes_net0[z][0].Get (0));
|
||||
NetDeviceContainer ndc0[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
ndc0[i] = p2p_1gb5ms.Install (nodes_net0[z][i]);
|
||||
}
|
||||
// Create Net1
|
||||
cout << " 1";
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net1[z][i].Add (node);
|
||||
stack.Install (nodes_net1[z][i]);
|
||||
}
|
||||
nodes_net1[z][0].Add (nodes_net1[z][1].Get (0));
|
||||
nodes_net1[z][2].Add (nodes_net1[z][0].Get (0));
|
||||
nodes_net1[z][3].Add (nodes_net1[z][0].Get (0));
|
||||
nodes_net1[z][4].Add (nodes_net1[z][1].Get (0));
|
||||
nodes_net1[z][5].Add (nodes_net1[z][1].Get (0));
|
||||
NetDeviceContainer ndc1[6];
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ndc1[i] = p2p_1gb5ms.Install (nodes_net1[z][i]);
|
||||
}
|
||||
// Connect Net0 <-> Net1
|
||||
NodeContainer net0_1;
|
||||
net0_1.Add (nodes_net0[z][2].Get (0));
|
||||
net0_1.Add (nodes_net1[z][0].Get (0));
|
||||
NetDeviceContainer ndc0_1;
|
||||
ndc0_1 = p2p_1gb5ms.Install (net0_1);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".1.252.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc0_1);
|
||||
// Create Net2
|
||||
cout << " 2";
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net2[z][i].Add (node);
|
||||
stack.Install (nodes_net2[z][i]);
|
||||
}
|
||||
nodes_net2[z][0].Add (nodes_net2[z][1].Get (0));
|
||||
nodes_net2[z][2].Add (nodes_net2[z][0].Get (0));
|
||||
nodes_net2[z][1].Add (nodes_net2[z][3].Get (0));
|
||||
nodes_net2[z][3].Add (nodes_net2[z][2].Get (0));
|
||||
nodes_net2[z][4].Add (nodes_net2[z][2].Get (0));
|
||||
nodes_net2[z][5].Add (nodes_net2[z][3].Get (0));
|
||||
nodes_net2[z][6].Add (nodes_net2[z][5].Get (0));
|
||||
nodes_net2[z][7].Add (nodes_net2[z][2].Get (0));
|
||||
nodes_net2[z][8].Add (nodes_net2[z][3].Get (0));
|
||||
nodes_net2[z][9].Add (nodes_net2[z][4].Get (0));
|
||||
nodes_net2[z][10].Add (nodes_net2[z][5].Get (0));
|
||||
nodes_net2[z][11].Add (nodes_net2[z][6].Get (0));
|
||||
nodes_net2[z][12].Add (nodes_net2[z][6].Get (0));
|
||||
nodes_net2[z][13].Add (nodes_net2[z][6].Get (0));
|
||||
NetDeviceContainer ndc2[14];
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
ndc2[i] = p2p_1gb5ms.Install (nodes_net2[z][i]);
|
||||
}
|
||||
NetDeviceContainer ndc2LAN[7][nLANClients];
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".4." << 15 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
for (uint32_t j = 0; j < nLANClients; ++j)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net2LAN[z][i][j].Add (node);
|
||||
stack.Install (nodes_net2LAN[z][i][j]);
|
||||
nodes_net2LAN[z][i][j].Add (nodes_net2[z][i + 7].Get (0));
|
||||
ndc2LAN[i][j] = p2p_100mb1ms.Install (nodes_net2LAN[z][i][j]);
|
||||
ifs2LAN[z][i][j] = address.Assign (ndc2LAN[i][j]);
|
||||
}
|
||||
}
|
||||
// Create Net3
|
||||
cout << " 3 ]" << endl;
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net3[z][i].Add (node);
|
||||
stack.Install (nodes_net3[z][i]);
|
||||
}
|
||||
nodes_net3[z][0].Add (nodes_net3[z][1].Get (0));
|
||||
nodes_net3[z][1].Add (nodes_net3[z][2].Get (0));
|
||||
nodes_net3[z][2].Add (nodes_net3[z][3].Get (0));
|
||||
nodes_net3[z][3].Add (nodes_net3[z][1].Get (0));
|
||||
nodes_net3[z][4].Add (nodes_net3[z][0].Get (0));
|
||||
nodes_net3[z][5].Add (nodes_net3[z][0].Get (0));
|
||||
nodes_net3[z][6].Add (nodes_net3[z][2].Get (0));
|
||||
nodes_net3[z][7].Add (nodes_net3[z][3].Get (0));
|
||||
nodes_net3[z][8].Add (nodes_net3[z][3].Get (0));
|
||||
NetDeviceContainer ndc3[9];
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
ndc3[i] = p2p_1gb5ms.Install (nodes_net3[z][i]);
|
||||
}
|
||||
NetDeviceContainer ndc3LAN[5][nLANClients];
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".5." << 10 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.255");
|
||||
for (uint32_t j = 0; j < nLANClients; ++j)
|
||||
{
|
||||
Ptr<Node> node = CreateObject<Node> (z % systemCount);
|
||||
nodes_net3LAN[z][i][j].Add (node);
|
||||
stack.Install (nodes_net3LAN[z][i][j]);
|
||||
nodes_net3LAN[z][i][j].Add (nodes_net3[z][i + 4].Get (0));
|
||||
ndc3LAN[i][j] = p2p_100mb1ms.Install (nodes_net3LAN[z][i][j]);
|
||||
ifs3LAN[z][i][j] = address.Assign (ndc3LAN[i][j]);
|
||||
}
|
||||
}
|
||||
cout << " Connecting Subnets..." << endl;
|
||||
// Create Lone Routers (Node 4 & 5)
|
||||
Ptr<Node> node1 = CreateObject<Node> (z % systemCount);
|
||||
Ptr<Node> node2 = CreateObject<Node> (z % systemCount);
|
||||
nodes_netLR[z].Add (node1);
|
||||
nodes_netLR[z].Add (node2);
|
||||
stack.Install (nodes_netLR[z]);
|
||||
NetDeviceContainer ndcLR;
|
||||
ndcLR = p2p_1gb5ms.Install (nodes_netLR[z]);
|
||||
// Connect Net2/Net3 through Lone Routers to Net0
|
||||
NodeContainer net0_4, net0_5, net2_4a, net2_4b, net3_5a, net3_5b;
|
||||
net0_4.Add (nodes_netLR[z].Get (0));
|
||||
net0_4.Add (nodes_net0[z][0].Get (0));
|
||||
net0_5.Add (nodes_netLR[z].Get (1));
|
||||
net0_5.Add (nodes_net0[z][1].Get (0));
|
||||
net2_4a.Add (nodes_netLR[z].Get (0));
|
||||
net2_4a.Add (nodes_net2[z][0].Get (0));
|
||||
net2_4b.Add (nodes_netLR[z].Get (1));
|
||||
net2_4b.Add (nodes_net2[z][1].Get (0));
|
||||
net3_5a.Add (nodes_netLR[z].Get (1));
|
||||
net3_5a.Add (nodes_net3[z][0].Get (0));
|
||||
net3_5b.Add (nodes_netLR[z].Get (1));
|
||||
net3_5b.Add (nodes_net3[z][1].Get (0));
|
||||
NetDeviceContainer ndc0_4, ndc0_5, ndc2_4a, ndc2_4b, ndc3_5a, ndc3_5b;
|
||||
ndc0_4 = p2p_1gb5ms.Install (net0_4);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".1.253.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc0_4);
|
||||
ndc0_5 = p2p_1gb5ms.Install (net0_5);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".1.254.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc0_5);
|
||||
ndc2_4a = p2p_1gb5ms.Install (net2_4a);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".4.253.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc2_4a);
|
||||
ndc2_4b = p2p_1gb5ms.Install (net2_4b);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".4.254.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc2_4b);
|
||||
ndc3_5a = p2p_1gb5ms.Install (net3_5a);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".5.253.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc3_5a);
|
||||
ndc3_5b = p2p_1gb5ms.Install (net3_5b);
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".5.254.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc3_5b);
|
||||
// Assign IP addresses
|
||||
cout << " Assigning IP addresses..." << endl;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".1." << 1 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs0[z][i] = address.Assign (ndc0[i]);
|
||||
}
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".2." << 1 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs1[z][i] = address.Assign (ndc1[i]);
|
||||
}
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".3.1.0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndcLR);
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".4." << 1 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs2[z][i] = address.Assign (ndc2[i]);
|
||||
}
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
oss.str ("");
|
||||
oss << 10 + z << ".5." << 1 + i << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs3[z][i] = address.Assign (ndc3[i]);
|
||||
}
|
||||
}
|
||||
// Create Ring Links
|
||||
if (nCN > 1)
|
||||
{
|
||||
cout << "Forming Ring Topology..." << endl;
|
||||
NodeContainer nodes_ring[nCN];
|
||||
for (uint32_t z = 0; z < nCN - 1; ++z)
|
||||
{
|
||||
nodes_ring[z].Add (nodes_net0[z][0].Get (0));
|
||||
nodes_ring[z].Add (nodes_net0[z + 1][0].Get (0));
|
||||
}
|
||||
nodes_ring[nCN - 1].Add (nodes_net0[nCN - 1][0].Get (0));
|
||||
nodes_ring[nCN - 1].Add (nodes_net0[0][0].Get (0));
|
||||
NetDeviceContainer ndc_ring[nCN];
|
||||
for (uint32_t z = 0; z < nCN; ++z)
|
||||
{
|
||||
ndc_ring[z] = p2p_2gb200ms.Install (nodes_ring[z]);
|
||||
oss.str ("");
|
||||
oss << "254.1." << z + 1 << ".0";
|
||||
address.SetBase (oss.str ().c_str (), "255.255.255.0");
|
||||
ifs = address.Assign (ndc_ring[z]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create Traffic Flows
|
||||
cout << "Creating UDP Traffic Flows:" << endl;
|
||||
Config::SetDefault ("ns3::OnOffApplication::MaxBytes",
|
||||
UintegerValue (nBytes));
|
||||
Config::SetDefault ("ns3::OnOffApplication::OnTime",
|
||||
RandomVariableValue (ConstantVariable (1)));
|
||||
Config::SetDefault ("ns3::OnOffApplication::OffTime",
|
||||
RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
|
||||
if (single)
|
||||
{
|
||||
if (systemCount == 1)
|
||||
{
|
||||
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (),
|
||||
9999));
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (nodes_net1[0][2].Get (0));
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
AddressValue remoteAddress (InetSocketAddress (ifs1[0][2].GetAddress (0), 9999));
|
||||
cout << "Remote Address is " << ifs1[0][2].GetAddress (0) << endl;
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net2LAN[0][0][0].Get (0)));
|
||||
clientApp.Start (Seconds (0));
|
||||
}
|
||||
else if (systemId == 1)
|
||||
{
|
||||
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (),
|
||||
9999));
|
||||
ApplicationContainer sinkApp =
|
||||
sinkHelper.Install (nodes_net1[1][0].Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
}
|
||||
else if (systemId == 0)
|
||||
{
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (ifs1[1][0].GetAddress (0), 9999));
|
||||
|
||||
cout << "Remote Address is " << ifs1[1][0].GetAddress (0) << endl;
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net2LAN[0][0][0].Get (0)));
|
||||
clientApp.Start (Seconds (0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UniformVariable urng;
|
||||
int r1;
|
||||
double r2;
|
||||
for (uint32_t z = 0; z < nCN; ++z)
|
||||
{
|
||||
uint32_t x = z + 1;
|
||||
if (z == nCN - 1)
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
// Subnet 2 LANs
|
||||
cout << " Campus Network " << z << " Flows [ Net2 ";
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
for (uint32_t j = 0; j < nLANClients; ++j)
|
||||
{
|
||||
// Sinks
|
||||
if (systemCount == 1)
|
||||
{
|
||||
PacketSinkHelper sinkHelper
|
||||
("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), 9999));
|
||||
|
||||
ApplicationContainer sinkApp =
|
||||
sinkHelper.Install (nodes_net2LAN[z][i][j].Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (100.0));
|
||||
}
|
||||
else if (systemId == z % systemCount)
|
||||
{
|
||||
PacketSinkHelper sinkHelper
|
||||
("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), 9999));
|
||||
|
||||
ApplicationContainer sinkApp =
|
||||
sinkHelper.Install (nodes_net2LAN[z][i][j].Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (100.0));
|
||||
}
|
||||
// Sources
|
||||
if (systemCount == 1)
|
||||
{
|
||||
r1 = 2 + (int)(4 * urng.GetValue ());
|
||||
r2 = 100 + (10 * urng.GetValue ());
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
|
||||
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
|
||||
clientApp.Start (Seconds (r2));
|
||||
}
|
||||
else if (systemId == x % systemCount)
|
||||
{
|
||||
r1 = 2 + (int)(4 * urng.GetValue ());
|
||||
r2 = 100 + (10 * urng.GetValue ());
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
|
||||
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
|
||||
clientApp.Start (Seconds (r2));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Subnet 3 LANs
|
||||
cout << "Net3 ]" << endl;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
for (uint32_t j = 0; j < nLANClients; ++j)
|
||||
{
|
||||
// Sinks
|
||||
if (systemCount == 1)
|
||||
{
|
||||
PacketSinkHelper sinkHelper
|
||||
("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), 9999));
|
||||
|
||||
ApplicationContainer sinkApp =
|
||||
sinkHelper.Install (nodes_net3LAN[z][i][j].Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (100.0));
|
||||
}
|
||||
else if (systemId == z % systemCount)
|
||||
{
|
||||
PacketSinkHelper sinkHelper
|
||||
("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (Ipv4Address::GetAny (), 9999));
|
||||
|
||||
ApplicationContainer sinkApp =
|
||||
sinkHelper.Install (nodes_net3LAN[z][i][j].Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (100.0));
|
||||
}
|
||||
// Sources
|
||||
if (systemCount == 1)
|
||||
{
|
||||
r1 = 2 + (int)(4 * urng.GetValue ());
|
||||
r2 = 100 + (10 * urng.GetValue ());
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
|
||||
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
|
||||
clientApp.Start (Seconds (r2));
|
||||
}
|
||||
else if (systemId == x % systemCount)
|
||||
{
|
||||
r1 = 2 + (int)(4 * urng.GetValue ());
|
||||
r2 = 100 + (10 * urng.GetValue ());
|
||||
OnOffHelper client ("ns3::UdpSocketFactory", Address ());
|
||||
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (ifs2LAN[z][i][j].GetAddress (0), 9999));
|
||||
|
||||
client.SetAttribute ("Remote", remoteAddress);
|
||||
ApplicationContainer clientApp;
|
||||
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
|
||||
clientApp.Start (Seconds (r2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << "Created " << NodeList::GetNNodes () << " nodes." << endl;
|
||||
TIMER_TYPE routingStart;
|
||||
TIMER_NOW (routingStart);
|
||||
|
||||
if (nix)
|
||||
{
|
||||
cout << "Using Nix-vectors..." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate routing tables
|
||||
cout << "Populating Routing tables..." << endl;
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
}
|
||||
|
||||
TIMER_TYPE routingEnd;
|
||||
TIMER_NOW (routingEnd);
|
||||
cout << "Routing tables population took "
|
||||
<< TIMER_DIFF (routingEnd, routingStart) << endl;
|
||||
|
||||
cout << "Running simulator..." << endl;
|
||||
TIMER_NOW (t1);
|
||||
Simulator::Stop (Seconds (200.0));
|
||||
Simulator::Run ();
|
||||
TIMER_NOW (t2);
|
||||
cout << "Simulator finished." << endl;
|
||||
Simulator::Destroy ();
|
||||
|
||||
double d1 = TIMER_DIFF (t1, t0), d2 = TIMER_DIFF (t2, t1);
|
||||
cout << "-----" << endl << "Runtime Stats:" << endl;
|
||||
cout << "Simulator init time: " << d1 << endl;
|
||||
cout << "Simulator run time: " << d2 << endl;
|
||||
cout << "Total elapsed time: " << d1 + d2 << endl;
|
||||
return 0;
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
245
examples/mpi/simple-distributed.cc
Normal file
245
examples/mpi/simple-distributed.cc
Normal file
@@ -0,0 +1,245 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* TestDistributed creates a dumbbell topology and logically splits it in
|
||||
* half. The left half is placed on logical processor 0 and the right half
|
||||
* is placed on logical processor 1.
|
||||
*
|
||||
* ------- -------
|
||||
* RANK 0 RANK 1
|
||||
* ------- | -------
|
||||
* |
|
||||
* n0 ---------| | |---------- n6
|
||||
* | | |
|
||||
* n1 -------\ | | | /------- n7
|
||||
* n4 ----------|---------- n5
|
||||
* n2 -------/ | | | \------- n8
|
||||
* | | |
|
||||
* n3 ---------| | |---------- n9
|
||||
*
|
||||
*
|
||||
* OnOff clients are placed on each left leaf node. Each right leaf node
|
||||
* is a packet sink for a left leaf node. As a packet travels from one
|
||||
* logical processor to another (the link between n4 and n5), MPI messages
|
||||
* are passed containing the serialized packet. The message is then
|
||||
* deserialized into a new packet and sent on as normal.
|
||||
*
|
||||
* One packet is sent from each left leaf node. The packet sinks on the
|
||||
* right leaf nodes output logging information when they receive the packet.
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
|
||||
#ifdef NS3_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleDistributed");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
// Distributed simulation setup
|
||||
MpiInterface::Enable (&argc, &argv);
|
||||
GlobalValue::Bind ("SimulatorImplementationType",
|
||||
StringValue ("ns3::DistributedSimulatorImpl"));
|
||||
|
||||
LogComponentEnable ("PacketSink", LOG_LEVEL_INFO);
|
||||
|
||||
uint32_t systemId = MpiInterface::GetSystemId ();
|
||||
uint32_t systemCount = MpiInterface::GetSize ();
|
||||
|
||||
// Check for valid distributed parameters.
|
||||
// Must have 2 and only 2 Logical Processors (LPs)
|
||||
if (systemCount != 2)
|
||||
{
|
||||
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Some default values
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (512));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("1Mbps"));
|
||||
Config::SetDefault ("ns3::OnOffApplication::MaxBytes", UintegerValue (512));
|
||||
bool nix = true;
|
||||
|
||||
// Parse command line
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("nix", "Enable the use of nix-vector or global routing", nix);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Create leaf nodes on left with system id 0
|
||||
NodeContainer leftLeafNodes;
|
||||
leftLeafNodes.Create (4, 0);
|
||||
|
||||
// Create router nodes. Left router
|
||||
// with system id 0, right router with
|
||||
// system id 1
|
||||
NodeContainer routerNodes;
|
||||
Ptr<Node> routerNode1 = CreateObject<Node> (0);
|
||||
Ptr<Node> routerNode2 = CreateObject<Node> (1);
|
||||
routerNodes.Add (routerNode1);
|
||||
routerNodes.Add (routerNode2);
|
||||
|
||||
// Create leaf nodes on left with system id 1
|
||||
NodeContainer rightLeafNodes;
|
||||
rightLeafNodes.Create (4, 1);
|
||||
|
||||
PointToPointHelper routerLink;
|
||||
routerLink.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
routerLink.SetChannelAttribute ("Delay", StringValue ("5ms"));
|
||||
|
||||
PointToPointHelper leafLink;
|
||||
leafLink.SetDeviceAttribute ("DataRate", StringValue ("1Mbps"));
|
||||
leafLink.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
|
||||
// Add link connecting routers
|
||||
NetDeviceContainer routerDevices;
|
||||
routerDevices = routerLink.Install (routerNodes);
|
||||
|
||||
// Add links for left side leaf nodes to left router
|
||||
NetDeviceContainer leftRouterDevices;
|
||||
NetDeviceContainer leftLeafDevices;
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
NetDeviceContainer temp = leafLink.Install (leftLeafNodes.Get (i), routerNodes.Get (0));
|
||||
leftLeafDevices.Add (temp.Get (0));
|
||||
leftRouterDevices.Add (temp.Get (1));
|
||||
}
|
||||
|
||||
// Add links for right side leaf nodes to right router
|
||||
NetDeviceContainer rightRouterDevices;
|
||||
NetDeviceContainer rightLeafDevices;
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
NetDeviceContainer temp = leafLink.Install (rightLeafNodes.Get (i), routerNodes.Get (1));
|
||||
rightLeafDevices.Add (temp.Get (0));
|
||||
rightRouterDevices.Add (temp.Get (1));
|
||||
}
|
||||
|
||||
InternetStackHelper stack;
|
||||
Ipv4NixVectorHelper nixRouting;
|
||||
Ipv4StaticRoutingHelper staticRouting;
|
||||
|
||||
Ipv4ListRoutingHelper list;
|
||||
list.Add (staticRouting, 0);
|
||||
list.Add (nixRouting, 10);
|
||||
|
||||
if (nix)
|
||||
{
|
||||
stack.SetRoutingHelper (list);
|
||||
}
|
||||
|
||||
stack.InstallAll ();
|
||||
|
||||
Ipv4InterfaceContainer routerInterfaces;
|
||||
Ipv4InterfaceContainer leftLeafInterfaces;
|
||||
Ipv4InterfaceContainer leftRouterInterfaces;
|
||||
Ipv4InterfaceContainer rightLeafInterfaces;
|
||||
Ipv4InterfaceContainer rightRouterInterfaces;
|
||||
|
||||
Ipv4AddressHelper leftAddress;
|
||||
leftAddress.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
|
||||
Ipv4AddressHelper routerAddress;
|
||||
routerAddress.SetBase ("10.2.1.0", "255.255.255.0");
|
||||
|
||||
Ipv4AddressHelper rightAddress;
|
||||
rightAddress.SetBase ("10.3.1.0", "255.255.255.0");
|
||||
|
||||
// Router-to-Router interfaces
|
||||
routerInterfaces = routerAddress.Assign (routerDevices);
|
||||
|
||||
// Left interfaces
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
NetDeviceContainer ndc;
|
||||
ndc.Add (leftLeafDevices.Get (i));
|
||||
ndc.Add (leftRouterDevices.Get (i));
|
||||
Ipv4InterfaceContainer ifc = leftAddress.Assign (ndc);
|
||||
leftLeafInterfaces.Add (ifc.Get (0));
|
||||
leftRouterInterfaces.Add (ifc.Get (1));
|
||||
leftAddress.NewNetwork ();
|
||||
}
|
||||
|
||||
// Right interfaces
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
NetDeviceContainer ndc;
|
||||
ndc.Add (rightLeafDevices.Get (i));
|
||||
ndc.Add (rightRouterDevices.Get (i));
|
||||
Ipv4InterfaceContainer ifc = rightAddress.Assign (ndc);
|
||||
rightLeafInterfaces.Add (ifc.Get (0));
|
||||
rightRouterInterfaces.Add (ifc.Get (1));
|
||||
rightAddress.NewNetwork ();
|
||||
}
|
||||
|
||||
if (!nix)
|
||||
{
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
}
|
||||
|
||||
// Create a packet sink on the right leafs to receive packets from left leafs
|
||||
uint16_t port = 50000;
|
||||
if (systemId == 1)
|
||||
{
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp;
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
sinkApp.Add (sinkHelper.Install (rightLeafNodes.Get (i)));
|
||||
}
|
||||
sinkApp.Start (Seconds (1.0));
|
||||
sinkApp.Stop (Seconds (5));
|
||||
}
|
||||
|
||||
// Create the OnOff applications to send
|
||||
if (systemId == 0)
|
||||
{
|
||||
OnOffHelper clientHelper ("ns3::UdpSocketFactory", Address ());
|
||||
clientHelper.SetAttribute
|
||||
("OnTime", RandomVariableValue (ConstantVariable (1)));
|
||||
clientHelper.SetAttribute
|
||||
("OffTime", RandomVariableValue (ConstantVariable (0)));
|
||||
|
||||
ApplicationContainer clientApps;
|
||||
for (uint32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (rightLeafInterfaces.GetAddress (i), port));
|
||||
clientHelper.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps.Add (clientHelper.Install (leftLeafNodes.Get (i)));
|
||||
}
|
||||
clientApps.Start (Seconds (1.0));
|
||||
clientApps.Stop (Seconds (5));
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds (5));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
244
examples/mpi/third-distributed.cc
Normal file
244
examples/mpi/third-distributed.cc
Normal file
@@ -0,0 +1,244 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
|
||||
#ifdef NS3_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
// Default Network Topology (same as third.cc from tutorial)
|
||||
// Distributed simulation, split along the p2p link
|
||||
// Number of wifi or csma nodes can be increased up to 250
|
||||
//
|
||||
// Wifi 10.1.3.0
|
||||
// AP
|
||||
// * * * *
|
||||
// | | | | 10.1.1.0
|
||||
// n5 n6 n7 n0 -------------- n1 n2 n3 n4
|
||||
// point-to-point | | | |
|
||||
// ================
|
||||
// | LAN 10.1.2.0
|
||||
// |
|
||||
// Rank 0 | Rank 1
|
||||
// -------------------------|----------------------------
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThirdExampleDistributed");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
// Distributed simulation setup
|
||||
MpiInterface::Enable (&argc, &argv);
|
||||
GlobalValue::Bind ("SimulatorImplementationType",
|
||||
StringValue ("ns3::DistributedSimulatorImpl"));
|
||||
|
||||
uint32_t systemId = MpiInterface::GetSystemId ();
|
||||
uint32_t systemCount = MpiInterface::GetSize ();
|
||||
|
||||
// Check for valid distributed parameters.
|
||||
// Must have 2 and only 2 Logical Processors (LPs)
|
||||
if (systemCount != 2)
|
||||
{
|
||||
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool verbose = true;
|
||||
uint32_t nCsma = 3;
|
||||
uint32_t nWifi = 3;
|
||||
bool tracing = false;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
|
||||
cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
|
||||
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
|
||||
cmd.AddValue ("tracing", "Enable pcap tracing", tracing);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
// Check for valid number of csma or wifi nodes
|
||||
// 250 should be enough, otherwise IP addresses
|
||||
// soon become an issue
|
||||
if (nWifi > 250 || nCsma > 250)
|
||||
{
|
||||
std::cout << "Too many wifi or csma nodes, max 200 each." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
NodeContainer p2pNodes;
|
||||
Ptr<Node> p2pNode1 = CreateObject<Node> (0); // Create node with rank 0
|
||||
Ptr<Node> p2pNode2 = CreateObject<Node> (1); // Create node with rank 1
|
||||
p2pNodes.Add (p2pNode1);
|
||||
p2pNodes.Add (p2pNode2);
|
||||
|
||||
PointToPointHelper pointToPoint;
|
||||
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
|
||||
NetDeviceContainer p2pDevices;
|
||||
p2pDevices = pointToPoint.Install (p2pNodes);
|
||||
|
||||
NodeContainer csmaNodes;
|
||||
csmaNodes.Add (p2pNodes.Get (1));
|
||||
csmaNodes.Create (nCsma , 1); // Create csma nodes with rank 1
|
||||
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
|
||||
|
||||
NetDeviceContainer csmaDevices;
|
||||
csmaDevices = csma.Install (csmaNodes);
|
||||
|
||||
NodeContainer wifiStaNodes;
|
||||
wifiStaNodes.Create (nWifi, 0); // Create wifi nodes with rank 0
|
||||
NodeContainer wifiApNode = p2pNodes.Get (0);
|
||||
|
||||
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
|
||||
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
||||
phy.SetChannel (channel.Create ());
|
||||
|
||||
WifiHelper wifi = WifiHelper::Default ();
|
||||
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
|
||||
|
||||
NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
|
||||
|
||||
Ssid ssid = Ssid ("ns-3-ssid");
|
||||
mac.SetType ("ns3::NqstaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
|
||||
NetDeviceContainer staDevices;
|
||||
staDevices = wifi.Install (phy, mac, wifiStaNodes);
|
||||
|
||||
mac.SetType ("ns3::NqapWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"BeaconGeneration", BooleanValue (true),
|
||||
"BeaconInterval", TimeValue (Seconds (2.5)));
|
||||
|
||||
NetDeviceContainer apDevices;
|
||||
apDevices = wifi.Install (phy, mac, wifiApNode);
|
||||
|
||||
MobilityHelper mobility;
|
||||
|
||||
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
|
||||
"MinX", DoubleValue (0.0),
|
||||
"MinY", DoubleValue (0.0),
|
||||
"DeltaX", DoubleValue (5.0),
|
||||
"DeltaY", DoubleValue (5.0),
|
||||
"GridWidth", UintegerValue (10),
|
||||
"LayoutType", StringValue ("RowFirst"));
|
||||
|
||||
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
|
||||
"Bounds", RectangleValue (Rectangle (-250, 250, -250, 250)));
|
||||
mobility.Install (wifiStaNodes);
|
||||
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
mobility.Install (wifiApNode);
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.Install (csmaNodes);
|
||||
stack.Install (wifiApNode);
|
||||
stack.Install (wifiStaNodes);
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
|
||||
address.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer p2pInterfaces;
|
||||
p2pInterfaces = address.Assign (p2pDevices);
|
||||
|
||||
address.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer csmaInterfaces;
|
||||
csmaInterfaces = address.Assign (csmaDevices);
|
||||
|
||||
address.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
address.Assign (staDevices);
|
||||
address.Assign (apDevices);
|
||||
|
||||
// If this simulator has system id 1, then
|
||||
// it should contain the server application,
|
||||
// since it is on one of the csma nodes
|
||||
if (systemId == 1)
|
||||
{
|
||||
UdpEchoServerHelper echoServer (9);
|
||||
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
|
||||
serverApps.Start (Seconds (1.0));
|
||||
serverApps.Stop (Seconds (10.0));
|
||||
}
|
||||
|
||||
// If the simulator has sytem id 0, then
|
||||
// it should contain the client application,
|
||||
// since it is on one of the wifi nodes
|
||||
if (systemId == 0)
|
||||
{
|
||||
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
|
||||
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
|
||||
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
|
||||
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
|
||||
|
||||
ApplicationContainer clientApps =
|
||||
echoClient.Install (wifiStaNodes.Get (nWifi - 1));
|
||||
clientApps.Start (Seconds (2.0));
|
||||
clientApps.Stop (Seconds (10.0));
|
||||
}
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
|
||||
Simulator::Stop (Seconds (10.0));
|
||||
|
||||
if (tracing == true)
|
||||
{
|
||||
// Depending on the system Id (rank), the pcap information
|
||||
// traced will be different. For example, the ethernet pcap
|
||||
// will be empty for rank0, since these nodes are placed on
|
||||
// on rank 1. All ethernet traffic will take place on rank 1.
|
||||
// Similar differences are seen in the p2p and wirless pcaps.
|
||||
if (systemId == 0)
|
||||
{
|
||||
pointToPoint.EnablePcapAll ("third-distributed-rank0");
|
||||
phy.EnablePcap ("third-distributed-rank0", apDevices.Get (0));
|
||||
csma.EnablePcap ("third-distributed-rank0", csmaDevices.Get (0), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
pointToPoint.EnablePcapAll ("third-distributed-rank1");
|
||||
phy.EnablePcap ("third-distributed-rank1", apDevices.Get (0));
|
||||
csma.EnablePcap ("third-distributed-rank1", csmaDevices.Get (0), true);
|
||||
}
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
1
examples/mpi/waf
vendored
Executable file
1
examples/mpi/waf
vendored
Executable file
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../../waf "$@"
|
||||
14
examples/mpi/wscript
Normal file
14
examples/mpi/wscript
Normal file
@@ -0,0 +1,14 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_program('simple-distributed',
|
||||
['point-to-point', 'internet-stack'])
|
||||
obj.source = 'simple-distributed.cc'
|
||||
|
||||
obj = bld.create_ns3_program('third-distributed',
|
||||
['point-to-point', 'internet-stack'])
|
||||
obj.source = 'third-distributed.cc'
|
||||
|
||||
obj = bld.create_ns3_program('nms-udp-nix',
|
||||
['point-to-point', 'internet-stack'])
|
||||
obj.source = 'nms-udp-nix.cc'
|
||||
@@ -268,6 +268,15 @@ Buffer::Buffer (uint32_t dataSize)
|
||||
Initialize (dataSize);
|
||||
}
|
||||
|
||||
Buffer::Buffer (uint32_t dataSize, bool initialize)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << dataSize << initialize);
|
||||
if (initialize == true)
|
||||
{
|
||||
Initialize (dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Buffer::CheckInternalState (void) const
|
||||
{
|
||||
@@ -667,6 +676,139 @@ Buffer::CreateFullCopy (void) const
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Buffer::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
|
||||
uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
|
||||
|
||||
// total size 4-bytes for dataStart length
|
||||
// + X number of bytes for dataStart
|
||||
// + 4-bytes for dataEnd length
|
||||
// + X number of bytes for dataEnd
|
||||
uint32_t sz = sizeof (uint32_t)
|
||||
+ sizeof (uint32_t)
|
||||
+ dataStart
|
||||
+ sizeof (uint32_t)
|
||||
+ dataEnd;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
uint32_t* p = (uint32_t*)buffer;
|
||||
uint32_t size = 0;
|
||||
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Add the zero data length
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
*p++ = m_zeroAreaEnd - m_zeroAreaStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add the length of actual start data
|
||||
uint32_t dataStartLength = m_zeroAreaStart - m_start;
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
*p++ = dataStartLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add the actual data
|
||||
if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
|
||||
{
|
||||
size += (dataStartLength + 3) & (~3);
|
||||
memcpy(p, m_data->m_data + m_start, dataStartLength);
|
||||
p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add the length of the actual end data
|
||||
uint32_t dataEndLength = m_end - m_zeroAreaEnd;
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
*p++ = dataEndLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add the actual data
|
||||
if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
|
||||
{
|
||||
size += (dataEndLength + 3) & (~3);
|
||||
memcpy(p, m_data->m_data+m_zeroAreaStart,dataEndLength);
|
||||
p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Serialzed everything successfully
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Buffer::Deserialize (uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
uint32_t* p = (uint32_t*)buffer;
|
||||
uint32_t sizeCheck = size-4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t zeroDataLength = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
// Create zero bytes
|
||||
Initialize (zeroDataLength);
|
||||
|
||||
// Add start data
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t dataStartLength = *p++;
|
||||
sizeCheck -= 4;
|
||||
AddAtStart (dataStartLength);
|
||||
|
||||
NS_ASSERT (sizeCheck >= dataStartLength);
|
||||
Begin ().Write ((uint8_t*)p, dataStartLength);
|
||||
p += (((dataStartLength+3)&(~3))/4);
|
||||
sizeCheck -= ((dataStartLength+3)&(~3));
|
||||
|
||||
// Add end data
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t dataEndLength = *p++;
|
||||
sizeCheck -= 4;
|
||||
AddAtEnd (dataEndLength);
|
||||
|
||||
NS_ASSERT (sizeCheck >= dataEndLength);
|
||||
Buffer::Iterator tmp = End ();
|
||||
tmp.Prev (dataEndLength);
|
||||
tmp.Write ((uint8_t*)p, dataEndLength);
|
||||
p += (((dataEndLength+3)&(~3))/4);
|
||||
sizeCheck -= ((dataEndLength+3)&(~3));
|
||||
|
||||
NS_ASSERT (sizeCheck == 0);
|
||||
// return zero if buffer did not
|
||||
// contain a complete message
|
||||
return (sizeCheck != 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Buffer::GetCurrentStartOffset (void) const
|
||||
{
|
||||
|
||||
@@ -476,6 +476,33 @@ public:
|
||||
|
||||
Buffer CreateFullCopy (void) const;
|
||||
|
||||
/**
|
||||
* \return the number of bytes required for serialization
|
||||
*/
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
|
||||
/**
|
||||
* \return zero if buffer not large enough
|
||||
* \param buffer points to serialization buffer
|
||||
* \param maxSize max number of bytes to write
|
||||
*
|
||||
* This buffer's contents are serialized into the raw
|
||||
* character buffer parameter. Note: The zero length
|
||||
* data is not copied entirely. Only the length of
|
||||
* zero byte data is serialized.
|
||||
*/
|
||||
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
|
||||
/**
|
||||
* \return zero if a complete buffer is not deserialized
|
||||
* \param buffer points to buffer for deserialization
|
||||
* \param size number of bytes to deserialize
|
||||
*
|
||||
* The raw character buffer is deserialized and all the
|
||||
* data is placed into this buffer.
|
||||
*/
|
||||
uint32_t Deserialize (uint8_t* buffer, uint32_t size);
|
||||
|
||||
int32_t GetCurrentStartOffset (void) const;
|
||||
int32_t GetCurrentEndOffset (void) const;
|
||||
|
||||
@@ -493,6 +520,7 @@ public:
|
||||
Buffer &operator = (Buffer const &o);
|
||||
Buffer ();
|
||||
Buffer (uint32_t dataSize);
|
||||
Buffer (uint32_t dataSize, bool initialize);
|
||||
~Buffer ();
|
||||
private:
|
||||
|
||||
|
||||
@@ -222,74 +222,105 @@ NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
|
||||
uint32_t
|
||||
NixVector::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t totalSizeInBytes;
|
||||
uint32_t totalSizeInBytes = 0;
|
||||
totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
|
||||
sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
|
||||
|
||||
// add four to this to account
|
||||
// for the nix-vector length
|
||||
// entry
|
||||
return totalSizeInBytes+4;
|
||||
}
|
||||
|
||||
void
|
||||
NixVector::Serialize (Buffer::Iterator i, uint32_t size) const
|
||||
{
|
||||
uint32_t bytesWritten = 0;
|
||||
|
||||
i.WriteU32 (size);
|
||||
bytesWritten += 4;
|
||||
|
||||
i.WriteU32 (m_used);
|
||||
bytesWritten += 4;
|
||||
|
||||
i.WriteU32 (m_currentVectorBitSize);
|
||||
bytesWritten += 4;
|
||||
|
||||
i.WriteU32 (m_totalBitSize);
|
||||
bytesWritten += 4;
|
||||
|
||||
for (uint32_t j = 0; j < m_nixVector.size (); j++)
|
||||
{
|
||||
i.WriteU32 (m_nixVector.at(j));
|
||||
bytesWritten += 4;
|
||||
}
|
||||
|
||||
NS_ASSERT (bytesWritten == size);
|
||||
return totalSizeInBytes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NixVector::Deserialize (Buffer::Iterator i)
|
||||
NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint32_t totalSize = i.ReadU32 ();
|
||||
uint32_t size = totalSize;
|
||||
size -= 4;
|
||||
uint32_t* p = buffer;
|
||||
uint32_t size = 0;
|
||||
|
||||
NS_ASSERT (size >= 4);
|
||||
m_used = i.ReadU32 ();
|
||||
size -=4;
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
// grab number of used bits
|
||||
*p++ = m_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_ASSERT (size >= 4);
|
||||
m_currentVectorBitSize = i.ReadU32 ();
|
||||
size -=4;
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
// grab number of current used bits
|
||||
// for the front vector
|
||||
*p++ = m_currentVectorBitSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_ASSERT (size >= 4);
|
||||
m_totalBitSize = i.ReadU32 ();
|
||||
size -=4;
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
// grab total bit size
|
||||
*p++ = m_totalBitSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for (uint32_t j = 0; j < m_nixVector.size (); j++)
|
||||
{
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
*p++ = m_nixVector.at(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Serialized successfully
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NixVector::Deserialize (uint32_t* buffer, uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint32_t* p = buffer;
|
||||
uint32_t sizeCheck = size - 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
m_used = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
m_currentVectorBitSize = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
m_totalBitSize = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
// make sure the nix-vector
|
||||
// is empty
|
||||
m_nixVector.clear ();
|
||||
while (size > 0)
|
||||
while (sizeCheck > 0)
|
||||
{
|
||||
NS_ASSERT (size >= 4);
|
||||
m_nixVector.push_back (i.ReadU32 ());
|
||||
size -=4;
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t nix = *p++;
|
||||
m_nixVector.push_back (nix);
|
||||
sizeCheck -= 4;
|
||||
}
|
||||
|
||||
NS_ASSERT (size == 0);
|
||||
return totalSize;
|
||||
NS_ASSERT (sizeCheck == 0);
|
||||
|
||||
// return zero if an entire nix-vector was
|
||||
// not deserialized
|
||||
return (sizeCheck != 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -105,17 +105,27 @@ class NixVector : public Object
|
||||
*/
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
/**
|
||||
* \param i Buffer iterator for writing
|
||||
* \return zero if buffer not large enough
|
||||
*
|
||||
* \param size number of bytes to write
|
||||
* \param buffer points to serialization buffer
|
||||
*
|
||||
* \param maxSize max number of bytes to write
|
||||
*
|
||||
* This nix-vector is serialized into the raw character
|
||||
* buffer parameter.
|
||||
*/
|
||||
void Serialize (Buffer::Iterator i, uint32_t size) const;
|
||||
uint32_t Serialize (uint32_t* buffer, uint32_t maxSize) const;
|
||||
/**
|
||||
* \return the number of bytes deserialized
|
||||
* \return zero if a complete nix-vector is not deserialized
|
||||
*
|
||||
* \param i Buffer iterator for reading
|
||||
* \param buffer points to buffer for deserialization
|
||||
*
|
||||
* \param size number of bytes to deserialize
|
||||
*
|
||||
* The raw character buffer containing all the nix-vector
|
||||
* information is deserialized into this nix-vector.
|
||||
*/
|
||||
uint32_t Deserialize (Buffer::Iterator i);
|
||||
uint32_t Deserialize (uint32_t* buffer, uint32_t size);
|
||||
/**
|
||||
* \return number of bits of numberOfNeighbors
|
||||
*
|
||||
|
||||
@@ -353,42 +353,43 @@ PacketMetadataTest::CheckHistory (Ptr<Packet> p, const char *file, int line, uin
|
||||
return false;
|
||||
}
|
||||
|
||||
#define ADD_HEADER(p, n) \
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
p->AddHeader (header); \
|
||||
#define ADD_HEADER(p, n) \
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
p->AddHeader (header); \
|
||||
}
|
||||
#define ADD_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
p->AddTrailer (trailer); \
|
||||
#define ADD_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
p->AddTrailer (trailer); \
|
||||
}
|
||||
#define REM_HEADER(p, n) \
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
p->RemoveHeader (header); \
|
||||
#define REM_HEADER(p, n) \
|
||||
{ \
|
||||
HistoryHeader<n> header; \
|
||||
p->RemoveHeader (header); \
|
||||
}
|
||||
#define REM_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
p->RemoveTrailer (trailer); \
|
||||
#define REM_TRAILER(p, n) \
|
||||
{ \
|
||||
HistoryTrailer<n> trailer; \
|
||||
p->RemoveTrailer (trailer); \
|
||||
}
|
||||
#define CHECK_HISTORY(p, ...) \
|
||||
{ \
|
||||
if (!CheckHistory (p, __FILE__, \
|
||||
__LINE__, __VA_ARGS__)) \
|
||||
{ \
|
||||
result = false; \
|
||||
} \
|
||||
Buffer buffer; \
|
||||
buffer = p->Serialize (); \
|
||||
Ptr<Packet> otherPacket = Create<Packet> ();\
|
||||
otherPacket->Deserialize (buffer); \
|
||||
if (!CheckHistory (otherPacket, __FILE__, \
|
||||
__LINE__, __VA_ARGS__)) \
|
||||
{ \
|
||||
result = false; \
|
||||
} \
|
||||
#define CHECK_HISTORY(p, ...) \
|
||||
{ \
|
||||
if (!CheckHistory (p, __FILE__, \
|
||||
__LINE__, __VA_ARGS__)) \
|
||||
{ \
|
||||
result = false; \
|
||||
} \
|
||||
uint32_t size = p->GetSerializedSize (); \
|
||||
uint8_t* buffer = new uint8_t[size]; \
|
||||
p->Serialize (buffer, size); \
|
||||
Ptr<Packet> otherPacket = Create<Packet> (buffer, size, true); \
|
||||
delete [] buffer; \
|
||||
if (!CheckHistory (otherPacket, __FILE__, \
|
||||
__LINE__, __VA_ARGS__)) \
|
||||
{ \
|
||||
result = false; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@@ -413,6 +414,7 @@ PacketMetadataTest::DoRun (void)
|
||||
ADD_TRAILER (p, 100);
|
||||
CHECK_HISTORY (p, 2, 10, 100);
|
||||
|
||||
|
||||
p = Create<Packet> (10);
|
||||
ADD_HEADER (p, 1);
|
||||
ADD_HEADER (p, 2);
|
||||
|
||||
@@ -959,7 +959,7 @@ PacketMetadata::GetTotalSize (void) const
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
uint64_t
|
||||
PacketMetadata::GetUid (void) const
|
||||
{
|
||||
return m_packetUid;
|
||||
@@ -1055,11 +1055,18 @@ PacketMetadata::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint32_t totalSize = 0;
|
||||
totalSize += 4;
|
||||
|
||||
// add 8 bytes for the packet uid
|
||||
totalSize += 8;
|
||||
|
||||
// if packet-metadata not enabled, total size
|
||||
// is simply 4-bytes for itself plus 8-bytes
|
||||
// for packet uid
|
||||
if (!m_enable)
|
||||
{
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
struct PacketMetadata::SmallItem item;
|
||||
struct PacketMetadata::ExtraItem extraItem;
|
||||
uint32_t current = m_head;
|
||||
@@ -1077,7 +1084,7 @@ PacketMetadata::GetSerializedSize (void) const
|
||||
tid.SetUid (uid);
|
||||
totalSize += 4 + tid.GetName ().size ();
|
||||
}
|
||||
totalSize += 1 + 4 + 2 + 4 + 4 + 4;
|
||||
totalSize += 1 + 4 + 2 + 4 + 4 + 8;
|
||||
if (current == m_tail)
|
||||
{
|
||||
break;
|
||||
@@ -1087,52 +1094,95 @@ PacketMetadata::GetSerializedSize (void) const
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
void
|
||||
PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
|
||||
|
||||
uint32_t
|
||||
PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint32_t bytesWritten = 0;
|
||||
i.WriteU32 (size);
|
||||
bytesWritten += 4;
|
||||
uint8_t* start = buffer;
|
||||
|
||||
buffer = AddToRawU64 (m_packetUid, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct PacketMetadata::SmallItem item;
|
||||
struct PacketMetadata::ExtraItem extraItem;
|
||||
uint32_t current = m_head;
|
||||
while (current != 0xffff)
|
||||
{
|
||||
ReadItems (current, &item, &extraItem);
|
||||
NS_LOG_LOGIC ("bytesWritten=" << bytesWritten << ", typeUid="<<
|
||||
NS_LOG_LOGIC ("bytesWritten=" << (uint32_t)(buffer - start) << ", typeUid="<<
|
||||
item.typeUid << ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
|
||||
", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
|
||||
extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
|
||||
|
||||
uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
|
||||
if (uid != 0)
|
||||
{
|
||||
TypeId tid;
|
||||
tid.SetUid (uid);
|
||||
std::string uidString = tid.GetName ();
|
||||
i.WriteU32 (uidString.size ());
|
||||
bytesWritten += 4;
|
||||
i.Write ((uint8_t *)uidString.c_str (), uidString.size ());
|
||||
bytesWritten += uidString.size ();
|
||||
uint32_t uidStringSize = uidString.size ();
|
||||
buffer = AddToRawU32 (uidStringSize, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
buffer = AddToRaw ((uint8_t *)uidString.c_str (),
|
||||
uidStringSize, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i.WriteU32 (0);
|
||||
bytesWritten += 4;
|
||||
buffer = AddToRawU32 (0, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t isBig = item.typeUid & 0x1;
|
||||
i.WriteU8 (isBig);
|
||||
bytesWritten += 1;
|
||||
i.WriteU32 (item.size);
|
||||
bytesWritten += 4;
|
||||
i.WriteU16 (item.chunkUid);
|
||||
bytesWritten += 2;
|
||||
i.WriteU32 (extraItem.fragmentStart);
|
||||
bytesWritten += 4;
|
||||
i.WriteU32 (extraItem.fragmentEnd);
|
||||
bytesWritten += 4;
|
||||
i.WriteU32 (extraItem.packetUid);
|
||||
bytesWritten += 4;
|
||||
buffer = AddToRawU8 (isBig, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = AddToRawU32 (item.size, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = AddToRawU16 (item.chunkUid, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = AddToRawU32 (extraItem.fragmentStart, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = AddToRawU32 (extraItem.fragmentEnd, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = AddToRawU64 (extraItem.packetUid, start, buffer, maxSize);
|
||||
if (buffer == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current == m_tail)
|
||||
{
|
||||
break;
|
||||
@@ -1141,21 +1191,28 @@ PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
|
||||
NS_ASSERT (current != item.next);
|
||||
current = item.next;
|
||||
}
|
||||
NS_ASSERT (bytesWritten == size);
|
||||
|
||||
NS_ASSERT ((uint32_t)(buffer - start) == maxSize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PacketMetadata::Deserialize (Buffer::Iterator i)
|
||||
PacketMetadata::Deserialize (uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint8_t* start = buffer;
|
||||
uint32_t desSize = size - 4;
|
||||
|
||||
buffer = ReadFromRawU64 (m_packetUid, start, buffer, size);
|
||||
desSize -= 8;
|
||||
|
||||
struct PacketMetadata::SmallItem item;
|
||||
struct PacketMetadata::ExtraItem extraItem;
|
||||
uint32_t totalSize = i.ReadU32 ();
|
||||
uint32_t size = totalSize;
|
||||
size -= 4;
|
||||
while (size > 0)
|
||||
while (desSize > 0)
|
||||
{
|
||||
uint32_t uidStringSize = i.ReadU32 ();
|
||||
size -= 4;
|
||||
uint32_t uidStringSize = 0;
|
||||
buffer = ReadFromRawU32 (uidStringSize, start, buffer, size);
|
||||
desSize -= 4;
|
||||
uint32_t uid;
|
||||
if (uidStringSize == 0)
|
||||
{
|
||||
@@ -1167,25 +1224,28 @@ PacketMetadata::Deserialize (Buffer::Iterator i)
|
||||
std::string uidString;
|
||||
for (uint32_t j = 0; j < uidStringSize; j++)
|
||||
{
|
||||
uidString.push_back (i.ReadU8 ());
|
||||
size --;
|
||||
uint8_t ch = 0;
|
||||
buffer = ReadFromRawU8 (ch, start, buffer, size);
|
||||
uidString.push_back (ch);
|
||||
desSize --;
|
||||
}
|
||||
TypeId tid = TypeId::LookupByName (uidString);
|
||||
uid = tid.GetUid ();
|
||||
}
|
||||
uint8_t isBig = i.ReadU8 ();
|
||||
size --;
|
||||
uint8_t isBig = 0;
|
||||
buffer = ReadFromRawU8 (isBig, start, buffer, size);
|
||||
desSize --;
|
||||
item.typeUid = (uid << 1) | isBig;
|
||||
item.size = i.ReadU32 ();
|
||||
size -= 4;
|
||||
item.chunkUid = i.ReadU16 ();
|
||||
size -= 2;
|
||||
extraItem.fragmentStart = i.ReadU32 ();
|
||||
size -= 4;
|
||||
extraItem.fragmentEnd = i.ReadU32 ();
|
||||
size -= 4;
|
||||
extraItem.packetUid = i.ReadU32 ();
|
||||
size -= 4;
|
||||
buffer = ReadFromRawU32 (item.size, start, buffer, size);
|
||||
desSize -= 4;
|
||||
buffer = ReadFromRawU16 (item.chunkUid, start, buffer, size);
|
||||
desSize -= 2;
|
||||
buffer = ReadFromRawU32 (extraItem.fragmentStart, start, buffer, size);
|
||||
desSize -= 4;
|
||||
buffer = ReadFromRawU32 (extraItem.fragmentEnd, start, buffer, size);
|
||||
desSize -= 4;
|
||||
buffer = ReadFromRawU64 (extraItem.packetUid, start, buffer, size);
|
||||
desSize -= 8;
|
||||
NS_LOG_LOGIC ("size=" << size << ", typeUid="<<item.typeUid <<
|
||||
", size="<<item.size<<", chunkUid="<<item.chunkUid<<
|
||||
", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
|
||||
@@ -1193,8 +1253,144 @@ PacketMetadata::Deserialize (Buffer::Iterator i)
|
||||
uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
|
||||
UpdateTail (tmp);
|
||||
}
|
||||
NS_ASSERT (size == 0);
|
||||
return totalSize;
|
||||
NS_ASSERT (desSize == 0);
|
||||
return (desSize !=0) ? 0 : 1;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::AddToRawU8 (const uint8_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer overflow
|
||||
if ((uint32_t)((current + sizeof (uint8_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy (current, &data, sizeof (uint8_t));
|
||||
return current + sizeof (uint8_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::AddToRawU16 (const uint16_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer overflow
|
||||
if ((uint32_t)((current + sizeof (uint16_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy (current, &data, sizeof (uint16_t));
|
||||
return current + sizeof (uint16_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::AddToRawU32 (const uint32_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer overflow
|
||||
if ((uint32_t)((current + sizeof (uint32_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy (current, &data, sizeof (uint32_t));
|
||||
return current + sizeof (uint32_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::AddToRawU64 (const uint64_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer overflow
|
||||
if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy (current, &data, sizeof (uint64_t));
|
||||
return current + sizeof (uint64_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::AddToRaw (const uint8_t* data,
|
||||
uint32_t dataSize,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer overflow
|
||||
if ((uint32_t)((current + dataSize - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy (current, data, dataSize);
|
||||
return current + dataSize;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::ReadFromRawU8 (uint8_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer underflow
|
||||
if ((uint32_t)((current + sizeof (uint8_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(&data, current, sizeof (uint8_t));
|
||||
return current + sizeof (uint8_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::ReadFromRawU16 (uint16_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer underflow
|
||||
if ((uint32_t)((current + sizeof (uint16_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(&data, current, sizeof (uint16_t));
|
||||
return current + sizeof (uint16_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::ReadFromRawU32 (uint32_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer underflow
|
||||
if ((uint32_t)((current + sizeof (uint32_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(&data, current, sizeof (uint32_t));
|
||||
return current + sizeof (uint32_t);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
PacketMetadata::ReadFromRawU64 (uint64_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize)
|
||||
{
|
||||
// First check buffer underflow
|
||||
if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(&data, current, sizeof (uint64_t));
|
||||
return current + sizeof (uint64_t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
static void Enable (void);
|
||||
static void EnableChecking (void);
|
||||
|
||||
inline PacketMetadata (uint32_t uid, uint32_t size);
|
||||
inline PacketMetadata (uint64_t uid, uint32_t size);
|
||||
inline PacketMetadata (PacketMetadata const &o);
|
||||
inline PacketMetadata &operator = (PacketMetadata const& o);
|
||||
inline ~PacketMetadata ();
|
||||
@@ -151,15 +151,63 @@ public:
|
||||
void RemoveAtStart (uint32_t start);
|
||||
void RemoveAtEnd (uint32_t end);
|
||||
|
||||
uint32_t GetUid (void) const;
|
||||
uint64_t GetUid (void) const;
|
||||
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
void Serialize (Buffer::Iterator i, uint32_t size) const;
|
||||
uint32_t Deserialize (Buffer::Iterator i);
|
||||
|
||||
ItemIterator BeginItem (Buffer buffer) const;
|
||||
|
||||
// Serialization to/from raw uint8_t*
|
||||
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
uint32_t Deserialize (uint8_t* buffer, uint32_t size);
|
||||
|
||||
private:
|
||||
// Helper for the raw serilization/deserialization
|
||||
static uint8_t* AddToRawU8 (const uint8_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* AddToRawU16 (const uint16_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* AddToRawU32 (const uint32_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* AddToRawU64 (const uint64_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* AddToRaw (const uint8_t* data,
|
||||
uint32_t dataSize,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* ReadFromRawU8 (uint8_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* ReadFromRawU16 (uint16_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* ReadFromRawU32 (uint32_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
|
||||
static uint8_t* ReadFromRawU64 (uint64_t& data,
|
||||
uint8_t* start,
|
||||
uint8_t* current,
|
||||
uint32_t maxSize);
|
||||
struct Data {
|
||||
/* number of references to this struct Data instance. */
|
||||
uint16_t m_count;
|
||||
@@ -231,9 +279,9 @@ private:
|
||||
/* the packetUid of the packet in which this header or trailer
|
||||
was first added. It could be different from the m_packetUid
|
||||
field if the user has aggregated multiple packets into one.
|
||||
stored as a fixed-size 32 bit integer.
|
||||
stored as a fixed-size 64 bit integer.
|
||||
*/
|
||||
uint32_t packetUid;
|
||||
uint64_t packetUid;
|
||||
};
|
||||
|
||||
class DataFreeList : public std::vector<struct Data *>
|
||||
@@ -297,15 +345,15 @@ private:
|
||||
uint16_t m_head;
|
||||
uint16_t m_tail;
|
||||
uint16_t m_used;
|
||||
uint32_t m_packetUid;
|
||||
uint64_t m_packetUid;
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
PacketMetadata::PacketMetadata (uint32_t uid, uint32_t size)
|
||||
: m_data (PacketMetadata::Create (10)),
|
||||
PacketMetadata::PacketMetadata (uint64_t uid, uint32_t size)
|
||||
: m_data (m_data = PacketMetadata::Create (10)),
|
||||
m_head (0xffff),
|
||||
m_tail (0xffff),
|
||||
m_used (0),
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "packet.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/test.h"
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
@@ -125,7 +126,7 @@ Packet::Packet ()
|
||||
: m_buffer (),
|
||||
m_byteTagList (),
|
||||
m_packetTagList (),
|
||||
m_metadata (m_globalUid, 0),
|
||||
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, 0),
|
||||
m_nixVector (0)
|
||||
{
|
||||
m_globalUid++;
|
||||
@@ -161,16 +162,27 @@ Packet::Packet (uint32_t size)
|
||||
: m_buffer (size),
|
||||
m_byteTagList (),
|
||||
m_packetTagList (),
|
||||
m_metadata (m_globalUid, size),
|
||||
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, size),
|
||||
m_nixVector (0)
|
||||
{
|
||||
m_globalUid++;
|
||||
}
|
||||
Packet::Packet (uint8_t const *buffer, uint32_t size, bool magic)
|
||||
: m_buffer (0, false),
|
||||
m_byteTagList (),
|
||||
m_packetTagList (),
|
||||
m_metadata (0,0),
|
||||
m_nixVector (0)
|
||||
{
|
||||
NS_ASSERT (magic);
|
||||
Deserialize (buffer, size);
|
||||
}
|
||||
|
||||
Packet::Packet (uint8_t const*buffer, uint32_t size)
|
||||
: m_buffer (),
|
||||
m_byteTagList (),
|
||||
m_packetTagList (),
|
||||
m_metadata (m_globalUid, size),
|
||||
m_metadata ((uint64_t)Simulator::GetSystemId () << 32 | m_globalUid, size),
|
||||
m_nixVector (0)
|
||||
{
|
||||
m_globalUid++;
|
||||
@@ -359,7 +371,7 @@ Packet::CopyData(std::ostream *os, uint32_t size) const
|
||||
return m_buffer.CopyData (os, size);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
uint64_t
|
||||
Packet::GetUid (void) const
|
||||
{
|
||||
return m_metadata.GetUid ();
|
||||
@@ -532,48 +544,197 @@ Packet::EnableChecking (void)
|
||||
PacketMetadata::EnableChecking ();
|
||||
}
|
||||
|
||||
Buffer
|
||||
Packet::Serialize (void) const
|
||||
uint32_t Packet::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Buffer buffer;
|
||||
uint32_t reserve;
|
||||
uint32_t size = 0;
|
||||
|
||||
// write metadata
|
||||
reserve = m_metadata.GetSerializedSize ();
|
||||
buffer.AddAtStart (reserve);
|
||||
m_metadata.Serialize (buffer.Begin (), reserve);
|
||||
if (m_nixVector)
|
||||
{
|
||||
// increment total size by the size of the nix-vector
|
||||
// ensuring 4-byte boundary
|
||||
size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
|
||||
|
||||
// write tags
|
||||
// add 4-bytes for entry of total length of nix-vector
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no nix-vector, still have to add 4-bytes
|
||||
// to account for the entry of total size for
|
||||
// nix-vector in the buffer
|
||||
size += 4;
|
||||
}
|
||||
|
||||
//Tag size
|
||||
//XXX
|
||||
//reserve = m_tags.GetSerializedSize ();
|
||||
//buffer.AddAtStart (reserve);
|
||||
//m_tags.Serialize (buffer.Begin (), reserve);
|
||||
|
||||
// aggregate byte buffer, metadata, and tags
|
||||
Buffer tmp = m_buffer.CreateFullCopy ();
|
||||
tmp.AddAtEnd (buffer);
|
||||
|
||||
// write byte buffer size.
|
||||
tmp.AddAtStart (4);
|
||||
tmp.Begin ().WriteU32 (m_buffer.GetSize ());
|
||||
//size += m_tags.GetSerializedSize ();
|
||||
|
||||
return tmp;
|
||||
// increment total size by size of meta-data
|
||||
// ensuring 4-byte boundary
|
||||
size += ((m_metadata.GetSerializedSize () + 3) & (~3));
|
||||
|
||||
// add 4-bytes for entry of total length of meta-data
|
||||
size += 4;
|
||||
|
||||
// increment total size by size of buffer
|
||||
// ensuring 4-byte boundary
|
||||
size += ((m_buffer.GetSerializedSize () + 3) & (~3));
|
||||
|
||||
// add 4-bytes for entry of total length of buffer
|
||||
size += 4;
|
||||
|
||||
return size;
|
||||
}
|
||||
void
|
||||
Packet::Deserialize (Buffer buffer)
|
||||
|
||||
uint32_t
|
||||
Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
uint32_t* p = (uint32_t*)buffer;
|
||||
uint32_t size = 0;
|
||||
|
||||
// if nix-vector exists, serialize it
|
||||
if (m_nixVector)
|
||||
{
|
||||
uint32_t nixSize = m_nixVector->GetSerializedSize ();
|
||||
if (size + nixSize <= maxSize)
|
||||
{
|
||||
// put the total length of nix-vector in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = nixSize + 4;
|
||||
size += nixSize;
|
||||
|
||||
// serialize the nix-vector
|
||||
uint32_t serialized =
|
||||
m_nixVector->Serialize (p, nixSize);
|
||||
if (serialized)
|
||||
{
|
||||
// increment p by nixSize bytes
|
||||
// ensuring 4-byte boundary
|
||||
p += ((nixSize+3) & (~3)) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no nix vector, set zero length,
|
||||
// ie 4-bytes, since it must include
|
||||
// length for itself
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
size += 4;
|
||||
*p++ = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize Tags
|
||||
// XXX
|
||||
|
||||
// Serialize Metadata
|
||||
uint32_t metaSize = m_metadata.GetSerializedSize ();
|
||||
if (size + metaSize <= maxSize)
|
||||
{
|
||||
// put the total length of metadata in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = metaSize + 4;
|
||||
size += metaSize;
|
||||
|
||||
// serialize the metadata
|
||||
uint32_t serialized =
|
||||
m_metadata.Serialize ((uint8_t*)p, metaSize);
|
||||
if (serialized)
|
||||
{
|
||||
// increment p by metaSize bytes
|
||||
// ensuring 4-byte boundary
|
||||
p += ((metaSize+3) & (~3)) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Serialize the packet contents
|
||||
uint32_t bufSize = m_buffer.GetSerializedSize ();
|
||||
if (size + bufSize <= maxSize)
|
||||
{
|
||||
// put the total length of the buffer in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = bufSize + 4;
|
||||
size += bufSize;
|
||||
|
||||
// serialize the buffer
|
||||
uint32_t serialized =
|
||||
m_buffer.Serialize ((uint8_t*)p, bufSize);
|
||||
if (serialized)
|
||||
{
|
||||
// increment p by bufSize bytes
|
||||
// ensuring 4-byte boundary
|
||||
p += ((bufSize+3) & (~3)) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Serialized successfully
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Packet::Deserialize (uint8_t const*buffer, uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Buffer buf = buffer;
|
||||
// read size
|
||||
uint32_t packetSize = buf.Begin ().ReadU32 ();
|
||||
buf.RemoveAtStart (4);
|
||||
|
||||
// read buffer.
|
||||
buf.RemoveAtEnd (buf.GetSize () - packetSize);
|
||||
m_buffer = buf;
|
||||
buffer.RemoveAtStart (4 + packetSize);
|
||||
uint32_t* p = (uint32_t*)buffer;
|
||||
|
||||
// read nix-vector
|
||||
NS_ASSERT (!m_nixVector);
|
||||
uint32_t nixSize = *p++;
|
||||
size -= nixSize;
|
||||
|
||||
// if size less than zero, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= 0);
|
||||
|
||||
if (nixSize > 4)
|
||||
{
|
||||
Ptr<NixVector> nix = CreateObject<NixVector> ();
|
||||
uint32_t nixDeserialized = nix->Deserialize (p, nixSize);
|
||||
if (!nixDeserialized)
|
||||
{
|
||||
// nix-vector not deserialized
|
||||
// completely
|
||||
return 0;
|
||||
}
|
||||
m_nixVector = nix;
|
||||
// increment p by nixSize ensuring
|
||||
// 4-byte boundary
|
||||
p += ((((nixSize - 4) + 3) & (~3)) / 4);
|
||||
}
|
||||
|
||||
// read tags
|
||||
//XXX
|
||||
@@ -581,9 +742,45 @@ Packet::Deserialize (Buffer buffer)
|
||||
//buffer.RemoveAtStart (tagsDeserialized);
|
||||
|
||||
// read metadata
|
||||
uint32_t metaSize = *p++;
|
||||
size -= metaSize;
|
||||
|
||||
// if size less than zero, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= 0);
|
||||
|
||||
uint32_t metadataDeserialized =
|
||||
m_metadata.Deserialize (buffer.Begin ());
|
||||
buffer.RemoveAtStart (metadataDeserialized);
|
||||
m_metadata.Deserialize ((uint8_t*)p, metaSize);
|
||||
if (!metadataDeserialized)
|
||||
{
|
||||
// meta-data not deserialized
|
||||
// completely
|
||||
return 0;
|
||||
}
|
||||
// increment p by metaSize ensuring
|
||||
// 4-byte boundary
|
||||
p += ((((metaSize - 4) + 3) & (~3)) / 4);
|
||||
|
||||
// read buffer contents
|
||||
uint32_t bufSize = *p++;
|
||||
size -= bufSize;
|
||||
|
||||
// if size less than zero, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= 0);
|
||||
|
||||
uint32_t bufferDeserialized =
|
||||
m_buffer.Deserialize ((uint8_t*)p, bufSize);
|
||||
if (!bufferDeserialized)
|
||||
{
|
||||
// buffer not deserialized
|
||||
// completely
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return zero if did not deserialize the
|
||||
// number of expected bytes
|
||||
return (size == 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -221,6 +221,17 @@ public:
|
||||
* \param size the size of the zero-filled payload
|
||||
*/
|
||||
Packet (uint32_t size);
|
||||
/**
|
||||
* Create a new packet from the serialized buffer. This new packet
|
||||
* is identical to the serialized packet contained in the buffer
|
||||
* and is magically deserialized for you
|
||||
*
|
||||
* \param buffer the serialized packet to be created
|
||||
* \param size the size of the packet for deserialization
|
||||
* \param magic allows packet deserialization;
|
||||
* asserts when set to false
|
||||
*/
|
||||
Packet (uint8_t const*buffer, uint32_t size, bool magic);
|
||||
/**
|
||||
* Create a packet with payload filled with the content
|
||||
* of this buffer. The input data is copied: the input
|
||||
@@ -379,7 +390,7 @@ public:
|
||||
* \returns an integer identifier which uniquely
|
||||
* identifies this packet.
|
||||
*/
|
||||
uint32_t GetUid (void) const;
|
||||
uint64_t GetUid (void) const;
|
||||
|
||||
/**
|
||||
* \param os output stream in which the data should be printed.
|
||||
@@ -420,36 +431,24 @@ public:
|
||||
static void EnableChecking (void);
|
||||
|
||||
/**
|
||||
* \returns a byte buffer
|
||||
* For packet serializtion, the total size is checked
|
||||
* in order to determine the size of the buffer
|
||||
* required for serialization
|
||||
*
|
||||
* This method creates a serialized representation of a Packet object
|
||||
* ready to be transmitted over a network to another system. This
|
||||
* serialized representation contains a copy of the packet byte buffer,
|
||||
* the tag list, and the packet metadata (if there is one).
|
||||
*
|
||||
* This method will trigger calls to the Serialize and GetSerializedSize
|
||||
* methods of each tag stored in this packet.
|
||||
*
|
||||
* This method will typically be used by parallel simulations where
|
||||
* the simulated system is partitioned and each partition runs on
|
||||
* a different CPU.
|
||||
* \returns number of bytes required for packet
|
||||
* serialization
|
||||
*/
|
||||
Buffer Serialize (void) const;
|
||||
/**
|
||||
* \param buffer a byte buffer
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
|
||||
/*
|
||||
* \param buffer a raw byte buffer to which the packet will be serialized
|
||||
* \param maxSize the max size of the buffer for bounds checking
|
||||
*
|
||||
* This method reads a byte buffer as created by Packet::Serialize
|
||||
* and restores the state of the Packet to what it was prior to
|
||||
* calling Serialize.
|
||||
* A packet is completely serialized and placed into the raw byte buffer
|
||||
*
|
||||
* This method will trigger calls to the Deserialize method
|
||||
* of each tag stored in this packet.
|
||||
*
|
||||
* This method will typically be used by parallel simulations where
|
||||
* the simulated system is partitioned and each partition runs on
|
||||
* a different CPU.
|
||||
* \returns zero if buffer size was too small
|
||||
*/
|
||||
void Deserialize (Buffer buffer);
|
||||
uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
|
||||
|
||||
/**
|
||||
* \param tag the new tag to add to this packet
|
||||
@@ -556,6 +555,9 @@ public:
|
||||
private:
|
||||
Packet (const Buffer &buffer, const ByteTagList &byteTagList,
|
||||
const PacketTagList &packetTagList, const PacketMetadata &metadata);
|
||||
|
||||
uint32_t Deserialize (uint8_t const*buffer, uint32_t size);
|
||||
|
||||
Buffer m_buffer;
|
||||
ByteTagList m_byteTagList;
|
||||
PacketTagList m_packetTagList;
|
||||
|
||||
@@ -124,4 +124,30 @@ PointToPointChannel::GetDevice (uint32_t i) const
|
||||
return GetPointToPointDevice (i);
|
||||
}
|
||||
|
||||
Time
|
||||
PointToPointChannel::GetDelay (void) const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
Ptr<PointToPointNetDevice>
|
||||
PointToPointChannel::GetSource (uint32_t i) const
|
||||
{
|
||||
return m_link[i].m_src;
|
||||
}
|
||||
|
||||
Ptr<PointToPointNetDevice>
|
||||
PointToPointChannel::GetDestination (uint32_t i) const
|
||||
{
|
||||
return m_link[i].m_dst;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointChannel::IsInitialized (void) const
|
||||
{
|
||||
NS_ASSERT (m_link[0].m_state != INITIALIZING);
|
||||
NS_ASSERT (m_link[1].m_state != INITIALIZING);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
* \param txTime Transmit time to apply
|
||||
* \returns true if successful (currently always true)
|
||||
*/
|
||||
bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
|
||||
virtual bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
|
||||
|
||||
/**
|
||||
* \brief Get number of devices on this channel
|
||||
@@ -91,6 +91,35 @@ public:
|
||||
*/
|
||||
virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* \brief Get the delay associated with this channel
|
||||
* \returns Time delay
|
||||
*/
|
||||
Time GetDelay (void) const;
|
||||
|
||||
/*
|
||||
* \brief Check to make sure the link is initialized
|
||||
* \returns true if initialized, asserts otherwise
|
||||
*/
|
||||
bool IsInitialized (void) const;
|
||||
|
||||
/*
|
||||
* \brief Get the net-device source
|
||||
* \param i the link requested
|
||||
* \returns Ptr to PointToPointNetDevice source for the
|
||||
* specified link
|
||||
*/
|
||||
Ptr<PointToPointNetDevice> GetSource (uint32_t i) const;
|
||||
|
||||
/*
|
||||
* \brief Get the net-device destination
|
||||
* \param i the link requested
|
||||
* \returns Ptr to PointToPointNetDevice destination for
|
||||
* the specifed link
|
||||
*/
|
||||
Ptr<PointToPointNetDevice> GetDestination (uint32_t i) const;
|
||||
|
||||
private:
|
||||
// Each point to point link has exactly two net devices
|
||||
static const int N_DEVICES = 2;
|
||||
|
||||
80
src/devices/point-to-point/point-to-point-remote-channel.cc
Normal file
80
src/devices/point-to-point/point-to-point-remote-channel.cc
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007, 2008 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "point-to-point-remote-channel.h"
|
||||
#include "point-to-point-net-device.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("PointToPointRemoteChannel");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (PointToPointRemoteChannel);
|
||||
|
||||
TypeId
|
||||
PointToPointRemoteChannel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::PointToPointRemoteChannel")
|
||||
.SetParent<PointToPointChannel> ()
|
||||
.AddConstructor<PointToPointRemoteChannel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
PointToPointRemoteChannel::PointToPointRemoteChannel ()
|
||||
{
|
||||
}
|
||||
|
||||
PointToPointRemoteChannel::~PointToPointRemoteChannel ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointRemoteChannel::TransmitStart (
|
||||
Ptr<Packet> p,
|
||||
Ptr<PointToPointNetDevice> src,
|
||||
Time txTime)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << p << src);
|
||||
NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
|
||||
|
||||
IsInitialized ();
|
||||
|
||||
uint32_t wire = src == GetSource (0) ? 0 : 1;
|
||||
Ptr<PointToPointNetDevice> dst = GetDestination (wire);
|
||||
|
||||
// Calculate the rxTime (absolute)
|
||||
Time rxTime = Simulator::Now () + txTime + GetDelay ();
|
||||
#ifdef NS3_MPI
|
||||
MpiInterface::SendPacket (p, rxTime, dst->GetNode ()->GetId (), dst->GetIfIndex ());
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
44
src/devices/point-to-point/point-to-point-remote-channel.h
Normal file
44
src/devices/point-to-point/point-to-point-remote-channel.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
// This object connects two point-to-point net devices where at least one
|
||||
// is not local to this simulator object. It simply over-rides the transmit
|
||||
// method and uses an MPI Send operation instead.
|
||||
|
||||
#ifndef POINT_TO_POINT_REMOTE_CHANNEL_H
|
||||
#define POINT_TO_POINT_REMOTE_CHANNEL_H
|
||||
|
||||
#include "point-to-point-channel.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class PointToPointRemoteChannel : public PointToPointChannel
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
PointToPointRemoteChannel ();
|
||||
~PointToPointRemoteChannel ();
|
||||
virtual bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src, Time txTime);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ def build(bld):
|
||||
module.source = [
|
||||
'point-to-point-net-device.cc',
|
||||
'point-to-point-channel.cc',
|
||||
'point-to-point-remote-channel.cc',
|
||||
'point-to-point-test.cc',
|
||||
'ppp-header.cc',
|
||||
]
|
||||
@@ -14,6 +15,7 @@ def build(bld):
|
||||
headers.source = [
|
||||
'point-to-point-net-device.h',
|
||||
'point-to-point-channel.h',
|
||||
'point-to-point-remote-channel.h',
|
||||
'ppp-header.h',
|
||||
]
|
||||
|
||||
|
||||
@@ -97,6 +97,14 @@ NodeContainer::Create (uint32_t n)
|
||||
}
|
||||
}
|
||||
void
|
||||
NodeContainer::Create (uint32_t n, uint32_t systemId)
|
||||
{
|
||||
for (uint32_t i = 0; i < n; i++)
|
||||
{
|
||||
m_nodes.push_back (CreateObject<Node> (systemId));
|
||||
}
|
||||
}
|
||||
void
|
||||
NodeContainer::Add (NodeContainer other)
|
||||
{
|
||||
for (Iterator i = other.Begin (); i != other.End (); i++)
|
||||
|
||||
@@ -236,6 +236,20 @@ public:
|
||||
*/
|
||||
void Create (uint32_t n);
|
||||
|
||||
/**
|
||||
* \brief Create n nodes with specifiec systemId for distributed simulations
|
||||
* and append pointers to them to the end of this NodeContainer.
|
||||
*
|
||||
* Nodes are at the heart of any ns-3 simulation. One of the first tasks that
|
||||
* any simulation needs to do is to create a number of nodes. This method
|
||||
* automates that task, and adds the ability to specifiy systemId for
|
||||
* distributed simulations.
|
||||
*
|
||||
* \param n The number of Nodes to create
|
||||
* \param systemId The system id or rank associated with this node
|
||||
*/
|
||||
void Create (uint32_t n, uint32_t systemId);
|
||||
|
||||
/**
|
||||
* \brief Append the contents of another NodeContainer to the end of
|
||||
* this container.
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-remote-channel.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
|
||||
#include "trace-helper.h"
|
||||
#include "point-to-point-helper.h"
|
||||
@@ -40,6 +42,7 @@ PointToPointHelper::PointToPointHelper ()
|
||||
m_queueFactory.SetTypeId ("ns3::DropTailQueue");
|
||||
m_deviceFactory.SetTypeId ("ns3::PointToPointNetDevice");
|
||||
m_channelFactory.SetTypeId ("ns3::PointToPointChannel");
|
||||
m_remoteChannelFactory.SetTypeId ("ns3::PointToPointRemoteChannel");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -66,6 +69,7 @@ void
|
||||
PointToPointHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
|
||||
{
|
||||
m_channelFactory.Set (n1, v1);
|
||||
m_remoteChannelFactory.Set (n1, v1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -223,7 +227,30 @@ PointToPointHelper::Install (Ptr<Node> a, Ptr<Node> b)
|
||||
b->AddDevice (devB);
|
||||
Ptr<Queue> queueB = m_queueFactory.Create<Queue> ();
|
||||
devB->SetQueue (queueB);
|
||||
Ptr<PointToPointChannel> channel = m_channelFactory.Create<PointToPointChannel> ();
|
||||
// If MPI is enabled, we need to see if both nodes have the same system id
|
||||
// (rank), and the rank is the same as this instance. If both are true,
|
||||
//use a normal p2p channel, otherwise use a remote channel
|
||||
bool useNormalChannel = true;
|
||||
Ptr<PointToPointChannel> channel = 0;
|
||||
if (MpiInterface::IsEnabled())
|
||||
{
|
||||
uint32_t n1SystemId = a->GetSystemId ();
|
||||
uint32_t n2SystemId = b->GetSystemId ();
|
||||
uint32_t currSystemId = MpiInterface::GetSystemId ();
|
||||
if (n1SystemId != currSystemId || n2SystemId != currSystemId)
|
||||
{
|
||||
useNormalChannel = false;
|
||||
}
|
||||
}
|
||||
if (useNormalChannel)
|
||||
{
|
||||
channel = m_channelFactory.Create<PointToPointChannel> ();
|
||||
}
|
||||
else
|
||||
{
|
||||
channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
|
||||
}
|
||||
|
||||
devA->Attach (channel);
|
||||
devB->Attach (channel);
|
||||
container.Add (devA);
|
||||
|
||||
@@ -116,7 +116,9 @@ public:
|
||||
* \param a first node
|
||||
* \param b second node
|
||||
*
|
||||
* Saves you from having to construct a temporary NodeContainer.
|
||||
* Saves you from having to construct a temporary NodeContainer.
|
||||
* Also, if MPI is enabled, for distributed simulations,
|
||||
* appropriate remote point-to-point channels are created.
|
||||
*/
|
||||
NetDeviceContainer Install (Ptr<Node> a, Ptr<Node> b);
|
||||
|
||||
@@ -177,6 +179,7 @@ private:
|
||||
|
||||
ObjectFactory m_queueFactory;
|
||||
ObjectFactory m_channelFactory;
|
||||
ObjectFactory m_remoteChannelFactory;
|
||||
ObjectFactory m_deviceFactory;
|
||||
};
|
||||
|
||||
|
||||
521
src/mpi/distributed-simulator-impl.cc
Normal file
521
src/mpi/distributed-simulator-impl.cc
Normal file
@@ -0,0 +1,521 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
#include "distributed-simulator-impl.h"
|
||||
#include "mpi-interface.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/scheduler.h"
|
||||
#include "ns3/event-impl.h"
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef NS3_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DistributedSimulatorImpl");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (DistributedSimulatorImpl);
|
||||
|
||||
LbtsMessage::~LbtsMessage ()
|
||||
{
|
||||
}
|
||||
|
||||
Time
|
||||
LbtsMessage::GetSmallestTime ()
|
||||
{
|
||||
return m_smallestTime;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
LbtsMessage::GetTxCount ()
|
||||
{
|
||||
return m_txCount;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
LbtsMessage::GetRxCount ()
|
||||
{
|
||||
return m_rxCount;
|
||||
}
|
||||
uint32_t
|
||||
LbtsMessage::GetMyId ()
|
||||
{
|
||||
return m_myId;
|
||||
}
|
||||
|
||||
Time DistributedSimulatorImpl::m_lookAhead = Seconds (0);
|
||||
|
||||
TypeId
|
||||
DistributedSimulatorImpl::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DistributedSimulatorImpl")
|
||||
.SetParent<Object> ()
|
||||
.AddConstructor<DistributedSimulatorImpl> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
DistributedSimulatorImpl::DistributedSimulatorImpl ()
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
m_myId = MpiInterface::GetSystemId ();
|
||||
m_systemCount = MpiInterface::GetSize ();
|
||||
|
||||
// Allocate the LBTS message buffer
|
||||
m_pLBTS = new LbtsMessage[m_systemCount];
|
||||
m_grantedTime = Seconds (0);
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
|
||||
m_stop = false;
|
||||
// uids are allocated from 4.
|
||||
// uid 0 is "invalid" events
|
||||
// uid 1 is "now" events
|
||||
// uid 2 is "destroy" events
|
||||
m_uid = 4;
|
||||
// before ::Run is entered, the m_currentUid will be zero
|
||||
m_currentUid = 0;
|
||||
m_currentTs = 0;
|
||||
m_currentContext = 0xffffffff;
|
||||
m_unscheduledEvents = 0;
|
||||
m_events = 0;
|
||||
}
|
||||
|
||||
DistributedSimulatorImpl::~DistributedSimulatorImpl ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::DoDispose (void)
|
||||
{
|
||||
while (!m_events->IsEmpty ())
|
||||
{
|
||||
Scheduler::Event next = m_events->RemoveNext ();
|
||||
next.impl->Unref ();
|
||||
}
|
||||
m_events = 0;
|
||||
delete [] m_pLBTS;
|
||||
SimulatorImpl::DoDispose ();
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Destroy ()
|
||||
{
|
||||
while (!m_destroyEvents.empty ())
|
||||
{
|
||||
Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
|
||||
m_destroyEvents.pop_front ();
|
||||
NS_LOG_LOGIC ("handle destroy " << ev);
|
||||
if (!ev->IsCancelled ())
|
||||
{
|
||||
ev->Invoke ();
|
||||
}
|
||||
}
|
||||
|
||||
MpiInterface::Destroy ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::CalculateLookAhead (void)
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
if (MpiInterface::GetSize () <= 1)
|
||||
{
|
||||
DistributedSimulatorImpl::m_lookAhead = Seconds (0);
|
||||
m_grantedTime = Seconds (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeContainer c = NodeContainer::GetGlobal ();
|
||||
for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
|
||||
{
|
||||
if ((*iter)->GetSystemId () != MpiInterface::GetSystemId ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < (*iter)->GetNDevices (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> localNetDevice = (*iter)->GetDevice (i);
|
||||
// only works for p2p links currently
|
||||
if (!localNetDevice->IsPointToPoint ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<Channel> channel = localNetDevice->GetChannel ();
|
||||
if (channel == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// grab the adjacent node
|
||||
Ptr<Node> remoteNode;
|
||||
if (channel->GetDevice (0) == localNetDevice)
|
||||
{
|
||||
remoteNode = (channel->GetDevice (1))->GetNode ();
|
||||
}
|
||||
else
|
||||
{
|
||||
remoteNode = (channel->GetDevice (0))->GetNode ();
|
||||
}
|
||||
|
||||
// if it's not remote, don't consider it
|
||||
if (remoteNode->GetSystemId () == MpiInterface::GetSystemId ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// compare delay on the channel with current value of
|
||||
// m_lookAhead. if delay on channel is smaller, make
|
||||
// it the new lookAhead.
|
||||
TimeValue delay;
|
||||
channel->GetAttribute ("Delay", delay);
|
||||
if (DistributedSimulatorImpl::m_lookAhead.IsZero ())
|
||||
{
|
||||
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
|
||||
m_grantedTime = delay.Get ();
|
||||
}
|
||||
if (delay.Get ().GetSeconds () < DistributedSimulatorImpl::m_lookAhead.GetSeconds ())
|
||||
{
|
||||
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
|
||||
m_grantedTime = delay.Get ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
|
||||
{
|
||||
Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
|
||||
|
||||
if (m_events != 0)
|
||||
{
|
||||
while (!m_events->IsEmpty ())
|
||||
{
|
||||
Scheduler::Event next = m_events->RemoveNext ();
|
||||
scheduler->Insert (next);
|
||||
}
|
||||
}
|
||||
m_events = scheduler;
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::ProcessOneEvent (void)
|
||||
{
|
||||
Scheduler::Event next = m_events->RemoveNext ();
|
||||
|
||||
NS_ASSERT (next.key.m_ts >= m_currentTs);
|
||||
m_unscheduledEvents--;
|
||||
|
||||
NS_LOG_LOGIC ("handle " << next.key.m_ts);
|
||||
m_currentTs = next.key.m_ts;
|
||||
m_currentContext = next.key.m_context;
|
||||
m_currentUid = next.key.m_uid;
|
||||
next.impl->Invoke ();
|
||||
next.impl->Unref ();
|
||||
}
|
||||
|
||||
bool
|
||||
DistributedSimulatorImpl::IsFinished (void) const
|
||||
{
|
||||
return m_events->IsEmpty () || m_stop;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
DistributedSimulatorImpl::NextTs (void) const
|
||||
{
|
||||
NS_ASSERT (!m_events->IsEmpty ());
|
||||
Scheduler::Event ev = m_events->PeekNext ();
|
||||
return ev.key.m_ts;
|
||||
}
|
||||
|
||||
Time
|
||||
DistributedSimulatorImpl::Next (void) const
|
||||
{
|
||||
return TimeStep (NextTs ());
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Run (void)
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
CalculateLookAhead ();
|
||||
m_stop = false;
|
||||
while (!m_events->IsEmpty () && !m_stop)
|
||||
{
|
||||
Time nextTime = Next ();
|
||||
if (nextTime > m_grantedTime)
|
||||
{ // Can't process, calculate a new LBTS
|
||||
// First receive any pending messages
|
||||
MpiInterface::ReceiveMessages ();
|
||||
// reset next time
|
||||
nextTime = Next ();
|
||||
// And check for send completes
|
||||
MpiInterface::TestSendComplete ();
|
||||
// Finally calculate the lbts
|
||||
LbtsMessage lMsg (MpiInterface::GetRxCount (), MpiInterface::GetTxCount (), m_myId, nextTime);
|
||||
m_pLBTS[m_myId] = lMsg;
|
||||
MPI_Allgather (&lMsg, sizeof (LbtsMessage), MPI_BYTE, m_pLBTS,
|
||||
sizeof (LbtsMessage), MPI_BYTE, MPI_COMM_WORLD);
|
||||
Time smallestTime = m_pLBTS[0].GetSmallestTime ();
|
||||
// The totRx and totTx counts insure there are no transient
|
||||
// messages; If totRx != totTx, there are transients,
|
||||
// so we don't update the granted time.
|
||||
uint32_t totRx = m_pLBTS[0].GetRxCount ();
|
||||
uint32_t totTx = m_pLBTS[0].GetTxCount ();
|
||||
|
||||
for (uint32_t i = 1; i < m_systemCount; ++i)
|
||||
{
|
||||
if (m_pLBTS[i].GetSmallestTime () < smallestTime)
|
||||
{
|
||||
smallestTime = m_pLBTS[i].GetSmallestTime ();
|
||||
}
|
||||
totRx += m_pLBTS[i].GetRxCount ();
|
||||
totTx += m_pLBTS[i].GetTxCount ();
|
||||
|
||||
}
|
||||
if (totRx == totTx)
|
||||
{
|
||||
m_grantedTime = smallestTime + DistributedSimulatorImpl::m_lookAhead;
|
||||
}
|
||||
}
|
||||
if (nextTime <= m_grantedTime)
|
||||
{ // Save to process
|
||||
ProcessOneEvent ();
|
||||
}
|
||||
}
|
||||
|
||||
// If the simulator stopped naturally by lack of events, make a
|
||||
// consistency test to check that we didn't lose any events along the way.
|
||||
NS_ASSERT (!m_events->IsEmpty () || m_unscheduledEvents == 0);
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t DistributedSimulatorImpl::GetSystemId () const
|
||||
{
|
||||
return m_myId;
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::RunOneEvent (void)
|
||||
{
|
||||
ProcessOneEvent ();
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Stop (void)
|
||||
{
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Stop (Time const &time)
|
||||
{
|
||||
Simulator::Schedule (time, &Simulator::Stop);
|
||||
}
|
||||
|
||||
//
|
||||
// Schedule an event for a _relative_ time in the future.
|
||||
//
|
||||
EventId
|
||||
DistributedSimulatorImpl::Schedule (Time const &time, EventImpl *event)
|
||||
{
|
||||
Time tAbsolute = time + TimeStep (m_currentTs);
|
||||
|
||||
NS_ASSERT (tAbsolute.IsPositive ());
|
||||
NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
|
||||
Scheduler::Event ev;
|
||||
ev.impl = event;
|
||||
ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
|
||||
ev.key.m_context = GetContext ();
|
||||
ev.key.m_uid = m_uid;
|
||||
m_uid++;
|
||||
m_unscheduledEvents++;
|
||||
m_events->Insert (ev);
|
||||
return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << context << time.GetTimeStep () << m_currentTs << event);
|
||||
|
||||
Scheduler::Event ev;
|
||||
ev.impl = event;
|
||||
ev.key.m_ts = m_currentTs + time.GetTimeStep ();
|
||||
ev.key.m_context = context;
|
||||
ev.key.m_uid = m_uid;
|
||||
m_uid++;
|
||||
m_unscheduledEvents++;
|
||||
m_events->Insert (ev);
|
||||
}
|
||||
|
||||
EventId
|
||||
DistributedSimulatorImpl::ScheduleNow (EventImpl *event)
|
||||
{
|
||||
Scheduler::Event ev;
|
||||
ev.impl = event;
|
||||
ev.key.m_ts = m_currentTs;
|
||||
ev.key.m_context = GetContext ();
|
||||
ev.key.m_uid = m_uid;
|
||||
m_uid++;
|
||||
m_unscheduledEvents++;
|
||||
m_events->Insert (ev);
|
||||
return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
|
||||
}
|
||||
|
||||
EventId
|
||||
DistributedSimulatorImpl::ScheduleDestroy (EventImpl *event)
|
||||
{
|
||||
EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
|
||||
m_destroyEvents.push_back (id);
|
||||
m_uid++;
|
||||
return id;
|
||||
}
|
||||
|
||||
Time
|
||||
DistributedSimulatorImpl::Now (void) const
|
||||
{
|
||||
return TimeStep (m_currentTs);
|
||||
}
|
||||
|
||||
Time
|
||||
DistributedSimulatorImpl::GetDelayLeft (const EventId &id) const
|
||||
{
|
||||
if (IsExpired (id))
|
||||
{
|
||||
return TimeStep (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TimeStep (id.GetTs () - m_currentTs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Remove (const EventId &id)
|
||||
{
|
||||
if (id.GetUid () == 2)
|
||||
{
|
||||
// destroy events.
|
||||
for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
|
||||
{
|
||||
if (*i == id)
|
||||
{
|
||||
m_destroyEvents.erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsExpired (id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Scheduler::Event event;
|
||||
event.impl = id.PeekEventImpl ();
|
||||
event.key.m_ts = id.GetTs ();
|
||||
event.key.m_context = id.GetContext ();
|
||||
event.key.m_uid = id.GetUid ();
|
||||
m_events->Remove (event);
|
||||
event.impl->Cancel ();
|
||||
// whenever we remove an event from the event list, we have to unref it.
|
||||
event.impl->Unref ();
|
||||
|
||||
m_unscheduledEvents--;
|
||||
}
|
||||
|
||||
void
|
||||
DistributedSimulatorImpl::Cancel (const EventId &id)
|
||||
{
|
||||
if (!IsExpired (id))
|
||||
{
|
||||
id.PeekEventImpl ()->Cancel ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DistributedSimulatorImpl::IsExpired (const EventId &ev) const
|
||||
{
|
||||
if (ev.GetUid () == 2)
|
||||
{
|
||||
if (ev.PeekEventImpl () == 0
|
||||
|| ev.PeekEventImpl ()->IsCancelled ())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// destroy events.
|
||||
for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
|
||||
{
|
||||
if (*i == ev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (ev.PeekEventImpl () == 0
|
||||
|| ev.GetTs () < m_currentTs
|
||||
|| (ev.GetTs () == m_currentTs
|
||||
&& ev.GetUid () <= m_currentUid)
|
||||
|| ev.PeekEventImpl ()->IsCancelled ())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Time
|
||||
DistributedSimulatorImpl::GetMaximumSimulationTime (void) const
|
||||
{
|
||||
// XXX: I am fairly certain other compilers use other non-standard
|
||||
// post-fixes to indicate 64 bit constants.
|
||||
return TimeStep (0x7fffffffffffffffLL);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
DistributedSimulatorImpl::GetContext (void) const
|
||||
{
|
||||
return m_currentContext;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
124
src/mpi/distributed-simulator-impl.h
Normal file
124
src/mpi/distributed-simulator-impl.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
#ifndef DISTRIBUTED_SIMULATOR_IMPL_H
|
||||
#define DISTRIBUTED_SIMULATOR_IMPL_H
|
||||
|
||||
#include "ns3/simulator-impl.h"
|
||||
#include "ns3/scheduler.h"
|
||||
#include "ns3/event-impl.h"
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// Structure used for all-reduce LBTS computation
|
||||
class LbtsMessage
|
||||
{
|
||||
public:
|
||||
LbtsMessage ()
|
||||
: m_txCount (0),
|
||||
m_rxCount (0),
|
||||
m_myId (0)
|
||||
{
|
||||
}
|
||||
|
||||
LbtsMessage (uint32_t rxc, uint32_t txc, uint32_t id, const Time& t)
|
||||
: m_txCount (txc),
|
||||
m_rxCount (rxc),
|
||||
m_myId (id),
|
||||
m_smallestTime (t)
|
||||
{
|
||||
}
|
||||
|
||||
~LbtsMessage ();
|
||||
|
||||
Time GetSmallestTime ();
|
||||
uint32_t GetTxCount ();
|
||||
uint32_t GetRxCount ();
|
||||
uint32_t GetMyId ();
|
||||
|
||||
private:
|
||||
uint32_t m_txCount;
|
||||
uint32_t m_rxCount;
|
||||
uint32_t m_myId;
|
||||
Time m_smallestTime;
|
||||
};
|
||||
|
||||
class DistributedSimulatorImpl : public SimulatorImpl
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
DistributedSimulatorImpl ();
|
||||
~DistributedSimulatorImpl ();
|
||||
|
||||
virtual void Destroy ();
|
||||
virtual bool IsFinished (void) const;
|
||||
virtual Time Next (void) const;
|
||||
virtual void Stop (void);
|
||||
virtual void Stop (Time const &time);
|
||||
virtual EventId Schedule (Time const &time, EventImpl *event);
|
||||
virtual void ScheduleWithContext (uint32_t context, Time const &time, EventImpl *event);
|
||||
virtual EventId ScheduleNow (EventImpl *event);
|
||||
virtual EventId ScheduleDestroy (EventImpl *event);
|
||||
virtual void Remove (const EventId &ev);
|
||||
virtual void Cancel (const EventId &ev);
|
||||
virtual bool IsExpired (const EventId &ev) const;
|
||||
virtual void Run (void);
|
||||
virtual void RunOneEvent (void);
|
||||
virtual Time Now (void) const;
|
||||
virtual Time GetDelayLeft (const EventId &id) const;
|
||||
virtual Time GetMaximumSimulationTime (void) const;
|
||||
virtual void SetScheduler (ObjectFactory schedulerFactory);
|
||||
virtual uint32_t GetSystemId (void) const;
|
||||
virtual uint32_t GetContext (void) const;
|
||||
|
||||
private:
|
||||
virtual void DoDispose (void);
|
||||
void CalculateLookAhead (void);
|
||||
|
||||
void ProcessOneEvent (void);
|
||||
uint64_t NextTs (void) const;
|
||||
typedef std::list<EventId> DestroyEvents;
|
||||
|
||||
DestroyEvents m_destroyEvents;
|
||||
bool m_stop;
|
||||
Ptr<Scheduler> m_events;
|
||||
uint32_t m_uid;
|
||||
uint32_t m_currentUid;
|
||||
uint64_t m_currentTs;
|
||||
uint32_t m_currentContext;
|
||||
// number of events that have been inserted but not yet scheduled,
|
||||
// not counting the "destroy" events; this is used for validation
|
||||
int m_unscheduledEvents;
|
||||
|
||||
LbtsMessage* m_pLBTS; // Allocated once we know how many systems
|
||||
uint32_t m_myId; // MPI Rank
|
||||
uint32_t m_systemCount; // MPI Size
|
||||
Time m_grantedTime; // Last LBTS
|
||||
static Time m_lookAhead; // Lookahead value
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* DISTRIBUTED_SIMULATOR_IMPL_H */
|
||||
287
src/mpi/mpi-interface.cc
Normal file
287
src/mpi/mpi-interface.cc
Normal file
@@ -0,0 +1,287 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
// This object contains static methods that provide an easy interface
|
||||
// to the necessary MPI information.
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <list>
|
||||
|
||||
#include "mpi-interface.h"
|
||||
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/simulator-impl.h"
|
||||
#include "ns3/nstime.h"
|
||||
|
||||
#ifdef NS3_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
SentBuffer::SentBuffer ()
|
||||
{
|
||||
m_buffer = 0;
|
||||
m_request = 0;
|
||||
}
|
||||
|
||||
SentBuffer::~SentBuffer ()
|
||||
{
|
||||
delete [] m_buffer;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
SentBuffer::GetBuffer ()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void
|
||||
SentBuffer::SetBuffer (uint8_t* buffer)
|
||||
{
|
||||
m_buffer = buffer;
|
||||
}
|
||||
|
||||
#ifdef NS3_MPI
|
||||
MPI_Request*
|
||||
SentBuffer::GetRequest ()
|
||||
{
|
||||
return &m_request;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t MpiInterface::m_sid = 0;
|
||||
uint32_t MpiInterface::m_size = 1;
|
||||
bool MpiInterface::m_initialized = false;
|
||||
bool MpiInterface::m_enabled = false;
|
||||
uint32_t MpiInterface::m_rxCount = 0;
|
||||
uint32_t MpiInterface::m_txCount = 0;
|
||||
std::list<SentBuffer> MpiInterface::m_pendingTx;
|
||||
|
||||
#ifdef NS3_MPI
|
||||
MPI_Request* MpiInterface::m_requests;
|
||||
char** MpiInterface::m_pRxBuffers;
|
||||
#endif
|
||||
|
||||
void
|
||||
MpiInterface::Destroy ()
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
for (uint32_t i = 0; i < GetSize (); ++i)
|
||||
{
|
||||
delete [] m_pRxBuffers[i];
|
||||
}
|
||||
delete [] m_pRxBuffers;
|
||||
delete [] m_requests;
|
||||
|
||||
m_pendingTx.clear ();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MpiInterface::GetRxCount ()
|
||||
{
|
||||
return m_rxCount;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MpiInterface::GetTxCount ()
|
||||
{
|
||||
return m_txCount;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MpiInterface::GetSystemId ()
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
Simulator::GetImplementation ();
|
||||
m_initialized = true;
|
||||
}
|
||||
return m_sid;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MpiInterface::GetSize ()
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
Simulator::GetImplementation ();
|
||||
m_initialized = true;
|
||||
}
|
||||
return m_size;
|
||||
}
|
||||
|
||||
bool
|
||||
MpiInterface::IsEnabled ()
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
Simulator::GetImplementation ();
|
||||
m_initialized = true;
|
||||
}
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void
|
||||
MpiInterface::Enable (int* pargc, char*** pargv)
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
// Initialize the MPI interface
|
||||
MPI_Init (pargc, pargv);
|
||||
MPI_Barrier (MPI_COMM_WORLD);
|
||||
MPI_Comm_rank (MPI_COMM_WORLD, (int*)&m_sid);
|
||||
MPI_Comm_size (MPI_COMM_WORLD, (int*)&m_size);
|
||||
m_enabled = true;
|
||||
m_initialized = true;
|
||||
// Post a non-blocking receive for all peers
|
||||
m_pRxBuffers = new char*[m_size];
|
||||
m_requests = new MPI_Request[m_size];
|
||||
for (uint32_t i = 0; i < GetSize (); ++i)
|
||||
{
|
||||
m_pRxBuffers[i] = new char[MAX_MPI_MSG_SIZE];
|
||||
MPI_Irecv (m_pRxBuffers[i], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
|
||||
MPI_COMM_WORLD, &m_requests[i]);
|
||||
}
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MpiInterface::SendPacket (Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev)
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
SentBuffer sendBuf;
|
||||
m_pendingTx.push_back (sendBuf);
|
||||
std::list<SentBuffer>::reverse_iterator i = m_pendingTx.rbegin (); // Points to the last element
|
||||
|
||||
uint32_t serializedSize = p->GetSerializedSize ();
|
||||
uint8_t* buffer = new uint8_t[serializedSize + 16];
|
||||
i->SetBuffer (buffer);
|
||||
// Add the time, dest node and dest device
|
||||
uint64_t t = rxTime.GetNanoSeconds ();
|
||||
uint64_t* pTime = (uint64_t*)buffer;
|
||||
*pTime++ = t;
|
||||
uint32_t* pData = (uint32_t*)pTime;
|
||||
*pData++ = node;
|
||||
*pData++ = dev;
|
||||
// Serialize the packet
|
||||
p->Serialize ((uint8_t*)pData, serializedSize);
|
||||
|
||||
// Find the system id for the destination node
|
||||
Ptr<Node> destNode = NodeList::GetNode (node);
|
||||
uint32_t nodeSysId = destNode->GetSystemId ();
|
||||
|
||||
MPI_Isend ((void*)i->GetBuffer (), serializedSize + 16, MPI_CHAR, nodeSysId,
|
||||
0, MPI_COMM_WORLD, (i->GetRequest ()));
|
||||
m_txCount++;
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MpiInterface::ReceiveMessages ()
|
||||
{ // Poll the non-block reads to see if data arrived
|
||||
#ifdef NS3_MPI
|
||||
while (true)
|
||||
{
|
||||
int flag = 0;
|
||||
int index = 0;
|
||||
MPI_Status status;
|
||||
|
||||
MPI_Testany (GetSize (), m_requests, &index, &flag, &status);
|
||||
if (!flag)
|
||||
{
|
||||
break; // No more messages
|
||||
}
|
||||
int count;
|
||||
MPI_Get_count (&status, MPI_CHAR, &count);
|
||||
m_rxCount++; // Count this receive
|
||||
|
||||
// Get the meta data first
|
||||
uint64_t* pTime = (uint64_t*)m_pRxBuffers[index];
|
||||
uint64_t nanoSeconds = *pTime++;
|
||||
uint32_t* pData = (uint32_t*)pTime;
|
||||
uint32_t node = *pData++;
|
||||
uint32_t dev = *pData++;
|
||||
|
||||
Time rxTime = NanoSeconds (nanoSeconds);
|
||||
|
||||
count -= sizeof (nanoSeconds) + sizeof (node) + sizeof (dev);
|
||||
|
||||
Ptr<Packet> p = Create<Packet> ((uint8_t*)pData, count, true);
|
||||
|
||||
// Find the correct node/device to schedule receive event
|
||||
Ptr<Node> pNode = NodeList::GetNode (node);
|
||||
uint32_t nDevices = pNode->GetNDevices ();
|
||||
Ptr<PointToPointNetDevice> pDev = 0;
|
||||
for (uint32_t i = 0; i < nDevices; ++i)
|
||||
{
|
||||
Ptr<NetDevice> pThisDev = pNode->GetDevice (i);
|
||||
if (pThisDev->GetIfIndex () == dev)
|
||||
{
|
||||
pDev = DynamicCast<PointToPointNetDevice> (pThisDev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERT (pNode && pDev);
|
||||
|
||||
// Schedule the rx event
|
||||
Simulator::ScheduleWithContext (pNode->GetId (), rxTime - Simulator::Now (),
|
||||
&PointToPointNetDevice::Receive,
|
||||
pDev, p);
|
||||
|
||||
// Re-queue the next read
|
||||
MPI_Irecv (m_pRxBuffers[index], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
|
||||
MPI_COMM_WORLD, &m_requests[index]);
|
||||
}
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MpiInterface::TestSendComplete ()
|
||||
{
|
||||
#ifdef NS3_MPI
|
||||
std::list<SentBuffer>::iterator i = m_pendingTx.begin ();
|
||||
while (i != m_pendingTx.end ())
|
||||
{
|
||||
MPI_Status status;
|
||||
int flag = 0;
|
||||
MPI_Test (i->GetRequest (), &flag, &status);
|
||||
std::list<SentBuffer>::iterator current = i; // Save current for erasing
|
||||
i++; // Advance to next
|
||||
if (flag)
|
||||
{ // This message is complete
|
||||
m_pendingTx.erase (current);
|
||||
}
|
||||
}
|
||||
#else
|
||||
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
85
src/mpi/mpi-interface.h
Normal file
85
src/mpi/mpi-interface.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
// This object contains static methods that provide an easy interface
|
||||
// to the necessary MPI information.
|
||||
|
||||
#ifndef NS3_MPI_INTERFACE_H
|
||||
#define NS3_MPI_INTERFACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/buffer.h"
|
||||
|
||||
struct ompi_request_t;
|
||||
typedef struct ompi_request_t* MPI_Request;
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
const uint32_t MAX_MPI_MSG_SIZE = 2000;
|
||||
// Define a class for tracking the non-block sends
|
||||
class SentBuffer
|
||||
{
|
||||
public:
|
||||
SentBuffer ();
|
||||
~SentBuffer ();
|
||||
|
||||
uint8_t* GetBuffer ();
|
||||
void SetBuffer (uint8_t*);
|
||||
MPI_Request* GetRequest ();
|
||||
|
||||
private:
|
||||
uint8_t* m_buffer;
|
||||
MPI_Request m_request;
|
||||
};
|
||||
|
||||
class Packet;
|
||||
|
||||
class MpiInterface
|
||||
{
|
||||
public:
|
||||
static void Destroy ();
|
||||
static uint32_t GetSystemId (); // Get the MPI Rank (system id)
|
||||
static uint32_t GetSize (); // Get the MPI Size (number of systems)
|
||||
static bool IsEnabled (); // True if using MPI
|
||||
static void Enable (int*, char***); // Called by ns3 main program
|
||||
|
||||
// Serialize and send a packet to the specified node and net device
|
||||
static void SendPacket (Ptr<Packet>, const Time &, uint32_t, uint32_t);
|
||||
static void ReceiveMessages (); // Check for received messages complete
|
||||
static void TestSendComplete (); // Check for completed sends
|
||||
static uint32_t GetRxCount ();
|
||||
static uint32_t GetTxCount ();
|
||||
|
||||
private:
|
||||
static uint32_t m_sid;
|
||||
static uint32_t m_size;
|
||||
static uint32_t m_rxCount; // Total packets received
|
||||
static uint32_t m_txCount; // Total packets sent
|
||||
static bool m_initialized;
|
||||
static bool m_enabled;
|
||||
static MPI_Request* m_requests; // Pending non-blocking receives
|
||||
static char** m_pRxBuffers; // Data buffers for non-blocking reads
|
||||
static std::list<SentBuffer> m_pendingTx; // List of pending non-blocking sends
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* NS3_MPI_INTERFACE_H */
|
||||
1
src/mpi/waf
vendored
Executable file
1
src/mpi/waf
vendored
Executable file
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../../waf "$@"
|
||||
23
src/mpi/wscript
Normal file
23
src/mpi/wscript
Normal file
@@ -0,0 +1,23 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
import sys
|
||||
|
||||
import Options
|
||||
|
||||
|
||||
def build(bld):
|
||||
env = bld.env_of_name('default')
|
||||
sim = bld.create_ns3_module('mpi', ['core', 'simulator'])
|
||||
sim.source = [
|
||||
'distributed-simulator-impl.cc',
|
||||
'mpi-interface.cc',
|
||||
]
|
||||
|
||||
headers = bld.new_task_gen('ns3header')
|
||||
headers.module = 'mpi'
|
||||
headers.source = [
|
||||
'distributed-simulator-impl.h',
|
||||
'mpi-interface.h',
|
||||
]
|
||||
|
||||
if env['ENABLE_MPI']:
|
||||
sim.uselib = 'MPI'
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/ipv4-routing-protocol.h"
|
||||
#include "ns3/ipv4-list-routing.h"
|
||||
#include "ns3/mpi-interface.h"
|
||||
#include "global-router-interface.h"
|
||||
#include "global-route-manager-impl.h"
|
||||
#include "candidate-queue.h"
|
||||
@@ -697,6 +698,13 @@ GlobalRouteManagerImpl::InitializeRoutes ()
|
||||
//
|
||||
Ptr<GlobalRouter> rtr =
|
||||
node->GetObject<GlobalRouter> ();
|
||||
|
||||
// Ignore nodes that are not assigned to our systemId (distributed sim)
|
||||
if (node->GetSystemId () != MpiInterface::GetSystemId ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// if the node has a global router interface, then run the global routing
|
||||
// algorithms.
|
||||
|
||||
@@ -106,6 +106,13 @@ DefaultSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
|
||||
m_events = scheduler;
|
||||
}
|
||||
|
||||
// System ID for non-distributed simulation is always zero
|
||||
uint32_t
|
||||
DefaultSimulatorImpl::GetSystemId (void) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
DefaultSimulatorImpl::ProcessOneEvent (void)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
virtual Time GetDelayLeft (const EventId &id) const;
|
||||
virtual Time GetMaximumSimulationTime (void) const;
|
||||
virtual void SetScheduler (ObjectFactory schedulerFactory);
|
||||
virtual uint32_t GetSystemId (void) const;
|
||||
virtual uint32_t GetContext (void) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -827,6 +827,13 @@ RealtimeSimulatorImpl::GetMaximumSimulationTime (void) const
|
||||
return TimeStep (0x7fffffffffffffffLL);
|
||||
}
|
||||
|
||||
// System ID for non-distributed simulation is always zero
|
||||
uint32_t
|
||||
RealtimeSimulatorImpl::GetSystemId (void) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RealtimeSimulatorImpl::GetContext (void) const
|
||||
{
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
virtual Time GetDelayLeft (const EventId &id) const;
|
||||
virtual Time GetMaximumSimulationTime (void) const;
|
||||
virtual void SetScheduler (ObjectFactory schedulerFactory);
|
||||
virtual uint32_t GetSystemId (void) const;
|
||||
virtual uint32_t GetContext (void) const;
|
||||
|
||||
void ScheduleRealtimeWithContext (uint32_t context, Time const &time, EventImpl *event);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
virtual Time GetDelayLeft (const EventId &id) const = 0;
|
||||
virtual Time GetMaximumSimulationTime (void) const = 0;
|
||||
virtual void SetScheduler (ObjectFactory schedulerFactory) = 0;
|
||||
virtual uint32_t GetSystemId () const = 0;
|
||||
virtual uint32_t GetContext (void) const = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -339,6 +339,21 @@ Simulator::GetContext (void)
|
||||
return GetImpl ()->GetContext ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Simulator::GetSystemId (void)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
if (*PeekImpl () != 0)
|
||||
{
|
||||
return GetImpl ()->GetSystemId ();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Simulator::SetImplementation (Ptr<SimulatorImpl> impl)
|
||||
{
|
||||
|
||||
@@ -770,6 +770,12 @@ public:
|
||||
* to delegate events to their own subclass of the EventImpl base class.
|
||||
*/
|
||||
static EventId ScheduleNow (const Ptr<EventImpl> &event);
|
||||
|
||||
/**
|
||||
* \returns the system id for this simulator; used for
|
||||
* MPI or other distributed simulations
|
||||
*/
|
||||
static uint32_t GetSystemId (void);
|
||||
private:
|
||||
Simulator ();
|
||||
~Simulator ();
|
||||
|
||||
@@ -50,6 +50,7 @@ all_modules = (
|
||||
'contrib/flow-monitor',
|
||||
'applications/udp-client-server',
|
||||
'devices/wimax',
|
||||
'mpi',
|
||||
)
|
||||
|
||||
def set_options(opt):
|
||||
|
||||
25
wscript
25
wscript
@@ -195,6 +195,10 @@ def set_options(opt):
|
||||
help=('Compile NS-3 statically: works only on linux, without python'),
|
||||
dest='enable_static', action='store_true',
|
||||
default=False)
|
||||
opt.add_option('--enable-mpi',
|
||||
help=('Compile NS-3 with MPI and distributed simulation support'),
|
||||
dest='enable_mpi', action='store_true',
|
||||
default=False)
|
||||
opt.add_option('--doxygen-no-build',
|
||||
help=('Run doxygen to generate html documentation from source comments, '
|
||||
'but do not wait for ns-3 to finish the full build.'),
|
||||
@@ -319,6 +323,27 @@ def configure(conf):
|
||||
if Options.options.enable_modules:
|
||||
conf.env['NS3_ENABLED_MODULES'] = ['ns3-'+mod for mod in
|
||||
Options.options.enable_modules.split(',')]
|
||||
# for MPI
|
||||
conf.find_program('mpic++', var='MPI')
|
||||
if Options.options.enable_mpi and conf.env['MPI']:
|
||||
p = subprocess.Popen([conf.env['MPI'], '-showme:compile'], stdout=subprocess.PIPE)
|
||||
flags = p.stdout.read().rstrip().split()
|
||||
p.wait()
|
||||
env.append_value("CXXFLAGS_MPI", flags)
|
||||
|
||||
p = subprocess.Popen([conf.env['MPI'], '-showme:link'], stdout=subprocess.PIPE)
|
||||
flags = p.stdout.read().rstrip().split()
|
||||
p.wait()
|
||||
env.append_value("LINKFLAGS_MPI", flags)
|
||||
|
||||
env.append_value('CXXDEFINES', 'NS3_MPI')
|
||||
conf.report_optional_feature("mpi", "MPI Support", True, '')
|
||||
conf.env['ENABLE_MPI'] = True
|
||||
else:
|
||||
if Options.options.enable_mpi:
|
||||
conf.report_optional_feature("mpi", "MPI Support", False, 'mpic++ not found')
|
||||
else:
|
||||
conf.report_optional_feature("mpi", "MPI Support", False, 'option --enable-mpi not selected')
|
||||
|
||||
# for suid bits
|
||||
conf.find_program('sudo', var='SUDO')
|
||||
|
||||
Reference in New Issue
Block a user