diff --git a/.hgignore b/.hgignore index 58c9dc78f..d5b25104e 100644 --- a/.hgignore +++ b/.hgignore @@ -2,6 +2,8 @@ .*\.o$ .*~$ build-dir +build .*\.sconsign doc/html.* doc/latex.* +.lock-wscript diff --git a/doc/main.txt b/doc/main.txt index e267038ca..c2b398e7f 100644 --- a/doc/main.txt +++ b/doc/main.txt @@ -19,6 +19,7 @@ * - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager * - debugging facilities: \ref debugging, \ref assert, \ref error * - \ref randomvariable + * - \ref config * - a class to handle automatic deletion of multiple sets of objects of different types: * ns3::ObjectContainer * diff --git a/examples/simple-p2p.cc b/examples/simple-p2p.cc index b767febbb..28028aeca 100644 --- a/examples/simple-p2p.cc +++ b/examples/simple-p2p.cc @@ -66,7 +66,6 @@ #include "ns3/trace-root.h" #include "ns3/p2p-topology.h" #include "ns3/onoff-application.h" -#include "ns3/application-list.h" #include "ns3/random-variable.h" using namespace ns3; @@ -132,6 +131,15 @@ int main (int argc, char *argv[]) channel2, n2, Ipv4Address("10.1.3.1"), n3, Ipv4Address("10.1.3.2")); + // Finally, we add static routes. These three steps (Channel and + // NetDevice creation, IP Address assignment, and routing) are + // separated because there may be a need to postpone IP Address + // assignment (emulation) or modify to use dynamic routing + PointToPointTopology::AddIpv4Routes(n0, n2, channel0); + PointToPointTopology::AddIpv4Routes(n1, n2, channel1); + PointToPointTopology::AddIpv4Routes(n2, n3, channel2); + + // Create the OnOff application to send UDP datagrams of size // 210 bytes at a rate of 448 Kb/s Ptr ooff = MakeNewObject ( @@ -175,7 +183,8 @@ int main (int argc, char *argv[]) // Also configure some tcpdump traces; each interface will be traced // The output files will be named simple-p2p.pcap-- - // and can be read by the "tcpdump -r" command + // and can be read by the "tcpdump -r" command (use "-tt" option to + // display timestamps correctly) PcapTrace pcaptrace ("simple-p2p.pcap"); pcaptrace.TraceAllIp (); diff --git a/ns3/_placeholder_ b/ns3/_placeholder_ new file mode 100644 index 000000000..67cc5baa2 --- /dev/null +++ b/ns3/_placeholder_ @@ -0,0 +1 @@ +This is a placeholder file used only to keep the ns3 directory present (needed for the WAF build system). diff --git a/samples/wscript b/samples/wscript new file mode 100644 index 000000000..deda03941 --- /dev/null +++ b/samples/wscript @@ -0,0 +1,30 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import Params + +def build(bld): + def create_ns_prog(name, source, deps=['core', 'common', 'simulator']): + obj = bld.create_obj('cpp', 'program') + obj.target = name + obj.uselib_local = ' '.join(["ns3-%s" % dep for dep in deps]) + obj.source = source + for module in deps: + obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,)) + return obj + + obj = create_ns_prog('main-callback', 'main-callback.cc') + obj = create_ns_prog('main-simulator', 'main-simulator.cc') + obj = create_ns_prog('main-packet', 'main-packet.cc') + #obj = create_ns_prog('main-trace', 'main-trace.cc') + obj = create_ns_prog('main-test', 'main-test.cc') + obj = create_ns_prog('main-ptr', 'main-ptr.cc') + + #obj = create_ns_prog('main-p2p-net-device-if', 'main-p2p-net-device-if.cc', + # deps=['core', 'common', 'simulator', 'node', 'p2p']) + + obj = create_ns_prog('main-simple', 'main-simple.cc', + deps=['core', 'common', 'simulator', + 'node', 'internet-node', 'applications']) + + #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', + # deps=['core', 'common', 'simulator', 'node', 'p2p']) + diff --git a/src/applications/wscript b/src/applications/wscript new file mode 100644 index 000000000..5c7591ca5 --- /dev/null +++ b/src/applications/wscript @@ -0,0 +1,20 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_obj('cpp', 'shlib') + obj.name = 'ns3-applications' + obj.target = obj.name + obj.deps = ['ns3-node'] + obj.source = [ + 'application-list.cc', + 'application.cc', + 'onoff-application.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'application-list.h', + 'application.h', + 'onoff-application.h', + ] diff --git a/src/common/wscript b/src/common/wscript new file mode 100644 index 000000000..8120e772d --- /dev/null +++ b/src/common/wscript @@ -0,0 +1,49 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + common = bld.create_obj('cpp', 'shlib') + common.name = 'ns3-common' + common.target = common.name + common.deps = ['ns3-core', 'ns3-simulator'] + common.source = [ + 'buffer.cc', + 'header.cc', + 'chunk.cc', + 'trailer.cc', + 'packet.cc', + 'tags.cc', + 'pcap-writer.cc', + 'variable-tracer-test.cc', + 'trace-context.cc', + 'trace-resolver.cc', + 'callback-trace-source.cc', + 'empty-trace-resolver.cc', + 'composite-trace-resolver.cc', + 'trace-root.cc', + 'data-rate.cc', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'buffer.h', + 'header.h', + 'chunk.h', + 'trailer.h', + 'tags.h', + 'packet.h', + 'uv-trace-source.h', + 'sv-trace-source.h', + 'fv-trace-source.h', + 'pcap-writer.h', + 'callback-trace-source.h', + 'trace-context.h', + 'trace-resolver.h', + 'empty-trace-resolver.h', + 'composite-trace-resolver.h', + 'array-trace-resolver.h', + 'trace-root.h', + 'terminal-trace-resolver.h', + 'smartvector.h', + 'smartset.h', + 'data-rate.h', + ] diff --git a/src/core/command-line.h b/src/core/command-line.h index f3186fde5..046058dd4 100644 --- a/src/core/command-line.h +++ b/src/core/command-line.h @@ -8,16 +8,48 @@ namespace ns3 { +/** + * \brief Command line argument processing class + * \ingroup config + * + * Often times in simulations, the user will want the ability to change and + * tweak simulation parameters without having to recompile the entire + * simulation. This can be done by passing arguments in from the command + * line invocation of a simulation. + * This class is a collection of static functions to aid in this facility. + * By using it, users get the automatic things like support for --help command + * line arguments. See samples/main-default-value.cc for more info. + */ class CommandLine { public: + /** + * \brief Add a command line argument to the system + * \param name Name of the string to expect on the command line + * \param help A help string for this param, displayed --help is used. + * \param value The desination to store the value read from the command line + */ template static void AddArgValue (const std::string &name, const std::string &help, T &value); + /** + * \brief Add a command line triggered function call to the system + * \param name Name of the string to expect on the command line + * \param help A help string for this param, displayed --help is used. + * \param value An ns3::Callback that gets called if name is present as a + * commandline argument. + */ static void AddArgCommand (const std::string &name, const std::string &help, Callback cb); + /** + * \brief Parse the command line for arguments thus far added + * \param argc Number of strings on the command line; pass this directly from + * the first argument of your main(int,char**) function + * \param argv Array of strings passed in as arguments; pass this directly from + * the second argument of your main(int,char**) function + */ static void Parse (int argc, char *argv[]); private: template diff --git a/src/core/default-value.h b/src/core/default-value.h index ef703ce84..f64e691fb 100644 --- a/src/core/default-value.h +++ b/src/core/default-value.h @@ -6,6 +6,11 @@ #include #include "callback.h" +/** + * \defgroup config Simulation configuration + * + */ + namespace ns3 { class DefaultValueBase @@ -45,6 +50,7 @@ class DefaultValueList }; /** + * \ingroup config * \param name name of variable to bind * \param value value to bind to the specified variable * @@ -58,6 +64,7 @@ void Bind (std::string name, std::string value); /** * \brief A Boolean variable for ns3::Bind + * \ingroup config * * Every instance of this type is automatically * registered in the variable pool which is used @@ -95,6 +102,7 @@ private: /** * \brief An Integer variable for ns3::Bind + * \ingroup config * * Every instance of this type is automatically * registered in the variable pool which is used @@ -147,6 +155,14 @@ private: T m_value; }; +/** + * \brief Named enumeration defaults + * \ingroup config + * + * Every instance of this type is automatically + * registered in the variable pool which is used + * by ns3::Bind. + */ class StringEnumDefaultValue : public DefaultValueBase { public: @@ -168,6 +184,7 @@ private: /** * \brief An enum variable for ns3::Bind + * \ingroup config * * Every instance of this type is automatically * registered in the variable pool which is used @@ -232,6 +249,11 @@ public: T m_value; }; +/** + * \brief Class used to call a certain function during the configuration of the + * simulation + * \ingroup config + */ class CommandDefaultValue : public DefaultValueBase { public: diff --git a/src/core/wscript b/src/core/wscript new file mode 100644 index 000000000..fdd95507b --- /dev/null +++ b/src/core/wscript @@ -0,0 +1,74 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys + + +def configure(conf): + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdlib.h' + e.define = 'HAVE_STDLIB_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdlib.h' + e.define = 'HAVE_GETENV' + e.run() + + conf.write_config_header('ns3/core-config.h') + + + +def build(bld): + core = bld.create_obj('cpp', 'shlib') + core.name = 'ns3-core' + core.target = core.name + core.deps = 'ns3-core-headers' + core.source = [ + 'reference-list-test.cc', + 'callback-test.cc', + 'debug.cc', + 'assert.cc', + 'ptr.cc', + 'object.cc', + 'test.cc', + 'random-variable.cc', + 'rng-stream.cc', + 'ns-unknown.cc', + 'uid-manager.cc', + 'default-value.cc', + 'command-line.cc', + 'type-name.cc', + 'ns-unknown-manager.cc', + ] + + if sys.platform == 'win32': + core.source.extend([ + 'win32-system-wall-clock-ms.cc', + ]) + else: + core.source.extend([ + 'unix-system-wall-clock-ms.cc', + ]) + + headers = bld.create_obj('ns3header') + headers.name = 'ns3-core-headers' + headers.source = [ + 'system-wall-clock-ms.h', + 'reference-list.h', + 'callback.h', + 'ptr.h', + 'object.h', + 'debug.h', + 'assert.h', + 'fatal-error.h', + 'test.h', + 'random-variable.h', + 'rng-stream.h', + 'ns-unknown.h', + 'default-value.h', + 'command-line.h', + 'type-name.h', + 'ns-unknown-manager.h', + ] + diff --git a/src/devices/p2p-gfr/p2p-channel.cc b/src/devices/p2p-gfr/p2p-channel.cc deleted file mode 100644 index 09e338cdc..000000000 --- a/src/devices/p2p-gfr/p2p-channel.cc +++ /dev/null @@ -1,98 +0,0 @@ -// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// All rights reserved. -// -// 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 F. Riley -// - -// Implementation of simple point-to-point channel -// George F. Riley, Georgia Tech, Spring 2007 - -#include "ns3/simulator.h" -#include "ns3/packet.h" -#include "ns3/node.h" -#include "p2p-channel.h" -#include "p2p-net-device.h" - -namespace ns3 { - -P2PChannel::P2PChannel(const Time& delay, double maxRate) - : m_nd1(0), m_nd2(0), - m_delay (delay), - m_maxRate (maxRate) -{ -} - -P2PChannel::~P2PChannel () -{} - -// Channels create compatible net devices -P2PNetDevice* P2PChannel::CreateNetDevice(Node *node, MacAddress address) -{ - // Create a new point-to-point network device - P2PNetDevice* nd = new P2PNetDevice(node, address); - nd->Connect (this); - // Add to list of peers - if (!m_nd1) m_nd1 = nd; - else m_nd2 = nd; - return nd; -} - -void P2PChannel::RemoveNetDevice(NetDevice* nd) -{ - if (nd == m_nd1) m_nd1 = 0; - if (nd == m_nd2) m_nd2 = 0; - // Now if all removed, remove the channel as well - if (!m_nd1 && !m_nd2) - { - delete this; - } -} - -void P2PChannel::Send(P2PNetDevice *device, Packet& p, double rate) -{ // Schedule a receive event at receiver - // First calculate time in future - double maxRate; - if (rate < m_maxRate) - { - maxRate = rate; - } - else - { - maxRate = m_maxRate; - } - Time txTime = Seconds (p.GetSize() * 8 / maxRate); - Time rxTime = m_delay + txTime; - P2PNetDevice *to, *from; - if (device == m_nd1) - { - from = m_nd1; - to = m_nd2; - } - else - { - from = m_nd2; - to = m_nd1; - } - // Schedule the receive event at receiver - Simulator::Schedule(rxTime, &P2PNetDevice::Receive, to, p); - // Schedule the link free event - Simulator::Schedule(txTime, &P2PNetDevice::TxComplete, from); - -} - -}//namespace ns3 diff --git a/src/devices/p2p-gfr/p2p-channel.h b/src/devices/p2p-gfr/p2p-channel.h deleted file mode 100644 index 891d3826f..000000000 --- a/src/devices/p2p-gfr/p2p-channel.h +++ /dev/null @@ -1,56 +0,0 @@ -// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// All rights reserved. -// -// 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 F. Riley -// - -// Definition of a simple point-to-point channel -// George F. Riley, Georgia Tech, Spring 2007 - -#ifndef P2P_CHANNEL_H -#define P2P_CHANNEL_H - -#include "ns3/nstime.h" -#include "ns3/mac-address.h" - -namespace ns3 { - -class P2PNetDevice; -class NetDevice; -class Node; -class Packet; - -class P2PChannel { -public: - P2PChannel(const Time& delay, double maxRate /* bits/s */); - ~P2PChannel(); - - P2PNetDevice* CreateNetDevice(Node *node, MacAddress address); - void RemoveNetDevice (NetDevice *device); - void Send (P2PNetDevice *device, Packet&p, double rate /* bits/s */); -private: - // The two endpoints of this channel - P2PNetDevice* m_nd1; - P2PNetDevice* m_nd2; - Time m_delay; - double m_maxRate; -}; - -}//namespace ns3 - -#endif diff --git a/src/devices/p2p-gfr/p2p-net-device.cc b/src/devices/p2p-gfr/p2p-net-device.cc deleted file mode 100644 index fe81c2f64..000000000 --- a/src/devices/p2p-gfr/p2p-net-device.cc +++ /dev/null @@ -1,80 +0,0 @@ -// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// All rights reserved. -// -// 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 F. Riley -// - -// Implementation of a point-to-point network device -// George F. Riley, Georgia Tech, Spring 2007 - -#include "ns3/empty-trace-resolver.h" -#include "p2p-net-device.h" -#include "p2p-channel.h" - -namespace ns3 { - -P2PNetDevice::P2PNetDevice (Node *node, MacAddress const &addr) - : NetDevice (node, addr), - m_rate (1000000) -{ - SetMtu (2300); - EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff")); -} - -P2PNetDevice::~P2PNetDevice() -{ // Inform channel that we are destroyed - m_channel->RemoveNetDevice(this); -} - -void -P2PNetDevice::SetRate (double rate) -{ - m_rate = rate; -} - -void -P2PNetDevice::Connect (P2PChannel *channel) -{ - m_channel = channel; - NotifyLinkUp (); -} - -bool -P2PNetDevice::SendTo (Packet& p, const MacAddress&) -{ - m_channel->Send (this, p, m_rate); - return true; -} - -TraceResolver * -P2PNetDevice::DoCreateTraceResolver (TraceContext const &context) -{ - return new EmptyTraceResolver (context); -} - -void -P2PNetDevice::Receive(Packet p) -{ - ForwardUp (p); -} - -void -P2PNetDevice::TxComplete (void) -{} - -}//namespace ns3 diff --git a/src/devices/p2p-gfr/p2p-net-device.h b/src/devices/p2p-gfr/p2p-net-device.h deleted file mode 100644 index 4809ea738..000000000 --- a/src/devices/p2p-gfr/p2p-net-device.h +++ /dev/null @@ -1,54 +0,0 @@ -// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// All rights reserved. -// -// 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 F. Riley -// - -// Definition for a Point-to-Point network device -// George F. Riley, Georgia Tech, Spring 2007 - -#ifndef P2P_NET_DEVICE_H -#define P2P_NET_DEVICE_H - -#include "ns3/net-device.h" - -namespace ns3 { - -class P2PChannel; - -class P2PNetDevice : public NetDevice { -public: - P2PNetDevice(Node *node, MacAddress const &addr); - virtual ~P2PNetDevice(); - - void SetRate (double rate); - void Connect (P2PChannel *channel); - void Receive(Packet p); - void TxComplete (void); - private: - virtual bool SendTo (Packet& p, const MacAddress& dest); - virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context); - - double m_rate; - P2PChannel *m_channel; -}; - -}//namespace ns3 - -#endif /* P2P_NET_DEVICE_H */ - diff --git a/src/devices/p2p/p2p-topology.cc b/src/devices/p2p/p2p-topology.cc index 720d5d513..7f9db4660 100644 --- a/src/devices/p2p/p2p-topology.cc +++ b/src/devices/p2p/p2p-topology.cc @@ -24,6 +24,8 @@ #include #include "ns3/assert.h" +#include "ns3/debug.h" +#include "ns3/fatal-error.h" #include "ns3/nstime.h" #include "ns3/internet-node.h" #include "ns3/ipv4-address.h" @@ -60,7 +62,7 @@ PointToPointTopology::AddPointToPointLink( return channel; } -bool +void PointToPointTopology::AddIpv4Addresses( Ptr chan, Ptr n1, const Ipv4Address& addr1, @@ -99,111 +101,72 @@ PointToPointTopology::AddIpv4Addresses( ip2->SetNetworkMask (index2, netmask); ip2->SetUp (index2); - ip1->AddHostRouteTo (addr2, index1); - ip2->AddHostRouteTo (addr1, index2); - - return true; } -#ifdef NOTYET +void +PointToPointTopology::AddIpv4Routes ( + Ptr n1, Ptr n2, Ptr chan) +{ + // The PointToPoint channel is used to find the relevant NetDevices + NS_ASSERT (chan->GetNDevices () == 2); + Ptr nd1 = chan->GetDevice (0); + Ptr nd2 = chan->GetDevice (1); -// Get the net device connecting node n1 to n2. For topologies where -// there are possibly multiple devices connecting n1 and n2 (for example -// wireless with two devices on different channels) this will return -// the first one found. -Ptr PointToPointTopology::GetNetDevice(Ptr n1, Ptr n2) -{ - for (NetDeviceList::NetDevices_t::const_iterator i = dlist.Begin(); - i != dlist.End(); ++i) - { // Check each device - Ptr nd = *i; // next device - Ptr c = nd->GetChannel(); - if (!c) continue; // No channel - if (c->NodeIsPeer(n2)) return nd; // found it + // Assert that n1 is the Node owning one of the two NetDevices + // and make sure that nd1 corresponds to it + if (nd1->GetNode ()->GetId () == n1->GetId ()) + { + ; // Do nothing + } + else if (nd2->GetNode ()->GetId () == n1->GetId ()) + { + std::swap(nd1, nd2); + } + else + { + NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel"); } - return 0; // None found -} - -// Get the channel connecting node n1 to node n2 -Ptr PointToPointTopology::GetChannel( - Ptr n1, - Ptr n2 -) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, so no channel - return nd->GetChannel(); -} -Ptr PointToPointTopology::GetQueue(Ptr n1, Ptr n2) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, so in queue - return nd->GetQueue(); + // Assert that n2 is the Node owning one of the two NetDevices + // and make sure that nd2 corresponds to it + if (nd2->GetNode ()->GetId () != n2->GetId ()) + { + NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel"); + } + + // Assert that both are Ipv4 nodes + Ptr ip1 = nd1->GetNode ()->QueryInterface (IIpv4::iid); + Ptr ip2 = nd2->GetNode ()->QueryInterface (IIpv4::iid); + NS_ASSERT(ip1 != 0 && ip2 != 0); + + // Get interface indexes for both nodes corresponding to the right channel + uint32_t index1 = 0; + bool found = false; + for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++) + { + if (ip1 ->GetNetDevice (i) == nd1) + { + index1 = i; + found = true; + } + } + NS_ASSERT(found); + + uint32_t index2 = 0; + found = false; + for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++) + { + if (ip2 ->GetNetDevice (i) == nd2) + { + index2 = i; + found = true; + } + } + NS_ASSERT(found); + + ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1); + ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); } -void PointToPointTopology::SetQueue(Ptr n1, Ptr n2, Ptr q) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, can't set queue - // Add the specified queue to the netdevice - return nd->SetQueue(q); -} - -#endif - -#ifdef GFR -P2PChannel Topology::AddDuplexLink(Ptr n1, const IPAddr& ip1, - Ptr n2, const IPAddr& ip2, - const Rate& rate, const Time& delay) -{ - // Get the net devices - P2PNetDevice* nd1 = ndl1->Add(P2PNetDevice(n1, rate, nil)); - P2PNetDevice* nd2 = ndl2->Add(P2PNetDevice(n1, rate, nd1->GetChannel())); - // Not implemented yet. Add appropriate layer 2 protocol for - // the net devices. - // Get the L3 proto for node 1 and configure it with this device - Ptr l3demux1 = n1->GetL3Demux(); - Ptr l3proto1 = nil; - // If the node 1 l3 demux exists, find the coresponding l3 protocol - if (l3demux1) l3proto1 = l3demux1->Lookup(ip1.L3Proto()); - // If the l3 protocol exists, configure this net device. Use a mask - // of all ones, since there is only one device on the remote end - // of this link - if (l3proto1) l3proto1->AddNetDevice(nd1, ip1, ip1.GetMask(ip1.Size()*8)); - // Same for node 2 - Ptr l3demux2 = n2->GetL3Demux(); - Ptr l3proto2 = nil; - // If the node 2 l3 demux exists, find the coresponding l3 protocol - if (l3demux2) l3proto2 = l3demux2->Lookup(ip2.L3Proto()); - if (l3proto2) l3proto2->AddNetDevice(nd2, ip2, ip2.GetMask(ip2.Size()*8)); - return dynamic_cast(nd1->GetChannel()); // Always succeeds -} - -// Get the channel connecting node n1 to node n2 -Ptr Topology::GetChannel(Ptr n1, Ptr n2) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, so no channel - return nd->GetChannel(); -} - -Ptr Topology::GetQueue(Ptr n1, Ptr n2) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, so in queue - return nd->GetQueue(); -} - -void Topology::SetQueue(Ptr n1, Ptr n2, Ptr q) -{ - Ptr nd = GetNetDevice(n1, n2); - if (!nd) return 0; // No net device, can't set queue - // Add the specified queue to the netdevice - return nd->SetQueue(q); -} - -#endif - } // namespace ns3 diff --git a/src/devices/p2p/p2p-topology.h b/src/devices/p2p/p2p-topology.h index 282c3a0a3..1cb643d94 100644 --- a/src/devices/p2p/p2p-topology.h +++ b/src/devices/p2p/p2p-topology.h @@ -34,47 +34,51 @@ class Node; class IPAddr; class DataRate; class Queue; -//class Time; /** - * \brief A helper class to create Topologies based on the ns3::PointToPointNetDevice and - * ns3::PointToPointChannel objects. - * - * XXX ?? - * I think that some of the methods below are not implemented. - * If so, remove them. + * \brief A helper class to create Topologies based on the + * ns3::PointToPointNetDevice and ns3::PointToPointChannel objects. */ class PointToPointTopology { public: /** + * \param n1 Node + * \param n2 Node + * \param rate Maximum transmission link rate + * \param delay one-way propagation delay + * \return Pointer to the underlying PointToPointChannel + * * Add a full-duplex point-to-point link between two nodes - * with the specified IP addresses, with specified maximum transmission rate - * and propagation delay. + * and attach PointToPointNetDevices to the resulting + * PointToPointChannel. */ static Ptr AddPointToPointLink( - Ptr, Ptr, const DataRate&, const Time&); + Ptr n1, Ptr n2, const DataRate& dataRate, const Time& delay); - static bool AddIpv4Addresses( - Ptr, - Ptr, const Ipv4Address&, - Ptr, const Ipv4Address&); + /** + * \param chan PointToPointChannel to use + * \param n1 Node + * \param addr1 Ipv4 Address for n1 + * \param n2 Node + * \param addr2 Ipv4 Address for n2 + * + * Add Ipv4Addresses to the Ipv4 interfaces associated with the + * two PointToPointNetDevices on the provided PointToPointChannel + */ + static void AddIpv4Addresses( + Ptr chan, + Ptr n1, const Ipv4Address& addr1, + Ptr n2, const Ipv4Address& addr2); /** - * Get the connecting node n1 to node n2 + * \param channel PointToPointChannel to use + * \param n1 Node + * \param n2 Node + * + * For the given PointToPointChannel, for each Node, add an + * IPv4 host route to the IPv4 address of the peer node. */ - static Ptr GetChannel(Ptr, Ptr); - /** - * Get the NetDevice connecting node n1 to n2 - */ - static Ptr GetNetDevice(Ptr, Ptr); - /** - * Get the queue associated with a link between two nodes - */ - static Queue* GetQueue(Ptr, Ptr); - /** - * Set the queue associated with a link between two nodes - */ - static Queue* SetQueue(Ptr, Ptr, const Queue&); + static void AddIpv4Routes (Ptr n1, Ptr n2, Ptr channel); }; } // namespace ns3 diff --git a/src/devices/p2p/wscript b/src/devices/p2p/wscript new file mode 100644 index 000000000..528594085 --- /dev/null +++ b/src/devices/p2p/wscript @@ -0,0 +1,18 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + p2p = bld.create_obj('cpp', 'shlib') + p2p.name = 'ns3-p2p' + p2p.target = p2p.name + p2p.deps = ['ns3-node'] + p2p.source = [ + 'p2p-net-device.cc', + 'p2p-channel.cc', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'p2p-net-device.h', + 'p2p-channel.h', + ] + diff --git a/src/devices/wscript b/src/devices/wscript new file mode 100644 index 000000000..e8c8a659e --- /dev/null +++ b/src/devices/wscript @@ -0,0 +1,6 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + bld.add_subdirs('p2p') + #bld.add_subdirs('p2p-gfr') + diff --git a/src/internet-node/i-ipv4-impl.cc b/src/internet-node/i-ipv4-impl.cc index 6ac4a58cd..19ec5f617 100644 --- a/src/internet-node/i-ipv4-impl.cc +++ b/src/internet-node/i-ipv4-impl.cc @@ -20,6 +20,7 @@ */ #include "i-ipv4-impl.h" #include "ipv4.h" +#include "ipv4-interface.h" #include "ns3/assert.h" #include "ns3/net-device.h" @@ -97,6 +98,11 @@ IIpv4Impl::GetNInterfaces (void) { return m_ipv4->GetNInterfaces (); } +Ptr +IIpv4Impl::GetNetDevice (uint32_t i) +{ + return m_ipv4->GetInterface (i)-> GetDevice (); +} void IIpv4Impl::SetAddress (uint32_t i, Ipv4Address address) diff --git a/src/internet-node/i-ipv4-impl.h b/src/internet-node/i-ipv4-impl.h index 3c9fc1b66..a2cac5edc 100644 --- a/src/internet-node/i-ipv4-impl.h +++ b/src/internet-node/i-ipv4-impl.h @@ -54,6 +54,7 @@ public: virtual void RemoveRoute (uint32_t i); virtual uint32_t AddInterface (Ptr device); virtual uint32_t GetNInterfaces (void); + virtual Ptr GetNetDevice(uint32_t i); virtual void SetAddress (uint32_t i, Ipv4Address address); virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); diff --git a/src/internet-node/wscript b/src/internet-node/wscript new file mode 100644 index 000000000..baeaaef87 --- /dev/null +++ b/src/internet-node/wscript @@ -0,0 +1,43 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_obj('cpp', 'shlib') + obj.name = 'ns3-internet-node' + obj.target = obj.name + obj.deps = ['ns3-node', 'ns3-applications'] + obj.source = [ + 'internet-node.cc', + 'l3-demux.cc', + 'l3-protocol.cc', + 'ipv4-l4-demux.cc', + 'ipv4-l4-protocol.cc', + 'ipv4-header.cc', + 'udp-header.cc', + 'ipv4-checksum.cc', + 'ipv4-interface.cc', + 'ipv4.cc', + 'ipv4-end-point.cc', + 'udp.cc', + 'arp-header.cc', + 'arp-cache.cc', + 'arp-ipv4-interface.cc', + 'arp.cc', + 'ipv4-loopback-interface.cc', + 'header-utils.cc', + 'udp-socket.cc', + 'ipv4-end-point-demux.cc', + 'i-udp-impl.cc', + 'i-arp-private.cc', + 'i-ipv4-impl.cc', + 'i-ipv4-private.cc', + 'ascii-trace.cc', + 'pcap-trace.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'internet-node.h', + 'ascii-trace.h', + 'pcap-trace.h', + ] diff --git a/src/node/application.h b/src/node/application.h index 5cc1809fc..f761467fe 100644 --- a/src/node/application.h +++ b/src/node/application.h @@ -21,32 +21,6 @@ #ifndef __APPLICATION_H__ #define __APPLICATION_H__ -// -// \brief The base class for all ns3 applicationes -// -// Class Application is the base class for all ns3 applications. -// Applications are associated with individual nodes, and are created -// using the AddApplication method in the ApplicationManager capability. -// -// Conceptually, an application has zero or more Socket -// objects associated with it, that are created using the Socket -// creation API of the Kernel capability. The Socket object -// API is modeled after the -// well-known BSD sockets interface, although it is somewhat -// simplified for use with ns3. Further, any socket call that -// would normally "block" in normal sockets will return immediately -// in ns3. A set of "upcalls" are defined that will be called when -// the previous blocking call would normally exit. THis is documented -// in more detail Socket class in socket.h. -// -// There is a second application class in ns3, called "ThreadedApplication" -// that implements a true sockets interface, which should be used -// when porting existing sockets code to ns3. The true -// sockets approach is significantly -// less memory--efficient using private stacks for each defined application, -// so that approach should be used with care. The design and implementation -// of the ThreadedApplication are still being discussed. - #include "ns3/event-id.h" #include "ns3/nstime.h" #include "ns3/object.h" @@ -59,7 +33,21 @@ class Node; class RandomVariable; /** - * \brief a model for userspace applications. + * \brief The base class for all ns3 applicationes + * + * Class Application is the base class for all ns3 applications. + * Applications are associated with individual nodes. + * + * Conceptually, an application has zero or more Socket + * objects associated with it, that are created using the Socket + * creation API of the Kernel capability. The Socket object + * API is modeled after the + * well-known BSD sockets interface, although it is somewhat + * simplified for use with ns3. Further, any socket call that + * would normally "block" in normal sockets will return immediately + * in ns3. A set of "upcalls" are defined that will be called when + * the previous blocking call would normally exit. THis is documented + * in more detail Socket class in socket.h. */ class Application : public Object { diff --git a/src/node/i-ipv4.h b/src/node/i-ipv4.h index 2f064b2d3..a04782119 100644 --- a/src/node/i-ipv4.h +++ b/src/node/i-ipv4.h @@ -122,6 +122,12 @@ public: */ virtual uint32_t GetNInterfaces (void) = 0; + /** + * \param index of interface + * \returns address of the NetDevice associated with the ipv4 interface + */ + virtual Ptr GetNetDevice (uint32_t i) = 0; + virtual void SetAddress (uint32_t i, Ipv4Address address) = 0; virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask) = 0; virtual Ipv4Mask GetNetworkMask (uint32_t t) const = 0; diff --git a/src/node/wscript b/src/node/wscript new file mode 100644 index 000000000..d3f0c5bfc --- /dev/null +++ b/src/node/wscript @@ -0,0 +1,40 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + node = bld.create_obj('cpp', 'shlib') + node.name = 'ns3-node' + node.target = node.name + node.deps = ['ns3-core', 'ns3-common', 'ns3-simulator'] + node.source = [ + 'node.cc', + 'ipv4-address.cc', + 'net-device.cc', + 'mac-address.cc', + 'llc-snap-header.cc', + 'ipv4-route.cc', + 'queue.cc', + 'drop-tail.cc', + 'channel.cc', + 'node-list.cc', + 'socket.cc', + 'i-udp.cc', + 'i-ipv4.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'node.h', + 'ipv4-address.h', + 'net-device.h', + 'mac-address.h', + 'ipv4-route.h', + 'queue.h', + 'drop-tail.h', + 'llc-snap-header.h', + 'channel.h', + 'node-list.h', + 'socket.h', + 'i-udp.h', + 'i-ipv4.h', + ] diff --git a/src/simulator/wscript b/src/simulator/wscript new file mode 100644 index 000000000..4bf989b44 --- /dev/null +++ b/src/simulator/wscript @@ -0,0 +1,95 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys + +import Params + + +def set_options(opt): + opt.add_option('--high-precision-as-double', + help=('Whether to use a double floating point' + ' type for high precision time values'), + action="store_true", default=False, + dest='high_precision_as_double') + + +def configure(conf): + if Params.g_options.high_precision_as_double: + conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1) + conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1 + highprec = 'long double' + else: + conf.env['USE_HIGH_PRECISION_DOUBLE'] = 0 + highprec = '128-bit integer' + conf.check_message_custom('high precision time', 'implementation', highprec) + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdint.h' + e.define = 'HAVE_STDINT_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'inttypes.h' + e.define = 'HAVE_INTTYPES_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'sys/inttypes.h' + e.define = 'HAVE_SYS_INT_TYPES_H' + e.run() + + conf.write_config_header('ns3/simulator-config.h') + + + +def build(bld): + sim = bld.create_obj('cpp', 'shlib') + sim.name = 'ns3-simulator' + sim.target = sim.name + sim.deps = 'ns3-simulator-headers ns3-core-headers' + + sim.source = [ + 'high-precision.cc', + 'time.cc', + 'event-id.cc', + 'scheduler.cc', + 'scheduler-factory.cc', + 'scheduler-list.cc', + 'scheduler-heap.cc', + 'scheduler-map.cc', + 'event-impl.cc', + 'simulator.cc', + ] + headers = bld.create_obj('ns3header') + headers.name = 'ns3-simulator-headers' + headers.source = [ + 'high-precision.h', + 'nstime.h', + 'event-id.h', + 'event-impl.h', + 'simulator.h', + 'scheduler.h', + 'scheduler-factory.h', + 'simulation-singleton.h', + ] + + env = bld.env_of_name('default') + if env['USE_HIGH_PRECISION_DOUBLE']: + sim.source.extend([ + 'high-precision-double.cc', + ]) + headers.source.extend([ + 'high-precision-double.h', + ]) + else: + sim.source.extend([ + 'high-precision-128.cc', + 'cairo-wideint.c', + ]) + headers.source.extend([ + 'high-precision-128.h', + 'cairo-wideint-private.h', + ]) + diff --git a/src/wscript b/src/wscript new file mode 100644 index 000000000..d47b86401 --- /dev/null +++ b/src/wscript @@ -0,0 +1,13 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def set_options(opt): + opt.sub_options('simulator') + +def configure(conf): + conf.sub_config('core') + conf.sub_config('simulator') + +def build(bld): + bld.add_subdirs('core common simulator') + bld.add_subdirs('node internet-node devices applications') + diff --git a/utils/wscript b/utils/wscript new file mode 100644 index 000000000..5b2e13e89 --- /dev/null +++ b/utils/wscript @@ -0,0 +1,25 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys +import Params + +def build(bld): + + def create_ns_prog(name, source): + obj = bld.create_obj('cpp', 'program') + obj.target = name + obj.deps = "ns3-core ns3-common ns3-simulator" + obj.uselib_local = "ns3-core ns3-common ns3-simulator" + obj.source = source + for module in ['core', 'common', 'simulator']: + obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,)) + return obj + + unit_tests = create_ns_prog('run-tests', 'run-tests.cc') + unit_tests.install_var = 0 #do not install + unit_tests.unit_test = 1 + + #if sys.platform != 'win32': + obj = create_ns_prog('bench-simulator', 'bench-simulator.cc') + obj = create_ns_prog('replay-simulation', 'replay-simulation.cc') + ## bench-packets requires missing header files + #obj = create_ns_prog('bench-packets', 'bench-packets.cc') diff --git a/wscript b/wscript new file mode 100644 index 000000000..f7dabf762 --- /dev/null +++ b/wscript @@ -0,0 +1,183 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import os + +import Params +import Object +import Action +import Common +import shutil +import subprocess + +Params.g_autoconfig = 1 + +# the following two variables are used by the target "waf dist" +VERSION = '3.0.1' +APPNAME = 'ns-3-waf' + +# these variables are mandatory ('/' are converted automatically) +srcdir = '.' +blddir = 'build' + +class Ns3Header(Object.genobj): + """A public NS-3 header file""" + def __init__(self, env=None): + Object.genobj.__init__(self, 'other') + self.inst_var = 'INCLUDEDIR' + self.inst_dir = 'ns3' + self.env = env + if not self.env: + self.env = Params.g_build.m_allenvs['default'] + + def apply(self): + ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3") + inputs = [] + outputs = [] + for filename in self.to_list(self.source): + src_node = self.path.find_source(filename) + if src_node is None: + Params.fatal("source ns3 header file %s not found" % (filename,)) + dst_node = ns3_dir_node.find_build(os.path.basename(filename)) + assert dst_node is not None + inputs.append(src_node) + outputs.append(dst_node) + task = self.create_task('ns3_headers', self.env, 1) + task.set_inputs(inputs) + task.set_outputs(outputs) + + def install(self): + for i in self.m_tasks: + current = Params.g_build.m_curdirnode + lst = map(lambda a: a.relpath_gen(current), i.m_outputs) + Common.install_files(self.inst_var, self.inst_dir, lst) + +def _ns3_headers_inst(task): + assert len(task.m_inputs) == len(task.m_outputs) + inputs = [node.srcpath(task.m_env) for node in task.m_inputs] + outputs = [node.bldpath(task.m_env) for node in task.m_outputs] + for src, dst in zip(inputs, outputs): + try: + os.chmod(dst, 0600) + except OSError: + pass + shutil.copy2(src, dst) + ## make the headers in builddir read-only, to prevent + ## accidental modification + os.chmod(dst, 0400) + return 0 + +def init(): + Object.register('ns3header', Ns3Header) + Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE') + +def set_options(opt): + # options provided by the modules + if not opt.tool_options('msvc'): + opt.tool_options('g++') + + opt.add_option('--enable-gcov', + help=('Enable code coverage analysis'), + action="store_true", default=False, + dest='enable_gcov') + + opt.add_option('--lcov-report', + help=('Generate a code coverage report ' + '(use this option at build time, not in configure)'), + action="store_true", default=False, + dest='lcov_report') + + opt.add_option('--doxygen', + help=('Run doxygen to generate html documentation from source comments'), + action="store_true", default=False, + dest='doxygen') + + # options provided in a script in a subdirectory named "src" + opt.sub_options('src') + + +def configure(conf): + if not conf.check_tool('msvc'): + if not conf.check_tool('g++'): + Params.fatal("No suitable compiler found") + + + # create the second environment, set the variant and set its name + variant_env = conf.env.copy() + variant_name = Params.g_options.debug_level.lower() + + if Params.g_options.enable_gcov: + variant_name += '-gcov' + variant_env.append_value('CCFLAGS', '-fprofile-arcs') + variant_env.append_value('CCFLAGS', '-ftest-coverage') + variant_env.append_value('CXXFLAGS', '-fprofile-arcs') + variant_env.append_value('CXXFLAGS', '-ftest-coverage') + variant_env.append_value('LINKFLAGS', '-fprofile-arcs') + + conf.env['NS3_ACTIVE_VARIANT'] = variant_name + variant_env['NS3_ACTIVE_VARIANT'] = variant_name + variant_env.set_variant(variant_name) + conf.set_env_name(variant_name, variant_env) + conf.setenv(variant_name) + + variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS') + if 'debug' in Params.g_options.debug_level.lower(): + variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE') + variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE') + + conf.sub_config('src') + + +def build(bld): + variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT'] + variant_env = bld.env_of_name(variant_name) + bld.m_allenvs['default'] = variant_env # switch to the active variant + # process subfolders from here + bld.add_subdirs('src') + bld.add_subdirs('samples utils') + + +def shutdown(): + import UnitTest + ut = UnitTest.unit_test() + ut.change_to_testfile_dir = True + ut.want_to_see_test_output = True + ut.want_to_see_test_error = True + ut.run() + #ut.print_results() + + if Params.g_options.lcov_report: + env = Params.g_build.env_of_name('default') + variant_name = env['NS3_ACTIVE_VARIANT'] + + if 'gcov' not in variant_name: + Params.fatal("project not configured for code coverage;" + " reconfigure with --enable-gcov") + + os.chdir(blddir) + try: + lcov_report_dir = os.path.join(variant_name, 'lcov-report') + create_dir_command = "rm -rf " + lcov_report_dir + create_dir_command += " && mkdir " + lcov_report_dir + ";" + + if subprocess.Popen(create_dir_command, shell=True).wait(): + raise SystemExit(1) + + info_file = os.path.join(lcov_report_dir, variant_name + '.info') + lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file + lcov_command += " --source-dirs=" + os.getcwd() + lcov_command += ":" + os.path.join( + os.getcwd(), variant_name, 'include') + if subprocess.Popen(lcov_command, shell=True).wait(): + raise SystemExit(1) + + genhtml_command = "../utils/lcov/genhtml -o " + lcov_report_dir + genhtml_command += " " + info_file + if subprocess.Popen(genhtml_command, shell=True).wait(): + raise SystemExit(1) + finally: + os.chdir("..") + + if Params.g_options.doxygen: + doxygen_config = os.path.join('doc', 'doxygen.conf') + if subprocess.Popen(['doxygen', doxygen_config]).wait(): + raise SystemExit(1) +